Migrate certificates, icons, logs to XDG dirs
[pidgin-git.git] / libpurple / protocols / yahoo / yahoo_filexfer.c
blobc2a4724a184606af6effaf486a135e3bc4c1214a
1 /*
2 * @file yahoo_filexfer.c Yahoo Filetransfer
4 * Purple 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.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 /* TODO: it needs further refactoring */
25 #include "internal.h"
27 #include "protocol.h"
28 #include "util.h"
29 #include "debug.h"
30 #include "http.h"
31 #include "network.h"
32 #include "notify.h"
33 #include "proxy.h"
34 #include "xfer.h"
35 #include "ymsg.h"
36 #include "yahoo_packet.h"
37 #include "yahoo_filexfer.h"
38 #include "yahoo_doodle.h"
39 #include "yahoo_friend.h"
41 #include <gio/gio.h>
43 struct yahoo_xfer_data {
44 gchar *url;
45 gboolean is_relay;
46 PurpleHttpConnection *hc;
48 gchar *host;
49 gchar *path;
50 PurpleConnection *gc;
51 gchar *xfer_peer_idstring;
52 gchar *xfer_idstring_for_relay;
53 int info_val_249;
55 /* contains all filenames, in case of multiple transfers, with the first
56 * one in the list being the current file's name (ymsg15) */
57 GSList *filename_list;
58 GSList *size_list; /* corresponds to filename_list, with size as **STRING** */
59 gboolean firstoflist;
62 static void
63 yahoo_xfer_data_free(struct yahoo_xfer_data *xd)
65 PurpleConnection *gc;
66 YahooData *yd;
67 PurpleXfer *xfer;
69 gc = xd->gc;
70 yd = purple_connection_get_protocol_data(gc);
72 /* remove entry from map */
73 if(xd->xfer_peer_idstring) {
74 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring);
75 if(xfer)
76 g_hash_table_remove(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring);
79 g_slist_free_full(xd->filename_list, g_free);
80 g_slist_free_full(xd->size_list, g_free);
82 g_free(xd->host);
83 g_free(xd->path);
84 g_free(xd->xfer_peer_idstring);
85 g_free(xd->xfer_idstring_for_relay);
86 g_free(xd);
89 static void
90 yahoo_xfer_start(PurpleXfer *xfer);
92 static PurpleXfer *
93 yahoo_ft_new_xfer_struct(PurpleConnection *gc, PurpleXferType type,
94 const char *who);
96 static PurpleHttpRequest *
97 yahoo_ft_new_req(struct yahoo_xfer_data *xd)
99 PurpleHttpRequest *req;
100 YahooData *yd;
102 g_return_val_if_fail(xd != NULL, NULL);
104 yd = purple_connection_get_protocol_data(xd->gc);
106 req = purple_http_request_new(xd->url);
107 purple_http_request_header_set(req, "User-Agent",
108 YAHOO_CLIENT_USERAGENT);
109 purple_http_request_header_set(req, "Cache-Control", "no-cache");
110 if (xd->is_relay) {
111 PurpleHttpCookieJar *cjar;
113 cjar = purple_http_request_get_cookie_jar(req);
114 purple_http_cookie_jar_set(cjar, "Y", yd->cookie_y);
115 purple_http_cookie_jar_set(cjar, "T", yd->cookie_t);
118 return req;
121 static gchar *
122 yahoo_ft_url_gen(PurpleXfer *xfer, const gchar *host)
124 struct yahoo_xfer_data *xfer_data;
125 PurpleAccount *account;
127 g_return_val_if_fail(host != NULL, NULL);
129 xfer_data = purple_xfer_get_protocol_data(xfer);
130 account = purple_connection_get_account(xfer_data->gc);
132 if (!xfer_data->is_relay) {
133 purple_debug_fatal("yahoo", "Non-relay FT aren't tested yet\n");
134 return NULL;
137 return g_strdup_printf("http://%s/relay?token=%s&sender=%s&recver=%s",
138 host, purple_url_encode(xfer_data->xfer_idstring_for_relay),
139 purple_normalize(account, purple_account_get_username(account)),
140 purple_xfer_get_remote_user(xfer));
143 static void
144 yahoo_xfer_init_15(PurpleXfer *xfer)
146 struct yahoo_xfer_data *xfer_data;
147 PurpleConnection *gc;
148 PurpleAccount *account;
149 YahooData *yd;
150 struct yahoo_packet *pkt;
152 xfer_data = purple_xfer_get_protocol_data(xfer);
153 gc = xfer_data->gc;
154 yd = purple_connection_get_protocol_data(gc);
155 account = purple_connection_get_account(gc);
157 if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND) {
158 gchar *filename;
159 filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
160 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
161 YAHOO_STATUS_AVAILABLE,
162 yd->session_id);
163 yahoo_packet_hash(pkt, "sssiiiisiii",
164 1, purple_normalize(account, purple_account_get_username(account)),
165 5, purple_xfer_get_remote_user(xfer),
166 265, xfer_data->xfer_peer_idstring,
167 222, 1,
168 266, 1,
169 302, 268,
170 300, 268,
171 27, filename,
172 28, (int)purple_xfer_get_size(xfer),
173 301, 268,
174 303, 268);
175 g_free(filename);
176 } else {
177 if(xfer_data->firstoflist == TRUE) {
178 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
179 YAHOO_STATUS_AVAILABLE, yd->session_id);
181 yahoo_packet_hash(pkt, "sssi",
182 1, purple_normalize(account, purple_account_get_username(account)),
183 5, purple_xfer_get_remote_user(xfer),
184 265, xfer_data->xfer_peer_idstring,
185 222, 3);
186 } else {
187 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
188 YAHOO_STATUS_AVAILABLE, yd->session_id);
190 yahoo_packet_hash(pkt, "sssi",
191 1, purple_normalize(account, purple_account_get_username(account)),
192 5, purple_xfer_get_remote_user(xfer),
193 265, xfer_data->xfer_peer_idstring,
194 271, 1);
197 yahoo_packet_send_and_free(pkt, yd);
200 static void
201 yahoo_xfer_cancel_send(PurpleXfer *xfer)
203 struct yahoo_xfer_data *xfer_data;
205 xfer_data = purple_xfer_get_protocol_data(xfer);
207 if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL)
209 PurpleConnection *gc;
210 PurpleAccount *account;
211 YahooData *yd;
212 struct yahoo_packet *pkt;
214 gc = xfer_data->gc;
215 yd = purple_connection_get_protocol_data(gc);
216 account = purple_connection_get_account(gc);
217 if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
219 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15,
220 YAHOO_STATUS_DISCONNECTED,
221 yd->session_id);
222 yahoo_packet_hash(pkt, "sssi",
223 1, purple_normalize(account, purple_account_get_username(account)),
224 5, purple_xfer_get_remote_user(xfer),
225 265, xfer_data->xfer_peer_idstring,
226 66, -1);
228 else
230 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
231 YAHOO_STATUS_AVAILABLE,
232 yd->session_id);
233 yahoo_packet_hash(pkt, "sssi",
234 1, purple_normalize(account, purple_account_get_username(account)),
235 5, purple_xfer_get_remote_user(xfer),
236 265, xfer_data->xfer_peer_idstring,
237 222, 2);
239 yahoo_packet_send_and_free(pkt, yd);
242 if (xfer_data) {
243 purple_http_conn_cancel(xfer_data->hc);
244 yahoo_xfer_data_free(xfer_data);
246 purple_xfer_set_protocol_data(xfer, NULL);
249 static void
250 yahoo_xfer_cancel_recv(PurpleXfer *xfer)
252 struct yahoo_xfer_data *xfer_data;
254 xfer_data = purple_xfer_get_protocol_data(xfer);
256 if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL)
259 PurpleConnection *gc;
260 PurpleAccount *account;
261 YahooData *yd;
262 struct yahoo_packet *pkt;
264 gc = xfer_data->gc;
265 yd = purple_connection_get_protocol_data(gc);
266 account = purple_connection_get_account(gc);
267 if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
269 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
270 YAHOO_STATUS_AVAILABLE,
271 yd->session_id);
272 yahoo_packet_hash(pkt, "sssi",
273 1, purple_normalize(account, purple_account_get_username(account)),
274 5, purple_xfer_get_remote_user(xfer),
275 265, xfer_data->xfer_peer_idstring,
276 222, 4);
278 else
280 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
281 YAHOO_STATUS_DISCONNECTED,
282 yd->session_id);
283 yahoo_packet_hash(pkt, "sssi",
284 1, purple_normalize(account, purple_account_get_username(account)),
285 5, purple_xfer_get_remote_user(xfer),
286 265, xfer_data->xfer_peer_idstring,
287 66, -1);
289 yahoo_packet_send_and_free(pkt, yd);
292 if (xfer_data) {
293 purple_http_conn_cancel(xfer_data->hc);
294 yahoo_xfer_data_free(xfer_data);
296 purple_xfer_set_protocol_data(xfer, NULL);
299 static void yahoo_xfer_end(PurpleXfer *xfer_old)
301 struct yahoo_xfer_data *xfer_data;
302 PurpleXfer *xfer = NULL;
303 PurpleConnection *gc;
304 YahooData *yd;
306 xfer_data = purple_xfer_get_protocol_data(xfer_old);
307 if(xfer_data
308 && purple_xfer_get_xfer_type(xfer_old) == PURPLE_XFER_TYPE_RECEIVE
309 && xfer_data->filename_list) {
310 /* removing top of filename & size list completely */
311 g_free( xfer_data->filename_list->data );
312 g_free( xfer_data->size_list->data );
314 xfer_data->filename_list->data = NULL;
315 xfer_data->size_list->data = NULL;
317 xfer_data->filename_list = g_slist_delete_link(xfer_data->filename_list, xfer_data->filename_list);
318 xfer_data->size_list = g_slist_delete_link(xfer_data->size_list, xfer_data->size_list);
320 /* if there are still more files */
321 if(xfer_data->filename_list)
323 gchar* filename;
324 char *utf8_filename;
326 filename = xfer_data->filename_list->data;
328 gc = xfer_data->gc;
329 yd = purple_connection_get_protocol_data(gc);
331 /* setting up xfer_data for next file's tranfer */
332 g_free(xfer_data->host);
333 g_free(xfer_data->path);
334 g_free(xfer_data->xfer_idstring_for_relay);
335 xfer_data->host = NULL;
336 xfer_data->host = NULL;
337 xfer_data->xfer_idstring_for_relay = NULL;
338 xfer_data->info_val_249 = 0;
339 xfer_data->firstoflist = FALSE;
341 /* Dereference xfer_data from old xfer */
342 purple_xfer_set_protocol_data(xfer_old, NULL);
344 /* Build the file transfer handle. */
345 xfer = yahoo_ft_new_xfer_struct(gc, PURPLE_XFER_TYPE_RECEIVE, purple_xfer_get_remote_user(xfer_old));
347 g_return_if_fail(xfer != NULL);
349 /* Set the info about the incoming file. */
350 utf8_filename = yahoo_string_decode(gc, filename, TRUE);
351 purple_xfer_set_filename(xfer, utf8_filename);
352 g_free(utf8_filename);
354 purple_xfer_set_protocol_data(xfer, xfer_data);
356 /* update map to current xfer */
357 g_hash_table_remove(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring);
358 g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer);
360 /* Now perform the request */
361 purple_xfer_request(xfer);
363 return;
366 if (xfer_data)
367 yahoo_xfer_data_free(xfer_data);
368 purple_xfer_set_protocol_data(xfer_old, NULL);
371 void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt)
373 GSList *l = pkt->hash;
375 char *me = NULL;
376 char *from = NULL;
377 char *service = NULL;
378 char *message = NULL;
379 char *command = NULL;
380 char *imv = NULL;
382 /* Get all the necessary values from this new packet */
383 while(l != NULL)
385 struct yahoo_pair *pair = l->data;
387 switch(pair->key) {
388 case 5: /* Get who the packet is for */
389 if (g_utf8_validate(pair->value, -1, NULL)) {
390 me = pair->value;
391 } else {
392 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
393 "got non-UTF-8 string for key %d\n", pair->key);
395 break;
396 case 4: /* Get who the packet is from */
397 if (g_utf8_validate(pair->value, -1, NULL)) {
398 from = pair->value;
399 } else {
400 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
401 "got non-UTF-8 string for key %d\n", pair->key);
403 break;
404 case 49: /* Get the type of service */
405 if (g_utf8_validate(pair->value, -1, NULL)) {
406 service = pair->value;
407 } else {
408 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
409 "got non-UTF-8 string for key %d\n", pair->key);
411 break;
412 case 14: /* Get the 'message' of the packet */
413 if (g_utf8_validate(pair->value, -1, NULL)) {
414 message = pair->value;
415 } else {
416 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
417 "got non-UTF-8 string for key %d\n", pair->key);
419 break;
420 case 13: /* Get the command associated with this packet */
421 if (g_utf8_validate(pair->value, -1, NULL)) {
422 command = pair->value;
423 } else {
424 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
425 "got non-UTF-8 string for key %d\n", pair->key);
427 break;
428 case 63: /* IMVironment name and version */
429 if (g_utf8_validate(pair->value, -1, NULL)) {
430 imv = pair->value;
431 } else {
432 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
433 "got non-UTF-8 string for key %d\n", pair->key);
435 break;
436 case 64: /* Not sure, but it does vary with initialization of Doodle */
437 break;
440 l = l->next;
443 /* If this packet is an IMVIRONMENT, handle it accordingly */
444 if(service != NULL && imv != NULL && !strcmp(service, "IMVIRONMENT"))
446 /* Check for a Doodle packet and handle it accordingly */
447 if(strstr(imv, "doodle;") != NULL)
448 yahoo_doodle_process(gc, me, from, command, message, imv);
450 /* If an IMVIRONMENT packet comes without a specific imviroment name */
451 if(!strcmp(imv, ";0"))
453 /* It is unfortunately time to close all IMVironments with the remote client */
454 yahoo_doodle_command_got_shutdown(gc, from);
459 PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who)
461 PurpleXfer *xfer;
462 struct yahoo_xfer_data *xfer_data;
464 g_return_val_if_fail(who != NULL, NULL);
466 xfer_data = g_new0(struct yahoo_xfer_data, 1);
467 xfer_data->gc = gc;
469 /* Build the file transfer handle. */
470 xfer = yahoo_ft_new_xfer_struct(gc, PURPLE_XFER_TYPE_SEND, who);
471 if (xfer == NULL)
473 g_free(xfer_data);
474 g_return_val_if_reached(NULL);
477 purple_xfer_set_protocol_data(xfer, xfer_data);
479 return xfer;
482 static gchar* yahoo_xfer_new_xfer_id(void)
484 gchar *ans;
485 int i,j;
486 ans = g_strnfill(24, ' ');
487 ans[23] = '$';
488 ans[22] = '$';
489 for(i = 0; i < 22; i++)
491 j = g_random_int_range (0,61);
492 if(j < 26)
493 ans[i] = j + 'a';
494 else if(j < 52)
495 ans[i] = j - 26 + 'A';
496 else
497 ans[i] = j - 52 + '0';
499 return ans;
502 static void
503 yahoo_xfer_dns_connected_15(GObject *sender, GAsyncResult *result, gpointer data)
505 GError *error = NULL;
506 GList *addresses = NULL;
507 GInetAddress *inet_address = NULL;
508 PurpleXfer *xfer;
509 struct yahoo_xfer_data *xd;
510 struct yahoo_packet *pkt;
511 PurpleConnection *gc;
512 PurpleAccount *account;
513 YahooData *yd;
514 gchar *filename;
516 if (!(xfer = data))
517 return;
518 if (!(xd = purple_xfer_get_protocol_data(xfer)))
519 return;
520 gc = xd->gc;
521 account = purple_connection_get_account(gc);
522 yd = purple_connection_get_protocol_data(gc);
524 addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(sender),
525 result, &error);
526 if(error) {
527 purple_debug_error("yahoo",
528 "Unable to find an IP address for relay.msg.yahoo.com : %s\n",
529 error->message);
531 purple_xfer_cancel_remote(xfer);
532 g_error_free(error);
534 return;
537 inet_address = G_INET_ADDRESS(addresses->data);
538 xd->host = g_inet_address_to_string(inet_address);
540 g_resolver_free_addresses(addresses);
542 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
543 filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
545 yahoo_packet_hash(pkt, "ssssis",
546 1, purple_normalize(account, purple_account_get_username(account)),
547 5, purple_xfer_get_remote_user(xfer),
548 265, xd->xfer_peer_idstring,
549 27, filename,
550 249, 3,
551 250, xd->host);
553 g_free(filename);
554 yahoo_packet_send_and_free(pkt, yd);
557 gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who)
559 if (!who)
560 return FALSE;
561 return TRUE;
564 void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file)
566 struct yahoo_xfer_data *xfer_data;
567 YahooData *yd = purple_connection_get_protocol_data(gc);
568 PurpleXfer *xfer = yahoo_new_xfer(gc, who);
570 g_return_if_fail(xfer != NULL);
572 #if 0
573 /* if we don't have a p2p connection, try establishing it now */
574 if( !g_hash_table_lookup(yd->peers, who) )
575 yahoo_send_p2p_pkt(gc, who, 0);
576 #endif
578 xfer_data = purple_xfer_get_protocol_data(xfer);
579 xfer_data->xfer_peer_idstring = yahoo_xfer_new_xfer_id();
580 g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer);
582 /* Now perform the request */
583 if (file)
584 purple_xfer_request_accepted(xfer, file);
585 else
586 purple_xfer_request(xfer);
589 void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt)
591 char *from = NULL;
592 char *imv = NULL;
593 long val_222 = 0L;
594 PurpleXfer *xfer;
595 YahooData *yd;
596 struct yahoo_xfer_data *xfer_data;
597 char *service = NULL;
598 char *filename = NULL;
599 char *xfer_peer_idstring = NULL;
600 char *utf8_filename;
601 GSList *l;
602 GSList *filename_list = NULL;
603 GSList *size_list = NULL;
604 int nooffiles = 0;
606 yd = purple_connection_get_protocol_data(gc);
608 for (l = pkt->hash; l; l = l->next) {
609 struct yahoo_pair *pair = l->data;
611 switch (pair->key) {
612 case 4:
613 if (g_utf8_validate(pair->value, -1, NULL)) {
614 from = pair->value;
615 } else {
616 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
617 "got non-UTF-8 string for key %d\n", pair->key);
619 break;
620 case 5: /* to */
621 break;
622 case 265:
623 if (g_utf8_validate(pair->value, -1, NULL)) {
624 xfer_peer_idstring = pair->value;
625 } else {
626 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
627 "got non-UTF-8 string for key %d\n", pair->key);
629 break;
630 case 27:
631 filename_list = g_slist_prepend(filename_list, g_strdup(pair->value));
632 nooffiles++;
633 break;
634 case 28:
635 if (g_utf8_validate(pair->value, -1, NULL)) {
636 size_list = g_slist_prepend(size_list, g_strdup(pair->value));
637 } else {
638 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
639 "got non-UTF-8 string for key %d\n", pair->key);
641 break;
642 case 222:
643 val_222 = atol(pair->value);
644 /* 1=send, 2=cancel, 3=accept, 4=reject */
645 break;
647 /* check for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
648 case 49:
649 if (g_utf8_validate(pair->value, -1, NULL)) {
650 service = pair->value;
651 } else {
652 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
653 "got non-UTF-8 string for key %d\n", pair->key);
655 break;
656 case 63:
657 if (g_utf8_validate(pair->value, -1, NULL)) {
658 imv = pair->value;
659 } else {
660 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
661 "got non-UTF-8 string for key %d\n", pair->key);
663 break;
664 /* end check */
668 if(!xfer_peer_idstring)
669 return;
671 if(val_222 == 2 || val_222 == 4)
673 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
674 xfer_peer_idstring);
675 if(!xfer) return;
676 purple_xfer_cancel_remote(xfer);
677 return;
679 if(val_222 == 3)
681 struct yahoo_xfer_data *xd;
682 GResolver *resolver;
684 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
685 xfer_peer_idstring);
686 if(!xfer)
687 return;
689 xd = purple_xfer_get_protocol_data(xfer);
692 * In the file trans info packet that we must reply with, we are
693 * supposed to mention the ip address...
694 * purple connect does not give me a way of finding the ip address...
695 * so, purple dnsquery is used... but retries, trying with next ip
696 * address etc. is not implemented..TODO
699 /* To send through p2p */
700 if( g_hash_table_lookup(yd->peers, from) ) {
701 /* send p2p file transfer information */
702 purple_debug_error("yahoo", "p2p file transfers are not supported yet\n");
703 /*xd->is_relay = FALSE;*/
705 xd->is_relay = TRUE;
707 resolver = g_resolver_get_default();
708 g_resolver_lookup_by_name_async(resolver,
709 YAHOO_XFER_RELAY_HOST,
710 NULL,
711 yahoo_xfer_dns_connected_15,
712 xfer);
713 g_object_unref(resolver);
715 return;
718 /* processing for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
720 * The remote user has changed their IMVironment. We
721 * record it for later use.
723 if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) {
724 g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv));
725 return;
728 if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
729 if (service && (strcmp("FILEXFER", service) != 0)) {
730 purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service);
731 return;
734 /* end processing */
736 if(!filename_list)
737 return;
738 /* have to change list into order in which client at other end sends */
739 filename_list = g_slist_reverse(filename_list);
740 size_list = g_slist_reverse(size_list);
741 filename = filename_list->data;
743 if(!from) return;
744 xfer_data = g_new0(struct yahoo_xfer_data, 1);
745 xfer_data->firstoflist = TRUE;
746 xfer_data->gc = gc;
747 xfer_data->xfer_peer_idstring = g_strdup(xfer_peer_idstring);
748 xfer_data->filename_list = filename_list;
749 xfer_data->size_list = size_list;
751 /* Build the file transfer handle. */
752 xfer = yahoo_ft_new_xfer_struct(gc, PURPLE_XFER_TYPE_RECEIVE, from);
754 /* Set the info about the incoming file. */
755 utf8_filename = yahoo_string_decode(gc, filename, TRUE);
756 purple_xfer_set_filename(xfer, utf8_filename);
757 g_free(utf8_filename);
759 purple_xfer_set_protocol_data(xfer, xfer_data);
761 g_hash_table_insert(yd->xfer_peer_idstring_map,
762 xfer_data->xfer_peer_idstring,
763 xfer);
765 if(nooffiles > 1) {
766 gchar* message;
767 message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), purple_xfer_get_remote_user(xfer), nooffiles);
768 purple_xfer_conversation_write(xfer, message, FALSE);
769 g_free(message);
771 /* Now perform the request */
772 purple_xfer_request(xfer);
775 static void
776 yahoo_process_filetrans_15_sent(PurpleHttpConnection *hc,
777 PurpleHttpResponse *response, gpointer _xfer)
779 PurpleXfer *xfer = _xfer;
780 struct yahoo_xfer_data *xd;
782 xd = purple_xfer_get_protocol_data(xfer);
784 xd->hc = NULL;
786 if (purple_xfer_is_cancelled(xfer))
787 return;
789 if (!purple_http_response_is_successful(response) ||
790 purple_xfer_get_bytes_remaining(xfer) > 0)
792 purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
793 purple_xfer_end(xfer);
794 } else {
795 purple_xfer_set_completed(xfer, TRUE);
796 purple_xfer_end(xfer);
800 static void
801 yahoo_process_filetrans_15_downloaded(PurpleHttpConnection *hc,
802 PurpleHttpResponse *response, gpointer _xfer)
804 PurpleXfer *xfer = _xfer;
805 struct yahoo_xfer_data *xd;
807 xd = purple_xfer_get_protocol_data(xfer);
809 xd->hc = NULL;
811 if (purple_xfer_is_cancelled(xfer))
812 return;
814 if (!purple_http_response_is_successful(response) ||
815 purple_xfer_get_bytes_remaining(xfer) > 0)
817 purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
818 purple_xfer_end(xfer);
819 } else {
820 purple_xfer_set_completed(xfer, TRUE);
821 purple_xfer_end(xfer);
825 static void
826 yahoo_process_filetrans_15_reader(PurpleHttpConnection *hc,
827 gchar *buffer, size_t offset, size_t length, gpointer _xfer,
828 PurpleHttpContentReaderCb cb)
830 PurpleXfer *xfer = _xfer;
831 gssize stored;
833 if ((goffset)offset != purple_xfer_get_bytes_sent(xfer)) {
834 purple_debug_warning("yahoo",
835 "offset != purple_xfer_get_bytes_sent(xfer)\n");
838 stored = purple_xfer_read_file(xfer, (guchar*)buffer, length);
840 cb(hc, (stored >= 0), (purple_xfer_get_bytes_remaining(xfer) == 0),
841 stored);
844 static gboolean
845 yahoo_process_filetrans_15_writer(PurpleHttpConnection *http_conn,
846 PurpleHttpResponse *response, const gchar *buffer, size_t offset,
847 size_t length, gpointer _xfer)
849 PurpleXfer *xfer = _xfer;
851 return purple_xfer_write_file(xfer, (const guchar*)buffer, length);
854 static void
855 yahoo_process_filetrans_15_watcher(PurpleHttpConnection *hc,
856 gboolean reading_state, int processed, int total, gpointer _xfer)
858 PurpleXfer *xfer = _xfer;
860 if (reading_state !=
861 (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE))
863 return;
866 purple_xfer_set_size(xfer, total);
867 purple_xfer_update_progress(xfer);
870 static void yahoo_xfer_start(PurpleXfer *xfer)
872 PurpleHttpRequest *req;
873 struct yahoo_xfer_data *xd;
875 xd = purple_xfer_get_protocol_data(xfer);
877 req = yahoo_ft_new_req(xd);
878 purple_http_request_set_timeout(req, -1);
879 if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE) {
880 purple_http_request_set_max_len(req, -1);
881 purple_http_request_set_response_writer(req,
882 yahoo_process_filetrans_15_writer, xfer);
883 xd->hc = purple_http_request(xd->gc, req,
884 yahoo_process_filetrans_15_downloaded, xfer);
885 } else {
886 purple_http_request_set_method(req, "POST");
887 /* YHttpServer quirk: it sets content-length, but doesn't sends
888 * any data. */
889 purple_http_request_set_max_len(req, 0);
890 purple_http_request_set_contents_reader(req,
891 yahoo_process_filetrans_15_reader,
892 purple_xfer_get_size(xfer), xfer);
893 xd->hc = purple_http_request(xd->gc, req,
894 yahoo_process_filetrans_15_sent, xfer);
897 purple_http_conn_set_progress_watcher(xd->hc,
898 yahoo_process_filetrans_15_watcher, xfer, -1);
899 purple_http_request_unref(req);
902 static void
903 yahoo_process_filetrans_info_15_got(PurpleHttpConnection *hc,
904 PurpleHttpResponse *response, gpointer _xfer)
906 PurpleXfer *xfer = _xfer;
907 struct yahoo_xfer_data *xd;
908 YahooData *yd;
910 xd = purple_xfer_get_protocol_data(xfer);
911 yd = purple_connection_get_protocol_data(xd->gc);
913 xd->hc = NULL;
915 if (!purple_http_response_is_successful(response)) {
916 purple_notify_error(yd->gc, NULL, _("File Transfer Failed"),
917 _("Unable to get file header."),
918 purple_request_cpar_from_connection(yd->gc));
919 purple_xfer_cancel_remote(xfer);
920 return;
923 purple_xfer_start(xfer, -1, NULL, 0);
926 void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt)
928 char *url = NULL;
929 long val_249 = 0;
930 long val_66 = 0;
931 PurpleXfer *xfer;
932 YahooData *yd;
933 struct yahoo_xfer_data *xfer_data;
934 char *xfer_peer_idstring = NULL;
935 char *xfer_idstring_for_relay = NULL;
936 GSList *l;
937 struct yahoo_packet *pkt_to_send;
939 yd = purple_connection_get_protocol_data(gc);
941 for (l = pkt->hash; l; l = l->next) {
942 struct yahoo_pair *pair = l->data;
944 switch (pair->key) {
945 case 4: /* from */
946 break;
947 case 5: /* to */
948 break;
949 case 265:
950 if (g_utf8_validate(pair->value, -1, NULL)) {
951 xfer_peer_idstring = pair->value;
952 } else {
953 purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
954 "got non-UTF-8 string for key %d\n", pair->key);
956 break;
957 case 27: /* filename */
958 break;
959 case 66:
960 val_66 = strtol(pair->value, NULL, 10);
961 break;
962 case 249:
963 val_249 = strtol(pair->value, NULL, 10);
964 /* 249 has value 1 or 2 when doing p2p transfer and value 3 when relaying through yahoo server */
965 break;
966 case 250:
967 if (g_utf8_validate(pair->value, -1, NULL)) {
968 url = pair->value; /* TODO: rename to host? what about non-relay? */
969 } else {
970 purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
971 "got non-UTF-8 string for key %d\n", pair->key);
973 break;
974 case 251:
975 if (g_utf8_validate(pair->value, -1, NULL)) {
976 xfer_idstring_for_relay = pair->value;
977 } else {
978 purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
979 "got non-UTF-8 string for key %d\n", pair->key);
981 break;
985 if(!xfer_peer_idstring)
986 return;
988 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring);
990 if(!xfer) return;
992 if(val_66==-1)
994 purple_xfer_cancel_remote(xfer);
995 return;
998 xfer_data = purple_xfer_get_protocol_data(xfer);
1000 xfer_data->info_val_249 = val_249;
1001 xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
1002 if(val_249 == 1 || val_249 == 3) {
1003 PurpleHttpRequest *req;
1004 PurpleAccount *account;
1006 xfer_data->is_relay = (val_249 == 3);
1008 if (!xfer_data->is_relay) {
1009 purple_debug_error("yahoo", "Non-relay FT aren't tested yet.\n");
1010 purple_notify_error(gc, NULL, _("File Transfer Failed"),
1011 _("Unsupported method"),
1012 purple_request_cpar_from_connection(gc));
1013 purple_xfer_cancel_remote(xfer);
1016 account = purple_connection_get_account(xfer_data->gc);
1018 xfer_data->url = yahoo_ft_url_gen(xfer, url);
1020 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
1021 YAHOO_STATUS_AVAILABLE, yd->session_id);
1022 yahoo_packet_hash(pkt_to_send, "ssssis",
1023 1, purple_normalize(account, purple_account_get_username(account)),
1024 5, purple_xfer_get_remote_user(xfer),
1025 265, xfer_data->xfer_peer_idstring,
1026 27, purple_xfer_get_filename(xfer),
1027 249, xfer_data->info_val_249,
1028 251, xfer_data->xfer_idstring_for_relay);
1030 yahoo_packet_send_and_free(pkt_to_send, yd);
1032 req = yahoo_ft_new_req(xfer_data);
1033 purple_http_request_set_method(req, "HEAD");
1034 xfer_data->hc = purple_http_request(gc, req, yahoo_process_filetrans_info_15_got, xfer);
1035 purple_http_request_unref(req);
1037 else if (val_249 == 2)
1038 purple_debug_error("yahoo", "p2p file transfers are not supported yet\n");
1041 /* TODO: Check filename etc. No probs till some hacker comes in the way */
1042 void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt)
1044 gchar *xfer_peer_idstring = NULL;
1045 gchar *xfer_idstring_for_relay = NULL;
1046 PurpleXfer *xfer;
1047 YahooData *yd;
1048 struct yahoo_xfer_data *xfer_data;
1049 GSList *l;
1050 long val_66 = 0;
1051 gchar *url = NULL;
1052 int val_249 = 0;
1054 yd = purple_connection_get_protocol_data(gc);
1055 for (l = pkt->hash; l; l = l->next) {
1056 struct yahoo_pair *pair = l->data;
1058 switch (pair->key) {
1059 case 251:
1060 if (g_utf8_validate(pair->value, -1, NULL)) {
1061 xfer_idstring_for_relay = pair->value;
1062 } else {
1063 purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
1064 "got non-UTF-8 string for key %d\n", pair->key);
1066 break;
1067 case 265:
1068 if (g_utf8_validate(pair->value, -1, NULL)) {
1069 xfer_peer_idstring = pair->value;
1070 } else {
1071 purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
1072 "got non-UTF-8 string for key %d\n", pair->key);
1074 break;
1075 case 66:
1076 val_66 = atol(pair->value);
1077 break;
1078 case 249:
1079 val_249 = atol(pair->value);
1080 break;
1081 case 250:
1082 if (g_utf8_validate(pair->value, -1, NULL)) {
1083 /* we get a p2p url here when sending file, connected as client */
1084 url = pair->value;
1085 } else {
1086 purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
1087 "got non-UTF-8 string for key %d\n", pair->key);
1089 break;
1093 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring);
1094 if(!xfer) return;
1096 if(val_66 == -1 || ( (!(xfer_idstring_for_relay)) && (val_249 != 2) ))
1098 purple_xfer_cancel_remote(xfer);
1099 return;
1102 if( (val_249 == 2) && (!(url)) )
1104 purple_xfer_cancel_remote(xfer);
1105 return;
1108 xfer_data = purple_xfer_get_protocol_data(xfer);
1109 if (url)
1110 xfer_data->host = g_strdup(url);
1112 xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
1114 xfer_data->url = yahoo_ft_url_gen(xfer, xfer_data->host);
1115 purple_xfer_start(xfer, -1, NULL, 0);
1118 static PurpleXfer *
1119 yahoo_ft_new_xfer_struct(PurpleConnection *gc, PurpleXferType type, const char *who)
1121 PurpleXfer *xfer;
1123 g_return_val_if_fail(gc != NULL, NULL);
1124 g_return_val_if_fail(who != NULL, NULL);
1126 xfer = purple_xfer_new(purple_connection_get_account(gc), type, who);
1128 g_return_val_if_fail(xfer != NULL, NULL);
1130 purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
1131 purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
1132 purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
1133 purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
1134 purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
1135 purple_xfer_set_request_denied_fnc(xfer, yahoo_xfer_cancel_recv);
1137 return xfer;