# HG changeset patch # User Jeffrey Connelly # Date 1180834139 0 # Node ID d8903e1320a9de3f2e3ea19601b7100867f7e800 # Parent aa8e70fa1edcc8e8ef2692facec898f3afe80f18 Previously, the return value of the processing function and msim_process() told msim_input_cb() whether to free the MsimMessage * or not, but now it is always freed. Functions can use msim_msg_clone() to keep a copy around if they need it. Message processing functions called from msim_process(), and msim_process() itself, now return TRUE if successful, FALSE if not successful. diff -r aa8e70fa1edc -r d8903e1320a9 libpurple/protocols/myspace/message.c --- a/libpurple/protocols/myspace/message.c Sat Jun 02 21:46:22 2007 +0000 +++ b/libpurple/protocols/myspace/message.c Sun Jun 03 01:28:59 2007 +0000 @@ -27,13 +27,82 @@ static gchar *msim_msg_pack_using(MsimMessage *msg, GFunc gf, gchar *sep, gchar *begin, gchar *end); static gchar *msim_msg_element_pack(MsimMessageElement *elem); +/** Create a new MsimMessage. */ MsimMessage *msim_msg_new(void) { /* Just an empty list. */ return NULL; } -/** Free an individual message element. */ +/** Clone an individual element. + * + * @param data MsimMessageElement * to clone. + * @param user_data Pointer to MsimMessage * to add cloned element to. + */ +static void msim_msg_clone_element(gpointer data, gpointer user_data) +{ + MsimMessageElement *elem; + MsimMessage **new; + gpointer new_data; + + elem = (MsimMessageElement *)data; + new = (MsimMessage **)user_data; + + switch (elem->type) + { + case MSIM_TYPE_BOOLEAN: + case MSIM_TYPE_INTEGER: + new_data = elem->data; + break; + + case MSIM_TYPE_RAW: + case MSIM_TYPE_STRING: + new_data = g_strdup((gchar *)elem->data); + break; + + case MSIM_TYPE_BINARY: + { + GString *gs; + + gs = (GString *)elem->data; + + new_data = g_string_new_len(gs->str, gs->len); + } + break; + /* TODO: other types */ + default: + purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type); + g_return_if_fail(NULL); + } + + /* Append cloned data. Note that the 'name' field is a static string, so it + * never needs to be copied nor freed. */ + *new = msim_msg_append(*new, elem->name, elem->type, new_data); +} + +/** Clone an existing MsimMessage. + * + * @return Cloned message; caller should free with msim_msg_free(). + */ +MsimMessage *msim_msg_clone(MsimMessage *old) +{ + MsimMessage *new; + + if (!old) + return NULL; + + new = msim_msg_new(); + + g_list_foreach(old, msim_msg_clone_element, &new); + + return new; +} + +/** Free an individual message element. + * + * @param data MsimMessageElement * to free. + * @param user_data Not used; required to match g_list_foreach() callback prototype. + */ static void msim_msg_free_element(gpointer data, gpointer user_data) { MsimMessageElement *elem; @@ -42,12 +111,12 @@ switch (elem->type) { - case MSIM_TYPE_BOOLEAN: /* Fall through */ + case MSIM_TYPE_BOOLEAN: case MSIM_TYPE_INTEGER: /* Integer value stored in gpointer - no need to free(). */ break; - case MSIM_TYPE_RAW: /* Fall through */ + case MSIM_TYPE_RAW: case MSIM_TYPE_STRING: /* Always free strings - caller should have g_strdup()'d if * string was static or temporary and not to be freed. */ diff -r aa8e70fa1edc -r d8903e1320a9 libpurple/protocols/myspace/message.h --- a/libpurple/protocols/myspace/message.h Sat Jun 02 21:46:22 2007 +0000 +++ b/libpurple/protocols/myspace/message.h Sun Jun 03 01:28:59 2007 +0000 @@ -45,6 +45,7 @@ #define MSIM_TYPE_LIST 'l' MsimMessage *msim_msg_new(void); +MsimMessage *msim_msg_clone(MsimMessage *old); void msim_msg_free(MsimMessage *msg); MsimMessage *msim_msg_append(MsimMessage *msg, gchar *name, MsimMessageType type, gpointer data); gchar *msim_msg_debug_string(MsimMessage *msg); diff -r aa8e70fa1edc -r d8903e1320a9 libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Sat Jun 02 21:46:22 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.c Sun Jun 03 01:28:59 2007 +0000 @@ -268,9 +268,9 @@ * @param session * @param msg Login challenge message. * - * @return 0, since the 'msg' parameter is no longer needed. + * @return TRUE if successful, FALSE if not */ -int msim_login_challenge(MsimSession *session, MsimMessage *msg) +gboolean msim_login_challenge(MsimSession *session, MsimMessage *msg) { PurpleAccount *account; gchar *response; @@ -278,13 +278,14 @@ gchar *nc; gsize nc_len; - g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(msg != NULL, 0); + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); - g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), 0); + g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), FALSE); account = session->account; - //assert(account); + + g_return_val_if_fail(account != NULL, FALSE); purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4); @@ -294,7 +295,7 @@ { purple_debug_info("msim", "bad nc length: %x != 0x40\n", nc_len); purple_connection_error(session->gc, _("Unexpected challenge length from server")); - return 0; + return FALSE; } purple_connection_update_progress(session->gc, _("Logging in"), 2, 4); @@ -303,7 +304,7 @@ g_free(nc); - msim_send(session, + return msim_send(session, "login2", MSIM_TYPE_INTEGER, MSIM_AUTH_ALGORITHM, "username", MSIM_TYPE_STRING, g_strdup(account->username), /* GString and gchar * response will be freed in msim_msg_free() in msim_send(). */ @@ -313,8 +314,6 @@ "status", MSIM_TYPE_INTEGER, 100, "id", MSIM_TYPE_INTEGER, 1, NULL); - - return 0; } #ifndef MSIM_USE_PURPLE_RC4 @@ -640,17 +639,17 @@ * @param message Text of message to send. * @param flags Purple instant message flags. * - * @return 0 + * @return TRUE if successful. * */ -int msim_send_im_by_userid(MsimSession *session, const gchar *userid, const gchar *message, PurpleMessageFlags flags) +gboolean msim_send_im_by_userid(MsimSession *session, const gchar *userid, const gchar *message, PurpleMessageFlags flags) { g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); g_return_val_if_fail(userid != NULL, 0); g_return_val_if_fail(msim_is_userid(userid) == TRUE, 0); g_return_val_if_fail(message != NULL, 0); - msim_send(session, + return msim_send(session, "bm", MSIM_TYPE_INTEGER, MSIM_BM_INSTANT, "sesskey", MSIM_TYPE_STRING, g_strdup(session->sesskey), "t", MSIM_TYPE_STRING, g_strdup(userid), @@ -662,8 +661,6 @@ /*if (strcmp(from_username, who) == 0) serv_got_im(gc, from_username, message, PURPLE_MESSAGE_RECV, time(NULL)); */ - - return 0; } @@ -741,15 +738,15 @@ * @param session The session * @param msg Message from the server, containing 'f' (userid from) and 'msg'. * - * @return 0, since msg can be freed. + * @return TRUE if successful. */ -int msim_incoming_im(MsimSession *session, MsimMessage *msg) +gboolean msim_incoming_im(MsimSession *session, MsimMessage *msg) { gchar *userid; gchar *msg_text; - g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(msg != NULL, 0); + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); /* TODO: where freed? */ userid = msim_msg_get_string(msg, "f"); @@ -761,7 +758,7 @@ msim_lookup_user(session, userid, msim_incoming_im_cb, msg_text); - return 0; + return TRUE; } /** @@ -770,16 +767,17 @@ * @param session * @param msg * - * @return 0 + * @return TRUE if successful. * * INCOMPLETE */ -int msim_incoming_action(MsimSession *session, MsimMessage *msg) +gboolean msim_incoming_action(MsimSession *session, MsimMessage *msg) { /* TODO: process */ purple_debug_info("msim", "msim_incoming_action: action <%s> from <%d>\n", msim_msg_get_string(msg, "msg"), msim_msg_get_integer(msg, "f")); - return 0; + + return FALSE; } /** @@ -819,10 +817,9 @@ * @param gc Connection. * @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. + * @return TRUE if successful. FALSE if processing failed. */ -int msim_process(PurpleConnection *gc, MsimMessage *msg) +gboolean msim_process(PurpleConnection *gc, MsimMessage *msg) { MsimSession *session; @@ -859,7 +856,7 @@ purple_connection_set_state(gc, PURPLE_CONNECTED); - return 0; + return TRUE; } else if (msim_msg_get(msg, "bm")) { guint bm; @@ -877,26 +874,19 @@ * purposes during development. */ return msim_incoming_im(session, msg); } - - if (bm == MSIM_BM_STATUS) - { - return msim_status(session, msg); - } else { /* else if strcmp(bm, "1") == 0) */ - return msim_incoming_im(session, msg); - } } 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; + return TRUE; } else { /* TODO: dump unknown msgs to file, so user can send them to me * if they wish, to help add support for new messages (inspired * by Alexandr Shutko, who maintains OSCAR protocol documentation). */ purple_debug_info("msim", "msim_process: unhandled message\n"); - return 0; + return FALSE; } } @@ -906,12 +896,12 @@ * @param session * @param msg Message reply from server. * - * @return 0, since the 'msg' field is no longer needed. + * @return TRUE if successful. */ -int msim_process_reply(MsimSession *session, MsimMessage *msg) +gboolean msim_process_reply(MsimSession *session, MsimMessage *msg) { - g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(msg != NULL, 0); + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); if (msim_msg_get(msg, "rid")) /* msim_lookup_user sets callback for here */ { @@ -953,20 +943,17 @@ { purple_debug_info("msim", "msim_process_body: calling callback now\n"); - cb(session, msg, data); + /* Clone message, so that the callback 'cb' can use it (needs to free it also). */ + cb(session, msim_msg_clone(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 'msg'; allow 'cb' to hang on to it and destroy - * it when it wants. */ - return 1; } else { purple_debug_info("msim", "msim_process_body: no callback for rid %d\n", rid); } } - return 0; + + return TRUE; } /** @@ -975,15 +962,15 @@ * @param session * @param msg The message. * - * @return 0, since 'msg' can be freed. + * @return TRUE if successfully reported error. */ -int msim_error(MsimSession *session, MsimMessage *msg) +gboolean msim_error(MsimSession *session, MsimMessage *msg) { gchar *errmsg, *full_errmsg; guint err; - g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); - g_return_val_if_fail(msg != NULL, 0); + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); err = msim_msg_get_integer(msg, "err"); errmsg = msim_msg_get_string(msg, "errmsg"); @@ -994,11 +981,11 @@ purple_debug_info("msim", "msim_error: %s\n", full_errmsg); - /* TODO: check 'fatal' and die if asked to. - * TODO: do something with the error # (localization of errmsg?) */ + /* TODO: do something with the error # (localization of errmsg?) */ purple_notify_error(session->account, g_strdup(_("MySpaceIM Error")), full_errmsg, NULL); + /* Destroy session if fatal. */ if (msim_msg_get(msg, "fatal")) { purple_debug_info("msim", "fatal error, destroy session\n"); @@ -1007,7 +994,7 @@ //msim_session_destroy(session); } - return 0; + return TRUE; } #if 0 @@ -1138,22 +1125,22 @@ * @param session * @param msg Status update message. * - * @return 0, since 'msg' can be freed. + * @return TRUE if successful. */ -int msim_status(MsimSession *session, MsimMessage *msg) +gboolean 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(msg != NULL, 0); + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); /* 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; + return FALSE; } /* TODO: free */ @@ -1161,7 +1148,7 @@ if (!userid) { purple_debug_info("msim", "msim_status: bm is status but no f field\n"); - return 0; + return FALSE; } /* TODO: if buddies were identified on buddy list by uid, wouldn't have to lookup @@ -1177,7 +1164,7 @@ */ msim_lookup_user(session, userid, msim_status_cb, status_str); - return 0; + return TRUE; } @@ -1291,9 +1278,18 @@ } else { - /* Process message. Returns 0 to free */ - if (msim_process(gc, msg) == 0) - msim_msg_free(msg); + /* Process message and then free it (processing function should + * clone message if it wants to keep it afterwards.) */ + if (!msim_process(gc, msg)) + { + gchar *dbs; + + dbs = msim_msg_debug_string(msg); + purple_debug_info("msim", "msim_input_cb: processing message failed on msg: %s\n", + dbs); + g_free(dbs); + } + msim_msg_free(msg); } /* Move remaining part of buffer to beginning. */ @@ -1498,7 +1494,7 @@ } - msim_send(session, + g_return_if_fail(msim_send(session, "persist", MSIM_TYPE_INTEGER, 1, "sesskey", MSIM_TYPE_STRING, g_strdup(session->sesskey), "cmd", MSIM_TYPE_INTEGER, 1, @@ -1508,7 +1504,7 @@ "rid", MSIM_TYPE_INTEGER, rid, /* TODO: dictionary field type */ "body", MSIM_TYPE_STRING, g_strdup_printf("%s=%s", field_name, user), - NULL); + NULL)); } @@ -1711,8 +1707,9 @@ msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v43")); msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v52/xxx\\yyy")); msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v7")); - purple_debug_info("msim", "msg=%s\n", msim_msg_debug_string(msg)); - purple_debug_info("msim", "msg=%s\n", msim_msg_pack(msg)); + purple_debug_info("msim", "msg debug str=%s\n", msim_msg_debug_string(msg)); + purple_debug_info("msim", "msg packed=%s\n", msim_msg_pack(msg)); + purple_debug_info("msim", "msg cloned=%s\n", msim_msg_pack(msim_msg_clone(msg))); msim_msg_free(msg); exit(0); } diff -r aa8e70fa1edc -r d8903e1320a9 libpurple/protocols/myspace/myspace.h --- a/libpurple/protocols/myspace/myspace.h Sat Jun 02 21:46:22 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.h Sun Jun 03 01:28:59 2007 +0000 @@ -159,7 +159,7 @@ gboolean msim_send_raw(MsimSession *session, const gchar *msg); void msim_login(PurpleAccount *acct); -int msim_login_challenge(MsimSession *session, MsimMessage *msg); +gboolean msim_login_challenge(MsimSession *session, MsimMessage *msg); gchar *msim_compute_login_response(gchar nonce[2 * NONCE_SIZE], gchar *email, gchar *password, guint *response_len); @@ -177,13 +177,13 @@ unsigned int msim_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state); -int msim_process_reply(MsimSession *session, MsimMessage *msg); -int msim_process(PurpleConnection *gc, MsimMessage *msg); +gboolean msim_process_reply(MsimSession *session, MsimMessage *msg); +gboolean msim_process(PurpleConnection *gc, MsimMessage *msg); -int msim_error(MsimSession *session, MsimMessage *msg); +gboolean msim_error(MsimSession *session, MsimMessage *msg); void msim_status_cb(MsimSession *session, MsimMessage *userinfo, gpointer data); -int msim_status(MsimSession *session, MsimMessage *msg); +gboolean 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,