diff libpurple/protocols/msn/contact.c @ 25396:06a802d32d71

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.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sun, 01 Feb 2009 08:04:41 +0000
parents 89670ae028bd
children 3e89d2c6bf93
line wrap: on
line diff
--- 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)