Mercurial > pidgin
changeset 23464:1ac5faa72c8d
explicit merge of '9d90ebdb7e38fdd77bb504bc3302a083616360d9'
and '547cd65fb6e1faeb37d88730f0dbf45075a08426'
to branch 'im.pidgin.cpw.qulogic.msn'
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Sat, 07 Jun 2008 03:10:15 +0000 |
parents | 99b4470a763e (current diff) 06b491a23d19 (diff) |
children | 1d97298ccff5 |
files | libpurple/protocols/msn/contact.c libpurple/protocols/msn/contact.h libpurple/protocols/msn/msn.c libpurple/protocols/msn/msnutils.c libpurple/protocols/msn/notification.c libpurple/protocols/msn/notification.h libpurple/protocols/msn/oim.c libpurple/protocols/msn/soap.c libpurple/protocols/msn/userlist.c libpurple/protocols/zephyr/zephyr.h |
diffstat | 17 files changed, 1125 insertions(+), 570 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/protocols/msn/contact.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/contact.c Sat Jun 07 03:10:15 2008 +0000 @@ -1,5 +1,5 @@ /** - * @file contact.c + * @file contact.c * get MSN contacts via SOAP request * created by MaYuan<mayuan2006@gmail.com> * @@ -29,6 +29,7 @@ #include "xmlnode.h" #include "group.h" #include "soap2.h" +#include "nexus.h" const char *MsnSoapPartnerScenarioText[] = { @@ -49,29 +50,10 @@ }; typedef struct { - MsnContact *contact; + MsnSession *session; MsnSoapPartnerScenario which; } GetContactListCbData; -/* new a contact */ -MsnContact * -msn_contact_new(MsnSession *session) -{ - MsnContact *contact; - - contact = g_new0(MsnContact, 1); - contact->session = session; - - return contact; -} - -/* destroy the contact */ -void -msn_contact_destroy(MsnContact *contact) -{ - g_free(contact); -} - MsnCallbackState * msn_callback_state_new(MsnSession *session) { @@ -200,33 +182,34 @@ static void msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { - if (resp && msn_soap_xml_get(resp->xml, "Body/Fault") == NULL) { + if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) { purple_debug_info("msnab", "Address Book successfully created!\n"); - msn_get_address_book((MsnContact *)data, MSN_PS_INITIAL, NULL, NULL); + msn_get_address_book((MsnSession *)data, MSN_PS_INITIAL, NULL, NULL); } else { purple_debug_info("msnab", "Address Book creation failed!\n"); } } static void -msn_create_address_book(MsnContact * contact) +msn_create_address_book(MsnSession *session) { gchar *body; - g_return_if_fail(contact != NULL); - g_return_if_fail(contact->session != NULL); - g_return_if_fail(contact->session->user != NULL); - g_return_if_fail(contact->session->user->passport != NULL); - + g_return_if_fail(session != NULL); + g_return_if_fail(session->user != NULL); + g_return_if_fail(session->user->passport != NULL); + purple_debug_info("msnab","Creating an Address Book.\n"); - body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE, contact->session->user->passport); + body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + session->user->passport); - msn_soap_message_send(contact->session, + 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, msn_create_address_cb, - contact); + session); g_free(body); } @@ -259,7 +242,7 @@ { xmlnode *type; - if ((type = msn_soap_xml_get(service, "Info/Handle/Type"))) { + if ((type = xmlnode_get_child(service, "Info/Handle/Type"))) { char *type_str = xmlnode_get_data(type); if (g_str_equal(type_str, "Profile")) { @@ -273,7 +256,7 @@ purple_account_set_string(session->account, "CLLastChange", lastchange_str); - for (membership = msn_soap_xml_get(service, + for (membership = xmlnode_get_child(service, "Memberships/Membership"); membership; membership = xmlnode_get_next_twin(membership)) { @@ -285,7 +268,7 @@ purple_debug_info("msncl", "MemberRole role: %s, list: %d\n", role_str, list); - for (member = msn_soap_xml_get(membership, "Members/Member"); + for (member = xmlnode_get_child(membership, "Members/Member"); member; member = xmlnode_get_next_twin(member)) { const char *member_type = xmlnode_get_attrib(member, "type"); if (g_str_equal(member_type, "PassportMember")) { @@ -310,7 +293,7 @@ /*parse contact list*/ static void -msn_parse_contact_list(MsnContact *contact, xmlnode *node) +msn_parse_contact_list(MsnSession *session, xmlnode *node) { xmlnode *fault, *faultnode; @@ -321,18 +304,18 @@ * * this is not handled yet */ - if ((fault = msn_soap_xml_get(node, "Body/Fault"))) { + if ((fault = xmlnode_get_child(node, "Body/Fault"))) { if ((faultnode = xmlnode_get_child(fault, "faultstring"))) { char *faultstring = xmlnode_get_data(faultnode); purple_debug_info("msncl", "Retrieving contact list failed: %s\n", faultstring); g_free(faultstring); } - if ((faultnode = msn_soap_xml_get(fault, "detail/errorcode"))) { + if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) { char *errorcode = xmlnode_get_data(faultnode); if (g_str_equal(errorcode, "ABDoesNotExist")) { - msn_create_address_book(contact); + msn_create_address_book(session); g_free(errorcode); return; } @@ -340,14 +323,14 @@ g_free(errorcode); } - msn_get_contact_list(contact, MSN_PS_INITIAL, NULL); + msn_get_contact_list(session, MSN_PS_INITIAL, NULL); } else { xmlnode *service; - for (service = msn_soap_xml_get(node, "Body/FindMembershipResponse/" + for (service = xmlnode_get_child(node, "Body/FindMembershipResponse/" "FindMembershipResult/Services/Service"); service; service = xmlnode_get_next_twin(service)) { - msn_parse_each_service(contact->session, service); + msn_parse_each_service(session, service); } } } @@ -357,8 +340,7 @@ gpointer data) { GetContactListCbData *cb_data = data; - MsnContact *contact = cb_data->contact; - MsnSession *session = contact->session; + MsnSession *session = cb_data->session; g_return_if_fail(session != NULL); @@ -368,7 +350,7 @@ purple_debug_misc("msncl","Got the contact list!\n"); - msn_parse_contact_list(cb_data->contact, resp->xml); + msn_parse_contact_list(session, resp->xml); abLastChange = purple_account_get_string(session->account, "ablastChange", NULL); dynamicItemLastChange = purple_account_get_string(session->account, @@ -379,9 +361,9 @@ /* XXX: this should be enabled when we can correctly do partial syncs with the server. Currently we need to retrieve the whole list to detect sync issues */ - msn_get_address_book(contact, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange); + msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange); #else - msn_get_address_book(contact, MSN_PS_INITIAL, NULL, NULL); + msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL); #endif } } @@ -391,12 +373,12 @@ /*SOAP get contact list*/ void -msn_get_contact_list(MsnContact * contact, +msn_get_contact_list(MsnSession *session, const MsnSoapPartnerScenario partner_scenario, const char *update_time) { gchar *body = NULL; gchar *update_str = NULL; - GetContactListCbData cb_data = { contact, partner_scenario }; + GetContactListCbData cb_data = { session, partner_scenario }; const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario]; purple_debug_misc("MSNCL","Getting Contact List.\n"); @@ -406,9 +388,11 @@ update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML,update_time); } - body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str, update_str ? update_str : ""); + body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + update_str ? update_str : ""); - msn_soap_message_send(contact->session, + 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, @@ -419,9 +403,8 @@ } static void -msn_parse_addressbook_groups(MsnContact *contact, xmlnode *node) +msn_parse_addressbook_groups(MsnSession *session, xmlnode *node) { - MsnSession *session = contact->session; xmlnode *group; purple_debug_info("MSNAB","msn_parse_addressbook_groups()\n"); @@ -507,9 +490,8 @@ } static void -msn_parse_addressbook_contacts(MsnContact *contact, xmlnode *node) +msn_parse_addressbook_contacts(MsnSession *session, xmlnode *node) { - MsnSession *session = contact->session; xmlnode *contactNode; char *passport = NULL, *Name = NULL, *uid = NULL, *type = NULL, *mobile_number = NULL; gboolean mobile = FALSE; @@ -655,18 +637,15 @@ } static gboolean -msn_parse_addressbook(MsnContact * contact, xmlnode *node) +msn_parse_addressbook(MsnSession *session, xmlnode *node) { - MsnSession * session; xmlnode *result; xmlnode *groups; xmlnode *contacts; xmlnode *abNode; xmlnode *fault; - session = contact->session; - - if ((fault = msn_soap_xml_get(node, "Body/Fault"))) { + if ((fault = xmlnode_get_child(node, "Body/Fault"))) { xmlnode *faultnode; if ((faultnode = xmlnode_get_child(fault, "faultstring"))) { @@ -675,7 +654,7 @@ g_free(faultstring); } - if ((faultnode = msn_soap_xml_get(fault, "detail/errorcode"))) { + if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) { gchar *errorcode = xmlnode_get_data(faultnode); purple_debug_info("MSNAB", "Error Code: %s\n", errorcode); @@ -690,7 +669,7 @@ return FALSE; } - result = msn_soap_xml_get(node, "Body/ABFindAllResponse/ABFindAllResult"); + result = xmlnode_get_child(node, "Body/ABFindAllResponse/ABFindAllResult"); if(result == NULL){ purple_debug_misc("MSNAB","receive no address book update\n"); return TRUE; @@ -701,7 +680,7 @@ /*Process Group List*/ groups = xmlnode_get_child(result,"groups"); if (groups != NULL) { - msn_parse_addressbook_groups(contact, groups); + msn_parse_addressbook_groups(session, groups); } /*add a default No group to set up the no group Membership*/ @@ -726,7 +705,7 @@ purple_debug_info("MSNAB","process contact list...\n"); contacts =xmlnode_get_child(result,"contacts"); if (contacts != NULL) { - msn_parse_addressbook_contacts(contact, contacts); + msn_parse_addressbook_contacts(session, contacts); } abNode =xmlnode_get_child(result,"ab"); @@ -753,19 +732,16 @@ static void msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { - MsnContact *contact = data; - MsnSession *session; + MsnSession *session = data; if (resp == NULL) return; - g_return_if_fail(contact != NULL); - session = contact->session; g_return_if_fail(session != NULL); purple_debug_misc("MSNAB", "Got the Address Book!\n"); - if (msn_parse_addressbook(contact, resp->xml)) { + if (msn_parse_addressbook(session, resp->xml)) { if (!session->logged_in) { msn_send_privacy(session->account->gc); msn_notification_dump_contact(session); @@ -776,7 +752,7 @@ send timestamps) */ /* - msn_get_address_book(contact, NULL, NULL); + msn_get_address_book(session, NULL, NULL); */ msn_session_disconnect(session); purple_connection_error_reason(session->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to retrieve MSN Address Book")); @@ -785,7 +761,7 @@ /*get the address book*/ void -msn_get_address_book(MsnContact *contact, +msn_get_address_book(MsnSession *session, MsnSoapPartnerScenario partner_scenario, const char *LastChanged, const char *dynamicItemLastChange) { @@ -799,13 +775,16 @@ else if (LastChanged != NULL) update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged); - body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE, MsnSoapPartnerScenarioText[partner_scenario], update_str ? update_str : ""); + body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE, + MsnSoapPartnerScenarioText[partner_scenario], + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + update_str ? update_str : ""); - msn_soap_message_send(contact->session, + 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, msn_get_address_cb, - contact); + session); g_free(update_str); g_free(body); @@ -844,7 +823,7 @@ /* add a Contact in MSN_INDIVIDUALS_GROUP */ void -msn_add_contact(MsnContact *contact, MsnCallbackState *state, const char *passport) +msn_add_contact(MsnSession *session, MsnCallbackState *state, const char *passport) { gchar *body = NULL; gchar *contact_xml = NULL; @@ -864,9 +843,11 @@ purple_debug_info("MSNCL","Adding contact %s to contact list\n", passport); contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport); - body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE, contact_xml); + body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + contact_xml); - msn_soap_message_send(contact->session, + msn_soap_message_send(session, msn_soap_message_new(MSN_CONTACT_ADD_SOAP_ACTION, xmlnode_from_str(body, -1)), MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, @@ -906,14 +887,14 @@ msn_notification_send_fqy(state->session, state->who); if (msn_userlist_user_is_in_list(user, MSN_LIST_PL)) { - msn_del_contact_from_list(state->session->contact, NULL, state->who, MSN_LIST_PL); + msn_del_contact_from_list(state->session, NULL, state->who, MSN_LIST_PL); msn_callback_state_free(state); return; } } if (state->action & MSN_MOVE_BUDDY) { - msn_del_contact_from_group(state->session->contact, state->who, state->old_group_name); + msn_del_contact_from_group(state->session, state->who, state->old_group_name); } } @@ -921,7 +902,7 @@ } void -msn_add_contact_to_group(MsnContact *contact, MsnCallbackState *state, +msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state, const char *passport, const char *groupId) { MsnUserList *userlist; @@ -931,24 +912,22 @@ g_return_if_fail(passport != NULL); g_return_if_fail(groupId != NULL); - g_return_if_fail(contact != NULL); - g_return_if_fail(contact->session != NULL); - g_return_if_fail(contact->session->userlist != NULL); + g_return_if_fail(session != NULL); - userlist = contact->session->userlist; + userlist = session->userlist; if (!strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) { user = msn_userlist_find_add_user(userlist, passport, passport); if (state->action & MSN_ADD_BUDDY) { - msn_add_contact(contact, state, passport); + msn_add_contact(session, state, passport); return; } if (state->action & MSN_MOVE_BUDDY) { msn_user_add_group_id(user, groupId); - msn_del_contact_from_group(contact, passport, state->old_group_name); + msn_del_contact_from_group(session, passport, state->old_group_name); } else { msn_callback_state_free(state); } @@ -972,7 +951,9 @@ contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport); } - body = g_strdup_printf(MSN_ADD_CONTACT_GROUP_TEMPLATE, groupId, contact_xml); + body = g_strdup_printf(MSN_ADD_CONTACT_GROUP_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + groupId, contact_xml); msn_soap_message_send(state->session, msn_soap_message_new(MSN_ADD_CONTACT_GROUP_SOAP_ACTION, @@ -1006,7 +987,7 @@ /*delete a Contact*/ void -msn_delete_contact(MsnContact *contact, const char *contactId) +msn_delete_contact(MsnSession *session, const char *contactId) { gchar *body = NULL; gchar *contact_id_xml = NULL ; @@ -1015,13 +996,16 @@ g_return_if_fail(contactId != NULL); contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, contactId); - state = msn_callback_state_new(contact->session); + state = msn_callback_state_new(session); msn_callback_state_set_uid(state, contactId); /* build SOAP request */ purple_debug_info("MSNCL","Deleting contact with contactId: %s\n", contactId); - body = g_strdup_printf(MSN_DEL_CONTACT_TEMPLATE, contact_id_xml); - msn_soap_message_send(contact->session, + body = g_strdup_printf(MSN_DEL_CONTACT_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + contact_id_xml); + + msn_soap_message_send(session, msn_soap_message_new(MSN_CONTACT_DEL_SOAP_ACTION, xmlnode_from_str(body, -1)), MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, @@ -1050,7 +1034,7 @@ } void -msn_del_contact_from_group(MsnContact *contact, const char *passport, const char *group_name) +msn_del_contact_from_group(MsnSession *session, const char *passport, const char *group_name) { MsnUserList * userlist; MsnUser *user; @@ -1060,11 +1044,9 @@ g_return_if_fail(passport != NULL); g_return_if_fail(group_name != NULL); - g_return_if_fail(contact != NULL); - g_return_if_fail(contact->session != NULL); - g_return_if_fail(contact->session->userlist != NULL); + g_return_if_fail(session != NULL); - userlist = contact->session->userlist; + userlist = session->userlist; groupId = msn_userlist_find_group_id(userlist, group_name); if (groupId != NULL) { @@ -1086,15 +1068,17 @@ return; } - state = msn_callback_state_new(contact->session); + state = msn_callback_state_new(session); msn_callback_state_set_who(state, passport); msn_callback_state_set_guid(state, groupId); msn_callback_state_set_old_group_name(state, group_name); contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid); - body = g_strdup_printf(MSN_CONTACT_DEL_GROUP_TEMPLATE, contact_id_xml, groupId); + body = g_strdup_printf(MSN_CONTACT_DEL_GROUP_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + contact_id_xml, groupId); - msn_soap_message_send(contact->session, + msn_soap_message_send(session, msn_soap_message_new(MSN_CONTACT_DEL_GROUP_SOAP_ACTION, xmlnode_from_str(body, -1)), MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, @@ -1117,7 +1101,7 @@ /* Update a contact's nickname */ void -msn_update_contact(MsnContact *contact, const char* nickname) +msn_update_contact(MsnSession *session, const char* nickname) { gchar *body = NULL, *escaped_nickname; @@ -1125,9 +1109,11 @@ escaped_nickname = g_markup_escape_text(nickname, -1); - body = g_strdup_printf(MSN_CONTACT_UPDATE_TEMPLATE, escaped_nickname); + body = g_strdup_printf(MSN_CONTACT_UPDATE_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + escaped_nickname); - msn_soap_message_send(contact->session, + msn_soap_message_send(session, msn_soap_message_new(MSN_CONTACT_UPDATE_SOAP_ACTION, xmlnode_from_str(body, -1)), MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, @@ -1153,14 +1139,14 @@ if (user != NULL) msn_user_unset_op(user, MSN_LIST_PL_OP); - msn_add_contact_to_list(session->contact, state, state->who, MSN_LIST_RL); + msn_add_contact_to_list(session, state, state->who, MSN_LIST_RL); return; } else if (state->list_id == MSN_LIST_AL) { purple_privacy_permit_remove(session->account, state->who, TRUE); - msn_add_contact_to_list(session->contact, NULL, state->who, MSN_LIST_BL); + msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_BL); } else if (state->list_id == MSN_LIST_BL) { purple_privacy_deny_remove(session->account, state->who, TRUE); - msn_add_contact_to_list(session->contact, NULL, state->who, MSN_LIST_AL); + msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_AL); } } @@ -1168,46 +1154,45 @@ } void -msn_del_contact_from_list(MsnContact *contact, MsnCallbackState *state, +msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state, const gchar *passport, const MsnListId list) { gchar *body = NULL, *member = NULL; MsnSoapPartnerScenario partner_scenario; MsnUser *user; - g_return_if_fail(contact != NULL); + g_return_if_fail(session != NULL); g_return_if_fail(passport != NULL); g_return_if_fail(list < 5); purple_debug_info("MSN CL", "Deleting contact %s from %s list\n", passport, MsnMemberRole[list]); if (state == NULL) { - state = msn_callback_state_new(contact->session); + state = msn_callback_state_new(session); } msn_callback_state_set_list_id(state, list); msn_callback_state_set_who(state, passport); if (list == MSN_LIST_PL) { - g_return_if_fail(contact->session != NULL); - g_return_if_fail(contact->session->userlist != NULL); + g_return_if_fail(session->userlist != NULL); - user = msn_userlist_find_user(contact->session->userlist, passport); + user = msn_userlist_find_user(session->userlist, passport); partner_scenario = MSN_PS_CONTACT_API; member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML, user->membership_id[MSN_LIST_PL]); } else { /* list == MSN_LIST_AL || list == MSN_LIST_BL */ partner_scenario = MSN_PS_BLOCK_UNBLOCK; - + member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML, passport); } body = g_strdup_printf( MSN_CONTACT_DELECT_FROM_LIST_TEMPLATE, - MsnSoapPartnerScenarioText[partner_scenario], - MsnMemberRole[list], - member); + MsnSoapPartnerScenarioText[partner_scenario], + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + MsnMemberRole[list], member); - msn_soap_message_send(contact->session, + msn_soap_message_send(session, msn_soap_message_new(MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION, xmlnode_from_str(body, -1)), MSN_CONTACT_SERVER, MSN_SHARE_POST_URL, @@ -1225,7 +1210,6 @@ g_return_if_fail(state != NULL); g_return_if_fail(state->session != NULL); - g_return_if_fail(state->session->contact != NULL); if (resp != NULL) { purple_debug_info("MSN CL", "Contact %s added successfully to %s list on server!\n", state->who, MsnMemberRole[state->list_id]); @@ -1239,7 +1223,7 @@ if (state->action & MSN_DENIED_BUDDY) { - msn_add_contact_to_list(state->session->contact, NULL, state->who, MSN_LIST_BL); + msn_add_contact_to_list(state->session, NULL, state->who, MSN_LIST_BL); } else if (state->list_id == MSN_LIST_AL) { purple_privacy_permit_add(state->session->account, state->who, TRUE); } else if (state->list_id == MSN_LIST_BL) { @@ -1252,20 +1236,20 @@ } void -msn_add_contact_to_list(MsnContact *contact, MsnCallbackState *state, +msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state, const gchar *passport, const MsnListId list) { gchar *body = NULL, *member = NULL; MsnSoapPartnerScenario partner_scenario; - g_return_if_fail(contact != NULL); + g_return_if_fail(session != NULL); g_return_if_fail(passport != NULL); g_return_if_fail(list < 5); purple_debug_info("MSN CL", "Adding contact %s to %s list\n", passport, MsnMemberRole[list]); if (state == NULL) { - state = msn_callback_state_new(contact->session); + state = msn_callback_state_new(session); } msn_callback_state_set_list_id(state, list); msn_callback_state_set_who(state, passport); @@ -1275,11 +1259,11 @@ member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML, state->who); body = g_strdup_printf(MSN_CONTACT_ADD_TO_LIST_TEMPLATE, - MsnSoapPartnerScenarioText[partner_scenario], - MsnMemberRole[list], - member); + MsnSoapPartnerScenarioText[partner_scenario], + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + MsnMemberRole[list], member); - msn_soap_message_send(contact->session, + msn_soap_message_send(session, msn_soap_message_new(MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION, xmlnode_from_str(body, -1)), MSN_CONTACT_SERVER, MSN_SHARE_POST_URL, @@ -1301,16 +1285,22 @@ /*get the gleams info*/ void -msn_get_gleams(MsnContact *contact) +msn_get_gleams(MsnSession *session) { MsnSoapReq *soap_request; + gchar *body = NULL; purple_debug_info("MSNP14","msn get gleams info...\n"); - msn_soap_message_send(contact->session, + + body = g_strdup_printf(MSN_GLEAMS_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS)); + + msn_soap_message_send(session, msn_soap_message_new(MSN_GET_GLEAMS_SOAP_ACTION, - xmlnode_from_str(MSN_GLEAMS_TEMPLATE, -1)), + xmlnode_from_str(body, -1)), MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, msn_gleams_read_cb, NULL); + g_free(body); } #endif @@ -1328,7 +1318,6 @@ g_return_if_fail(state->session != NULL); g_return_if_fail(state->session->userlist != NULL); - g_return_if_fail(state->session->contact != NULL); if (resp == NULL) { msn_callback_state_free(state); @@ -1349,7 +1338,7 @@ /* the response is taken from http://telepathy.freedesktop.org/wiki/Pymsn/MSNP/ContactListActions should copy it to msnpiki some day */ - xmlnode *guid_node = msn_soap_xml_get(resp->xml, + xmlnode *guid_node = xmlnode_get_child(resp->xml, "Body/ABGroupAddResponse/ABGroupAddResult/guid"); if (guid_node) { @@ -1364,7 +1353,7 @@ state->who, state->new_group_name); } else if (state->action & MSN_MOVE_BUDDY) { - msn_add_contact_to_group(session->contact, state, state->who, guid); + msn_add_contact_to_group(session, state, state->who, guid); g_free(guid); return; } @@ -1393,6 +1382,7 @@ msn_add_group(MsnSession *session, MsnCallbackState *state, const char* group_name) { char *body = NULL; + char *escaped_group_name = NULL; g_return_if_fail(session != NULL); g_return_if_fail(group_name != NULL); @@ -1409,7 +1399,10 @@ /* escape group name's html special chars so it can safely be sent * in a XML SOAP request */ - body = g_markup_printf_escaped(MSN_GROUP_ADD_TEMPLATE, group_name); + escaped_group_name = g_markup_escape_text(group_name, -1); + body = g_strdup_printf(MSN_GROUP_ADD_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + escaped_group_name); msn_soap_message_send(session, msn_soap_message_new(MSN_GROUP_ADD_SOAP_ACTION, @@ -1417,6 +1410,7 @@ MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, msn_group_read_cb, state); + g_free(escaped_group_name); g_free(body); } @@ -1452,7 +1446,9 @@ msn_callback_state_set_action(state, MSN_DEL_GROUP); msn_callback_state_set_guid(state, guid); - body = g_strdup_printf(MSN_GROUP_DEL_TEMPLATE, guid); + body = g_strdup_printf(MSN_GROUP_DEL_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + guid); msn_soap_message_send(session, msn_soap_message_new(MSN_GROUP_DEL_SOAP_ACTION, @@ -1470,6 +1466,7 @@ gchar *body = NULL; const gchar * guid; MsnCallbackState *state; + char *escaped_group_name; g_return_if_fail(session != NULL); g_return_if_fail(session->userlist != NULL); @@ -1493,8 +1490,10 @@ msn_callback_state_set_action(state, MSN_RENAME_GROUP); - body = g_markup_printf_escaped(MSN_GROUP_RENAME_TEMPLATE, - guid, new_group_name); + escaped_group_name = g_markup_escape_text(new_group_name, -1); + body = g_strdup_printf(MSN_GROUP_RENAME_TEMPLATE, + msn_nexus_get_token_str(session->nexus, MSN_AUTH_CONTACTS), + guid, escaped_group_name); msn_soap_message_send(session, msn_soap_message_new(MSN_GROUP_RENAME_SOAP_ACTION, @@ -1502,5 +1501,6 @@ MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, msn_group_read_cb, state); + g_free(escaped_group_name); g_free(body); }
--- a/libpurple/protocols/msn/contact.h Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/contact.h Sat Jun 07 03:10:15 2008 +0000 @@ -25,15 +25,20 @@ #ifndef _MSN_CONTACT_H_ #define _MSN_CONTACT_H_ +#include "session.h" + #define MSN_CONTACT_SERVER "contacts.msn.com" /* Get Contact List */ #define MSN_GET_CONTACT_POST_URL "/abservice/SharingService.asmx" #define MSN_GET_CONTACT_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership" -#define MSN_GET_CONTACT_UPDATE_XML "<View>Full</View>"\ + +#define MSN_GET_CONTACT_UPDATE_XML \ + "<View>Full</View>"\ "<deltasOnly>true</deltasOnly>"\ "<lastChange>%s</lastChange>" + #define MSN_GET_CONTACT_TEMPLATE "<?xml version='1.0' encoding='utf-8'?>"\ "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ @@ -44,6 +49,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ @@ -72,7 +78,11 @@ #define MSN_ADD_ADDRESSBOOK_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABAdd" #define MSN_ADD_ADDRESSBOOK_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ "<soap:Header>"\ "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ @@ -81,6 +91,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -98,7 +109,8 @@ /* Get AddressBook */ #define MSN_GET_ADDRESS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll" #define MSN_GET_ADDRESS_FULL_TIME "0001-01-01T00:00:00.0000000-08:00" -#define MSN_GET_ADDRESS_UPDATE_XML "<deltasOnly>true</deltasOnly>"\ +#define MSN_GET_ADDRESS_UPDATE_XML \ + "<deltasOnly>true</deltasOnly>"\ "<lastChange>%s</lastChange>" #define MSN_GET_GLEAM_UPDATE_XML \ @@ -107,7 +119,11 @@ "<dynamicItemLastChange>%s</dynamicItemLastChange>" #define MSN_GET_ADDRESS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ "<soap:Header>"\ "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ @@ -116,6 +132,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -131,7 +148,11 @@ /*Gleams SOAP request template*/ #define MSN_GET_GLEAMS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll" #define MSN_GLEAMS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ "<soap:Header>"\ "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ @@ -140,6 +161,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -157,26 +179,40 @@ * Contact Management SOAP actions *******************************************************/ -/* Add a new contact t*/ +/* Add a new contact */ #define MSN_CONTACT_ADD_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactAdd" -#define MSN_CONTACT_LIVE_PENDING_XML "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\"><contactInfo><contactType>LivePending</contactType><passportName>%s</passportName><isMessengerUser>true</isMessengerUser></contactInfo></Contact>" +#define MSN_CONTACT_LIVE_PENDING_XML \ + "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<contactInfo>"\ + "<contactType>LivePending</contactType>"\ + "<passportName>%s</passportName>"\ + "<isMessengerUser>true</isMessengerUser>"\ + "</contactInfo>"\ + "</Contact>" -#define MSN_CONTACT_XML "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ - "<contactInfo>"\ - "<passportName>%s</passportName>"\ - "<isSmtp>false</isSmtp>"\ - "<isMessengerUser>true</isMessengerUser>"\ - "</contactInfo>"\ - "</Contact>" +#define MSN_CONTACT_XML \ + "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<contactInfo>"\ + "<passportName>%s</passportName>"\ + "<isSmtp>false</isSmtp>"\ + "<isMessengerUser>true</isMessengerUser>"\ + "</contactInfo>"\ + "</Contact>" -#define MSN_CONTACT_DISPLAYNAME_XML "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\"><contactInfo><displayName>%s</displayName><passportName>%s</passportName><isMessengerUser>true</isMessengerUser></contactInfo></Contact>" - -#define MSN_ADD_CONTACT_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>ContactSave</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><contacts>%s</contacts><options><EnableAllowListManagement>true</EnableAllowListManagement></options></ABContactAdd></soap:Body></soap:Envelope>" +#define MSN_CONTACT_DISPLAYNAME_XML \ + "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<contactInfo>"\ + "<displayName>%s</displayName>"\ + "<passportName>%s</passportName>"\ + "<isMessengerUser>true</isMessengerUser>"\ + "</contactInfo>"\ + "</Contact>" -/* Add a contact to a group */ -#define MSN_ADD_CONTACT_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactAdd" -#define MSN_ADD_CONTACT_GROUP_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ +#define MSN_ADD_CONTACT_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ "<soap:Header>"\ "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ @@ -185,6 +221,36 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ + "</ABAuthHeader>"\ + "</soap:Header>"\ + "<soap:Body>"\ + "<ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<abId>00000000-0000-0000-0000-000000000000</abId>"\ + "<contacts>%s</contacts>"\ + "<options>"\ + "<EnableAllowListManagement>true</EnableAllowListManagement>"\ + "</options>"\ + "</ABContactAdd>"\ + "</soap:Body>"\ +"</soap:Envelope>" + +/* Add a contact to a group */ +#define MSN_ADD_CONTACT_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactAdd" +#define MSN_ADD_CONTACT_GROUP_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ + "<soap:Header>"\ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ + "<IsMigration>false</IsMigration>"\ + "<PartnerScenario>ContactSave</PartnerScenario>"\ + "</ABApplicationHeader>"\ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -207,17 +273,12 @@ /* Delete a contact from the Contact List */ #define MSN_CONTACT_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactDelete" #define MSN_CONTACT_ID_XML "<Contact><contactId>%s</contactId></Contact>" -#define MSN_DEL_CONTACT_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>Timer</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><contacts>%s</contacts></ABContactDelete></soap:Body></soap:Envelope>" - -/* Remove a contact from a group */ -#define MSN_CONTACT_DEL_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactDelete" -#define MSN_CONTACT_DEL_GROUP_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>Timer</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABGroupContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><contacts>%s</contacts><groupFilter><groupIds><guid>%s</guid></groupIds></groupFilter></ABGroupContactDelete></soap:Body></soap:Envelope>" - - -/* Update Contact Nickname */ -#define MSN_CONTACT_UPDATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" -#define MSN_CONTACT_UPDATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ +#define MSN_DEL_CONTACT_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ "<soap:Header>"\ "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ @@ -226,6 +287,67 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ + "</ABAuthHeader>"\ + "</soap:Header>"\ + "<soap:Body>"\ + "<ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<abId>00000000-0000-0000-0000-000000000000</abId>"\ + "<contacts>%s</contacts>"\ + "</ABContactDelete>"\ + "</soap:Body>"\ +"</soap:Envelope>" + +/* Remove a contact from a group */ +#define MSN_CONTACT_DEL_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactDelete" +#define MSN_CONTACT_DEL_GROUP_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ + "<soap:Header>"\ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ + "<IsMigration>false</IsMigration>"\ + "<PartnerScenario>Timer</PartnerScenario>"\ + "</ABApplicationHeader>"\ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ + "</ABAuthHeader>"\ + "</soap:Header>"\ + "<soap:Body>"\ + "<ABGroupContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<abId>00000000-0000-0000-0000-000000000000</abId>"\ + "<contacts>%s</contacts>"\ + "<groupFilter>"\ + "<groupIds>"\ + "<guid>%s</guid>"\ + "</groupIds>"\ + "</groupFilter>"\ + "</ABGroupContactDelete>"\ + "</soap:Body>"\ +"</soap:Envelope>" + + +/* Update Contact Nickname */ +#define MSN_CONTACT_UPDATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" +#define MSN_CONTACT_UPDATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ + "<soap:Header>"\ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ + "<IsMigration>false</IsMigration>"\ + "<PartnerScenario>Timer</PartnerScenario>"\ + "</ABApplicationHeader>"\ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -255,22 +377,28 @@ #define MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/AddMember" #define MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/DeleteMember" -#define MSN_MEMBER_PASSPORT_XML "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"PassportMember\">"\ - "<Type>Passport</Type>"\ - "<State>Accepted</State>"\ - "<PassportName>%s</PassportName>"\ - "</Member>" +#define MSN_MEMBER_PASSPORT_XML \ + "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"PassportMember\">"\ + "<Type>Passport</Type>"\ + "<State>Accepted</State>"\ + "<PassportName>%s</PassportName>"\ + "</Member>" -#define MSN_MEMBER_MEMBERSHIPID_XML "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"PassportMember\">"\ - "<Type>Passport</Type>"\ - "<MembershipId>%u</MembershipId>"\ - "<State>Accepted</State>"\ - "</Member>" +#define MSN_MEMBER_MEMBERSHIPID_XML \ + "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"PassportMember\">"\ + "<Type>Passport</Type>"\ + "<MembershipId>%u</MembershipId>"\ + "<State>Accepted</State>"\ + "</Member>" /* first delete contact from allow list */ #define MSN_CONTACT_DELECT_FROM_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ "<soap:Header>"\ "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ @@ -279,6 +407,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -301,7 +430,11 @@ "</soap:Envelope>" #define MSN_CONTACT_ADD_TO_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ "<soap:Header>"\ "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ @@ -310,6 +443,7 @@ "</ABApplicationHeader>"\ "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ "</ABAuthHeader>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -339,15 +473,111 @@ /* add a group */ #define MSN_GROUP_ADD_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupAdd" -#define MSN_GROUP_ADD_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>GroupSave</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABGroupAdd xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><groupAddOptions><fRenameOnMsgrConflict>false</fRenameOnMsgrConflict></groupAddOptions><groupInfo><GroupInfo><name>%s</name><groupType>C8529CE2-6EAD-434d-881F-341E17DB3FF8</groupType><fMessenger>false</fMessenger><annotations><Annotation><Name>MSN.IM.Display</Name><Value>1</Value></Annotation></annotations></GroupInfo></groupInfo></ABGroupAdd></soap:Body></soap:Envelope>" +#define MSN_GROUP_ADD_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ + "<soap:Header>"\ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ + "<IsMigration>false</IsMigration>"\ + "<PartnerScenario>GroupSave</PartnerScenario>"\ + "</ABApplicationHeader>"\ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ + "</ABAuthHeader>"\ + "</soap:Header>"\ + "<soap:Body>"\ + "<ABGroupAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<abId>00000000-0000-0000-0000-000000000000</abId>"\ + "<groupAddOptions>"\ + "<fRenameOnMsgrConflict>false</fRenameOnMsgrConflict>"\ + "</groupAddOptions>"\ + "<groupInfo>"\ + "<GroupInfo>"\ + "<name>%s</name>"\ + "<groupType>C8529CE2-6EAD-434d-881F-341E17DB3FF8</groupType>"\ + "<fMessenger>false</fMessenger>"\ + "<annotations>"\ + "<Annotation>"\ + "<Name>MSN.IM.Display</Name>"\ + "<Value>1</Value>"\ + "</Annotation>"\ + "</annotations>"\ + "</GroupInfo>"\ + "</groupInfo>"\ + "</ABGroupAdd>"\ + "</soap:Body>"\ +"</soap:Envelope>" /* delete a group */ #define MSN_GROUP_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupDelete" -#define MSN_GROUP_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>Timer</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABGroupDelete xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><groupFilter><groupIds><guid>%s</guid></groupIds></groupFilter></ABGroupDelete></soap:Body></soap:Envelope>" +#define MSN_GROUP_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ + "<soap:Header>"\ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ + "<IsMigration>false</IsMigration>"\ + "<PartnerScenario>Timer</PartnerScenario>"\ + "</ABApplicationHeader>"\ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ + "</ABAuthHeader>"\ + "</soap:Header>"\ + "<soap:Body>"\ + "<ABGroupDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<abId>00000000-0000-0000-0000-000000000000</abId>"\ + "<groupFilter>"\ + "<groupIds>"\ + "<guid>%s</guid>"\ + "</groupIds>"\ + "</groupFilter>"\ + "</ABGroupDelete>"\ + "</soap:Body>"\ +"</soap:Envelope>" /* change a group's name */ #define MSN_GROUP_RENAME_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupUpdate" -#define MSN_GROUP_RENAME_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>Timer</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABGroupUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><groups><Group><groupId>%s</groupId><groupInfo><name>%s</name></groupInfo><propertiesChanged>GroupName </propertiesChanged></Group></groups></ABGroupUpdate></soap:Body></soap:Envelope>" +#define MSN_GROUP_RENAME_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope"\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\ + "<soap:Header>"\ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\ + "<IsMigration>false</IsMigration>"\ + "<PartnerScenario>Timer</PartnerScenario>"\ + "</ABApplicationHeader>"\ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<ManagedGroupRequest>false</ManagedGroupRequest>"\ + "<TicketToken>%s</TicketToken>"\ + "</ABAuthHeader>"\ + "</soap:Header>"\ + "<soap:Body>"\ + "<ABGroupUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\ + "<abId>00000000-0000-0000-0000-000000000000</abId>"\ + "<groups>"\ + "<Group>"\ + "<groupId>%s</groupId>"\ + "<groupInfo>"\ + "<name>%s</name>"\ + "</groupInfo>"\ + "<propertiesChanged>GroupName </propertiesChanged>"\ + "</Group>"\ + "</groups>"\ + "</ABGroupUpdate>"\ + "</soap:Body>"\ +"</soap:Envelope>" typedef enum { @@ -360,15 +590,6 @@ MSN_RENAME_GROUP = 0x40, } MsnCallbackAction; -typedef struct _MsnContact MsnContact; - -struct _MsnContact -{ - MsnSession *session; - - MsnSoapConn *soapconn; -}; - typedef struct _MsnCallbackState MsnCallbackState; struct _MsnCallbackState @@ -395,9 +616,6 @@ /************************************************ * function prototype ************************************************/ -MsnContact * msn_contact_new(MsnSession *session); -void msn_contact_destroy(MsnContact *contact); - MsnCallbackState * msn_callback_state_new(MsnSession *session); void msn_callback_state_free(MsnCallbackState *state); void msn_callback_state_set_who(MsnCallbackState *state, const gchar *who); @@ -411,24 +629,24 @@ void msn_callback_state_set_action(MsnCallbackState *state, MsnCallbackAction action); -void msn_contact_connect(MsnContact *contact); -void msn_get_contact_list(MsnContact * contact, +void msn_contact_connect(MsnSession *session); +void msn_get_contact_list(MsnSession *session, const MsnSoapPartnerScenario partner_scenario, const char *update); -void msn_get_address_book(MsnContact *contact, +void msn_get_address_book(MsnSession *session, const MsnSoapPartnerScenario partner_scenario, const char * update, const char * gupdate); /* contact SOAP operations */ -void msn_update_contact(MsnContact *contact, const char* nickname); +void msn_update_contact(MsnSession *session, const char* nickname); -void msn_add_contact(MsnContact *contact, MsnCallbackState *state, +void msn_add_contact(MsnSession *session, MsnCallbackState *state, const char *passport); -void msn_delete_contact(MsnContact *contact, const char *contactId); +void msn_delete_contact(MsnSession *session, const char *contactId); -void msn_add_contact_to_group(MsnContact *contact, MsnCallbackState *state, +void msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state, const char *passport, const char *groupId); -void msn_del_contact_from_group(MsnContact *contact, const char *passport, +void msn_del_contact_from_group(MsnSession *session, const char *passport, const char *group_name); /* group operations */ void msn_add_group(MsnSession *session, MsnCallbackState *state, @@ -438,9 +656,9 @@ const char *new_group_name); /* lists operations */ -void msn_add_contact_to_list(MsnContact *contact, MsnCallbackState *state, +void msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state, const gchar *passport, const MsnListId list); -void msn_del_contact_from_list(MsnContact *contact, MsnCallbackState *state, +void msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state, const gchar *passport, const MsnListId list); void msn_contact_connect_init(MsnSoapConn *soapconn);
--- a/libpurple/protocols/msn/msn.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/msn.c Sat Jun 07 03:10:15 2008 +0000 @@ -27,6 +27,7 @@ #include "msn.h" #include "accountopt.h" +#include "contact.h" #include "msg.h" #include "page.h" #include "pluginpref.h" @@ -1062,7 +1063,10 @@ } msn_import_html(message, &msgformat, &msgtext); - if(msn_user_is_online(account, who)|| + /* this is incorrect, we should try to initiate a connection to the + buddy first, and only falls back if that fails. Otherwise we can + only send offline message to invisible buddies */ + if (msn_user_is_online(account, who)|| msn_user_is_yahoo(account, who)){ /*User online,then send Online Instant Message*/ @@ -1145,7 +1149,7 @@ } msn_message_destroy(msg); - }else { + } else { /*send Offline Instant Message,only to MSN Passport User*/ MsnSession *session; char *friendname; @@ -1156,8 +1160,11 @@ friendname = msn_encode_mime(account->username); msn_oim_prep_send_msg_info(session->oim, purple_account_get_username(account), - friendname, who, message); + friendname, who, msgtext); msn_oim_send_msg(session->oim); + + g_free(msgformat); + g_free(msgtext); g_free(friendname); } @@ -1369,10 +1376,10 @@ msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL); /* delete contact from Block list and add it to Allow in the callback */ - msn_del_contact_from_list(session->contact, NULL, who, MSN_LIST_BL); + msn_del_contact_from_list(session, NULL, who, MSN_LIST_BL); } else { /* just add the contact to Allow list */ - msn_add_contact_to_list(session->contact, NULL, who, MSN_LIST_AL); + msn_add_contact_to_list(session, NULL, who, MSN_LIST_AL); } @@ -1397,10 +1404,10 @@ msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_AL); /* delete contact from Allow list and add it to Block in the callback */ - msn_del_contact_from_list(session->contact, NULL, who, MSN_LIST_AL); + msn_del_contact_from_list(session, NULL, who, MSN_LIST_AL); } else { /* just add the contact to Block list */ - msn_add_contact_to_list(session->contact, NULL, who, MSN_LIST_BL); + msn_add_contact_to_list(session, NULL, who, MSN_LIST_BL); } msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_BL); @@ -1423,7 +1430,7 @@ msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_AL); - msn_del_contact_from_list(session->contact, NULL, who, MSN_LIST_AL); + msn_del_contact_from_list(session, NULL, who, MSN_LIST_AL); if (user != NULL && user->list_op & MSN_LIST_RL_OP) msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_BL); @@ -1446,7 +1453,7 @@ msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL); - msn_del_contact_from_list(session->contact, NULL, who, MSN_LIST_BL); + msn_del_contact_from_list(session, NULL, who, MSN_LIST_BL); if (user != NULL && user->list_op & MSN_LIST_RL_OP) msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_AL);
--- a/libpurple/protocols/msn/msn.h Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/msn.h Sat Jun 07 03:10:15 2008 +0000 @@ -66,12 +66,10 @@ /* Windows Live Messenger Server*/ #define WLM_SERVER "muser.messenger.hotmail.com" #define WLM_PORT 1863 -#define WLM_PROT_VER 13 -/*This MSNP14 Support chat with Yahoo Messenger*/ -#define WLM_YAHOO_PROT_VER 14 +#define WLM_PROT_VER 15 -#define WLM_MAX_PROTOCOL 14 -#define WLM_MIN_PROTOCOL 13 +#define WLM_MAX_PROTOCOL 15 +#define WLM_MIN_PROTOCOL 15 #define MSN_TYPING_RECV_TIMEOUT 6 #define MSN_TYPING_SEND_TIMEOUT 4
--- a/libpurple/protocols/msn/msnutils.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/msnutils.c Sat Jun 07 03:10:15 2008 +0000 @@ -514,8 +514,8 @@ { PurpleCipher *cipher; PurpleCipherContext *context; - char *productKey = MSNP13_WLM_PRODUCT_KEY, - *productID = MSNP13_WLM_PRODUCT_ID, + char *productKey = MSNP15_WLM_PRODUCT_KEY, + *productID = MSNP15_WLM_PRODUCT_ID, *hexChars = "0123456789abcdef", buf[BUFSIZE]; unsigned char md5Hash[16], *newHash;
--- a/libpurple/protocols/msn/nexus.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/nexus.c Sat Jun 07 03:10:15 2008 +0000 @@ -26,7 +26,24 @@ #include "nexus.h" #include "notification.h" -#undef NEXUS_LOGIN_TWN + +/************************************************************************** + * Valid Ticket Tokens + **************************************************************************/ + +#define SSO_VALID_TICKET_DOMAIN 0 +#define SSO_VALID_TICKET_POLICY 1 +static char *ticket_domains[][2] = { + /* http://msnpiki.msnfanatic.com/index.php/MSNP15:SSO */ + /* {"Domain", "Policy Ref URI"}, Purpose */ + {"messengerclear.live.com", NULL}, /* Authentication for messenger. */ + {"messenger.msn.com", "?id=507"}, /* Authentication for receiving OIMs. */ + {"contacts.msn.com", "MBI"}, /* Authentication for the Contact server. */ + {"messengersecure.live.com", "MBI_SSL"}, /* Authentication for sending OIMs. */ + {"spaces.live.com", "MBI"}, /* Authentication for the Windows Live Spaces */ + {"livecontacts.live.com", "MBI"}, /* Live Contacts API, a simplified version of the Contacts SOAP service */ + {"storage.live.com", "MBI"}, /* Storage REST API */ +}; /************************************************************************** * Main @@ -36,12 +53,17 @@ msn_nexus_new(MsnSession *session) { MsnNexus *nexus; + int i; nexus = g_new0(MsnNexus, 1); nexus->session = session; - nexus->challenge_data = g_hash_table_new_full(g_str_hash, - g_str_equal, g_free, g_free); + nexus->token_len = sizeof(ticket_domains) / sizeof(char *[2]); + nexus->tokens = g_new0(MsnTicketToken, nexus->token_len); + + for (i = 0; i < nexus->token_len; i++) + nexus->tokens[i].token = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); return nexus; } @@ -49,48 +71,199 @@ void msn_nexus_destroy(MsnNexus *nexus) { - if (nexus->challenge_data != NULL) - g_hash_table_destroy(nexus->challenge_data); + int i; + for (i = 0; i < nexus->token_len; i++) { + g_hash_table_destroy(nexus->tokens[i].token); + g_free(nexus->tokens[i].secret); + } + + g_free(nexus->tokens); + g_free(nexus->policy); + g_free(nexus->nonce); + g_free(nexus); +} + +/************************************************************************** + * RPS/SSO Authentication + **************************************************************************/ + +static char * +sha1_hmac(const char *key, int key_len, const char *message, int msg_len) +{ + PurpleCipherContext *context; + char *result; + gboolean ret; + + context = purple_cipher_context_new_by_name("hmac", NULL); + purple_cipher_context_set_option(context, "hash", "sha1"); + purple_cipher_context_set_key_with_len(context, (guchar *)key, key_len); + + purple_cipher_context_append(context, (guchar *)message, msg_len); + result = g_malloc(20); + ret = purple_cipher_context_digest(context, 20, (guchar *)result, NULL); + + purple_cipher_context_destroy(context); + + return result; +} + +static char * +rps_create_key(const char *key, int key_len, const char *data, size_t data_len) +{ + char *hash1, *hash2, *hash3, *hash4; + char *result; + + hash1 = sha1_hmac(key, key_len, data, data_len); + hash1 = g_realloc(hash1, 20 + data_len); + memcpy(hash1 + 20, data, data_len); + hash2 = sha1_hmac(key, key_len, hash1, 20 + data_len); + + hash3 = sha1_hmac(key, key_len, hash1, 20); + + hash3 = g_realloc(hash3, 20 + data_len); + memcpy(hash3 + 20, data, data_len); + hash4 = sha1_hmac(key, key_len, hash3, 20 + data_len); + + result = g_malloc(24); + memcpy(result, hash2, 20); + memcpy(result + 20, hash4, 4); + + g_free(hash1); + g_free(hash2); + g_free(hash3); + g_free(hash4); + + return result; +} + +static char * +des3_cbc(const char *key, const char *iv, const char *data, int len) +{ + PurpleCipherContext *des3; + char *out; + size_t outlen; - g_free(nexus->challenge_data_str); - g_free(nexus); + des3 = purple_cipher_context_new_by_name("des3", NULL); + purple_cipher_context_set_key(des3, (guchar *)key); + purple_cipher_context_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC); + purple_cipher_context_set_iv(des3, (guchar *)iv, 8); + + out = g_malloc(len); + purple_cipher_context_encrypt(des3, (guchar *)data, len, (guchar *)out, &outlen); + + purple_cipher_context_destroy(des3); + + return out; +} + +#define CRYPT_MODE_CBC 1 +#define CIPHER_TRIPLE_DES 0x6603 +#define HASH_SHA1 0x8004 +static char * +msn_rps_encrypt(MsnNexus *nexus) +{ + MsnUsrKey *usr_key; + const char *magic1 = "WS-SecureConversationSESSION KEY HASH"; + const char *magic2 = "WS-SecureConversationSESSION KEY ENCRYPTION"; + size_t len; + char *hash; + char *key1, *key2, *key3; + gsize key1_len; + char *nonce_fixed; + char *cipher; + char *response; + + usr_key = g_malloc(sizeof(MsnUsrKey)); + usr_key->size = GUINT32_TO_LE(28); + usr_key->crypt_mode = GUINT32_TO_LE(CRYPT_MODE_CBC); + usr_key->cipher_type = GUINT32_TO_LE(CIPHER_TRIPLE_DES); + usr_key->hash_type = GUINT32_TO_LE(HASH_SHA1); + usr_key->iv_len = GUINT32_TO_LE(8); + usr_key->hash_len = GUINT32_TO_LE(20); + usr_key->cipher_len = GUINT32_TO_LE(72); + + key1 = (char *)purple_base64_decode((const char *)nexus->tokens[MSN_AUTH_MESSENGER].secret, &key1_len); + len = strlen(magic1); + key2 = rps_create_key(key1, key1_len, magic1, len); + len = strlen(magic2); + key3 = rps_create_key(key1, key1_len, magic2, len); + + usr_key->iv[0] = 0x46; //rand() % 256; + usr_key->iv[1] = 0xC4; + usr_key->iv[2] = 0x14; + usr_key->iv[3] = 0x9F; + usr_key->iv[4] = 0xFF; + usr_key->iv[5] = 0xFC; + usr_key->iv[6] = 0x91; + usr_key->iv[7] = 0x61; + + len = strlen(nexus->nonce); + hash = sha1_hmac(key2, 24, nexus->nonce, len); + + /* We need to pad this to 72 bytes, apparently */ + nonce_fixed = g_malloc(len + 8); + memcpy(nonce_fixed, nexus->nonce, len); + memset(nonce_fixed + len, 0x08, 8); + cipher = des3_cbc(key3, usr_key->iv, nonce_fixed, len + 8); + g_free(nonce_fixed); + + memcpy(usr_key->hash, hash, 20); + memcpy(usr_key->cipher, cipher, 72); + + g_free(key1); + g_free(key2); + g_free(key3); + g_free(hash); + g_free(cipher); + + response = purple_base64_encode((guchar *)usr_key, sizeof(MsnUsrKey)); + + g_free(usr_key); + + return response; } /************************************************************************** * Login **************************************************************************/ -static void -nexus_got_response_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) +static gboolean +nexus_parse_response(MsnNexus *nexus, xmlnode *xml) { - MsnNexus *nexus = data; - MsnSession *session = nexus->session; xmlnode *node; + gboolean result = FALSE; - if (resp == NULL) { - msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Unable to connect")); - return; - } + node = xmlnode_get_child(xml, "Body/RequestSecurityTokenResponseCollection/RequestSecurityTokenResponse"); - node = msn_soap_xml_get(resp->xml, "Body/" - "RequestSecurityTokenResponseCollection/RequestSecurityTokenResponse"); + if (node) + node = node->next; /* The first one is not useful */ + else + return FALSE; for (; node; node = node->next) { - xmlnode *token = msn_soap_xml_get(node, - "RequestedSecurityToken/BinarySecurityToken"); + xmlnode *token = xmlnode_get_child(node, "RequestedSecurityToken/BinarySecurityToken"); + xmlnode *secret = xmlnode_get_child(node, "RequestedProofToken/BinarySecret"); + xmlnode *expires = xmlnode_get_child(node, "LifeTime/Expires"); if (token) { - char *token_str = xmlnode_get_data(token); + char *token_str, *expiry_str; + const char *id_str = xmlnode_get_attrib(token, "Id"); char **elems, **cur, **tokens; - char *msn_twn_t, *msn_twn_p, *cert_str; + int id; + + if (id_str == NULL) continue; + id = atol(id_str + 7) - 1; /* 'Compact#' or 'PPToken#' */ + if (id >= nexus->token_len) + continue; /* Where did this come from? */ + + token_str = xmlnode_get_data(token); if (token_str == NULL) continue; - elems = g_strsplit(token_str, "&", 0); for (cur = elems; *cur != NULL; cur++){ tokens = g_strsplit(*cur, "=", 2); - g_hash_table_insert(nexus->challenge_data, tokens[0], tokens[1]); + g_hash_table_insert(nexus->tokens[id].token, tokens[0], tokens[1]); /* Don't free each of the tokens, only the array. */ g_free(tokens); } @@ -98,30 +271,59 @@ g_free(token_str); g_strfreev(elems); - msn_twn_t = g_hash_table_lookup(nexus->challenge_data, "t"); - msn_twn_p = g_hash_table_lookup(nexus->challenge_data, "p"); + if (secret) + nexus->tokens[id].secret = xmlnode_get_data(secret); + else + nexus->tokens[id].secret = NULL; - /*setup the t and p parameter for session*/ - g_free(session->passport_info.t); - session->passport_info.t = g_strdup(msn_twn_t); - - g_free(session->passport_info.p); - session->passport_info.p = g_strdup(msn_twn_p); + /* Yay for MS using ISO-8601 */ + expiry_str = xmlnode_get_data(expires); - cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p); - msn_got_login_params(session, cert_str); + nexus->tokens[id].expiry = purple_str_to_time(expiry_str, + FALSE, NULL, NULL, NULL); - purple_debug_info("MSN Nexus","Close nexus connection!\n"); - g_free(cert_str); - msn_nexus_destroy(nexus); - session->nexus = NULL; + g_free(expiry_str); - return; + purple_debug_info("msnp15", "Updated ticket for domain '%s'\n", + ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); + result = TRUE; } } - /* we must have failed! */ - msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication: cannot find authenticate token in server response")); + return result; +} + +static void +nexus_got_response_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) +{ + MsnNexus *nexus = data; + MsnSession *session = nexus->session; + char *msn_twn_t, *msn_twn_p, *ticket; + char *response; + + if (resp == NULL) { + msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Unable to connect")); + return; + } + + if (!nexus_parse_response(nexus, resp->xml)) { + msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Invalid response")); + return; + } + + /*setup the t and p parameter for session*/ + msn_twn_t = g_hash_table_lookup(nexus->tokens[MSN_AUTH_MESSENGER].token, "t"); + msn_twn_p = g_hash_table_lookup(nexus->tokens[MSN_AUTH_MESSENGER].token, "p"); + g_free(session->passport_info.t); + session->passport_info.t = g_strdup(msn_twn_t); + g_free(session->passport_info.p); + session->passport_info.p = g_strdup(msn_twn_p); + + ticket = g_strdup_printf("t=%s&p=%s", msn_twn_t, msn_twn_p); + response = msn_rps_encrypt(nexus); + msn_got_login_params(session, ticket, response); + g_free(ticket); + g_free(response); } /*when connect, do the SOAP Style windows Live ID authentication */ @@ -129,92 +331,119 @@ msn_nexus_connect(MsnNexus *nexus) { MsnSession *session = nexus->session; - char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf; - char *fs0,*fs; - const char *username; - char *password; - char *tail; -#ifdef NEXUS_LOGIN_TWN - char *challenge_str; -#else - char *rst1_str,*rst2_str,*rst3_str; -#endif + char *username, *password; + GString *domains; + char *request; + int i; + + MsnSoapMessage *soap; + + msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); + + username = g_strdup(purple_account_get_username(session->account)); + password = g_strndup(purple_connection_get_password(session->account->gc), 16); + + purple_debug_info("msnp15", "Logging on %s, with policy '%s', nonce '%s'\n", + username, nexus->policy, nexus->nonce); + + domains = g_string_new(NULL); + for (i = 0; i < nexus->token_len; i++) { + g_string_append_printf(domains, MSN_SSO_RST_TEMPLATE, + i+1, + ticket_domains[i][SSO_VALID_TICKET_DOMAIN], + ticket_domains[i][SSO_VALID_TICKET_POLICY] != NULL ? + ticket_domains[i][SSO_VALID_TICKET_POLICY] : + nexus->policy); + } + + request = g_strdup_printf(MSN_SSO_TEMPLATE, username, password, domains->str); + g_free(username); + g_free(password); + g_string_free(domains, TRUE); + + soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1)); + g_free(request); + msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, + nexus_got_response_cb, nexus); +} + +static void +nexus_got_update_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) +{ + MsnNexus *nexus = data; + + nexus_parse_response(nexus, resp->xml); +} + +static void +msn_nexus_update_token(MsnNexus *nexus, int id) +{ + MsnSession *session = nexus->session; + char *username, *password; + char *domain; + char *request; MsnSoapMessage *soap; - purple_debug_info("MSN Nexus","Starting Windows Live ID authentication\n"); - msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); - - /*prepare the Windows Live ID authentication token*/ - username = purple_account_get_username(session->account); + username = g_strdup(purple_account_get_username(session->account)); password = g_strndup(purple_connection_get_password(session->account->gc), 16); - lc = (char *)g_hash_table_lookup(nexus->challenge_data, "lc"); - id = (char *)g_hash_table_lookup(nexus->challenge_data, "id"); - tw = (char *)g_hash_table_lookup(nexus->challenge_data, "tw"); - fs0= (char *)g_hash_table_lookup(nexus->challenge_data, "fs"); - ru = (char *)g_hash_table_lookup(nexus->challenge_data, "ru"); - ct = (char *)g_hash_table_lookup(nexus->challenge_data, "ct"); - kpp= (char *)g_hash_table_lookup(nexus->challenge_data, "kpp"); - kv = (char *)g_hash_table_lookup(nexus->challenge_data, "kv"); - ver= (char *)g_hash_table_lookup(nexus->challenge_data, "ver"); - rn = (char *)g_hash_table_lookup(nexus->challenge_data, "rn"); - tpf= (char *)g_hash_table_lookup(nexus->challenge_data, "tpf"); - - /* - * add some fail-safe code to avoid windows Purple Crash bug #1540454 - * If any of these string is NULL, will return Authentication Fail! - * for when windows g_strdup_printf() implementation get NULL point,It crashed! - */ - if(!(lc && id && tw && ru && ct && kpp && kv && ver && tpf)){ - purple_debug_error("MSN Nexus","WLM Authenticate Key Error!\n"); - msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication Failed")); - g_free(password); - msn_nexus_destroy(nexus); - session->nexus = NULL; - return; - } + purple_debug_info("msnp15", "Updating ticket for user '%s' on domain '%s'\n", + username, ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); - /* - * in old MSN NS server's "USR TWN S" return,didn't include fs string - * so we use a default "1" for fs. - */ - if(fs0){ - fs = g_strdup(fs0); - }else{ - fs = g_strdup("1"); - } - -#ifdef NEXUS_LOGIN_TWN - challenge_str = g_strdup_printf( - "lc=%s&id=%s&tw=%s&fs=%s&ru=%s&ct=%s&kpp=%s&kv=%s&ver=%s&rn=%s&tpf=%s\r\n", - lc,id,tw,fs,ru,ct,kpp,kv,ver,rn,tpf - ); + /* TODO: This really assumes if we send RSTn, the server responds with + Compactn, even if there is no RST(n-1). This needs checking. + */ + domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE, + id, + ticket_domains[id][SSO_VALID_TICKET_DOMAIN], + ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ? + ticket_domains[id][SSO_VALID_TICKET_POLICY] : + nexus->policy); - /*build the SOAP windows Live ID XML body */ - tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE, username, password, challenge_str); - g_free(challenge_str); -#else - rst1_str = g_strdup_printf( - "id=%s&tw=%s&fs=%s&kpp=%s&kv=%s&ver=%s&rn=%s", - id,tw,fs,kpp,kv,ver,rn - ); - rst2_str = g_strdup_printf( - "fs=%s&id=%s&kv=%s&rn=%s&tw=%s&ver=%s", - fs,id,kv,rn,tw,ver - ); - rst3_str = g_strdup_printf("id=%s",id); - tail = g_strdup_printf(TWN_LIVE_ENVELOP_TEMPLATE,username,password,rst1_str,rst2_str,rst3_str); - g_free(rst1_str); - g_free(rst2_str); - g_free(rst3_str); -#endif - g_free(fs); + request = g_strdup_printf(MSN_SSO_TEMPLATE, username, password, domain); + g_free(username); g_free(password); + g_free(domain); - soap = msn_soap_message_new(NULL, xmlnode_from_str(tail, -1)); - g_free(tail); - msn_soap_message_send(nexus->session, soap, MSN_TWN_SERVER, TWN_POST_URL, - nexus_got_response_cb, nexus); + soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1)); + g_free(request); + msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, + nexus_got_update_cb, nexus); } +GHashTable * +msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id) +{ + g_return_val_if_fail(nexus != NULL, NULL); + g_return_val_if_fail(id < nexus->token_len, NULL); + + if (time(NULL) > nexus->tokens[id].expiry) + msn_nexus_update_token(nexus, id); + + return nexus->tokens[id].token; +} + +const char * +msn_nexus_get_token_str(MsnNexus *nexus, MsnAuthDomains id) +{ + static char buf[1024]; + GHashTable *token = msn_nexus_get_token(nexus, id); + const char *msn_t; + const char *msn_p; + gint ret; + + g_return_val_if_fail(token != NULL, NULL); + + msn_t = g_hash_table_lookup(token, "t"); + msn_p = g_hash_table_lookup(token, "p"); + + g_return_val_if_fail(msn_t != NULL, NULL); + g_return_val_if_fail(msn_p != NULL, NULL); + + ret = g_snprintf(buf, sizeof(buf) - 1, "t=%s&p=%s", msn_t, msn_p); + g_return_val_if_fail(ret != -1, NULL); + + return buf; +} +
--- a/libpurple/protocols/msn/nexus.h Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/nexus.h Sat Jun 07 03:10:15 2008 +0000 @@ -26,125 +26,115 @@ #include "soap.h" -/*#define MSN_TWN_SERVER "loginnet.passport.com"*/ -#define MSN_TWN_SERVER "login.live.com" - -#define TWN_START_TOKEN "<wsse:BinarySecurityToken Id=\"PPToken1\">" -#define TWN_END_TOKEN "</wsse:BinarySecurityToken>" +/* Index into ticket_tokens in nexus.c Keep updated! */ +typedef enum +{ + MSN_AUTH_MESSENGER = 0, + MSN_AUTH_MESSENGER_WEB = 1, + MSN_AUTH_CONTACTS = 2, + MSN_AUTH_LIVE_SECURE = 3, + MSN_AUTH_SPACES = 4, + MSN_AUTH_LIVE_CONTACTS = 5, + MSN_AUTH_STORAGE = 6 +} MsnAuthDomains; -#define TWN_POST_URL "/RST.srf" -#define TWN_ENVELOP_TEMPLATE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"\ - "<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\ - "<Header>"\ - "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">"\ - "<ps:HostingApp>{3:B}</ps:HostingApp>"\ - "<ps:BinaryVersion>4</ps:BinaryVersion>"\ - "<ps:UIVersion>1</ps:UIVersion>"\ - "<ps:Cookies></ps:Cookies>"\ - "<ps:RequestParams>AQAAAAIAAABsYwQAAAAzMDg0</ps:RequestParams>"\ - "</ps:AuthInfo>"\ - "<wsse:Security>"\ - "<wsse:UsernameToken Id=\"user\">"\ - "<wsse:Username>%s</wsse:Username>"\ - "<wsse:Password>%s</wsse:Password>"\ - "</wsse:UsernameToken>"\ - "</wsse:Security>"\ - "</Header>"\ - "<Body>"\ - "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">"\ - "<wst:RequestSecurityToken Id=\"RST0\">"\ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\ - "<wsp:AppliesTo>"\ - "<wsa:EndpointReference>"\ - "<wsa:Address>http://Passport.NET/tb</wsa:Address>"\ - "</wsa:EndpointReference>"\ - "</wsp:AppliesTo>"\ - "</wst:RequestSecurityToken>"\ - "<wst:RequestSecurityToken Id=\"RST1\">"\ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\ - "<wsp:AppliesTo>"\ - "<wsa:EndpointReference>"\ - "<wsa:Address>messenger.msn.com</wsa:Address>"\ - "</wsa:EndpointReference>"\ - "</wsp:AppliesTo>"\ - "<wsse:PolicyReference URI=\"?%s\">"\ - "</wsse:PolicyReference>"\ - "</wst:RequestSecurityToken>"\ - "</ps:RequestMultipleSecurityTokens>"\ - "</Body>"\ - "</Envelope>" +#define MSN_SSO_SERVER "login.live.com" +#define SSO_POST_URL "/RST.srf" + +#define MSN_SSO_RST_TEMPLATE \ +"<wst:RequestSecurityToken Id=\"RST%d\">"\ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\ + "<wsp:AppliesTo>"\ + "<wsa:EndpointReference>"\ + "<wsa:Address>%s</wsa:Address>"\ + "</wsa:EndpointReference>"\ + "</wsp:AppliesTo>"\ + "<wsse:PolicyReference URI=\"%s\"></wsse:PolicyReference>"\ +"</wst:RequestSecurityToken>" -#define TWN_LIVE_START_TOKEN "<wsse:BinarySecurityToken Id=\"PPToken1\">" -#define TWN_LIVE_END_TOKEN "</wsse:BinarySecurityToken>" -#define TWN_LIVE_ENVELOP_TEMPLATE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"\ -"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\ - "<Header>"\ - "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">"\ - "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\ - "<ps:BinaryVersion>4</ps:BinaryVersion>"\ - "<ps:UIVersion>1</ps:UIVersion>"\ - "<ps:Cookies></ps:Cookies>"\ - "<ps:RequestParams>AQAAAAIAAABsYwQAAAAyMDUy</ps:RequestParams>"\ - "</ps:AuthInfo>"\ - "<wsse:Security>"\ - "<wsse:UsernameToken Id=\"user\">"\ - "<wsse:Username>%s</wsse:Username>"\ - "<wsse:Password>%s</wsse:Password>"\ - "</wsse:UsernameToken>"\ - "</wsse:Security>"\ - "</Header>"\ - "<Body>"\ - "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">"\ - "<wst:RequestSecurityToken Id=\"RST0\">"\ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\ - "<wsp:AppliesTo>"\ - "<wsa:EndpointReference>"\ - "<wsa:Address>http://Passport.NET/tb</wsa:Address>"\ - "</wsa:EndpointReference>"\ - "</wsp:AppliesTo>"\ - "</wst:RequestSecurityToken>"\ - "<wst:RequestSecurityToken Id=\"RST1\">"\ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\ - "<wsp:AppliesTo>"\ - "<wsa:EndpointReference>"\ - "<wsa:Address>messenger.msn.com</wsa:Address>"\ - "</wsa:EndpointReference>"\ - "</wsp:AppliesTo>"\ - "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>"\ - "</wst:RequestSecurityToken>"\ - "<wst:RequestSecurityToken Id=\"RST2\">"\ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\ - "<wsp:AppliesTo>"\ - "<wsa:EndpointReference>"\ - "<wsa:Address>contacts.msn.com</wsa:Address>"\ - "</wsa:EndpointReference>"\ - "</wsp:AppliesTo>"\ - "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>"\ - " </wst:RequestSecurityToken>"\ - "<wst:RequestSecurityToken Id=\"RST3\">"\ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\ - "<wsp:AppliesTo>"\ - "<wsa:EndpointReference>"\ - "<wsa:Address>voice.messenger.msn.com</wsa:Address>"\ - "</wsa:EndpointReference>"\ - " </wsp:AppliesTo>"\ - "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>"\ - "</wst:RequestSecurityToken>"\ - "</ps:RequestMultipleSecurityTokens>"\ - "</Body>"\ +#define MSN_SSO_TEMPLATE "<?xml version='1.0' encoding='utf-8'?>"\ +"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\""\ + " xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\""\ + " xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\""\ + " xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\""\ + " xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\""\ + " xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\""\ + " xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\""\ + " xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\ + "<Header>"\ + "<ps:AuthInfo"\ + " xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\ + " Id=\"PPAuthInfo\">"\ + "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\ + "<ps:BinaryVersion>4</ps:BinaryVersion>"\ + "<ps:UIVersion>1</ps:UIVersion>"\ + "<ps:Cookies></ps:Cookies>"\ + "<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>"\ + "</ps:AuthInfo>"\ + "<wsse:Security>"\ + "<wsse:UsernameToken Id=\"user\">"\ + "<wsse:Username>%s</wsse:Username>"\ + "<wsse:Password>%s</wsse:Password>"\ + "</wsse:UsernameToken>"\ + "</wsse:Security>"\ + "</Header>"\ + "<Body>"\ + "<ps:RequestMultipleSecurityTokens"\ + " xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\ + " Id=\"RSTS\">"\ + "<wst:RequestSecurityToken Id=\"RST0\">"\ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\ + "<wsp:AppliesTo>"\ + "<wsa:EndpointReference>"\ + "<wsa:Address>http://Passport.NET/tb</wsa:Address>"\ + "</wsa:EndpointReference>"\ + "</wsp:AppliesTo>"\ + "</wst:RequestSecurityToken>"\ + "%s" /* Other RSTn tokens */\ + "</ps:RequestMultipleSecurityTokens>"\ + "</Body>"\ "</Envelope>" +typedef struct _MsnUsrKey MsnUsrKey; +struct _MsnUsrKey +{ + int size; // 28. Does not count data + int crypt_mode; // CRYPT_MODE_CBC (1) + int cipher_type; // TripleDES (0x6603) + int hash_type; // SHA1 (0x8004) + int iv_len; // 8 + int hash_len; // 20 + int cipher_len; // 72 + // Data + char iv[8]; + char hash[20]; + char cipher[72]; +}; + +typedef struct _MsnTicketToken MsnTicketToken; +struct _MsnTicketToken { + GHashTable *token; + char *secret; + time_t expiry; +}; + typedef struct _MsnNexus MsnNexus; struct _MsnNexus { MsnSession *session; - char * challenge_data_str; - GHashTable *challenge_data; + char *policy; + char *nonce; + + MsnTicketToken *tokens; + int token_len; }; void msn_nexus_connect(MsnNexus *nexus); MsnNexus *msn_nexus_new(MsnSession *session); void msn_nexus_destroy(MsnNexus *nexus); +GHashTable *msn_nexus_get_token(MsnNexus *session, MsnAuthDomains id); +const char *msn_nexus_get_token_str(MsnNexus *session, MsnAuthDomains id); #endif /* _MSN_NEXUS_H_ */ +
--- a/libpurple/protocols/msn/notification.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/notification.c Sat Jun 07 03:10:15 2008 +0000 @@ -23,6 +23,7 @@ */ #include "msn.h" #include "notification.h" +#include "contact.h" #include "state.h" #include "error.h" #include "msnutils.h" @@ -34,6 +35,15 @@ static MsnTable *cbs_table; +/**************************************************************************** + * Local Function Prototype + ****************************************************************************/ + +static void msn_notification_post_adl(MsnCmdProc *cmdproc, const char *payload, int payload_len); +static void +msn_add_contact_xml(MsnSession *session, xmlnode *mlNode,const char *passport, + MsnListOp list_op, MsnUserType type); + /************************************************************************** * Main **************************************************************************/ @@ -195,7 +205,7 @@ **************************************************************************/ void -msn_got_login_params(MsnSession *session, const char *login_params) +msn_got_login_params(MsnSession *session, const char *ticket, const char *response) { MsnCmdProc *cmdproc; @@ -203,7 +213,7 @@ msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END); - msn_cmdproc_send(cmdproc, "USR", "TWN S %s", login_params); + msn_cmdproc_send(cmdproc, "USR", "SSO S %s %s", ticket, response); } static void @@ -212,8 +222,8 @@ PurpleAccount *account; account = cmdproc->session->account; - msn_cmdproc_send(cmdproc, "USR", "TWN I %s", - purple_account_get_username(account)); + + msn_cmdproc_send(cmdproc, "USR", "SSO I %s", purple_account_get_username(account)); } static void @@ -239,32 +249,14 @@ // msn_cmdproc_send(cmdproc, "SYN", "%s", "0"); //TODO we should use SOAP contact to fetch contact list } - else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")) + else if (!g_ascii_strcasecmp(cmd->params[1], "SSO")) { - /* Passport authentication */ - char **elems, **cur, **tokens; + /* RPS authentication */ session->nexus = msn_nexus_new(session); - /* Parse the challenge data. */ - session->nexus->challenge_data_str = g_strdup(cmd->params[3]); - elems = g_strsplit(cmd->params[3], ",", 0); - - for (cur = elems; *cur != NULL; cur++) - { - tokens = g_strsplit(*cur, "=", 2); - if(tokens[0] && tokens[1]) - { - purple_debug_info("MSNP14","challenge %p,key:%s,value:%s\n", - session->nexus->challenge_data,tokens[0],tokens[1]); - g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]); - /* Don't free each of the tokens, only the array. */ - g_free(tokens); - } else - g_strfreev(tokens); - } - - g_strfreev(elems); + session->nexus->policy = g_strdup(cmd->params[3]); + session->nexus->nonce = g_strdup(cmd->params[4]); msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START); @@ -327,14 +319,15 @@ } /* - * Windows Live Messenger 8.0 + * Windows Live Messenger 8.5 * Notice :CVR String discriminate! * reference of http://www.microsoft.com/globaldev/reference/oslocversion.mspx * to see the Local ID */ msn_cmdproc_send(cmdproc, "CVR", // "0x0409 winnt 5.1 i386 MSG80BETA 8.0.0689 msmsgs %s", - "0x0804 winnt 5.1 i386 MSNMSGR 8.0.0792 msmsgs %s", +// "0x0804 winnt 5.1 i386 MSNMSGR 8.0.0792 msmsgs %s", + "0x0409 winnt 5.1 i386 MSNMSGR 8.5.1288 msmsgs %s", purple_account_get_username(account)); } @@ -545,7 +538,7 @@ context = purple_cipher_context_new(cipher, NULL); purple_cipher_context_append(context, (const guchar *)cmd->params[1], strlen(cmd->params[1])); - challenge_resp = MSNP13_WLM_PRODUCT_KEY; + challenge_resp = MSNP15_WLM_PRODUCT_KEY; purple_cipher_context_append(context, (const guchar *)challenge_resp, strlen(challenge_resp)); @@ -560,7 +553,7 @@ msn_handle_chl(cmd->params[1], buf); #endif // purple_debug_info("MSNP14","<<challenge:{%s}:{%s}\n",cmd->params[1],buf); - trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP13_WLM_PRODUCT_ID); + trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP15_WLM_PRODUCT_ID); msn_transaction_set_payload(trans, buf, 32); @@ -640,7 +633,7 @@ { MsnTransaction *trans; purple_debug_info("MSN Notification","Sending ADL with payload: %s\n", payload); - trans = msn_transaction_new(cmdproc, "ADL", "%i", payload_len); + trans = msn_transaction_new(cmdproc, "ADL","%" G_GSIZE_FORMAT, payload_len); msn_transaction_set_payload(trans, payload, payload_len); msn_cmdproc_send_trans(cmdproc, trans); } @@ -782,7 +775,7 @@ if (list_op & MSN_LIST_RL_OP) { /* someone is adding us */ // got_new_entry(cmdproc->session->account->gc, passport, decoded_friendly_name); - msn_get_contact_list(cmdproc->session->contact, MSN_PS_PENDING_LIST, NULL); + msn_get_contact_list(cmdproc->session, MSN_PS_PENDING_LIST, NULL); } // g_free(decoded_friendly_name); @@ -839,9 +832,8 @@ { purple_debug_info("MSN Notification","FQY payload:\n%s\n", payload); g_return_if_fail(cmdproc->session != NULL); - g_return_if_fail(cmdproc->session->contact != NULL); // msn_notification_post_adl(cmdproc, payload, len); -// msn_get_address_book(cmdproc->session->contact, MSN_AB_SAVE_CONTACT, NULL, NULL); +// msn_get_address_book(cmdproc->session, MSN_AB_SAVE_CONTACT, NULL, NULL); } static void @@ -1292,7 +1284,7 @@ if (!strcmp(type, "MFN")) { friendlyname = purple_url_decode(cmd->params[2]); - msn_update_contact(session->contact, friendlyname); + msn_update_contact(session, friendlyname); purple_connection_set_display_name( purple_account_get_connection(session->account), @@ -1774,17 +1766,16 @@ /*starting retrieve the contact list*/ clLastChange = purple_account_get_string(session->account, "CLLastChange", NULL); - session->contact = msn_contact_new(session); #ifdef MSN_PARTIAL_LISTS /* msn_userlist_load defeats all attempts at trying to detect blist sync issues */ msn_userlist_load(session); - msn_get_contact_list(session->contact, MSN_PS_INITIAL, clLastChange); + msn_get_contact_list(session, MSN_PS_INITIAL, clLastChange); #else /* always get the full list? */ - msn_get_contact_list(session->contact, MSN_PS_INITIAL, NULL); + msn_get_contact_list(session, MSN_PS_INITIAL, NULL); #endif #if 0 - msn_contact_connect(session->contact); + msn_contact_connect(session); #endif } @@ -2172,3 +2163,21 @@ msn_table_destroy(cbs_table); } + msn_table_add_msg_type(cbs_table, + "text/x-msmsgsemailnotification", + email_msg); + /*delete an offline Message notification*/ + msn_table_add_msg_type(cbs_table, + "text/x-msmsgsactivemailnotification", + delete_oim_msg); + msn_table_add_msg_type(cbs_table, + "application/x-msmsgssystemmessage", + system_msg); +} + +void +msn_notification_end(void) +{ + msn_table_destroy(cbs_table); +} +
--- a/libpurple/protocols/msn/notification.h Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/notification.h Sat Jun 07 03:10:15 2008 +0000 @@ -25,6 +25,11 @@ #define _MSN_NOTIFICATION_H_ /*MSN protocol challenge info*/ + +/*MSNP15 challenge: WLM 8.5.1288.816*/ +#define MSNP15_WLM_PRODUCT_KEY "ILTXC!4IXB5FB*PX" +#define MSNP15_WLM_PRODUCT_ID "PROD0119GSJUC$18" + /*MSNP13 challenge*/ #define MSNP13_WLM_PRODUCT_KEY "O4BG@C7BWLYQX?5G" #define MSNP13_WLM_PRODUCT_ID "PROD01065C%ZFN6F" @@ -76,6 +81,6 @@ */ void msn_notification_close(MsnNotification *notification); -void msn_got_login_params(MsnSession *session, const char *login_params); +void msn_got_login_params(MsnSession *session, const char *ticket, const char *response); #endif /* _MSN_NOTIFICATION_H_ */
--- a/libpurple/protocols/msn/oim.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/oim.c Sat Jun 07 03:10:15 2008 +0000 @@ -41,6 +41,7 @@ } MsnOimRecvData; /*Local Function Prototype*/ +static void msn_parse_oim_xml(MsnOim *oim, xmlnode *node); static void msn_oim_post_single_get_msg(MsnOim *oim, char *msgid); static MsnOimSendReq *msn_oim_new_send_req(const char *from_member, const char *friendname, @@ -114,6 +115,50 @@ } /**************************************** + * OIM GetMetadata request + * **************************************/ +static void +msn_oim_get_metadata_cb(MsnSoapMessage *request, MsnSoapMessage *response, + gpointer data) +{ + MsnOim *oim = data; + + if (response) { + msn_parse_oim_xml(oim, + xmlnode_get_child(response->xml, "Body/GetMetadataResponse/MD")); + } +} + +/* Post to get the OIM Metadata */ +static void +msn_oim_get_metadata(MsnOim *oim) +{ + char *soap_body; + GHashTable *token; + const char *msn_t; + const char *msn_p; + + token = msn_nexus_get_token(oim->session->nexus, MSN_AUTH_MESSENGER_WEB); + g_return_if_fail(token != NULL); + + msn_t = g_hash_table_lookup(token, "t"); + msn_p = g_hash_table_lookup(token, "p"); + + g_return_if_fail(msn_t != NULL); + g_return_if_fail(msn_p != NULL); + + soap_body = g_strdup_printf(MSN_OIM_GET_METADATA_TEMPLATE, msn_t, msn_p); + + msn_soap_message_send(oim->session, + msn_soap_message_new(MSN_OIM_GET_METADATA_ACTION, + xmlnode_from_str(soap_body, -1)), + MSN_OIM_RETRIEVE_HOST, MSN_OIM_RETRIEVE_URL, + msn_oim_get_metadata_cb, oim); + + g_free(soap_body); +} + +/**************************************** * OIM send SOAP request * **************************************/ /*encode the message to OIM Message Format*/ @@ -148,7 +193,7 @@ if (response == NULL) { purple_debug_info("MSNP14", "cannot send OIM: %s\n", msg->oim_msg); } else { - xmlnode *faultNode = msn_soap_xml_get(response->xml, "Body/Fault"); + xmlnode *faultNode = xmlnode_get_child(response->xml, "Body/Fault"); if (faultNode == NULL) { /*Send OK! return*/ @@ -160,9 +205,11 @@ char *faultcode_str = xmlnode_get_data(faultcode); if (g_str_equal(faultcode_str, "q0:AuthenticationFailed")) { - xmlnode *challengeNode = msn_soap_xml_get(faultNode, + xmlnode *challengeNode = xmlnode_get_child(faultNode, "detail/LockKeyChallenge"); + g_free(faultcode_str); + if (challengeNode == NULL) { if (oim->challenge) { g_free(oim->challenge); @@ -217,7 +264,7 @@ msn_oim_send_msg(MsnOim *oim) { MsnOimSendReq *oim_request; - char *soap_body,*mspauth; + char *soap_body; char *msg_body; g_return_if_fail(oim != NULL); @@ -225,16 +272,12 @@ g_return_if_fail(oim_request != NULL); purple_debug_info("MSNP14","sending OIM: %s\n", oim_request->oim_msg); - mspauth = g_strdup_printf("t=%s&p=%s", - oim->session->passport_info.t, - oim->session->passport_info.p - ); /* if we got the challenge lock key, we compute it * else we go for the SOAP fault and resend it. */ if(oim->challenge == NULL){ - purple_debug_info("MSNP14","no lock key challenge,wait for SOAP Fault and Resend\n"); + purple_debug_info("MSNP14","no lock key challenge, wait for SOAP Fault and Resend\n"); } msg_body = msn_oim_msg_to_str(oim, oim_request->oim_msg); @@ -242,8 +285,8 @@ oim_request->from_member, oim_request->friendname, oim_request->to_member, - mspauth, - MSNP13_WLM_PRODUCT_ID, + msn_nexus_get_token_str(oim->session->nexus, MSN_AUTH_LIVE_SECURE), + MSNP15_WLM_PRODUCT_ID, oim->challenge ? oim->challenge : "", oim->send_seq, msg_body); @@ -258,7 +301,6 @@ oim->send_seq++; } - g_free(mspauth); g_free(msg_body); g_free(soap_body); } @@ -272,7 +314,7 @@ { MsnOimRecvData *rdata = data; - if (response && msn_soap_xml_get(response->xml, "Body/Fault") == NULL) { + if (response && xmlnode_get_child(response->xml, "Body/Fault") == NULL) { purple_debug_info("msnoim", "delete OIM success\n"); rdata->oim->oim_list = g_list_remove(rdata->oim->oim_list, rdata->msg_id); @@ -291,11 +333,22 @@ MsnOim *oim = rdata->oim; char *msgid = rdata->msg_id; char *soap_body; + GHashTable *token; + const char *msn_t; + const char *msn_p; purple_debug_info("MSNP14","Delete single OIM Message {%s}\n",msgid); - soap_body = g_strdup_printf(MSN_OIM_DEL_TEMPLATE, - oim->session->passport_info.t, oim->session->passport_info.p, msgid); + token = msn_nexus_get_token(oim->session->nexus, MSN_AUTH_MESSENGER_WEB); + g_return_if_fail(token != NULL); + + msn_t = g_hash_table_lookup(token, "t"); + msn_p = g_hash_table_lookup(token, "p"); + + g_return_if_fail(msn_t != NULL); + g_return_if_fail(msn_p != NULL); + + soap_body = g_strdup_printf(MSN_OIM_DEL_TEMPLATE, msn_t, msn_p, msgid); msn_soap_message_send(oim->session, msn_soap_message_new(MSN_OIM_DEL_SOAP_ACTION, @@ -445,7 +498,7 @@ MsnOimRecvData *rdata = data; if (response != NULL) { - xmlnode *msg_node = msn_soap_xml_get(response->xml, + xmlnode *msg_node = xmlnode_get_child(response->xml, "Body/GetMessageResponse/GetMessageResult"); if (msg_node) { @@ -468,20 +521,37 @@ void msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg) { - xmlnode *node, *mNode; - xmlnode *iu_node; - MsnSession *session = oim->session; + xmlnode *node; purple_debug_info("MSNP14:OIM", "%s\n", xmlmsg); - node = xmlnode_from_str(xmlmsg, -1); + if (!strcmp(xmlmsg, "too-large")) { + /* Too many OIM's to send via NS, so we need to request them via SOAP. */ + msn_oim_get_metadata(oim); + } else { + node = xmlnode_from_str(xmlmsg, -1); + msn_parse_oim_xml(oim, node); + xmlnode_free(node); + } +} + +static void +msn_parse_oim_xml(MsnOim *oim, xmlnode *node) +{ + xmlnode *mNode; + xmlnode *iu_node; + MsnSession *session = oim->session; + + g_return_if_fail(node != NULL); + if (strcmp(node->name, "MD") != 0) { + char *xmlmsg = xmlnode_to_str(node, NULL); purple_debug_info("msnoim", "WTF is this? %s\n", xmlmsg); - xmlnode_free(node); + g_free(xmlmsg); return; } - iu_node = msn_soap_xml_get(node, "E/IU"); + iu_node = xmlnode_get_child(node, "E/IU"); if (iu_node != NULL && purple_account_get_check_mail(session->account)) { @@ -528,8 +598,6 @@ g_free(rtime); g_free(nickname); } - - xmlnode_free(node); } /*Post to get the Offline Instant Message*/ @@ -538,14 +606,24 @@ { char *soap_body; MsnOimRecvData *data = g_new0(MsnOimRecvData, 1); + GHashTable *token; + const char *msn_t; + const char *msn_p; purple_debug_info("MSNP14","Get single OIM Message\n"); + token = msn_nexus_get_token(oim->session->nexus, MSN_AUTH_MESSENGER_WEB); + g_return_if_fail(token != NULL); + + msn_t = g_hash_table_lookup(token, "t"); + msn_p = g_hash_table_lookup(token, "p"); + g_return_if_fail(msn_t != NULL); + g_return_if_fail(msn_p != NULL); + data->oim = oim; data->msg_id = msgid; - soap_body = g_strdup_printf(MSN_OIM_GET_TEMPLATE, - oim->session->passport_info.t, oim->session->passport_info.p, msgid); + soap_body = g_strdup_printf(MSN_OIM_GET_TEMPLATE, msn_t, msn_p, msgid); msn_soap_message_send(oim->session, msn_soap_message_new(MSN_OIM_GET_SOAP_ACTION,
--- a/libpurple/protocols/msn/oim.h Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/oim.h Sat Jun 07 03:10:15 2008 +0000 @@ -25,13 +25,37 @@ #ifndef _MSN_OIM_H_ #define _MSN_OIM_H_ -/*OIM Retrieve SOAP Template*/ +/* OIM Retrieval Info */ #define MSN_OIM_RETRIEVE_HOST "rsi.hotmail.com" #define MSN_OIM_RETRIEVE_URL "/rsi/rsi.asmx" + +/* OIM GetMetadata SOAP Template */ +#define MSN_OIM_GET_METADATA_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMetadata" + +#define MSN_OIM_GET_METADATA_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +"<soap:Envelope"\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ + "<soap:Header>"\ + "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\ + "<t>%s</t>"\ + "<p>%s</p>"\ + "</PassportCookie>"\ + "</soap:Header>"\ + "<soap:Body>"\ + "<GetMetadata xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\" />"\ + "</soap:Body>"\ +"</soap:Envelope>" + +/*OIM GetMessage SOAP Template*/ #define MSN_OIM_GET_SOAP_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMessage" #define MSN_OIM_GET_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ +"<soap:Envelope"\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ "<soap:Header>"\ "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\ "<t>%s</t>"\ @@ -46,15 +70,18 @@ "</soap:Body>"\ "</soap:Envelope>" -/*OIM Delete SOAP Template*/ +/*OIM DeleteMessages SOAP Template*/ #define MSN_OIM_DEL_SOAP_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/DeleteMessages" #define MSN_OIM_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ +"<soap:Envelope"\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ "<soap:Header>"\ "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\ "<t>%s</t>"\ - " <p>%s</p>"\ + "<p>%s</p>"\ "</PassportCookie>"\ "</soap:Header>"\ "<soap:Body>"\ @@ -77,11 +104,21 @@ #define MSN_OIM_SEND_HOST "ows.messenger.msn.com" #define MSN_OIM_SEND_URL "/OimWS/oim.asmx" -#define MSN_OIM_SEND_SOAP_ACTION "http://messenger.msn.com/ws/2004/09/oim/Store" +#define MSN_OIM_SEND_SOAP_ACTION "http://messenger.live.com/ws/2006/09/oim/Store2" #define MSN_OIM_SEND_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ -"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ +"<soap:Envelope"\ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\ + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\ + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\ "<soap:Header>"\ - "<From memberName=\"%s\" friendlyName=\"%s\" xml:lang=\"en-US\" proxy=\"MSNMSGR\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\" msnpVer=\"MSNP14\" buildVer=\"8.0.0792\"/>"\ + "<From"\ + " memberName=\"%s\""\ + " friendlyName=\"%s\""\ + " xml:lang=\"en-US\""\ + " proxy=\"MSNMSGR\""\ + " xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\""\ + " msnpVer=\"MSNP15\""\ + " buildVer=\"8.5.1288\"/>"\ "<To memberName=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\ "<Ticket passport=\"%s\" appid=\"%s\" lockkey=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\ "<Sequence xmlns=\"http://schemas.xmlsoap.org/ws/2003/03/rm\">"\
--- a/libpurple/protocols/msn/session.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/session.c Sat Jun 07 03:10:15 2008 +0000 @@ -45,8 +45,6 @@ purple_account_get_username(account), NULL); session->oim = msn_oim_new(session); - /*if you want to chat with Yahoo Messenger*/ - //session->protocol_ver = WLM_YAHOO_PROT_VER; session->protocol_ver = WLM_PROT_VER; return session; @@ -93,15 +91,13 @@ if (session->nexus != NULL) msn_nexus_destroy(session->nexus); - if (session->contact != NULL) - msn_contact_destroy(session->contact); if (session->oim != NULL) msn_oim_destroy(session->oim); if (session->user != NULL) msn_user_destroy(session->user); - if (session->soap_table) + if (session->soap_table != NULL) g_hash_table_destroy(session->soap_table); if (session->soap_cleanup_handle)
--- a/libpurple/protocols/msn/session.h Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/session.h Sat Jun 07 03:10:15 2008 +0000 @@ -38,7 +38,6 @@ #include "cmdproc.h" #include "nexus.h" #include "httpconn.h" -#include "contact.h" #include "oim.h" #include "userlist.h" @@ -96,7 +95,6 @@ MsnNotification *notification; MsnNexus *nexus; - MsnContact *contact; MsnOim *oim; MsnSync *sync;
--- a/libpurple/protocols/msn/soap.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/soap.c Sat Jun 07 03:10:15 2008 +0000 @@ -841,7 +841,6 @@ "POST %s HTTP/1.1\r\n" "SOAPAction: %s\r\n" "Content-Type:text/xml; charset=utf-8\r\n" - "Cookie: MSPAuth=%s\r\n" "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n" "Accept: */*\r\n" "Host: %s\r\n" @@ -851,7 +850,6 @@ "%s", request->login_path, request->soap_action, - soapconn->session->passport_info.mspauth, request->login_host, strlen(request->body), request->body
--- a/libpurple/protocols/msn/soap2.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/soap2.c Sat Jun 07 03:10:15 2008 +0000 @@ -82,6 +82,7 @@ static void msn_soap_request_destroy(MsnSoapRequest *req); static void msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect); +static gboolean msn_soap_write_cb_internal(gpointer data, gint fd, PurpleInputCondition cond, gboolean initial); static gboolean msn_soap_cleanup_each(gpointer key, gpointer value, gpointer data) @@ -231,6 +232,7 @@ } g_free(faultdata); + msn_soap_message_destroy(response); return TRUE; } else if (g_str_equal(faultdata, "wsse:FailedAuthentication")) { xmlnode *reason = xmlnode_get_child(body, "faultstring"); @@ -242,6 +244,7 @@ g_free(reasondata); g_free(faultdata); + msn_soap_message_destroy(response); return FALSE; } @@ -254,6 +257,7 @@ conn->current_request = NULL; request->cb(request->message, response, request->cb_data); + msn_soap_message_destroy(response); msn_soap_request_destroy(request); } @@ -397,10 +401,8 @@ message->xml = node; if (!msn_soap_handle_body(conn, message)) { - msn_soap_message_destroy(message); return; } - msn_soap_message_destroy(message); } msn_soap_connection_handle_next(conn); @@ -417,27 +419,34 @@ static void msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond) { + msn_soap_write_cb_internal(data, fd, cond, FALSE); +} + +static gboolean +msn_soap_write_cb_internal(gpointer data, gint fd, PurpleInputCondition cond, + gboolean initial) +{ MsnSoapConnection *conn = data; int written; - g_return_if_fail(cond == PURPLE_INPUT_WRITE); + if (cond != PURPLE_INPUT_WRITE) return TRUE; written = purple_ssl_write(conn->ssl, conn->buf->str + conn->handled_len, conn->buf->len - conn->handled_len); if (written < 0 && errno == EAGAIN) - return; + return TRUE; else if (written <= 0) { purple_ssl_close(conn->ssl); conn->ssl = NULL; - msn_soap_connection_handle_next(conn); - return; + if (!initial) msn_soap_connection_handle_next(conn); + return FALSE; } conn->handled_len += written; if (conn->handled_len < conn->buf->len) - return; + return TRUE; /* we are done! */ g_string_free(conn->buf, TRUE); @@ -451,6 +460,7 @@ purple_input_remove(conn->event_handle); conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ, msn_soap_read_cb, conn); + return TRUE; } static gboolean @@ -469,22 +479,15 @@ int len = -1; char *body = xmlnode_to_str(req->message->xml, &len); GSList *iter; - char *authstr = NULL; g_queue_pop_head(conn->queue); conn->buf = g_string_new(""); - if (conn->session->passport_info.mspauth) - authstr = g_strdup_printf("Cookie: MSPAuth=%s\r\n", - conn->session->passport_info.mspauth); - - g_string_append_printf(conn->buf, "POST %s HTTP/1.1\r\n" "SOAPAction: %s\r\n" "Content-Type:text/xml; charset=utf-8\r\n" - "%s" "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n" "Accept: */*\r\n" "Host: %s\r\n" @@ -492,7 +495,7 @@ "Connection: Keep-Alive\r\n" "Cache-Control: no-cache\r\n", req->path, req->message->action ? req->message->action : "", - authstr ? authstr : "", conn->host, len); + conn->host, len); for (iter = req->message->headers; iter; iter = iter->next) { g_string_append(conn->buf, (char *)iter->data); @@ -509,9 +512,18 @@ conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_WRITE, msn_soap_write_cb, conn); - msn_soap_write_cb(conn, conn->ssl->fd, PURPLE_INPUT_WRITE); + if (!msn_soap_write_cb_internal(conn, conn->ssl->fd, PURPLE_INPUT_WRITE, TRUE)) { + /* Not connected => reconnect and retry */ + purple_debug_info("soap", "not connected, reconnecting"); + + conn->connected = FALSE; + conn->current_request = NULL; + msn_soap_connection_sanitize(conn, FALSE); + + g_queue_push_head(conn->queue, req); + conn->event_handle = purple_timeout_add(0, msn_soap_connection_run, conn); + } - g_free(authstr); g_free(body); } } @@ -664,21 +676,3 @@ g_free(req); } -xmlnode * -msn_soap_xml_get(xmlnode *parent, const char *node) -{ - xmlnode *ret = NULL; - char **tokens = g_strsplit(node, "/", -1); - int i; - - for (i = 0; tokens[i]; i++) { - if ((ret = xmlnode_get_child(parent, tokens[i])) != NULL) - parent = ret; - else - break; - } - - g_strfreev(tokens); - return ret; -} -
--- a/libpurple/protocols/msn/soap2.h Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/soap2.h Sat Jun 07 03:10:15 2008 +0000 @@ -53,6 +53,4 @@ void msn_soap_message_destroy(MsnSoapMessage *message); -xmlnode *msn_soap_xml_get(xmlnode *parent, const char *node); - #endif
--- a/libpurple/protocols/msn/userlist.c Sat Jun 07 00:00:34 2008 +0000 +++ b/libpurple/protocols/msn/userlist.c Sat Jun 07 03:10:15 2008 +0000 @@ -24,6 +24,8 @@ #include "msn.h" #include "userlist.h" +#include "contact.h" + const char *lists[] = { "FL", "AL", "BL", "RL" }; typedef struct @@ -51,7 +53,7 @@ msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_AL); - msn_del_contact_from_list(session->contact, NULL, pa->who, MSN_LIST_PL); + msn_del_contact_from_list(session, NULL, pa->who, MSN_LIST_PL); } g_free(pa->who); @@ -75,7 +77,7 @@ msn_callback_state_set_action(state, MSN_DENIED_BUDDY); msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_BL); - msn_del_contact_from_list(session->contact, state, pa->who, MSN_LIST_PL); + msn_del_contact_from_list(session, state, pa->who, MSN_LIST_PL); } g_free(pa->who); @@ -647,7 +649,6 @@ g_return_if_fail(userlist != NULL); g_return_if_fail(userlist->session != NULL); - g_return_if_fail(userlist->session->contact != NULL); g_return_if_fail(who != NULL); user = msn_userlist_find_user(userlist, who); @@ -656,7 +657,7 @@ /* delete the contact from address book via soap action */ if (user != NULL) { - msn_delete_contact(userlist->session->contact, user->uid); + msn_delete_contact(userlist->session, user->uid); } } @@ -758,7 +759,7 @@ /* Add contact in the Contact server with a SOAP request and if successful, send ADL with MSN_LIST_AL and MSN_LIST_FL and a FQY */ - msn_add_contact_to_group(userlist->session->contact, state, who, group_id); + msn_add_contact_to_group(userlist->session, state, who, group_id); } void @@ -859,7 +860,6 @@ g_return_if_fail(userlist != NULL); g_return_if_fail(userlist->session != NULL); - g_return_if_fail(userlist->session->contact != NULL); state = msn_callback_state_new(userlist->session); msn_callback_state_set_who(state, who); @@ -878,7 +878,7 @@ /* add the contact to the new group, and remove it from the old one in * the callback */ - msn_add_contact_to_group(userlist->session->contact, state, who, new_group_id); + msn_add_contact_to_group(userlist->session, state, who, new_group_id); } /*load userlist from the Blist file cache*/