# HG changeset patch # User Ka-Hing Cheung # Date 1176610347 0 # Node ID 60bc0649874626261e590abc3ee04c79cb419085 # Parent 6167ee79ecd0b881581628b544bce66d90e3580d Committing khc's msnp14 changes from Trac Ticket #148. --rlaager committer: Richard Laager diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/Makefile.am --- a/libpurple/protocols/msn/Makefile.am Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/Makefile.am Sun Apr 15 04:12:27 2007 +0000 @@ -8,6 +8,8 @@ cmdproc.h \ command.c \ command.h \ + contact.c\ + contact.h\ dialog.c \ dialog.h \ directconn.c \ @@ -30,6 +32,8 @@ notification.h \ object.c \ object.h \ + oim.c\ + oim.h\ page.c \ page.h \ servconn.c \ @@ -46,6 +50,8 @@ slpmsg.h \ slpsession.c \ slpsession.h \ + soap.c\ + soap.h\ state.c \ state.h \ switchboard.c \ @@ -60,8 +66,8 @@ user.h \ userlist.c \ userlist.h \ - msn-utils.c \ - msn-utils.h + msnutils.c \ + msnutils.h AM_CFLAGS = $(st) diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/Makefile.mingw --- a/libpurple/protocols/msn/Makefile.mingw Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/Makefile.mingw Sun Apr 15 04:12:27 2007 +0000 @@ -39,6 +39,7 @@ ## C_SRC = cmdproc.c \ command.c \ + contact.c\ dialog.c \ directconn.c \ error.c \ @@ -50,6 +51,7 @@ nexus.c \ notification.c \ object.c \ + oim.c\ page.c \ servconn.c \ session.c \ @@ -58,6 +60,7 @@ slplink.c \ slpmsg.c \ slpsession.c \ + soap.c\ state.c \ switchboard.c \ sync.c \ @@ -65,7 +68,7 @@ transaction.c \ user.c \ userlist.c \ - msn-utils.c + msnutils.c OBJECTS = $(C_SRC:%.c=%.o) diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/cmdproc.c --- a/libpurple/protocols/msn/cmdproc.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/cmdproc.c Sun Apr 15 04:12:27 2007 +0000 @@ -89,8 +89,7 @@ tmp = (incoming) ? 'S' : 'C'; - if ((show[len - 1] == '\n') && (show[len - 2] == '\r')) - { + if ((show[len - 1] == '\n') && (show[len - 2] == '\r')){ show[len - 2] = '\0'; } @@ -127,14 +126,14 @@ trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds, trans->command); - if (trans->payload != NULL) - { + if (trans->payload != NULL){ data = g_realloc(data, len + trans->payload_len); memcpy(data + len, trans->payload, trans->payload_len); len += trans->payload_len; } msn_servconn_write(servconn, data, len); +// purple_debug_info("<<","%s\n",data); g_free(data); } @@ -228,8 +227,7 @@ { MsnMsgTypeCb cb; - if (msn_message_get_content_type(msg) == NULL) - { + if (msn_message_get_content_type(msg) == NULL){ purple_debug_misc("msn", "failed to find message content\n"); return; } @@ -237,8 +235,7 @@ cb = g_hash_table_lookup(cmdproc->cbs_table->msgs, msn_message_get_content_type(msg)); - if (cb == NULL) - { + if (cb == NULL){ purple_debug_warning("msn", "Unhandled content-type '%s'\n", msn_message_get_content_type(msg)); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/command.c --- a/libpurple/protocols/msn/command.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/command.c Sun Apr 15 04:12:27 2007 +0000 @@ -24,6 +24,10 @@ #include "msn.h" #include "command.h" +/*local Function prototype*/ +int msn_get_payload_position(char *str); +int msn_set_payload_len(MsnCommand *cmd); + static gboolean is_num(char *str) { @@ -36,6 +40,72 @@ return TRUE; } +/* + * check the command is the command with payload content + * if it is return TRUE + * else return FALSE + */ +static gboolean +msn_check_payload_cmd(char *str) +{ + if( (!strcmp(str,"ADL")) || + (!strcmp(str,"GCF")) || + (!strcmp(str,"SG")) || + (!strcmp(str,"MSG")) || + (!strcmp(str,"RML")) || + (!strcmp(str,"UBX")) || + (!strcmp(str,"UBN")) || + (!strcmp(str,"UUM")) || + (!strcmp(str,"UBM")) || + (!strcmp(str,"FQY")) || + (!strcmp(str,"UUN")) || + (!strcmp(str,"UUX"))){ + return TRUE; + } + + return FALSE; +} + +/*get the payload positon*/ +int msn_get_payload_position(char *str) +{ + /*because MSG has "MSG hotmail hotmail [payload length]"*/ + if(!(strcmp(str,"MSG"))|| (!strcmp(str,"UBX")) ){ + return 2; + } + /*Yahoo User Message UBM + * Format UBM email@yahoo.com 32 1 [payload length]*/ + if(!(strcmp(str,"UBM"))|| (!strcmp(str,"UUM")) ){ + return 3; + } + + return 1; +} + +/* + * set command Payload length + */ +int +msn_set_payload_len(MsnCommand *cmd) +{ + char * param; + + if(msn_check_payload_cmd(cmd->command)){ + param = cmd->params[msn_get_payload_position(cmd->command)]; +#if 0 + if(!(strcmp(cmd->command,"MSG"))){ + param = cmd->params[2]; + }else{ + param = cmd->params[1]; + } +#endif + cmd->payload_len = is_num(param) ? atoi(param) : 0; + }else{ + cmd->payload_len = 0; + } + return 0; +} + MsnCommand * msn_command_from_string(const char *string) { @@ -68,9 +138,13 @@ param = cmd->params[0]; cmd->trId = is_num(param) ? atoi(param) : 0; + }else{ + cmd->trId = 0; } - else - cmd->trId = 0; + + /*add payload Length checking*/ + msn_set_payload_len(cmd); + purple_debug_info("MaYuan","get payload len:%d\n",cmd->payload_len); msn_command_ref(cmd); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/dialog.c --- a/libpurple/protocols/msn/dialog.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/dialog.c Sun Apr 15 04:12:27 2007 +0000 @@ -34,40 +34,20 @@ } MsnAddRemData; -/* Remove the buddy referenced by the MsnAddRemData before the serverside list is changed. - * If the buddy will be added, he'll be added back; if he will be removed, he won't be. */ -static void -msn_complete_sync_issue(MsnAddRemData *data) -{ - PurpleBuddy *buddy; - PurpleGroup *group = NULL; - - if (data->group != NULL) - group = purple_find_group(data->group); - - if (group != NULL) - buddy = purple_find_buddy_in_group(purple_connection_get_account(data->gc), data->who, group); - else - buddy = purple_find_buddy(purple_connection_get_account(data->gc), data->who); - - if (buddy != NULL) - purple_blist_remove_buddy(buddy); -} - static void msn_add_cb(MsnAddRemData *data) { - MsnSession *session; - MsnUserList *userlist; - - msn_complete_sync_issue(data); + if (g_list_find(purple_connections_get_all(), data->gc) != NULL) + { + MsnSession *session = data->gc->proto_data; + MsnUserList *userlist = session->userlist; - session = data->gc->proto_data; - userlist = session->userlist; + msn_userlist_add_buddy(userlist, data->who, MSN_LIST_FL, data->group); + } - 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); } @@ -75,17 +55,17 @@ static void msn_rem_cb(MsnAddRemData *data) { - MsnSession *session; - MsnUserList *userlist; - - msn_complete_sync_issue(data); + if (g_list_find(purple_connections_get_all(), data->gc) != NULL) + { + MsnSession *session = data->gc->proto_data; + MsnUserList *userlist = session->userlist; - session = data->gc->proto_data; - userlist = session->userlist; + msn_userlist_rem_buddy(userlist, data->who, MSN_LIST_FL, data->group); + } - 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); } @@ -98,6 +78,8 @@ PurpleAccount *account; MsnAddRemData *data; char *msg, *reason; + PurpleBuddy *buddy; + PurpleGroup *group = NULL; account = session->account; gc = purple_account_get_connection(account); @@ -111,16 +93,13 @@ 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?"), @@ -132,6 +111,18 @@ _("Yes"), G_CALLBACK(msn_add_cb), _("No"), G_CALLBACK(msn_rem_cb)); + if (group_name != NULL) + group = purple_find_group(group_name); + + if (group != NULL){ + buddy = purple_find_buddy_in_group(account, passport, group); + }else{ + buddy = purple_find_buddy(account, passport); + } + + if (buddy != NULL) + purple_blist_remove_buddy(buddy); + g_free(reason); g_free(msg); } diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/directconn.c --- a/libpurple/protocols/msn/directconn.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/directconn.c Sun Apr 15 04:12:27 2007 +0000 @@ -76,7 +76,6 @@ * Connection Functions **************************************************************************/ -#if 0 static int create_listener(int port) { @@ -160,7 +159,6 @@ return fd; } -#endif static size_t msn_directconn_write(MsnDirectConn *directconn, @@ -288,6 +286,11 @@ /* ERROR */ purple_debug_error("msn", "error reading\n"); + if (directconn->inpa) + purple_input_remove(directconn->inpa); + + close(directconn->fd); + msn_directconn_destroy(directconn); return; @@ -302,6 +305,11 @@ /* ERROR */ purple_debug_error("msn", "error reading\n"); + if (directconn->inpa) + purple_input_remove(directconn->inpa); + + close(directconn->fd); + msn_directconn_destroy(directconn); return; @@ -348,17 +356,22 @@ /* ERROR */ purple_debug_error("msn", "error reading\n"); + if (directconn->inpa) + purple_input_remove(directconn->inpa); + + close(directconn->fd); + msn_directconn_destroy(directconn); } } static void -connect_cb(gpointer data, gint source, const gchar *error_message) +connect_cb(gpointer data, gint source, PurpleInputCondition cond) { MsnDirectConn* directconn; int fd; - purple_debug_misc("msn", "directconn: connect_cb: %d\n", source); + purple_debug_misc("msn", "directconn: connect_cb: %d, %d.\n", source, cond); directconn = data; directconn->connect_data = NULL; @@ -434,7 +447,6 @@ return FALSE; } -#if 0 void msn_directconn_listen(MsnDirectConn *directconn) { @@ -454,7 +466,6 @@ directconn->port = port; directconn->c = 0; } -#endif MsnDirectConn* msn_directconn_new(MsnSlpLink *slplink) @@ -476,6 +487,7 @@ void msn_directconn_destroy(MsnDirectConn *directconn) { + if (directconn->connect_data != NULL) purple_proxy_connect_cancel(directconn->connect_data); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/directconn.h --- a/libpurple/protocols/msn/directconn.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/directconn.h Sun Apr 15 04:12:27 2007 +0000 @@ -52,9 +52,7 @@ MsnDirectConn *msn_directconn_new(MsnSlpLink *slplink); gboolean msn_directconn_connect(MsnDirectConn *directconn, const char *host, int port); -#if 0 void msn_directconn_listen(MsnDirectConn *directconn); -#endif void msn_directconn_send_msg(MsnDirectConn *directconn, MsnMessage *msg); void msn_directconn_parse_nonce(MsnDirectConn *directconn, const char *nonce); void msn_directconn_destroy(MsnDirectConn *directconn); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/group.c --- a/libpurple/protocols/msn/group.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/group.c Sun Apr 15 04:12:27 2007 +0000 @@ -25,18 +25,18 @@ #include "group.h" MsnGroup * -msn_group_new(MsnUserList *userlist, int id, const char *name) +msn_group_new(MsnUserList *userlist, const char *id, const char *name) { MsnGroup *group; - g_return_val_if_fail(id >= 0, NULL); + g_return_val_if_fail(id != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); group = g_new0(MsnGroup, 1); msn_userlist_add_group(userlist, group); - group->id = id; + group->id = g_strdup(id); group->name = g_strdup(name); return group; @@ -47,17 +47,18 @@ { g_return_if_fail(group != NULL); + g_free(group->id); g_free(group->name); g_free(group); } void -msn_group_set_id(MsnGroup *group, int id) +msn_group_set_id(MsnGroup *group, const char *id) { g_return_if_fail(group != NULL); - g_return_if_fail(id >= 0); + g_return_if_fail(id != NULL); - group->id = id; + group->id = g_strdup(id); } void @@ -72,10 +73,10 @@ group->name = g_strdup(name); } -int +char* msn_group_get_id(const MsnGroup *group) { - g_return_val_if_fail(group != NULL, -1); + g_return_val_if_fail(group != NULL, NULL); return group->id; } @@ -87,3 +88,4 @@ return group->name; } + diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/group.h --- a/libpurple/protocols/msn/group.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/group.h Sun Apr 15 04:12:27 2007 +0000 @@ -30,8 +30,21 @@ #include "session.h" #include "user.h" +#include "soap.h" +#include "userlist.h" -#include "userlist.h" +#define MSN_ADD_GROUPS "test111C8529CE2-6EAD-434d-881F-341E17DB3FF8falseMSN.IM.Display1" + +#define MSN_ADD_GROUP_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseGroupSavefalse00000000-0000-0000-0000-000000000000false%s" + +#define MSN_GROUP_IDS "9e57e654-59f0-44d1-aedc-0a7500b7e51f" +#define MSN_DELETE_GROUP_TEMPLATE "09607671-1C32-421F-A6A6-CBFAA51AB5F4falseTimerfalse00000000-0000-0000-0000-000000000000%s" + +#define MSN_INDIVIDUALS_GROUP_ID "1983" +#define MSN_INDIVIDUALS_GROUP_NAME "Other Contacts" + +#define MSN_NON_IM_GROUP_ID "email" +#define MSN_NON_IM_GROUP_NAME "Non-IM Contacts" /** * A group. @@ -39,8 +52,9 @@ struct _MsnGroup { MsnSession *session; /**< The MSN session. */ + MsnSoapConn *soapconn; - int id; /**< The group ID. */ + char *id; /**< The group ID. */ char *name; /**< The name of the group. */ }; @@ -58,7 +72,7 @@ * * @return A new group structure. */ -MsnGroup *msn_group_new(MsnUserList *userlist, int id, const char *name); +MsnGroup *msn_group_new(MsnUserList *userlist, const char *id, const char *name); /** * Destroys a group structure. @@ -73,7 +87,7 @@ * @param group The group. * @param id The ID. */ -void msn_group_set_id(MsnGroup *group, int id); +void msn_group_set_id(MsnGroup *group, const char *id); /** * Sets the name for a group. @@ -90,7 +104,7 @@ * * @return The ID. */ -int msn_group_get_id(const MsnGroup *group); +char* msn_group_get_id(const MsnGroup *group); /** * Returns the name for a group. diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/history.c --- a/libpurple/protocols/msn/history.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/history.c Sun Apr 15 04:12:27 2007 +0000 @@ -84,3 +84,4 @@ msn_transaction_destroy(trans); } } + diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/msg.c --- a/libpurple/protocols/msn/msg.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/msg.c Sun Apr 15 04:12:27 2007 +0000 @@ -23,6 +23,7 @@ */ #include "msn.h" #include "msg.h" +#define MSN_DEBUG_MSG MsnMessage * msn_message_new(MsnMsgType type) @@ -104,8 +105,7 @@ purple_debug_info("msn", "message unref (%p)[%d]\n", msg, msg->ref_count); #endif - if (msg->ref_count == 0) - { + if (msg->ref_count == 0){ msn_message_destroy(msg); return NULL; @@ -126,7 +126,7 @@ msn_message_set_charset(msg, "UTF-8"); msn_message_set_flag(msg, 'A'); msn_message_set_attr(msg, "X-MMS-IM-Format", - "FN=MS%20Sans%20Serif; EF=; CO=0; PF=0"); + "FN=MS%20Sans%20Serif; EF=; CO=0; CS=86;PF=0"); message_cr = purple_str_add_cr(message); msn_message_set_bin_data(msg, message_cr, strlen(message_cr)); @@ -206,7 +206,8 @@ void msn_message_parse_payload(MsnMessage *msg, - const char *payload, size_t payload_len) + const char *payload, size_t payload_len, + const char *line_dem,const char *body_dem) { char *tmp_base, *tmp; const char *content_type; @@ -214,12 +215,12 @@ char **elems, **cur, **tokens; g_return_if_fail(payload != NULL); - +// purple_debug_info("MaYuan","payload:{%s}\n",payload); tmp_base = tmp = g_malloc0(payload_len + 1); memcpy(tmp_base, payload, payload_len); /* Parse the attributes. */ - end = strstr(tmp, "\r\n\r\n"); + end = strstr(tmp, body_dem); /* TODO? some clients use \r delimiters instead of \r\n, the official client * doesn't send such messages, but does handle receiving them. We'll just * avoid crashing for now */ @@ -229,10 +230,9 @@ } *end = '\0'; - elems = g_strsplit(tmp, "\r\n", 0); + elems = g_strsplit(tmp, line_dem, 0); - for (cur = elems; *cur != NULL; cur++) - { + for (cur = elems; *cur != NULL; cur++){ const char *key, *value; tokens = g_strsplit(*cur, ": ", 2); @@ -240,20 +240,17 @@ key = tokens[0]; value = tokens[1]; - if (!strcmp(key, "MIME-Version")) - { + /*if not MIME content ,then return*/ + if (!strcmp(key, "MIME-Version")){ g_strfreev(tokens); continue; } - if (!strcmp(key, "Content-Type")) - { + if (!strcmp(key, "Content-Type")){ char *charset, *c; - if ((c = strchr(value, ';')) != NULL) - { - if ((charset = strchr(c, '=')) != NULL) - { + if ((c = strchr(value, ';')) != NULL){ + if ((charset = strchr(c, '=')) != NULL) { charset++; msn_message_set_charset(msg, charset); } @@ -262,9 +259,7 @@ } msn_message_set_content_type(msg, value); - } - else - { + }else{ msn_message_set_attr(msg, key, value); } @@ -274,14 +269,13 @@ g_strfreev(elems); /* Proceed to the end of the "\r\n\r\n" */ - tmp = end + 4; + tmp = end + strlen(body_dem); /* Now we *should* be at the body. */ content_type = msn_message_get_content_type(msg); if (content_type != NULL && - !strcmp(content_type, "application/x-msnmsgrp2p")) - { + !strcmp(content_type, "application/x-msnmsgrp2p")){ MsnSlpHeader header; MsnSlpFooter footer; int body_len; @@ -323,9 +317,7 @@ tmp += sizeof(footer); msg->msnslp_footer.value = GUINT32_FROM_BE(footer.value); } - } - else - { + }else{ if (payload_len - (tmp - tmp_base) > 0) { msg->body_len = payload_len - (tmp - tmp_base); msg->body = g_malloc0(msg->body_len + 1); @@ -476,15 +468,14 @@ } else { - if (body != NULL) - { + if (body != NULL){ memcpy(n, body, body_len); n += body_len; + *n = '\0'; } } - if (ret_size != NULL) - { + if (ret_size != NULL){ *ret_size = n - base; if (*ret_size > 1664) @@ -523,14 +514,11 @@ if (msg->body != NULL) g_free(msg->body); - if (data != NULL && len > 0) - { + if (data != NULL && len > 0){ msg->body = g_malloc0(len + 1); memcpy(msg->body, data, len); msg->body_len = len; - } - else - { + }else{ msg->body = NULL; msg->body_len = 0; } @@ -785,3 +773,4 @@ g_string_free(str, TRUE); } + diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/msg.h --- a/libpurple/protocols/msn/msg.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/msg.h Sun Apr 15 04:12:27 2007 +0000 @@ -34,6 +34,12 @@ typedef void (*MsnMsgCb)(MsnMessage *, void *data); +#define MSG_BODY_DEM "\r\n\r\n" +#define MSG_LINE_DEM "\r\n" + +#define MSG_OIM_BODY_DEM "\n\n" +#define MSG_OIM_LINE_DEM "\n" + /* typedef enum { @@ -180,7 +186,8 @@ * @param payload_len The length of the payload. */ void msn_message_parse_payload(MsnMessage *msg, const char *payload, - size_t payload_len); + size_t payload_len, + const char *line_dem,const char *body_dem); /** * Destroys a message. diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Sun Apr 15 04:12:27 2007 +0000 @@ -37,7 +37,7 @@ #include "cmds.h" #include "core.h" #include "prpl.h" -#include "msn-utils.h" +#include "msnutils.h" #include "version.h" #include "switchboard.h" @@ -114,7 +114,7 @@ return PURPLE_CMD_RET_OK; } -static void +void msn_act_id(PurpleConnection *gc, const char *entry) { MsnCmdProc *cmdproc; @@ -122,6 +122,9 @@ PurpleAccount *account; const char *alias; + char *soapbody; + MsnSoapReq *soap_request; + session = gc->proto_data; cmdproc = session->notification->cmdproc; account = purple_connection_get_account(gc); @@ -138,9 +141,27 @@ return; } - msn_cmdproc_send(cmdproc, "REA", "%s %s", - purple_account_get_username(account), - alias); + if (*alias == '\0') { + alias = purple_url_encode(purple_account_get_username(account)); + } + + msn_cmdproc_send(cmdproc, "PRP", "MFN %s", alias); + + soapbody = g_strdup_printf(MSN_CONTACT_UPDATE_TEMPLATE, alias); + /*build SOAP and POST it*/ + soap_request = msn_soap_request_new(MSN_CONTACT_SERVER, + MSN_ADDRESS_BOOK_POST_URL, + MSN_CONTACT_UPDATE_SOAP_ACTION, + soapbody, + NULL, + NULL); + + session->contact->soapconn->read_cb = NULL; + msn_soap_post(session->contact->soapconn, + soap_request, + msn_contact_connect_init); + + g_free(soapbody); } static void @@ -429,14 +450,12 @@ session = gc->proto_data; xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); - if (xfer) - { - slplink = msn_session_get_slplink(session, who); + + 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; } @@ -480,18 +499,56 @@ return "msn"; } +/* + * Set the User status text + * Add the PSM String Using "Name - PSM String" format + */ static char * msn_status_text(PurpleBuddy *buddy) { PurplePresence *presence; PurpleStatus *status; + const char *msg, *name, *cmedia; + char *psm_str, *tmp2, *text; presence = purple_buddy_get_presence(buddy); status = purple_presence_get_active_status(presence); - if (!purple_presence_is_available(presence) && !purple_presence_is_idle(presence)) - { - return g_strdup(purple_status_get_name(status)); + msg = purple_status_get_attr_string(status, "message"); + cmedia=purple_status_get_attr_string(status, "currentmedia"); + + if (!purple_presence_is_available(presence) && !purple_presence_is_idle(presence)){ + name = purple_status_get_name(status); + }else{ + name = NULL; + } + + if (cmedia != NULL) { + if(name) { + tmp2 = g_strdup_printf("%s - %s", name, cmedia); + text = g_markup_escape_text(tmp2, -1); + } else { + text = g_markup_escape_text(cmedia, -1); + } + return text; + } else if (msg != NULL) { + tmp2 = purple_markup_strip_html(msg); + if (name){ + psm_str = g_strdup_printf("%s - %s", name, tmp2); + g_free(tmp2); + }else{ + psm_str = tmp2; + } + text = g_markup_escape_text(psm_str, -1); + g_free(psm_str); + return text; + } else { + if (!purple_presence_is_available(presence) && !purple_presence_is_idle(presence)){ + psm_str = g_strdup(purple_status_get_name(status)); + text = g_markup_escape_text(psm_str, -1); + g_free(psm_str); + return text; + } } return NULL; @@ -509,8 +566,24 @@ if (purple_presence_is_online(presence)) { + const char *psm, *currentmedia; + char *tmp; + + psm = purple_status_get_attr_string(status, "message"); + currentmedia = purple_status_get_attr_string(status, "currentmedia"); + purple_notify_user_info_add_pair(user_info, _("Status"), (purple_presence_is_idle(presence) ? _("Idle") : purple_status_get_name(status))); + if (psm) { + tmp = g_markup_escape_text(psm, -1); + purple_notify_user_info_add_pair(user_info, _("PSM"), tmp); + g_free(tmp); + } + if (currentmedia) { + tmp = g_markup_escape_text(currentmedia, -1); + purple_notify_user_info_add_pair(user_info, _("Current media"), tmp); + g_free(tmp); + } } if (full && user) @@ -535,29 +608,48 @@ { PurpleStatusType *status; GList *types = NULL; - +#if 0 status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, NULL, NULL, FALSE, TRUE, FALSE); +#endif + status = purple_status_type_new_with_attrs( + PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, status); - status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - NULL, NULL, FALSE, TRUE, FALSE); + status = purple_status_type_new_with_attrs( + PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, status); - status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - "brb", _("Be Right Back"), FALSE, TRUE, FALSE); + status = purple_status_type_new_with_attrs( + PURPLE_STATUS_AWAY, "brb", _("Be Right Back"), TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, status); - status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, - "busy", _("Busy"), FALSE, TRUE, FALSE); + status = purple_status_type_new_with_attrs( + PURPLE_STATUS_AWAY, "busy", _("Busy"), TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, - "phone", _("On the Phone"), FALSE, TRUE, FALSE); + status = purple_status_type_new_with_attrs( + PURPLE_STATUS_AWAY, "phone", _("On the Phone"), TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - "lunch", _("Out to Lunch"), FALSE, TRUE, FALSE); + status = purple_status_type_new_with_attrs( + PURPLE_STATUS_AWAY, "lunch", _("Out to Lunch"), TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, @@ -696,7 +788,8 @@ return; } - http_method = purple_account_get_bool(account, "http_method", FALSE); + if (purple_account_get_bool(account, "http_method", FALSE)) + http_method = TRUE; host = purple_account_get_string(account, "server", MSN_SERVER); port = purple_account_get_int(account, "port", MSN_PORT); @@ -743,6 +836,7 @@ char *msgformat; char *msgtext; + purple_debug_info("MaYuan","send IM {%s} to %s\n",message,who); account = purple_connection_get_account(gc); if (buddy) { @@ -756,58 +850,86 @@ } msn_import_html(message, &msgformat, &msgtext); + if(msn_user_is_online(account, who)|| + msn_user_is_yahoo(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; - } + purple_debug_info("MaYuan","prepare to send online Message\n"); + if (g_ascii_strcasecmp(who, purple_account_get_username(account))) + { + MsnSession *session; + MsnSwitchBoard *swboard; - msg = msn_message_new_plain(msgtext); - msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); - - g_free(msgformat); - g_free(msgtext); + session = gc->proto_data; + if(msn_user_is_yahoo(account,who)){ + /*we send the online and offline Message to Yahoo User via UBM*/ + purple_debug_info("MaYuan","send to Yahoo User\n"); + uum_send_msg(session,msg); + }else{ + purple_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); - if (g_ascii_strcasecmp(who, purple_account_get_username(account))) - { - MsnSession *session; - MsnSwitchBoard *swboard; + 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,only to MSN Passport User*/ + MsnSession *session; + MsnOim *oim; + char *friendname; + + purple_debug_info("MaYuan","prepare to send offline Message\n"); session = gc->proto_data; - swboard = msn_session_get_swboard(session, who, MSN_SB_FLAG_IM); + /* XXX/khc: hack */ + if (!session->oim) + session->oim = msn_oim_new(session); - msn_switchboard_send_msg(swboard, msg, TRUE); + oim = session->oim; + friendname = msn_encode_mime(account->username); + msn_oim_prep_send_msg_info(oim, purple_account_get_username(account), + friendname, who, message); + 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; } @@ -867,8 +989,7 @@ gc = purple_account_get_connection(account); - if (gc != NULL) - { + if (gc != NULL){ session = gc->proto_data; msn_change_status(session); } @@ -945,6 +1066,7 @@ userlist = session->userlist; who = msn_normalize(gc->account, buddy->name); + purple_debug_info("MaYuan","add user:{%s} to group:{%s}\n",who,group->name); if (!session->logged_in) { #if 0 @@ -1092,12 +1214,9 @@ cmdproc = session->notification->cmdproc; if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL || - account->perm_deny == PURPLE_PRIVACY_DENY_USERS) - { + account->perm_deny == PURPLE_PRIVACY_DENY_USERS){ msn_cmdproc_send(cmdproc, "BLP", "%s", "AL"); - } - else - { + }else{ msn_cmdproc_send(cmdproc, "BLP", "%s", "BL"); } } @@ -1237,22 +1356,22 @@ { MsnSession *session; MsnCmdProc *cmdproc; - int old_gid; + const char *old_gid; const char *enc_new_group_name; session = gc->proto_data; cmdproc = session->notification->cmdproc; enc_new_group_name = purple_url_encode(group->name); + purple_debug_info("MaYuan","rename group:old{%s},new{%s}",old_name,enc_new_group_name); old_gid = msn_userlist_find_group_id(session->userlist, old_name); - if (old_gid >= 0) - { + if (old_gid != NULL){ + /*find a Group*/ msn_cmdproc_send(cmdproc, "REG", "%d %s 0", old_gid, enc_new_group_name); - } - else - { + }else{ + /*not found*/ msn_cmdproc_send(cmdproc, "ADG", "%s 0", enc_new_group_name); } } @@ -1308,14 +1427,19 @@ { MsnSession *session; MsnCmdProc *cmdproc; - int group_id; + const char *group_id; session = gc->proto_data; cmdproc = session->notification->cmdproc; - if ((group_id = msn_userlist_find_group_id(session->userlist, group->name)) >= 0) - { - msn_cmdproc_send(cmdproc, "RMG", "%d", group_id); + /*we can't delete the default group*/ + if(!strcmp(group->name,MSN_INDIVIDUALS_GROUP_NAME)|| + !strcmp(group->name,MSN_NON_IM_GROUP_NAME)){ + return ; + } + group_id = msn_userlist_find_group_id(session->userlist, group->name); + if (group_id != NULL){ + msn_del_group(session,group_id); } } @@ -1330,19 +1454,16 @@ b = purple_find_buddy(purple_connection_get_account(info_data->gc), info_data->name); - if (b) - { + if (b){ char *tmp; - if (b->alias && b->alias[0]) - { + if (b->alias && b->alias[0]){ char *aliastext = g_markup_escape_text(b->alias, -1); purple_notify_user_info_add_pair(user_info, _("Alias"), aliastext); g_free(aliastext); } - if (b->server_alias) - { + if (b->server_alias){ char *nicktext = g_markup_escape_text(b->server_alias, -1); tmp = g_strdup_printf("%s
", nicktext); purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); @@ -1366,12 +1487,10 @@ { char *p, *q; - if ((p = strstr(url_text, " contactparams:photopreauthurl=\"")) != NULL) - { - p += strlen(" contactparams:photopreauthurl=\""); + if ((p = strstr(url_text, PHOTO_URL)) != NULL){ + p += strlen(PHOTO_URL); } - - if (p && (strncmp(p, "http://", 8) == 0) && ((q = strchr(p, '"')) != NULL)) + if (p && (strncmp(p, "http://",strlen("http://")) == 0) && ((q = strchr(p, '"')) != NULL)) return g_strndup(p, q - p); return NULL; @@ -1420,7 +1539,7 @@ MsnGetInfoStepTwoData *info2_data = NULL; #endif - purple_debug_info("msn", "In msn_got_info\n"); + purple_debug_info("msn", "In msn_got_info,url_text:{%s}\n",url_text); /* Make sure the connection is still valid */ if (g_list_find(purple_connections_get_all(), info_data->gc) == NULL) @@ -1801,6 +1920,7 @@ #if PHOTO_SUPPORT /* Find the URL to the photo; must be before the marshalling [Bug 994207] */ photo_url_text = msn_get_photo_url(url_text); + purple_debug_info("Ma Yuan","photo url:{%s}\n",photo_url_text); /* Marshall the existing state */ info2_data = g_malloc0(sizeof(MsnGetInfoStepTwoData)); @@ -2025,7 +2145,7 @@ msn_add_deny, /* add_deny */ msn_rem_permit, /* rem_permit */ msn_rem_deny, /* rem_deny */ - msn_set_permit_deny, /* set_permit_deny */ + msn_set_permit_deny, /* set_permit_deny */ NULL, /* join_chat */ NULL, /* reject chat invite */ NULL, /* get_chat_name */ @@ -2075,10 +2195,10 @@ "MSN", /**< name */ VERSION, /**< version */ /** summary */ - N_("MSN Protocol Plugin"), + N_("Windows Live Messenger Protocol Plugin"), /** description */ - N_("MSN Protocol Plugin"), - "Christian Hammond ", /**< author */ + N_("Windows Live Messenger Protocol Plugin"), + "MaYuan ", /**< author */ PURPLE_WEBSITE, /**< homepage */ msn_load, /**< load */ @@ -2097,11 +2217,11 @@ PurpleAccountOption *option; option = purple_account_option_string_new(_("Server"), "server", - MSN_SERVER); + WLM_SERVER); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_int_new(_("Port"), "port", 1863); + option = purple_account_option_int_new(_("Port"), "port", WLM_PORT); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/msn.h --- a/libpurple/protocols/msn/msn.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/msn.h Sun Apr 15 04:12:27 2007 +0000 @@ -62,12 +62,24 @@ #define USEROPT_MSNPORT 4 #define MSN_PORT 1863 +/* Windows Live Messenger Server*/ +#define WLM_SERVER "muser.messenger.hotmail.com" +#define WLM_PORT 1863 +#define WLM_PROT_VER 13 +/*This MSNP14 Support chat with Yahoo Messenger*/ +#define WLM_YAHOO_PROT_VER 14 + +#define WLM_MAX_PROTOCOL 14 +#define WLM_MIN_PROTOCOL 13 + #define MSN_TYPING_RECV_TIMEOUT 6 #define MSN_TYPING_SEND_TIMEOUT 4 #define HOTMAIL_URL "http://www.hotmail.com/cgi-bin/folders" #define PASSPORT_URL "http://lc1.law13.hotmail.passport.com/cgi-bin/dologin?login=" -#define PROFILE_URL "http://spaces.msn.com/profile.aspx?mem=" +/*#define PROFILE_URL "http://spaces.msn.com/profile.aspx?mem="*/ +#define PROFILE_URL "http://spaces.live.com/profile.aspx?mem=" +#define PHOTO_URL " contactparams:photopreauthurl=\"" #define USEROPT_HOTMAIL 0 @@ -88,6 +100,7 @@ MSN_LIST_RL_OP = 0x08 } MsnListOp; +#define MSN_LIST_OP_MASK 0x07 typedef enum { @@ -128,4 +141,7 @@ (MSN_CLIENT_ID_RESERVED_2 << 8) | \ (MSN_CLIENT_ID_CAPABILITIES)) +void msn_act_id(PurpleConnection *gc, const char *entry); + + #endif /* _MSN_H_ */ diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/nexus.c --- a/libpurple/protocols/msn/nexus.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/nexus.c Sun Apr 15 04:12:27 2007 +0000 @@ -22,9 +22,15 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "msn.h" +#include "soap.h" #include "nexus.h" #include "notification.h" +#undef NEXUS_LOGIN_TWN + +/*Local Function Prototype*/ +static void nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc,PurpleInputCondition cond); + /************************************************************************** * Main **************************************************************************/ @@ -36,6 +42,9 @@ nexus = g_new0(MsnNexus, 1); nexus->session = session; + /*we must use SSL connection to do Windows Live ID authentication*/ + nexus->soapconn = msn_soap_new(session,nexus,1); + nexus->challenge_data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); @@ -45,24 +54,14 @@ void msn_nexus_destroy(MsnNexus *nexus) { - if (nexus->gsc) - purple_ssl_close(nexus->gsc); - - g_free(nexus->login_host); - - g_free(nexus->login_path); - if (nexus->challenge_data != NULL) g_hash_table_destroy(nexus->challenge_data); - if (nexus->input_handler > 0) - purple_input_remove(nexus->input_handler); - g_free(nexus->write_buf); - g_free(nexus->read_buf); - + msn_soap_destroy(nexus->soapconn); g_free(nexus); } +#if 0 /* khc */ /************************************************************************** * Util **************************************************************************/ @@ -121,278 +120,236 @@ nexus->written_cb(nexus, source, 0); } +#endif /************************************************************************** * Login **************************************************************************/ - static void -login_connect_cb(gpointer data, PurpleSslConnection *gsc, - PurpleInputCondition cond); +nexus_login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) +{ + MsnSoapConn * soapconn = data; + MsnSession *session; + + session = soapconn->session; + g_return_if_fail(session != NULL); + + soapconn->gsc = NULL; + msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication:Unable to connect")); + /* the above line will result in nexus being destroyed, so we don't want + * to destroy it here, or we'd crash */ +} + +/*process the SOAP reply, get the Authentication Info*/ static void -login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) +nexus_login_read_cb(gpointer data, gint source, PurpleInputCondition cond) { + MsnSoapConn * soapconn = data; MsnNexus *nexus; MsnSession *session; - nexus = data; - g_return_if_fail(nexus != NULL); + char *base, *c; + char *msn_twn_t,*msn_twn_p; + char *login_params; + char **elems, **cur, **tokens; + char * cert_str; - nexus->gsc = NULL; - + nexus = soapconn->parent; + g_return_if_fail(nexus != NULL); session = nexus->session; g_return_if_fail(session != NULL); - msn_session_set_error(session, MSN_ERROR_AUTH, _("Unable to connect")); - /* the above line will result in nexus being destroyed, so we don't want - * to destroy it here, or we'd crash */ + purple_debug_misc("msn", "TWN Server Reply: {%s}\n", soapconn->read_buf); + + /*reply OK, we should process the SOAP body*/ + purple_debug_info("MaYuan","Windows Live ID Reply OK!\n"); + + //TODO: we should parse it using XML +#ifdef NEXUS_LOGIN_TWN + base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_START_TOKEN); + base += strlen(TWN_START_TOKEN); + c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_END_TOKEN); +#else + base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_LIVE_START_TOKEN); + base += strlen(TWN_LIVE_START_TOKEN); + c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_LIVE_END_TOKEN); +#endif + login_params = g_strndup(base, c - base); + + // purple_debug_info("msn", "TWN Cert: {%s}\n", login_params); + + /* Parse the challenge data. */ + elems = g_strsplit(login_params, "&", 0); + + for (cur = elems; *cur != NULL; cur++){ + tokens = g_strsplit(*cur, "=", 2); + g_hash_table_insert(nexus->challenge_data, tokens[0], tokens[1]); + /* Don't free each of the tokens, only the array. */ + g_free(tokens); + } + + g_strfreev(elems); + + msn_twn_t = (char *)g_hash_table_lookup(nexus->challenge_data, "t"); + msn_twn_p = (char *)g_hash_table_lookup(nexus->challenge_data, "p"); + + /*setup the t and p parameter for session*/ + if (session->passport_info.t != NULL){ + g_free(session->passport_info.t); + } + session->passport_info.t = g_strdup(msn_twn_t); + + if (session->passport_info.p != NULL) + g_free(session->passport_info.p); + session->passport_info.p = g_strdup(msn_twn_p); + + cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p); + msn_got_login_params(session, cert_str); + + purple_debug_info("MaYuan","close nexus connection! \n"); + g_free(cert_str); + g_free(login_params); + msn_nexus_destroy(nexus); + session->nexus = NULL; + + return; } static void nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond) { - MsnNexus *nexus = data; - MsnSession *session; - int len; + MsnSoapConn * soapconn = data; - session = nexus->session; - g_return_if_fail(session != NULL); - - if (nexus->input_handler == 0) - //TODO: Use purple_ssl_input_add()? - nexus->input_handler = purple_input_add(nexus->gsc->fd, - PURPLE_INPUT_READ, nexus_login_written_cb, nexus); + soapconn->read_cb = nexus_login_read_cb; +// msn_soap_read_cb(data,source,cond); +} - len = msn_ssl_read(nexus); - - if (len < 0 && errno == EAGAIN) - return; - else if (len < 0) { - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - /* TODO: error handling */ - return; - } - - if (g_strstr_len(nexus->read_buf, nexus->read_len, - "\r\n\r\n") == NULL) - return; - - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - - purple_ssl_close(nexus->gsc); - nexus->gsc = NULL; - - purple_debug_misc("msn", "ssl buffer: {%s}", nexus->read_buf); - - if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL) - { - /* Redirect. */ - char *location, *c; - - location = strstr(nexus->read_buf, "Location: "); - if (location == NULL) - { - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - - 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(nexus->login_path); - nexus->login_path = g_strdup(c); - - *c = '\0'; - } - - g_free(nexus->login_host); - nexus->login_host = g_strdup(location); - - nexus->gsc = purple_ssl_connect(session->account, - nexus->login_host, PURPLE_SSL_DEFAULT_PORT, - login_connect_cb, login_error_cb, nexus); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 401 Unauthorized") != NULL) - { - const char *error; - - if ((error = strstr(nexus->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 = purple_url_decode(temp); - g_free(temp); - } - } - - msn_session_set_error(session, MSN_ERROR_AUTH, error); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 503 Service Unavailable")) - { - msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, NULL); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK")) - { - char *base, *c; - char *login_params; - -#if 0 - /* All your base are belong to us. */ - base = buffer; - - /* For great cookie! */ - while ((base = strstr(base, "Set-Cookie: ")) != NULL) - { - base += strlen("Set-Cookie: "); - - c = strchr(base, ';'); - - session->login_cookies = - g_list_append(session->login_cookies, - g_strndup(base, c - base)); - } +/*when connect, do the SOAP Style windows Live ID authentication */ +void +nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc, + PurpleInputCondition cond) +{ + MsnSoapConn *soapconn; + MsnNexus * nexus; + MsnSession *session; + char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf; + char *fs0,*fs; + char *username, *password; + char *request_str, *head, *tail; +#ifdef NEXUS_LOGIN_TWN + char *challenge_str; +#else + char *rst1_str,*rst2_str,*rst3_str; #endif - base = strstr(nexus->read_buf, "Authentication-Info: "); + purple_debug_info("MaYuan","starting Windows Live ID authentication\n"); + + soapconn = data; + g_return_if_fail(soapconn != NULL); + + nexus = soapconn->parent; + g_return_if_fail(nexus != NULL); - g_return_if_fail(base != NULL); + session = soapconn->session; + g_return_if_fail(session != NULL); + + msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); + + /*prepare the Windows Live ID authentication token*/ + username = g_strdup(purple_account_get_username(session->account)); + password = g_strdup(purple_connection_get_password(session->account->gc)); - base = strstr(base, "from-PP='"); - base += strlen("from-PP='"); - c = strchr(base, '\''); + lc = (char *)g_hash_table_lookup(nexus->challenge_data, "lc"); + id = (char *)g_hash_table_lookup(nexus->challenge_data, "id"); + tw = (char *)g_hash_table_lookup(nexus->challenge_data, "tw"); + fs0= (char *)g_hash_table_lookup(nexus->challenge_data, "fs"); + ru = (char *)g_hash_table_lookup(nexus->challenge_data, "ru"); + ct = (char *)g_hash_table_lookup(nexus->challenge_data, "ct"); + kpp= (char *)g_hash_table_lookup(nexus->challenge_data, "kpp"); + kv = (char *)g_hash_table_lookup(nexus->challenge_data, "kv"); + ver= (char *)g_hash_table_lookup(nexus->challenge_data, "ver"); + rn = (char *)g_hash_table_lookup(nexus->challenge_data, "rn"); + tpf= (char *)g_hash_table_lookup(nexus->challenge_data, "tpf"); - login_params = g_strndup(base, c - base); - - msn_got_login_params(session, login_params); - - g_free(login_params); - + /* + * add some fail-safe code to avoid windows Purple Crash bug #1540454 + * If any of these string is NULL, will return Authentication Fail! + * for when windows g_strdup_printf() implementation get NULL point,It crashed! + */ + if(!(lc && id && tw && ru && ct && kpp && kv && ver && tpf)){ + purple_debug_error("MaYuan","WLM Authenticate Key Error!\n"); + msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication Failed")); + g_free(username); + g_free(password); + purple_ssl_close(gsc); msn_nexus_destroy(nexus); session->nexus = NULL; return; } - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - -} - -/* this guards against missing hash entries */ -static char * -nexus_challenge_data_lookup(GHashTable *challenge_data, const char *key) -{ - char *entry; - - return (entry = (char *)g_hash_table_lookup(challenge_data, key)) ? - entry : "(null)"; -} + /* + * in old MSN NS server's "USR TWN S" return,didn't include fs string + * so we use a default "1" for fs. + */ + if(fs0){ + fs = g_strdup(fs0); + }else{ + fs = g_strdup("1"); + } -void -login_connect_cb(gpointer data, PurpleSslConnection *gsc, - PurpleInputCondition cond) -{ - MsnNexus *nexus; - MsnSession *session; - char *username, *password; - char *request_str, *head, *tail; - char *buffer = NULL; - guint32 ctint; - - nexus = data; - g_return_if_fail(nexus != NULL); - - session = nexus->session; - g_return_if_fail(session != NULL); - - msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); +#ifdef NEXUS_LOGIN_TWN + challenge_str = g_strdup_printf( + "lc=%s&id=%s&tw=%s&fs=%s&ru=%s&ct=%s&kpp=%s&kv=%s&ver=%s&rn=%s&tpf=%s\r\n", + lc,id,tw,fs,ru,ct,kpp,kv,ver,rn,tpf + ); - username = - g_strdup(purple_url_encode(purple_account_get_username(session->account))); - - password = - g_strdup(purple_url_encode(purple_connection_get_password(session->account->gc))); - - ctint = strtoul((char *)g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200; - - head = g_strdup_printf( - "GET %s HTTP/1.1\r\n" - "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s", - nexus->login_path, - (char *)g_hash_table_lookup(nexus->challenge_data, "ru"), - username); + /*build the SOAP windows Live ID XML body */ + tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE,username,password,challenge_str ); + g_free(challenge_str); +#else + rst1_str = g_strdup_printf( + "id=%s&tw=%s&fs=%s&kpp=%s&kv=%s&ver=%s&rn=%s", + id,tw,fs,kpp,kv,ver,rn + ); + rst2_str = g_strdup_printf( + "fs=%s&id=%s&kv=%s&rn=%s&tw=%s&ver=%s", + fs,id,kv,rn,tw,ver + ); + rst3_str = g_strdup_printf("id=%s",id); + tail = g_strdup_printf(TWN_LIVE_ENVELOP_TEMPLATE,username,password,rst1_str,rst2_str,rst3_str); + g_free(rst1_str); + g_free(rst2_str); + g_free(rst3_str); +#endif + g_free(fs); - tail = g_strdup_printf( - "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%" G_GUINT32_FORMAT ",kpp=%s,kv=%s,ver=%s,tpf=%s\r\n" - "User-Agent: MSMSGS\r\n" - "Host: %s\r\n" - "Connection: Keep-Alive\r\n" - "Cache-Control: no-cache\r\n", - nexus_challenge_data_lookup(nexus->challenge_data, "lc"), - nexus_challenge_data_lookup(nexus->challenge_data, "id"), - nexus_challenge_data_lookup(nexus->challenge_data, "tw"), - nexus_challenge_data_lookup(nexus->challenge_data, "fs"), - nexus_challenge_data_lookup(nexus->challenge_data, "ru"), - ctint, - nexus_challenge_data_lookup(nexus->challenge_data, "kpp"), - nexus_challenge_data_lookup(nexus->challenge_data, "kv"), - nexus_challenge_data_lookup(nexus->challenge_data, "ver"), - nexus_challenge_data_lookup(nexus->challenge_data, "tpf"), - nexus->login_host); + soapconn->login_path = g_strdup(TWN_POST_URL); + head = g_strdup_printf( + "POST %s HTTP/1.1\r\n" + "Accept: text/*\r\n" + "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n" + "Host: %s\r\n" + "Content-Length: %d\r\n" + "Connection: Keep-Alive\r\n" + "Cache-Control: no-cache\r\n\r\n", + soapconn->login_path,soapconn->login_host,(int)strlen(tail)); - buffer = g_strdup_printf("%s,pwd=XXXXXXXX,%s\r\n", head, tail); - request_str = g_strdup_printf("%s,pwd=%s,%s\r\n", head, password, tail); + request_str = g_strdup_printf("%s%s", head,tail); + purple_debug_misc("msn", "TWN Sending: {%s}\n", request_str); - purple_debug_misc("msn", "Sending: {%s}\n", buffer); - - g_free(buffer); g_free(head); g_free(tail); g_free(username); g_free(password); - nexus->write_buf = request_str; - nexus->written_len = 0; - - nexus->read_len = 0; - - nexus->written_cb = nexus_login_written_cb; - - nexus->input_handler = purple_input_add(gsc->fd, PURPLE_INPUT_WRITE, - nexus_write_cb, nexus); - - nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); + /*prepare to send the SOAP request*/ + msn_soap_write(soapconn,request_str,nexus_login_written_cb); return; - - } +#if 0 /* khc */ static void nexus_connect_written_cb(gpointer data, gint source, PurpleInputCondition cond) { @@ -468,10 +425,13 @@ } +#endif + /************************************************************************** * Connect **************************************************************************/ +#if 0 /* khc */ static void nexus_connect_cb(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond) @@ -500,10 +460,14 @@ nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); } +#endif + void msn_nexus_connect(MsnNexus *nexus) { - nexus->gsc = purple_ssl_connect(nexus->session->account, - "nexus.passport.com", PURPLE_SSL_DEFAULT_PORT, - nexus_connect_cb, login_error_cb, nexus); + /* Authenticate via Windows Live ID. */ + purple_debug_info("MaYuan","msn_nexus_connect...\n"); + msn_soap_init(nexus->soapconn,MSN_TWN_SERVER,1,nexus_login_connect_cb,nexus_login_error_cb); + msn_soap_connect(nexus->soapconn); } + diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/nexus.h --- a/libpurple/protocols/msn/nexus.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/nexus.h Sun Apr 15 04:12:27 2007 +0000 @@ -24,25 +24,124 @@ #ifndef _MSN_NEXUS_H_ #define _MSN_NEXUS_H_ +#include "soap.h" + +/*#define MSN_TWN_SERVER "loginnet.passport.com"*/ +#define MSN_TWN_SERVER "login.live.com" + +#define TWN_START_TOKEN "" +#define TWN_END_TOKEN "" + +#define TWN_POST_URL "/RST.srf" +#define TWN_ENVELOP_TEMPLATE ""\ + ""\ + "
"\ + ""\ + "{3:B}"\ + "4"\ + "1"\ + ""\ + "AQAAAAIAAABsYwQAAAAzMDg0"\ + ""\ + ""\ + ""\ + "%s"\ + "%s"\ + ""\ + ""\ + "
"\ + ""\ + ""\ + ""\ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue"\ + ""\ + ""\ + "http://Passport.NET/tb"\ + ""\ + ""\ + ""\ + ""\ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue"\ + ""\ + ""\ + "messenger.msn.com"\ + ""\ + ""\ + ""\ + ""\ + ""\ + ""\ + ""\ + "
" + +#define TWN_LIVE_START_TOKEN "" +#define TWN_LIVE_END_TOKEN "" +#define TWN_LIVE_ENVELOP_TEMPLATE ""\ +""\ + "
"\ + ""\ + "{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}"\ + "4"\ + "1"\ + ""\ + "AQAAAAIAAABsYwQAAAAyMDUy"\ + ""\ + ""\ + ""\ + "%s"\ + "%s"\ + ""\ + ""\ + "
"\ + ""\ + ""\ + ""\ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue"\ + ""\ + ""\ + "http://Passport.NET/tb"\ + ""\ + ""\ + ""\ + ""\ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue"\ + ""\ + ""\ + "messenger.msn.com"\ + ""\ + ""\ + ""\ + ""\ + ""\ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue"\ + ""\ + ""\ + "contacts.msn.com"\ + ""\ + ""\ + ""\ + " "\ + ""\ + "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue"\ + ""\ + ""\ + "voice.messenger.msn.com"\ + ""\ + " "\ + ""\ + ""\ + ""\ + ""\ +"
" + typedef struct _MsnNexus MsnNexus; struct _MsnNexus { MsnSession *session; - - char *login_host; - char *login_path; + MsnSoapConn *soapconn; + char * challenge_data_str; GHashTable *challenge_data; - PurpleSslConnection *gsc; - - guint input_handler; - - char *write_buf; - gsize written_len; - PurpleInputFunction written_cb; - - char *read_buf; - gsize read_len; }; void msn_nexus_connect(MsnNexus *nexus); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/notification.c --- a/libpurple/protocols/msn/notification.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/notification.c Sun Apr 15 04:12:27 2007 +0000 @@ -25,7 +25,7 @@ #include "notification.h" #include "state.h" #include "error.h" -#include "msn-utils.h" +#include "msnutils.h" #include "page.h" #include "userlist.h" @@ -34,6 +34,14 @@ static MsnTable *cbs_table; +/**************************************************************************** + * Local Function Prototype + ****************************************************************************/ + +static void msn_notification_fqy_yahoo(MsnSession *session, const char *passport); +static void msn_notification_post_adl(MsnCmdProc *cmdproc, char *payload, int payload_len); +static void msn_add_contact_xml(xmlnode *mlNode, const char *passport, int list_op, int type); + /************************************************************************** * Main **************************************************************************/ @@ -102,19 +110,22 @@ account = session->account; /* Allocate an array for CVR0, NULL, and all the versions */ - a = c = g_new0(char *, session->protocol_ver - 8 + 3); +// a = c = g_new0(char *, session->protocol_ver - WLM_MIN_PROTOCOL + 3); + a = c = g_new0(char *, WLM_MAX_PROTOCOL - WLM_MIN_PROTOCOL + 3); - for (i = session->protocol_ver; i >= 8; i--) +// for (i = session->protocol_ver; i >= WLM_MIN_PROTOCOL; i--) + for (i = WLM_MAX_PROTOCOL; i >= WLM_MIN_PROTOCOL; i--) *c++ = g_strdup_printf("MSNP%d", i); *c++ = g_strdup("CVR0"); vers = g_strjoinv(" ", a); - if (session->login_step == MSN_LOGIN_STEP_START) + if (session->login_step == MSN_LOGIN_STEP_START){ msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE); - else + }else{ msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE2); + } msn_cmdproc_send(cmdproc, "VER", "%s", vers); @@ -153,7 +164,7 @@ **************************************************************************/ static void -group_error_helper(MsnSession *session, const char *msg, int group_id, int error) +group_error_helper(MsnSession *session, const char *msg, const char *group_id, int error) { PurpleAccount *account; PurpleConnection *gc; @@ -163,24 +174,16 @@ account = session->account; gc = purple_account_get_connection(account); - if (error == 224) - { - if (group_id == 0) - { + if (error == 224){ + if (group_id == 0){ return; - } - else - { + }else{ const char *group_name; - group_name = - msn_userlist_find_group_name(session->userlist, - group_id); + group_name = msn_userlist_find_group_name(session->userlist,group_id); reason = g_strdup_printf(_("%s is not a valid group."), group_name); } - } - else - { + }else{ reason = g_strdup(_("Unknown error.")); } @@ -214,7 +217,6 @@ PurpleAccount *account; account = cmdproc->session->account; - msn_cmdproc_send(cmdproc, "USR", "TWN I %s", purple_account_get_username(account)); } @@ -230,34 +232,37 @@ account = session->account; gc = purple_account_get_connection(account); - if (!g_ascii_strcasecmp(cmd->params[1], "OK")) - { - /* OK */ + if (!g_ascii_strcasecmp(cmd->params[1], "OK")){ + /* authenticate OK */ + /* friendly name part no longer true in msnp11 */ +#if 0 const char *friendly = purple_url_decode(cmd->params[3]); purple_connection_set_display_name(gc, friendly); - +#endif msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN); - msn_cmdproc_send(cmdproc, "SYN", "%s", "0"); - } - else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")) - { +// msn_cmdproc_send(cmdproc, "SYN", "%s", "0"); + //TODO we should use SOAP contact to fetch contact list + } else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")){ /* Passport authentication */ char **elems, **cur, **tokens; session->nexus = msn_nexus_new(session); /* Parse the challenge data. */ - + session->nexus->challenge_data_str = g_strdup(cmd->params[3]); elems = g_strsplit(cmd->params[3], ",", 0); - for (cur = elems; *cur != NULL; cur++) - { - tokens = g_strsplit(*cur, "=", 2); + for (cur = elems; *cur != NULL; cur++){ + tokens = g_strsplit(*cur, "=", 2); + if(tokens[0]&&tokens[1]){ + purple_debug_info("MaYuan","challenge %p,key:%s,value:%s\n", + session->nexus->challenge_data,tokens[0],tokens[1]); g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]); - /* Don't free each of the tokens, only the array. */ - g_free(tokens); + } + /* Don't free each of the tokens, only the array. */ + g_free(tokens); } g_strfreev(elems); @@ -306,24 +311,29 @@ g_snprintf(proto_str, sizeof(proto_str), "MSNP%d", session->protocol_ver); - for (i = 1; i < cmd->param_count; i++) - { - if (!strcmp(cmd->params[i], proto_str)) - { + 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) { protocol_supported = TRUE; break; } } - if (!protocol_supported) - { + if (!protocol_supported){ msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL, NULL); return; } + /* + * Windows Live Messenger 8.0 + * Notice :CVR String discriminate! + * reference of http://www.microsoft.com/globaldev/reference/oslocversion.mspx + * to see the Local ID + */ msn_cmdproc_send(cmdproc, "CVR", - "0x0409 winnt 5.1 i386 MSNMSGR 6.0.0602 MSMSGS %s", +// "0x0409 winnt 5.1 i386 MSG80BETA 8.0.0689 msmsgs %s", + "0x0804 winnt 5.1 i386 MSNMSGR 8.0.0792 msmsgs %s", purple_account_get_username(account)); } @@ -366,7 +376,7 @@ msg = msn_message_new_from_cmd(cmdproc->session, cmd); - msn_message_parse_payload(msg, payload, len); + msn_message_parse_payload(msg, payload, len,MSG_LINE_DEM,MSG_BODY_DEM); #ifdef MSN_DEBUG_NS msn_message_show_readable(msg, "Notification", TRUE); #endif @@ -379,54 +389,171 @@ static void msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { + purple_debug_info("MaYuan","Processing MSG... \n"); + if(cmd->payload_len == 0){ + return; + } /* 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); cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len); } } +/*send Message to Yahoo Messenger*/ +void +uum_send_msg(MsnSession *session,MsnMessage *msg) +{ + MsnCmdProc *cmdproc; + MsnTransaction *trans; + char *payload; + gsize payload_len; + int type; + + cmdproc = session->notification->cmdproc; + g_return_if_fail(msg != NULL); + payload = msn_message_gen_payload(msg, &payload_len); + purple_debug_info("MaYuan","send UUM,payload{%s},strlen:%d,len:%d\n", + payload,strlen(payload),payload_len); + type = msg->type; + trans = msn_transaction_new(cmdproc, "UUM","%s 32 %d %d",msg->remote_user,type,payload_len); + msn_transaction_set_payload(trans, payload, strlen(payload)); + msn_cmdproc_send_trans(cmdproc, trans); +} + +static void +ubm_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, + size_t len) +{ + MsnMessage *msg; + PurpleConnection *gc; + const char *passport; + const char *content_type; + + purple_debug_info("MaYuan","Process UBM payload:%s\n",payload); + msg = msn_message_new_from_cmd(cmdproc->session, cmd); + + msn_message_parse_payload(msg, payload, len,MSG_LINE_DEM,MSG_BODY_DEM); +#ifdef MSN_DEBUG_NS + msn_message_show_readable(msg, "Notification", TRUE); +#endif + + gc = cmdproc->session->account->gc; + passport = msg->remote_user; + + content_type = msn_message_get_content_type(msg); + purple_debug_info("MaYuan","type:%d\n",content_type); + if(!strcmp(content_type,"text/plain")){ + const char *value; + const char *body; + char *body_str; + char *body_enc; + char *body_final = NULL; + size_t body_len; + + body = msn_message_get_bin_data(msg, &body_len); + body_str = g_strndup(body, body_len); + body_enc = g_markup_escape_text(body_str, -1); + g_free(body_str); + + if ((value = msn_message_get_attr(msg, "X-MMS-IM-Format")) != NULL) { + char *pre, *post; + + msn_parse_format(value, &pre, &post); + body_final = g_strdup_printf("%s%s%s", pre ? pre : "", + body_enc ? body_enc : "", post ? post : ""); + g_free(pre); + g_free(post); + g_free(body_enc); + } + serv_got_im(gc, passport, body_final, 0, time(NULL)); + } + if(!strcmp(content_type,"text/x-msmsgscontrol")){ + if(msn_message_get_attr(msg, "TypingUser") != NULL){ + serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT, + PURPLE_TYPING); + } + } + if(!strcmp(content_type,"text/x-msnmsgr-datacast")){ + char *username, *str; + PurpleAccount *account; + PurpleBuddy *buddy; + const char *user; + + account = cmdproc->session->account; + user = msg->remote_user; + + if ((buddy = purple_find_buddy(account, user)) != NULL){ + username = g_markup_escape_text(purple_buddy_get_alias(buddy), -1); + }else{ + username = g_markup_escape_text(user, -1); + } + + str = g_strdup_printf(_("%s just sent you a Nudge!"), username); + g_free(username); + msn_session_report_user(cmdproc->session,user,str,PURPLE_MESSAGE_SYSTEM); + g_free(str); + } + msn_message_destroy(msg); +} + +/*Yahoo msg process*/ +static void +ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_info("MaYuan","Processing UBM... \n"); + if(cmd->payload_len == 0){ + return; + } + /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued + * command and we are processing it */ + if (cmd->payload == NULL){ + cmdproc->last_cmd->payload_cb = ubm_cmd_post; + cmdproc->servconn->payload_len = atoi(cmd->params[2]); + }else{ + g_return_if_fail(cmd->payload_cb != NULL); + + purple_debug_info("MaYuan","UBM payload:{%s}\n",cmd->payload); + ubm_cmd_post(cmdproc, cmd, cmd->payload, cmd->payload_len); + } +} + /************************************************************************** * Challenges + * we use MD5 to caculate the Chanllenges **************************************************************************/ - static void chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnTransaction *trans; char buf[33]; - const char *challenge_resp; - PurpleCipher *cipher; - PurpleCipherContext *context; - guchar digest[16]; - int i; +#if 0 cipher = purple_ciphers_find_cipher("md5"); context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (const guchar *)cmd->params[1], strlen(cmd->params[1])); - - challenge_resp = "VT6PX?UQTM4WM%YR"; + challenge_resp = MSNP13_WLM_PRODUCT_KEY; purple_cipher_context_append(context, (const guchar *)challenge_resp, strlen(challenge_resp)); purple_cipher_context_digest(context, sizeof(digest), digest, NULL); purple_cipher_context_destroy(context); - for (i = 0; i < 16; i++) + for (i = 0; i < 16; i++){ g_snprintf(buf + (i*2), 3, "%02x", digest[i]); - - trans = msn_transaction_new(cmdproc, "QRY", "%s 32", "PROD0038W!61ZTF9"); + } +#else + msn_handle_chl(cmd->params[1], buf); +#endif +// purple_debug_info("MaYuan","<params[1],buf); + trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP13_WLM_PRODUCT_ID); msn_transaction_set_payload(trans, buf, 32); @@ -436,43 +563,182 @@ /************************************************************************** * Buddy Lists **************************************************************************/ +/* add contact to xmlnode */ +static void +msn_add_contact_xml(xmlnode *mlNode,const char *passport,int list_op,int type) +{ + xmlnode *d_node,*c_node; + char **tokens; + char *email,*domain; + char *list_op_str,*type_str; + + purple_debug_info("MaYuan","passport:%s\n",passport); + tokens = g_strsplit(passport, "@", 2); + email = tokens[0]; + domain = tokens[1]; + + /*find a domain Node*/ + for(d_node = xmlnode_get_child(mlNode,"d"); d_node; d_node = xmlnode_get_next_twin(d_node)){ + const char * attr = NULL; + purple_debug_info("MaYuan","d_node:%s\n",d_node->name); + attr = xmlnode_get_attrib(d_node,"n"); + if(attr == NULL){ + continue; + } + if(!strcmp(attr,domain)){ + break; + } + } + if(d_node == NULL){ + /*domain not found, create a new domain Node*/ + purple_debug_info("MaYuan","get No d_node\n"); + d_node = xmlnode_new("d"); + xmlnode_set_attrib(d_node,"n",domain); + xmlnode_insert_child(mlNode,d_node); + } + + /*create contact node*/ + c_node = xmlnode_new("c"); + xmlnode_set_attrib(c_node,"n",email); + + list_op_str = g_strdup_printf("%d",list_op); + purple_debug_info("MaYuan","list_op:%d\n",list_op_str); + xmlnode_set_attrib(c_node,"l",list_op_str); + g_free(list_op_str); +#if 0 + type_str = g_strdup_printf("%d",type); + xmlnode_set_attrib(c_node,"t",type_str); +#else + if(g_strrstr(domain,"yahoo") != NULL){ + type_str = g_strdup_printf("32"); + }else{ + /*passport*/ + type_str = g_strdup_printf("1"); + } + /*mobile*/ + //type_str = g_strdup_printf("4"); + xmlnode_set_attrib(c_node,"t",type_str); + g_free(type_str); +#endif + xmlnode_insert_child(d_node, c_node); + + g_free(tokens); +} static void -add_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +msn_notification_post_adl(MsnCmdProc *cmdproc, char *payload, int payload_len) { - MsnSession *session; + MsnTransaction *trans; + + purple_debug_info("MaYuan","Send ADL{%s}\n",payload); + trans = msn_transaction_new(cmdproc, "ADL","%d",strlen(payload)); + msn_transaction_set_payload(trans, payload, strlen(payload)); + msn_cmdproc_send_trans(cmdproc, trans); +} + +/*dump contact info to NS*/ +void +msn_notification_dump_contact(MsnSession *session) +{ + MsnUserList *userlist; MsnUser *user; - const char *list; - const char *passport; - const char *friendly; - MsnListId list_id; - int group_id; + GList *l; + xmlnode *adl_node; + char *payload; + int payload_len; + const char *display_name; + + userlist = session->userlist; + adl_node = xmlnode_new("ml"); + adl_node->child = NULL; + xmlnode_set_attrib(adl_node, "l", "1"); + + /*get the userlist*/ + for (l = userlist->users; l != NULL; l = l->next){ + user = l->data; + msn_add_contact_xml(adl_node,user->passport,user->list_op&MSN_LIST_OP_MASK,user->type); + } + + payload = xmlnode_to_str(adl_node,&payload_len); + xmlnode_free(adl_node); - list = cmd->params[1]; - passport = cmd->params[3]; - friendly = purple_url_decode(cmd->params[4]); + msn_notification_post_adl(session->notification->cmdproc,payload,payload_len); + + display_name = purple_connection_get_display_name(session->account->gc); + if (display_name && strcmp(display_name, + purple_account_get_username(session->account))) { + msn_act_id(session->account->gc, display_name); + } + +} - session = cmdproc->session; +/*Post FQY to NS,Inform add a Yahoo User*/ +static void +msn_notification_fqy_yahoo(MsnSession *session, const char *passport) +{ + MsnTransaction *trans; + MsnCmdProc *cmdproc; + char* email,*domain,*payload; + char **tokens; - user = msn_userlist_find_user(session->userlist, passport); + cmdproc = session->notification->cmdproc; - if (user == NULL) - { - user = msn_user_new(session->userlist, passport, friendly); - msn_userlist_add_user(session->userlist, user); - } - else - msn_user_set_friendly_name(user, friendly); + tokens = g_strsplit(passport, "@", 2); + email = tokens[0]; + domain = tokens[1]; + + payload = g_strdup_printf("",domain,email); + trans = msn_transaction_new(cmdproc, "FQY","%d",strlen(payload)); + msn_transaction_set_payload(trans, payload, strlen(payload)); + msn_cmdproc_send_trans(cmdproc, trans); + + g_free(payload); + g_free(tokens); +} + +static void +blp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_info("MaYuan","Process BLP\n"); +} + +static void +adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_info("MaYuan","Process ADL\n"); +} - list_id = msn_get_list_id(list); +static void +fqy_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, + size_t len) +{ + purple_debug_info("MaYuan","FQY payload{%s}\n",payload); + msn_notification_post_adl(cmdproc,payload,len); +} + +static void +fqy_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_info("MaYuan","Process FQY\n"); + cmdproc->last_cmd->payload_cb = fqy_cmd_post; +} - if (cmd->param_count >= 6) - group_id = atoi(cmd->params[5]); - else - group_id = -1; +static void +rml_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ +#if 0 + MsnTransaction *trans; + char * payload; +#endif - msn_got_add_user(session, user, list_id, group_id); - msn_user_update(user); + purple_debug_info("MaYuan","Process ADL\n"); +#if 0 + trans = msn_transaction_new(cmdproc, "RML",""); + + msn_transaction_set_payload(trans, payload, strlen(payload)); + + msn_cmdproc_send_trans(cmdproc, trans); +#endif } static void @@ -567,7 +833,7 @@ group_name = purple_url_decode(cmd->params[2]); - msn_group_new(session->userlist, group_id, group_name); + msn_group_new(session->userlist, cmd->params[3], group_name); /* There is a user that must me moved to this group */ if (cmd->trans->data) @@ -614,6 +880,7 @@ PurpleConnection *gc; MsnUser *user; MsnObject *msnobj; + int wlmclient; const char *state, *passport, *friendly; session = cmdproc->session; @@ -622,7 +889,9 @@ state = cmd->params[1]; passport = cmd->params[2]; - friendly = purple_url_decode(cmd->params[3]); + /*if a contact is actually on the WLM part or the yahoo part*/ + wlmclient = atoi(cmd->params[3]); + friendly = purple_url_decode(cmd->params[4]); user = msn_userlist_find_user(session->userlist, passport); @@ -630,9 +899,8 @@ msn_user_set_friendly_name(user, friendly); - if (session->protocol_ver >= 9 && cmd->param_count == 6) - { - msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5])); + 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); } @@ -664,6 +932,7 @@ MsnUser *user; MsnObject *msnobj; int clientid; + int wlmclient; const char *state, *passport, *friendly, *old_friendly; session = cmdproc->session; @@ -672,7 +941,8 @@ state = cmd->params[0]; passport = cmd->params[1]; - friendly = purple_url_decode(cmd->params[2]); + wlmclient = atoi(cmd->params[2]); + friendly = purple_url_decode(cmd->params[3]); user = msn_userlist_find_user(session->userlist, passport); @@ -683,21 +953,16 @@ msn_user_set_friendly_name(user, friendly); } - if (session->protocol_ver >= 9) - { - if (cmd->param_count == 5) - { - msnobj = - msn_object_new_from_string(purple_url_decode(cmd->params[4])); + 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); } } - clientid = atoi(cmd->params[3]); + clientid = atoi(cmd->params[4]); user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE); msn_user_set_state(user, state); @@ -793,6 +1058,12 @@ msn_user_set_work_phone(session->user, NULL); else if (!strcmp(type, "PHM")) msn_user_set_mobile_phone(session->user, NULL); + else if (!strcmp(type, "MFM")) { + type = cmd->params[1]; + purple_connection_set_display_name( + purple_account_get_connection(session->account), + purple_url_decode(cmd->params[2])); + } } } @@ -800,11 +1071,10 @@ reg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; - int group_id; - const char *group_name; + const char *group_id, *group_name; session = cmdproc->session; - group_id = atoi(cmd->params[2]); + group_id = cmd->params[2]; group_name = purple_url_decode(cmd->params[3]); msn_userlist_rename_group_id(session->userlist, group_id, group_name); @@ -813,12 +1083,12 @@ static void reg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) { - int group_id; + const char * group_id; char **params; params = g_strsplit(trans->params, " ", 0); - group_id = atoi(params[0]); + group_id = params[0]; group_error_helper(cmdproc->session, _("Unable to rename group"), group_id, error); @@ -830,10 +1100,8 @@ { MsnSession *session; MsnUser *user; - const char *list; - const char *passport; + const char *group_id, *list, *passport; MsnListId list_id; - int group_id; session = cmdproc->session; list = cmd->params[1]; @@ -845,9 +1113,9 @@ list_id = msn_get_list_id(list); if (cmd->param_count == 5) - group_id = atoi(cmd->params[4]); + group_id = cmd->params[4]; else - group_id = -1; + group_id = NULL; msn_got_rem_user(session, user, list_id, group_id); msn_user_update(user); @@ -857,10 +1125,10 @@ rmg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; - int group_id; + const char *group_id; session = cmdproc->session; - group_id = atoi(cmd->params[2]); + group_id = cmd->params[2]; msn_userlist_remove_group_id(session->userlist, group_id); } @@ -868,7 +1136,7 @@ static void rmg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) { - int group_id; + const char *group_id; char **params; params = g_strsplit(trans->params, " ", 0); @@ -1106,12 +1374,9 @@ 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; @@ -1124,6 +1389,86 @@ g_free(host); } +static void +gcf_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, + size_t len) +{ + /*get the payload content*/ + purple_debug_info("MaYuan","GCF{%s}\n",cmd->payload); +} + +static void +gcf_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_info("MaYuan","Processing GCF... \n"); + cmdproc->last_cmd->payload_cb = gcf_cmd_post; + return; +} + +static void +sbs_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_info("MaYuan","Processing SBS... \n"); + if(cmd->payload_len == 0){ + return; + } + /*get the payload content*/ +} + +/* + * Get the UBX's PSM info + * Post it to the User status + * Thanks for Chris 's code + */ +static void +ubx_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, + size_t len) +{ + MsnSession *session; + PurpleAccount *account; + PurpleConnection *gc; + MsnUser *user; + const char *passport; + char *psm_str, *currentmedia_str; + + /*get the payload content*/ +// purple_debug_info("MaYuan","UBX {%s} payload{%s}\n",cmd->params[0], cmd->payload); + + session = cmdproc->session; + account = session->account; + gc = purple_account_get_connection(account); + + passport = cmd->params[0]; + user = msn_userlist_find_user(session->userlist, passport); + + psm_str = msn_get_psm(cmd->payload,len); + currentmedia_str = msn_parse_currentmedia( + msn_get_currentmedia(cmd->payload, len)); + + msn_user_set_statusline(user, psm_str); + msn_user_set_currentmedia(user, currentmedia_str); + msn_user_update(user); + + g_free(psm_str); + g_free(currentmedia_str); +} + +static void +ubx_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_info("MaYuan","UBX... \n"); + if(cmd->payload_len == 0){ + return; + } + cmdproc->last_cmd->payload_cb = ubx_cmd_post; +} + +static void +uux_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_info("MaYuan","UUX... \n"); +} + /************************************************************************** * Message Types **************************************************************************/ @@ -1133,50 +1478,59 @@ { MsnSession *session; const char *value; + const char *clLastChange; + purple_debug_info("MaYuan","profile_msg... \n"); session = cmdproc->session; if (strcmp(msg->remote_user, "Hotmail")) /* This isn't an official message. */ return; - if ((value = msn_message_get_attr(msg, "kv")) != NULL) - { + if ((value = msn_message_get_attr(msg, "kv")) != NULL){ if (session->passport_info.kv != NULL) g_free(session->passport_info.kv); session->passport_info.kv = g_strdup(value); } - if ((value = msn_message_get_attr(msg, "sid")) != NULL) - { + if ((value = msn_message_get_attr(msg, "sid")) != NULL){ if (session->passport_info.sid != NULL) g_free(session->passport_info.sid); 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); + purple_debug_info("MaYuan","MSPAuth:%s\n",value); 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)); + } if ((value = msn_message_get_attr(msg, "LoginTime")) != NULL) session->passport_info.sl = atol(value); + + /*starting retrieve the contact list*/ + msn_userlist_load(session); + + msn_session_set_bnode(session); + session->contact = msn_contact_new(session); + clLastChange = purple_blist_node_get_string(msn_session_get_bnode(session),"CLLastChange"); + msn_get_contact_list(session->contact, clLastChange); +// msn_contact_connect(session->contact); } static void @@ -1232,6 +1586,71 @@ g_hash_table_destroy(table); } +/*offline Message notification process*/ +static void +initial_mdata_msg(MsnCmdProc *cmdproc, MsnMessage *msg) +{ + MsnSession *session; + char **elems, **cur, **tokens; + +// purple_debug_info("MaYuan","mdata...{%s} \n",msg->body); + +// /*time debug*/ + { + const char *timestr; + time_t t; + struct tm *tm; + char datestr[]="2006-07-15T07:21:26+0700"; + GDate *date; + time(&t); + tm = gmtime(&t); + timestr = purple_utf8_strftime("%a, %d %b %Y %T %Z", tm); +// strftime(datestr,strlen(datestr),"%a",tm); + date = g_date_new(); + g_date_set_parse(date,datestr); + purple_debug_info("MaYuan","date is NULL?date valid%d\n",g_date_valid(date)); + g_date_free(date); + purple_debug_info("MaYuan","utf8 time:{%s}\n",timestr); + } + + /*new a oim session*/ + session = cmdproc->session; + session->oim = msn_oim_new(session); +// msn_oim_connect(session->oim); + + /*parse offline message data*/ + elems = g_strsplit(msg->body, "\r\n", 0); + for (cur = elems; *cur != NULL; cur++){ + const char *key, *value; + +// purple_debug_info("MaYuan","cur:{%s}\n",*cur); + tokens = g_strsplit(*cur, ": ", 2); + + key = tokens[0]; + value = tokens[1]; + + /*if not MIME content ,then return*/ + if ((key != NULL) && (!strcmp(key, "Mail-Data")) ){ +// purple_debug_info("MaYuan","data:{%s}\n",value); + msn_parse_oim_msg(session->oim,value); + g_strfreev(tokens); + break; + } + + g_strfreev(tokens); + } + + g_strfreev(elems); +/* test code for add group*/ +// msn_add_group(session,"hello"); +} + +/*offline Message Notification*/ +static void +delete_oim_msg(MsnCmdProc *cmdproc, MsnMessage *msg) +{ +} + static void email_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { @@ -1338,46 +1757,62 @@ void msn_notification_add_buddy(MsnNotification *notification, const char *list, const char *who, const char *store_name, - int group_id) + const char *group_id) { MsnCmdProc *cmdproc; + xmlnode *adl_node; + char *payload; + int payload_len; + cmdproc = notification->servconn->cmdproc; - if (group_id < 0 && !strcmp(list, "FL")) - group_id = 0; + if (strcmp(list, "FL") != 0){ + } + + adl_node = xmlnode_new("ml"); + adl_node->child = NULL; + + msn_add_contact_xml(adl_node,who,1,1); - if (group_id >= 0) - { - msn_cmdproc_send(cmdproc, "ADD", "%s %s %s %d", - list, who, store_name, group_id); - } - else - { - msn_cmdproc_send(cmdproc, "ADD", "%s %s %s", list, who, store_name); + payload = xmlnode_to_str(adl_node,&payload_len); + xmlnode_free(adl_node); + if(msn_user_is_yahoo(notification->session->account,who)){ + msn_notification_fqy_yahoo(notification->session, who); + }else{ + msn_notification_post_adl(notification->servconn->cmdproc, + payload,payload_len); } } void msn_notification_rem_buddy(MsnNotification *notification, const char *list, - const char *who, int group_id) + const char *who, const char *group_id) { MsnCmdProc *cmdproc; + MsnTransaction *trans; + xmlnode *rml_node; + char *payload; + int payload_len; + cmdproc = notification->servconn->cmdproc; - if (group_id >= 0) - { - msn_cmdproc_send(cmdproc, "REM", "%s %s %d", list, who, group_id); - } - else - { - msn_cmdproc_send(cmdproc, "REM", "%s %s", list, who); - } + rml_node = xmlnode_new("ml"); + rml_node->child = NULL; + + msn_add_contact_xml(rml_node,who,1,1); + + payload = xmlnode_to_str(rml_node,&payload_len); + xmlnode_free(rml_node); + + purple_debug_info("MaYuan","RML{%s}\n",payload); + trans = msn_transaction_new(cmdproc, "RML","%d",strlen(payload)); + msn_transaction_set_payload(trans, payload, strlen(payload)); + msn_cmdproc_send_trans(cmdproc, trans); } /************************************************************************** * Init **************************************************************************/ - void msn_notification_init(void) { @@ -1388,18 +1823,18 @@ /* Synchronous */ msn_table_add_cmd(cbs_table, "CHG", "CHG", NULL); msn_table_add_cmd(cbs_table, "CHG", "ILN", iln_cmd); - msn_table_add_cmd(cbs_table, "ADD", "ADD", add_cmd); - msn_table_add_cmd(cbs_table, "ADD", "ILN", iln_cmd); + msn_table_add_cmd(cbs_table, "ADL", "ILN", iln_cmd); msn_table_add_cmd(cbs_table, "REM", "REM", rem_cmd); msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd); msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd); + msn_table_add_cmd(cbs_table, "USR", "GCF", gcf_cmd); msn_table_add_cmd(cbs_table, "SYN", "SYN", syn_cmd); msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd); msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd); msn_table_add_cmd(cbs_table, "REA", "REA", rea_cmd); msn_table_add_cmd(cbs_table, "PRP", "PRP", prp_cmd); - /* msn_table_add_cmd(cbs_table, "BLP", "BLP", blp_cmd); */ - msn_table_add_cmd(cbs_table, "BLP", "BLP", NULL); + msn_table_add_cmd(cbs_table, "BLP", "BLP", blp_cmd); +// msn_table_add_cmd(cbs_table, "BLP", "BLP", NULL); msn_table_add_cmd(cbs_table, "REG", "REG", reg_cmd); msn_table_add_cmd(cbs_table, "ADG", "ADG", adg_cmd); msn_table_add_cmd(cbs_table, "RMG", "RMG", rmg_cmd); @@ -1408,11 +1843,15 @@ /* Asynchronous */ msn_table_add_cmd(cbs_table, NULL, "IPG", ipg_cmd); msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd); + msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd); + msn_table_add_cmd(cbs_table, NULL, "GCF", gcf_cmd); + msn_table_add_cmd(cbs_table, NULL, "SBS", sbs_cmd); msn_table_add_cmd(cbs_table, NULL, "NOT", not_cmd); msn_table_add_cmd(cbs_table, NULL, "CHL", chl_cmd); - msn_table_add_cmd(cbs_table, NULL, "REM", rem_cmd); - msn_table_add_cmd(cbs_table, NULL, "ADD", add_cmd); + msn_table_add_cmd(cbs_table, NULL, "RML", rml_cmd); + msn_table_add_cmd(cbs_table, NULL, "ADL", adl_cmd); + msn_table_add_cmd(cbs_table, NULL, "FQY", fqy_cmd); msn_table_add_cmd(cbs_table, NULL, "QRY", NULL); msn_table_add_cmd(cbs_table, NULL, "QNG", NULL); @@ -1422,6 +1861,9 @@ msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd); msn_table_add_cmd(cbs_table, NULL, "RNG", rng_cmd); + msn_table_add_cmd(cbs_table, NULL, "UBX", ubx_cmd); + msn_table_add_cmd(cbs_table, NULL, "UUX", uux_cmd); + msn_table_add_cmd(cbs_table, NULL, "URL", url_cmd); msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd); @@ -1435,12 +1877,24 @@ msn_table_add_msg_type(cbs_table, "text/x-msmsgsprofile", profile_msg); + /*initial OIM notification*/ + msn_table_add_msg_type(cbs_table, + "text/x-msmsgsinitialmdatanotification", + initial_mdata_msg); + /*OIM notification when user online*/ + msn_table_add_msg_type(cbs_table, + "text/x-msmsgsoimnotification", + initial_mdata_msg); msn_table_add_msg_type(cbs_table, "text/x-msmsgsinitialemailnotification", initial_email_msg); msn_table_add_msg_type(cbs_table, "text/x-msmsgsemailnotification", email_msg); + /*delete an offline Message notification*/ + msn_table_add_msg_type(cbs_table, + "text/x-msmsgsactivemailnotification", + delete_oim_msg); msn_table_add_msg_type(cbs_table, "application/x-msmsgssystemmessage", system_msg); @@ -1451,3 +1905,4 @@ { msn_table_destroy(cbs_table); } + diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/notification.h --- a/libpurple/protocols/msn/notification.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/notification.h Sun Apr 15 04:12:27 2007 +0000 @@ -24,6 +24,14 @@ #ifndef _MSN_NOTIFICATION_H_ #define _MSN_NOTIFICATION_H_ +/*MSN protocol challenge info*/ +/*MSNP13 challenge*/ +#define MSNP13_WLM_PRODUCT_KEY "O4BG@C7BWLYQX?5G" +#define MSNP13_WLM_PRODUCT_ID "PROD01065C%ZFN6F" + +#define MSNP10_PRODUCT_KEY "VT6PX?UQTM4WM%YR" +#define MSNP10_PRODUCT_ID "PROD0038W!61ZTF9" + typedef struct _MsnNotification MsnNotification; #include "session.h" @@ -40,21 +48,23 @@ }; #include "state.h" +void uum_send_msg(MsnSession *session,MsnMessage *msg); void msn_notification_end(void); void msn_notification_init(void); void msn_notification_add_buddy(MsnNotification *notification, const char *list, const char *who, - const char *store_name, int group_id); + const char *store_name, const char *group_id); void msn_notification_rem_buddy(MsnNotification *notification, const char *list, const char *who, - int group_id); + const char *group_id); MsnNotification *msn_notification_new(MsnSession *session); void msn_notification_destroy(MsnNotification *notification); gboolean msn_notification_connect(MsnNotification *notification, const char *host, int port); void msn_notification_disconnect(MsnNotification *notification); +void msn_notification_dump_contact(MsnSession *session); /** * Closes a notification. diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/object.c --- a/libpurple/protocols/msn/object.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/object.c Sun Apr 15 04:12:27 2007 +0000 @@ -281,8 +281,7 @@ g_return_val_if_fail(sha1c != NULL, NULL); - for (l = local_objs; l != NULL; l = l->next) - { + for (l = local_objs; l != NULL; l = l->next){ MsnObject *local_obj = l->data; if (!strcmp(msn_object_get_sha1c(local_obj), sha1c)) @@ -331,3 +330,4 @@ return NULL; } + diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/servconn.c --- a/libpurple/protocols/msn/servconn.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/servconn.c Sun Apr 15 04:12:27 2007 +0000 @@ -166,9 +166,9 @@ **************************************************************************/ static void -connect_cb(gpointer data, gint source, const gchar *error_message) +connect_cb(gpointer data, gint source, PurpleInputCondition cond) { - MsnServConn *servconn; + MsnServConn *servconn = data; servconn = data; servconn->connect_data = NULL; @@ -240,9 +240,9 @@ { servconn->processing = TRUE; return TRUE; + }else{ + return FALSE; } - else - return FALSE; } void @@ -435,14 +435,12 @@ 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; } } while (servconn->connected && !servconn->wasted && servconn->rx_len > 0); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/session.c --- a/libpurple/protocols/msn/session.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/session.c Sun Apr 15 04:12:27 2007 +0000 @@ -42,8 +42,11 @@ session->user = msn_user_new(session->userlist, purple_account_get_username(account), NULL); - - session->protocol_ver = 9; + session->bnode = NULL; + + /*if you want to chat with Yahoo Messenger*/ + //session->protocol_ver = WLM_YAHOO_PROT_VER; + session->protocol_ver = WLM_PROT_VER; session->conv_seq = 1; return session; @@ -70,6 +73,8 @@ msn_userlist_destroy(session->userlist); + g_free(session->passport_info.t); + g_free(session->passport_info.p); g_free(session->passport_info.kv); g_free(session->passport_info.sid); g_free(session->passport_info.mspauth); @@ -87,6 +92,11 @@ if (session->nexus != NULL) msn_nexus_destroy(session->nexus); + if (session->contact != NULL) + msn_contact_destroy(session->contact); + if (session->oim != NULL) + msn_oim_destroy(session->oim); + if (session->user != NULL) msn_user_destroy(session->user); @@ -154,6 +164,38 @@ return NULL; } +/*get the conversation*/ +PurpleConversation * +msn_session_get_conv(MsnSession *session,const char *passport) +{ + PurpleAccount *account; + PurpleConversation * conv; + + g_return_val_if_fail(session != NULL, NULL); + account = session->account; + + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + passport, account); + if(conv == NULL){ + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, passport); + } + return conv; +} + +/* put Message to User Conversation + * + * passport - the one want to talk to you + */ +void +msn_session_report_user(MsnSession *session,const char *passport,char *msg,PurpleMessageFlags flags) +{ + PurpleConversation * conv; + + if ((conv = msn_session_get_conv(session,passport)) != NULL){ + purple_conversation_write(conv, NULL, msg, flags, time(NULL)); + } +} + MsnSwitchBoard * msn_session_find_swboard_with_conv(MsnSession *session, PurpleConversation *conv) { @@ -219,21 +261,16 @@ return swboard; } -static void -msn_session_sync_users(MsnSession *session) +/*setup the bnode, for MSN SOAP contact/address book op*/ +void +msn_session_set_bnode(MsnSession *session) { PurpleBlistNode *gnode, *cnode, *bnode; PurpleConnection *gc = purple_account_get_connection(session->account); g_return_if_fail(gc != NULL); - /* 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_blist_get_root(); gnode; gnode = gnode->next) { - PurpleGroup *group = (PurpleGroup *)gnode; - const char *group_name = group->name; + 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) { @@ -244,36 +281,88 @@ if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) continue; b = (PurpleBuddy *)bnode; - if(purple_buddy_get_account(b) == purple_connection_get_account(gc)) { + if(b->account == gc->account){ + session->bnode = bnode; + return; + } + } + } + } + session->bnode = NULL; +} + +/*get bnode*/ +PurpleBlistNode * +msn_session_get_bnode(MsnSession *session) +{ +#if 1 + return session->bnode; +#else + return purple_get_blist()->root; +#endif +} + +static void +msn_session_sync_users(MsnSession *session) +{ + PurpleBlistNode *gnode, *cnode, *bnode; + PurpleConnection *gc = purple_account_get_connection(session->account); + + g_return_if_fail(gc != NULL); + + /* 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){ + PurpleGroup *group = (PurpleGroup *)gnode; + const char *group_name = group->name; + if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + continue; + if(!g_strcasecmp(group_name, MSN_INDIVIDUALS_GROUP_NAME) + || !g_strcasecmp(group_name,MSN_NON_IM_GROUP_NAME)){ + continue; + } + for(cnode = gnode->child; cnode; cnode = cnode->next) { + if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + continue; + for(bnode = cnode->child; bnode; bnode = bnode->next) { + PurpleBuddy *b; + if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + continue; + b = (PurpleBuddy *)bnode; + if(b->account == gc->account){ MsnUser *remote_user; gboolean found = FALSE; - remote_user = msn_userlist_find_user(session->userlist, purple_buddy_get_name(b)); + 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); - if ((remote_user != NULL) && (remote_user->list_op & MSN_LIST_FL_OP)) - { - int group_id; + if ((remote_user != NULL) && (remote_user->list_op & MSN_LIST_FL_OP)){ + const char *group_id; GList *l; + purple_debug_info("MaYuan","remote user:{%s}\n",b->name); group_id = msn_userlist_find_group_id(remote_user->userlist, group_name); + if(group_id == NULL){ + continue; + } + purple_debug_info("MaYuan","group_id:{%s}\n",group_id); - for (l = remote_user->group_ids; l != NULL; l = l->next) - { - if (group_id == GPOINTER_TO_INT(l->data)) - { + 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)){ 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, purple_buddy_get_name(b), group_name); + msn_show_sync_issue(session, b->name, group_name); } } } @@ -405,3 +494,4 @@ /* Sync users */ msn_session_sync_users(session); } + diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/session.h --- a/libpurple/protocols/msn/session.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/session.h Sun Apr 15 04:12:27 2007 +0000 @@ -38,6 +38,8 @@ #include "cmdproc.h" #include "nexus.h" #include "httpconn.h" +#include "contact.h" +#include "oim.h" #include "userlist.h" #include "sync.h" @@ -94,6 +96,8 @@ MsnNotification *notification; MsnNexus *nexus; + MsnContact *contact; + MsnOim *oim; MsnSync *sync; MsnUserList *userlist; @@ -105,8 +109,18 @@ int conv_seq; /**< The current conversation sequence number. */ + /*psm info*/ + char *psm; + + /*first blist contact node*/ + PurpleBlistNode *bnode; + struct { + /*t and p, get via USR TWN*/ + char *t; + char *p; + char *kv; char *sid; char *mspauth; @@ -114,7 +128,6 @@ char *file; char *client_ip; int client_port; - } passport_info; }; @@ -224,4 +237,17 @@ */ void msn_session_finish_login(MsnSession *session); +/*get conversation via session, + * If has one, return that,else create a new one; + */ +PurpleConversation *msn_session_get_conv(MsnSession *session,const char *passport); + +/*post message to User*/ +void msn_session_report_user(MsnSession *session,const char *passport, + char *msg,PurpleMessageFlags flags); + +void msn_session_set_bnode(MsnSession *session); + +PurpleBlistNode *msn_session_get_bnode(MsnSession *session); + #endif /* _MSN_SESSION_H_ */ diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/slp.c --- a/libpurple/protocols/msn/slp.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/slp.c Sun Apr 15 04:12:27 2007 +0000 @@ -33,6 +33,8 @@ /* ms to delay between sending buddy icon requests to the server. */ #define BUDDY_ICON_DELAY 20000 +/*debug SLP*/ +#define MSN_DEBUG_UD static void send_ok(MsnSlpCall *slpcall, const char *branch, const char *type, const char *content); @@ -751,7 +753,7 @@ * reporting bugs. Hopefully this doesn't cause more crashes. Stu. */ if (slplink->swboard != NULL) - slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); + slplink->swboard->slplink = slplink; else purple_debug_error("msn", "msn_p2p_msg, swboard is NULL, ouch!\n"); } @@ -771,15 +773,14 @@ gc = slpcall->slplink->session->account->gc; who = slpcall->slplink->remote_user; - if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, gc->account))) { + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, gc->account); - /* FIXME: it would be better if we wrote the data as we received it - instead of all at once, calling write multiple times and - close once at the very end - */ - purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size); - purple_conv_custom_smiley_close(conv, slpcall->data_info); - } + /* FIXME: it would be better if we wrote the data as we received it + instead of all at once, calling write multiple times and + close once at the very end + */ + purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size); + purple_conv_custom_smiley_close(conv, slpcall->data_info ); #ifdef MSN_DEBUG_UD purple_debug_info("msn", "Got smiley: %s\n", slpcall->data_info); #endif diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/slpcall.c --- a/libpurple/protocols/msn/slpcall.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/slpcall.c Sun Apr 15 04:12:27 2007 +0000 @@ -22,6 +22,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "msn.h" +#include "msnutils.h" #include "slpcall.h" #include "slpsession.h" @@ -30,24 +31,6 @@ /* #define MSN_DEBUG_SLPCALL */ /************************************************************************** - * Util - **************************************************************************/ - -static char * -rand_guid() -{ - return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X", - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111); -} - -/************************************************************************** * Main **************************************************************************/ diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/slplink.c --- a/libpurple/protocols/msn/slplink.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/slplink.c Sun Apr 15 04:12:27 2007 +0000 @@ -102,7 +102,7 @@ g_return_if_fail(slplink != NULL); if (slplink->swboard != NULL) - slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); + slplink->swboard->slplink = NULL; session = slplink->session; @@ -259,7 +259,7 @@ return; /* If swboard is destroyed we will be too */ - slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); + slplink->swboard->slplink = slplink; } msn_switchboard_send_msg(slplink->swboard, msg, TRUE); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/state.c --- a/libpurple/protocols/msn/state.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/state.c Sun Apr 15 04:12:27 2007 +0000 @@ -38,6 +38,208 @@ N_("Available") }; +/* Local Function Prototype*/ +static char *msn_build_psm(const char *psmstr,const char *mediastr, + const char *guidstr); + +/* + * WLM media PSM info build prcedure + * + * Result can like: + * \0Music\01\0{0} - {1}\0 Song Title\0Song Artist\0Song Album\0\0\ + * \0Games\01\0Playing {0}\0Game Name\0\ + * \0Office\01\0Office Message\0Office App Name\0" + */ +static char * +msn_build_psm(const char *psmstr,const char *mediastr, const char *guidstr) +{ + xmlnode *dataNode,*psmNode,*mediaNode,*guidNode; + char *result; + int length; + + dataNode = xmlnode_new("Data"); + + psmNode = xmlnode_new("PSM"); + if(psmstr != NULL){ + xmlnode_insert_data(psmNode,psmstr,strlen(psmstr)); + } + xmlnode_insert_child(dataNode,psmNode); + + mediaNode = xmlnode_new("CurrentMedia"); + if(mediastr != NULL){ + xmlnode_insert_data(psmNode,mediastr,strlen(mediastr)); + } + xmlnode_insert_child(dataNode,mediaNode); + + guidNode = xmlnode_new("MachineGuid"); + if(guidstr != NULL){ + xmlnode_insert_data(guidNode,guidstr,strlen(guidstr)); + } + xmlnode_insert_child(dataNode,guidNode); + + result = xmlnode_to_str(dataNode,&length); + return result; +} + +/* parse CurrentMedia string */ +char * +msn_parse_currentmedia(const char *cmedia) +{ + char **cmedia_array; + char *buffer=NULL, *inptr, *outptr, *tmpptr; + int length, strings, tmp; + + purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia); + if( (cmedia == NULL) || (!strcmp(cmedia, ""))) { + purple_debug_info("msn", "No currentmedia string\n"); + return NULL; + } + + cmedia_array=g_strsplit(cmedia, "\\0", 0); + + strings=1; /* Skip first empty string */ + length=5; /* Space for '\0' (1 byte) and prefix (4 bytes) */ + while(strcmp(cmedia_array[strings], "")) { + length+= strlen(cmedia_array[strings]); + strings++; + } + + if((strings>3) && (!strcmp(cmedia_array[2], "1"))) { /* Check if enabled */ + + buffer=g_malloc(length); + + inptr=cmedia_array[3]; + outptr=buffer; + + if(!strcmp(cmedia_array[1], "Music")) { + strcpy(outptr, "np. "); + outptr+=4; + }/* else if(!strcmp(cmedia_array[1], "Games")) { + } else if(!strcmp(cmedia_array[1], "Office")) { + }*/ + + while(*inptr!='\0') { + if((*inptr == '{') && (strlen(inptr) > 2) && (*(inptr+2) == '}') ) { + errno = 0; + tmp = strtol(inptr+1,&tmpptr,10); + if( (errno!=0) || (tmpptr == (inptr+1)) || + ((tmp+5)>(strings)) ) { + *outptr = *inptr; /* Conversion not successful */ + outptr++; + } else { + /* Replace {?} tag with appropriate text */ + strcpy(outptr, cmedia_array[tmp+4]); + outptr+=strlen(cmedia_array[tmp+4]); + inptr+=2; + } + } else { + *outptr = *inptr; + outptr++; + } + inptr++; + } + *outptr='\0'; + purple_debug_info("msn", "Parsed currentmedia string, result: \"%s\"\n", + buffer); + } else { + purple_debug_info("msn", "Current media marked disabled, not parsing\n"); + } + + g_strfreev(cmedia_array); + return buffer; +} + +/* get the CurrentMedia info from the XML string */ +char * +msn_get_currentmedia(char *xml_str, gsize len) +{ + xmlnode *payloadNode, *currentmediaNode; + char *currentmedia_str, *currentmedia; + + purple_debug_info("msn","msn get CurrentMedia\n"); + payloadNode = xmlnode_from_str(xml_str, len); + if (!payloadNode){ + purple_debug_error("msn","PSM XML parse Error!\n"); + return NULL; + } + currentmediaNode = xmlnode_get_child(payloadNode, "CurrentMedia"); + if (currentmediaNode == NULL){ + purple_debug_info("msn","No CurrentMedia Node"); + g_free(payloadNode); + return NULL; + } + currentmedia_str = xmlnode_get_data(currentmediaNode); + currentmedia = g_strdup(currentmedia_str); + + g_free(currentmediaNode); + g_free(payloadNode); + + return currentmedia; +} + +/*get the PSM info from the XML string*/ +char * +msn_get_psm(char *xml_str, gsize len) +{ + xmlnode *payloadNode, *psmNode; + char *psm_str, *psm; + + purple_debug_info("Ma Yuan","msn get PSM\n"); + payloadNode = xmlnode_from_str(xml_str, len); + if (!payloadNode){ + purple_debug_error("MaYuan","PSM XML parse Error!\n"); + return NULL; + } + psmNode = xmlnode_get_child(payloadNode, "PSM"); + if (psmNode == NULL){ + purple_debug_info("Ma Yuan","No PSM status Node"); + g_free(payloadNode); + return NULL; + } + psm_str = xmlnode_get_data(psmNode); + psm = g_strdup(psm_str); + + g_free(psmNode); + g_free(payloadNode); + + return psm; +} + +/* set the MSN's PSM info,Currently Read from the status Line + * Thanks for Cris Code + */ +void +msn_set_psm(MsnSession *session) +{ + PurpleAccount *account = session->account; + PurplePresence *presence; + PurpleStatus *status; + MsnCmdProc *cmdproc; + MsnTransaction *trans; + char *payload; + const char *statusline; + + g_return_if_fail(session != NULL); + g_return_if_fail(session->notification != NULL); + + cmdproc = session->notification->cmdproc; + /*prepare PSM info*/ + if(session->psm){ + g_free(session->psm); + } + /*Get the PSM string from Purple's Status Line*/ + presence = purple_account_get_presence(account); + status = purple_presence_get_active_status(presence); + statusline = purple_status_get_attr_string(status, "message"); + session ->psm = msn_build_psm(statusline, NULL, NULL); + payload = session->psm; + + purple_debug_info("MaYuan","UUX{%s}\n",payload); + trans = msn_transaction_new(cmdproc, "UUX","%d",strlen(payload)); + msn_transaction_set_payload(trans, payload, strlen(payload)); + msn_cmdproc_send_trans(cmdproc, trans); +} + void msn_change_status(MsnSession *session) { @@ -63,13 +265,10 @@ msnobj = msn_user_get_object(user); - if (msnobj == NULL) - { + if (msnobj == NULL){ msn_cmdproc_send(cmdproc, "CHG", "%s %d", state_text, MSN_CLIENT_ID); - } - else - { + }else{ char *msnobj_str; msnobj_str = msn_object_to_string(msnobj); @@ -79,6 +278,7 @@ g_free(msnobj_str); } + msn_set_psm(session); } const char * diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/state.h --- a/libpurple/protocols/msn/state.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/state.h Sun Apr 15 04:12:27 2007 +0000 @@ -59,6 +59,17 @@ const char *msn_state_get_text(MsnAwayType state); +void msn_set_psm(MsnSession *session); + +/* Parse CurrentMedia string */ +char * msn_parse_currentmedia(const char *cmedia); + +/* Get the CurrentMedia info from the XML string */ +char * msn_get_currentmedia(char *xml_str,gsize len); + +/*get the PSM info from the XML string*/ +char * msn_get_psm(char *xml_str,gsize len); + MsnAwayType msn_state_from_account(PurpleAccount *account); #endif /* _MSN_STATE_H_ */ diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/switchboard.c --- a/libpurple/protocols/msn/switchboard.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/switchboard.c Sun Apr 15 04:12:27 2007 +0000 @@ -25,10 +25,12 @@ #include "prefs.h" #include "switchboard.h" #include "notification.h" -#include "msn-utils.h" +#include "msnutils.h" #include "error.h" +#define MSN_DEBUG_SB + static MsnTable *cbs_table; static void msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, @@ -82,8 +84,8 @@ swboard->destroying = TRUE; /* If it linked us is because its looking for trouble */ - while (swboard->slplinks != NULL) - msn_slplink_destroy(swboard->slplinks->data); + if (swboard->slplink != NULL) + msn_slplink_destroy(swboard->slplink); /* Destroy the message queue */ while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) @@ -527,6 +529,7 @@ payload = msn_message_gen_payload(msg, &payload_len); #ifdef MSN_DEBUG_SB + purple_debug_info("MaYuan","SB length:{%d}",payload_len); msn_message_show_readable(msg, "SB SEND", FALSE); #endif @@ -614,6 +617,7 @@ g_return_if_fail(swboard != NULL); g_return_if_fail(msg != NULL); + purple_debug_info("Ma Yuan","switchboard send msg..\n"); if (msn_switchboard_can_send(swboard)) release_msg(swboard, msg); else if (queue) @@ -720,7 +724,8 @@ msg = msn_message_new_from_cmd(cmdproc->session, cmd); - msn_message_parse_payload(msg, payload, len); + msn_message_parse_payload(msg, payload, len, + MSG_LINE_DEM,MSG_BODY_DEM); #ifdef MSN_DEBUG_SB msn_message_show_readable(msg, "SB RECV", FALSE); #endif @@ -742,6 +747,14 @@ } static void +ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) +{ + purple_debug_misc("MaYuan","get UBM...\n"); + cmdproc->servconn->payload_len = atoi(cmd->params[4]); + cmdproc->last_cmd->payload_cb = msg_cmd_post; +} + +static void nak_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnMessage *msg; @@ -976,16 +989,13 @@ swboard = cmdproc->data; g_return_if_fail(swboard != NULL); - if (msn_switchboard_is_invited(swboard)) - { + if (msn_switchboard_is_invited(swboard)){ swboard->empty = FALSE; msn_cmdproc_send(cmdproc, "ANS", "%s %s %s", purple_account_get_username(account), swboard->auth_key, swboard->session_id); - } - else - { + }else{ msn_cmdproc_send(cmdproc, "USR", "%s %s", purple_account_get_username(account), swboard->auth_key); @@ -1054,6 +1064,8 @@ cal_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) { int reason = MSN_SB_ERROR_UNKNOWN; + MsnMessage *msg; + MsnSwitchBoard *swboard = trans->data; if (error == 215) { @@ -1066,7 +1078,19 @@ } purple_debug_warning("msn", "cal_error: command %s gave error %i\n", trans->command, error); + purple_debug_warning("msn", "Will Use Offline Message to sendit\n"); +// cal_error_helper(trans, reason); + /*offline Message send Process*/ + + while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL){ + purple_debug_warning("Ma Yuan","offline msg to send:{%s}\n",msg->body); + /* The messages could not be sent due to a switchboard error */ + swboard->error = MSN_SB_ERROR_USER_OFFLINE; + msg_error_helper(swboard->cmdproc, msg, + MSN_MSG_ERROR_SB); + msn_message_unref(msg); + } cal_error_helper(trans, reason); } @@ -1110,6 +1134,7 @@ /* The conversation window was closed. */ return; + purple_debug_info("MaYuan","Switchboard:auth:{%s} socket:{%s}\n",cmd->params[4],cmd->params[2]); msn_switchboard_set_auth_key(swboard, cmd->params[4]); msn_parse_socket(cmd->params[2], &host, &port); @@ -1222,6 +1247,7 @@ msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd); msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd); + msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd); msn_table_add_cmd(cbs_table, NULL, "JOI", joi_cmd); msn_table_add_cmd(cbs_table, NULL, "BYE", bye_cmd); msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/switchboard.h --- a/libpurple/protocols/msn/switchboard.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/switchboard.h Sun Apr 15 04:12:27 2007 +0000 @@ -102,7 +102,7 @@ MsnSBErrorType error; /**< The error that occurred in this switchboard (if applicable). */ - GList *slplinks; /**< The list of slplinks that are using this switchboard. */ + MsnSlpLink *slplink; /**< The slplink that is using this switchboard. */ }; /** diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/sync.c --- a/libpurple/protocols/msn/sync.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/sync.c Sun Apr 15 04:12:27 2007 +0000 @@ -35,8 +35,7 @@ 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. @@ -44,9 +43,7 @@ * 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. * @@ -89,10 +86,9 @@ lsg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session = cmdproc->session; - const char *name; - int group_id; + const char *name, *group_id; - group_id = atoi(cmd->params[0]); + group_id = cmd->params[0]; name = purple_url_decode(cmd->params[1]); msn_group_new(session->userlist, group_id, name); diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/table.c --- a/libpurple/protocols/msn/table.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/table.c Sun Apr 15 04:12:27 2007 +0000 @@ -77,20 +77,14 @@ cbs = NULL; - if (command == NULL) - { + if (command == NULL){ cbs = table->async; - } - else if (strcmp(command, "fallback") == 0) - { + }else if (strcmp(command, "fallback") == 0) { cbs = table->fallback; - } - else - { + }else{ cbs = g_hash_table_lookup(table->cmds, command); - if (cbs == NULL) - { + if (cbs == NULL){ cbs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); g_hash_table_insert(table->cmds, command, cbs); } diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/transaction.c --- a/libpurple/protocols/msn/transaction.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/transaction.c Sun Apr 15 04:12:27 2007 +0000 @@ -205,8 +205,7 @@ void msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb) { - if (trans->timer) - { + if (trans->timer){ purple_debug_error("msn", "This shouldn't be happening\n"); purple_timeout_remove(trans->timer); } diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/user.c --- a/libpurple/protocols/msn/user.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/user.c Sun Apr 15 04:12:27 2007 +0000 @@ -25,6 +25,7 @@ #include "user.h" #include "slp.h" +/*new a user object*/ MsnUser * msn_user_new(MsnUserList *userlist, const char *passport, const char *store_name) @@ -50,6 +51,7 @@ return user; } +/*destroy a user object*/ void msn_user_destroy(MsnUser *user) { @@ -58,8 +60,13 @@ if (user->clientcaps != NULL) g_hash_table_destroy(user->clientcaps); - if (user->group_ids != NULL) + if (user->group_ids != NULL){ + GList *l; + for (l = user->group_ids; l != NULL; l = l->next){ + g_free(l->data); + } g_list_free(user->group_ids); + } if (user->msnobj != NULL) msn_object_destroy(user->msnobj); @@ -67,6 +74,7 @@ g_free(user->passport); g_free(user->friendly_name); g_free(user->store_name); + g_free(user->uid); g_free(user->phone.home); g_free(user->phone.work); g_free(user->phone.mobile); @@ -81,7 +89,18 @@ account = user->userlist->session->account; - if (user->status != NULL) { + if (user->statusline != NULL && user->currentmedia != NULL) { + purple_prpl_got_user_status(account, user->passport, user->status, + "message", user->statusline, + "currentmedia", user->currentmedia, NULL); + } else if (user->currentmedia != NULL) { + purple_prpl_got_user_status(account, user->passport, "currentmedia", + user->currentmedia, NULL); + } else if (user->statusline != NULL) { + //char *status = g_strdup_printf("%s - %s", user->status, user->statusline); + purple_prpl_got_user_status(account, user->passport, user->status, + "message", user->statusline, NULL); + } else if (user->status != NULL) { if (!strcmp(user->status, "offline") && user->mobile) { purple_prpl_got_user_status(account, user->passport, "available", NULL); purple_prpl_got_user_status(account, user->passport, "mobile", NULL); @@ -142,12 +161,56 @@ } void +msn_user_set_statusline(MsnUser *user, const char *statusline) +{ + g_return_if_fail(user != NULL); + + g_free(user->statusline); + user->statusline = g_strdup(statusline); +} + +void +msn_user_set_currentmedia(MsnUser *user, const char *currentmedia) +{ + g_return_if_fail(user != NULL); + + g_free(user->currentmedia); + user->currentmedia = g_strdup(currentmedia); +} + +void msn_user_set_store_name(MsnUser *user, const char *name) { g_return_if_fail(user != NULL); - g_free(user->store_name); - user->store_name = g_strdup(name); + if (name != NULL){ + g_free(user->store_name); + user->store_name = g_strdup(name); + } +} + +void +msn_user_set_uid(MsnUser *user, const char *uid) +{ + g_return_if_fail(user != NULL); + + g_free(user->uid); + user->uid = g_strdup(uid); +} + +void +msn_user_set_type(MsnUser *user,int type) +{ + g_return_if_fail(user != NULL); + + user->type = type; +} + +void +msn_user_set_op(MsnUser *user,int list_op) +{ + g_return_if_fail(list_op != 0); + user->list_op |= list_op; } void @@ -159,20 +222,16 @@ 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); @@ -224,62 +283,83 @@ 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); } } +/*add group id to User object*/ void -msn_user_add_group_id(MsnUser *user, int id) +msn_user_add_group_id(MsnUser *user, const char* id) { MsnUserList *userlist; PurpleAccount *account; PurpleBuddy *b; PurpleGroup *g; const char *passport; + char *group_id; const char *group_name; g_return_if_fail(user != NULL); - g_return_if_fail(id >= 0); + g_return_if_fail(id != NULL); - user->group_ids = g_list_append(user->group_ids, GINT_TO_POINTER(id)); + group_id = g_strdup(id); + user->group_ids = g_list_append(user->group_ids, group_id); userlist = user->userlist; account = userlist->session->account; passport = msn_user_get_passport(user); - group_name = msn_userlist_find_group_name(userlist, id); + group_name = msn_userlist_find_group_name(userlist, group_id); + + purple_debug_info("User","group id:%s,name:%s,user:%s\n",group_id,group_name,passport); g = purple_find_group(group_name); - if ((id == 0) && (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); } + b->proto_data = user; + /*Update the blist Node info*/ +// purple_blist_node_set_string(&(b->node), "", ""); +} - b->proto_data = user; +/*check if the msn user is online*/ +gboolean +msn_user_is_online(PurpleAccount *account, const char *name) +{ + PurpleBuddy *buddy; + + buddy =purple_find_buddy(account,name); + return PURPLE_BUDDY_IS_ONLINE(buddy); +} + +/*check to see if user is yahoo user? + * TODO: we need to identify it via contact parse + */ +gboolean +msn_user_is_yahoo(PurpleAccount *account ,const char *name) +{ + return (strstr(name,"yahoo") != NULL); } void -msn_user_remove_group_id(MsnUser *user, int id) +msn_user_remove_group_id(MsnUser *user, const char * id) { g_return_if_fail(user != NULL); - g_return_if_fail(id >= 0); + g_return_if_fail(id != NULL); - user->group_ids = g_list_remove(user->group_ids, GINT_TO_POINTER(id)); + user->group_ids = g_list_remove(user->group_ids, id); + /* khc need to use g_list_find_custom here to find the right link */ + //g_free(id); } void diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/user.h --- a/libpurple/protocols/msn/user.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/user.h Sun Apr 15 04:12:27 2007 +0000 @@ -45,7 +45,12 @@ char *store_name; /**< The name stored in the server. */ char *friendly_name; /**< The friendly name. */ + char * uid; /*< User Id */ + const char *status; /**< The state of the user. */ + char *statusline; /**< The state of the user. */ + char *currentmedia; /**< The current media of the user. */ + gboolean idle; /**< The idle state of the user. */ struct @@ -65,6 +70,7 @@ GHashTable *clientcaps; /**< The client's capabilities. */ + int type; int list_op; }; @@ -102,6 +108,22 @@ */ void msn_user_update(MsnUser *user); + /** + * Sets the new statusline of user. + * + * @param user The user. + * @param state The statusline string. + */ +void msn_user_set_statusline(MsnUser *user, const char *statusline); + + /** + * Sets the current media of user. + * + * @param user The user. + * @param state The statusline string. + */ +void msn_user_set_currentmedia(MsnUser *user, const char *currentmedia); + /** * Sets the new state of user. * @@ -156,7 +178,7 @@ * @param user The user. * @param id The group ID. */ -void msn_user_add_group_id(MsnUser *user, int id); +void msn_user_add_group_id(MsnUser *user, const char * id); /** * Removes the group ID from a user. @@ -164,7 +186,7 @@ * @param user The user. * @param id The group ID. */ -void msn_user_remove_group_id(MsnUser *user, int id); +void msn_user_remove_group_id(MsnUser *user, const char * id); /** * Sets the home phone number for a user. @@ -182,6 +204,9 @@ */ void msn_user_set_work_phone(MsnUser *user, const char *number); +void msn_user_set_uid(MsnUser *user, const char *uid); +void msn_user_set_type(MsnUser *user,int type); + /** * Sets the mobile phone number for a user. * @@ -279,6 +304,21 @@ */ GHashTable *msn_user_get_client_caps(const MsnUser *user); +/** + * check to see if user is online + */ +gboolean +msn_user_is_online(PurpleAccount *account, const char *name); + +/** + * check to see if user is Yahoo User + */ +gboolean +msn_user_is_yahoo(PurpleAccount *account ,const char *name); + +void msn_user_set_op(MsnUser *user,int list_op); + /*@}*/ + #endif /* _MSN_USER_H_ */ diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/userlist.c --- a/libpurple/protocols/msn/userlist.c Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/userlist.c Sun Apr 15 04:12:27 2007 +0000 @@ -53,10 +53,13 @@ static void msn_cancel_add_cb(MsnPermitAdd *pa) { - MsnSession *session = pa->gc->proto_data; - MsnUserList *userlist = session->userlist; + if (g_list_find(purple_connections_get_all(), pa->gc) != NULL) + { + MsnSession *session = pa->gc->proto_data; + MsnUserList *userlist = session->userlist; - msn_userlist_add_buddy(userlist, pa->who, MSN_LIST_BL, NULL); + msn_userlist_add_buddy(userlist, pa->who, MSN_LIST_BL, NULL); + } g_free(pa->who); g_free(pa->friendly); @@ -76,6 +79,7 @@ purple_account_request_authorization(purple_connection_get_account(gc), passport, NULL, friendly, NULL, purple_find_buddy(purple_connection_get_account(gc), passport) != NULL, G_CALLBACK(msn_accept_add_cb), G_CALLBACK(msn_cancel_add_cb), pa); + } /************************************************************************** @@ -83,22 +87,22 @@ **************************************************************************/ static gboolean -user_is_in_group(MsnUser *user, int group_id) +user_is_in_group(MsnUser *user, const char * group_id) { if (user == NULL) return FALSE; - if (group_id < 0) + if (group_id == NULL) return FALSE; - if (g_list_find(user->group_ids, GINT_TO_POINTER(group_id))) + if (g_list_find(user->group_ids, group_id)) return TRUE; return FALSE; } static gboolean -user_is_there(MsnUser *user, int list_id, int group_id) +user_is_there(MsnUser *user, int list_id, const char * group_id) { int list_op; @@ -110,9 +114,8 @@ if (!(user->list_op & list_op)) return FALSE; - if (list_id == MSN_LIST_FL) - { - if (group_id >= 0) + if (list_id == MSN_LIST_FL){ + if (group_id != NULL) return user_is_in_group(user, group_id); } @@ -151,25 +154,25 @@ msn_request_add_group(MsnUserList *userlist, const char *who, const char *old_group_name, const char *new_group_name) { + MsnSession *session; MsnCmdProc *cmdproc; - MsnTransaction *trans; MsnMoveBuddy *data; - cmdproc = userlist->session->notification->cmdproc; + session = userlist->session; + cmdproc = session->notification->cmdproc; data = g_new0(MsnMoveBuddy, 1); data->who = g_strdup(who); - if (old_group_name) + if (old_group_name){ data->old_group_name = g_strdup(old_group_name); + /*delete the old group via SOAP action*/ + msn_del_group(session,old_group_name); + } - trans = msn_transaction_new(cmdproc, "ADG", "%s %d", - purple_url_encode(new_group_name), - 0); + /*add new group via SOAP action*/ + msn_add_group(session, new_group_name); - msn_transaction_set_data(trans, data); - - msn_cmdproc_send_trans(cmdproc, trans); } /************************************************************************** @@ -193,12 +196,13 @@ void msn_got_add_user(MsnSession *session, MsnUser *user, - MsnListId list_id, int group_id) + MsnListId list_id, const char * group_id) { PurpleAccount *account; const char *passport; const char *friendly; + purple_debug_info("MaYuan","got add user...\n"); account = session->account; passport = msn_user_get_passport(user); @@ -212,25 +216,17 @@ serv_got_alias(gc, passport, friendly); - if (group_id >= 0) + 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; @@ -254,14 +250,13 @@ 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 * name instead? --KingAnt */ - got_new_entry(gc, passport, friendly); +// got_new_entry(gc, passport, friendly); } } @@ -271,7 +266,7 @@ void msn_got_rem_user(MsnSession *session, MsnUser *user, - MsnListId list_id, int group_id) + MsnListId list_id, const char * group_id) { PurpleAccount *account; const char *passport; @@ -280,29 +275,19 @@ 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 >= 0) - { + if (group_id != NULL){ 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", @@ -327,11 +312,9 @@ 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); - } } @@ -350,13 +333,11 @@ 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)) - { - int group_id; - group_id = GPOINTER_TO_INT(c->data); + for (c = group_ids; c != NULL; c = g_slist_next(c)) { + char *group_id; + group_id = c->data; msn_user_add_group_id(user, group_id); } @@ -365,22 +346,19 @@ 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? @@ -389,13 +367,12 @@ * 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); } } - user->list_op = list_op; + user->list_op |= list_op; } /************************************************************************** @@ -425,18 +402,16 @@ { GList *l; - for (l = userlist->users; l != NULL; l = l->next) - { + /*destroy userlist*/ + for (l = userlist->users; l != NULL; l = l->next){ msn_user_destroy(l->data); } - g_list_free(userlist->users); - for (l = userlist->groups; l != NULL; l = l->next) - { + /*destroy group list*/ + for (l = userlist->groups; l != NULL; l = l->next){ msn_group_destroy(l->data); } - g_list_free(userlist->groups); g_queue_free(userlist->buddy_icon_requests); @@ -447,6 +422,20 @@ g_free(userlist); } +MsnUser * +msn_userlist_find_add_user(MsnUserList *userlist,const char *passport,const char *userName) +{ + MsnUser *user; + + user = msn_userlist_find_user(userlist, passport); + if (user == NULL){ + user = msn_user_new(userlist, passport, userName); + msn_userlist_add_user(userlist, user); + } + msn_user_set_store_name(user, userName); + return user; +} + void msn_userlist_add_user(MsnUserList *userlist, MsnUser *user) { @@ -466,14 +455,15 @@ 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); - if (!strcmp(passport, user->passport)) + if (!g_strcasecmp(passport, user->passport)){ +// purple_debug_info("MsnUserList","return:%p\n",user); return user; + } } return NULL; @@ -492,18 +482,17 @@ } MsnGroup * -msn_userlist_find_group_with_id(MsnUserList *userlist, int id) +msn_userlist_find_group_with_id(MsnUserList *userlist, const char * id) { GList *l; g_return_val_if_fail(userlist != NULL, NULL); - g_return_val_if_fail(id >= 0, NULL); + g_return_val_if_fail(id != 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->id == id) + if (!g_strcasecmp(group->id,id)) return group; } @@ -518,45 +507,46 @@ 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_ascii_strcasecmp(name, group->name)) + if ((group->name != NULL) && !g_strcasecmp(name, group->name)) return group; } return NULL; } -int +const char * msn_userlist_find_group_id(MsnUserList *userlist, const char *group_name) { MsnGroup *group; group = msn_userlist_find_group_with_name(userlist, group_name); - if (group != NULL) + if (group != NULL){ return msn_group_get_id(group); - else - return -1; + }else{ + return NULL; + } } const char * -msn_userlist_find_group_name(MsnUserList *userlist, int group_id) +msn_userlist_find_group_name(MsnUserList *userlist, const char * group_id) { MsnGroup *group; 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 -msn_userlist_rename_group_id(MsnUserList *userlist, int group_id, +msn_userlist_rename_group_id(MsnUserList *userlist, const char * group_id, const char *new_name) { MsnGroup *group; @@ -568,7 +558,7 @@ } void -msn_userlist_remove_group_id(MsnUserList *userlist, int group_id) +msn_userlist_remove_group_id(MsnUserList *userlist, const char * group_id) { MsnGroup *group; @@ -586,18 +576,22 @@ const char *who, int list_id, const char *group_name) { MsnUser *user; - int group_id; + const char *group_id; const char *list; user = msn_userlist_find_user(userlist, who); - group_id = -1; + + g_return_if_fail(user != NULL); - if (group_name != NULL) - { + /*delete the contact from address book via soap action*/ + msn_delete_contact(userlist->session->contact,user->uid); + + group_id = NULL; + + if (group_name != NULL){ group_id = msn_userlist_find_group_id(userlist, group_name); - if (group_id < 0) - { + if (group_id == NULL){ /* Whoa, there is no such group. */ purple_debug_error("msn", "Group doesn't exist: %s\n", group_name); return; @@ -605,8 +599,7 @@ } /* 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); @@ -619,25 +612,25 @@ msn_notification_rem_buddy(userlist->session->notification, list, who, group_id); } +/*add buddy*/ void msn_userlist_add_buddy(MsnUserList *userlist, const char *who, int list_id, const char *group_name) { MsnUser *user; - int group_id; + const char *group_id; const char *list; const char *store_name; - group_id = -1; + 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 */ - if (list_id == MSN_LIST_FL) - { + if (list_id == MSN_LIST_FL) { char *str = g_strdup_printf(_("Unable to add \"%s\"."), who); purple_notify_error(NULL, NULL, str, _("The screen name specified is invalid.")); @@ -647,12 +640,10 @@ return; } - if (group_name != NULL) - { + if (group_name != NULL){ group_id = msn_userlist_find_group_id(userlist, group_name); - if (group_id < 0) - { + if (group_id == NULL){ /* Whoa, we must add that group first. */ msn_request_add_group(userlist, who, NULL, group_name); return; @@ -662,8 +653,7 @@ 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; @@ -674,20 +664,23 @@ /* Then request the add to the server. */ list = lists[list_id]; + 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 msn_userlist_move_buddy(MsnUserList *userlist, const char *who, const char *old_group_name, const char *new_group_name) { - int new_group_id; + const char *new_group_id; new_group_id = msn_userlist_find_group_id(userlist, new_group_name); - if (new_group_id < 0) - { + if (new_group_id == NULL){ msn_request_add_group(userlist, who, old_group_name, new_group_name); return; } @@ -695,3 +688,48 @@ msn_userlist_add_buddy(userlist, who, MSN_LIST_FL, new_group_name); msn_userlist_rem_buddy(userlist, who, MSN_LIST_FL, old_group_name); } + +/*load userlist from the Blist file cache*/ +void +msn_userlist_load(MsnSession *session) +{ + PurpleBlistNode *gnode, *cnode, *bnode; + PurpleConnection *gc = purple_account_get_connection(session->account); + GSList *l; + MsnUser * user; + + g_return_if_fail(gc != NULL); + + 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)) + continue; + for(bnode = cnode->child; bnode; bnode = bnode->next) { + PurpleBuddy *b; + if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + continue; + b = (PurpleBuddy *)bnode; + if(b->account == gc->account){ + user = msn_userlist_find_add_user(session->userlist, + b->name,NULL); + b->proto_data = user; + msn_user_set_op(user, MSN_LIST_FL_OP); + } + } + } + } + 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) { + user = msn_userlist_find_add_user(session->userlist, + (char *)l->data,NULL); + msn_user_set_op(user, MSN_LIST_BL_OP); + } + +} + diff -r 6167ee79ecd0 -r 60bc06498746 libpurple/protocols/msn/userlist.h --- a/libpurple/protocols/msn/userlist.h Sun Apr 15 00:32:57 2007 +0000 +++ b/libpurple/protocols/msn/userlist.h Sun Apr 15 04:12:27 2007 +0000 @@ -67,30 +67,34 @@ MsnListId msn_get_list_id(const char *list); void msn_got_add_user(MsnSession *session, MsnUser *user, - MsnListId list_id, int group_id); + MsnListId list_id, const char *group_id); void msn_got_rem_user(MsnSession *session, MsnUser *user, - MsnListId list_id, int group_id); + MsnListId list_id, const char *group_id); void msn_got_lst_user(MsnSession *session, MsnUser *user, int list_op, GSList *group_ids); MsnUserList *msn_userlist_new(MsnSession *session); void msn_userlist_destroy(MsnUserList *userlist); + void msn_userlist_add_user(MsnUserList *userlist, MsnUser *user); void msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user); MsnUser *msn_userlist_find_user(MsnUserList *userlist, - const char *passport); + const char *passport); +MsnUser *msn_userlist_find_add_user(MsnUserList *userlist, + const char *passport,const char *userName); + void msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group); void msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group); -MsnGroup *msn_userlist_find_group_with_id(MsnUserList *userlist, int id); +MsnGroup *msn_userlist_find_group_with_id(MsnUserList *userlist, const char *id); MsnGroup *msn_userlist_find_group_with_name(MsnUserList *userlist, const char *name); -int msn_userlist_find_group_id(MsnUserList *userlist, +const char * msn_userlist_find_group_id(MsnUserList *userlist, const char *group_name); const char *msn_userlist_find_group_name(MsnUserList *userlist, - int group_id); -void msn_userlist_rename_group_id(MsnUserList *userlist, int group_id, + const char *group_id); +void msn_userlist_rename_group_id(MsnUserList *userlist, const char *group_id, const char *new_name); -void msn_userlist_remove_group_id(MsnUserList *userlist, int group_id); +void msn_userlist_remove_group_id(MsnUserList *userlist, const char *group_id); void msn_userlist_rem_buddy(MsnUserList *userlist, const char *who, int list_id, const char *group_name); @@ -99,5 +103,6 @@ void msn_userlist_move_buddy(MsnUserList *userlist, const char *who, const char *old_group_name, const char *new_group_name); +void msn_userlist_load(MsnSession *session); #endif /* _MSN_USERLIST_H_ */