| 26361:eeb395e3523f | 26362:de9cf498a73a |
|---|---|
| 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" |
| 233 case 19: /* custom message */ | 235 case 19: /* custom message */ |
| 234 if (f) | 236 if (f) |
| 235 message = pair->value; | 237 message = pair->value; |
| 236 break; | 238 break; |
| 237 case 11: /* this is the buddy's session id */ | 239 case 11: /* this is the buddy's session id */ |
| 240 if (f) | |
| 241 f->session_id = strtol(pair->value, NULL, 10); | |
| 238 break; | 242 break; |
| 239 case 17: /* in chat? */ | 243 case 17: /* in chat? */ |
| 240 break; | 244 break; |
| 241 case 47: /* is custom status away or not? 2=idle*/ | 245 case 47: /* is custom status away or not? 2=idle*/ |
| 242 if (!f) | 246 if (!f) |
| 519 } | 523 } |
| 520 b = purple_buddy_new(account, norm_bud, NULL); | 524 b = purple_buddy_new(account, norm_bud, NULL); |
| 521 purple_blist_add_buddy(b, NULL, g, NULL); | 525 purple_blist_add_buddy(b, NULL, g, NULL); |
| 522 } | 526 } |
| 523 yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp); | 527 yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp); |
| 528 | |
| 529 /* set p2p status not connected and no p2p packet sent */ | |
| 530 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); | |
| 531 f->p2p_packet_sent = 0; | |
| 524 | 532 |
| 525 } else { | 533 } else { |
| 526 /* This buddy is on the ignore list (and therefore in no group) */ | 534 /* This buddy is on the ignore list (and therefore in no group) */ |
| 527 purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n", | 535 purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n", |
| 528 account->username, norm_bud); | 536 account->username, norm_bud); |
| 633 purple_blist_add_buddy(b, NULL, g, NULL); | 641 purple_blist_add_buddy(b, NULL, g, NULL); |
| 634 export = TRUE; | 642 export = TRUE; |
| 635 } | 643 } |
| 636 | 644 |
| 637 yahoo_do_group_check(account, ht, norm_bud, grp); | 645 yahoo_do_group_check(account, ht, norm_bud, grp); |
| 646 /* set p2p status not connected and no p2p packet sent */ | |
| 647 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); | |
| 648 f->p2p_packet_sent = 0; | |
| 649 | |
| 638 g_free(norm_bud); | 650 g_free(norm_bud); |
| 639 } | 651 } |
| 640 g_strfreev(buddies); | 652 g_strfreev(buddies); |
| 641 g_strfreev(split); | 653 g_strfreev(split); |
| 642 g_free(grp); | 654 g_free(grp); |
| 689 } | 701 } |
| 690 /* Now that we've got the list, request aliases */ | 702 /* Now that we've got the list, request aliases */ |
| 691 yahoo_fetch_aliases(gc); | 703 yahoo_fetch_aliases(gc); |
| 692 } | 704 } |
| 693 | 705 |
| 694 static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt) | 706 /* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */ |
| 707 static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type) | |
| 695 { | 708 { |
| 696 PurpleAccount *account; | 709 PurpleAccount *account; |
| 697 char *msg = NULL; | 710 char *msg = NULL; |
| 698 char *from = NULL; | 711 char *from = NULL; |
| 699 char *stat = NULL; | 712 char *stat = NULL; |
| 700 char *game = NULL; | 713 char *game = NULL; |
| 701 YahooFriend *f = NULL; | 714 YahooFriend *f = NULL; |
| 702 GSList *l = pkt->hash; | 715 GSList *l = pkt->hash; |
| 716 gint val_11 = 0; | |
| 717 struct yahoo_data *yd = gc->proto_data; | |
| 703 | 718 |
| 704 account = purple_connection_get_account(gc); | 719 account = purple_connection_get_account(gc); |
| 705 | 720 |
| 706 while (l) { | 721 while (l) { |
| 707 struct yahoo_pair *pair = l->data; | 722 struct yahoo_pair *pair = l->data; |
| 708 if (pair->key == 4) | 723 if (pair->key == 4 || pair->key == 1) |
| 709 from = pair->value; | 724 from = pair->value; |
| 710 if (pair->key == 49) | 725 if (pair->key == 49) |
| 711 msg = pair->value; | 726 msg = pair->value; |
| 712 if (pair->key == 13) | 727 if (pair->key == 13) |
| 713 stat = pair->value; | 728 stat = pair->value; |
| 714 if (pair->key == 14) | 729 if (pair->key == 14) |
| 715 game = pair->value; | 730 game = pair->value; |
| 731 if (pair->key == 11) | |
| 732 val_11 = strtol(pair->value, NULL, 10); | |
| 716 l = l->next; | 733 l = l->next; |
| 717 } | 734 } |
| 718 | 735 |
| 719 if (!from || !msg) | 736 if (!from || !msg) |
| 720 return; | 737 return; |
| 738 | |
| 739 /* disconnect the peer if connected through p2p and sends wrong value for session id */ | |
| 740 if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) { | |
| 741 purple_debug_warning("yahoo","p2p: %s sent us notify with wrong session id. Disconnecting p2p connection to peer\n", from); | |
| 742 /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */ | |
| 743 g_hash_table_remove(yd->peers, from); | |
| 744 return; | |
| 745 } | |
| 721 | 746 |
| 722 if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")) | 747 if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")) |
| 723 && (purple_privacy_check(account, from))) | 748 && (purple_privacy_check(account, from))) |
| 724 { | 749 { |
| 725 if (*stat == '1') | 750 if (*stat == '1') |
| 762 int utf8; | 787 int utf8; |
| 763 int buddy_icon; | 788 int buddy_icon; |
| 764 char *msg; | 789 char *msg; |
| 765 }; | 790 }; |
| 766 | 791 |
| 767 static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt) | 792 static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt) |
| 793 { | |
| 794 PurpleAccount *account; | |
| 795 GSList *l = pkt->hash; | |
| 796 struct _yahoo_im *sms = NULL; | |
| 797 struct yahoo_data *yd; | |
| 798 char *server_msg = NULL; | |
| 799 char *m; | |
| 800 | |
| 801 yd = gc->proto_data; | |
| 802 account = purple_connection_get_account(gc); | |
| 803 | |
| 804 while (l != NULL) { | |
| 805 struct yahoo_pair *pair = l->data; | |
| 806 if (pair->key == 4) { | |
| 807 sms = g_new0(struct _yahoo_im, 1); | |
| 808 sms->from = g_strdup_printf("+%s", pair->value); | |
| 809 sms->time = time(NULL); | |
| 810 sms->utf8 = TRUE; | |
| 811 } | |
| 812 if (pair->key == 14) { | |
| 813 if (sms) | |
| 814 sms->msg = pair->value; | |
| 815 } | |
| 816 if (pair->key == 68) | |
| 817 if(sms) | |
| 818 g_hash_table_insert(yd->sms_carrier, g_strdup(sms->from), g_strdup(pair->value)); | |
| 819 if (pair->key == 16) | |
| 820 server_msg = pair->value; | |
| 821 l = l->next; | |
| 822 } | |
| 823 | |
| 824 if( (pkt->status == -1) || (pkt->status == YAHOO_STATUS_DISCONNECTED) ) { | |
| 825 if (server_msg) { | |
| 826 PurpleConversation *c; | |
| 827 c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms->from, account); | |
| 828 if (c == NULL) | |
| 829 c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sms->from); | |
| 830 purple_conversation_write(c, NULL, server_msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
| 831 } | |
| 832 else | |
| 833 purple_notify_error(gc, NULL, _("Your SMS was not delivered"), NULL); | |
| 834 | |
| 835 g_free(sms->from); | |
| 836 g_free(sms); | |
| 837 return ; | |
| 838 } | |
| 839 | |
| 840 if (!sms->from || !sms->msg) { | |
| 841 g_free(sms); | |
| 842 return; | |
| 843 } | |
| 844 | |
| 845 m = yahoo_string_decode(gc, sms->msg, sms->utf8); | |
| 846 serv_got_im(gc, sms->from, m, 0, sms->time); | |
| 847 | |
| 848 g_free(m); | |
| 849 g_free(sms->from); | |
| 850 g_free(sms); | |
| 851 } | |
| 852 | |
| 853 /* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */ | |
| 854 static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type) | |
| 768 { | 855 { |
| 769 PurpleAccount *account; | 856 PurpleAccount *account; |
| 770 struct yahoo_data *yd = gc->proto_data; | 857 struct yahoo_data *yd = gc->proto_data; |
| 771 GSList *l = pkt->hash; | 858 GSList *l = pkt->hash; |
| 772 GSList *list = NULL; | 859 GSList *list = NULL; |
| 773 struct _yahoo_im *im = NULL; | 860 struct _yahoo_im *im = NULL; |
| 774 const char *imv = NULL; | 861 const char *imv = NULL; |
| 862 gint val_11 = 0; | |
| 775 | 863 |
| 776 account = purple_connection_get_account(gc); | 864 account = purple_connection_get_account(gc); |
| 777 | 865 |
| 778 if (pkt->status <= 1 || pkt->status == 5) { | 866 if (pkt->status <= 1 || pkt->status == 5 || pkt->status == YAHOO_STATUS_OFFLINE) { |
| 867 /* messages are received with status YAHOO_STATUS_OFFLINE in case of p2p */ | |
| 779 while (l != NULL) { | 868 while (l != NULL) { |
| 780 struct yahoo_pair *pair = l->data; | 869 struct yahoo_pair *pair = l->data; |
| 781 if (pair->key == 4) { | 870 if (pair->key == 4 || pair->key == 1) { |
| 782 im = g_new0(struct _yahoo_im, 1); | 871 im = g_new0(struct _yahoo_im, 1); |
| 783 list = g_slist_append(list, im); | 872 list = g_slist_append(list, im); |
| 784 im->from = pair->value; | 873 im->from = pair->value; |
| 785 im->time = time(NULL); | 874 im->time = time(NULL); |
| 786 im->utf8 = TRUE; | 875 im->utf8 = TRUE; |
| 796 im->buddy_icon = strtol(pair->value, NULL, 10); | 885 im->buddy_icon = strtol(pair->value, NULL, 10); |
| 797 if (pair->key == 14) { | 886 if (pair->key == 14) { |
| 798 if (im) | 887 if (im) |
| 799 im->msg = pair->value; | 888 im->msg = pair->value; |
| 800 } | 889 } |
| 890 /* peer session id */ | |
| 891 if (pair->key == 11) { | |
| 892 if (im) | |
| 893 val_11 = strtol(pair->value, NULL, 10); | |
| 894 } | |
| 801 /* IMV key */ | 895 /* IMV key */ |
| 802 if (pair->key == 63) | 896 if (pair->key == 63) |
| 803 { | 897 { |
| 804 imv = pair->value; | 898 imv = pair->value; |
| 805 } | 899 } |
| 806 l = l->next; | 900 l = l->next; |
| 807 } | 901 } |
| 808 } else if (pkt->status == 2) { | 902 } else if (pkt->status == 2) { |
| 809 purple_notify_error(gc, NULL, | 903 purple_notify_error(gc, NULL, |
| 810 _("Your Yahoo! message did not get sent."), NULL); | 904 _("Your Yahoo! message did not get sent."), NULL); |
| 905 } | |
| 906 | |
| 907 /* disconnect the peer if connected through p2p and sends wrong value for session id */ | |
| 908 if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) { | |
| 909 purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im->from); | |
| 910 /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */ | |
| 911 g_hash_table_remove(yd->peers, im->from); | |
| 912 return; | |
| 811 } | 913 } |
| 812 | 914 |
| 813 /** TODO: It seems that this check should be per IM, not global */ | 915 /** TODO: It seems that this check should be per IM, not global */ |
| 814 /* Check for the Doodle IMV */ | 916 /* Check for the Doodle IMV */ |
| 815 if (im != NULL && imv!= NULL && im->from != NULL) | 917 if (im != NULL && imv!= NULL && im->from != NULL) |
| 2185 char *group = NULL; | 2287 char *group = NULL; |
| 2186 char *decoded_group; | 2288 char *decoded_group; |
| 2187 char *buf; | 2289 char *buf; |
| 2188 YahooFriend *f; | 2290 YahooFriend *f; |
| 2189 GSList *l = pkt->hash; | 2291 GSList *l = pkt->hash; |
| 2292 struct yahoo_data *yd = gc->proto_data; | |
| 2293 int protocol = 0; | |
| 2190 | 2294 |
| 2191 while (l) { | 2295 while (l) { |
| 2192 struct yahoo_pair *pair = l->data; | 2296 struct yahoo_pair *pair = l->data; |
| 2193 | 2297 |
| 2194 switch (pair->key) { | 2298 switch (pair->key) { |
| 2199 who = pair->value; | 2303 who = pair->value; |
| 2200 break; | 2304 break; |
| 2201 case 65: | 2305 case 65: |
| 2202 group = pair->value; | 2306 group = pair->value; |
| 2203 break; | 2307 break; |
| 2308 case 241: | |
| 2309 protocol = strtol(pair->value, NULL, 10); | |
| 2310 break; | |
| 2204 } | 2311 } |
| 2205 | 2312 |
| 2206 l = l->next; | 2313 l = l->next; |
| 2207 } | 2314 } |
| 2208 | 2315 |
| 2212 group = ""; | 2319 group = ""; |
| 2213 | 2320 |
| 2214 if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */ | 2321 if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */ |
| 2215 f = yahoo_friend_find_or_new(gc, who); | 2322 f = yahoo_friend_find_or_new(gc, who); |
| 2216 yahoo_update_status(gc, who, f); | 2323 yahoo_update_status(gc, who, f); |
| 2324 if(protocol) | |
| 2325 f->protocol = protocol; | |
| 2326 | |
| 2327 if( !g_hash_table_lookup(yd->peers, who) ) { | |
| 2328 /* we are not connected as client, so set friend to not connected */ | |
| 2329 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); | |
| 2330 f->p2p_packet_sent = 0; | |
| 2331 } | |
| 2332 else /* we are already connected. set friend to YAHOO_P2PSTATUS_WE_ARE_CLIENT */ | |
| 2333 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT); | |
| 2217 return; | 2334 return; |
| 2218 } | 2335 } |
| 2219 | 2336 |
| 2220 decoded_group = yahoo_string_decode(gc, group, FALSE); | 2337 decoded_group = yahoo_string_decode(gc, group, FALSE); |
| 2221 buf = g_strdup_printf(_("Could not add buddy %s to group %s to the server list on account %s."), | 2338 buf = g_strdup_printf(_("Could not add buddy %s to group %s to the server list on account %s."), |
| 2224 purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); | 2341 purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); |
| 2225 g_free(buf); | 2342 g_free(buf); |
| 2226 g_free(decoded_group); | 2343 g_free(decoded_group); |
| 2227 } | 2344 } |
| 2228 | 2345 |
| 2346 /* write pkt to the source */ | |
| 2347 static void yahoo_p2p_write_pkt(gint source, struct yahoo_packet *pkt) | |
| 2348 { | |
| 2349 size_t pkt_len; | |
| 2350 guchar *raw_packet; | |
| 2351 | |
| 2352 /*build the raw packet and send it to the host*/ | |
| 2353 pkt_len = yahoo_packet_build(pkt, 0, 0, 0, &raw_packet); | |
| 2354 if(write(source, raw_packet, pkt_len) != pkt_len) | |
| 2355 purple_debug_warning("yahoo","p2p: couldn't write to the source\n"); | |
| 2356 g_free(raw_packet); | |
| 2357 } | |
| 2358 | |
| 2359 static void yahoo_p2p_keepalive_cb(gpointer key, gpointer value, gpointer user_data) | |
| 2360 { | |
| 2361 struct yahoo_p2p_data *p2p_data = value; | |
| 2362 PurpleConnection *gc = user_data; | |
| 2363 struct yahoo_packet *pkt_to_send; | |
| 2364 PurpleAccount *account; | |
| 2365 struct yahoo_data *yd = gc->proto_data; | |
| 2366 | |
| 2367 account = purple_connection_get_account(gc); | |
| 2368 | |
| 2369 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
| 2370 yahoo_packet_hash(pkt_to_send, "ssisi", | |
| 2371 4, purple_normalize(account, purple_account_get_username(account)), | |
| 2372 5, p2p_data->host_username, | |
| 2373 241, 0, /* Protocol identifier */ | |
| 2374 49, "PEERTOPEER", | |
| 2375 13, 7); | |
| 2376 yahoo_p2p_write_pkt(p2p_data->source, pkt_to_send); | |
| 2377 | |
| 2378 yahoo_packet_free(pkt_to_send); | |
| 2379 } | |
| 2380 | |
| 2381 static gboolean yahoo_p2p_keepalive(gpointer data) | |
| 2382 { | |
| 2383 PurpleConnection *gc = data; | |
| 2384 struct yahoo_data *yd = gc->proto_data; | |
| 2385 | |
| 2386 g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc); | |
| 2387 | |
| 2388 return TRUE; | |
| 2389 } | |
| 2390 | |
| 2391 /* destroy p2p_data associated with a peer and close p2p connection. | |
| 2392 * g_hash_table_remove() calls this function to destroy p2p_data associated with the peer, | |
| 2393 * call g_hash_table_remove() instead of this fucntion if peer has an entry in the table */ | |
| 2394 static void yahoo_p2p_disconnect_destroy_data(gpointer data) | |
| 2395 { | |
| 2396 struct yahoo_p2p_data *p2p_data; | |
| 2397 YahooFriend *f; | |
| 2398 | |
| 2399 if(!(p2p_data = data)) | |
| 2400 return ; | |
| 2401 | |
| 2402 /* If friend, set him not connected */ | |
| 2403 f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username); | |
| 2404 if (f) | |
| 2405 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); | |
| 2406 | |
| 2407 if(p2p_data->source >= 0) | |
| 2408 close(p2p_data->source); | |
| 2409 purple_input_remove(p2p_data->input_event); | |
| 2410 g_free(p2p_data->host_ip); | |
| 2411 g_free(p2p_data->host_username); | |
| 2412 g_free(p2p_data); | |
| 2413 } | |
| 2414 | |
| 2415 /* exchange of initial p2pfilexfer packets, service type YAHOO_SERVICE_P2PFILEXFER */ | |
| 2416 static void yahoo_p2p_process_p2pfilexfer(gpointer data, gint source, struct yahoo_packet *pkt) | |
| 2417 { | |
| 2418 struct yahoo_p2p_data *p2p_data; | |
| 2419 char *who = NULL; | |
| 2420 GSList *l = pkt->hash; | |
| 2421 struct yahoo_packet *pkt_to_send; | |
| 2422 PurpleAccount *account; | |
| 2423 int val_13_to_send = 0; | |
| 2424 struct yahoo_data *yd; | |
| 2425 YahooFriend *f; | |
| 2426 | |
| 2427 if(!(p2p_data = data)) | |
| 2428 return ; | |
| 2429 | |
| 2430 yd = p2p_data->gc->proto_data; | |
| 2431 | |
| 2432 /* lets see whats in the packet */ | |
| 2433 while (l) { | |
| 2434 struct yahoo_pair *pair = l->data; | |
| 2435 | |
| 2436 switch (pair->key) { | |
| 2437 case 4: | |
| 2438 who = pair->value; | |
| 2439 if(strncmp(who, p2p_data->host_username, strlen(p2p_data->host_username)) != 0) { | |
| 2440 /* from whom are we receiving the packets ?? */ | |
| 2441 purple_debug_warning("yahoo","p2p: received data from wrong user\n"); | |
| 2442 return; | |
| 2443 } | |
| 2444 break; | |
| 2445 case 13: | |
| 2446 p2p_data->val_13 = strtol(pair->value, NULL, 10); /* Value should be 5-7 */ | |
| 2447 break; | |
| 2448 /* case 5, 49 look laters, no use right now */ | |
| 2449 } | |
| 2450 l = l->next; | |
| 2451 } | |
| 2452 | |
| 2453 account = purple_connection_get_account(p2p_data->gc); | |
| 2454 | |
| 2455 /* key_13: sort of a counter. | |
| 2456 * WHEN WE ARE CLIENT: yahoo server sends val_13 = 0, we send to peer val_13 = 1, receive back val_13 = 5, | |
| 2457 * we send val_13=6, receive val_13=7, we send val_13=7, HALT. Keep sending val_13 = 7 as keep alive. | |
| 2458 * WHEN WE ARE SERVER: we send val_13 = 0 to yahoo server, peer sends us val_13 = 1, we send val_13 = 5, | |
| 2459 * receive val_13 = 6, send val_13 = 7, receive val_13 = 7. HALT. Keep sending val_13 = 7 as keep alive. */ | |
| 2460 | |
| 2461 switch(p2p_data->val_13) { | |
| 2462 case 1 : val_13_to_send = 5; break; | |
| 2463 case 5 : val_13_to_send = 6; break; | |
| 2464 case 6 : val_13_to_send = 7; break; | |
| 2465 case 7 : if( g_hash_table_lookup(yd->peers, p2p_data->host_username) ) | |
| 2466 return; | |
| 2467 val_13_to_send = 7; break; | |
| 2468 default: purple_debug_warning("yahoo","p2p:Unknown value for key 13\n"); | |
| 2469 return; | |
| 2470 } | |
| 2471 | |
| 2472 /* Build the yahoo packet */ | |
| 2473 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
| 2474 yahoo_packet_hash(pkt_to_send, "ssisi", | |
| 2475 4, purple_normalize(account, purple_account_get_username(account)), | |
| 2476 5, p2p_data->host_username, | |
| 2477 241, 0, /* Protocol identifier */ | |
| 2478 49, "PEERTOPEER", | |
| 2479 13, val_13_to_send); | |
| 2480 | |
| 2481 /* build the raw packet and send it to the host */ | |
| 2482 yahoo_p2p_write_pkt(source, pkt_to_send); | |
| 2483 yahoo_packet_free(pkt_to_send); | |
| 2484 | |
| 2485 if( val_13_to_send == 7 ) | |
| 2486 if( !g_hash_table_lookup(yd->peers, p2p_data->host_username) ) { | |
| 2487 g_hash_table_insert(yd->peers, g_strdup(p2p_data->host_username), p2p_data); | |
| 2488 /* If the peer is a friend, set him connected */ | |
| 2489 f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username); | |
| 2490 if (f) { | |
| 2491 if(p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) { | |
| 2492 p2p_data->session_id = f->session_id; | |
| 2493 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_SERVER); | |
| 2494 } | |
| 2495 else | |
| 2496 yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT); | |
| 2497 } | |
| 2498 } | |
| 2499 } | |
| 2500 | |
| 2501 /* callback function associated with receiving of data, not considering receipt of multiple YMSG packets in a single TCP packet */ | |
| 2502 static void yahoo_p2p_read_pkt_cb(gpointer data, gint source, PurpleInputCondition cond) | |
| 2503 { | |
| 2504 guchar buf[1024]; /* is it safe to assume a fixed array length of 1024 ?? */ | |
| 2505 int len; | |
| 2506 int pos = 0; | |
| 2507 int pktlen; | |
| 2508 struct yahoo_packet *pkt; | |
| 2509 guchar *start = NULL; | |
| 2510 struct yahoo_p2p_data *p2p_data; | |
| 2511 struct yahoo_data *yd; | |
| 2512 | |
| 2513 if(!(p2p_data = data)) | |
| 2514 return ; | |
| 2515 yd = p2p_data->gc->proto_data; | |
| 2516 | |
| 2517 len = read(source, buf, sizeof(buf)); | |
| 2518 if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) | |
| 2519 return ; /* No Worries*/ | |
| 2520 else if (len <= 0) | |
| 2521 { | |
| 2522 purple_debug_warning("yahoo","p2p: Error in connection, or host disconnected\n"); | |
| 2523 /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */ | |
| 2524 if( g_hash_table_lookup(yd->peers, p2p_data->host_username) ) | |
| 2525 g_hash_table_remove(yd->peers,p2p_data->host_username); | |
| 2526 else | |
| 2527 yahoo_p2p_disconnect_destroy_data(data); | |
| 2528 return; | |
| 2529 } | |
| 2530 | |
| 2531 if(len < YAHOO_PACKET_HDRLEN) | |
| 2532 return; | |
| 2533 | |
| 2534 if(strncmp((char *)buf, "YMSG", MIN(4, len)) != 0) { | |
| 2535 /* Not a YMSG packet */ | |
| 2536 purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n"); | |
| 2537 | |
| 2538 start = memchr(buf + 1, 'Y', len - 1); | |
| 2539 if(start) { | |
| 2540 g_memmove(buf, start, len - (start - buf)); | |
| 2541 len -= start - buf; | |
| 2542 } else { | |
| 2543 g_free(buf); | |
| 2544 return; | |
| 2545 } | |
| 2546 } | |
| 2547 | |
| 2548 pos += 4; /* YMSG */ | |
| 2549 pos += 2; | |
| 2550 pos += 2; | |
| 2551 | |
| 2552 pktlen = yahoo_get16(buf + pos); pos += 2; | |
| 2553 purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: %d bytes to read\n", len); | |
| 2554 | |
| 2555 pkt = yahoo_packet_new(0, 0, 0); | |
| 2556 pkt->service = yahoo_get16(buf + pos); pos += 2; | |
| 2557 pkt->status = yahoo_get32(buf + pos); pos += 4; | |
| 2558 pkt->id = yahoo_get32(buf + pos); pos += 4; | |
| 2559 | |
| 2560 purple_debug(PURPLE_DEBUG_MISC, "yahoo", "p2p: Yahoo Service: 0x%02x Status: %d\n",pkt->service, pkt->status); | |
| 2561 yahoo_packet_read(pkt, buf + pos, pktlen); | |
| 2562 | |
| 2563 /* packet processing */ | |
| 2564 switch(pkt->service) { | |
| 2565 case YAHOO_SERVICE_P2PFILEXFER: | |
| 2566 yahoo_p2p_process_p2pfilexfer(data, source, pkt); | |
| 2567 break; | |
| 2568 case YAHOO_SERVICE_MESSAGE: | |
| 2569 yahoo_process_message(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P); | |
| 2570 break; | |
| 2571 case YAHOO_SERVICE_NOTIFY: | |
| 2572 yahoo_process_notify(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P); | |
| 2573 break; | |
| 2574 default: | |
| 2575 purple_debug_warning("yahoo","p2p: p2p service %d Unhandled\n",pkt->service); | |
| 2576 } | |
| 2577 | |
| 2578 yahoo_packet_free(pkt); | |
| 2579 } | |
| 2580 | |
| 2581 static void yahoo_p2p_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond) | |
| 2582 { | |
| 2583 int acceptfd; | |
| 2584 struct yahoo_p2p_data *p2p_data; | |
| 2585 struct yahoo_data *yd; | |
| 2586 | |
| 2587 if(!(p2p_data = data)) | |
| 2588 return ; | |
| 2589 yd = p2p_data->gc->proto_data; | |
| 2590 | |
| 2591 acceptfd = accept(source, NULL, 0); | |
| 2592 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) | |
| 2593 return; | |
| 2594 else if(acceptfd == -1) { | |
| 2595 purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno)); | |
| 2596 yahoo_p2p_disconnect_destroy_data(data); | |
| 2597 return; | |
| 2598 } | |
| 2599 | |
| 2600 /* remove watcher and close p2p server */ | |
| 2601 purple_input_remove(yd->yahoo_p2p_server_watcher); | |
| 2602 close(yd->yahoo_local_p2p_server_fd); | |
| 2603 yd->yahoo_local_p2p_server_fd = -1; | |
| 2604 | |
| 2605 /* Add an Input Read event to the file descriptor */ | |
| 2606 p2p_data->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data); | |
| 2607 p2p_data->source = acceptfd; | |
| 2608 } | |
| 2609 | |
| 2610 static gboolean yahoo_cancel_p2p_server_listen_cb(gpointer data) | |
| 2611 { | |
| 2612 struct yahoo_p2p_data *p2p_data; | |
| 2613 struct yahoo_data *yd; | |
| 2614 | |
| 2615 if(!(p2p_data = data)) | |
| 2616 return FALSE; | |
| 2617 | |
| 2618 yd = p2p_data->gc->proto_data; | |
| 2619 | |
| 2620 purple_debug_warning("yahoo","yahoo p2p server timeout, peer failed to connect"); | |
| 2621 yahoo_p2p_disconnect_destroy_data(data); | |
| 2622 purple_input_remove(yd->yahoo_p2p_server_watcher); | |
| 2623 yd->yahoo_p2p_server_watcher = 0; | |
| 2624 close(yd->yahoo_local_p2p_server_fd); | |
| 2625 yd->yahoo_local_p2p_server_fd = -1; | |
| 2626 yd->yahoo_p2p_server_timeout_handle = 0; | |
| 2627 | |
| 2628 return FALSE; | |
| 2629 } | |
| 2630 | |
| 2631 static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data) | |
| 2632 { | |
| 2633 struct yahoo_p2p_data *p2p_data; | |
| 2634 struct yahoo_data *yd; | |
| 2635 | |
| 2636 if(!(p2p_data = data)) | |
| 2637 return ; | |
| 2638 | |
| 2639 if(listenfd == -1) { | |
| 2640 purple_debug_warning("yahoo","p2p: error starting p2p server\n"); | |
| 2641 yahoo_p2p_disconnect_destroy_data(data); | |
| 2642 return; | |
| 2643 } | |
| 2644 | |
| 2645 yd = p2p_data->gc->proto_data; | |
| 2646 | |
| 2647 /* Add an Input Read event to the file descriptor */ | |
| 2648 yd->yahoo_local_p2p_server_fd = listenfd; | |
| 2649 yd->yahoo_p2p_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_server_send_connected_cb,data); | |
| 2650 | |
| 2651 /* add timeout */ | |
| 2652 yd->yahoo_p2p_server_timeout_handle = purple_timeout_add_seconds(YAHOO_P2P_SERVER_TIMEOUT, yahoo_cancel_p2p_server_listen_cb, data); | |
| 2653 } | |
| 2654 | |
| 2655 /* send p2p pkt containing our encoded ip, asking peer to connect to us */ | |
| 2656 void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13) | |
| 2657 { | |
| 2658 const char *public_ip; | |
| 2659 guint32 temp[4]; | |
| 2660 guint32 ip; | |
| 2661 char temp_str[100]; | |
| 2662 gchar *base64_ip = NULL; | |
| 2663 YahooFriend *f; | |
| 2664 struct yahoo_packet *pkt; | |
| 2665 PurpleAccount *account; | |
| 2666 struct yahoo_data *yd = gc->proto_data; | |
| 2667 struct yahoo_p2p_data *p2p_data; | |
| 2668 | |
| 2669 f = yahoo_friend_find(gc, who); | |
| 2670 account = purple_connection_get_account(gc); | |
| 2671 | |
| 2672 /* Do not send invitation if already listening for other connection */ | |
| 2673 if(yd->yahoo_local_p2p_server_fd >= 0) | |
| 2674 return; | |
| 2675 | |
| 2676 /* One shouldn't try to connect to self */ | |
| 2677 if( strcmp(purple_normalize(account, purple_account_get_username(account)), who) == 0) | |
| 2678 return; | |
| 2679 | |
| 2680 /* 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 */ | |
| 2681 if( !( f && (yahoo_friend_get_p2p_status(f) == YAHOO_P2PSTATUS_NOT_CONNECTED) && (f->p2p_packet_sent == 0)) ) | |
| 2682 return; | |
| 2683 | |
| 2684 /* Dont send p2p packet to buddies of other protocols */ | |
| 2685 if(f->protocol) | |
| 2686 return; | |
| 2687 | |
| 2688 /* Finally, don't try to connect to buddies not online or on sms */ | |
| 2689 if( (f->status == YAHOO_STATUS_OFFLINE) || f->sms ) | |
| 2690 return; | |
| 2691 | |
| 2692 public_ip = purple_network_get_public_ip(); | |
| 2693 if( (sscanf(public_ip, "%u.%u.%u.%u", &temp[0], &temp[1], &temp[2], &temp[3])) !=4 ) | |
| 2694 return ; | |
| 2695 | |
| 2696 ip = (temp[3] << 24) | (temp[2] <<16) | (temp[1] << 8) | temp[0]; | |
| 2697 sprintf(temp_str, "%d", ip); | |
| 2698 base64_ip = purple_base64_encode( (guchar *)temp_str, strlen(temp_str) ); | |
| 2699 | |
| 2700 pkt = yahoo_packet_new(YAHOO_SERVICE_PEERTOPEER, YAHOO_STATUS_AVAILABLE, 0); | |
| 2701 yahoo_packet_hash(pkt, "sssissis", | |
| 2702 1, purple_normalize(account, purple_account_get_username(account)), | |
| 2703 4, purple_normalize(account, purple_account_get_username(account)), | |
| 2704 12, base64_ip, /* base64 encode ip */ | |
| 2705 61, 0, /* To-do : figure out what is 61 for?? */ | |
| 2706 2, "", | |
| 2707 5, who, | |
| 2708 13, val_13, | |
| 2709 49, "PEERTOPEER"); | |
| 2710 yahoo_packet_send_and_free(pkt, yd); | |
| 2711 | |
| 2712 f->p2p_packet_sent = 1; /* set p2p_packet_sent to sent */ | |
| 2713 | |
| 2714 p2p_data = g_new0(struct yahoo_p2p_data, 1); | |
| 2715 | |
| 2716 p2p_data->gc = gc; | |
| 2717 p2p_data->host_ip = NULL; | |
| 2718 p2p_data->host_username = g_strdup(who); | |
| 2719 p2p_data->val_13 = val_13; | |
| 2720 p2p_data->connection_type = YAHOO_P2P_WE_ARE_SERVER; | |
| 2721 | |
| 2722 purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, p2p_data); | |
| 2723 | |
| 2724 g_free(base64_ip); | |
| 2725 } | |
| 2726 | |
| 2727 /* function called when connection to p2p host is setup */ | |
| 2728 static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message) | |
| 2729 { | |
| 2730 struct yahoo_p2p_data *p2p_data; | |
| 2731 struct yahoo_packet *pkt_to_send; | |
| 2732 PurpleAccount *account; | |
| 2733 struct yahoo_data *yd; | |
| 2734 | |
| 2735 if(!(p2p_data = data)) | |
| 2736 return ; | |
| 2737 yd = p2p_data->gc->proto_data; | |
| 2738 | |
| 2739 if(error_message != NULL) { | |
| 2740 purple_debug_warning("yahoo","p2p: %s\n",error_message); | |
| 2741 yahoo_send_p2p_pkt(p2p_data->gc, p2p_data->host_username, 2);/* send p2p init packet with val_13=2 */ | |
| 2742 | |
| 2743 yahoo_p2p_disconnect_destroy_data(p2p_data); | |
| 2744 return; | |
| 2745 } | |
| 2746 | |
| 2747 /* Add an Input Read event to the file descriptor */ | |
| 2748 p2p_data->input_event = purple_input_add(source, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data); | |
| 2749 p2p_data->source = source; | |
| 2750 | |
| 2751 account = purple_connection_get_account(p2p_data->gc); | |
| 2752 | |
| 2753 /* Build the yahoo packet */ | |
| 2754 pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
| 2755 yahoo_packet_hash(pkt_to_send, "ssisi", | |
| 2756 4, purple_normalize(account, purple_account_get_username(account)), | |
| 2757 5, p2p_data->host_username, | |
| 2758 241, 0, /* Protocol identifier */ | |
| 2759 49, "PEERTOPEER", | |
| 2760 13, 1); /* we receive key13= 0 or 2, we send key13=1 */ | |
| 2761 | |
| 2762 yahoo_p2p_write_pkt(source, pkt_to_send); /* build raw packet and send */ | |
| 2763 yahoo_packet_free(pkt_to_send); | |
| 2764 } | |
| 2765 | |
| 2229 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt) | 2766 static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt) |
| 2230 { | 2767 { |
| 2231 GSList *l = pkt->hash; | 2768 GSList *l = pkt->hash; |
| 2232 char *who = NULL; | 2769 char *who = NULL; |
| 2233 char *base64 = NULL; | 2770 char *base64 = NULL; |
| 2234 guchar *decoded; | 2771 guchar *decoded; |
| 2235 gsize len; | 2772 gsize len; |
| 2773 gint val_13 = 0; | |
| 2774 gint val_11 = 0; | |
| 2775 PurpleAccount *account; | |
| 2776 YahooFriend *f; | |
| 2777 | |
| 2778 /* if status is YAHOO_STATUS_BUSY, don't do anything, peer wont connect */ | |
| 2779 if(pkt->status == YAHOO_STATUS_BUSY) | |
| 2780 return ; | |
| 2236 | 2781 |
| 2237 while (l) { | 2782 while (l) { |
| 2238 struct yahoo_pair *pair = l->data; | 2783 struct yahoo_pair *pair = l->data; |
| 2239 | 2784 |
| 2240 switch (pair->key) { | 2785 switch (pair->key) { |
| 2250 case 12: | 2795 case 12: |
| 2251 base64 = pair->value; | 2796 base64 = pair->value; |
| 2252 /* so, this is an ip address. in base64. decoded it's in ascii. | 2797 /* so, this is an ip address. in base64. decoded it's in ascii. |
| 2253 after strtol, it's in reversed byte order. Who thought this up?*/ | 2798 after strtol, it's in reversed byte order. Who thought this up?*/ |
| 2254 break; | 2799 break; |
| 2800 case 13: | |
| 2801 val_13 = strtol(pair->value, NULL, 10); | |
| 2802 break; | |
| 2803 case 11: | |
| 2804 val_11 = strtol(pair->value, NULL, 10); /* session id of peer */ | |
| 2805 if( (f = yahoo_friend_find(gc, who)) ) | |
| 2806 f->session_id = val_11; | |
| 2807 break; | |
| 2255 /* | 2808 /* |
| 2256 TODO: figure these out | 2809 TODO: figure these out |
| 2257 yahoo: Key: 61 Value: 0 | 2810 yahoo: Key: 61 Value: 0 |
| 2258 yahoo: Key: 2 Value: | 2811 yahoo: Key: 2 Value: |
| 2259 yahoo: Key: 13 Value: 0 | 2812 yahoo: Key: 13 Value: 0 packet count ?? |
| 2260 yahoo: Key: 49 Value: PEERTOPEER | 2813 yahoo: Key: 49 Value: PEERTOPEER |
| 2261 yahoo: Key: 140 Value: 1 | 2814 yahoo: Key: 140 Value: 1 |
| 2262 yahoo: Key: 11 Value: -1786225828 | |
| 2263 */ | 2815 */ |
| 2264 | 2816 |
| 2265 } | 2817 } |
| 2266 | 2818 |
| 2267 l = l->next; | 2819 l = l->next; |
| 2269 | 2821 |
| 2270 if (base64) { | 2822 if (base64) { |
| 2271 guint32 ip; | 2823 guint32 ip; |
| 2272 char *tmp2; | 2824 char *tmp2; |
| 2273 YahooFriend *f; | 2825 YahooFriend *f; |
| 2826 char *host_ip; | |
| 2827 struct yahoo_p2p_data *p2p_data = g_new0(struct yahoo_p2p_data, 1); | |
| 2274 | 2828 |
| 2275 decoded = purple_base64_decode(base64, &len); | 2829 decoded = purple_base64_decode(base64, &len); |
| 2276 if (len) { | 2830 if (len) { |
| 2277 char *tmp = purple_str_binary_to_ascii(decoded, len); | 2831 char *tmp = purple_str_binary_to_ascii(decoded, len); |
| 2278 purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); | 2832 purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); |
| 2281 | 2835 |
| 2282 tmp2 = g_strndup((const gchar *)decoded, len); /* so its \0 terminated...*/ | 2836 tmp2 = g_strndup((const gchar *)decoded, len); /* so its \0 terminated...*/ |
| 2283 ip = strtol(tmp2, NULL, 10); | 2837 ip = strtol(tmp2, NULL, 10); |
| 2284 g_free(tmp2); | 2838 g_free(tmp2); |
| 2285 g_free(decoded); | 2839 g_free(decoded); |
| 2286 tmp2 = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, | 2840 host_ip = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, |
| 2287 (ip >> 24) & 0xff); | 2841 (ip >> 24) & 0xff); |
| 2288 f = yahoo_friend_find(gc, who); | 2842 f = yahoo_friend_find(gc, who); |
| 2289 if (f) | 2843 if (f) |
| 2290 yahoo_friend_set_ip(f, tmp2); | 2844 yahoo_friend_set_ip(f, host_ip); |
| 2291 g_free(tmp2); | 2845 purple_debug_info("yahoo", "IP : %s\n", host_ip); |
| 2846 | |
| 2847 account = purple_connection_get_account(gc); | |
| 2848 | |
| 2849 if(val_11==0) { | |
| 2850 if(!f) | |
| 2851 return; | |
| 2852 else | |
| 2853 val_11 = f->session_id; | |
| 2854 } | |
| 2855 | |
| 2856 p2p_data->host_username = g_strdup(who); | |
| 2857 p2p_data->val_13 = val_13; | |
| 2858 p2p_data->session_id = val_11; | |
| 2859 p2p_data->host_ip = host_ip; | |
| 2860 p2p_data->gc = gc; | |
| 2861 p2p_data->connection_type = YAHOO_P2P_WE_ARE_CLIENT; | |
| 2862 | |
| 2863 /* connect to host */ | |
| 2864 if((purple_proxy_connect(NULL, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, p2p_data))==NULL) { | |
| 2865 yahoo_p2p_disconnect_destroy_data(p2p_data); | |
| 2866 purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip); | |
| 2867 } | |
| 2292 } | 2868 } |
| 2293 } | 2869 } |
| 2294 | 2870 |
| 2295 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt) | 2871 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt) |
| 2296 { | 2872 { |
| 2366 case YAHOO_SERVICE_Y6_STATUS_UPDATE: | 2942 case YAHOO_SERVICE_Y6_STATUS_UPDATE: |
| 2367 case YAHOO_SERVICE_STATUS_15: | 2943 case YAHOO_SERVICE_STATUS_15: |
| 2368 yahoo_process_status(gc, pkt); | 2944 yahoo_process_status(gc, pkt); |
| 2369 break; | 2945 break; |
| 2370 case YAHOO_SERVICE_NOTIFY: | 2946 case YAHOO_SERVICE_NOTIFY: |
| 2371 yahoo_process_notify(gc, pkt); | 2947 yahoo_process_notify(gc, pkt, YAHOO_PKT_TYPE_SERVER); |
| 2372 break; | 2948 break; |
| 2373 case YAHOO_SERVICE_MESSAGE: | 2949 case YAHOO_SERVICE_MESSAGE: |
| 2374 case YAHOO_SERVICE_GAMEMSG: | 2950 case YAHOO_SERVICE_GAMEMSG: |
| 2375 case YAHOO_SERVICE_CHATMSG: | 2951 case YAHOO_SERVICE_CHATMSG: |
| 2376 yahoo_process_message(gc, pkt); | 2952 yahoo_process_message(gc, pkt, YAHOO_PKT_TYPE_SERVER); |
| 2377 break; | 2953 break; |
| 2378 case YAHOO_SERVICE_SYSMESSAGE: | 2954 case YAHOO_SERVICE_SYSMESSAGE: |
| 2379 yahoo_process_sysmessage(gc, pkt); | 2955 yahoo_process_sysmessage(gc, pkt); |
| 2380 break; | 2956 break; |
| 2381 case YAHOO_SERVICE_NEWMAIL: | 2957 case YAHOO_SERVICE_NEWMAIL: |
| 2448 case YAHOO_SERVICE_PRESENCE_SESSION: | 3024 case YAHOO_SERVICE_PRESENCE_SESSION: |
| 2449 yahoo_process_presence(gc, pkt); | 3025 yahoo_process_presence(gc, pkt); |
| 2450 break; | 3026 break; |
| 2451 case YAHOO_SERVICE_P2PFILEXFER: | 3027 case YAHOO_SERVICE_P2PFILEXFER: |
| 2452 /* This case had no break and continued; thus keeping it this way.*/ | 3028 /* This case had no break and continued; thus keeping it this way.*/ |
| 2453 yahoo_process_p2pfilexfer(gc, pkt); | 3029 yahoo_process_p2p(gc, pkt); /* P2PFILEXFER handled the same way as process_p2p */ |
| 3030 yahoo_process_p2pfilexfer(gc, pkt); /* redundant ??, need to have a break now */ | |
| 2454 case YAHOO_SERVICE_FILETRANSFER: | 3031 case YAHOO_SERVICE_FILETRANSFER: |
| 2455 yahoo_process_filetransfer(gc, pkt); | 3032 yahoo_process_filetransfer(gc, pkt); |
| 2456 break; | 3033 break; |
| 2457 case YAHOO_SERVICE_PEERTOPEER: | 3034 case YAHOO_SERVICE_PEERTOPEER: |
| 2458 yahoo_process_p2p(gc, pkt); | 3035 yahoo_process_p2p(gc, pkt); |
| 2481 case YAHOO_SERVICE_FILETRANS_INFO_15: | 3058 case YAHOO_SERVICE_FILETRANS_INFO_15: |
| 2482 yahoo_process_filetrans_info_15(gc, pkt); | 3059 yahoo_process_filetrans_info_15(gc, pkt); |
| 2483 break; | 3060 break; |
| 2484 case YAHOO_SERVICE_FILETRANS_ACC_15: | 3061 case YAHOO_SERVICE_FILETRANS_ACC_15: |
| 2485 yahoo_process_filetrans_acc_15(gc, pkt); | 3062 yahoo_process_filetrans_acc_15(gc, pkt); |
| 3063 break; | |
| 3064 case YAHOO_SERVICE_SMS_MSG: | |
| 3065 yahoo_process_sms_message(gc, pkt); | |
| 2486 break; | 3066 break; |
| 2487 | 3067 |
| 2488 default: | 3068 default: |
| 2489 purple_debug(PURPLE_DEBUG_ERROR, "yahoo", | 3069 purple_debug(PURPLE_DEBUG_ERROR, "yahoo", |
| 2490 "Unhandled service 0x%02x\n", pkt->service); | 3070 "Unhandled service 0x%02x\n", pkt->service); |
| 3003 /* TODO: Is there a good grow size for the buffer? */ | 3583 /* TODO: Is there a good grow size for the buffer? */ |
| 3004 yd->txbuf = purple_circ_buffer_new(0); | 3584 yd->txbuf = purple_circ_buffer_new(0); |
| 3005 yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); | 3585 yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); |
| 3006 yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | 3586 yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); |
| 3007 yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); | 3587 yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); |
| 3588 yd->peers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_p2p_disconnect_destroy_data); | |
| 3589 yd->sms_carrier = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
| 3590 yd->yahoo_p2p_timer = purple_timeout_add_seconds(YAHOO_P2P_KEEPALIVE_SECS, yahoo_p2p_keepalive, gc); | |
| 3008 yd->confs = NULL; | 3591 yd->confs = NULL; |
| 3009 yd->conf_id = 2; | 3592 yd->conf_id = 2; |
| 3010 yd->last_keepalive = yd->last_ping = time(NULL); | 3593 yd->last_keepalive = yd->last_ping = time(NULL); |
| 3011 | 3594 |
| 3012 yd->current_status = get_yahoo_status_from_purple_status(status); | 3595 yd->current_status = get_yahoo_status_from_purple_status(status); |
| 3068 | 3651 |
| 3069 yd->chat_online = FALSE; | 3652 yd->chat_online = FALSE; |
| 3070 if (yd->in_chat) | 3653 if (yd->in_chat) |
| 3071 yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */ | 3654 yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */ |
| 3072 | 3655 |
| 3656 purple_timeout_remove(yd->yahoo_p2p_timer); | |
| 3657 if(yd->yahoo_p2p_server_timeout_handle != 0) | |
| 3658 purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle); | |
| 3659 | |
| 3660 /* close p2p server if it is waiting for a peer to connect */ | |
| 3661 purple_input_remove(yd->yahoo_p2p_server_watcher); | |
| 3662 close(yd->yahoo_local_p2p_server_fd); | |
| 3663 yd->yahoo_local_p2p_server_fd = -1; | |
| 3664 | |
| 3665 g_hash_table_destroy(yd->sms_carrier); | |
| 3666 g_hash_table_destroy(yd->peers); | |
| 3073 g_hash_table_destroy(yd->friends); | 3667 g_hash_table_destroy(yd->friends); |
| 3074 g_hash_table_destroy(yd->imvironments); | 3668 g_hash_table_destroy(yd->imvironments); |
| 3075 g_hash_table_destroy(yd->xfer_peer_idstring_map); | 3669 g_hash_table_destroy(yd->xfer_peer_idstring_map); |
| 3076 g_free(yd->chat_name); | 3670 g_free(yd->chat_name); |
| 3077 | 3671 |
| 3607 m = g_list_append(m, act); | 4201 m = g_list_append(m, act); |
| 3608 | 4202 |
| 3609 return m; | 4203 return m; |
| 3610 } | 4204 } |
| 3611 | 4205 |
| 4206 struct yahoo_sms_carrier_cb_data { | |
| 4207 PurpleConnection *gc; | |
| 4208 char *who; | |
| 4209 char *what; | |
| 4210 }; | |
| 4211 | |
| 4212 static int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags); | |
| 4213 | |
| 4214 static void yahoo_get_sms_carrier_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, | |
| 4215 const gchar *webdata, size_t len, const gchar *error_message) | |
| 4216 { | |
| 4217 struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data; | |
| 4218 PurpleConnection *gc = sms_cb_data->gc; | |
| 4219 struct yahoo_data *yd = gc->proto_data; | |
| 4220 char *mobile_no = NULL; | |
| 4221 char *status = NULL; | |
| 4222 char *carrier = NULL; | |
| 4223 PurpleAccount *account = purple_connection_get_account(gc); | |
| 4224 PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account); | |
| 4225 | |
| 4226 if (error_message != NULL) { | |
| 4227 purple_conversation_write(conv, NULL, "Cant send SMS, Unable to obtain mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
| 4228 | |
| 4229 g_free(sms_cb_data->who); | |
| 4230 g_free(sms_cb_data->what); | |
| 4231 g_free(sms_cb_data); | |
| 4232 return ; | |
| 4233 } | |
| 4234 else if (len > 0 && webdata && *webdata) { | |
| 4235 xmlnode *validate_data_root = xmlnode_from_str(webdata, -1); | |
| 4236 xmlnode *validate_data_child = xmlnode_get_child(validate_data_root, "mobile_no"); | |
| 4237 mobile_no = (char *)xmlnode_get_attrib(validate_data_child, "msisdn"); | |
| 4238 | |
| 4239 validate_data_root = xmlnode_copy(validate_data_child); | |
| 4240 validate_data_child = xmlnode_get_child(validate_data_root, "status"); | |
| 4241 status = xmlnode_get_data(validate_data_child); | |
| 4242 | |
| 4243 validate_data_child = xmlnode_get_child(validate_data_root, "carrier"); | |
| 4244 carrier = xmlnode_get_data(validate_data_child); | |
| 4245 | |
| 4246 purple_debug_info("yahoo","SMS validate data: Mobile:%s, Status:%s, Carrier:%s\n", mobile_no, status, carrier); | |
| 4247 | |
| 4248 if( strcmp(status, "Valid") == 0) { | |
| 4249 g_hash_table_insert(yd->sms_carrier, g_strdup_printf("+%s", mobile_no), g_strdup(carrier)); | |
| 4250 yahoo_send_im(sms_cb_data->gc, sms_cb_data->who, sms_cb_data->what, PURPLE_MESSAGE_SEND); | |
| 4251 } | |
| 4252 else { | |
| 4253 g_hash_table_insert(yd->sms_carrier, g_strdup_printf("+%s", mobile_no), g_strdup("Unknown")); | |
| 4254 purple_conversation_write(conv, NULL, "Cant send SMS, Unknown mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
| 4255 } | |
| 4256 | |
| 4257 xmlnode_free(validate_data_child); | |
| 4258 xmlnode_free(validate_data_root); | |
| 4259 g_free(sms_cb_data->who); | |
| 4260 g_free(sms_cb_data->what); | |
| 4261 g_free(sms_cb_data); | |
| 4262 g_free(mobile_no); | |
| 4263 g_free(status); | |
| 4264 g_free(carrier); | |
| 4265 } | |
| 4266 } | |
| 4267 | |
| 4268 static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data) | |
| 4269 { | |
| 4270 struct yahoo_data *yd = gc->proto_data; | |
| 4271 PurpleUtilFetchUrlData *url_data; | |
| 4272 struct yahoo_sms_carrier_cb_data *sms_cb_data; | |
| 4273 char *validate_request_str = NULL; | |
| 4274 char *request = NULL; | |
| 4275 gboolean use_whole_url = FALSE; | |
| 4276 xmlnode *validate_request_root = NULL; | |
| 4277 xmlnode *validate_request_child = NULL; | |
| 4278 | |
| 4279 if(!(sms_cb_data = data)) | |
| 4280 return; | |
| 4281 | |
| 4282 validate_request_root = xmlnode_new("validate"); | |
| 4283 xmlnode_set_attrib(validate_request_root, "intl", "us"); | |
| 4284 xmlnode_set_attrib(validate_request_root, "version", YAHOO_CLIENT_VERSION); | |
| 4285 xmlnode_set_attrib(validate_request_root, "qos", "0"); | |
| 4286 | |
| 4287 validate_request_child = xmlnode_new_child(validate_request_root, "mobile_no"); | |
| 4288 xmlnode_set_attrib(validate_request_child, "msisdn", sms_cb_data->who + 1); | |
| 4289 | |
| 4290 validate_request_str = xmlnode_to_str(validate_request_root, NULL); | |
| 4291 | |
| 4292 xmlnode_free(validate_request_child); | |
| 4293 xmlnode_free(validate_request_root); | |
| 4294 | |
| 4295 request = g_strdup_printf( | |
| 4296 "POST /mobileno?intl=us&version=%s HTTP/1.1\r\n" | |
| 4297 "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s; path=/; domain=.yahoo.com;\r\n" | |
| 4298 "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\n" | |
| 4299 "Host: validate.msg.yahoo.com\r\n" | |
| 4300 "Content-Length: %d\r\n" | |
| 4301 "Cache-Control: no-cache\r\n\r\n%s", | |
| 4302 YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str); | |
| 4303 | |
| 4304 /* use whole URL if using HTTP Proxy */ | |
| 4305 if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP)) | |
| 4306 use_whole_url = TRUE; | |
| 4307 | |
| 4308 url_data = purple_util_fetch_url_request(YAHOO_SMS_CARRIER_URL, use_whole_url, | |
| 4309 "Mozilla/4.0 (compatible; MSIE 5.5)", TRUE, request, FALSE, | |
| 4310 yahoo_get_sms_carrier_cb, data); | |
| 4311 | |
| 4312 g_free(request); | |
| 4313 g_free(validate_request_str); | |
| 4314 | |
| 4315 if (!url_data) { | |
| 4316 PurpleAccount *account = purple_connection_get_account(gc); | |
| 4317 PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account); | |
| 4318 purple_conversation_write(conv, NULL, "Cant send SMS, Unable to obtain mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
| 4319 g_free(sms_cb_data->who); | |
| 4320 g_free(sms_cb_data->what); | |
| 4321 g_free(sms_cb_data); | |
| 4322 } | |
| 4323 } | |
| 4324 | |
| 3612 static int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags) | 4325 static int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags) |
| 3613 { | 4326 { |
| 3614 struct yahoo_data *yd = gc->proto_data; | 4327 struct yahoo_data *yd = gc->proto_data; |
| 3615 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0); | 4328 struct yahoo_packet *pkt; |
| 3616 char *msg = yahoo_html_to_codes(what); | 4329 char *msg = yahoo_html_to_codes(what); |
| 3617 char *msg2; | 4330 char *msg2; |
| 3618 gboolean utf8 = TRUE; | 4331 gboolean utf8 = TRUE; |
| 3619 PurpleWhiteboard *wb; | 4332 PurpleWhiteboard *wb; |
| 3620 int ret = 1; | 4333 int ret = 1; |
| 3621 YahooFriend *f = NULL; | 4334 YahooFriend *f = NULL; |
| 4335 struct yahoo_p2p_data *p2p_data; | |
| 3622 | 4336 |
| 3623 msg2 = yahoo_string_encode(gc, msg, &utf8); | 4337 msg2 = yahoo_string_encode(gc, msg, &utf8); |
| 3624 | 4338 |
| 4339 if( strncmp(who, "+", 1) == 0 ) { | |
| 4340 /* we have an sms to be sent */ | |
| 4341 gchar *carrier = NULL; | |
| 4342 const char *alias = NULL; | |
| 4343 PurpleAccount *account = purple_connection_get_account(gc); | |
| 4344 PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account); | |
| 4345 | |
| 4346 carrier = g_hash_table_lookup(yd->sms_carrier, who); | |
| 4347 if (!carrier) { | |
| 4348 struct yahoo_sms_carrier_cb_data *sms_cb_data; | |
| 4349 sms_cb_data = g_malloc(sizeof(struct yahoo_sms_carrier_cb_data)); | |
| 4350 sms_cb_data->gc = gc; | |
| 4351 sms_cb_data->who = g_malloc(strlen(who)); | |
| 4352 sms_cb_data->what = g_malloc(strlen(what)); | |
| 4353 strcpy(sms_cb_data->who, who); | |
| 4354 strcpy(sms_cb_data->what, what); | |
| 4355 | |
| 4356 purple_conversation_write(conv, NULL, "Getting mobile carrier to send the sms", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
| 4357 | |
| 4358 yahoo_get_sms_carrier(gc, sms_cb_data); | |
| 4359 | |
| 4360 g_free(msg); | |
| 4361 g_free(msg2); | |
| 4362 return ret; | |
| 4363 } | |
| 4364 else if( strcmp(carrier,"Unknown") == 0 ) { | |
| 4365 purple_conversation_write(conv, NULL, "Cant send SMS, Unknown mobile carrier", PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
| 4366 | |
| 4367 g_free(msg); | |
| 4368 g_free(msg2); | |
| 4369 return -1; | |
| 4370 } | |
| 4371 | |
| 4372 alias = purple_account_get_alias(account); | |
| 4373 pkt = yahoo_packet_new(YAHOO_SERVICE_SMS_MSG, YAHOO_STATUS_AVAILABLE, 0); | |
| 4374 yahoo_packet_hash(pkt, "sssss", | |
| 4375 1, purple_connection_get_display_name(gc), | |
| 4376 69, alias, | |
| 4377 5, who + 1, | |
| 4378 68, carrier, | |
| 4379 14, msg2); | |
| 4380 yahoo_packet_send_and_free(pkt, yd); | |
| 4381 | |
| 4382 g_free(msg); | |
| 4383 g_free(msg2); | |
| 4384 | |
| 4385 return ret; | |
| 4386 } | |
| 4387 | |
| 4388 pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0); | |
| 3625 yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, who); | 4389 yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, who); |
| 3626 if ((f = yahoo_friend_find(gc, who)) && f->protocol) | 4390 if ((f = yahoo_friend_find(gc, who)) && f->protocol) |
| 3627 yahoo_packet_hash_int(pkt, 241, f->protocol); | 4391 yahoo_packet_hash_int(pkt, 241, f->protocol); |
| 4392 else | |
| 4393 if(strchr(who,'@')) | |
| 4394 yahoo_packet_hash_int(pkt, 241, 2); | |
| 3628 | 4395 |
| 3629 if (utf8) | 4396 if (utf8) |
| 3630 yahoo_packet_hash_str(pkt, 97, "1"); | 4397 yahoo_packet_hash_str(pkt, 97, "1"); |
| 3631 yahoo_packet_hash_str(pkt, 14, msg2); | 4398 yahoo_packet_hash_str(pkt, 14, msg2); |
| 3632 | 4399 |
| 3661 yahoo_packet_hash_str(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */ | 4428 yahoo_packet_hash_str(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */ |
| 3662 else | 4429 else |
| 3663 yahoo_packet_hash_str(pkt, 206, "2"); | 4430 yahoo_packet_hash_str(pkt, 206, "2"); |
| 3664 | 4431 |
| 3665 /* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */ | 4432 /* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */ |
| 3666 if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) | 4433 if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) { |
| 3667 yahoo_packet_send(pkt, yd); | 4434 /* if p2p link exists, send through it. To-do: key 15, time value to be sent in case of p2p */ |
| 4435 if( (p2p_data = g_hash_table_lookup(yd->peers, who)) ) { | |
| 4436 yahoo_packet_hash_int(pkt, 11, p2p_data->session_id); | |
| 4437 yahoo_p2p_write_pkt(p2p_data->source, pkt); | |
| 4438 } | |
| 4439 else { | |
| 4440 yahoo_packet_send(pkt, yd); | |
| 4441 yahoo_send_p2p_pkt(gc, who, 0); /* send p2p packet, with val_13=0 */ | |
| 4442 } | |
| 4443 } | |
| 3668 else | 4444 else |
| 3669 ret = -E2BIG; | 4445 ret = -E2BIG; |
| 3670 | 4446 |
| 3671 yahoo_packet_free(pkt); | 4447 yahoo_packet_free(pkt); |
| 3672 | 4448 |
| 3677 } | 4453 } |
| 3678 | 4454 |
| 3679 static unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) | 4455 static unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) |
| 3680 { | 4456 { |
| 3681 struct yahoo_data *yd = gc->proto_data; | 4457 struct yahoo_data *yd = gc->proto_data; |
| 4458 struct yahoo_p2p_data *p2p_data; | |
| 4459 | |
| 3682 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, 0); | 4460 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, 0); |
| 3683 yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), | 4461 |
| 4462 /* Don't do anything if sms is being typed */ | |
| 4463 if( strncmp(who, "+", 1) == 0 ) | |
| 4464 return 0; | |
| 4465 | |
| 4466 /* check to see if p2p link exists, send through it */ | |
| 4467 if( (p2p_data = g_hash_table_lookup(yd->peers, who)) ) { | |
| 4468 yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc), | |
| 4469 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", | |
| 4470 5, who, 11, p2p_data->session_id, 1002, "1"); /* To-do: key 15 to be sent in case of p2p */ | |
| 4471 yahoo_p2p_write_pkt(p2p_data->source, pkt); | |
| 4472 yahoo_packet_free(pkt); | |
| 4473 } | |
| 4474 else { /* send through yahoo server */ | |
| 4475 yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), | |
| 3684 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", | 4476 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", |
| 3685 5, who, 1002, "1"); | 4477 5, who, 1002, "1"); |
| 3686 | 4478 yahoo_packet_send_and_free(pkt, yd); |
| 3687 yahoo_packet_send_and_free(pkt, yd); | 4479 } |
| 3688 | 4480 |
| 3689 return 0; | 4481 return 0; |
| 3690 } | 4482 } |
| 3691 | 4483 |
| 3692 static void yahoo_session_presence_remove(gpointer key, gpointer value, gpointer data) | 4484 static void yahoo_session_presence_remove(gpointer key, gpointer value, gpointer data) |
| 3933 else | 4725 else |
| 3934 group = "Buddies"; | 4726 group = "Buddies"; |
| 3935 | 4727 |
| 3936 group2 = yahoo_string_encode(gc, group, NULL); | 4728 group2 = yahoo_string_encode(gc, group, NULL); |
| 3937 pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0); | 4729 pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0); |
| 3938 yahoo_packet_hash(pkt, "ssssssssss", | 4730 if(strchr(buddy->name, '@')) { |
| 3939 14, "", | 4731 yahoo_packet_hash(pkt, "sssssssssss", |
| 3940 65, group2, | 4732 14, "", |
| 3941 97, "1", | 4733 65, group2, |
| 3942 1, purple_connection_get_display_name(gc), | 4734 97, "1", |
| 3943 302, "319", | 4735 1, purple_connection_get_display_name(gc), |
| 3944 300, "319", | 4736 302, "319", |
| 3945 7, buddy->name, | 4737 300, "319", |
| 3946 334, "0", | 4738 7, buddy->name, |
| 3947 301, "319", | 4739 241, "2", |
| 3948 303, "319" | 4740 334, "0", |
| 3949 ); | 4741 301, "319", |
| 4742 303, "319" | |
| 4743 ); | |
| 4744 } | |
| 4745 else { | |
| 4746 yahoo_packet_hash(pkt, "ssssssssss", | |
| 4747 14, "", | |
| 4748 65, group2, | |
| 4749 97, "1", | |
| 4750 1, purple_connection_get_display_name(gc), | |
| 4751 302, "319", | |
| 4752 300, "319", | |
| 4753 7, buddy->name, | |
| 4754 334, "0", | |
| 4755 301, "319", | |
| 4756 303, "319" | |
| 4757 ); | |
| 4758 } | |
| 4759 | |
| 3950 if (f && f->protocol) | 4760 if (f && f->protocol) |
| 3951 yahoo_packet_hash_int(pkt, 241, f->protocol); | 4761 yahoo_packet_hash_int(pkt, 241, f->protocol); |
| 3952 yahoo_packet_send_and_free(pkt, yd); | 4762 yahoo_packet_send_and_free(pkt, yd); |
| 3953 g_free(group2); | 4763 g_free(group2); |
| 3954 } | 4764 } |
| 3959 struct yahoo_packet *pkt; | 4769 struct yahoo_packet *pkt; |
| 3960 GSList *buddies, *l; | 4770 GSList *buddies, *l; |
| 3961 PurpleGroup *g; | 4771 PurpleGroup *g; |
| 3962 gboolean remove = TRUE; | 4772 gboolean remove = TRUE; |
| 3963 char *cg; | 4773 char *cg; |
| 3964 | 4774 YahooFriend *f = yahoo_friend_find(gc, buddy->name); |
| 3965 if (!(yahoo_friend_find(gc, buddy->name))) | 4775 |
| 4776 if (!f) | |
| 3966 return; | 4777 return; |
| 3967 | 4778 |
| 3968 buddies = purple_find_buddies(purple_connection_get_account(gc), buddy->name); | 4779 buddies = purple_find_buddies(purple_connection_get_account(gc), buddy->name); |
| 3969 for (l = buddies; l; l = l->next) { | 4780 for (l = buddies; l; l = l->next) { |
| 3970 g = purple_buddy_get_group(l->data); | 4781 g = purple_buddy_get_group(l->data); |
| 3981 | 4792 |
| 3982 cg = yahoo_string_encode(gc, group->name, NULL); | 4793 cg = yahoo_string_encode(gc, group->name, NULL); |
| 3983 pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0); | 4794 pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0); |
| 3984 yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), | 4795 yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), |
| 3985 7, buddy->name, 65, cg); | 4796 7, buddy->name, 65, cg); |
| 4797 if(f->protocol) | |
| 4798 yahoo_packet_hash_int(pkt, 241, f->protocol); | |
| 3986 yahoo_packet_send_and_free(pkt, yd); | 4799 yahoo_packet_send_and_free(pkt, yd); |
| 3987 g_free(cg); | 4800 g_free(cg); |
| 3988 } | 4801 } |
| 3989 | 4802 |
| 3990 static void yahoo_add_deny(PurpleConnection *gc, const char *who) { | 4803 static void yahoo_add_deny(PurpleConnection *gc, const char *who) { |
| 4053 const char *old_group, const char *new_group) | 4866 const char *old_group, const char *new_group) |
| 4054 { | 4867 { |
| 4055 struct yahoo_data *yd = gc->proto_data; | 4868 struct yahoo_data *yd = gc->proto_data; |
| 4056 struct yahoo_packet *pkt; | 4869 struct yahoo_packet *pkt; |
| 4057 char *gpn, *gpo; | 4870 char *gpn, *gpo; |
| 4871 YahooFriend *f = yahoo_friend_find(gc, who); | |
| 4058 | 4872 |
| 4059 /* Step 0: If they aren't on the server list anyway, | 4873 /* Step 0: If they aren't on the server list anyway, |
| 4060 * don't bother letting the server know. | 4874 * don't bother letting the server know. |
| 4061 */ | 4875 */ |
| 4062 if (!yahoo_friend_find(gc, who)) | 4876 if (!f) |
| 4063 return; | 4877 return; |
| 4064 | 4878 |
| 4065 /* If old and new are the same, we would probably | 4879 /* If old and new are the same, we would probably |
| 4066 * end up deleting the buddy, which would be bad. | 4880 * end up deleting the buddy, which would be bad. |
| 4067 * This might happen because of the charset conversation. | 4881 * This might happen because of the charset conversation. |
| 4073 g_free(gpo); | 4887 g_free(gpo); |
| 4074 return; | 4888 return; |
| 4075 } | 4889 } |
| 4076 | 4890 |
| 4077 pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, 0); | 4891 pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, 0); |
| 4078 yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc), | 4892 if(f->protocol) |
| 4893 yahoo_packet_hash(pkt, "ssssissss", 1, purple_connection_get_display_name(gc), | |
| 4894 302, "240", 300, "240", 7, who, 241, f->protocol, 224, gpo, 264, gpn, 301, | |
| 4895 "240", 303, "240"); | |
| 4896 else | |
| 4897 yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc), | |
| 4079 302, "240", 300, "240", 7, who, 224, gpo, 264, gpn, 301, | 4898 302, "240", 300, "240", 7, who, 224, gpo, 264, gpn, 301, |
| 4080 "240", 303, "240"); | 4899 "240", 303, "240"); |
| 4081 yahoo_packet_send_and_free(pkt, yd); | 4900 yahoo_packet_send_and_free(pkt, yd); |
| 4082 | 4901 |
| 4083 g_free(gpn); | 4902 g_free(gpn); |
| 4287 /* Spaces are encoded as '+' */ | 5106 /* Spaces are encoded as '+' */ |
| 4288 g_strdelimit(message, "+", ' '); | 5107 g_strdelimit(message, "+", ' '); |
| 4289 purple_conv_send_confirm(conv, message); | 5108 purple_conv_send_confirm(conv, message); |
| 4290 } | 5109 } |
| 4291 } | 5110 } |
| 4292 /*else | 5111 /* else |
| 4293 **If pidgindialogs_im() was in the core, we could use it here. | 5112 **If pidgindialogs_im() was in the core, we could use it here. |
| 4294 * It is all purple_request_* based, but I'm not sure it really belongs in the core | 5113 * It is all purple_request_* based, but I'm not sure it really belongs in the core |
| 4295 pidgindialogs_im();*/ | 5114 pidgindialogs_im(); */ |
| 4296 | 5115 |
| 4297 return TRUE; | 5116 return TRUE; |
| 4298 } | 5117 } |
| 4299 /* ymsgr:Chat?roomname */ | 5118 /* ymsgr:Chat?roomname */ |
| 4300 else if (!g_ascii_strcasecmp(cmd, "Chat")) { | 5119 else if (!g_ascii_strcasecmp(cmd, "Chat")) { |
| 4304 /* This is somewhat hacky, but the params aren't useful after this command */ | 5123 /* This is somewhat hacky, but the params aren't useful after this command */ |
| 4305 g_hash_table_insert(params, g_strdup("room"), g_strdup(rname)); | 5124 g_hash_table_insert(params, g_strdup("room"), g_strdup(rname)); |
| 4306 g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat")); | 5125 g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat")); |
| 4307 serv_join_chat(purple_account_get_connection(acct), params); | 5126 serv_join_chat(purple_account_get_connection(acct), params); |
| 4308 } | 5127 } |
| 4309 /*else | 5128 /* else |
| 4310 ** Same as above (except that this would have to be re-written using purple_request_*) | 5129 ** Same as above (except that this would have to be re-written using purple_request_*) |
| 4311 pidgin_blist_joinchat_show(); */ | 5130 pidgin_blist_joinchat_show(); */ |
| 4312 | 5131 |
| 4313 return TRUE; | 5132 return TRUE; |
| 4314 } | 5133 } |
| 4374 yahoo_set_idle, | 5193 yahoo_set_idle, |
| 4375 NULL, /* change_passwd*/ | 5194 NULL, /* change_passwd*/ |
| 4376 yahoo_add_buddy, | 5195 yahoo_add_buddy, |
| 4377 NULL, /* add_buddies */ | 5196 NULL, /* add_buddies */ |
| 4378 yahoo_remove_buddy, | 5197 yahoo_remove_buddy, |
| 4379 NULL, /*remove_buddies */ | 5198 NULL, /* remove_buddies */ |
| 4380 NULL, /* add_permit */ | 5199 NULL, /* add_permit */ |
| 4381 yahoo_add_deny, | 5200 yahoo_add_deny, |
| 4382 NULL, /* rem_permit */ | 5201 NULL, /* rem_permit */ |
| 4383 yahoo_rem_deny, | 5202 yahoo_rem_deny, |
| 4384 yahoo_set_permit_deny, | 5203 yahoo_set_permit_deny, |