Mercurial > pidgin
annotate src/protocols/yahoo/yahoo_filexfer.c @ 10394:45a0a07e8b25
[gaim-migrate @ 11623]
Renamed yahoo_packet_hash to yahoo_packet_hash_str, added
yahoo_packet_hash_int, and a new variable arg yahoo_packet_hash that calls
either of them.
I was going to add some more format chars to yahoo_packet_hash, and may
yet. Stuff like automaticly converting strings' character sets or html
to yahoo codes, etc. But first I want to look at how yahoo 6 handles
character sets and see if it's any different.
Feel free to give opinions on if these changes are actually better,
assuming you actually look at them, as opposed to running away like a girly
man when you see yahoo protocol code.
committer: Tailor Script <tailor@pidgin.im>
author | Tim Ringenbach <marv@pidgin.im> |
---|---|
date | Fri, 17 Dec 2004 00:05:32 +0000 |
parents | a8f9e5ce4f92 |
children | 96307e1a47c9 |
rev | line source |
---|---|
7651 | 1 /* |
2 * @file yahoo_filexfer.c Yahoo Filetransfer | |
3 * | |
8046 | 4 * Gaim is the legal property of its developers, whose names are too numerous |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7651 | 7 * |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 */ | |
22 | |
23 #include "prpl.h" | |
24 #include "internal.h" | |
25 #include "util.h" | |
26 #include "debug.h" | |
27 #include "notify.h" | |
28 #include "proxy.h" | |
29 #include "ft.h" | |
30 #include "yahoo.h" | |
10392 | 31 #include "yahoo_packet.h" |
7651 | 32 #include "yahoo_filexfer.h" |
33 | |
34 | |
35 | |
36 struct yahoo_xfer_data { | |
37 gchar *host; | |
38 gchar *path; | |
39 int port; | |
40 GaimConnection *gc; | |
41 long expires; | |
42 gboolean started; | |
43 gchar *rxqueue; | |
44 guint rxlen; | |
45 }; | |
46 | |
47 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) | |
48 { | |
49 if (xd->host) | |
50 g_free(xd->host); | |
51 if (xd->path) | |
52 g_free(xd->path); | |
53 g_free(xd); | |
54 } | |
55 | |
56 static void yahoo_receivefile_connected(gpointer data, gint source, GaimInputCondition condition) | |
57 { | |
58 GaimXfer *xfer; | |
59 struct yahoo_xfer_data *xd; | |
60 gchar *buf; | |
61 | |
62 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | |
63 "AAA - in yahoo_receivefile_connected\n"); | |
64 if (!(xfer = data)) | |
65 return; | |
66 if (!(xd = xfer->data)) | |
67 return; | |
68 if (source < 0) { | |
69 gaim_xfer_error(GAIM_XFER_RECEIVE, xfer->who, _("Unable to connect.")); | |
7805 | 70 gaim_xfer_cancel_remote(xfer); |
7651 | 71 return; |
72 } | |
73 | |
74 xfer->fd = source; | |
75 gaim_xfer_start(xfer, source, NULL, 0); | |
76 | |
77 buf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", xd->path, xd->host); | |
78 write(xfer->fd, buf, strlen(buf)); | |
79 g_free(buf); | |
80 | |
81 return; | |
82 } | |
83 | |
84 static void yahoo_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) | |
85 { | |
86 GaimXfer *xfer; | |
87 struct yahoo_xfer_data *xd; | |
88 struct yahoo_packet *pkt; | |
89 gchar *size, *post, *buf; | |
90 int content_length; | |
91 GaimConnection *gc; | |
92 GaimAccount *account; | |
93 struct yahoo_data *yd; | |
7805 | 94 char *filename; |
7651 | 95 |
96 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | |
97 "AAA - in yahoo_sendfile_connected\n"); | |
98 if (!(xfer = data)) | |
99 return; | |
100 if (!(xd = xfer->data)) | |
101 return; | |
102 | |
103 gc = xd->gc; | |
104 account = gaim_connection_get_account(gc); | |
105 yd = gc->proto_data; | |
106 | |
107 | |
108 | |
109 if (source < 0) { | |
110 gaim_xfer_error(GAIM_XFER_RECEIVE, xfer->who, _("Unable to connect.")); | |
7805 | 111 gaim_xfer_cancel_remote(xfer); |
7651 | 112 return; |
113 } | |
114 | |
115 xfer->fd = source; | |
116 gaim_xfer_start(xfer, source, NULL, 0); | |
117 | |
118 | |
119 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
120 | |
10111 | 121 size = g_strdup_printf("%" G_GSIZE_FORMAT, gaim_xfer_get_size(xfer)); |
7805 | 122 filename = g_path_get_basename(gaim_xfer_get_local_filename(xfer)); |
10394 | 123 |
124 yahoo_packet_hash(pkt, "sssss", 0, gaim_connection_get_display_name(gc), | |
125 5, xfer->who, 14, "", 27, filename, 28, size); | |
7651 | 126 |
127 content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt); | |
128 | |
129 buf = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t); | |
130 | |
131 post = g_strdup_printf("POST /notifyft HTTP/1.0\r\n" | |
10111 | 132 "Content-length: %" G_GSIZE_FORMAT "\r\n" |
7651 | 133 "Host: %s:%d\r\n" |
134 "Cookie: %s\r\n" | |
135 "\r\n", | |
136 content_length + 4 + gaim_xfer_get_size(xfer), | |
137 gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST), | |
138 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
139 buf); | |
140 write(xfer->fd, post, strlen(post)); | |
141 | |
10392 | 142 yahoo_packet_send_special(pkt, xfer->fd, 8); |
7651 | 143 yahoo_packet_free(pkt); |
144 | |
145 write(xfer->fd, "29\xc0\x80", 4); | |
146 | |
147 g_free(size); | |
148 g_free(post); | |
149 g_free(buf); | |
7805 | 150 g_free(filename); |
7651 | 151 } |
152 | |
153 static void yahoo_xfer_init(GaimXfer *xfer) | |
154 { | |
155 struct yahoo_xfer_data *xfer_data; | |
156 GaimConnection *gc; | |
157 GaimAccount *account; | |
7827 | 158 struct yahoo_data *yd; |
7651 | 159 |
160 xfer_data = xfer->data; | |
161 gc = xfer_data->gc; | |
7827 | 162 yd = gc->proto_data; |
7651 | 163 account = gaim_connection_get_account(gc); |
164 | |
165 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { | |
10361 | 166 if (0 && gaim_xfer_get_size(xfer) >= 1048577) { |
7651 | 167 gaim_notify_error(gc, NULL, _("File Transfer Aborted"), |
8282 | 168 _("Gaim cannot send files over Yahoo! that are bigger than " |
169 "One Megabyte (1,048,576 bytes).")); | |
170 gaim_xfer_cancel_local(xfer); | |
171 } else { | |
9164 | 172 if (yd->jp) { |
173 if (gaim_proxy_connect(account, gaim_account_get_string(account, "xferjp_host", YAHOOJP_XFER_HOST), | |
174 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
175 yahoo_sendfile_connected, xfer) == -1) | |
176 { | |
177 gaim_notify_error(gc, NULL, _("File Transfer Aborted"), | |
178 _("Unable to establish file descriptor.")); | |
179 gaim_xfer_cancel_remote(xfer); | |
180 } | |
181 } else { | |
182 if (gaim_proxy_connect(account, gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST), | |
183 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
184 yahoo_sendfile_connected, xfer) == -1) | |
185 { | |
186 gaim_notify_error(gc, NULL, _("File Transfer Aborted"), | |
187 _("Unable to establish file descriptor.")); | |
188 gaim_xfer_cancel_remote(xfer); | |
189 } | |
8282 | 190 } |
7651 | 191 } |
192 } else { | |
193 xfer->fd = gaim_proxy_connect(account, xfer_data->host, xfer_data->port, | |
194 yahoo_receivefile_connected, xfer); | |
195 if (xfer->fd == -1) { | |
196 gaim_notify_error(gc, NULL, _("File Transfer Aborted"), | |
197 _("Unable to establish file descriptor.")); | |
198 gaim_xfer_cancel_remote(xfer); | |
199 } | |
200 } | |
201 } | |
202 | |
203 static void yahoo_xfer_start(GaimXfer *xfer) | |
204 { | |
205 /* We don't need to do anything here, do we? */ | |
206 } | |
207 | |
208 static void yahoo_xfer_end(GaimXfer *xfer) | |
209 { | |
210 GaimAccount *account; | |
211 struct yahoo_xfer_data *xfer_data; | |
212 | |
213 account = gaim_xfer_get_account(xfer); | |
214 xfer_data = xfer->data; | |
215 | |
216 | |
217 if (xfer_data) | |
218 yahoo_xfer_data_free(xfer_data); | |
219 xfer->data = NULL; | |
220 | |
221 } | |
222 | |
223 guint calculate_length(const gchar *l, size_t len) | |
224 { | |
225 int i; | |
226 | |
227 for (i = 0; i < len; i++) { | |
228 if (!g_ascii_isdigit(l[i])) | |
229 continue; | |
230 return strtol(l + i, NULL, 10); | |
231 } | |
232 return 0; | |
233 } | |
234 | |
235 | |
8231
f50c059b6384
[gaim-migrate @ 8954]
Christian Hammond <chipx86@chipx86.com>
parents:
8046
diff
changeset
|
236 ssize_t yahoo_xfer_read(char **buffer, GaimXfer *xfer) |
7651 | 237 { |
7710 | 238 gchar buf[4096]; |
7682 | 239 ssize_t len; |
7651 | 240 gchar *start = NULL; |
241 gchar *length; | |
242 gchar *end; | |
7710 | 243 int filelen; |
7651 | 244 struct yahoo_xfer_data *xd = xfer->data; |
245 | |
246 if (gaim_xfer_get_type(xfer) != GAIM_XFER_RECEIVE) { | |
247 return 0; | |
248 } | |
249 | |
250 len = read(xfer->fd, buf, sizeof(buf)); | |
251 | |
7682 | 252 if (len <= 0) { |
7710 | 253 if ((gaim_xfer_get_size(xfer) > 0) && |
9798 | 254 (gaim_xfer_get_bytes_sent(xfer) >= gaim_xfer_get_size(xfer))) { |
7682 | 255 gaim_xfer_set_completed(xfer, TRUE); |
9798 | 256 return 0; |
257 } else | |
258 return -1; | |
7651 | 259 } |
260 | |
261 | |
262 if (!xd->started) { | |
263 xd->rxqueue = g_realloc(xd->rxqueue, len + xd->rxlen); | |
264 memcpy(xd->rxqueue + xd->rxlen, buf, len); | |
265 xd->rxlen += len; | |
266 | |
267 length = g_strstr_len(xd->rxqueue, len, "Content-length:"); | |
268 if (length) { | |
269 end = g_strstr_len(length, length - xd->rxqueue, "\r\n"); | |
270 if (!end) | |
271 return 0; | |
7710 | 272 if ((filelen = calculate_length(length, len - (length - xd->rxqueue)))) |
273 gaim_xfer_set_size(xfer, filelen); | |
7651 | 274 } |
275 start = g_strstr_len(xd->rxqueue, len, "\r\n\r\n"); | |
276 if (start) | |
277 start += 4; | |
278 if (!start || start > (xd->rxqueue + len)) | |
279 return 0; | |
280 xd->started = TRUE; | |
281 | |
282 len -= (start - xd->rxqueue); | |
283 | |
284 *buffer = g_malloc(len); | |
285 memcpy(*buffer, start, len); | |
286 g_free(xd->rxqueue); | |
287 xd->rxqueue = NULL; | |
288 xd->rxlen = 0; | |
289 } else { | |
290 *buffer = g_malloc(len); | |
291 memcpy(*buffer, buf, len); | |
292 } | |
293 | |
294 return len; | |
295 } | |
296 | |
8231
f50c059b6384
[gaim-migrate @ 8954]
Christian Hammond <chipx86@chipx86.com>
parents:
8046
diff
changeset
|
297 ssize_t yahoo_xfer_write(const char *buffer, size_t size, GaimXfer *xfer) |
7651 | 298 { |
7710 | 299 ssize_t len; |
7651 | 300 struct yahoo_xfer_data *xd = xfer->data; |
301 | |
302 if (!xd) | |
9798 | 303 return -1; |
7651 | 304 |
305 if (gaim_xfer_get_type(xfer) != GAIM_XFER_SEND) { | |
9798 | 306 return -1; |
7651 | 307 } |
308 | |
309 len = write(xfer->fd, buffer, size); | |
310 | |
7710 | 311 if (len == -1) { |
312 if (gaim_xfer_get_bytes_sent(xfer) >= gaim_xfer_get_size(xfer)) | |
313 gaim_xfer_set_completed(xfer, TRUE); | |
314 if ((errno != EAGAIN) && (errno != EINTR)) | |
9798 | 315 return -1; |
7710 | 316 return 0; |
317 } | |
318 | |
319 if ((gaim_xfer_get_bytes_sent(xfer) + len) >= gaim_xfer_get_size(xfer)) | |
7651 | 320 gaim_xfer_set_completed(xfer, TRUE); |
321 | |
322 return len; | |
323 } | |
324 | |
325 static void yahoo_xfer_cancel_send(GaimXfer *xfer) | |
326 { | |
327 GaimAccount *account; | |
328 struct yahoo_xfer_data *xfer_data; | |
329 | |
330 xfer_data = xfer->data; | |
331 account = gaim_xfer_get_account(xfer); | |
332 | |
333 if (xfer_data) | |
334 yahoo_xfer_data_free(xfer_data); | |
335 xfer->data = NULL; | |
336 } | |
337 | |
338 static void yahoo_xfer_cancel_recv(GaimXfer *xfer) | |
339 { | |
340 GaimAccount *account; | |
341 struct yahoo_xfer_data *xfer_data; | |
342 | |
343 account = gaim_xfer_get_account(xfer); | |
344 xfer_data = xfer->data; | |
345 | |
346 if (xfer_data) | |
347 yahoo_xfer_data_free(xfer_data); | |
348 xfer->data = NULL; | |
349 } | |
350 | |
351 void yahoo_process_filetransfer(GaimConnection *gc, struct yahoo_packet *pkt) | |
352 { | |
353 char *from = NULL; | |
354 char *to = NULL; | |
355 char *msg = NULL; | |
356 char *url = NULL; | |
357 long expires = 0; | |
358 GaimXfer *xfer; | |
359 struct yahoo_xfer_data *xfer_data; | |
360 | |
361 char *service = NULL; | |
362 | |
363 char *filename = NULL; | |
364 unsigned long filesize = 0L; | |
365 | |
366 GSList *l; | |
367 | |
368 for (l = pkt->hash; l; l = l->next) { | |
369 struct yahoo_pair *pair = l->data; | |
370 | |
371 if (pair->key == 4) | |
372 from = pair->value; | |
373 if (pair->key == 5) | |
374 to = pair->value; | |
375 if (pair->key == 14) | |
376 msg = pair->value; | |
377 if (pair->key == 20) | |
378 url = pair->value; | |
379 if (pair->key == 38) | |
380 expires = strtol(pair->value, NULL, 10); | |
381 | |
382 if (pair->key == 27) | |
383 filename = pair->value; | |
384 if (pair->key == 28) | |
385 filesize = atol(pair->value); | |
386 | |
387 if (pair->key == 49) | |
388 service = pair->value; | |
389 } | |
390 | |
391 if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) { | |
10261 | 392 if (service && (strcmp("FILEXFER", service) != 0)) { |
7651 | 393 gaim_debug_misc("yahoo", "unhandled service 0x%02x", pkt->service); |
394 return; | |
395 } | |
396 } | |
397 | |
398 if (msg) { | |
399 char *tmp; | |
400 tmp = strchr(msg, '\006'); | |
401 if (tmp) | |
402 *tmp = '\0'; | |
403 } | |
404 | |
405 if (!url || !from) | |
406 return; | |
407 | |
408 | |
409 /* Setup the Yahoo-specific file transfer data */ | |
410 xfer_data = g_new0(struct yahoo_xfer_data, 1); | |
411 xfer_data->gc = gc; | |
9227
9171e528d7e5
[gaim-migrate @ 10023]
Christian Hammond <chipx86@chipx86.com>
parents:
9164
diff
changeset
|
412 if (!gaim_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) { |
7651 | 413 g_free(xfer_data); |
414 return; | |
415 } | |
416 | |
417 gaim_debug_misc("yahoo_filexfer", "Host is %s, port is %d, path is %s, and the full url was %s.\n", | |
418 xfer_data->host, xfer_data->port, xfer_data->path, url); | |
419 | |
420 /* Build the file transfer handle. */ | |
421 xfer = gaim_xfer_new(gc->account, GAIM_XFER_RECEIVE, from); | |
422 xfer->data = xfer_data; | |
423 | |
424 /* Set the info about the incoming file. */ | |
425 if (filename) | |
426 gaim_xfer_set_filename(xfer, filename); | |
427 else { | |
428 gchar *start, *end; | |
429 start = g_strrstr(xfer_data->path, "/"); | |
430 if (start) | |
431 start++; | |
432 end = g_strrstr(xfer_data->path, "?"); | |
433 if (start && *start && end) { | |
434 filename = g_strndup(start, end - start); | |
435 gaim_xfer_set_filename(xfer, filename); | |
436 g_free(filename); | |
437 filename = NULL; | |
438 } | |
439 } | |
440 | |
441 gaim_xfer_set_size(xfer, filesize); | |
442 | |
443 /* Setup our I/O op functions */ | |
444 gaim_xfer_set_init_fnc(xfer, yahoo_xfer_init); | |
445 gaim_xfer_set_start_fnc(xfer, yahoo_xfer_start); | |
446 gaim_xfer_set_end_fnc(xfer, yahoo_xfer_end); | |
447 gaim_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); | |
448 gaim_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); | |
449 gaim_xfer_set_read_fnc(xfer, yahoo_xfer_read); | |
450 gaim_xfer_set_write_fnc(xfer, yahoo_xfer_write); | |
451 | |
452 /* Now perform the request */ | |
453 gaim_xfer_request(xfer); | |
454 } | |
455 | |
456 void yahoo_send_file(GaimConnection *gc, const char *who, const char *file) | |
457 { | |
458 GaimXfer *xfer; | |
459 struct yahoo_xfer_data *xfer_data; | |
460 | |
9466 | 461 if (!who) |
7651 | 462 return; |
463 | |
464 xfer_data = g_new0(struct yahoo_xfer_data, 1); | |
465 xfer_data->gc = gc; | |
466 | |
467 | |
468 /* Build the file transfer handle. */ | |
469 xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who); | |
470 xfer->data = xfer_data; | |
471 | |
472 /* Setup our I/O op functions */ | |
473 gaim_xfer_set_init_fnc(xfer, yahoo_xfer_init); | |
474 gaim_xfer_set_start_fnc(xfer, yahoo_xfer_start); | |
475 gaim_xfer_set_end_fnc(xfer, yahoo_xfer_end); | |
476 gaim_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); | |
477 gaim_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); | |
478 gaim_xfer_set_read_fnc(xfer, yahoo_xfer_read); | |
479 gaim_xfer_set_write_fnc(xfer, yahoo_xfer_write); | |
480 | |
481 /* Now perform the request */ | |
9466 | 482 if (file) |
483 gaim_xfer_request_accepted(xfer, file); | |
484 else | |
485 gaim_xfer_request(xfer); | |
7651 | 486 } |