Mercurial > pidgin
diff libpurple/protocols/qq/qq_process.c @ 24145:ec3f7d3e0445
2008.10.04 - lonicerae <lonicerae(at)gmail.com>
* fixed a bug in qq_base.c
author | SHiNE CsyFeK <csyfek@gmail.com> |
---|---|
date | Wed, 22 Oct 2008 14:49:38 +0000 |
parents | a95c7e71064c |
children | ce94189f15ad |
line wrap: on
line diff
--- a/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:48:46 2008 +0000 +++ b/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:49:38 2008 +0000 @@ -58,7 +58,7 @@ }; /* default process, decrypt and dump */ -static void process_unknow_cmd(PurpleConnection *gc,const gchar *title, guint8 *data, gint data_len, guint16 cmd, guint16 seq) +static void process_cmd_unknow(PurpleConnection *gc,const gchar *title, guint8 *data, gint data_len, guint16 cmd, guint16 seq) { qq_data *qd; gchar *msg_utf8 = NULL; @@ -81,285 +81,8 @@ } } -/* parse the reply to send_im */ -static void do_im_ack(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd; - - g_return_if_fail(data != NULL && data_len != 0); - - qd = gc->proto_data; - - if (data[0] != 0) { - purple_debug_warning("QQ", "Failed sent IM\n"); - purple_notify_error(gc, _("Error"), _("Failed to send IM."), NULL); - return; - } - - purple_debug_info("QQ", "OK sent IM\n"); -} - -static void do_server_news(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd = (qq_data *) gc->proto_data; - gint bytes; - 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); - - /* qq_show_packet("Rcv news", data, data_len); */ - - temp = g_newa(guint8, data_len); - bytes = 4; /* ignore unknown 4 bytes */ - - bytes += qq_get8(&temp_len, data + bytes); - g_return_if_fail(bytes + temp_len <= data_len); - bytes += qq_getdata(temp, temp_len, data+bytes); - title = g_strndup((gchar *)temp, temp_len); - - bytes += qq_get8(&temp_len, data + bytes); - g_return_if_fail(bytes + temp_len <= data_len); - bytes += qq_getdata(temp, temp_len, data+bytes); - brief = g_strndup((gchar *)temp, temp_len); - - bytes += qq_get8(&temp_len, data + bytes); - g_return_if_fail(bytes + temp_len <= data_len); - bytes += qq_getdata(temp, temp_len, data+bytes); - url = g_strndup((gchar *)temp, temp_len); - - title_utf8 = qq_to_utf8(title, QQ_CHARSET_DEFAULT); - content = g_strdup_printf(_("Server News:\n%s\n%s\n%s"), title, brief, url); - content_utf8 = qq_to_utf8(content, QQ_CHARSET_DEFAULT); - - if (qd->is_show_news) { - qq_got_attention(gc, content_utf8); - } else { - 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); - g_free(content_utf8); -} - -static void do_msg_sys_30(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint len; - guint8 reply; - gchar **segments, *msg_utf8; - - g_return_if_fail(data != NULL && data_len != 0); - - len = data_len; - - if (NULL == (segments = split_data(data, len, "\x2f", 2))) - return; - - reply = strtol(segments[0], NULL, 10); - if (reply == 1) - purple_debug_warning("QQ", "We are kicked out by QQ server\n"); - - msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT); - qq_got_attention(gc, msg_utf8); -} - -static void do_msg_sys_4c(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint bytes; - gint msg_len; - GString *content; - gchar *msg = NULL; - - g_return_if_fail(data != NULL && data_len > 0); - - bytes = 6; /* skip 0x(06 00 01 1e 01 1c)*/ - - content = g_string_new(""); - while (bytes < data_len) { - msg_len = qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data + bytes); - g_string_append(content, msg); - g_string_append(content, "\n"); - g_free(msg); - - if (msg_len <= 1) { - break; - } - bytes += msg_len; - } - if (bytes != data_len) { - purple_debug_warning("QQ", "Failed to read QQ_MSG_SYS_4C\n"); - qq_show_packet("do_msg_sys_4c", data, data_len); - } - qq_got_attention(gc, content->str); - g_string_free(content, FALSE); -} - -static const gchar *get_im_type_desc(gint type) -{ - switch (type) { - case QQ_MSG_TO_BUDDY: - return "QQ_MSG_TO_BUDDY"; - case QQ_MSG_TO_UNKNOWN: - return "QQ_MSG_TO_UNKNOWN"; - case QQ_MSG_UNKNOWN_QUN_IM: - return "QQ_MSG_UNKNOWN_QUN_IM"; - case QQ_MSG_ADD_TO_QUN: - return "QQ_MSG_ADD_TO_QUN"; - case QQ_MSG_DEL_FROM_QUN: - return "QQ_MSG_DEL_FROM_QUN"; - case QQ_MSG_APPLY_ADD_TO_QUN: - return "QQ_MSG_APPLY_ADD_TO_QUN"; - case QQ_MSG_CREATE_QUN: - return "QQ_MSG_CREATE_QUN"; - case QQ_MSG_SYS_30: - return "QQ_MSG_SYS_30"; - case QQ_MSG_SYS_4C: - return "QQ_MSG_SYS_4C"; - case QQ_MSG_APPROVE_APPLY_ADD_TO_QUN: - return "QQ_MSG_APPROVE_APPLY_ADD_TO_QUN"; - case QQ_MSG_REJCT_APPLY_ADD_TO_QUN: - return "QQ_MSG_REJCT_APPLY_ADD_TO_QUN"; - case QQ_MSG_TEMP_QUN_IM: - return "QQ_MSG_TEMP_QUN_IM"; - case QQ_MSG_QUN_IM: - return "QQ_MSG_QUN_IM"; - case QQ_MSG_NEWS: - return "QQ_MSG_NEWS"; - case QQ_MSG_EXTEND: - return "QQ_MSG_EXTEND"; - case QQ_MSG_EXTEND_85: - return "QQ_MSG_EXTEND_85"; - default: - return "QQ_MSG_UNKNOWN"; - } -} - -/* I receive a message, mainly it is text msg, - * but we need to proess other types (group etc) */ -static void process_private_msg(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc) -{ - qq_data *qd; - gint bytes; - - struct { - guint32 uid_from; - guint32 uid_to; - guint32 seq; - struct in_addr ip_from; - guint16 port_from; - guint16 msg_type; - } header; - - g_return_if_fail(data != NULL && data_len != 0); - - qd = (qq_data *) gc->proto_data; - - if (data_len < 16) { /* we need to ack with the first 16 bytes */ - purple_debug_error("QQ", "MSG is too short\n"); - return; - } else { - /* when we receive a message, - * we send an ACK which is the first 16 bytes of incoming packet */ - qq_send_server_reply(gc, QQ_CMD_RECV_IM, seq, data, 16); - } - - /* check len first */ - if (data_len < 20) { /* length of im_header */ - purple_debug_error("QQ", "Invald MSG header, len %d < 20\n", data_len); - return; - } - - bytes = 0; - bytes += qq_get32(&(header.uid_from), data + bytes); - bytes += qq_get32(&(header.uid_to), data + bytes); - bytes += qq_get32(&(header.seq), data + bytes); - /* if the message is delivered via server, it is server IP/port */ - bytes += qq_getIP(&(header.ip_from), data + bytes); - bytes += qq_get16(&(header.port_from), data + bytes); - bytes += qq_get16(&(header.msg_type), data + bytes); - /* im_header prepared */ - - if (header.uid_to != qd->uid) { /* should not happen */ - purple_debug_error("QQ", "MSG to [%d], NOT me\n", header.uid_to); - return; - } - - /* check bytes */ - if (bytes >= data_len - 1) { - purple_debug_warning("QQ", "Empty MSG\n"); - return; - } - - switch (header.msg_type) { - case QQ_MSG_NEWS: - do_server_news(data + bytes, data_len - bytes, gc); - break; - case QQ_MSG_EXTEND: - case QQ_MSG_EXTEND_85: - purple_debug_info("QQ", "MSG from buddy [%d]\n", header.uid_from); - qq_process_extend_im(gc, data + bytes, data_len - bytes); - break; - case QQ_MSG_TO_UNKNOWN: - case QQ_MSG_TO_BUDDY: - purple_debug_info("QQ", "MSG from buddy [%d]\n", header.uid_from); - qq_process_im(gc, data + bytes, data_len - bytes); - break; - case QQ_MSG_UNKNOWN_QUN_IM: - case QQ_MSG_TEMP_QUN_IM: - case QQ_MSG_QUN_IM: - purple_debug_info("QQ", "MSG from room [%d]\n", header.uid_from); - qq_process_room_msg_normal(data + bytes, data_len - bytes, header.uid_from, gc, header.msg_type); - break; - case QQ_MSG_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from [%d], Added\n", header.uid_from); - /* uid_from is group id - * we need this to create a dummy group and add to blist */ - qq_process_room_msg_been_added(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_DEL_FROM_QUN: - purple_debug_info("QQ", "Notice from room [%d], Removed\n", header.uid_from); - /* uid_from is group id */ - qq_process_room_msg_been_removed(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Joined\n", header.uid_from); - /* uid_from is group id */ - qq_process_room_msg_apply_join(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_APPROVE_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Confirm add in\n", - header.uid_from); - /* uid_from is group id */ - qq_process_room_msg_been_approved(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_REJCT_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Refuse add in\n", - header.uid_from); - /* uid_from is group id */ - qq_process_room_msg_been_rejected(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_SYS_30: - do_msg_sys_30(gc, data + bytes, data_len - bytes); - break; - case QQ_MSG_SYS_4C: - do_msg_sys_4c(gc, data + bytes, data_len - bytes); - break; - default: - purple_debug_warning("QQ", "MSG from [%d], unknown type %s [0x%04X]\n", - header.uid_from, get_im_type_desc(header.msg_type), header.msg_type); - qq_show_packet("Unknown MSG type", data, data_len); - break; - } -} - /* Send ACK if the sys message needs an ACK */ -static void request_server_ack(PurpleConnection *gc, guint8 code, guint32 from, guint16 seq) +static void ack_server_msg(PurpleConnection *gc, guint8 code, guint32 from, guint16 seq) { qq_data *qd; guint8 bar, *ack; @@ -389,7 +112,7 @@ "Fail creating sys msg ACK, expect %d bytes, build %d bytes\n", ack_len, bytes); } -static void do_server_notice(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) +static void process_server_notice(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) { qq_data *qd = (qq_data *) gc->proto_data; gchar *title, *content; @@ -425,7 +148,7 @@ to = segments[2]; msg = segments[3]; - request_server_ack(gc, code[0], strtol(from, NULL, 10), seq); + ack_server_msg(gc, code[0], strtol(from, NULL, 10), seq); if (strtol(to, NULL, 10) != qd->uid) { /* not to me */ purple_debug_error("QQ", "Recv sys msg to [%s], not me!, discard\n", to); @@ -450,7 +173,7 @@ qq_process_buddy_from_server(gc, funct, from, to, msg_utf8); break; case QQ_SERVER_NOTICE: - do_server_notice(gc, from, to, msg_utf8); + process_server_notice(gc, from, to, msg_utf8); break; case QQ_SERVER_NEW_CLIENT: purple_debug_warning("QQ", "QQ Server has newer client version\n"); @@ -493,7 +216,7 @@ /* now process the packet */ switch (cmd) { case QQ_CMD_RECV_IM: - process_private_msg(data, data_len, seq, gc); + qq_process_recv_im(data, data_len, seq, gc); break; case QQ_CMD_RECV_MSG_SYS: process_server_msg(data, data_len, seq, gc); @@ -502,7 +225,7 @@ qq_process_buddy_change_status(data, data_len, gc); break; default: - process_unknow_cmd(gc, _("Unknow SERVER CMD"), data, data_len, cmd, seq); + process_cmd_unknow(gc, _("Unknow SERVER CMD"), data, data_len, cmd, seq); break; } } @@ -898,16 +621,25 @@ case QQ_CMD_LOGIN: default: if (qd->client_version >= 2007) { + purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5\n"); data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_twice_md5); + if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5\n"); - } else { + purple_debug_warning("QQ", "Dpwd_twice_md5 *OK*\n"); + } + else { + purple_debug_warning("QQ", "Dpwd_twice_md5 *FAILED*, try login_key, last data_len=%d\n", data_len); data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.login_key); + if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by login_key\n"); + purple_debug_warning("QQ", "Dlogin_key *OK*\n"); + } + else { + purple_debug_warning("QQ", "Dlogin_key *FAILED*\n"); } } - } else { + } + else { /* May use password_twice_md5 in the past version like QQ2005 */ data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.random_key); if (data_len >= 0) { @@ -933,6 +665,7 @@ return QQ_LOGIN_REPLY_ERR; } + purple_debug_warning("QQ", "we are processing: 0x%02x\n", cmd); switch (cmd) { case QQ_CMD_GET_SERVER: ret_8 = qq_process_get_server(gc, data, data_len); @@ -958,7 +691,7 @@ case QQ_CMD_CHECK_PWD: ret_8 = qq_process_check_pwd(gc, data, data_len); if (ret_8 != QQ_LOGIN_REPLY_OK) { - return ret_8; + return ret_8; } if (qd->client_version == 2008) { qq_request_login_2008(gc); @@ -975,7 +708,7 @@ ret_8 = qq_process_login(gc, data, data_len); } if (ret_8 != QQ_LOGIN_REPLY_OK) { - return ret_8; + return ret_8; } purple_connection_update_progress(gc, _("Logined"), QQ_CONNECT_STEPS - 1, QQ_CONNECT_STEPS); @@ -992,7 +725,8 @@ qq_update_all(gc, 0); break; default: - process_unknow_cmd(gc, _("Unknow LOGIN CMD"), data, data_len, cmd, seq); + purple_debug_warning("QQ", "UNKNOWN LOGIN CMD: %d\n", cmd); + process_cmd_unknow(gc, _("Unknow LOGIN CMD"), data, data_len, cmd, seq); return QQ_LOGIN_REPLY_ERR; } return QQ_LOGIN_REPLY_OK; @@ -1056,7 +790,7 @@ qq_process_change_status_reply(data, data_len, gc); break; case QQ_CMD_SEND_IM: - do_im_ack(data, data_len, gc); + qq_process_send_im_reply(data, data_len, gc); break; case QQ_CMD_KEEP_ALIVE: if (qd->client_version >= 2008) { @@ -1099,7 +833,7 @@ purple_debug_info("QQ", "All buddies and groups received\n"); break; default: - process_unknow_cmd(gc, _("Unknow CLIENT CMD"), data, data_len, cmd, seq); + process_cmd_unknow(gc, _("Unknow CLIENT CMD"), data, data_len, cmd, seq); is_unknow = TRUE; break; }