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
|
|
215 pkt_buf_len = yahoo_packet_build(pkt, 8, FALSE, &pkt_buf);
|
|
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 }
|