Mercurial > pidgin
changeset 24676:781723b2a170
merge of '08fd5918978aecbd045771fb72fd0d80c7fcf941'
and 'e2dc0cf4e0a3f0c81eb9c91c4d2041e87d2c4c68'
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Wed, 10 Dec 2008 06:51:47 +0000 |
parents | 641fe4c2b2a5 (current diff) 98afd76647bd (diff) |
children | eae0e194658e |
files | ChangeLog pidgin/gtkblist.c pidgin/pixmaps/protocols/16/facebook.png pidgin/pixmaps/protocols/22/facebook.png pidgin/pixmaps/protocols/48/facebook.png pidgin/pixmaps/status/48/rtl/login.png pidgin/pixmaps/status/48/rtl/logout.png |
diffstat | 11 files changed, 534 insertions(+), 142 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Dec 08 02:22:59 2008 +0000 +++ b/ChangeLog Wed Dec 10 06:51:47 2008 +0000 @@ -20,6 +20,9 @@ connected (Paul Aurich) * Fix a crash in purple_accounts_delete that happens when this function is called before the buddy list is initialized (Florian Quèze) + * On MSN, the Games and Office media can now be set and displayed (in + addition to the previous Music media). The Media status text now shows + the album, if possible. Gadu-Gadu: * Fix some problems with Gadu-Gadu buddy icons (Adam Strzelecki)
--- a/libpurple/protocols/msn/contact.c Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/contact.c Wed Dec 10 06:51:47 2008 +0000 @@ -176,28 +176,6 @@ return 0; } -/* get Network */ -/* QuLogic: These names don't really refer to the MsnNetwork, - * but I haven't yet written the code to properly use them. - */ -static MsnNetwork -msn_get_network(char *type) -{ - g_return_val_if_fail(type != NULL, 0); - - if (!strcmp(type,"Regular")) { - return MSN_NETWORK_PASSPORT; - } - if (!strcmp(type,"Live")) { - return MSN_NETWORK_PASSPORT; - } - if (!strcmp(type,"LivePending")) { - return MSN_NETWORK_PASSPORT; - } - - return MSN_NETWORK_UNKNOWN; -} - /* Create the AddressBook in the server, if we don't have one */ static void msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) @@ -245,9 +223,26 @@ char *type = xmlnode_get_data(xmlnode_get_child(member, "Type")); char *member_id = xmlnode_get_data(xmlnode_get_child(member, "MembershipId")); MsnUser *user = msn_userlist_find_add_user(session->userlist, passport, NULL); + xmlnode *annotation; + guint nid = MSN_NETWORK_PASSPORT; - purple_debug_info("msn", "CL: %s name: %s, Type: %s, MembershipID: %s\n", - node, passport, type, member_id == NULL ? "(null)" : member_id); + for (annotation = xmlnode_get_child(member, "Annotations/Annotation"); + annotation; + annotation = xmlnode_get_next_twin(annotation)) { + char *name = xmlnode_get_data(xmlnode_get_child(annotation, "Name")); + if (name && !strcmp(name, "MSN.IM.BuddyType")) { + char *value = xmlnode_get_data(xmlnode_get_child(annotation, "Value")); + if (value != NULL) + nid = strtoul(value, NULL, 10); + g_free(value); + } + g_free(name); + } + + purple_debug_info("msn", "CL: %s name: %s, Type: %s, MembershipID: %s, NetworkID: %u\n", + node, passport, type, member_id == NULL ? "(null)" : member_id, nid); + + msn_user_set_network(user, nid); if (member_id) { user->membership_id[list] = atoi(member_id); @@ -445,16 +440,16 @@ if ((groupInfo = xmlnode_get_child(group, "groupInfo")) && (groupname = xmlnode_get_child(groupInfo, "name"))) group_name = xmlnode_get_data(groupname); - msn_group_new(session->userlist, group_id, group_name); - - if (group_id == NULL){ + if (group_id == NULL) { /* Group of ungroupped buddies */ g_free(group_name); continue; } + msn_group_new(session->userlist, group_id, group_name); + purple_debug_info("msn", "AB group_id: %s, name: %s\n", group_id, group_name ? group_name : "(null)"); - if ((purple_find_group(group_name)) == NULL){ + if ((purple_find_group(group_name)) == NULL) { PurpleGroup *g = purple_group_new(group_name); purple_blist_add_group(g, NULL); } @@ -528,7 +523,6 @@ xmlnode *contactId, *contactInfo, *contactType, *passportName, *displayName, *guid, *groupIds, *messenger_user; xmlnode *annotation; MsnUser *user; - MsnNetwork networkId; if (!(contactId = xmlnode_get_child(contactNode,"contactId")) || !(contactInfo = xmlnode_get_child(contactNode, "contactInfo")) @@ -569,7 +563,6 @@ g_free(is_messenger_user); } - networkId = msn_get_network(type); passportName = xmlnode_get_child(contactInfo, "passportName"); if (passportName == NULL) { xmlnode *emailsNode, *contactEmailNode, *emailNode; @@ -600,7 +593,6 @@ if (msnEnabled && !strcmp(msnEnabled, "true")) { /*Messenger enabled, Get the Passport*/ purple_debug_info("msn", "AB Yahoo User %s\n", passport ? passport : "(null)"); - networkId = MSN_NETWORK_YAHOO; g_free(msnEnabled); break; } else { @@ -628,6 +620,15 @@ name = xmlnode_get_data(xmlnode_get_child(annotation, "Name")); if (!strcmp(name, "AB.NickName")) alias = xmlnode_get_data(xmlnode_get_child(annotation, "Value")); + else if (!strcmp(name, "MSN.IM.HasSharedFolder")) + ; /* Do nothing yet... */ + else if (!strcmp(name, "AB.Spouse")) + ; /* Do nothing yet... */ + else if (!strcmp(name, "MSN.Mobile.ContactId")) + ; /* Do nothing yet... */ + else + purple_debug_info("msn", + "Unknown AB contact annotation: %s\n", name); g_free(name); } @@ -639,7 +640,6 @@ user = msn_userlist_find_add_user(session->userlist, passport, Name); msn_user_set_uid(user, uid); - msn_user_set_network(user, networkId); msn_user_set_mobile_phone(user, mobile_number); groupIds = xmlnode_get_child(contactInfo, "groupIds"); @@ -870,7 +870,7 @@ gpointer data) { MsnCallbackState *state = data; - xmlnode *faultcode; + xmlnode *fault; char *faultcode_str; if (resp == NULL) { @@ -880,9 +880,9 @@ return; } - faultcode = xmlnode_get_child(resp->xml, "Body/Fault/faultcode"); + fault = xmlnode_get_child(resp->xml, "Body/Fault"); - if (faultcode == NULL) { + if (fault == NULL) { /* No errors */ if (state->cb) ((MsnSoapCallback)state->cb)(req, resp, data); @@ -890,7 +890,7 @@ return; } - faultcode_str = xmlnode_get_data(faultcode); + faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode")); if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) { purple_debug_info("msn", @@ -903,12 +903,15 @@ } else { - /* We don't know how to respond to this faultcode, so just log it */ - /* XXX: Probably should notify the user or undo the change or something? */ - char *str = xmlnode_to_str(xmlnode_get_child(resp->xml, "Body/Fault"), NULL); - purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", - msn_contact_operation_str(state->action), str); - g_free(str); + if (state->cb) { + ((MsnSoapCallback)state->cb)(req, resp, data); + } else { + /* We don't know how to respond to this faultcode, so log it */ + char *str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), str); + g_free(str); + } msn_callback_state_free(state); } @@ -943,21 +946,44 @@ MsnUser *user; xmlnode *guid; + xmlnode *fault; + g_return_if_fail(session != NULL); + userlist = session->userlist; + + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode")); + if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) { + /* Do something special! */ + purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n"); - userlist = session->userlist; + } else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) { + PurpleBuddy *buddy = purple_find_buddy(session->account, state->who); + char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who); + purple_notify_error(state->session, _("Buddy Add error"), str, + _("The username specified does not exist.")); + g_free(str); + msn_userlist_rem_buddy(userlist, state->who); + if (buddy != NULL) + purple_blist_remove_buddy(buddy); + + } else { + /* We don't know how to respond to this faultcode, so log it */ + char *fault_str = xmlnode_to_str(fault, NULL); + if (fault_str != NULL) { + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + } + } + return; + } purple_debug_info("msn", "Contact added successfully\n"); - /* the code this block is replacing didn't send ADL for yahoo contacts, - * but i haven't confirmed this is WLM's behaviour wrt yahoo contacts - */ - if ( !msn_user_is_yahoo(session->account, state->who) ) { - msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL); - msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL); - } - - msn_notification_send_fqy(session, state->who); + msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL); + msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL); user = msn_userlist_find_add_user(userlist, state->who, state->who); msn_user_add_group_id(user, state->guid); @@ -976,6 +1002,7 @@ void msn_add_contact(MsnSession *session, MsnCallbackState *state, const char *passport) { + MsnUser *user; gchar *body = NULL; gchar *contact_xml = NULL; @@ -993,7 +1020,21 @@ purple_debug_info("msn", "Adding contact %s to contact list\n", passport); - contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport); + user = msn_userlist_find_user(session->userlist, passport); + if (user == NULL) { + purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport); + return; /* guess this never happened! */ + } + + if (user->networkid != MSN_NETWORK_PASSPORT) { + contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML, + user->networkid == MSN_NETWORK_YAHOO ? + "Messenger2" : + "Messenger3", + passport, 0); + } else { + contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport); + } body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE, contact_xml); state->body = xmlnode_from_str(body, -1); @@ -1011,11 +1052,41 @@ gpointer data) { MsnCallbackState *state = data; + MsnSession *session = state->session; MsnUserList *userlist; + xmlnode *fault; + + g_return_if_fail(session != NULL); + userlist = session->userlist; + + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode")); + if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) { + /* Do something special! */ + purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n"); - g_return_if_fail(data != NULL); + } else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) { + PurpleBuddy *buddy = purple_find_buddy(session->account, state->who); + char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who); + purple_notify_error(session, _("Buddy Add error"), str, + _("The username specified does not exist.")); + g_free(str); + msn_userlist_rem_buddy(userlist, state->who); + if (buddy != NULL) + purple_blist_remove_buddy(buddy); - userlist = state->session->userlist; + } else { + /* We don't know how to respond to this faultcode, so log it */ + char *fault_str = xmlnode_to_str(fault, NULL); + if (fault_str != NULL) { + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + } + } + return; + } if (msn_userlist_add_buddy_to_group(userlist, state->who, state->new_group_name)) { @@ -1036,11 +1107,8 @@ g_free(uid); } - if ( !msn_user_is_yahoo(state->session->account, state->who) ) { - msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL); - msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL); - } - msn_notification_send_fqy(state->session, state->who); + msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL); + msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL); if (msn_userlist_user_is_in_list(user, MSN_LIST_PL)) { msn_del_contact_from_list(state->session, NULL, state->who, MSN_LIST_PL); @@ -1095,8 +1163,14 @@ return; /* guess this never happened! */ } - if (user != NULL && user->uid != NULL) { + if (user->uid != NULL) { contact_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid); + } else if (user->networkid != MSN_NETWORK_PASSPORT) { + contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML, + user->networkid == MSN_NETWORK_YAHOO ? + "Messenger2" : + "Messenger3", + passport, 0); } else { contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport); } @@ -1120,6 +1194,17 @@ MsnCallbackState *state = data; MsnUserList *userlist = state->session->userlist; MsnUser *user = msn_userlist_find_user_with_id(userlist, state->uid); + xmlnode *fault; + + /* We don't know how to respond to this faultcode, so log it */ + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *fault_str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + return; + } purple_debug_info("msn", "Delete contact successful\n"); @@ -1140,8 +1225,8 @@ contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid); purple_debug_info("msn", "Deleting contact with contactId: %s\n", user->uid); } else { - contact_id_xml = g_strdup_printf(MSN_CONTACT_XML, user->passport); - purple_debug_info("msn", "Deleting contact with passport: %s\n", user->passport); + purple_debug_info("msn", "Unable to delete contact %s without a ContactId\n", user->passport); + return; } state = msn_callback_state_new(session); @@ -1165,6 +1250,17 @@ gpointer data) { MsnCallbackState *state = data; + xmlnode *fault; + + /* We don't know how to respond to this faultcode, so log it */ + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *fault_str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + return; + } if (msn_userlist_rem_buddy_from_group(state->session->userlist, state->who, state->old_group_name)) { @@ -1235,6 +1331,19 @@ msn_update_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { + MsnCallbackState *state = (MsnCallbackState *)data; + xmlnode *fault; + + /* We don't know how to respond to this faultcode, so log it */ + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *fault_str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + return; + } + purple_debug_info("msn", "Contact updated successfully\n"); } @@ -1312,6 +1421,17 @@ { MsnCallbackState *state = data; MsnSession *session = state->session; + xmlnode *fault; + + /* We don't know how to respond to this faultcode, so log it */ + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *fault_str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + return; + } purple_debug_info("msn", "Contact %s deleted successfully from %s list on server!\n", state->who, MsnMemberRole[state->list_id]); @@ -1339,10 +1459,13 @@ const gchar *passport, const MsnListId list) { gchar *body = NULL, *member = NULL; + const char *type = "PassportMember"; + gchar *federate = NULL; MsnSoapPartnerScenario partner_scenario; MsnUser *user; g_return_if_fail(session != NULL); + g_return_if_fail(session->userlist != NULL); g_return_if_fail(passport != NULL); g_return_if_fail(list < 5); @@ -1354,21 +1477,27 @@ msn_callback_state_set_list_id(state, list); msn_callback_state_set_who(state, passport); + user = msn_userlist_find_user(session->userlist, passport); + if (user && user->networkid != MSN_NETWORK_PASSPORT) { + type = "EmailMember"; + federate = g_strdup_printf(MSN_MEMBER_FEDERATED_ANNOTATION_XML, + user->networkid); + } + if (list == MSN_LIST_PL) { - g_return_if_fail(session->userlist != NULL); - - 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]); + member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML, + type, user->membership_id[MSN_LIST_PL], + federate ? federate : ""); } else { /* list == MSN_LIST_AL || list == MSN_LIST_BL */ partner_scenario = MSN_PS_BLOCK_UNBLOCK; - - member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML, passport); + member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML, + type, passport, + federate ? federate : ""); } - body = g_strdup_printf(MSN_CONTACT_DELECT_FROM_LIST_TEMPLATE, + body = g_strdup_printf(MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE, MsnSoapPartnerScenarioText[partner_scenario], MsnMemberRole[list], member); @@ -1378,6 +1507,7 @@ state->cb = msn_del_contact_from_list_read_cb; msn_contact_request(state); + g_free(federate); g_free(member); g_free(body); } @@ -1387,8 +1517,18 @@ gpointer data) { MsnCallbackState *state = data; + xmlnode *fault; - g_return_if_fail(state != NULL); + /* We don't know how to respond to this faultcode, so log it */ + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *fault_str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + return; + } + g_return_if_fail(state->session != NULL); purple_debug_info("msn", "Contact %s added successfully to %s list on server!\n", state->who, MsnMemberRole[state->list_id]); @@ -1415,7 +1555,10 @@ const gchar *passport, const MsnListId list) { gchar *body = NULL, *member = NULL; + const char *type = "PassportMember"; + gchar *federate = NULL; MsnSoapPartnerScenario partner_scenario; + MsnUser *user; g_return_if_fail(session != NULL); g_return_if_fail(passport != NULL); @@ -1429,9 +1572,16 @@ msn_callback_state_set_list_id(state, list); msn_callback_state_set_who(state, passport); - partner_scenario = (list == MSN_LIST_RL) ? MSN_PS_CONTACT_API : MSN_PS_BLOCK_UNBLOCK; + user = msn_userlist_find_user(session->userlist, passport); + if (user && user->networkid != MSN_NETWORK_PASSPORT) { + type = "EmailMember"; + federate = g_strdup_printf(MSN_MEMBER_FEDERATED_ANNOTATION_XML, + user->networkid); + } - member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML, state->who); + partner_scenario = (list == MSN_LIST_RL) ? MSN_PS_CONTACT_API : MSN_PS_BLOCK_UNBLOCK; + member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML, + type, state->who, federate ? federate : ""); body = g_strdup_printf(MSN_CONTACT_ADD_TO_LIST_TEMPLATE, MsnSoapPartnerScenarioText[partner_scenario], @@ -1443,6 +1593,7 @@ state->cb = msn_add_contact_to_list_read_cb; msn_contact_request(state); + g_free(federate); g_free(member); g_free(body); } @@ -1482,6 +1633,17 @@ MsnCallbackState *state = data; MsnSession *session; MsnUserList *userlist; + xmlnode *fault; + + /* We don't know how to respond to this faultcode, so log it */ + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *fault_str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + return; + } purple_debug_info("msn", "Group request successful.\n"); @@ -1661,3 +1823,4 @@ g_free(escaped_group_name); g_free(body); } +
--- a/libpurple/protocols/msn/contact.h Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/contact.h Wed Dec 10 06:51:47 2008 +0000 @@ -211,6 +211,27 @@ "</contactInfo>"\ "</Contact>" +#define MSN_CONTACT_ID_XML \ + "<Contact>"\ + "<contactId>%s</contactId>"\ + "</Contact>" + +#define MSN_CONTACT_EMAIL_XML \ + "<Contact>"\ + "<contactInfo>"\ + "<emails>"\ + "<ContactEmail>"\ + "<contactEmailType>%s</contactEmailType>"\ + "<email>%s</email>"\ + "<isMessengerEnabled>true</isMessengerEnabled>"\ + "<Capability>%d</Capability>"\ + "<MessengerEnabledExternally>false</MessengerEnabledExternally>"\ + "<propertiesChanged/>"\ + "</ContactEmail>"\ + "</emails>"\ + "</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\""\ @@ -275,7 +296,6 @@ /* 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/\""\ @@ -376,22 +396,32 @@ #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\">"\ + "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\ "<Type>Passport</Type>"\ "<State>Accepted</State>"\ "<PassportName>%s</PassportName>"\ + "%s"\ "</Member>" #define MSN_MEMBER_MEMBERSHIPID_XML \ - "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"PassportMember\">"\ + "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\ "<Type>Passport</Type>"\ "<MembershipId>%u</MembershipId>"\ "<State>Accepted</State>"\ + "%s"\ "</Member>" +#define MSN_MEMBER_FEDERATED_ANNOTATION_XML \ + "<Annotations>"\ + "<Annotation>"\ + "<Name>MSN.IM.BuddyType</Name>"\ + "<Value>%02d:</Value>"\ + "</Annotation>"\ + "</Annotations>" + /* first delete contact from allow list */ -#define MSN_CONTACT_DELECT_FROM_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\ +#define MSN_CONTACT_DELETE_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\""\
--- a/libpurple/protocols/msn/msn.c Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/msn.c Wed Dec 10 06:51:47 2008 +0000 @@ -647,25 +647,41 @@ presence = purple_buddy_get_presence(buddy); status = purple_presence_get_active_status(presence); - /* I think status message should take precedence over media */ - msg = purple_status_get_attr_string(status, "message"); - if (msg && *msg) - return g_markup_escape_text(msg, -1); - if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { - const char *title, *artist; + const char *title, *game, *office; char *media, *esc; status = purple_presence_get_status(presence, "tune"); title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE); - artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); - - media = g_strdup_printf("%s%s%s", title, artist ? " - " : "", - artist ? artist : ""); + + game = purple_status_get_attr_string(status, "game"); + office = purple_status_get_attr_string(status, "office"); + + if (title && *title) { + const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); + const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM); + media = g_strdup_printf("%s%s%s%s%s%s", title, + (artist && *artist) ? " - " : "", + (artist && *artist) ? artist : "", + (album && *album) ? " (" : "", + (album && *album) ? album : "", + (album && *album) ? ")" : ""); + } + else if (game && *game) + media = g_strdup_printf("Playing %s", game); + else if (office && *office) + media = g_strdup_printf("Editing %s", office); + else + return NULL; esc = g_markup_escape_text(media, -1); g_free(media); return esc; } + /* Official client says media takes precedence over message */ + msg = purple_status_get_attr_string(status, "message"); + if (msg && *msg) + return g_markup_escape_text(msg, -1); + return NULL; } @@ -681,6 +697,7 @@ if (purple_presence_is_online(presence)) { const char *psm, *name; + const char *mediatype = NULL; char *currentmedia = NULL; char *tmp; @@ -688,10 +705,20 @@ if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { PurpleStatus *tune = purple_presence_get_status(presence, "tune"); const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE); - const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST); - const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM); - currentmedia = purple_util_format_song_info(title, artist, album, NULL); - /* We could probably just use user->media.title etc. here */ + const char *game = purple_status_get_attr_string(tune, "game"); + const char *office = purple_status_get_attr_string(tune, "office"); + if (title && *title) { + const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST); + const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM); + mediatype = _("Now Listening"); + currentmedia = purple_util_format_song_info(title, artist, album, NULL); + } else if (game && *game) { + mediatype = _("Playing a game"); + currentmedia = g_strdup(game); + } else if (office && *office) { + mediatype = _("Working"); + currentmedia = g_strdup(office); + } } if (!purple_status_is_available(status)) { @@ -745,7 +772,7 @@ } if (currentmedia) { - purple_notify_user_info_add_pair(user_info, _("Now Listening"), currentmedia); + purple_notify_user_info_add_pair(user_info, mediatype, currentmedia); g_free(currentmedia); } } @@ -840,6 +867,8 @@ PURPLE_TUNE_ARTIST, _("Artist"), purple_value_new(PURPLE_TYPE_STRING), PURPLE_TUNE_ALBUM, _("Album"), purple_value_new(PURPLE_TYPE_STRING), PURPLE_TUNE_TITLE, _("Title"), purple_value_new(PURPLE_TYPE_STRING), + "game", _("Game Title"), purple_value_new(PURPLE_TYPE_STRING), + "office", _("Office Title"), purple_value_new(PURPLE_TYPE_STRING), NULL); types = g_list_append(types, status); @@ -1414,21 +1443,18 @@ purple_debug_info("msn", "msn_add_buddy: %s\n", who); #endif -#if 0 - /* Which is the max? */ - if (session->fl_users_count >= 150) - { - purple_debug_info("msn", "Too many buddies\n"); - /* Buddy list full */ - /* TODO: purple should be notified of this */ - return; - } -#endif - /* XXX - Would group ever be NULL here? I don't think so... * shx: Yes it should; MSN handles non-grouped buddies, and this is only * internal. */ - msn_userlist_add_buddy(userlist, who, group ? group->name : NULL); + if (msn_userlist_find_user(userlist, who) != NULL) { + /* We already know this buddy. This function takes care of users + already in the list and stuff... */ + msn_userlist_add_buddy(userlist, who, group ? group->name : NULL); + } else { + /* We need to check the network for this buddy first */ + msn_userlist_save_pending_buddy(userlist, who, group ? group->name : NULL); + msn_notification_send_fqy(session, who); + } } static void
--- a/libpurple/protocols/msn/notification.c Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/notification.c Wed Dec 10 06:51:47 2008 +0000 @@ -849,10 +849,35 @@ fqy_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) { - purple_debug_info("msn", "FQY payload:\n%s\n", payload); - g_return_if_fail(cmdproc->session != NULL); -/* msn_notification_post_adl(cmdproc, payload, len); */ -/* msn_get_address_book(cmdproc->session, MSN_AB_SAVE_CONTACT, NULL, NULL); */ + MsnUserList *userlist; + xmlnode *ml, *d, *c; + const char *domain; + const char *local; + const char *type; + char *passport; + MsnNetwork network = MSN_NETWORK_PASSPORT; + + userlist = cmdproc->session->userlist; + + /* FQY response: + <ml><d n="domain.com"><c n="local-node" t="network" /></d></ml> */ + ml = xmlnode_from_str(payload, len); + d = xmlnode_get_child(ml, "d"); + c = xmlnode_get_child(d, "c"); + domain = xmlnode_get_attrib(d, "n"); + local = xmlnode_get_attrib(c, "n"); + type = xmlnode_get_attrib(c, "t"); + + passport = g_strdup_printf("%s@%s", local, domain); + + if (type != NULL) + network = (MsnNetwork)strtoul(type, NULL, 10); + purple_debug_info("msn", "FQY response says %s is from network %d\n", + passport, network); + msn_userlist_add_pending_buddy(userlist, passport, network); + + g_free(passport); + xmlnode_free(ml); } static void @@ -1578,7 +1603,7 @@ MsnUser *user; const char *passport; char *psm_str, *str; - CurrentMedia media = {NULL, NULL, NULL}; + CurrentMedia media = {CURRENT_MEDIA_UNKNOWN, NULL, NULL, NULL}; session = cmdproc->session; account = session->account;
--- a/libpurple/protocols/msn/state.c Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/state.c Wed Dec 10 06:51:47 2008 +0000 @@ -100,14 +100,15 @@ cmedia_array = g_strsplit(cmedia, "\\0", 0); /* - * 0: Media Player - * 1: 'Music' + * 0: Application + * 1: 'Music'/'Games'/'Office' * 2: '1' if enabled, '0' if not * 3: Format (eg. {0} by {1}) * 4: Title - * 5: Artist - * 6: Album - * 7: ? + * If 'Music': + * 5: Artist + * 6: Album + * 7: ? */ #if GLIB_CHECK_VERSION(2,6,0) strings = g_strv_length(cmedia_array); @@ -118,6 +119,15 @@ if (strings >= 4 && !strcmp(cmedia_array[2], "1")) { parsed = TRUE; + if (!strcmp(cmedia_array[1], "Music")) + media->type = CURRENT_MEDIA_MUSIC; + else if (!strcmp(cmedia_array[1], "Games")) + media->type = CURRENT_MEDIA_GAMES; + else if (!strcmp(cmedia_array[1], "Office")) + media->type = CURRENT_MEDIA_OFFICE; + else + media->type = CURRENT_MEDIA_UNKNOWN; + g_free(media->title); if (strings == 4) { media->title = g_strdup(cmedia_array[3]); @@ -199,21 +209,33 @@ static char * create_media_string(PurplePresence *presence) { - const char *artist, *title, *album; + const char *title, *game, *office; char *ret; PurpleStatus *status = purple_presence_get_status(presence, "tune"); if (!status || !purple_status_is_active(status)) - return g_strdup_printf("WMP\\0Music\\00\\0{0} - {1}\\0\\0\\0\\0\\0"); + return g_strdup_printf("\\0Music\\00\\0\\0"); - artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE); - album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM); + game = purple_status_get_attr_string(status, "game"); + office = purple_status_get_attr_string(status, "office"); - ret = g_strdup_printf("WMP\\0Music\\0%c\\0{0} - {1}\\0%s\\0%s\\0%s\\0\\0", - (title && *title) ? '1' : '0', - title ? title : "", - artist ? artist : "", - album ? album : ""); + if (title && *title) { + const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); + const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM); + ret = g_strdup_printf("WMP\\0Music\\01\\0{0}%s%s\\0%s\\0%s\\0%s\\0", + artist ? " - {1}" : "", + album ? " ({2})" : "", + title, + artist ? artist : "", + album ? album : ""); + } + else if (game && *game) + ret = g_strdup_printf("\\0Games\\01\\0Playing {0}\\0%s\\0", game); + else if (office && *office) + ret = g_strdup_printf("\\0Office\\01\\0Editing {0}\\0%s\\0", office); + else + ret = g_strdup_printf("\\0Music\\00\\0\\0"); + return ret; }
--- a/libpurple/protocols/msn/user.c Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/user.c Wed Dec 10 06:51:47 2008 +0000 @@ -106,12 +106,25 @@ purple_prpl_got_user_status_deactive(account, user->passport, "mobile"); } - if (!offline && user->media.title) { - purple_prpl_got_user_status(account, user->passport, "tune", - PURPLE_TUNE_ARTIST, user->media.artist, - PURPLE_TUNE_ALBUM, user->media.album, - PURPLE_TUNE_TITLE, user->media.title, - NULL); + if (!offline && user->media.type != CURRENT_MEDIA_UNKNOWN) { + if (user->media.type == CURRENT_MEDIA_MUSIC) { + purple_prpl_got_user_status(account, user->passport, "tune", + PURPLE_TUNE_ARTIST, user->media.artist, + PURPLE_TUNE_ALBUM, user->media.album, + PURPLE_TUNE_TITLE, user->media.title, + NULL); + } else if (user->media.type == CURRENT_MEDIA_GAMES) { + purple_prpl_got_user_status(account, user->passport, "tune", + "game", user->media.title, + NULL); + } else if (user->media.type == CURRENT_MEDIA_OFFICE) { + purple_prpl_got_user_status(account, user->passport, "tune", + "office", user->media.title, + NULL); + } else { + purple_debug_warning("msn", "Got CurrentMedia with unknown type %d.\n", + user->media.type); + } } else { purple_prpl_got_user_status_deactive(account, user->passport, "tune"); } @@ -191,6 +204,7 @@ g_free(user->media.album); g_free(user->media.artist); + user->media.type = media ? media->type : CURRENT_MEDIA_UNKNOWN; user->media.title = media ? g_strdup(media->title) : NULL; user->media.artist = media ? g_strdup(media->artist) : NULL; user->media.album = media ? g_strdup(media->album) : NULL; @@ -326,6 +340,20 @@ } void +msn_user_set_pending_group(MsnUser *user, const char *group) +{ + user->pending_group = g_strdup(group); +} + +char * +msn_user_remove_pending_group(MsnUser *user) +{ + char *group = user->pending_group; + user->pending_group = NULL; + return group; +} + +void msn_user_set_home_phone(MsnUser *user, const char *number) { g_return_if_fail(user != NULL);
--- a/libpurple/protocols/msn/user.h Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/user.h Wed Dec 10 06:51:47 2008 +0000 @@ -45,11 +45,20 @@ /** * Current media. */ +typedef enum +{ + CURRENT_MEDIA_UNKNOWN, + CURRENT_MEDIA_MUSIC, + CURRENT_MEDIA_GAMES, + CURRENT_MEDIA_OFFICE +} CurrentMediaType; + typedef struct _CurrentMedia { + CurrentMediaType type; /**< Type. */ + char *title; /**< Title. */ char *artist; /**< Artist. */ char *album; /**< Album. */ - char *title; /**< Title. */ } CurrentMedia; /** @@ -82,6 +91,7 @@ gboolean mobile; /**< Signed up with MSN Mobile. */ GList *group_ids; /**< The group IDs. */ + char *pending_group; /**< A pending group to add. */ MsnObject *msnobj; /**< The user's MSN Object. */ @@ -204,6 +214,23 @@ void msn_user_remove_group_id(MsnUser *user, const char * id); /** + * Sets the pending group for a user. + * + * @param user The user. + * @param group The group name. + */ +void msn_user_set_pending_group(MsnUser *user, const char *group); + +/** + * Removes the pending group from a user. + * + * @param user The user. + * + * @return Returns the pending group name. + */ +char *msn_user_remove_pending_group(MsnUser *user); + +/** * Sets the home phone number for a user. * * @param user The user.
--- a/libpurple/protocols/msn/userlist.c Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/userlist.c Wed Dec 10 06:51:47 2008 +0000 @@ -184,10 +184,6 @@ { msn_user_add_group_id(user, group_id); } - else - { - /* session->sync->fl_users_count++; */ - } } else if (list_id == MSN_LIST_AL) { @@ -253,10 +249,6 @@ msn_user_remove_group_id(user, group_id); return; } - else - { - /* session->sync->fl_users_count--; */ - } } else if (list_id == MSN_LIST_AL) { @@ -756,6 +748,62 @@ msn_add_contact_to_group(userlist->session, state, who, group_id); } +/* + * Save a buddy address/group until we get back response from FQY + */ +void +msn_userlist_save_pending_buddy(MsnUserList *userlist, + const char *who, + const char *group_name) +{ + MsnUser *user; + + g_return_if_fail(userlist != NULL); + + user = msn_user_new(userlist, who, NULL); + msn_user_set_pending_group(user, group_name); + msn_user_set_network(user, MSN_NETWORK_UNKNOWN); + userlist->pending = g_list_prepend(userlist->pending, user); +} + +/* + * Actually adds a buddy once we have the response from FQY + */ +void +msn_userlist_add_pending_buddy(MsnUserList *userlist, + const char *who, + /*MsnNetwork*/ int network) +{ + MsnUser *user = NULL; + GList *l; + char *group; + + for (l = userlist->pending; l != NULL; l = l->next) + { + user = (MsnUser *)l->data; + + if (!g_strcasecmp(who, user->passport)) { + userlist->pending = g_list_delete_link(userlist->pending, l); + break; + } + } + + if (user == NULL) { + purple_debug_error("msn", "Attempting to add a pending user that does not exist.\n"); + return; + } + + /* Bit of a hack, but by adding to userlist now, the rest of the code + * will know what network to use. + */ + msn_user_set_network(user, network); + msn_userlist_add_user(userlist, user); + + group = msn_user_remove_pending_group(user); + msn_userlist_add_buddy(userlist, who, group); + g_free(group); +} + void msn_userlist_add_buddy_to_list(MsnUserList *userlist, const char *who, MsnListId list_id)
--- a/libpurple/protocols/msn/userlist.h Mon Dec 08 02:22:59 2008 +0000 +++ b/libpurple/protocols/msn/userlist.h Wed Dec 10 06:51:47 2008 +0000 @@ -47,13 +47,12 @@ GList *users; /* Contains MsnUsers */ GList *groups; /* Contains MsnGroups */ + GList *pending; /* MsnUsers pending addition (waiting for FQY response) */ GQueue *buddy_icon_requests; int buddy_icon_window; guint buddy_icon_request_timer; - int fl_users_count; - }; gboolean msn_userlist_user_is_in_group(MsnUser *user, const char * group_id); @@ -93,6 +92,12 @@ void msn_userlist_rem_buddy(MsnUserList *userlist, const char *who); void msn_userlist_add_buddy(MsnUserList *userlist, const char *who, const char *group_name); +void msn_userlist_save_pending_buddy(MsnUserList *userlist, + const char *who, + const char *group_name); +void msn_userlist_add_pending_buddy(MsnUserList *userlist, + const char *who, + /*MsnNetwork*/ int network); void msn_userlist_move_buddy(MsnUserList *userlist, const char *who, const char *old_group_name, const char *new_group_name);
--- a/pidgin/gtkblist.c Mon Dec 08 02:22:59 2008 +0000 +++ b/pidgin/gtkblist.c Wed Dec 10 06:51:47 2008 +0000 @@ -3630,6 +3630,7 @@ const char *name = NULL; char *filename, *path; PurplePresence *p; + PurpleStatus *tune; if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { if(!gtknode->contact_expanded) { @@ -3668,7 +3669,21 @@ return _pidgin_blist_get_cached_emblem(path); } - if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) { + tune = purple_presence_get_status(p, "tune"); + if (tune && purple_status_is_active(tune)) { + /* Only in MSN. + * TODO: Replace "Tune" with generalized "Media" in 3.0. */ + if (purple_status_get_attr_string(tune, "game") != NULL) { + path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "game.png", NULL); + return _pidgin_blist_get_cached_emblem(path); + } + /* Only in MSN. + * TODO: Replace "Tune" with generalized "Media" in 3.0. */ + if (purple_status_get_attr_string(tune, "office") != NULL) { + path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "office.png", NULL); + return _pidgin_blist_get_cached_emblem(path); + } + /* Regular old "tune" is the only one in all protocols. */ path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "music.png", NULL); return _pidgin_blist_get_cached_emblem(path); }