Mercurial > pidgin
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 } |