| 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; |
| 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; |