# HG changeset patch # User Jeffrey Connelly # Date 1180678172 0 # Node ID d3e17c9d16e98e2dff7cede14525f74a95495ac3 # Parent 3b226f9544a3a3c2887b280956cc2e9e33a9ef6c Use MsimMessage for receiving messages everywhere, instead of GHashTable. diff -r 3b226f9544a3 -r d3e17c9d16e9 libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Fri Jun 01 05:52:25 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.c Fri Jun 01 06:09:32 2007 +0000 @@ -265,33 +265,30 @@ * Process a login challenge, sending a response. * * @param session - * @param table Hash table of login challenge message. + * @param msg Login challenge message. * - * @return 0, since the 'table' parameter is no longer needed. + * @return 0, since the 'msg' parameter is no longer needed. */ -int msim_login_challenge(MsimSession *session, GHashTable *table) +int msim_login_challenge(MsimSession *session, MsimMessage *msg) { PurpleAccount *account; - gchar *nc_str; - guchar *nc; gchar *response; - gsize nc_len; guint response_len; + gchar *nc; + gsize nc_len; g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(table != NULL, 0); + g_return_val_if_fail(msg != NULL, 0); - nc_str = g_hash_table_lookup(table, "nc"); + g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), 0); account = session->account; //assert(account); purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4); - purple_debug_info("msim", "nc=<%s>\n", nc_str); + purple_debug_info("msim", "nc is %d bytes, decoded\n", nc_len); - nc = (guchar *)purple_base64_decode(nc_str, &nc_len); - purple_debug_info("msim", "base64 decoded to %d bytes\n", nc_len); if (nc_len != 0x40) { purple_debug_info("msim", "bad nc length: %x != 0x40\n", nc_len); @@ -438,7 +435,7 @@ * @return Binary login challenge response, ready to send to the server. Must be g_free()'d * when finished. */ -gchar *msim_compute_login_response(guchar nonce[2 * NONCE_SIZE], +gchar *msim_compute_login_response(gchar nonce[2 * NONCE_SIZE], gchar *email, gchar *password, guint *response_len) { PurpleCipherContext *key_context; @@ -491,7 +488,7 @@ sha1 = purple_ciphers_find_cipher("sha1"); key_context = purple_cipher_context_new(sha1, NULL); purple_cipher_context_append(key_context, hash_pw, HASH_SIZE); - purple_cipher_context_append(key_context, nonce + NONCE_SIZE, NONCE_SIZE); + purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); purple_cipher_context_digest(key_context, sizeof(key), key, NULL); #ifdef MSIM_DEBUG_LOGIN_CHALLENGE @@ -642,7 +639,7 @@ * @param message Text of message to send. * @param flags Purple instant message flags. * - * @return 0, since the 'table' parameter is no longer needed. + * @return 0 * */ int msim_send_im_by_userid(MsimSession *session, const gchar *userid, const gchar *message, PurpleMessageFlags flags) @@ -676,19 +673,23 @@ * @param session * @param userinfo User info message from server containing a 'body' field * with a 'UserID' key. This is where the user ID is taken from. + * Will be destroyed after use. * @param data A send_im_cb_struct * of information on the IM to send. * */ -void msim_send_im_by_userid_cb(MsimSession *session, GHashTable *userinfo, gpointer data) +void msim_send_im_by_userid_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) { send_im_cb_struct *s; gchar *userid; GHashTable *body; + gchar *body_str; g_return_if_fail(MSIM_SESSION_VALID(session)); g_return_if_fail(userinfo != NULL); - body = msim_parse_body(g_hash_table_lookup(userinfo, "body")); + body_str = msim_msg_get_string(userinfo, "body"); + body = msim_parse_body(body_str); + g_free(body_str); g_return_if_fail(body != NULL); userid = g_hash_table_lookup(body, "UserID"); @@ -697,7 +698,9 @@ msim_send_im_by_userid(session, userid, s->message, s->flags); g_hash_table_destroy(body); - g_hash_table_destroy(userinfo); + /* g_hash_table_destroy(userinfo); */ + /* TODO: do we need to free userinfo here? */ + msim_msg_free(userinfo); g_free(s->message); g_free(s->who); } @@ -709,16 +712,17 @@ * @param userinfo Message from server on user's info, containing UserName. * @param data A gchar * of the incoming instant message's text. */ -void msim_incoming_im_cb(MsimSession *session, GHashTable *userinfo, gpointer data) +void msim_incoming_im_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) { - gchar *msg; - gchar *username; + gchar *msg, *username, *body_str; GHashTable *body; g_return_if_fail(MSIM_SESSION_VALID(session)); g_return_if_fail(userinfo != NULL); - body = msim_parse_body(g_hash_table_lookup(userinfo, "body")); + body_str = msim_msg_get_string(userinfo, "body"); + body = msim_parse_body(body_str); + g_free(body); g_return_if_fail(body != NULL); username = g_hash_table_lookup(body, "UserName"); @@ -726,35 +730,35 @@ msg = (gchar *)data; serv_got_im(session->gc, username, msg, PURPLE_MESSAGE_RECV, time(NULL)); + msim_msg_free(userinfo); /* TODO: Should we? */ g_hash_table_destroy(body); - g_hash_table_destroy(userinfo); } /** * Handle an incoming message. * * @param session The session - * @param table Message from the server, containing 'f' (userid from) and 'msg'. + * @param msg Message from the server, containing 'f' (userid from) and 'msg'. * - * @return 0, since table can be freed. + * @return 0, since msg can be freed. */ -int msim_incoming_im(MsimSession *session, GHashTable *table) +int msim_incoming_im(MsimSession *session, MsimMessage *msg) { gchar *userid; - gchar *msg; + gchar *msg_text; g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(table != NULL, 0); - + g_return_val_if_fail(msg != NULL, 0); - userid = g_hash_table_lookup(table, "f"); - msg = g_hash_table_lookup(table, "msg"); + /* TODO: where freed? */ + userid = msim_msg_get_string(msg, "f"); + msg_text = msim_msg_get_string(msg, "msg"); purple_debug_info("msim", "msim_incoming_im: got msg <%s> from <%s>, resolving username\n", - msg, userid); + msg_text, userid); - msim_lookup_user(session, userid, msim_incoming_im_cb, g_strdup(msg)); + msim_lookup_user(session, userid, msim_incoming_im_cb, msg_text); return 0; } @@ -764,7 +768,7 @@ * Process a message. * * @param gc Connection. - * @param table Any message from the server. + * @param msg Any message from the server. * * @return The return value of the function used to process the message, or -1 if * called with invalid parameters. @@ -792,52 +796,52 @@ } #endif - /* TODO: convert to use MsimMessage. */ -#if 0 - if (g_hash_table_lookup(table, "nc")) + if (msim_msg_get(msg, "nc")) { - return msim_login_challenge(session, table); - } else if (g_hash_table_lookup(table, "sesskey")) { - purple_debug_info("msim", "SESSKEY=<%s>\n", (gchar *)g_hash_table_lookup(table, "sesskey")); + return msim_login_challenge(session, msg); + } else if (msim_msg_get(msg, "sesskey")) { purple_connection_update_progress(gc, _("Connected"), 3, 4); - session->sesskey = g_strdup(g_hash_table_lookup(table, "sesskey")); + /* Freed in msim_session_destroy */ + session->sesskey = msim_msg_get_string(msg, "sesskey"); + purple_debug_info("msim", "SESSKEY=<%s>\n", session->sesskey); /* Comes with: proof,profileid,userid,uniquenick -- all same values * (at least for me). */ - session->userid = g_strdup(g_hash_table_lookup(table, "userid")); + /* Freed in msim_session_destroy */ + session->userid = msim_msg_get_string(msg, "userid"); purple_connection_set_state(gc, PURPLE_CONNECTED); return 0; - } else if (g_hash_table_lookup(table, "bm")) { + } else if (msim_msg_get(msg, "bm")) { guint bm; - bm = atoi(g_hash_table_lookup(table, "bm")); + bm = msim_msg_get_integer(msg, "bm"); switch (bm) { case MSIM_BM_STATUS: - return msim_status(session, table); + return msim_status(session, msg); case MSIM_BM_INSTANT: - return msim_incoming_im(session, table); + return msim_incoming_im(session, msg); default: /* Not really an IM, but show it for informational * purposes during development. */ - return msim_incoming_im(session, table); + return msim_incoming_im(session, msg); } if (bm == MSIM_BM_STATUS) { - return msim_status(session, table); + return msim_status(session, msg); } else { /* else if strcmp(bm, "1") == 0) */ - return msim_incoming_im(session, table); + return msim_incoming_im(session, msg); } - } else if (g_hash_table_lookup(table, "rid")) { - return msim_process_reply(session, table); - } else if (g_hash_table_lookup(table, "error")) { - return msim_error(session, table); - } else if (g_hash_table_lookup(table, "ka")) { + } else if (msim_msg_get(msg, "rid")) { + return msim_process_reply(session, msg); + } else if (msim_msg_get(msg, "error")) { + return msim_error(session, msg); + } else if (msim_msg_get(msg, "ka")) { purple_debug_info("msim", "msim_process: got keep alive\n"); return 0; } else { @@ -847,38 +851,30 @@ purple_debug_info("msim", "msim_process: unhandled message\n"); return 0; } -#else - return 0; -#endif } /** * Process a message reply from the server. * * @param session - * @param table Message reply from server. + * @param msg Message reply from server. * - * @return 0, since the 'table' field is no longer needed. + * @return 0, since the 'msg' field is no longer needed. */ -int msim_process_reply(MsimSession *session, GHashTable *table) +int msim_process_reply(MsimSession *session, MsimMessage *msg) { - gchar *rid_str; - g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(table != NULL, 0); + g_return_val_if_fail(msg != NULL, 0); - rid_str = g_hash_table_lookup(table, "rid"); - - if (rid_str) /* msim_lookup_user sets callback for here */ + if (msim_msg_get(msg, "rid")) /* msim_lookup_user sets callback for here */ { MSIM_USER_LOOKUP_CB cb; gpointer data; guint rid; + GHashTable *body; + gchar *username, *body_str; - GHashTable *body; - gchar *username; - - rid = atol(rid_str); + rid = msim_msg_get_integer(msg, "rid"); /* Cache the user info. Currently, the GHashTable of user info in * this cache never expires so is never freed. TODO: expire and destroy @@ -886,19 +882,22 @@ * Some information never changes (username->userid map), some does. * TODO: Cache what doesn't change only */ - body = msim_parse_body(g_hash_table_lookup(table, "body")); + body_str = msim_msg_get_string(msg, "body"); + body = msim_parse_body(body_str); + g_free(body_str); + + /* TODO: implement a better hash-like interface, and use it. */ username = g_hash_table_lookup(body, "UserName"); if (username) { + /* TODO: permanently associated with blist item, if in buddy in blist */ g_hash_table_insert(session->user_lookup_cache, g_strdup(username), body); } else { purple_debug_info("msim", - "msim_process_reply: not caching <%s>, no UserName\n", - g_hash_table_lookup(table, "body")); + "msim_process_reply: not caching body, no UserName\n"); } /* If a callback is registered for this userid lookup, call it. */ - cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid)); data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); @@ -906,12 +905,12 @@ { purple_debug_info("msim", "msim_process_body: calling callback now\n"); - cb(session, table, data); + cb(session, msg, data); g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid)); g_hash_table_remove(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); /* Return 1 to tell caller of msim_process (msim_input_cb) to - * not destroy 'table'; allow 'cb' to hang on to it and destroy + * not destroy 'msg'; allow 'cb' to hang on to it and destroy * it when it wants. */ return 1; } else { @@ -926,21 +925,24 @@ * Handle an error from the server. * * @param session - * @param table The message. + * @param msg The message. * - * @return 0, since 'table' can be freed. + * @return 0, since 'msg' can be freed. */ -int msim_error(MsimSession *session, GHashTable *table) +int msim_error(MsimSession *session, MsimMessage *msg) { - gchar *err, *errmsg, *full_errmsg; + gchar *errmsg, *full_errmsg; + guint err; g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(table != NULL, 0); + g_return_val_if_fail(msg != NULL, 0); - err = g_hash_table_lookup(table, "err"); - errmsg = g_hash_table_lookup(table, "errmsg"); + err = msim_msg_get_integer(msg, "err"); + errmsg = msim_msg_get_string(msg, "errmsg"); - full_errmsg = g_strdup_printf(_("Protocol error, code %s: %s"), err, errmsg); + full_errmsg = g_strdup_printf(_("Protocol error, code %d: %s"), err, errmsg); + + g_free(errmsg); purple_debug_info("msim", "msim_error: %s\n", full_errmsg); @@ -949,7 +951,7 @@ purple_notify_error(session->account, g_strdup(_("MySpaceIM Error")), full_errmsg, NULL); - if (g_hash_table_lookup(table, "fatal")) + if (msim_msg_get(msg, "fatal")) { purple_debug_info("msim", "fatal error, destroy session\n"); purple_connection_error(session->gc, full_errmsg); @@ -973,15 +975,16 @@ * * @param session * @param userinfo Looked up user information from server. - * @param data gchar * status string. + * @param data gchar * status string, will be freed. * */ -void msim_status_cb(MsimSession *session, GHashTable *userinfo, gpointer data) +void msim_status_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) { PurpleBuddyList *blist; PurpleBuddy *buddy; PurplePresence *presence; GHashTable *body; + gchar *body_str; //PurpleStatus *status; gchar **status_array; GList *list; @@ -995,7 +998,9 @@ status_str = (gchar *)data; - body = msim_parse_body(g_hash_table_lookup(userinfo, "body")); + body_str = msim_msg_get_string(userinfo, "body"); + body = msim_parse_body(body_str); + g_free(body_str); g_return_if_fail(body != NULL); username = g_hash_table_lookup(body, "UserName"); @@ -1051,34 +1056,41 @@ g_strfreev(status_array); g_list_free(list); g_hash_table_destroy(body); - g_hash_table_destroy(userinfo); - /* Do not free status_str - it will be freed by g_hash_table_destroy on session->userid_lookup_cb_data */ + msim_msg_free(userinfo); /* TODO: right? */ + /* Do not free status_str - it will currently be freed by g_hash_table_destroy + * on session->user_lookup_cb_data. But this is questionable (TODO: unask) since + * sometimes user_lookup_cb_data stores integers in gpointers, and sometimes + * real gpointers that need to be freed, like our status_str. + */ + /* g_free(status_str); */ } /** * Process incoming status messages. * * @param session - * @param table Status update message. + * @param msg Status update message. * - * @return 0, since 'table' can be freed. + * @return 0, since 'msg' can be freed. */ -int msim_status(MsimSession *session, GHashTable *table) +int msim_status(MsimSession *session, MsimMessage *msg) { gchar *status_str; gchar *userid; g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(table != NULL, 0); + g_return_val_if_fail(msg != NULL, 0); - status_str = g_hash_table_lookup(table, "msg"); + /* TODO: free */ + status_str = msim_msg_get_string(msg, "msg"); if (!status_str) { purple_debug_info("msim", "msim_status: bm is status but no status msg\n"); return 0; } - userid = g_hash_table_lookup(table, "f"); + /* TODO: free */ + userid = msim_msg_get_string(msg, "f"); if (!userid) { purple_debug_info("msim", "msim_status: bm is status but no f field\n"); @@ -1091,8 +1103,12 @@ "msim_status: got status msg <%s> for <%s>, scheduling lookup\n", status_str, userid); - /* Actually update status once obtain username */ - msim_lookup_user(session, userid, msim_status_cb, g_strdup(status_str)); + /* Actually update status, once username is obtained. + * status_str() will currently be freed by g_hash_table_destroy() on + * user_lookup_cb_data (TODO: this is questionable, since it can also + * store gpointers. Fix this, and the 2 other TODOs of the same problem.) + */ + msim_lookup_user(session, userid, msim_status_cb, status_str); return 0; } @@ -1275,9 +1291,12 @@ session->gc = purple_account_get_connection(acct); session->fd = -1; session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, NULL); /* do NOT free function pointers! */ + g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */ session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, g_free); + g_direct_equal, NULL, g_free);/* TODO: we don't know what the values are, + they could be integers inside gpointers + or strings, but we free them anyway. + Figure this out, once free cache. */ session->user_lookup_cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy); session->rxoff = 0; diff -r 3b226f9544a3 -r d3e17c9d16e9 libpurple/protocols/myspace/myspace.h --- a/libpurple/protocols/myspace/myspace.h Fri Jun 01 05:52:25 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.h Fri Jun 01 06:09:32 2007 +0000 @@ -122,7 +122,7 @@ /* Callback function pointer type for when a user's information is received, * initiated from a user lookup. */ -typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, GHashTable *userinfo, +typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, MsimMessage *userinfo, gpointer data); /* Passed to MSIM_USER_LOOKUP_CB for msim_send_im_cb - called when @@ -147,13 +147,10 @@ void print_hash_item(gpointer key, gpointer value, gpointer user_data); gboolean msim_send_raw(MsimSession *session, const gchar *msg); -gchar *msim_pack(GHashTable *table); -gboolean msim_sendh(MsimSession *session, GHashTable *table); -gboolean msim_send(MsimSession *session, ...); void msim_login(PurpleAccount *acct); -int msim_login_challenge(MsimSession *session, GHashTable *table); -gchar *msim_compute_login_response(guchar nonce[2 * NONCE_SIZE], +int msim_login_challenge(MsimSession *session, MsimMessage *msg); +gchar *msim_compute_login_response(gchar nonce[2 * NONCE_SIZE], gchar *email, gchar *password, guint *response_len); int msim_send_im(PurpleConnection *gc, const char *who, @@ -161,18 +158,18 @@ int msim_send_im_by_userid(MsimSession *session, const gchar *userid, const gchar *message, PurpleMessageFlags flags); void msim_send_im_by_userid_cb(MsimSession *session, - GHashTable *userinfo, gpointer data); -void msim_incoming_im_cb(MsimSession *session, GHashTable *userinfo, + MsimMessage *userinfo, gpointer data); +void msim_incoming_im_cb(MsimSession *session, MsimMessage *userinfo, gpointer data); -int msim_incoming_im(MsimSession *session, GHashTable *table); +int msim_incoming_im(MsimSession *session, MsimMessage *msg); -int msim_process_reply(MsimSession *session, GHashTable *table); +int msim_process_reply(MsimSession *session, MsimMessage *msg); int msim_process(PurpleConnection *gc, MsimMessage *msg); -int msim_error(MsimSession *session, GHashTable *table); -void msim_status_cb(MsimSession *session, GHashTable *userinfo, +int msim_error(MsimSession *session, MsimMessage *msg); +void msim_status_cb(MsimSession *session, MsimMessage *userinfo, gpointer data); -int msim_status(MsimSession *session, GHashTable *table); +int msim_status(MsimSession *session, MsimMessage *msg); void msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond); void msim_connect_cb(gpointer data, gint source,