comparison libpurple/protocols/yahoo/yahoo_filexfer.c @ 22018:118046227581

This patch from Thanumalayan S. implements Yahoo protocol version 15 file transfer support. Currently sending multiple files from an official Yahoo client is treated as multiple individual transfers that must be accepted separately. This also changes things so that we identify as Yahoo Messenger version 8.0 (previously we were identifying as 6.0 or not at all). committer: John Bailey <rekkanoryo@rekkanoryo.org>
author Thanumalayan <madthanu@gmail.com>
date Sun, 06 Jan 2008 19:45:03 +0000
parents 97d530d11cc0
children 4163dcf643ae
comparison
equal deleted inserted replaced
22017:97d530d11cc0 22018:118046227581
19 * along with this program; if not, write to the Free Software 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 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 */ 21 */
22 22
23 #include "internal.h" 23 #include "internal.h"
24 #include "dnsquery.h"
24 25
25 #include "prpl.h" 26 #include "prpl.h"
26 #include "util.h" 27 #include "util.h"
27 #include "debug.h" 28 #include "debug.h"
28 #include "notify.h" 29 #include "notify.h"
30 #include "ft.h" 31 #include "ft.h"
31 #include "yahoo.h" 32 #include "yahoo.h"
32 #include "yahoo_packet.h" 33 #include "yahoo_packet.h"
33 #include "yahoo_filexfer.h" 34 #include "yahoo_filexfer.h"
34 #include "yahoo_doodle.h" 35 #include "yahoo_doodle.h"
36 #include "yahoo_friend.h"
35 37
36 struct yahoo_xfer_data { 38 struct yahoo_xfer_data {
37 gchar *host; 39 gchar *host;
38 gchar *path; 40 gchar *path;
39 int port; 41 int port;
44 gsize txbuflen; 46 gsize txbuflen;
45 gsize txbuf_written; 47 gsize txbuf_written;
46 guint tx_handler; 48 guint tx_handler;
47 gchar *rxqueue; 49 gchar *rxqueue;
48 guint rxlen; 50 guint rxlen;
51 gchar *xfer_idstring_between_peers;
52 gchar *xfer_idstring_for_relay;
53 int version; /*0 for old, 15 for Y7(YMSG 15)*/
54 int info_val_249;
55 enum {STARTED = 0,HEAD_REQUESTED,HEAD_REPLY_RECEIVED,TRANSFER_PHASE,ACCEPTED} status_15;
56 GSList *filename_list;/*contains all filenames, in case of multiple transfers, with the first one in the list being the current(ymsg15)*/
57 GSList *size_list;/*corresponds to filename_list, with size as **STRING** */
58 gboolean firstoflist;
49 }; 59 };
50 60
51 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) 61 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd)
52 { 62 {
63 PurpleConnection *gc;
64 struct yahoo_data *yd;
65 PurpleXfer *xfer;
66 GSList *l;
67
68 gc = xd->gc;
69 yd = gc->proto_data;
70
71 /*remove entry from map*/
72 if(xd->xfer_idstring_between_peers) {
73 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xd->xfer_idstring_between_peers);
74 if(xfer)
75 g_hash_table_remove(yd->xfer_peer_idstring_map, xd->xfer_idstring_between_peers);
76 }
77
78 /*empty file & filesize list*/
79 for (l = xd->filename_list; l; l = l->next) {
80 g_free(l->data);
81 l->data=NULL;
82 }
83 for (l = xd->size_list; l; l = l->next) {
84 g_free(l->data);
85 l->data=NULL;
86 }
87 g_slist_free(xd->filename_list);
88 g_slist_free(xd->size_list);
89
53 g_free(xd->host); 90 g_free(xd->host);
54 g_free(xd->path); 91 g_free(xd->path);
55 g_free(xd->txbuf); 92 g_free(xd->txbuf);
93 g_free(xd->xfer_idstring_between_peers);
94 g_free(xd->xfer_idstring_for_relay);
56 if (xd->tx_handler) 95 if (xd->tx_handler)
57 purple_input_remove(xd->tx_handler); 96 purple_input_remove(xd->tx_handler);
58 g_free(xd); 97 g_free(xd);
59 } 98 }
60 99
289 purple_xfer_cancel_remote(xfer); 328 purple_xfer_cancel_remote(xfer);
290 } 329 }
291 } 330 }
292 } 331 }
293 332
333 static void yahoo_xfer_init_15(PurpleXfer *xfer)
334 {
335 struct yahoo_xfer_data *xfer_data;
336 PurpleConnection *gc;
337 PurpleAccount *account;
338 struct yahoo_data *yd;
339 struct yahoo_packet *pkt;
340
341 xfer_data = xfer->data;
342 gc = xfer_data->gc;
343 yd = gc->proto_data;
344 account = purple_connection_get_account(gc);
345
346 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
347 gchar *filename;
348 filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
349 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
350 YAHOO_STATUS_AVAILABLE,
351 yd->session_id);
352 yahoo_packet_hash(pkt, "sssiiiisiii",
353 1, purple_normalize(account, purple_account_get_username(account)),
354 5, xfer->who,
355 265, xfer_data->xfer_idstring_between_peers,
356 222, 1,
357 266, 1,
358 302, 268,
359 300, 268,
360 27, filename,
361 28, xfer->size,
362 301, 268,
363 303, 268);
364 g_free(filename);
365 } else {
366 if(xfer_data->firstoflist == TRUE) {
367 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
368 YAHOO_STATUS_AVAILABLE, yd->session_id);
369
370 yahoo_packet_hash(pkt, "sssi",
371 1, purple_normalize(account, purple_account_get_username(account)),
372 5, xfer->who,
373 265, xfer_data->xfer_idstring_between_peers,
374 222, 3);
375 } else {
376 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
377 YAHOO_STATUS_AVAILABLE, yd->session_id);
378
379 yahoo_packet_hash(pkt, "sssi",
380 1, purple_normalize(account, purple_account_get_username(account)),
381 5, xfer->who,
382 265, xfer_data->xfer_idstring_between_peers,
383 271, 1);
384 }
385 }
386 yahoo_packet_send_and_free(pkt, yd);
387 }
388
294 static void yahoo_xfer_start(PurpleXfer *xfer) 389 static void yahoo_xfer_start(PurpleXfer *xfer)
295 { 390 {
296 /* We don't need to do anything here, do we? */ 391 /* We don't need to do anything here, do we? */
297 }
298
299 static void yahoo_xfer_end(PurpleXfer *xfer)
300 {
301 struct yahoo_xfer_data *xfer_data;
302
303 xfer_data = xfer->data;
304
305 if (xfer_data)
306 yahoo_xfer_data_free(xfer_data);
307 xfer->data = NULL;
308
309 } 392 }
310 393
311 static guint calculate_length(const gchar *l, size_t len) 394 static guint calculate_length(const gchar *l, size_t len)
312 { 395 {
313 int i; 396 int i;
417 { 500 {
418 struct yahoo_xfer_data *xfer_data; 501 struct yahoo_xfer_data *xfer_data;
419 502
420 xfer_data = xfer->data; 503 xfer_data = xfer->data;
421 504
505 if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
506 {
507 PurpleConnection *gc;
508 PurpleAccount *account;
509 struct yahoo_data *yd;
510 struct yahoo_packet *pkt;
511
512 gc = xfer_data->gc;
513 yd = gc->proto_data;
514 account = purple_connection_get_account(gc);
515 if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
516 {
517 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15,
518 YAHOO_STATUS_DISCONNECTED,
519 yd->session_id);
520 yahoo_packet_hash(pkt, "sssi",
521 1, purple_normalize(account, purple_account_get_username(account)),
522 5, xfer->who,
523 265, xfer_data->xfer_idstring_between_peers,
524 66, -1);
525 }
526 else
527 {
528 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
529 YAHOO_STATUS_AVAILABLE,
530 yd->session_id);
531 yahoo_packet_hash(pkt, "sssi",
532 1, purple_normalize(account, purple_account_get_username(account)),
533 5, xfer->who,
534 265, xfer_data->xfer_idstring_between_peers,
535 222, 2);
536 }
537 yahoo_packet_send_and_free(pkt, yd);
538 }
539
540
422 if (xfer_data) 541 if (xfer_data)
423 yahoo_xfer_data_free(xfer_data); 542 yahoo_xfer_data_free(xfer_data);
424 xfer->data = NULL; 543 xfer->data = NULL;
425 } 544 }
426 545
428 { 547 {
429 struct yahoo_xfer_data *xfer_data; 548 struct yahoo_xfer_data *xfer_data;
430 549
431 xfer_data = xfer->data; 550 xfer_data = xfer->data;
432 551
552 if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
553 {
554
555 PurpleConnection *gc;
556 PurpleAccount *account;
557 struct yahoo_data *yd;
558 struct yahoo_packet *pkt;
559
560 gc = xfer_data->gc;
561 yd = gc->proto_data;
562 account = purple_connection_get_account(gc);
563 if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
564 {
565 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
566 YAHOO_STATUS_AVAILABLE,
567 yd->session_id);
568 yahoo_packet_hash(pkt, "sssi",
569 1, purple_normalize(account, purple_account_get_username(account)),
570 5, xfer->who,
571 265, xfer_data->xfer_idstring_between_peers,
572 222, 4);
573 }
574 else
575 {
576 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
577 YAHOO_STATUS_DISCONNECTED,
578 yd->session_id);
579 yahoo_packet_hash(pkt, "sssi",
580 1, purple_normalize(account, purple_account_get_username(account)),
581 5, xfer->who,
582 265, xfer_data->xfer_idstring_between_peers,
583 66, -1);
584 }
585 yahoo_packet_send_and_free(pkt, yd);
586 }
587
433 if (xfer_data) 588 if (xfer_data)
434 yahoo_xfer_data_free(xfer_data); 589 yahoo_xfer_data_free(xfer_data);
435 xfer->data = NULL; 590 xfer->data = NULL;
591 }
592
593 static void yahoo_xfer_end(PurpleXfer *xfer_old)
594 {
595 struct yahoo_xfer_data *xfer_data;
596 PurpleXfer *xfer = NULL;
597 PurpleConnection *gc;
598 struct yahoo_data *yd;
599
600 xfer_data = xfer_old->data;
601 if(xfer_data && xfer_data->version == 15
602 && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE
603 && xfer_data->filename_list) {
604
605 /* removing top of filename & size list completely */
606 g_free( xfer_data->filename_list->data );
607 g_free( xfer_data->size_list->data );
608
609 xfer_data->filename_list->data = NULL;
610 xfer_data->size_list->data = NULL;
611
612 xfer_data->filename_list = g_slist_delete_link(xfer_data->filename_list, xfer_data->filename_list);
613 xfer_data->size_list = g_slist_delete_link(xfer_data->size_list, xfer_data->size_list);
614
615 /* if there are still more files */
616 if(xfer_data->filename_list)
617 {
618 gchar* filename;
619 long filesize;
620
621 filename = xfer_data->filename_list->data;
622 filesize = atol( xfer_data->size_list->data );
623
624 gc = xfer_data->gc;
625 yd = gc->proto_data;
626
627 /* setting up xfer_data for next file's tranfer */
628 g_free(xfer_data->host);
629 g_free(xfer_data->path);
630 g_free(xfer_data->txbuf);
631 g_free(xfer_data->rxqueue);
632 g_free(xfer_data->xfer_idstring_for_relay);
633 if (xfer_data->tx_handler)
634 purple_input_remove(xfer_data->tx_handler);
635 xfer_data->host = NULL;
636 xfer_data->host = NULL;
637 xfer_data->port = 0;
638 xfer_data->expires = 0;
639 xfer_data->started = FALSE;
640 xfer_data->txbuf = NULL;
641 xfer_data->txbuflen = 0;
642 xfer_data->txbuf_written = 0;
643 xfer_data->tx_handler = (int) NULL;
644 xfer_data->rxqueue = NULL;
645 xfer_data->rxlen = 0;
646 xfer_data->xfer_idstring_for_relay = NULL;
647 xfer_data->info_val_249 = 0;
648 xfer_data->status_15 = STARTED;
649 xfer_data->firstoflist = FALSE;
650
651 /* Dereference xfer_data from old xfer */
652 xfer_old->data = NULL;
653
654 /* Build the file transfer handle. */
655 xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who);
656
657
658 if (xfer) {
659 /* Set the info about the incoming file. */
660 char *utf8_filename = yahoo_string_decode(gc, filename, TRUE);
661 purple_xfer_set_filename(xfer, utf8_filename);
662 g_free(utf8_filename);
663 purple_xfer_set_size(xfer, filesize);
664
665 xfer->data = xfer_data;
666
667 /* Setup our I/O op functions */
668 purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
669 purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
670 purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
671 purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
672 purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
673 purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
674 purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
675 purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv);
676
677 /*update map to current xfer*/
678 g_hash_table_remove(yd->xfer_peer_idstring_map, xfer_data->xfer_idstring_between_peers);
679 g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_idstring_between_peers, xfer);
680
681 /* Now perform the request */
682 purple_xfer_request(xfer);
683 }
684 return;
685 }
686 }
687 if (xfer_data)
688 yahoo_xfer_data_free(xfer_data);
689 xfer_old->data = NULL;
690
436 } 691 }
437 692
438 void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt) 693 void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt)
439 { 694 {
440 GSList *l = pkt->hash; 695 GSList *l = pkt->hash;
655 } 910 }
656 911
657 return xfer; 912 return xfer;
658 } 913 }
659 914
915 static gchar* yahoo_xfer_new_xfer_id()
916 {
917 gchar *ans;
918 int i,j;
919 ans = g_strnfill(24, ' ');
920 ans[23] = '$';
921 ans[22] = '$';
922 for(i = 0; i < 22; i++)
923 {
924 j = g_random_int_range (0,61);
925 if(j < 26)
926 ans[i] = j + 'a';
927 else if(j < 52)
928 ans[i] = j - 26 + 'A';
929 else
930 ans[i] = j - 52 + '0';
931 }
932 return ans;
933 }
934
935 static void yahoo_xfer_dns_connected_15(GSList *hosts, gpointer data, const char *error_message)
936 {
937 PurpleXfer *xfer;
938 struct yahoo_xfer_data *xd;
939 struct sockaddr_in *addr;
940 struct yahoo_packet *pkt;
941 long actaddr;
942 long a,b,c,d;
943 PurpleConnection *gc;
944 PurpleAccount *account;
945 struct yahoo_data *yd;
946 gchar *url;
947 gchar *filename;
948
949 if (!(xfer = data))
950 return;
951 if (!(xd = xfer->data))
952 return;
953 gc = xd->gc;
954 account = purple_connection_get_account(gc);
955 yd = gc->proto_data;
956
957 if(!hosts)
958 {
959 purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n");
960 purple_xfer_cancel_remote(xfer);
961 return;
962 }
963
964 /* Discard the length... */
965 hosts = g_slist_remove(hosts, hosts->data);
966 if(!hosts)
967 {
968 purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n");
969 purple_xfer_cancel_remote(xfer);
970 return;
971 }
972
973 /*TODO:actually, u must try with addr no.1 , if its not working addr no.2 .....*/
974 addr = hosts->data;
975 actaddr = addr->sin_addr.s_addr;
976 d = actaddr % 256;
977 actaddr = (actaddr - d) / 256;
978 c = actaddr % 256;
979 actaddr = (actaddr - c) / 256;
980 b = actaddr % 256;
981 actaddr = (actaddr - b) / 256;
982 a = actaddr;
983 if(yd->jp)
984 xd->port = YAHOOJP_XFER_RELAY_PORT;
985 else
986 xd->port = YAHOO_XFER_RELAY_PORT;
987
988 url = g_strdup_printf("%ld.%ld.%ld.%ld", d, c, b, a);
989 if (!purple_url_parse(url, &(xd->host), &(xd->port), &(xd->path), NULL, NULL)) {
990 purple_xfer_cancel_remote(xfer);
991 return;
992 }
993 g_free(url);
994 /* Free the address... */
995 g_free(hosts->data);
996 hosts = g_slist_remove(hosts, hosts->data);
997 addr = NULL;
998 while (hosts != NULL)
999 {
1000 /* Discard the length... */
1001 hosts = g_slist_remove(hosts, hosts->data);
1002 /* Free the address... */
1003 g_free(hosts->data);
1004 hosts = g_slist_remove(hosts, hosts->data);
1005 }
1006
1007 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
1008 filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
1009
1010 yahoo_packet_hash(pkt, "ssssis",
1011 1, purple_normalize(account, purple_account_get_username(account)),
1012 5, xfer->who,
1013 265, xd->xfer_idstring_between_peers,
1014 27, filename,
1015 249, 3,
1016 250, xd->host);
1017
1018 g_free(filename);
1019 yahoo_packet_send_and_free(pkt, yd);
1020 }
1021
1022
660 void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file) 1023 void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file)
661 { 1024 {
1025 struct yahoo_xfer_data *xfer_data;
1026 struct yahoo_data *yd;
1027 int ver = 0;
662 PurpleXfer *xfer = yahoo_new_xfer(gc, who); 1028 PurpleXfer *xfer = yahoo_new_xfer(gc, who);
663 1029 YahooFriend *yf = yahoo_friend_find(gc, who);
1030
1031 /* To determine whether client uses ymsg 15 i.e. client is higher than YM 7 */
1032 if(yf && yf->version_id > 500000)
1033 ver=15;
664 g_return_if_fail(xfer != NULL); 1034 g_return_if_fail(xfer != NULL);
1035
1036 if(ver == 15) {
1037 yd = gc->proto_data;
1038 xfer_data = xfer->data;
1039 xfer_data->status_15 = STARTED;
1040 purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
1041 xfer_data->version = 15;
1042 xfer_data->xfer_idstring_between_peers = yahoo_xfer_new_xfer_id();
1043 g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_idstring_between_peers, xfer);
1044 }
665 1045
666 /* Now perform the request */ 1046 /* Now perform the request */
667 if (file) 1047 if (file)
668 purple_xfer_request_accepted(xfer, file); 1048 purple_xfer_request_accepted(xfer, file);
669 else 1049 else
670 purple_xfer_request(xfer); 1050 purple_xfer_request(xfer);
671 } 1051 }
1052
1053 static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message);/*using this in recv_cb*/
1054 static void yahoo_xfer_recv_cb_15(gpointer data, gint source, PurpleInputCondition condition)
1055 {
1056 PurpleXfer *xfer;
1057 struct yahoo_xfer_data *xd;
1058 int did;
1059 gchar* buf;
1060 gchar* t;
1061 PurpleAccount *account;
1062 PurpleConnection *gc;
1063
1064 xfer = data;
1065 xd = xfer->data;
1066 account = purple_connection_get_account(xd->gc);
1067 gc = xd->gc;
1068
1069 buf=g_strnfill(1000, 0);
1070 while((did = read(source, buf, 998)) > 0)
1071 {
1072 xd->txbuflen += did;
1073 buf[did] = '\0';
1074 t = xd->txbuf;
1075 xd->txbuf = g_strconcat(t,buf,NULL);
1076 g_free(t);
1077 }
1078 g_free(buf);
1079
1080 if (did < 0 && errno == EAGAIN) return;
1081 else if (did < 0) {
1082 purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
1083 purple_xfer_cancel_remote(xfer);
1084 return;
1085 }
1086
1087 purple_input_remove(xd->tx_handler);
1088 xd->tx_handler = 0;
1089 xd->txbuflen = 0;
1090
1091 if(xd->status_15 == HEAD_REQUESTED) {
1092 xd->status_15 = HEAD_REPLY_RECEIVED;
1093 close(source);/*Is this required?*/
1094 g_free(xd->txbuf);
1095 xd->txbuf = NULL;
1096 if (purple_proxy_connect(NULL, account, xd->host, xd->port, yahoo_xfer_connected_15, xfer) == NULL)
1097 {
1098 purple_notify_error(gc, NULL, _("File Transfer Failed"),
1099 _("Unable to establish file descriptor."));
1100 purple_xfer_cancel_remote(xfer);
1101 }
1102 } else {
1103 purple_debug_error("yahoo","Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n",
1104 purple_xfer_get_type(xfer),
1105 xd->status_15);
1106 return;
1107 }
1108 }
1109
1110 static void yahoo_xfer_send_cb_15(gpointer data, gint source, PurpleInputCondition condition)
1111 {
1112 PurpleXfer *xfer;
1113 struct yahoo_xfer_data *xd;
1114 int remaining, written;
1115
1116 xfer = data;
1117 xd = xfer->data;
1118 remaining = xd->txbuflen - xd->txbuf_written;
1119 written = write(source, xd->txbuf + xd->txbuf_written, remaining);
1120
1121 if (written < 0 && errno == EAGAIN)
1122 written = 0;
1123 else if (written <= 0) {
1124 purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
1125 purple_xfer_cancel_remote(xfer);
1126 return;
1127 }
1128
1129 if (written < remaining) {
1130 xd->txbuf_written += written;
1131 return;
1132 }
1133
1134 purple_input_remove(xd->tx_handler);
1135 xd->tx_handler = 0;
1136 g_free(xd->txbuf);
1137 xd->txbuf = NULL;
1138 xd->txbuflen = 0;
1139 xd->txbuf_written = 0;
1140
1141 if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
1142 {
1143 xd->status_15 = HEAD_REQUESTED;
1144 xd->tx_handler = purple_input_add(source, PURPLE_INPUT_READ, yahoo_xfer_recv_cb_15, xfer);
1145 yahoo_xfer_recv_cb_15(xfer, source, PURPLE_INPUT_READ);
1146 }
1147 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
1148 {
1149 xd->status_15 = TRANSFER_PHASE;
1150 xfer->fd = source;
1151 purple_xfer_start(xfer, source, NULL, 0);
1152 }
1153 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED)
1154 {
1155 xd->status_15 = TRANSFER_PHASE;
1156 xfer->fd = source;
1157 purple_xfer_start(xfer, source, NULL, 0);
1158 }
1159 else
1160 {
1161 purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15);
1162 return;
1163 }
1164
1165 }
1166
1167
1168 static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message)
1169 {
1170 PurpleXfer *xfer;
1171 struct yahoo_xfer_data *xd;
1172 PurpleAccount *account;
1173 struct yahoo_data* yd;
1174
1175 if (!(xfer = data))
1176 return;
1177 if (!(xd = xfer->data))
1178 return;
1179 yd = xd->gc->proto_data;
1180 account = purple_connection_get_account(xd->gc);
1181 if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
1182 purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
1183 xfer->who, _("Unable to connect."));
1184 purple_xfer_cancel_remote(xfer);
1185 return;
1186 }
1187 /* The first time we get here, assemble the tx buffer */
1188 if (xd->txbuflen == 0)
1189 {
1190 gchar* cookies;
1191 cookies = yahoo_get_cookies(xd->gc);
1192 if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED)
1193 {
1194 xd->txbuf = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost: %s\r\nContent-Length: %ld\r\nCache-Control: no-cache\r\n\r\n",
1195 purple_url_encode(xd->xfer_idstring_for_relay),
1196 purple_normalize(account, purple_account_get_username(account)),
1197 xfer->who,
1198 cookies,
1199 xd->host,
1200 (long int)xfer->size);
1201 }
1202 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
1203 {
1204 xd->txbuf = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nAccept:*/*\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost:%s\r\nContent-Length: 0\r\nCache-Control: no-cache\r\n\r\n",
1205 purple_url_encode(xd->xfer_idstring_for_relay),
1206 purple_normalize(account, purple_account_get_username(account)),
1207 xfer->who,
1208 cookies,
1209 xd->host);
1210 }
1211 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
1212 {
1213 xd->txbuf = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost:%s\r\nConnection: Keep-Alive\r\n\r\n",
1214 purple_url_encode(xd->xfer_idstring_for_relay),
1215 purple_normalize(account, purple_account_get_username(account)),
1216 xfer->who,
1217 cookies,
1218 xd->host);
1219 }
1220 else
1221 {
1222 purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15);
1223 g_free(cookies);
1224 return;
1225 }
1226 xd->txbuflen = strlen(xd->txbuf);
1227 xd->txbuf_written = 0;
1228 g_free(cookies);
1229 }
1230
1231 if (!xd->tx_handler)
1232 {
1233 xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
1234 yahoo_xfer_send_cb_15, xfer);
1235 yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE);
1236 }
1237 }
1238
1239 void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt)
1240 {
1241 char *from = NULL;
1242 char *to = NULL;
1243 char *imv = NULL;
1244 long val_222 = 0L;
1245 PurpleXfer *xfer;
1246 struct yahoo_data *yd;
1247 struct yahoo_xfer_data *xfer_data;
1248 char *service = NULL;
1249 char *filename = NULL;
1250 char *xfer_idstring_between_peers = NULL;
1251 unsigned long filesize = 0L;
1252 GSList *l;
1253 GSList *filename_list = NULL;
1254 GSList *size_list = NULL;
1255 int nooffiles = 0;
1256
1257 yd = gc->proto_data;
1258
1259 for (l = pkt->hash; l; l = l->next) {
1260 struct yahoo_pair *pair = l->data;
1261
1262 switch (pair->key) {
1263 case 4:
1264 from = pair->value;
1265 break;
1266 case 5:
1267 to = pair->value;
1268 break;
1269 case 265:
1270 xfer_idstring_between_peers = pair->value;
1271 break;
1272 case 27:
1273 filename_list = g_slist_prepend(filename_list, g_strdup(pair->value));
1274 nooffiles++;
1275 break;
1276 case 28:
1277 size_list = g_slist_prepend(size_list, g_strdup(pair->value));
1278 break;
1279 case 222:
1280 val_222 = atol(pair->value);
1281 /* 1=send, 2=cancel, 3=accept, 4=reject */
1282 break;
1283
1284 /*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.*/
1285 case 49:
1286 service = pair->value;
1287 break;
1288 case 63:
1289 imv = pair->value;
1290 break;
1291 /*end check*/
1292
1293 }
1294 }
1295 if(!xfer_idstring_between_peers)
1296 return;
1297
1298 if(val_222 == 2 || val_222 == 4)
1299 {
1300 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
1301 xfer_idstring_between_peers);
1302 if(!xfer) return;
1303 purple_xfer_cancel_remote(xfer);
1304 return;
1305 }
1306 if(val_222 == 3)
1307 {
1308 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
1309 xfer_idstring_between_peers);
1310 if(!xfer)
1311 return;
1312 /*
1313 * In the file trans info packet tht we must reply with , we are supposed to mention the ip address...
1314 * purple connect does not give me a way of finding the ip address...
1315 * so, purple dnsquery is used... but retries, trying with next ip address etc. is not implemented..TODO
1316 */
1317 if (yd->jp)
1318 {
1319 purple_dnsquery_a(YAHOOJP_XFER_RELAY_HOST, YAHOOJP_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer);
1320 }
1321 else
1322 {
1323 purple_dnsquery_a(YAHOO_XFER_RELAY_HOST, YAHOO_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer);
1324 }
1325 return;
1326 }
1327
1328 /*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.*/
1329 /*
1330 * The remote user has changed their IMVironment. We
1331 * record it for later use.
1332 */
1333 if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) {
1334 g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv));
1335 return;
1336 }
1337
1338 if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
1339 if (service && (strcmp("FILEXFER", service) != 0)) {
1340 purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service);
1341 return;
1342 }
1343 }
1344 /*end processing*/
1345
1346 if(!filename_list)
1347 return;
1348 /* have to change list into order in which client at other end sends */
1349 filename_list = g_slist_reverse(filename_list);
1350 size_list = g_slist_reverse(size_list);
1351 filename = filename_list->data;
1352 filesize = atol(size_list->data);
1353
1354 if(!from) return;
1355 xfer_data = g_new0(struct yahoo_xfer_data, 1);
1356 xfer_data->version = 15;
1357 xfer_data->firstoflist = TRUE;
1358 xfer_data->gc = gc;
1359 xfer_data->xfer_idstring_between_peers = g_strdup(xfer_idstring_between_peers);
1360 xfer_data->filename_list = filename_list;
1361 xfer_data->size_list = size_list;
1362
1363 /* Build the file transfer handle. */
1364 xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
1365 xfer->message = NULL;
1366
1367 if (xfer)
1368 {
1369 /* Set the info about the incoming file. */
1370 char *utf8_filename = yahoo_string_decode(gc, filename, TRUE);
1371 purple_xfer_set_filename(xfer, utf8_filename);
1372 g_free(utf8_filename);
1373 purple_xfer_set_size(xfer, filesize);
1374
1375 xfer->data = xfer_data;
1376
1377
1378 /* Setup our I/O op functions */
1379 purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
1380 purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
1381 purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
1382 purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
1383 purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
1384 purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
1385 purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
1386 purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv);
1387
1388 g_hash_table_insert(yd->xfer_peer_idstring_map,
1389 xfer_data->xfer_idstring_between_peers,
1390 xfer);
1391
1392 if(nooffiles > 1) {
1393 gchar* message;
1394 message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles);
1395 purple_xfer_conversation_write(xfer, message, FALSE);
1396 g_free(message);
1397 }
1398 /* Now perform the request */
1399 purple_xfer_request(xfer);
1400 }
1401 }
1402
1403 void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt)
1404 {
1405 char *from = NULL;
1406 char *to = NULL;
1407 char *url = NULL;
1408 long val_249 = 0;
1409 long val_66 = 0;
1410 PurpleXfer *xfer;
1411 struct yahoo_data *yd;
1412 struct yahoo_xfer_data *xfer_data;
1413 char *filename = NULL;
1414 char *xfer_idstring_between_peers = NULL;
1415 char *xfer_idstring_for_relay = NULL;
1416 GSList *l;
1417 struct yahoo_packet *pkt_to_send;
1418 PurpleAccount *account;
1419
1420 yd = gc->proto_data;
1421
1422 for (l = pkt->hash; l; l = l->next) {
1423 struct yahoo_pair *pair = l->data;
1424
1425 switch (pair->key) {
1426 case 4:
1427 from = pair->value;
1428 break;
1429 case 5:
1430 to = pair->value;
1431 break;
1432 case 265:
1433 xfer_idstring_between_peers = pair->value;
1434 break;
1435 case 27:
1436 filename = pair->value;
1437 break;
1438 case 66:
1439 val_66 = strtol(pair->value, NULL, 10);
1440 break;
1441 case 249:
1442 val_249 = strtol(pair->value, NULL, 10); /*
1443 * really pissed off with this- i hv seen 2 occurences of this
1444 * being 1(its normally 3) - and in those cases, the url
1445 * format and corresponding processing seems to be different
1446 * (i havent tested - couldnt reproduce a 1), although i
1447 * guess its easier.
1448 */
1449 break;
1450 case 250:
1451 url = pair->value;
1452 break;
1453 case 251:
1454 xfer_idstring_for_relay = pair->value;
1455 break;
1456 }
1457 }
1458
1459 if(!xfer_idstring_between_peers)
1460 return;
1461
1462 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_idstring_between_peers);
1463
1464 if(!xfer) return;
1465
1466 if(val_66==-1)
1467 {
1468 purple_xfer_cancel_remote(xfer);
1469 return;
1470 }
1471
1472 xfer_data = xfer->data;
1473
1474 xfer_data->info_val_249 = val_249;
1475 xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
1476 if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) {
1477 purple_xfer_cancel_remote(xfer);
1478 return;
1479 }
1480
1481 account = purple_connection_get_account(xfer_data->gc);
1482
1483 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
1484 YAHOO_STATUS_AVAILABLE, yd->session_id);
1485
1486 yahoo_packet_hash(pkt_to_send, "ssssisi",
1487 1, purple_normalize(account, purple_account_get_username(account)),
1488 5, xfer->who,
1489 265, xfer_data->xfer_idstring_between_peers,
1490 27, xfer->filename,
1491 249, xfer_data->info_val_249,
1492 251, xfer_data->xfer_idstring_for_relay,
1493 222, 3);
1494
1495 yahoo_packet_send_and_free(pkt_to_send, yd);
1496 if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port,
1497 yahoo_xfer_connected_15, xfer) == NULL) {
1498 purple_notify_error(gc, NULL, _("File Transfer Failed"),
1499 _("Unable to establish file descriptor."));
1500 purple_xfer_cancel_remote(xfer);
1501 }
1502
1503 }
1504 /*TODO: Check filename etc. No probs till some hacker comes in the way*/
1505 void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt)
1506 {
1507 gchar *xfer_idstring_between_peers = NULL;
1508 gchar *xfer_idstring_for_relay = NULL;
1509 PurpleXfer *xfer;
1510 struct yahoo_data *yd;
1511 struct yahoo_xfer_data *xfer_data;
1512 GSList *l;
1513 PurpleAccount *account;
1514 long val_66 = 0;
1515
1516 yd = gc->proto_data;
1517 for (l = pkt->hash; l; l = l->next) {
1518 struct yahoo_pair *pair = l->data;
1519
1520 switch (pair->key) {
1521 case 251:
1522 xfer_idstring_for_relay = pair->value;
1523 break;
1524 case 265:
1525 xfer_idstring_between_peers = pair->value;
1526 break;
1527 case 66:
1528 val_66 = atol(pair->value);
1529 }
1530 }
1531
1532 xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_idstring_between_peers);
1533 if(!xfer) return;
1534
1535 if(val_66 == -1 || !(xfer_idstring_for_relay))
1536 {
1537 purple_xfer_cancel_remote(xfer);
1538 return;
1539 }
1540
1541 xfer_data = xfer->data;
1542 xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
1543 xfer_data->status_15 = ACCEPTED;
1544 account = purple_connection_get_account(gc);
1545
1546 if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port,
1547 yahoo_xfer_connected_15, xfer) == NULL)
1548 {
1549 purple_notify_error(gc, NULL, _("File Transfer Failed"),_("Unable to connect"));
1550 purple_xfer_cancel_remote(xfer);
1551 }
1552 }