diff libpurple/protocols/qq/qq_process.c @ 23753:5f454b975a99

2008.08.10 - csyfek <csyfek(at)gmail.com> * Commit to Pidgin 2008.08.06 - ccpaging <ecc_hy(at)hotmail.com> * Rename names of variables, Group, to Room * Functions of group_network merged into qq_network and qq_process * Canceled managing glist of group packet, add sub_cmdd and room_id to transaction * Fixed error of demo group: If 'room list' and 'room infor' are not setup, response received from server will emits 'room_id = 0' packet. 2008.08.04 - ccpaging <ecc_hy(at)hotmail.com> * Use new crypt/decrypt functions * Rename crypt.c/h to qq_crypt.c/h * Clean code of decrypt functions * Fixed decryption failure 2008.08.04 - csyfek <csyfek(at)gmail.com> * Update AUTHORS
author SHiNE CsyFeK <csyfek@gmail.com>
date Sun, 10 Aug 2008 04:32:14 +0000
parents eba700811832
children 967344bc404d e16982ad923f
line wrap: on
line diff
--- a/libpurple/protocols/qq/qq_process.c	Sat Aug 09 23:23:48 2008 +0000
+++ b/libpurple/protocols/qq/qq_process.c	Sun Aug 10 04:32:14 2008 +0000
@@ -37,8 +37,17 @@
 #include "group_info.h"
 #include "group_free.h"
 #include "char_conv.h"
-#include "crypt.h"
-#include "group_network.h"
+#include "qq_crypt.h"
+
+#include "group_conv.h"
+#include "group_find.h"
+#include "group_internal.h"
+#include "group_im.h"
+#include "group_info.h"
+#include "group_join.h"
+#include "group_opt.h"
+#include "group_search.h"
+
 #include "header_info.h"
 #include "qq_base.h"
 #include "im.h"
@@ -49,28 +58,24 @@
 #include "sys_msg.h"
 #include "utils.h"
 
+enum {
+	QQ_ROOM_CMD_REPLY_OK = 0x00,
+	QQ_ROOM_CMD_REPLY_SEARCH_ERROR = 0x02,
+	QQ_ROOM_CMD_REPLY_NOT_MEMBER = 0x0a
+};
+
 /* default process, decrypt and dump */
-static void process_cmd_unknow(PurpleConnection *gc,gchar *title, guint8 *buf, gint buf_len, guint16 cmd, guint16 seq)
+static void process_cmd_unknow(PurpleConnection *gc,gchar *title, guint8 *data, gint data_len, guint16 cmd, guint16 seq)
 {
 	qq_data *qd;
-	guint8 *data;
-	gint data_len;
 	gchar *msg_utf8 = NULL;
 
-	g_return_if_fail(buf != NULL && buf_len != 0);
+	g_return_if_fail(data != NULL && data_len != 0);
 
-	qq_show_packet(title, buf, buf_len);
+	qq_show_packet(title, data, data_len);
 
 	qd = (qq_data *) gc->proto_data;
 
-	data_len = buf_len;
-	data = g_newa(guint8, data_len);
-	memset(data, 0, data_len);
-	if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &data_len )) {
-		purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail decrypt packet with default process\n");
-		return;
-	}
-	
 	qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ",
 			data, data_len,
 			">>> [%d] %s -> [default] decrypt and dump",
@@ -78,13 +83,39 @@
 
 	msg_utf8 = try_dump_as_gbk(data, data_len);
 	if (msg_utf8) {
+		purple_notify_info(gc, NULL, msg_utf8, NULL);
 		g_free(msg_utf8);
 	}
 }
 
 void qq_proc_cmd_server(PurpleConnection *gc,
-	guint16 cmd, guint16 seq, guint8 *data, gint data_len)
+	guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len)
 {
+	qq_data *qd;
+
+	guint8 *data;
+	gint data_len;
+
+	g_return_if_fail (gc != NULL && gc->proto_data != NULL);
+	qd = (qq_data *) gc->proto_data;
+
+	data = g_newa(guint8, rcved_len);
+	data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
+	if (data_len < 0) {
+		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+			"Can not decrypt server cmd by session key, [%05d], 0x%04X %s, len %d\n", 
+			seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
+		qq_show_packet("Can not decrypted", rcved, rcved_len);
+		return;
+	}
+
+	if (data_len <= 0) {
+		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+			"Server cmd decrypted is empty, [%05d], 0x%04X %s, len %d\n", 
+			seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
+		return;
+	}
+	
 	/* now process the packet */
 	switch (cmd) {
 		case QQ_CMD_RECV_IM:
@@ -134,7 +165,7 @@
 		qq_send_packet_get_buddies_list(gc, 0);
 
 		/* refresh groups */
-		qq_send_packet_get_all_list_with_group(gc, 0);
+		qq_send_packet_get_buddies_and_rooms(gc, 0);
 
 		return;
 	}
@@ -168,14 +199,223 @@
 	}
 }
 
+static void process_room_cmd_notify(PurpleConnection *gc, 
+	guint8 room_cmd, guint8 room_id, guint8 reply_cmd, guint8 reply, guint8 *data, gint data_len)
+{
+	gchar *msg, *msg_utf8;
+	g_return_if_fail(data != NULL && data_len > 0);
+
+	msg = g_strndup((gchar *) data, data_len);	/* it will append 0x00 */
+	msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
+	g_free(msg);
+	
+	msg = g_strdup_printf(_(
+		"Reply %s(0x%02X )\n"
+		"Sent %s(0x%02X )\n"
+		"Room id %d, reply [0x%02X]: \n"
+		"%s"), 
+		qq_get_room_cmd_desc(reply_cmd), reply_cmd, 
+		qq_get_room_cmd_desc(room_cmd), room_cmd, 
+		room_id, reply, msg_utf8);
+		
+	purple_notify_error(gc, NULL, _("Failed room reply"), msg);
+	g_free(msg);
+	g_free(msg_utf8);
+}
+
+void qq_proc_room_cmd_reply(PurpleConnection *gc,
+	guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len)
+{
+	qq_data *qd;
+	guint8 *data;
+	gint data_len;
+	qq_group *group;
+	gint bytes;
+	guint8 reply_cmd, reply;
+
+	g_return_if_fail (gc != NULL && gc->proto_data != NULL);
+	qd = (qq_data *) gc->proto_data;
+
+	data = g_newa(guint8, rcved_len);
+	data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
+	if (data_len < 0) {
+		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+			"Can not decrypt room cmd by session key, [%05d], 0x%02X %s for %d, len %d\n", 
+			seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+		qq_show_packet("Can not decrypted", rcved, rcved_len);
+		return;
+	}
+
+	if (room_id <= 0) {
+		purple_debug(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;
+	}
+
+	if (data_len <= 2) {
+		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+			"Invaild len of room cmd decrypted, [%05d], 0x%02X %s for %d, len %d\n", 
+			seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+		return;
+	}
+	
+	group = qq_room_search_id(gc, room_id);
+	if (group == NULL) {
+		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+			"Missing room id in [%05d], 0x%02X %s for %d, len %d\n", 
+			seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+	}
+	
+	bytes = 0;
+	bytes += qq_get8(&reply_cmd, data + bytes);
+	bytes += qq_get8(&reply, data + bytes);
+
+	if (reply_cmd != room_cmd) {
+		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+			"Missing room cmd in reply 0x%02X %s, [%05d], 0x%02X %s for %d, len %d\n", 
+			reply_cmd, qq_get_room_cmd_desc(reply_cmd),
+			seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+	}
+	
+	/* now process the packet */
+	if (reply != QQ_ROOM_CMD_REPLY_OK) {
+		if (group != NULL) {
+			qq_set_pending_id(&qd->joining_groups, group->ext_id, FALSE);
+		}
+		
+		switch (reply) {	/* this should be all errors */
+		case QQ_ROOM_CMD_REPLY_NOT_MEMBER:
+			if (group != NULL) {
+				purple_debug(PURPLE_DEBUG_WARNING,
+					   "QQ",
+					   _("You are not a member of group \"%s\"\n"), group->group_name_utf8);
+				group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
+				qq_group_refresh(gc, group);
+			}
+			break;
+		case QQ_ROOM_CMD_REPLY_SEARCH_ERROR:
+			if (qd->roomlist != NULL) {
+				if (purple_roomlist_get_in_progress(qd->roomlist))
+					purple_roomlist_set_in_progress(qd->roomlist, FALSE);
+			}
+		default:
+			process_room_cmd_notify(gc, room_cmd, room_id, reply_cmd, reply, data + bytes, data_len - bytes);
+		}
+		return;
+	}
+
+	/* seems ok so far, so we process the reply according to sub_cmd */
+	switch (reply_cmd) {
+	case QQ_ROOM_CMD_GET_INFO:
+		qq_process_room_cmd_get_info(data + bytes, data_len - bytes, gc);
+		if (group != NULL) {
+			qq_send_cmd_group_get_members_info(gc, group);
+			qq_send_cmd_group_get_online_members(gc, group);
+		}
+		break;
+	case QQ_ROOM_CMD_CREATE:
+		qq_group_process_create_group_reply(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_CHANGE_INFO:
+		qq_group_process_modify_info_reply(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_MEMBER_OPT:
+		qq_group_process_modify_members_reply(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_ACTIVATE:
+		qq_group_process_activate_group_reply(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_SEARCH:
+		qq_process_group_cmd_search_group(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_JOIN:
+		qq_process_group_cmd_join_group(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_AUTH:
+		qq_process_group_cmd_join_group_auth(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_QUIT:
+		qq_process_group_cmd_exit_group(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_SEND_MSG:
+		qq_process_group_cmd_im(data + bytes, data_len - bytes, gc);
+		break;
+	case QQ_ROOM_CMD_GET_ONLINES:
+		qq_process_room_cmd_get_onlines(data + bytes, data_len - bytes, gc);
+		if (group != NULL)
+			qq_group_conv_refresh_online_member(gc, group);
+		break;
+	case QQ_ROOM_CMD_GET_MEMBER_INFO:
+		qq_process_room_cmd_get_members(data + bytes, data_len - bytes, gc);
+		if (group != NULL)
+			qq_group_conv_refresh_online_member(gc, group);
+		break;
+	default:
+		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+			   "Unknow room cmd 0x%02X %s\n", 
+			   reply_cmd, qq_get_room_cmd_desc(reply_cmd));
+	}
+}
+
 void qq_proc_cmd_reply(PurpleConnection *gc,
-	guint16 cmd, guint16 seq, guint8 *data, gint data_len)
+	guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len)
 {
+	qq_data *qd;
+
+	guint8 *data;
+	gint data_len;
+
+	gboolean ret_bool = FALSE;
 	guint8 ret_8 = 0;
 	guint16 ret_16 = 0;
 	guint32 ret_32 = 0;
 	gchar *error_msg = NULL;
 
+	g_return_if_fail(rcved_len > 0);
+
+	g_return_if_fail (gc != NULL && gc->proto_data != NULL);
+	qd = (qq_data *) gc->proto_data;
+
+	data = g_newa(guint8, rcved_len);
+	if (cmd == QQ_CMD_TOKEN) {
+		g_memmove(data, rcved, rcved_len);
+		data_len = rcved_len;
+	} else if (cmd == QQ_CMD_LOGIN) {
+		/* May use password_twice_md5 in the past version like QQ2005*/
+		data_len = qq_decrypt(data, rcved, rcved_len, qd->inikey);
+		if (data_len >= 0) {
+			purple_debug(PURPLE_DEBUG_WARNING, "QQ", 
+					"Decrypt login reply packet with inikey, %d bytes\n", data_len);
+		} else {
+			data_len = qq_decrypt(data, rcved, rcved_len, qd->password_twice_md5);
+			if (data_len >= 0) {
+				purple_debug(PURPLE_DEBUG_WARNING, "QQ", 
+					"Decrypt login reply packet with password_twice_md5, %d bytes\n", data_len);
+			} else {
+				purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 
+					_("Can not decrypt login reply"));
+				return;
+			}
+		}
+	} else {
+		data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
+		if (data_len < 0) {
+			purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+				"Can not reply by session key, [%05d], 0x%04X %s, len %d\n", 
+				seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
+			qq_show_packet("Can not decrypted", rcved, rcved_len);
+			return;
+		}
+	}
+	
+	if (data_len <= 0) {
+		purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+			"Reply decrypted is empty, [%05d], 0x%04X %s, len %d\n", 
+			seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
+		return;
+	}
+
 	switch (cmd) {
 		case QQ_CMD_TOKEN:
 			ret_8 = qq_process_token_reply(gc, error_msg, data, data_len);
@@ -246,14 +486,11 @@
 				qq_send_packet_get_buddies_online(gc, 0);
 			}
 			break;
-		case QQ_CMD_GROUP_CMD:
-			qq_process_group_cmd_reply(data, data_len, seq, gc);
-			break;
-		case QQ_CMD_GET_ALL_LIST_WITH_GROUP:
-			ret_32 = qq_process_get_all_list_with_group_reply(data, data_len, gc);
+		case QQ_CMD_GET_BUDDIES_AND_ROOMS:
+			ret_32 = qq_process_get_buddies_and_rooms(data, data_len, gc);
 			if (ret_32 > 0 && ret_32 < 0xffffffff) {
 				purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n");
-				qq_send_packet_get_all_list_with_group(gc, ret_32);
+				qq_send_packet_get_buddies_and_rooms(gc, ret_32);
 			} else {
 				purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies and groups received\n"); 
 			}