# HG changeset patch # User Elliott Sales de Andrade # Date 1233475481 0 # Node ID 06a802d32d71ac8c56a0939e3241f93dea9ba362 # Parent 89670ae028bde8f506b4a95d6778a95b16461e53 I incorrectly assumed that the FindMembership and ABFindAll SOAP requests on MSN would not require token updates. However, these two requests may be made when it discovers that someone is requesting to be on your buddy list. Change these SOAP requests so that they will auto-update tokens. References #7921, only because I saw it in the log there, but probably doesn't fix it. diff -r 89670ae028bd -r 06a802d32d71 libpurple/protocols/msn/contact.c --- a/libpurple/protocols/msn/contact.c Sat Jan 31 07:37:11 2009 +0000 +++ b/libpurple/protocols/msn/contact.c Sun Feb 01 08:04:41 2009 +0000 @@ -158,6 +158,113 @@ state->action |= action; } +/*************************************************************** + * General SOAP handling + ***************************************************************/ + +static const char * +msn_contact_operation_str(MsnCallbackAction action) +{ + /* Make sure this is large enough when adding more */ + static char buf[BUF_LEN]; + buf[0] = '\0'; + + if (action & MSN_ADD_BUDDY) + strcat(buf, "Adding Buddy,"); + if (action & MSN_MOVE_BUDDY) + strcat(buf, "Moving Buddy,"); + if (action & MSN_ACCEPTED_BUDDY) + strcat(buf, "Accepted Buddy,"); + if (action & MSN_DENIED_BUDDY) + strcat(buf, "Denied Buddy,"); + if (action & MSN_ADD_GROUP) + strcat(buf, "Adding Group,"); + if (action & MSN_DEL_GROUP) + strcat(buf, "Deleting Group,"); + if (action & MSN_RENAME_GROUP) + strcat(buf, "Renaming Group,"); + if (action & MSN_UPDATE_INFO) + strcat(buf, "Updating Contact Info,"); + + return buf; +} + +static gboolean msn_contact_request(MsnCallbackState *state); + +static void +msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp, + gpointer data) +{ + MsnCallbackState *state = data; + xmlnode *fault; + char *faultcode_str; + + if (resp == NULL) { + purple_debug_error("msn", + "Operation {%s} failed. No response received from server.\n", + msn_contact_operation_str(state->action)); + return; + } + + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + + if (fault == NULL) { + /* No errors */ + if (state->cb) + ((MsnSoapCallback)state->cb)(req, resp, data); + msn_callback_state_free(state); + return; + } + + faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode")); + + if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) { + purple_debug_info("msn", + "Contact Operation {%s} failed because of bad token." + " Updating token now and retrying operation.\n", + msn_contact_operation_str(state->action)); + /* Token has expired, so renew it, and try again later */ + msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS, + (GSourceFunc)msn_contact_request, data); + } + else + { + if (state->cb) { + ((MsnSoapCallback)state->cb)(req, resp, data); + } else { + /* We don't know how to respond to this faultcode, so log it */ + char *str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), str); + g_free(str); + } + msn_callback_state_free(state); + } + + g_free(faultcode_str); +} + +static gboolean +msn_contact_request(MsnCallbackState *state) +{ + if (state->token == NULL) + state->token = xmlnode_get_child(state->body, + "Header/ABAuthHeader/TicketToken"); + /* delete old & replace with new token */ + xmlnode_free(state->token->child); + xmlnode_insert_data(state->token, + msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1); + msn_soap_message_send(state->session, + msn_soap_message_new(state->post_action, xmlnode_copy(state->body)), + MSN_CONTACT_SERVER, state->post_url, FALSE, + msn_contact_request_cb, state); + return FALSE; +} + +/*************************************************************** + * Address Book and Membership List Operations + ***************************************************************/ + /*get MSN member role utility*/ static MsnListId msn_get_memberrole(const char *role) @@ -180,9 +287,10 @@ static void msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { + MsnCallbackState *state = data; if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) { purple_debug_info("msn", "Address Book successfully created!\n"); - msn_get_address_book((MsnSession *)data, MSN_PS_INITIAL, NULL, NULL); + msn_get_address_book(state->session, MSN_PS_INITIAL, NULL, NULL); } else { purple_debug_info("msn", "Address Book creation failed!\n"); } @@ -192,7 +300,7 @@ msn_create_address_book(MsnSession *session) { gchar *body; - gchar *token_str; + MsnCallbackState *state; g_return_if_fail(session != NULL); g_return_if_fail(session->user != NULL); @@ -200,17 +308,15 @@ purple_debug_info("msn", "Creating an Address Book.\n"); - token_str = g_markup_escape_text( - msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1); body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE, - token_str, session->user->passport); - g_free(token_str); + session->user->passport); - msn_soap_message_send(session, - msn_soap_message_new(MSN_ADD_ADDRESSBOOK_SOAP_ACTION, - xmlnode_from_str(body, -1)), - MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, FALSE, - msn_create_address_cb, session); + state = msn_callback_state_new(session); + state->body = xmlnode_from_str(body, -1); + state->post_action = MSN_ADD_ADDRESSBOOK_SOAP_ACTION; + state->post_url = MSN_ADDRESS_BOOK_POST_URL; + state->cb = msn_create_address_cb; + msn_contact_request(state); g_free(body); } @@ -362,8 +468,8 @@ msn_get_contact_list_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { - GetContactListCbData *cb_data = data; - MsnSession *session = cb_data->session; + MsnCallbackState *state = data; + MsnSession *session = state->session; g_return_if_fail(session != NULL); @@ -379,7 +485,7 @@ dynamicItemLastChange = purple_account_get_string(session->account, "dynamicItemLastChange", NULL); - if (cb_data->which == MSN_PS_INITIAL) { + if (state->partner_scenario == MSN_PS_INITIAL) { #ifdef MSN_PARTIAL_LISTS /* XXX: this should be enabled when we can correctly do partial syncs with the server. Currently we need to retrieve the whole @@ -390,8 +496,6 @@ #endif } } - - g_free(cb_data); } /*SOAP get contact list*/ @@ -402,7 +506,7 @@ gchar *body = NULL; gchar *update_str = NULL; gchar *token_str; - GetContactListCbData cb_data = { session, partner_scenario }; + MsnCallbackState *state; const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario]; purple_debug_misc("msn", "Getting Contact List.\n"); @@ -412,17 +516,16 @@ update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML, update_time); } - token_str = g_markup_escape_text( - msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1); body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str, - token_str, update_str ? update_str : ""); - g_free(token_str); + update_str ? update_str : ""); - msn_soap_message_send(session, - msn_soap_message_new(MSN_GET_CONTACT_SOAP_ACTION, - xmlnode_from_str(body, -1)), - MSN_CONTACT_SERVER, MSN_GET_CONTACT_POST_URL, FALSE, - msn_get_contact_list_cb, g_memdup(&cb_data, sizeof(cb_data))); + state = msn_callback_state_new(session); + state->partner_scenario = partner_scenario; + state->body = xmlnode_from_str(body, -1); + state->post_action = MSN_GET_CONTACT_SOAP_ACTION; + state->post_url = MSN_GET_CONTACT_POST_URL; + state->cb = msn_get_contact_list_cb; + msn_contact_request(state); g_free(update_str); g_free(body); @@ -771,10 +874,8 @@ static void msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { - MsnSession *session = data; - - if (resp == NULL) - return; + MsnCallbackState *state = data; + MsnSession *session = state->session; g_return_if_fail(session != NULL); @@ -803,7 +904,7 @@ const char *dynamicItemLastChange) { char *body, *update_str = NULL; - gchar *token_str; + MsnCallbackState *state; purple_debug_misc("msn", "Getting Address Book\n"); @@ -813,19 +914,16 @@ else if (LastChanged != NULL) update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged); - token_str = g_markup_escape_text( - msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1); body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE, MsnSoapPartnerScenarioText[partner_scenario], - token_str, update_str ? update_str : ""); - g_free(token_str); - msn_soap_message_send(session, - msn_soap_message_new(MSN_GET_ADDRESS_SOAP_ACTION, - xmlnode_from_str(body, -1)), - MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, FALSE, - msn_get_address_cb, session); + state = msn_callback_state_new(session); + state->body = xmlnode_from_str(body, -1); + state->post_action = MSN_GET_ADDRESS_SOAP_ACTION; + state->post_url = MSN_ADDRESS_BOOK_POST_URL; + state->cb = msn_get_address_cb; + msn_contact_request(state); g_free(update_str); g_free(body); @@ -835,105 +933,6 @@ * Contact Operations ***************************************************************/ -static const char * -msn_contact_operation_str(MsnCallbackAction action) -{ - /* Make sure this is large enough when adding more */ - static char buf[BUF_LEN]; - buf[0] = '\0'; - - if (action & MSN_ADD_BUDDY) - strcat(buf, "Adding Buddy,"); - if (action & MSN_MOVE_BUDDY) - strcat(buf, "Moving Buddy,"); - if (action & MSN_ACCEPTED_BUDDY) - strcat(buf, "Accepted Buddy,"); - if (action & MSN_DENIED_BUDDY) - strcat(buf, "Denied Buddy,"); - if (action & MSN_ADD_GROUP) - strcat(buf, "Adding Group,"); - if (action & MSN_DEL_GROUP) - strcat(buf, "Deleting Group,"); - if (action & MSN_RENAME_GROUP) - strcat(buf, "Renaming Group,"); - if (action & MSN_UPDATE_INFO) - strcat(buf, "Updating Contact Info,"); - - return buf; -} - -static gboolean msn_contact_request(MsnCallbackState *state); - -static void -msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp, - gpointer data) -{ - MsnCallbackState *state = data; - xmlnode *fault; - char *faultcode_str; - - if (resp == NULL) { - purple_debug_error("msn", - "Operation {%s} failed. No response received from server.\n", - msn_contact_operation_str(state->action)); - return; - } - - fault = xmlnode_get_child(resp->xml, "Body/Fault"); - - if (fault == NULL) { - /* No errors */ - if (state->cb) - ((MsnSoapCallback)state->cb)(req, resp, data); - msn_callback_state_free(state); - return; - } - - faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode")); - - if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) { - purple_debug_info("msn", - "Contact Operation {%s} failed because of bad token." - " Updating token now and retrying operation.\n", - msn_contact_operation_str(state->action)); - /* Token has expired, so renew it, and try again later */ - msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS, - (GSourceFunc)msn_contact_request, data); - } - else - { - if (state->cb) { - ((MsnSoapCallback)state->cb)(req, resp, data); - } else { - /* We don't know how to respond to this faultcode, so log it */ - char *str = xmlnode_to_str(fault, NULL); - purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", - msn_contact_operation_str(state->action), str); - g_free(str); - } - msn_callback_state_free(state); - } - - g_free(faultcode_str); -} - -static gboolean -msn_contact_request(MsnCallbackState *state) -{ - if (state->token == NULL) - state->token = xmlnode_get_child(state->body, - "Header/ABAuthHeader/TicketToken"); - /* delete old & replace with new token */ - xmlnode_free(state->token->child); - xmlnode_insert_data(state->token, - msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1); - msn_soap_message_send(state->session, - msn_soap_message_new(state->post_action, xmlnode_copy(state->body)), - MSN_CONTACT_SERVER, state->post_url, FALSE, - msn_contact_request_cb, state); - return FALSE; -} - static void msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) diff -r 89670ae028bd -r 06a802d32d71 libpurple/protocols/msn/contact.h --- a/libpurple/protocols/msn/contact.h Sat Jan 31 07:37:11 2009 +0000 +++ b/libpurple/protocols/msn/contact.h Sun Feb 01 08:04:41 2009 +0000 @@ -52,7 +52,7 @@ ""\ ""\ "false"\ - "%s"\ + "EMPTY"\ ""\ ""\ ""\ @@ -94,7 +94,7 @@ ""\ ""\ "false"\ - "%s"\ + "EMPTY"\ ""\ ""\ ""\ @@ -135,7 +135,7 @@ ""\ ""\ "false"\ - "%s"\ + "EMPTY"\ ""\ ""\ ""\ @@ -619,6 +619,15 @@ MSN_UPDATE_INFO = 0x80 } MsnCallbackAction; +typedef enum +{ + MSN_PS_INITIAL, + MSN_PS_SAVE_CONTACT, + MSN_PS_PENDING_LIST, + MSN_PS_CONTACT_API, + MSN_PS_BLOCK_UNBLOCK +} MsnSoapPartnerScenario; + typedef struct _MsnCallbackState MsnCallbackState; struct _MsnCallbackState @@ -636,19 +645,12 @@ const gchar *post_action; const gchar *post_url; MsnSoapCallback cb; + /* For msn_get_contact_list only */ + MsnSoapPartnerScenario partner_scenario; }; typedef enum { - MSN_PS_INITIAL, - MSN_PS_SAVE_CONTACT, - MSN_PS_PENDING_LIST, - MSN_PS_CONTACT_API, - MSN_PS_BLOCK_UNBLOCK -} MsnSoapPartnerScenario; - -typedef enum -{ MSN_UPDATE_DISPLAY, /* Real display name */ MSN_UPDATE_ALIAS, /* Aliased display name */ MSN_UPDATE_COMMENT