# HG changeset patch # User Ma Yuan # Date 1156562700 0 # Node ID 1b6c631012d9ceca41451af41c6a421bf3566994 # Parent 509383ef25f8226dd8f3cd05f15de5ea2a66cff0 [gaim-migrate @ 17034] middle version for oim send not stable,don't use it! committed by MaYuan committer: Ethan Blanton diff -r 509383ef25f8 -r 1b6c631012d9 src/protocols/msn/contact.c --- a/src/protocols/msn/contact.c Thu Aug 24 16:38:30 2006 +0000 +++ b/src/protocols/msn/contact.c Sat Aug 26 03:25:00 2006 +0000 @@ -117,7 +117,7 @@ int list_op =0; char * passport; xmlnode * node,*body,*response,*result,*services,*service,*memberships; - xmlnode *membershipnode,*members,*member,*passportNode,*role; + xmlnode *membershipnode,*members,*member,*passportNode; session = contact->session; gaim_debug_misc("xml","parse contact list:{%s}\nsize:%d\n",contact->soapconn->body,contact->soapconn->body_len); @@ -143,9 +143,13 @@ gaim_debug_misc("xml","memberships{%p},name:%s\n",memberships,memberships->name); for(membershipnode = xmlnode_get_child(memberships, "Membership"); membershipnode; membershipnode = xmlnode_get_next_twin(membershipnode)){ - role = xmlnode_get_child(membershipnode,"MemberRole"); - list_op = msn_get_memberrole(xmlnode_get_data(role)); - gaim_debug_misc("memberrole","role:%s,list_op:%d\n",xmlnode_get_data(role),list_op); + xmlnode *roleNode; + char *role; + roleNode = xmlnode_get_child(membershipnode,"MemberRole"); + role=xmlnode_get_data(roleNode); + list_op = msn_get_memberrole(role); + gaim_debug_misc("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)){ @@ -160,9 +164,11 @@ typeNode = xmlnode_get_child(member,"Type"); type = xmlnode_get_data(typeNode); gaim_debug_misc("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")){ } @@ -174,6 +180,7 @@ gaim_debug_info("Email","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); } } } @@ -268,18 +275,20 @@ continue; } - gaim_debug_misc("MsnContact","group_id:%s name:%s\n",group_id,group_name); + 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_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("MsnContact","group_id:%s name:%s,value:%d\n",group_id,group_name,*group_name=='\0'); + 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); @@ -293,7 +302,7 @@ 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("MsnContact","group_id:%s name:%s,value:%d\n",group_id,group_name,*group_name=='\0'); + 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); @@ -335,38 +344,44 @@ if(!strcmp(msnEnabled,"true")){ emailNode = xmlnode_get_child(contactEmailNode,"email"); passport = xmlnode_get_data(emailNode); - gaim_debug_info("Ma Yuan","Yahoo User %s\n",passport); + gaim_debug_info("MsnAB","Yahoo User %s\n",passport); break; } + g_free(msnEnabled); } }else{ passport = xmlnode_get_data(passportName); } displayName = xmlnode_get_child(contactInfo,"displayName"); - if(displayName == NULL) - Name = passport; - else + if(displayName == NULL){ + Name = g_strdup(passport); + }else{ Name =xmlnode_get_data(displayName); + } - gaim_debug_misc("contact","name:%s,Id:{%s},display:{%s}\n", + gaim_debug_misc("MsnAB","name:%s,Id:{%s},display:{%s}\n", passport, - xmlnode_get_data(contactId), + 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("MsnContact","\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("contact","guid:%s\n",group_id); + gaim_debug_misc("MsnAB","guid:%s\n",group_id); + g_free(group_id); } }else{ group_id = g_strdup(MSN_INDIVIDUALS_GROUP_ID); diff -r 509383ef25f8 -r 1b6c631012d9 src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Thu Aug 24 16:38:30 2006 +0000 +++ b/src/protocols/msn/msn.c Sat Aug 26 03:25:00 2006 +0000 @@ -824,65 +824,81 @@ account = gaim_connection_get_account(gc); msn_import_html(message, &msgformat, &msgtext); + if(msn_user_is_online(account, who)){ + /*User online,then send Online Instant Message*/ - if (strlen(msgtext) + strlen(msgformat) + strlen(VERSION) > 1564) - { + if (strlen(msgtext) + strlen(msgformat) + strlen(VERSION) > 1564) + { + g_free(msgformat); + g_free(msgtext); + + return -E2BIG; + } + + msg = msn_message_new_plain(msgtext); + msg->remote_user = g_strdup(who); + msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); + g_free(msgformat); g_free(msgtext); - return -E2BIG; - } + gaim_debug_info("MaYuan","prepare to send online Message\n"); + if (g_ascii_strcasecmp(who, gaim_account_get_username(account))) + { + MsnSession *session; + MsnSwitchBoard *swboard; - msg = msn_message_new_plain(msgtext); - msg->remote_user = g_strdup(who); - msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); - - g_free(msgformat); - g_free(msgtext); + session = gc->proto_data; + if(strstr(who,"yahoo") != NULL){ + gaim_debug_info("MaYuan","send to Yahoo!\n"); + uum_send_msg(session,msg); + }else{ + gaim_debug_info("MaYuan","send via switchboard\n"); + swboard = msn_session_get_swboard(session, who, MSN_SB_FLAG_IM); + msn_switchboard_send_msg(swboard, msg, TRUE); + } + } + else + { + char *body_str, *body_enc, *pre, *post; + const char *format; + /* + * In MSN, you can't send messages to yourself, so + * we'll fake like we received it ;) + */ + body_str = msn_message_to_string(msg); + body_enc = g_markup_escape_text(body_str, -1); + g_free(body_str); - gaim_debug_info("MaYuan","prepare to send...\n"); - if (g_ascii_strcasecmp(who, gaim_account_get_username(account))) - { + format = msn_message_get_attr(msg, "X-MMS-IM-Format"); + msn_parse_format(format, &pre, &post); + body_str = g_strdup_printf("%s%s%s", pre ? pre : "", + body_enc ? body_enc : "", post ? post : ""); + g_free(body_enc); + g_free(pre); + g_free(post); + + serv_got_typing_stopped(gc, who); + serv_got_im(gc, who, body_str, flags, time(NULL)); + g_free(body_str); + } + + msn_message_destroy(msg); + }else { + /*send Offline Instant Message*/ MsnSession *session; - MsnSwitchBoard *swboard; - + MsnOim *oim; + char *friendname; + + gaim_debug_info("MaYuan","prepare to send offline Message\n"); session = gc->proto_data; - if(strstr(who,"yahoo") != NULL){ - gaim_debug_info("MaYuan","send to Yahoo!\n"); - uum_send_msg(session,msg); - }else{ - gaim_debug_info("MaYuan","send via switchboard\n"); - swboard = msn_session_get_swboard(session, who, MSN_SB_FLAG_IM); - msn_switchboard_send_msg(swboard, msg, TRUE); - } + oim = session->oim; + friendname = g_strdup_printf("=?utf-8?B?Y2xpZW50?="); + msn_oim_prep_send_msg_info(oim, + gaim_account_get_username(account),friendname,who, + msg); + msn_oim_send_msg(oim); } - else - { - char *body_str, *body_enc, *pre, *post; - const char *format; - /* - * In MSN, you can't send messages to yourself, so - * we'll fake like we received it ;) - */ - body_str = msn_message_to_string(msg); - body_enc = g_markup_escape_text(body_str, -1); - g_free(body_str); - - format = msn_message_get_attr(msg, "X-MMS-IM-Format"); - msn_parse_format(format, &pre, &post); - body_str = g_strdup_printf("%s%s%s", pre ? pre : "", - body_enc ? body_enc : "", post ? post : ""); - g_free(body_enc); - g_free(pre); - g_free(post); - - serv_got_typing_stopped(gc, who); - serv_got_im(gc, who, body_str, flags, time(NULL)); - g_free(body_str); - } - - msn_message_destroy(msg); - return 1; } diff -r 509383ef25f8 -r 1b6c631012d9 src/protocols/msn/oim.c --- a/src/protocols/msn/oim.c Thu Aug 24 16:38:30 2006 +0000 +++ b/src/protocols/msn/oim.c Sat Aug 26 03:25:00 2006 +0000 @@ -26,11 +26,13 @@ #include "msn.h" #include "soap.h" #include "oim.h" +#include "msn-utils.h" /*Local Function Prototype*/ static void msn_oim_post_single_get_msg(MsnOim *oim,const char *msgid); void msn_oim_retrieve_connect_init(MsnSoapConn *soapconn); void msn_oim_send_connect_init(MsnSoapConn *soapconn); +void msn_oim_free_send_req(MsnOimSendReq *req); /*new a OIM object*/ MsnOim * @@ -41,9 +43,13 @@ 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; } @@ -51,14 +57,74 @@ void msn_oim_destroy(MsnOim *oim) { + MsnOimSendReq *request; + 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); } +MsnOimSendReq * +msn_oim_new_send_req(char *from_member, + char*friendname,char* to_member, + gint send_seq, + 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; +} + +void +msn_oim_free_send_req(MsnOimSendReq *req) +{ + 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*/ +char * +msn_oim_msg_to_str(MsnOim *oim,char *body) +{ + char *oim_body; + char *oim_base64,*oim_base16; + + gaim_debug_info("MaYuan","encode OIM Message...\n"); + gaim_debug_info("MaYuan","runid:{%s}\n",oim->run_id); + gaim_debug_info("MaYuan","body:{%s}\n",body); + oim_base64 = gaim_base64_encode((const guchar *)body, strlen(body)); + gaim_debug_info("MaYuan","encode body:{%s}\n",oim_base64); + oim_base16 = gaim_base16_encode((const guchar *)body, strlen(body)); + gaim_debug_info("MaYuan","encode body:{%s}\n",oim_base16); + + oim_body = g_strdup_printf(MSN_OIM_MSG_TEMPLATE, + oim->run_id,oim->send_seq,oim_base64); + gaim_debug_info("MaYuan","start base64 encode\n",body); + + return oim_body; +} + /*oim SOAP server login error*/ static void msn_oim_send_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) @@ -88,14 +154,54 @@ g_return_if_fail(session != NULL); } +void +msn_oim_send_process(MsnOim *oim,char *body,int len) +{ + xmlnode *responseNode,*bodyNode,*faultNode; + xmlnode *detailNode,*challengeNode; + char *challenge; + + 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; + + 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*/ + detailNode = xmlnode_get_child(faultNode, "detail"); + challengeNode = xmlnode_get_child(detailNode,"LockKeyChallenge"); +// gaim_debug_info("MaYuan","challenge:{%s}\n",challenge); + + gaim_debug_info("MaYuan","prepare to dup the challenge\n"); + g_free(oim->challenge); + oim->challenge = xmlnode_get_data(challengeNode); + gaim_debug_info("MaYuan","lockkey:{%s}\n",oim->challenge); + + xmlnode_free(responseNode); + + /*repost the send*/ + gaim_debug_info("MaYuan","prepare to repost the send...\n"); + msn_oim_send_msg(oim); +} + static void msn_oim_send_read_cb(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond) { MsnSoapConn * soapconn = data; - MsnOim * msnoim; + MsnOim * oim; gaim_debug_info("MaYuan","read buffer:{%s}\n",soapconn->body); + msn_oim_send_process(oim,soapconn->body,soapconn->body_len); } static void @@ -107,43 +213,68 @@ // msn_soap_read_cb(data,source,cond); } -/*pose single message to oim server*/ +void +msn_oim_prep_send_msg_info(MsnOim *oim, + char *membername,char*friendname,char *tomember, + char * msg) +{ + MsnOimSendReq *request; + + 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_single_msg(MsnOim *oim,char * msg) +msn_oim_send_msg(MsnOim *oim) { MsnSoapReq *soap_request; - const char *soap_body,*t,*p; - + MsnOimSendReq *oim_request; + char *soap_body,*mspauth; + char *msg_body; + char buf[33]; + + oim_request = g_queue_pop_head(oim->send_queue); + if(oim_request == NULL){ + return; + } gaim_debug_info("MaYuan","send single OIM Message\n"); - oim->sendconn->login_path = g_strdup(MSN_OIM_SEND_URL); - oim->sendconn->soap_action = g_strdup(MSN_OIM_SEND_SOAP_ACTION); - t = oim->session->passport_info.t; - p = oim->session->passport_info.p; -#if 0 - oimsoapbody = g_strdup_printf(MSN_OIM_SEND_TEMPLATE, - membername, - friendname, - tomember, + mspauth = g_strdup_printf("t=%s&p=%s", + oim->session->passport_info.t, + oim->session->passport_info.p + ); + gaim_debug_info("MaYuan","get mspauth...\n"); + if(oim->challenge != NULL){ + msn_handle_chl(oim->challenge, buf); + }else{ + g_queue_push_head(oim->send_queue,oim_request); + buf[0]='\0'; + } + gaim_debug_info("MaYuan","get challenge...\n"); + + msg_body = msn_oim_msg_to_str(oim, oim_request->oim_msg); + gaim_debug_info("MaYuan","get body...\n"); + soap_body = g_strdup_printf(MSN_OIM_SEND_TEMPLATE, + oim_request->from_member, + oim_request->friendname, + oim_request->to_member, mspauth, - prod_id, - lock_key, - msg_num, - msg + MSNP13_WLM_PRODUCT_ID, + buf, + oim_request->send_seq, + msg_body ); -#endif + gaim_debug_info("MaYuan","post body...\n"); 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); - msn_soap_post(oim->sendconn,soap_request,msn_oim_send_connect_init); -} + g_free(mspauth); + g_free(msg_body); + g_free(soap_body); -void msn_oim_send_msg(MsnOim *oim,char *msg) -{ - if(msn_soap_connected(oim->sendconn) == -1){ - } - + msn_soap_post(oim->sendconn,soap_request,msn_oim_send_connect_init); } /**************************************** @@ -304,6 +435,7 @@ 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); @@ -342,14 +474,14 @@ void msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg) { - xmlnode *mdNode,*mNode,*INode,*nNode,*ENode,*rtNode; + 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)){ - INode = xmlnode_get_child(mNode,"E"); - passport = xmlnode_get_data(INode); + ENode = xmlnode_get_child(mNode,"E"); + passport = xmlnode_get_data(ENode); INode = xmlnode_get_child(mNode,"I"); msgid = xmlnode_get_data(INode); rtNode = xmlnode_get_child(mNode,"RT"); @@ -360,6 +492,10 @@ 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); } } diff -r 509383ef25f8 -r 1b6c631012d9 src/protocols/msn/oim.h --- a/src/protocols/msn/oim.h Thu Aug 24 16:38:30 2006 +0000 +++ b/src/protocols/msn/oim.h Sat Aug 26 03:25:00 2006 +0000 @@ -67,18 +67,26 @@ "" /*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"\ - "%s"\ + "%d"\ ""\ ""\ ""\ @@ -87,6 +95,17 @@ ""\ "" +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 @@ -97,7 +116,10 @@ GList * oim_list; MsnSoapConn *sendconn; - gint LockKeyChallenge; + char *challenge; + char *run_id; + gint send_seq; + GQueue *send_queue; }; /**************************************************** @@ -109,6 +131,13 @@ void msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg); +/*Send OIM Message*/ +void msn_oim_prep_send_msg_info(MsnOim *oim, + char *membername,char*friendname,char *tomember, + char * msg); + +void msn_oim_send_msg(MsnOim *oim); + /*get the OIM message*/ void msn_oim_get_msg(MsnOim *oim); diff -r 509383ef25f8 -r 1b6c631012d9 src/protocols/msn/slpcall.c --- a/src/protocols/msn/slpcall.c Thu Aug 24 16:38:30 2006 +0000 +++ b/src/protocols/msn/slpcall.c Sat Aug 26 03:25:00 2006 +0000 @@ -33,7 +33,7 @@ * Util **************************************************************************/ -static char * +char * rand_guid() { return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X", diff -r 509383ef25f8 -r 1b6c631012d9 src/protocols/msn/soap.c --- a/src/protocols/msn/soap.c Thu Aug 24 16:38:30 2006 +0000 +++ b/src/protocols/msn/soap.c Sat Aug 26 03:25:00 2006 +0000 @@ -324,7 +324,8 @@ msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, error); } - else if (strstr(soapconn->read_buf, "HTTP/1.1 200 OK")) + 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"); diff -r 509383ef25f8 -r 1b6c631012d9 src/protocols/msn/user.c --- a/src/protocols/msn/user.c Thu Aug 24 16:38:30 2006 +0000 +++ b/src/protocols/msn/user.c Sat Aug 26 03:25:00 2006 +0000 @@ -298,6 +298,16 @@ b->proto_data = user; } +/*check if the msn user is online*/ +gboolean +msn_user_is_online(GaimAccount *account, const char *name) +{ + GaimBuddy *buddy; + + buddy =gaim_find_buddy(account,name); + return GAIM_BUDDY_IS_ONLINE(buddy); +} + void msn_user_remove_group_id(MsnUser *user, const char * id) {