Mercurial > pidgin.yaz
comparison libpurple/protocols/yahoo/yahoo.c @ 27933:f44832c6a65b
propagate from branch 'im.pidgin.pidgin' (head a840b7a77c7e395db5e7877fab90763d91f70b3a)
to branch 'im.pidgin.pidgin.yaz' (head 42d24988b115ba197f27a95547b1445c10f06d2c)
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Sun, 08 Mar 2009 20:38:09 +0000 |
parents | d8e6a2d592a4 7114d475a9e7 |
children | 1337d2813b2d |
comparison
equal
deleted
inserted
replaced
27932:4033fea1709c | 27933:f44832c6a65b |
---|---|
28 #include "blist.h" | 28 #include "blist.h" |
29 #include "cipher.h" | 29 #include "cipher.h" |
30 #include "cmds.h" | 30 #include "cmds.h" |
31 #include "core.h" | 31 #include "core.h" |
32 #include "debug.h" | 32 #include "debug.h" |
33 #include "network.h" | |
33 #include "notify.h" | 34 #include "notify.h" |
34 #include "privacy.h" | 35 #include "privacy.h" |
35 #include "prpl.h" | 36 #include "prpl.h" |
36 #include "proxy.h" | 37 #include "proxy.h" |
37 #include "request.h" | 38 #include "request.h" |
38 #include "server.h" | 39 #include "server.h" |
39 #include "util.h" | 40 #include "util.h" |
40 #include "version.h" | 41 #include "version.h" |
42 #include "xmlnode.h" | |
41 | 43 |
42 #include "yahoo.h" | 44 #include "yahoo.h" |
43 #include "yahoochat.h" | 45 #include "yahoochat.h" |
44 #include "yahoo_aliases.h" | 46 #include "yahoo_aliases.h" |
45 #include "yahoo_auth.h" | 47 #include "yahoo_auth.h" |
151 GSList *l = pkt->hash; | 153 GSList *l = pkt->hash; |
152 YahooFriend *f = NULL; | 154 YahooFriend *f = NULL; |
153 char *name = NULL; | 155 char *name = NULL; |
154 gboolean unicode = FALSE; | 156 gboolean unicode = FALSE; |
155 char *message = NULL; | 157 char *message = NULL; |
158 char *msn_name = NULL; | |
156 | 159 |
157 if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { | 160 if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { |
158 if (!purple_account_get_remember_password(account)) | 161 if (!purple_account_get_remember_password(account)) |
159 purple_account_set_password(account, NULL); | 162 purple_account_set_password(account, NULL); |
160 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE, | 163 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE, |
233 case 19: /* custom message */ | 236 case 19: /* custom message */ |
234 if (f) | 237 if (f) |
235 message = pair->value; | 238 message = pair->value; |
236 break; | 239 break; |
237 case 11: /* this is the buddy's session id */ | 240 case 11: /* this is the buddy's session id */ |
241 if (f) | |
242 f->session_id = strtol(pair->value, NULL, 10); | |
238 break; | 243 break; |
239 case 17: /* in chat? */ | 244 case 17: /* in chat? */ |
240 break; | 245 break; |
241 case 47: /* is custom status away or not? 2=idle*/ | 246 case 47: /* is custom status away or not? 2=idle*/ |
242 if (!f) | 247 if (!f) |
348 break; | 353 break; |
349 case 244: /* client version number. Yahoo Client Detection */ | 354 case 244: /* client version number. Yahoo Client Detection */ |
350 if(f && strtol(pair->value, NULL, 10)) | 355 if(f && strtol(pair->value, NULL, 10)) |
351 f->version_id = strtol(pair->value, NULL, 10); | 356 f->version_id = strtol(pair->value, NULL, 10); |
352 break; | 357 break; |
353 | 358 case 241: /* protocol buddy belongs to */ |
359 if(strtol(pair->value, NULL, 10) == 2) { | |
360 msn_name = g_strconcat("msn/", name, NULL); | |
361 name = msn_name; | |
362 } | |
363 break; | |
354 default: | 364 default: |
355 purple_debug_warning("yahoo", | 365 purple_debug_warning("yahoo", |
356 "Unknown status key %d\n", pair->key); | 366 "Unknown status key %d\n", pair->key); |
357 break; | 367 break; |
358 } | 368 } |
470 | 480 |
471 PurpleAccount *account = purple_connection_get_account(gc); | 481 PurpleAccount *account = purple_connection_get_account(gc); |
472 struct yahoo_data *yd = gc->proto_data; | 482 struct yahoo_data *yd = gc->proto_data; |
473 GHashTable *ht; | 483 GHashTable *ht; |
474 char *norm_bud = NULL; | 484 char *norm_bud = NULL; |
485 char *temp = NULL; | |
475 YahooFriend *f = NULL; /* It's your friends. They're going to want you to share your StarBursts. */ | 486 YahooFriend *f = NULL; /* It's your friends. They're going to want you to share your StarBursts. */ |
476 /* But what if you had no friends? */ | 487 /* But what if you had no friends? */ |
477 PurpleBuddy *b; | 488 PurpleBuddy *b; |
478 PurpleGroup *g; | 489 PurpleGroup *g; |
490 int protocol = 0; | |
491 int stealth = 0; | |
479 | 492 |
480 | 493 |
481 ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free); | 494 ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free); |
482 | 495 |
483 while (l) { | 496 while (l) { |
497 yd->current_list15_grp = NULL; | 510 yd->current_list15_grp = NULL; |
498 } | 511 } |
499 | 512 |
500 break; | 513 break; |
501 case 301: /* This is 319 before all s/n's in a group after the first. It is followed by an identical 300. */ | 514 case 301: /* This is 319 before all s/n's in a group after the first. It is followed by an identical 300. */ |
502 break; | 515 if(temp != NULL) { |
503 case 300: /* This is 318 before a group, 319 before any s/n in a group, and 320 before any ignored s/n. */ | 516 if(protocol == 2) |
504 break; | 517 norm_bud = g_strconcat("msn/", temp, NULL); |
505 case 65: /* This is the group */ | 518 else |
506 g_free(yd->current_list15_grp); | 519 norm_bud = g_strdup(temp); |
507 yd->current_list15_grp = yahoo_string_decode(gc, pair->value, FALSE); | 520 |
508 break; | 521 if (yd->current_list15_grp) { |
509 case 7: /* buddy's s/n */ | 522 /* This buddy is in a group */ |
510 g_free(norm_bud); | 523 f = yahoo_friend_find_or_new(gc, norm_bud); |
511 norm_bud = g_strdup(purple_normalize(account, pair->value)); | 524 if (!(b = purple_find_buddy(account, norm_bud))) { |
512 | 525 if (!(g = purple_find_group(yd->current_list15_grp))) { |
513 if (yd->current_list15_grp) { | 526 g = purple_group_new(yd->current_list15_grp); |
514 /* This buddy is in a group */ | 527 purple_blist_add_group(g, NULL); |
515 f = yahoo_friend_find_or_new(gc, norm_bud); | |
516 if (!(b = purple_find_buddy(account, norm_bud))) { | |
517 if (!(g = purple_find_group(yd->current_list15_grp))) { | |
518 g = purple_group_new(yd->current_list15_grp); | |
519 purple_blist_add_group(g, NULL); | |
520 } | 528 } |
521 b = purple_buddy_new(account, norm_bud, NULL); | 529 b = purple_buddy_new(account, norm_bud, NULL); |
522 purple_blist_add_buddy(b, NULL, g, NULL); | 530 purple_blist_add_buddy(b, NULL, g, NULL); |
523 } | 531 } |
524 yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp); | 532 yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp); |
525 | 533 if(protocol != 0) { |
526 } else { | 534 f->protocol = protocol; |
527 /* This buddy is on the ignore list (and therefore in no group) */ | 535 purple_debug_info("yahoo", "Setting protocol to %d\n", f->protocol); |
528 purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n", | 536 } |
529 account->username, norm_bud); | 537 if(stealth == 2) |
530 purple_privacy_deny_add(account, norm_bud, 1); | 538 f->presence = YAHOO_PRESENCE_PERM_OFFLINE; |
539 | |
540 /* set p2p status not connected and no p2p packet sent */ | |
541 if(protocol == 0) { | |
542 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); | |
543 f->p2p_packet_sent = 0; | |
544 } else | |
545 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT); | |
546 } else { | |
547 /* This buddy is on the ignore list (and therefore in no group) */ | |
548 purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n",account->username, norm_bud); | |
549 purple_privacy_deny_add(account, norm_bud, 1); | |
550 } | |
551 | |
552 protocol = 0; | |
553 stealth = 0; | |
554 norm_bud = NULL; | |
555 temp = NULL; | |
531 } | 556 } |
532 break; | 557 break; |
558 case 300: /* This is 318 before a group, 319 before any s/n in a group, and 320 before any ignored s/n. */ | |
559 break; | |
560 case 65: /* This is the group */ | |
561 g_free(yd->current_list15_grp); | |
562 yd->current_list15_grp = yahoo_string_decode(gc, pair->value, FALSE); | |
563 break; | |
564 case 7: /* buddy's s/n */ | |
565 temp = g_strdup(purple_normalize(account, pair->value)); | |
566 break; | |
533 case 241: /* another protocol user */ | 567 case 241: /* another protocol user */ |
534 if (f) { | 568 protocol = strtol(pair->value, NULL, 10); |
535 f->protocol = strtol(pair->value, NULL, 10); | |
536 purple_debug_info("yahoo", "Setting protocol to %d\n", f->protocol); | |
537 } | |
538 break; | 569 break; |
539 case 59: /* somebody told cookies come here too, but im not sure */ | 570 case 59: /* somebody told cookies come here too, but im not sure */ |
540 yahoo_process_cookie(yd, pair->value); | 571 yahoo_process_cookie(yd, pair->value); |
541 break; | 572 break; |
542 case 317: /* Stealth Setting */ | 573 case 317: /* Stealth Setting */ |
543 if (f && (strtol(pair->value, NULL, 10) == 2)) { | 574 stealth = strtol(pair->value, NULL, 10); |
544 f->presence = YAHOO_PRESENCE_PERM_OFFLINE; | |
545 } | |
546 break; | 575 break; |
547 /* case 242: */ /* this seems related to 241 */ | 576 /* case 242: */ /* this seems related to 241 */ |
548 /* break; */ | 577 /* break; */ |
549 } | 578 } |
550 } | 579 } |
551 | 580 |
552 g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL); | 581 g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL); |
553 g_hash_table_destroy(ht); | 582 g_hash_table_destroy(ht); |
554 g_free(norm_bud); | 583 g_free(norm_bud); |
584 g_free(temp); | |
555 } | 585 } |
556 | 586 |
557 static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt) | 587 static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt) |
558 { | 588 { |
559 GSList *l = pkt->hash; | 589 GSList *l = pkt->hash; |
634 purple_blist_add_buddy(b, NULL, g, NULL); | 664 purple_blist_add_buddy(b, NULL, g, NULL); |
635 export = TRUE; | 665 export = TRUE; |
636 } | 666 } |
637 | 667 |
638 yahoo_do_group_check(account, ht, norm_bud, grp); | 668 yahoo_do_group_check(account, ht, norm_bud, grp); |
669 /* set p2p status not connected and no p2p packet sent */ | |
670 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); | |
671 f->p2p_packet_sent = 0; | |
672 | |
639 g_free(norm_bud); | 673 g_free(norm_bud); |
640 } | 674 } |
641 g_strfreev(buddies); | 675 g_strfreev(buddies); |
642 g_strfreev(split); | 676 g_strfreev(split); |
643 g_free(grp); | 677 g_free(grp); |
690 } | 724 } |
691 /* Now that we've got the list, request aliases */ | 725 /* Now that we've got the list, request aliases */ |
692 yahoo_fetch_aliases(gc); | 726 yahoo_fetch_aliases(gc); |
693 } | 727 } |
694 | 728 |
695 static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt) | 729 /* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */ |
730 static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type) | |
696 { | 731 { |
697 PurpleAccount *account; | 732 PurpleAccount *account; |
698 char *msg = NULL; | 733 char *msg = NULL; |
699 char *from = NULL; | 734 char *from = NULL; |
700 char *stat = NULL; | 735 char *stat = NULL; |
701 char *game = NULL; | 736 char *game = NULL; |
702 YahooFriend *f = NULL; | 737 YahooFriend *f = NULL; |
703 GSList *l = pkt->hash; | 738 GSList *l = pkt->hash; |
739 gint val_11 = 0; | |
740 struct yahoo_data *yd = gc->proto_data; | |
741 gboolean msn = FALSE; | |
742 char *msn_from = NULL; | |
704 | 743 |
705 account = purple_connection_get_account(gc); | 744 account = purple_connection_get_account(gc); |
706 | 745 |
707 while (l) { | 746 while (l) { |
708 struct yahoo_pair *pair = l->data; | 747 struct yahoo_pair *pair = l->data; |
709 if (pair->key == 4) | 748 if (pair->key == 4 || pair->key == 1) |
710 from = pair->value; | 749 from = pair->value; |
711 if (pair->key == 49) | 750 if (pair->key == 49) |
712 msg = pair->value; | 751 msg = pair->value; |
713 if (pair->key == 13) | 752 if (pair->key == 13) |
714 stat = pair->value; | 753 stat = pair->value; |
715 if (pair->key == 14) | 754 if (pair->key == 14) |
716 game = pair->value; | 755 game = pair->value; |
756 if (pair->key == 11) | |
757 val_11 = strtol(pair->value, NULL, 10); | |
758 if (pair->key == 241) | |
759 if(strtol(pair->value, NULL, 10) == 2) | |
760 msn = TRUE; | |
717 l = l->next; | 761 l = l->next; |
718 } | 762 } |
719 | 763 |
720 if (!from || !msg) | 764 if (!from || !msg) |
721 return; | 765 return; |
766 | |
767 /* disconnect the peer if connected through p2p and sends wrong value for session id */ | |
768 if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) { | |
769 purple_debug_warning("yahoo","p2p: %s sent us notify with wrong session id. Disconnecting p2p connection to peer\n", from); | |
770 /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */ | |
771 g_hash_table_remove(yd->peers, from); | |
772 return; | |
773 } | |
774 | |
775 if(msn) | |
776 msn_from = g_strconcat("msn/", from, NULL); | |
722 | 777 |
723 if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")) | 778 if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")) |
724 && (purple_privacy_check(account, from))) | 779 && (purple_privacy_check(account, from))) |
725 { | 780 { |
726 if (*stat == '1') | 781 if(msn) { |
727 serv_got_typing(gc, from, 0, PURPLE_TYPING); | 782 if (*stat == '1') |
728 else | 783 serv_got_typing(gc, msn_from, 0, PURPLE_TYPING); |
729 serv_got_typing_stopped(gc, from); | 784 else |
785 serv_got_typing_stopped(gc, msn_from); | |
786 } | |
787 else { | |
788 if (*stat == '1') | |
789 serv_got_typing(gc, from, 0, PURPLE_TYPING); | |
790 else | |
791 serv_got_typing_stopped(gc, from); | |
792 } | |
730 } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) { | 793 } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) { |
731 PurpleBuddy *bud = purple_find_buddy(account, from); | 794 PurpleBuddy *bud = purple_find_buddy(account, from); |
732 | 795 |
733 if (!bud) { | 796 if (!bud) { |
734 purple_debug(PURPLE_DEBUG_WARNING, "yahoo", | 797 purple_debug(PURPLE_DEBUG_WARNING, "yahoo", |
752 char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from); | 815 char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from); |
753 purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL)); | 816 purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL)); |
754 g_free(buf); | 817 g_free(buf); |
755 } | 818 } |
756 | 819 |
820 g_free(msn_from); | |
757 } | 821 } |
758 | 822 |
759 | 823 |
760 struct _yahoo_im { | 824 struct _yahoo_im { |
761 char *from; | 825 char *from; |
763 int utf8; | 827 int utf8; |
764 int buddy_icon; | 828 int buddy_icon; |
765 char *msg; | 829 char *msg; |
766 }; | 830 }; |
767 | 831 |
768 static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt) | 832 static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt) |
833 { | |
834 PurpleAccount *account; | |
835 GSList *l = pkt->hash; | |
836 struct _yahoo_im *sms = NULL; | |
837 struct yahoo_data *yd; | |
838 char *server_msg = NULL; | |
839 char *m; | |
840 | |
841 yd = gc->proto_data; | |
842 account = purple_connection_get_account(gc); | |
843 | |
844 while (l != NULL) { | |
845 struct yahoo_pair *pair = l->data; | |
846 if (pair->key == 4) { | |
847 sms = g_new0(struct _yahoo_im, 1); | |
848 sms->from = g_strdup_printf("+%s", pair->value); | |
849 sms->time = time(NULL); | |
850 sms->utf8 = TRUE; | |
851 } | |
852 if (pair->key == 14) { | |
853 if (sms) | |
854 sms->msg = pair->value; | |
855 } | |
856 if (pair->key == 68) | |
857 if(sms) | |
858 g_hash_table_insert(yd->sms_carrier, g_strdup(sms->from), g_strdup(pair->value)); | |
859 if (pair->key == 16) | |
860 server_msg = pair->value; | |
861 l = l->next; | |
862 } | |
863 | |
864 if( (pkt->status == -1) || (pkt->status == YAHOO_STATUS_DISCONNECTED) ) { | |
865 if (server_msg) { | |
866 PurpleConversation *c; | |
867 c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms->from, account); | |
868 if (c == NULL) | |
869 c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sms->from); | |
870 purple_conversation_write(c, NULL, server_msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
871 } | |
872 else | |
873 purple_notify_error(gc, NULL, _("Your SMS was not delivered"), NULL); | |
874 | |
875 g_free(sms->from); | |
876 g_free(sms); | |
877 return ; | |
878 } | |
879 | |
880 if (!sms->from || !sms->msg) { | |
881 g_free(sms); | |
882 return; | |
883 } | |
884 | |
885 m = yahoo_string_decode(gc, sms->msg, sms->utf8); | |
886 serv_got_im(gc, sms->from, m, 0, sms->time); | |
887 | |
888 g_free(m); | |
889 g_free(sms->from); | |
890 g_free(sms); | |
891 } | |
892 | |
893 /* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */ | |
894 static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type) | |
769 { | 895 { |
770 PurpleAccount *account; | 896 PurpleAccount *account; |
771 struct yahoo_data *yd = gc->proto_data; | 897 struct yahoo_data *yd = gc->proto_data; |
772 GSList *l = pkt->hash; | 898 GSList *l = pkt->hash; |
773 GSList *list = NULL; | 899 GSList *list = NULL; |
774 struct _yahoo_im *im = NULL; | 900 struct _yahoo_im *im = NULL; |
775 const char *imv = NULL; | 901 const char *imv = NULL; |
902 gint val_11 = 0; | |
903 gboolean msn = FALSE; | |
904 char *msn_from = NULL; | |
776 | 905 |
777 account = purple_connection_get_account(gc); | 906 account = purple_connection_get_account(gc); |
778 | 907 |
779 if (pkt->status <= 1 || pkt->status == 5) { | 908 if (pkt->status <= 1 || pkt->status == 5 || pkt->status == YAHOO_STATUS_OFFLINE) { |
909 /* messages are received with status YAHOO_STATUS_OFFLINE in case of p2p */ | |
780 while (l != NULL) { | 910 while (l != NULL) { |
781 struct yahoo_pair *pair = l->data; | 911 struct yahoo_pair *pair = l->data; |
782 if (pair->key == 4) { | 912 if (pair->key == 4 || pair->key == 1) { |
783 im = g_new0(struct _yahoo_im, 1); | 913 im = g_new0(struct _yahoo_im, 1); |
784 list = g_slist_append(list, im); | 914 list = g_slist_append(list, im); |
785 im->from = pair->value; | 915 im->from = pair->value; |
786 im->time = time(NULL); | 916 im->time = time(NULL); |
787 im->utf8 = TRUE; | 917 im->utf8 = TRUE; |
797 im->buddy_icon = strtol(pair->value, NULL, 10); | 927 im->buddy_icon = strtol(pair->value, NULL, 10); |
798 if (pair->key == 14) { | 928 if (pair->key == 14) { |
799 if (im) | 929 if (im) |
800 im->msg = pair->value; | 930 im->msg = pair->value; |
801 } | 931 } |
932 if (pair->key == 241) { | |
933 if(strtol(pair->value, NULL, 10) == 2) | |
934 msn = TRUE; | |
935 } | |
936 /* peer session id */ | |
937 if (pair->key == 11) { | |
938 if (im) | |
939 val_11 = strtol(pair->value, NULL, 10); | |
940 } | |
802 /* IMV key */ | 941 /* IMV key */ |
803 if (pair->key == 63) | 942 if (pair->key == 63) |
804 { | 943 { |
805 imv = pair->value; | 944 imv = pair->value; |
806 } | 945 } |
807 l = l->next; | 946 l = l->next; |
808 } | 947 } |
809 } else if (pkt->status == 2) { | 948 } else if (pkt->status == 2) { |
810 purple_notify_error(gc, NULL, | 949 purple_notify_error(gc, NULL, |
811 _("Your Yahoo! message did not get sent."), NULL); | 950 _("Your Yahoo! message did not get sent."), NULL); |
951 } | |
952 | |
953 if(msn) | |
954 msn_from = g_strconcat("msn/", im->from, NULL); | |
955 | |
956 /* disconnect the peer if connected through p2p and sends wrong value for session id */ | |
957 if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) { | |
958 purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im->from); | |
959 /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */ | |
960 g_hash_table_remove(yd->peers, im->from); | |
961 return; | |
812 } | 962 } |
813 | 963 |
814 /** TODO: It seems that this check should be per IM, not global */ | 964 /** TODO: It seems that this check should be per IM, not global */ |
815 /* Check for the Doodle IMV */ | 965 /* Check for the Doodle IMV */ |
816 if (im != NULL && imv!= NULL && im->from != NULL) | 966 if (im != NULL && imv!= NULL && im->from != NULL) |
845 } | 995 } |
846 | 996 |
847 for (l = list; l; l = l->next) { | 997 for (l = list; l; l = l->next) { |
848 YahooFriend *f; | 998 YahooFriend *f; |
849 char *m, *m2; | 999 char *m, *m2; |
1000 PurpleConversation *c; | |
850 im = l->data; | 1001 im = l->data; |
851 | 1002 |
852 if (!im->from || !im->msg) { | 1003 if (!im->from || !im->msg) { |
853 g_free(im); | 1004 g_free(im); |
854 continue; | 1005 continue; |
867 m2 = purple_strreplace(m, "\r\n", "\n"); | 1018 m2 = purple_strreplace(m, "\r\n", "\n"); |
868 g_free(m); | 1019 g_free(m); |
869 m = m2; | 1020 m = m2; |
870 purple_util_chrreplace(m, '\r', '\n'); | 1021 purple_util_chrreplace(m, '\r', '\n'); |
871 | 1022 |
1023 c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->from, account); | |
1024 if ((c == NULL) && msn) | |
1025 c=purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, msn_from, account); | |
1026 | |
872 if (!strcmp(m, "<ding>")) { | 1027 if (!strcmp(m, "<ding>")) { |
873 PurpleConversation *c; | |
874 char *username; | 1028 char *username; |
875 | 1029 |
876 c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->from, account); | 1030 if(c == NULL) { |
877 if (c == NULL) | 1031 if(msn) |
878 c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, im->from); | 1032 c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, msn_from); |
879 | 1033 else |
880 username = g_markup_escape_text(im->from, -1); | 1034 c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, im->from); |
1035 } | |
1036 if(msn) | |
1037 username = g_markup_escape_text(msn_from, -1); | |
1038 else | |
1039 username = g_markup_escape_text(im->from, -1); | |
1040 | |
881 purple_prpl_got_attention(gc, username, YAHOO_BUZZ); | 1041 purple_prpl_got_attention(gc, username, YAHOO_BUZZ); |
882 g_free(username); | 1042 g_free(username); |
883 g_free(m); | 1043 g_free(m); |
884 g_free(im); | 1044 g_free(im); |
1045 g_free(msn_from); | |
885 continue; | 1046 continue; |
886 } | 1047 } |
887 | 1048 |
888 m2 = yahoo_codes_to_html(m); | 1049 m2 = yahoo_codes_to_html(m); |
889 g_free(m); | 1050 g_free(m); |
890 serv_got_im(gc, im->from, m2, 0, im->time); | 1051 |
1052 if(msn) | |
1053 serv_got_im(gc, msn_from, m2, 0, im->time); | |
1054 else | |
1055 serv_got_im(gc, im->from, m2, 0, im->time); | |
1056 | |
891 g_free(m2); | 1057 g_free(m2); |
892 | 1058 |
893 if ((f = yahoo_friend_find(gc, im->from)) && im->buddy_icon == 2) { | 1059 /* laters : implement buddy icon for msn friends */ |
894 if (yahoo_friend_get_buddy_icon_need_request(f)) { | 1060 if(!msn) { |
895 yahoo_send_picture_request(gc, im->from); | 1061 if ((f = yahoo_friend_find(gc, im->from)) && im->buddy_icon == 2) { |
896 yahoo_friend_set_buddy_icon_need_request(f, FALSE); | 1062 if (yahoo_friend_get_buddy_icon_need_request(f)) { |
1063 yahoo_send_picture_request(gc, im->from); | |
1064 yahoo_friend_set_buddy_icon_need_request(f, FALSE); | |
1065 } | |
897 } | 1066 } |
898 } | 1067 } |
899 | 1068 |
900 g_free(im); | 1069 g_free(im); |
1070 g_free(msn_from); | |
901 } | 1071 } |
902 g_slist_free(list); | 1072 g_slist_free(list); |
903 } | 1073 } |
904 | 1074 |
905 static void yahoo_process_sysmessage(PurpleConnection *gc, struct yahoo_packet *pkt) | 1075 static void yahoo_process_sysmessage(PurpleConnection *gc, struct yahoo_packet *pkt) |
1028 | 1198 |
1029 static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *pkt) { | 1199 static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *pkt) { |
1030 PurpleAccount *account; | 1200 PurpleAccount *account; |
1031 GSList *l = pkt->hash; | 1201 GSList *l = pkt->hash; |
1032 const char *msg = NULL; | 1202 const char *msg = NULL; |
1203 int protocol = 0; | |
1033 | 1204 |
1034 account = purple_connection_get_account(gc); | 1205 account = purple_connection_get_account(gc); |
1035 | 1206 |
1036 /* Buddy authorized/declined our addition */ | 1207 /* Buddy authorized/declined our addition */ |
1037 if (pkt->status == 1) { | 1208 if (pkt->status == 1) { |
1038 const char *who = NULL; | 1209 char *temp = NULL; |
1210 char *who = NULL; | |
1039 int response = 0; | 1211 int response = 0; |
1040 | 1212 |
1041 while (l) { | 1213 while (l) { |
1042 struct yahoo_pair *pair = l->data; | 1214 struct yahoo_pair *pair = l->data; |
1043 | 1215 |
1044 switch (pair->key) { | 1216 switch (pair->key) { |
1045 case 4: | 1217 case 4: |
1046 who = pair->value; | 1218 temp = pair->value; |
1047 break; | 1219 break; |
1048 case 13: | 1220 case 13: |
1049 response = strtol(pair->value, NULL, 10); | 1221 response = strtol(pair->value, NULL, 10); |
1050 break; | 1222 break; |
1051 case 14: | 1223 case 14: |
1052 msg = pair->value; | 1224 msg = pair->value; |
1053 break; | 1225 break; |
1226 case 241: | |
1227 protocol = strtol(pair->value, NULL, 10); | |
1228 break; | |
1054 } | 1229 } |
1055 l = l->next; | 1230 l = l->next; |
1056 } | 1231 } |
1232 | |
1233 if(protocol == 0) | |
1234 who = g_strdup(temp); | |
1235 else if(protocol == 2) | |
1236 who = g_strconcat("msn/", temp, NULL); | |
1057 | 1237 |
1058 if (response == 1) /* Authorized */ | 1238 if (response == 1) /* Authorized */ |
1059 purple_debug_info("yahoo", "Received authorization from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); | 1239 purple_debug_info("yahoo", "Received authorization from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); |
1060 else if (response == 2) { /* Declined */ | 1240 else if (response == 2) { /* Declined */ |
1061 purple_debug_info("yahoo", "Received authorization decline from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); | 1241 purple_debug_info("yahoo", "Received authorization decline from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); |
1062 yahoo_buddy_denied_our_add(gc, who, msg); | 1242 yahoo_buddy_denied_our_add(gc, who, msg); |
1063 } else | 1243 } else |
1064 purple_debug_error("yahoo", "Received unknown authorization response of %d from buddy '%s'.\n", response, who ? who : "(Unknown Buddy)"); | 1244 purple_debug_error("yahoo", "Received unknown authorization response of %d from buddy '%s'.\n", response, who ? who : "(Unknown Buddy)"); |
1065 | 1245 g_free(who); |
1066 } | 1246 } |
1067 /* Buddy requested authorization to add us. */ | 1247 /* Buddy requested authorization to add us. */ |
1068 else if (pkt->status == 3) { | 1248 else if (pkt->status == 3) { |
1069 struct yahoo_add_request *add_req; | 1249 struct yahoo_add_request *add_req; |
1070 const char *firstname = NULL, *lastname = NULL; | 1250 const char *firstname = NULL, *lastname = NULL; |
1251 char *temp = NULL; | |
1071 | 1252 |
1072 add_req = g_new0(struct yahoo_add_request, 1); | 1253 add_req = g_new0(struct yahoo_add_request, 1); |
1073 add_req->gc = gc; | 1254 add_req->gc = gc; |
1074 | 1255 |
1075 while (l) { | 1256 while (l) { |
1076 struct yahoo_pair *pair = l->data; | 1257 struct yahoo_pair *pair = l->data; |
1077 | 1258 |
1078 switch (pair->key) { | 1259 switch (pair->key) { |
1079 case 4: | 1260 case 4: |
1261 temp = pair->value; | |
1080 add_req->who = g_strdup(pair->value); | 1262 add_req->who = g_strdup(pair->value); |
1081 break; | 1263 break; |
1082 case 5: | 1264 case 5: |
1083 add_req->id = g_strdup(pair->value); | 1265 add_req->id = g_strdup(pair->value); |
1084 break; | 1266 break; |
1096 break; | 1278 break; |
1097 | 1279 |
1098 } | 1280 } |
1099 l = l->next; | 1281 l = l->next; |
1100 } | 1282 } |
1283 if(add_req->protocol == 2) | |
1284 add_req->who = g_strconcat("msn/", temp, NULL); | |
1285 else | |
1286 add_req->who = g_strdup(temp); | |
1101 | 1287 |
1102 if (add_req->id && add_req->who) { | 1288 if (add_req->id && add_req->who) { |
1103 char *alias = NULL, *dec_msg = NULL; | 1289 char *alias = NULL, *dec_msg = NULL; |
1104 | 1290 |
1105 if (!purple_privacy_check(account, add_req->who)) | 1291 if (!purple_privacy_check(account, add_req->who)) |
2197 | 2383 |
2198 static void yahoo_process_addbuddy(PurpleConnection *gc, struct yahoo_packet *pkt) | 2384 static void yahoo_process_addbuddy(PurpleConnection *gc, struct yahoo_packet *pkt) |
2199 { | 2385 { |
2200 int err = 0; | 2386 int err = 0; |
2201 char *who = NULL; | 2387 char *who = NULL; |
2388 char *temp = NULL; | |
2202 char *group = NULL; | 2389 char *group = NULL; |
2203 char *decoded_group; | 2390 char *decoded_group; |
2204 char *buf; | 2391 char *buf; |
2205 YahooFriend *f; | 2392 YahooFriend *f; |
2206 GSList *l = pkt->hash; | 2393 GSList *l = pkt->hash; |
2394 struct yahoo_data *yd = gc->proto_data; | |
2395 int protocol = 0; | |
2396 gboolean msn = FALSE; | |
2207 | 2397 |
2208 while (l) { | 2398 while (l) { |
2209 struct yahoo_pair *pair = l->data; | 2399 struct yahoo_pair *pair = l->data; |
2210 | 2400 |
2211 switch (pair->key) { | 2401 switch (pair->key) { |
2212 case 66: | 2402 case 66: |
2213 err = strtol(pair->value, NULL, 10); | 2403 err = strtol(pair->value, NULL, 10); |
2214 break; | 2404 break; |
2215 case 7: | 2405 case 7: |
2216 who = pair->value; | 2406 temp = pair->value; |
2217 break; | 2407 break; |
2218 case 65: | 2408 case 65: |
2219 group = pair->value; | 2409 group = pair->value; |
2220 break; | 2410 break; |
2411 case 241: | |
2412 protocol = strtol(pair->value, NULL, 10); | |
2413 if(protocol == 2) | |
2414 msn = TRUE; | |
2415 break; | |
2221 } | 2416 } |
2222 | 2417 |
2223 l = l->next; | 2418 l = l->next; |
2224 } | 2419 } |
2225 | 2420 |
2226 if (!who) | 2421 if (!temp) |
2227 return; | 2422 return; |
2228 if (!group) | 2423 if (!group) |
2229 group = ""; | 2424 group = ""; |
2425 | |
2426 if(msn) | |
2427 who = g_strconcat("msn/", temp, NULL); | |
2428 else | |
2429 who = g_strdup(temp); | |
2230 | 2430 |
2231 if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */ | 2431 if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */ |
2232 f = yahoo_friend_find_or_new(gc, who); | 2432 f = yahoo_friend_find_or_new(gc, who); |
2233 yahoo_update_status(gc, who, f); | 2433 yahoo_update_status(gc, who, f); |
2434 if(protocol) | |
2435 f->protocol = protocol; | |
2436 | |
2437 if( !g_hash_table_lookup(yd->peers, who) ) { | |
2438 /* we are not connected as client, so set friend to not connected */ | |
2439 if(msn) | |
2440 yahoo_friend_set_p2p_status(f,YAHOO_P2PSTATUS_DO_NOT_CONNECT); | |
2441 else { | |
2442 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); | |
2443 f->p2p_packet_sent = 0; | |
2444 } | |
2445 } | |
2446 else /* we are already connected. set friend to YAHOO_P2PSTATUS_WE_ARE_CLIENT */ | |
2447 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT); | |
2234 return; | 2448 return; |
2235 } | 2449 } |
2236 | 2450 |
2237 decoded_group = yahoo_string_decode(gc, group, FALSE); | 2451 decoded_group = yahoo_string_decode(gc, group, FALSE); |
2238 buf = g_strdup_printf(_("Could not add buddy %s to group %s to the server list on account %s."), | 2452 buf = g_strdup_printf(_("Could not add buddy %s to group %s to the server list on account %s."), |
2239 who, decoded_group, purple_connection_get_display_name(gc)); | 2453 who, decoded_group, purple_connection_get_display_name(gc)); |
2240 if (!purple_conv_present_error(who, purple_connection_get_account(gc), buf)) | 2454 if (!purple_conv_present_error(who, purple_connection_get_account(gc), buf)) |
2241 purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); | 2455 purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); |
2242 g_free(buf); | 2456 g_free(buf); |
2243 g_free(decoded_group); | 2457 g_free(decoded_group); |
2458 g_free(who); | |
2459 } | |
2460 | |
2461 /* write pkt to the source */ | |
2462 static void yahoo_p2p_write_pkt(gint source, struct yahoo_packet *pkt) | |
2463 { | |
2464 size_t pkt_len; | |
2465 guchar *raw_packet; | |
2466 | |
2467 /*build the raw packet and send it to the host*/ | |
2468 pkt_len = yahoo_packet_build(pkt, 0, 0, 0, &raw_packet); | |
2469 if(write(source, raw_packet, pkt_len) != pkt_len) | |
2470 purple_debug_warning("yahoo","p2p: couldn't write to the source\n"); | |
2471 g_free(raw_packet); | |
2472 } | |
2473 | |
2474 static void yahoo_p2p_keepalive_cb(gpointer key, gpointer value, gpointer user_data) | |
2475 { | |
2476 struct yahoo_p2p_data *p2p_data = value; | |
2477 PurpleConnection *gc = user_data; | |
2478 struct yahoo_packet *pkt_to_send; | |
2479 PurpleAccount *account; | |
2480 struct yahoo_data *yd = gc->proto_data; | |
2481 | |
2482 account = purple_connection_get_account(gc); | |
2483 | |
2484 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
2485 yahoo_packet_hash(pkt_to_send, "ssisi", | |
2486 4, purple_normalize(account, purple_account_get_username(account)), | |
2487 5, p2p_data->host_username, | |
2488 241, 0, /* Protocol identifier */ | |
2489 49, "PEERTOPEER", | |
2490 13, 7); | |
2491 yahoo_p2p_write_pkt(p2p_data->source, pkt_to_send); | |
2492 | |
2493 yahoo_packet_free(pkt_to_send); | |
2494 } | |
2495 | |
2496 static gboolean yahoo_p2p_keepalive(gpointer data) | |
2497 { | |
2498 PurpleConnection *gc = data; | |
2499 struct yahoo_data *yd = gc->proto_data; | |
2500 | |
2501 g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc); | |
2502 | |
2503 return TRUE; | |
2504 } | |
2505 | |
2506 /* destroy p2p_data associated with a peer and close p2p connection. | |
2507 * g_hash_table_remove() calls this function to destroy p2p_data associated with the peer, | |
2508 * call g_hash_table_remove() instead of this fucntion if peer has an entry in the table */ | |
2509 static void yahoo_p2p_disconnect_destroy_data(gpointer data) | |
2510 { | |
2511 struct yahoo_p2p_data *p2p_data; | |
2512 YahooFriend *f; | |
2513 | |
2514 if(!(p2p_data = data)) | |
2515 return ; | |
2516 | |
2517 /* If friend, set him not connected */ | |
2518 f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username); | |
2519 if (f) | |
2520 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); | |
2521 | |
2522 if(p2p_data->source >= 0) | |
2523 close(p2p_data->source); | |
2524 purple_input_remove(p2p_data->input_event); | |
2525 g_free(p2p_data->host_ip); | |
2526 g_free(p2p_data->host_username); | |
2527 g_free(p2p_data); | |
2528 } | |
2529 | |
2530 /* exchange of initial p2pfilexfer packets, service type YAHOO_SERVICE_P2PFILEXFER */ | |
2531 static void yahoo_p2p_process_p2pfilexfer(gpointer data, gint source, struct yahoo_packet *pkt) | |
2532 { | |
2533 struct yahoo_p2p_data *p2p_data; | |
2534 char *who = NULL; | |
2535 GSList *l = pkt->hash; | |
2536 struct yahoo_packet *pkt_to_send; | |
2537 PurpleAccount *account; | |
2538 int val_13_to_send = 0; | |
2539 struct yahoo_data *yd; | |
2540 YahooFriend *f; | |
2541 | |
2542 if(!(p2p_data = data)) | |
2543 return ; | |
2544 | |
2545 yd = p2p_data->gc->proto_data; | |
2546 | |
2547 /* lets see whats in the packet */ | |
2548 while (l) { | |
2549 struct yahoo_pair *pair = l->data; | |
2550 | |
2551 switch (pair->key) { | |
2552 case 4: | |
2553 who = pair->value; | |
2554 if(strncmp(who, p2p_data->host_username, strlen(p2p_data->host_username)) != 0) { | |
2555 /* from whom are we receiving the packets ?? */ | |
2556 purple_debug_warning("yahoo","p2p: received data from wrong user\n"); | |
2557 return; | |
2558 } | |
2559 break; | |
2560 case 13: | |
2561 p2p_data->val_13 = strtol(pair->value, NULL, 10); /* Value should be 5-7 */ | |
2562 break; | |
2563 /* case 5, 49 look laters, no use right now */ | |
2564 } | |
2565 l = l->next; | |
2566 } | |
2567 | |
2568 account = purple_connection_get_account(p2p_data->gc); | |
2569 | |
2570 /* key_13: sort of a counter. | |
2571 * WHEN WE ARE CLIENT: yahoo server sends val_13 = 0, we send to peer val_13 = 1, receive back val_13 = 5, | |
2572 * we send val_13=6, receive val_13=7, we send val_13=7, HALT. Keep sending val_13 = 7 as keep alive. | |
2573 * WHEN WE ARE SERVER: we send val_13 = 0 to yahoo server, peer sends us val_13 = 1, we send val_13 = 5, | |
2574 * receive val_13 = 6, send val_13 = 7, receive val_13 = 7. HALT. Keep sending val_13 = 7 as keep alive. */ | |
2575 | |
2576 switch(p2p_data->val_13) { | |
2577 case 1 : val_13_to_send = 5; break; | |
2578 case 5 : val_13_to_send = 6; break; | |
2579 case 6 : val_13_to_send = 7; break; | |
2580 case 7 : if( g_hash_table_lookup(yd->peers, p2p_data->host_username) ) | |
2581 return; | |
2582 val_13_to_send = 7; break; | |
2583 default: purple_debug_warning("yahoo","p2p:Unknown value for key 13\n"); | |
2584 return; | |
2585 } | |
2586 | |
2587 /* Build the yahoo packet */ | |
2588 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
2589 yahoo_packet_hash(pkt_to_send, "ssisi", | |
2590 4, purple_normalize(account, purple_account_get_username(account)), | |
2591 5, p2p_data->host_username, | |
2592 241, 0, /* Protocol identifier */ | |
2593 49, "PEERTOPEER", | |
2594 13, val_13_to_send); | |
2595 | |
2596 /* build the raw packet and send it to the host */ | |
2597 yahoo_p2p_write_pkt(source, pkt_to_send); | |
2598 yahoo_packet_free(pkt_to_send); | |
2599 | |
2600 if( val_13_to_send == 7 ) | |
2601 if( !g_hash_table_lookup(yd->peers, p2p_data->host_username) ) { | |
2602 g_hash_table_insert(yd->peers, g_strdup(p2p_data->host_username), p2p_data); | |
2603 /* If the peer is a friend, set him connected */ | |
2604 f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username); | |
2605 if (f) { | |
2606 if(p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) { | |
2607 p2p_data->session_id = f->session_id; | |
2608 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_SERVER); | |
2609 } | |
2610 else | |
2611 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT); | |
2612 } | |
2613 } | |
2614 } | |
2615 | |
2616 /* callback function associated with receiving of data, not considering receipt of multiple YMSG packets in a single TCP packet */ | |
2617 static void yahoo_p2p_read_pkt_cb(gpointer data, gint source, PurpleInputCondition cond) | |
2618 { | |
2619 guchar buf[1024]; /* is it safe to assume a fixed array length of 1024 ?? */ | |
2620 int len; | |
2621 int pos = 0; | |
2622 int pktlen; | |
2623 struct yahoo_packet *pkt; | |
2624 guchar *start = NULL; | |
2625 struct yahoo_p2p_data *p2p_data; | |
2626 struct yahoo_data *yd; | |
2627 | |
2628 if(!(p2p_data = data)) | |
2629 return ; | |
2630 yd = p2p_data->gc->proto_data; | |
2631 | |
2632 len = read(source, buf, sizeof(buf)); | |
2633 if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) | |
2634 return ; /* No Worries*/ | |
2635 else if (len <= 0) | |
2636 { | |
2637 purple_debug_warning("yahoo","p2p: Error in connection, or host disconnected\n"); | |
2638 /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */ | |
2639 if( g_hash_table_lookup(yd->peers, p2p_data->host_username) ) | |
2640 g_hash_table_remove(yd->peers,p2p_data->host_username); | |
2641 else | |
2642 yahoo_p2p_disconnect_destroy_data(data); | |
2643 return; | |
2644 } | |
2645 | |
2646 if(len < YAHOO_PACKET_HDRLEN) | |
2647 return; | |
2648 | |
2649 if(strncmp((char *)buf, "YMSG", MIN(4, len)) != 0) { | |
2650 /* Not a YMSG packet */ | |
2651 purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n"); | |
2652 | |
2653 start = memchr(buf + 1, 'Y', len - 1); | |
2654 if(start) { | |
2655 g_memmove(buf, start, len - (start - buf)); | |
2656 len -= start - buf; | |
2657 } else { | |
2658 g_free(buf); | |
2659 return; | |
2660 } | |
2661 } | |
2662 | |
2663 pos += 4; /* YMSG */ | |
2664 pos += 2; | |
2665 pos += 2; | |
2666 | |
2667 pktlen = yahoo_get16(buf + pos); pos += 2; | |
2668 purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: %d bytes to read\n", len); | |
2669 | |
2670 pkt = yahoo_packet_new(0, 0, 0); | |
2671 pkt->service = yahoo_get16(buf + pos); pos += 2; | |
2672 pkt->status = yahoo_get32(buf + pos); pos += 4; | |
2673 pkt->id = yahoo_get32(buf + pos); pos += 4; | |
2674 | |
2675 purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: Yahoo Service: 0x%02x Status: %d\n",pkt->service, pkt->status); | |
2676 yahoo_packet_read(pkt, buf + pos, pktlen); | |
2677 | |
2678 /* packet processing */ | |
2679 switch(pkt->service) { | |
2680 case YAHOO_SERVICE_P2PFILEXFER: | |
2681 yahoo_p2p_process_p2pfilexfer(data, source, pkt); | |
2682 break; | |
2683 case YAHOO_SERVICE_MESSAGE: | |
2684 yahoo_process_message(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P); | |
2685 break; | |
2686 case YAHOO_SERVICE_NOTIFY: | |
2687 yahoo_process_notify(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P); | |
2688 break; | |
2689 default: | |
2690 purple_debug_warning("yahoo","p2p: p2p service %d Unhandled\n",pkt->service); | |
2691 } | |
2692 | |
2693 yahoo_packet_free(pkt); | |
2694 } | |
2695 | |
2696 static void yahoo_p2p_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond) | |
2697 { | |
2698 int acceptfd; | |
2699 struct yahoo_p2p_data *p2p_data; | |
2700 struct yahoo_data *yd; | |
2701 | |
2702 if(!(p2p_data = data)) | |
2703 return ; | |
2704 yd = p2p_data->gc->proto_data; | |
2705 | |
2706 acceptfd = accept(source, NULL, 0); | |
2707 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) | |
2708 return; | |
2709 else if(acceptfd == -1) { | |
2710 purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno)); | |
2711 yahoo_p2p_disconnect_destroy_data(data); | |
2712 return; | |
2713 } | |
2714 | |
2715 /* remove timeout */ | |
2716 purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle); | |
2717 yd->yahoo_p2p_server_timeout_handle = 0; | |
2718 | |
2719 /* remove watcher and close p2p server */ | |
2720 purple_input_remove(yd->yahoo_p2p_server_watcher); | |
2721 close(yd->yahoo_local_p2p_server_fd); | |
2722 yd->yahoo_local_p2p_server_fd = -1; | |
2723 | |
2724 /* Add an Input Read event to the file descriptor */ | |
2725 p2p_data->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data); | |
2726 p2p_data->source = acceptfd; | |
2727 } | |
2728 | |
2729 static gboolean yahoo_cancel_p2p_server_listen_cb(gpointer data) | |
2730 { | |
2731 struct yahoo_p2p_data *p2p_data; | |
2732 struct yahoo_data *yd; | |
2733 | |
2734 if(!(p2p_data = data)) | |
2735 return FALSE; | |
2736 | |
2737 yd = p2p_data->gc->proto_data; | |
2738 | |
2739 purple_debug_warning("yahoo","yahoo p2p server timeout, peer failed to connect"); | |
2740 yahoo_p2p_disconnect_destroy_data(data); | |
2741 purple_input_remove(yd->yahoo_p2p_server_watcher); | |
2742 yd->yahoo_p2p_server_watcher = 0; | |
2743 close(yd->yahoo_local_p2p_server_fd); | |
2744 yd->yahoo_local_p2p_server_fd = -1; | |
2745 yd->yahoo_p2p_server_timeout_handle = 0; | |
2746 | |
2747 return FALSE; | |
2748 } | |
2749 | |
2750 static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data) | |
2751 { | |
2752 struct yahoo_p2p_data *p2p_data; | |
2753 struct yahoo_data *yd; | |
2754 | |
2755 if(!(p2p_data = data)) | |
2756 return ; | |
2757 | |
2758 if(listenfd == -1) { | |
2759 purple_debug_warning("yahoo","p2p: error starting p2p server\n"); | |
2760 yahoo_p2p_disconnect_destroy_data(data); | |
2761 return; | |
2762 } | |
2763 | |
2764 yd = p2p_data->gc->proto_data; | |
2765 | |
2766 /* Add an Input Read event to the file descriptor */ | |
2767 yd->yahoo_local_p2p_server_fd = listenfd; | |
2768 yd->yahoo_p2p_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_server_send_connected_cb,data); | |
2769 | |
2770 /* add timeout */ | |
2771 yd->yahoo_p2p_server_timeout_handle = purple_timeout_add_seconds(YAHOO_P2P_SERVER_TIMEOUT, yahoo_cancel_p2p_server_listen_cb, data); | |
2772 } | |
2773 | |
2774 /* send p2p pkt containing our encoded ip, asking peer to connect to us */ | |
2775 void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13) | |
2776 { | |
2777 const char *public_ip; | |
2778 guint32 temp[4]; | |
2779 guint32 ip; | |
2780 char temp_str[100]; | |
2781 gchar *base64_ip = NULL; | |
2782 YahooFriend *f; | |
2783 struct yahoo_packet *pkt; | |
2784 PurpleAccount *account; | |
2785 struct yahoo_data *yd = gc->proto_data; | |
2786 struct yahoo_p2p_data *p2p_data; | |
2787 | |
2788 f = yahoo_friend_find(gc, who); | |
2789 account = purple_connection_get_account(gc); | |
2790 | |
2791 /* Do not send invitation if already listening for other connection */ | |
2792 if(yd->yahoo_local_p2p_server_fd >= 0) | |
2793 return; | |
2794 | |
2795 /* One shouldn't try to connect to self */ | |
2796 if( strcmp(purple_normalize(account, purple_account_get_username(account)), who) == 0) | |
2797 return; | |
2798 | |
2799 /* send packet to only those friends who arent p2p connected and to whom we havent already sent. Do not send if this condition doesn't hold good */ | |
2800 if( !( f && (yahoo_friend_get_p2p_status(f) == YAHOO_P2PSTATUS_NOT_CONNECTED) && (f->p2p_packet_sent == 0)) ) | |
2801 return; | |
2802 | |
2803 /* Dont send p2p packet to buddies of other protocols */ | |
2804 if(f->protocol) | |
2805 return; | |
2806 | |
2807 /* Finally, don't try to connect to buddies not online or on sms */ | |
2808 if( (f->status == YAHOO_STATUS_OFFLINE) || f->sms ) | |
2809 return; | |
2810 | |
2811 public_ip = purple_network_get_public_ip(); | |
2812 if( (sscanf(public_ip, "%u.%u.%u.%u", &temp[0], &temp[1], &temp[2], &temp[3])) !=4 ) | |
2813 return ; | |
2814 | |
2815 ip = (temp[3] << 24) | (temp[2] <<16) | (temp[1] << 8) | temp[0]; | |
2816 sprintf(temp_str, "%d", ip); | |
2817 base64_ip = purple_base64_encode( (guchar *)temp_str, strlen(temp_str) ); | |
2818 | |
2819 pkt = yahoo_packet_new(YAHOO_SERVICE_PEERTOPEER, YAHOO_STATUS_AVAILABLE, 0); | |
2820 yahoo_packet_hash(pkt, "sssissis", | |
2821 1, purple_normalize(account, purple_account_get_username(account)), | |
2822 4, purple_normalize(account, purple_account_get_username(account)), | |
2823 12, base64_ip, /* base64 encode ip */ | |
2824 61, 0, /* To-do : figure out what is 61 for?? */ | |
2825 2, "", | |
2826 5, who, | |
2827 13, val_13, | |
2828 49, "PEERTOPEER"); | |
2829 yahoo_packet_send_and_free(pkt, yd); | |
2830 | |
2831 f->p2p_packet_sent = 1; /* set p2p_packet_sent to sent */ | |
2832 | |
2833 p2p_data = g_new0(struct yahoo_p2p_data, 1); | |
2834 | |
2835 p2p_data->gc = gc; | |
2836 p2p_data->host_ip = NULL; | |
2837 p2p_data->host_username = g_strdup(who); | |
2838 p2p_data->val_13 = val_13; | |
2839 p2p_data->connection_type = YAHOO_P2P_WE_ARE_SERVER; | |
2840 | |
2841 purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, p2p_data); | |
2842 | |
2843 g_free(base64_ip); | |
2844 } | |
2845 | |
2846 /* function called when connection to p2p host is setup */ | |
2847 static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message) | |
2848 { | |
2849 struct yahoo_p2p_data *p2p_data; | |
2850 struct yahoo_packet *pkt_to_send; | |
2851 PurpleAccount *account; | |
2852 struct yahoo_data *yd; | |
2853 | |
2854 if(!(p2p_data = data)) | |
2855 return ; | |
2856 yd = p2p_data->gc->proto_data; | |
2857 | |
2858 if(error_message != NULL) { | |
2859 purple_debug_warning("yahoo","p2p: %s\n",error_message); | |
2860 yahoo_send_p2p_pkt(p2p_data->gc, p2p_data->host_username, 2);/* send p2p init packet with val_13=2 */ | |
2861 | |
2862 yahoo_p2p_disconnect_destroy_data(p2p_data); | |
2863 return; | |
2864 } | |
2865 | |
2866 /* Add an Input Read event to the file descriptor */ | |
2867 p2p_data->input_event = purple_input_add(source, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data); | |
2868 p2p_data->source = source; | |
2869 | |
2870 account = purple_connection_get_account(p2p_data->gc); | |
2871 | |
2872 /* Build the yahoo packet */ | |
2873 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
2874 yahoo_packet_hash(pkt_to_send, "ssisi", | |
2875 4, purple_normalize(account, purple_account_get_username(account)), | |
2876 5, p2p_data->host_username, | |
2877 241, 0, /* Protocol identifier */ | |
2878 49, "PEERTOPEER", | |
2879 13, 1); /* we receive key13= 0 or 2, we send key13=1 */ | |
2880 | |
2881 yahoo_p2p_write_pkt(source, pkt_to_send); /* build raw packet and send */ | |
2882 yahoo_packet_free(pkt_to_send); | |
2244 } | 2883 } |
2245 | 2884 |
2246 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt) | 2885 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt) |
2247 { | 2886 { |
2248 GSList *l = pkt->hash; | 2887 GSList *l = pkt->hash; |
2249 char *who = NULL; | 2888 char *who = NULL; |
2250 char *base64 = NULL; | 2889 char *base64 = NULL; |
2251 guchar *decoded; | 2890 guchar *decoded; |
2252 gsize len; | 2891 gsize len; |
2892 gint val_13 = 0; | |
2893 gint val_11 = 0; | |
2894 PurpleAccount *account; | |
2895 YahooFriend *f; | |
2896 | |
2897 /* if status is not 1 ie YAHOO_STATUS_BRB, the packet bounced back, so contains our own ip */ | |
2898 if(!(pkt->status == YAHOO_STATUS_BRB)) | |
2899 return ; | |
2253 | 2900 |
2254 while (l) { | 2901 while (l) { |
2255 struct yahoo_pair *pair = l->data; | 2902 struct yahoo_pair *pair = l->data; |
2256 | 2903 |
2257 switch (pair->key) { | 2904 switch (pair->key) { |
2267 case 12: | 2914 case 12: |
2268 base64 = pair->value; | 2915 base64 = pair->value; |
2269 /* so, this is an ip address. in base64. decoded it's in ascii. | 2916 /* so, this is an ip address. in base64. decoded it's in ascii. |
2270 after strtol, it's in reversed byte order. Who thought this up?*/ | 2917 after strtol, it's in reversed byte order. Who thought this up?*/ |
2271 break; | 2918 break; |
2919 case 13: | |
2920 val_13 = strtol(pair->value, NULL, 10); | |
2921 break; | |
2922 case 11: | |
2923 val_11 = strtol(pair->value, NULL, 10); /* session id of peer */ | |
2924 if( (f = yahoo_friend_find(gc, who)) ) | |
2925 f->session_id = val_11; | |
2926 break; | |
2272 /* | 2927 /* |
2273 TODO: figure these out | 2928 TODO: figure these out |
2274 yahoo: Key: 61 Value: 0 | 2929 yahoo: Key: 61 Value: 0 |
2275 yahoo: Key: 2 Value: | 2930 yahoo: Key: 2 Value: |
2276 yahoo: Key: 13 Value: 0 | 2931 yahoo: Key: 13 Value: 0 packet count ?? |
2277 yahoo: Key: 49 Value: PEERTOPEER | 2932 yahoo: Key: 49 Value: PEERTOPEER |
2278 yahoo: Key: 140 Value: 1 | 2933 yahoo: Key: 140 Value: 1 |
2279 yahoo: Key: 11 Value: -1786225828 | |
2280 */ | 2934 */ |
2281 | 2935 |
2282 } | 2936 } |
2283 | 2937 |
2284 l = l->next; | 2938 l = l->next; |
2286 | 2940 |
2287 if (base64) { | 2941 if (base64) { |
2288 guint32 ip; | 2942 guint32 ip; |
2289 char *tmp2; | 2943 char *tmp2; |
2290 YahooFriend *f; | 2944 YahooFriend *f; |
2945 char *host_ip; | |
2946 struct yahoo_p2p_data *p2p_data = g_new0(struct yahoo_p2p_data, 1); | |
2291 | 2947 |
2292 decoded = purple_base64_decode(base64, &len); | 2948 decoded = purple_base64_decode(base64, &len); |
2293 if (len) { | 2949 if (len) { |
2294 char *tmp = purple_str_binary_to_ascii(decoded, len); | 2950 char *tmp = purple_str_binary_to_ascii(decoded, len); |
2295 purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); | 2951 purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); |
2298 | 2954 |
2299 tmp2 = g_strndup((const gchar *)decoded, len); /* so its \0 terminated...*/ | 2955 tmp2 = g_strndup((const gchar *)decoded, len); /* so its \0 terminated...*/ |
2300 ip = strtol(tmp2, NULL, 10); | 2956 ip = strtol(tmp2, NULL, 10); |
2301 g_free(tmp2); | 2957 g_free(tmp2); |
2302 g_free(decoded); | 2958 g_free(decoded); |
2303 tmp2 = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, | 2959 host_ip = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, |
2304 (ip >> 24) & 0xff); | 2960 (ip >> 24) & 0xff); |
2305 f = yahoo_friend_find(gc, who); | 2961 f = yahoo_friend_find(gc, who); |
2306 if (f) | 2962 if (f) |
2307 yahoo_friend_set_ip(f, tmp2); | 2963 yahoo_friend_set_ip(f, host_ip); |
2308 g_free(tmp2); | 2964 purple_debug_info("yahoo", "IP : %s\n", host_ip); |
2965 | |
2966 account = purple_connection_get_account(gc); | |
2967 | |
2968 if(val_11==0) { | |
2969 if(!f) | |
2970 return; | |
2971 else | |
2972 val_11 = f->session_id; | |
2973 } | |
2974 | |
2975 p2p_data->host_username = g_strdup(who); | |
2976 p2p_data->val_13 = val_13; | |
2977 p2p_data->session_id = val_11; | |
2978 p2p_data->host_ip = host_ip; | |
2979 p2p_data->gc = gc; | |
2980 p2p_data->connection_type = YAHOO_P2P_WE_ARE_CLIENT; | |
2981 | |
2982 /* connect to host */ | |
2983 if((purple_proxy_connect(NULL, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, p2p_data))==NULL) { | |
2984 yahoo_p2p_disconnect_destroy_data(p2p_data); | |
2985 purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip); | |
2986 } | |
2309 } | 2987 } |
2310 } | 2988 } |
2311 | 2989 |
2312 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt) | 2990 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt) |
2313 { | 2991 { |
2383 case YAHOO_SERVICE_Y6_STATUS_UPDATE: | 3061 case YAHOO_SERVICE_Y6_STATUS_UPDATE: |
2384 case YAHOO_SERVICE_STATUS_15: | 3062 case YAHOO_SERVICE_STATUS_15: |
2385 yahoo_process_status(gc, pkt); | 3063 yahoo_process_status(gc, pkt); |
2386 break; | 3064 break; |
2387 case YAHOO_SERVICE_NOTIFY: | 3065 case YAHOO_SERVICE_NOTIFY: |
2388 yahoo_process_notify(gc, pkt); | 3066 yahoo_process_notify(gc, pkt, YAHOO_PKT_TYPE_SERVER); |
2389 break; | 3067 break; |
2390 case YAHOO_SERVICE_MESSAGE: | 3068 case YAHOO_SERVICE_MESSAGE: |
2391 case YAHOO_SERVICE_GAMEMSG: | 3069 case YAHOO_SERVICE_GAMEMSG: |
2392 case YAHOO_SERVICE_CHATMSG: | 3070 case YAHOO_SERVICE_CHATMSG: |
2393 yahoo_process_message(gc, pkt); | 3071 yahoo_process_message(gc, pkt, YAHOO_PKT_TYPE_SERVER); |
2394 break; | 3072 break; |
2395 case YAHOO_SERVICE_SYSMESSAGE: | 3073 case YAHOO_SERVICE_SYSMESSAGE: |
2396 yahoo_process_sysmessage(gc, pkt); | 3074 yahoo_process_sysmessage(gc, pkt); |
2397 break; | 3075 break; |
2398 case YAHOO_SERVICE_NEWMAIL: | 3076 case YAHOO_SERVICE_NEWMAIL: |
2465 case YAHOO_SERVICE_PRESENCE_SESSION: | 3143 case YAHOO_SERVICE_PRESENCE_SESSION: |
2466 yahoo_process_presence(gc, pkt); | 3144 yahoo_process_presence(gc, pkt); |
2467 break; | 3145 break; |
2468 case YAHOO_SERVICE_P2PFILEXFER: | 3146 case YAHOO_SERVICE_P2PFILEXFER: |
2469 /* This case had no break and continued; thus keeping it this way.*/ | 3147 /* This case had no break and continued; thus keeping it this way.*/ |
2470 yahoo_process_p2pfilexfer(gc, pkt); | 3148 yahoo_process_p2p(gc, pkt); /* P2PFILEXFER handled the same way as process_p2p */ |
3149 yahoo_process_p2pfilexfer(gc, pkt); /* redundant ??, need to have a break now */ | |
2471 case YAHOO_SERVICE_FILETRANSFER: | 3150 case YAHOO_SERVICE_FILETRANSFER: |
2472 yahoo_process_filetransfer(gc, pkt); | 3151 yahoo_process_filetransfer(gc, pkt); |
2473 break; | 3152 break; |
2474 case YAHOO_SERVICE_PEERTOPEER: | 3153 case YAHOO_SERVICE_PEERTOPEER: |
2475 yahoo_process_p2p(gc, pkt); | 3154 yahoo_process_p2p(gc, pkt); |
2498 case YAHOO_SERVICE_FILETRANS_INFO_15: | 3177 case YAHOO_SERVICE_FILETRANS_INFO_15: |
2499 yahoo_process_filetrans_info_15(gc, pkt); | 3178 yahoo_process_filetrans_info_15(gc, pkt); |
2500 break; | 3179 break; |
2501 case YAHOO_SERVICE_FILETRANS_ACC_15: | 3180 case YAHOO_SERVICE_FILETRANS_ACC_15: |
2502 yahoo_process_filetrans_acc_15(gc, pkt); | 3181 yahoo_process_filetrans_acc_15(gc, pkt); |
3182 break; | |
3183 case YAHOO_SERVICE_SMS_MSG: | |
3184 yahoo_process_sms_message(gc, pkt); | |
2503 break; | 3185 break; |
2504 | 3186 |
2505 default: | 3187 default: |
2506 purple_debug(PURPLE_DEBUG_ERROR, "yahoo", | 3188 purple_debug(PURPLE_DEBUG_ERROR, "yahoo", |
2507 "Unhandled service 0x%02x\n", pkt->service); | 3189 "Unhandled service 0x%02x\n", pkt->service); |
3014 | 3696 |
3015 purple_connection_update_progress(gc, _("Connecting"), 1, 2); | 3697 purple_connection_update_progress(gc, _("Connecting"), 1, 2); |
3016 | 3698 |
3017 purple_connection_set_display_name(gc, purple_account_get_username(account)); | 3699 purple_connection_set_display_name(gc, purple_account_get_username(account)); |
3018 | 3700 |
3701 yd->yahoo_local_p2p_server_fd = -1; | |
3019 yd->fd = -1; | 3702 yd->fd = -1; |
3020 yd->txhandler = 0; | 3703 yd->txhandler = 0; |
3021 /* TODO: Is there a good grow size for the buffer? */ | 3704 /* TODO: Is there a good grow size for the buffer? */ |
3022 yd->txbuf = purple_circ_buffer_new(0); | 3705 yd->txbuf = purple_circ_buffer_new(0); |
3023 yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); | 3706 yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); |
3024 yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | 3707 yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); |
3025 yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); | 3708 yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); |
3709 yd->peers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_p2p_disconnect_destroy_data); | |
3710 yd->sms_carrier = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
3711 yd->yahoo_p2p_timer = purple_timeout_add_seconds(YAHOO_P2P_KEEPALIVE_SECS, yahoo_p2p_keepalive, gc); | |
3026 yd->confs = NULL; | 3712 yd->confs = NULL; |
3027 yd->conf_id = 2; | 3713 yd->conf_id = 2; |
3028 yd->last_keepalive = yd->last_ping = time(NULL); | 3714 yd->last_keepalive = yd->last_ping = time(NULL); |
3029 | 3715 |
3030 yd->current_status = get_yahoo_status_from_purple_status(status); | 3716 yd->current_status = get_yahoo_status_from_purple_status(status); |
3086 | 3772 |
3087 yd->chat_online = FALSE; | 3773 yd->chat_online = FALSE; |
3088 if (yd->in_chat) | 3774 if (yd->in_chat) |
3089 yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */ | 3775 yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */ |
3090 | 3776 |
3777 purple_timeout_remove(yd->yahoo_p2p_timer); | |
3778 if(yd->yahoo_p2p_server_timeout_handle != 0) | |
3779 purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle); | |
3780 | |
3781 /* close p2p server if it is waiting for a peer to connect */ | |
3782 purple_input_remove(yd->yahoo_p2p_server_watcher); | |
3783 close(yd->yahoo_local_p2p_server_fd); | |
3784 yd->yahoo_local_p2p_server_fd = -1; | |
3785 | |
3786 g_hash_table_destroy(yd->sms_carrier); | |
3787 g_hash_table_destroy(yd->peers); | |
3091 g_hash_table_destroy(yd->friends); | 3788 g_hash_table_destroy(yd->friends); |
3092 g_hash_table_destroy(yd->imvironments); | 3789 g_hash_table_destroy(yd->imvironments); |
3093 g_hash_table_destroy(yd->xfer_peer_idstring_map); | 3790 g_hash_table_destroy(yd->xfer_peer_idstring_map); |
3094 g_free(yd->chat_name); | 3791 g_free(yd->chat_name); |
3095 | 3792 |
3634 m = g_list_append(m, act); | 4331 m = g_list_append(m, act); |
3635 | 4332 |
3636 return m; | 4333 return m; |
3637 } | 4334 } |
3638 | 4335 |
4336 struct yahoo_sms_carrier_cb_data { | |
4337 PurpleConnection *gc; | |
4338 char *who; | |
4339 char *what; | |
4340 }; | |
4341 | |
4342 static int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags); | |
4343 | |
4344 static void yahoo_get_sms_carrier_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, | |
4345 const gchar *webdata, size_t len, const gchar *error_message) | |
4346 { | |
4347 struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data; | |
4348 PurpleConnection *gc = sms_cb_data->gc; | |
4349 struct yahoo_data *yd = gc->proto_data; | |
4350 char *mobile_no = NULL; | |
4351 char *status = NULL; | |
4352 char *carrier = NULL; | |
4353 PurpleAccount *account = purple_connection_get_account(gc); | |
4354 PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account); | |
4355 | |
4356 if (error_message != NULL) { | |
4357 purple_conversation_write(conv, NULL, "Cant send SMS, Unable to obtain mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
4358 | |
4359 g_free(sms_cb_data->who); | |
4360 g_free(sms_cb_data->what); | |
4361 g_free(sms_cb_data); | |
4362 return ; | |
4363 } | |
4364 else if (len > 0 && webdata && *webdata) { | |
4365 xmlnode *validate_data_root = xmlnode_from_str(webdata, -1); | |
4366 xmlnode *validate_data_child = xmlnode_get_child(validate_data_root, "mobile_no"); | |
4367 mobile_no = (char *)xmlnode_get_attrib(validate_data_child, "msisdn"); | |
4368 | |
4369 validate_data_root = xmlnode_copy(validate_data_child); | |
4370 validate_data_child = xmlnode_get_child(validate_data_root, "status"); | |
4371 status = xmlnode_get_data(validate_data_child); | |
4372 | |
4373 validate_data_child = xmlnode_get_child(validate_data_root, "carrier"); | |
4374 carrier = xmlnode_get_data(validate_data_child); | |
4375 | |
4376 purple_debug_info("yahoo","SMS validate data: Mobile:%s, Status:%s, Carrier:%s\n", mobile_no, status, carrier); | |
4377 | |
4378 if( strcmp(status, "Valid") == 0) { | |
4379 g_hash_table_insert(yd->sms_carrier, g_strdup_printf("+%s", mobile_no), g_strdup(carrier)); | |
4380 yahoo_send_im(sms_cb_data->gc, sms_cb_data->who, sms_cb_data->what, PURPLE_MESSAGE_SEND); | |
4381 } | |
4382 else { | |
4383 g_hash_table_insert(yd->sms_carrier, g_strdup_printf("+%s", mobile_no), g_strdup("Unknown")); | |
4384 purple_conversation_write(conv, NULL, "Cant send SMS, Unknown mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
4385 } | |
4386 | |
4387 xmlnode_free(validate_data_child); | |
4388 xmlnode_free(validate_data_root); | |
4389 g_free(sms_cb_data->who); | |
4390 g_free(sms_cb_data->what); | |
4391 g_free(sms_cb_data); | |
4392 g_free(mobile_no); | |
4393 g_free(status); | |
4394 g_free(carrier); | |
4395 } | |
4396 } | |
4397 | |
4398 static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data) | |
4399 { | |
4400 struct yahoo_data *yd = gc->proto_data; | |
4401 PurpleUtilFetchUrlData *url_data; | |
4402 struct yahoo_sms_carrier_cb_data *sms_cb_data; | |
4403 char *validate_request_str = NULL; | |
4404 char *request = NULL; | |
4405 gboolean use_whole_url = FALSE; | |
4406 xmlnode *validate_request_root = NULL; | |
4407 xmlnode *validate_request_child = NULL; | |
4408 | |
4409 if(!(sms_cb_data = data)) | |
4410 return; | |
4411 | |
4412 validate_request_root = xmlnode_new("validate"); | |
4413 xmlnode_set_attrib(validate_request_root, "intl", "us"); | |
4414 xmlnode_set_attrib(validate_request_root, "version", YAHOO_CLIENT_VERSION); | |
4415 xmlnode_set_attrib(validate_request_root, "qos", "0"); | |
4416 | |
4417 validate_request_child = xmlnode_new_child(validate_request_root, "mobile_no"); | |
4418 xmlnode_set_attrib(validate_request_child, "msisdn", sms_cb_data->who + 1); | |
4419 | |
4420 validate_request_str = xmlnode_to_str(validate_request_root, NULL); | |
4421 | |
4422 xmlnode_free(validate_request_child); | |
4423 xmlnode_free(validate_request_root); | |
4424 | |
4425 request = g_strdup_printf( | |
4426 "POST /mobileno?intl=us&version=%s HTTP/1.1\r\n" | |
4427 "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s; path=/; domain=.yahoo.com;\r\n" | |
4428 "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\n" | |
4429 "Host: validate.msg.yahoo.com\r\n" | |
4430 "Content-Length: %d\r\n" | |
4431 "Cache-Control: no-cache\r\n\r\n%s", | |
4432 YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str); | |
4433 | |
4434 /* use whole URL if using HTTP Proxy */ | |
4435 if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP)) | |
4436 use_whole_url = TRUE; | |
4437 | |
4438 url_data = purple_util_fetch_url_request(YAHOO_SMS_CARRIER_URL, use_whole_url, | |
4439 "Mozilla/4.0 (compatible; MSIE 5.5)", TRUE, request, FALSE, | |
4440 yahoo_get_sms_carrier_cb, data); | |
4441 | |
4442 g_free(request); | |
4443 g_free(validate_request_str); | |
4444 | |
4445 if (!url_data) { | |
4446 PurpleAccount *account = purple_connection_get_account(gc); | |
4447 PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account); | |
4448 purple_conversation_write(conv, NULL, "Cant send SMS, Unable to obtain mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
4449 g_free(sms_cb_data->who); | |
4450 g_free(sms_cb_data->what); | |
4451 g_free(sms_cb_data); | |
4452 } | |
4453 } | |
4454 | |
3639 static int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags) | 4455 static int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags) |
3640 { | 4456 { |
3641 struct yahoo_data *yd = gc->proto_data; | 4457 struct yahoo_data *yd = gc->proto_data; |
3642 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0); | 4458 struct yahoo_packet *pkt = NULL; |
3643 char *msg = yahoo_html_to_codes(what); | 4459 char *msg = yahoo_html_to_codes(what); |
3644 char *msg2; | 4460 char *msg2; |
3645 gboolean utf8 = TRUE; | 4461 gboolean utf8 = TRUE; |
3646 PurpleWhiteboard *wb; | 4462 PurpleWhiteboard *wb; |
3647 int ret = 1; | 4463 int ret = 1; |
3648 YahooFriend *f = NULL; | 4464 YahooFriend *f = NULL; |
3649 gsize lenb = 0; | 4465 gsize lenb = 0; |
3650 glong lenc = 0; | 4466 glong lenc = 0; |
3651 | 4467 struct yahoo_p2p_data *p2p_data; |
4468 gboolean msn = FALSE; | |
3652 msg2 = yahoo_string_encode(gc, msg, &utf8); | 4469 msg2 = yahoo_string_encode(gc, msg, &utf8); |
3653 | 4470 |
3654 if(msg2) { | 4471 if(msg2) { |
3655 lenb = strlen(msg2); | 4472 lenb = strlen(msg2); |
3656 lenc = g_utf8_strlen(msg2, -1); | 4473 lenc = g_utf8_strlen(msg2, -1); |
3665 g_free(msg2); | 4482 g_free(msg2); |
3666 return -E2BIG; | 4483 return -E2BIG; |
3667 } | 4484 } |
3668 } | 4485 } |
3669 | 4486 |
3670 yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, who); | 4487 msn = g_str_has_prefix(who, "msn/") || g_str_has_prefix(who, "MSN/"); |
3671 if ((f = yahoo_friend_find(gc, who)) && f->protocol) | 4488 |
3672 yahoo_packet_hash_int(pkt, 241, f->protocol); | 4489 if( strncmp(who, "+", 1) == 0 ) { |
4490 /* we have an sms to be sent */ | |
4491 gchar *carrier = NULL; | |
4492 const char *alias = NULL; | |
4493 PurpleAccount *account = purple_connection_get_account(gc); | |
4494 PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account); | |
4495 | |
4496 carrier = g_hash_table_lookup(yd->sms_carrier, who); | |
4497 if (!carrier) { | |
4498 struct yahoo_sms_carrier_cb_data *sms_cb_data; | |
4499 sms_cb_data = g_malloc(sizeof(struct yahoo_sms_carrier_cb_data)); | |
4500 sms_cb_data->gc = gc; | |
4501 sms_cb_data->who = g_malloc(strlen(who)); | |
4502 sms_cb_data->what = g_malloc(strlen(what)); | |
4503 strcpy(sms_cb_data->who, who); | |
4504 strcpy(sms_cb_data->what, what); | |
4505 | |
4506 purple_conversation_write(conv, NULL, "Getting mobile carrier to send the sms", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
4507 | |
4508 yahoo_get_sms_carrier(gc, sms_cb_data); | |
4509 | |
4510 g_free(msg); | |
4511 g_free(msg2); | |
4512 return ret; | |
4513 } | |
4514 else if( strcmp(carrier,"Unknown") == 0 ) { | |
4515 purple_conversation_write(conv, NULL, "Cant send SMS, Unknown mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
4516 | |
4517 g_free(msg); | |
4518 g_free(msg2); | |
4519 return -1; | |
4520 } | |
4521 | |
4522 alias = purple_account_get_alias(account); | |
4523 pkt = yahoo_packet_new(YAHOO_SERVICE_SMS_MSG, YAHOO_STATUS_AVAILABLE, 0); | |
4524 yahoo_packet_hash(pkt, "sssss", | |
4525 1, purple_connection_get_display_name(gc), | |
4526 69, alias, | |
4527 5, who + 1, | |
4528 68, carrier, | |
4529 14, msg2); | |
4530 yahoo_packet_send_and_free(pkt, yd); | |
4531 | |
4532 g_free(msg); | |
4533 g_free(msg2); | |
4534 | |
4535 return ret; | |
4536 } | |
4537 | |
4538 pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0); | |
4539 if(msn) { | |
4540 yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, who+4); | |
4541 yahoo_packet_hash_int(pkt, 241, 2); | |
4542 } | |
4543 else { | |
4544 yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, who); | |
4545 if ((f = yahoo_friend_find(gc, who)) && f->protocol) | |
4546 yahoo_packet_hash_int(pkt, 241, f->protocol); | |
4547 } | |
3673 | 4548 |
3674 if (utf8) | 4549 if (utf8) |
3675 yahoo_packet_hash_str(pkt, 97, "1"); | 4550 yahoo_packet_hash_str(pkt, 97, "1"); |
3676 yahoo_packet_hash_str(pkt, 14, msg2); | 4551 yahoo_packet_hash_str(pkt, 14, msg2); |
3677 | 4552 |
3706 yahoo_packet_hash_str(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */ | 4581 yahoo_packet_hash_str(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */ |
3707 else | 4582 else |
3708 yahoo_packet_hash_str(pkt, 206, "2"); | 4583 yahoo_packet_hash_str(pkt, 206, "2"); |
3709 | 4584 |
3710 /* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */ | 4585 /* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */ |
3711 if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) | 4586 if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) { |
3712 yahoo_packet_send(pkt, yd); | 4587 /* if p2p link exists, send through it. To-do: key 15, time value to be sent in case of p2p */ |
4588 if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !msn ) { | |
4589 yahoo_packet_hash_int(pkt, 11, p2p_data->session_id); | |
4590 yahoo_p2p_write_pkt(p2p_data->source, pkt); | |
4591 } | |
4592 else { | |
4593 yahoo_packet_send(pkt, yd); | |
4594 if(!msn) | |
4595 yahoo_send_p2p_pkt(gc, who, 0); /* send p2p packet, with val_13=0 */ | |
4596 } | |
4597 } | |
3713 else | 4598 else |
3714 ret = -E2BIG; | 4599 ret = -E2BIG; |
3715 | 4600 |
3716 yahoo_packet_free(pkt); | 4601 yahoo_packet_free(pkt); |
3717 | 4602 |
3722 } | 4607 } |
3723 | 4608 |
3724 static unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) | 4609 static unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) |
3725 { | 4610 { |
3726 struct yahoo_data *yd = gc->proto_data; | 4611 struct yahoo_data *yd = gc->proto_data; |
3727 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, 0); | 4612 struct yahoo_p2p_data *p2p_data; |
3728 yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), | 4613 gboolean msn = (g_str_has_prefix(who, "msn/") || g_str_has_prefix(who, "MSN/")); |
4614 struct yahoo_packet *pkt = NULL; | |
4615 | |
4616 /* Don't do anything if sms is being typed */ | |
4617 if( strncmp(who, "+", 1) == 0 ) | |
4618 return 0; | |
4619 | |
4620 pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, 0); | |
4621 | |
4622 /* check to see if p2p link exists, send through it */ | |
4623 if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !msn ) { | |
4624 yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc), | |
3729 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", | 4625 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", |
3730 5, who, 1002, "1"); | 4626 5, who, 11, p2p_data->session_id, 1002, "1"); /* To-do: key 15 to be sent in case of p2p */ |
3731 | 4627 yahoo_p2p_write_pkt(p2p_data->source, pkt); |
3732 yahoo_packet_send_and_free(pkt, yd); | 4628 yahoo_packet_free(pkt); |
4629 } | |
4630 else { /* send through yahoo server */ | |
4631 if(msn) | |
4632 yahoo_packet_hash(pkt, "sssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), | |
4633 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", | |
4634 5, who+4, 1002, "1", 241, "2"); | |
4635 else | |
4636 yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), | |
4637 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", | |
4638 5, who+4, 1002, "1"); | |
4639 yahoo_packet_send_and_free(pkt, yd); | |
4640 } | |
3733 | 4641 |
3734 return 0; | 4642 return 0; |
3735 } | 4643 } |
3736 | 4644 |
3737 static void yahoo_session_presence_remove(gpointer key, gpointer value, gpointer data) | 4645 static void yahoo_session_presence_remove(gpointer key, gpointer value, gpointer data) |
3973 struct yahoo_packet *pkt; | 4881 struct yahoo_packet *pkt; |
3974 const char *group = NULL; | 4882 const char *group = NULL; |
3975 char *group2; | 4883 char *group2; |
3976 YahooFriend *f; | 4884 YahooFriend *f; |
3977 const char *bname; | 4885 const char *bname; |
4886 gboolean msn = FALSE; | |
3978 | 4887 |
3979 if (!yd->logged_in) | 4888 if (!yd->logged_in) |
3980 return; | 4889 return; |
3981 | 4890 |
3982 bname = purple_buddy_get_name(buddy); | 4891 bname = purple_buddy_get_name(buddy); |
3983 if (!purple_privacy_check(purple_connection_get_account(gc), bname)) | 4892 if (!purple_privacy_check(purple_connection_get_account(gc), bname)) |
3984 return; | 4893 return; |
3985 | 4894 |
3986 f = yahoo_friend_find(gc, bname); | 4895 f = yahoo_friend_find(gc, bname); |
4896 msn = g_str_has_prefix(bname, "msn/") || g_str_has_prefix(bname, "MSN/"); | |
3987 | 4897 |
3988 g = purple_buddy_get_group(buddy); | 4898 g = purple_buddy_get_group(buddy); |
3989 if (g) | 4899 if (g) |
3990 group = purple_group_get_name(g); | 4900 group = purple_group_get_name(g); |
3991 else | 4901 else |
3992 group = "Buddies"; | 4902 group = "Buddies"; |
3993 | 4903 |
3994 group2 = yahoo_string_encode(gc, group, NULL); | 4904 group2 = yahoo_string_encode(gc, group, NULL); |
3995 pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0); | 4905 pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0); |
3996 yahoo_packet_hash(pkt, "ssssssssss", | 4906 if(msn) { |
3997 14, "", | 4907 yahoo_packet_hash(pkt, "sssssssssss", |
3998 65, group2, | 4908 14, "", |
3999 97, "1", | 4909 65, group2, |
4000 1, purple_connection_get_display_name(gc), | 4910 97, "1", |
4001 302, "319", | 4911 1, purple_connection_get_display_name(gc), |
4002 300, "319", | 4912 302, "319", |
4003 7, bname, | 4913 300, "319", |
4004 334, "0", | 4914 7, bname + 4, |
4005 301, "319", | 4915 241, "2", |
4006 303, "319" | 4916 334, "0", |
4007 ); | 4917 301, "319", |
4008 if (f && f->protocol) | 4918 303, "319" |
4919 ); | |
4920 } | |
4921 else { | |
4922 yahoo_packet_hash(pkt, "ssssssssss", | |
4923 14, "", | |
4924 65, group2, | |
4925 97, "1", | |
4926 1, purple_connection_get_display_name(gc), | |
4927 302, "319", | |
4928 300, "319", | |
4929 7, bname, | |
4930 334, "0", | |
4931 301, "319", | |
4932 303, "319" | |
4933 ); | |
4934 } | |
4935 if (f && f->protocol && !msn) | |
4009 yahoo_packet_hash_int(pkt, 241, f->protocol); | 4936 yahoo_packet_hash_int(pkt, 241, f->protocol); |
4937 | |
4010 yahoo_packet_send_and_free(pkt, yd); | 4938 yahoo_packet_send_and_free(pkt, yd); |
4011 g_free(group2); | 4939 g_free(group2); |
4012 } | 4940 } |
4013 | 4941 |
4014 static void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) | 4942 static void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) |
4018 GSList *buddies, *l; | 4946 GSList *buddies, *l; |
4019 PurpleGroup *g; | 4947 PurpleGroup *g; |
4020 gboolean remove = TRUE; | 4948 gboolean remove = TRUE; |
4021 char *cg; | 4949 char *cg; |
4022 const char *bname, *gname; | 4950 const char *bname, *gname; |
4951 YahooFriend *f = NULL; | |
4952 gboolean msn = FALSE; | |
4023 | 4953 |
4024 bname = purple_buddy_get_name(buddy); | 4954 bname = purple_buddy_get_name(buddy); |
4025 if (!(yahoo_friend_find(gc, bname))) | 4955 f = yahoo_friend_find(gc, bname); |
4956 if (!f) | |
4026 return; | 4957 return; |
4027 | 4958 |
4028 gname = purple_group_get_name(group); | 4959 gname = purple_group_get_name(group); |
4029 buddies = purple_find_buddies(purple_connection_get_account(gc), bname); | 4960 buddies = purple_find_buddies(purple_connection_get_account(gc), bname); |
4961 if(f->protocol == 2) | |
4962 msn = TRUE; | |
4030 for (l = buddies; l; l = l->next) { | 4963 for (l = buddies; l; l = l->next) { |
4031 g = purple_buddy_get_group(l->data); | 4964 g = purple_buddy_get_group(l->data); |
4032 if (purple_utf8_strcasecmp(gname, purple_group_get_name(g))) { | 4965 if (purple_utf8_strcasecmp(gname, purple_group_get_name(g))) { |
4033 remove = FALSE; | 4966 remove = FALSE; |
4034 break; | 4967 break; |
4040 if (remove) | 4973 if (remove) |
4041 g_hash_table_remove(yd->friends, bname); | 4974 g_hash_table_remove(yd->friends, bname); |
4042 | 4975 |
4043 cg = yahoo_string_encode(gc, gname, NULL); | 4976 cg = yahoo_string_encode(gc, gname, NULL); |
4044 pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0); | 4977 pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0); |
4045 yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), | 4978 |
4979 if(msn) | |
4980 yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), | |
4981 7, bname+4, 65, cg); | |
4982 else | |
4983 yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), | |
4046 7, bname, 65, cg); | 4984 7, bname, 65, cg); |
4985 if(f->protocol) | |
4986 yahoo_packet_hash_int(pkt, 241, f->protocol); | |
4047 yahoo_packet_send_and_free(pkt, yd); | 4987 yahoo_packet_send_and_free(pkt, yd); |
4048 g_free(cg); | 4988 g_free(cg); |
4049 } | 4989 } |
4050 | 4990 |
4051 static void yahoo_add_deny(PurpleConnection *gc, const char *who) { | 4991 static void yahoo_add_deny(PurpleConnection *gc, const char *who) { |
4114 const char *old_group, const char *new_group) | 5054 const char *old_group, const char *new_group) |
4115 { | 5055 { |
4116 struct yahoo_data *yd = gc->proto_data; | 5056 struct yahoo_data *yd = gc->proto_data; |
4117 struct yahoo_packet *pkt; | 5057 struct yahoo_packet *pkt; |
4118 char *gpn, *gpo; | 5058 char *gpn, *gpo; |
5059 YahooFriend *f = yahoo_friend_find(gc, who); | |
5060 gboolean msn = FALSE; | |
5061 const char *temp = NULL; | |
4119 | 5062 |
4120 /* Step 0: If they aren't on the server list anyway, | 5063 /* Step 0: If they aren't on the server list anyway, |
4121 * don't bother letting the server know. | 5064 * don't bother letting the server know. |
4122 */ | 5065 */ |
4123 if (!yahoo_friend_find(gc, who)) | 5066 if (!f) |
4124 return; | 5067 return; |
5068 | |
5069 if(f->protocol == 2) { | |
5070 msn = TRUE; | |
5071 temp = who+4; | |
5072 } else | |
5073 temp = who; | |
4125 | 5074 |
4126 /* If old and new are the same, we would probably | 5075 /* If old and new are the same, we would probably |
4127 * end up deleting the buddy, which would be bad. | 5076 * end up deleting the buddy, which would be bad. |
4128 * This might happen because of the charset conversation. | 5077 * This might happen because of the charset conversation. |
4129 */ | 5078 */ |
4134 g_free(gpo); | 5083 g_free(gpo); |
4135 return; | 5084 return; |
4136 } | 5085 } |
4137 | 5086 |
4138 pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, 0); | 5087 pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, 0); |
4139 yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc), | 5088 if(f->protocol) |
4140 302, "240", 300, "240", 7, who, 224, gpo, 264, gpn, 301, | 5089 yahoo_packet_hash(pkt, "ssssissss", 1, purple_connection_get_display_name(gc), |
5090 302, "240", 300, "240", 7, temp, 241, f->protocol, 224, gpo, 264, gpn, 301, | |
5091 "240", 303, "240"); | |
5092 else | |
5093 yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc), | |
5094 302, "240", 300, "240", 7, temp, 224, gpo, 264, gpn, 301, | |
4141 "240", 303, "240"); | 5095 "240", 303, "240"); |
4142 yahoo_packet_send_and_free(pkt, yd); | 5096 yahoo_packet_send_and_free(pkt, yd); |
4143 | 5097 |
4144 g_free(gpn); | 5098 g_free(gpn); |
4145 g_free(gpo); | 5099 g_free(gpo); |
4347 /* Spaces are encoded as '+' */ | 5301 /* Spaces are encoded as '+' */ |
4348 g_strdelimit(message, "+", ' '); | 5302 g_strdelimit(message, "+", ' '); |
4349 purple_conv_send_confirm(conv, message); | 5303 purple_conv_send_confirm(conv, message); |
4350 } | 5304 } |
4351 } | 5305 } |
4352 /*else | 5306 /* else |
4353 **If pidgindialogs_im() was in the core, we could use it here. | 5307 **If pidgindialogs_im() was in the core, we could use it here. |
4354 * It is all purple_request_* based, but I'm not sure it really belongs in the core | 5308 * It is all purple_request_* based, but I'm not sure it really belongs in the core |
4355 pidgindialogs_im();*/ | 5309 pidgindialogs_im(); */ |
4356 | 5310 |
4357 return TRUE; | 5311 return TRUE; |
4358 } | 5312 } |
4359 /* ymsgr:Chat?roomname */ | 5313 /* ymsgr:Chat?roomname */ |
4360 else if (!g_ascii_strcasecmp(cmd, "Chat")) { | 5314 else if (!g_ascii_strcasecmp(cmd, "Chat")) { |
4364 /* This is somewhat hacky, but the params aren't useful after this command */ | 5318 /* This is somewhat hacky, but the params aren't useful after this command */ |
4365 g_hash_table_insert(params, g_strdup("room"), g_strdup(rname)); | 5319 g_hash_table_insert(params, g_strdup("room"), g_strdup(rname)); |
4366 g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat")); | 5320 g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat")); |
4367 serv_join_chat(purple_account_get_connection(acct), params); | 5321 serv_join_chat(purple_account_get_connection(acct), params); |
4368 } | 5322 } |
4369 /*else | 5323 /* else |
4370 ** Same as above (except that this would have to be re-written using purple_request_*) | 5324 ** Same as above (except that this would have to be re-written using purple_request_*) |
4371 pidgin_blist_joinchat_show(); */ | 5325 pidgin_blist_joinchat_show(); */ |
4372 | 5326 |
4373 return TRUE; | 5327 return TRUE; |
4374 } | 5328 } |
4434 yahoo_set_idle, | 5388 yahoo_set_idle, |
4435 NULL, /* change_passwd*/ | 5389 NULL, /* change_passwd*/ |
4436 yahoo_add_buddy, | 5390 yahoo_add_buddy, |
4437 NULL, /* add_buddies */ | 5391 NULL, /* add_buddies */ |
4438 yahoo_remove_buddy, | 5392 yahoo_remove_buddy, |
4439 NULL, /*remove_buddies */ | 5393 NULL, /* remove_buddies */ |
4440 NULL, /* add_permit */ | 5394 NULL, /* add_permit */ |
4441 yahoo_add_deny, | 5395 yahoo_add_deny, |
4442 NULL, /* rem_permit */ | 5396 NULL, /* rem_permit */ |
4443 yahoo_rem_deny, | 5397 yahoo_rem_deny, |
4444 yahoo_set_permit_deny, | 5398 yahoo_set_permit_deny, |