changeset 19785:852b32710df0

[gaim-migrate @ 16507] add the contact list retrieve and dump contact list to server currently can do chanllenge successfully But can't get the buddy list done by MaYuan<mayuan2006@gmail.com> committer: Ethan Blanton <elb@pidgin.im>
author Ma Yuan <mayuan2006@gmail.com>
date Mon, 17 Jul 2006 12:22:37 +0000
parents bc30c6270d9f
children 23258253c7a0
files src/protocols/msn/Makefile.am src/protocols/msn/cmdproc.c src/protocols/msn/command.c src/protocols/msn/contact.c src/protocols/msn/contact.h src/protocols/msn/dialog.c src/protocols/msn/group.c src/protocols/msn/group.h src/protocols/msn/msn-utils.c src/protocols/msn/msn-utils.h src/protocols/msn/msn.h src/protocols/msn/nexus.c src/protocols/msn/notification.c src/protocols/msn/notification.h src/protocols/msn/object.c src/protocols/msn/oim.c src/protocols/msn/oim.h src/protocols/msn/session.c src/protocols/msn/soap.c src/protocols/msn/soap.h src/protocols/msn/user.c src/protocols/msn/user.h src/protocols/msn/userlist.c src/protocols/msn/userlist.h
diffstat 24 files changed, 914 insertions(+), 244 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/msn/Makefile.am	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/Makefile.am	Mon Jul 17 12:22:37 2006 +0000
@@ -32,6 +32,8 @@
 	notification.h \
 	object.c \
 	object.h \
+	oim.c\
+	oim.h\
 	page.c \
 	page.h \
 	servconn.c \
--- a/src/protocols/msn/cmdproc.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/cmdproc.c	Mon Jul 17 12:22:37 2006 +0000
@@ -134,6 +134,7 @@
 	}
 
 	msn_servconn_write(servconn, data, len);
+	gaim_debug_info("<<","%s",data);
 
 	g_free(data);
 }
--- a/src/protocols/msn/command.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/command.c	Mon Jul 17 12:22:37 2006 +0000
@@ -47,7 +47,6 @@
 	if( (!strcmp(str,"ADL")) ||
 		(!strcmp(str,"GCF")) ||
 		(!strcmp(str,"MSG")) ||
-		(!strcmp(str,"QRY")) ||
 		(!strcmp(str,"RML")) ||
 		(!strcmp(str,"UBX")) ||
 		(!strcmp(str,"UBN")) ||
--- a/src/protocols/msn/contact.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/contact.c	Mon Jul 17 12:22:37 2006 +0000
@@ -37,9 +37,7 @@
 
 	contact = g_new0(MsnContact, 1);
 	contact->session = session;
-	contact->soapconn = msn_soap_new(session);
-	contact->soapconn->parent = contact;
-	contact->soapconn->ssl_conn = 1;
+	contact->soapconn = msn_soap_new(session,contact,1);
 
 	return contact;
 }
@@ -84,13 +82,44 @@
 	msn_get_contact_list(contact);
 }
 
+/*get MSN member role utility*/
+static int
+msn_get_memberrole(char * role)
+{
+	if(!strcmp(role,"Allow")){
+		return MSN_LIST_AL_OP;
+	}else if(!strcmp(role,"Block")){
+		return MSN_LIST_BL_OP;
+	}else if(!strcmp(role,"Reverse")){
+		return MSN_LIST_RL_OP;
+	}else if(!strcmp(role,"Forward")){
+		return MSN_LIST_FL_OP;
+	}
+	return 0;
+}
+
+/*get User Type*/
+static int 
+msn_get_user_type(char * type)
+{
+	if(!strcmp(type,"Regular")){
+		return 1;
+	}
+	return 0;
+}
+
+/*parse contact list*/
 static void
 msn_parse_contact_list(MsnContact * contact)
 {
-	xmlnode * node,*envelop,*body,*response,*result,*services,*service,*memberships;
-	xmlnode *membershipnode,*members,*member,*passport,*role;
-	int len;
+	MsnSession * session;
+	MsnUser *user;
+	int list_op =0;
+	char * passport;
+	xmlnode * node,*body,*response,*result,*services,*service,*memberships;
+	xmlnode *membershipnode,*members,*member,*passportNode,*role;
 
+	session = contact->session;
 	gaim_debug_misc("xml","parse contact list:{%s}\nsize:%d\n",contact->soapconn->body,contact->soapconn->body_len);
 	node = 	xmlnode_from_str(contact->soapconn->body, contact->soapconn->body_len);
 //	node = 	xmlnode_from_str(contact->soapconn->body, -1);
@@ -115,16 +144,28 @@
 	for(membershipnode = xmlnode_get_child(memberships, "Membership"); membershipnode;
 					membershipnode = xmlnode_get_next_twin(membershipnode)){
 		role = xmlnode_get_child(membershipnode,"MemberRole");
-		gaim_debug_misc("memberrole","role:%s\n",xmlnode_get_data(role));
+	//	gaim_debug_misc("memberrole","role:%s\n",xmlnode_get_data(role));
+		list_op = msn_get_memberrole(xmlnode_get_data(role));
+		gaim_debug_misc("memberrole","role:%s,list_op:%d\n",xmlnode_get_data(role),list_op);
 		members = xmlnode_get_child(membershipnode,"Members");
-			for(member = xmlnode_get_child(members, "Member"); member;
-					member = xmlnode_get_next_twin(member)){
-				passport = xmlnode_get_child(member,"PassportName");
-				gaim_debug_misc("Passport","name:%s\n",xmlnode_get_data(passport));
+		for(member = xmlnode_get_child(members, "Member"); member;
+				member = xmlnode_get_next_twin(member)){
+			passportNode = xmlnode_get_child(member,"PassportName");
+			passport = xmlnode_get_data(passportNode);
+			gaim_debug_misc("Passport","name:%s\n",passport);
+			user = msn_userlist_find_user(session->userlist, passport);
+			if (user == NULL){
+				user = msn_user_new(session->userlist, passport, "");
+				msn_userlist_add_user(session->userlist, user);
 			}
+//			user->list_op |= list_op;
+			msn_got_lst_user(session, user, list_op, NULL);
+		}
 	}
 
 	xmlnode_free(node);
+
+	msn_get_address_book(contact);
 }
 
 static void
@@ -156,55 +197,182 @@
 void
 msn_get_contact_list(MsnContact * contact)
 {
-	char * soap_head = NULL;
-	char * soap_body = NULL;
-	char * request_str = NULL;
-
 	gaim_debug_info("MaYuan","msn_get_contact_list()...\n");
 	contact->soapconn->login_path = g_strdup(MSN_GET_CONTACT_POST_URL);
-	soap_body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE);
-	soap_head = g_strdup_printf(
-					"POST %s HTTP/1.1\r\n"
-					"SOAPAction: http://www.msn.com/webservices/AddressBook/FindMembership\r\n"
-					"Content-Type:text/xml; charset=utf-8\r\n"
-					"Cookie: MSPAuth=%s\r\n"
-					"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
-					"Accept: text/*\r\n"
-					"Host: %s\r\n"
-					"Content-Length: %d\r\n"
-					"Connection: Keep-Alive\r\n"
-					"Cache-Control: no-cache\r\n\r\n",
-					contact->soapconn->login_path,
-					contact->session->passport_info.mspauth,
-					contact->soapconn->login_host,
-					strlen(soap_body)
-					);
-	request_str = g_strdup_printf("%s%s", soap_head,soap_body);
-	g_free(soap_head);
-	g_free(soap_body);
-
-//	gaim_debug_info("MaYuan","send to contact server{%s}\n",request_str);
-	msn_soap_write(contact->soapconn,request_str,msn_contact_written_cb);
+	contact->soapconn->soap_action = g_strdup(MSN_GET_CONTACT_SOAP_ACTION);
+	msn_soap_post(contact->soapconn,MSN_GET_CONTACT_TEMPLATE,msn_contact_written_cb);
 }
 
-msn_add_contact()
+static void
+msn_parse_addressbook(MsnContact * contact)
 {
-}
+	MsnSession * session;
+	xmlnode * node,*body,*response,*result;
+	xmlnode *groups,*group,*groupname,*groupId,*groupInfo;
+	xmlnode	*contacts,*contactNode,*contactId,*contactInfo,*contactType,*passportName,*displayName,*groupIds,*guid;
+	xmlnode *ab;
+
+	session = contact->session;
+	gaim_debug_misc("xml","parse addressbook:{%s}\nsize:%d\n",contact->soapconn->body,contact->soapconn->body_len);
+	node = 	xmlnode_from_str(contact->soapconn->body, contact->soapconn->body_len);
+
+	if(node == NULL){
+		gaim_debug_misc("xml","parse from str err!\n");
+		return;
+	}
+	gaim_debug_misc("xml","node{%p},name:%s,child:%s,last:%s\n",node,node->name,node->child->name,node->lastchild->name);
+	body = xmlnode_get_child(node,"Body");
+	gaim_debug_misc("xml","body{%p},name:%s\n",body,body->name);
+	response = xmlnode_get_child(body,"ABFindAllResponse");
+	gaim_debug_misc("xml","response{%p},name:%s\n",response,response->name);
+	result =xmlnode_get_child(response,"ABFindAllResult");
+	gaim_debug_misc("xml","result{%p},name:%s\n",result,result->name);
+	groups =xmlnode_get_child(result,"groups");
+	for(group = xmlnode_get_child(groups, "Group"); group;
+					group = xmlnode_get_next_twin(group)){
+			char * name,*group_id;
+			groupId = xmlnode_get_child(group,"groupId");
+			group_id = xmlnode_get_data(groupId);
+			groupInfo = xmlnode_get_child(group,"groupInfo");
+			groupname = xmlnode_get_child(groupInfo,"name");
+			name = xmlnode_get_data(groupname);
+
+			msn_group_new(session->userlist, group_id, name);
+
+			if (group_id == NULL)
+					/* Group of ungroupped buddies */
+					continue;
+
+			if ((gaim_find_group(name)) == NULL){
+					GaimGroup *g = gaim_group_new(name);
+					gaim_blist_add_group(g, NULL);
+			}
+
+			gaim_debug_misc("group","name:%s,Id:{%s}\n",name,group_id);
+	}
 
-msn_delete_contact()
-{
+	contacts =xmlnode_get_child(result,"contacts");
+	for(contactNode = xmlnode_get_child(contacts, "Contact"); contactNode;
+				contactNode = xmlnode_get_next_twin(contactNode)){
+		MsnUser *user;
+		char *passport,*Name,*uid,*type;
+
+		contactId= xmlnode_get_child(contactNode,"contactId");
+		uid = xmlnode_get_data(contactId);
+
+		contactInfo = xmlnode_get_child(contactNode,"contactInfo");
+		contactType = xmlnode_get_child(contactInfo,"contactType");
+		type = xmlnode_get_data(contactType);
+
+		passportName = xmlnode_get_child(contactInfo,"passportName");
+		passport = xmlnode_get_data(passportName);
+
+		displayName = xmlnode_get_child(contactInfo,"displayName");
+		Name =xmlnode_get_data(displayName);
+
+		gaim_debug_misc("contact","name:%s,Id:{%s},display:{%s}\n",
+						passport,
+						xmlnode_get_data(contactId),
+						Name);
+
+		user = msn_userlist_find_user(session->userlist, passport);
+		if (user == NULL){
+			user = msn_user_new(session->userlist, passport, Name);
+			msn_userlist_add_user(session->userlist, user);
+		}
+		msn_user_set_uid(user,uid);
+		msn_user_set_type(user,msn_get_user_type(type));
+
+		groupIds = xmlnode_get_child(contactInfo,"groupIds");
+		if(groupIds){
+			for(guid = xmlnode_get_child(groupIds, "guid");guid;
+							guid = xmlnode_get_next_twin(guid)){
+				char * group_id;
+
+				group_id = xmlnode_get_data(guid);
+				msn_user_add_group_id(user,group_id);
+				gaim_debug_misc("contact","guid:%s\n",group_id);
+			}
+		}else{
+			gaim_debug_misc("contact","guid is NULL\n");
+		}
+	}
+
+	ab =xmlnode_get_child(result,"ab");
+
+	xmlnode_free(node);
+	msn_soap_free_read_buf(contact->soapconn);
+
+	dump_adl_cmd(session);
+	msn_session_finish_login(session);
 }
 
-msn_block_contact()
+static void
+msn_get_address_cb(gpointer data, gint source, GaimInputCondition cond)
 {
+	MsnSoapConn * soapconn = data;	
+	MsnContact *contact;
+	MsnSession *session;
+
+	contact = soapconn->parent;
+	g_return_if_fail(contact != NULL);
+	session = soapconn->session;
+	g_return_if_fail(session != NULL);
+
+//	gaim_debug_misc("msn", "soap contact server Reply: {%s}\n", soapconn->read_buf);
+	msn_parse_addressbook(contact);
+}
+
+/**/
+static void
+msn_address_written_cb(gpointer data, gint source, GaimInputCondition cond)
+{
+	MsnSoapConn * soapconn = data;	
+
+	gaim_debug_info("MaYuan","finish contact written\n");
+	soapconn->read_cb = msn_get_address_cb;
+	msn_soap_read_cb(data,source,cond);
 }
 
-msn_unblock_contact()
+/*get the address book*/
+void
+msn_get_address_book(MsnContact *contact)
 {
+	gaim_debug_info("MaYuan","msn_get_address_book()...\n");
+	/*build SOAP and POST it*/
+	contact->soapconn->login_path = g_strdup(MSN_GET_ADDRESS_POST_URL);
+	contact->soapconn->soap_action = g_strdup(MSN_GET_ADDRESS_SOAP_ACTION);
+	msn_soap_post(contact->soapconn,MSN_GET_ADDRESS_TEMPLATE,msn_address_written_cb);
+}
+
+void
+msn_add_contact(MsnContact *contact)
+{
+
 }
 
-msn_get_gleams()
+void
+msn_delete_contact(MsnContact *contact)
+{	
+
+}
+
+void
+msn_block_contact(MsnContact *contact)
+{	
+
+}
+
+void
+msn_unblock_contact(MsnContact *contact)
+{	
+
+}
+
+void
+msn_get_gleams(MsnContact *contact)
 {
+
 }
 
 void
--- a/src/protocols/msn/contact.h	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/contact.h	Mon Jul 17 12:22:37 2006 +0000
@@ -28,6 +28,7 @@
 #define MSN_CONTACT_SERVER	"contacts.msn.com"
 
 #define MSN_GET_CONTACT_POST_URL	"/abservice/SharingService.asmx"
+#define MSN_GET_CONTACT_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership"
 #define MSN_GET_CONTACT_TEMPLATE	"<?xml version='1.0' encoding='utf-8'?>"\
 "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
 	"<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
@@ -55,7 +56,9 @@
 	"</soap:Body>"\
 "</soap:Envelope>"
 
-#define MSN_ADDRESS_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+#define MSN_GET_ADDRESS_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABFindAll"
+#define MSN_GET_ADDRESS_POST_URL	"/abservice/abservice.asmx"
+#define MSN_GET_ADDRESS_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
 "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
 	"<soap:Header>"\
 		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
@@ -97,6 +100,25 @@
 	"</soap:Body>"\
 "</soap:Envelope>"
 
+#define MSN_CONTACT_ADD_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactAdd"
+#define MSN_CONTACT_XML	"<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\"><contactInfo><contactType>LivePending</contactType><passportName>%s</passportName><isMessengerUser>true</isMessengerUser></contactInfo></Contact>"
+
+#define MSN_ADD_CONTACT_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>ContactSave</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><contacts>%s</contacts><options><EnableAllowListManagement>true</EnableAllowListManagement></options></ABContactAdd></soap:Body></soap:Envelope>"
+
+#define MSN_CONTACT_DEL_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABContactDelete"
+#define MSN_CONTACTS_DEL		"<Contact><contactId>5e8a2e64-c271-443f-ac86-2429f3ffd18a</contactId></Contact>"
+#define MSN_DEL_CONTACT_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>Timer</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><contacts>%s</contacts></ABContactDelete></soap:Body></soap:Envelope>"
+
+#define MSN_MEMBER_TEMPLATE		"<Member xsi:type=\"PassportMember\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><Type>Passport</Type><State>Accepted</State><PassportName>%s</PassportName></Member>"
+
+/*block means add contact to block list*/
+#define MSN_CONTACT_BLOCK_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/AddMember"
+#define MSN_BLOCK_CONTACT_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>BlockUnblock</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><AddMember xmlns=\"http://www.msn.com/webservices/AddressBook\"><serviceHandle><Id>0</Id><Type>Messenger</Type><ForeignId></ForeignId></serviceHandle><memberships><Membership><MemberRole>Block</MemberRole><Members>%s</Members></Membership></memberships></AddMember></soap:Body></soap:Envelope>"
+
+/*unblock means delete contact to block list*/
+#define MSN_CONTACT_UNBLOCK_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/DeleteMember"
+#define MSN_UNBLOCK_CONTACT_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>BlockUnblock</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><DeleteMember xmlns=\"http://www.msn.com/webservices/AddressBook\"><serviceHandle><Id>0</Id><Type>Messenger</Type><ForeignId></ForeignId></serviceHandle><memberships><Membership><MemberRole>Block</MemberRole><Members>%s</Members></Membership></memberships></DeleteMember></soap:Body></soap:Envelope>"
+
 typedef struct _MsnContact MsnContact;
 
 struct _MsnContact
@@ -108,11 +130,11 @@
 
 /*function prototype*/
 MsnContact * msn_contact_new(MsnSession *session);
-void msn_get_contact_list(MsnContact * contact);
-void msn_contact_connect(MsnContact *contact);
+void msn_contact_destroy(MsnContact *contact);
 
-void msn_contact_destroy(MsnContact *contact);
+void msn_contact_connect(MsnContact *contact);
 void msn_get_contact_list(MsnContact * contact);
+void msn_get_address_book(MsnContact *contact);
 
 #endif/* _MSN_CMDPROC_H_*/
 
--- a/src/protocols/msn/dialog.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/dialog.c	Mon Jul 17 12:22:37 2006 +0000
@@ -93,16 +93,13 @@
 						  gaim_account_get_username(account),
 						  gaim_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?"),
--- a/src/protocols/msn/group.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/group.c	Mon Jul 17 12:22:37 2006 +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,7 +73,7 @@
 	group->name = g_strdup(name);
 }
 
-int
+char*
 msn_group_get_id(const MsnGroup *group)
 {
 	g_return_val_if_fail(group != NULL, -1);
@@ -87,3 +88,4 @@
 
 	return group->name;
 }
+
--- a/src/protocols/msn/group.h	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/group.h	Mon Jul 17 12:22:37 2006 +0000
@@ -30,8 +30,15 @@
 
 #include "session.h"
 #include "user.h"
+#include "soap.h"
+#include "userlist.h"
 
-#include "userlist.h"
+#define MSN_ADD_GROUPS	"<GroupInfo><name>test111</name><groupType>C8529CE2-6EAD-434d-881F-341E17DB3FF8</groupType><fMessenger>false</fMessenger><annotations><Annotation><Name>MSN.IM.Display</Name><Value>1</Value></Annotation></annotations></GroupInfo>"
+
+#define MSN_ADD_GROUP_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>GroupSave</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABGroupAdd xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><groupAddOptions><fRenameOnMsgrConflict>false</fRenameOnMsgrConflict></groupAddOptions><groupInfo>%s</groupInfo></ABGroupAdd></soap:Body></soap:Envelope>"
+
+#define MSN_GROUP_IDS	"<guid>9e57e654-59f0-44d1-aedc-0a7500b7e51f</guid>"
+#define MSN_DELETE_GROUP_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"><soap:Header><ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId><IsMigration>false</IsMigration><PartnerScenario>Timer</PartnerScenario></ABApplicationHeader><ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\"><ManagedGroupRequest>false</ManagedGroupRequest></ABAuthHeader></soap:Header><soap:Body><ABGroupDelete xmlns=\"http://www.msn.com/webservices/AddressBook\"><abId>00000000-0000-0000-0000-000000000000</abId><groupFilter><groupIds>%s</groupIds></groupFilter></ABGroupDelete></soap:Body></soap:Envelope>"
 
 /**
  * A group.
@@ -39,8 +46,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 +66,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 +81,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 +98,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.
--- a/src/protocols/msn/msn-utils.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/msn-utils.c	Mon Jul 17 12:22:37 2006 +0000
@@ -23,6 +23,7 @@
  */
 #include "msn.h"
 #include "msn-utils.h"
+//#include <openssl/md5.h>
 
 void
 msn_parse_format(const char *mime, char **pre_ret, char **post_ret)
@@ -362,3 +363,122 @@
 	*ret_port = port;
 }
 
+/*check the edian of system*/
+int 
+isBigEndian(void)
+{
+		short int word = 0x0100;
+		char *byte = (char *)&word;
+
+		return(byte[0]);
+}
+
+/*swap utility*/
+unsigned int 
+swapInt(unsigned int dw)
+{
+		unsigned int tmp;
+		tmp =  (dw & 0x000000FF);
+		tmp = ((dw & 0x0000FF00) >> 0x08) | (tmp << 0x08);
+		tmp = ((dw & 0x00FF0000) >> 0x10) | (tmp << 0x08);
+		tmp = ((dw & 0xFF000000) >> 0x18) | (tmp << 0x08);
+		return(tmp);
+}
+
+/*
+ * handle MSN Chanllege computation
+ *This algorithm reference with http://msnpiki.msnfanatic.com/index.php/MSNP11:Challenges
+ */
+#define BUFSIZE	256
+void 
+msn_handle_chl(char *input, char *output)
+{
+		GaimCipher *cipher;
+		GaimCipherContext *context;
+		char *productKey = MSNP13_WLM_PRODUCT_KEY,
+			 *productID  = MSNP13_WLM_PRODUCT_ID,
+			 *hexChars   = "0123456789abcdef",
+			 buf[BUFSIZE];
+		unsigned char md5Hash[16], *newHash;
+		unsigned int *md5Parts, *chlStringParts, newHashParts[5];
+
+		long long nHigh=0, nLow=0;
+
+		int i, bigEndian;
+
+		/* Determine our endianess */
+		bigEndian = isBigEndian();
+
+		/* Create the MD5 hash by using Gaim MD5 algorithm*/
+		cipher = gaim_ciphers_find_cipher("md5");
+		context = gaim_cipher_context_new(cipher, NULL);
+
+		gaim_cipher_context_append(context, (const guchar *)input,
+						strlen(input));
+		gaim_cipher_context_append(context, (const guchar *)productKey,
+						strlen(productKey));
+		gaim_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL);
+		gaim_cipher_context_destroy(context);
+
+		/* Split it into four integers */
+		md5Parts = (unsigned int *)md5Hash;
+		for(i=0; i<4; i++){  
+				/* check for endianess */
+				if(bigEndian)
+						md5Parts[i] = swapInt(md5Parts[i]);
+
+				/* & each integer with 0x7FFFFFFF          */
+				/* and save one unmodified array for later */
+				newHashParts[i] = md5Parts[i];
+				md5Parts[i] &= 0x7FFFFFFF;
+		}
+
+		/* make a new string and pad with '0' */
+		snprintf(buf, BUFSIZE-5, "%s%s", input, productID);
+		i = strlen(buf);
+		memset(&buf[i], '0', 8 - (i % 8));
+		buf[i + (8 - (i % 8))]='\0';
+
+		/* split into integers */
+		chlStringParts = (unsigned int *)buf;
+
+		/* this is magic */
+		for (i=0; i<(strlen(buf)/4)-1; i+=2){
+				long long temp;
+
+				if(bigEndian){
+						chlStringParts[i]   = swapInt(chlStringParts[i]);
+						chlStringParts[i+1] = swapInt(chlStringParts[i+1]);
+				}
+
+				temp=(md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF;
+				nHigh=(md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF;
+				nLow=nLow + nHigh + temp;
+		}
+		nHigh=(nHigh+md5Parts[1]) % 0x7FFFFFFF;
+		nLow=(nLow+md5Parts[3]) % 0x7FFFFFFF;
+
+		newHashParts[0]^=nHigh;
+		newHashParts[1]^=nLow;
+		newHashParts[2]^=nHigh;
+		newHashParts[3]^=nLow;
+
+		/* swap more bytes if big endian */
+		for(i=0; i<4 && bigEndian; i++)
+				newHashParts[i] = swapInt(newHashParts[i]); 
+
+		/* make a string of the parts */
+		newHash = (unsigned char *)newHashParts;
+
+		/* convert to hexadecimal */
+		for (i=0; i<16; i++)
+		{
+				output[i*2]=hexChars[(newHash[i]>>4)&0xF];
+				output[(i*2)+1]=hexChars[newHash[i]&0xF];
+		}
+
+		output[32]='\0';
+
+//		gaim_debug_info("MaYuan","chl output{%s}\n",output);
+}
+
--- a/src/protocols/msn/msn-utils.h	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/msn-utils.h	Mon Jul 17 12:22:37 2006 +0000
@@ -47,5 +47,9 @@
 void msn_import_html(const char *html, char **attributes, char **message);
 
 void msn_parse_socket(const char *str, char **ret_host, int *ret_port);
+void msn_handle_chl(char *input, char *output);
+int isBigEndian(void);
+unsigned int swapInt(unsigned int dw);
+
 
 #endif /* _MSN_UTILS_H_ */
--- a/src/protocols/msn/msn.h	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/msn.h	Mon Jul 17 12:22:37 2006 +0000
@@ -66,6 +66,7 @@
 #define WLM_SERVER			"muser.messenger.hotmail.com"
 #define WLM_PORT			1863
 #define WLM_PROT_VER		13
+#define WLM_MAX_PROTOCOL	14
 #define WLM_MIN_PROTOCOL	13
 
 #define MSN_TYPING_RECV_TIMEOUT 6
--- a/src/protocols/msn/nexus.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/nexus.c	Mon Jul 17 12:22:37 2006 +0000
@@ -37,10 +37,9 @@
 
 	nexus = g_new0(MsnNexus, 1);
 	nexus->session = session;
-	nexus->soapconn = msn_soap_new(session);
-	nexus->soapconn->parent = nexus;
 	/*we must use SSL connection to do Windows Live ID authentication*/
-	nexus->soapconn->ssl_conn = 1;
+	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);
 
--- a/src/protocols/msn/notification.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/notification.c	Mon Jul 17 12:22:37 2006 +0000
@@ -102,9 +102,11 @@
 	account = session->account;
 
 	/* Allocate an array for CVR0, NULL, and all the versions */
-	a = c = g_new0(char *, session->protocol_ver - WLM_MIN_PROTOCOL + 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 >= WLM_MIN_PROTOCOL; 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");
@@ -163,24 +165,16 @@
 	account = session->account;
 	gc = gaim_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 +208,6 @@
 	GaimAccount *account;
 
 	account = cmdproc->session->account;
-
 	msn_cmdproc_send(cmdproc, "USR", "TWN I %s",
 					 gaim_account_get_username(account));
 }
@@ -303,17 +296,15 @@
 
 	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; i++){
+//		gaim_debug_info("MaYuan","%s\,proto_str:%s\n",cmd->params[i],proto_str);
+		if (!strcmp(cmd->params[i], proto_str))	{
 			protocol_supported = TRUE;
 			break;
 		}
 	}
 
-	if (!protocol_supported)
-	{
+	if (!protocol_supported){
 		msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL,
 							  NULL);
 		return;
@@ -324,7 +315,8 @@
 	 * Notice :CVR String discriminate!
 	 */
 	msn_cmdproc_send(cmdproc, "CVR",
-					 "0x0409 winnt 5.1 i386 MSG80BETA 8.0.0689 msmsgs %s",
+//					 "0x0409 winnt 5.1 i386 MSG80BETA 8.0.0689 msmsgs %s",
+					"0x0804 winnt 5.1 i386 MSNMSGR 8.0.0792 msmsgs %s",
 					 gaim_account_get_username(account));
 }
 
@@ -405,18 +397,12 @@
 {
 	MsnTransaction *trans;
 	char buf[33];
-	const char *challenge_resp;
-	GaimCipher *cipher;
-	GaimCipherContext *context;
-	guchar digest[16];
-	int i;
 
+#if 0
 	cipher = gaim_ciphers_find_cipher("md5");
 	context = gaim_cipher_context_new(cipher, NULL);
-
 	gaim_cipher_context_append(context, (const guchar *)cmd->params[1],
 							   strlen(cmd->params[1]));
-
 	challenge_resp = MSNP13_WLM_PRODUCT_KEY;
 
 	gaim_cipher_context_append(context, (const guchar *)challenge_resp,
@@ -424,9 +410,13 @@
 	gaim_cipher_context_digest(context, sizeof(digest), digest, NULL);
 	gaim_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]);
-
+	}
+#else
+	msn_handle_chl(cmd->params[1], buf);
+#endif
+	gaim_debug_info("MaYuan","<<challenge:{%s}:{%s}\n",cmd->params[1],buf);
 	trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP13_WLM_PRODUCT_ID);
 
 	msn_transaction_set_payload(trans, buf, 32);
@@ -437,6 +427,102 @@
 /**************************************************************************
  * Buddy Lists
  **************************************************************************/
+void
+dump_adl_cmd(MsnSession *session)
+{
+	MsnCmdProc *cmdproc;
+	MsnTransaction *trans;
+	MsnUserList *userlist;
+	MsnUser *user;
+	GList *l;
+	xmlnode *adl_node,*d_node,*c_node;
+	char **tokens;
+	char *email,*domain;
+	char * payload,*attr;
+	char *list_op,*type;
+	int payload_len;
+
+	cmdproc = session->notification->cmdproc;
+	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;
+
+		gaim_debug_info("MaYuan","passport:%s\n",user->passport);
+		tokens = g_strsplit(user->passport, "@", 2);
+		email = tokens[0];
+		domain = tokens[1];
+
+		/*find a domain node*/
+		for(d_node = xmlnode_get_child(adl_node,"d"); d_node; d_node = xmlnode_get_next_twin(d_node)){
+			gaim_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){
+			gaim_debug_info("MaYuan","get No d_node\n");
+			d_node = xmlnode_new("d");
+			xmlnode_set_attrib(d_node,"n",domain);
+			xmlnode_insert_child(adl_node,d_node);
+		}
+
+		/*create contact node*/
+		c_node = xmlnode_new("c");
+		xmlnode_set_attrib(c_node,"n",email);
+
+		list_op = g_strdup_printf("%d",user->list_op);
+		gaim_debug_info("MaYuan","list_op:%d\n",user->list_op);
+		xmlnode_set_attrib(c_node,"l",list_op);
+#if 1
+		type = g_strdup_printf("%d",user->type);
+		xmlnode_set_attrib(c_node,"t",type);
+#else
+		xmlnode_set_attrib(c_node,"t","1");
+#endif
+		xmlnode_insert_child(d_node, c_node);
+
+		g_free(list_op);
+		g_free(type);
+	}
+
+	payload = xmlnode_to_str(adl_node,payload_len);
+
+	gaim_debug_info("MaYuan","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);
+}
+
+static void
+adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+	
+}
+
+static void
+rml_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+	MsnTransaction *trans;
+	char * payload;
+
+	trans = msn_transaction_new(cmdproc, "RML","");
+
+	msn_transaction_set_payload(trans, payload, strlen(payload));
+
+	msn_cmdproc_send_trans(cmdproc, trans);
+}
+
 static void
 add_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
@@ -456,13 +542,12 @@
 
 	user = msn_userlist_find_user(session->userlist, passport);
 
-	if (user == NULL)
-	{
+	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);
 	}
-	else
-		msn_user_set_friendly_name(user, friendly);
 
 	list_id = msn_get_list_id(list);
 
@@ -554,10 +639,6 @@
 	g_strfreev(params);
 }
 
-static void adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
-{
-}
-
 static void
 adg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
@@ -634,8 +715,7 @@
 
 	msn_user_set_friendly_name(user, friendly);
 
-	if (session->protocol_ver >= 9 && cmd->param_count == 6)
-	{
+	if (session->protocol_ver >= 9 && cmd->param_count == 6){
 		msnobj = msn_object_new_from_string(gaim_url_decode(cmd->params[5]));
 		msn_user_set_object(user, msnobj);
 	}
@@ -684,16 +764,12 @@
 
 	msn_user_set_friendly_name(user, friendly);
 
-	if (session->protocol_ver >= 9)
-	{
-		if (cmd->param_count == 5)
-		{
+	if (session->protocol_ver >= 9){
+		if (cmd->param_count == 5){
 			msnobj =
 				msn_object_new_from_string(gaim_url_decode(cmd->params[4]));
 			msn_user_set_object(user, msnobj);
-		}
-		else
-		{
+		}else{
 			msn_user_set_object(user, NULL);
 		}
 	}
@@ -1195,7 +1271,6 @@
 	/*starting retrieve the contact list*/
 	session->contact = msn_contact_new(session);
 	msn_contact_connect(session->contact);
-
 }
 
 static void
@@ -1252,6 +1327,12 @@
 }
 
 static void
+initial_mdata_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+{
+	gaim_debug_info("MaYuan","mdata...{%s} \n",msg->body);
+}
+
+static void
 email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
 {
 	MsnSession *session;
@@ -1458,6 +1539,9 @@
 						   "text/x-msmsgsprofile",
 						   profile_msg);
 	msn_table_add_msg_type(cbs_table,
+							"text/x-msmsgsinitialmdatanotification",
+							initial_mdata_msg);	
+	msn_table_add_msg_type(cbs_table,
 						   "text/x-msmsgsinitialemailnotification",
 						   initial_email_msg);
 	msn_table_add_msg_type(cbs_table,
--- a/src/protocols/msn/notification.h	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/notification.h	Mon Jul 17 12:22:37 2006 +0000
@@ -63,6 +63,7 @@
 gboolean msn_notification_connect(MsnNotification *notification,
 							  const char *host, int port);
 void msn_notification_disconnect(MsnNotification *notification);
+void dump_adl_cmd(MsnSession *session);
 
 /**
  * Closes a notification.
--- a/src/protocols/msn/object.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/object.c	Mon Jul 17 12:22:37 2006 +0000
@@ -283,8 +283,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))
@@ -333,3 +332,4 @@
 
 	return NULL;
 }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/msn/oim.c	Mon Jul 17 12:22:37 2006 +0000
@@ -0,0 +1,103 @@
+/**
+ * @file oim.c 
+ * 	get and send MSN offline Instant Message via SOAP request
+ *	Author
+ * 		MaYuan<mayuan2006@gmail.com>
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "msn.h"
+#include "soap.h"
+#include "oim.h"
+
+/*new a OIM object*/
+MsnOim *
+msn_oim_new(MsnSession *session)
+{
+	MsnOim *oim;
+
+	oim = g_new0(MsnOim, 1);
+	oim->session = session;
+	oim->retrieveconn = msn_soap_new(session,oim,1);
+	oim->sendconn = msn_soap_new(session,oim,1);
+
+	return oim;
+}
+
+/*destroy the oim object*/
+void
+msn_oim_destroy(MsnOim *oim)
+{
+	msn_soap_destroy(oim->retrieveconn);
+	msn_soap_destroy(oim->sendconn);
+	g_free(oim);
+}
+
+/*oim SOAP server login error*/
+static void
+msn_oim_login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data)
+{
+	MsnSoapConn *soapconn = data;
+	MsnSession *session;
+
+	session = soapconn->session;
+	g_return_if_fail(session != NULL);
+
+	msn_session_set_error(session, MSN_ERROR_SERV_DOWN, _("Unable to connect to OIM server"));
+}
+
+/*msn oim SOAP server connect process*/
+static void
+msn_oim_login_connect_cb(gpointer data, GaimSslConnection *gsc,
+				 GaimInputCondition cond)
+{
+	MsnSoapConn *soapconn = data;
+	MsnSession * session;
+	MsnOim *oim;
+
+	oim = soapconn->parent;
+	g_return_if_fail(oim != NULL);
+
+	session = oim->session;
+	g_return_if_fail(session != NULL);
+}
+
+void msn_oim_send_msg(MsnOim *oim,char * msg)
+{
+	if(msn_soap_connected(oim->sendconn) == -1){
+		msn_soap_init(oim->sendconn,MSN_OIM_SEND_HOST,1,
+					msn_oim_login_connect_cb,
+					msn_oim_login_error_cb);
+	}
+	
+}
+
+/*msn oim server connect*/
+void
+msn_oim_connect(MsnOim *oim)
+{
+	gaim_debug_info("MaYuan","msn_oim_connect...\n");
+
+	msn_soap_init(oim->retrieveconn,MSN_OIM_RETRIEVE_HOST,1,
+					msn_oim_login_connect_cb,
+					msn_oim_login_error_cb);
+}
+
+/*endof oim.c*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/msn/oim.h	Mon Jul 17 12:22:37 2006 +0000
@@ -0,0 +1,103 @@
+/**
+ * @file oim.h			Header file for oim.c
+ *	Author
+ * 		MaYuan<mayuan2006@gmail.com>
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _MSN_OIM_H_
+#define _MSN_OIM_H_
+
+#define MSN_OIM_RETRIEVE_HOST	"rsi.hotmail.com"
+#define MSN_OIM_RETRIEVE__URL	"/rsi/rsi.asmx"
+#define MSN_OIM_GET_SOAP_ACTION	"http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMessage"
+#define MSN_OIM_DEL_SOAP_ACTION	"http://www.hotmail.msn.com/ws/2004/09/oim/rsi/DeleteMessages"
+
+#define MSN_OIM_GET_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+	"<soap:Header>"\
+		"<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+			"<t>%s</t>"\
+			"<p>%s</p>"\
+		"</PassportCookie>"\
+	"</soap:Header>"\
+	"<soap:Body>"\
+		"<GetMessage xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+			"<messageId>%s</messageId>"\
+			"<alsoMarkAsRead>false</alsoMarkAsRead>"\
+		"</GetMessage>"\
+	"</soap:Body>"\
+"</soap:Envelope>"
+
+#define MSN_OIM_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+	"<soap:Header>"\
+		"<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+			"<t>%s</t>"\
+			" <p>%s</p>"\
+		"</PassportCookie>"\
+	"</soap:Header>"\
+	"<soap:Body>"\
+		"<DeleteMessages xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+			"<messageIds>"\
+				"<messageId>%s</messageId>"\
+			"</messageIds>"\
+		"</DeleteMessages>"\
+	"</soap:Body>"\
+"</soap:Envelope>"
+
+#define MSN_OIM_SEND_HOST	"ows.messenger.msn.com"
+#define MSN_OIM_SEND_URL	"/OimWS/oim.asmx"
+#define MSN_OIM_SEND_SOAP_ACTION	"http://messenger.msn.com/ws/2004/09/oim/Store"
+#define MSN_OIM_SEND_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+	"<soap:Header>"\
+		"<From memberName=\"%s\" friendlyName=\"%s\" xml:lang=\"en-US\" proxy=\"MSNMSGR\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\" msnpVer=\"MSNP13\" buildVer=\"8.0.0689\"/>"\
+		"<To memberName=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\
+		"<Ticket passport=\"%s\" appid=\"%s\" lockkey=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\
+		"<Sequence xmlns=\"http://schemas.xmlsoap.org/ws/2003/03/rm\">"\
+			"<Identifier xmlns=\"http://schemas.xmlsoap.org/ws/2002/07/utility\">http://messenger.msn.com</Identifier>"\
+			"<MessageNumber>%s</MessageNumber>"\
+		"</Sequence>"\
+	"</soap:Header>"\
+	"<soap:Body>"\
+		"<MessageType xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">text</MessageType>"\
+		"<Content xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">%s</Content>"\
+	"</soap:Body>"\
+"</soap:Envelope>"
+
+typedef struct _MsnOim MsnOim;
+
+struct _MsnOim
+{
+	MsnSession *session;
+
+	MsnSoapConn *retrieveconn;
+
+	MsnSoapConn *sendconn;
+	gint	LockKeyChallenge;
+};
+
+/*function prototype*/
+MsnOim * msn_oim_new(MsnSession *session);
+void msn_oim_destroy(MsnOim *oim);
+
+#endif/* _MSN_OIM_H_*/
+/*endof oim.h*/
--- a/src/protocols/msn/session.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/session.c	Mon Jul 17 12:22:37 2006 +0000
@@ -252,18 +252,15 @@
 
 					remote_user = msn_userlist_find_user(session->userlist, b->name);
 
-					if ((remote_user != NULL) && (remote_user->list_op & MSN_LIST_FL_OP))
-					{
+					if ((remote_user != NULL) && (remote_user->list_op & MSN_LIST_FL_OP)){
 						int group_id;
 						GList *l;
 
 						group_id = msn_userlist_find_group_id(remote_user->userlist,
 								group_name);
 
-						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){
+							if (group_id == GPOINTER_TO_INT(l->data)){
 								found = TRUE;
 								break;
 							}
@@ -271,8 +268,7 @@
 
 					}
 
-					if (!found)
-					{
+					if (!found){
 						/* The user was not on the server list or not in that group
 						 * on the server list */
 						msn_show_sync_issue(session, b->name, group_name);
@@ -407,3 +403,4 @@
 	/* Sync users */
 	msn_session_sync_users(session);
 }
+
--- a/src/protocols/msn/soap.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/soap.c	Mon Jul 17 12:22:37 2006 +0000
@@ -26,14 +26,19 @@
 #include "msn.h"
 #include "soap.h"
 
+//msn_soap_new(MsnSession *session,gpointer data,int sslconn)
 /*new a soap connection*/
 MsnSoapConn *
-msn_soap_new(MsnSession *session)
+msn_soap_new(MsnSession *session,gpointer data,int sslconn)
 {
 	MsnSoapConn *soapconn;
 
 	soapconn = g_new0(MsnSoapConn, 1);
 	soapconn->session = session;
+	soapconn->parent = data;
+	soapconn->ssl_conn = sslconn;
+
+	soapconn->gsc = NULL;
 	soapconn->input_handler = -1;
 	soapconn->output_handler = -1;
 	return soapconn;
@@ -118,6 +123,18 @@
 	g_free(soapconn);
 }
 
+/*check the soap is connected?
+ * if connected return 0
+ */
+int
+msn_soap_connected(MsnSoapConn *soapconn)
+{
+	if(soapconn->ssl_conn){
+		return (soapconn->gsc == NULL? -1 : 0);
+	}
+	return(soapconn->fd>0? 0 : -1);
+}
+
 /*read and append the content to the buffer*/
 static gssize
 msn_soap_read(MsnSoapConn *soapconn)
@@ -154,7 +171,7 @@
 	char * body_start,*body_len;
 	char *length_start,*length_end;
 
-	gaim_debug_misc("MaYuan", "soap read cb\n");
+//	gaim_debug_misc("MaYuan", "soap read cb\n");
 	session = soapconn->session;
 	g_return_if_fail(session != NULL);
 
@@ -207,6 +224,12 @@
 
 	g_free(body_len);
 
+#if 1
+	/*remove the read handler*/
+	gaim_input_remove(soapconn->input_handler);
+	soapconn->input_handler = -1;
+#endif
+
 	/*call the read callback*/
 	if(soapconn->read_cb != NULL){
 		soapconn->read_cb(soapconn,source,0);
@@ -218,8 +241,8 @@
 	/*remove the read handler*/
 	gaim_input_remove(soapconn->input_handler);
 	soapconn->input_handler = -1;
-	gaim_ssl_close(soapconn->gsc);
-	soapconn->gsc = NULL;
+//	gaim_ssl_close(soapconn->gsc);
+//	soapconn->gsc = NULL;
 #endif
 }
 
@@ -294,9 +317,50 @@
 	soapconn->write_buf = write_buf;
 	soapconn->written_len = 0;
 	soapconn->written_cb = written_cb;
+
+	/*clear the read buffer first*/
 	/*start the write*/
 	soapconn->output_handler = gaim_input_add(soapconn->gsc->fd, GAIM_INPUT_WRITE,
 													msn_soap_write_cb, soapconn);
 	msn_soap_write_cb(soapconn, soapconn->gsc->fd, GAIM_INPUT_WRITE);
 }
 
+/*Post the soap action*/
+void
+msn_soap_post(MsnSoapConn *soapconn,const char * body,GaimInputFunction written_cb)
+{
+	char * soap_head = NULL;
+	char * soap_body = NULL;
+	char * request_str = NULL;
+
+	gaim_debug_info("MaYuan","msn_get_address_book()...\n");
+	soap_body = g_strdup_printf(body);
+	soap_head = g_strdup_printf(
+					"POST %s HTTP/1.1\r\n"
+					"SOAPAction: %s\r\n"
+					"Content-Type:text/xml; charset=utf-8\r\n"
+					"Cookie: MSPAuth=%s\r\n"
+					"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
+					"Accept: text/*\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->soap_action,
+					soapconn->session->passport_info.mspauth,
+					soapconn->login_host,
+					strlen(soap_body)
+					);
+	request_str = g_strdup_printf("%s%s", soap_head,soap_body);
+	g_free(soapconn->login_path);
+	g_free(soapconn->soap_action);
+	g_free(soap_head);
+	g_free(soap_body);
+
+	/*free read buffer*/
+	msn_soap_free_read_buf(soapconn);
+//	gaim_debug_info("MaYuan","send to contact server{%s}\n",request_str);
+	msn_soap_write(soapconn,request_str,written_cb);
+}
+
--- a/src/protocols/msn/soap.h	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/soap.h	Mon Jul 17 12:22:37 2006 +0000
@@ -35,6 +35,7 @@
 
 	char *login_host;
 	char *login_path;
+	char *soap_action;
 
 	/*ssl connection?*/
 	guint	ssl_conn;
@@ -69,7 +70,8 @@
 
 /*Function Prototype*/
 /*new a soap conneciton */
-MsnSoapConn *msn_soap_new(MsnSession *session);
+MsnSoapConn *msn_soap_new(MsnSession *session,gpointer data,int sslconn);
+
 /*destroy */
 void msn_soap_destroy(MsnSoapConn *soapconn);
 
@@ -78,10 +80,15 @@
 
 /*write to soap*/
 void msn_soap_write(MsnSoapConn * soapconn, char *write_buf, GaimInputFunction written_cb);
+void msn_soap_post(MsnSoapConn *soapconn,const char * body,GaimInputFunction written_cb);
+
 void  msn_soap_free_read_buf(MsnSoapConn *soapconn);
 void msn_soap_free_write_buf(MsnSoapConn *soapconn);
 void msn_soap_connect_cb(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond);
 void msn_soap_read_cb(gpointer data, gint source, GaimInputCondition cond);
 
+/*check if the soap connection is connected*/
+int msn_soap_connected(MsnSoapConn *soapconn);
+
 #endif/*_MSN_SOAP_H_*/
 
--- a/src/protocols/msn/user.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/user.c	Mon Jul 17 12:22:37 2006 +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)
 {
@@ -67,6 +69,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);
@@ -144,6 +147,23 @@
 }
 
 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_buddy_icon(MsnUser *user, const char *filename)
 {
 	struct stat st;
@@ -152,20 +172,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){
 		GaimCipherContext *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);
@@ -217,16 +233,15 @@
 		base64 = gaim_base64_encode(digest, sizeof(digest));
 		msn_object_set_sha1c(msnobj, base64);
 		g_free(base64);
-	}
-	else
-	{
+	}else{
 		gaim_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;
 	GaimAccount *account;
@@ -236,9 +251,9 @@
 	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));
+	user->group_ids = g_list_append(user->group_ids,id);
 
 	userlist = user->userlist;
 	account = userlist->session->account;
@@ -248,16 +263,14 @@
 
 	g = gaim_find_group(group_name);
 
-	if ((id == 0) && (g == NULL))
-	{
+	if ((id == 0) && (g == NULL)){
 		g = gaim_group_new(group_name);
 		gaim_blist_add_group(g, NULL);
 	}
 
 	b = gaim_find_buddy_in_group(account, passport, g);
 
-	if (b == NULL)
-	{
+	if (b == NULL){
 		b = gaim_buddy_new(account, passport, NULL);
 
 		gaim_blist_add_buddy(b, NULL, g, NULL);
@@ -267,12 +280,12 @@
 }
 
 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);
 }
 
 void
--- a/src/protocols/msn/user.h	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/user.h	Mon Jul 17 12:22:37 2006 +0000
@@ -45,6 +45,8 @@
 	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.         */
 	gboolean idle;          /**< The idle state of the user.    */
 
@@ -65,6 +67,7 @@
 
 	GHashTable *clientcaps; /**< The client's capabilities.     */
 
+	int type;
 	int list_op;
 };
 
@@ -156,7 +159,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 +167,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 +185,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.
  *
--- a/src/protocols/msn/userlist.c	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/userlist.c	Mon Jul 17 12:22:37 2006 +0000
@@ -119,22 +119,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;
 
@@ -146,9 +146,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);
 	}
 
@@ -199,13 +198,7 @@
 	if (old_group_name)
 		data->old_group_name = g_strdup(old_group_name);
 
-	trans = msn_transaction_new(cmdproc, "ADG", "%s %d",
-								gaim_url_encode(new_group_name),
-								0);
-
-	msn_transaction_set_data(trans, data);
-
-	msn_cmdproc_send_trans(cmdproc, trans);
+	/*TODO:add new group via SOAP action*/
 }
 
 /**************************************************************************
@@ -229,7 +222,7 @@
 
 void
 msn_got_add_user(MsnSession *session, MsnUser *user,
-				 MsnListId list_id, int group_id)
+				 MsnListId list_id, const char * group_id)
 {
 	GaimAccount *account;
 	const char *passport;
@@ -248,25 +241,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){
 		gaim_privacy_permit_add(account, passport, TRUE);
-	}
-	else if (list_id == MSN_LIST_BL)
-	{
+	}else if (list_id == MSN_LIST_BL){
 		gaim_privacy_deny_add(account, passport, TRUE);
-	}
-	else if (list_id == MSN_LIST_RL)
-	{
+	}else if (list_id == MSN_LIST_RL){
 		GaimConnection *gc;
 		GaimConversation *convo;
 
@@ -290,8 +275,7 @@
  			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
@@ -307,7 +291,7 @@
 
 void
 msn_got_rem_user(MsnSession *session, MsnUser *user,
-				 MsnListId list_id, int group_id)
+				 MsnListId list_id, const char * group_id)
 {
 	GaimAccount *account;
 	const char *passport;
@@ -401,22 +385,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. */
 		gaim_privacy_deny_remove(account, passport, TRUE);
 		gaim_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. */
 		gaim_privacy_permit_remove(account, passport, TRUE);
 		gaim_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?
@@ -425,13 +406,12 @@
 		 *       should use the friendly name, instead? --KingAnt
 		 */
 
-		if (!(list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP)))
-		{
+		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;
 }
 
 /**************************************************************************
@@ -461,18 +441,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);
@@ -502,8 +480,7 @@
 
 	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;
 
 		g_return_val_if_fail(user->passport != NULL, NULL);
@@ -528,18 +505,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 (!strcmp(group->id,id))
 			return group;
 	}
 
@@ -565,7 +541,7 @@
 	return NULL;
 }
 
-int
+const char *
 msn_userlist_find_group_id(MsnUserList *userlist, const char *group_name)
 {
 	MsnGroup *group;
@@ -575,24 +551,25 @@
 	if (group != NULL)
 		return msn_group_get_id(group);
 	else
-		return -1;
+		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;
@@ -604,7 +581,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;
 
@@ -622,18 +599,16 @@
 					   const char *who, int list_id, const char *group_name)
 {
 	MsnUser *user;
-	int group_id;
+	char *group_id;
 	const char *list;
 
 	user = msn_userlist_find_user(userlist, who);
-	group_id = -1;
+	group_id = NULL;
 
-	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, there is no such group. */
 			gaim_debug_error("msn", "Group doesn't exist: %s\n", group_name);
 			return;
@@ -641,8 +616,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];
 		gaim_debug_error("msn", "User '%s' is not there: %s\n",
 						 who, list);
@@ -667,13 +641,11 @@
 
 	group_id = -1;
 
-	if (!gaim_email_is_valid(who))
-	{
+	if (!gaim_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);
 			gaim_notify_error(NULL, NULL, str,
 							  _("The screen name specified is invalid."));
@@ -683,12 +655,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 < 0){
 			/* Whoa, we must add that group first. */
 			msn_request_add_group(userlist, who, NULL, group_name);
 			return;
@@ -698,8 +668,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];
 		gaim_debug_error("msn", "User '%s' is already there: %s\n", who, list);
 		return;
@@ -722,8 +691,7 @@
 
 	new_group_id = msn_userlist_find_group_id(userlist, new_group_name);
 
-	if (new_group_id < 0)
-	{
+	if (new_group_id < 0){
 		msn_request_add_group(userlist, who, old_group_name, new_group_name);
 		return;
 	}
@@ -731,3 +699,4 @@
 	msn_userlist_add_buddy(userlist, who, MSN_LIST_FL, new_group_name);
 	msn_userlist_rem_buddy(userlist, who, MSN_LIST_FL, old_group_name);
 }
+
--- a/src/protocols/msn/userlist.h	Sun Jul 09 16:48:25 2006 +0000
+++ b/src/protocols/msn/userlist.h	Mon Jul 17 12:22:37 2006 +0000
@@ -67,9 +67,9 @@
 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);
 
@@ -81,16 +81,16 @@
 								const char *passport);
 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);