# HG changeset patch # User SHiNE CsyFeK # Date 1224686543 0 # Node ID 832178d951ca290d0de6d2fd77ba265f6f5921a0 # Parent dc112387190f9349ce2d560a15018fd8cf6bab3e 2008.09.30 - ccpaging * Successfully login using 2007/2008 protocols diff -r dc112387190f -r 832178d951ca libpurple/protocols/qq/ChangeLog --- a/libpurple/protocols/qq/ChangeLog Wed Oct 22 14:41:13 2008 +0000 +++ b/libpurple/protocols/qq/ChangeLog Wed Oct 22 14:42:23 2008 +0000 @@ -1,3 +1,6 @@ +2008.09.30 - ccpaging + * Successfully login using 2007/2008 protocols + 2008.09.29 - ccpaging * 'Check Password' function for protocol 2007/2008 diff -r dc112387190f -r 832178d951ca libpurple/protocols/qq/qq.c --- a/libpurple/protocols/qq/qq.c Wed Oct 22 14:41:13 2008 +0000 +++ b/libpurple/protocols/qq/qq.c Wed Oct 22 14:42:23 2008 +0000 @@ -219,6 +219,7 @@ qq_disconnect(gc); + if (qd->redirect) g_free(qd->redirect); if (qd->ld.token) g_free(qd->ld.token); if (qd->ld.token_ex) g_free(qd->ld.token_ex); if (qd->captcha.token) g_free(qd->captcha.token); diff -r dc112387190f -r 832178d951ca libpurple/protocols/qq/qq.h --- a/libpurple/protocols/qq/qq.h Wed Oct 22 14:41:13 2008 +0000 +++ b/libpurple/protocols/qq/qq.h Wed Oct 22 14:42:23 2008 +0000 @@ -41,7 +41,6 @@ typedef struct _qq_interval qq_interval; typedef struct _qq_net_stat qq_net_stat; typedef struct _qq_add_request qq_add_request; -typedef struct _qq_redirect_data qq_redirect_data; typedef struct _qq_login_data qq_login_data; typedef struct _qq_captcha_data qq_captcha_data; @@ -68,14 +67,6 @@ guint8 login_key[QQ_KEY_LENGTH]; }; -struct _qq_redirect_data { - guint16 ret; - guint8 b1; - guint32 w1; - guint32 w2; - struct in_addr ip; -}; - struct _qq_add_request { guint32 uid; PurpleConnection *gc; @@ -150,7 +141,8 @@ struct in_addr redirect_ip; guint16 redirect_port; - qq_redirect_data redirect_data; + guint8 *redirect; + guint8 redirect_len; guint check_watcher; guint connect_watcher; diff -r dc112387190f -r 832178d951ca libpurple/protocols/qq/qq_base.c --- a/libpurple/protocols/qq/qq_base.c Wed Oct 22 14:41:13 2008 +0000 +++ b/libpurple/protocols/qq/qq_base.c Wed Oct 22 14:42:23 2008 +0000 @@ -509,17 +509,19 @@ g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; - raw_data = g_newa(guint8, sizeof(qd->redirect_data)); - memset(raw_data, 0, sizeof(qd->redirect_data)); + raw_data = g_newa(guint8, 128); + memset(raw_data, 0, 128); - encrypted = g_newa(guint8, sizeof(qd->redirect_data) + 16); /* 16 bytes more */ + encrypted = g_newa(guint8, 128 + 16); /* 16 bytes more */ bytes = 0; - bytes += qq_put16(raw_data + bytes, qd->redirect_data.ret); - bytes += qq_put8(raw_data + bytes, qd->redirect_data.b1); - bytes += qq_put32(raw_data + bytes, qd->redirect_data.w1); - bytes += qq_put32(raw_data + bytes, qd->redirect_data.w2); - bytes += qq_putIP(raw_data + bytes, &(qd->redirect_data.ip)); + if (qd->redirect == NULL) { + /* first packet to get server */ + qd->redirect_len = 15; + qd->redirect = g_realloc(qd->redirect, qd->redirect_len); + memset(qd->redirect, 0, qd->redirect_len); + } + bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len); encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); @@ -537,6 +539,7 @@ { qq_data *qd; gint bytes; + guint16 ret; g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); qd = (qq_data *) gc->proto_data; @@ -545,9 +548,9 @@ /* qq_show_packet("Get Server", data, data_len); */ bytes = 0; - bytes += qq_get16(&qd->redirect_data.ret, data + bytes); - if (qd->redirect_data.ret == 0) { - memset(&qd->redirect_data, 0, sizeof(qd->redirect_data)); + bytes += qq_get16(&ret, data + bytes); + if (ret == 0) { + /* Notice: do not clear redirect_data here. It will be used in login*/ qd->redirect_ip.s_addr = 0; return QQ_LOGIN_REPLY_OK; } @@ -559,15 +562,13 @@ return QQ_LOGIN_REPLY_ERR; } - bytes += qq_get8(&qd->redirect_data.b1, data + bytes); - bytes += qq_get32(&qd->redirect_data.w1, data + bytes); - bytes += qq_get32(&qd->redirect_data.w2, data + bytes); - bytes += qq_getIP(&qd->redirect_data.ip, data + bytes); - purple_debug_info("QQ", "Get server %d-%d-%d%d, %s\n", - qd->redirect_data.ret, qd->redirect_data.b1, qd->redirect_data.w1, qd->redirect_data.w2, - inet_ntoa(qd->redirect_data.ip)); + qd->redirect_len = data_len; + qd->redirect = g_realloc(qd->redirect, qd->redirect_len); + qq_getdata(qd->redirect, qd->redirect_len, data); + qq_show_packet("Redirect to", qd->redirect, qd->redirect_len); - g_memmove(&qd->redirect_ip, &qd->redirect_data.ip, sizeof(qd->redirect_ip)); + qq_getIP(&qd->redirect_ip, data + 11); + purple_debug_info("QQ", "Get server %s\n", inet_ntoa(qd->redirect_ip)); return QQ_LOGIN_REPLY_REDIRECT; } @@ -809,10 +810,8 @@ bytes += qq_get8(&reply, data + bytes); bytes += qq_get16(&(qd->ld.token_ex_len), data + bytes); - if (qd->ld.token_ex != NULL) g_free(qd->ld.token_ex); - qd->ld.token_ex = g_new0(guint8, qd->ld.token_ex_len); + qd->ld.token_ex = g_realloc(qd->ld.token_ex, qd->ld.token_ex_len); bytes += qq_getdata(qd->ld.token_ex, qd->ld.token_ex_len , data + bytes); - if(reply != 1) { purple_debug_info("QQ", "Captcha verified, result %d\n", reply); @@ -877,221 +876,7 @@ return crc ^ 0xffffffffL; } -void qq_request_check_pwd_2007(PurpleConnection *gc) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - gint count; - static guint8 header[] = { - 0x00, 0x5F, 0x00, 0x00, 0x08, 0x04, 0x01, 0xE0 - }; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); - memset(raw_data, 0, MAX_PACKET_SIZE - 16); - - encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ - - /* Encrypted password and put in encrypted */ - bytes = 0; - bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); - bytes += qq_put16(raw_data + bytes, rand() & 0); - bytes += qq_put16(raw_data + bytes, rand() & 0xffff); - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); - /* create packet */ - bytes = 0; - bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); - /* token get from qq_process_token_ex */ - bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len); - bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); - /* password encrypted */ - bytes += qq_put16(raw_data + bytes, encrypted_len); - bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* random data, 20 bytes */ - bytes += qq_put16(raw_data + bytes, 0x0014); /* length of next segment*/ - count = 0x14; - while (count--) bytes += qq_put8(raw_data + bytes, rand() & 0xff); - /* put length into first 2 bytes */ - qq_put16(raw_data, bytes - 2); - /* tail */ - bytes += qq_put8(raw_data + bytes, 0); /* length of next segment */ - bytes += qq_put8(raw_data + bytes, 0x03); /* length of next segment */ - bytes += qq_put8(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]); - bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]); - qq_show_packet("QQ", raw_data, bytes); - /* Encrypted by random key*/ - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE); -} - -guint8 qq_process_check_pwd_2007( PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - int bytes; - guint8 ret; - guint16 unknown_len; - gchar *error = NULL; - gchar *msg, *msg_utf8; - guint16 msg_len; - PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - - g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); - qd = (qq_data *) gc->proto_data; - - bytes = 2; // skip 2 bytes - bytes += qq_get8(&ret, data + bytes); - bytes += 4; // skip 4 bytes - /* 2 unknow */ - bytes += qq_get16(&unknown_len, data + bytes); - bytes += unknown_len; - bytes += qq_get16(&unknown_len, data + bytes); - bytes += unknown_len; - if (ret == QQ_LOGIN_REPLY_OK) { - /* get login_token */ - bytes += qq_get16(&qd->ld.login_token_len, data + bytes); - if (qd->ld.login_token != NULL) g_free(qd->ld.login_token); - qd->ld.login_token = g_new0(guint8, qd->ld.login_token_len); - bytes += qq_getdata(qd->ld.login_token, qd->ld.login_token_len, data + bytes); - /* get login_key */ - bytes += qq_getdata(qd->ld.login_key, sizeof(qd->ld.login_key), data + bytes); - return QQ_LOGIN_REPLY_OK; - } - - switch (ret) - { - case 0x34: /* invalid password, 2nd byte is 0xc6 */ - if (!purple_account_get_remember_password(gc->account)) { - purple_account_set_password(gc->account, NULL); - } - error = g_strdup(_("Error password")); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - case 0x33: /* need activation */ - case 0x51: /* need activation */ - error = g_strdup(_("Need active")); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - case 0xBF: /* uid is not exist */ - error = g_strdup(_("invalid user name")); - reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME; - break; - default: - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, - ">>> [default] decrypt and dump"); - error = g_strdup_printf( - _("Unknow reply code when checking password (0x%02X)"), - ret ); - reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; - break; - } - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, - ">>> [default] decrypt and dump"); - bytes = 11; - bytes += qq_get16(&msg_len, data + bytes); - - msg = g_strndup((gchar *)data + bytes, msg_len); - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - - purple_debug_error("QQ", "%s:\n%s\n", error, msg_utf8); - purple_connection_error_reason(gc, reason, msg_utf8); - - g_free(error); - g_free(msg); - g_free(msg_utf8); - return QQ_LOGIN_REPLY_ERR; -} - -guint8 qq_process_check_pwd_2008( PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - int bytes; - guint8 ret; - gchar *error = NULL; - gchar *msg, *msg_utf8; - guint16 msg_len; - PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - - g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); - qd = (qq_data *) gc->proto_data; - - bytes = 1; // skip 1 bytes, always 0 - bytes += qq_get8(&ret, data + bytes); - if (ret == 0x97) { - /* get login_token */ - bytes += qq_get16(&qd->ld.login_token_len, data); - if (qd->ld.login_token != NULL) g_free(qd->ld.login_token); - qd->ld.login_token = g_new0(guint8, qd->ld.login_token_len); - bytes += qq_getdata(qd->ld.login_token, qd->ld.login_token_len, data + bytes); - /* get login_key */ - bytes += qq_getdata(qd->ld.login_key, sizeof(qd->ld.login_key), data + bytes); - return QQ_LOGIN_REPLY_OK; - } - - switch (ret) - { - case 0xc6: /* invalid password */ - if (!purple_account_get_remember_password(gc->account)) { - purple_account_set_password(gc->account, NULL); - } - error = g_strdup(_("Error password")); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - case 0x33: /* need activation */ - case 0x51: /* need activation */ - error = g_strdup(_("Need active")); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - case 0xBF: /* uid is not exist */ - error = g_strdup(_("invalid user name")); - reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME; - break; - default: - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, - ">>> [default] decrypt and dump"); - error = g_strdup_printf( - _("Unknow reply code when checking password (0x%02X)"), - ret ); - reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; - break; - } - - bytes = 11; - bytes += qq_get16(&msg_len, data + bytes); - - msg = g_strndup((gchar *)data + bytes, msg_len); - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - - purple_debug_error("QQ", "%s: %s\n", error, msg_utf8); - purple_connection_error_reason(gc, reason, msg_utf8); - - g_free(error); - g_free(msg); - g_free(msg_utf8); - return QQ_LOGIN_REPLY_ERR; -} - -void qq_request_check_pwd_2008(PurpleConnection *gc) +void qq_request_check_pwd(PurpleConnection *gc) { qq_data *qd; guint8 *buf, *raw_data; @@ -1138,15 +923,17 @@ bytes += qq_putdata(raw_data + bytes, unknown, sizeof(unknown)); bytes += qq_put32( raw_data + bytes, crc32(0xFFFFFFFF, unknown, sizeof(unknown))); + /* put length into first 2 bytes */ - qq_put16(raw_data, bytes - 2); + qq_put8(raw_data + 1, bytes - 2); + /* tail */ bytes += qq_put16(raw_data + bytes, 0x0003); bytes += qq_put8(raw_data + bytes, 0); bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]); bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]); - qq_show_packet("Check password", raw_data, bytes); + /* qq_show_packet("Check password", raw_data, bytes); */ /* Encrypted by random key*/ encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); @@ -1160,6 +947,89 @@ qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE); } +guint8 qq_process_check_pwd( PurpleConnection *gc, guint8 *data, gint data_len) +{ + qq_data *qd; + int bytes; + guint8 ret; + gchar *error = NULL; + guint16 unknow_token_len; + gchar *msg, *msg_utf8; + guint16 msg_len; + PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; + + g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); + + g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); + qd = (qq_data *) gc->proto_data; + + /* qq_show_packet("Check password reply", data, data_len); */ + + bytes = 0; + bytes += qq_get16(&unknow_token_len, data + bytes); /* maybe total length */ + bytes += qq_get8(&ret, data + bytes); + bytes += 4; /* 0x(00 00 6d b9) */ + /* unknow_token_len may 0 when not reply ok*/ + bytes += qq_get16(&unknow_token_len, data + bytes); /* 0x0020 */ + bytes += unknow_token_len; + bytes += qq_get16(&unknow_token_len, data + bytes); /* 0x0020 */ + bytes += unknow_token_len; + + if (ret == 0) { + /* get login_token */ + bytes += qq_get16(&qd->ld.login_token_len, data + bytes); + if (qd->ld.login_token != NULL) g_free(qd->ld.login_token); + qd->ld.login_token = g_new0(guint8, qd->ld.login_token_len); + bytes += qq_getdata(qd->ld.login_token, qd->ld.login_token_len, data + bytes); + qq_show_packet("Get login token", qd->ld.login_token, qd->ld.login_token_len); + /* get login_key */ + bytes += qq_getdata(qd->ld.login_key, sizeof(qd->ld.login_key), data + bytes); + qq_show_packet("Get login key", qd->ld.login_key, sizeof(qd->ld.login_key)); + return QQ_LOGIN_REPLY_OK; + } + + switch (ret) + { + case 0x34: /* invalid password */ + if (!purple_account_get_remember_password(gc->account)) { + purple_account_set_password(gc->account, NULL); + } + error = g_strdup(_("Error password")); + reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; + break; + case 0x33: /* need activation */ + case 0x51: /* need activation */ + error = g_strdup(_("Need active")); + reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; + break; + case 0xBF: /* uid is not exist */ + error = g_strdup(_("invalid user name")); + reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME; + break; + default: + qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, + ">>> [default] decrypt and dump"); + error = g_strdup_printf( + _("Unknow reply code when checking password (0x%02X)"), + ret ); + reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; + break; + } + + bytes += qq_get16(&msg_len, data + bytes); + + msg = g_strndup((gchar *)data + bytes, msg_len); + msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); + + purple_debug_error("QQ", "%s: %s\n", error, msg_utf8); + purple_connection_error_reason(gc, reason, msg_utf8); + + g_free(error); + g_free(msg); + g_free(msg_utf8); + return QQ_LOGIN_REPLY_ERR; +} + void qq_request_login_2007(PurpleConnection *gc) { qq_data *qd; @@ -1208,7 +1078,7 @@ /* create packet */ bytes = 0; - bytes += qq_put16(raw_data + bytes, 0); + bytes += qq_put16(raw_data + bytes, 0); /* Unknow */ /* password encrypted */ bytes += qq_put16(raw_data + bytes, encrypted_len); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); @@ -1216,28 +1086,30 @@ encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); g_return_if_fail(encrypted_len == 16); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* unknow fill */ + /* unknow fill 0 */ memset(raw_data + bytes, 0, 19); bytes += 19; bytes += qq_putdata(raw_data + bytes, login_1_16, sizeof(login_1_16)); - bytes += qq_put8(raw_data + bytes, (guint8)rand() & 0xff); + bytes += qq_put8(raw_data + bytes, rand() & 0xff); bytes += qq_put8(raw_data + bytes, qd->login_mode); /* unknow 10 bytes zero filled*/ memset(raw_data + bytes, 0, 10); bytes += 10; /* redirect data, 15 bytes */ - bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); + bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len); /* unknow fill */ bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16)); /* captcha token get from qq_process_token_ex */ - bytes += qq_put8(raw_data + bytes, qd->captcha.token_len); - bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); + bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len); + bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); /* unknow fill */ bytes += qq_putdata(raw_data + bytes, login_3_83, sizeof(login_3_83)); memset(raw_data + bytes, 0, 332 - sizeof(login_3_83)); bytes += 332 - sizeof(login_3_83); + qq_show_packet("Login", raw_data, bytes); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key); buf = g_newa(guint8, MAX_PACKET_SIZE); @@ -1362,7 +1234,6 @@ /* create packet */ bytes = 0; bytes += qq_put16(raw_data + bytes, 0); /* Unknow */ - bytes += qq_put8(raw_data + bytes, 0); /* Separator */ /* password encrypted */ bytes += qq_put16(raw_data + bytes, encrypted_len); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); @@ -1387,12 +1258,12 @@ memset(raw_data + bytes, 0, 10); bytes += 10; /* redirect data, 15 bytes */ - bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); + bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len); /* unknow fill */ bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16)); /* captcha token get from qq_process_token_ex */ - bytes += qq_put8(raw_data + bytes, qd->captcha.token_len); - bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); + bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len); + bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); /* unknow fill */ bytes += qq_putdata(raw_data + bytes, login_3_18, sizeof(login_3_18)); bytes += qq_put8(raw_data + bytes , sizeof(login_4_16)); @@ -1401,7 +1272,7 @@ memset(raw_data + bytes, 0, 10); bytes += 10; /* redirect data, 15 bytes */ - bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); + bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len); /* unknow fill */ bytes += qq_putdata(raw_data + bytes, login_5_6, sizeof(login_5_6)); bytes += qq_put8(raw_data + bytes , sizeof(login_6_16)); @@ -1410,6 +1281,7 @@ memset(raw_data + bytes, 0, 249); bytes += 249; + qq_show_packet("Login request", raw_data, bytes); encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key); buf = g_newa(guint8, MAX_PACKET_SIZE); diff -r dc112387190f -r 832178d951ca libpurple/protocols/qq/qq_base.h --- a/libpurple/protocols/qq/qq_base.h Wed Oct 22 14:41:13 2008 +0000 +++ b/libpurple/protocols/qq/qq_base.h Wed Oct 22 14:42:23 2008 +0000 @@ -61,11 +61,8 @@ guint8 qq_process_token_ex(PurpleConnection *gc, guint8 *buf, gint buf_len); void qq_captcha_input_dialog(PurpleConnection *gc,qq_captcha_data *captcha); -void qq_request_check_pwd_2007(PurpleConnection *gc); -guint8 qq_process_check_pwd_2007( PurpleConnection *gc, guint8 *data, gint data_len); - -void qq_request_check_pwd_2008(PurpleConnection *gc); -guint8 qq_process_check_pwd_2008( PurpleConnection *gc, guint8 *data, gint data_len); +void qq_request_check_pwd(PurpleConnection *gc); +guint8 qq_process_check_pwd( PurpleConnection *gc, guint8 *data, gint data_len); void qq_request_login_2007(PurpleConnection *gc); guint8 qq_process_login_2007( PurpleConnection *gc, guint8 *data, gint data_len); diff -r dc112387190f -r 832178d951ca libpurple/protocols/qq/qq_process.c --- a/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:41:13 2008 +0000 +++ b/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:42:23 2008 +0000 @@ -663,11 +663,7 @@ case QQ_CMD_TOKEN_EX: ret_8 = qq_process_token_ex(gc, data, data_len); if (ret_8 == QQ_LOGIN_REPLY_OK) { - if (qd->client_version == 2008) { - qq_request_check_pwd_2008(gc); - } else { - qq_request_check_pwd_2007(gc); - } + qq_request_check_pwd(gc); } else if (ret_8 == QQ_LOGIN_REPLY_NEXT_TOKEN_EX) { qq_request_token_ex_next(gc); } else if (ret_8 == QQ_LOGIN_REPLY_CAPTCHA_DLG) { @@ -678,11 +674,7 @@ } break; case QQ_CMD_CHECK_PWD: - if (qd->client_version == 2008) { - ret_8 = qq_process_check_pwd_2008(gc, data, data_len); - } else { - ret_8 = qq_process_check_pwd_2007(gc, data, data_len); - } + ret_8 = qq_process_check_pwd(gc, data, data_len); if (ret_8 != QQ_LOGIN_REPLY_OK) { return ret_8; }