pidgin.openq: a1204255: 2009.10.02 - ccpaging <ccpaging(at)gmail...
csyfek at gmail.com
csyfek at gmail.com
Wed Oct 22 12:12:18 EDT 2008
-----------------------------------------------------------------
Revision: a1204255da7539e4db8d86fa00d0a532afc0c07a
Ancestor: 2fa69c961d2404c06ff3f8307112ef5095995530
Author: csyfek at gmail.com
Date: 2008-10-22T14:43:46
Branch: im.pidgin.pidgin.openq
URL: http://d.pidgin.im/viewmtn/revision/info/a1204255da7539e4db8d86fa00d0a532afc0c07a
Modified files:
libpurple/protocols/qq/ChangeLog
libpurple/protocols/qq/buddy_list.c
libpurple/protocols/qq/buddy_list.h
libpurple/protocols/qq/char_conv.c
libpurple/protocols/qq/char_conv.h
libpurple/protocols/qq/group_im.c
libpurple/protocols/qq/im.c
libpurple/protocols/qq/packet_parse.c
libpurple/protocols/qq/packet_parse.h
libpurple/protocols/qq/qq.c libpurple/protocols/qq/qq_base.c
libpurple/protocols/qq/qq_base.h
libpurple/protocols/qq/qq_network.c
libpurple/protocols/qq/qq_network.h
libpurple/protocols/qq/qq_process.c
libpurple/protocols/qq/send_file.c
ChangeLog:
2009.10.02 - ccpaging <ccpaging(at)gmail.com>
* Added 'Captcha Display' function
* Most functions from patch written by Emil Alexiev merged into trunk,
except 'buddy operations'
* 'online buddy status' and 'qun buddies' still have problems
-------------- next part --------------
============================================================
--- libpurple/protocols/qq/ChangeLog b29ecb8e886615ccbb95b04f60c3075e96e8eb3b
+++ libpurple/protocols/qq/ChangeLog b91d6b9d72b981dbce3bf88d025525bd76f55945
@@ -1,3 +1,8 @@
+2009.10.02 - ccpaging <ccpaging(at)gmail.com>
+ * Added 'Captcha Display' function
+ * Most functions from patch written by Emil Alexiev merged into trunk, except 'buddy operations'
+ * 'online buddy status' and 'qun buddies' still have problems
+
2008.09.30 - ccpaging <ccpaging(at)gmail.com>
* Successfully login using 2007/2008 protocols
============================================================
--- libpurple/protocols/qq/buddy_list.c ced41b6fcd418107900307abbb3c333e2cfa689a
+++ libpurple/protocols/qq/buddy_list.c 4ffdca36498c9dbd077a24972759cd52a933d465
@@ -84,9 +84,12 @@ void qq_request_get_buddies_list(PurpleC
* server may return a position tag if list is too long for one packet */
void qq_request_get_buddies_list(PurpleConnection *gc, guint16 position, gint update_class)
{
+ qq_data *qd;
guint8 raw_data[16] = {0};
gint bytes = 0;
+ qd = (qq_data *) gc->proto_data;
+
/* 000-001 starting position, can manually specify */
bytes += qq_put16(raw_data + bytes, position);
/* before Mar 18, 2004, any value can work, and we sent 00
@@ -95,7 +98,10 @@ void qq_request_get_buddies_list(PurpleC
* Now I tested that 00,00,00,00,00,01 work perfectly
* March 22, found the 00,00,00 starts to work as well */
bytes += qq_put8(raw_data + bytes, 0x00);
-
+ if (qd->client_version >= 2007) {
+ bytes += qq_put16(raw_data + bytes, 0x0000);
+ }
+
qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDIES_LIST, raw_data, bytes, update_class, 0);
}
@@ -177,7 +183,7 @@ guint8 qq_process_get_buddies_online_rep
count = 0;
while (bytes < data_len) {
if (data_len - bytes < QQ_ONLINE_BUDDY_ENTRY_LEN) {
- purple_debug_error("QQ", "[buddies online] only %d, need %d",
+ purple_debug_error("QQ", "[buddies online] only %d, need %d\n",
(data_len - bytes), QQ_ONLINE_BUDDY_ENTRY_LEN);
break;
}
@@ -292,11 +298,18 @@ guint16 qq_process_get_buddies_list_repl
bytes += pascal_len;
qq_filter_str(q_bud->nickname);
+ /* Fixme: merge following as 32bit flag */
bytes += qq_get16(&unknown, data + bytes);
bytes += qq_get8(&q_bud->ext_flag, data + bytes);
bytes += qq_get8(&q_bud->comm_flag, data + bytes);
+
+ if (qd->client_version >= 2007) {
+ bytes += 4; /* skip 4 bytes */
+ bytes_expected = 16 + pascal_len;
+ } else {
+ bytes_expected = 12 + pascal_len;
+ }
- bytes_expected = 12 + pascal_len;
if (q_bud->uid == 0 || (bytes - buddy_bytes) != bytes_expected) {
purple_debug_info("QQ",
@@ -390,6 +403,10 @@ guint32 qq_process_get_buddies_and_rooms
purple_debug_info("QQ",
"Not find room id %d in qq_process_get_buddies_and_rooms\n", uid);
qq_set_pending_id(&qd->adding_groups_from_server, uid, TRUE);
+ //group = g_newa(qq_group, 1);
+ //group->id = uid;
+ qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, uid, NULL, 0,
+ 0, 0);
} else {
group->my_role = QQ_ROOM_ROLE_YES;
qq_group_refresh(gc, group);
@@ -421,6 +438,7 @@ gboolean is_online(guint8 status)
case QQ_BUDDY_ONLINE_NORMAL:
case QQ_BUDDY_ONLINE_AWAY:
case QQ_BUDDY_ONLINE_INVISIBLE:
+ case QQ_BUDDY_ONLINE_BUSY:
return TRUE;
case QQ_BUDDY_CHANGE_TO_OFFLINE:
return FALSE;
@@ -469,6 +487,13 @@ void qq_request_change_status(PurpleConn
if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) {
away_cmd = QQ_BUDDY_ONLINE_INVISIBLE;
+ } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE))
+ {
+ if (qd->client_version >= 2007) {
+ away_cmd = QQ_BUDDY_ONLINE_BUSY;
+ } else {
+ away_cmd = QQ_BUDDY_ONLINE_INVISIBLE;
+ }
} else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY)
|| purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY)
|| purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) {
@@ -476,13 +501,13 @@ void qq_request_change_status(PurpleConn
} else {
away_cmd = QQ_BUDDY_ONLINE_NORMAL;
}
-
+
misc_status = 0x00000000;
fake_video = purple_prefs_get_bool("/plugins/prpl/qq/show_fake_video");
if (fake_video)
misc_status |= QQ_MISC_STATUS_HAVING_VIIDEO;
- if (qd->client_version > 2005) {
+ if (qd->client_version >= 2007) {
bytes = 0;
bytes += qq_put8(raw_data + bytes, away_cmd);
/* status version */
@@ -625,6 +650,9 @@ void qq_update_buddy_contact(PurpleConne
case QQ_BUDDY_ONLINE_INVISIBLE:
status_id = "invisible";
break;
+ case QQ_BUDDY_ONLINE_BUSY:
+ status_id = "busy";
+ break;
default:
status_id = "invisible";
purple_debug_error("QQ", "unknown status: %x\n", q_bud->status);
============================================================
--- libpurple/protocols/qq/buddy_list.h e163ac3f29e44454cf0cdf5f5b6af2fd4a0f3848
+++ libpurple/protocols/qq/buddy_list.h f8beb3b9d675b30c9128e7acf8aff396b411bd64
@@ -45,7 +45,8 @@ enum {
QQ_BUDDY_ONLINE_NORMAL = 10,
QQ_BUDDY_CHANGE_TO_OFFLINE = 20,
QQ_BUDDY_ONLINE_AWAY = 30,
- QQ_BUDDY_ONLINE_INVISIBLE = 40
+ QQ_BUDDY_ONLINE_INVISIBLE = 40,
+ QQ_BUDDY_ONLINE_BUSY = 50,
};
void qq_request_get_buddies_online(PurpleConnection *gc, guint8 position, gint update_class);
============================================================
--- libpurple/protocols/qq/char_conv.c eee3c39ca1bb92e50e3b9092341ffce8d4071f19
+++ libpurple/protocols/qq/char_conv.c 401be250c456459219f5a293203ca59c1d2972f9
@@ -141,7 +141,7 @@ gint convert_as_pascal_string(guint8 *da
}
/* convert QQ formatted msg to Purple formatted msg (and UTF-8) */
-gchar *qq_encode_to_purple(guint8 *data, gint len, const gchar *msg)
+gchar *qq_encode_to_purple(guint8 *data, gint len, const gchar *msg, const gint client_version)
{
GString *encoded;
guint8 font_attr, font_size, color[3], bar;
@@ -153,6 +153,9 @@ gchar *qq_encode_to_purple(guint8 *data,
/* checked qq_show_packet OK */
/* qq_show_packet("QQ_MESG recv for font style", data, len); */
+ if (client_version >= 2007) {
+ bytes += 1;
+ }
bytes += qq_get8(&font_attr, data + bytes);
bytes += qq_getdata(color, 3, data + bytes); /* red,green,blue */
color_code = g_strdup_printf("#%02x%02x%02x", color[0], color[1], color[2]);
@@ -232,8 +235,10 @@ gchar *qq_smiley_to_purple(gchar *text)
converted = g_string_new("");
segments = split_data((guint8 *) text, strlen(text), "\x14\x15", 0);
- g_string_append(converted, segments[0]);
+ if(segments == NULL)
+ return NULL;
+ g_string_append(converted, segments[0]);
while ((*(++segments)) != NULL) {
cur_seg = *segments;
qq_smiley = cur_seg[0];
============================================================
--- libpurple/protocols/qq/char_conv.h c982dd5edde48bc1ff655d59a9c762b9fd162fde
+++ libpurple/protocols/qq/char_conv.h 207f24991e06d598d52cffeecc87516e00ab9a03
@@ -37,7 +37,7 @@ gchar *qq_to_utf8(const gchar *str, cons
gchar *utf8_to_qq(const gchar *str, const gchar *to_charset);
gchar *qq_to_utf8(const gchar *str, const gchar *from_charset);
-gchar *qq_encode_to_purple(guint8 *font_attr_data, gint len, const gchar *msg);
+gchar *qq_encode_to_purple(guint8 *font_attr_data, gint len, const gchar *msg, const gint client_version);
gchar *qq_im_filter_html(const gchar *text);
void qq_filter_str(gchar *str);
============================================================
--- libpurple/protocols/qq/group_im.c 61e16cd31f54b9f0b254330ccc744d9c94e6a8f9
+++ libpurple/protocols/qq/group_im.c 3966fcb6e6a1f8fda309e328d46e8b5830d3eb4c
@@ -401,12 +401,12 @@ void qq_process_room_msg_normal(guint8 *
/* group im_group has no flag to indicate whether it has font_attr or not */
msg_with_purple_smiley = qq_smiley_to_purple(packet.msg);
- if (packet.font_attr_len > 0)
+ if (packet.font_attr_len > 0) {
msg_utf8_encoded = qq_encode_to_purple(packet.font_attr,
- packet.font_attr_len, msg_with_purple_smiley);
- else
+ packet.font_attr_len, msg_with_purple_smiley, qd->client_version);
+ } else {
msg_utf8_encoded = qq_to_utf8(msg_with_purple_smiley, QQ_CHARSET_DEFAULT);
-
+ }
group = qq_room_search_id(gc, id);
qq_room_got_chat_in(gc, group, packet.member_uid, msg_utf8_encoded, packet.send_time);
============================================================
--- libpurple/protocols/qq/im.c b4ccbe8ec5e04eaaf3a822baa7b4f5243ef4eee0
+++ libpurple/protocols/qq/im.c 4db6a4426726984be7305ad84bf712aa44b00edc
@@ -390,7 +390,8 @@ static void process_recv_normal_im_text(
msg_utf8_encoded = im_text->is_there_font_attr ?
qq_encode_to_purple(im_text->font_attr,
im_text->font_attr_len,
- msg_with_purple_smiley) : qq_to_utf8(msg_with_purple_smiley, QQ_CHARSET_DEFAULT);
+ msg_with_purple_smiley, qd->client_version)
+ : qq_to_utf8(msg_with_purple_smiley, QQ_CHARSET_DEFAULT);
/* send encoded to purple, note that we use im_text->send_time,
* not the time we receive the message
============================================================
--- libpurple/protocols/qq/packet_parse.c 62cdbf4a27fb94fdb2458c47a37eae5367bd6c2d
+++ libpurple/protocols/qq/packet_parse.c 50b4e2960eb3809ce3ddb42ac25800292a3a67ce
@@ -151,6 +151,9 @@ gint qq_put32(guint8 *buf, guint32 dw)
* return the number of bytes packed, otherwise return -1 */
gint qq_put32(guint8 *buf, guint32 dw)
{
+ guint32 dw_dest;
+ memcpy(&dw_dest, buf, sizeof(dw_dest));
+
guint32 dw_porter;
dw_porter = g_htonl(dw);
#ifdef PARSER_DEBUG
@@ -161,6 +164,19 @@ gint qq_put32(guint8 *buf, guint32 dw)
return sizeof(dw_porter);
}
+gint qq_putime(guint8 *buf, time_t *t)
+{
+ guint32 dw, dw_porter;
+ memcpy(&dw, t, sizeof(dw));
+ dw_porter = g_htonl(dw);
+#ifdef PARSER_DEBUG
+ purple_debug_info("QQ", "[DBG][put32] buf %p\n", (void *)buf);
+ purple_debug_info("QQ", "[DBG][put32] dw 0x%08x, dw_porter 0x%08x\n", dw, dw_porter);
+#endif
+ memcpy(buf, &dw_porter, sizeof(dw_porter));
+ return sizeof(dw_porter);
+}
+
gint qq_putIP(guint8* buf, struct in_addr *ip)
{
memcpy(buf, ip, sizeof(struct in_addr));
============================================================
--- libpurple/protocols/qq/packet_parse.h 2a60f02107e0c4e04f2c8186e1adf8f0466b36e9
+++ libpurple/protocols/qq/packet_parse.h 89769c59d1224745e5a85b9372cdbaed07fa01dd
@@ -54,6 +54,7 @@ gint qq_putIP(guint8* buf, struct in_add
gint qq_put16(guint8 *buf, guint16 w);
gint qq_put32(guint8 *buf, guint32 dw);
gint qq_putIP(guint8* buf, struct in_addr *ip);
+gint qq_putime(guint8 *buf, time_t *t);
gint qq_putdata(guint8 *buf, const guint8 *data, const int datalen);
/*
============================================================
--- libpurple/protocols/qq/qq.c 6026eaa9bcbb6d84fb4c4c0bb68c08cbfe214bea
+++ libpurple/protocols/qq/qq.c d6924486ed11ec637cfb8cda8f079ab51b9d0179
@@ -267,6 +267,9 @@ static gchar *qq_status_text(PurpleBuddy
case QQ_BUDDY_ONLINE_INVISIBLE:
g_string_append(status, _("Invisible"));
break;
+ case QQ_BUDDY_ONLINE_BUSY:
+ g_string_append(status, _("Busy"));
+ break;
default:
g_string_printf(status, _("Unknown-%d"), q_bud->status);
}
@@ -405,6 +408,10 @@ static GList *qq_status_types(PurpleAcco
"invisible", _("Invisible"), FALSE, TRUE, FALSE);
types = g_list_append(types, status);
+ status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE,
+ "busy", _("Busy"), TRUE, TRUE, FALSE);
+ types = g_list_append(types, status);
+
status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
"offline", _("Offline"), FALSE, TRUE, FALSE);
types = g_list_append(types, status);
@@ -898,7 +905,9 @@ static void init_plugin(PurplePlugin *pl
GList *server_list = NULL;
GList *server_kv_list = NULL;
GList *it;
+//#ifdef DEBUG
GList *version_kv_list = NULL;
+//#endif
server_list = server_list_build('A');
@@ -927,7 +936,7 @@ static void init_plugin(PurplePlugin *pl
option = purple_account_option_list_new(_("Select Server"), "server", server_kv_list);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-#ifdef DEBUG
+//#ifdef DEBUG
kvp = g_new0(PurpleKeyValuePair, 1);
kvp->key = g_strdup(_("QQ2005"));
kvp->value = g_strdup("qq2005");
@@ -945,7 +954,7 @@ static void init_plugin(PurplePlugin *pl
option = purple_account_option_list_new(_("Client Version"), "client_version", version_kv_list);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-#endif
+//#endif
option = purple_account_option_bool_new(_("Connect by TCP"), "use_tcp", TRUE);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
============================================================
--- libpurple/protocols/qq/qq_base.c 28e364ec00620f7d5751cf7dd568b4f13c1de426
+++ libpurple/protocols/qq/qq_base.c cff38b38098d8ef21f94b7a1e12713de27aaa3cb
@@ -460,11 +460,10 @@ void qq_request_keep_alive(PurpleConnect
* with this command, server return the same result including
* the amount of online QQ users, my ip and port */
bytes += qq_put32(raw_data + bytes, qd->uid);
-
- qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, 4);
+ qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, bytes);
}
-/* parse the return of keep-alive packet, it includes some system information */
+/* parse the return ofqq_process_keep_alive keep-alive packet, it includes some system information */
gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
@@ -497,6 +496,107 @@ gboolean qq_process_keep_alive(guint8 *d
return TRUE;
}
+void qq_request_keep_alive_2007(PurpleConnection *gc)
+{
+ qq_data *qd;
+ guint8 raw_data[32] = {0};
+ gint bytes= 0;
+ gchar *uid_str;
+
+ qd = (qq_data *) gc->proto_data;
+
+ /* In fact, we can send whatever we like to server
+ * with this command, server return the same result including
+ * the amount of online QQ users, my ip and port */
+ uid_str = g_strdup_printf("%u", qd->uid);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)uid_str, strlen(uid_str));
+ qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, bytes);
+
+ g_free(uid_str);
+}
+
+gboolean qq_process_keep_alive_2007(guint8 *data, gint data_len, PurpleConnection *gc)
+{
+ qq_data *qd;
+ gint bytes= 0;
+ guint8 ret;
+
+ g_return_val_if_fail(data != NULL && data_len != 0, FALSE);
+
+ qd = (qq_data *) gc->proto_data;
+
+ /* qq_show_packet("Keep alive reply packet", data, len); */
+
+ bytes = 0;
+ bytes += qq_get8(&ret, data + bytes);
+ bytes += qq_get32(&qd->online_total, data + bytes);
+ if(0 == qd->online_total) {
+ purple_connection_error_reason(gc,
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+ _("Keep alive error"));
+ }
+
+ bytes += qq_getIP(&qd->my_ip, data + bytes);
+ bytes += qq_get16(&qd->my_port, data + bytes);
+ return TRUE;
+}
+
+void qq_request_keep_alive_2008(PurpleConnection *gc)
+{
+ qq_data *qd;
+ guint8 raw_data[16] = {0};
+ gint bytes= 0;
+
+ qd = (qq_data *) gc->proto_data;
+
+ /* In fact, we can send whatever we like to server
+ * with this command, server return the same result including
+ * the amount of online QQ users, my ip and port */
+ bytes += qq_put32(raw_data + bytes, qd->uid);
+ bytes += qq_putime(raw_data + bytes, &qd->login_time);
+ qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, bytes);
+}
+
+gboolean qq_process_keep_alive_2008(guint8 *data, gint data_len, PurpleConnection *gc)
+{
+ qq_data *qd;
+ gint bytes= 0;
+ guint8 ret;
+ time_t server_time;
+ struct tm *tm_local;
+
+ g_return_val_if_fail(data != NULL && data_len != 0, FALSE);
+
+ qd = (qq_data *) gc->proto_data;
+
+ /* qq_show_packet("Keep alive reply packet", data, len); */
+
+ bytes = 0;
+ bytes += qq_get8(&ret, data + bytes);
+ bytes += qq_get32(&qd->online_total, data + bytes);
+ if(0 == qd->online_total) {
+ purple_connection_error_reason(gc,
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+ _("Keep alive error"));
+ }
+
+ bytes += qq_getIP(&qd->my_ip, data + bytes);
+ bytes += qq_get16(&qd->my_port, data + bytes);
+ /* skip 2 byytes, 0x(00 3c) */
+ bytes += 2;
+ bytes += qq_getime(&server_time, data + bytes);
+ /* skip 5 bytes, all are 0 */
+
+ purple_debug_info("QQ", "keep alive, %s:%d\n",
+ inet_ntoa(qd->my_ip), qd->my_port);
+
+ tm_local = localtime(&server_time);
+ purple_debug_info("QQ", "Server time: %d-%d-%d, %d:%d:%d\n",
+ (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday,
+ tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec);
+ return TRUE;
+}
+
/* For QQ2007/2008 */
void qq_request_get_server(PurpleConnection *gc)
{
@@ -681,8 +781,8 @@ static void request_token_ex_code(Purple
bytes += qq_put32(raw_data + bytes, 0);
bytes += qq_put16(raw_data + bytes, code_len);
bytes += qq_putdata(raw_data + bytes, code, code_len);
- bytes += qq_put16(raw_data + bytes, qd->captcha.token_len); /* captcha token */
- bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len);
+ bytes += qq_put16(raw_data + bytes, qd->ld.token_ex_len); /* login token ex */
+ bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len);
encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key);
@@ -811,7 +911,9 @@ guint8 qq_process_token_ex(PurpleConnect
bytes += qq_get16(&(qd->ld.token_ex_len), data + bytes);
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);
+ bytes += qq_getdata(qd->ld.token_ex, qd->ld.token_ex_len, data + bytes);
+ qq_show_packet("Get token ex", qd->ld.token_ex, qd->ld.token_ex_len);
+
if(reply != 1)
{
purple_debug_info("QQ", "Captcha verified, result %d\n", reply);
@@ -828,9 +930,12 @@ guint8 qq_process_token_ex(PurpleConnect
bytes += qq_get8(&qd->captcha.next_index, data + bytes);
bytes += qq_get16(&qd->captcha.token_len, data + bytes);
- qd->captcha.token = g_new0(guint8, qd->captcha.token_len);
+ qd->captcha.token = g_realloc(qd->captcha.token, qd->captcha.token_len);
bytes += qq_getdata(qd->captcha.token, qd->captcha.token_len, data + bytes);
+ qq_show_packet("Get captcha token", qd->captcha.token, qd->captcha.token_len);
+ purple_debug_info("QQ", "Request next captcha %d, new %d, total %d\n",
+ qd->captcha.next_index, captcha_len, qd->captcha.data_len);
if(qd->captcha.next_index > 0)
{
return QQ_LOGIN_REPLY_NEXT_TOKEN_EX;
@@ -894,7 +999,7 @@ void qq_request_check_pwd(PurpleConnecti
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);
+ g_return_if_fail(qd->ld.token_ex != NULL && qd->ld.token_ex_len > 0);
raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
memset(raw_data, 0, MAX_PACKET_SIZE - 16);
@@ -913,7 +1018,7 @@ void qq_request_check_pwd(PurpleConnecti
bytes = 0;
bytes += qq_putdata(raw_data + bytes, header, sizeof(header));
/* token get from qq_request_token_ex */
- bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len);
+ bytes += qq_put8(raw_data + bytes, (guint8)(qd->ld.token_ex_len & 0xff));
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);
@@ -923,7 +1028,7 @@ void qq_request_check_pwd(PurpleConnecti
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_put8(raw_data + 1, bytes - 2);
@@ -933,7 +1038,7 @@ void qq_request_check_pwd(PurpleConnecti
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);
@@ -963,7 +1068,7 @@ guint8 qq_process_check_pwd( PurpleConne
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); */
+ qq_show_packet("Check password reply", data, data_len);
bytes = 0;
bytes += qq_get16(&unknow_token_len, data + bytes); /* maybe total length */
@@ -1097,11 +1202,12 @@ void qq_request_login_2007(PurpleConnect
memset(raw_data + bytes, 0, 10);
bytes += 10;
/* redirect data, 15 bytes */
+ qq_show_packet("Redirect", qd->redirect, qd->redirect_len);
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->ld.token_ex_len);
+ bytes += qq_put8(raw_data + bytes, (guint8)(qd->ld.token_ex_len & 0xff));
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));
@@ -1130,8 +1236,10 @@ guint8 qq_process_login_2007( PurpleConn
qq_data *qd;
gint bytes;
guint8 ret;
+ guint32 uid;
gchar *error;
- guint32 uid;
+ gchar *msg;
+ gchar *msg_utf8;
g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR);
@@ -1140,15 +1248,34 @@ guint8 qq_process_login_2007( PurpleConn
bytes = 0;
bytes += qq_get8(&ret, data + bytes);
if (ret != 0) {
- qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len,
- ">>> [default] decrypt and dump");
- error = g_strdup_printf(
- _("Unknow reply code when login (0x%02X)"),
- ret );
+ msg = g_strndup((gchar *)data + bytes, data_len - bytes);
+ msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
+
+ switch (ret) {
+ case 0x05:
+ error = g_strdup_printf(
+ _("Server is busy now, Please try later\n%s"),
+ ret, msg_utf8);
+ break;
+ case 0x0A:
+ /* 0a 2d 9a 4b 9a 01 01 00 00 00 05 00 00 00 00 79 0e 5f fd */
+ default:
+ error = g_strdup_printf(
+ _("Unknow reply code when login (0x%02X):\n%s"),
+ ret, msg_utf8);
+ break;
+ }
+
+ purple_debug_error("QQ", "%s\n", error);
purple_connection_error_reason(gc,
PURPLE_CONNECTION_ERROR_OTHER_ERROR,
error);
+
+ qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, error);
+
g_free(error);
+ g_free(msg_utf8);
+ g_free(msg);
return QQ_LOGIN_REPLY_ERR;
}
@@ -1262,7 +1389,7 @@ void qq_request_login_2008(PurpleConnect
/* 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->ld.token_ex_len);
+ bytes += qq_put8(raw_data + bytes, (guint8)(qd->ld.token_ex_len & 0xff));
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));
@@ -1301,8 +1428,10 @@ guint8 qq_process_login_2008( PurpleConn
qq_data *qd;
gint bytes;
guint8 ret;
+ guint32 uid;
gchar *error;
- guint32 uid;
+ gchar *msg;
+ gchar *msg_utf8;
g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR);
@@ -1311,15 +1440,32 @@ guint8 qq_process_login_2008( PurpleConn
bytes = 0;
bytes += qq_get8(&ret, data + bytes);
if (ret != 0) {
- qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len,
- ">>> [default] decrypt and dump");
- error = g_strdup_printf(
- _("Unknow reply code when login (0x%02X)"),
- ret );
+ msg = g_strndup((gchar *)data + bytes, data_len - bytes);
+ msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
+
+ switch (ret) {
+ case 0x05:
+ error = g_strdup_printf(
+ _("Server is busy now, Please try later\n%s"),
+ ret, msg_utf8);
+ break;
+ default:
+ error = g_strdup_printf(
+ _("Unknow reply code when login (0x%02X):\n%s"),
+ ret, msg_utf8);
+ break;
+ }
+
+ purple_debug_error("QQ", "%s\n", error);
purple_connection_error_reason(gc,
PURPLE_CONNECTION_ERROR_OTHER_ERROR,
error);
+
+ qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, error);
+
g_free(error);
+ g_free(msg_utf8);
+ g_free(msg);
return QQ_LOGIN_REPLY_ERR;
}
============================================================
--- libpurple/protocols/qq/qq_base.h 3d8a80825363d0941c79352ba552c5a03b87bc89
+++ libpurple/protocols/qq/qq_base.h ab3178def027c3d85eb21ecf515ef9c721686757
@@ -52,6 +52,12 @@ gboolean qq_process_keep_alive(guint8 *d
void qq_request_keep_alive(PurpleConnection *gc);
gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc);
+void qq_request_keep_alive_2007(PurpleConnection *gc);
+gboolean qq_process_keep_alive_2007(guint8 *data, gint data_len, PurpleConnection *gc);
+
+void qq_request_keep_alive_2008(PurpleConnection *gc);
+gboolean qq_process_keep_alive_2008(guint8 *data, gint data_len, PurpleConnection *gc);
+
/* for QQ2007/2008 */
void qq_request_get_server(PurpleConnection *gc);
guint16 qq_process_get_server(PurpleConnection *gc, guint8 *rcved, gint rcved_len);
============================================================
--- libpurple/protocols/qq/qq_network.c e980710f438f68c435ac95ed09bcdf732e091bb3
+++ libpurple/protocols/qq/qq_network.c ecfb66d708a004a81b2ac2644516b07dcb27ff84
@@ -667,7 +667,13 @@ static gboolean network_timeout(gpointer
qd->itv_count.keep_alive--;
if (qd->itv_count.keep_alive <= 0) {
qd->itv_count.keep_alive = qd->itv_config.keep_alive;
- qq_request_keep_alive(gc);
+ if (qd->client_version >= 2008) {
+ qq_request_keep_alive_2008(gc);
+ } else if (qd->client_version >= 2007) {
+ qq_request_keep_alive_2007(gc);
+ } else {
+ qq_request_keep_alive(gc);
+ }
return TRUE;
}
@@ -691,7 +697,9 @@ static void set_all_keys(PurpleConnectio
const gchar *passwd;
guint8 *dest;
int dest_len = QQ_KEY_LENGTH;
-
+#ifndef DEBUG
+ int bytes;
+#endif
/* _qq_show_socket("Got login socket", source); */
g_return_if_fail(gc != NULL && gc->proto_data != NULL);
@@ -771,7 +779,7 @@ static void connect_cb(gpointer data, gi
set_all_keys( gc );
- if (qd->client_version > 2005) {
+ if (qd->client_version >= 2007) {
purple_connection_update_progress(gc, _("Get server ..."), 2, QQ_CONNECT_STEPS);
qq_request_get_server(gc);
return;
============================================================
--- libpurple/protocols/qq/qq_network.h 1e908088d3f41d42646e83d59572f2670a6b3ece
+++ libpurple/protocols/qq/qq_network.h b5da3ac74a10b4a53df0b6ea29860d12e42d0d61
@@ -30,7 +30,7 @@
#include "qq.h"
-#define QQ_CONNECT_STEPS 3 /* steps in connection */
+#define QQ_CONNECT_STEPS 4 /* steps in connection */
gboolean qq_connect_later(gpointer data);
void qq_disconnect(PurpleConnection *gc);
============================================================
--- libpurple/protocols/qq/qq_process.c 704cd19e09d79732c04337624136c8529cef47f9
+++ libpurple/protocols/qq/qq_process.c 1cd91fd9f8aa68e792523cc394bfad6cca747445
@@ -589,7 +589,7 @@ guint8 qq_proc_login_cmds(PurpleConnecti
switch (cmd) {
case QQ_CMD_TOKEN:
if (qq_process_token(gc, rcved, rcved_len) == QQ_LOGIN_REPLY_OK) {
- if (qd->client_version > 2005) {
+ if (qd->client_version >= 2007) {
qq_request_token_ex(gc);
} else {
qq_request_login(gc);
@@ -615,7 +615,7 @@ guint8 qq_proc_login_cmds(PurpleConnecti
break;
case QQ_CMD_LOGIN:
default:
- if (qd->client_version > 2005) {
+ if (qd->client_version >= 2007) {
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");
@@ -696,6 +696,7 @@ guint8 qq_proc_login_cmds(PurpleConnecti
return ret_8;
}
+ purple_connection_update_progress(gc, _("Logined"), QQ_CONNECT_STEPS - 1, QQ_CONNECT_STEPS);
purple_debug_info("QQ", "Login repliess OK; everything is fine\n");
purple_connection_set_state(gc, PURPLE_CONNECTED);
qd->is_login = TRUE; /* must be defined after sev_finish_login */
@@ -776,7 +777,13 @@ void qq_proc_client_cmds(PurpleConnectio
qq_process_send_im_reply(data, data_len, gc);
break;
case QQ_CMD_KEEP_ALIVE:
- qq_process_keep_alive(data, data_len, gc);
+ if (qd->client_version >= 2008) {
+ qq_process_keep_alive_2008(data, data_len, gc);
+ } else if (qd->client_version >= 2007) {
+ qq_process_keep_alive_2007(data, data_len, gc);
+ } else {
+ qq_process_keep_alive(data, data_len, gc);
+ }
break;
case QQ_CMD_GET_BUDDIES_ONLINE:
ret_8 = qq_process_get_buddies_online_reply(data, data_len, gc);
============================================================
--- libpurple/protocols/qq/send_file.c 271b750f28e52519c0b0cdef1c6ca880d5b418dc
+++ libpurple/protocols/qq/send_file.c d7e6ab68ca7284c476a7e822bb9cff1c43deb564
@@ -121,11 +121,8 @@ static ssize_t _qq_xfer_udp_send(const g
sin.sin_port = g_htons(info->remote_minor_port);
sin.sin_addr.s_addr = g_htonl(info->remote_real_ip);
}
- purple_debug_info("QQ", "sending to channel: %d.%d.%d.%d:%d\n",
- (int)sin.sin_addr.s_addr & 0xff,
- (int)(sin.sin_addr.s_addr >> 8) & 0xff,
- (int)(sin.sin_addr.s_addr >> 16) & 0xff,
- (int)sin.sin_addr.s_addr >> 24,
+ purple_debug_info("QQ", "sending to channel: %s:%d\n",
+ inet_ntoa(sin.sin_addr),
(int)g_ntohs(sin.sin_port)
);
return sendto(info->sender_fd, buf, len, 0, (struct sockaddr *) &sin, sizeof(sin));
More information about the Commits
mailing list