Mercurial > pidgin.yaz
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 { |