comparison libpurple/protocols/msn/contact.c @ 25036: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
comparison
equal deleted inserted replaced
25035:89670ae028bd 25036:06a802d32d71
156 g_return_if_fail(state != NULL); 156 g_return_if_fail(state != NULL);
157 157
158 state->action |= action; 158 state->action |= action;
159 } 159 }
160 160
161 /***************************************************************
162 * General SOAP handling
163 ***************************************************************/
164
165 static const char *
166 msn_contact_operation_str(MsnCallbackAction action)
167 {
168 /* Make sure this is large enough when adding more */
169 static char buf[BUF_LEN];
170 buf[0] = '\0';
171
172 if (action & MSN_ADD_BUDDY)
173 strcat(buf, "Adding Buddy,");
174 if (action & MSN_MOVE_BUDDY)
175 strcat(buf, "Moving Buddy,");
176 if (action & MSN_ACCEPTED_BUDDY)
177 strcat(buf, "Accepted Buddy,");
178 if (action & MSN_DENIED_BUDDY)
179 strcat(buf, "Denied Buddy,");
180 if (action & MSN_ADD_GROUP)
181 strcat(buf, "Adding Group,");
182 if (action & MSN_DEL_GROUP)
183 strcat(buf, "Deleting Group,");
184 if (action & MSN_RENAME_GROUP)
185 strcat(buf, "Renaming Group,");
186 if (action & MSN_UPDATE_INFO)
187 strcat(buf, "Updating Contact Info,");
188
189 return buf;
190 }
191
192 static gboolean msn_contact_request(MsnCallbackState *state);
193
194 static void
195 msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
196 gpointer data)
197 {
198 MsnCallbackState *state = data;
199 xmlnode *fault;
200 char *faultcode_str;
201
202 if (resp == NULL) {
203 purple_debug_error("msn",
204 "Operation {%s} failed. No response received from server.\n",
205 msn_contact_operation_str(state->action));
206 return;
207 }
208
209 fault = xmlnode_get_child(resp->xml, "Body/Fault");
210
211 if (fault == NULL) {
212 /* No errors */
213 if (state->cb)
214 ((MsnSoapCallback)state->cb)(req, resp, data);
215 msn_callback_state_free(state);
216 return;
217 }
218
219 faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode"));
220
221 if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
222 purple_debug_info("msn",
223 "Contact Operation {%s} failed because of bad token."
224 " Updating token now and retrying operation.\n",
225 msn_contact_operation_str(state->action));
226 /* Token has expired, so renew it, and try again later */
227 msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS,
228 (GSourceFunc)msn_contact_request, data);
229 }
230 else
231 {
232 if (state->cb) {
233 ((MsnSoapCallback)state->cb)(req, resp, data);
234 } else {
235 /* We don't know how to respond to this faultcode, so log it */
236 char *str = xmlnode_to_str(fault, NULL);
237 purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
238 msn_contact_operation_str(state->action), str);
239 g_free(str);
240 }
241 msn_callback_state_free(state);
242 }
243
244 g_free(faultcode_str);
245 }
246
247 static gboolean
248 msn_contact_request(MsnCallbackState *state)
249 {
250 if (state->token == NULL)
251 state->token = xmlnode_get_child(state->body,
252 "Header/ABAuthHeader/TicketToken");
253 /* delete old & replace with new token */
254 xmlnode_free(state->token->child);
255 xmlnode_insert_data(state->token,
256 msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1);
257 msn_soap_message_send(state->session,
258 msn_soap_message_new(state->post_action, xmlnode_copy(state->body)),
259 MSN_CONTACT_SERVER, state->post_url, FALSE,
260 msn_contact_request_cb, state);
261 return FALSE;
262 }
263
264 /***************************************************************
265 * Address Book and Membership List Operations
266 ***************************************************************/
267
161 /*get MSN member role utility*/ 268 /*get MSN member role utility*/
162 static MsnListId 269 static MsnListId
163 msn_get_memberrole(const char *role) 270 msn_get_memberrole(const char *role)
164 { 271 {
165 g_return_val_if_fail(role != NULL, 0); 272 g_return_val_if_fail(role != NULL, 0);
178 285
179 /* Create the AddressBook in the server, if we don't have one */ 286 /* Create the AddressBook in the server, if we don't have one */
180 static void 287 static void
181 msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) 288 msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
182 { 289 {
290 MsnCallbackState *state = data;
183 if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) { 291 if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) {
184 purple_debug_info("msn", "Address Book successfully created!\n"); 292 purple_debug_info("msn", "Address Book successfully created!\n");
185 msn_get_address_book((MsnSession *)data, MSN_PS_INITIAL, NULL, NULL); 293 msn_get_address_book(state->session, MSN_PS_INITIAL, NULL, NULL);
186 } else { 294 } else {
187 purple_debug_info("msn", "Address Book creation failed!\n"); 295 purple_debug_info("msn", "Address Book creation failed!\n");
188 } 296 }
189 } 297 }
190 298
191 static void 299 static void
192 msn_create_address_book(MsnSession *session) 300 msn_create_address_book(MsnSession *session)
193 { 301 {
194 gchar *body; 302 gchar *body;
195 gchar *token_str; 303 MsnCallbackState *state;
196 304
197 g_return_if_fail(session != NULL); 305 g_return_if_fail(session != NULL);
198 g_return_if_fail(session->user != NULL); 306 g_return_if_fail(session->user != NULL);
199 g_return_if_fail(session->user->passport != NULL); 307 g_return_if_fail(session->user->passport != NULL);
200 308
201 purple_debug_info("msn", "Creating an Address Book.\n"); 309 purple_debug_info("msn", "Creating an Address Book.\n");
202 310
203 token_str = g_markup_escape_text(
204 msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1);
205 body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE, 311 body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE,
206 token_str, session->user->passport); 312 session->user->passport);
207 g_free(token_str); 313
208 314 state = msn_callback_state_new(session);
209 msn_soap_message_send(session, 315 state->body = xmlnode_from_str(body, -1);
210 msn_soap_message_new(MSN_ADD_ADDRESSBOOK_SOAP_ACTION, 316 state->post_action = MSN_ADD_ADDRESSBOOK_SOAP_ACTION;
211 xmlnode_from_str(body, -1)), 317 state->post_url = MSN_ADDRESS_BOOK_POST_URL;
212 MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, FALSE, 318 state->cb = msn_create_address_cb;
213 msn_create_address_cb, session); 319 msn_contact_request(state);
214 320
215 g_free(body); 321 g_free(body);
216 } 322 }
217 323
218 static void 324 static void
360 466
361 static void 467 static void
362 msn_get_contact_list_cb(MsnSoapMessage *req, MsnSoapMessage *resp, 468 msn_get_contact_list_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
363 gpointer data) 469 gpointer data)
364 { 470 {
365 GetContactListCbData *cb_data = data; 471 MsnCallbackState *state = data;
366 MsnSession *session = cb_data->session; 472 MsnSession *session = state->session;
367 473
368 g_return_if_fail(session != NULL); 474 g_return_if_fail(session != NULL);
369 475
370 if (resp != NULL) { 476 if (resp != NULL) {
371 const char *abLastChange; 477 const char *abLastChange;
377 abLastChange = purple_account_get_string(session->account, 483 abLastChange = purple_account_get_string(session->account,
378 "ablastChange", NULL); 484 "ablastChange", NULL);
379 dynamicItemLastChange = purple_account_get_string(session->account, 485 dynamicItemLastChange = purple_account_get_string(session->account,
380 "dynamicItemLastChange", NULL); 486 "dynamicItemLastChange", NULL);
381 487
382 if (cb_data->which == MSN_PS_INITIAL) { 488 if (state->partner_scenario == MSN_PS_INITIAL) {
383 #ifdef MSN_PARTIAL_LISTS 489 #ifdef MSN_PARTIAL_LISTS
384 /* XXX: this should be enabled when we can correctly do partial 490 /* XXX: this should be enabled when we can correctly do partial
385 syncs with the server. Currently we need to retrieve the whole 491 syncs with the server. Currently we need to retrieve the whole
386 list to detect sync issues */ 492 list to detect sync issues */
387 msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange); 493 msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange);
388 #else 494 #else
389 msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL); 495 msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL);
390 #endif 496 #endif
391 } 497 }
392 } 498 }
393
394 g_free(cb_data);
395 } 499 }
396 500
397 /*SOAP get contact list*/ 501 /*SOAP get contact list*/
398 void 502 void
399 msn_get_contact_list(MsnSession *session, 503 msn_get_contact_list(MsnSession *session,
400 const MsnSoapPartnerScenario partner_scenario, const char *update_time) 504 const MsnSoapPartnerScenario partner_scenario, const char *update_time)
401 { 505 {
402 gchar *body = NULL; 506 gchar *body = NULL;
403 gchar *update_str = NULL; 507 gchar *update_str = NULL;
404 gchar *token_str; 508 gchar *token_str;
405 GetContactListCbData cb_data = { session, partner_scenario }; 509 MsnCallbackState *state;
406 const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario]; 510 const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario];
407 511
408 purple_debug_misc("msn", "Getting Contact List.\n"); 512 purple_debug_misc("msn", "Getting Contact List.\n");
409 513
410 if (update_time != NULL) { 514 if (update_time != NULL) {
411 purple_debug_info("msn", "CL Last update time: %s\n", update_time); 515 purple_debug_info("msn", "CL Last update time: %s\n", update_time);
412 update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML, update_time); 516 update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML, update_time);
413 } 517 }
414 518
415 token_str = g_markup_escape_text(
416 msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1);
417 body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str, 519 body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str,
418 token_str, update_str ? update_str : ""); 520 update_str ? update_str : "");
419 g_free(token_str); 521
420 522 state = msn_callback_state_new(session);
421 msn_soap_message_send(session, 523 state->partner_scenario = partner_scenario;
422 msn_soap_message_new(MSN_GET_CONTACT_SOAP_ACTION, 524 state->body = xmlnode_from_str(body, -1);
423 xmlnode_from_str(body, -1)), 525 state->post_action = MSN_GET_CONTACT_SOAP_ACTION;
424 MSN_CONTACT_SERVER, MSN_GET_CONTACT_POST_URL, FALSE, 526 state->post_url = MSN_GET_CONTACT_POST_URL;
425 msn_get_contact_list_cb, g_memdup(&cb_data, sizeof(cb_data))); 527 state->cb = msn_get_contact_list_cb;
528 msn_contact_request(state);
426 529
427 g_free(update_str); 530 g_free(update_str);
428 g_free(body); 531 g_free(body);
429 } 532 }
430 533
769 } 872 }
770 873
771 static void 874 static void
772 msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) 875 msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
773 { 876 {
774 MsnSession *session = data; 877 MsnCallbackState *state = data;
775 878 MsnSession *session = state->session;
776 if (resp == NULL)
777 return;
778 879
779 g_return_if_fail(session != NULL); 880 g_return_if_fail(session != NULL);
780 881
781 purple_debug_misc("msn", "Got the Address Book!\n"); 882 purple_debug_misc("msn", "Got the Address Book!\n");
782 883
801 msn_get_address_book(MsnSession *session, 902 msn_get_address_book(MsnSession *session,
802 MsnSoapPartnerScenario partner_scenario, const char *LastChanged, 903 MsnSoapPartnerScenario partner_scenario, const char *LastChanged,
803 const char *dynamicItemLastChange) 904 const char *dynamicItemLastChange)
804 { 905 {
805 char *body, *update_str = NULL; 906 char *body, *update_str = NULL;
806 gchar *token_str; 907 MsnCallbackState *state;
807 908
808 purple_debug_misc("msn", "Getting Address Book\n"); 909 purple_debug_misc("msn", "Getting Address Book\n");
809 910
810 /*build SOAP and POST it*/ 911 /*build SOAP and POST it*/
811 if (dynamicItemLastChange != NULL) 912 if (dynamicItemLastChange != NULL)
812 update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, dynamicItemLastChange); 913 update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, dynamicItemLastChange);
813 else if (LastChanged != NULL) 914 else if (LastChanged != NULL)
814 update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged); 915 update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged);
815 916
816 token_str = g_markup_escape_text(
817 msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), -1);
818 body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE, 917 body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE,
819 MsnSoapPartnerScenarioText[partner_scenario], 918 MsnSoapPartnerScenarioText[partner_scenario],
820 token_str,
821 update_str ? update_str : ""); 919 update_str ? update_str : "");
822 g_free(token_str); 920
823 921 state = msn_callback_state_new(session);
824 msn_soap_message_send(session, 922 state->body = xmlnode_from_str(body, -1);
825 msn_soap_message_new(MSN_GET_ADDRESS_SOAP_ACTION, 923 state->post_action = MSN_GET_ADDRESS_SOAP_ACTION;
826 xmlnode_from_str(body, -1)), 924 state->post_url = MSN_ADDRESS_BOOK_POST_URL;
827 MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, FALSE, 925 state->cb = msn_get_address_cb;
828 msn_get_address_cb, session); 926 msn_contact_request(state);
829 927
830 g_free(update_str); 928 g_free(update_str);
831 g_free(body); 929 g_free(body);
832 } 930 }
833 931
834 /*************************************************************** 932 /***************************************************************
835 * Contact Operations 933 * Contact Operations
836 ***************************************************************/ 934 ***************************************************************/
837
838 static const char *
839 msn_contact_operation_str(MsnCallbackAction action)
840 {
841 /* Make sure this is large enough when adding more */
842 static char buf[BUF_LEN];
843 buf[0] = '\0';
844
845 if (action & MSN_ADD_BUDDY)
846 strcat(buf, "Adding Buddy,");
847 if (action & MSN_MOVE_BUDDY)
848 strcat(buf, "Moving Buddy,");
849 if (action & MSN_ACCEPTED_BUDDY)
850 strcat(buf, "Accepted Buddy,");
851 if (action & MSN_DENIED_BUDDY)
852 strcat(buf, "Denied Buddy,");
853 if (action & MSN_ADD_GROUP)
854 strcat(buf, "Adding Group,");
855 if (action & MSN_DEL_GROUP)
856 strcat(buf, "Deleting Group,");
857 if (action & MSN_RENAME_GROUP)
858 strcat(buf, "Renaming Group,");
859 if (action & MSN_UPDATE_INFO)
860 strcat(buf, "Updating Contact Info,");
861
862 return buf;
863 }
864
865 static gboolean msn_contact_request(MsnCallbackState *state);
866
867 static void
868 msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
869 gpointer data)
870 {
871 MsnCallbackState *state = data;
872 xmlnode *fault;
873 char *faultcode_str;
874
875 if (resp == NULL) {
876 purple_debug_error("msn",
877 "Operation {%s} failed. No response received from server.\n",
878 msn_contact_operation_str(state->action));
879 return;
880 }
881
882 fault = xmlnode_get_child(resp->xml, "Body/Fault");
883
884 if (fault == NULL) {
885 /* No errors */
886 if (state->cb)
887 ((MsnSoapCallback)state->cb)(req, resp, data);
888 msn_callback_state_free(state);
889 return;
890 }
891
892 faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode"));
893
894 if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
895 purple_debug_info("msn",
896 "Contact Operation {%s} failed because of bad token."
897 " Updating token now and retrying operation.\n",
898 msn_contact_operation_str(state->action));
899 /* Token has expired, so renew it, and try again later */
900 msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS,
901 (GSourceFunc)msn_contact_request, data);
902 }
903 else
904 {
905 if (state->cb) {
906 ((MsnSoapCallback)state->cb)(req, resp, data);
907 } else {
908 /* We don't know how to respond to this faultcode, so log it */
909 char *str = xmlnode_to_str(fault, NULL);
910 purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
911 msn_contact_operation_str(state->action), str);
912 g_free(str);
913 }
914 msn_callback_state_free(state);
915 }
916
917 g_free(faultcode_str);
918 }
919
920 static gboolean
921 msn_contact_request(MsnCallbackState *state)
922 {
923 if (state->token == NULL)
924 state->token = xmlnode_get_child(state->body,
925 "Header/ABAuthHeader/TicketToken");
926 /* delete old & replace with new token */
927 xmlnode_free(state->token->child);
928 xmlnode_insert_data(state->token,
929 msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1);
930 msn_soap_message_send(state->session,
931 msn_soap_message_new(state->post_action, xmlnode_copy(state->body)),
932 MSN_CONTACT_SERVER, state->post_url, FALSE,
933 msn_contact_request_cb, state);
934 return FALSE;
935 }
936 935
937 static void 936 static void
938 msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, 937 msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
939 gpointer data) 938 gpointer data)
940 { 939 {