libpurple/protocols/myspace/myspace.c

branch
soc.2007.msimprpl
changeset 17950
c146721d0ca7
parent 17949
a74745e42b2b
child 17951
313b994beb1d
equal deleted inserted replaced
17949:a74745e42b2b 17950:c146721d0ca7
692 /** 692 /**
693 * Callback to handle incoming messages, after resolving userid. 693 * Callback to handle incoming messages, after resolving userid.
694 * 694 *
695 * @param session 695 * @param session
696 * @param userinfo Message from server on user's info, containing UserName. 696 * @param userinfo Message from server on user's info, containing UserName.
697 * @param data A MsimMessage * of the incoming message. 697 * @param data A MsimMessage * of the incoming message, will be freed.
698 */ 698 */
699 void msim_incoming_im_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) 699 void msim_incoming_im_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
700 { 700 {
701 gchar *username, *body_str; 701 gchar *username, *body_str;
702 MsimMessage *msg; 702 MsimMessage *msg;
715 msg = (MsimMessage *)data; 715 msg = (MsimMessage *)data;
716 serv_got_im(session->gc, username, msim_msg_get_string(msg, "msg"), PURPLE_MESSAGE_RECV, time(NULL)); 716 serv_got_im(session->gc, username, msim_msg_get_string(msg, "msg"), PURPLE_MESSAGE_RECV, time(NULL));
717 717
718 /* msim_msg_free(userinfo); */ /* TODO: Should we? */ 718 /* msim_msg_free(userinfo); */ /* TODO: Should we? */
719 g_hash_table_destroy(body); 719 g_hash_table_destroy(body);
720 /* Free copy cloned in msim_incoming_im(). */
720 msim_msg_free(msg); 721 msim_msg_free(msg);
721 } 722 }
722 723
723 /** 724 /**
724 * Handle an incoming instant message. 725 * Handle an incoming instant message.
740 741
741 purple_debug_info("msim", 742 purple_debug_info("msim",
742 "msim_incoming_im: got msg from <%s>, resolving username\n", userid); 743 "msim_incoming_im: got msg from <%s>, resolving username\n", userid);
743 744
744 /* TODO: don't use callbacks */ 745 /* TODO: don't use callbacks */
745 /* msg will be freed in callback */ 746 /* Cloned msg will be freed in callback */
746 msim_lookup_user(session, userid, msim_incoming_im_cb, msim_msg_clone(msg)); 747 msim_lookup_user(session, userid, msim_incoming_im_cb, msim_msg_clone(msg));
747 748
748 return TRUE; 749 return TRUE;
749 } 750 }
750 751
796 purple_debug_info("msim", "msim_send_typing(%s): %d\n", name, state); 797 purple_debug_info("msim", "msim_send_typing(%s): %d\n", name, state);
797 //msim_send_action(name, typing_str); 798 //msim_send_action(name, typing_str);
798 return 0; 799 return 0;
799 } 800 }
800 801
802 /** After a uid is resolved to username, tag it with the username and submit for processing.
803 *
804 * @param session
805 * @param userinfo Response messsage to resolving request.
806 * @param data MsimMessage *, the message to attach information to.
807 */
808 static void msim_incoming_resolved(MsimSession *session, MsimMessage *userinfo, gpointer data)
809 {
810 gchar *body_str;
811 GHashTable *body;
812 gchar *username;
813 MsimMessage *msg;
814
815 body_str = msim_msg_get_string(userinfo, "body");
816 g_return_if_fail(body_str != NULL);
817 body = msim_parse_body(body_str);
818 g_return_if_fail(body != NULL);
819 g_free(body_str);
820
821 username = g_hash_table_lookup(body, "UserName");
822 g_return_if_fail(username != NULL);
823
824 msg = (MsimMessage *)data;
825 /* Special elements name beginning with '_', we'll use internally within the
826 * program (did not come from the wire). */
827 msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
828
829 msim_process(session, msg);
830
831 /* Free copy cloned in msim_preprocess_incoming(). */
832 /* TODO: find out freedom */
833 //XXX msim_msg_free(msg);
834 g_hash_table_destroy(body);
835 }
836
837 /** Preprocess incoming messages, resolving as needed, calling msim_process() when ready to process.
838 *
839 * TODO: if no uid to resolve, process immediately. if uid, check if know username,
840 * if so, tag and process immediately, if not, queue, send resolve msg, and process
841 * once get username.
842 *
843 * @param session
844 * @param msg MsimMessage *, freed by caller.
845 */
846 gboolean msim_preprocess_incoming(MsimSession *session, MsimMessage *msg)
847 {
848 if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f"))
849 {
850 /* 'f' = userid message is from, in buddy messages */
851
852 /* TODO: if know uid->username mapping already, process immediately */
853
854 /* Send lookup request. */
855 /* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */
856 purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n");
857 msim_lookup_user(session, msim_msg_get_string(msg, "f"), msim_incoming_resolved, msim_msg_clone(msg));
858
859 /* indeterminate */
860 return TRUE;
861 } else {
862 /* Nothing to resolve - send directly to processing. */
863 return msim_process(session, msg);
864 }
865 }
866
801 /** 867 /**
802 * Process a message. 868 * Process a message.
803 * 869 *
804 * @param gc Connection. 870 * @param session
805 * @param msg Any message from the server. 871 * @param msg A message from the server, ready for processing (possibly with resolved username information attached). Caller frees.
806 * 872 *
807 * @return TRUE if successful. FALSE if processing failed. 873 * @return TRUE if successful. FALSE if processing failed.
808 */ 874 */
809 gboolean msim_process(PurpleConnection *gc, MsimMessage *msg) 875 gboolean msim_process(MsimSession *session, MsimMessage *msg)
810 { 876 {
811 MsimSession *session; 877 g_return_val_if_fail(session != NULL, -1);
812
813 g_return_val_if_fail(gc != NULL, -1);
814 g_return_val_if_fail(msg != NULL, -1); 878 g_return_val_if_fail(msg != NULL, -1);
815
816 session = (MsimSession *)gc->proto_data;
817 879
818 #ifdef MSIM_DEBUG_MSG 880 #ifdef MSIM_DEBUG_MSG
819 { 881 {
820 msim_msg_dump("ready to process: %s\n", msg); 882 msim_msg_dump("ready to process: %s\n", msg);
821 } 883 }
824 if (msim_msg_get(msg, "nc")) 886 if (msim_msg_get(msg, "nc"))
825 { 887 {
826 return msim_login_challenge(session, msg); 888 return msim_login_challenge(session, msg);
827 } else if (msim_msg_get(msg, "sesskey")) { 889 } else if (msim_msg_get(msg, "sesskey")) {
828 890
829 purple_connection_update_progress(gc, _("Connected"), 3, 4); 891 purple_connection_update_progress(session->gc, _("Connected"), 3, 4);
830 892
831 /* Freed in msim_session_destroy */ 893 /* Freed in msim_session_destroy */
832 session->sesskey = msim_msg_get_integer(msg, "sesskey"); 894 session->sesskey = msim_msg_get_integer(msg, "sesskey");
833 purple_debug_info("msim", "SESSKEY=<%d>\n", session->sesskey); 895 purple_debug_info("msim", "SESSKEY=<%d>\n", session->sesskey);
834 896
835 /* Comes with: proof,profileid,userid,uniquenick -- all same values 897 /* Comes with: proof,profileid,userid,uniquenick -- all same values
836 * (at least for me). */ 898 * (at least for me). */
837 /* Freed in msim_session_destroy */ 899 /* Freed in msim_session_destroy */
838 session->userid = msim_msg_get_string(msg, "userid"); 900 session->userid = msim_msg_get_string(msg, "userid");
839 901
840 purple_connection_set_state(gc, PURPLE_CONNECTED); 902 purple_connection_set_state(session->gc, PURPLE_CONNECTED);
841 903
842 return TRUE; 904 return TRUE;
843 } else if (msim_msg_get(msg, "bm")) { 905 } else if (msim_msg_get(msg, "bm")) {
844 guint bm; 906 guint bm;
845 907
978 } 1040 }
979 1041
980 return TRUE; 1042 return TRUE;
981 } 1043 }
982 1044
983 #if 0 1045 /**
984 /* Not sure about this */ 1046 * Process incoming status messages.
985 void msim_status_now(gchar *who, gpointer data) 1047 *
986 { 1048 * @param session
987 printf("msim_status_now: %s\n", who); 1049 * @param msg Status update message. Caller frees.
988 } 1050 *
989 #endif 1051 * @return TRUE if successful.
990 1052 */
991 /** 1053 gboolean msim_status(MsimSession *session, MsimMessage *msg)
992 * Callback to update incoming status messages, after looked up username. 1054 {
993 *
994 * @param session
995 * @param userinfo Looked up user information from server.
996 * @param data MsimMessage * The status message.
997 *
998 */
999 void msim_status_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
1000 {
1001 MsimMessage *msg;
1002 PurpleBuddyList *blist; 1055 PurpleBuddyList *blist;
1003 PurpleBuddy *buddy; 1056 PurpleBuddy *buddy;
1004 GHashTable *body;
1005 gchar *body_str;
1006 //PurpleStatus *status; 1057 //PurpleStatus *status;
1007 gchar **status_array; 1058 gchar **status_array;
1008 GList *list; 1059 GList *list;
1009 gchar *status_headline; 1060 gchar *status_headline;
1010 gchar *status_str; 1061 gchar *status_str;
1011 gint i, status_code, purple_status_code; 1062 gint i, status_code, purple_status_code;
1012 gchar *username; 1063 gchar *username;
1013 1064
1014 g_return_if_fail(MSIM_SESSION_VALID(session)); 1065 g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
1015 g_return_if_fail(userinfo != NULL); 1066 g_return_val_if_fail(msg != NULL, FALSE);
1016
1017 msg = (MsimMessage *)data;
1018 1067
1019 status_str = msim_msg_get_string(msg, "msg"); 1068 status_str = msim_msg_get_string(msg, "msg");
1020 1069 g_return_val_if_fail(status_str != NULL, FALSE);
1021 body_str = msim_msg_get_string(userinfo, "body"); 1070
1022 body = msim_parse_body(body_str); 1071 msim_msg_dump("msim_status msg=%s\n", msg);
1023 g_free(body_str); 1072
1024 g_return_if_fail(body != NULL); 1073 /* Helpfully looked up by msim_incoming_resolve() for us. */
1025 1074 username = msim_msg_get_string(msg, "_username");
1026 username = g_hash_table_lookup(body, "UserName");
1027 /* Note: DisplayName doesn't seem to be resolvable. It could be displayed on 1075 /* Note: DisplayName doesn't seem to be resolvable. It could be displayed on
1028 * the buddy list, if the UserID was stored along with it. */ 1076 * the buddy list, if the UserID was stored along with it. */
1029 1077
1030 g_return_if_fail(username != NULL); 1078 if (username == NULL)
1079 {
1080 g_free(status_str);
1081 g_return_val_if_fail(NULL, FALSE);
1082 }
1031 1083
1032 purple_debug_info("msim", 1084 purple_debug_info("msim",
1033 "msim_status_cb: updating status for <%s> to <%s>\n", 1085 "msim_status_cb: updating status for <%s> to <%s>\n",
1034 username, status_str); 1086 username, status_str);
1035 1087
1067 "msim_status: making new buddy for %s\n", username); 1119 "msim_status: making new buddy for %s\n", username);
1068 buddy = purple_buddy_new(session->account, username, NULL); 1120 buddy = purple_buddy_new(session->account, username, NULL);
1069 1121
1070 purple_blist_add_buddy(buddy, NULL, NULL, NULL); 1122 purple_blist_add_buddy(buddy, NULL, NULL, NULL);
1071 /* All buddies on list should have 'uid' integer associated with them. */ 1123 /* All buddies on list should have 'uid' integer associated with them. */
1072 purple_blist_node_set_int(&buddy->node, "uid", atoi(g_hash_table_lookup(body, "UserID"))); 1124 purple_blist_node_set_int(&buddy->node, "uid", msim_msg_get_integer(msg, "f"));
1073 purple_debug_info("msim", "UID=%d\n", purple_blist_node_get_int(&buddy->node, "uid")); 1125 purple_debug_info("msim", "UID=%d\n", purple_blist_node_get_int(&buddy->node, "uid"));
1074 } else { 1126 } else {
1075 purple_debug_info("msim", "msim_status: found buddy %s\n", username); 1127 purple_debug_info("msim", "msim_status: found buddy %s\n", username);
1076 } 1128 }
1077 1129
1091 } 1143 }
1092 purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL); 1144 purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL);
1093 1145
1094 g_strfreev(status_array); 1146 g_strfreev(status_array);
1095 g_free(status_str); 1147 g_free(status_str);
1148 g_free(username);
1096 g_list_free(list); 1149 g_list_free(list);
1097 g_hash_table_destroy(body);
1098 msim_msg_free(msg);
1099 }
1100
1101 /**
1102 * Process incoming status messages.
1103 *
1104 * @param session
1105 * @param msg Status update message.
1106 *
1107 * @return TRUE if successful.
1108 */
1109 gboolean msim_status(MsimSession *session, MsimMessage *msg)
1110 {
1111 gchar *userid;
1112
1113 g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
1114 g_return_val_if_fail(msg != NULL, FALSE);
1115
1116 /* TODO: free? */
1117 userid = msim_msg_get_string(msg, "f");
1118 g_return_val_if_fail(userid != NULL, FALSE);
1119
1120 /* TODO: if buddies were identified on buddy list by uid, wouldn't have to lookup
1121 * before updating the status! Much more efficient. */
1122 purple_debug_info("msim",
1123 "msim_status: got status for <%s>, scheduling lookup\n", userid);
1124
1125 /* Actually update status, once username is obtained.
1126 * status_str() will currently be freed by g_hash_table_destroy() on
1127 * user_lookup_cb_data (TODO: this is questionable, since it can also
1128 * store gpointers. Fix this, and the 2 other TODOs of the same problem.)
1129 */
1130 /* TODO: don't use callbacks */
1131 /* callback will free cloned msg */
1132 msim_lookup_user(session, userid, msim_status_cb, msim_msg_clone(msg));
1133 1150
1134 return TRUE; 1151 return TRUE;
1135 } 1152 }
1136 1153
1137 /** Add a buddy to user's buddy list. TODO: make work. Should receive statuses from added buddy. */ 1154 /** Add a buddy to user's buddy list. TODO: make work. Should receive statuses from added buddy. */
1223 * 1240 *
1224 * @param gc_uncasted A PurpleConnection pointer. 1241 * @param gc_uncasted A PurpleConnection pointer.
1225 * @param source File descriptor. 1242 * @param source File descriptor.
1226 * @param cond PURPLE_INPUT_READ 1243 * @param cond PURPLE_INPUT_READ
1227 * 1244 *
1228 * Reads the input, and dispatches msim_process() to handle it. 1245 * Reads the input, and calls msim_preprocess_incoming() to handle it.
1229 */ 1246 */
1230 void msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond) 1247 void msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond)
1231 { 1248 {
1232 PurpleConnection *gc; 1249 PurpleConnection *gc;
1233 PurpleAccount *account; 1250 PurpleAccount *account;
1327 } 1344 }
1328 else 1345 else
1329 { 1346 {
1330 /* Process message and then free it (processing function should 1347 /* Process message and then free it (processing function should
1331 * clone message if it wants to keep it afterwards.) */ 1348 * clone message if it wants to keep it afterwards.) */
1332 if (!msim_process(gc, msg)) 1349 if (!msim_preprocess_incoming(session, msg))
1333 { 1350 {
1334 msim_msg_dump("msim_input_cb: processing message failed on msg: %s\n", msg); 1351 msim_msg_dump("msim_input_cb: preprocessing message failed on msg: %s\n", msg);
1335 } 1352 }
1336 msim_msg_free(msg); 1353 msim_msg_free(msg);
1337 } 1354 }
1338 1355
1339 /* Move remaining part of buffer to beginning. */ 1356 /* Move remaining part of buffer to beginning. */

mercurial