changeset 23861:a1acca6ff789

merge of '77e249bc561fc09bc5fe8f9c6f8b573701b5d63d' and 'fca38a4d41e1b8322fa295cbfaa98418b980b2a4'
author Mike Ruprecht <maiku@soc.pidgin.im>
date Sat, 19 Jul 2008 03:10:38 +0000
parents eb8c8a926589 (current diff) 7ff380f97abc (diff)
children 3ffe166a355e
files
diffstat 26 files changed, 165 insertions(+), 145 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/bonjour/bonjour_ft.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/bonjour/bonjour_ft.c	Sat Jul 19 03:10:38 2008 +0000
@@ -300,6 +300,8 @@
 		}
 		if (xf->proxy_connection != NULL)
 			purple_proxy_connect_cancel(xf->proxy_connection);
+		if (xf->proxy_info != NULL)
+			purple_proxy_info_destroy(xf->proxy_info);
 		if (xf->listen_data != NULL)
 			purple_network_listen_cancel(xf->listen_data);
 		g_free(xf->iq_id);
@@ -802,6 +804,8 @@
 	xmlnode *q_node, *tmp_node;
 	BonjourData *bd;
 
+	xf->proxy_connection = NULL;
+
 	if(source < 0) {
 		purple_debug_error("bonjour", "Error connecting via SOCKS5 - %s\n",
 			error_message ? error_message : "(null)");
@@ -815,9 +819,6 @@
 
 	bd = xf->data;
 
-	purple_proxy_info_destroy(xf->proxy_info);
-	xf->proxy_connection = NULL;
-	xf->proxy_info = NULL;
 	/* Here, start the file transfer.*/
 
 	/* Notify Initiator of Connection */
@@ -871,8 +872,6 @@
 		xep_ft_si_reject(xf->data, xf->iq_id, xfer->who, "404", "cancel");
 		/* Cancel the connection */
 		purple_xfer_cancel_local(xfer);
-		/*purple_proxy_info_destroy(xf->proxy_info);
-		xf->proxy_info = NULL;*/
 	}
 }
 
--- a/libpurple/protocols/msn/cmdproc.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/msn/cmdproc.c	Sat Jul 19 03:10:38 2008 +0000
@@ -263,7 +263,7 @@
 	MsnTransaction *trans = NULL;
 
 	if (cmd->trId)
-		trans = msn_history_find(cmdproc->history, cmd->trId);
+		cmd->trans = trans = msn_history_find(cmdproc->history, cmd->trId);
 
 	if (trans != NULL)
 		if (trans->timer) {
@@ -309,8 +309,6 @@
 
 	if (cb == NULL && trans != NULL)
 	{
-		cmd->trans = trans;
-
 		if (trans->callbacks != NULL)
 			cb = g_hash_table_lookup(trans->callbacks, cmd->command);
 	}
--- a/libpurple/protocols/msn/msn.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/msn/msn.c	Sat Jul 19 03:10:38 2008 +0000
@@ -428,14 +428,25 @@
 	gc = (PurpleConnection *) action->context;
 	session = gc->proto_data;
 
-	if (session->passport_info.file == NULL)
-	{
+	/** apparently the correct value is 777, use 750 as a failsafe */ 
+	if (time (NULL) - session->passport_info.mail_timestamp >= 750) {
+		MsnTransaction *trans;
+		MsnCmdProc *cmdproc;
+
+		cmdproc = session->notification->cmdproc;
+
+		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
+		msn_transaction_set_data(trans, GUINT_TO_POINTER (TRUE));
+
+		msn_cmdproc_send_trans(cmdproc, trans);
+
+	} else if (session->passport_info.file != NULL) {
+		purple_notify_uri(gc, session->passport_info.file);
+
+	} else {
 		purple_notify_error(gc, NULL,
 						  _("This Hotmail account may not be active."), NULL);
-		return;
 	}
-
-	purple_notify_uri(gc, session->passport_info.file);
 }
 
 static void
@@ -824,10 +835,6 @@
 static GList *
 msn_actions(PurplePlugin *plugin, gpointer context)
 {
-	PurpleConnection *gc = (PurpleConnection *)context;
-	PurpleAccount *account;
-	const char *user;
-
 	GList *m = NULL;
 	PurplePluginAction *act;
 
@@ -867,17 +874,10 @@
 	m = g_list_append(m, act);
 #endif
 
-	account = purple_connection_get_account(gc);
-	user = msn_normalize(account, purple_account_get_username(account));
-
-	if ((strstr(user, "@hotmail.") != NULL) ||
-		(strstr(user, "@msn.com") != NULL))
-	{
-		m = g_list_append(m, NULL);
-		act = purple_plugin_action_new(_("Open Hotmail Inbox"),
-				msn_show_hotmail_inbox);
-		m = g_list_append(m, act);
-	}
+	m = g_list_append(m, NULL);
+	act = purple_plugin_action_new(_("Open Hotmail Inbox"),
+			msn_show_hotmail_inbox);
+	m = g_list_append(m, act);
 
 	return m;
 }
--- a/libpurple/protocols/msn/notification.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/msn/notification.c	Sat Jul 19 03:10:38 2008 +0000
@@ -918,29 +918,7 @@
 static void
 qng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
-	MsnSession *session;
-	static int count = 0;
-	const char *passport;
-	PurpleAccount *account;
-
-	session = cmdproc->session;
-	account = session->account;
-
-	if (session->passport_info.file == NULL)
-		return;
-
-	passport = purple_normalize(account, purple_account_get_username(account));
-
-	if ((strstr(passport, "@hotmail.") == NULL) &&
-		(strstr(passport, "@live.com") == NULL) &&
-		(strstr(passport, "@msn.com") == NULL))
-		return;
-
-	if (count++ < 26)
-		return;
-
-	count = 0;
-	msn_cmdproc_send(cmdproc, "URL", "%s", "INBOX");
+	/* TODO: Call PNG after the timeout specified. */
 }
 
 
@@ -1273,46 +1251,39 @@
 url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	MsnSession *session;
+	PurpleConnection *gc;
 	PurpleAccount *account;
 	const char *rru;
 	const char *url;
-	PurpleCipher *cipher;
-	PurpleCipherContext *context;
-	guchar digest[16];
+	PurpleCipherContext *cipher;
+	gchar digest[33];
 	FILE *fd;
 	char *buf;
-	char buf2[3];
-	char sendbuf[64];
-	int i;
+
+	gulong tmp_timestamp;
 
 	session = cmdproc->session;
 	account = session->account;
+	gc = account->gc;
 
 	rru = cmd->params[1];
 	url = cmd->params[2];
 
+	session->passport_info.mail_timestamp = time(NULL);
+	tmp_timestamp = session->passport_info.mail_timestamp - session->passport_info.sl;
+
 	buf = g_strdup_printf("%s%lu%s",
 			   session->passport_info.mspauth ? session->passport_info.mspauth : "BOGUS",
-			   time(NULL) - session->passport_info.sl,
-			   purple_connection_get_password(account->gc));
+			   tmp_timestamp,
+			   purple_connection_get_password(gc));
 
-	cipher = purple_ciphers_find_cipher("md5");
-	context = purple_cipher_context_new(cipher, NULL);
-
-	purple_cipher_context_append(context, (const guchar *)buf, strlen(buf));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-	purple_cipher_context_destroy(context);
+	cipher = purple_cipher_context_new_by_name("md5", NULL);
+	purple_cipher_context_append(cipher, (const guchar *)buf, strlen(buf));
+	purple_cipher_context_digest_to_str(cipher, sizeof(digest), digest, NULL);
+	purple_cipher_context_destroy(cipher);
 
 	g_free(buf);
 
-	memset(sendbuf, 0, sizeof(sendbuf));
-
-	for (i = 0; i < 16; i++)
-	{
-		g_snprintf(buf2, sizeof(buf2), "%02x", digest[i]);
-		strcat(sendbuf, buf2);
-	}
-
 	if (session->passport_info.file != NULL)
 	{
 		g_unlink(session->passport_info.file);
@@ -1324,6 +1295,11 @@
 		purple_debug_error("msn",
 						 "Error opening temp passport file: %s\n",
 						 g_strerror(errno));
+		/* The user wanted to check his or her email */
+		if (cmd->trans && cmd->trans->data)
+			/* TODO: This error might be a bit technical... */
+			purple_notify_error(gc, NULL,
+							  _("Error opening temporary passport file."), NULL);
 	}
 	else
 	{
@@ -1355,14 +1331,14 @@
 					session->passport_info.kv);
 		fprintf(fd, "<input type=\"hidden\" name=\"id\" value=\"2\">\n");
 		fprintf(fd, "<input type=\"hidden\" name=\"sl\" value=\"%ld\">\n",
-				time(NULL) - session->passport_info.sl);
+				tmp_timestamp);
 		fprintf(fd, "<input type=\"hidden\" name=\"rru\" value=\"%s\">\n",
 				rru);
 		if (session->passport_info.mspauth != NULL)
 			fprintf(fd, "<input type=\"hidden\" name=\"auth\" value=\"%s\">\n",
 					session->passport_info.mspauth);
 		fprintf(fd, "<input type=\"hidden\" name=\"creds\" value=\"%s\">\n",
-				sendbuf); /* TODO Digest me (huh? -- ChipX86) */
+				digest); /* TODO Digest me (huh? -- ChipX86) */
 		fprintf(fd, "<input type=\"hidden\" name=\"svc\" value=\"mail\">\n");
 		fprintf(fd, "<input type=\"hidden\" name=\"js\" value=\"yes\">\n");
 		fprintf(fd, "</form></body>\n");
@@ -1374,6 +1350,12 @@
 							 "Error closing temp passport file: %s\n",
 							 g_strerror(errno));
 
+			/* The user wanted to check his or her email */
+			if (cmd->trans && cmd->trans->data)
+				/* TODO: This error might be a bit technical... */
+				purple_notify_error(gc, NULL,
+								  _("Error closing temporary passport file."), NULL);
+
 			g_unlink(session->passport_info.file);
 			g_free(session->passport_info.file);
 			session->passport_info.file = NULL;
@@ -1402,6 +1384,10 @@
 			}
 		}
 #endif
+
+		/* The user wants to check his or her email */
+		if (cmd->trans && cmd->trans->data)
+			purple_notify_uri(purple_account_get_connection(account), session->passport_info.file);
 	}
 }
 /**************************************************************************
--- a/libpurple/protocols/msn/oim.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/msn/oim.c	Sat Jul 19 03:10:38 2008 +0000
@@ -138,6 +138,9 @@
 	xmlnode *fault = NULL;
 	xmlnode *faultcode = NULL;
 
+	if (response == NULL)
+		return;
+
 	fault = xmlnode_get_child(response->xml, "Body/Fault");
 	if (fault)
 		faultcode = xmlnode_get_child(fault, "faultcode");
--- a/libpurple/protocols/msn/session.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/msn/session.c	Sat Jul 19 03:10:38 2008 +0000
@@ -454,7 +454,6 @@
 	PurpleAccount *account;
 	PurpleConnection *gc;
 	PurpleStoredImage *img;
-	const char *passport;
 
 	if (session->logged_in)
 		return;
@@ -474,17 +473,5 @@
 
 	/* Sync users */
 	msn_session_sync_users(session);
-	/* It seems that some accounts that haven't accessed hotmail for a while
-	 * and @msn.com accounts don't automatically get the initial email
-	 * notification so we always request it on login
-	 */
-
-	passport = purple_normalize(account, purple_account_get_username(account));
-
-	if ((strstr(passport, "@hotmail.") != NULL) ||
-		(strstr(passport, "@msn.com") != NULL))
-	{
-		msn_cmdproc_send(session->notification->cmdproc, "URL", "%s", "INBOX");
-	}
 }
 
--- a/libpurple/protocols/msn/session.h	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/msn/session.h	Sat Jul 19 03:10:38 2008 +0000
@@ -118,6 +118,7 @@
 		char *file;
 		char *client_ip;
 		int client_port;
+		gulong mail_timestamp;
 	} passport_info;
 
 	GHashTable *soap_table;
--- a/libpurple/protocols/oscar/flap_connection.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/oscar/flap_connection.c	Sat Jul 19 03:10:38 2008 +0000
@@ -299,12 +299,12 @@
 		conn->connect_data = NULL;
 	}
 
-	if (conn->connect_data != NULL)
+	if (conn->new_conn_data != NULL)
 	{
 		if (conn->type == SNAC_FAMILY_CHAT)
 		{
 			oscar_chat_destroy(conn->new_conn_data);
-			conn->connect_data = NULL;
+			conn->new_conn_data = NULL;
 		}
 	}
 
--- a/libpurple/protocols/qq/AUTHORS	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/AUTHORS	Sat Jul 19 03:10:38 2008 +0000
@@ -16,7 +16,7 @@
 
 Lovely Patch Writers
 =====
-Gnap.An     : message displaying, documentation
+gnap        : message displaying, documentation
 manphiz     : qun processing
 moo         : qun processing
 Coly Li     : qun processing
@@ -32,4 +32,4 @@
 rlaager@pidgin.im
 OpenQ Team
 LumaQQ Team
-OpenQ@GoogleGroup
+OpenQ Google Group
--- a/libpurple/protocols/qq/ChangeLog	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/ChangeLog	Sat Jul 19 03:10:38 2008 +0000
@@ -1,3 +1,11 @@
+2008.07.12 - ccpaging <ecc_hy(at)hotmail.com>
+	* Fixed: Always lost connection. Now send keep alive packet in every 30 seconds
+	* Minor fix for debug information
+	* Filter \r\n and replace with SPCAE in group notive
+	* Fixed a memory leak
+	* Tickets:
+	* Fixes #4024.
+
 2008.06.29 - csyfek <csyfek(at)gmail.com>
 	* Minor bug fix
 	* Add some doxygen syntax for preparing development documentation
--- a/libpurple/protocols/qq/buddy_info.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/buddy_info.c	Sat Jul 19 03:10:38 2008 +0000
@@ -208,8 +208,8 @@
 	return FALSE;
 }
 
-	static PurpleNotifyUserInfo *
-info_to_notify_user_info(const contact_info *info)
+static PurpleNotifyUserInfo *
+	info_to_notify_user_info(const contact_info *info)
 {
 	PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
 	const gchar *intro;
@@ -826,7 +826,8 @@
 	PurpleBuddy *b;
 	qq_data *qd;
 	qq_buddy *q_bud;
-	gchar *alias_utf8, *purple_name;
+	gchar *alias_utf8;
+	gchar *purple_name;
 	PurpleAccount *account = purple_connection_get_account(gc);
 
 	qd = (qq_data *) gc->proto_data;
@@ -1009,7 +1010,7 @@
 		bytes += qq_get16(&level, decr_buf + bytes);
 		bytes += qq_get16(&timeRemainder, decr_buf + bytes);
 		purple_debug(PURPLE_DEBUG_INFO, "QQ", 
-				"Level packet entry:\nuid: %d\nonlineTime: %d\nlevel: %d\ntimeRemainder: %d\n", 
+				"Level uid: %d, onlineTime: %d, level: %d, timeRemainder: %d\n", 
 				uid, onlineTime, level, timeRemainder);
 		purple_name = uid_to_purple_name(uid);
 		b = purple_find_buddy(account, purple_name);
--- a/libpurple/protocols/qq/buddy_list.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/buddy_list.c	Sat Jul 19 03:10:38 2008 +0000
@@ -234,12 +234,11 @@
 				"qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n");
 	}
 
-	if (position != QQ_FRIENDS_ONLINE_POSITION_END) {
-		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d online buddies, nextposition=%u\n",
-								count, (guint) position);
-		if (position != QQ_FRIENDS_ONLINE_POSITION_START) {
-			purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more online buddies\n"); 
-		}
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d online buddies, nextposition=%u\n",
+							count, (guint) position);
+	if (position != QQ_FRIENDS_ONLINE_POSITION_END
+		  && position != QQ_FRIENDS_ONLINE_POSITION_START) {
+		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more online buddies\n"); 
 		qq_send_packet_get_buddies_online(gc, position);
 	} else {
 		purple_debug(PURPLE_DEBUG_INFO, "QQ", "All online buddies received\n"); 
@@ -318,8 +317,8 @@
 
 		if (QQ_DEBUG) {
 			purple_debug(PURPLE_DEBUG_INFO, "QQ",
-					"buddy [%09d]: flag1=0x%02x, comm_flag=0x%02x\n",
-					q_bud->uid, q_bud->flag1, q_bud->comm_flag);
+					"buddy [%09d]: flag1=0x%02x, comm_flag=0x%02x, nick=%s\n",
+					q_bud->uid, q_bud->flag1, q_bud->comm_flag, q_bud->nickname);
 		}
 
 		name = uid_to_purple_name(q_bud->uid);
@@ -432,7 +431,9 @@
 
 	purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get all list done, %d buddies and %d Quns\n", i, j);
 	purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position);
-	if (position != QQ_FRIENDS_ALL_LIST_POSITION_START && position != QQ_FRIENDS_ALL_LIST_POSITION_START) {
+
+	if (position != QQ_FRIENDS_ALL_LIST_POSITION_START
+		&& position != QQ_FRIENDS_ALL_LIST_POSITION_END) {
 		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n");
 		qq_send_packet_get_all_list_with_group(gc, position);
 	} else {
--- a/libpurple/protocols/qq/buddy_status.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/buddy_status.c	Sat Jul 19 03:10:38 2008 +0000
@@ -205,7 +205,9 @@
 		b = purple_find_buddy(gc->account, name);
 		g_free(name);
 		q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
-		qq_update_buddy_contact(gc, q_bud);
+		if (q_bud != NULL) {
+			qq_update_buddy_contact(gc, q_bud);
+		}
 	}
 }
 
--- a/libpurple/protocols/qq/char_conv.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/char_conv.c	Sat Jul 19 03:10:38 2008 +0000
@@ -123,10 +123,7 @@
 	return g_strdup(QQ_NULL_MSG);
 }
 
-/**
- * @brief 把输入作为一个pascal字符串并返回一个用UFT-8转换的c-字符串.\n
- * 返回已读入的字节数,或者当遇到错误时返回-1.该完成转换的UTF-8字符串被保存到ret中
- *
+/*
  * take the input as a pascal string and return a converted c-string in UTF-8
  * returns the number of bytes read, return -1 if fatal error
  * the converted UTF-8 will be saved in ret
@@ -281,3 +278,17 @@
 	g_string_free(converted, FALSE);
 	return ret;
 }
+
+void qq_filter_str(gchar *str) {
+	gchar *temp;
+	if (str == NULL) {
+		return;
+	}
+
+	for (temp = str; *temp != 0; temp++) {
+		if (*temp == '\r' || *temp == '\n')  *temp = 0x20;
+	}
+	g_strstrip(str);
+}
+
+
--- a/libpurple/protocols/qq/char_conv.h	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/char_conv.h	Sat Jul 19 03:10:38 2008 +0000
@@ -40,5 +40,5 @@
 gchar *qq_encode_to_purple(guint8 *font_attr_data, gint len, const gchar *msg);
 
 gchar *qq_im_filter_html(const gchar *text);
-
+void qq_filter_str(gchar *str);
 #endif
--- a/libpurple/protocols/qq/group_conv.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/group_conv.c	Sat Jul 19 03:10:38 2008 +0000
@@ -99,7 +99,9 @@
 			list = list->next;
 		}
 
-		purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE);
+		if (names != NULL && flags != NULL) {
+			purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE);
+		}
 	}
 	/* clean up names */
 	while (names != NULL) {
--- a/libpurple/protocols/qq/group_free.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/group_free.c	Sat Jul 19 03:10:38 2008 +0000
@@ -55,8 +55,10 @@
 {
 	g_return_if_fail(group != NULL);
 	qq_group_free_member(group);
+	g_free(group->my_status_desc);
 	g_free(group->group_name_utf8);
 	g_free(group->group_desc_utf8);
+	g_free(group->notice_utf8);
 	g_free(group);
 }
 
--- a/libpurple/protocols/qq/group_info.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/group_info.c	Sat Jul 19 03:10:38 2008 +0000
@@ -87,7 +87,7 @@
 	/* only get online members when conversation window is on */
 	if (NULL == purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,group->group_name_utf8, purple_connection_get_account(gc))) {
 		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
-				"Conv windows for \"%s\" is not on, do not get online members\n", group->group_name_utf8);
+				"Conversation for \"%s\" is not open, ignore to get online members\n", group->group_name_utf8);
 		return;
 	}
 
@@ -141,9 +141,6 @@
 	qq_send_group_cmd(gc, group, raw_data, bytes);
 }
 
-/**
- * @brief 处理群信息.当前群信息的处理还不完善,由于版本的不同导致协议的解读有差异.
- */
 void qq_process_group_cmd_get_group_info(guint8 *data, gint len, PurpleConnection *gc)
 {
 	qq_group *group;
@@ -157,6 +154,7 @@
 	guint32 unknown4;
 	guint8 unknown1;
 	gint bytes, num;
+	gchar *notice;
 
 	g_return_if_fail(data != NULL && len > 0);
 	qd = (qq_data *) gc->proto_data;
@@ -186,22 +184,20 @@
 	bytes += qq_get32(&(group->group_category), data + bytes);
 	bytes += qq_get16(&max_members, data + bytes);
 	bytes += qq_get8(&unknown1, data + bytes);
-	/* XXX
-	 * the following, while Eva:
+	/* the following, while Eva:
 	 * 4(unk), 4(verID), 1(nameLen), nameLen(qunNameContent), 1(0x00),
 	 * 2(qunNoticeLen), qunNoticeLen(qunNoticeContent, 1(qunDescLen),
 	 * qunDestLen(qunDestcontent)) */
 	bytes += qq_get8(&unknown1, data + bytes);
-	purple_debug(PURPLE_DEBUG_INFO, "QQ", "type=%u creatorid=%u category=%u\n",
-			group->group_type, group->creator_uid, group->group_category);
-	purple_debug(PURPLE_DEBUG_INFO, "QQ", "maxmembers=%u", max_members); 
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "type=%u creatorid=%u category=%u maxmembers=%u\n",
+			group->group_type, group->creator_uid, group->group_category, max_members);
 	
 	/* strlen + <str content> */
 	bytes += convert_as_pascal_string(data + bytes, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
 	purple_debug(PURPLE_DEBUG_INFO, "QQ", "group \"%s\"\n", group->group_name_utf8); 
 	bytes += qq_get16(&unknown, data + bytes);	/* 0x0000 */
-	bytes += convert_as_pascal_string(data + bytes, &(group->notice_utf8), QQ_CHARSET_DEFAULT);
-	purple_debug(PURPLE_DEBUG_INFO, "QQ", "notice \"%s\"\n", group->notice_utf8); 
+	bytes += convert_as_pascal_string(data + bytes, &notice, QQ_CHARSET_DEFAULT);
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "notice \"%s\"\n", notice); 
 	bytes += convert_as_pascal_string(data + bytes, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT);
 	purple_debug(PURPLE_DEBUG_INFO, "QQ", "group_desc \"%s\"\n", group->group_desc_utf8); 
 
@@ -235,11 +231,16 @@
 			group->group_name_utf8, purple_connection_get_account(gc));
 	if(NULL == purple_conv) {
 		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
-				"Conv windows for \"%s\" is not on, do not set topic\n", group->group_name_utf8);
+				"Conversation for \"%s\" is not open, do not set topic\n", group->group_name_utf8);
+		return;
 	}
-	else {
-		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(purple_conv), NULL, group->notice_utf8);
-	}
+
+	/* filter \r\n in notice */
+	qq_filter_str(notice);
+	group->notice_utf8 = strdup(notice);
+	g_free(notice);
+	
+	purple_conv_chat_set_topic(PURPLE_CONV_CHAT(purple_conv), NULL, group->notice_utf8);
 }
 
 void qq_process_group_cmd_get_online_members(guint8 *data, gint len, PurpleConnection *gc)
@@ -296,6 +297,7 @@
 	guint16 unknown;
 	qq_group *group;
 	qq_buddy *member;
+	gchar *nick;
 
 	g_return_if_fail(data != NULL && len > 0);
 
@@ -318,11 +320,24 @@
 		bytes += qq_get16(&(member->face), data + bytes);
 		bytes += qq_get8(&(member->age), data + bytes);
 		bytes += qq_get8(&(member->gender), data + bytes);
-		bytes += convert_as_pascal_string(data + bytes, &(member->nickname), QQ_CHARSET_DEFAULT);
+		bytes += convert_as_pascal_string(data + bytes, &nick, QQ_CHARSET_DEFAULT);
 		bytes += qq_get16(&unknown, data + bytes);
 		bytes += qq_get8(&(member->flag1), data + bytes);
 		bytes += qq_get8(&(member->comm_flag), data + bytes);
 
+		/* filter \r\n in nick */
+		qq_filter_str(nick);
+		member->nickname = g_strdup(nick);
+		g_free(nick);
+		
+		/*
+		if (QQ_DEBUG) {
+			purple_debug(PURPLE_DEBUG_INFO, "QQ",
+					"member [%09d]: flag1=0x%02x, comm_flag=0x%02x, nick=%s\n",
+					member_uid, member->flag1, member->comm_flag, member->nickname);
+		}
+		*/
+
 		member->last_refresh = time(NULL);
 	}
 	if(bytes > len) {
--- a/libpurple/protocols/qq/group_internal.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/group_internal.c	Sat Jul 19 03:10:38 2008 +0000
@@ -230,9 +230,7 @@
 		*list = g_slist_remove(*list, GINT_TO_POINTER(id));
 }
 
-/**
- * @brief Return the location of id in list, or NULL if not found (返回id在链表中的位置,没有找到则返回NULL)
- */
+/* Return the location of id in list, or NULL if not found */
 GSList *qq_get_pending_id(GSList *list, guint32 id)
 {
         return g_slist_find(list, GINT_TO_POINTER(id));
--- a/libpurple/protocols/qq/qq.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/qq.c	Sat Jul 19 03:10:38 2008 +0000
@@ -747,7 +747,6 @@
 	NULL,							/* unregister_user */
 	NULL,							/* send_attention */
 	NULL,							/* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,							/* get_account_text_table */
 	NULL,							/* initiate_media */
 	NULL                            /* can_do_media */
--- a/libpurple/protocols/qq/qq_network.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/qq_network.c	Sat Jul 19 03:10:38 2008 +0000
@@ -189,13 +189,13 @@
 	return FALSE;		/* set mask */
 }
 
-static gboolean packet_check_ack(qq_data *qd, guint16 seq)
+static gboolean packet_check_ack(qq_data *qd, guint16 cmd, guint16 seq)
 {
 	gpointer trans;
 
 	g_return_val_if_fail(qd != NULL, FALSE);
 
-	trans = qq_send_trans_find(qd, seq);
+	trans = qq_send_trans_find(qd, cmd, seq);
 	if (trans == NULL) {
 		return FALSE;
 	}
@@ -360,7 +360,7 @@
 
 	/* ack packet, we need to update send tranactions */
 	/* we do not check duplication for server ack */
-	is_reply = packet_check_ack(qd, seq);
+	is_reply = packet_check_ack(qd, cmd, seq);
 	if ( !is_reply ) {
 		if ( !qd->logged_in ) {
 			/* packets before login */
@@ -460,7 +460,10 @@
 		return;
 	}
 
-	gc->last_received = time(NULL);
+	/* keep alive will be sent in 30 seconds since last_receive
+	 *  QQ need a keep alive packet in every 60 seconds
+	 gc->last_received = time(NULL);
+	*/
 	purple_debug(PURPLE_DEBUG_INFO, "TCP_PENDING",
 			   "Read %d bytes from socket, rxlen is %d\n", buf_len, qd->tcp_rxlen);
 	qd->tcp_rxqueue = g_realloc(qd->tcp_rxqueue, buf_len + qd->tcp_rxlen);
@@ -565,7 +568,10 @@
 		return;
 	}
 
-	gc->last_received = time(NULL);
+	/* keep alive will be sent in 30 seconds since last_receive
+	 *  QQ need a keep alive packet in every 60 seconds
+	 gc->last_received = time(NULL);
+	*/
 
 	if (buf_len < QQ_UDP_HEADER_LENGTH) {
 		if (buf[0] != QQ_PACKET_TAG || buf[buf_len - 1] != QQ_PACKET_TAIL) {
@@ -1240,7 +1246,6 @@
 	}
 
 	if (QQ_DEBUG) {
-		qq_show_packet("QQ_SEND_CMD", buf, buf_len);
 		purple_debug(PURPLE_DEBUG_INFO, "QQ",
 				"<== [%05d], %s, total %d bytes is sent %d\n", 
 				seq, qq_get_cmd_desc(cmd), buf_len, bytes_sent);
--- a/libpurple/protocols/qq/qq_trans.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/qq_trans.c	Sat Jul 19 03:10:38 2008 +0000
@@ -83,7 +83,7 @@
 	g_free(trans);
 }
 
-gpointer qq_send_trans_find(qq_data *qd, guint16 seq)
+gpointer qq_send_trans_find(qq_data *qd, guint16 cmd, guint16 seq)
 {
 	GList *curr;
 	GList *next;
@@ -93,7 +93,7 @@
 	while(curr) {
 		next = curr->next;
 		trans = (transaction *) (curr->data);
-		if(trans->seq == seq) {
+		if(trans->cmd == cmd && trans->seq == seq) {
 			return trans;
 		}
 		curr = next;
--- a/libpurple/protocols/qq/qq_trans.h	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/qq_trans.h	Sat Jul 19 03:10:38 2008 +0000
@@ -30,7 +30,7 @@
 
 void qq_send_trans_append(qq_data *qd, guint8 *buf, gint bus_len, guint16 cmd, guint16 seq);
 void qq_send_trans_remove(qq_data *qd, gpointer data);
-gpointer qq_send_trans_find(qq_data *qd, guint16 seq);
+gpointer qq_send_trans_find(qq_data *qd, guint16 cmd, guint16 seq);
 void qq_send_trans_remove_all(qq_data *qd);
 
 gint qq_send_trans_scan(qq_data *qd, gint *start, guint8 *buf, gint maxlen, guint16 *cmd, gint *retries);
--- a/libpurple/protocols/qq/send_file.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/qq/send_file.c	Sat Jul 19 03:10:38 2008 +0000
@@ -156,7 +156,7 @@
 	gint size;
 	/* FIXME: It seems that the transfer never use a packet
 	 * larger than 1500 bytes, so if it happened to be a
-	 * larger packet, either error occurred or protocol should
+	 * larger packet, either error occured or protocol should
 	 * be modified
 	 */
 	ft_info *info;
--- a/libpurple/protocols/yahoo/yahoo_profile.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_profile.c	Sat Jul 19 03:10:38 2008 +0000
@@ -1282,6 +1282,10 @@
 	url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, yahoo_got_info, data);
 	if (url_data != NULL)
 		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+	else {
+		g_free(data->name);
+		g_free(data);
+	}
 
 	g_free(url);
 }
--- a/pidgin/gtkaccount.c	Sat Jul 19 03:10:00 2008 +0000
+++ b/pidgin/gtkaccount.c	Sat Jul 19 03:10:38 2008 +0000
@@ -1186,7 +1186,6 @@
 	char *tmp;
 	gboolean new_acct = FALSE, icon_change = FALSE;
 	PurpleAccount *account;
-	PurplePluginProtocolInfo *prpl_info;
 
 	/* Build the username string. */
 	username = g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->screenname_entry)));
@@ -1254,8 +1253,7 @@
 		purple_account_set_alias(account, NULL);
 
 	/* Buddy Icon */
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin);
-	if (prpl_info != NULL && prpl_info->icon_spec.format != NULL)
+	if (dialog->prpl_info != NULL && dialog->prpl_info->icon_spec.format != NULL)
 	{
 		const char *filename;