Mercurial > pidgin.yaz
annotate libgaim/protocols/yahoo/yahoo_filexfer.c @ 14446:1bee09450652
[gaim-migrate @ 17160]
This patch was mentioned by Mark on gaim-devel; Tim replied, "That sounds good. As long as they're both #define's I can easily change." which they are :)
Yahoo! Japan appears to not support - or at least not support in its current iteration -- the new Yahoo protocol version (0x000f), disconnecting us immediately if we send it. When connecting to Yahoo Japan, we now send the old version, (0x000c).
committer: Tailor Script <tailor@pidgin.im>
author | Evan Schoenberg <evan.s@dreskin.net> |
---|---|
date | Mon, 04 Sep 2006 21:58:49 +0000 |
parents | 60b1bc8dbf37 |
children | 118fd0dc5b6e |
rev | line source |
---|---|
14192 | 1 /* |
2 * @file yahoo_filexfer.c Yahoo Filetransfer | |
3 * | |
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. | |
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" | |
31 #include "yahoo_packet.h" | |
32 #include "yahoo_filexfer.h" | |
33 #include "yahoo_doodle.h" | |
34 | |
35 struct yahoo_xfer_data { | |
36 gchar *host; | |
37 gchar *path; | |
38 int port; | |
39 GaimConnection *gc; | |
40 long expires; | |
41 gboolean started; | |
42 gchar *txbuf; | |
43 gsize txbuflen; | |
44 gsize txbuf_written; | |
45 guint tx_handler; | |
46 gchar *rxqueue; | |
47 guint rxlen; | |
48 }; | |
49 | |
50 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) | |
51 { | |
52 g_free(xd->host); | |
53 g_free(xd->path); | |
54 g_free(xd->txbuf); | |
55 if (xd->tx_handler) | |
56 gaim_input_remove(xd->tx_handler); | |
57 g_free(xd); | |
58 } | |
59 | |
60 static void yahoo_receivefile_send_cb(gpointer data, gint source, GaimInputCondition condition) | |
61 { | |
62 GaimXfer *xfer; | |
63 struct yahoo_xfer_data *xd; | |
64 int remaining, written; | |
65 | |
66 xfer = data; | |
67 xd = xfer->data; | |
68 | |
69 remaining = xd->txbuflen - xd->txbuf_written; | |
70 written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining); | |
71 | |
72 if (written < 0 && errno == EAGAIN) | |
73 written = 0; | |
74 else if (written <= 0) { | |
75 gaim_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno); | |
76 gaim_xfer_cancel_remote(xfer); | |
77 return; | |
78 } | |
79 | |
80 if (written < remaining) { | |
81 xd->txbuf_written += written; | |
82 return; | |
83 } | |
84 | |
85 gaim_input_remove(xd->tx_handler); | |
86 xd->tx_handler = 0; | |
87 g_free(xd->txbuf); | |
88 xd->txbuf = NULL; | |
89 xd->txbuflen = 0; | |
90 | |
91 gaim_xfer_start(xfer, source, NULL, 0); | |
92 | |
93 } | |
94 | |
95 static void yahoo_receivefile_connected(gpointer data, gint source, const gchar *error_message) | |
96 { | |
97 GaimXfer *xfer; | |
98 struct yahoo_xfer_data *xd; | |
99 | |
100 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | |
101 "AAA - in yahoo_receivefile_connected\n"); | |
102 if (!(xfer = data)) | |
103 return; | |
104 if (!(xd = xfer->data)) | |
105 return; | |
106 if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) { | |
107 gaim_xfer_error(GAIM_XFER_RECEIVE, gaim_xfer_get_account(xfer), | |
108 xfer->who, _("Unable to connect.")); | |
109 gaim_xfer_cancel_remote(xfer); | |
110 return; | |
111 } | |
112 | |
113 xfer->fd = source; | |
114 | |
115 /* The first time we get here, assemble the tx buffer */ | |
116 if (xd->txbuflen == 0) { | |
117 xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", | |
118 xd->path, xd->host); | |
119 xd->txbuflen = strlen(xd->txbuf); | |
120 xd->txbuf_written = 0; | |
121 } | |
122 | |
123 if (!xd->tx_handler) | |
124 { | |
125 xd->tx_handler = gaim_input_add(source, GAIM_INPUT_WRITE, | |
126 yahoo_receivefile_send_cb, xfer); | |
127 yahoo_receivefile_send_cb(xfer, source, GAIM_INPUT_WRITE); | |
128 } | |
129 } | |
130 | |
131 static void yahoo_sendfile_send_cb(gpointer data, gint source, GaimInputCondition condition) | |
132 { | |
133 GaimXfer *xfer; | |
134 struct yahoo_xfer_data *xd; | |
135 int written, remaining; | |
136 | |
137 xfer = data; | |
138 xd = xfer->data; | |
139 | |
140 remaining = xd->txbuflen - xd->txbuf_written; | |
141 written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining); | |
142 | |
143 if (written < 0 && errno == EAGAIN) | |
144 written = 0; | |
145 else if (written <= 0) { | |
146 gaim_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno); | |
147 gaim_xfer_cancel_remote(xfer); | |
148 return; | |
149 } | |
150 | |
151 if (written < remaining) { | |
152 xd->txbuf_written += written; | |
153 return; | |
154 } | |
155 | |
156 gaim_input_remove(xd->tx_handler); | |
157 xd->tx_handler = 0; | |
158 g_free(xd->txbuf); | |
159 xd->txbuf = NULL; | |
160 xd->txbuflen = 0; | |
161 | |
162 gaim_xfer_start(xfer, source, NULL, 0); | |
163 } | |
164 | |
165 static void yahoo_sendfile_connected(gpointer data, gint source, const gchar *error_message) | |
166 { | |
167 GaimXfer *xfer; | |
168 struct yahoo_xfer_data *xd; | |
169 struct yahoo_packet *pkt; | |
170 gchar *size, *filename, *encoded_filename, *header; | |
171 guchar *pkt_buf; | |
172 const char *host; | |
173 int port; | |
174 size_t content_length, header_len, pkt_buf_len; | |
175 GaimConnection *gc; | |
176 GaimAccount *account; | |
177 struct yahoo_data *yd; | |
178 | |
179 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | |
180 "AAA - in yahoo_sendfile_connected\n"); | |
181 if (!(xfer = data)) | |
182 return; | |
183 if (!(xd = xfer->data)) | |
184 return; | |
185 | |
186 if (source < 0) { | |
187 gaim_xfer_error(GAIM_XFER_RECEIVE, gaim_xfer_get_account(xfer), | |
188 xfer->who, _("Unable to connect.")); | |
189 gaim_xfer_cancel_remote(xfer); | |
190 return; | |
191 } | |
192 | |
193 xfer->fd = source; | |
194 | |
195 /* Assemble the tx buffer */ | |
196 gc = xd->gc; | |
197 account = gaim_connection_get_account(gc); | |
198 yd = gc->proto_data; | |
199 | |
200 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER, | |
201 YAHOO_STATUS_AVAILABLE, yd->session_id); | |
202 | |
203 size = g_strdup_printf("%" G_GSIZE_FORMAT, gaim_xfer_get_size(xfer)); | |
204 filename = g_path_get_basename(gaim_xfer_get_local_filename(xfer)); | |
205 encoded_filename = yahoo_string_encode(gc, filename, NULL); | |
206 | |
207 yahoo_packet_hash(pkt, "sssss", 0, gaim_connection_get_display_name(gc), | |
208 5, xfer->who, 14, "", 27, encoded_filename, 28, size); | |
209 g_free(size); | |
210 g_free(encoded_filename); | |
211 g_free(filename); | |
212 | |
213 content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt); | |
214 | |
14446
1bee09450652
[gaim-migrate @ 17160]
Evan Schoenberg <evan.s@dreskin.net>
parents:
14192
diff
changeset
|
215 pkt_buf_len = yahoo_packet_build(pkt, 8, FALSE, yd->jp, &pkt_buf); |
14192 | 216 yahoo_packet_free(pkt); |
217 | |
218 host = gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST); | |
219 port = gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT); | |
220 header = g_strdup_printf( | |
221 "POST http://%s:%d/notifyft HTTP/1.0\r\n" | |
222 "Content-length: %" G_GSIZE_FORMAT "\r\n" | |
223 "Host: %s:%d\r\n" | |
224 "Cookie: Y=%s; T=%s\r\n" | |
225 "\r\n", | |
226 host, port, content_length + 4 + gaim_xfer_get_size(xfer), | |
227 host, port, yd->cookie_y, yd->cookie_t); | |
228 | |
229 header_len = strlen(header); | |
230 | |
231 xd->txbuflen = header_len + pkt_buf_len + 4; | |
232 xd->txbuf = g_malloc(xd->txbuflen); | |
233 | |
234 memcpy(xd->txbuf, header, header_len); | |
235 g_free(header); | |
236 memcpy(xd->txbuf + header_len, pkt_buf, pkt_buf_len); | |
237 g_free(pkt_buf); | |
238 memcpy(xd->txbuf + header_len + pkt_buf_len, "29\xc0\x80", 4); | |
239 | |
240 xd->txbuf_written = 0; | |
241 | |
242 if (xd->tx_handler == 0) | |
243 { | |
244 xd->tx_handler = gaim_input_add(source, GAIM_INPUT_WRITE, | |
245 yahoo_sendfile_send_cb, xfer); | |
246 yahoo_sendfile_send_cb(xfer, source, GAIM_INPUT_WRITE); | |
247 } | |
248 } | |
249 | |
250 static void yahoo_xfer_init(GaimXfer *xfer) | |
251 { | |
252 struct yahoo_xfer_data *xfer_data; | |
253 GaimConnection *gc; | |
254 GaimAccount *account; | |
255 struct yahoo_data *yd; | |
256 | |
257 xfer_data = xfer->data; | |
258 gc = xfer_data->gc; | |
259 yd = gc->proto_data; | |
260 account = gaim_connection_get_account(gc); | |
261 | |
262 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { | |
263 if (yd->jp) { | |
264 if (gaim_proxy_connect(account, gaim_account_get_string(account, "xferjp_host", YAHOOJP_XFER_HOST), | |
265 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
266 yahoo_sendfile_connected, xfer) == NULL) | |
267 { | |
268 gaim_notify_error(gc, NULL, _("File Transfer Failed"), | |
269 _("Unable to establish file descriptor.")); | |
270 gaim_xfer_cancel_remote(xfer); | |
271 } | |
272 } else { | |
273 if (gaim_proxy_connect(account, gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST), | |
274 gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT), | |
275 yahoo_sendfile_connected, xfer) == NULL) | |
276 { | |
277 gaim_notify_error(gc, NULL, _("File Transfer Failed"), | |
278 _("Unable to establish file descriptor.")); | |
279 gaim_xfer_cancel_remote(xfer); | |
280 } | |
281 } | |
282 } else { | |
283 /* TODO: Using xfer->fd like this is probably a bad thing... */ | |
284 if (gaim_proxy_connect(account, xfer_data->host, xfer_data->port, | |
285 yahoo_receivefile_connected, xfer) == NULL) | |
286 xfer->fd = -1; | |
287 else | |
288 xfer->fd = 0; | |
289 if (xfer->fd == -1) { | |
290 gaim_notify_error(gc, NULL, _("File Transfer Failed"), | |
291 _("Unable to establish file descriptor.")); | |
292 gaim_xfer_cancel_remote(xfer); | |
293 } | |
294 } | |
295 } | |
296 | |
297 static void yahoo_xfer_start(GaimXfer *xfer) | |
298 { | |
299 /* We don't need to do anything here, do we? */ | |
300 } | |
301 | |
302 static void yahoo_xfer_end(GaimXfer *xfer) | |
303 { | |
304 struct yahoo_xfer_data *xfer_data; | |
305 | |
306 xfer_data = xfer->data; | |
307 | |
308 if (xfer_data) | |
309 yahoo_xfer_data_free(xfer_data); | |
310 xfer->data = NULL; | |
311 | |
312 } | |
313 | |
314 static guint calculate_length(const gchar *l, size_t len) | |
315 { | |
316 int i; | |
317 | |
318 for (i = 0; i < len; i++) { | |
319 if (!g_ascii_isdigit(l[i])) | |
320 continue; | |
321 return strtol(l + i, NULL, 10); | |
322 } | |
323 return 0; | |
324 } | |
325 | |
326 static gssize yahoo_xfer_read(guchar **buffer, GaimXfer *xfer) | |
327 { | |
328 gchar buf[4096]; | |
329 gssize len; | |
330 gchar *start = NULL; | |
331 gchar *length; | |
332 gchar *end; | |
333 int filelen; | |
334 struct yahoo_xfer_data *xd = xfer->data; | |
335 | |
336 if (gaim_xfer_get_type(xfer) != GAIM_XFER_RECEIVE) { | |
337 return 0; | |
338 } | |
339 | |
340 len = read(xfer->fd, buf, sizeof(buf)); | |
341 | |
342 if (len <= 0) { | |
343 if ((gaim_xfer_get_size(xfer) > 0) && | |
344 (gaim_xfer_get_bytes_sent(xfer) >= gaim_xfer_get_size(xfer))) { | |
345 gaim_xfer_set_completed(xfer, TRUE); | |
346 return 0; | |
347 } else | |
348 return -1; | |
349 } | |
350 | |
351 if (!xd->started) { | |
352 xd->rxqueue = g_realloc(xd->rxqueue, len + xd->rxlen); | |
353 memcpy(xd->rxqueue + xd->rxlen, buf, len); | |
354 xd->rxlen += len; | |
355 | |
356 length = g_strstr_len(xd->rxqueue, len, "Content-length:"); | |
357 /* some proxies re-write this header, changing the capitalization :( | |
358 * technically that's allowed since headers are case-insensitive | |
359 * [RFC 2616, section 4.2] */ | |
360 if (length == NULL) | |
361 length = g_strstr_len(xd->rxqueue, len, "Content-Length:"); | |
362 if (length) { | |
363 end = g_strstr_len(length, length - xd->rxqueue, "\r\n"); | |
364 if (!end) | |
365 return 0; | |
366 if ((filelen = calculate_length(length, len - (length - xd->rxqueue)))) | |
367 gaim_xfer_set_size(xfer, filelen); | |
368 } | |
369 start = g_strstr_len(xd->rxqueue, len, "\r\n\r\n"); | |
370 if (start) | |
371 start += 4; | |
372 if (!start || start > (xd->rxqueue + len)) | |
373 return 0; | |
374 xd->started = TRUE; | |
375 | |
376 len -= (start - xd->rxqueue); | |
377 | |
378 *buffer = g_malloc(len); | |
379 memcpy(*buffer, start, len); | |
380 g_free(xd->rxqueue); | |
381 xd->rxqueue = NULL; | |
382 xd->rxlen = 0; | |
383 } else { | |
384 *buffer = g_malloc(len); | |
385 memcpy(*buffer, buf, len); | |
386 } | |
387 | |
388 return len; | |
389 } | |
390 | |
391 static gssize yahoo_xfer_write(const guchar *buffer, size_t size, GaimXfer *xfer) | |
392 { | |
393 gssize len; | |
394 struct yahoo_xfer_data *xd = xfer->data; | |
395 | |
396 if (!xd) | |
397 return -1; | |
398 | |
399 if (gaim_xfer_get_type(xfer) != GAIM_XFER_SEND) { | |
400 return -1; | |
401 } | |
402 | |
403 len = write(xfer->fd, buffer, size); | |
404 | |
405 if (len == -1) { | |
406 if (gaim_xfer_get_bytes_sent(xfer) >= gaim_xfer_get_size(xfer)) | |
407 gaim_xfer_set_completed(xfer, TRUE); | |
408 if ((errno != EAGAIN) && (errno != EINTR)) | |
409 return -1; | |
410 return 0; | |
411 } | |
412 | |
413 if ((gaim_xfer_get_bytes_sent(xfer) + len) >= gaim_xfer_get_size(xfer)) | |
414 gaim_xfer_set_completed(xfer, TRUE); | |
415 | |
416 return len; | |
417 } | |
418 | |
419 static void yahoo_xfer_cancel_send(GaimXfer *xfer) | |
420 { | |
421 struct yahoo_xfer_data *xfer_data; | |
422 | |
423 xfer_data = xfer->data; | |
424 | |
425 if (xfer_data) | |
426 yahoo_xfer_data_free(xfer_data); | |
427 xfer->data = NULL; | |
428 } | |
429 | |
430 static void yahoo_xfer_cancel_recv(GaimXfer *xfer) | |
431 { | |
432 struct yahoo_xfer_data *xfer_data; | |
433 | |
434 xfer_data = xfer->data; | |
435 | |
436 if (xfer_data) | |
437 yahoo_xfer_data_free(xfer_data); | |
438 xfer->data = NULL; | |
439 } | |
440 | |
441 void yahoo_process_p2pfilexfer(GaimConnection *gc, struct yahoo_packet *pkt) | |
442 { | |
443 GSList *l = pkt->hash; | |
444 | |
445 char *me = NULL; | |
446 char *from = NULL; | |
447 char *service = NULL; | |
448 char *message = NULL; | |
449 char *command = NULL; | |
450 char *imv = NULL; | |
451 char *unknown = NULL; | |
452 | |
453 /* Get all the necessary values from this new packet */ | |
454 while(l != NULL) | |
455 { | |
456 struct yahoo_pair *pair = l->data; | |
457 | |
458 if(pair->key == 5) /* Get who the packet is for */ | |
459 me = pair->value; | |
460 | |
461 if(pair->key == 4) /* Get who the packet is from */ | |
462 from = pair->value; | |
463 | |
464 if(pair->key == 49) /* Get the type of service */ | |
465 service = pair->value; | |
466 | |
467 if(pair->key == 14) /* Get the 'message' of the packet */ | |
468 message = pair->value; | |
469 | |
470 if(pair->key == 13) /* Get the command associated with this packet */ | |
471 command = pair->value; | |
472 | |
473 if(pair->key == 63) /* IMVironment name and version */ | |
474 imv = pair->value; | |
475 | |
476 if(pair->key == 64) /* Not sure, but it does vary with initialization of Doodle */ | |
477 unknown = pair->value; /* So, I'll keep it (for a little while atleast) */ | |
478 | |
479 l = l->next; | |
480 } | |
481 | |
482 /* If this packet is an IMVIRONMENT, handle it accordingly */ | |
483 if(service != NULL && imv != NULL && !strcmp(service, "IMVIRONMENT")) | |
484 { | |
485 /* Check for a Doodle packet and handle it accordingly */ | |
486 if(!strcmp(imv, "doodle;11")) | |
487 yahoo_doodle_process(gc, me, from, command, message); | |
488 | |
489 /* If an IMVIRONMENT packet comes without a specific imviroment name */ | |
490 if(!strcmp(imv, ";0")) | |
491 { | |
492 /* It is unfortunately time to close all IMVironments with the remote client */ | |
493 yahoo_doodle_command_got_shutdown(gc, from); | |
494 } | |
495 } | |
496 } | |
497 | |
498 void yahoo_process_filetransfer(GaimConnection *gc, struct yahoo_packet *pkt) | |
499 { | |
500 char *from = NULL; | |
501 char *to = NULL; | |
502 char *msg = NULL; | |
503 char *url = NULL; | |
504 char *imv = NULL; | |
505 long expires = 0; | |
506 GaimXfer *xfer; | |
507 struct yahoo_data *yd; | |
508 struct yahoo_xfer_data *xfer_data; | |
509 char *service = NULL; | |
510 char *filename = NULL; | |
511 unsigned long filesize = 0L; | |
512 GSList *l; | |
513 | |
514 yd = gc->proto_data; | |
515 | |
516 for (l = pkt->hash; l; l = l->next) { | |
517 struct yahoo_pair *pair = l->data; | |
518 | |
519 if (pair->key == 4) | |
520 from = pair->value; | |
521 if (pair->key == 5) | |
522 to = pair->value; | |
523 if (pair->key == 14) | |
524 msg = pair->value; | |
525 if (pair->key == 20) | |
526 url = pair->value; | |
527 if (pair->key == 38) | |
528 expires = strtol(pair->value, NULL, 10); | |
529 if (pair->key == 27) | |
530 filename = pair->value; | |
531 if (pair->key == 28) | |
532 filesize = atol(pair->value); | |
533 if (pair->key == 49) | |
534 service = pair->value; | |
535 if (pair->key == 63) | |
536 imv = pair->value; | |
537 } | |
538 | |
539 /* | |
540 * The remote user has changed their IMVironment. We | |
541 * record it for later use. | |
542 */ | |
543 if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) { | |
544 g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv)); | |
545 return; | |
546 } | |
547 | |
548 if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) { | |
549 if (service && (strcmp("FILEXFER", service) != 0)) { | |
550 gaim_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service); | |
551 return; | |
552 } | |
553 } | |
554 | |
555 if (msg) { | |
556 char *tmp; | |
557 tmp = strchr(msg, '\006'); | |
558 if (tmp) | |
559 *tmp = '\0'; | |
560 } | |
561 | |
562 if (!url || !from) | |
563 return; | |
564 | |
565 /* Setup the Yahoo-specific file transfer data */ | |
566 xfer_data = g_new0(struct yahoo_xfer_data, 1); | |
567 xfer_data->gc = gc; | |
568 if (!gaim_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) { | |
569 g_free(xfer_data); | |
570 return; | |
571 } | |
572 | |
573 gaim_debug_misc("yahoo_filexfer", "Host is %s, port is %d, path is %s, and the full url was %s.\n", | |
574 xfer_data->host, xfer_data->port, xfer_data->path, url); | |
575 | |
576 /* Build the file transfer handle. */ | |
577 xfer = gaim_xfer_new(gc->account, GAIM_XFER_RECEIVE, from); | |
578 xfer->data = xfer_data; | |
579 | |
580 /* Set the info about the incoming file. */ | |
581 if (filename) { | |
582 char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); | |
583 gaim_xfer_set_filename(xfer, utf8_filename); | |
584 g_free(utf8_filename); | |
585 } else { | |
586 gchar *start, *end; | |
587 start = g_strrstr(xfer_data->path, "/"); | |
588 if (start) | |
589 start++; | |
590 end = g_strrstr(xfer_data->path, "?"); | |
591 if (start && *start && end) { | |
592 char *utf8_filename; | |
593 filename = g_strndup(start, end - start); | |
594 utf8_filename = yahoo_string_decode(gc, filename, TRUE); | |
595 g_free(filename); | |
596 gaim_xfer_set_filename(xfer, utf8_filename); | |
597 g_free(utf8_filename); | |
598 filename = NULL; | |
599 } | |
600 } | |
601 | |
602 gaim_xfer_set_size(xfer, filesize); | |
603 | |
604 /* Setup our I/O op functions */ | |
605 gaim_xfer_set_init_fnc(xfer, yahoo_xfer_init); | |
606 gaim_xfer_set_start_fnc(xfer, yahoo_xfer_start); | |
607 gaim_xfer_set_end_fnc(xfer, yahoo_xfer_end); | |
608 gaim_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); | |
609 gaim_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); | |
610 gaim_xfer_set_read_fnc(xfer, yahoo_xfer_read); | |
611 gaim_xfer_set_write_fnc(xfer, yahoo_xfer_write); | |
612 | |
613 /* Now perform the request */ | |
614 gaim_xfer_request(xfer); | |
615 } | |
616 | |
617 GaimXfer *yahoo_new_xfer(GaimConnection *gc, const char *who) | |
618 { | |
619 GaimXfer *xfer; | |
620 struct yahoo_xfer_data *xfer_data; | |
621 | |
622 g_return_val_if_fail(who != NULL, NULL); | |
623 | |
624 xfer_data = g_new0(struct yahoo_xfer_data, 1); | |
625 xfer_data->gc = gc; | |
626 | |
627 /* Build the file transfer handle. */ | |
628 xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who); | |
629 xfer->data = xfer_data; | |
630 | |
631 /* Setup our I/O op functions */ | |
632 gaim_xfer_set_init_fnc(xfer, yahoo_xfer_init); | |
633 gaim_xfer_set_start_fnc(xfer, yahoo_xfer_start); | |
634 gaim_xfer_set_end_fnc(xfer, yahoo_xfer_end); | |
635 gaim_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); | |
636 gaim_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); | |
637 gaim_xfer_set_read_fnc(xfer, yahoo_xfer_read); | |
638 gaim_xfer_set_write_fnc(xfer, yahoo_xfer_write); | |
639 | |
640 return xfer; | |
641 } | |
642 | |
643 void yahoo_send_file(GaimConnection *gc, const char *who, const char *file) | |
644 { | |
645 GaimXfer *xfer = yahoo_new_xfer(gc, who); | |
646 | |
647 g_return_if_fail(xfer != NULL); | |
648 | |
649 /* Now perform the request */ | |
650 if (file) | |
651 gaim_xfer_request_accepted(xfer, file); | |
652 else | |
653 gaim_xfer_request(xfer); | |
654 } |