pidgin.openq: 12cded14: 2008.10.04 - lonicerae <lonicerae(at)gma...
csyfek at gmail.com
csyfek at gmail.com
Wed Oct 22 12:11:39 EDT 2008
-----------------------------------------------------------------
Revision: 12cded1415954b28cc6aeada24ba0ec74b00bb64
Ancestor: 1c4fb0989f727182cef6938d8de6c1fe1a734843
Author: csyfek at gmail.com
Date: 2008-10-22T14:49:38
Branch: im.pidgin.pidgin.openq
URL: http://d.pidgin.im/viewmtn/revision/info/12cded1415954b28cc6aeada24ba0ec74b00bb64
Modified files:
libpurple/protocols/qq/ChangeLog
libpurple/protocols/qq/buddy_info.c
libpurple/protocols/qq/buddy_list.c
libpurple/protocols/qq/buddy_opt.c
libpurple/protocols/qq/buddy_opt.h
libpurple/protocols/qq/char_conv.c
libpurple/protocols/qq/char_conv.h
libpurple/protocols/qq/group_conv.c
libpurple/protocols/qq/group_im.c
libpurple/protocols/qq/group_im.h
libpurple/protocols/qq/group_info.c
libpurple/protocols/qq/group_search.c
libpurple/protocols/qq/im.c libpurple/protocols/qq/im.h
libpurple/protocols/qq/packet_parse.c
libpurple/protocols/qq/qq.c libpurple/protocols/qq/qq_base.c
libpurple/protocols/qq/qq_process.c
libpurple/protocols/qq/utils.c
ChangeLog:
2008.10.04 - lonicerae <lonicerae(at)gmail.com>
* fixed a bug in qq_base.c
-------------- next part --------------
============================================================
--- libpurple/protocols/qq/ChangeLog bd331462880384f1dc7c42905bc0870b59a8cfe3
+++ libpurple/protocols/qq/ChangeLog 674f79309e6c9d40876d83f4315e8a265a305c37
@@ -1,13 +1,6 @@
-2008.10.05 - ccpaging <ccpagint(at)gmail.com>
- * Add my uid into buddy list
- * Fixed a minor bug in qq_create_buddy. Not get new buddy's info.
- * There are 38 fields in protocol 2008, one more than 2005/2007.
- * The packet of Modifing buddy info is changed. Need sample to fix it.
+2008.10.04 - lonicerae <lonicerae(at)gmail.com>
+ * fixed a bug in qq_base.c
-2008.10.04 - ccpaging <ccpagint(at)gmail.com>
- * Update protocol for 2007
- * Code cleanup
-
2008.10.03 - ccpaging <ccpaging(at)gmail.com>
* 2007 protocol:
1. fixed 'get room info'
============================================================
--- libpurple/protocols/qq/buddy_info.c 216d8d86ce1128cb4f6e5239c4ba7f04a3d8b75b
+++ libpurple/protocols/qq/buddy_info.c 4b4646f45db0551d43b28343429b6555cc0a098f
@@ -85,7 +85,7 @@ enum {
QQ_INFO_UNKNOW3, QQ_INFO_UNKNOW4, QQ_INFO_UNKNOW5,
QQ_INFO_IS_PUB_MOBILE, QQ_INFO_IS_PUB_CONTACT, QQ_INFO_COLLEGE, QQ_INFO_HOROSCOPE,
QQ_INFO_ZODIAC, QQ_INFO_BLOOD, QQ_INFO_SHOW, QQ_INFO_UNKNOW6,
- QQ_INFO_LAST_2007, QQ_INFO_LAST,
+ QQ_INFO_LAST,
};
enum {
@@ -142,8 +142,7 @@ static const QQ_FIELD_INFO field_infos[]
{ QQ_FIELD_EXT, QQ_FIELD_CHOICE, "zodiac", N_("Zodiac"), zodiac_names, QQ_ZODIAC_SIZE },
{ QQ_FIELD_EXT, QQ_FIELD_CHOICE, "blood", N_("Blood"), blood_types, QQ_BLOOD_SIZE },
{ QQ_FIELD_UNUSED, QQ_FIELD_STRING, "qq_show", "QQ Show", NULL, 0 },
- { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow6", "Unknow6", NULL, 0 },
- { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "LAST_2005", "LAST_2005", NULL, 0 }
+ { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow6", "Unknow6", NULL, 0 }
};
typedef struct _modify_info_request {
@@ -569,53 +568,35 @@ static void buddy_local_icon_upate(Purpl
}
/* after getting info or modify myself, refresh the buddy list accordingly */
-static void qq_set_buddy_info(gchar **segments, PurpleConnection *gc)
+static void qq_refresh_buddy_and_myself(gchar **segments, PurpleConnection *gc)
{
- PurpleBuddy *purple_buddy;
+ PurpleBuddy *b;
qq_data *qd;
- guint32 uid;
- qq_buddy *buddy;
+ qq_buddy *q_bud;
gchar *alias_utf8;
gchar *purple_name;
PurpleAccount *account = purple_connection_get_account(gc);
qd = (qq_data *) gc->proto_data;
+ purple_name = uid_to_purple_name(strtol(segments[QQ_INFO_UID], NULL, 10));
- uid = strtol(segments[QQ_INFO_UID], NULL, 10);
- purple_name = uid_to_purple_name(uid);
-
alias_utf8 = qq_to_utf8(segments[QQ_INFO_NICK], QQ_CHARSET_DEFAULT);
if (qd->uid == strtol(segments[QQ_INFO_UID], NULL, 10)) { /* it is me */
- purple_debug_info("QQ", "Got my info\n");
qd->my_icon = strtol(segments[QQ_INFO_FACE], NULL, 10);
if (alias_utf8 != NULL)
purple_account_set_alias(account, alias_utf8);
-
- /* add me to buddy list */
- purple_buddy = purple_find_buddy(gc->account, purple_name);
- if ( purple_buddy == NULL) {
- purple_buddy = qq_create_buddy(gc, uid, TRUE, FALSE);
- }
- buddy = g_new0(qq_buddy, 1);
- buddy->uid = uid;
- buddy->status = QQ_BUDDY_ONLINE_NORMAL;
- purple_buddy->proto_data = buddy;
- qd->buddies = g_list_append(qd->buddies, buddy);
}
-
/* update buddy list (including myself, if myself is the buddy) */
- purple_buddy = purple_find_buddy(gc->account, purple_name);
- buddy = (purple_buddy == NULL) ? NULL : (qq_buddy *) purple_buddy->proto_data;
- if (buddy != NULL) { /* I have this buddy */
- buddy->age = strtol(segments[QQ_INFO_AGE], NULL, 10);
- buddy->gender = strtol(segments[QQ_INFO_GENDER], NULL, 10);
- buddy->face = strtol(segments[QQ_INFO_FACE], NULL, 10);
+ b = purple_find_buddy(gc->account, purple_name);
+ q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
+ if (q_bud != NULL) { /* I have this buddy */
+ q_bud->age = strtol(segments[QQ_INFO_AGE], NULL, 10);
+ q_bud->gender = strtol(segments[QQ_INFO_GENDER], NULL, 10);
+ q_bud->face = strtol(segments[QQ_INFO_FACE], NULL, 10);
if (alias_utf8 != NULL)
- buddy->nickname = g_strdup(alias_utf8);
- qq_update_buddy_contact(gc, buddy);
- buddy_local_icon_upate(gc->account, purple_name, buddy->face);
- } else {
- purple_debug_info("QQ", "Can not find buddy data of %s\n", purple_name);
+ q_bud->nickname = g_strdup(alias_utf8);
+ qq_update_buddy_contact(gc, q_bud);
+ buddy_local_icon_upate(gc->account, purple_name, q_bud->face);
}
g_free(purple_name);
g_free(alias_utf8);
@@ -626,18 +607,12 @@ void qq_process_get_buddy_info(guint8 *d
{
qq_data *qd;
gchar **segments;
- gint field_count;
g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- if (qd->client_version >= 2008) {
- field_count = QQ_INFO_LAST;
- } else {
- field_count = QQ_INFO_LAST_2007;
- }
- if (NULL == (segments = split_data(data, data_len, "\x1e", field_count)))
+ if (NULL == (segments = split_data(data, data_len, "\x1e", QQ_INFO_LAST)))
return;
#ifdef DEBUG
@@ -652,13 +627,13 @@ void qq_process_get_buddy_info(guint8 *d
segments[QQ_INFO_FACE] = icon;
request_modify_info(gc, segments);
- qq_set_buddy_info(segments, gc);
+ qq_refresh_buddy_and_myself(segments, gc);
}
g_strfreev(segments);
return;
}
- qq_set_buddy_info(segments, gc);
+ qq_refresh_buddy_and_myself(segments, gc);
switch (action) {
case QQ_BUDDY_INFO_DISPLAY:
info_display_only(gc, segments);
@@ -722,7 +697,7 @@ void qq_request_get_buddies_level(Purple
if ( qd->buddies == NULL) {
return;
}
-
+
/* server only reply levels for online buddies */
size = 4 * g_list_length(qd->buddies) + 1 + 4;
buf = g_newa(guint8, size);
@@ -746,7 +721,7 @@ static void process_level(PurpleConnecti
guint32 uid, onlineTime;
guint16 level, timeRemainder;
qq_buddy *buddy;
-
+
while (data_len - bytes >= 12) {
bytes += qq_get32(&uid, data + bytes);
bytes += qq_get32(&onlineTime, data + bytes);
@@ -809,11 +784,11 @@ static void process_level_2007(PurpleCon
buddy->onlineTime = onlineTime;
buddy->level = level;
buddy->timeRemainder = timeRemainder;
-
+
/* extend bytes in qq2007*/
bytes += 4; /* skip 8 bytes */
- /* qq_show_packet("Buddies level", data + bytes, data_len - bytes); */
-
+ qq_show_packet("Buddies level", data + bytes, data_len - bytes);
+
do {
bytes += qq_get16(&str_len, data + bytes);
if (str_len <= 0 || bytes + str_len > data_len) {
============================================================
--- libpurple/protocols/qq/buddy_list.c 47d1d3cfe183ee7ac1f45ed6d1b75e2a2c480172
+++ libpurple/protocols/qq/buddy_list.c 495b58af9d842a708d6c5b3836b4968dbed257e1
@@ -101,7 +101,7 @@ void qq_request_get_buddies_list(PurpleC
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);
}
@@ -251,13 +251,13 @@ guint16 qq_process_get_buddies_list_repl
guint16 qq_process_get_buddies_list_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- qq_buddy *buddy;
+ qq_buddy *q_bud;
gint bytes_expected, count;
gint bytes, buddy_bytes;
- gint nickname_len;
guint16 position, unknown;
- gchar *purple_name;
- PurpleBuddy *purple_buddy;
+ guint8 pascal_len;
+ gchar *name;
+ PurpleBuddy *b;
g_return_val_if_fail(data != NULL && data_len != 0, -1);
@@ -273,39 +273,40 @@ guint16 qq_process_get_buddies_list_repl
/* the following data is buddy list in this packet */
count = 0;
while (bytes < data_len) {
- buddy = g_new0(qq_buddy, 1);
+ q_bud = g_new0(qq_buddy, 1);
/* set flag */
buddy_bytes = bytes;
/* 000-003: uid */
- bytes += qq_get32(&buddy->uid, data + bytes);
+ bytes += qq_get32(&q_bud->uid, data + bytes);
/* 004-005: icon index (1-255) */
- bytes += qq_get16(&buddy->face, data + bytes);
+ bytes += qq_get16(&q_bud->face, data + bytes);
/* 006-006: age */
- bytes += qq_get8(&buddy->age, data + bytes);
+ bytes += qq_get8(&q_bud->age, data + bytes);
/* 007-007: gender */
- bytes += qq_get8(&buddy->gender, data + bytes);
+ bytes += qq_get8(&q_bud->gender, data + bytes);
- nickname_len = qq_get_vstr(&buddy->nickname, QQ_CHARSET_DEFAULT, data + bytes);
- bytes += nickname_len;
- qq_filter_str(buddy->nickname);
+ pascal_len = convert_as_pascal_string(data + bytes, &q_bud->nickname, QQ_CHARSET_DEFAULT);
+ bytes += pascal_len;
+ qq_filter_str(q_bud->nickname);
/* Fixme: merge following as 32bit flag */
bytes += qq_get16(&unknown, data + bytes);
- bytes += qq_get8(&buddy->ext_flag, data + bytes);
- bytes += qq_get8(&buddy->comm_flag, 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 + nickname_len;
+ bytes_expected = 16 + pascal_len;
} else {
- bytes_expected = 12 + nickname_len;
+ bytes_expected = 12 + pascal_len;
}
- if (buddy->uid == 0 || (bytes - buddy_bytes) != bytes_expected) {
+
+ if (q_bud->uid == 0 || (bytes - buddy_bytes) != bytes_expected) {
purple_debug_info("QQ",
"Buddy entry, expect %d bytes, read %d bytes\n", bytes_expected, bytes - buddy_bytes);
- g_free(buddy->nickname);
- g_free(buddy);
+ g_free(q_bud->nickname);
+ g_free(q_bud);
continue;
} else {
count++;
@@ -313,20 +314,20 @@ guint16 qq_process_get_buddies_list_repl
#if 1
purple_debug_info("QQ", "buddy [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n",
- buddy->uid, buddy->ext_flag, buddy->comm_flag, buddy->nickname);
+ q_bud->uid, q_bud->ext_flag, q_bud->comm_flag, q_bud->nickname);
#endif
- purple_name = uid_to_purple_name(buddy->uid);
- purple_buddy = purple_find_buddy(gc->account, purple_name);
- g_free(purple_name);
+ name = uid_to_purple_name(q_bud->uid);
+ b = purple_find_buddy(gc->account, name);
+ g_free(name);
- if (purple_buddy == NULL) {
- purple_buddy = qq_create_buddy(gc, buddy->uid, TRUE, FALSE);
+ if (b == NULL) {
+ b = qq_create_buddy(gc, q_bud->uid, TRUE, FALSE);
}
- purple_buddy->proto_data = buddy;
- qd->buddies = g_list_append(qd->buddies, buddy);
- qq_update_buddy_contact(gc, buddy);
+ b->proto_data = q_bud;
+ qd->buddies = g_list_append(qd->buddies, q_bud);
+ qq_update_buddy_contact(gc, q_bud);
}
if(bytes > data_len) {
@@ -360,7 +361,7 @@ guint32 qq_process_get_buddies_and_rooms
bytes += qq_get8(&reply_code, data + bytes);
if(0 != reply_code) {
- purple_debug_warning("QQ", "qq_process_get_buddies_and_rooms, %d\n", reply_code);
+ purple_debug_warning("QQ", "qq_process_get_buddies_and_rooms, %d", reply_code);
}
bytes += qq_get32(&unknown, data + bytes);
@@ -491,7 +492,7 @@ 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)
============================================================
--- libpurple/protocols/qq/buddy_opt.c 30c3938a43b04fdf1c703f860622b3c739aaa294
+++ libpurple/protocols/qq/buddy_opt.c 1927a7ce3773676baf01458d1b8d50293e70fecf
@@ -346,7 +346,7 @@ void qq_remove_buddy_and_me(PurpleBlistN
uid = purple_name_to_uid(who);
g_return_if_fail(uid > 0);
-
+
if (uid == qd->uid) {
return;
}
@@ -501,13 +501,12 @@ PurpleGroup *qq_create_group(const gchar
/* we add new buddy, if the received packet is from someone not in my list
* return the PurpleBuddy that is just created */
-PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid,
- gboolean is_known, gboolean is_create_data)
+PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create)
{
- PurpleBuddy *purple_buddy;
+ PurpleBuddy *buddy;
PurpleGroup *group;
qq_data *qd;
- qq_buddy *buddy;
+ qq_buddy *q_bud;
gchar *buddy_name, *group_name;
g_return_val_if_fail(gc->account != NULL && uid != 0, NULL);
@@ -523,13 +522,13 @@ PurpleBuddy *qq_create_buddy(PurpleConne
group = qq_create_group(group_name);
buddy_name = uid_to_purple_name(uid);
- purple_buddy = purple_find_buddy(gc->account, buddy_name);
+ buddy = purple_find_buddy(gc->account, buddy_name);
/* remove old, we can not simply return here
* because there might be old local copy of this buddy */
- if (purple_buddy != NULL)
- purple_blist_remove_buddy(purple_buddy);
+ if (buddy != NULL)
+ purple_blist_remove_buddy(buddy);
- purple_buddy = purple_buddy_new(gc->account, buddy_name, NULL);
+ buddy = purple_buddy_new(gc->account, buddy_name, NULL);
if ( !is_known) {
if (purple_privacy_check(gc->account, buddy_name)) {
purple_privacy_deny(gc->account, buddy_name, TRUE, FALSE);
@@ -538,29 +537,29 @@ PurpleBuddy *qq_create_buddy(PurpleConne
}
}
- if (!is_create_data)
- purple_buddy->proto_data = NULL;
+ if (!create)
+ buddy->proto_data = NULL;
else {
- buddy = g_new0(qq_buddy, 1);
- buddy->uid = uid;
- purple_buddy->proto_data = buddy;
- qd->buddies = g_list_append(qd->buddies, buddy);
- qq_request_buddy_info(gc, uid, 0, 0);
+ q_bud = g_new0(qq_buddy, 1);
+ q_bud->uid = uid;
+ buddy->proto_data = q_bud;
+ qd->buddies = g_list_append(qd->buddies, q_bud);
+ qq_request_buddy_info(gc, qd->uid, 0, 0);
qq_request_get_buddies_online(gc, 0, 0);
if (qd->client_version >= 2007) {
- qq_request_get_level_2007(gc, uid);
+ qq_request_get_level_2007(gc, q_bud->uid);
} else {
- qq_request_get_level(gc, uid);
+ qq_request_get_level(gc, q_bud->uid);
}
}
- purple_blist_add_buddy(purple_buddy, NULL, group, NULL);
+ purple_blist_add_buddy(buddy, NULL, group, NULL);
purple_debug_warning("QQ", "Add new buddy: [%s]\n", buddy_name);
g_free(buddy_name);
g_free(group_name);
- return purple_buddy;
+ return buddy;
}
qq_buddy *qq_get_buddy(PurpleConnection *gc, guint32 uid)
@@ -575,9 +574,9 @@ qq_buddy *qq_get_buddy(PurpleConnection
purple_buddy = purple_find_buddy(purple_connection_get_account(gc), purple_name);
g_free(purple_name);
if (purple_buddy == NULL) return NULL;
-
+
if (purple_buddy->proto_data == NULL) {
- purple_debug_error("QQ", "Can not find buddy data of %d\n", uid);
+ purple_debug_error("QQ", "Null data of buddy %d\n", uid);
return NULL;
}
return (qq_buddy *) purple_buddy->proto_data;
============================================================
--- libpurple/protocols/qq/buddy_opt.h 473416970c5daaff96838e8d22030f400f870190
+++ libpurple/protocols/qq/buddy_opt.h a8aa4abd2b033d840cb17e674ff9740de2f5c6c4
@@ -36,8 +36,7 @@ void qq_remove_buddy(PurpleConnection *g
const char *old_group, const char *new_group);
void qq_remove_buddy_and_me(PurpleBlistNode * node);
void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
-PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid,
- gboolean is_known, gboolean is_create_data);
+PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create);
void qq_buddies_list_free(PurpleAccount *account, qq_data *qd);
void qq_process_buddy_remove(guint8 *buf, gint buf_len, PurpleConnection *gc);
============================================================
--- libpurple/protocols/qq/char_conv.c ba89588cf39e61f57b36476bcbf92a1a2e906049
+++ libpurple/protocols/qq/char_conv.c 31b8a186e0b6c66790a4cde4ee5bb3be65e00cf6
@@ -98,7 +98,7 @@ static gboolean _check_underline(gchar f
}
/* convert a string from from_charset to to_charset, using g_convert */
-static gchar *do_convert(const gchar *str, gssize len, const gchar *to_charset, const gchar *from_charset)
+static gchar *_my_convert(const gchar *str, gssize len, const gchar *to_charset, const gchar *from_charset)
{
GError *error = NULL;
gchar *ret;
@@ -128,18 +128,14 @@ static gchar *do_convert(const gchar *st
* returns the number of bytes read, return -1 if fatal error
* the converted UTF-8 will be saved in ret
*/
-gint qq_get_vstr(gchar **ret, const gchar *from_charset, guint8 *data)
+gint convert_as_pascal_string(guint8 *data, gchar **ret, const gchar *from_charset)
{
guint8 len;
g_return_val_if_fail(data != NULL && from_charset != NULL, -1);
len = data[0];
- if (len == 0) {
- *ret = g_strdup("");
- return 1;
- }
- *ret = do_convert((gchar *) (data + 1), (gssize) len, UTF8, from_charset);
+ *ret = _my_convert((gchar *) (data + 1), (gssize) len, UTF8, from_charset);
return len + 1;
}
@@ -218,15 +214,15 @@ gchar *qq_encode_to_purple(guint8 *data,
return ret;
}
-/* two convenience methods, using do_convert */
+/* two convenience methods, using _my_convert */
gchar *utf8_to_qq(const gchar *str, const gchar *to_charset)
{
- return do_convert(str, -1, to_charset, UTF8);
+ return _my_convert(str, -1, to_charset, UTF8);
}
gchar *qq_to_utf8(const gchar *str, const gchar *from_charset)
{
- return do_convert(str, -1, UTF8, from_charset);
+ return _my_convert(str, -1, UTF8, from_charset);
}
/* QQ uses binary code for smiley, while purple uses strings.
============================================================
--- libpurple/protocols/qq/char_conv.h 75967b49f64945d2895ba0c3e6ccfd8ab7a8c775
+++ libpurple/protocols/qq/char_conv.h c64955f321ca01b9e69ceb6af5638f729504b316
@@ -29,7 +29,7 @@
#define QQ_CHARSET_DEFAULT "GB18030"
-gint qq_get_vstr(gchar **ret, const gchar *from_charset, guint8 *data);
+gint convert_as_pascal_string(guint8 *data, gchar **ret, const gchar *from_charset);
gchar *qq_smiley_to_purple(gchar *text);
gchar *purple_smiley_to_qq(gchar *text);
============================================================
--- libpurple/protocols/qq/group_conv.c f4eed693830c31d316dde54fc32af5a82c065e37
+++ libpurple/protocols/qq/group_conv.c 7615797f0108d685b7433b6aa67efaa649b74043
@@ -74,64 +74,55 @@ void qq_group_conv_refresh_online_member
gchar *member_name, *member_uid;
PurpleConversation *conv;
gint flag;
- gboolean is_find;
g_return_if_fail(group != NULL);
+ names = NULL;
+ flags = NULL;
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
group->title_utf8, purple_connection_get_account(gc));
+ if (conv != NULL && group->members != NULL) {
+ list = group->members;
+ while (list != NULL) {
+ member = (qq_buddy *) list->data;
- g_return_if_fail (conv != NULL && group->members != NULL);
+ /* we need unique identifiers for everyone in the chat or else we'll
+ * run into problems with functions like get_cb_real_name from qq.c */
+ member_name = (member->nickname != NULL && *(member->nickname) != '\0') ?
+ g_strdup_printf("%s (%u)", member->nickname, member->uid) :
+ g_strdup_printf("(%u)", member->uid);
+ member_uid = g_strdup_printf("(%u)", member->uid);
- names = NULL;
- flags = NULL;
+ flag = 0;
+ /* TYPING to put online above OP and FOUNDER */
+ if (is_online(member->status))
+ flag |= (PURPLE_CBFLAGS_TYPING | PURPLE_CBFLAGS_VOICE);
+ if(1 == (member->role & 1)) flag |= PURPLE_CBFLAGS_OP;
+ if(member->uid == group->creator_uid) flag |= PURPLE_CBFLAGS_FOUNDER;
- list = group->members;
- while (list != NULL) {
- member = (qq_buddy *) list->data;
-
- /* we need unique identifiers for everyone in the chat or else we'll
- * run into problems with functions like get_cb_real_name from qq.c */
- member_name = (member->nickname != NULL && *(member->nickname) != '\0') ?
- g_strdup_printf("%s (%u)", member->nickname, member->uid) :
- g_strdup_printf("(%u)", member->uid);
- member_uid = g_strdup_printf("(%u)", member->uid);
-
- flag = 0;
- /* TYPING to put online above OP and FOUNDER */
- if (is_online(member->status)) flag |= (PURPLE_CBFLAGS_TYPING | PURPLE_CBFLAGS_VOICE);
- if(1 == (member->role & 1)) flag |= PURPLE_CBFLAGS_OP;
- if(member->uid == group->creator_uid) flag |= PURPLE_CBFLAGS_FOUNDER;
-
- is_find = TRUE;
- if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_name))
- {
- purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv),
- member_name,
- flag);
- } else if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_uid))
- {
- purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv),
- member_uid,
- flag);
- purple_conv_chat_rename_user(PURPLE_CONV_CHAT(conv), member_uid, member_name);
- } else {
- is_find = FALSE;
+ if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_name))
+ {
+ purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv),
+ member_name,
+ flag);
+ } else if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_uid))
+ {
+ purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv),
+ member_uid,
+ flag);
+ purple_conv_chat_rename_user(PURPLE_CONV_CHAT(conv), member_uid, member_name);
+ } else {
+ /* always put it even offline */
+ names = g_list_append(names, member_name);
+ flags = g_list_append(flags, GINT_TO_POINTER(flag));
+ }
+ g_free(member_uid);
+ list = list->next;
}
- if (!is_find) {
- /* always put it even offline */
- names = g_list_append(names, member_name);
- flags = g_list_append(flags, GINT_TO_POINTER(flag));
- } else {
- g_free(member_name);
- }
- g_free(member_uid);
- list = list->next;
- }
- if (names != NULL && flags != NULL) {
- purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE);
+ if (names != NULL && flags != NULL) {
+ purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE);
+ }
}
-
/* clean up names */
while (names != NULL) {
member_name = (gchar *) names->data;
============================================================
--- libpurple/protocols/qq/group_im.c f5541027af16174014a720973ce185fdf6c02af3
+++ libpurple/protocols/qq/group_im.c 3966fcb6e6a1f8fda309e328d46e8b5830d3eb4c
@@ -107,7 +107,7 @@ void qq_process_room_msg_apply_join(guin
g_return_if_fail(ext_id > 0 && user_uid > 0);
- bytes += qq_get_vstr(&reason_utf8, QQ_CHARSET_DEFAULT, data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT);
msg = g_strdup_printf(_("%d request to join Qun %d"), user_uid, ext_id);
reason = g_strdup_printf(_("Message: %s"), reason_utf8);
@@ -161,7 +161,7 @@ void qq_room_got_chat_in(PurpleConnectio
if (uid_from != 0) {
buddy = qq_group_find_member_by_uid(group, uid_from);
if (buddy == NULL || buddy->nickname == NULL)
- from = g_strdup_printf("%d", uid_from);
+ from = uid_to_purple_name(uid_from);
else
from = g_strdup(buddy->nickname);
} else {
@@ -192,7 +192,7 @@ void qq_process_room_msg_been_rejected(g
g_return_if_fail(ext_id > 0 && admin_uid > 0);
- bytes += qq_get_vstr(&reason_utf8, QQ_CHARSET_DEFAULT, data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT);
msg = g_strdup_printf
(_("Failed to join Qun %d, operated by admin %d"), ext_id, admin_uid);
@@ -231,7 +231,7 @@ void qq_process_room_msg_been_approved(g
g_return_if_fail(ext_id > 0 && admin_uid > 0);
/* it is also a "?" here, so do not display */
- bytes += qq_get_vstr(&reason, QQ_CHARSET_DEFAULT, data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &reason, QQ_CHARSET_DEFAULT);
group = qq_room_search_id(gc, id);
if (group != NULL) {
@@ -317,7 +317,7 @@ void qq_process_room_msg_been_added(guin
}
/* recv an IM from a group chat */
-void qq_process_room_msg_normal(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type)
+void qq_process_room_msg_normal(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type)
{
gchar *msg_with_purple_smiley, *msg_utf8_encoded;
qq_data *qd;
@@ -353,7 +353,7 @@ void qq_process_room_msg_normal(guint8 *
bytes += qq_get32(&(packet.ext_id), data + bytes);
bytes += qq_get8(&(packet.type8), data + bytes);
- if(QQ_MSG_TEMP_QUN_IM == msg_type) {
+ if(QQ_RECV_IM_TEMP_QUN_IM == im_type) {
bytes += qq_get32(&(id), data + bytes);
}
@@ -384,7 +384,7 @@ void qq_process_room_msg_normal(guint8 *
* buf.getInt();
*/
- if(msg_type != QQ_MSG_UNKNOWN_QUN_IM)
+ if(im_type != QQ_RECV_IM_UNKNOWN_QUN_IM)
skip_len = 10;
else
skip_len = 0;
============================================================
--- libpurple/protocols/qq/group_im.h c88a46b90ac649fc8ee4a03e39dd63a7838bda66
+++ libpurple/protocols/qq/group_im.h f082bf0a6d5c24f2fa63cf2d18a18461f1283fbb
@@ -36,7 +36,7 @@ void qq_process_group_cmd_im(guint8 *dat
void qq_process_group_cmd_im(guint8 *data, gint len, PurpleConnection *gc);
-void qq_process_room_msg_normal(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type);
+void qq_process_room_msg_normal(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type);
void qq_process_room_msg_apply_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc);
============================================================
--- libpurple/protocols/qq/group_info.c 8b6e7e7e5e215fbc04e1e2df9c5cafec71a894a0
+++ libpurple/protocols/qq/group_info.c e2f85dba96ba90bbfe4bf8b31862726fed324c53
@@ -157,7 +157,7 @@ void qq_process_room_cmd_get_info(guint8
qd = (qq_data *) gc->proto_data;
/* qq_show_packet("Room Info", data, data_len); */
-
+
bytes = 0;
bytes += qq_get32(&id, data + bytes);
g_return_if_fail(id > 0);
@@ -191,16 +191,15 @@ void qq_process_room_cmd_get_info(guint8
purple_debug_info("QQ", "type=%u creatorid=%u category=%u maxmembers=%u\n",
group->type8, group->creator_uid, group->category, max_members);
- if (qd->client_version >= 2007) {
- /* skip 7 bytes unknow in qq2007 0x(00 00 01 00 00 00 fc)*/
- bytes += 7;
- }
+ /* skip 7 bytes unknow in qq2007 0x(00 00 01 00 00 00 fc)*/
+ bytes += 7;
+
/* qq_show_packet("Room Info", data + bytes, data_len - bytes); */
/* strlen + <str content> */
- bytes += qq_get_vstr(&(group->title_utf8), QQ_CHARSET_DEFAULT, data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &(group->title_utf8), QQ_CHARSET_DEFAULT);
bytes += qq_get16(&unknown, data + bytes); /* 0x0000 */
- bytes += qq_get_vstr(¬ice, QQ_CHARSET_DEFAULT, data + bytes);
- bytes += qq_get_vstr(&(group->desc_utf8), QQ_CHARSET_DEFAULT, data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, ¬ice, QQ_CHARSET_DEFAULT);
+ bytes += convert_as_pascal_string(data + bytes, &(group->desc_utf8), QQ_CHARSET_DEFAULT);
purple_debug_info("QQ", "room [%s] notice [%s] desc [%s] unknow 0x%04X\n",
group->title_utf8, notice, group->desc_utf8, unknown);
@@ -315,7 +314,9 @@ void qq_process_room_cmd_get_buddies(gui
g_return_if_fail(data != NULL && len > 0);
- /* qq_show_packet("qq_process_room_cmd_get_buddies", data, len); */
+#if 0
+ qq_show_packet("qq_process_room_cmd_get_buddies", data, len);
+#endif
bytes = 0;
bytes += qq_get32(&id, data + bytes);
@@ -336,7 +337,7 @@ void qq_process_room_cmd_get_buddies(gui
bytes += qq_get16(&(member->face), data + bytes);
bytes += qq_get8(&(member->age), data + bytes);
bytes += qq_get8(&(member->gender), data + bytes);
- bytes += qq_get_vstr(&nick, QQ_CHARSET_DEFAULT, data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &nick, QQ_CHARSET_DEFAULT);
bytes += qq_get16(&unknown, data + bytes);
bytes += qq_get8(&(member->ext_flag), data + bytes);
bytes += qq_get8(&(member->comm_flag), data + bytes);
============================================================
--- libpurple/protocols/qq/group_search.c c5319ea7ed2161cea7094b975136175f3d1b13db
+++ libpurple/protocols/qq/group_search.c 9109c264ca8a47e9e284ba5388fd2fdb1a16e6b1
@@ -110,10 +110,10 @@ void qq_process_group_cmd_search_group(g
bytes += qq_get16(&(unknown), data + bytes);
bytes += qq_get16(&(unknown), data + bytes);
bytes += qq_get32(&(group.category), data + bytes);
- bytes += qq_get_vstr(&(group.title_utf8), QQ_CHARSET_DEFAULT, data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &(group.title_utf8), QQ_CHARSET_DEFAULT);
bytes += qq_get16(&(unknown), data + bytes);
bytes += qq_get8(&(group.auth_type), data + bytes);
- bytes += qq_get_vstr(&(group.desc_utf8), QQ_CHARSET_DEFAULT, data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &(group.desc_utf8), QQ_CHARSET_DEFAULT);
/* end of one qq_group */
if(bytes != len) {
purple_debug_error("QQ",
============================================================
--- libpurple/protocols/qq/im.c 149454f1c6459b5284ce03fbca93b582f51cdd16
+++ libpurple/protocols/qq/im.c 4db6a4426726984be7305ad84bf712aa44b00edc
@@ -35,6 +35,7 @@
#include "buddy_list.h"
#include "buddy_opt.h"
#include "char_conv.h"
+#include "group_im.h"
#include "qq_define.h"
#include "im.h"
#include "packet_parse.h"
@@ -42,6 +43,7 @@
#include "send_file.h"
#include "utils.h"
+#define QQ_SEND_IM_REPLY_OK 0x00
#define DEFAULT_FONT_NAME_LEN 4
enum
@@ -62,15 +64,52 @@ enum
QQ_NORMAL_IM_FILE_EX_NOTIFY_IP = 0x87
};
-typedef struct _qq_im_header qq_im_header;
-typedef struct _qq_recv_extended_im_text qq_recv_extended_im_text;
+enum {
+ QQ_RECV_SYS_IM_KICK_OUT = 0x01
+};
-struct _qq_im_header {
+typedef struct _qq_recv_im_header qq_recv_im_header;
+typedef struct _qq_recv_normal_im_text qq_recv_normal_im_text;
+typedef struct _qq_recv_normal_im_common qq_recv_normal_im_common;
+typedef struct _qq_recv_normal_im_unprocessed qq_recv_normal_im_unprocessed;
+
+struct _qq_recv_normal_im_common {
/* this is the common part of normal_text */
- guint16 version_from;
- guint32 uid_from;
- guint32 uid_to;
+ guint16 sender_ver;
+ guint32 sender_uid;
+ guint32 receiver_uid;
guint8 session_md5[QQ_KEY_LENGTH];
+ guint16 normal_im_type;
+};
+
+struct _qq_recv_normal_im_text {
+ qq_recv_normal_im_common *common;
+ /* now comes the part for text only */
+ guint16 msg_seq;
+ guint32 send_time;
+ guint16 sender_icon;
+ guint8 unknown2[3];
+ guint8 is_there_font_attr;
+ guint8 unknown3[4];
+ guint8 msg_type;
+ gchar *msg; /* no fixed length, ends with 0x00 */
+ guint8 *font_attr;
+ gint font_attr_len;
+};
+
+struct _qq_recv_normal_im_unprocessed {
+ qq_recv_normal_im_common *common;
+ /* now comes the part of unprocessed */
+ guint8 *unknown; /* no fixed length */
+ gint length;
+};
+
+struct _qq_recv_im_header {
+ guint32 sender_uid;
+ guint32 receiver_uid;
+ guint32 server_im_seq;
+ struct in_addr sender_ip;
+ guint16 sender_port;
guint16 im_type;
};
@@ -143,22 +182,118 @@ guint8 *qq_get_send_im_tail(const gchar
return (guint8 *) send_im_tail;
}
+static const gchar *qq_get_recv_im_type_str(gint type)
+{
+ switch (type) {
+ case QQ_RECV_IM_TO_BUDDY:
+ return "QQ_RECV_IM_TO_BUDDY";
+ case QQ_RECV_IM_TO_UNKNOWN:
+ return "QQ_RECV_IM_TO_UNKNOWN";
+ case QQ_RECV_IM_UNKNOWN_QUN_IM:
+ return "QQ_RECV_IM_UNKNOWN_QUN_IM";
+ case QQ_RECV_IM_ADD_TO_QUN:
+ return "QQ_RECV_IM_ADD_TO_QUN";
+ case QQ_RECV_IM_DEL_FROM_QUN:
+ return "QQ_RECV_IM_DEL_FROM_QUN";
+ case QQ_RECV_IM_APPLY_ADD_TO_QUN:
+ return "QQ_RECV_IM_APPLY_ADD_TO_QUN";
+ case QQ_RECV_IM_CREATE_QUN:
+ return "QQ_RECV_IM_CREATE_QUN";
+ case QQ_RECV_IM_SYS_NOTIFICATION:
+ return "QQ_RECV_IM_SYS_NOTIFICATION";
+ case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN:
+ return "QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN";
+ case QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN:
+ return "QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN";
+ case QQ_RECV_IM_TEMP_QUN_IM:
+ return "QQ_RECV_IM_TEMP_QUN_IM";
+ case QQ_RECV_IM_QUN_IM:
+ return "QQ_RECV_IM_QUN_IM";
+ case QQ_RECV_IM_NEWS:
+ return "QQ_RECV_IM_NEWS";
+ case QQ_RECV_IM_FROM_BUDDY_2006:
+ return "QQ_RECV_IM_FROM_BUDDY_2006";
+ case QQ_RECV_IM_FROM_UNKNOWN_2006:
+ return "QQ_RECV_IM_FROM_UNKNOWN_2006";
+ default:
+ return "QQ_RECV_IM_UNKNOWN";
+ }
+}
+
/* read the common parts of the normal_im,
* returns the bytes read if succeed, or -1 if there is any error */
-static gint get_im_header(qq_im_header *im_header, guint8 *data, gint len)
+static gint normal_im_common_read(guint8 *data, gint len, qq_recv_normal_im_common *common)
{
gint bytes;
- g_return_val_if_fail(data != NULL && len > 0, -1);
+ g_return_val_if_fail(data != NULL && len != 0 && common != NULL, -1);
bytes = 0;
- bytes += qq_get16(&(im_header->version_from), data + bytes);
- bytes += qq_get32(&(im_header->uid_from), data + bytes);
- bytes += qq_get32(&(im_header->uid_to), data + bytes);
- bytes += qq_getdata(im_header->session_md5, QQ_KEY_LENGTH, data + bytes);
- bytes += qq_get16(&(im_header->im_type), data + bytes);
+ /* now push data into common header */
+ bytes += qq_get16(&(common->sender_ver), data + bytes);
+ bytes += qq_get32(&(common->sender_uid), data + bytes);
+ bytes += qq_get32(&(common->receiver_uid), data + bytes);
+ bytes += qq_getdata(common->session_md5, QQ_KEY_LENGTH, data + bytes);
+ bytes += qq_get16(&(common->normal_im_type), data + bytes);
+
+ if (bytes != 28) { /* read common place fail */
+ purple_debug_error("QQ", "Expect 28 bytes, read %d bytes\n", bytes);
+ return -1;
+ }
+
return bytes;
}
+static void process_recv_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);
+
+#if 0
+ qq_show_packet("Rcv news", data, data_len);
+#endif
+
+ 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);
+}
+
void qq_got_attention(PurpleConnection *gc, const gchar *msg)
{
qq_data *qd;
@@ -181,316 +316,215 @@ void qq_got_attention(PurpleConnection *
}
/* process received normal text IM */
-static void process_im_text(PurpleConnection *gc, guint8 *data, gint len, qq_im_header *im_header)
+static void process_recv_normal_im_text(guint8 *data, gint len, qq_recv_normal_im_common *common, PurpleConnection *gc)
{
guint16 purple_msg_type;
gchar *name;
gchar *msg_with_purple_smiley;
gchar *msg_utf8_encoded;
qq_data *qd;
+ qq_recv_normal_im_text *im_text;
gint bytes = 0;
PurpleBuddy *b;
qq_buddy *qq_b;
- struct {
- /* now comes the part for text only */
- guint16 msg_seq;
- guint32 send_time;
- guint16 sender_icon;
- guint8 unknown2[3];
- guint8 is_there_font_attr;
- guint8 unknown3[4];
- guint8 msg_type;
- gchar *msg; /* no fixed length, ends with 0x00 */
- guint8 *font_attr;
- gint font_attr_len;
- } im_text;
+ g_return_if_fail(common != NULL);
+ qd = (qq_data *) gc->proto_data;
- g_return_if_fail (data != NULL && len > 0);
- g_return_if_fail(im_header != NULL);
-
- qd = (qq_data *) gc->proto_data;
- memset(&im_text, 0, sizeof(im_text));
-
+ /* now it is QQ_NORMAL_IM_TEXT */
+ /*
+ if (*cursor >= (data + len - 1)) {
+ purple_debug_warning("QQ", "Received normal IM text is empty\n");
+ return;
+ } else
+ */
+ im_text = g_newa(qq_recv_normal_im_text, 1);
+
+ im_text->common = common;
+
/* push data into im_text */
- bytes += qq_get16(&(im_text.msg_seq), data + bytes);
- bytes += qq_get32(&(im_text.send_time), data + bytes);
- bytes += qq_get16(&(im_text.sender_icon), data + bytes);
- bytes += qq_getdata((guint8 *) & (im_text.unknown2), 3, data + bytes);
- bytes += qq_get8(&(im_text.is_there_font_attr), data + bytes);
+ bytes += qq_get16(&(im_text->msg_seq), data + bytes);
+ bytes += qq_get32(&(im_text->send_time), data + bytes);
+ bytes += qq_get16(&(im_text->sender_icon), data + bytes);
+ bytes += qq_getdata((guint8 *) & (im_text->unknown2), 3, data + bytes);
+ bytes += qq_get8(&(im_text->is_there_font_attr), data + bytes);
/**
* from lumaqq for unknown3
* totalFragments = buf.get() & 255;
* fragmentSequence = buf.get() & 255;
* messageId = buf.getChar();
*/
- bytes += qq_getdata((guint8 *) & (im_text.unknown3), 4, data + bytes);
- bytes += qq_get8(&(im_text.msg_type), data + bytes);
+ bytes += qq_getdata((guint8 *) & (im_text->unknown3), 4, data + bytes);
+ bytes += qq_get8(&(im_text->msg_type), data + bytes);
/* we need to check if this is auto-reply
* QQ2003iii build 0304, returns the msg without font_attr
* even the is_there_font_attr shows 0x01, and msg does not ends with 0x00 */
- if (im_text.msg_type == QQ_IM_AUTO_REPLY) {
- im_text.is_there_font_attr = 0x00; /* indeed there is no this flag */
- im_text.msg = g_strndup((gchar *)(data + bytes), len - bytes);
+ if (im_text->msg_type == QQ_IM_AUTO_REPLY) {
+ im_text->is_there_font_attr = 0x00; /* indeed there is no this flag */
+ im_text->msg = g_strndup((gchar *)(data + bytes), len - bytes);
} else { /* it is normal mesasge */
- if (im_text.is_there_font_attr) {
- im_text.msg = g_strdup((gchar *)(data + bytes));
- bytes += strlen(im_text.msg) + 1; /* length decided by strlen! will it cause a crash? */
- im_text.font_attr_len = len - bytes;
- im_text.font_attr = g_memdup(data + bytes, im_text.font_attr_len);
- } else /* not im_text.is_there_font_attr */
- im_text.msg = g_strndup((gchar *)(data + bytes), len - bytes);
- } /* if im_text.msg_type */
+ if (im_text->is_there_font_attr) {
+ im_text->msg = g_strdup((gchar *)(data + bytes));
+ bytes += strlen(im_text->msg) + 1; /* length decided by strlen! will it cause a crash? */
+ im_text->font_attr_len = len - bytes;
+ im_text->font_attr = g_memdup(data + bytes, im_text->font_attr_len);
+ } else /* not im_text->is_there_font_attr */
+ im_text->msg = g_strndup((gchar *)(data + bytes), len - bytes);
+ } /* if im_text->msg_type */
- name = uid_to_purple_name(im_header->uid_from);
+ name = uid_to_purple_name(common->sender_uid);
b = purple_find_buddy(gc->account, name);
if (b == NULL) {
- qq_create_buddy(gc, im_header->uid_from, FALSE, TRUE);
+ qq_create_buddy(gc, common->sender_uid, FALSE, TRUE);
b = purple_find_buddy(gc->account, name);
}
qq_b = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
if (qq_b != NULL) {
- qq_b->client_tag = im_header->version_from;
+ qq_b->client_tag = common->sender_ver;
}
- purple_msg_type = (im_text.msg_type == QQ_IM_AUTO_REPLY) ? PURPLE_MESSAGE_AUTO_RESP : 0;
+ purple_msg_type = (im_text->msg_type == QQ_IM_AUTO_REPLY) ? PURPLE_MESSAGE_AUTO_RESP : 0;
- msg_with_purple_smiley = qq_smiley_to_purple(im_text.msg);
- 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_smiley_to_purple(im_text->msg);
+ 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, 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,
+ /* send encoded to purple, note that we use im_text->send_time,
* not the time we receive the message
* as it may have been delayed when I am not online. */
- serv_got_im(gc, name, msg_utf8_encoded, purple_msg_type, (time_t) im_text.send_time);
+ serv_got_im(gc, name, msg_utf8_encoded, purple_msg_type, (time_t) im_text->send_time);
g_free(msg_utf8_encoded);
g_free(msg_with_purple_smiley);
g_free(name);
- g_free(im_text.msg);
- if (im_text.font_attr) g_free(im_text.font_attr);
+ g_free(im_text->msg);
+ if (im_text->is_there_font_attr)
+ g_free(im_text->font_attr);
}
-/* process received extended (2007) text IM */
-static void process_extend_im_text(
- PurpleConnection *gc, guint8 *data, gint len, qq_im_header *im_header)
-{
- guint16 purple_msg_type;
- gchar *name;
- gchar *msg_with_purple_smiley;
- gchar *msg_utf8_encoded;
- qq_data *qd;
- gint bytes, text_len;
-
- struct {
- /* now comes the part for text only */
- guint16 sessionId;
- guint32 send_time;
- guint16 senderHead;
- guint32 flag;
- guint8 unknown2[8];
- guint8 fragmentCount;
- guint8 fragmentIndex;
- guint16 messageId;
- guint8 replyType;
- gchar *msg; /* no fixed length, ends with 0x00 */
- guint8 fromMobileQQ;
-
- guint8 is_there_font_attr;
- guint8 *font_attr;
- gint8 font_attr_len;
- } im_text;
-
- g_return_if_fail (data != NULL && len > 0);
- g_return_if_fail(im_header != NULL);
-
- qd = (qq_data *) gc->proto_data;
- memset(&im_text, 0, sizeof(im_text));
-
- /* push data into im_text */
- bytes = 0;
- bytes += qq_get16(&(im_text.sessionId), data + bytes);
- bytes += qq_get32(&(im_text.send_time), data + bytes);
- bytes += qq_get16(&(im_text.senderHead), data + bytes);
- bytes += qq_get32(&(im_text.flag), data + bytes);
-
- bytes += qq_getdata(im_text.unknown2, 8, data + bytes);
- bytes += qq_get8(&(im_text.fragmentCount), data + bytes);
- bytes += qq_get8(&(im_text.fragmentIndex), data + bytes);
-
- bytes += qq_get16(&(im_text.messageId), data + bytes);
- bytes += qq_get8(&(im_text.replyType), data + bytes);
-
- im_text.font_attr_len = data[len-1] & 0xff;
-
- text_len = len - bytes - im_text.font_attr_len;
- im_text.msg = g_strndup((gchar *)(data + bytes), text_len);
- bytes += text_len;
- if(im_text.font_attr_len >= 0)
- im_text.font_attr = g_memdup(data + bytes, im_text.font_attr_len);
- else
- {
- purple_debug_error("QQ", "Failed to get IM's font attribute len %d\n",
- im_text.font_attr_len);
- return;
- }
-
- if(im_text.fragmentCount == 0)
- im_text.fragmentCount = 1;
-
- // Filter tail space
- if(im_text.fragmentIndex == im_text.fragmentCount -1)
- {
- gint real_len = text_len;
- while(real_len > 0 && im_text.msg[real_len - 1] == 0x20)
- real_len --;
-
- text_len = real_len;
- // Null string instaed of space
- im_text.msg[text_len] = 0;
- }
-
- name = uid_to_purple_name(im_header->uid_from);
- if (purple_find_buddy(gc->account, name) == NULL)
- qq_create_buddy(gc, im_header->uid_from, FALSE, TRUE);
-
- purple_msg_type = 0;
-
- msg_with_purple_smiley = qq_smiley_to_purple(im_text.msg);
- msg_utf8_encoded = im_text.font_attr ?
- qq_encode_to_purple(im_text.font_attr,
- im_text.font_attr_len,
- 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
- * as it may have been delayed when I am not online. */
- serv_got_im(gc, name, msg_utf8_encoded, purple_msg_type, (time_t) im_text.send_time);
-
- g_free(msg_utf8_encoded);
- g_free(msg_with_purple_smiley);
- g_free(name);
- g_free(im_text.msg);
- if (im_text.font_attr) g_free(im_text.font_attr);
-}
-
/* it is a normal IM, maybe text or video request */
-void qq_process_im(PurpleConnection *gc, guint8 *data, gint len)
+static void process_recv_normal_im(guint8 *data, gint len, PurpleConnection *gc)
{
gint bytes = 0;
- qq_im_header im_header;
+ qq_recv_normal_im_common *common;
+ qq_recv_normal_im_unprocessed *im_unprocessed;
- g_return_if_fail (data != NULL && len > 0);
+ g_return_if_fail (data != NULL && len != 0);
- bytes = get_im_header(&im_header, data, len);
+ common = g_newa (qq_recv_normal_im_common, 1);
+
+ bytes = normal_im_common_read(data, len, common);
if (bytes < 0) {
- purple_debug_error("QQ", "Fail read im header, len %d\n", len);
- qq_show_packet ("IM Header", data, len);
+ purple_debug_error("QQ", "Fail read the common part of normal IM\n");
return;
}
- purple_debug_info("QQ",
- "Got IM to %d, type: %02X from: %d ver: %s (%04X)\n",
- im_header.uid_to, im_header.im_type, im_header.uid_from,
- qq_get_ver_desc(im_header.version_from), im_header.version_from);
- switch (im_header.im_type) {
+ switch (common->normal_im_type) {
case QQ_NORMAL_IM_TEXT:
+ purple_debug_info("QQ",
+ "Normal IM, text type:\n [%d] => [%d], src: %s (%04X)\n",
+ common->sender_uid, common->receiver_uid,
+ qq_get_ver_desc (common->sender_ver), common->sender_ver);
if (bytes >= len - 1) {
purple_debug_warning("QQ", "Received normal IM text is empty\n");
return;
}
- process_im_text(gc, data + bytes, len - bytes, &im_header);
+ process_recv_normal_im_text(data + bytes, len - bytes, common, gc);
break;
case QQ_NORMAL_IM_FILE_REJECT_UDP:
- qq_process_recv_file_reject(data + bytes, len - bytes, im_header.uid_from, gc);
+ qq_process_recv_file_reject(data + bytes, len - bytes, common->sender_uid, gc);
break;
case QQ_NORMAL_IM_FILE_APPROVE_UDP:
- qq_process_recv_file_accept(data + bytes, len - bytes, im_header.uid_from, gc);
+ qq_process_recv_file_accept(data + bytes, len - bytes, common->sender_uid, gc);
break;
case QQ_NORMAL_IM_FILE_REQUEST_UDP:
- qq_process_recv_file_request(data + bytes, len - bytes, im_header.uid_from, gc);
+ qq_process_recv_file_request(data + bytes, len - bytes, common->sender_uid, gc);
break;
case QQ_NORMAL_IM_FILE_CANCEL:
- qq_process_recv_file_cancel(data + bytes, len - bytes, im_header.uid_from, gc);
+ qq_process_recv_file_cancel(data + bytes, len - bytes, common->sender_uid, gc);
break;
case QQ_NORMAL_IM_FILE_NOTIFY:
- qq_process_recv_file_notify(data + bytes, len - bytes, im_header.uid_from, gc);
+ qq_process_recv_file_notify(data + bytes, len - bytes, common->sender_uid, gc);
break;
case QQ_NORMAL_IM_FILE_REQUEST_TCP:
/* Check ReceivedFileIM::parseContents in eva*/
/* some client use this function for detect invisable buddy*/
+ purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_REQUEST_TCP\n");
+ qq_show_packet ("Not support", data, len);
+ break;
case QQ_NORMAL_IM_FILE_APPROVE_TCP:
+ purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_APPROVE_TCP\n");
+ qq_show_packet ("Not support", data, len);
+ break;
case QQ_NORMAL_IM_FILE_REJECT_TCP:
+ purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_REJECT_TCP\n");
+ qq_show_packet ("Not support", data, len);
+ break;
case QQ_NORMAL_IM_FILE_PASV:
+ purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_PASV\n");
+ qq_show_packet ("Not support", data, len);
+ break;
case QQ_NORMAL_IM_FILE_EX_REQUEST_UDP:
+ purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_REQUEST_TCP\n");
+ qq_show_packet ("QQ", data, len);
+ break;
case QQ_NORMAL_IM_FILE_EX_REQUEST_ACCEPT:
+ purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_EX_REQUEST_ACCEPT\n");
+ qq_show_packet ("QQ", data, len);
+ break;
case QQ_NORMAL_IM_FILE_EX_REQUEST_CANCEL:
+ purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_EX_REQUEST_CANCEL\n");
+ qq_show_packet ("Not support", data, len);
+ break;
case QQ_NORMAL_IM_FILE_EX_NOTIFY_IP:
+ purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_EX_NOTIFY_IP\n");
qq_show_packet ("Not support", data, len);
break;
default:
+ im_unprocessed = g_newa (qq_recv_normal_im_unprocessed, 1);
+ im_unprocessed->common = common;
+ im_unprocessed->unknown = data + bytes;
+ im_unprocessed->length = len - bytes;
/* a simple process here, maybe more later */
- qq_show_packet ("Unknow", data + bytes, len - bytes);
+ purple_debug_warning("QQ",
+ "Normal IM, unprocessed type [0x%04x], len %d\n",
+ common->normal_im_type, im_unprocessed->length);
+ qq_show_packet ("QQ", im_unprocessed->unknown, im_unprocessed->length);
return;
}
}
-/* it is a extended IM, maybe text or video request */
-void qq_process_extend_im(PurpleConnection *gc, guint8 *data, gint len)
+/* process im from system administrator */
+static void process_recv_sys_im(guint8 *data, gint data_len, PurpleConnection *gc)
{
- gint bytes;
- qq_im_header im_header;
+ gint len;
+ guint8 reply;
+ gchar **segments, *msg_utf8;
- g_return_if_fail (data != NULL && len > 0);
+ g_return_if_fail(data != NULL && data_len != 0);
- bytes = get_im_header(&im_header, data, len);
- if (bytes < 0) {
- purple_debug_error("QQ", "Fail read im header, len %d\n", len);
- qq_show_packet ("IM Header", data, len);
+ len = data_len;
+
+ if (NULL == (segments = split_data(data, len, "\x2f", 2)))
return;
- }
- purple_debug_info("QQ",
- "Got Extend IM to %d, type: %02X from: %d ver: %s (%04X)\n",
- im_header.uid_to, im_header.im_type, im_header.uid_from,
- qq_get_ver_desc(im_header.version_from), im_header.version_from);
- switch (im_header.im_type) {
- case QQ_NORMAL_IM_TEXT:
- process_extend_im_text(gc, data + bytes, len - bytes, &im_header);
- break;
- case QQ_NORMAL_IM_FILE_REJECT_UDP:
- qq_process_recv_file_reject (data + bytes, len - bytes, im_header.uid_from, gc);
- break;
- case QQ_NORMAL_IM_FILE_APPROVE_UDP:
- qq_process_recv_file_accept (data + bytes, len - bytes, im_header.uid_from, gc);
- break;
- case QQ_NORMAL_IM_FILE_REQUEST_UDP:
- qq_process_recv_file_request (data + bytes, len - bytes, im_header.uid_from, gc);
- break;
- case QQ_NORMAL_IM_FILE_CANCEL:
- qq_process_recv_file_cancel (data + bytes, len - bytes, im_header.uid_from, gc);
- break;
- case QQ_NORMAL_IM_FILE_NOTIFY:
- qq_process_recv_file_notify (data + bytes, len - bytes, im_header.uid_from, gc);
- break;
- default:
- /* a simple process here, maybe more later */
- qq_show_packet ("Unknow", data + bytes, len - bytes);
- break;
- }
+ reply = strtol(segments[0], NULL, 10);
+ if (reply == QQ_RECV_SYS_IM_KICK_OUT)
+ purple_debug_warning("QQ", "We are kicked out by QQ server\n");
+ msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT);
+ purple_notify_warning(gc, NULL, _("System Message"), msg_utf8);
}
-/* send an IM to uid_to */
-void qq_request_send_im(PurpleConnection *gc, guint32 uid_to, gchar *msg, gint type)
+/* send an IM to to_uid */
+void qq_send_packet_im(PurpleConnection *gc, guint32 to_uid, gchar *msg, gint type)
{
qq_data *qd;
guint8 *raw_data, *send_im_tail;
- guint16 im_type;
+ guint16 normal_im_type;
gint msg_len, raw_len, font_name_len, tail_len, bytes;
time_t now;
gchar *msg_filtered;
@@ -500,7 +534,7 @@ void qq_request_send_im(PurpleConnection
const gchar *start, *end, *last;
qd = (qq_data *) gc->proto_data;
- im_type = QQ_NORMAL_IM_TEXT;
+ normal_im_type = QQ_NORMAL_IM_TEXT;
last = msg;
while (purple_markup_find_tag("font", last, &start, &end, &attribs)) {
@@ -557,17 +591,17 @@ void qq_request_send_im(PurpleConnection
/* 000-003: receiver uid */
bytes += qq_put32(raw_data + bytes, qd->uid);
/* 004-007: sender uid */
- bytes += qq_put32(raw_data + bytes, uid_to);
+ bytes += qq_put32(raw_data + bytes, to_uid);
/* 008-009: sender client version */
bytes += qq_put16(raw_data + bytes, qd->client_tag);
/* 010-013: receiver uid */
bytes += qq_put32(raw_data + bytes, qd->uid);
/* 014-017: sender uid */
- bytes += qq_put32(raw_data + bytes, uid_to);
+ bytes += qq_put32(raw_data + bytes, to_uid);
/* 018-033: md5 of (uid+session_key) */
bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16);
/* 034-035: message type */
- bytes += qq_put16(raw_data + bytes, im_type);
+ bytes += qq_put16(raw_data + bytes, normal_im_type);
/* 036-037: sequence number */
bytes += qq_put16(raw_data + bytes, qd->send_seq);
/* 038-041: send time */
@@ -606,5 +640,127 @@ void qq_request_send_im(PurpleConnection
g_free(msg_filtered);
}
+/* parse the reply to send_im */
+void qq_process_send_im_reply(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] != QQ_SEND_IM_REPLY_OK) {
+ purple_debug_warning("QQ", "Send IM fail\n");
+ purple_notify_error(gc, _("Error"), _("Failed to send IM."), NULL);
+ } else {
+ purple_debug_info("QQ", "IM ACK OK\n");
+ }
+}
+
+/* I receive a message, mainly it is text msg,
+ * but we need to proess other types (group etc) */
+void qq_process_recv_im(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc)
+{
+ qq_data *qd;
+ gint bytes;
+ qq_recv_im_header *im_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;
+ im_header = g_newa(qq_recv_im_header, 1);
+ bytes += qq_get32(&(im_header->sender_uid), data + bytes);
+ bytes += qq_get32(&(im_header->receiver_uid), data + bytes);
+ bytes += qq_get32(&(im_header->server_im_seq), data + bytes);
+ /* if the message is delivered via server, it is server IP/port */
+ bytes += qq_getIP(&(im_header->sender_ip), data + bytes);
+ bytes += qq_get16(&(im_header->sender_port), data + bytes);
+ bytes += qq_get16(&(im_header->im_type), data + bytes);
+ /* im_header prepared */
+
+ if (im_header->receiver_uid != qd->uid) { /* should not happen */
+ purple_debug_error("QQ", "MSG to [%d], NOT me\n", im_header->receiver_uid);
+ return;
+ }
+
+ /* check bytes */
+ if (bytes >= data_len - 1) {
+ purple_debug_warning("QQ", "Empty MSG\n");
+ return;
+ }
+
+ switch (im_header->im_type) {
+ case QQ_RECV_IM_NEWS:
+ process_recv_news(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_RECV_IM_FROM_BUDDY_2006:
+ case QQ_RECV_IM_FROM_UNKNOWN_2006:
+ case QQ_RECV_IM_TO_UNKNOWN:
+ case QQ_RECV_IM_TO_BUDDY:
+ purple_debug_info("QQ", "MSG from buddy [%d]\n", im_header->sender_uid);
+ process_recv_normal_im(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_RECV_IM_UNKNOWN_QUN_IM:
+ case QQ_RECV_IM_TEMP_QUN_IM:
+ case QQ_RECV_IM_QUN_IM:
+ purple_debug_info("QQ", "MSG from room [%d]\n", im_header->sender_uid);
+ /* sender_uid is in fact id */
+ qq_process_room_msg_normal(data + bytes, data_len - bytes, im_header->sender_uid, gc, im_header->im_type);
+ break;
+ case QQ_RECV_IM_ADD_TO_QUN:
+ purple_debug_info("QQ", "Notice from [%d], Added\n", im_header->sender_uid);
+ /* sender_uid 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, im_header->sender_uid, gc);
+ break;
+ case QQ_RECV_IM_DEL_FROM_QUN:
+ purple_debug_info("QQ", "Notice from room [%d], Removed\n", im_header->sender_uid);
+ /* sender_uid is group id */
+ qq_process_room_msg_been_removed(data + bytes, data_len - bytes, im_header->sender_uid, gc);
+ break;
+ case QQ_RECV_IM_APPLY_ADD_TO_QUN:
+ purple_debug_info("QQ", "Notice from room [%d], Joined\n", im_header->sender_uid);
+ /* sender_uid is group id */
+ qq_process_room_msg_apply_join(data + bytes, data_len - bytes, im_header->sender_uid, gc);
+ break;
+ case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN:
+ purple_debug_info("QQ", "Notice from room [%d], Confirm add in\n",
+ im_header->sender_uid);
+ /* sender_uid is group id */
+ qq_process_room_msg_been_approved(data + bytes, data_len - bytes, im_header->sender_uid, gc);
+ break;
+ case QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN:
+ purple_debug_info("QQ", "Notice from room [%d], Refuse add in\n",
+ im_header->sender_uid);
+ /* sender_uid is group id */
+ qq_process_room_msg_been_rejected(data + bytes, data_len - bytes, im_header->sender_uid, gc);
+ break;
+ case QQ_RECV_IM_SYS_NOTIFICATION:
+ purple_debug_info("QQ", "Admin notice from [%d]\n", im_header->sender_uid);
+ process_recv_sys_im(data + bytes, data_len - bytes, gc);
+ break;
+ default:
+ purple_debug_warning("QQ", "MSG from [%d], unknown type %s [0x%02x]\n",
+ im_header->sender_uid, qq_get_recv_im_type_str(im_header->im_type),
+ im_header->im_type);
+ qq_show_packet("Unknown MSG type", data, data_len);
+ }
+}
+
============================================================
--- libpurple/protocols/qq/im.h 68fc7419d10cdee69f3934cf68562b4eee133c1b
+++ libpurple/protocols/qq/im.h 0e8503aeb523371d6975e46fcff382849e1da18c
@@ -39,22 +39,21 @@ enum {
};
enum {
- QQ_MSG_TO_BUDDY = 0x0009,
- QQ_MSG_TO_UNKNOWN = 0x000a,
- QQ_MSG_NEWS = 0x0018,
- QQ_MSG_UNKNOWN_QUN_IM = 0x0020,
- QQ_MSG_ADD_TO_QUN = 0x0021,
- QQ_MSG_DEL_FROM_QUN = 0x0022,
- QQ_MSG_APPLY_ADD_TO_QUN = 0x0023,
- QQ_MSG_APPROVE_APPLY_ADD_TO_QUN = 0x0024,
- QQ_MSG_REJCT_APPLY_ADD_TO_QUN = 0x0025,
- QQ_MSG_CREATE_QUN = 0x0026,
- QQ_MSG_TEMP_QUN_IM = 0x002A,
- QQ_MSG_QUN_IM = 0x002B,
- QQ_MSG_SYS_30 = 0x0030,
- QQ_MSG_SYS_4C = 0x004C,
- QQ_MSG_EXTEND = 0x0084,
- QQ_MSG_EXTEND_85 = 0x0085,
+ QQ_RECV_IM_TO_BUDDY = 0x0009,
+ QQ_RECV_IM_TO_UNKNOWN = 0x000a,
+ QQ_RECV_IM_NEWS = 0x0018,
+ QQ_RECV_IM_UNKNOWN_QUN_IM = 0x0020,
+ QQ_RECV_IM_ADD_TO_QUN = 0x0021,
+ QQ_RECV_IM_DEL_FROM_QUN = 0x0022,
+ QQ_RECV_IM_APPLY_ADD_TO_QUN = 0x0023,
+ QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN = 0x0024,
+ QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN = 0x0025,
+ QQ_RECV_IM_CREATE_QUN = 0x0026,
+ QQ_RECV_IM_TEMP_QUN_IM = 0x002A,
+ QQ_RECV_IM_QUN_IM = 0x002B,
+ QQ_RECV_IM_SYS_NOTIFICATION = 0x0030,
+ QQ_RECV_IM_FROM_BUDDY_2006 = 0x0084,
+ QQ_RECV_IM_FROM_UNKNOWN_2006 = 0x0085,
};
void qq_got_attention(PurpleConnection *gc, const gchar *msg);
@@ -64,8 +63,8 @@ guint8 *qq_get_send_im_tail(const gchar
const gchar *font_name,
gboolean is_bold, gboolean is_italic, gboolean is_underline, gint len);
-void qq_request_send_im(PurpleConnection *gc, guint32 uid_to, gchar *msg, gint type);
+void qq_send_packet_im(PurpleConnection *gc, guint32 to_uid, gchar *msg, gint type);
+void qq_process_recv_im(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc);
+void qq_process_send_im_reply(guint8 *data, gint data_len, PurpleConnection *gc);
-void qq_process_im(PurpleConnection *gc, guint8 *data, gint len);
-void qq_process_extend_im(PurpleConnection *gc, guint8 *data, gint len);
#endif
============================================================
--- libpurple/protocols/qq/packet_parse.c 32d80ed6abd86bf50178e31f882f1709c01cb849
+++ libpurple/protocols/qq/packet_parse.c 50b4e2960eb3809ce3ddb42ac25800292a3a67ce
@@ -151,7 +151,10 @@ 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_porter;
+ guint32 dw_dest;
+ memcpy(&dw_dest, buf, sizeof(dw_dest));
+
+ guint32 dw_porter;
dw_porter = g_htonl(dw);
#ifdef PARSER_DEBUG
purple_debug_info("QQ", "[DBG][put32] buf %p\n", (void *)buf);
============================================================
--- libpurple/protocols/qq/qq.c 024c70f5255acc43a35f6c2d9abe7abf07160791
+++ libpurple/protocols/qq/qq.c c4ff8818581b7ac06ce5a0015249b143b3f8332e
@@ -435,7 +435,7 @@ static gint qq_send_im(PurpleConnection
/* send an instant msg to a buddy */
static gint qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags)
{
- gint type, uid_to;
+ gint type, to_uid;
gchar *msg, *msg_with_qq_smiley;
qq_data *qd;
@@ -446,15 +446,15 @@ static gint qq_send_im(PurpleConnection
g_return_val_if_fail(strlen(message) <= QQ_MSG_IM_MAX, -E2BIG);
type = (flags == PURPLE_MESSAGE_AUTO_RESP ? QQ_IM_AUTO_REPLY : QQ_IM_TEXT);
- uid_to = purple_name_to_uid(who);
+ to_uid = purple_name_to_uid(who);
/* if msg is to myself, bypass the network */
- if (uid_to == qd->uid) {
+ if (to_uid == qd->uid) {
serv_got_im(gc, who, message, flags, time(NULL));
} else {
msg = utf8_to_qq(message, QQ_CHARSET_DEFAULT);
msg_with_qq_smiley = purple_smiley_to_qq(msg);
- qq_request_send_im(gc, uid_to, msg_with_qq_smiley, type);
+ qq_send_packet_im(gc, to_uid, msg_with_qq_smiley, type);
g_free(msg);
g_free(msg_with_qq_smiley);
}
============================================================
--- libpurple/protocols/qq/qq_base.c 9b8171d8563b11d961d8b9d8a6395ba40573e796
+++ libpurple/protocols/qq/qq_base.c 5598f25925f3294052ae1146d456359b538cbccc
@@ -66,7 +66,7 @@ static gint8 process_login_ok(PurpleConn
struct tm *tm_local;
qd = (qq_data *) gc->proto_data;
- /* qq_show_packet("Login reply", data, len); */
+ qq_show_packet("Login reply", data, len);
if (len < 139) {
purple_connection_error_reason(gc,
@@ -665,7 +665,7 @@ guint16 qq_process_get_server(PurpleConn
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); */
+ qq_show_packet("Redirect to", qd->redirect, qd->redirect_len);
qq_getIP(&qd->redirect_ip, data + 11);
purple_debug_info("QQ", "Get server %s\n", inet_ntoa(qd->redirect_ip));
@@ -912,7 +912,7 @@ 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);
- /* qq_show_packet("Get token ex", qd->ld.token_ex, qd->ld.token_ex_len); */
+ qq_show_packet("Get token ex", qd->ld.token_ex, qd->ld.token_ex_len);
if(reply != 1)
{
@@ -932,7 +932,7 @@ guint8 qq_process_token_ex(PurpleConnect
bytes += qq_get16(&qd->captcha.token_len, data + bytes);
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); */
+ 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);
@@ -1038,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);
@@ -1068,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 */
@@ -1086,11 +1086,10 @@ guint8 qq_process_check_pwd( PurpleConne
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); */
-
+ 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)); */
+ qq_show_packet("Get login key", qd->ld.login_key, sizeof(qd->ld.login_key));
return QQ_LOGIN_REPLY_OK;
}
@@ -1203,7 +1202,7 @@ 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); */
+ 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));
@@ -1215,7 +1214,7 @@ void qq_request_login_2007(PurpleConnect
memset(raw_data + bytes, 0, 332 - sizeof(login_3_83));
bytes += 332 - sizeof(login_3_83);
- /* qq_show_packet("Login", raw_data, bytes); */
+ qq_show_packet("Login", raw_data, bytes);
encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key);
@@ -1243,24 +1242,27 @@ guint8 qq_process_login_2007( PurpleConn
gchar *msg_utf8;
g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR);
+ purple_debug_info("QQ", "FN_base, GO\n");
qd = (qq_data *) gc->proto_data;
bytes = 0;
bytes += qq_get8(&ret, data + bytes);
if (ret != 0) {
+ purple_debug_info("QQ", "FN_base, RET!=0\n");
msg = g_strndup((gchar *)data + bytes, data_len - bytes);
msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
+ purple_debug_info("QQ", "FN_base, SW RET now\n");
switch (ret) {
case 0x05:
+ purple_debug_info("QQ", "FN_base, RET:0x%02x\n", ret);
error = g_strdup_printf(
- _("Server is busy now (0x%02X), Please try later\n%s"),
- ret, msg_utf8);
+ _("Server is busy now, Please try later\n%s"),
+ msg_utf8);
break;
case 0x0A:
/* 0a 2d 9a 4b 9a 01 01 00 00 00 05 00 00 00 00 79 0e 5f fd */
- /* Missing get server before login*/
default:
error = g_strdup_printf(
_("Unknow reply code when login (0x%02X):\n%s"),
@@ -1410,7 +1412,7 @@ void qq_request_login_2008(PurpleConnect
memset(raw_data + bytes, 0, 249);
bytes += 249;
- /* qq_show_packet("Login request", raw_data, bytes); */
+ 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);
@@ -1448,8 +1450,8 @@ guint8 qq_process_login_2008( PurpleConn
switch (ret) {
case 0x05:
error = g_strdup_printf(
- _("Server is busy now (0x%02X), Please try later\n%s"),
- ret, msg_utf8);
+ _("Server is busy now, Please try later\n%s"),
+ msg_utf8);
break;
default:
error = g_strdup_printf(
============================================================
--- libpurple/protocols/qq/qq_process.c d6dd7bdb840ab2b18638b06c8f84a066d91345e7
+++ libpurple/protocols/qq/qq_process.c 959af8e9d77f5d9891a45367963a1b717ad64e56
@@ -58,7 +58,7 @@ enum {
};
/* 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 @@ static void process_unknow_cmd(PurpleCon
}
}
-/* 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 @@ static void request_server_ack(PurpleCon
"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 @@ static void process_server_msg(guint8 *d
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 @@ static void process_server_msg(guint8 *d
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 @@ void qq_proc_server_cmd(PurpleConnection
/* 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 @@ void qq_proc_server_cmd(PurpleConnection
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 @@ guint8 qq_proc_login_cmds(PurpleConnecti
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 @@ guint8 qq_proc_login_cmds(PurpleConnecti
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 @@ guint8 qq_proc_login_cmds(PurpleConnecti
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 @@ guint8 qq_proc_login_cmds(PurpleConnecti
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 @@ guint8 qq_proc_login_cmds(PurpleConnecti
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 @@ void qq_proc_client_cmds(PurpleConnectio
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 @@ void qq_proc_client_cmds(PurpleConnectio
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;
}
============================================================
--- libpurple/protocols/qq/utils.c 37c633905a0cecbf22dddab17181ef4c9d39f899
+++ libpurple/protocols/qq/utils.c 04641274f6c41533729f1f25e750ce3d1203a38d
@@ -104,7 +104,7 @@ gchar **split_data(guint8 *data, gint le
{
guint8 *input;
gchar **segments;
- gint count, j;
+ gint i, j;
g_return_val_if_fail(data != NULL && len != 0 && delimit != 0, NULL);
@@ -118,18 +118,22 @@ gchar **split_data(guint8 *data, gint le
if (expected_fields <= 0)
return segments;
- for (count = 0; segments[count] != NULL; count++) {;
+ for (i = 0; segments[i] != NULL; i++) {;
}
- if (count < expected_fields) { /* not enough fields */
- purple_debug_error("QQ", "Less fields %d then %d\n", count, expected_fields);
+ if (i < expected_fields) { /* not enough fields */
+ purple_debug_error("QQ", "Invalid data, expect %d fields, found only %d, discard\n",
+ expected_fields, i);
+ g_strfreev(segments);
return NULL;
- } else if (count > expected_fields) { /* more fields, OK */
- purple_debug_warning("QQ", "More fields %d than %d\n", count, expected_fields);
+ } else if (i > expected_fields) { /* more fields, OK */
+ purple_debug_warning("QQ", "Dangerous data, expect %d fields, found %d, return all\n",
+ expected_fields, i);
/* free up those not used */
- for (j = expected_fields; j < count; j++) {
+ for (j = expected_fields; j < i; j++) {
purple_debug_warning("QQ", "field[%d] is %s\n", j, segments[j]);
g_free(segments[j]);
}
+
segments[expected_fields] = NULL;
}
@@ -193,7 +197,7 @@ gchar *chat_name_to_purple_name(const gc
g_return_val_if_fail(start != NULL, NULL);
end = strchr(start, ')');
g_return_val_if_fail(end != NULL && (end - start) > 1, NULL);
-
+
ret = g_strndup(start + 1, end - start - 1);
return ret;
More information about the Commits
mailing list