# HG changeset patch # User Richard Laager # Date 1176611396 0 # Node ID 6f986caeab59cafb908d5007dcbe013373198a39 # Parent 60bc0649874626261e590abc3ee04c79cb419085# Parent 61d6a3dfbb3ca2d61c352ba0c80b2470a42c6340 merge of 'b4911943cba6f29cf0694dfd563cac17612236dc' and 'c28931a50bfa21e0be81777bcd91fdeab9116d77' diff -r 60bc06498746 -r 6f986caeab59 libpurple/internal.h --- a/libpurple/internal.h Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/internal.h Sun Apr 15 04:29:56 2007 +0000 @@ -75,6 +75,7 @@ #ifndef _WIN32 #include #include +#include #endif #include #include diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/msn/README Sun Apr 15 04:29:56 2007 +0000 @@ -0,0 +1,55 @@ +MSNP14 Implementation +by Ma Yuan + +1. Introduction +------------- + +MSNP14 Protocol, proposed by Windows Live Messenger, is new, and there is no available implementation except the official one on Windows Platform. + +It has introduced many new features attractable to many users, such as: +* Offline Instant Message + You can send the offline Message to the offline User, + The message will be posted to that user the next time when he is online. + +* Communicate with Yahoo User + U can chat with the Yahoo User in MSN, That's Fantastic! Till now , + you can send text/Nudge to Yahoo User. + +* Windows Live ID authentition + WLM use the Window Live ID Authentication process,Known as Passport 3.0, + The procedure is totally different to the previous Passport 2.0 + +* Video/Audio Conversation + U can communicate with other's via Video/Audio. +(Though very interesting, not implemented in this version) + +2.New Features Added +----------------- + +Till now, This project has implemented the following Feature: +* Windows Live ID authentication. + +* Offline Instant Message +Now can send and receive the Offline Instant Message to MSN user and Yahoo User. + +*contact management +Can add/delete Contact +Can add/delete Group + +* Communicate with Yahoo User +Can send/receive Message/Nudge to Yahoo User. + +*. Changes to made to fit MSNP14 Protocol + +3. Reference +------------- + +The very useful sites of MSN Protocol: +MSNpiki site: +reverse engineer of MSN Protocol.up to dated. +http://msnpiki.msnfanatic.com/index.php/MSN_Protocol_Version_13 + +hypothetic site: +old MSN Protocol Introduction,but very useful for basic idea of MSN protocol +http://www.hypothetic.org/docs/msn/index.php + diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/cmdproc.c diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/command.c --- a/libpurple/protocols/msn/command.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/command.c Sun Apr 15 04:29:56 2007 +0000 @@ -138,7 +138,9 @@ param = cmd->params[0]; cmd->trId = is_num(param) ? atoi(param) : 0; - }else{ + } + else + { cmd->trId = 0; } diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/contact.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/msn/contact.c Sun Apr 15 04:29:56 2007 +0000 @@ -0,0 +1,879 @@ +/** + * @file contact.c + * get MSN contacts via SOAP request + * created by MaYuan + * + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "msn.h" +#include "soap.h" +#include "contact.h" +#include "xmlnode.h" +#include "group.h" + +/*define This to debug the Contact Server*/ +#undef MSN_CONTACT_SOAP_DEBUG + +/*new a contact*/ +MsnContact * +msn_contact_new(MsnSession *session) +{ + MsnContact *contact; + + contact = g_new0(MsnContact, 1); + contact->session = session; + contact->soapconn = msn_soap_new(session,contact,1); + + return contact; +} + +/*destroy the contact*/ +void +msn_contact_destroy(MsnContact *contact) +{ + msn_soap_destroy(contact->soapconn); + g_free(contact); +} + +/*contact SOAP server login error*/ +static void +msn_contact_login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) +{ + MsnSoapConn *soapconn = data; + MsnSession *session; + + session = soapconn->session; + g_return_if_fail(session != NULL); + + msn_session_set_error(session, MSN_ERROR_SERV_DOWN, _("Unable to connect to contact server")); +} + +/*msn contact SOAP server connect process*/ +static void +msn_contact_login_connect_cb(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + MsnSoapConn *soapconn = data; + MsnSession * session; + MsnContact *contact; + + contact = soapconn->parent; + g_return_if_fail(contact != NULL); + + session = contact->session; + g_return_if_fail(session != NULL); + + /*login ok!We can retrieve the contact list*/ +// msn_get_contact_list(contact,NULL); +} + +/*get MSN member role utility*/ +static int +msn_get_memberrole(char * role) +{ + if(!strcmp(role,"Allow")){ + return MSN_LIST_AL_OP; + }else if(!strcmp(role,"Block")){ + return MSN_LIST_BL_OP; + }else if(!strcmp(role,"Reverse")){ + return MSN_LIST_RL_OP; + } + return 0; +} + +/*get User Type*/ +static int +msn_get_user_type(char * type) +{ + if(!strcmp(type,"Regular")){ + return 1; + } + if(!strcmp(type,"Live")){ + return 1; + } + if(!strcmp(type,"LivePending")){ + return 1; + } + + return 0; +} + +/*parse contact list*/ +static void +msn_parse_contact_list(MsnContact * contact) +{ + MsnSession * session; + int list_op =0; + char * passport; + xmlnode * node,*body,*response,*result,*services; + xmlnode *service,*memberships; + xmlnode *LastChangeNode; + xmlnode *membershipnode,*members,*member,*passportNode; + char *LastChangeStr; + + session = contact->session; + gaim_debug_misc("MSNCL","parse contact list:{%s}\nsize:%d\n",contact->soapconn->body,contact->soapconn->body_len); + node = xmlnode_from_str(contact->soapconn->body, contact->soapconn->body_len); + + if(node == NULL){ + gaim_debug_misc("MSNCL","parse contact from str err!\n"); + return; + } + gaim_debug_misc("MSNCL","node{%p},name:%s,child:%s,last:%s\n",node,node->name,node->child->name,node->lastchild->name); + body = xmlnode_get_child(node,"Body"); + gaim_debug_misc("MSNCL","body{%p},name:%s\n",body,body->name); + response = xmlnode_get_child(body,"FindMembershipResponse"); + + if (response == NULL) { + /* we may get a response if our cache data is too old: + * + * Need to do full sync. Can't sync deltas Client + * has too old a copy for us to do a delta sync + */ + msn_get_contact_list(contact, NULL); + return; + } + + gaim_debug_misc("MSNCL","response{%p},name:%s\n",response,response->name); + result =xmlnode_get_child(response,"FindMembershipResult"); + if(result == NULL){ + gaim_debug_misc("MSNCL","receive No Update!\n"); + return; + } + gaim_debug_misc("MSNCL","result{%p},name:%s\n",result,result->name); + services =xmlnode_get_child(result,"Services"); + gaim_debug_misc("MSNCL","services{%p},name:%s\n",services,services->name); + service =xmlnode_get_child(services,"Service"); + gaim_debug_misc("MSNCL","service{%p},name:%s\n",service,service->name); + + /*Last Change Node*/ + LastChangeNode = xmlnode_get_child(service,"LastChange"); + LastChangeStr = xmlnode_get_data(LastChangeNode); + gaim_debug_misc("MSNCL","LastChangeNode0 %s\n",LastChangeStr); + gaim_blist_node_set_string(msn_session_get_bnode(contact->session),"CLLastChange",LastChangeStr); + gaim_debug_misc("MSNCL","LastChangeNode %s\n",LastChangeStr); + + memberships =xmlnode_get_child(service,"Memberships"); + gaim_debug_misc("MSNCL","memberships{%p},name:%s\n",memberships,memberships->name); + for(membershipnode = xmlnode_get_child(memberships, "Membership"); membershipnode; + membershipnode = xmlnode_get_next_twin(membershipnode)){ + xmlnode *roleNode; + char *role; + roleNode = xmlnode_get_child(membershipnode,"MemberRole"); + role=xmlnode_get_data(roleNode); + list_op = msn_get_memberrole(role); + gaim_debug_misc("MSNCL","MemberRole role:%s,list_op:%d\n",role,list_op); + g_free(role); + members = xmlnode_get_child(membershipnode,"Members"); + for(member = xmlnode_get_child(members, "Member"); member; + member = xmlnode_get_next_twin(member)){ + MsnUser *user; + xmlnode * typeNode; + char * type; + + gaim_debug_misc("MSNCL","type:%s\n",xmlnode_get_attrib(member,"type")); + if(!g_strcasecmp(xmlnode_get_attrib(member,"type"),"PassportMember")){ + passportNode = xmlnode_get_child(member,"PassportName"); + passport = xmlnode_get_data(passportNode); + typeNode = xmlnode_get_child(member,"Type"); + type = xmlnode_get_data(typeNode); + gaim_debug_misc("MSNCL","Passport name:%s,type:%s\n",passport,type); + g_free(type); + + user = msn_userlist_find_add_user(session->userlist,passport,NULL); + msn_got_lst_user(session, user, list_op, NULL); + g_free(passport); + } + if(!g_strcasecmp(xmlnode_get_attrib(member,"type"),"PhoneMember")){ + } + if(!g_strcasecmp(xmlnode_get_attrib(member,"type"),"EmailMember")){ + xmlnode *emailNode; + + emailNode = xmlnode_get_child(member,"Email"); + passport = xmlnode_get_data(emailNode); + gaim_debug_info("MSNCL","Email Member :name:%s,list_op:%d\n",passport,list_op); + user = msn_userlist_find_add_user(session->userlist,passport,NULL); + msn_got_lst_user(session,user,list_op,NULL); + g_free(passport); + } + } + } + + xmlnode_free(node); +} + +static void +msn_get_contact_list_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn *soapconn = data; + MsnContact *contact; + MsnSession *session; + const char *abLastChange; + const char *dynamicItemLastChange; + + contact = soapconn->parent; + g_return_if_fail(contact != NULL); + session = soapconn->session; + g_return_if_fail(session != NULL); + +#ifdef MSN_CONTACT_SOAP_DEBUG + gaim_debug_misc("msn", "soap contact server Reply: {%s}\n", soapconn->read_buf); +#endif + msn_parse_contact_list(contact); + /*free the read buffer*/ + msn_soap_free_read_buf(soapconn); + + abLastChange = gaim_blist_node_get_string(msn_session_get_bnode(contact->session),"ablastChange"); + dynamicItemLastChange = gaim_blist_node_get_string(msn_session_get_bnode(contact->session),"dynamicItemLastChange"); + msn_get_address_book(contact, abLastChange, dynamicItemLastChange); +} + +static void +msn_get_contact_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","finish contact written\n"); + soapconn->read_cb = msn_get_contact_list_cb; +// msn_soap_read_cb(data,source,cond); +} + +/*SOAP get contact list*/ +void +msn_get_contact_list(MsnContact * contact, const char *update_time) +{ + MsnSoapReq *soap_request; + char *body = NULL; + char * update_str; + + gaim_debug_info("MaYuan","Getting Contact List...\n"); + if(update_time != NULL){ + gaim_debug_info("MSNCL","last update time:{%s}\n",update_time); + update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML,update_time); + }else{ + update_str = g_strdup(""); + } + body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, update_str); + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_GET_CONTACT_POST_URL,MSN_GET_CONTACT_SOAP_ACTION, + body, + msn_get_contact_list_cb, + msn_get_contact_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); + g_free(update_str); + g_free(body); +} + +static gboolean +msn_parse_addressbook(MsnContact * contact) +{ + MsnSession * session; + xmlnode * node,*body,*response,*result; + xmlnode *groups,*group,*groupname,*groupId,*groupInfo; + xmlnode *contacts,*contactNode,*contactId,*contactInfo,*contactType,*passportName,*displayName,*groupIds,*guid; + xmlnode *abNode; + char *group_name,*group_id; + + session = contact->session; + gaim_debug_misc("xml","parse addressbook:{%s}\nsize:%d\n",contact->soapconn->body,contact->soapconn->body_len); + node = xmlnode_from_str(contact->soapconn->body, contact->soapconn->body_len); + + if(node == NULL){ + gaim_debug_misc("xml","parse from str err!\n"); + return FALSE; + } + gaim_debug_misc("xml","node{%p},name:%s,child:%s,last:%s\n",node,node->name,node->child->name,node->lastchild->name); + body = xmlnode_get_child(node,"Body"); + gaim_debug_misc("xml","body{%p},name:%s\n",body,body->name); + response = xmlnode_get_child(body,"ABFindAllResponse"); + + if (response == NULL) { + return FALSE; + } + + gaim_debug_misc("xml","response{%p},name:%s\n",response,response->name); + result =xmlnode_get_child(response,"ABFindAllResult"); + if(result == NULL){ + gaim_debug_misc("MSNAB","receive no address book update\n"); + return TRUE; + } + gaim_debug_misc("xml","result{%p},name:%s\n",result,result->name); + + /*Process Group List*/ + groups =xmlnode_get_child(result,"groups"); + for(group = xmlnode_get_child(groups, "Group"); group; + group = xmlnode_get_next_twin(group)){ + groupId = xmlnode_get_child(group,"groupId"); + group_id = xmlnode_get_data(groupId); + 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){ + /* Group of ungroupped buddies */ + continue; + } + + gaim_debug_misc("MsnAB","group_id:%s name:%s\n",group_id,group_name); + if ((gaim_find_group(group_name)) == NULL){ + GaimGroup *g = gaim_group_new(group_name); + gaim_blist_node_set_string(&(g->node),"groupId",group_id); + gaim_blist_add_group(g, NULL); + } + g_free(group_id); + g_free(group_name); + } + /*add a default No group to set up the no group Membership*/ + group_id = g_strdup(MSN_INDIVIDUALS_GROUP_ID); + group_name = g_strdup(MSN_INDIVIDUALS_GROUP_NAME); + msn_group_new(session->userlist,group_id , group_name); + if (group_id != NULL){ + gaim_debug_misc("MsnAB","group_id:%s name:%s,value:%d\n",group_id,group_name,*group_name=='\0'); + if ((gaim_find_group(group_name)) == NULL){ + GaimGroup *g = gaim_group_new(group_name); + gaim_blist_add_group(g, NULL); + } + } + g_free(group_name); + g_free(group_id); + + /*add a default No group to set up the no group Membership*/ + group_id = g_strdup(MSN_NON_IM_GROUP_ID); + group_name = g_strdup(MSN_NON_IM_GROUP_NAME); + msn_group_new(session->userlist,group_id , group_name); + if (group_id != NULL){ + gaim_debug_misc("MsnAB","group_id:%s name:%s,value:%d\n",group_id,group_name,*group_name=='\0'); + if ((gaim_find_group(group_name)) == NULL){ + GaimGroup *g = gaim_group_new(group_name); + gaim_blist_add_group(g, NULL); + } + } + g_free(group_name); + g_free(group_id); + + /*Process contact List*/ + gaim_debug_info("MSNAB","process contact list...\n"); + contacts =xmlnode_get_child(result,"contacts"); + for(contactNode = xmlnode_get_child(contacts, "Contact"); contactNode; + contactNode = xmlnode_get_next_twin(contactNode)){ + MsnUser *user; + char *passport,*Name,*uid,*type; + + passport = NULL; + + contactId= xmlnode_get_child(contactNode,"contactId"); + uid = xmlnode_get_data(contactId); + + contactInfo = xmlnode_get_child(contactNode,"contactInfo"); + contactType = xmlnode_get_child(contactInfo,"contactType"); + type = xmlnode_get_data(contactType); + + /*setup the Display Name*/ + if (!strcmp(type, "Me")){ + char *friendly; + friendly = xmlnode_get_data(xmlnode_get_child(contactInfo, "displayName")); + gaim_connection_set_display_name(session->account->gc, gaim_url_decode(friendly)); + g_free(friendly); + } + + passportName = xmlnode_get_child(contactInfo,"passportName"); + if(passportName == NULL){ + xmlnode *emailsNode, *contactEmailNode, *emailNode; + xmlnode *messengerEnabledNode; + char *msnEnabled; + + /*TODO: add it to the none-instant Messenger group and recognize as email Membership*/ + /*Yahoo User?*/ + emailsNode = xmlnode_get_child(contactInfo,"emails"); + if(emailsNode == NULL){ + /*TODO: need to support the Mobile type*/ + continue; + } + for(contactEmailNode = xmlnode_get_child(emailsNode,"ContactEmail");contactEmailNode; + contactEmailNode = xmlnode_get_next_twin(contactEmailNode) ){ + messengerEnabledNode = xmlnode_get_child(contactEmailNode,"isMessengerEnabled"); + if(messengerEnabledNode == NULL){ + break; + } + msnEnabled = xmlnode_get_data(messengerEnabledNode); + if(!strcmp(msnEnabled,"true")){ + /*Messenger enabled, Get the Passport*/ + emailNode = xmlnode_get_child(contactEmailNode,"email"); + passport = xmlnode_get_data(emailNode); + gaim_debug_info("MsnAB","Yahoo User %s\n",passport); + break; + }else{ + /*TODO maybe we can just ignore it in Gaim?*/ + emailNode = xmlnode_get_child(contactEmailNode,"email"); + passport = xmlnode_get_data(emailNode); + gaim_debug_info("MSNAB","Other type user\n"); + } + g_free(msnEnabled); + } + }else{ + passport = xmlnode_get_data(passportName); + } + + if(passport == NULL){ + continue; + } + + displayName = xmlnode_get_child(contactInfo,"displayName"); + if(displayName == NULL){ + Name = g_strdup(passport); + }else{ + Name =xmlnode_get_data(displayName); + } + + gaim_debug_misc("MsnAB","passport:{%s} uid:{%s} display:{%s}\n", + passport,uid,Name); + + user = msn_userlist_find_add_user(session->userlist, passport,Name); + msn_user_set_uid(user,uid); + msn_user_set_type(user,msn_get_user_type(type)); + user->list_op |= MSN_LIST_FL_OP; + g_free(Name); + g_free(passport); + g_free(uid); + g_free(type); + + gaim_debug_misc("MsnAB","parse guid...\n"); + groupIds = xmlnode_get_child(contactInfo,"groupIds"); + if(groupIds){ + for(guid = xmlnode_get_child(groupIds, "guid");guid; + guid = xmlnode_get_next_twin(guid)){ + group_id = xmlnode_get_data(guid); + msn_user_add_group_id(user,group_id); + gaim_debug_misc("MsnAB","guid:%s\n",group_id); + g_free(group_id); + } + }else{ + /*not in any group,Then set default group*/ + group_id = g_strdup(MSN_INDIVIDUALS_GROUP_ID); + msn_user_add_group_id(user,group_id); + g_free(group_id); + } + } + + abNode =xmlnode_get_child(result,"ab"); + if(abNode != NULL){ + xmlnode *LastChangeNode, *DynamicItemLastChangedNode; + char *lastchange, *dynamicChange; + + LastChangeNode = xmlnode_get_child(abNode,"lastChange"); + lastchange = xmlnode_get_data(LastChangeNode); + gaim_debug_info("MsnAB"," lastchanged Time:{%s}\n",lastchange); + gaim_blist_node_set_string(msn_session_get_bnode(contact->session),"ablastChange",lastchange); + + DynamicItemLastChangedNode = xmlnode_get_child(abNode,"DynamicItemLastChanged"); + dynamicChange = xmlnode_get_data(DynamicItemLastChangedNode); + gaim_debug_info("MsnAB"," DynamicItemLastChanged :{%s}\n",dynamicChange); + gaim_blist_node_set_string(msn_session_get_bnode(contact->session),"DynamicItemLastChanged",lastchange); + } + + xmlnode_free(node); + msn_soap_free_read_buf(contact->soapconn); + return TRUE; +} + +static void +msn_get_address_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + MsnContact *contact; + MsnSession *session; + + contact = soapconn->parent; + g_return_if_fail(contact != NULL); + session = soapconn->session; + g_return_if_fail(session != NULL); + +// gaim_debug_misc("msn", "soap contact server Reply: {%s}\n", soapconn->read_buf); + if (msn_parse_addressbook(contact)) { + msn_notification_dump_contact(session); + msn_set_psm(session); + msn_session_finish_login(session); + } else { + msn_get_address_book(contact, NULL, NULL); + } + + /*free the read buffer*/ + msn_soap_free_read_buf(soapconn); +} + +/**/ +static void +msn_address_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","finish contact written\n"); + soapconn->read_cb = msn_get_address_cb; +} + +/*get the address book*/ +void +msn_get_address_book(MsnContact *contact, const char *LastChanged, const char *dynamicItemLastChange) +{ + MsnSoapReq *soap_request; + char *body = NULL; + char *ab_update_str,*update_str; + + gaim_debug_info("MaYuan","msn_get_address_book()...\n"); + /*build SOAP and POST it*/ + if(LastChanged != NULL){ + ab_update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML,LastChanged); + }else{ + ab_update_str = g_strdup(""); + } + if(dynamicItemLastChange != NULL){ + update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, + dynamicItemLastChange); + }else{ + update_str = g_strdup(ab_update_str); + } + g_free(ab_update_str); + + body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE,update_str); + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_ADDRESS_BOOK_POST_URL,MSN_GET_ADDRESS_SOAP_ACTION, + body, + msn_get_address_cb, + msn_address_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); + g_free(update_str); + g_free(body); +} + +static void +msn_add_contact_read_cb(gpointer data, gint source, GaimInputCondition cond) +{ + gaim_debug_info("MaYuan","add contact read done\n"); +} + +static void +msn_add_contact_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","finish add contact written\n"); + soapconn->read_cb = msn_add_contact_read_cb; +// msn_soap_read_cb(data,source,cond); +} + +/*add a Contact */ +void +msn_add_contact(MsnContact *contact,const char *passport,const char *groupId) +{ + MsnSoapReq *soap_request; + char *body = NULL; + char *contact_xml = NULL; + char *soap_action; + + gaim_debug_info("MaYuan","msn add a contact...\n"); + contact_xml = g_strdup_printf(MSN_CONTACT_XML,passport); + if(groupId == NULL){ + body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE,contact_xml); + g_free(contact_xml); + /*build SOAP and POST it*/ + soap_action = g_strdup(MSN_CONTACT_ADD_SOAP_ACTION); + }else{ + body = g_strdup_printf(MSN_ADD_CONTACT_GROUP_TEMPLATE,groupId,contact_xml); + g_free(contact_xml); + /*build SOAP and POST it*/ + soap_action = g_strdup(MSN_ADD_CONTACT_GROUP_SOAP_ACTION); + } + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_ADDRESS_BOOK_POST_URL,soap_action, + body, + msn_add_contact_read_cb, + msn_add_contact_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); + + g_free(soap_action); + g_free(body); +} + +static void +msn_delete_contact_read_cb(gpointer data, gint source, GaimInputCondition cond) +{ + gaim_debug_info("MaYuan","delete contact read done\n"); +} + +static void +msn_delete_contact_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","delete contact written\n"); + soapconn->read_cb = msn_delete_contact_read_cb; +// msn_soap_read_cb(data,source,cond); +} + +/*delete a Contact*/ +void +msn_delete_contact(MsnContact *contact,const char *contactId) +{ + char *body = NULL; + char *contact_xml = NULL ; + MsnSoapReq *soap_request; + + g_return_if_fail(contactId != NULL); + gaim_debug_info("MaYuan","msn delete a contact,contactId:{%s}...\n",contactId); + contact_xml = g_strdup_printf(MSN_CONTACTS_DEL_XML,contactId); + body = g_strdup_printf(MSN_DEL_CONTACT_TEMPLATE,contact_xml); + g_free(contact_xml); + /*build SOAP and POST it*/ + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_ADDRESS_BOOK_POST_URL,MSN_CONTACT_DEL_SOAP_ACTION, + body, + msn_delete_contact_read_cb, + msn_delete_contact_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); + + g_free(body); +} + +static void +msn_update_contact_read_cb(gpointer data, gint source, GaimInputCondition cond) +{ + gaim_debug_info("MaYuan","update contact read done\n"); +} + +static void +msn_update_contact_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","update contact written\n"); + soapconn->read_cb = msn_update_contact_read_cb; +// msn_soap_read_cb(data,source,cond); +} + +/*update a contact's Nickname*/ +#if 0 +void +msn_update_contact(MsnContact *contact,const char* nickname) +{ + MsnSoapReq *soap_request; + char *body = NULL; + + gaim_debug_info("MaYuan","msn unblock a contact...\n"); + + body = g_strdup_printf(MSN_CONTACT_UPDATE_TEMPLATE,nickname); + /*build SOAP and POST it*/ + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_ADDRESS_BOOK_POST_URL,MSN_CONTACT_UPDATE_SOAP_ACTION, + body, + msn_update_contact_read_cb, + msn_update_contact_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); + + g_free(body); +} +#endif + +static void +msn_block_read_cb(gpointer data, gint source, GaimInputCondition cond) +{ + gaim_debug_info("MaYuan","block read done\n"); +} + +static void +msn_block_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","finish unblock written\n"); + soapconn->read_cb = msn_block_read_cb; +} + +/*block a Contact*/ +void +msn_block_contact(MsnContact *contact,const char* membership_id) +{ + MsnSoapReq *soap_request; + char *body = NULL; + + gaim_debug_info("MaYuan","msn block a contact...\n"); + body = g_strdup_printf(MSN_CONTACT_DELECT_FROM_ALLOW_TEMPLATE,membership_id); + /*build SOAP and POST it*/ + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_SHARE_POST_URL,MSN_CONTACT_BLOCK_SOAP_ACTION, + body, + msn_block_read_cb, + msn_block_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); + + g_free(body); +} + +static void +msn_unblock_read_cb(gpointer data, gint source, GaimInputCondition cond) +{ + gaim_debug_info("MaYuan","unblock read done\n"); +} + +static void +msn_unblock_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","finish unblock written\n"); + soapconn->read_cb = msn_unblock_read_cb; +} + +/*unblock a contact*/ +void +msn_unblock_contact(MsnContact *contact,const char* passport) +{ + MsnSoapReq *soap_request; + char *body = NULL; + + gaim_debug_info("MaYuan","msn unblock a contact...\n"); + + body = g_strdup_printf(MSN_UNBLOCK_CONTACT_TEMPLATE,passport); + /*build SOAP and POST it*/ + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_SHARE_POST_URL,MSN_CONTACT_UNBLOCK_SOAP_ACTION, + body, + msn_unblock_read_cb, + msn_unblock_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); + + g_free(body); +} + +static void +msn_gleams_read_cb(gpointer data, gint source, GaimInputCondition cond) +{ + gaim_debug_info("MaYuan","Gleams read done\n"); +} + +static void +msn_gleams_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","finish Group written\n"); + soapconn->read_cb = msn_gleams_read_cb; +// msn_soap_read_cb(data,source,cond); +} + +#if 0 +/*get the gleams info*/ +void +msn_get_gleams(MsnContact *contact) +{ + MsnSoapReq *soap_request; + + gaim_debug_info("MaYuan","msn get gleams info...\n"); + /*build SOAP and POST it*/ + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_ADDRESS_BOOK_POST_URL,MSN_GET_GLEAMS_SOAP_ACTION, + MSN_GLEAMS_TEMPLATE, + msn_gleams_read_cb, + msn_gleams_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); +} +#endif + +/*************************************************************** + * Group Operation + ***************************************************************/ +static void +msn_group_read_cb(gpointer data, gint source, GaimInputCondition cond) +{ + gaim_debug_info("MaYuan","Group read \n"); +} + +static void +msn_group_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","finish Group written\n"); + soapconn->read_cb = msn_group_read_cb; +// msn_soap_read_cb(data,source,cond); +} + +/*add group*/ +void msn_add_group(MsnSession *session,const char* group_name) +{ + MsnSoapReq *soap_request; + MsnContact *contact ; + char *body = NULL; + + g_return_if_fail(session != NULL); + contact = session->contact; + gaim_debug_info("MaYuan","msn add group...\n"); + + body = g_strdup_printf(MSN_GROUP_ADD_TEMPLATE,group_name); + /*build SOAP and POST it*/ + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_ADDRESS_BOOK_POST_URL,MSN_GROUP_ADD_SOAP_ACTION, + body, + msn_group_read_cb, + msn_group_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); +} + +/*delete a group*/ +void msn_del_group(MsnSession *session,const char *guid) +{ + MsnSoapReq *soap_request; + MsnContact *contact; + char *body = NULL; + + g_return_if_fail(session != NULL); + /*if group uid we need to del is NULL, + * we need to delete nothing + */ + g_return_if_fail(guid != NULL); + contact = session->contact; + gaim_debug_info("MaYuan","msn del group...\n"); + + body = g_strdup_printf(MSN_GROUP_DEL_TEMPLATE,guid); + /*build SOAP and POST it*/ + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_ADDRESS_BOOK_POST_URL,MSN_GROUP_DEL_SOAP_ACTION, + body, + msn_group_read_cb, + msn_group_written_cb); + msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init); + + g_free(body); +} + +void +msn_contact_connect_init(MsnSoapConn *soapconn) +{ + /* Authenticate via Windows Live ID. */ + gaim_debug_info("MaYuan","msn_contact_connect...\n"); + + msn_soap_init(soapconn,MSN_CONTACT_SERVER,1, + msn_contact_login_connect_cb, + msn_contact_login_error_cb); +} + diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/contact.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/msn/contact.h Sun Apr 15 04:29:56 2007 +0000 @@ -0,0 +1,236 @@ +/** + * @file contact.h Header file for contact.c + * Author + * MaYuan + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _MSN_CONTACT_H_ +#define _MSN_CONTACT_H_ + +#define MSN_CONTACT_SERVER "omega.contacts.msn.com" + +/*get contact list soap request template*/ +#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 "Full"\ + "true"\ + "%s" +#define MSN_GET_CONTACT_TEMPLATE ""\ +""\ + ""\ + ""\ + "09607671-1C32-421F-A6A6-CBFAA51AB5F4"\ + "false"\ + "Initial"\ + ""\ + ""\ + "false"\ + ""\ + ""\ + ""\ + ""\ + ""\ + ""\ + "Messenger"\ + "Invitation"\ + "SocialNetwork"\ + "Space"\ + "Profile"\ + ""\ + ""\ + "%s"\ + ""\ + ""\ +"" + +/************************************************ + * Address Book SOAP + * *********************************************/ +#define MSN_ADDRESS_BOOK_POST_URL "/abservice/abservice.asmx" +/*get addressbook soap request template*/ +#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 "true"\ + "%s" + +#define MSN_GET_GLEAM_UPDATE_XML \ + "%s"\ + "Gleam"\ + "%s" + +#define MSN_GET_ADDRESS_TEMPLATE ""\ +""\ + ""\ + ""\ + "09607671-1C32-421F-A6A6-CBFAA51AB5F4"\ + "false"\ + "Initial"\ + ""\ + ""\ + "false"\ + ""\ + ""\ + ""\ + ""\ + "00000000-0000-0000-0000-000000000000"\ + "Full"\ + "%s"\ + ""\ + ""\ +"" + +/*Gleams SOAP request template*/ +#define MSN_GET_GLEAMS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll" +#define MSN_GLEAMS_TEMPLATE ""\ +""\ + ""\ + ""\ + "09607671-1C32-421F-A6A6-CBFAA51AB5F4"\ + "false"\ + "Initial"\ + ""\ + ""\ + "false"\ + ""\ + ""\ + ""\ + ""\ + "00000000-0000-0000-0000-000000000000"\ + "Full"\ + "Gleam"\ + "0001-01-01T00:00:00.0000000-08:00"\ + ""\ + ""\ +"" + +/******************************************************* + * Contact Add/del SOAP Action + *******************************************************/ +/*add conatct soap request*/ +#define MSN_CONTACT_ADD_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactAdd" +#define MSN_CONTACT_XML "LivePending%strue" + +#define MSN_ADD_CONTACT_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseContactSavefalse00000000-0000-0000-0000-000000000000%strue" + +/*Contact Group Add*/ +#define MSN_ADD_CONTACT_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactAdd" +#define MSN_ADD_CONTACT_GROUP_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseContactSavefalse00000000-0000-0000-0000-000000000000%s%struetrue" + +/*delete contact from contact list soap request template*/ +#define MSN_CONTACT_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactDelete" +#define MSN_CONTACTS_DEL_XML "%s" +#define MSN_DEL_CONTACT_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseTimerfalse00000000-0000-0000-0000-000000000000%s" + +#define MSN_MEMBER_TEMPLATE "PassportAccepted%s" + +/******************************************************* + * Contact Block/Unblock SOAP Action + *******************************************************/ +/*block means delete from allow list and add contact to block list*/ +#define MSN_SHARE_POST_URL "/abservice/SharingService.asmx" +#define MSN_CONTACT_BLOCK_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/AddMember" +/*first delete contact from allow list*/ +#define MSN_CONTACT_DELECT_FROM_ALLOW_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseBlockUnblockfalse0MessengerAllowPassport%sAccepted" + +#define MSN_CONTACT_ADD_TO_BLOCK_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseBlockUnblockfalse0MessengerBlock%s" + +/*unblock means delete contact from block list*/ +#define MSN_CONTACT_UNBLOCK_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/DeleteMember" +#define MSN_UNBLOCK_CONTACT_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseBlockUnblockfalse0MessengerBlock%s" + +/*Update Contact Nickname*/ +#define MSN_CONTACT_UPDATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" +#define MSN_CONTACT_UPDATE_TEMPLATE ""\ +""\ +""\ + ""\ + "09607671-1C32-421F-A6A6-CBFAA51AB5F4"\ + "false"\ + "Timer"\ + ""\ + ""\ + "false"\ + ""\ + ""\ + ""\ + ""\ + "00000000-0000-0000-0000-000000000000"\ + ""\ + ""\ + ""\ + "Me"\ + "%s"\ + ""\ + "DisplayName"\ + ""\ + ""\ + ""\ + ""\ +" " + +/******************************************************* + * Group SOAP Action + *******************************************************/ +/*add a group*/ +#define MSN_GROUP_ADD_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupAdd" +#define MSN_GROUP_ADD_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseGroupSavefalse00000000-0000-0000-0000-000000000000false%sC8529CE2-6EAD-434d-881F-341E17DB3FF8falseMSN.IM.Display1" + +/*delete a group*/ +#define MSN_GROUP_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupDelete" +#define MSN_GROUP_DEL_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseTimerfalse00000000-0000-0000-0000-000000000000%s" + + +typedef struct _MsnContact MsnContact; + +struct _MsnContact +{ + MsnSession *session; + + MsnSoapConn *soapconn; +}; + +/************************************************ + * function prototype + ************************************************/ +MsnContact * msn_contact_new(MsnSession *session); +void msn_contact_destroy(MsnContact *contact); + +void msn_contact_connect(MsnContact *contact); +void msn_get_contact_list(MsnContact * contact, const char *update); +void msn_get_address_book(MsnContact *contact, const char * update, const char * gupdate); + +/*contact SOAP Operation*/ +void msn_add_contact(MsnContact *contact,const char *passport,const char *groupId); +void msn_delete_contact(MsnContact *contact,const char *contactId); + + +/*group operation*/ +void msn_add_group(MsnSession *session,const char* group_name); +void msn_del_group(MsnSession *session,const char *guid); + +/*contact Block/unblock operation*/ +void msn_block_contact(MsnContact *contact,const char* membership_id); +void msn_unblock_contact(MsnContact *contact,const char* passport); + +void msn_contact_connect_init(MsnSoapConn *soapconn); + +#endif/* _MSN_CMDPROC_H_*/ + diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/dialog.c --- a/libpurple/protocols/msn/dialog.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/dialog.c Sun Apr 15 04:29:56 2007 +0000 @@ -45,9 +45,7 @@ msn_userlist_add_buddy(userlist, data->who, MSN_LIST_FL, data->group); } - if (data->group != NULL) - g_free(data->group); - + g_free(data->group); g_free(data->who); g_free(data); } @@ -63,9 +61,7 @@ msn_userlist_rem_buddy(userlist, data->who, MSN_LIST_FL, data->group); } - if (data->group != NULL) - g_free(data->group); - + g_free(data->group); g_free(data->who); g_free(data); } @@ -93,13 +89,16 @@ purple_account_get_username(account), purple_account_get_protocol_name(account)); - if (group_name != NULL){ + if (group_name != NULL) + { reason = g_strdup_printf(_("%s on the local list is " "inside the group \"%s\" but not on " "the server list. " "Do you want this buddy to be added?"), passport, group_name); - }else{ + } + else + { reason = g_strdup_printf(_("%s is on the local list but " "not on the server list. " "Do you want this buddy to be added?"), @@ -114,9 +113,9 @@ if (group_name != NULL) group = purple_find_group(group_name); - if (group != NULL){ + if (group != NULL) buddy = purple_find_buddy_in_group(account, passport, group); - }else{ + else buddy = purple_find_buddy(account, passport); } diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/msg.c diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Sun Apr 15 04:29:56 2007 +0000 @@ -451,11 +451,14 @@ xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); - slplink = msn_session_get_slplink(session, who); + if (xfer) + { + slplink = msn_session_get_slplink(session, who); - xfer->data = slplink; + xfer->data = slplink; - purple_xfer_set_init_fnc(xfer, t_msn_xfer_init); + purple_xfer_set_init_fnc(xfer, t_msn_xfer_init); + } return xfer; } diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/msn.h diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/notification.c --- a/libpurple/protocols/msn/notification.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/notification.c Sun Apr 15 04:29:56 2007 +0000 @@ -311,9 +311,11 @@ g_snprintf(proto_str, sizeof(proto_str), "MSNP%d", session->protocol_ver); - for (i = 1; i < cmd->param_count -1; i++){ + for (i = 1; i < cmd->param_count -1; i++) + { purple_debug_info("MaYuan","%s,proto_str:%s\n",cmd->params[i],proto_str); - if (strcmp(cmd->params[i], proto_str) >= 0) { + if (strcmp(cmd->params[i], proto_str) >= 0) + { protocol_supported = TRUE; break; } @@ -395,10 +397,13 @@ } /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued * command and we are processing it */ - if (cmd->payload == NULL){ + if (cmd->payload == NULL) + { cmdproc->last_cmd->payload_cb = msg_cmd_post; cmdproc->servconn->payload_len = atoi(cmd->params[2]); - }else{ + } + else + { g_return_if_fail(cmd->payload_cb != NULL); purple_debug_info("MaYuan","MSG payload:{%s}\n",cmd->payload); @@ -899,7 +904,8 @@ msn_user_set_friendly_name(user, friendly); - if (session->protocol_ver >= 9 && cmd->param_count == 8){ + if (session->protocol_ver >= 9 && cmd->param_count == 8) + { msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[6])); msn_user_set_object(user, msnobj); } @@ -953,11 +959,15 @@ msn_user_set_friendly_name(user, friendly); } - if (session->protocol_ver >= 9){ - if (cmd->param_count == 7){ + if (session->protocol_ver >= 9) + { + if (cmd->param_count == 7) + { msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5])); msn_user_set_object(user, msnobj); - }else{ + } + else + { msn_user_set_object(user, NULL); } } @@ -1374,9 +1384,12 @@ msn_parse_socket(cmd->params[2], &host, &port); - if (!strcmp(cmd->params[1], "SB")){ + if (!strcmp(cmd->params[1], "SB")) + { purple_debug_error("msn", "This shouldn't be handled here.\n"); - }else if (!strcmp(cmd->params[1], "NS")){ + } + else if (!strcmp(cmd->params[1], "NS")) + { MsnSession *session; session = cmdproc->session; @@ -1501,7 +1514,8 @@ session->passport_info.sid = g_strdup(value); } - if ((value = msn_message_get_attr(msg, "MSPAuth")) != NULL){ + if ((value = msn_message_get_attr(msg, "MSPAuth")) != NULL) + { if (session->passport_info.mspauth != NULL) g_free(session->passport_info.mspauth); @@ -1509,14 +1523,16 @@ session->passport_info.mspauth = g_strdup(value); } - if ((value = msn_message_get_attr(msg, "ClientIP")) != NULL){ + if ((value = msn_message_get_attr(msg, "ClientIP")) != NULL) + { if (session->passport_info.client_ip != NULL) g_free(session->passport_info.client_ip); session->passport_info.client_ip = g_strdup(value); } - if ((value = msn_message_get_attr(msg, "ClientPort")) != NULL){ + if ((value = msn_message_get_attr(msg, "ClientPort")) != NULL) + { session->passport_info.client_port = ntohs(atoi(value)); } @@ -1766,9 +1782,6 @@ cmdproc = notification->servconn->cmdproc; - if (strcmp(list, "FL") != 0){ - } - adl_node = xmlnode_new("ml"); adl_node->child = NULL; @@ -1776,9 +1789,12 @@ payload = xmlnode_to_str(adl_node,&payload_len); xmlnode_free(adl_node); - if(msn_user_is_yahoo(notification->session->account,who)){ + if (msn_user_is_yahoo(notification->session->account,who)) + { msn_notification_fqy_yahoo(notification->session, who); - }else{ + } + else + { msn_notification_post_adl(notification->servconn->cmdproc, payload,payload_len); } diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/oim.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/msn/oim.c Sun Apr 15 04:29:56 2007 +0000 @@ -0,0 +1,597 @@ +/** + * @file oim.c + * get and send MSN offline Instant Message via SOAP request + * Author + * MaYuan + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "msn.h" +#include "soap.h" +#include "oim.h" +#include "msnutils.h" + +/*Local Function Prototype*/ +static void msn_oim_post_single_get_msg(MsnOim *oim,const char *msgid); +static MsnOimSendReq *msn_oim_new_send_req(const char *from_member, + const char *friendname, + const char* to_member, + gint send_seq, + const char *msg); +static void msn_oim_retrieve_connect_init(MsnSoapConn *soapconn); +static void msn_oim_send_connect_init(MsnSoapConn *soapconn); +static void msn_oim_free_send_req(MsnOimSendReq *req); +static void msn_oim_report_to_user(MsnOim *oim, char *msg_str); +static void msn_oim_get_process(MsnOim *oim, char *oim_msg); +static char *msn_oim_msg_to_str(MsnOim *oim, const char *body); +const void msn_oim_send_process(MsnOim *oim, const char *body, int len); + +/*new a OIM object*/ +MsnOim * +msn_oim_new(MsnSession *session) +{ + MsnOim *oim; + + oim = g_new0(MsnOim, 1); + oim->session = session; + oim->retrieveconn = msn_soap_new(session,oim,1); + + oim->oim_list = NULL; + oim->sendconn = msn_soap_new(session,oim,1); + oim->run_id = rand_guid(); + oim->challenge = NULL; + oim->send_queue = g_queue_new(); + oim->send_seq = 1; + return oim; +} + +/*destroy the oim object*/ +void +msn_oim_destroy(MsnOim *oim) +{ + MsnOimSendReq *request; + + gaim_debug_info("OIM","destroy the OIM \n"); + msn_soap_destroy(oim->retrieveconn); + msn_soap_destroy(oim->sendconn); + g_free(oim->run_id); + g_free(oim->challenge); + + while((request = g_queue_pop_head(oim->send_queue)) != NULL){ + msn_oim_free_send_req(request); + } + g_queue_free(oim->send_queue); + + g_free(oim); +} + +static MsnOimSendReq * +msn_oim_new_send_req(const char *from_member, const char*friendname, + const char* to_member, gint send_seq, + const char *msg) +{ + MsnOimSendReq *request; + + request = g_new0(MsnOimSendReq, 1); + request->from_member =g_strdup(from_member); + request->friendname = g_strdup(friendname); + request->to_member = g_strdup(to_member); + request->send_seq = send_seq; + request->oim_msg = g_strdup(msg); + return request; +} + +static void +msn_oim_free_send_req(MsnOimSendReq *req) +{ + g_return_if_fail(req != NULL); + + g_free(req->from_member); + g_free(req->friendname); + g_free(req->to_member); + g_free(req->oim_msg); + + g_free(req); +} + +/**************************************** + * OIM send SOAP request + * **************************************/ +/*encode the message to OIM Message Format*/ +static char * +msn_oim_msg_to_str(MsnOim *oim, const char *body) +{ + char *oim_body,*oim_base64; + + gaim_debug_info("MaYuan","encode OIM Message...\n"); + oim_base64 = gaim_base64_encode((const guchar *)body, strlen(body)); + gaim_debug_info("MaYuan","encoded base64 body:{%s}\n",oim_base64); + oim_body = g_strdup_printf(MSN_OIM_MSG_TEMPLATE, + oim->run_id,oim->send_seq,oim_base64); + + return oim_body; +} + +/*oim SOAP server login error*/ +static void +msn_oim_send_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) +{ + MsnSoapConn *soapconn = data; + MsnSession *session; + + session = soapconn->session; + g_return_if_fail(session != NULL); + + msn_session_set_error(session, MSN_ERROR_SERV_DOWN, _("Unable to connect to OIM server")); +} + +/*msn oim SOAP server connect process*/ +static void +msn_oim_send_connect_cb(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + MsnSoapConn *soapconn = data; + MsnSession * session; + MsnOim *oim; + + oim = soapconn->parent; + g_return_if_fail(oim != NULL); + + session = oim->session; + g_return_if_fail(session != NULL); +} + +/* + * Process the send return SOAP string + * If got SOAP Fault,get the lock key,and resend it. + */ +const void +msn_oim_send_process(MsnOim *oim, const char *body, int len) +{ + xmlnode *responseNode, *bodyNode; + xmlnode *faultNode, *faultCodeNode, *faultstringNode; + xmlnode *detailNode, *challengeNode; + char *faultCodeStr, *faultstring; + + responseNode = xmlnode_from_str(body,len); + g_return_if_fail(responseNode != NULL); + bodyNode = xmlnode_get_child(responseNode,"Body"); + faultNode = xmlnode_get_child(bodyNode,"Fault"); + if(faultNode == NULL){ + /*Send OK! return*/ + MsnOimSendReq *request; + + gaim_debug_info("MaYuan","send OIM OK!"); + xmlnode_free(responseNode); + request = g_queue_pop_head(oim->send_queue); + msn_oim_free_send_req(request); + /*send next buffered Offline Message*/ + msn_soap_post(oim->sendconn,NULL,msn_oim_send_connect_init); + return; + } + /*get the challenge,and repost it*/ + faultCodeNode = xmlnode_get_child(faultNode,"faultcode"); + if(faultCodeNode == NULL){ + gaim_debug_info("MaYuan","faultcode Node is NULL\n"); + goto oim_send_process_fail; + } + faultCodeStr = xmlnode_get_data(faultCodeNode); + gaim_debug_info("MaYuan","fault code:{%s}\n",faultCodeStr); + + if(strcmp(faultCodeStr,"q0:AuthenticationFailed")){ + /*other Fault Reason?*/ + goto oim_send_process_fail; + } + + faultstringNode = xmlnode_get_child(faultNode,"faultstring"); + faultstring = xmlnode_get_data(faultstringNode); + gaim_debug_info("MaYuan","fault string :{%s}\n",faultstring); + + /* lock key fault reason, + * compute the challenge and resend it + */ + detailNode = xmlnode_get_child(faultNode, "detail"); + if(detailNode == NULL){ + goto oim_send_process_fail; + } + challengeNode = xmlnode_get_child(detailNode,"LockKeyChallenge"); + + g_free(oim->challenge); + oim->challenge = xmlnode_get_data(challengeNode); + gaim_debug_info("MaYuan","lockkey:{%s}\n",oim->challenge); + + /*repost the send*/ + gaim_debug_info("MaYuan","prepare to repost the send...\n"); + msn_oim_send_msg(oim); + +oim_send_process_fail: + xmlnode_free(responseNode); + return ; +} + +static void +msn_oim_send_read_cb(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + MsnSession *session = soapconn->session; + MsnOim * oim; + + g_return_if_fail(session != NULL); + oim = soapconn->session->oim; + g_return_if_fail(oim != NULL); + + gaim_debug_info("MaYuan","read buffer:{%s}\n",soapconn->body); + msn_oim_send_process(oim,soapconn->body,soapconn->body_len); +} + +static void +msn_oim_send_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + soapconn->read_cb = msn_oim_send_read_cb; +// msn_soap_read_cb(data,source,cond); +} + +void +msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername, + const char* friendname, const char *tomember, + const char * msg) +{ + MsnOimSendReq *request; + + g_return_if_fail(oim != NULL); + + request = msn_oim_new_send_req(membername,friendname,tomember,oim->send_seq,msg); + g_queue_push_tail(oim->send_queue,request); +} + +/*post send single message request to oim server*/ +void +msn_oim_send_msg(MsnOim *oim) +{ + MsnSoapReq *soap_request; + MsnOimSendReq *oim_request; + char *soap_body,*mspauth; + char *msg_body; + char buf[33]; + + g_return_if_fail(oim != NULL); + oim_request = g_queue_pop_head(oim->send_queue); + g_return_if_fail(oim_request != NULL); + + gaim_debug_info("MaYuan","send single OIM Message\n"); + mspauth = g_strdup_printf("t=%s&p=%s", + oim->session->passport_info.t, + oim->session->passport_info.p + ); + g_queue_push_head(oim->send_queue,oim_request); + + /* if we got the challenge lock key, we compute it + * else we go for the SOAP fault and resend it. + */ + if(oim->challenge != NULL){ + msn_handle_chl(oim->challenge, buf); + }else{ + gaim_debug_info("MaYuan","no lock key challenge,wait for SOAP Fault and Resend\n"); + buf[0]='\0'; + } + gaim_debug_info("MaYuan","get the lock key challenge {%s}\n",buf); + + msg_body = msn_oim_msg_to_str(oim, oim_request->oim_msg); + soap_body = g_strdup_printf(MSN_OIM_SEND_TEMPLATE, + oim_request->from_member, + oim_request->friendname, + oim_request->to_member, + mspauth, + MSNP13_WLM_PRODUCT_ID, + buf, + oim_request->send_seq, + msg_body + ); + soap_request = msn_soap_request_new(MSN_OIM_SEND_HOST, + MSN_OIM_SEND_URL,MSN_OIM_SEND_SOAP_ACTION, + soap_body, + msn_oim_send_read_cb, + msn_oim_send_written_cb); + g_free(mspauth); + g_free(msg_body); + g_free(soap_body); + + /*increase the offline Sequence control*/ + if(oim->challenge != NULL){ + oim->send_seq++; + } + msn_soap_post(oim->sendconn,soap_request,msn_oim_send_connect_init); +} + +/**************************************** + * OIM delete SOAP request + * **************************************/ +static void +msn_oim_delete_read_cb(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + gaim_debug_info("MaYuan","OIM delete read buffer:{%s}\n",soapconn->body); + + msn_soap_free_read_buf(soapconn); + /*get next single Offline Message*/ + msn_soap_post(soapconn,NULL,msn_oim_retrieve_connect_init); +} + +static void +msn_oim_delete_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + soapconn->read_cb = msn_oim_delete_read_cb; +} + +/*Post to get the Offline Instant Message*/ +static void +msn_oim_post_delete_msg(MsnOim *oim,const char *msgid) +{ + MsnSoapReq *soap_request; + const char *soap_body,*t,*p; + + g_return_if_fail(oim != NULL); + g_return_if_fail(msgid != NULL); + + gaim_debug_info("MaYuan","Delete single OIM Message {%s}\n",msgid); + t = oim->session->passport_info.t; + p = oim->session->passport_info.p; + + soap_body = g_strdup_printf(MSN_OIM_DEL_TEMPLATE, + t, + p, + msgid + ); + soap_request = msn_soap_request_new(MSN_OIM_RETRIEVE_HOST, + MSN_OIM_RETRIEVE_URL,MSN_OIM_DEL_SOAP_ACTION, + soap_body, + msn_oim_delete_read_cb, + msn_oim_delete_written_cb); + msn_soap_post(oim->retrieveconn,soap_request,msn_oim_retrieve_connect_init); +} + +/**************************************** + * OIM get SOAP request + * **************************************/ +/*oim SOAP server login error*/ +static void +msn_oim_get_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) +{ + MsnSoapConn *soapconn = data; + MsnSession *session; + + session = soapconn->session; + g_return_if_fail(session != NULL); + msn_soap_clean_unhandled_request(soapconn); + +// msn_session_set_error(session, MSN_ERROR_SERV_DOWN, _("Unable to connect to OIM server")); +} + +/*msn oim SOAP server connect process*/ +static void +msn_oim_get_connect_cb(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + MsnSoapConn *soapconn = data; + MsnSession * session; + MsnOim *oim; + + oim = soapconn->parent; + g_return_if_fail(oim != NULL); + + session = oim->session; + g_return_if_fail(session != NULL); + + gaim_debug_info("MaYuan","oim get SOAP Server connected!\n"); +} + +/*Post the Offline Instant Message to User Conversation*/ +static void +msn_oim_report_to_user(MsnOim *oim, char *msg_str) +{ + MsnMessage *message; + char *date,*from,*decode_msg; + gsize body_len; + char **tokens; + char *start,*end; + int has_nick = 0; + char *passport_str, *passport; + char *msg_id; + + message = msn_message_new(MSN_MSG_UNKNOWN); + + msn_message_parse_payload(message, msg_str, strlen(msg_str), + MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM); + gaim_debug_info("MaYuan","oim body:{%s}\n",message->body); + decode_msg = gaim_base64_decode(message->body,&body_len); + date = (char *)g_hash_table_lookup(message->attr_table, "Date"); + from = (char *)g_hash_table_lookup(message->attr_table, "From"); + if(strstr(from," ")){ + has_nick = 1; + } + if(has_nick){ + tokens = g_strsplit(from , " " , 2); + passport_str = g_strdup(tokens[1]); + gaim_debug_info("MaYuan","oim Date:{%s},nickname:{%s},tokens[1]:{%s} passport{%s}\n", + date,tokens[0],tokens[1],passport_str); + g_strfreev(tokens); + }else{ + passport_str = g_strdup(from); + gaim_debug_info("MaYuan","oim Date:{%s},passport{%s}\n", + date,passport_str); + } + start = strstr(passport_str,"<"); + start += 1; + end = strstr(passport_str,">"); + passport = g_strndup(start,end - start); + g_free(passport_str); + gaim_debug_info("MaYuan","oim Date:{%s},passport{%s}\n",date,passport); + + msn_session_report_user(oim->session,passport,decode_msg,GAIM_MESSAGE_SYSTEM); + + /*Now get the oim message ID from the oim_list. + * and append to read list to prepare for deleting the Offline Message when sign out + */ + if(oim->oim_list != NULL){ + msg_id = oim->oim_list->data; + msn_oim_post_delete_msg(oim,msg_id); + oim->oim_list = g_list_remove(oim->oim_list, oim->oim_list->data); + g_free(msg_id); + } + + g_free(passport); +} + +/* Parse the XML data, + * prepare to report the OIM to user + */ +static void +msn_oim_get_process(MsnOim *oim, char *oim_msg) +{ + xmlnode *oimNode,*bodyNode,*responseNode,*msgNode; + char *msg_data,*msg_str; + + oimNode = xmlnode_from_str(oim_msg, strlen(oim_msg)); + bodyNode = xmlnode_get_child(oimNode,"Body"); + responseNode = xmlnode_get_child(bodyNode,"GetMessageResponse"); + msgNode = xmlnode_get_child(responseNode,"GetMessageResult"); + msg_data = xmlnode_get_data(msgNode); + msg_str = g_strdup(msg_data); + g_free(msg_data); + gaim_debug_info("OIM","msg:{%s}\n",msg_str); + msn_oim_report_to_user(oim,msg_str); + + g_free(msg_str); +} + +static void +msn_oim_get_read_cb(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + MsnOim * oim = soapconn->session->oim; + + gaim_debug_info("MaYuan","OIM get read buffer:{%s}\n",soapconn->body); + + /*we need to process the read message!*/ + msn_oim_get_process(oim,soapconn->body); + msn_soap_free_read_buf(soapconn); + + /*get next single Offline Message*/ + msn_soap_post(soapconn,NULL,msn_oim_retrieve_connect_init); +} + +static void +msn_oim_get_written_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn * soapconn = data; + + soapconn->read_cb = msn_oim_get_read_cb; +// msn_soap_read_cb(data,source,cond); +} + +/* parse the oim XML data + * and post it to the soap server to get the Offline Message + * */ +void +msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg) +{ + xmlnode *mdNode,*mNode,*ENode,*INode,*rtNode,*nNode; + char *passport,*rTime,*msgid,*nickname; + + mdNode = xmlnode_from_str(xmlmsg, strlen(xmlmsg)); + for(mNode = xmlnode_get_child(mdNode, "M"); mNode; + mNode = xmlnode_get_next_twin(mNode)){ + /*email Node*/ + ENode = xmlnode_get_child(mNode,"E"); + passport = xmlnode_get_data(ENode); + /*Index */ + INode = xmlnode_get_child(mNode,"I"); + msgid = xmlnode_get_data(INode); + /*Nickname*/ + nNode = xmlnode_get_child(mNode,"N"); + nickname = xmlnode_get_data(nNode); + /*receive time*/ + rtNode = xmlnode_get_child(mNode,"RT"); + if(rtNode != NULL) + rTime = xmlnode_get_data(rtNode); +/* gaim_debug_info("MaYuan","E:{%s},I:{%s},rTime:{%s}\n",passport,msgid,rTime);*/ + + oim->oim_list = g_list_append(oim->oim_list,msgid); + msn_oim_post_single_get_msg(oim,msgid); + g_free(passport); +// g_free(msgid); + g_free(rTime); + g_free(nickname); + } +} + +/*Post to get the Offline Instant Message*/ +static void +msn_oim_post_single_get_msg(MsnOim *oim,const char *msgid) +{ + MsnSoapReq *soap_request; + const char *soap_body,*t,*p; + + gaim_debug_info("MaYuan","Get single OIM Message\n"); + t = oim->session->passport_info.t; + p = oim->session->passport_info.p; + + soap_body = g_strdup_printf(MSN_OIM_GET_TEMPLATE, + t, + p, + msgid + ); + soap_request = msn_soap_request_new(MSN_OIM_RETRIEVE_HOST, + MSN_OIM_RETRIEVE_URL,MSN_OIM_GET_SOAP_ACTION, + soap_body, + msn_oim_get_read_cb, + msn_oim_get_written_cb); + msn_soap_post(oim->retrieveconn,soap_request,msn_oim_retrieve_connect_init); +} + +/*msn oim retrieve server connect init */ +static void +msn_oim_retrieve_connect_init(MsnSoapConn *soapconn) +{ + gaim_debug_info("MaYuan","msn_oim_connect...\n"); + msn_soap_init(soapconn,MSN_OIM_RETRIEVE_HOST,1, + msn_oim_get_connect_cb, + msn_oim_get_error_cb); +} + +/*Msn OIM Send Server Connect Init Function*/ +static void +msn_oim_send_connect_init(MsnSoapConn *sendconn) +{ + gaim_debug_info("MaYuan","msn oim send connect init...\n"); + msn_soap_init(sendconn,MSN_OIM_SEND_HOST,1, + msn_oim_send_connect_cb, + msn_oim_send_error_cb); +} + +/*endof oim.c*/ diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/oim.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/msn/oim.h Sun Apr 15 04:29:56 2007 +0000 @@ -0,0 +1,148 @@ +/** + * @file oim.h Header file for oim.c + * Author + * MaYuan + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _MSN_OIM_H_ +#define _MSN_OIM_H_ + +/*OIM Retrieve SOAP Template*/ +#define MSN_OIM_RETRIEVE_HOST "rsi.hotmail.com" +#define MSN_OIM_RETRIEVE_URL "/rsi/rsi.asmx" +#define MSN_OIM_GET_SOAP_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMessage" + +#define MSN_OIM_GET_TEMPLATE ""\ +""\ + ""\ + ""\ + "%s"\ + "

%s

"\ + "
"\ + "
"\ + ""\ + ""\ + "%s"\ + "false"\ + ""\ + ""\ +"
" + +/*OIM Delete SOAP Template*/ +#define MSN_OIM_DEL_SOAP_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/DeleteMessages" + +#define MSN_OIM_DEL_TEMPLATE ""\ +""\ + ""\ + ""\ + "%s"\ + "

%s

"\ + "
"\ + "
"\ + ""\ + ""\ + ""\ + "%s"\ + ""\ + ""\ + ""\ +"
" + +/*OIM Send SOAP Template*/ +#define MSN_OIM_MSG_TEMPLATE "MIME-Version: 1.0\n"\ + "Content-Type: text/plain; charset=UTF-8\n"\ + "Content-Transfer-Encoding: base64\n"\ + "X-OIM-Message-Type: OfflineMessage\n"\ + "X-OIM-Run-Id: {%s}\n"\ + "X-OIM-Sequence-Num: %d\n\n"\ + "%s" + +#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_TEMPLATE ""\ +""\ + ""\ + ""\ + ""\ + ""\ + ""\ + "http://messenger.msn.com"\ + "%d"\ + ""\ + ""\ + ""\ + "text"\ + "%s"\ + ""\ +"" + +typedef struct _MsnOimSendReq MsnOimSendReq; + +struct _MsnOimSendReq +{ + char *from_member; + char *friendname; + char *to_member; + char *oim_msg; + gint send_seq; +}; + +typedef struct _MsnOim MsnOim; + +struct _MsnOim +{ + MsnSession *session; + + MsnSoapConn *retrieveconn; + GList * oim_list; + + MsnSoapConn *sendconn; + char *challenge; + char *run_id; + gint send_seq; + GQueue *send_queue; +}; + +/**************************************************** + * function prototype + * **************************************************/ +MsnOim * msn_oim_new(MsnSession *session); +void msn_oim_destroy(MsnOim *oim); +void msn_oim_connect(MsnOim *oim); + +void msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg); + +/*Send OIM Message*/ +void msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername, + const char *friendname, const char *tomember, + const char * msg); + +void msn_oim_send_msg(MsnOim *oim); + +/*get the OIM message*/ +void msn_oim_get_msg(MsnOim *oim); + +/*report the oim message to the conversation*/ +void msn_oim_report_user(MsnOim *oim,const char *passport,char *msg); + +#endif/* _MSN_OIM_H_*/ +/*endof oim.h*/ diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/servconn.c --- a/libpurple/protocols/msn/servconn.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/servconn.c Sun Apr 15 04:29:56 2007 +0000 @@ -240,7 +240,9 @@ { servconn->processing = TRUE; return TRUE; - }else{ + } + else + { return FALSE; } } @@ -435,10 +437,13 @@ servconn->rx_len -= cur_len; - if (servconn->payload_len){ + if (servconn->payload_len) + { msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len); servconn->payload_len = 0; - }else{ + } + else + { msn_cmdproc_process_cmd_text(servconn->cmdproc, cur); servconn->payload_len = servconn->cmdproc->last_cmd->payload_len; } diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/session.c --- a/libpurple/protocols/msn/session.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/session.c Sun Apr 15 04:29:56 2007 +0000 @@ -270,7 +270,11 @@ g_return_if_fail(gc != NULL); - for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next){ + /* The core used to use msn_add_buddy to add all buddies before + * being logged in. This no longer happens, so we manually iterate + * over the whole buddy list to identify sync issues. */ + for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next) + { if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) continue; for(cnode = gnode->child; cnode; cnode = cnode->next) { @@ -314,7 +318,7 @@ * being logged in. This no longer happens, so we manually iterate * over the whole buddy list to identify sync issues. */ - for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next){ + for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next) { PurpleGroup *group = (PurpleGroup *)gnode; const char *group_name = group->name; if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) @@ -331,14 +335,14 @@ if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) continue; b = (PurpleBuddy *)bnode; - if(b->account == gc->account){ + if(purple_buddy_get_account(b) == purple_connection_get_account(gc)) { MsnUser *remote_user; gboolean found = FALSE; - purple_debug_info("MaYuan","buddy name:%s,group name:%s\n",b->name,group_name); - remote_user = msn_userlist_find_user(session->userlist, b->name); + remote_user = msn_userlist_find_user(session->userlist, purple_buddy_get_name(b)); - if ((remote_user != NULL) && (remote_user->list_op & MSN_LIST_FL_OP)){ + if ((remote_user != NULL) && (remote_user->list_op & MSN_LIST_FL_OP)) + { const char *group_id; GList *l; @@ -350,16 +354,19 @@ } purple_debug_info("MaYuan","group_id:{%s}\n",group_id); - for (l = remote_user->group_ids; l != NULL; l = l->next){ + for (l = remote_user->group_ids; l != NULL; l = l->next) + { purple_debug_info("MaYuan","l->data:{%s}\n",l->data); - if (!g_strcasecmp(group_id ,l->data)){ + if (!g_strcasecmp(group_id ,l->data)) + { found = TRUE; break; } } } - if (!found){ + if (!found) + { /* The user was not on the server list or not in that group * on the server list */ msn_show_sync_issue(session, b->name, group_name); diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/session.h diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/soap.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/msn/soap.c Sun Apr 15 04:29:56 2007 +0000 @@ -0,0 +1,593 @@ +/** + * @file soap.c + * SOAP connection related process + * Author + * MaYuan + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "msn.h" +#include "soap.h" + +/*define this Macro to debug soap server action*/ +#undef MSN_SOAP_DEBUG + +/*local function prototype*/ +void msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step); + +/*setup the soap process step*/ +void +msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step) +{ + soapconn->step = step; +} + +//msn_soap_new(MsnSession *session,gpointer data,int sslconn) +/*new a soap connection*/ +MsnSoapConn * +msn_soap_new(MsnSession *session,gpointer data,int sslconn) +{ + MsnSoapConn *soapconn; + + soapconn = g_new0(MsnSoapConn, 1); + soapconn->session = session; + soapconn->parent = data; + soapconn->ssl_conn = sslconn; + + soapconn->gsc = NULL; + soapconn->input_handler = -1; + soapconn->output_handler = -1; + + msn_soap_set_process_step(soapconn,MSN_SOAP_UNCONNECTED); + soapconn->soap_queue = g_queue_new(); + return soapconn; +} + +/*ssl soap connect callback*/ +void +msn_soap_connect_cb(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + MsnSoapConn * soapconn; + MsnSession *session; + + gaim_debug_info("MaYuan","Soap connection connected!\n"); + soapconn = data; + g_return_if_fail(soapconn != NULL); + + session = soapconn->session; + g_return_if_fail(session != NULL); + + soapconn->gsc = gsc; + + /*connection callback*/ + if(soapconn->connect_cb != NULL){ + soapconn->connect_cb(data,gsc,cond); + } + + msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTED); + /*we do the SOAP request here*/ + msn_soap_post_head_request(soapconn); +} + +/*ssl soap error callback*/ +static void +msn_soap_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) +{ + MsnSoapConn * soapconn = data; + + g_return_if_fail(data != NULL); + gaim_debug_info("MaYuan","Soap connection error!\n"); + msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED); + + /*error callback*/ + if(soapconn->error_cb != NULL){ + soapconn->error_cb(gsc,error,data); + } +} + +/*init the soap connection*/ +void +msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl, + GaimSslInputFunction connect_cb, + GaimSslErrorFunction error_cb) +{ + gaim_debug_info("MaYuan","msn_soap_init...\n"); + soapconn->login_host = g_strdup(host); + soapconn->ssl_conn = ssl; + soapconn->connect_cb = connect_cb; + soapconn->error_cb = error_cb; +} + +/*connect the soap connection*/ +void +msn_soap_connect(MsnSoapConn *soapconn) +{ + if(soapconn->ssl_conn){ + gaim_ssl_connect(soapconn->session->account, soapconn->login_host, + GAIM_SSL_DEFAULT_PORT, msn_soap_connect_cb, msn_soap_error_cb, + soapconn); + }else{ + } + msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTING); +} + +/*close the soap connection*/ +void +msn_soap_close(MsnSoapConn *soapconn) +{ + if(soapconn->ssl_conn){ + if(soapconn->gsc != NULL){ + gaim_ssl_close(soapconn->gsc); + soapconn->gsc = NULL; + } + }else{ + } + msn_soap_set_process_step(soapconn,MSN_SOAP_UNCONNECTED); +} + +/*clean the unhandled SOAP request*/ +void +msn_soap_clean_unhandled_request(MsnSoapConn *soapconn) +{ + MsnSoapReq *request; + + g_return_if_fail(soapconn != NULL); + + while ((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){ + msn_soap_request_free(request); + } +} + +/*destroy the soap connection*/ +void +msn_soap_destroy(MsnSoapConn *soapconn) +{ + if(soapconn->login_host) + g_free(soapconn->login_host); + + if(soapconn->login_path) + g_free(soapconn->login_path); + + /*remove the write handler*/ + if (soapconn->output_handler > 0){ + gaim_input_remove(soapconn->output_handler); + } + /*remove the read handler*/ + if (soapconn->input_handler > 0){ + gaim_input_remove(soapconn->input_handler); + } + msn_soap_free_read_buf(soapconn); + msn_soap_free_write_buf(soapconn); + + /*close ssl connection*/ + msn_soap_close(soapconn); + + /*process the unhandled soap request*/ + msn_soap_clean_unhandled_request(soapconn); + + g_queue_free(soapconn->soap_queue); + g_free(soapconn); +} + +/*check the soap is connected? + * if connected return 1 + */ +int +msn_soap_connected(MsnSoapConn *soapconn) +{ + if(soapconn->ssl_conn){ + return (soapconn->gsc == NULL? 0 : 1); + } + return(soapconn->fd>0? 1 : 0); +} + +/*read and append the content to the buffer*/ +static gssize +msn_soap_read(MsnSoapConn *soapconn) +{ + gssize len,requested_len; + char temp_buf[MSN_SOAP_READ_BUFF_SIZE]; + +// requested_len = (soapconn->need_to_read > 0) ? soapconn->need_to_read : MSN_SOAP_READ_BUFF_SIZE; + requested_len = MSN_SOAP_READ_BUFF_SIZE; + if(soapconn->ssl_conn){ + len = gaim_ssl_read(soapconn->gsc, temp_buf,requested_len); + }else{ + len = read(soapconn->fd, temp_buf,requested_len); + } + if(len >0){ + soapconn->read_buf = g_realloc(soapconn->read_buf, + soapconn->read_len + len + 1); + memcpy(soapconn->read_buf + soapconn->read_len, temp_buf, len); + soapconn->read_len += len; + soapconn->read_buf[soapconn->read_len] = '\0'; + } +#ifdef MSN_SOAP_DEBUG + gaim_debug_info("MaYuan","++soap ssl read:{%d}\n",len); + gaim_debug_info("MaYuan","nexus ssl read:{%s}\n",soapconn->read_buf); +#endif + return len; +} + +/*read the whole SOAP server response*/ +void +msn_soap_read_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn *soapconn = data; + MsnSession *session; + int len; + char * body_start,*body_len; + char *length_start,*length_end; + +// gaim_debug_misc("MaYuan", "soap read cb\n"); + session = soapconn->session; + g_return_if_fail(session != NULL); + + if (soapconn->input_handler == -1){ + soapconn->input_handler = gaim_input_add(soapconn->gsc->fd, + GAIM_INPUT_READ, msn_soap_read_cb, soapconn); + } + + /*read the request header*/ + len = msn_soap_read(soapconn); + if (len < 0 && errno == EAGAIN){ + return; + }else if (len < 0) { + gaim_debug_error("msn", "read Error!len:%d\n",len); + gaim_input_remove(soapconn->input_handler); + soapconn->input_handler = -1; + g_free(soapconn->read_buf); + soapconn->read_buf = NULL; + soapconn->read_len = 0; + /* TODO: error handling */ + return; + } + + if(soapconn->read_buf == NULL){ + return; + } + + if (strstr(soapconn->read_buf, "HTTP/1.1 302") != NULL) + { + /* Redirect. */ + char *location, *c; + + gaim_debug_error("MaYuan", "soap redirect\n"); + location = strstr(soapconn->read_buf, "Location: "); + if (location == NULL) + { + msn_soap_free_read_buf(soapconn); + + return; + } + location = strchr(location, ' ') + 1; + + if ((c = strchr(location, '\r')) != NULL) + *c = '\0'; + + /* Skip the http:// */ + if ((c = strchr(location, '/')) != NULL) + location = c + 2; + + if ((c = strchr(location, '/')) != NULL) + { + g_free(soapconn->login_path); + soapconn->login_path = g_strdup(c); + + *c = '\0'; + } + + g_free(soapconn->login_host); + soapconn->login_host = g_strdup(location); + + gaim_ssl_connect(session->account, soapconn->login_host, + GAIM_SSL_DEFAULT_PORT, msn_soap_connect_cb, + msn_soap_error_cb, soapconn); + } + else if (strstr(soapconn->read_buf, "HTTP/1.1 401 Unauthorized") != NULL) + { + const char *error; + + gaim_debug_error("MaYuan", "soap 401\n"); + if ((error = strstr(soapconn->read_buf, "WWW-Authenticate")) != NULL) + { + if ((error = strstr(error, "cbtxt=")) != NULL) + { + const char *c; + char *temp; + + error += strlen("cbtxt="); + + if ((c = strchr(error, '\n')) == NULL) + c = error + strlen(error); + + temp = g_strndup(error, c - error); + error = gaim_url_decode(temp); + g_free(temp); + } + } + + msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, error); + } + else if ((strstr(soapconn->read_buf, "HTTP/1.1 200 OK")) + ||(strstr(soapconn->read_buf, "HTTP/1.1 500"))) + { + /*OK! process the SOAP body*/ + body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n"); + if(!body_start){ + return; + } + body_start += 4; + + // gaim_debug_misc("msn", "Soap Read: {%s}\n", soapconn->read_buf); + + /* we read the content-length*/ + length_start = strstr(soapconn->read_buf, "Content-Length: "); + length_start += strlen("Content-Length: "); + length_end = strstr(length_start, "\r\n"); + body_len = g_strndup(length_start,length_end - length_start); + + /*setup the conn body */ + soapconn->body = body_start; + soapconn->body_len = atoi(body_len); +#ifdef MSN_SOAP_DEBUG + gaim_debug_misc("MaYuan","SOAP Read length :%d,body len:%d\n",soapconn->read_len,soapconn->body_len); +#endif + soapconn->need_to_read = (body_start - soapconn->read_buf +soapconn->body_len) - soapconn->read_len; + if(soapconn->need_to_read >0){ + return; + } + g_free(body_len); + + /*remove the read handler*/ + gaim_input_remove(soapconn->input_handler); + soapconn->input_handler = -1; + /* + * close the soap connection,if more soap request came, + * Just reconnect to do it, + * + * To solve the problem described below: + * When I post the soap request in one socket one after the other, + * The first read is ok, But the second soap read always got 0 bytes, + * Weird! + * */ + msn_soap_close(soapconn); + + /*call the read callback*/ + if(soapconn->read_cb != NULL){ + soapconn->read_cb(soapconn,source,0); + } + } + return; +} + +void +msn_soap_free_read_buf(MsnSoapConn *soapconn) +{ + if(soapconn->read_buf){ + g_free(soapconn->read_buf); + } + soapconn->read_buf = NULL; + soapconn->read_len = 0; + soapconn->need_to_read = 0; +} + +void +msn_soap_free_write_buf(MsnSoapConn *soapconn) +{ + if(soapconn->write_buf){ + g_free(soapconn->write_buf); + } + soapconn->write_buf = NULL; + soapconn->written_len = 0; +} + +/*Soap write process func*/ +static void +msn_soap_write_cb(gpointer data, gint source, GaimInputCondition cond) +{ + MsnSoapConn *soapconn = data; + int len, total_len; + + g_return_if_fail(soapconn != NULL); + if(soapconn->write_buf == NULL){ + gaim_debug_error("MaYuan","soap buffer is NULL\n"); + gaim_input_remove(soapconn->output_handler); + soapconn->output_handler = -1; + return; + } + total_len = strlen(soapconn->write_buf); + + /* + * write the content to SSL server, + */ + len = gaim_ssl_write(soapconn->gsc, + soapconn->write_buf + soapconn->written_len, + total_len - soapconn->written_len); + + if (len < 0 && errno == EAGAIN) + return; + else if (len <= 0){ + /*SSL write error!*/ + gaim_input_remove(soapconn->output_handler); + soapconn->output_handler = -1; + /* TODO: notify of the error */ + return; + } + soapconn->written_len += len; + + if (soapconn->written_len < total_len) + return; + + gaim_input_remove(soapconn->output_handler); + soapconn->output_handler = -1; + + /*clear the write buff*/ + msn_soap_free_write_buf(soapconn); + + /* Write finish! + * callback for write done + */ + if(soapconn->written_cb != NULL){ + soapconn->written_cb(soapconn, source, 0); + } + /*maybe we need to read the input?*/ + msn_soap_read_cb(soapconn,source,0); +} + +/*write the buffer to SOAP connection*/ +void +msn_soap_write(MsnSoapConn * soapconn, char *write_buf, GaimInputFunction written_cb) +{ + soapconn->write_buf = write_buf; + soapconn->written_len = 0; + soapconn->written_cb = written_cb; + + /*clear the read buffer first*/ + /*start the write*/ + soapconn->output_handler = gaim_input_add(soapconn->gsc->fd, GAIM_INPUT_WRITE, + msn_soap_write_cb, soapconn); + msn_soap_write_cb(soapconn, soapconn->gsc->fd, GAIM_INPUT_WRITE); +} + +/* New a soap request*/ +MsnSoapReq * +msn_soap_request_new(const char *host,const char *post_url,const char *soap_action, + const char *body, + GaimInputFunction read_cb,GaimInputFunction written_cb) +{ + MsnSoapReq *request; + + request = g_new0(MsnSoapReq, 1); + request->id = 0; + + request->login_host = g_strdup(host); + request->login_path = g_strdup(post_url); + request->soap_action = g_strdup(soap_action); + request->body = g_strdup(body); + request->read_cb = read_cb; + request->written_cb = written_cb; + + return request; +} + +/*free a soap request*/ +void +msn_soap_request_free(MsnSoapReq *request) +{ + g_return_if_fail(request != NULL); + + g_free(request->login_host); + g_free(request->login_path); + g_free(request->soap_action); + g_free(request->body); + request->read_cb = NULL; + request->written_cb = NULL; + + g_free(request); +} + +/*post the soap request queue's head request*/ +void +msn_soap_post_head_request(MsnSoapConn *soapconn) +{ + g_return_if_fail(soapconn->soap_queue != NULL); + + if(!g_queue_is_empty(soapconn->soap_queue)){ + MsnSoapReq *request; + if((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){ + msn_soap_post_request(soapconn,request); + } + } + msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTED_IDLE); +} + +/*post the soap request , + * if not connected, Connected first. + */ +void +msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request, + MsnSoapConnectInitFunction msn_soap_init_func) +{ + if(request != NULL){ + g_queue_push_tail(soapconn->soap_queue, request); + } + if(!msn_soap_connected(soapconn)&&(soapconn->step == MSN_SOAP_UNCONNECTED) + &&(!g_queue_is_empty(soapconn->soap_queue))){ + /*not connected?and we have something to process connect it first*/ + gaim_debug_info("Ma Yuan","soap is not connected!\n"); + msn_soap_init_func(soapconn); + msn_soap_connect(soapconn); + return; + } + gaim_debug_info("Ma Yuan","soap connected!\n"); + + /*if connected, what we only needed to do is to queue the request, + * when SOAP request in the queue processed done, will do this command. + * we just waiting... + * If we send the request this time,error may occure + */ +#if 0 + if(soapconn->step == MSN_SOAP_CONNECTED_IDLE){ + msn_soap_post_head_request(soapconn); + } +#endif +} + +/*Post the soap request action*/ +void +msn_soap_post_request(MsnSoapConn *soapconn,MsnSoapReq *request) +{ + char * soap_head = NULL; + char * request_str = NULL; + + gaim_debug_info("MaYuan","msn_soap_post_request()...\n"); + msn_soap_set_process_step(soapconn,MSN_SOAP_PROCESSING); + soap_head = g_strdup_printf( + "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" + "Content-Length: %d\r\n" + "Connection: Keep-Alive\r\n" + "Cache-Control: no-cache\r\n\r\n", + request->login_path, + request->soap_action, + soapconn->session->passport_info.mspauth, + request->login_host, + strlen(request->body) + ); + request_str = g_strdup_printf("%s%s", soap_head,request->body); + g_free(soap_head); + +#ifdef MSN_SOAP_DEBUG + gaim_debug_info("MaYuan","send to server{%s}\n",request_str); +#endif + + /*free read buffer*/ + msn_soap_free_read_buf(soapconn); + /*post it to server*/ + msn_soap_write(soapconn,request_str,request->written_cb); +} + diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/soap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/msn/soap.h Sun Apr 15 04:29:56 2007 +0000 @@ -0,0 +1,145 @@ +/** + * @file soap.h + * header file for SOAP connection related process + * Author + * MaYuan + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _MSN_SOAP_H_ +#define _MSN_SOAP_H_ + +#define MSN_SOAP_READ_BUFF_SIZE 8192 + +typedef enum +{ + MSN_SOAP_UNCONNECTED, + MSN_SOAP_CONNECTING, + MSN_SOAP_CONNECTED, + MSN_SOAP_PROCESSING, + MSN_SOAP_CONNECTED_IDLE +}MsnSoapStep; + +/*MSN SoapRequest structure*/ +typedef struct _MsnSoapReq MsnSoapReq; + +/*MSN Https connection structure*/ +typedef struct _MsnSoapConn MsnSoapConn; + +typedef void (*MsnSoapConnectInitFunction)(MsnSoapConn *); + +struct _MsnSoapReq{ + /*request sequence*/ + int id; + + char *login_host; + char *login_path; + char *soap_action; + + char *body; + + GaimInputFunction read_cb; + GaimInputFunction written_cb; +}; + +struct _MsnSoapConn{ + MsnSession *session; + gpointer parent; + + char *login_host; + char *login_path; + char *soap_action; + + MsnSoapStep step; + /*ssl connection?*/ + guint ssl_conn; + /*normal connection*/ + guint fd; + /*SSL connection*/ + GaimSslConnection *gsc; + /*ssl connection callback*/ + GaimSslInputFunction connect_cb; + /*ssl error callback*/ + GaimSslErrorFunction error_cb; + + /*read handler*/ + guint input_handler; + /*write handler*/ + guint output_handler; + + /*Queue of SOAP request to send*/ + int soap_id; + GQueue *soap_queue; + + /*write buffer*/ + char *write_buf; + gsize written_len; + GaimInputFunction written_cb; + + /*read buffer*/ + char *read_buf; + gsize read_len; + gsize need_to_read; + GaimInputFunction read_cb; + + /*HTTP reply body part*/ + char *body; + int body_len; +}; + +/*Function Prototype*/ +/*Soap Request Function */ +MsnSoapReq *msn_soap_request_new(const char *host, const char *post_url, + const char *soap_action, const char *body, + GaimInputFunction read_cb, + GaimInputFunction written_cb); + +void msn_soap_request_free(MsnSoapReq *request); +void msn_soap_post_request(MsnSoapConn *soapconn,MsnSoapReq *request); +void msn_soap_post_head_request(MsnSoapConn *soapconn); + +/*new a soap conneciton */ +MsnSoapConn *msn_soap_new(MsnSession *session,gpointer data,int sslconn); + +/*destroy */ +void msn_soap_destroy(MsnSoapConn *soapconn); + +/*init a soap conneciton */ +void msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl,GaimSslInputFunction connect_cb,GaimSslErrorFunction error_cb); +void msn_soap_connect(MsnSoapConn *soapconn); +void msn_soap_close(MsnSoapConn *soapconn); + +/*write to soap*/ +void msn_soap_write(MsnSoapConn * soapconn, char *write_buf, GaimInputFunction written_cb); +void msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request,MsnSoapConnectInitFunction msn_soap_init_func); + +void msn_soap_free_read_buf(MsnSoapConn *soapconn); +void msn_soap_free_write_buf(MsnSoapConn *soapconn); +void msn_soap_connect_cb(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond); +void msn_soap_read_cb(gpointer data, gint source, GaimInputCondition cond); + +/*clean the unhandled request*/ +void msn_soap_clean_unhandled_request(MsnSoapConn *soapconn); + +/*check if the soap connection is connected*/ +int msn_soap_connected(MsnSoapConn *soapconn); + +#endif/*_MSN_SOAP_H_*/ + diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/state.c diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/state.h diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/switchboard.c --- a/libpurple/protocols/msn/switchboard.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/switchboard.c Sun Apr 15 04:29:56 2007 +0000 @@ -968,7 +968,7 @@ str = g_strdup_printf(_("%s just sent you a Nudge!"), username); g_free(username); - msn_switchboard_report_user(swboard, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, str); + msn_switchboard_report_user(swboard, PURPLE_MESSAGE_SYSTEM, str); g_free(str); } diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/sync.c --- a/libpurple/protocols/msn/sync.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/sync.c Sun Apr 15 04:29:56 2007 +0000 @@ -35,7 +35,8 @@ list_name = cmd->params[0]; - if (!g_ascii_strcasecmp(list_name, "AL")){ + if (!g_ascii_strcasecmp(list_name, "AL")) + { /* * If the current setting is AL, messages from users who * are not in BL will be delivered. @@ -43,7 +44,9 @@ * In other words, deny some. */ gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS; - }else{ + } + else + { /* If the current setting is BL, only messages from people * who are in the AL will be delivered. * @@ -86,7 +89,8 @@ lsg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session = cmdproc->session; - const char *name, *group_id; + const char *name; + const char *group_id; group_id = cmd->params[0]; name = purple_url_decode(cmd->params[1]); diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/user.c --- a/libpurple/protocols/msn/user.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/user.c Sun Apr 15 04:29:56 2007 +0000 @@ -222,16 +222,20 @@ g_return_if_fail(user != NULL); - if (filename == NULL || g_stat(filename, &st) == -1){ + if (filename == NULL || g_stat(filename, &st) == -1) + { msn_user_set_object(user, NULL); - }else if ((fp = g_fopen(filename, "rb")) != NULL){ + } + else if ((fp = g_fopen(filename, "rb")) != NULL) + { PurpleCipherContext *ctx; char *buf; gsize len; char *base64; unsigned char digest[20]; - if (msnobj == NULL) { + if (msnobj == NULL) + { msnobj = msn_object_new(); msn_object_set_local(msnobj); msn_object_set_type(msnobj, MSN_OBJECT_USERTILE); @@ -283,7 +287,9 @@ base64 = purple_base64_encode(digest, sizeof(digest)); msn_object_set_sha1c(msnobj, base64); g_free(base64); - }else{ + } + else + { purple_debug_error("msn", "Unable to open buddy icon %s!\n", filename); msn_user_set_object(user, NULL); } @@ -317,13 +323,15 @@ g = purple_find_group(group_name); - if ((id == NULL) && (g == NULL)){ + if ((id == NULL) && (g == NULL)) + { g = purple_group_new(group_name); purple_blist_add_group(g, NULL); } b = purple_find_buddy_in_group(account, passport, g); - if (b == NULL){ + if (b == NULL) + { b = purple_buddy_new(account, passport, NULL); purple_blist_add_buddy(b, NULL, g, NULL); } diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/user.h diff -r 60bc06498746 -r 6f986caeab59 libpurple/protocols/msn/userlist.c --- a/libpurple/protocols/msn/userlist.c Sun Apr 15 04:12:27 2007 +0000 +++ b/libpurple/protocols/msn/userlist.c Sun Apr 15 04:29:56 2007 +0000 @@ -219,14 +219,22 @@ if (group_id != NULL) { msn_user_add_group_id(user, group_id); - }else{ + } + else + { /* session->sync->fl_users_count++; */ } - }else if (list_id == MSN_LIST_AL){ + } + else if (list_id == MSN_LIST_AL) + { purple_privacy_permit_add(account, passport, TRUE); - }else if (list_id == MSN_LIST_BL){ + } + else if (list_id == MSN_LIST_BL) + { purple_privacy_deny_add(account, passport, TRUE); - }else if (list_id == MSN_LIST_RL){ + } + else if (list_id == MSN_LIST_RL) + { PurpleConnection *gc; PurpleConversation *convo; @@ -250,7 +258,8 @@ g_free(msg); } - if (!(user->list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP))){ + if (!(user->list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP))) + { /* * TODO: The friendly name was NULL for me when I * looked at this. Maybe we should use the store @@ -275,19 +284,29 @@ passport = msn_user_get_passport(user); - if (list_id == MSN_LIST_FL){ + if (list_id == MSN_LIST_FL) + { /* TODO: When is the user totally removed? */ - if (group_id != NULL){ + if (group_id >= 0) + { msn_user_remove_group_id(user, group_id); return; - }else{ + } + else + { /* session->sync->fl_users_count--; */ } - }else if (list_id == MSN_LIST_AL){ + } + else if (list_id == MSN_LIST_AL) + { purple_privacy_permit_remove(account, passport, TRUE); - }else if (list_id == MSN_LIST_BL){ + } + else if (list_id == MSN_LIST_BL) + { purple_privacy_deny_remove(account, passport, TRUE); - }else if (list_id == MSN_LIST_RL){ + } + else if (list_id == MSN_LIST_RL) + { PurpleConversation *convo; purple_debug_info("msn", @@ -312,7 +331,8 @@ user->list_op &= ~(1 << list_id); /* purple_user_remove_list_id (user, list_id); */ - if (user->list_op == 0){ + if (user->list_op == 0) + { purple_debug_info("msn", "Buddy '%s' shall be deleted?.\n", passport); } @@ -333,7 +353,8 @@ passport = msn_user_get_passport(user); store = msn_user_get_store_name(user); - if (list_op & MSN_LIST_FL_OP){ + if (list_op & MSN_LIST_FL_OP) + { GSList *c; for (c = group_ids; c != NULL; c = g_slist_next(c)) { char *group_id; @@ -346,19 +367,22 @@ serv_got_alias(gc, passport, store); } - if (list_op & MSN_LIST_AL_OP){ + if (list_op & MSN_LIST_AL_OP) + { /* These are users who are allowed to see our status. */ purple_privacy_deny_remove(account, passport, TRUE); purple_privacy_permit_add(account, passport, TRUE); } - if (list_op & MSN_LIST_BL_OP){ + if (list_op & MSN_LIST_BL_OP) + { /* These are users who are not allowed to see our status. */ purple_privacy_permit_remove(account, passport, TRUE); purple_privacy_deny_add(account, passport, TRUE); } - if (list_op & MSN_LIST_RL_OP){ + if (list_op & MSN_LIST_RL_OP) + { /* These are users who have us on their buddy list. */ /* * TODO: What is store name set to when this happens? @@ -367,8 +391,9 @@ * should use the friendly name, instead? --KingAnt */ - if (!(list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP))){ -// got_new_entry(gc, passport, store); + if (!(list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP))) + { + got_new_entry(gc, passport, store); } } @@ -403,13 +428,15 @@ GList *l; /*destroy userlist*/ - for (l = userlist->users; l != NULL; l = l->next){ + for (l = userlist->users; l != NULL; l = l->next) + { msn_user_destroy(l->data); } g_list_free(userlist->users); /*destroy group list*/ - for (l = userlist->groups; l != NULL; l = l->next){ + for (l = userlist->groups; l != NULL; l = l->next) + { msn_group_destroy(l->data); } g_list_free(userlist->groups); @@ -428,7 +455,8 @@ MsnUser *user; user = msn_userlist_find_user(userlist, passport); - if (user == NULL){ + if (user == NULL) + { user = msn_user_new(userlist, passport, userName); msn_userlist_add_user(userlist, user); } @@ -455,7 +483,8 @@ g_return_val_if_fail(passport != NULL, NULL); - for (l = userlist->users; l != NULL; l = l->next){ + for (l = userlist->users; l != NULL; l = l->next) + { MsnUser *user = (MsnUser *)l->data; // purple_debug_info("MsnUserList","user passport:%s,passport:%s\n",user->passport,passport); g_return_val_if_fail(user->passport != NULL, NULL); @@ -507,7 +536,8 @@ g_return_val_if_fail(userlist != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); - for (l = userlist->groups; l != NULL; l = l->next){ + for (l = userlist->groups; l != NULL; l = l->next) + { MsnGroup *group = l->data; if ((group->name != NULL) && !g_strcasecmp(name, group->name)) @@ -524,11 +554,10 @@ group = msn_userlist_find_group_with_name(userlist, group_name); - if (group != NULL){ + if (group != NULL) return msn_group_get_id(group); - }else{ + else return NULL; - } } const char * @@ -538,11 +567,10 @@ group = msn_userlist_find_group_with_id(userlist, group_id); - if (group != NULL){ + if (group != NULL) return msn_group_get_name(group); - }else{ + else return NULL; - } } void @@ -599,7 +627,8 @@ } /* First we're going to check if not there. */ - if (!(user_is_there(user, list_id, group_id))){ + if (!(user_is_there(user, list_id, group_id))) + { list = lists[list_id]; purple_debug_error("msn", "User '%s' is not there: %s\n", who, list); @@ -626,7 +655,8 @@ purple_debug_info("MaYuan", "userlist add buddy,name:{%s},group:{%s}\n",who ,group_name); group_id = NULL; - if (!purple_email_is_valid(who)){ + if (!purple_email_is_valid(who)) + { /* only notify the user about problems adding to the friends list * maybe we should do something else for other lists, but it probably * won't cause too many problems if we just ignore it */ @@ -640,10 +670,12 @@ return; } - if (group_name != NULL){ + if (group_name != NULL) + { group_id = msn_userlist_find_group_id(userlist, group_name); - if (group_id == NULL){ + if (group_id == NULL) + { /* Whoa, we must add that group first. */ msn_request_add_group(userlist, who, NULL, group_name); return; @@ -653,7 +685,8 @@ user = msn_userlist_find_user(userlist, who); /* First we're going to check if it's already there. */ - if (user_is_there(user, list_id, group_id)){ + if (user_is_there(user, list_id, group_id)) + { list = lists[list_id]; purple_debug_error("msn", "User '%s' is already there: %s\n", who, list); return; @@ -666,10 +699,8 @@ purple_debug_info("MaYuan", "add user:{%s} to group id {%s}\n",store_name ,group_id); msn_add_contact(userlist->session->contact,who,group_id); -#if 1 msn_notification_add_buddy(userlist->session->notification, list, who, store_name, group_id); -#endif } void @@ -680,7 +711,8 @@ new_group_id = msn_userlist_find_group_id(userlist, new_group_name); - if (new_group_id == NULL){ + if (new_group_id == NULL) + { msn_request_add_group(userlist, who, old_group_name, new_group_name); return; } @@ -700,18 +732,22 @@ g_return_if_fail(gc != NULL); - for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next){ - if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next) + { + if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) continue; - for(cnode = gnode->child; cnode; cnode = cnode->next) { - if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + for (cnode = gnode->child; cnode; cnode = cnode->next) + { + if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) continue; - for(bnode = cnode->child; bnode; bnode = bnode->next) { + for (bnode = cnode->child; bnode; bnode = bnode->next) + { PurpleBuddy *b; - if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) continue; b = (PurpleBuddy *)bnode; - if(b->account == gc->account){ + if (b->account == gc->account) + { user = msn_userlist_find_add_user(session->userlist, b->name,NULL); b->proto_data = user; @@ -720,12 +756,14 @@ } } } - for (l = session->account->permit; l != NULL; l = l->next) { + for (l = session->account->permit; l != NULL; l = l->next) + { user = msn_userlist_find_add_user(session->userlist, (char *)l->data,NULL); msn_user_set_op(user, MSN_LIST_AL_OP); } - for (l = session->account->deny; l != NULL; l = l->next) { + for (l = session->account->deny; l != NULL; l = l->next) + { user = msn_userlist_find_add_user(session->userlist, (char *)l->data,NULL); msn_user_set_op(user, MSN_LIST_BL_OP);