summaryrefslogtreecommitdiff
path: root/libpurple/protocols/qq/qq_process.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpurple/protocols/qq/qq_process.c')
-rw-r--r--libpurple/protocols/qq/qq_process.c284
1 files changed, 260 insertions, 24 deletions
diff --git a/libpurple/protocols/qq/qq_process.c b/libpurple/protocols/qq/qq_process.c
index 2b8749d000..b1fafb1762 100644
--- a/libpurple/protocols/qq/qq_process.c
+++ b/libpurple/protocols/qq/qq_process.c
@@ -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 @@ static void process_cmd_unknow(PurpleConnection *gc,gchar *title, guint8 *buf, g
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 @@ static void process_cmd_login(PurpleConnection *gc, guint8 *data, gint data_len)
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,222 @@ static void process_cmd_login(PurpleConnection *gc, guint8 *data, gint data_len)
}
}
+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;
+
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 +485,11 @@ void qq_proc_cmd_reply(PurpleConnection *gc,
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");
}