Mercurial > pidgin
annotate src/protocols/yahoo/yahoo_filexfer.c @ 10654:f2e86683cafc
[gaim-migrate @ 12182]
sf patch #1152664, from Richard Laager
This patches does three things:
First, it uses aliases in file transfer messages
whenever possible.
Second, it fixes the case where file transfer
completion messages are not showing for MSN.
Third, it makes the wording more consistent:
Canceled is used to describe cases when the file
transfer was actively canceled by either party.
Failed is used otherwise. Aborted is no longer
used at all. Previously, aborted was used in
some places while failed was used under the
same circumstances in other places. Also,
in the file transfer box, canceled was used in
one place for remotely or locally canceled
files while in another place in the same box
canceled was only used for locally canceled
files (failed was used for remotely canceled
files).
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sun, 06 Mar 2005 00:23:54 +0000 |
parents | 8fbab42659c2 |
children | ca3e0882d377 |
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) { | |
10654 | 69 gaim_xfer_error(GAIM_XFER_RECEIVE, gaim_xfer_get_account(xfer), |
70 xfer->who, _("Unable to connect.")); | |
7805 | 71 gaim_xfer_cancel_remote(xfer); |
7651 | 72 return; |
73 } | |
74 | |
75 xfer->fd = source; | |
76 gaim_xfer_start(xfer, source, NULL, 0); | |
77 | |
10651 | 78 buf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", |
79 xd->path, xd->host); | |
7651 | 80 write(xfer->fd, buf, strlen(buf)); |
81 g_free(buf); | |
82 | |
83 return; | |
84 } | |
85 | |
86 static void yahoo_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) | |
87 { | |
88 GaimXfer *xfer; | |
89 struct yahoo_xfer_data *xd; | |
90 struct yahoo_packet *pkt; | |
91 gchar *size, *post, *buf; | |
10576 | 92 const char *host; |
10575 | 93 int content_length, port; |
7651 | 94 GaimConnection *gc; |
95 GaimAccount *account; | |
96 struct yahoo_data *yd; | |
7805 | 97 char *filename; |
7651 | 98 |
99 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | |
100 "AAA - in yahoo_sendfile_connected\n"); | |
101 if (!(xfer = data)) | |
102 return; | |
103 if (!(xd = xfer->data)) | |
104 return; | |
105 | |
106 gc = xd->gc; | |
107 account = gaim_connection_get_account(gc); | |
108 yd = gc->proto_data; | |
109 | |
110 | |
111 | |
112 if (source < 0) { | |
10654 | 113 gaim_xfer_error(GAIM_XFER_RECEIVE, gaim_xfer_get_account(xfer), |
114 xfer->who, _("Unable to connect.")); | |
7805 | 115 gaim_xfer_cancel_remote(xfer); |
7651 | 116 return; |
117 } | |
118 | |
119 xfer->fd = source; | |
120 gaim_xfer_start(xfer, source, NULL, 0); | |
121 | |
122 | |
123 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
124 | |
10111 | 125 size = g_strdup_printf("%" G_GSIZE_FORMAT, gaim_xfer_get_size(xfer)); |
7805 | 126 filename = g_path_get_basename(gaim_xfer_get_local_filename(xfer)); |
10394 | 127 |
128 yahoo_packet_hash(pkt, "sssss", 0, gaim_connection_get_display_name(gc), | |
129 5, xfer->who, 14, "", 27, filename, 28, size); | |
7651 | 130 |
131 content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt); | |
132 | |
133 buf = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t); | |
134 | |
10576 | 135 host = gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST); |
10575 | 136 port = gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT); |
137 post = g_strdup_printf("POST http://%s:%d/notifyft HTTP/1.0\r\n" | |
10111 | 138 "Content-length: %" G_GSIZE_FORMAT "\r\n" |
7651 | 139 "Host: %s:%d\r\n" |
140 "Cookie: %s\r\n" | |
141 "\r\n", | |
10576 | 142 host, port, content_length + 4 + gaim_xfer_get_size(xfer), host, port, buf); |
7651 | 143 write(xfer->fd, post, strlen(post)); |
144 | |
10392 | 145 yahoo_packet_send_special(pkt, xfer->fd, 8); |
7651 | 146 yahoo_packet_free(pkt); |
147 | |
148 write(xfer->fd, "29\xc0\x80", 4); | |
149 | |
150 g_free(size); | |
151 g_free(post); | |
152 g_free(buf); | |
7805 | 153 g_free(filename); |
7651 | 154 } |
155 | |
156 static void yahoo_xfer_init(GaimXfer *xfer) | |
157 { | |
158 struct yahoo_xfer_data *xfer_data; | |
159 GaimConnection *gc; | |
160 GaimAccount *account; | |
7827 | 161 struct yahoo_data *yd; |
7651 | 162 |
163 xfer_data = xfer->data; | |
164 gc = xfer_data->gc; | |
7827 | 165 yd = gc->proto_data; |
7651 | 166 account = gaim_connection_get_account(gc); |
167 | |
168 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { | |
10361 | 169 if (0 && gaim_xfer_get_size(xfer) >= 1048577) { |
10654 | 170 gaim_notify_error(gc, NULL, _("File Transfer Failed"), |
8282 | 171 _("Gaim cannot send files over Yahoo! that are bigger than " |
172 "One Megabyte (1,048,576 bytes).")); | |
173 gaim_xfer_cancel_local(xfer); | |
174 } else { | |
9164 | 175 if (yd->jp) { |
176 if (gaim_proxy_connect(account, gaim_account_get_string(account, "xferjp_host", YAHOOJP_XFER_HOST), | |
177 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
178 yahoo_sendfile_connected, xfer) == -1) | |
179 { | |
10654 | 180 gaim_notify_error(gc, NULL, _("File Transfer Failed"), |
9164 | 181 _("Unable to establish file descriptor.")); |
182 gaim_xfer_cancel_remote(xfer); | |
183 } | |
184 } else { | |
185 if (gaim_proxy_connect(account, gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST), | |
186 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
187 yahoo_sendfile_connected, xfer) == -1) | |
188 { | |
10654 | 189 gaim_notify_error(gc, NULL, _("File Transfer Failed"), |
9164 | 190 _("Unable to establish file descriptor.")); |
191 gaim_xfer_cancel_remote(xfer); | |
192 } | |
8282 | 193 } |
7651 | 194 } |
195 } else { | |
196 xfer->fd = gaim_proxy_connect(account, xfer_data->host, xfer_data->port, | |
197 yahoo_receivefile_connected, xfer); | |
198 if (xfer->fd == -1) { | |
10654 | 199 gaim_notify_error(gc, NULL, _("File Transfer Failed"), |
7651 | 200 _("Unable to establish file descriptor.")); |
201 gaim_xfer_cancel_remote(xfer); | |
202 } | |
203 } | |
204 } | |
205 | |
206 static void yahoo_xfer_start(GaimXfer *xfer) | |
207 { | |
208 /* We don't need to do anything here, do we? */ | |
209 } | |
210 | |
211 static void yahoo_xfer_end(GaimXfer *xfer) | |
212 { | |
213 GaimAccount *account; | |
214 struct yahoo_xfer_data *xfer_data; | |
215 | |
216 account = gaim_xfer_get_account(xfer); | |
217 xfer_data = xfer->data; | |
218 | |
219 | |
220 if (xfer_data) | |
221 yahoo_xfer_data_free(xfer_data); | |
222 xfer->data = NULL; | |
223 | |
224 } | |
225 | |
226 guint calculate_length(const gchar *l, size_t len) | |
227 { | |
228 int i; | |
229 | |
230 for (i = 0; i < len; i++) { | |
231 if (!g_ascii_isdigit(l[i])) | |
232 continue; | |
233 return strtol(l + i, NULL, 10); | |
234 } | |
235 return 0; | |
236 } | |
237 | |
238 | |
8231
f50c059b6384
[gaim-migrate @ 8954]
Christian Hammond <chipx86@chipx86.com>
parents:
8046
diff
changeset
|
239 ssize_t yahoo_xfer_read(char **buffer, GaimXfer *xfer) |
7651 | 240 { |
7710 | 241 gchar buf[4096]; |
7682 | 242 ssize_t len; |
7651 | 243 gchar *start = NULL; |
244 gchar *length; | |
245 gchar *end; | |
7710 | 246 int filelen; |
7651 | 247 struct yahoo_xfer_data *xd = xfer->data; |
248 | |
249 if (gaim_xfer_get_type(xfer) != GAIM_XFER_RECEIVE) { | |
250 return 0; | |
251 } | |
252 | |
253 len = read(xfer->fd, buf, sizeof(buf)); | |
254 | |
7682 | 255 if (len <= 0) { |
7710 | 256 if ((gaim_xfer_get_size(xfer) > 0) && |
9798 | 257 (gaim_xfer_get_bytes_sent(xfer) >= gaim_xfer_get_size(xfer))) { |
7682 | 258 gaim_xfer_set_completed(xfer, TRUE); |
9798 | 259 return 0; |
260 } else | |
261 return -1; | |
7651 | 262 } |
263 | |
264 | |
265 if (!xd->started) { | |
266 xd->rxqueue = g_realloc(xd->rxqueue, len + xd->rxlen); | |
267 memcpy(xd->rxqueue + xd->rxlen, buf, len); | |
268 xd->rxlen += len; | |
269 | |
270 length = g_strstr_len(xd->rxqueue, len, "Content-length:"); | |
10579 | 271 /* some proxies re-write this header, changing the capitalization :( |
272 * technically that's allowed since headers are case-insensitive | |
273 * [RFC 2616, section 4.2] */ | |
274 if (length == NULL) | |
275 length = g_strstr_len(xd->rxqueue, len, "Content-Length:"); | |
7651 | 276 if (length) { |
277 end = g_strstr_len(length, length - xd->rxqueue, "\r\n"); | |
278 if (!end) | |
279 return 0; | |
7710 | 280 if ((filelen = calculate_length(length, len - (length - xd->rxqueue)))) |
281 gaim_xfer_set_size(xfer, filelen); | |
7651 | 282 } |
283 start = g_strstr_len(xd->rxqueue, len, "\r\n\r\n"); | |
284 if (start) | |
285 start += 4; | |
286 if (!start || start > (xd->rxqueue + len)) | |
287 return 0; | |
288 xd->started = TRUE; | |
289 | |
290 len -= (start - xd->rxqueue); | |
291 | |
292 *buffer = g_malloc(len); | |
293 memcpy(*buffer, start, len); | |
294 g_free(xd->rxqueue); | |
295 xd->rxqueue = NULL; | |
296 xd->rxlen = 0; | |
297 } else { | |
298 *buffer = g_malloc(len); | |
299 memcpy(*buffer, buf, len); | |
300 } | |
301 | |
302 return len; | |
303 } | |
304 | |
8231
f50c059b6384
[gaim-migrate @ 8954]
Christian Hammond <chipx86@chipx86.com>
parents:
8046
diff
changeset
|
305 ssize_t yahoo_xfer_write(const char *buffer, size_t size, GaimXfer *xfer) |
7651 | 306 { |
7710 | 307 ssize_t len; |
7651 | 308 struct yahoo_xfer_data *xd = xfer->data; |
309 | |
310 if (!xd) | |
9798 | 311 return -1; |
7651 | 312 |
313 if (gaim_xfer_get_type(xfer) != GAIM_XFER_SEND) { | |
9798 | 314 return -1; |
7651 | 315 } |
316 | |
317 len = write(xfer->fd, buffer, size); | |
318 | |
7710 | 319 if (len == -1) { |
320 if (gaim_xfer_get_bytes_sent(xfer) >= gaim_xfer_get_size(xfer)) | |
321 gaim_xfer_set_completed(xfer, TRUE); | |
322 if ((errno != EAGAIN) && (errno != EINTR)) | |
9798 | 323 return -1; |
7710 | 324 return 0; |
325 } | |
326 | |
327 if ((gaim_xfer_get_bytes_sent(xfer) + len) >= gaim_xfer_get_size(xfer)) | |
7651 | 328 gaim_xfer_set_completed(xfer, TRUE); |
329 | |
330 return len; | |
331 } | |
332 | |
333 static void yahoo_xfer_cancel_send(GaimXfer *xfer) | |
334 { | |
335 GaimAccount *account; | |
336 struct yahoo_xfer_data *xfer_data; | |
337 | |
338 xfer_data = xfer->data; | |
339 account = gaim_xfer_get_account(xfer); | |
340 | |
341 if (xfer_data) | |
342 yahoo_xfer_data_free(xfer_data); | |
343 xfer->data = NULL; | |
344 } | |
345 | |
346 static void yahoo_xfer_cancel_recv(GaimXfer *xfer) | |
347 { | |
348 GaimAccount *account; | |
349 struct yahoo_xfer_data *xfer_data; | |
350 | |
351 account = gaim_xfer_get_account(xfer); | |
352 xfer_data = xfer->data; | |
353 | |
354 if (xfer_data) | |
355 yahoo_xfer_data_free(xfer_data); | |
356 xfer->data = NULL; | |
357 } | |
358 | |
359 void yahoo_process_filetransfer(GaimConnection *gc, struct yahoo_packet *pkt) | |
360 { | |
361 char *from = NULL; | |
362 char *to = NULL; | |
363 char *msg = NULL; | |
364 char *url = NULL; | |
365 long expires = 0; | |
366 GaimXfer *xfer; | |
367 struct yahoo_xfer_data *xfer_data; | |
368 | |
369 char *service = NULL; | |
370 | |
371 char *filename = NULL; | |
372 unsigned long filesize = 0L; | |
373 | |
374 GSList *l; | |
375 | |
376 for (l = pkt->hash; l; l = l->next) { | |
377 struct yahoo_pair *pair = l->data; | |
378 | |
379 if (pair->key == 4) | |
380 from = pair->value; | |
381 if (pair->key == 5) | |
382 to = pair->value; | |
383 if (pair->key == 14) | |
384 msg = pair->value; | |
385 if (pair->key == 20) | |
386 url = pair->value; | |
387 if (pair->key == 38) | |
388 expires = strtol(pair->value, NULL, 10); | |
389 | |
390 if (pair->key == 27) | |
391 filename = pair->value; | |
392 if (pair->key == 28) | |
393 filesize = atol(pair->value); | |
394 | |
395 if (pair->key == 49) | |
396 service = pair->value; | |
397 } | |
398 | |
399 if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) { | |
10261 | 400 if (service && (strcmp("FILEXFER", service) != 0)) { |
7651 | 401 gaim_debug_misc("yahoo", "unhandled service 0x%02x", pkt->service); |
402 return; | |
403 } | |
404 } | |
405 | |
406 if (msg) { | |
407 char *tmp; | |
408 tmp = strchr(msg, '\006'); | |
409 if (tmp) | |
410 *tmp = '\0'; | |
411 } | |
412 | |
413 if (!url || !from) | |
414 return; | |
415 | |
416 | |
417 /* Setup the Yahoo-specific file transfer data */ | |
418 xfer_data = g_new0(struct yahoo_xfer_data, 1); | |
419 xfer_data->gc = gc; | |
9227
9171e528d7e5
[gaim-migrate @ 10023]
Christian Hammond <chipx86@chipx86.com>
parents:
9164
diff
changeset
|
420 if (!gaim_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) { |
7651 | 421 g_free(xfer_data); |
422 return; | |
423 } | |
424 | |
425 gaim_debug_misc("yahoo_filexfer", "Host is %s, port is %d, path is %s, and the full url was %s.\n", | |
426 xfer_data->host, xfer_data->port, xfer_data->path, url); | |
427 | |
428 /* Build the file transfer handle. */ | |
429 xfer = gaim_xfer_new(gc->account, GAIM_XFER_RECEIVE, from); | |
430 xfer->data = xfer_data; | |
431 | |
432 /* Set the info about the incoming file. */ | |
433 if (filename) | |
434 gaim_xfer_set_filename(xfer, filename); | |
435 else { | |
436 gchar *start, *end; | |
437 start = g_strrstr(xfer_data->path, "/"); | |
438 if (start) | |
439 start++; | |
440 end = g_strrstr(xfer_data->path, "?"); | |
441 if (start && *start && end) { | |
442 filename = g_strndup(start, end - start); | |
443 gaim_xfer_set_filename(xfer, filename); | |
444 g_free(filename); | |
445 filename = NULL; | |
446 } | |
447 } | |
448 | |
449 gaim_xfer_set_size(xfer, filesize); | |
450 | |
451 /* Setup our I/O op functions */ | |
452 gaim_xfer_set_init_fnc(xfer, yahoo_xfer_init); | |
453 gaim_xfer_set_start_fnc(xfer, yahoo_xfer_start); | |
454 gaim_xfer_set_end_fnc(xfer, yahoo_xfer_end); | |
455 gaim_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); | |
456 gaim_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); | |
457 gaim_xfer_set_read_fnc(xfer, yahoo_xfer_read); | |
458 gaim_xfer_set_write_fnc(xfer, yahoo_xfer_write); | |
459 | |
460 /* Now perform the request */ | |
461 gaim_xfer_request(xfer); | |
462 } | |
463 | |
464 void yahoo_send_file(GaimConnection *gc, const char *who, const char *file) | |
465 { | |
466 GaimXfer *xfer; | |
467 struct yahoo_xfer_data *xfer_data; | |
468 | |
9466 | 469 if (!who) |
7651 | 470 return; |
471 | |
472 xfer_data = g_new0(struct yahoo_xfer_data, 1); | |
473 xfer_data->gc = gc; | |
474 | |
475 | |
476 /* Build the file transfer handle. */ | |
477 xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who); | |
478 xfer->data = xfer_data; | |
479 | |
480 /* Setup our I/O op functions */ | |
481 gaim_xfer_set_init_fnc(xfer, yahoo_xfer_init); | |
482 gaim_xfer_set_start_fnc(xfer, yahoo_xfer_start); | |
483 gaim_xfer_set_end_fnc(xfer, yahoo_xfer_end); | |
484 gaim_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); | |
485 gaim_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); | |
486 gaim_xfer_set_read_fnc(xfer, yahoo_xfer_read); | |
487 gaim_xfer_set_write_fnc(xfer, yahoo_xfer_write); | |
488 | |
489 /* Now perform the request */ | |
9466 | 490 if (file) |
491 gaim_xfer_request_accepted(xfer, file); | |
492 else | |
493 gaim_xfer_request(xfer); | |
7651 | 494 } |