Mercurial > pidgin.yaz
comparison libpurple/protocols/myspace/myspace.c @ 17337:d3e17c9d16e9
Use MsimMessage for receiving messages everywhere, instead of GHashTable.
author | Jeffrey Connelly <jaconnel@calpoly.edu> |
---|---|
date | Fri, 01 Jun 2007 06:09:32 +0000 |
parents | 793301c04e3a |
children | 9ecd2bb0ecc1 |
comparison
equal
deleted
inserted
replaced
17336:3b226f9544a3 | 17337:d3e17c9d16e9 |
---|---|
263 } | 263 } |
264 /** | 264 /** |
265 * Process a login challenge, sending a response. | 265 * Process a login challenge, sending a response. |
266 * | 266 * |
267 * @param session | 267 * @param session |
268 * @param table Hash table of login challenge message. | 268 * @param msg Login challenge message. |
269 * | 269 * |
270 * @return 0, since the 'table' parameter is no longer needed. | 270 * @return 0, since the 'msg' parameter is no longer needed. |
271 */ | 271 */ |
272 int msim_login_challenge(MsimSession *session, GHashTable *table) | 272 int msim_login_challenge(MsimSession *session, MsimMessage *msg) |
273 { | 273 { |
274 PurpleAccount *account; | 274 PurpleAccount *account; |
275 gchar *nc_str; | |
276 guchar *nc; | |
277 gchar *response; | 275 gchar *response; |
278 gsize nc_len; | |
279 guint response_len; | 276 guint response_len; |
277 gchar *nc; | |
278 gsize nc_len; | |
280 | 279 |
281 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); | 280 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); |
282 g_return_val_if_fail(table != NULL, 0); | 281 g_return_val_if_fail(msg != NULL, 0); |
283 | 282 |
284 nc_str = g_hash_table_lookup(table, "nc"); | 283 g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), 0); |
285 | 284 |
286 account = session->account; | 285 account = session->account; |
287 //assert(account); | 286 //assert(account); |
288 | 287 |
289 purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4); | 288 purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4); |
290 | 289 |
291 purple_debug_info("msim", "nc=<%s>\n", nc_str); | 290 purple_debug_info("msim", "nc is %d bytes, decoded\n", nc_len); |
292 | 291 |
293 nc = (guchar *)purple_base64_decode(nc_str, &nc_len); | |
294 purple_debug_info("msim", "base64 decoded to %d bytes\n", nc_len); | |
295 if (nc_len != 0x40) | 292 if (nc_len != 0x40) |
296 { | 293 { |
297 purple_debug_info("msim", "bad nc length: %x != 0x40\n", nc_len); | 294 purple_debug_info("msim", "bad nc length: %x != 0x40\n", nc_len); |
298 purple_connection_error(session->gc, _("Unexpected challenge length from server")); | 295 purple_connection_error(session->gc, _("Unexpected challenge length from server")); |
299 return 0; | 296 return 0; |
436 * @param response_len Will be written with response length. | 433 * @param response_len Will be written with response length. |
437 * | 434 * |
438 * @return Binary login challenge response, ready to send to the server. Must be g_free()'d | 435 * @return Binary login challenge response, ready to send to the server. Must be g_free()'d |
439 * when finished. | 436 * when finished. |
440 */ | 437 */ |
441 gchar *msim_compute_login_response(guchar nonce[2 * NONCE_SIZE], | 438 gchar *msim_compute_login_response(gchar nonce[2 * NONCE_SIZE], |
442 gchar *email, gchar *password, guint *response_len) | 439 gchar *email, gchar *password, guint *response_len) |
443 { | 440 { |
444 PurpleCipherContext *key_context; | 441 PurpleCipherContext *key_context; |
445 PurpleCipher *sha1; | 442 PurpleCipher *sha1; |
446 #ifdef MSIM_USE_PURPLE_RC4 | 443 #ifdef MSIM_USE_PURPLE_RC4 |
489 | 486 |
490 /* key = sha1(sha1(pw) + nonce2) */ | 487 /* key = sha1(sha1(pw) + nonce2) */ |
491 sha1 = purple_ciphers_find_cipher("sha1"); | 488 sha1 = purple_ciphers_find_cipher("sha1"); |
492 key_context = purple_cipher_context_new(sha1, NULL); | 489 key_context = purple_cipher_context_new(sha1, NULL); |
493 purple_cipher_context_append(key_context, hash_pw, HASH_SIZE); | 490 purple_cipher_context_append(key_context, hash_pw, HASH_SIZE); |
494 purple_cipher_context_append(key_context, nonce + NONCE_SIZE, NONCE_SIZE); | 491 purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); |
495 purple_cipher_context_digest(key_context, sizeof(key), key, NULL); | 492 purple_cipher_context_digest(key_context, sizeof(key), key, NULL); |
496 | 493 |
497 #ifdef MSIM_DEBUG_LOGIN_CHALLENGE | 494 #ifdef MSIM_DEBUG_LOGIN_CHALLENGE |
498 purple_debug_info("msim", "key = "); | 495 purple_debug_info("msim", "key = "); |
499 for (i = 0; i < sizeof(key); i++) | 496 for (i = 0; i < sizeof(key); i++) |
640 * @param session | 637 * @param session |
641 * @param userid ASCII numeric userid. | 638 * @param userid ASCII numeric userid. |
642 * @param message Text of message to send. | 639 * @param message Text of message to send. |
643 * @param flags Purple instant message flags. | 640 * @param flags Purple instant message flags. |
644 * | 641 * |
645 * @return 0, since the 'table' parameter is no longer needed. | 642 * @return 0 |
646 * | 643 * |
647 */ | 644 */ |
648 int msim_send_im_by_userid(MsimSession *session, const gchar *userid, const gchar *message, PurpleMessageFlags flags) | 645 int msim_send_im_by_userid(MsimSession *session, const gchar *userid, const gchar *message, PurpleMessageFlags flags) |
649 { | 646 { |
650 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); | 647 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); |
674 * Calls msim_send_im_by_userid. | 671 * Calls msim_send_im_by_userid. |
675 * | 672 * |
676 * @param session | 673 * @param session |
677 * @param userinfo User info message from server containing a 'body' field | 674 * @param userinfo User info message from server containing a 'body' field |
678 * with a 'UserID' key. This is where the user ID is taken from. | 675 * with a 'UserID' key. This is where the user ID is taken from. |
676 * Will be destroyed after use. | |
679 * @param data A send_im_cb_struct * of information on the IM to send. | 677 * @param data A send_im_cb_struct * of information on the IM to send. |
680 * | 678 * |
681 */ | 679 */ |
682 void msim_send_im_by_userid_cb(MsimSession *session, GHashTable *userinfo, gpointer data) | 680 void msim_send_im_by_userid_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) |
683 { | 681 { |
684 send_im_cb_struct *s; | 682 send_im_cb_struct *s; |
685 gchar *userid; | 683 gchar *userid; |
686 GHashTable *body; | 684 GHashTable *body; |
685 gchar *body_str; | |
687 | 686 |
688 g_return_if_fail(MSIM_SESSION_VALID(session)); | 687 g_return_if_fail(MSIM_SESSION_VALID(session)); |
689 g_return_if_fail(userinfo != NULL); | 688 g_return_if_fail(userinfo != NULL); |
690 | 689 |
691 body = msim_parse_body(g_hash_table_lookup(userinfo, "body")); | 690 body_str = msim_msg_get_string(userinfo, "body"); |
691 body = msim_parse_body(body_str); | |
692 g_free(body_str); | |
692 g_return_if_fail(body != NULL); | 693 g_return_if_fail(body != NULL); |
693 | 694 |
694 userid = g_hash_table_lookup(body, "UserID"); | 695 userid = g_hash_table_lookup(body, "UserID"); |
695 | 696 |
696 s = (send_im_cb_struct *)data; | 697 s = (send_im_cb_struct *)data; |
697 msim_send_im_by_userid(session, userid, s->message, s->flags); | 698 msim_send_im_by_userid(session, userid, s->message, s->flags); |
698 | 699 |
699 g_hash_table_destroy(body); | 700 g_hash_table_destroy(body); |
700 g_hash_table_destroy(userinfo); | 701 /* g_hash_table_destroy(userinfo); */ |
702 /* TODO: do we need to free userinfo here? */ | |
703 msim_msg_free(userinfo); | |
701 g_free(s->message); | 704 g_free(s->message); |
702 g_free(s->who); | 705 g_free(s->who); |
703 } | 706 } |
704 | 707 |
705 /** | 708 /** |
707 * | 710 * |
708 * @param session | 711 * @param session |
709 * @param userinfo Message from server on user's info, containing UserName. | 712 * @param userinfo Message from server on user's info, containing UserName. |
710 * @param data A gchar * of the incoming instant message's text. | 713 * @param data A gchar * of the incoming instant message's text. |
711 */ | 714 */ |
712 void msim_incoming_im_cb(MsimSession *session, GHashTable *userinfo, gpointer data) | 715 void msim_incoming_im_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) |
713 { | 716 { |
714 gchar *msg; | 717 gchar *msg, *username, *body_str; |
715 gchar *username; | |
716 GHashTable *body; | 718 GHashTable *body; |
717 | 719 |
718 g_return_if_fail(MSIM_SESSION_VALID(session)); | 720 g_return_if_fail(MSIM_SESSION_VALID(session)); |
719 g_return_if_fail(userinfo != NULL); | 721 g_return_if_fail(userinfo != NULL); |
720 | 722 |
721 body = msim_parse_body(g_hash_table_lookup(userinfo, "body")); | 723 body_str = msim_msg_get_string(userinfo, "body"); |
724 body = msim_parse_body(body_str); | |
725 g_free(body); | |
722 g_return_if_fail(body != NULL); | 726 g_return_if_fail(body != NULL); |
723 | 727 |
724 username = g_hash_table_lookup(body, "UserName"); | 728 username = g_hash_table_lookup(body, "UserName"); |
725 | 729 |
726 msg = (gchar *)data; | 730 msg = (gchar *)data; |
727 serv_got_im(session->gc, username, msg, PURPLE_MESSAGE_RECV, time(NULL)); | 731 serv_got_im(session->gc, username, msg, PURPLE_MESSAGE_RECV, time(NULL)); |
728 | 732 |
733 msim_msg_free(userinfo); /* TODO: Should we? */ | |
729 g_hash_table_destroy(body); | 734 g_hash_table_destroy(body); |
730 g_hash_table_destroy(userinfo); | |
731 } | 735 } |
732 | 736 |
733 /** | 737 /** |
734 * Handle an incoming message. | 738 * Handle an incoming message. |
735 * | 739 * |
736 * @param session The session | 740 * @param session The session |
737 * @param table Message from the server, containing 'f' (userid from) and 'msg'. | 741 * @param msg Message from the server, containing 'f' (userid from) and 'msg'. |
738 * | 742 * |
739 * @return 0, since table can be freed. | 743 * @return 0, since msg can be freed. |
740 */ | 744 */ |
741 int msim_incoming_im(MsimSession *session, GHashTable *table) | 745 int msim_incoming_im(MsimSession *session, MsimMessage *msg) |
742 { | 746 { |
743 gchar *userid; | 747 gchar *userid; |
744 gchar *msg; | 748 gchar *msg_text; |
745 | 749 |
746 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); | 750 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); |
747 g_return_val_if_fail(table != NULL, 0); | 751 g_return_val_if_fail(msg != NULL, 0); |
748 | 752 |
749 | 753 /* TODO: where freed? */ |
750 userid = g_hash_table_lookup(table, "f"); | 754 userid = msim_msg_get_string(msg, "f"); |
751 msg = g_hash_table_lookup(table, "msg"); | 755 msg_text = msim_msg_get_string(msg, "msg"); |
752 | 756 |
753 purple_debug_info("msim", | 757 purple_debug_info("msim", |
754 "msim_incoming_im: got msg <%s> from <%s>, resolving username\n", | 758 "msim_incoming_im: got msg <%s> from <%s>, resolving username\n", |
755 msg, userid); | 759 msg_text, userid); |
756 | 760 |
757 msim_lookup_user(session, userid, msim_incoming_im_cb, g_strdup(msg)); | 761 msim_lookup_user(session, userid, msim_incoming_im_cb, msg_text); |
758 | 762 |
759 return 0; | 763 return 0; |
760 } | 764 } |
761 | 765 |
762 | 766 |
763 /** | 767 /** |
764 * Process a message. | 768 * Process a message. |
765 * | 769 * |
766 * @param gc Connection. | 770 * @param gc Connection. |
767 * @param table Any message from the server. | 771 * @param msg Any message from the server. |
768 * | 772 * |
769 * @return The return value of the function used to process the message, or -1 if | 773 * @return The return value of the function used to process the message, or -1 if |
770 * called with invalid parameters. | 774 * called with invalid parameters. |
771 */ | 775 */ |
772 int msim_process(PurpleConnection *gc, MsimMessage *msg) | 776 int msim_process(PurpleConnection *gc, MsimMessage *msg) |
790 | 794 |
791 purple_debug_info("msim", "------------------------------\n"); | 795 purple_debug_info("msim", "------------------------------\n"); |
792 } | 796 } |
793 #endif | 797 #endif |
794 | 798 |
795 /* TODO: convert to use MsimMessage. */ | 799 if (msim_msg_get(msg, "nc")) |
796 #if 0 | 800 { |
797 if (g_hash_table_lookup(table, "nc")) | 801 return msim_login_challenge(session, msg); |
798 { | 802 } else if (msim_msg_get(msg, "sesskey")) { |
799 return msim_login_challenge(session, table); | |
800 } else if (g_hash_table_lookup(table, "sesskey")) { | |
801 purple_debug_info("msim", "SESSKEY=<%s>\n", (gchar *)g_hash_table_lookup(table, "sesskey")); | |
802 | 803 |
803 purple_connection_update_progress(gc, _("Connected"), 3, 4); | 804 purple_connection_update_progress(gc, _("Connected"), 3, 4); |
804 | 805 |
805 session->sesskey = g_strdup(g_hash_table_lookup(table, "sesskey")); | 806 /* Freed in msim_session_destroy */ |
807 session->sesskey = msim_msg_get_string(msg, "sesskey"); | |
808 purple_debug_info("msim", "SESSKEY=<%s>\n", session->sesskey); | |
806 | 809 |
807 /* Comes with: proof,profileid,userid,uniquenick -- all same values | 810 /* Comes with: proof,profileid,userid,uniquenick -- all same values |
808 * (at least for me). */ | 811 * (at least for me). */ |
809 session->userid = g_strdup(g_hash_table_lookup(table, "userid")); | 812 /* Freed in msim_session_destroy */ |
813 session->userid = msim_msg_get_string(msg, "userid"); | |
810 | 814 |
811 purple_connection_set_state(gc, PURPLE_CONNECTED); | 815 purple_connection_set_state(gc, PURPLE_CONNECTED); |
812 | 816 |
813 return 0; | 817 return 0; |
814 } else if (g_hash_table_lookup(table, "bm")) { | 818 } else if (msim_msg_get(msg, "bm")) { |
815 guint bm; | 819 guint bm; |
816 | 820 |
817 bm = atoi(g_hash_table_lookup(table, "bm")); | 821 bm = msim_msg_get_integer(msg, "bm"); |
818 switch (bm) | 822 switch (bm) |
819 { | 823 { |
820 case MSIM_BM_STATUS: | 824 case MSIM_BM_STATUS: |
821 return msim_status(session, table); | 825 return msim_status(session, msg); |
822 case MSIM_BM_INSTANT: | 826 case MSIM_BM_INSTANT: |
823 return msim_incoming_im(session, table); | 827 return msim_incoming_im(session, msg); |
824 default: | 828 default: |
825 /* Not really an IM, but show it for informational | 829 /* Not really an IM, but show it for informational |
826 * purposes during development. */ | 830 * purposes during development. */ |
827 return msim_incoming_im(session, table); | 831 return msim_incoming_im(session, msg); |
828 } | 832 } |
829 | 833 |
830 if (bm == MSIM_BM_STATUS) | 834 if (bm == MSIM_BM_STATUS) |
831 { | 835 { |
832 return msim_status(session, table); | 836 return msim_status(session, msg); |
833 } else { /* else if strcmp(bm, "1") == 0) */ | 837 } else { /* else if strcmp(bm, "1") == 0) */ |
834 return msim_incoming_im(session, table); | 838 return msim_incoming_im(session, msg); |
835 } | 839 } |
836 } else if (g_hash_table_lookup(table, "rid")) { | 840 } else if (msim_msg_get(msg, "rid")) { |
837 return msim_process_reply(session, table); | 841 return msim_process_reply(session, msg); |
838 } else if (g_hash_table_lookup(table, "error")) { | 842 } else if (msim_msg_get(msg, "error")) { |
839 return msim_error(session, table); | 843 return msim_error(session, msg); |
840 } else if (g_hash_table_lookup(table, "ka")) { | 844 } else if (msim_msg_get(msg, "ka")) { |
841 purple_debug_info("msim", "msim_process: got keep alive\n"); | 845 purple_debug_info("msim", "msim_process: got keep alive\n"); |
842 return 0; | 846 return 0; |
843 } else { | 847 } else { |
844 /* TODO: dump unknown msgs to file, so user can send them to me | 848 /* TODO: dump unknown msgs to file, so user can send them to me |
845 * if they wish, to help add support for new messages (inspired | 849 * if they wish, to help add support for new messages (inspired |
846 * by Alexandr Shutko, who maintains OSCAR protocol documentation). */ | 850 * by Alexandr Shutko, who maintains OSCAR protocol documentation). */ |
847 purple_debug_info("msim", "msim_process: unhandled message\n"); | 851 purple_debug_info("msim", "msim_process: unhandled message\n"); |
848 return 0; | 852 return 0; |
849 } | 853 } |
850 #else | |
851 return 0; | |
852 #endif | |
853 } | 854 } |
854 | 855 |
855 /** | 856 /** |
856 * Process a message reply from the server. | 857 * Process a message reply from the server. |
857 * | 858 * |
858 * @param session | 859 * @param session |
859 * @param table Message reply from server. | 860 * @param msg Message reply from server. |
860 * | 861 * |
861 * @return 0, since the 'table' field is no longer needed. | 862 * @return 0, since the 'msg' field is no longer needed. |
862 */ | 863 */ |
863 int msim_process_reply(MsimSession *session, GHashTable *table) | 864 int msim_process_reply(MsimSession *session, MsimMessage *msg) |
864 { | 865 { |
865 gchar *rid_str; | |
866 | |
867 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); | 866 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); |
868 g_return_val_if_fail(table != NULL, 0); | 867 g_return_val_if_fail(msg != NULL, 0); |
869 | 868 |
870 rid_str = g_hash_table_lookup(table, "rid"); | 869 if (msim_msg_get(msg, "rid")) /* msim_lookup_user sets callback for here */ |
871 | |
872 if (rid_str) /* msim_lookup_user sets callback for here */ | |
873 { | 870 { |
874 MSIM_USER_LOOKUP_CB cb; | 871 MSIM_USER_LOOKUP_CB cb; |
875 gpointer data; | 872 gpointer data; |
876 guint rid; | 873 guint rid; |
877 | |
878 GHashTable *body; | 874 GHashTable *body; |
879 gchar *username; | 875 gchar *username, *body_str; |
880 | 876 |
881 rid = atol(rid_str); | 877 rid = msim_msg_get_integer(msg, "rid"); |
882 | 878 |
883 /* Cache the user info. Currently, the GHashTable of user info in | 879 /* Cache the user info. Currently, the GHashTable of user info in |
884 * this cache never expires so is never freed. TODO: expire and destroy | 880 * this cache never expires so is never freed. TODO: expire and destroy |
885 * | 881 * |
886 * Some information never changes (username->userid map), some does. | 882 * Some information never changes (username->userid map), some does. |
887 * TODO: Cache what doesn't change only | 883 * TODO: Cache what doesn't change only |
888 */ | 884 */ |
889 body = msim_parse_body(g_hash_table_lookup(table, "body")); | 885 body_str = msim_msg_get_string(msg, "body"); |
886 body = msim_parse_body(body_str); | |
887 g_free(body_str); | |
888 | |
889 /* TODO: implement a better hash-like interface, and use it. */ | |
890 username = g_hash_table_lookup(body, "UserName"); | 890 username = g_hash_table_lookup(body, "UserName"); |
891 if (username) | 891 if (username) |
892 { | 892 { |
893 /* TODO: permanently associated with blist item, if in buddy in blist */ | |
893 g_hash_table_insert(session->user_lookup_cache, g_strdup(username), body); | 894 g_hash_table_insert(session->user_lookup_cache, g_strdup(username), body); |
894 } else { | 895 } else { |
895 purple_debug_info("msim", | 896 purple_debug_info("msim", |
896 "msim_process_reply: not caching <%s>, no UserName\n", | 897 "msim_process_reply: not caching body, no UserName\n"); |
897 g_hash_table_lookup(table, "body")); | |
898 } | 898 } |
899 | 899 |
900 /* If a callback is registered for this userid lookup, call it. */ | 900 /* If a callback is registered for this userid lookup, call it. */ |
901 | |
902 cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid)); | 901 cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid)); |
903 data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); | 902 data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); |
904 | 903 |
905 if (cb) | 904 if (cb) |
906 { | 905 { |
907 purple_debug_info("msim", | 906 purple_debug_info("msim", |
908 "msim_process_body: calling callback now\n"); | 907 "msim_process_body: calling callback now\n"); |
909 cb(session, table, data); | 908 cb(session, msg, data); |
910 g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid)); | 909 g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid)); |
911 g_hash_table_remove(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); | 910 g_hash_table_remove(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); |
912 | 911 |
913 /* Return 1 to tell caller of msim_process (msim_input_cb) to | 912 /* Return 1 to tell caller of msim_process (msim_input_cb) to |
914 * not destroy 'table'; allow 'cb' to hang on to it and destroy | 913 * not destroy 'msg'; allow 'cb' to hang on to it and destroy |
915 * it when it wants. */ | 914 * it when it wants. */ |
916 return 1; | 915 return 1; |
917 } else { | 916 } else { |
918 purple_debug_info("msim", | 917 purple_debug_info("msim", |
919 "msim_process_body: no callback for rid %d\n", rid); | 918 "msim_process_body: no callback for rid %d\n", rid); |
924 | 923 |
925 /** | 924 /** |
926 * Handle an error from the server. | 925 * Handle an error from the server. |
927 * | 926 * |
928 * @param session | 927 * @param session |
929 * @param table The message. | 928 * @param msg The message. |
930 * | 929 * |
931 * @return 0, since 'table' can be freed. | 930 * @return 0, since 'msg' can be freed. |
932 */ | 931 */ |
933 int msim_error(MsimSession *session, GHashTable *table) | 932 int msim_error(MsimSession *session, MsimMessage *msg) |
934 { | 933 { |
935 gchar *err, *errmsg, *full_errmsg; | 934 gchar *errmsg, *full_errmsg; |
935 guint err; | |
936 | 936 |
937 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); | 937 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); |
938 g_return_val_if_fail(table != NULL, 0); | 938 g_return_val_if_fail(msg != NULL, 0); |
939 | 939 |
940 err = g_hash_table_lookup(table, "err"); | 940 err = msim_msg_get_integer(msg, "err"); |
941 errmsg = g_hash_table_lookup(table, "errmsg"); | 941 errmsg = msim_msg_get_string(msg, "errmsg"); |
942 | 942 |
943 full_errmsg = g_strdup_printf(_("Protocol error, code %s: %s"), err, errmsg); | 943 full_errmsg = g_strdup_printf(_("Protocol error, code %d: %s"), err, errmsg); |
944 | |
945 g_free(errmsg); | |
944 | 946 |
945 purple_debug_info("msim", "msim_error: %s\n", full_errmsg); | 947 purple_debug_info("msim", "msim_error: %s\n", full_errmsg); |
946 | 948 |
947 /* TODO: check 'fatal' and die if asked to. | 949 /* TODO: check 'fatal' and die if asked to. |
948 * TODO: do something with the error # (localization of errmsg?) */ | 950 * TODO: do something with the error # (localization of errmsg?) */ |
949 purple_notify_error(session->account, g_strdup(_("MySpaceIM Error")), | 951 purple_notify_error(session->account, g_strdup(_("MySpaceIM Error")), |
950 full_errmsg, NULL); | 952 full_errmsg, NULL); |
951 | 953 |
952 if (g_hash_table_lookup(table, "fatal")) | 954 if (msim_msg_get(msg, "fatal")) |
953 { | 955 { |
954 purple_debug_info("msim", "fatal error, destroy session\n"); | 956 purple_debug_info("msim", "fatal error, destroy session\n"); |
955 purple_connection_error(session->gc, full_errmsg); | 957 purple_connection_error(session->gc, full_errmsg); |
956 close(session->fd); | 958 close(session->fd); |
957 //msim_session_destroy(session); | 959 //msim_session_destroy(session); |
971 /** | 973 /** |
972 * Callback to update incoming status messages, after looked up username. | 974 * Callback to update incoming status messages, after looked up username. |
973 * | 975 * |
974 * @param session | 976 * @param session |
975 * @param userinfo Looked up user information from server. | 977 * @param userinfo Looked up user information from server. |
976 * @param data gchar * status string. | 978 * @param data gchar * status string, will be freed. |
977 * | 979 * |
978 */ | 980 */ |
979 void msim_status_cb(MsimSession *session, GHashTable *userinfo, gpointer data) | 981 void msim_status_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) |
980 { | 982 { |
981 PurpleBuddyList *blist; | 983 PurpleBuddyList *blist; |
982 PurpleBuddy *buddy; | 984 PurpleBuddy *buddy; |
983 PurplePresence *presence; | 985 PurplePresence *presence; |
984 GHashTable *body; | 986 GHashTable *body; |
987 gchar *body_str; | |
985 //PurpleStatus *status; | 988 //PurpleStatus *status; |
986 gchar **status_array; | 989 gchar **status_array; |
987 GList *list; | 990 GList *list; |
988 gchar *status_text, *status_code; | 991 gchar *status_text, *status_code; |
989 gchar *status_str; | 992 gchar *status_str; |
993 g_return_if_fail(MSIM_SESSION_VALID(session)); | 996 g_return_if_fail(MSIM_SESSION_VALID(session)); |
994 g_return_if_fail(userinfo != NULL); | 997 g_return_if_fail(userinfo != NULL); |
995 | 998 |
996 status_str = (gchar *)data; | 999 status_str = (gchar *)data; |
997 | 1000 |
998 body = msim_parse_body(g_hash_table_lookup(userinfo, "body")); | 1001 body_str = msim_msg_get_string(userinfo, "body"); |
1002 body = msim_parse_body(body_str); | |
1003 g_free(body_str); | |
999 g_return_if_fail(body != NULL); | 1004 g_return_if_fail(body != NULL); |
1000 | 1005 |
1001 username = g_hash_table_lookup(body, "UserName"); | 1006 username = g_hash_table_lookup(body, "UserName"); |
1002 /* Note: DisplayName doesn't seem to be resolvable. It could be displayed on | 1007 /* Note: DisplayName doesn't seem to be resolvable. It could be displayed on |
1003 * the buddy list, if the UserID was stored along with it. */ | 1008 * the buddy list, if the UserID was stored along with it. */ |
1049 /* purple_presence_set_status_active(presence, PURPLE_STATUS_AVAILABLE, TRUE); */ | 1054 /* purple_presence_set_status_active(presence, PURPLE_STATUS_AVAILABLE, TRUE); */ |
1050 | 1055 |
1051 g_strfreev(status_array); | 1056 g_strfreev(status_array); |
1052 g_list_free(list); | 1057 g_list_free(list); |
1053 g_hash_table_destroy(body); | 1058 g_hash_table_destroy(body); |
1054 g_hash_table_destroy(userinfo); | 1059 msim_msg_free(userinfo); /* TODO: right? */ |
1055 /* Do not free status_str - it will be freed by g_hash_table_destroy on session->userid_lookup_cb_data */ | 1060 /* Do not free status_str - it will currently be freed by g_hash_table_destroy |
1061 * on session->user_lookup_cb_data. But this is questionable (TODO: unask) since | |
1062 * sometimes user_lookup_cb_data stores integers in gpointers, and sometimes | |
1063 * real gpointers that need to be freed, like our status_str. | |
1064 */ | |
1065 /* g_free(status_str); */ | |
1056 } | 1066 } |
1057 | 1067 |
1058 /** | 1068 /** |
1059 * Process incoming status messages. | 1069 * Process incoming status messages. |
1060 * | 1070 * |
1061 * @param session | 1071 * @param session |
1062 * @param table Status update message. | 1072 * @param msg Status update message. |
1063 * | 1073 * |
1064 * @return 0, since 'table' can be freed. | 1074 * @return 0, since 'msg' can be freed. |
1065 */ | 1075 */ |
1066 int msim_status(MsimSession *session, GHashTable *table) | 1076 int msim_status(MsimSession *session, MsimMessage *msg) |
1067 { | 1077 { |
1068 gchar *status_str; | 1078 gchar *status_str; |
1069 gchar *userid; | 1079 gchar *userid; |
1070 | 1080 |
1071 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); | 1081 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); |
1072 g_return_val_if_fail(table != NULL, 0); | 1082 g_return_val_if_fail(msg != NULL, 0); |
1073 | 1083 |
1074 status_str = g_hash_table_lookup(table, "msg"); | 1084 /* TODO: free */ |
1085 status_str = msim_msg_get_string(msg, "msg"); | |
1075 if (!status_str) | 1086 if (!status_str) |
1076 { | 1087 { |
1077 purple_debug_info("msim", "msim_status: bm is status but no status msg\n"); | 1088 purple_debug_info("msim", "msim_status: bm is status but no status msg\n"); |
1078 return 0; | 1089 return 0; |
1079 } | 1090 } |
1080 | 1091 |
1081 userid = g_hash_table_lookup(table, "f"); | 1092 /* TODO: free */ |
1093 userid = msim_msg_get_string(msg, "f"); | |
1082 if (!userid) | 1094 if (!userid) |
1083 { | 1095 { |
1084 purple_debug_info("msim", "msim_status: bm is status but no f field\n"); | 1096 purple_debug_info("msim", "msim_status: bm is status but no f field\n"); |
1085 return 0; | 1097 return 0; |
1086 } | 1098 } |
1089 * before updating the status! Much more efficient. */ | 1101 * before updating the status! Much more efficient. */ |
1090 purple_debug_info("msim", | 1102 purple_debug_info("msim", |
1091 "msim_status: got status msg <%s> for <%s>, scheduling lookup\n", | 1103 "msim_status: got status msg <%s> for <%s>, scheduling lookup\n", |
1092 status_str, userid); | 1104 status_str, userid); |
1093 | 1105 |
1094 /* Actually update status once obtain username */ | 1106 /* Actually update status, once username is obtained. |
1095 msim_lookup_user(session, userid, msim_status_cb, g_strdup(status_str)); | 1107 * status_str() will currently be freed by g_hash_table_destroy() on |
1108 * user_lookup_cb_data (TODO: this is questionable, since it can also | |
1109 * store gpointers. Fix this, and the 2 other TODOs of the same problem.) | |
1110 */ | |
1111 msim_lookup_user(session, userid, msim_status_cb, status_str); | |
1096 | 1112 |
1097 return 0; | 1113 return 0; |
1098 } | 1114 } |
1099 | 1115 |
1100 | 1116 |
1273 session->magic = MSIM_SESSION_STRUCT_MAGIC; | 1289 session->magic = MSIM_SESSION_STRUCT_MAGIC; |
1274 session->account = acct; | 1290 session->account = acct; |
1275 session->gc = purple_account_get_connection(acct); | 1291 session->gc = purple_account_get_connection(acct); |
1276 session->fd = -1; | 1292 session->fd = -1; |
1277 session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, | 1293 session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, |
1278 g_direct_equal, NULL, NULL); /* do NOT free function pointers! */ | 1294 g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */ |
1279 session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, | 1295 session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, |
1280 g_direct_equal, NULL, g_free); | 1296 g_direct_equal, NULL, g_free);/* TODO: we don't know what the values are, |
1297 they could be integers inside gpointers | |
1298 or strings, but we free them anyway. | |
1299 Figure this out, once free cache. */ | |
1281 session->user_lookup_cache = g_hash_table_new_full(g_str_hash, g_str_equal, | 1300 session->user_lookup_cache = g_hash_table_new_full(g_str_hash, g_str_equal, |
1282 g_free, (GDestroyNotify)g_hash_table_destroy); | 1301 g_free, (GDestroyNotify)g_hash_table_destroy); |
1283 session->rxoff = 0; | 1302 session->rxoff = 0; |
1284 session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE); | 1303 session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE); |
1285 session->next_rid = 1; | 1304 session->next_rid = 1; |