changeset 23756:1a0caf9983fa

applied changes from 92d52eef2994d2697999177804e3665989cfa352 through 5688199e261449d33b5803dafff50d860896ebcb Reapplied 5688199e261449d33b5803dafff50d860896ebcb. 2008.09.04 - ccpaging <ccpaging(at)gmail.com> * minor code cleaned committer: Daniel Atallah <daniel.atallah@gmail.com>
author SHiNE CsyFeK <csyfek@gmail.com>
date Mon, 15 Sep 2008 03:02:06 +0000
parents 23cec4360d4a
children 69c218fd5d54
files libpurple/protocols/qq/buddy_info.c libpurple/protocols/qq/buddy_list.c libpurple/protocols/qq/buddy_list.h libpurple/protocols/qq/buddy_opt.c libpurple/protocols/qq/group_conv.c libpurple/protocols/qq/group_conv.h libpurple/protocols/qq/group_im.c libpurple/protocols/qq/group_info.c libpurple/protocols/qq/group_join.c libpurple/protocols/qq/group_opt.c libpurple/protocols/qq/im.c libpurple/protocols/qq/qq.c libpurple/protocols/qq/qq_network.c libpurple/protocols/qq/qq_network.h libpurple/protocols/qq/qq_process.c libpurple/protocols/qq/qq_trans.c libpurple/protocols/qq/qq_trans.h libpurple/protocols/qq/sys_msg.c
diffstat 18 files changed, 208 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/qq/buddy_info.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/buddy_info.c	Mon Sep 15 03:02:06 2008 +0000
@@ -711,7 +711,7 @@
 	data[data_len] = '\0';
 	if (qd->uid == atoi((gchar *) data)) {	/* return should be my uid */
 		purple_debug_info("QQ", "Update info ACK OK\n");
-		purple_notify_info(gc, NULL, _("My information has been updated"), NULL);
+		purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), _("Change buddy information."));
 	}
 }
 
--- a/libpurple/protocols/qq/buddy_list.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/buddy_list.c	Mon Sep 15 03:02:06 2008 +0000
@@ -424,7 +424,7 @@
 		case QQ_BUDDY_ONLINE_AWAY:
 		case QQ_BUDDY_ONLINE_INVISIBLE:
 			return TRUE;
-		case QQ_BUDDY_ONLINE_OFFLINE:
+		case QQ_BUDDY_CHANGE_TO_OFFLINE:
 			return FALSE;
 	}
 	return FALSE;
@@ -556,19 +556,17 @@
 	g_free(name);
 	q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
 	if (q_bud == NULL) {
-		purple_debug_error("QQ",
-				"got information of unknown buddy %d\n", bs.uid);
+		purple_debug_warning("QQ", "Get status of unknown buddy %d\n", bs.uid);
 		return;
 	}
 
-	purple_debug_info("QQ", "status:.uid = %d, q_bud->uid = %d\n", bs.uid , q_bud->uid);
 	if(bs.ip.s_addr != 0) {
 		q_bud->ip.s_addr = bs.ip.s_addr;
 		q_bud->port = bs.port;
 	}
 	q_bud->status =bs.status;
 
-	if (q_bud->status == QQ_BUDDY_ONLINE_NORMAL) {
+	if (q_bud->status == QQ_BUDDY_ONLINE_NORMAL && q_bud->level <= 0) {
 		qq_request_get_level(gc, q_bud->uid);
 	}
 	qq_update_buddy_contact(gc, q_bud);
@@ -610,7 +608,7 @@
 	case QQ_BUDDY_ONLINE_NORMAL:
 		status_id = "available";
 		break;
-	case QQ_BUDDY_ONLINE_OFFLINE:
+	case QQ_BUDDY_CHANGE_TO_OFFLINE:
 		status_id = "offline";
 		break;
 	case QQ_BUDDY_ONLINE_AWAY:
@@ -632,11 +630,6 @@
 	else
 		purple_prpl_got_user_status_deactive(gc->account, purple_name, "mobile");
 
-	if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO && q_bud->status != QQ_BUDDY_OFFLINE)
-		purple_prpl_got_user_status(gc->account, purple_name, "video", NULL);
-	else
-		purple_prpl_got_user_status_deactive(gc->account, purple_name, "video");
-
 	g_free(purple_name);
 }
 
@@ -657,7 +650,7 @@
 		q_bud = (qq_buddy *) list->data;
 		if (q_bud != NULL && now > q_bud->last_update + QQ_UPDATE_ONLINE_INTERVAL
 				&& q_bud->status != QQ_BUDDY_ONLINE_INVISIBLE) {
-			q_bud->status = QQ_BUDDY_ONLINE_OFFLINE;
+			q_bud->status = QQ_BUDDY_CHANGE_TO_OFFLINE;
 			qq_update_buddy_contact(gc, q_bud);
 		}
 		list = list->next;
--- a/libpurple/protocols/qq/buddy_list.h	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/buddy_list.h	Mon Sep 15 03:02:06 2008 +0000
@@ -43,7 +43,7 @@
 enum {
 	QQ_BUDDY_OFFLINE = 0x00,
 	QQ_BUDDY_ONLINE_NORMAL = 10,
-	QQ_BUDDY_ONLINE_OFFLINE = 20,
+	QQ_BUDDY_CHANGE_TO_OFFLINE = 20,
 	QQ_BUDDY_ONLINE_AWAY = 30,
 	QQ_BUDDY_ONLINE_INVISIBLE = 40
 };
--- a/libpurple/protocols/qq/buddy_opt.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/buddy_opt.c	Mon Sep 15 03:02:06 2008 +0000
@@ -282,10 +282,11 @@
 	if (data[0] != QQ_REMOVE_BUDDY_REPLY_OK) {
 		/* there is no reason return from server */
 		purple_debug_warning("QQ", "Remove buddy fails\n");
+		purple_notify_info(gc, _("QQ Buddy"), _("Failed:"),  _("Remove buddy"));
 	} else {		/* if reply */
 		purple_debug_info("QQ", "Remove buddy OK\n");
 		/* TODO: We don't really need to notify the user about this, do we? */
-		purple_notify_info(gc, NULL, _("You have successfully removed a buddy"), NULL);
+		purple_notify_info(gc, _("QQ Buddy"), _("Successed:"),  _("Remove buddy"));
 	}
 }
 
@@ -301,11 +302,11 @@
 	if (data[0] != QQ_REMOVE_SELF_REPLY_OK) {
 		/* there is no reason return from server */
 		purple_debug_warning("QQ", "Remove self fails\n");
-		purple_notify_info(gc, NULL, _("Failed removing from friend's buddy list"), NULL);
+		purple_notify_info(gc, _("QQ Buddy"), _("Failed:"), _("Remove from other's buddy list"));
 	} else {		/* if reply */
 		purple_debug_info("QQ", "Remove from a buddy OK\n");
 		/* TODO: Does the user really need to be notified about this? */
-		purple_notify_info(gc, NULL, _("Successed removing from friend's buddy list"), NULL);
+		purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), _("Remove from other's buddy list"));
 	}
 }
 
@@ -378,8 +379,8 @@
 		g_free(nombre);
 	} else {	/* add OK */
 		qq_add_buddy_by_recv_packet(gc, for_uid, TRUE, TRUE);
-		msg = g_strdup_printf(_("You have added %d to buddy list"), for_uid);
-		purple_notify_info(gc, NULL, msg, NULL);
+		msg = g_strdup_printf(_("Add into %d's buddy list"), for_uid);
+		purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), msg);
 		g_free(msg);
 	}
 	g_strfreev(segments);
--- a/libpurple/protocols/qq/group_conv.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/group_conv.c	Mon Sep 15 03:02:06 2008 +0000
@@ -25,25 +25,38 @@
 #include <glib.h>
 #include "qq.h"
 
-#include "conversation.h"
-
 #include "group_conv.h"
 #include "buddy_list.h"
+#include "header_info.h"
+#include "qq_network.h"
+#include "qq_process.h"
 #include "utils.h"
 
 /* show group conversation window */
-void qq_group_conv_show_window(PurpleConnection *gc, qq_group *group)
+PurpleConversation *qq_room_conv_create(PurpleConnection *gc, qq_group *group)
 {
 	PurpleConversation *conv;
 	qq_data *qd;
 
-	g_return_if_fail(group != NULL);
+	g_return_val_if_fail(group != NULL, NULL);
 	qd = (qq_data *) gc->proto_data;
 
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, 
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
 			group->title_utf8, purple_connection_get_account(gc));
-	if (conv == NULL)	/* show only one window per group */
-		serv_got_joined_chat(gc, qd->channel++, group->title_utf8);
+	if (conv != NULL)	{
+		/* show only one window per group */
+		return conv;
+	}
+
+	serv_got_joined_chat(gc, qd->channel++, group->title_utf8);
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->title_utf8, purple_connection_get_account(gc));
+	if (conv != NULL) {
+		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, group->notice_utf8);
+		/* qq_update_room(gc, 0, group->id); */
+		qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_ONLINES, group->id);
+		return conv;
+	}
+	return NULL;
 }
 
 /* refresh online member in group conversation window */
--- a/libpurple/protocols/qq/group_conv.h	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/group_conv.h	Mon Sep 15 03:02:06 2008 +0000
@@ -26,9 +26,10 @@
 #define _QQ_GROUP_CONV_H_
 
 #include "connection.h"
+#include "conversation.h"
 #include "group.h"
 
-void qq_group_conv_show_window(PurpleConnection *gc, qq_group *group);
+PurpleConversation *qq_room_conv_create(PurpleConnection *gc, qq_group *group);
 void qq_group_conv_refresh_online_member(PurpleConnection *gc, qq_group *group);
 
 #endif
--- a/libpurple/protocols/qq/group_im.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/group_im.c	Mon Sep 15 03:02:06 2008 +0000
@@ -37,6 +37,7 @@
 #include "group_info.h"
 #include "group_im.h"
 #include "group_opt.h"
+#include "group_conv.h"
 #include "im.h"
 #include "header_info.h"
 #include "packet_parse.h"
@@ -243,7 +244,7 @@
 	g_return_if_fail(ext_id > 0 && uid > 0);
 
 	msg = g_strdup_printf(_("[%d] removed from Qun \"%d\""), uid, ext_id);
-	purple_notify_info(gc, _("QQ Qun Operation"), msg, NULL);
+	purple_notify_info(gc, _("QQ Qun Operation"), _("Notice:"), msg);
 
 	group = qq_room_search_id(gc, id);
 	if (group != NULL) {
@@ -274,7 +275,7 @@
 	g_return_if_fail(ext_id > 0 && uid > 0);
 
 	msg = g_strdup_printf(_("[%d] added to Qun \"%d\""), uid, ext_id);
-	purple_notify_info(gc, _("QQ Qun Operation"), msg, _("Qun is in buddy list"));
+	purple_notify_info(gc, _("QQ Qun Operation"), _("Notice:"), msg);
 
 	group = qq_room_search_id(gc, id);
 	if (group != NULL) {
@@ -378,13 +379,8 @@
 	g_return_if_fail(group != NULL);
 
 	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->title_utf8, purple_connection_get_account(gc));
-	if (conv == NULL && purple_prefs_get_bool("/plugins/prpl/qq/prompt_group_msg_on_recv")) {
-		/* New conv should open, get group info*/
-		/* qq_update_room(gc, 0, group->id); */
-		qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_ONLINES, group->id);
-
-		serv_got_joined_chat(gc, qd->channel++, group->title_utf8);
-		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->title_utf8, purple_connection_get_account(gc));
+	if (conv == NULL && purple_prefs_get_bool("/plugins/prpl/qq/show_room_when_newin")) {
+		conv = qq_room_conv_create(gc, group);
 	}
 
 	if (conv != NULL) {
--- a/libpurple/protocols/qq/group_info.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/group_info.c	Mon Sep 15 03:02:06 2008 +0000
@@ -59,7 +59,7 @@
 	list = group->members;
 	while (list != NULL) {
 		member = (qq_buddy *) list->data;
-		member->status = QQ_BUDDY_ONLINE_OFFLINE;
+		member->status = QQ_BUDDY_CHANGE_TO_OFFLINE;
 		list = list->next;
 	}
 }
@@ -189,6 +189,11 @@
 	if (group->creator_uid == qd->uid)
 		group->my_role = QQ_ROOM_ROLE_ADMIN;
 
+	/* filter \r\n in notice */
+	qq_filter_str(notice);
+	group->notice_utf8 = strdup(notice);
+	g_free(notice);
+
 	qq_group_refresh(gc, group);
 
 	purple_conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
@@ -199,11 +204,7 @@
 		return;
 	}
 
-	/* filter \r\n in notice */
-	qq_filter_str(notice);
-	group->notice_utf8 = strdup(notice);
-	g_free(notice);
-
+	purple_debug_info("QQ", "Set chat topic to %s\n", group->notice_utf8);
 	purple_conv_chat_set_topic(PURPLE_CONV_CHAT(purple_conv), NULL, group->notice_utf8);
 }
 
--- a/libpurple/protocols/qq/group_join.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/group_join.c	Mon Sep 15 03:02:06 2008 +0000
@@ -38,6 +38,7 @@
 #include "group_info.h"
 #include "group_join.h"
 #include "group_opt.h"
+#include "group_conv.h"
 #include "group_search.h"
 #include "header_info.h"
 #include "packet_parse.h"
@@ -47,6 +48,7 @@
 enum {
 	QQ_ROOM_JOIN_OK = 0x01,
 	QQ_ROOM_JOIN_NEED_AUTH = 0x02,
+	QQ_ROOM_JOIN_DENIED = 0x03,
 };
 
 static void _qq_group_exit_with_gc_and_id(gc_and_uid *g)
@@ -192,7 +194,7 @@
 			purple_blist_remove_chat(chat);
 		qq_group_delete_internal_record(qd, id);
 	}
-	purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully left the Qun"), NULL);
+	purple_notify_info(gc, _("QQ Qun Operation"), _("Successed:"), _("Remove from Qun"));
 }
 
 /* Process the reply to group_auth subcmd */
@@ -214,8 +216,7 @@
 	bytes += qq_get32(&id, data + bytes);
 	g_return_if_fail(id > 0);
 
-	purple_notify_info(gc, _("QQ Qun Auth"),
-		     _("Your authorization request has been accepted by the QQ server"), NULL);
+	purple_notify_info(gc, _("QQ Qun Operation"), _("Successed:"), _("Join to Qun"));
 }
 
 /* process group cmd reply "join group" */
@@ -225,6 +226,7 @@
 	guint32 id;
 	guint8 reply;
 	qq_group *group;
+	gchar *msg;
 
 	g_return_if_fail(data != NULL && len > 0);
 
@@ -244,13 +246,11 @@
 	g_return_if_fail(group != NULL);
 	switch (reply) {
 	case QQ_ROOM_JOIN_OK:
-		purple_debug_info("QQ", "Succeed joining group \"%s\"\n", group->title_utf8);
+		purple_debug_info("QQ", "Successed in joining group \"%s\"\n", group->title_utf8);
 		group->my_role = QQ_ROOM_ROLE_YES;
 		qq_group_refresh(gc, group);
 		/* this must be shown before getting online members */
-		qq_group_conv_show_window(gc, group);
-		/* qq_update_room(gc, 0, group->id); */
-		qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_ONLINES, group->id);
+		qq_room_conv_create(gc, group);
 		break;
 	case QQ_ROOM_JOIN_NEED_AUTH:
 		purple_debug_info("QQ",
@@ -260,10 +260,17 @@
 		qq_group_refresh(gc, group);
 		_qq_group_join_auth(gc, group);
 		break;
+	case QQ_ROOM_JOIN_DENIED:
+		msg = g_strdup_printf(_("Qun %d denied to join"), group->ext_id);
+		purple_notify_info(gc, _("QQ Qun Operation"), _("Failed:"), msg);
+		g_free(msg);
+		break;
 	default:
 		purple_debug_info("QQ",
-			   "Error joining group [%d] %s, unknown reply: 0x%02x\n",
+			   "Failed joining group [%d] %s, unknown reply: 0x%02x\n",
 			   group->ext_id, group->title_utf8, reply);
+
+		purple_notify_info(gc, _("QQ Qun Operation"), _("Failed:"), _("Join Qun, Unknow Reply"));
 	}
 }
 
--- a/libpurple/protocols/qq/group_opt.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/group_opt.c	Mon Sep 15 03:02:06 2008 +0000
@@ -212,8 +212,7 @@
 
 	purple_debug_info("QQ", "Succeed in modify members for room %d\n", group->ext_id);
 
-	purple_notify_info(gc, _("QQ Qun Operation"),
-			_("You have successfully modified Qun member"), NULL);
+	purple_notify_info(gc, _("QQ Qun Operation"), _("Successed:"), _("Change Qun member"));
 }
 
 void qq_room_change_info(PurpleConnection *gc, qq_group *group)
@@ -279,7 +278,7 @@
 	purple_debug_info("QQ", "Succeed in modify info for Qun %d\n", group->ext_id);
 	qq_group_refresh(gc, group);
 
-	purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun information"), NULL);
+	purple_notify_info(gc, _("QQ Qun Operation"), _("Successed:"), _("Change Qun information"));
 }
 
 /* we create a very simple group first, and then let the user to modify */
--- a/libpurple/protocols/qq/im.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/im.c	Mon Sep 15 03:02:06 2008 +0000
@@ -250,6 +250,7 @@
 	guint8 *temp;
 	guint8 temp_len;
 	gchar *title, *brief, *url;
+	gchar *title_utf8;
 	gchar *content, *content_utf8;
 
 	g_return_if_fail(data != NULL && data_len != 0);
@@ -276,15 +277,17 @@
 	bytes += qq_getdata(temp, temp_len, data+bytes);
 	url = g_strndup((gchar *)temp, temp_len);
 
-	content = g_strdup_printf(_("Title: %s\nBrief: %s\n\n%s"), title, brief, url);
+	title_utf8 = qq_to_utf8(title, QQ_CHARSET_DEFAULT);
+	content = g_strdup_printf(_("%s\n\n%s"), brief, url);
 	content_utf8 = qq_to_utf8(content, QQ_CHARSET_DEFAULT);
 
 	if (qd->is_show_news) {
-		purple_notify_info(gc, NULL, _("QQ Server News"), content_utf8);
+		purple_notify_info(gc, _("QQ Server News"), title_utf8, content_utf8);
 	} else {
-		purple_debug_info("QQ", "QQ Server news:\n%s", content_utf8);
+		purple_debug_info("QQ", "QQ Server news:\n%s\n%s", title_utf8, content_utf8);
 	}
 	g_free(title);
+	g_free(title_utf8);
 	g_free(brief);
 	g_free(url);
 	g_free(content);
--- a/libpurple/protocols/qq/qq.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/qq.c	Mon Sep 15 03:02:06 2008 +0000
@@ -231,7 +231,7 @@
 		g_string_append(status, _("Online"));
 		break;
 	/* TODO What does this status mean? Labelling it as offline... */
-	case QQ_BUDDY_ONLINE_OFFLINE:
+	case QQ_BUDDY_CHANGE_TO_OFFLINE:
 		g_string_append(status, _("Offline"));
 		break;
 	case QQ_BUDDY_ONLINE_AWAY:
@@ -868,7 +868,7 @@
 	purple_prefs_add_none("/plugins/prpl/qq");
 	purple_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE);
 	purple_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE);
-	purple_prefs_add_bool("/plugins/prpl/qq/prompt_group_msg_on_recv", TRUE);
+	purple_prefs_add_bool("/plugins/prpl/qq/show_room_when_newin", TRUE);
 
 }
 
--- a/libpurple/protocols/qq/qq_network.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/qq_network.c	Mon Sep 15 03:02:06 2008 +0000
@@ -1056,25 +1056,26 @@
 }
 
 gint qq_send_cmd_encrypted(PurpleConnection *gc, guint16 cmd, guint16 seq,
-	guint8 *data, gint data_len, gboolean need_ack)
+	guint8 *encrypted_data, gint encrypted_len, gboolean is_save2trans)
 {
-	gint send_len;
+	gint sent_len;
 
 #if 1
+		/* qq_show_packet("qq_send_cmd_encrypted", data, data_len); */
 		purple_debug_info("QQ", "<== [%05d], %s(0x%04X), datalen %d\n",
-				seq, qq_get_cmd_desc(cmd), cmd, data_len);
+				seq, qq_get_cmd_desc(cmd), cmd, encrypted_len);
 #endif
 
-	send_len = packet_send_out(gc, cmd, seq, data, data_len);
-	if (need_ack)  {
-		qq_trans_add_client_cmd(gc, cmd, seq, data, data_len, 0, 0);
+	sent_len = packet_send_out(gc, cmd, seq, encrypted_data, encrypted_len);
+	if (is_save2trans)  {
+		qq_trans_add_client_cmd(gc, cmd, seq, encrypted_data, encrypted_len, 0, 0);
 	}
-	return send_len;
+	return sent_len;
 }
 
 /* Encrypt data with session_key, and send packet out */
 static gint send_cmd_detail(PurpleConnection *gc, guint16 cmd, guint16 seq,
-	guint8 *data, gint data_len, gboolean need_ack, gint update_class, guint32 ship32)
+	guint8 *data, gint data_len, gboolean is_save2trans, gint update_class, guint32 ship32)
 {
 	qq_data *qd;
 	guint8 *encrypted_data;
@@ -1096,8 +1097,9 @@
 
 	bytes_sent = packet_send_out(gc, cmd, seq, encrypted_data, encrypted_len);
 
-	if (need_ack)  {
-		qq_trans_add_client_cmd(gc, cmd, seq, encrypted_data, encrypted_len, update_class, ship32);
+	if (is_save2trans)  {
+		qq_trans_add_client_cmd(gc, cmd, seq, encrypted_data, encrypted_len,
+				update_class, ship32);
 	}
 	return bytes_sent;
 }
@@ -1120,12 +1122,12 @@
 	return send_cmd_detail(gc, cmd, seq, data, data_len, TRUE, update_class, ship32);
 }
 
-/* set seq and need_ack, then call send_cmd_detail */
+/* set seq and is_save2trans, then call send_cmd_detail */
 gint qq_send_cmd(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len)
 {
 	qq_data *qd;
 	guint16 seq;
-	gboolean need_ack;
+	gboolean is_save2trans;
 
 	g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
 	qd = (qq_data *) gc->proto_data;
@@ -1133,26 +1135,47 @@
 
 	if (cmd != QQ_CMD_LOGOUT) {
 		seq = ++qd->send_seq;
-		need_ack = TRUE;
+		is_save2trans = TRUE;
 	} else {
 		seq = 0xFFFF;
-		need_ack = FALSE;
+		is_save2trans = FALSE;
 	}
 #if 1
 		purple_debug_info("QQ", "<== [%05d], %s(0x%04X), datalen %d\n",
 				seq, qq_get_cmd_desc(cmd), cmd, data_len);
 #endif
-	return send_cmd_detail(gc, cmd, seq, data, data_len, need_ack, 0, 0);
+	return send_cmd_detail(gc, cmd, seq, data, data_len, is_save2trans, 0, 0);
 }
 
-/* set seq and need_ack, then call send_cmd_detail */
+/* set seq and is_save2trans, then call send_cmd_detail */
 gint qq_send_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len)
 {
+	qq_data *qd;
+	guint8 *encrypted_data;
+	gint encrypted_len;
+	gint bytes_sent;
+
+	g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
+	qd = (qq_data *)gc->proto_data;
+	g_return_val_if_fail(data != NULL && data_len > 0, -1);
+
 #if 1
 		purple_debug_info("QQ", "<== [SRV-%05d], %s(0x%04X), datalen %d\n",
 				seq, qq_get_cmd_desc(cmd), cmd, data_len);
 #endif
-	return send_cmd_detail(gc, cmd, seq, data, data_len, FALSE, 0, 0);
+	/* at most 16 bytes more */
+	encrypted_data = g_newa(guint8, data_len + 16);
+	encrypted_len = qq_encrypt(encrypted_data, data, data_len, qd->session_key);
+	if (encrypted_len < 16) {
+		purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n",
+				encrypted_len, seq, cmd, qq_get_cmd_desc(cmd));
+		return -1;
+	}
+
+	bytes_sent = packet_send_out(gc, cmd, seq, encrypted_data, encrypted_len);
+	qq_trans_add_server_reply(gc, cmd, seq, encrypted_data, encrypted_len);
+
+	return bytes_sent;
 }
 
 static gint send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id,
@@ -1198,13 +1221,14 @@
 
 	bytes_sent = packet_send_out(gc, QQ_CMD_ROOM, seq, encrypted_data, encrypted_len);
 #if 1
-		/* qq_show_packet("QQ_SEND_DATA", buf, buf_len); */
+		/* qq_show_packet("send_room_cmd", buf, buf_len); */
 		purple_debug_info("QQ",
 				"<== [%05d], %s (0x%02X) to room %d, datalen %d\n",
 				seq, qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len);
 #endif
 
-	qq_trans_add_room_cmd(gc, seq, room_cmd, room_id, buf, buf_len, update_class, ship32);
+	qq_trans_add_room_cmd(gc, seq, room_cmd, room_id, encrypted_data, encrypted_len,
+			update_class, ship32);
 	return bytes_sent;
 }
 
--- a/libpurple/protocols/qq/qq_network.h	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/qq_network.h	Mon Sep 15 03:02:06 2008 +0000
@@ -36,7 +36,7 @@
 void qq_disconnect(PurpleConnection *gc);
 
 gint qq_send_cmd_encrypted(PurpleConnection *gc, guint16 cmd, guint16 seq,
-		guint8 *data, gint data_len, gboolean need_ack);
+		guint8 *encrypted_data, gint encrypted_len, gboolean is_save2trans);
 gint qq_send_cmd(PurpleConnection *gc, guint16 cmd, guint8 *data, gint datalen);
 gint qq_send_cmd_mess(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len,
 		gint update_class, guint32 ship32);
--- a/libpurple/protocols/qq/qq_process.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/qq_process.c	Mon Sep 15 03:02:06 2008 +0000
@@ -78,7 +78,7 @@
 
 	msg_utf8 = try_dump_as_gbk(data, data_len);
 	if (msg_utf8 != NULL) {
-		purple_notify_info(gc, title, msg_utf8, NULL);
+		purple_notify_info(gc, _("QQ Error"), title, msg_utf8);
 		g_free(msg_utf8);
 	}
 }
@@ -130,6 +130,7 @@
 static void process_room_cmd_notify(PurpleConnection *gc,
 	guint8 room_cmd, guint8 room_id, guint8 reply, guint8 *data, gint data_len)
 {
+	gchar *prim;
 	gchar *msg, *msg_utf8;
 	g_return_if_fail(data != NULL && data_len > 0);
 
@@ -137,11 +138,12 @@
 	msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
 	g_free(msg);
 
-	msg = g_strdup_printf(_("Command %s(0x%02X) id %d, reply [0x%02X]:\n%s"),
-		qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, reply, msg_utf8);
+	prim = g_strdup_printf(_("Error reply of %s(0x%02X)\nRoom %d, reply 0x%02X"),
+		qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, reply);
 
-	purple_notify_error(gc, NULL, _("Invalid QQ Qun reply"), msg);
-	g_free(msg);
+	purple_notify_error(gc, _("QQ Qun Command"), prim, msg_utf8);
+
+	g_free(prim);
 	g_free(msg_utf8);
 }
 
@@ -343,7 +345,7 @@
 		purple_debug_warning("QQ",
 			"Invaild room id, [%05d], 0x%02X %s for %d, len %d\n",
 			seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
-		return;
+		/* Some room cmd has no room id, like QQ_ROOM_CMD_SEARCH */
 	}
 
 	if (data_len <= 2) {
--- a/libpurple/protocols/qq/qq_trans.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/qq_trans.c	Mon Sep 15 03:02:06 2008 +0000
@@ -35,12 +35,13 @@
 #include "qq_process.h"
 #include "qq_trans.h"
 
-#define QQ_RESEND_MAX               3	/* max resend per packet */
+#define QQ_RESEND_MAX               4	/* max resend per packet */
 
 enum {
 	QQ_TRANS_IS_SERVER = 0x01,			/* Is server command or client command */
 	QQ_TRANS_IS_IMPORT = 0x02,			/* Only notice if not get reply; or resend, disconn if reties get 0*/
-	QQ_TRANS_REMAINED = 0x04,		/* server command before login*/
+	QQ_TRANS_REMAINED = 0x04,				/* server command before login*/
+	QQ_TRANS_IS_REPLY = 0x08,				/* server command before login*/
 };
 
 struct _qq_transaction {
@@ -63,42 +64,6 @@
 	guint32 ship32;
 };
 
-qq_transaction *qq_trans_find_rcved(PurpleConnection *gc, guint16 cmd, guint16 seq)
-{
-	qq_data *qd = (qq_data *)gc->proto_data;
-	GList *curr;
-	GList *next;
-	qq_transaction *trans;
-
-	if (qd->transactions == NULL) {
-		return NULL;
-	}
-
-	next = qd->transactions;
-	while( (curr = next) ) {
-		next = curr->next;
-
-		trans = (qq_transaction *) (curr->data);
-		if(trans->cmd == cmd && trans->seq == seq) {
-			if (trans->rcved_times == 0) {
-				trans->scan_times = 0;
-			}
-			trans->rcved_times++;
-			/* server may not get our confirm reply before, send reply again*/
-			/* only rcved buffer stored in transaction
-			if (qq_trans_is_server(trans) && qq_trans_is_dup(trans)) {
-				if (trans->data != NULL && trans->data_len > 0) {
-					qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE);
-				}
-			}
-			*/
-			return trans;
-		}
-	}
-
-	return NULL;
-}
-
 gboolean qq_trans_is_server(qq_transaction *trans)
 {
 	g_return_val_if_fail(trans != NULL, FALSE);
@@ -175,8 +140,11 @@
 static void trans_remove(PurpleConnection *gc, qq_transaction *trans)
 {
 	qq_data *qd = (qq_data *)gc->proto_data;
-	g_return_if_fail(qd != NULL && trans != NULL);
 
+	g_return_if_fail(gc != NULL && gc->proto_data != NULL);
+	qd = (qq_data *) gc->proto_data;
+
+	g_return_if_fail(trans != NULL);
 #if 0
 	purple_debug_info("QQ_TRANS",
 				"Remove [%s%05d] retry %d rcved %d scan %d %s\n",
@@ -190,6 +158,27 @@
 	g_free(trans);
 }
 
+static qq_transaction *trans_find(PurpleConnection *gc, guint16 cmd, guint16 seq)
+{
+	qq_data *qd;
+	GList *list;
+	qq_transaction *trans;
+
+	g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL);
+	qd = (qq_data *) gc->proto_data;
+
+	list = qd->transactions;
+	while (list != NULL) {
+		trans = (qq_transaction *) list->data;
+		if(trans->cmd == cmd && trans->seq == seq) {
+			return trans;
+		}
+		list = list->next;
+	}
+
+	return NULL;
+}
+
 void qq_trans_add_client_cmd(PurpleConnection *gc,
 	guint16 cmd, guint16 seq, guint8 *data, gint data_len, gint update_class, guint32 ship32)
 {
@@ -207,6 +196,28 @@
 	qd->transactions = g_list_append(qd->transactions, trans);
 }
 
+qq_transaction *qq_trans_find_rcved(PurpleConnection *gc, guint16 cmd, guint16 seq)
+{
+	qq_transaction *trans;
+
+	trans = trans_find(gc, cmd, seq);
+	if (trans == NULL) {
+		return NULL;
+	}
+
+	if (trans->rcved_times == 0) {
+		trans->scan_times = 0;
+	}
+	trans->rcved_times++;
+	/* server may not get our confirm reply before, send reply again*/
+	if (qq_trans_is_server(trans) && (trans->flag & QQ_TRANS_IS_REPLY)) {
+		if (trans->data != NULL && trans->data_len > 0) {
+			qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE);
+		}
+	}
+	return trans;
+}
+
 void qq_trans_add_room_cmd(PurpleConnection *gc,
 		guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *data, gint data_len,
 		gint update_class, guint32 ship32)
@@ -226,10 +237,10 @@
 }
 
 void qq_trans_add_server_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq,
-		guint8 *data, gint data_len)
+		guint8 *rcved, gint rcved_len)
 {
 	qq_data *qd = (qq_data *)gc->proto_data;
-	qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, QQ_CMD_CLASS_NONE, 0);
+	qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, rcved, rcved_len, QQ_CMD_CLASS_NONE, 0);
 
 	trans->flag = QQ_TRANS_IS_SERVER;
 	trans->send_retries = 0;
@@ -241,6 +252,27 @@
 	qd->transactions = g_list_append(qd->transactions, trans);
 }
 
+void qq_trans_add_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq,
+		guint8 *reply, gint reply_len)
+{
+	qq_transaction *trans;
+
+	g_return_if_fail(reply != NULL && reply_len > 0);
+
+	trans = trans_find(gc, cmd, seq);
+	if (trans == NULL) {
+		return;
+	}
+
+	g_return_if_fail(trans->flag & QQ_TRANS_IS_SERVER);
+	trans->flag |= QQ_TRANS_IS_REPLY;
+
+	if (trans->data)	g_free(trans->data);
+
+	trans->data = g_memdup(reply, reply_len);
+	trans->data_len = reply_len;
+}
+
 void qq_trans_add_remain(PurpleConnection *gc, guint16 cmd, guint16 seq,
 		guint8 *data, gint data_len)
 {
@@ -349,7 +381,7 @@
 			continue;
 		}
 
-		purple_debug_error("QQ_TRANS",
+		purple_debug_warning("QQ_TRANS",
 				"Resend [%d] %s data %p, len %d, send_retries %d\n",
 				trans->seq, qq_get_cmd_desc(trans->cmd),
 				trans->data, trans->data_len, trans->send_retries);
--- a/libpurple/protocols/qq/qq_trans.h	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/qq_trans.h	Mon Sep 15 03:02:06 2008 +0000
@@ -43,9 +43,10 @@
 void qq_trans_add_room_cmd(PurpleConnection *gc,
 		guint16 seq, guint8 room_cmd, guint32 room_id,
 		guint8 *data, gint data_len, gint update_class, guint32 ship32);
-
 void qq_trans_add_server_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq,
-	guint8 *data, gint data_len);
+	guint8 *rcved, gint rcved_len);
+void qq_trans_add_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq,
+		guint8 *reply, gint reply_len);
 void qq_trans_add_remain(PurpleConnection *gc, guint16 cmd, guint16 seq,
 	guint8 *data, gint data_len);
 
--- a/libpurple/protocols/qq/sys_msg.c	Mon Sep 15 03:01:03 2008 +0000
+++ b/libpurple/protocols/qq/sys_msg.c	Mon Sep 15 03:02:06 2008 +0000
@@ -178,9 +178,9 @@
 					_("Add"), G_CALLBACK(qq_add_buddy_with_gc_and_uid),
 				    _("Search"), G_CALLBACK(_qq_search_before_add_with_gc_and_uid));
 	} else {
-		message = g_strdup_printf(_("%s has added you [%s] to his or her buddy list"), from, to);
+		message = g_strdup_printf(_("%s added you [%s] to buddy list"), from, to);
 		_qq_sys_msg_log_write(gc, message, from);
-		purple_notify_info(gc, NULL, message, NULL);
+		purple_notify_info(gc, _("QQ Budy"), _("Successed:"), message);
 	}
 
 	g_free(name);
@@ -198,7 +198,7 @@
 	reason = g_strdup_printf(_("Message: %s"), msg_utf8);
 	_qq_sys_msg_log_write(gc, message, from);
 
-	purple_notify_info(gc, NULL, message, reason);
+	purple_notify_info(gc, _("QQ Buddy"), message, reason);
 	g_free(message);
 	g_free(reason);
 }
@@ -216,7 +216,7 @@
 
 	message = g_strdup_printf(_("Requestion approved by %s"), from);
 	_qq_sys_msg_log_write(gc, message, from);
-	purple_notify_info(gc, NULL, message, NULL);
+	purple_notify_info(gc, _("QQ Buddy"), _("Notice:"), message);
 
 	g_free(message);
 }
@@ -284,13 +284,13 @@
 
 	g_return_if_fail(from != NULL && to != NULL);
 
-	title = g_strdup_printf(_("QQ Server Notice from %s:"), from);
+	title = g_strdup_printf(_("From %s:"), from);
 	content = g_strdup_printf(_("%s"), msg_utf8);
 
 	if (qd->is_show_notice) {
-		purple_notify_info(gc, NULL, title, content);
+		purple_notify_info(gc, _("QQ Server Notice"), title, content);
 	} else {
-		purple_debug_info("QQ", "Server notice from %s:\n%s", from, msg_utf8);
+		purple_debug_info("QQ", "QQ Server notice from %s:\n%s", from, msg_utf8);
 }
 	g_free(title);
 	g_free(content);