summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSHiNE CsyFeK <csyfek@gmail.com>2008-06-24 11:58:57 +0000
committerSHiNE CsyFeK <csyfek@gmail.com>2008-06-24 11:58:57 +0000
commit5913706e48f9b7b2ca073e55b3cc7d72128e3b35 (patch)
tree99fda5a55422f273d2a5286b8b2adfd2f4f11dd0
parent037f9848fb30b353830f1efcd5e3d52695e139bf (diff)
downloadpidgin-5913706e48f9b7b2ca073e55b3cc7d72128e3b35.tar.gz
patch-02-fix-multiarch
*** patch-02-fix-multiarch *** * Rewrite read_packet and create_packet functions, use qq_put and qq_get functions instead * New logic in accord with protocol models to handle packets, some related functions rewritten Apply patch from #5639. Fix #303.
-rw-r--r--libpurple/protocols/qq/buddy_info.c331
-rw-r--r--libpurple/protocols/qq/buddy_info.h41
-rw-r--r--libpurple/protocols/qq/buddy_list.c446
-rw-r--r--libpurple/protocols/qq/buddy_opt.c139
-rw-r--r--libpurple/protocols/qq/buddy_status.c175
-rw-r--r--libpurple/protocols/qq/buddy_status.h2
-rw-r--r--libpurple/protocols/qq/char_conv.c23
-rw-r--r--libpurple/protocols/qq/crypt.c17
-rw-r--r--libpurple/protocols/qq/crypt.h9
-rw-r--r--libpurple/protocols/qq/file_trans.c421
-rw-r--r--libpurple/protocols/qq/group_im.c175
-rw-r--r--libpurple/protocols/qq/group_im.h40
-rw-r--r--libpurple/protocols/qq/group_info.c210
-rw-r--r--libpurple/protocols/qq/group_info.h6
-rw-r--r--libpurple/protocols/qq/group_join.c186
-rw-r--r--libpurple/protocols/qq/group_join.h6
-rw-r--r--libpurple/protocols/qq/group_network.c185
-rw-r--r--libpurple/protocols/qq/group_opt.c163
-rw-r--r--libpurple/protocols/qq/group_opt.h8
-rw-r--r--libpurple/protocols/qq/group_search.c85
-rw-r--r--libpurple/protocols/qq/group_search.h2
-rw-r--r--libpurple/protocols/qq/im.c410
-rw-r--r--libpurple/protocols/qq/keep_alive.c7
-rw-r--r--libpurple/protocols/qq/login_logout.c140
-rw-r--r--libpurple/protocols/qq/packet_parse.c310
-rw-r--r--libpurple/protocols/qq/packet_parse.h30
-rw-r--r--libpurple/protocols/qq/qq_proxy.c98
-rw-r--r--libpurple/protocols/qq/recv_core.c210
-rw-r--r--libpurple/protocols/qq/send_core.c116
-rw-r--r--libpurple/protocols/qq/send_core.h4
-rw-r--r--libpurple/protocols/qq/send_file.c208
-rw-r--r--libpurple/protocols/qq/send_file.h19
-rw-r--r--libpurple/protocols/qq/sys_msg.c15
33 files changed, 2318 insertions, 1919 deletions
diff --git a/libpurple/protocols/qq/buddy_info.c b/libpurple/protocols/qq/buddy_info.c
index 624b75b7bc..5a994c8c4e 100644
--- a/libpurple/protocols/qq/buddy_info.c
+++ b/libpurple/protocols/qq/buddy_info.c
@@ -94,6 +94,46 @@ typedef struct _qq_info_query {
gboolean modify_info;
} qq_info_query;
+typedef struct _contact_info {
+ gchar *uid;
+ gchar *nick;
+ gchar *country;
+ gchar *province;
+ gchar *zipcode;
+ gchar *address;
+ gchar *tel;
+ gchar *age;
+ gchar *gender;
+ gchar *name;
+ gchar *email;
+ gchar *pager_sn;
+ gchar *pager_num;
+ gchar *pager_sp;
+ gchar *pager_base_num;
+ gchar *pager_type;
+ gchar *occupation;
+ gchar *homepage;
+ gchar *auth_type;
+ gchar *unknown1;
+ gchar *unknown2;
+ gchar *face;
+ gchar *hp_num;
+ gchar *hp_type;
+ gchar *intro;
+ gchar *city;
+ gchar *unknown3;
+ gchar *unknown4;
+ gchar *unknown5;
+ gchar *is_open_hp;
+ gchar *is_open_contact;
+ gchar *college;
+ gchar *horoscope;
+ gchar *zodiac;
+ gchar *blood;
+ gchar *qq_show;
+ gchar *unknown6; /* always 0x2D */
+} contact_info;
+
/* We get an info packet on ourselves before we modify our information.
* Even though not all of the information is modifiable, it still
* all needs to be there when we send out the modify info packet */
@@ -137,7 +177,7 @@ static gchar *field_value(const gchar *field, const gchar **choice, gint choice_
} else {
return NULL;
}
- /* else ASCIIized index */
+ /* else ASCIIized index */
} else {
if (strcmp(choice[index], "-") != 0)
return g_strdup(choice[index]);
@@ -161,14 +201,14 @@ static gboolean append_field_value(PurpleNotifyUserInfo *user_info, const gchar
if (value != NULL) {
purple_notify_user_info_add_pair(user_info, title, value);
g_free(value);
-
+
return TRUE;
}
-
+
return FALSE;
}
-static PurpleNotifyUserInfo *
+ static PurpleNotifyUserInfo *
info_to_notify_user_info(const contact_info *info)
{
PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
@@ -209,25 +249,25 @@ info_to_notify_user_info(const contact_info *info)
/* for debugging */
/*
- g_string_append_printf(info_text, "<br /><br /><b>%s</b><br />", "Miscellaneous");
- append_field_value(info_text, info->pager_sn, "pager_sn", NULL, 0);
- append_field_value(info_text, info->pager_num, "pager_num", NULL, 0);
- append_field_value(info_text, info->pager_sp, "pager_sp", NULL, 0);
- append_field_value(info_text, info->pager_base_num, "pager_base_num", NULL, 0);
- append_field_value(info_text, info->pager_type, "pager_type", NULL, 0);
- append_field_value(info_text, info->auth_type, "auth_type", NULL, 0);
- append_field_value(info_text, info->unknown1, "unknown1", NULL, 0);
- append_field_value(info_text, info->unknown2, "unknown2", NULL, 0);
- append_field_value(info_text, info->face, "face", NULL, 0);
- append_field_value(info_text, info->hp_type, "hp_type", NULL, 0);
- append_field_value(info_text, info->unknown3, "unknown3", NULL, 0);
- append_field_value(info_text, info->unknown4, "unknown4", NULL, 0);
- append_field_value(info_text, info->unknown5, "unknown5", NULL, 0);
- append_field_value(info_text, info->is_open_hp, "is_open_hp", NULL, 0);
- append_field_value(info_text, info->is_open_contact, "is_open_contact", NULL, 0);
- append_field_value(info_text, info->qq_show, "qq_show", NULL, 0);
- append_field_value(info_text, info->unknown6, "unknown6", NULL, 0);
- */
+ g_string_append_printf(info_text, "<br /><br /><b>%s</b><br />", "Miscellaneous");
+ append_field_value(info_text, info->pager_sn, "pager_sn", NULL, 0);
+ append_field_value(info_text, info->pager_num, "pager_num", NULL, 0);
+ append_field_value(info_text, info->pager_sp, "pager_sp", NULL, 0);
+ append_field_value(info_text, info->pager_base_num, "pager_base_num", NULL, 0);
+ append_field_value(info_text, info->pager_type, "pager_type", NULL, 0);
+ append_field_value(info_text, info->auth_type, "auth_type", NULL, 0);
+ append_field_value(info_text, info->unknown1, "unknown1", NULL, 0);
+ append_field_value(info_text, info->unknown2, "unknown2", NULL, 0);
+ append_field_value(info_text, info->face, "face", NULL, 0);
+ append_field_value(info_text, info->hp_type, "hp_type", NULL, 0);
+ append_field_value(info_text, info->unknown3, "unknown3", NULL, 0);
+ append_field_value(info_text, info->unknown4, "unknown4", NULL, 0);
+ append_field_value(info_text, info->unknown5, "unknown5", NULL, 0);
+ append_field_value(info_text, info->is_open_hp, "is_open_hp", NULL, 0);
+ append_field_value(info_text, info->is_open_contact, "is_open_contact", NULL, 0);
+ append_field_value(info_text, info->qq_show, "qq_show", NULL, 0);
+ append_field_value(info_text, info->unknown6, "unknown6", NULL, 0);
+ */
return user_info;
}
@@ -271,27 +311,140 @@ void qq_prepare_modify_info(PurpleConnection *gc)
}
/* send packet to modify personal information */
-static void qq_send_packet_modify_info(PurpleConnection *gc, gchar **segments)
+static void qq_send_packet_modify_info(PurpleConnection *gc, contact_info *info)
{
- gint i;
- guint8 *raw_data, *cursor, bar;
+ gint bytes = 0;
+ guint8 raw_data[MAX_PACKET_SIZE - 128] = {0};
+ guint8 bar;
- g_return_if_fail(segments != NULL);
+ g_return_if_fail(info != NULL);
bar = 0x1f;
- raw_data = g_newa(guint8, MAX_PACKET_SIZE - 128);
- cursor = raw_data;
- create_packet_b(raw_data, &cursor, bar);
+ bytes += qq_put8(raw_data + bytes, bar);
/* important! skip the first uid entry */
- for (i = 1; i < QQ_CONTACT_FIELDS; i++) {
- create_packet_b(raw_data, &cursor, bar);
- create_packet_data(raw_data, &cursor, (guint8 *) segments[i], strlen(segments[i]));
- }
- create_packet_b(raw_data, &cursor, bar);
-
- qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, TRUE, 0, TRUE, raw_data, cursor - raw_data);
+ /*
+ for (i = 1; i < QQ_CONTACT_FIELDS; i++) {
+ create_packet_b(raw_data, &cursor, bar);
+ create_packet_data(raw_data, &cursor, (guint8 *) segments[i], strlen(segments[i]));
+ }
+ */
+ /* uid */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->uid, strlen(info->uid));
+ /* nick */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->nick, strlen(info->nick));
+ /* country */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->country, strlen(info->country));
+ /* province */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->province, strlen(info->province));
+ /* zipcode */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->zipcode, strlen(info->zipcode));
+ /* address */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->address, strlen(info->address));
+ /* tel */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->tel, strlen(info->tel));
+ /* age */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->age, strlen(info->age));
+ /* gender */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->gender, strlen(info->gender));
+ /* name */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->name, strlen(info->name));
+ /* email */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->email, strlen(info->email));
+ /* pager_sn */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->pager_sn, strlen(info->pager_sn));
+ /* pager_num */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->pager_num, strlen(info->pager_num));
+ /* pager_sp */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->pager_sp, strlen(info->pager_sp));
+ /* pager_base_num */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->pager_base_num, strlen(info->pager_base_num));
+ /* pager_type */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->pager_type, strlen(info->pager_type));
+ /* occupation */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->occupation, strlen(info->occupation));
+ /* homepage */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->homepage, strlen(info->homepage));
+ /* auth_type */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->auth_type, strlen(info->auth_type));
+ /* unknown1 */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->unknown1, strlen(info->unknown1));
+ /* unknown2 */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->unknown2, strlen(info->unknown2));
+ /* face */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->face, strlen(info->face));
+ /* hp_num */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->hp_num, strlen(info->hp_num));
+ /* hp_type */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->hp_type, strlen(info->hp_type));
+ /* intro */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->intro, strlen(info->intro));
+ /* city */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->city, strlen(info->city));
+ /* unknown3 */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->unknown3, strlen(info->unknown3));
+ /* unknown4 */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->unknown4, strlen(info->unknown4));
+ /* unknown5 */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->unknown5, strlen(info->unknown5));
+ /* is_open_hp */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->is_open_hp, strlen(info->is_open_hp));
+ /* is_open_contact */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->is_open_contact, strlen(info->is_open_contact));
+ /* college */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->college, strlen(info->college));
+ /* horoscope */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->horoscope, strlen(info->horoscope));
+ /* zodiac */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->zodiac, strlen(info->zodiac));
+ /* blood */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->blood, strlen(info->blood));
+ /* qq_show */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->qq_show, strlen(info->qq_show));
+ /* unknown6 */
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *)info->unknown6, strlen(info->unknown6));
+
+ bytes += qq_put8(raw_data + bytes, bar);
+
+ qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, TRUE, 0, TRUE, raw_data, bytes);
}
@@ -407,8 +560,11 @@ static void modify_info_ok_cb(modify_info_data *mid, PurpleRequestFields *fields
groups = groups->next;
}
- /* This casting looks like a horrible idea to me -DAA */
- qq_send_packet_modify_info(gc, (gchar **) info);
+ /* This casting looks like a horrible idea to me -DAA
+ * yes, rewritten -s3e
+ * qq_send_packet_modify_info(gc, (gchar **) info);
+ */
+ qq_send_packet_modify_info(gc, info);
g_strfreev((gchar **) mid->info);
g_free(mid);
@@ -520,11 +676,11 @@ static void create_modify_info_dialogue(PurpleConnection *gc, const contact_info
mid->info->unknown6 = g_strdup(info->unknown6);
purple_request_fields(gc, _("Modify my information"),
- _("Modify my information"), NULL, fields,
- _("Update my information"), G_CALLBACK(modify_info_ok_cb),
- _("Cancel"), G_CALLBACK(modify_info_cancel_cb),
- purple_connection_get_account(gc), NULL, NULL,
- mid);
+ _("Modify my information"), NULL, fields,
+ _("Update my information"), G_CALLBACK(modify_info_ok_cb),
+ _("Cancel"), G_CALLBACK(modify_info_cancel_cb),
+ purple_connection_get_account(gc), NULL, NULL,
+ mid);
}
}
@@ -578,10 +734,9 @@ void qq_set_buddy_icon_for_user(PurpleAccount *account, const gchar *who, const
gchar *data;
gsize len;
- if (!g_file_get_contents(iconfile, &data, &len, NULL))
+ if (!g_file_get_contents(iconfile, &data, &len, NULL)) {
g_return_if_reached();
- else
- {
+ } else {
purple_buddy_icons_set_for_user(account, who, data, len, icon_num);
}
}
@@ -608,10 +763,10 @@ void qq_set_my_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
/* make sure we're using an appropriate icon */
if (!(g_ascii_strncasecmp(icon_path, buddy_icon_dir, dir_len) == 0
- && icon_path[dir_len] == G_DIR_SEPARATOR
- && g_ascii_strncasecmp(icon_path + dir_len + 1, QQ_ICON_PREFIX, prefix_len) == 0
- && g_ascii_strncasecmp(icon_path + dir_len + 1 + prefix_len + icon_len, QQ_ICON_SUFFIX, suffix_len) == 0
- && icon_len <= 3)) {
+ && icon_path[dir_len] == G_DIR_SEPARATOR
+ && g_ascii_strncasecmp(icon_path + dir_len + 1, QQ_ICON_PREFIX, prefix_len) == 0
+ && g_ascii_strncasecmp(icon_path + dir_len + 1 + prefix_len + icon_len, QQ_ICON_SUFFIX, suffix_len) == 0
+ && icon_len <= 3)) {
if (icon_global)
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "%s\n", errmsg);
else
@@ -650,13 +805,13 @@ static void _qq_update_buddy_icon(PurpleAccount *account, const gchar *name, gin
old_icon_num = purple_buddy_icons_get_checksum_for_user(buddy);
if (old_icon_num == NULL ||
- strcmp(icon_num_str, old_icon_num))
+ strcmp(icon_num_str, old_icon_num))
{
gchar *icon_path;
icon_path = g_strconcat(qq_buddy_icon_dir(), G_DIR_SEPARATOR_S,
- QQ_ICON_PREFIX, icon_num_str,
- QQ_ICON_SUFFIX, NULL);
+ QQ_ICON_PREFIX, icon_num_str,
+ QQ_ICON_SUFFIX, NULL);
qq_set_buddy_icon_for_user(account, name, icon_num_str, icon_path);
g_free(icon_path);
@@ -665,7 +820,7 @@ static void _qq_update_buddy_icon(PurpleAccount *account, const gchar *name, gin
}
/* after getting info or modify myself, refresh the buddy list accordingly */
-void qq_refresh_buddy_and_myself(contact_info *info, PurpleConnection *gc)
+static void qq_refresh_buddy_and_myself(contact_info *info, PurpleConnection *gc)
{
PurpleBuddy *b;
qq_data *qd;
@@ -728,7 +883,7 @@ void qq_process_get_info_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
qd->modifying_face = FALSE;
g_free(info->face);
info->face = icon;
- qq_send_packet_modify_info(gc, segments);
+ qq_send_packet_modify_info(gc, (contact_info *)segments);
}
qq_refresh_buddy_and_myself(info, gc);
@@ -777,35 +932,35 @@ void qq_info_query_free(qq_data *qd)
void qq_send_packet_get_level(PurpleConnection *gc, guint32 uid)
{
- guint8 buf[5];
- guint32 tmp = g_htonl(uid);
- buf[0] = 0;
- memcpy(buf+1, &tmp, 4);
- qq_send_cmd(gc, QQ_CMD_GET_LEVEL, TRUE, 0, TRUE, buf, 5);
+ guint8 buf[16] = {0};
+ gint bytes = 0;
+
+ bytes += qq_put8(buf + bytes, 0x00);
+ bytes += qq_put32(buf + bytes, uid);
+
+ qq_send_cmd(gc, QQ_CMD_GET_LEVEL, TRUE, 0, TRUE, buf, bytes);
}
void qq_send_packet_get_buddies_levels(PurpleConnection *gc)
{
- guint8 *buf, *tmp;
+ guint8 *buf;
guint16 size;
qq_buddy *q_bud;
qq_data *qd = (qq_data *) gc->proto_data;
GList *node = qd->buddies;
+ gint bytes = 0;
if (qd->buddies) {
/* server only sends back levels for online buddies, no point
- * in asking for anyone else */
- size = 4*g_list_length(qd->buddies) + 1;
+ * in asking for anyone else */
+ size = 4 * g_list_length(qd->buddies) + 1;
buf = g_new0(guint8, size);
- tmp = buf + 1;
+ bytes += 1;
- while (node != NULL) {
- guint32 tmp4;
+ while (NULL != node) {
q_bud = (qq_buddy *) node->data;
- if (q_bud != NULL) {
- tmp4 = g_htonl(q_bud->uid);
- memcpy(tmp, &tmp4, 4);
- tmp += 4;
+ if (NULL != q_bud) {
+ bytes += qq_put32(buf + bytes, q_bud->uid);
}
node = node->next;
}
@@ -822,10 +977,11 @@ void qq_process_get_level_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
PurpleBuddy *b;
qq_buddy *q_bud;
gint decr_len, i;
- guint8 *decr_buf, *tmp;
+ guint8 *decr_buf;
PurpleAccount *account = purple_connection_get_account(gc);
qq_data *qd = (qq_data *) gc->proto_data;
-
+ gint bytes = 0;
+
decr_len = buf_len;
decr_buf = g_new0(guint8, buf_len);
if (!qq_decrypt(buf, buf_len, qd->session_key, decr_buf, &decr_len)) {
@@ -835,28 +991,23 @@ void qq_process_get_level_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
decr_len--;
if (decr_len % 12 != 0) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Get levels list of abnormal length. Truncating last %d bytes.\n", decr_len % 12);
+ "Get levels list of abnormal length. Truncating last %d bytes.\n", decr_len % 12);
decr_len -= (decr_len % 12);
}
-
- tmp = decr_buf + 1;
+
+ bytes += 1;
/* this byte seems random */
/*
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Byte one of get_level packet: %d\n", buf[0]);
- */
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Byte one of get_level packet: %d\n", buf[0]);
+ */
for (i = 0; i < decr_len; i += 12) {
- uid = g_ntohl(*(guint32 *) tmp);
- tmp += 4;
- onlineTime = g_ntohl(*(guint32 *) tmp);
- tmp += 4;
- level = g_ntohs(*(guint16 *) tmp);
- tmp += 2;
- timeRemainder = g_ntohs(*(guint16 *) tmp);
- tmp += 2;
- /*
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Level packet entry:\nuid: %d\nonlineTime: %d\nlevel: %d\ntimeRemainder: %d\n",
+ bytes += qq_get32(&uid, decr_buf + bytes);
+ bytes += qq_get32(&onlineTime, decr_buf + bytes);
+ bytes += qq_get16(&level, decr_buf + bytes);
+ bytes += qq_get16(&timeRemainder, decr_buf + bytes);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Level packet entry:\nuid: %d\nonlineTime: %d\nlevel: %d\ntimeRemainder: %d\n",
uid, onlineTime, level, timeRemainder);
- */
purple_name = uid_to_purple_name(uid);
b = purple_find_buddy(account, purple_name);
q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
@@ -872,7 +1023,7 @@ void qq_process_get_level_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
}
} else {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Got an online buddy %d, but not in my buddy list\n", uid);
+ "Got an online buddy %d, but not in my buddy list\n", uid);
}
g_free(purple_name);
}
diff --git a/libpurple/protocols/qq/buddy_info.h b/libpurple/protocols/qq/buddy_info.h
index 7e121f5d1f..63be1da164 100644
--- a/libpurple/protocols/qq/buddy_info.h
+++ b/libpurple/protocols/qq/buddy_info.h
@@ -44,47 +44,6 @@
#define QQ_ICON_PREFIX "qq_"
#define QQ_ICON_SUFFIX ".png"
-typedef struct _contact_info {
- gchar *uid;
- gchar *nick;
- gchar *country;
- gchar *province;
- gchar *zipcode;
- gchar *address;
- gchar *tel;
- gchar *age;
- gchar *gender;
- gchar *name;
- gchar *email;
- gchar *pager_sn;
- gchar *pager_num;
- gchar *pager_sp;
- gchar *pager_base_num;
- gchar *pager_type;
- gchar *occupation;
- gchar *homepage;
- gchar *auth_type;
- gchar *unknown1;
- gchar *unknown2;
- gchar *face;
- gchar *hp_num;
- gchar *hp_type;
- gchar *intro;
- gchar *city;
- gchar *unknown3;
- gchar *unknown4;
- gchar *unknown5;
- gchar *is_open_hp;
- gchar *is_open_contact;
- gchar *college;
- gchar *horoscope;
- gchar *zodiac;
- gchar *blood;
- gchar *qq_show;
- gchar *unknown6; /* always 0x2D */
-} contact_info;
-
-void qq_refresh_buddy_and_myself(contact_info *info, PurpleConnection *gc);
void qq_send_packet_get_info(PurpleConnection *gc, guint32 uid, gboolean show_window);
void qq_set_my_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img);
void qq_set_buddy_icon_for_user(PurpleAccount *account, const gchar *who, const gchar *icon_num, const gchar *iconfile);
diff --git a/libpurple/protocols/qq/buddy_list.c b/libpurple/protocols/qq/buddy_list.c
index 7c64455d79..69ea5fe640 100644
--- a/libpurple/protocols/qq/buddy_list.c
+++ b/libpurple/protocols/qq/buddy_list.c
@@ -64,23 +64,23 @@ typedef struct _qq_friends_online_entry {
void qq_send_packet_get_buddies_online(PurpleConnection *gc, guint8 position)
{
qq_data *qd;
- guint8 *raw_data, *cursor;
+ guint8 *raw_data;
+ gint bytes = 0;
qd = (qq_data *) gc->proto_data;
raw_data = g_newa(guint8, 5);
- cursor = raw_data;
/* 000-000 get online friends cmd
* only 0x02 and 0x03 returns info from server, other valuse all return 0xff
* I can also only send the first byte (0x02, or 0x03)
* and the result is the same */
- create_packet_b(raw_data, &cursor, QQ_GET_ONLINE_BUDDY_02);
+ bytes += qq_put8(raw_data + bytes, QQ_GET_ONLINE_BUDDY_02);
/* 001-001 seems it supports 255 online buddies at most */
- create_packet_b(raw_data, &cursor, position);
+ bytes += qq_put8(raw_data + bytes, position);
/* 002-002 */
- create_packet_b(raw_data, &cursor, 0x00);
+ bytes += qq_put8(raw_data + bytes, 0x00);
/* 003-004 */
- create_packet_w(raw_data, &cursor, 0x0000);
+ bytes += qq_put16(raw_data + bytes, 0x0000);
qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_ONLINE, TRUE, 0, TRUE, raw_data, 5);
qd->last_get_online = time(NULL);
@@ -90,42 +90,36 @@ void qq_send_packet_get_buddies_online(PurpleConnection *gc, guint8 position)
* server may return a position tag if list is too long for one packet */
void qq_send_packet_get_buddies_list(PurpleConnection *gc, guint16 position)
{
- guint8 *raw_data, *cursor;
- gint data_len;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
- data_len = 3;
- raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
/* 000-001 starting position, can manually specify */
- create_packet_w(raw_data, &cursor, position);
+ bytes += qq_put16(raw_data + bytes, position);
/* before Mar 18, 2004, any value can work, and we sent 00
* I do not know what data QQ server is expecting, as QQ2003iii 0304 itself
* even can sending packets 00 and get no response.
* Now I tested that 00,00,00,00,00,01 work perfectly
* March 22, found the 00,00,00 starts to work as well */
- create_packet_b(raw_data, &cursor, 0x00);
+ bytes += qq_put8(raw_data + bytes, 0x00);
- qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_LIST, TRUE, 0, TRUE, raw_data, data_len);
+ qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_LIST, TRUE, 0, TRUE, raw_data, bytes);
}
/* get all list, buddies & Quns with groupsid support */
void qq_send_packet_get_all_list_with_group(PurpleConnection *gc, guint32 position)
{
- guint8 *raw_data, *cursor;
- gint data_len;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
- data_len = 10;
- raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
/* 0x01 download, 0x02, upload */
- create_packet_b(raw_data, &cursor, 0x01);
+ bytes += qq_put8(raw_data + bytes, 0x01);
/* unknown 0x02 */
- create_packet_b(raw_data, &cursor, 0x02);
+ bytes += qq_put8(raw_data + bytes, 0x02);
/* unknown 00 00 00 00 */
- create_packet_dw(raw_data, &cursor, 0x00000000);
- create_packet_dw(raw_data, &cursor, position);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
+ bytes += qq_put32(raw_data + bytes, position);
- qq_send_cmd(gc, QQ_CMD_GET_ALL_LIST_WITH_GROUP, TRUE, 0, TRUE, raw_data, data_len);
+ qq_send_cmd(gc, QQ_CMD_GET_ALL_LIST_WITH_GROUP, TRUE, 0, TRUE, raw_data, bytes);
}
static void _qq_buddies_online_reply_dump_unclear(qq_friends_online_entry *fe)
@@ -151,8 +145,8 @@ static void _qq_buddies_online_reply_dump_unclear(qq_friends_online_entry *fe)
void qq_process_get_buddies_online_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len, bytes;
- guint8 *data, *cursor, position;
+ gint len, bytes, bytes_buddy;
+ guint8 *data, position;
PurpleBuddy *b;
qq_buddy *q_bud;
qq_friends_online_entry *fe;
@@ -162,96 +156,100 @@ void qq_process_get_buddies_online_reply(guint8 *buf, gint buf_len, PurpleConnec
qd = (qq_data *) gc->proto_data;
len = buf_len;
data = g_newa(guint8, len);
- cursor = data;
purple_debug(PURPLE_DEBUG_INFO, "QQ", "processing get_buddies_online_reply\n");
-
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
-
- _qq_show_packet("Get buddies online reply packet", data, len);
-
- read_packet_b(data, &cursor, len, &position);
-
- fe = g_newa(qq_friends_online_entry, 1);
- fe->s = g_newa(qq_buddy_status, 1);
-
- while (cursor < (data + len)) {
- /* based on one online buddy entry */
- bytes = 0;
- /* 000-030 qq_buddy_status */
- bytes += qq_buddy_status_read(data, &cursor, len, fe->s);
- /* 031-032: unknown4 */
- bytes += read_packet_w(data, &cursor, len, &fe->unknown1);
- /* 033-033: flag1 */
- bytes += read_packet_b(data, &cursor, len, &fe->flag1);
- /* 034-034: comm_flag */
- bytes += read_packet_b(data, &cursor, len, &fe->comm_flag);
- /* 035-036: */
- bytes += read_packet_w(data, &cursor, len, &fe->unknown2);
- /* 037-037: */
- bytes += read_packet_b(data, &cursor, len, &fe->ending); /* 0x00 */
-
- if (fe->s->uid == 0 || bytes != QQ_ONLINE_BUDDY_ENTRY_LEN) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "uid=0 or entry complete len(%d) != %d",
- bytes, QQ_ONLINE_BUDDY_ENTRY_LEN);
- g_free(fe->s->ip);
- g_free(fe->s->unknown_key);
- continue;
- } /* check if it is a valid entry */
-
- if (QQ_DEBUG)
- _qq_buddies_online_reply_dump_unclear(fe);
-
- /* update buddy information */
- b = purple_find_buddy(purple_connection_get_account(gc), uid_to_purple_name(fe->s->uid));
- q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
-
- if (q_bud != NULL) { /* we find one and update qq_buddy */
- if(0 != fe->s->client_version)
- q_bud->client_version = fe->s->client_version;
- g_memmove(q_bud->ip, fe->s->ip, 4);
- q_bud->port = fe->s->port;
- q_bud->status = fe->s->status;
- q_bud->flag1 = fe->flag1;
- q_bud->comm_flag = fe->comm_flag;
- qq_update_buddy_contact(gc, q_bud);
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Got an online buddy %d, but not in my buddy list\n", fe->s->uid);
- }
+ if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies online");
+ return;
+ }
+
+ _qq_show_packet("Get buddies online reply packet", data, len);
+
+ bytes = 0;
+ bytes += qq_get8(&position, data + bytes);
+
+ fe = g_newa(qq_friends_online_entry, 1);
+ fe->s = g_newa(qq_buddy_status, 1);
+
+ while (bytes < len) {
+ /* set flag */
+ bytes_buddy = bytes;
+ /* based on one online buddy entry */
+ /* ATTTENTION! NEWED in the sub function, but FREED here */
+ /* 000-030 qq_buddy_status */
+ bytes += qq_buddy_status_read(fe->s, data + bytes);
+ /* 031-032: unknown4 */
+ bytes += qq_get16(&fe->unknown1, data + bytes);
+ /* 033-033: flag1 */
+ bytes += qq_get8(&fe->flag1, data + bytes);
+ /* 034-034: comm_flag */
+ bytes += qq_get8(&fe->comm_flag, data + bytes);
+ /* 035-036: */
+ bytes += qq_get16(&fe->unknown2, data + bytes);
+ /* 037-037: */
+ bytes += qq_get8(&fe->ending, data + bytes); /* 0x00 */
+
+ if (fe->s->uid == 0 || (bytes - bytes_buddy) != QQ_ONLINE_BUDDY_ENTRY_LEN) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "uid=0 or entry complete len(%d) != %d",
+ (bytes - bytes_buddy), QQ_ONLINE_BUDDY_ENTRY_LEN);
g_free(fe->s->ip);
g_free(fe->s->unknown_key);
- }
-
- if(cursor > (data + len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n");
- }
+ continue;
+ } /* check if it is a valid entry */
- if (position != QQ_FRIENDS_ONLINE_POSITION_END) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Has more online buddies, position from %d\n", position);
+ if (QQ_DEBUG) {
+ _qq_buddies_online_reply_dump_unclear(fe);
+ }
- qq_send_packet_get_buddies_online(gc, position);
+ /* update buddy information */
+ b = purple_find_buddy(purple_connection_get_account(gc), uid_to_purple_name(fe->s->uid));
+ q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
+
+ if (q_bud != NULL) { /* we find one and update qq_buddy */
+ if(0 != fe->s->client_version)
+ q_bud->client_version = fe->s->client_version;
+ g_memmove(q_bud->ip, fe->s->ip, 4);
+ q_bud->port = fe->s->port;
+ q_bud->status = fe->s->status;
+ q_bud->flag1 = fe->flag1;
+ q_bud->comm_flag = fe->comm_flag;
+ qq_update_buddy_contact(gc, q_bud);
} else {
- qq_send_packet_get_buddies_levels(gc);
- qq_refresh_all_buddy_status(gc);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Got an online buddy %d, but not in my buddy list\n", fe->s->uid);
}
+ g_free(fe->s->ip);
+ g_free(fe->s->unknown_key);
+ }
+
+ if(bytes > len) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n");
+ }
+
+ if (position != QQ_FRIENDS_ONLINE_POSITION_END) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Has more online buddies, position from %d\n", position);
+
+ qq_send_packet_get_buddies_online(gc, position);
} else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies online");
+ qq_send_packet_get_buddies_levels(gc);
+ qq_refresh_all_buddy_status(gc);
}
}
+
/* process reply for get_buddies_list */
void qq_process_get_buddies_list_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
{
qq_data *qd;
qq_buddy *q_bud;
- gint len, bytes, bytes_expected, i;
+ gint len, bytes_expected, i;
+ gint bytes, buddy_bytes;
guint16 position, unknown;
- guint8 *data, *cursor, pascal_len;
+ guint8 *data, pascal_len;
gchar *name;
PurpleBuddy *b;
@@ -260,81 +258,84 @@ void qq_process_get_buddies_list_reply(guint8 *buf, gint buf_len, PurpleConnecti
qd = (qq_data *) gc->proto_data;
len = buf_len;
data = g_newa(guint8, len);
- cursor = data;
-
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- read_packet_w(data, &cursor, len, &position);
- /* the following data is buddy list in this packet */
- i = 0;
- while (cursor < (data + len)) {
- q_bud = g_new0(qq_buddy, 1);
- bytes = 0;
- /* 000-003: uid */
- bytes += read_packet_dw(data, &cursor, len, &q_bud->uid);
- /* 004-005: icon index (1-255) */
- bytes += read_packet_w(data, &cursor, len, &q_bud->face);
- /* 006-006: age */
- bytes += read_packet_b(data, &cursor, len, &q_bud->age);
- /* 007-007: gender */
- bytes += read_packet_b(data, &cursor, len, &q_bud->gender);
- pascal_len = convert_as_pascal_string(cursor, &q_bud->nickname, QQ_CHARSET_DEFAULT);
- cursor += pascal_len;
- bytes += pascal_len;
- bytes += read_packet_w(data, &cursor, len, &unknown);
- /* flag1: (0-7)
- * bit1 => qq show
- * comm_flag: (0-7)
- * bit1 => member
- * bit4 => TCP mode
- * bit5 => open mobile QQ
- * bit6 => bind to mobile
- * bit7 => whether having a video
- */
- bytes += read_packet_b(data, &cursor, len, &q_bud->flag1);
- bytes += read_packet_b(data, &cursor, len, &q_bud->comm_flag);
-
- bytes_expected = 12 + pascal_len;
-
- if (q_bud->uid == 0 || bytes != bytes_expected) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "Buddy entry, expect %d bytes, read %d bytes\n", bytes_expected, bytes);
- g_free(q_bud->nickname);
- g_free(q_bud);
- continue;
- } else {
- i++;
- }
- if (QQ_DEBUG) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "buddy [%09d]: flag1=0x%02x, comm_flag=0x%02x\n",
- q_bud->uid, q_bud->flag1, q_bud->comm_flag);
- }
+ if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies list");
+ return;
+ }
+ bytes = 0;
+ bytes += qq_get16(&position, data + bytes);
+ /* the following data is buddy list in this packet */
+ i = 0;
+ while (bytes < len) {
+ q_bud = g_new0(qq_buddy, 1);
+ /* set flag */
+ buddy_bytes = bytes;
+ /* 000-003: uid */
+ bytes += qq_get32(&q_bud->uid, data + bytes);
+ /* 004-005: icon index (1-255) */
+ bytes += qq_get16(&q_bud->face, data + bytes);
+ /* 006-006: age */
+ bytes += qq_get8(&q_bud->age, data + bytes);
+ /* 007-007: gender */
+ bytes += qq_get8(&q_bud->gender, data + bytes);
+
+ pascal_len = convert_as_pascal_string(data + bytes, &q_bud->nickname, QQ_CHARSET_DEFAULT);
+ bytes += pascal_len;
+
+ bytes += qq_get16(&unknown, data + bytes);
+ /* flag1: (0-7)
+ * bit1 => qq show
+ * comm_flag: (0-7)
+ * bit1 => member
+ * bit4 => TCP mode
+ * bit5 => open mobile QQ
+ * bit6 => bind to mobile
+ * bit7 => whether having a video
+ */
+ bytes += qq_get8(&q_bud->flag1, data + bytes);
+ bytes += qq_get8(&q_bud->comm_flag, data + bytes);
+
+ bytes_expected = 12 + pascal_len;
+
+ if (q_bud->uid == 0 || (bytes - buddy_bytes) != bytes_expected) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Buddy entry, expect %d bytes, read %d bytes\n", bytes_expected, bytes - buddy_bytes);
+ g_free(q_bud->nickname);
+ g_free(q_bud);
+ continue;
+ } else {
+ i++;
+ }
- name = uid_to_purple_name(q_bud->uid);
- b = purple_find_buddy(gc->account, name);
- g_free(name);
+ if (QQ_DEBUG) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "buddy [%09d]: flag1=0x%02x, comm_flag=0x%02x\n",
+ q_bud->uid, q_bud->flag1, q_bud->comm_flag);
+ }
- if (b == NULL)
- b = qq_add_buddy_by_recv_packet(gc, q_bud->uid, TRUE, FALSE);
+ name = uid_to_purple_name(q_bud->uid);
+ b = purple_find_buddy(gc->account, name);
+ g_free(name);
- b->proto_data = q_bud;
- qd->buddies = g_list_append(qd->buddies, q_bud);
- qq_update_buddy_contact(gc, q_bud);
+ if (b == NULL) {
+ b = qq_add_buddy_by_recv_packet(gc, q_bud->uid, TRUE, FALSE);
}
- if(cursor > (data + len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "qq_process_get_buddies_list_reply: Dangerous error! maybe protocol changed, notify developers!");
- }
- if (position == QQ_FRIENDS_LIST_POSITION_END) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get friends list done, %d buddies\n", i);
- qq_send_packet_get_buddies_online(gc, QQ_FRIENDS_ONLINE_POSITION_START);
- } else {
- qq_send_packet_get_buddies_list(gc, position);
- }
+ b->proto_data = q_bud;
+ qd->buddies = g_list_append(qd->buddies, q_bud);
+ qq_update_buddy_contact(gc, q_bud);
+ }
+
+ if(bytes > len) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "qq_process_get_buddies_list_reply: Dangerous error! maybe protocol changed, notify developers!");
+ }
+ if (position == QQ_FRIENDS_LIST_POSITION_END) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get friends list done, %d buddies\n", i);
+ qq_send_packet_get_buddies_online(gc, QQ_FRIENDS_ONLINE_POSITION_START);
} else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies list");
+ qq_send_packet_get_buddies_list(gc, position);
}
}
@@ -342,7 +343,8 @@ void qq_process_get_all_list_with_group_reply(guint8 *buf, gint buf_len, PurpleC
{
qq_data *qd;
gint len, i, j;
- guint8 *data, *cursor;
+ gint bytes = 0;
+ guint8 *data;
guint8 sub_cmd, reply_code;
guint32 unknown, position;
guint32 uid;
@@ -354,62 +356,66 @@ void qq_process_get_all_list_with_group_reply(guint8 *buf, gint buf_len, PurpleC
qd = (qq_data *) gc->proto_data;
len = buf_len;
data = g_newa(guint8, len);
- cursor = data;
-
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- read_packet_b(data, &cursor, len, &sub_cmd);
- g_return_if_fail(sub_cmd == 0x01);
- read_packet_b(data, &cursor, len, &reply_code);
- if(0 != reply_code) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- "Get all list with group reply, reply_code(%d) is not zero", reply_code);
- }
- read_packet_dw(data, &cursor, len, &unknown);
- read_packet_dw(data, &cursor, len, &position);
- /* the following data is all list in this packet */
- i = 0;
- j = 0;
- while (cursor < (data + len)) {
- /* 00-03: uid */
- read_packet_dw(data, &cursor, len, &uid);
- /* 04: type 0x1:buddy 0x4:Qun */
- read_packet_b(data, &cursor, len, &type);
- /* 05: groupid*4 */ /* seems to always be 0 */
- read_packet_b(data, &cursor, len, &groupid);
- /*
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "groupid: %i\n", groupid);
- groupid >>= 2;
- */
- if (uid == 0 || (type != 0x1 && type != 0x4)) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "Buddy entry, uid=%d, type=%d", uid, type);
- continue;
- }
- if(0x1 == type) { /* a buddy */
- /* don't do anything but count - buddies are handled by
- * qq_send_packet_get_buddies_list */
- ++i;
- } else { /* a group */
- group = qq_group_find_by_id(gc, uid, QQ_INTERNAL_ID);
- if(group == NULL) {
- qq_set_pending_id(&qd->adding_groups_from_server, uid, TRUE);
- group = g_newa(qq_group, 1);
- group->internal_group_id = uid;
- qq_send_cmd_group_get_group_info(gc, group);
- } else {
- group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
- qq_group_refresh(gc, group);
- qq_send_cmd_group_get_group_info(gc, group);
- }
- ++j;
+
+ if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt all list with group");
+ return;
+ }
+
+ bytes += qq_get8(&sub_cmd, data + bytes);
+ g_return_if_fail(sub_cmd == 0x01);
+
+ bytes += qq_get8(&reply_code, data + bytes);
+ if(0 != reply_code) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Get all list with group reply, reply_code(%d) is not zero", reply_code);
+ }
+
+ bytes += qq_get32(&unknown, data + bytes);
+ bytes += qq_get32(&position, data + bytes);
+ /* the following data is all list in this packet */
+ i = 0;
+ j = 0;
+ while (bytes < len) {
+ /* 00-03: uid */
+ bytes += qq_get32(&uid, data + bytes);
+ /* 04: type 0x1:buddy 0x4:Qun */
+ bytes += qq_get8(&type, data + bytes);
+ /* 05: groupid*4 */ /* seems to always be 0 */
+ bytes += qq_get8(&groupid, data + bytes);
+ /*
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "groupid: %i\n", groupid);
+ groupid >>= 2;
+ */
+ if (uid == 0 || (type != 0x1 && type != 0x4)) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Buddy entry, uid=%d, type=%d", uid, type);
+ continue;
+ }
+ if(0x1 == type) { /* a buddy */
+ /* don't do anything but count - buddies are handled by
+ * qq_send_packet_get_buddies_list */
+ ++i;
+ } else { /* a group */
+ group = qq_group_find_by_id(gc, uid, QQ_INTERNAL_ID);
+ if(group == NULL) {
+ qq_set_pending_id(&qd->adding_groups_from_server, uid, TRUE);
+ group = g_newa(qq_group, 1);
+ group->internal_group_id = uid;
+ qq_send_cmd_group_get_group_info(gc, group);
+ } else {
+ group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
+ qq_group_refresh(gc, group);
+ qq_send_cmd_group_get_group_info(gc, group);
}
+ ++j;
}
- if(cursor > (data + len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "qq_process_get_all_list_with_group_reply: Dangerous error! maybe protocol changed, notify developers!");
- }
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get all list done, %d buddies and %d Quns\n", i, j);
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt all list with group");
}
+
+ if(bytes > len) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "qq_process_get_all_list_with_group_reply: Dangerous error! maybe protocol changed, notify developers!");
+ }
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get all list done, %d buddies and %d Quns\n", i, j);
}
diff --git a/libpurple/protocols/qq/buddy_opt.c b/libpurple/protocols/qq/buddy_opt.c
index 15ea046a05..d2e2925327 100644
--- a/libpurple/protocols/qq/buddy_opt.c
+++ b/libpurple/protocols/qq/buddy_opt.c
@@ -73,15 +73,14 @@ static void _qq_send_packet_remove_buddy(PurpleConnection *gc, guint32 uid)
/* try to remove myself from someone's buddy list */
static void _qq_send_packet_remove_self_from(PurpleConnection *gc, guint32 uid)
{
- guint8 *raw_data, *cursor;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
g_return_if_fail(uid > 0);
- raw_data = g_newa(guint8, 4);
- cursor = raw_data;
- create_packet_dw(raw_data, &cursor, uid);
+ bytes += qq_put32(raw_data + bytes, uid);
- qq_send_cmd(gc, QQ_CMD_REMOVE_SELF, TRUE, 0, TRUE, raw_data, 4);
+ qq_send_cmd(gc, QQ_CMD_REMOVE_SELF, TRUE, 0, TRUE, raw_data, bytes);
}
/* try to add a buddy without authentication */
@@ -110,27 +109,27 @@ static void _qq_send_packet_add_buddy(PurpleConnection *gc, guint32 uid)
static void _qq_send_packet_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text)
{
gchar *text_qq, uid_str[11];
- guint8 bar, *cursor, *raw_data;
+ guint8 bar, *raw_data;
+ gint bytes = 0;
g_return_if_fail(uid != 0);
g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
bar = 0x1f;
raw_data = g_newa(guint8, QQ_MSG_IM_MAX);
- cursor = raw_data;
- create_packet_data(raw_data, &cursor, (guint8 *) uid_str, strlen(uid_str));
- create_packet_b(raw_data, &cursor, bar);
- create_packet_b(raw_data, &cursor, response);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *) uid_str, strlen(uid_str));
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_put8(raw_data + bytes, response);
if (text != NULL) {
text_qq = utf8_to_qq(text, QQ_CHARSET_DEFAULT);
- create_packet_b(raw_data, &cursor, bar);
- create_packet_data(raw_data, &cursor, (guint8 *) text_qq, strlen(text_qq));
+ bytes += qq_put8(raw_data + bytes, bar);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *) text_qq, strlen(text_qq));
g_free(text_qq);
}
- qq_send_cmd(gc, QQ_CMD_BUDDY_AUTH, TRUE, 0, TRUE, raw_data, cursor - raw_data);
+ qq_send_cmd(gc, QQ_CMD_BUDDY_AUTH, TRUE, 0, TRUE, raw_data, bytes);
}
static void _qq_send_packet_add_buddy_auth_with_gc_and_uid(gc_and_uid *g, const gchar *text)
@@ -210,10 +209,10 @@ void qq_reject_add_request_with_gc_and_uid(gc_and_uid *g)
nombre = uid_to_purple_name(uid);
purple_request_input(gc, _("Reject request"), msg1, msg2,
- _("Sorry, you are not my type..."), TRUE, FALSE,
- NULL, _("Reject"), G_CALLBACK(_qq_reject_add_request_real), _("Cancel"), NULL,
- purple_connection_get_account(gc), nombre, NULL,
- g2);
+ _("Sorry, you are not my type..."), TRUE, FALSE,
+ NULL, _("Reject"), G_CALLBACK(_qq_reject_add_request_real), _("Cancel"), NULL,
+ purple_connection_get_account(gc), nombre, NULL,
+ g2);
g_free(nombre);
}
@@ -257,7 +256,8 @@ void qq_process_add_buddy_auth_reply(guint8 *buf, gint buf_len, PurpleConnection
{
qq_data *qd;
gint len;
- guint8 *data, *cursor, reply;
+ gint bytes = 0;
+ guint8 *data, reply;
gchar **segments, *msg_utf8;
g_return_if_fail(buf != NULL && buf_len != 0);
@@ -265,22 +265,23 @@ void qq_process_add_buddy_auth_reply(guint8 *buf, gint buf_len, PurpleConnection
qd = (qq_data *) gc->proto_data;
len = buf_len;
data = g_newa(guint8, len);
- cursor = data;
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- read_packet_b(data, &cursor, len, &reply);
- if (reply != QQ_ADD_BUDDY_AUTH_REPLY_OK) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add buddy with auth request failed\n");
- if (NULL == (segments = split_data(data, len, "\x1f", 2)))
- return;
- msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT);
- purple_notify_error(gc, NULL, _("Add buddy with auth request failed"), msg_utf8);
- g_free(msg_utf8);
- } else {
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Add buddy with auth request OK\n");
+ if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt add buddy with auth reply\n");
+ }
+
+ bytes += qq_get8(&reply, data + bytes);
+
+ if (reply != QQ_ADD_BUDDY_AUTH_REPLY_OK) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add buddy with auth request failed\n");
+ if (NULL == (segments = split_data(data, len, "\x1f", 2))) {
+ return;
}
+ msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT);
+ purple_notify_error(gc, NULL, _("Add buddy with auth request failed"), msg_utf8);
+ g_free(msg_utf8);
} else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt add buddy with auth reply\n");
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Add buddy with auth request OK\n");
}
}
@@ -289,7 +290,8 @@ void qq_process_remove_buddy_reply(guint8 *buf, gint buf_len, PurpleConnection *
{
qq_data *qd;
gint len;
- guint8 *data, *cursor, reply;
+ gint bytes = 0;
+ guint8 *data, reply;
g_return_if_fail(buf != NULL && buf_len != 0);
@@ -297,20 +299,20 @@ void qq_process_remove_buddy_reply(guint8 *buf, gint buf_len, PurpleConnection *
len = buf_len;
data = g_newa(guint8, len);
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- cursor = data;
- read_packet_b(data, &cursor, len, &reply);
- if (reply != QQ_REMOVE_BUDDY_REPLY_OK) {
- /* there is no reason return from server */
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Remove buddy fails\n");
- } else { /* if reply */
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Remove buddy OK\n");
- /* TODO: We don't really need to notify the user about this, do we? */
- purple_notify_info(gc, NULL, _("You have successfully removed a buddy"), NULL);
- }
- } else {
+ if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt remove buddy reply\n");
}
+
+ bytes += qq_get8(&reply, data + bytes);
+
+ if (reply != QQ_REMOVE_BUDDY_REPLY_OK) {
+ /* there is no reason return from server */
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Remove buddy fails\n");
+ } else { /* if reply */
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Remove buddy OK\n");
+ /* TODO: We don't really need to notify the user about this, do we? */
+ purple_notify_info(gc, NULL, _("You have successfully removed a buddy"), NULL);
+ }
}
/* process the server reply for my request to remove myself from a buddy */
@@ -318,7 +320,8 @@ void qq_process_remove_self_reply(guint8 *buf, gint buf_len, PurpleConnection *g
{
qq_data *qd;
gint len;
- guint8 *data, *cursor, reply;
+ gint bytes = 0;
+ guint8 *data, reply;
g_return_if_fail(buf != NULL && buf_len != 0);
@@ -326,20 +329,20 @@ void qq_process_remove_self_reply(guint8 *buf, gint buf_len, PurpleConnection *g
len = buf_len;
data = g_newa(guint8, len);
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- cursor = data;
- read_packet_b(data, &cursor, len, &reply);
- if (reply != QQ_REMOVE_SELF_REPLY_OK)
- /* there is no reason return from server */
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Remove self fails\n");
- else { /* if reply */
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Remove self from a buddy OK\n");
- /* TODO: Does the user really need to be notified about this? */
- purple_notify_info(gc, NULL, _("You have successfully removed yourself from your friend's buddy list"), NULL);
- }
- } else {
+ if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt remove self reply\n");
}
+
+ bytes += qq_get8(&reply, data + bytes);
+
+ if (reply != QQ_REMOVE_SELF_REPLY_OK) {
+ /* there is no reason return from server */
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Remove self fails\n");
+ } else { /* if reply */
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Remove self from a buddy OK\n");
+ /* TODO: Does the user really need to be notified about this? */
+ purple_notify_info(gc, NULL, _("You have successfully removed yourself from your friend's buddy list"), NULL);
+ }
}
void qq_process_add_buddy_reply(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection *gc)
@@ -403,14 +406,14 @@ void qq_process_add_buddy_reply(guint8 *buf, gint buf_len, guint16 seq, PurpleCo
g->uid = for_uid;
msg = g_strdup_printf(_("User %d needs authentication"), for_uid);
purple_request_input(gc, NULL, msg,
- _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */
- _("Would you be my friend?"),
- TRUE, FALSE, NULL, _("Send"),
- G_CALLBACK
- (_qq_send_packet_add_buddy_auth_with_gc_and_uid),
- _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid),
- purple_connection_get_account(gc), nombre, NULL,
- g);
+ _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */
+ _("Would you be my friend?"),
+ TRUE, FALSE, NULL, _("Send"),
+ G_CALLBACK
+ (_qq_send_packet_add_buddy_auth_with_gc_and_uid),
+ _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid),
+ purple_connection_get_account(gc), nombre, NULL,
+ g);
g_free(msg);
g_free(nombre);
} else { /* add OK */
@@ -457,7 +460,7 @@ PurpleBuddy *qq_add_buddy_by_recv_packet(PurpleConnection *gc, guint32 uid, gboo
g_return_val_if_fail(a != NULL && uid != 0, NULL);
group_name = is_known ?
- g_strdup_printf(PURPLE_GROUP_QQ_FORMAT, purple_account_get_username(a)) : g_strdup(PURPLE_GROUP_QQ_UNKNOWN);
+ g_strdup_printf(PURPLE_GROUP_QQ_FORMAT, purple_account_get_username(a)) : g_strdup(PURPLE_GROUP_QQ_UNKNOWN);
g = qq_get_purple_group(group_name);
@@ -512,8 +515,8 @@ void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
if (b != NULL)
purple_blist_remove_buddy(b);
purple_notify_error(gc, NULL,
- _("QQid Error"),
- _("Invalid QQid"));
+ _("QQid Error"),
+ _("Invalid QQid"));
}
}
diff --git a/libpurple/protocols/qq/buddy_status.c b/libpurple/protocols/qq/buddy_status.c
index db90b4027b..80658f3fbe 100644
--- a/libpurple/protocols/qq/buddy_status.c
+++ b/libpurple/protocols/qq/buddy_status.c
@@ -3,7 +3,7 @@
*
* purple
*
- * Purple is the legal property of its developers, whose names are too numerous
+ * Purple is the legal property ofr its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
@@ -66,35 +66,33 @@ void qq_buddy_status_dump_unclear(qq_buddy_status *s)
* using different accounts to get info. */
/* parse the data into qq_buddy_status */
-gint qq_buddy_status_read(guint8 *data, guint8 **cursor, gint len, qq_buddy_status *s)
+gint qq_buddy_status_read(qq_buddy_status *s, guint8 *data)
{
- gint bytes;
+ gint bytes = 0;
- g_return_val_if_fail(data != NULL && *cursor != NULL && s != NULL, -1);
-
- bytes = 0;
+ g_return_val_if_fail(data != NULL && s != NULL, -1);
/* 000-003: uid */
- bytes += read_packet_dw(data, cursor, len, &s->uid);
+ bytes += qq_get32(&s->uid, data + bytes);
/* 004-004: 0x01 */
- bytes += read_packet_b(data, cursor, len, &s->unknown1);
+ bytes += qq_get8(&s->unknown1, data + bytes);
/* this is no longer the IP, it seems QQ (as of 2006) no longer sends
* the buddy's IP in this packet. all 0s */
/* 005-008: ip */
s->ip = g_new0(guint8, 4);
- bytes += read_packet_data(data, cursor, len, s->ip, 4);
+ bytes += qq_getdata(s->ip, 4, data + bytes);
/* port info is no longer here either */
/* 009-010: port */
- bytes += read_packet_w(data, cursor, len, &s->port);
+ bytes += qq_get16(&s->port, data + bytes);
/* 011-011: 0x00 */
- bytes += read_packet_b(data, cursor, len, &s->unknown2);
+ bytes += qq_get8(&s->unknown2, data + bytes);
/* 012-012: status */
- bytes += read_packet_b(data, cursor, len, &s->status);
+ bytes += qq_get8(&s->status, data + bytes);
/* 013-014: client_version */
- bytes += read_packet_w(data, cursor, len, &s->client_version);
+ bytes += qq_get16(&s->client_version, data + bytes);
/* 015-030: unknown key */
s->unknown_key = g_new0(guint8, QQ_KEY_LENGTH);
- bytes += read_packet_data(data, cursor, len, s->unknown_key, QQ_KEY_LENGTH);
+ bytes += qq_getdata(s->unknown_key, QQ_KEY_LENGTH, data + bytes);
if (s->uid == 0 || bytes != 31)
return -1;
@@ -106,17 +104,17 @@ gint qq_buddy_status_read(guint8 *data, guint8 **cursor, gint len, qq_buddy_stat
gboolean is_online(guint8 status)
{
switch(status) {
- case QQ_BUDDY_ONLINE_NORMAL:
- case QQ_BUDDY_ONLINE_AWAY:
- case QQ_BUDDY_ONLINE_INVISIBLE:
- return TRUE;
- case QQ_BUDDY_ONLINE_OFFLINE:
- return FALSE;
+ case QQ_BUDDY_ONLINE_NORMAL:
+ case QQ_BUDDY_ONLINE_AWAY:
+ case QQ_BUDDY_ONLINE_INVISIBLE:
+ return TRUE;
+ case QQ_BUDDY_ONLINE_OFFLINE:
+ return FALSE;
}
return FALSE;
}
- /* Help calculate the correct icon index to tell the server. */
+/* Help calculate the correct icon index to tell the server. */
gint get_icon_offset(PurpleConnection *gc)
{
PurpleAccount *account;
@@ -131,7 +129,7 @@ gint get_icon_offset(PurpleConnection *gc)
|| purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY)
|| purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) {
return 1;
- } else {
+ } else {
return 0;
}
}
@@ -140,7 +138,9 @@ gint get_icon_offset(PurpleConnection *gc)
void qq_send_packet_change_status(PurpleConnection *gc)
{
qq_data *qd;
- guint8 *raw_data, *cursor, away_cmd;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
+ guint8 away_cmd;
guint32 misc_status;
gboolean fake_video;
PurpleAccount *account;
@@ -163,28 +163,24 @@ void qq_send_packet_change_status(PurpleConnection *gc)
away_cmd = QQ_BUDDY_ONLINE_NORMAL;
}
- raw_data = g_new0(guint8, 5);
- cursor = raw_data;
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;
- create_packet_b(raw_data, &cursor, away_cmd);
- create_packet_dw(raw_data, &cursor, misc_status);
-
- qq_send_cmd(gc, QQ_CMD_CHANGE_ONLINE_STATUS, TRUE, 0, TRUE, raw_data, 5);
+ bytes = 0;
+ bytes += qq_put8(raw_data + bytes, away_cmd);
+ bytes += qq_put32(raw_data + bytes, misc_status);
- g_free(raw_data);
+ qq_send_cmd(gc, QQ_CMD_CHANGE_ONLINE_STATUS, TRUE, 0, TRUE, raw_data, bytes);
}
/* parse the reply packet for change_status */
void qq_process_change_status_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len;
- guint8 *data, *cursor, reply;
+ gint len, bytes;
+ guint8 *data, reply;
PurpleBuddy *b;
qq_buddy *q_bud;
gchar *name;
@@ -195,21 +191,22 @@ void qq_process_change_status_reply(guint8 *buf, gint buf_len, PurpleConnection
len = buf_len;
data = g_newa(guint8, len);
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- cursor = data;
- read_packet_b(data, &cursor, len, &reply);
- if (reply != QQ_CHANGE_ONLINE_STATUS_REPLY_OK) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Change status fail\n");
- } else {
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Change status OK\n");
- name = uid_to_purple_name(qd->uid);
- b = purple_find_buddy(gc->account, name);
- g_free(name);
- q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
- qq_update_buddy_contact(gc, q_bud);
- }
- } else {
+ if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &len) ) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt chg status reply\n");
+ return;
+ }
+
+ bytes = 0;
+ bytes = qq_get8(&reply, data + bytes);
+ if (reply != QQ_CHANGE_ONLINE_STATUS_REPLY_OK) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Change status fail\n");
+ } else {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Change status OK\n");
+ name = uid_to_purple_name(qd->uid);
+ b = purple_find_buddy(gc->account, name);
+ g_free(name);
+ q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
+ qq_update_buddy_contact(gc, q_bud);
}
}
@@ -219,7 +216,7 @@ void qq_process_friend_change_status(guint8 *buf, gint buf_len, PurpleConnection
qq_data *qd;
gint len, bytes;
guint32 my_uid;
- guint8 *data, *cursor;
+ guint8 *data;
PurpleBuddy *b;
qq_buddy *q_bud;
qq_buddy_status *s;
@@ -230,51 +227,53 @@ void qq_process_friend_change_status(guint8 *buf, gint buf_len, PurpleConnection
qd = (qq_data *) gc->proto_data;
len = buf_len;
data = g_newa(guint8, len);
- cursor = data;
-
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- s = g_new0(qq_buddy_status, 1);
- bytes = 0;
- /* 000-030: qq_buddy_status */
- bytes += qq_buddy_status_read(data, &cursor, len, s);
- /* 031-034: my uid */
- /* This has a value of 0 when we've changed our status to
- * QQ_BUDDY_ONLINE_INVISIBLE */
- bytes += read_packet_dw(data, &cursor, len, &my_uid);
-
- if (bytes != 35) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "bytes(%d) != 35\n", bytes);
- g_free(s->ip);
- g_free(s->unknown_key);
- g_free(s);
- return;
- }
- name = uid_to_purple_name(s->uid);
- b = purple_find_buddy(gc->account, name);
- g_free(name);
- q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
- if (q_bud) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "s->uid = %d, q_bud->uid = %d\n", s->uid , q_bud->uid);
- if(0 != *((guint32 *)s->ip)) {
- g_memmove(q_bud->ip, s->ip, 4);
- q_bud->port = s->port;
- }
- q_bud->status = s->status;
- if(0 != s->client_version)
- q_bud->client_version = s->client_version;
- if (q_bud->status == QQ_BUDDY_ONLINE_NORMAL)
- qq_send_packet_get_level(gc, q_bud->uid);
- qq_update_buddy_contact(gc, q_bud);
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "got information of unknown buddy %d\n", s->uid);
- }
+ if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &len) ) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddy status change packet\n");
+ return;
+ }
+ s = g_new0(qq_buddy_status, 1);
+ bytes = 0;
+ /* 000-030: qq_buddy_status */
+ bytes += qq_buddy_status_read(s, data + bytes);
+ /* 031-034: my uid */
+ /* This has a value of 0 when we've changed our status to
+ * QQ_BUDDY_ONLINE_INVISIBLE */
+ bytes += qq_get32(&my_uid, data + bytes);
+
+ if (bytes != 35) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "bytes(%d) != 35\n", bytes);
g_free(s->ip);
g_free(s->unknown_key);
g_free(s);
+ return;
+ }
+
+ name = uid_to_purple_name(s->uid);
+ b = purple_find_buddy(gc->account, name);
+ g_free(name);
+ q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
+ if (q_bud) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "s->uid = %d, q_bud->uid = %d\n", s->uid , q_bud->uid);
+ if(0 != *((guint32 *)s->ip)) {
+ g_memmove(q_bud->ip, s->ip, 4);
+ q_bud->port = s->port;
+ }
+ q_bud->status = s->status;
+ if(0 != s->client_version) {
+ q_bud->client_version = s->client_version;
+ }
+ if (q_bud->status == QQ_BUDDY_ONLINE_NORMAL) {
+ qq_send_packet_get_level(gc, q_bud->uid);
+ }
+ qq_update_buddy_contact(gc, q_bud);
} else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddy status change packet\n");
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "got information of unknown buddy %d\n", s->uid);
}
+
+ g_free(s->ip);
+ g_free(s->unknown_key);
+ g_free(s);
}
diff --git a/libpurple/protocols/qq/buddy_status.h b/libpurple/protocols/qq/buddy_status.h
index e358c9c2e4..18c9b77dab 100644
--- a/libpurple/protocols/qq/buddy_status.h
+++ b/libpurple/protocols/qq/buddy_status.h
@@ -52,7 +52,7 @@ enum {
void qq_buddy_status_dump_unclear(qq_buddy_status *s);
gboolean is_online(guint8 status);
-gint qq_buddy_status_read(guint8 *data, guint8 **cursor, gint len, qq_buddy_status *s);
+gint qq_buddy_status_read(qq_buddy_status *s, guint8 *data);
gint get_icon_offset(PurpleConnection *gc);
void qq_send_packet_change_status(PurpleConnection *gc);
diff --git a/libpurple/protocols/qq/char_conv.c b/libpurple/protocols/qq/char_conv.c
index 627aacd86d..25636924f4 100644
--- a/libpurple/protocols/qq/char_conv.c
+++ b/libpurple/protocols/qq/char_conv.c
@@ -142,22 +142,23 @@ gint convert_as_pascal_string(guint8 *data, gchar **ret, const gchar *from_chars
gchar *qq_encode_to_purple(guint8 *data, gint len, const gchar *msg)
{
GString *encoded;
- guint8 font_attr, font_size, color[3], bar, *cursor;
+ guint8 font_attr, font_size, color[3], bar;
gboolean is_bold, is_italic, is_underline;
guint16 charset_code;
gchar *font_name, *color_code, *msg_utf8, *tmp, *ret;
+ gint bytes = 0;
- cursor = data;
+ /* checked _qq_show_packet OK */
_qq_show_packet("QQ_MESG recv for font style", data, len);
- read_packet_b(data, &cursor, len, &font_attr);
- read_packet_data(data, &cursor, len, color, 3); /* red,green,blue */
+ 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]);
- read_packet_b(data, &cursor, len, &bar); /* skip, not sure of its use */
- read_packet_w(data, &cursor, len, &charset_code);
+ bytes += qq_get8(&bar, data + bytes); /* skip, not sure of its use */
+ bytes += qq_get16(&charset_code, data + bytes);
- tmp = g_strndup((gchar *) cursor, data + len - cursor);
+ tmp = g_strndup((gchar *)(data + bytes), len - bytes);
font_name = qq_to_utf8(tmp, QQ_CHARSET_DEFAULT);
g_free(tmp);
@@ -177,11 +178,11 @@ gchar *qq_encode_to_purple(guint8 *data, gint len, const gchar *msg)
/* Henry: The range QQ sends rounds from 8 to 22, where a font size
* of 10 is equal to 3 in html font tag */
g_string_append_printf(encoded,
- "<font color=\"%s\"><font face=\"%s\"><font size=\"%d\">",
- color_code, font_name, font_size / 3);
+ "<font color=\"%s\"><font face=\"%s\"><font size=\"%d\">",
+ color_code, font_name, font_size / 3);
purple_debug(PURPLE_DEBUG_INFO, "QQ_MESG",
- "recv <font color=\"%s\"><font face=\"%s\"><font size=\"%d\">\n",
- color_code, font_name, font_size / 3);
+ "recv <font color=\"%s\"><font face=\"%s\"><font size=\"%d\">\n",
+ color_code, font_name, font_size / 3);
g_string_append(encoded, msg_utf8);
if (is_bold) {
diff --git a/libpurple/protocols/qq/crypt.c b/libpurple/protocols/qq/crypt.c
index d1f2d9af40..296034610d 100644
--- a/libpurple/protocols/qq/crypt.c
+++ b/libpurple/protocols/qq/crypt.c
@@ -296,3 +296,20 @@ gint qq_decrypt(const guint8 *const instr, gint instrlen,
}
return 1;
}
+
+/* return 1 is succeed, otherwise return 0
+gint qq_crypt(gint flag,
+ const guint8 *const instr, gint instrlen,
+ const guint8 *const key,
+ guint8 *outstr, gint *outstrlen_ptr)
+{
+ if (flag == DECRYPT)
+ return qq_decrypt(instr, instrlen, key, outstr, outstrlen_ptr);
+ else if (flag == ENCRYPT)
+ qq_encrypt(instr, instrlen, key, outstr, outstrlen_ptr);
+ else
+ return 0;
+
+ return 1;
+}
+*/
diff --git a/libpurple/protocols/qq/crypt.h b/libpurple/protocols/qq/crypt.h
index 9937ab90ad..49ae65aa8c 100644
--- a/libpurple/protocols/qq/crypt.h
+++ b/libpurple/protocols/qq/crypt.h
@@ -35,4 +35,13 @@ gint qq_decrypt(const guint8 *const instr, gint instrlen,
const guint8 *const key,
guint8 *outstr, gint *outstrlen_ptr);
+/*
+#define DECRYPT 0x00
+#define ENCRYPT 0x01
+
+gint qq_crypt(gint flag,
+ const guint8 *const instr, gint instrlen,
+ const guint8 *const key,
+ guint8 *outstr, gint *outstrlen_ptr);
+*/
#endif
diff --git a/libpurple/protocols/qq/file_trans.c b/libpurple/protocols/qq/file_trans.c
index f6e31e7014..e0453b2137 100644
--- a/libpurple/protocols/qq/file_trans.c
+++ b/libpurple/protocols/qq/file_trans.c
@@ -43,7 +43,6 @@
#include "utils.h"
struct _qq_file_header {
- guint8 tag;
guint16 client_ver;
guint8 file_key;
guint32 sender_uid;
@@ -58,11 +57,11 @@ static guint32 _get_file_key(guint8 seed)
key = seed | (seed << 8) | (seed << 16) | (seed << 24);
return key;
}
-
+
static guint32 _gen_file_key(void)
{
guint8 seed;
-
+
seed = random();
return _get_file_key(seed);
}
@@ -126,16 +125,17 @@ static void _fill_file_md5(const gchar *filename, gint filelen, guint8 *md5)
purple_cipher_context_destroy(context);
}
-static void _qq_get_file_header(guint8 *buf, guint8 **cursor, gint buflen, qq_file_header *fh)
+static gint _qq_get_file_header(qq_file_header *fh, guint8 *buf)
{
- read_packet_b(buf, cursor, buflen, &(fh->tag));
- read_packet_w(buf, cursor, buflen, &(fh->client_ver));
- read_packet_b(buf, cursor, buflen, &fh->file_key);
- read_packet_dw(buf, cursor, buflen, &(fh->sender_uid));
- read_packet_dw(buf, cursor, buflen, &(fh->receiver_uid));
+ gint bytes = 0;
+ bytes += qq_get16(&(fh->client_ver), buf + bytes);
+ bytes += qq_get8(&fh->file_key, buf + bytes);
+ bytes += qq_get32(&(fh->sender_uid), buf + bytes);
+ bytes += qq_get32(&(fh->receiver_uid), buf + bytes);
fh->sender_uid = _decrypt_qq_uid(fh->sender_uid, _get_file_key(fh->file_key));
fh->receiver_uid = _decrypt_qq_uid(fh->receiver_uid, _get_file_key(fh->file_key));
+ return bytes;
}
static const gchar *qq_get_file_cmd_desc(gint type)
@@ -190,7 +190,7 @@ static int _qq_xfer_open_file(const gchar *filename, const gchar *method, Purple
fd = open(purple_xfer_get_local_filename(xfer), O_RDWR|O_CREAT, 0644);
info->buffer = mmap(0, purple_xfer_get_size(xfer), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FILE, fd, 0);
}
-
+
if (info->buffer == NULL) {
return - 1;
}
@@ -258,8 +258,8 @@ void qq_xfer_close_file(PurpleXfer *xfer)
static gint _qq_send_file(PurpleConnection *gc, guint8 *data, gint len, guint16 packet_type, guint32 to_uid)
{
- gint bytes;
- guint8 *cursor, *buf;
+ guint8 *raw_data;
+ gint bytes = 0;
guint32 file_key;
qq_data *qd;
ft_info *info;
@@ -267,21 +267,19 @@ static gint _qq_send_file(PurpleConnection *gc, guint8 *data, gint len, guint16
qd = (qq_data *) gc->proto_data;
g_return_val_if_fail(qd->session_key != NULL, -1);
info = (ft_info *) qd->xfer->data;
- bytes = 0;
- buf = g_newa(guint8, MAX_PACKET_SIZE);
- cursor = buf;
+ raw_data = g_newa(guint8, MAX_PACKET_SIZE);
file_key = _gen_file_key();
- bytes += create_packet_b(buf, &cursor, packet_type);
- bytes += create_packet_w(buf, &cursor, QQ_CLIENT);
- bytes += create_packet_b(buf, &cursor, file_key & 0xff);
- bytes += create_packet_dw(buf, &cursor, _encrypt_qq_uid(qd->uid, file_key));
- bytes += create_packet_dw(buf, &cursor, _encrypt_qq_uid(to_uid, file_key));
- bytes += create_packet_data(buf, &cursor, data, len);
+ bytes += qq_put8(raw_data + bytes, packet_type);
+ bytes += qq_put16(raw_data + bytes, QQ_CLIENT);
+ bytes += qq_put8(raw_data + bytes, file_key & 0xff);
+ bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(qd->uid, file_key));
+ bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(to_uid, file_key));
+ bytes += qq_putdata(raw_data + bytes, data, len);
if (bytes == len + 12) {
- _qq_xfer_write(buf, bytes, qd->xfer);
+ _qq_xfer_write(raw_data, bytes, qd->xfer);
} else
purple_debug(PURPLE_DEBUG_INFO, "QQ", "send_file: want %d but got %d\n", len + 12, bytes);
return bytes;
@@ -292,57 +290,57 @@ void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, guint32
{
qq_data *qd;
gint bytes, bytes_expected, encrypted_len;
- guint8 *raw_data, *cursor, *encrypted_data;
+ guint8 *raw_data, *encrypted_data;
time_t now;
ft_info *info;
-
+ gchar *hex_dump;
+
qd = (qq_data *) gc->proto_data;
info = (ft_info *) qd->xfer->data;
- raw_data = g_new0 (guint8, 61);
- cursor = raw_data;
-
+ raw_data = g_newa (guint8, 61);
bytes = 0;
+
now = time(NULL);
- bytes += create_packet_data(raw_data, &cursor, qd->session_md5, 16);
- bytes += create_packet_w(raw_data, &cursor, packet_type);
+ bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16);
+ bytes += qq_put16(raw_data + bytes, packet_type);
switch (packet_type) {
case QQ_FILE_CMD_SENDER_SAY_HELLO:
case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
case QQ_FILE_CMD_NOTIFY_IP_ACK:
case QQ_FILE_CMD_RECEIVER_SAY_HELLO:
- bytes += create_packet_w(raw_data, &cursor, info->send_seq);
+ bytes += qq_put16(raw_data + bytes, info->send_seq);
break;
default:
- bytes += create_packet_w(raw_data, &cursor, ++qd->send_seq);
+ bytes += qq_put16(raw_data + bytes, ++qd->send_seq);
}
- bytes += create_packet_dw(raw_data, &cursor, (guint32) now);
- bytes += create_packet_b(raw_data, &cursor, 0x00);
- bytes += create_packet_b(raw_data, &cursor, qd->my_icon);
- bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
- bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
- bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
- bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
- bytes += create_packet_w(raw_data, &cursor, 0x0000);
- bytes += create_packet_b(raw_data, &cursor, 0x00);
+ bytes += qq_put32(raw_data + bytes, (guint32) now);
+ bytes += qq_put8(raw_data + bytes, 0x00);
+ bytes += qq_put8(raw_data + bytes, qd->my_icon);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
+ bytes += qq_put16(raw_data + bytes, 0x0000);
+ bytes += qq_put8(raw_data + bytes, 0x00);
/* 0x65: send a file, 0x6b: send a custom face */
- bytes += create_packet_b(raw_data, &cursor, QQ_FILE_TRANSFER_FILE); /* FIXME temp by gfhuang */
+ bytes += qq_put8(raw_data + bytes, QQ_FILE_TRANSFER_FILE); /* FIXME temp by gfhuang */
switch (packet_type)
{
case QQ_FILE_CMD_SENDER_SAY_HELLO:
case QQ_FILE_CMD_RECEIVER_SAY_HELLO:
case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
- bytes += create_packet_b(raw_data, &cursor, 0x00);
- bytes += create_packet_b(raw_data, &cursor, hellobyte);
+ bytes += qq_put8(raw_data + bytes, 0x00);
+ bytes += qq_put8(raw_data + bytes, hellobyte);
bytes_expected = 48;
break;
case QQ_FILE_CMD_PING:
case QQ_FILE_CMD_PONG:
case QQ_FILE_CMD_NOTIFY_IP_ACK:
- bytes += qq_fill_conn_info(raw_data, &cursor, info);
+ bytes += qq_fill_conn_info(raw_data, info);
bytes_expected = 61;
break;
default:
@@ -350,51 +348,53 @@ void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, guint32
packet_type);
bytes_expected = 0;
}
-
- if (bytes == bytes_expected) {
- gchar *hex_dump = hex_dump_to_str(raw_data, bytes);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "sending packet[%s]: \n%s", qq_get_file_cmd_desc(packet_type), hex_dump);
- g_free(hex_dump);
- encrypted_len = bytes + 16;
- encrypted_data = g_newa(guint8, encrypted_len);
- qq_encrypt(raw_data, bytes, info->file_session_key, encrypted_data, &encrypted_len);
- /*debug: try to decrypt it */
- /*
- if (QQ_DEBUG) {
- guint8 *buf;
- int buflen;
- hex_dump = hex_dump_to_str(encrypted_data, encrypted_len);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "encrypted packet: \n%s", hex_dump);
- g_free(hex_dump);
- buf = g_newa(guint8, MAX_PACKET_SIZE);
- buflen = encrypted_len;
- if (qq_decrypt(encrypted_data, encrypted_len, info->file_session_key, buf, &buflen)) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypt success\n");
- if (buflen == bytes && memcmp(raw_data, buf, buflen) == 0)
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "checksum ok\n");
- hex_dump = hex_dump_to_str(buf, buflen);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypted packet: \n%s", hex_dump);
- g_free(hex_dump);
- } else {
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypt fail\n");
- }
- }
- */
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type));
- _qq_send_file(gc, encrypted_data, encrypted_len, QQ_FILE_CONTROL_PACKET_TAG, info->to_uid);
- }
- else
+ if (bytes != bytes_expected) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "qq_send_file_ctl_packet: Expected to get %d bytes, but get %d",
bytes_expected, bytes);
+ return;
+ }
+
+ hex_dump = hex_dump_to_str(raw_data, bytes);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "sending packet[%s]: \n%s", qq_get_file_cmd_desc(packet_type), hex_dump);
+ g_free(hex_dump);
+
+ encrypted_len = bytes + 16;
+ encrypted_data = g_newa(guint8, encrypted_len);
+ qq_encrypt(raw_data, bytes, info->file_session_key, encrypted_data, &encrypted_len);
+ /*debug: try to decrypt it */
+ /*
+ if (QQ_DEBUG) {
+ guint8 *buf;
+ int buflen;
+ hex_dump = hex_dump_to_str(encrypted_data, encrypted_len);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "encrypted packet: \n%s", hex_dump);
+ g_free(hex_dump);
+ buf = g_newa(guint8, MAX_PACKET_SIZE);
+ buflen = encrypted_len;
+ if (qq_crypt(DECRYPT, encrypted_data, encrypted_len, info->file_session_key, buf, &buflen)) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypt success\n");
+ if (buflen == bytes && memcmp(raw_data, buf, buflen) == 0)
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "checksum ok\n");
+ hex_dump = hex_dump_to_str(buf, buflen);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypted packet: \n%s", hex_dump);
+ g_free(hex_dump);
+ } else {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypt fail\n");
+ }
+ }
+ */
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type));
+ _qq_send_file(gc, encrypted_data, encrypted_len, QQ_FILE_CONTROL_PACKET_TAG, info->to_uid);
}
/* send a file to udp channel with QQ_FILE_DATA_PACKET_TAG */
static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type, guint8 sub_type,
guint32 fragment_index, guint16 seq, guint8 *data, gint len)
{
+ guint8 *raw_data, filename_md5[QQ_KEY_LENGTH], file_md5[QQ_KEY_LENGTH];
gint bytes;
- guint8 *raw_data, *cursor, filename_md5[QQ_KEY_LENGTH], file_md5[QQ_KEY_LENGTH];
guint32 fragment_size = 1000;
gchar *filename;
gint filename_len, filesize;
@@ -408,17 +408,16 @@ static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type,
filesize = purple_xfer_get_size(qd->xfer);
raw_data = g_newa(guint8, MAX_PACKET_SIZE);
- cursor = raw_data;
bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, 0x00);
- bytes += create_packet_w(raw_data, &cursor, packet_type);
+ bytes += qq_put8(raw_data + bytes, 0x00);
+ bytes += qq_put16(raw_data + bytes, packet_type);
switch (packet_type) {
case QQ_FILE_BASIC_INFO:
case QQ_FILE_DATA_INFO:
case QQ_FILE_EOF:
- bytes += create_packet_w(raw_data, &cursor, 0x0000);
- bytes += create_packet_b(raw_data, &cursor, 0x00);
+ bytes += qq_put16(raw_data + bytes, 0x0000);
+ bytes += qq_put8(raw_data + bytes, 0x00);
break;
case QQ_FILE_CMD_FILE_OP:
switch(sub_type)
@@ -437,44 +436,44 @@ static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type,
"start transfering data, %d fragments with %d length each\n",
info->fragment_num, info->fragment_len);
/* Unknown */
- bytes += create_packet_w(raw_data, &cursor, 0x0000);
+ bytes += qq_put16(raw_data + bytes, 0x0000);
/* Sub-operation type */
- bytes += create_packet_b(raw_data, &cursor, sub_type);
+ bytes += qq_put8(raw_data + bytes, sub_type);
/* Length of file */
- bytes += create_packet_dw(raw_data, &cursor, filesize);
+ bytes += qq_put32(raw_data + bytes, filesize);
/* Number of fragments */
- bytes += create_packet_dw(raw_data, &cursor, info->fragment_num);
+ bytes += qq_put32(raw_data + bytes, info->fragment_num);
/* Length of a single fragment */
- bytes += create_packet_dw(raw_data, &cursor, info->fragment_len);
- bytes += create_packet_data(raw_data, &cursor, file_md5, 16);
- bytes += create_packet_data(raw_data, &cursor, filename_md5, 16);
+ bytes += qq_put32(raw_data + bytes, info->fragment_len);
+ bytes += qq_putdata(raw_data + bytes, file_md5, 16);
+ bytes += qq_putdata(raw_data + bytes, filename_md5, 16);
/* Length of filename */
- bytes += create_packet_w(raw_data, &cursor, filename_len);
+ bytes += qq_put16(raw_data + bytes, filename_len);
/* 8 unknown bytes */
- bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
- bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
/* filename */
- bytes += create_packet_data(raw_data, &cursor, (guint8 *) filename,
+ bytes += qq_putdata(raw_data + bytes, (guint8 *) filename,
filename_len);
break;
case QQ_FILE_DATA_INFO:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
"sending %dth fragment with length %d, offset %d\n",
fragment_index, len, (fragment_index-1)*fragment_size);
- /* bytes += create_packet_w(raw_data, &cursor, ++(qd->send_seq)); */
- bytes += create_packet_w(raw_data, &cursor, info->send_seq);
- bytes += create_packet_b(raw_data, &cursor, sub_type);
- /* bytes += create_packet_dw(raw_data, &cursor, fragment_index); */
- bytes += create_packet_dw(raw_data, &cursor, fragment_index - 1);
- bytes += create_packet_dw(raw_data, &cursor, (fragment_index - 1) * fragment_size);
- bytes += create_packet_w(raw_data, &cursor, len);
- bytes += create_packet_data(raw_data, &cursor, data, len);
+ /* bytes += qq_put16(raw_data + bytes, ++(qd->send_seq)); */
+ bytes += qq_put16(raw_data + bytes, info->send_seq);
+ bytes += qq_put8(raw_data + bytes, sub_type);
+ /* bytes += qq_put32(raw_data + bytes, fragment_index); */
+ bytes += qq_put32(raw_data + bytes, fragment_index - 1);
+ bytes += qq_put32(raw_data + bytes, (fragment_index - 1) * fragment_size);
+ bytes += qq_put16(raw_data + bytes, len);
+ bytes += qq_putdata(raw_data + bytes, data, len);
break;
case QQ_FILE_EOF:
purple_debug(PURPLE_DEBUG_INFO, "QQ", "end of sending data\n");
- /* bytes += create_packet_w(raw_data, &cursor, info->fragment_num + 1); */
- bytes += create_packet_w(raw_data, &cursor, info->fragment_num);
- bytes += create_packet_b(raw_data, &cursor, sub_type);
+ /* bytes += qq_put16(raw_data + bytes, info->fragment_num + 1); */
+ bytes += qq_put16(raw_data + bytes, info->fragment_num);
+ bytes += qq_put8(raw_data + bytes, sub_type);
/* purple_xfer_set_completed(qd->xfer, TRUE); */
}
break;
@@ -482,18 +481,18 @@ static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type,
switch (sub_type)
{
case QQ_FILE_BASIC_INFO:
- bytes += create_packet_w(raw_data, &cursor, 0x0000);
- bytes += create_packet_b(raw_data, &cursor, sub_type);
- bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
+ bytes += qq_put16(raw_data + bytes, 0x0000);
+ bytes += qq_put8(raw_data + bytes, sub_type);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
break;
case QQ_FILE_DATA_INFO:
- bytes += create_packet_w(raw_data, &cursor, seq);
- bytes += create_packet_b(raw_data, &cursor, sub_type);
- bytes += create_packet_dw(raw_data, &cursor, fragment_index);
+ bytes += qq_put16(raw_data + bytes, seq);
+ bytes += qq_put8(raw_data + bytes, sub_type);
+ bytes += qq_put32(raw_data + bytes, fragment_index);
break;
case QQ_FILE_EOF:
- bytes += create_packet_w(raw_data, &cursor, filesize / QQ_FILE_FRAGMENT_MAXLEN + 2);
- bytes += create_packet_b(raw_data, &cursor, sub_type);
+ bytes += qq_put16(raw_data + bytes, filesize / QQ_FILE_FRAGMENT_MAXLEN + 2);
+ bytes += qq_put8(raw_data + bytes, sub_type);
break;
}
}
@@ -520,9 +519,11 @@ static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type,
*/
-static void _qq_process_recv_file_ctl_packet(PurpleConnection *gc, guint8 *data, guint8 *cursor,
- gint len, qq_file_header *fh)
+static void _qq_process_recv_file_ctl_packet(PurpleConnection *gc, guint8 *data, gint len)
{
+ gint bytes ;
+ gint decryped_bytes;
+ qq_file_header fh;
guint8 *decrypted_data;
gint decrypted_len;
qq_data *qd = (qq_data *) gc->proto_data;
@@ -530,61 +531,67 @@ static void _qq_process_recv_file_ctl_packet(PurpleConnection *gc, guint8 *data,
guint16 seq;
guint8 hellobyte;
ft_info *info = (ft_info *) qd->xfer->data;
+ gchar *hex_dump;
+
+ bytes = 0;
+ bytes += _qq_get_file_header(&fh, data + bytes);
decrypted_data = g_newa(guint8, len);
decrypted_len = len;
- if (qq_decrypt(cursor, len - (cursor - data), qd->session_md5, decrypted_data, &decrypted_len)) {
- gchar *hex_dump;
- cursor = decrypted_data + 16; /* skip md5 section */
- read_packet_w(decrypted_data, &cursor, decrypted_len, &packet_type);
- read_packet_w(decrypted_data, &cursor, decrypted_len, &seq);
- cursor += 4+1+1+19+1;
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "==> [%d] receive %s packet\n", seq, qq_get_file_cmd_desc(packet_type));
- hex_dump = hex_dump_to_str(decrypted_data, decrypted_len);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypted control packet received: \n%s", hex_dump);
- g_free(hex_dump);
- switch (packet_type) {
- case QQ_FILE_CMD_NOTIFY_IP_ACK:
- cursor = decrypted_data;
- qq_get_conn_info(decrypted_data, &cursor, decrypted_len, info);
-/* qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PING, fh->sender_uid, 0); */
- qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh->sender_uid, 0);
- break;
- case QQ_FILE_CMD_SENDER_SAY_HELLO:
- /* I'm receiver, if we receive SAY_HELLO from sender, we send back the ACK */
- cursor += 47;
- read_packet_b(decrypted_data, &cursor,
- decrypted_len, &hellobyte);
-
- qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO_ACK, fh->sender_uid, hellobyte);
- qq_send_file_ctl_packet(gc, QQ_FILE_CMD_RECEIVER_SAY_HELLO, fh->sender_uid, 0);
- break;
- case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
- /* I'm sender, do nothing */
- break;
- case QQ_FILE_CMD_RECEIVER_SAY_HELLO:
- /* I'm sender, ack the hello packet and send the first data */
- cursor += 47;
- read_packet_b(decrypted_data, &cursor,
- decrypted_len, &hellobyte);
- qq_send_file_ctl_packet(gc, QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK, fh->sender_uid, hellobyte);
- _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_BASIC_INFO, 0, 0, NULL, 0);
- break;
- case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
- /* I'm receiver, do nothing */
- break;
- case QQ_FILE_CMD_PING:
- /* I'm receiver, ack the PING */
- qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PONG, fh->sender_uid, 0);
- break;
- case QQ_FILE_CMD_PONG:
- qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh->sender_uid, 0);
- break;
- default:
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "unprocess file command %d\n", packet_type);
- }
- }
+ if ( !qq_decrypt(data, len, qd->session_md5, decrypted_data, &decrypted_len) ) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt rcv file ctrl packet\n");
+ return;
+ }
+
+ /* only for debug info */
+ decryped_bytes = 16; /* skip md5 section */
+ decryped_bytes += qq_get16(&packet_type, decrypted_data + decryped_bytes);
+ decryped_bytes += qq_get16(&seq, decrypted_data + decryped_bytes);
+ decryped_bytes += 4+1+1+19+1; /* skip something */
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "==> [%d] receive %s packet\n", seq, qq_get_file_cmd_desc(packet_type));
+ hex_dump = hex_dump_to_str(decrypted_data, decrypted_len);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypted control packet received: \n%s", hex_dump);
+ g_free(hex_dump);
+
+ switch (packet_type) {
+ case QQ_FILE_CMD_NOTIFY_IP_ACK:
+ decryped_bytes = 0;
+ qq_get_conn_info(info, decrypted_data + decryped_bytes);
+ /* qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PING, fh->sender_uid, 0); */
+ qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh.sender_uid, 0);
+ break;
+ case QQ_FILE_CMD_SENDER_SAY_HELLO:
+ /* I'm receiver, if we receive SAY_HELLO from sender, we send back the ACK */
+ decryped_bytes += 47;
+ decryped_bytes += qq_get8(&hellobyte, decrypted_data + decryped_bytes);
+ qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO_ACK, fh.sender_uid, hellobyte);
+ qq_send_file_ctl_packet(gc, QQ_FILE_CMD_RECEIVER_SAY_HELLO, fh.sender_uid, 0);
+ break;
+ case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
+ /* I'm sender, do nothing */
+ break;
+ case QQ_FILE_CMD_RECEIVER_SAY_HELLO:
+ /* I'm sender, ack the hello packet and send the first data */
+ decryped_bytes += 47;
+ decryped_bytes += qq_get8(&hellobyte, decrypted_data + decryped_bytes);
+ qq_send_file_ctl_packet(gc, QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK, fh.sender_uid, hellobyte);
+ _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_BASIC_INFO, 0, 0, NULL, 0);
+ break;
+ case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
+ /* I'm receiver, do nothing */
+ break;
+ case QQ_FILE_CMD_PING:
+ /* I'm receiver, ack the PING */
+ qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PONG, fh.sender_uid, 0);
+ break;
+ case QQ_FILE_CMD_PONG:
+ qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh.sender_uid, 0);
+ break;
+ default:
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "unprocess file command %d\n", packet_type);
+ }
}
static void _qq_recv_file_progess(PurpleConnection *gc, guint8 *buffer, guint16 len, guint32 index, guint32 offset)
@@ -609,15 +616,15 @@ static void _qq_recv_file_progess(PurpleConnection *gc, guint8 *buffer, guint16
purple_debug(PURPLE_DEBUG_INFO, "QQ", "duplicate %dth fragment, drop it!\n", index+1);
return;
}
-
+
info->window |= mask;
_qq_xfer_write_file(buffer, index, len, xfer);
-
+
xfer->bytes_sent += len;
xfer->bytes_remaining -= len;
purple_xfer_update_progress(xfer);
-
+
mask = 0x1 << (info->max_fragment_index % sizeof(info->window));
while (info->window & mask)
{
@@ -639,7 +646,7 @@ static void _qq_send_file_progess(PurpleConnection *gc)
guint8 *buffer;
guint i;
gint readbytes;
-
+
if (purple_xfer_get_bytes_remaining(xfer) <= 0) return;
if (info->window == 0 && info->max_fragment_index == 0)
{
@@ -655,7 +662,7 @@ static void _qq_send_file_progess(PurpleConnection *gc)
readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + i, info->fragment_len, xfer);
if (readbytes > 0)
_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO,
- info->max_fragment_index + i + 1, 0, buffer, readbytes);
+ info->max_fragment_index + i + 1, 0, buffer, readbytes);
}
if (mask & 0x8000) mask = 0x0001;
else mask = mask << 1;
@@ -706,8 +713,8 @@ static void _qq_update_send_progess(PurpleConnection *gc, guint32 fragment_index
info->fragment_len, xfer);
if (readbytes > 0)
_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO,
- info->max_fragment_index + sizeof(info->window) + 1, 0, buffer, readbytes);
-
+ info->max_fragment_index + sizeof(info->window) + 1, 0, buffer, readbytes);
+
info->max_fragment_index ++;
if (mask & 0x8000) mask = 0x0001;
else mask = mask << 1;
@@ -718,9 +725,10 @@ static void _qq_update_send_progess(PurpleConnection *gc, guint32 fragment_index
fragment_index, info->window, info->max_fragment_index);
}
-static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, guint8 *cursor,
- gint len, guint32 to_uid)
+static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, gint len)
{
+ gint bytes ;
+ qq_file_header fh;
guint16 packet_type;
guint16 packet_seq;
guint8 sub_type;
@@ -729,24 +737,27 @@ static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, guint
guint32 fragment_offset;
qq_data *qd = (qq_data *) gc->proto_data;
ft_info *info = (ft_info *) qd->xfer->data;
-
- cursor += 1; /* skip an unknown byte */
- read_packet_w(data, &cursor, len, &packet_type);
+
+ bytes = 0;
+ bytes += _qq_get_file_header(&fh, data + bytes);
+
+ bytes += 1; /* skip an unknown byte */
+ bytes += qq_get16(&packet_type, data + bytes);
switch(packet_type)
{
case QQ_FILE_CMD_FILE_OP:
- read_packet_w(data, &cursor, len, &packet_seq);
- read_packet_b(data, &cursor, len, &sub_type);
+ bytes += qq_get16(&packet_seq, data + bytes);
+ bytes += qq_get8(&sub_type, data + bytes);
switch (sub_type)
{
case QQ_FILE_BASIC_INFO:
- cursor += 4; /* file length, we have already known it from xfer */
- read_packet_dw(data, &cursor, len, &info->fragment_num);
- read_packet_dw(data, &cursor, len, &info->fragment_len);
+ bytes += 4; /* file length, we have already known it from xfer */
+ bytes += qq_get32(&info->fragment_num, data + bytes);
+ bytes += qq_get32(&info->fragment_len, data + bytes);
- /* FIXME: We must check the md5 here, if md5 doesn't match
- * we will ignore the packet or send sth as error number
- */
+ /* FIXME: We must check the md5 here,
+ * if md5 doesn't match we will ignore
+ * the packet or send sth as error number */
info->max_fragment_index = 0;
info->window = 0;
@@ -757,27 +768,27 @@ static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, guint
0, 0, NULL, 0);
break;
case QQ_FILE_DATA_INFO:
- read_packet_dw(data, &cursor, len, &fragment_index);
- read_packet_dw(data, &cursor, len, &fragment_offset);
- read_packet_w(data, &cursor, len, &fragment_len);
+ bytes += qq_get32(&fragment_index, data + bytes);
+ bytes += qq_get32(&fragment_offset, data + bytes);
+ bytes += qq_get16(&fragment_len, data + bytes);
purple_debug(PURPLE_DEBUG_INFO, "QQ",
"received %dth fragment with length %d, offset %d\n",
fragment_index, fragment_len, fragment_offset);
-
+
_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type,
fragment_index, packet_seq, NULL, 0);
- _qq_recv_file_progess(gc, cursor, fragment_len, fragment_index, fragment_offset);
+ _qq_recv_file_progess(gc, data + bytes, fragment_len, fragment_index, fragment_offset);
break;
case QQ_FILE_EOF:
purple_debug(PURPLE_DEBUG_INFO, "QQ", "end of receiving\n");
_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type,
- 0, 0, NULL, 0);
+ 0, 0, NULL, 0);
break;
}
break;
case QQ_FILE_CMD_FILE_OP_ACK:
- read_packet_w(data, &cursor, len, &packet_seq);
- read_packet_b(data, &cursor, len, &sub_type);
+ bytes += qq_get16(&packet_seq, data + bytes);
+ bytes += qq_get8(&sub_type, data + bytes);
switch (sub_type)
{
case QQ_FILE_BASIC_INFO:
@@ -787,16 +798,16 @@ static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, guint
_qq_send_file_progess(gc);
break;
case QQ_FILE_DATA_INFO:
- read_packet_dw(data, &cursor, len, &fragment_index);
+ bytes += qq_get32(&fragment_index, data + bytes);
_qq_update_send_progess(gc, fragment_index);
if (purple_xfer_is_completed(qd->xfer))
_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_EOF, 0, 0, NULL, 0);
- /* else
+ /* else
_qq_send_file_progess(gc); */
break;
case QQ_FILE_EOF:
/* FIXME: OK, we can end the connection successfully */
-
+
_qq_send_file_data_packet(gc, QQ_FILE_EOF, 0, 0, 0, NULL, 0);
purple_xfer_set_completed(qd->xfer, TRUE);
break;
@@ -820,21 +831,21 @@ static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, guint
void qq_process_recv_file(PurpleConnection *gc, guint8 *data, gint len)
{
- guint8 *cursor;
- qq_file_header fh;
+ gint bytes;
+ guint8 tag;
qq_data *qd;
qd = (qq_data *) gc->proto_data;
- cursor = data;
- _qq_get_file_header(data, &cursor, len, &fh);
+ bytes = 0;
+ bytes += qq_get8(&tag, data + bytes);
- switch (fh.tag) {
+ switch (tag) {
case QQ_FILE_CONTROL_PACKET_TAG:
- _qq_process_recv_file_ctl_packet(gc, data, cursor, len, &fh);
+ _qq_process_recv_file_ctl_packet(gc, data + bytes, len - bytes);
break;
case QQ_FILE_DATA_PACKET_TAG:
- _qq_process_recv_file_data(gc, data, cursor, len, fh.sender_uid);
+ _qq_process_recv_file_data(gc, data + bytes, len - bytes);
break;
default:
purple_debug(PURPLE_DEBUG_INFO, "QQ", "unknown packet tag");
diff --git a/libpurple/protocols/qq/group_im.c b/libpurple/protocols/qq/group_im.c
index 5053d20465..6c41115660 100644
--- a/libpurple/protocols/qq/group_im.c
+++ b/libpurple/protocols/qq/group_im.c
@@ -58,7 +58,7 @@ typedef struct _qq_recv_group_im {
void qq_send_packet_group_im(PurpleConnection *gc, qq_group *group, const gchar *msg)
{
gint data_len, bytes;
- guint8 *raw_data, *cursor, *send_im_tail;
+ guint8 *raw_data, *send_im_tail;
guint16 msg_len;
gchar *msg_filtered;
@@ -67,19 +67,19 @@ void qq_send_packet_group_im(PurpleConnection *gc, qq_group *group, const gchar
msg_filtered = purple_markup_strip_html(msg);
purple_debug_info("QQ_MESG", "filterd qq qun mesg: %s\n", msg_filtered);
msg_len = strlen(msg_filtered);
+
data_len = 7 + msg_len + QQ_SEND_IM_AFTER_MSG_LEN;
raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_SEND_MSG);
- bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
- bytes += create_packet_w(raw_data, &cursor, msg_len + QQ_SEND_IM_AFTER_MSG_LEN);
- bytes += create_packet_data(raw_data, &cursor, (guint8 *) msg_filtered, msg_len);
+ bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_SEND_MSG);
+ bytes += qq_put32(raw_data + bytes, group->internal_group_id);
+ bytes += qq_put16(raw_data + bytes, msg_len + QQ_SEND_IM_AFTER_MSG_LEN);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *) msg_filtered, msg_len);
send_im_tail = qq_get_send_im_tail(NULL, NULL, NULL,
- FALSE, FALSE, FALSE,
- QQ_SEND_IM_AFTER_MSG_LEN);
- bytes += create_packet_data(raw_data, &cursor, send_im_tail, QQ_SEND_IM_AFTER_MSG_LEN);
+ FALSE, FALSE, FALSE,
+ QQ_SEND_IM_AFTER_MSG_LEN);
+ bytes += qq_putdata(raw_data + bytes, send_im_tail, QQ_SEND_IM_AFTER_MSG_LEN);
g_free(send_im_tail);
g_free(msg_filtered);
@@ -87,11 +87,11 @@ void qq_send_packet_group_im(PurpleConnection *gc, qq_group *group, const gchar
qq_send_group_cmd(gc, group, raw_data, data_len);
else
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail creating group_im packet, expect %d bytes, build %d bytes\n", data_len, bytes);
+ "Fail creating group_im packet, expect %d bytes, build %d bytes\n", data_len, bytes);
}
/* this is the ACK */
-void qq_process_group_cmd_im(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_process_group_cmd_im(guint8 *data, gint len, PurpleConnection *gc)
{
/* return should be the internal group id
* but we have nothing to do with it */
@@ -99,29 +99,26 @@ void qq_process_group_cmd_im(guint8 *data, guint8 **cursor, gint len, PurpleConn
}
/* receive an application to join the group */
-void qq_process_recv_group_im_apply_join
- (guint8 *data, guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc)
+void qq_process_recv_group_im_apply_join(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc)
{
guint32 external_group_id, user_uid;
guint8 group_type;
gchar *reason_utf8, *msg, *reason;
group_member_opt *g;
gchar *nombre;
+ gint bytes = 0;
g_return_if_fail(internal_group_id > 0 && data != NULL && len > 0);
- if (*cursor >= (data + len - 1)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received group msg apply_join is empty\n");
- return;
- }
+ // Fixme: check length here
- read_packet_dw(data, cursor, len, &external_group_id);
- read_packet_b(data, cursor, len, &group_type);
- read_packet_dw(data, cursor, len, &user_uid);
+ bytes += qq_get32(&external_group_id, data + bytes);
+ bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&user_uid, data + bytes);
g_return_if_fail(external_group_id > 0 && user_uid > 0);
- convert_as_pascal_string(*cursor, &reason_utf8, QQ_CHARSET_DEFAULT);
+ bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT);
msg = g_strdup_printf(_("User %d requested to join group %d"), user_uid, external_group_id);
reason = g_strdup_printf(_("Reason: %s"), reason_utf8);
@@ -134,17 +131,17 @@ void qq_process_recv_group_im_apply_join
nombre = uid_to_purple_name(user_uid);
purple_request_action(gc, _("QQ Qun Operation"),
- msg, reason,
- PURPLE_DEFAULT_ACTION_NONE,
- purple_connection_get_account(gc), nombre, NULL,
- g, 3,
- _("Approve"),
- G_CALLBACK
- (qq_group_approve_application_with_struct),
- _("Reject"),
- G_CALLBACK
- (qq_group_reject_application_with_struct),
- _("Search"), G_CALLBACK(qq_group_search_application_with_struct));
+ msg, reason,
+ PURPLE_DEFAULT_ACTION_NONE,
+ purple_connection_get_account(gc), nombre, NULL,
+ g, 3,
+ _("Approve"),
+ G_CALLBACK
+ (qq_group_approve_application_with_struct),
+ _("Reject"),
+ G_CALLBACK
+ (qq_group_reject_application_with_struct),
+ _("Search"), G_CALLBACK(qq_group_search_application_with_struct));
g_free(nombre);
g_free(reason);
@@ -153,31 +150,28 @@ void qq_process_recv_group_im_apply_join
}
/* the request to join a group is rejected */
-void qq_process_recv_group_im_been_rejected
- (guint8 *data, guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc)
+void qq_process_recv_group_im_been_rejected(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc)
{
guint32 external_group_id, admin_uid;
guint8 group_type;
gchar *reason_utf8, *msg, *reason;
qq_group *group;
+ gint bytes = 0;
g_return_if_fail(data != NULL && len > 0);
- if (*cursor >= (data + len - 1)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received group msg been_rejected is empty\n");
- return;
- }
+ // Fixme: check length here
- read_packet_dw(data, cursor, len, &external_group_id);
- read_packet_b(data, cursor, len, &group_type);
- read_packet_dw(data, cursor, len, &admin_uid);
+ bytes += qq_get32(&external_group_id, data + bytes);
+ bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&admin_uid, data + bytes);
g_return_if_fail(external_group_id > 0 && admin_uid > 0);
- convert_as_pascal_string(*cursor, &reason_utf8, QQ_CHARSET_DEFAULT);
+ bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT);
msg = g_strdup_printf
- (_("Your request to join group %d has been rejected by admin %d"), external_group_id, admin_uid);
+ (_("Your request to join group %d has been rejected by admin %d"), external_group_id, admin_uid);
reason = g_strdup_printf(_("Reason: %s"), reason_utf8);
purple_notify_warning(gc, _("QQ Qun Operation"), msg, reason);
@@ -194,31 +188,28 @@ void qq_process_recv_group_im_been_rejected
}
/* the request to join a group is approved */
-void qq_process_recv_group_im_been_approved
- (guint8 *data, guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc)
+void qq_process_recv_group_im_been_approved(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc)
{
guint32 external_group_id, admin_uid;
guint8 group_type;
gchar *reason_utf8, *msg;
qq_group *group;
+ gint bytes = 0;
g_return_if_fail(data != NULL && len > 0);
- if (*cursor >= (data + len - 1)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received group msg been_approved is empty\n");
- return;
- }
+ // Fixme: check length here
- read_packet_dw(data, cursor, len, &external_group_id);
- read_packet_b(data, cursor, len, &group_type);
- read_packet_dw(data, cursor, len, &admin_uid);
+ bytes += qq_get32(&external_group_id, data + bytes);
+ bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&admin_uid, data + bytes);
g_return_if_fail(external_group_id > 0 && admin_uid > 0);
/* it is also a "æ— " here, so do not display */
- convert_as_pascal_string(*cursor, &reason_utf8, QQ_CHARSET_DEFAULT);
+ bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT);
msg = g_strdup_printf
- (_("Your request to join group %d has been approved by admin %d"), external_group_id, admin_uid);
+ (_("Your request to join group %d has been approved by admin %d"), external_group_id, admin_uid);
purple_notify_warning(gc, _("QQ Qun Operation"), msg, NULL);
@@ -233,24 +224,21 @@ void qq_process_recv_group_im_been_approved
}
/* process the packet when removed from a group */
-void qq_process_recv_group_im_been_removed
- (guint8 *data, guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc)
+void qq_process_recv_group_im_been_removed(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc)
{
guint32 external_group_id, uid;
guint8 group_type;
gchar *msg;
qq_group *group;
+ gint bytes = 0;
g_return_if_fail(data != NULL && len > 0);
- if (*cursor >= (data + len - 1)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received group msg been_removed is empty\n");
- return;
- }
+ // Fixme: check length here
- read_packet_dw(data, cursor, len, &external_group_id);
- read_packet_b(data, cursor, len, &group_type);
- read_packet_dw(data, cursor, len, &uid);
+ bytes += qq_get32(&external_group_id, data + bytes);
+ bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&uid, data + bytes);
g_return_if_fail(external_group_id > 0 && uid > 0);
@@ -267,24 +255,21 @@ void qq_process_recv_group_im_been_removed
}
/* process the packet when added to a group */
-void qq_process_recv_group_im_been_added
- (guint8 *data, guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc)
+void qq_process_recv_group_im_been_added(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc)
{
guint32 external_group_id, uid;
guint8 group_type;
qq_group *group;
gchar *msg;
+ gint bytes = 0;
g_return_if_fail(data != NULL && len > 0);
- if (*cursor >= (data + len - 1)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received group msg been_added is empty\n");
- return;
- }
+ // Fixme: check length here
- read_packet_dw(data, cursor, len, &external_group_id);
- read_packet_b(data, cursor, len, &group_type);
- read_packet_dw(data, cursor, len, &uid);
+ bytes += qq_get32(&external_group_id, data + bytes);
+ bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&uid, data + bytes);
g_return_if_fail(external_group_id > 0 && uid > 0);
@@ -307,8 +292,7 @@ void qq_process_recv_group_im_been_added
}
/* recv an IM from a group chat */
-void qq_process_recv_group_im(guint8 *data, guint8 **cursor, gint data_len,
- guint32 internal_group_id, PurpleConnection *gc, guint16 im_type)
+void qq_process_recv_group_im(guint8 *data, gint data_len, guint32 internal_group_id, PurpleConnection *gc, guint16 im_type)
{
gchar *msg_with_purple_smiley, *msg_utf8_encoded, *im_src_name, *hex_dump;
guint16 unknown;
@@ -319,32 +303,31 @@ void qq_process_recv_group_im(guint8 *data, guint8 **cursor, gint data_len,
qq_group *group;
qq_recv_group_im *im_group;
gint skip_len;
+ gint bytes = 0;
g_return_if_fail(data != NULL && data_len > 0);
+
+ // Fixme: check length here
+
qd = (qq_data *) gc->proto_data;
- hex_dump = hex_dump_to_str(*cursor, data_len - (*cursor - data));
+ hex_dump = hex_dump_to_str(data, data_len);
purple_debug(PURPLE_DEBUG_INFO, "QQ", "group im hex dump\n%s\n", hex_dump);
- if (*cursor >= (data + data_len - 1)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received group im_group is empty\n");
- return;
- }
-
im_group = g_newa(qq_recv_group_im, 1);
- read_packet_dw(data, cursor, data_len, &(im_group->external_group_id));
- read_packet_b(data, cursor, data_len, &(im_group->group_type));
+ bytes += qq_get32(&(im_group->external_group_id), data + bytes);
+ bytes += qq_get8(&(im_group->group_type), data + bytes);
if(QQ_RECV_IM_TEMP_QUN_IM == im_type) {
- read_packet_dw(data, cursor, data_len, &(internal_group_id));
+ bytes += qq_get32(&(internal_group_id), data + bytes);
}
- read_packet_dw(data, cursor, data_len, &(im_group->member_uid));
- read_packet_w(data, cursor, data_len, &unknown); /* 0x0001? */
- read_packet_w(data, cursor, data_len, &(im_group->msg_seq));
- read_packet_time(data, cursor, data_len, &im_group->send_time);
- read_packet_dw(data, cursor, data_len, &unknown4); /* versionID */
+ bytes += qq_get32(&(im_group->member_uid), bytes + data);
+ bytes += qq_get16(&unknown, data + bytes); /* 0x0001? */
+ bytes += qq_get16(&(im_group->msg_seq), data + bytes);
+ bytes += qq_getime(&im_group->send_time, data + bytes);
+ bytes += qq_get32(&unknown4, data + bytes); /* versionID */
/*
* length includes font_attr
* this msg_len includes msg and font_attr
@@ -355,7 +338,7 @@ void qq_process_recv_group_im(guint8 *data, guint8 **cursor, gint data_len,
* 3. font_attr
*/
- read_packet_w(data, cursor, data_len, &(im_group->msg_len));
+ bytes += qq_get16(&(im_group->msg_len), data + bytes);
g_return_if_fail(im_group->msg_len > 0);
/*
@@ -371,14 +354,14 @@ void qq_process_recv_group_im(guint8 *data, guint8 **cursor, gint data_len,
skip_len = 10;
else
skip_len = 0;
- *cursor += skip_len;
+ bytes += skip_len;
- im_group->msg = g_strdup((gchar *) *cursor);
- *cursor += strlen(im_group->msg) + 1;
+ im_group->msg = g_strdup((gchar *) data + bytes);
+ bytes += strlen(im_group->msg) + 1;
/* there might not be any font_attr, check it */
im_group->font_attr_len = im_group->msg_len - strlen(im_group->msg) - 1 - skip_len;
if (im_group->font_attr_len > 0)
- im_group->font_attr = g_memdup(*cursor, im_group->font_attr_len);
+ im_group->font_attr = g_memdup(data + bytes, im_group->font_attr_len);
else
im_group->font_attr = NULL;
@@ -386,7 +369,7 @@ void qq_process_recv_group_im(guint8 *data, guint8 **cursor, gint data_len,
msg_with_purple_smiley = qq_smiley_to_purple(im_group->msg);
if (im_group->font_attr_len > 0)
msg_utf8_encoded = qq_encode_to_purple(im_group->font_attr,
- im_group->font_attr_len, msg_with_purple_smiley);
+ im_group->font_attr_len, msg_with_purple_smiley);
else
msg_utf8_encoded = qq_to_utf8(msg_with_purple_smiley, QQ_CHARSET_DEFAULT);
@@ -406,8 +389,8 @@ void qq_process_recv_group_im(guint8 *data, guint8 **cursor, gint data_len,
else
im_src_name = g_strdup(member->nickname);
serv_got_chat_in(gc,
- purple_conv_chat_get_id(PURPLE_CONV_CHAT
- (conv)), im_src_name, 0, msg_utf8_encoded, im_group->send_time);
+ purple_conv_chat_get_id(PURPLE_CONV_CHAT
+ (conv)), im_src_name, 0, msg_utf8_encoded, im_group->send_time);
g_free(im_src_name);
}
g_free(hex_dump);
diff --git a/libpurple/protocols/qq/group_im.h b/libpurple/protocols/qq/group_im.h
index 4b5a373965..e409f094b4 100644
--- a/libpurple/protocols/qq/group_im.h
+++ b/libpurple/protocols/qq/group_im.h
@@ -30,17 +30,31 @@
#include "group.h"
void qq_send_packet_group_im(PurpleConnection *gc, qq_group *group, const gchar *msg);
-void qq_process_group_cmd_im(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
-void qq_process_recv_group_im(guint8 *data,
- guint8 **cursor, gint data_len, guint32 internal_group_id, PurpleConnection *gc, guint16 im_type);
-void qq_process_recv_group_im_apply_join(guint8 *data,
- guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
-void qq_process_recv_group_im_been_rejected(guint8 *data,
- guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
-void qq_process_recv_group_im_been_approved(guint8 *data,
- guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
-void qq_process_recv_group_im_been_removed(guint8 *data,
- guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
-void qq_process_recv_group_im_been_added(guint8 *data,
- guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+
+//void qq_process_group_cmd_im(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
+void qq_process_group_cmd_im(guint8 *data, gint len, PurpleConnection *gc);
+
+//void qq_process_recv_group_im(guint8 *data,
+// guint8 **cursor, gint data_len, guint32 internal_group_id, PurpleConnection *gc, guint16 im_type);
+void qq_process_recv_group_im(guint8 *data, gint data_len, guint32 internal_group_id, PurpleConnection *gc, guint16 im_type);
+
+//void qq_process_recv_group_im_apply_join(guint8 *data,
+// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+void qq_process_recv_group_im_apply_join(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
+
+//void qq_process_recv_group_im_been_rejected(guint8 *data,
+// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+void qq_process_recv_group_im_been_rejected(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
+
+//void qq_process_recv_group_im_been_approved(guint8 *data,
+// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+void qq_process_recv_group_im_been_approved(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
+
+//void qq_process_recv_group_im_been_removed(guint8 *data,
+// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+void qq_process_recv_group_im_been_removed(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
+
+//void qq_process_recv_group_im_been_added(guint8 *data,
+// guint8 **cursor, gint len, guint32 internal_group_id, PurpleConnection *gc);
+void qq_process_recv_group_im_been_added(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc);
#endif
diff --git a/libpurple/protocols/qq/group_info.c b/libpurple/protocols/qq/group_info.c
index 190449c23f..f9cefcc9d8 100644
--- a/libpurple/protocols/qq/group_info.c
+++ b/libpurple/protocols/qq/group_info.c
@@ -43,7 +43,7 @@ static gboolean _is_group_member_need_update_info(qq_buddy *member)
{
g_return_val_if_fail(member != NULL, FALSE);
return (member->nickname == NULL) ||
- (time(NULL) - member->last_refresh) > QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL;
+ (time(NULL) - member->last_refresh) > QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL;
}
/* this is done when we receive the reply to get_online_members sub_cmd
@@ -65,100 +65,83 @@ static void _qq_group_set_members_all_offline(qq_group *group)
/* send packet to get detailed information of one group */
void qq_send_cmd_group_get_group_info(PurpleConnection *gc, qq_group *group)
{
- guint8 *raw_data, *cursor;
- gint bytes, data_len;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
g_return_if_fail(group != NULL);
- data_len = 5;
- raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
-
- bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_GET_GROUP_INFO);
- bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
+ bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_GET_GROUP_INFO);
+ bytes += qq_put32(raw_data + bytes, group->internal_group_id);
- if (bytes != data_len)
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_GET_GROUP_INFO));
- else
- qq_send_group_cmd(gc, group, raw_data, data_len);
+ qq_send_group_cmd(gc, group, raw_data, bytes);
}
/* send packet to get online group member, called by keep_alive */
void qq_send_cmd_group_get_online_members(PurpleConnection *gc, qq_group *group)
{
- guint8 *raw_data, *cursor;
- gint bytes, data_len;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
g_return_if_fail(group != NULL);
/* only get online members when conversation window is on */
if (NULL == purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,group->group_name_utf8, purple_connection_get_account(gc))) {
purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- "Conv windows for \"%s\" is not on, do not get online members\n", group->group_name_utf8);
+ "Conv windows for \"%s\" is not on, do not get online members\n", group->group_name_utf8);
return;
}
- data_len = 5;
- raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
-
- bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_GET_ONLINE_MEMBER);
- bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
+ bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_GET_ONLINE_MEMBER);
+ bytes += qq_put32(raw_data + bytes, group->internal_group_id);
- if (bytes != data_len)
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_GET_ONLINE_MEMBER));
- else
- qq_send_group_cmd(gc, group, raw_data, data_len);
+ qq_send_group_cmd(gc, group, raw_data, bytes);
}
/* send packet to get info for each group member */
void qq_send_cmd_group_get_members_info(PurpleConnection *gc, qq_group *group)
{
- guint8 *raw_data, *cursor;
- gint bytes, data_len, i;
+ guint8 *raw_data;
+ gint bytes, num, data_len;
GList *list;
qq_buddy *member;
g_return_if_fail(group != NULL);
- for (i = 0, list = group->members; list != NULL; list = list->next) {
+ for (num = 0, list = group->members; list != NULL; list = list->next) {
member = (qq_buddy *) list->data;
if (_is_group_member_need_update_info(member))
- i++;
+ num++;
}
- if (i <= 0) {
+ if (num <= 0) {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "No group member needs to to update info now.\n");
return;
}
- data_len = 5 + 4 * i;
+ data_len = 5 + 4 * num;
raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_GET_MEMBER_INFO);
- bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
+ bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_GET_MEMBER_INFO);
+ bytes += qq_put32(raw_data + bytes, group->internal_group_id);
list = group->members;
while (list != NULL) {
member = (qq_buddy *) list->data;
if (_is_group_member_need_update_info(member))
- bytes += create_packet_dw(raw_data, &cursor, member->uid);
+ bytes += qq_put32(raw_data + bytes, member->uid);
list = list->next;
}
- if (bytes != data_len)
+ if (bytes != data_len) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_GET_MEMBER_INFO));
- else
- qq_send_group_cmd(gc, group, raw_data, data_len);
+ "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_GET_MEMBER_INFO));
+ return;
+ }
+
+ qq_send_group_cmd(gc, group, raw_data, bytes);
}
-void qq_process_group_cmd_get_group_info(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_process_group_cmd_get_group_info(guint8 *data, gint len, PurpleConnection *gc)
{
qq_group *group;
qq_buddy *member;
@@ -168,16 +151,18 @@ void qq_process_group_cmd_get_group_info(guint8 *data, guint8 **cursor, gint len
guint16 unknown, max_members;
guint32 member_uid, internal_group_id, external_group_id;
GSList *pending_id;
- gint pascal_len, i;
guint32 unknown4;
guint8 unknown1;
+ gint bytes, num;
g_return_if_fail(data != NULL && len > 0);
qd = (qq_data *) gc->proto_data;
- read_packet_dw(data, cursor, len, &(internal_group_id));
+ bytes = 0;
+ bytes += qq_get32(&(internal_group_id), data + bytes);
g_return_if_fail(internal_group_id > 0);
- read_packet_dw(data, cursor, len, &(external_group_id));
+
+ bytes += qq_get32(&(external_group_id), data + bytes);
g_return_if_fail(internal_group_id > 0);
pending_id = qq_get_pending_id(qd->adding_groups_from_server, internal_group_id);
@@ -189,32 +174,30 @@ void qq_process_group_cmd_get_group_info(guint8 *data, guint8 **cursor, gint len
group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
- read_packet_b(data, cursor, len, &(group->group_type));
- read_packet_dw(data, cursor, len, &unknown4); /* unknown 4 bytes */
- read_packet_dw(data, cursor, len, &(group->creator_uid));
- read_packet_b(data, cursor, len, &(group->auth_type));
- read_packet_dw(data, cursor, len, &unknown4); /* oldCategory */
- read_packet_w(data, cursor, len, &unknown);
- read_packet_dw(data, cursor, len, &(group->group_category));
- read_packet_w(data, cursor, len, &max_members);
- read_packet_b(data, cursor, len, &unknown1);
- read_packet_dw(data, cursor, len, &(unknown4)); /* versionID */
-
- pascal_len = convert_as_pascal_string(*cursor, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
- *cursor += pascal_len;
- read_packet_w(data, cursor, len, &(unknown)); /* 0x0000 */
- pascal_len = convert_as_pascal_string(*cursor, &(group->notice_utf8), QQ_CHARSET_DEFAULT);
- *cursor += pascal_len;
- pascal_len = convert_as_pascal_string(*cursor, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT);
- *cursor += pascal_len;
-
- i = 0;
+ bytes += qq_get8(&(group->group_type), data + bytes);
+ bytes += qq_get32(&unknown4, data + bytes); /* unknown 4 bytes */
+ bytes += qq_get32(&(group->creator_uid), data + bytes);
+ bytes += qq_get8(&(group->auth_type), data + bytes);
+ bytes += qq_get32(&unknown4, data + bytes); /* oldCategory */
+ bytes += qq_get16(&unknown, data + bytes);
+ bytes += qq_get32(&(group->group_category), data + bytes);
+ bytes += qq_get16(&max_members, data + bytes);
+ bytes += qq_get8(&unknown1, data + bytes);
+ bytes += qq_get32(&(unknown4), data + bytes); /* versionID */
+
+ /* strlen + <str content> */
+ bytes += convert_as_pascal_string(data + bytes, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
+ bytes += qq_get16(&unknown, data + bytes); /* 0x0000 */
+ bytes += convert_as_pascal_string(data + bytes, &(group->notice_utf8), QQ_CHARSET_DEFAULT);
+ bytes += convert_as_pascal_string(data + bytes, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT);
+
+ num = 0;
/* now comes the member list separated by 0x00 */
- while (*cursor < data + len) {
- read_packet_dw(data, cursor, len, &member_uid);
- i++;
- read_packet_b(data, cursor, len, &organization);
- read_packet_b(data, cursor, len, &role);
+ while (bytes < len) {
+ bytes += qq_get32(&member_uid, data + bytes);
+ num++;
+ bytes += qq_get8(&organization, data + bytes);
+ bytes += qq_get8(&role, data + bytes);
if(organization != 0 || role != 0) {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "group member %d: organization=%d, role=%d\n", member_uid, organization, role);
@@ -223,11 +206,11 @@ void qq_process_group_cmd_get_group_info(guint8 *data, guint8 **cursor, gint len
if (member != NULL)
member->role = role;
}
- if(*cursor > (data + len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "group_cmd_get_group_info: Dangerous error! maybe protocol changed, notify me!");
- }
+ if(bytes > len) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "group_cmd_get_group_info: Dangerous error! maybe protocol changed, notify me!");
+ }
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "group \"%s\" has %d members\n", group->group_name_utf8, i);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "group \"%s\" has %d members\n", group->group_name_utf8, num);
if (group->creator_uid == qd->uid)
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_ADMIN;
@@ -237,33 +220,32 @@ void qq_process_group_cmd_get_group_info(guint8 *data, guint8 **cursor, gint len
purple_conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
group->group_name_utf8, purple_connection_get_account(gc));
if(NULL == purple_conv) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- "Conv windows for \"%s\" is not on, do not set topic\n", group->group_name_utf8);
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Conv windows for \"%s\" is not on, do not set topic\n", group->group_name_utf8);
}
else {
purple_conv_chat_set_topic(PURPLE_CONV_CHAT(purple_conv), NULL, group->notice_utf8);
}
}
-void qq_process_group_cmd_get_online_members(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_process_group_cmd_get_online_members(guint8 *data, gint len, PurpleConnection *gc)
{
guint32 internal_group_id, member_uid;
guint8 unknown;
- gint bytes, i;
+ gint bytes, num;
qq_group *group;
qq_buddy *member;
g_return_if_fail(data != NULL && len > 0);
- if (data + len - *cursor < 4) {
+ if (len <= 3) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Invalid group online member reply, discard it!\n");
return;
}
bytes = 0;
- i = 0;
- bytes += read_packet_dw(data, cursor, len, &internal_group_id);
- bytes += read_packet_b(data, cursor, len, &unknown); /* 0x3c ?? */
+ bytes += qq_get32(&internal_group_id, data + bytes);
+ bytes += qq_get8(&unknown, data + bytes); /* 0x3c ?? */
g_return_if_fail(internal_group_id > 0);
group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
@@ -275,61 +257,63 @@ void qq_process_group_cmd_get_online_members(guint8 *data, guint8 **cursor, gint
/* set all offline first, then update those online */
_qq_group_set_members_all_offline(group);
- while (*cursor < data + len) {
- bytes += read_packet_dw(data, cursor, len, &member_uid);
- i++;
+ num = 0;
+ while (bytes < len) {
+ bytes += qq_get32(&member_uid, data + bytes);
+ num++;
member = qq_group_find_or_add_member(gc, group, member_uid);
if (member != NULL)
member->status = QQ_BUDDY_ONLINE_NORMAL;
}
- if(*cursor > (data + len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "group_cmd_get_online_members: Dangerous error! maybe protocol changed, notify developers!");
- }
+ if(bytes > len) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "group_cmd_get_online_members: Dangerous error! maybe protocol changed, notify developers!");
+ }
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Group \"%s\" has %d online members\n", group->group_name_utf8, i);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Group \"%s\" has %d online members\n", group->group_name_utf8, num);
}
/* process the reply to get_members_info packet */
-void qq_process_group_cmd_get_members_info(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_process_group_cmd_get_members_info(guint8 *data, gint len, PurpleConnection *gc)
{
+ gint bytes;
+ gint num;
guint32 internal_group_id, member_uid;
guint16 unknown;
- gint pascal_len, i;
qq_group *group;
qq_buddy *member;
g_return_if_fail(data != NULL && len > 0);
- read_packet_dw(data, cursor, len, &internal_group_id);
+ bytes = 0;
+ bytes += qq_get32(&internal_group_id, data + bytes);
g_return_if_fail(internal_group_id > 0);
group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
- i = 0;
+ num = 0;
/* now starts the member info, as get buddy list reply */
- while (*cursor < data + len) {
- read_packet_dw(data, cursor, len, &member_uid);
+ while (bytes < len) {
+ bytes += qq_get32(&member_uid, data + bytes);
g_return_if_fail(member_uid > 0);
member = qq_group_find_member_by_uid(group, member_uid);
g_return_if_fail(member != NULL);
- i++;
- read_packet_w(data, cursor, len, &(member->face));
- read_packet_b(data, cursor, len, &(member->age));
- read_packet_b(data, cursor, len, &(member->gender));
- pascal_len = convert_as_pascal_string(*cursor, &(member->nickname), QQ_CHARSET_DEFAULT);
- *cursor += pascal_len;
- read_packet_w(data, cursor, len, &unknown);
- read_packet_b(data, cursor, len, &(member->flag1));
- read_packet_b(data, cursor, len, &(member->comm_flag));
+ num++;
+ bytes += qq_get16(&(member->face), data + bytes);
+ bytes += qq_get8(&(member->age), data + bytes);
+ bytes += qq_get8(&(member->gender), data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &(member->nickname), QQ_CHARSET_DEFAULT);
+ bytes += qq_get16(&unknown, data + bytes);
+ bytes += qq_get8(&(member->flag1), data + bytes);
+ bytes += qq_get8(&(member->comm_flag), data + bytes);
member->last_refresh = time(NULL);
}
- if(*cursor > (data + len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "group_cmd_get_members_info: Dangerous error! maybe protocol changed, notify developers!");
- }
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Group \"%s\" obtained %d member info\n", group->group_name_utf8, i);
+ if(bytes > len) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "group_cmd_get_members_info: Dangerous error! maybe protocol changed, notify developers!");
+ }
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Group \"%s\" obtained %d member info\n", group->group_name_utf8, num);
}
diff --git a/libpurple/protocols/qq/group_info.h b/libpurple/protocols/qq/group_info.h
index be3208440b..dfa3d8aa19 100644
--- a/libpurple/protocols/qq/group_info.h
+++ b/libpurple/protocols/qq/group_info.h
@@ -32,8 +32,8 @@
void qq_send_cmd_group_get_group_info(PurpleConnection *gc, qq_group *group);
void qq_send_cmd_group_get_online_members(PurpleConnection *gc, qq_group *group);
void qq_send_cmd_group_get_members_info(PurpleConnection *gc, qq_group *group);
-void qq_process_group_cmd_get_group_info(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
-void qq_process_group_cmd_get_online_members(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
-void qq_process_group_cmd_get_members_info(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
+void qq_process_group_cmd_get_group_info(guint8 *data, gint len, PurpleConnection *gc);
+void qq_process_group_cmd_get_online_members(guint8 *data, gint len, PurpleConnection *gc);
+void qq_process_group_cmd_get_members_info(guint8 *data, gint len, PurpleConnection *gc);
#endif
diff --git a/libpurple/protocols/qq/group_join.c b/libpurple/protocols/qq/group_join.c
index 8debc1645f..bfa72b5d71 100644
--- a/libpurple/protocols/qq/group_join.c
+++ b/libpurple/protocols/qq/group_join.c
@@ -64,8 +64,8 @@ static void _qq_group_exit_with_gc_and_id(gc_and_uid *g)
/* send packet to join a group without auth */
void qq_send_cmd_group_join_group(PurpleConnection *gc, qq_group *group)
{
- guint8 *raw_data, *cursor;
- gint bytes, data_len;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
g_return_if_fail(group != NULL);
@@ -86,19 +86,11 @@ void qq_send_cmd_group_join_group(PurpleConnection *gc, qq_group *group)
break;
}
- data_len = 5;
- raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
-
bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_JOIN_GROUP);
- bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
+ bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_JOIN_GROUP);
+ bytes += qq_put32(raw_data + bytes, group->internal_group_id);
- if (bytes != data_len)
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_JOIN_GROUP));
- else
- qq_send_group_cmd(gc, group, raw_data, data_len);
+ qq_send_group_cmd(gc, group, raw_data, bytes);
}
static void _qq_group_join_auth_with_gc_and_id(gc_and_uid *g, const gchar *reason_utf8)
@@ -145,7 +137,7 @@ static void _qq_group_join_auth(PurpleConnection *gc, qq_group *group)
void qq_send_cmd_group_auth(PurpleConnection *gc, qq_group *group, guint8 opt, guint32 uid, const gchar *reason_utf8)
{
- guint8 *raw_data, *cursor;
+ guint8 *raw_data;
gchar *reason_qq;
gint bytes, data_len;
@@ -164,50 +156,42 @@ void qq_send_cmd_group_auth(PurpleConnection *gc, qq_group *group, guint8 opt, g
data_len = 10 + strlen(reason_qq) + 1;
raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_JOIN_GROUP_AUTH);
- bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
- bytes += create_packet_b(raw_data, &cursor, opt);
- bytes += create_packet_dw(raw_data, &cursor, uid);
- bytes += create_packet_b(raw_data, &cursor, strlen(reason_qq));
- bytes += create_packet_data(raw_data, &cursor, (guint8 *) reason_qq, strlen(reason_qq));
-
- if (bytes != data_len)
+ bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_JOIN_GROUP_AUTH);
+ bytes += qq_put32(raw_data + bytes, group->internal_group_id);
+ bytes += qq_put8(raw_data + bytes, opt);
+ bytes += qq_put32(raw_data + bytes, uid);
+ bytes += qq_put8(raw_data + bytes, strlen(reason_qq));
+ bytes += qq_putdata(raw_data + bytes, (guint8 *) reason_qq, strlen(reason_qq));
+
+ if (bytes != data_len) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
"Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_JOIN_GROUP_AUTH));
- else
- qq_send_group_cmd(gc, group, raw_data, data_len);
+ return;
+ }
+
+ qq_send_group_cmd(gc, group, raw_data, data_len);
}
/* send a packet to exit a group */
void qq_send_cmd_group_exit_group(PurpleConnection *gc, qq_group *group)
{
- guint8 *raw_data, *cursor;
- gint bytes, data_len;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
g_return_if_fail(group != NULL);
- data_len = 5;
- raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
-
- bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_EXIT_GROUP);
- bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
+ bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_EXIT_GROUP);
+ bytes += qq_put32(raw_data + bytes, group->internal_group_id);
- if (bytes != data_len)
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_EXIT_GROUP));
- else
- qq_send_group_cmd(gc, group, raw_data, data_len);
+ qq_send_group_cmd(gc, group, raw_data, bytes);
}
/* If comes here, cmd is OK already */
-void qq_process_group_cmd_exit_group(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_process_group_cmd_exit_group(guint8 *data, gint len, PurpleConnection *gc)
{
- gint bytes, expected_bytes;
+ gint bytes;
guint32 internal_group_id;
PurpleChat *chat;
qq_group *group;
@@ -216,96 +200,94 @@ void qq_process_group_cmd_exit_group(guint8 *data, guint8 **cursor, gint len, Pu
g_return_if_fail(data != NULL && len > 0);
qd = (qq_data *) gc->proto_data;
+ if (len < 4) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Invalid exit group reply, expect %d bytes, read %d bytes\n", 4, len);
+ return;
+ }
+
bytes = 0;
- expected_bytes = 4;
- bytes += read_packet_dw(data, cursor, len, &internal_group_id);
-
- if (bytes == expected_bytes) {
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
- if (group != NULL) {
- chat =
- purple_blist_find_chat
+ bytes += qq_get32(&internal_group_id, data + bytes);
+
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ if (group != NULL) {
+ chat = purple_blist_find_chat
(purple_connection_get_account(gc), g_strdup_printf("%d", group->external_group_id));
- if (chat != NULL)
- purple_blist_remove_chat(chat);
- qq_group_delete_internal_record(qd, internal_group_id);
- }
- purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully left the group"), NULL);
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Invalid exit group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
+ if (chat != NULL)
+ purple_blist_remove_chat(chat);
+ qq_group_delete_internal_record(qd, internal_group_id);
}
+ purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully left the group"), NULL);
}
/* Process the reply to group_auth subcmd */
-void qq_process_group_cmd_join_group_auth(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_process_group_cmd_join_group_auth(guint8 *data, gint len, PurpleConnection *gc)
{
- gint bytes, expected_bytes;
+ gint bytes;
guint32 internal_group_id;
qq_data *qd;
g_return_if_fail(data != NULL && len > 0);
qd = (qq_data *) gc->proto_data;
+ if (len < 4) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Invalid join group reply, expect %d bytes, read %d bytes\n", 4, len);
+ return;
+ }
bytes = 0;
- expected_bytes = 4;
- bytes += read_packet_dw(data, cursor, len, &internal_group_id);
+ bytes += qq_get32(&internal_group_id, data + bytes);
g_return_if_fail(internal_group_id > 0);
- if (bytes == expected_bytes)
- purple_notify_info
- (gc, _("QQ Group Auth"),
+ purple_notify_info(gc, _("QQ Group Auth"),
_("Your authorization request has been accepted by the QQ server"), NULL);
- else
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
}
/* process group cmd reply "join group" */
-void qq_process_group_cmd_join_group(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_process_group_cmd_join_group(guint8 *data, gint len, PurpleConnection *gc)
{
- gint bytes, expected_bytes;
+ gint bytes;
guint32 internal_group_id;
guint8 reply;
qq_group *group;
g_return_if_fail(data != NULL && len > 0);
- bytes = 0;
- expected_bytes = 5;
- bytes += read_packet_dw(data, cursor, len, &internal_group_id);
- bytes += read_packet_b(data, cursor, len, &reply);
-
- if (bytes != expected_bytes) {
+ if (len < 5) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
+ "Invalid join group reply, expect %d bytes, read %d bytes\n", 5, len);
return;
- } else { /* join group OK */
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
- /* need to check if group is NULL or not. */
- g_return_if_fail(group != NULL);
- switch (reply) {
- case QQ_GROUP_JOIN_OK:
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed joining group \"%s\"\n", group->group_name_utf8);
- group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
- qq_group_refresh(gc, group);
- /* this must be shown before getting online members */
- qq_group_conv_show_window(gc, group);
- qq_send_cmd_group_get_group_info(gc, group);
- break;
- case QQ_GROUP_JOIN_NEED_AUTH:
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "Fail joining group [%d] %s, needs authentication\n",
- group->external_group_id, group->group_name_utf8);
- group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
- qq_group_refresh(gc, group);
- _qq_group_join_auth(gc, group);
- break;
- default:
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "Error joining group [%d] %s, unknown reply: 0x%02x\n",
- group->external_group_id, group->group_name_utf8, reply);
- }
+ }
+
+ bytes = 0;
+ bytes += qq_get32(&internal_group_id, data + bytes);
+ bytes += qq_get8(&reply, data + bytes);
+
+ /* join group OK */
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ /* need to check if group is NULL or not. */
+ g_return_if_fail(group != NULL);
+ switch (reply) {
+ case QQ_GROUP_JOIN_OK:
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed joining group \"%s\"\n", group->group_name_utf8);
+ group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
+ qq_group_refresh(gc, group);
+ /* this must be shown before getting online members */
+ qq_group_conv_show_window(gc, group);
+ qq_send_cmd_group_get_group_info(gc, group);
+ break;
+ case QQ_GROUP_JOIN_NEED_AUTH:
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Fail joining group [%d] %s, needs authentication\n",
+ group->external_group_id, group->group_name_utf8);
+ group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
+ qq_group_refresh(gc, group);
+ _qq_group_join_auth(gc, group);
+ break;
+ default:
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Error joining group [%d] %s, unknown reply: 0x%02x\n",
+ group->external_group_id, group->group_name_utf8, reply);
}
}
diff --git a/libpurple/protocols/qq/group_join.h b/libpurple/protocols/qq/group_join.h
index 5c42e31ed5..1c346717b6 100644
--- a/libpurple/protocols/qq/group_join.h
+++ b/libpurple/protocols/qq/group_join.h
@@ -46,8 +46,8 @@ void qq_group_join(PurpleConnection *gc, GHashTable *data);
void qq_send_cmd_group_join_group(PurpleConnection *gc, qq_group *group);
void qq_group_exit(PurpleConnection *gc, GHashTable *data);
void qq_send_cmd_group_exit_group(PurpleConnection *gc, qq_group *group);
-void qq_process_group_cmd_exit_group(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
-void qq_process_group_cmd_join_group_auth(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
-void qq_process_group_cmd_join_group(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
+void qq_process_group_cmd_exit_group(guint8 *data, gint len, PurpleConnection *gc);
+void qq_process_group_cmd_join_group_auth(guint8 *data, gint len, PurpleConnection *gc);
+void qq_process_group_cmd_join_group(guint8 *data, gint len, PurpleConnection *gc);
#endif
diff --git a/libpurple/protocols/qq/group_network.c b/libpurple/protocols/qq/group_network.c
index e88f7bb24e..037d23ae29 100644
--- a/libpurple/protocols/qq/group_network.c
+++ b/libpurple/protocols/qq/group_network.c
@@ -81,12 +81,12 @@ const gchar *qq_group_cmd_get_desc(qq_group_cmd cmd)
}
/* default process of reply error */
-static void _qq_process_group_cmd_reply_error_default(guint8 reply, guint8 *cursor, gint len, PurpleConnection *gc)
+static void _qq_process_group_cmd_reply_error_default(guint8 reply, guint8 *data, gint len, PurpleConnection *gc)
{
gchar *msg, *msg_utf8;
- g_return_if_fail(cursor != NULL && len > 0);
+ g_return_if_fail(data != NULL && len > 0);
- msg = g_strndup((gchar *) cursor, len); /* it will append 0x00 */
+ msg = g_strndup((gchar *) data, len); /* it will append 0x00 */
msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
g_free(msg);
msg = g_strdup_printf(_("Code [0x%02X]: %s"), reply, msg_utf8);
@@ -96,7 +96,7 @@ static void _qq_process_group_cmd_reply_error_default(guint8 reply, guint8 *curs
}
/* default process, dump only */
-static void _qq_process_group_cmd_reply_default(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+static void _qq_process_group_cmd_reply_default(guint8 *data, gint len, PurpleConnection *gc)
{
gchar *hex_dump;
g_return_if_fail(data != NULL && len > 0);
@@ -136,7 +136,7 @@ void qq_process_group_cmd_reply(guint8 *buf, gint buf_len, guint16 seq, PurpleCo
qq_data *qd;
gint len, bytes;
guint32 internal_group_id;
- guint8 *data, *cursor, sub_cmd, reply;
+ guint8 *data, sub_cmd, reply;
g_return_if_fail(buf != NULL && buf_len != 0);
@@ -149,102 +149,101 @@ void qq_process_group_cmd_reply(guint8 *buf, gint buf_len, guint16 seq, PurpleCo
return;
}
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- if (len <= 2) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Group cmd reply is too short, only %d bytes\n", len);
- return;
- }
+ if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &len) ) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt group cmd reply\n");
+ return;
+ }
- bytes = 0;
- cursor = data;
- bytes += read_packet_b(data, &cursor, len, &sub_cmd);
- bytes += read_packet_b(data, &cursor, len, &reply);
-
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
-
- if (reply != QQ_GROUP_CMD_REPLY_OK) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- "Group cmd reply says cmd %s fails\n", qq_group_cmd_get_desc(sub_cmd));
-
- if (group != NULL)
- qq_set_pending_id(&qd->joining_groups, group->external_group_id, FALSE);
-
- switch (reply) { /* this should be all errors */
- case QQ_GROUP_CMD_REPLY_NOT_MEMBER:
- if (group != NULL) {
- purple_debug(PURPLE_DEBUG_WARNING,
- "QQ",
- "You are not a member of group \"%s\"\n", group->group_name_utf8);
- group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
- qq_group_refresh(gc, group);
- }
- break;
- case QQ_GROUP_CMD_REPLY_SEARCH_ERROR:
- if (qd->roomlist != NULL) {
- if (purple_roomlist_get_in_progress(qd->roomlist))
- purple_roomlist_set_in_progress(qd->roomlist, FALSE);
- }
- _qq_process_group_cmd_reply_error_default(reply, cursor, len - bytes, gc);
- break;
- default:
- _qq_process_group_cmd_reply_error_default(reply, cursor, len - bytes, gc);
- }
- return;
- }
+ if (len <= 2) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Group cmd reply is too short, only %d bytes\n", len);
+ return;
+ }
+
+ bytes = 0;
+ bytes += qq_get8(&sub_cmd, data + bytes);
+ bytes += qq_get8(&reply, data + bytes);
+
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
- /* seems ok so far, so we process the reply according to sub_cmd */
- switch (sub_cmd) {
- case QQ_GROUP_CMD_GET_GROUP_INFO:
- qq_process_group_cmd_get_group_info(data, &cursor, len, gc);
+ if (reply != QQ_GROUP_CMD_REPLY_OK) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Group cmd reply says cmd %s fails\n", qq_group_cmd_get_desc(sub_cmd));
+
+ if (group != NULL)
+ qq_set_pending_id(&qd->joining_groups, group->external_group_id, FALSE);
+
+ switch (reply) { /* this should be all errors */
+ case QQ_GROUP_CMD_REPLY_NOT_MEMBER:
if (group != NULL) {
- qq_send_cmd_group_get_members_info(gc, group);
- qq_send_cmd_group_get_online_members(gc, group);
+ purple_debug(PURPLE_DEBUG_WARNING,
+ "QQ",
+ "You are not a member of group \"%s\"\n", group->group_name_utf8);
+ group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
+ qq_group_refresh(gc, group);
}
break;
- case QQ_GROUP_CMD_CREATE_GROUP:
- qq_group_process_create_group_reply(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_MODIFY_GROUP_INFO:
- qq_group_process_modify_info_reply(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_MEMBER_OPT:
- qq_group_process_modify_members_reply(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_ACTIVATE_GROUP:
- qq_group_process_activate_group_reply(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_SEARCH_GROUP:
- qq_process_group_cmd_search_group(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_JOIN_GROUP:
- qq_process_group_cmd_join_group(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_JOIN_GROUP_AUTH:
- qq_process_group_cmd_join_group_auth(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_EXIT_GROUP:
- qq_process_group_cmd_exit_group(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_SEND_MSG:
- qq_process_group_cmd_im(data, &cursor, len, gc);
- break;
- case QQ_GROUP_CMD_GET_ONLINE_MEMBER:
- qq_process_group_cmd_get_online_members(data, &cursor, len, gc);
- if (group != NULL)
- qq_group_conv_refresh_online_member(gc, group);
- break;
- case QQ_GROUP_CMD_GET_MEMBER_INFO:
- qq_process_group_cmd_get_members_info(data, &cursor, len, gc);
- if (group != NULL)
- qq_group_conv_refresh_online_member(gc, group);
+ case QQ_GROUP_CMD_REPLY_SEARCH_ERROR:
+ if (qd->roomlist != NULL) {
+ if (purple_roomlist_get_in_progress(qd->roomlist))
+ purple_roomlist_set_in_progress(qd->roomlist, FALSE);
+ }
+ _qq_process_group_cmd_reply_error_default(reply, data + bytes, len - bytes, gc);
break;
default:
- purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- "Group cmd %s is processed by default\n", qq_group_cmd_get_desc(sub_cmd));
- _qq_process_group_cmd_reply_default(data, &cursor, len, gc);
+ _qq_process_group_cmd_reply_error_default(reply, data + bytes, len - bytes, gc);
}
+ return;
+ }
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt group cmd reply\n");
+ /* seems ok so far, so we process the reply according to sub_cmd */
+ switch (sub_cmd) {
+ case QQ_GROUP_CMD_GET_GROUP_INFO:
+ qq_process_group_cmd_get_group_info(data + bytes, len - bytes, gc);
+ if (group != NULL) {
+ qq_send_cmd_group_get_members_info(gc, group);
+ qq_send_cmd_group_get_online_members(gc, group);
+ }
+ break;
+ case QQ_GROUP_CMD_CREATE_GROUP:
+ qq_group_process_create_group_reply(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_MODIFY_GROUP_INFO:
+ qq_group_process_modify_info_reply(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_MEMBER_OPT:
+ qq_group_process_modify_members_reply(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_ACTIVATE_GROUP:
+ qq_group_process_activate_group_reply(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_SEARCH_GROUP:
+ qq_process_group_cmd_search_group(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_JOIN_GROUP:
+ qq_process_group_cmd_join_group(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_JOIN_GROUP_AUTH:
+ qq_process_group_cmd_join_group_auth(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_EXIT_GROUP:
+ qq_process_group_cmd_exit_group(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_SEND_MSG:
+ qq_process_group_cmd_im(data + bytes, len - bytes, gc);
+ break;
+ case QQ_GROUP_CMD_GET_ONLINE_MEMBER:
+ qq_process_group_cmd_get_online_members(data + bytes, len - bytes, gc);
+ if (group != NULL)
+ qq_group_conv_refresh_online_member(gc, group);
+ break;
+ case QQ_GROUP_CMD_GET_MEMBER_INFO:
+ qq_process_group_cmd_get_members_info(data + bytes, len - bytes, gc);
+ if (group != NULL)
+ qq_group_conv_refresh_online_member(gc, group);
+ break;
+ default:
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Group cmd %s is processed by default\n", qq_group_cmd_get_desc(sub_cmd));
+ _qq_process_group_cmd_reply_default(data + bytes, len, gc);
}
}
diff --git a/libpurple/protocols/qq/group_opt.c b/libpurple/protocols/qq/group_opt.c
index 8eff65ea64..d673dc6a3c 100644
--- a/libpurple/protocols/qq/group_opt.c
+++ b/libpurple/protocols/qq/group_opt.c
@@ -57,22 +57,24 @@ static void _sort(guint32 *list)
static void _qq_group_member_opt(PurpleConnection *gc, qq_group *group, gint operation, guint32 *members)
{
- guint8 *data, *cursor;
+ guint8 *data;
gint i, count, data_len;
+ gint bytes;
g_return_if_fail(members != NULL);
- for (i = 0; members[i] != 0xffffffff; i++) {;
+ for (count = 0; members[count] != 0xffffffff; count++) {;
}
- count = i;
data_len = 6 + count * 4;
data = g_newa(guint8, data_len);
- cursor = data;
- create_packet_b(data, &cursor, QQ_GROUP_CMD_MEMBER_OPT);
- create_packet_dw(data, &cursor, group->internal_group_id);
- create_packet_b(data, &cursor, operation);
+
+ bytes = 0;
+ bytes += qq_put8(data + bytes, QQ_GROUP_CMD_MEMBER_OPT);
+ bytes += qq_put32(data + bytes, group->internal_group_id);
+ bytes += qq_put8(data + bytes, operation);
for (i = 0; i < count; i++)
- create_packet_dw(data, &cursor, members[i]);
- qq_send_group_cmd(gc, group, data, data_len);
+ bytes += qq_put32(data + bytes, members[i]);
+
+ qq_send_group_cmd(gc, group, data, bytes);
}
static void _qq_group_do_nothing_with_struct(group_member_opt *g)
@@ -97,11 +99,11 @@ void qq_group_search_application_with_struct(group_member_opt *g)
qq_send_packet_get_info(g->gc, g->member, TRUE); /* we want to see window */
purple_request_action(g->gc, NULL, _("Do you want to approve the request?"), "",
- PURPLE_DEFAULT_ACTION_NONE,
- purple_connection_get_account(g->gc), NULL, NULL,
- g, 2,
- _("Reject"), G_CALLBACK(qq_group_reject_application_with_struct),
- _("Approve"), G_CALLBACK(qq_group_approve_application_with_struct));
+ PURPLE_DEFAULT_ACTION_NONE,
+ purple_connection_get_account(g->gc), NULL, NULL,
+ g, 2,
+ _("Reject"), G_CALLBACK(qq_group_reject_application_with_struct),
+ _("Approve"), G_CALLBACK(qq_group_approve_application_with_struct));
}
void qq_group_reject_application_with_struct(group_member_opt *g)
@@ -193,13 +195,15 @@ void qq_group_modify_members(PurpleConnection *gc, qq_group *group, guint32 *new
_qq_group_member_opt(gc, group, QQ_GROUP_MEMBER_ADD, add_members);
}
-void qq_group_process_modify_members_reply(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc)
{
+ gint bytes;
guint32 internal_group_id;
qq_group *group;
g_return_if_fail(data != NULL);
- read_packet_dw(data, cursor, len, &internal_group_id);
+ bytes = 0;
+ bytes += qq_get32(&internal_group_id, data + bytes);
g_return_if_fail(internal_group_id > 0);
/* we should have its info locally */
@@ -213,8 +217,9 @@ void qq_group_process_modify_members_reply(guint8 *data, guint8 **cursor, gint l
void qq_group_modify_info(PurpleConnection *gc, qq_group *group)
{
- gint data_len, data_written;
- guint8 *data, *cursor;
+ guint8 *data;
+ gint data_len;
+ gint bytes;
gchar *group_name, *group_desc, *notice;
g_return_if_fail(group != NULL);
@@ -228,47 +233,50 @@ void qq_group_modify_info(PurpleConnection *gc, qq_group *group)
+ 1 + strlen(notice);
data = g_newa(guint8, data_len);
- cursor = data;
- data_written = 0;
+ bytes = 0;
/* 000-000 */
- data_written += create_packet_b(data, &cursor, QQ_GROUP_CMD_MODIFY_GROUP_INFO);
+ bytes += qq_put8(data + bytes, QQ_GROUP_CMD_MODIFY_GROUP_INFO);
/* 001-004 */
- data_written += create_packet_dw(data, &cursor, group->internal_group_id);
+ bytes += qq_put32(data + bytes, group->internal_group_id);
/* 005-005 */
- data_written += create_packet_b(data, &cursor, 0x01);
+ bytes += qq_put8(data + bytes, 0x01);
/* 006-006 */
- data_written += create_packet_b(data, &cursor, group->auth_type);
+ bytes += qq_put8(data + bytes, group->auth_type);
/* 007-008 */
- data_written += create_packet_w(data, &cursor, 0x0000);
+ bytes += qq_put16(data + bytes, 0x0000);
/* 009-010 */
- data_written += create_packet_w(data, &cursor, group->group_category);
+ bytes += qq_put16(data + bytes, group->group_category);
- data_written += create_packet_b(data, &cursor, strlen(group_name));
- data_written += create_packet_data(data, &cursor, (guint8 *) group_name, strlen(group_name));
+ bytes += qq_put8(data + bytes, strlen(group_name));
+ bytes += qq_putdata(data + bytes, (guint8 *) group_name, strlen(group_name));
- data_written += create_packet_w(data, &cursor, 0x0000);
+ bytes += qq_put16(data + bytes, 0x0000);
- data_written += create_packet_b(data, &cursor, strlen(notice));
- data_written += create_packet_data(data, &cursor, (guint8 *) notice, strlen(notice));
+ bytes += qq_put8(data + bytes, strlen(notice));
+ bytes += qq_putdata(data+ bytes, (guint8 *) notice, strlen(notice));
- data_written += create_packet_b(data, &cursor, strlen(group_desc));
- data_written += create_packet_data(data, &cursor, (guint8 *) group_desc, strlen(group_desc));
+ bytes += qq_put8(data + bytes, strlen(group_desc));
+ bytes += qq_putdata(data + bytes, (guint8 *) group_desc, strlen(group_desc));
- if (data_written != data_len)
+ if (bytes != data_len) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
"Fail to create group_modify_info packet, expect %d bytes, wrote %d bytes\n",
- data_len, data_written);
- else
- qq_send_group_cmd(gc, group, data, data_len);
+ data_len, bytes);
+ return;
+ }
+
+ qq_send_group_cmd(gc, group, data, bytes);
}
-void qq_group_process_modify_info_reply(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_group_process_modify_info_reply(guint8 *data, gint len, PurpleConnection *gc)
{
+ gint bytes;
guint32 internal_group_id;
qq_group *group;
g_return_if_fail(data != NULL);
- read_packet_dw(data, cursor, len, &internal_group_id);
+ bytes = 0;
+ bytes += qq_get32(&internal_group_id, data + bytes);
g_return_if_fail(internal_group_id > 0);
/* we should have its info locally */
@@ -284,42 +292,44 @@ void qq_group_process_modify_info_reply(guint8 *data, guint8 **cursor, gint len,
/* we create a very simple group first, and then let the user to modify */
void qq_group_create_with_name(PurpleConnection *gc, const gchar *name)
{
- gint data_len, data_written;
- guint8 *data, *cursor;
+ gint data_len;
+ guint8 *data;
+ gint bytes;
qq_data *qd;
g_return_if_fail(name != NULL);
qd = (qq_data *) gc->proto_data;
data_len = 7 + 1 + strlen(name) + 2 + 1 + 1 + 4;
data = g_newa(guint8, data_len);
- cursor = data;
- data_written = 0;
+ bytes = 0;
/* we create the simpleset group, only group name is given */
/* 000 */
- data_written += create_packet_b(data, &cursor, QQ_GROUP_CMD_CREATE_GROUP);
+ bytes += qq_put8(data + bytes, QQ_GROUP_CMD_CREATE_GROUP);
/* 001 */
- data_written += create_packet_b(data, &cursor, QQ_GROUP_TYPE_PERMANENT);
+ bytes += qq_put8(data + bytes, QQ_GROUP_TYPE_PERMANENT);
/* 002 */
- data_written += create_packet_b(data, &cursor, QQ_GROUP_AUTH_TYPE_NEED_AUTH);
+ bytes += qq_put8(data + bytes, QQ_GROUP_AUTH_TYPE_NEED_AUTH);
/* 003-004 */
- data_written += create_packet_w(data, &cursor, 0x0000);
+ bytes += qq_put16(data + bytes, 0x0000);
/* 005-006 */
- data_written += create_packet_w(data, &cursor, 0x0003);
+ bytes += qq_put16(data + bytes, 0x0003);
/* 007 */
- data_written += create_packet_b(data, &cursor, strlen(name));
- data_written += create_packet_data(data, &cursor, (guint8 *) name, strlen(name));
- data_written += create_packet_w(data, &cursor, 0x0000);
- data_written += create_packet_b(data, &cursor, 0x00); /* no group notice */
- data_written += create_packet_b(data, &cursor, 0x00); /* no group desc */
- data_written += create_packet_dw(data, &cursor, qd->uid); /* I am member of coz */
-
- if (data_written != data_len)
+ bytes += qq_put8(data + bytes, strlen(name));
+ bytes += qq_putdata(data + bytes, (guint8 *) name, strlen(name));
+ bytes += qq_put16(data + bytes, 0x0000);
+ bytes += qq_put8(data + bytes, 0x00); /* no group notice */
+ bytes += qq_put8(data + bytes, 0x00); /* no group desc */
+ bytes += qq_put32(data + bytes, qd->uid); /* I am member of coz */
+
+ if (bytes != data_len) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
"Fail create create_group packet, expect %d bytes, written %d bytes\n",
- data_len, data_written);
- else
- qq_send_group_cmd(gc, NULL, data, data_len);
+ data_len, bytes);
+ return;
+ }
+
+ qq_send_group_cmd(gc, NULL, data, bytes);
}
static void qq_group_setup_with_gc_and_uid(gc_and_uid *g)
@@ -335,8 +345,9 @@ static void qq_group_setup_with_gc_and_uid(gc_and_uid *g)
g_free(g);
}
-void qq_group_process_create_group_reply(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_group_process_create_group_reply(guint8 *data, gint len, PurpleConnection *gc)
{
+ gint bytes;
guint32 internal_group_id, external_group_id;
qq_group *group;
gc_and_uid *g;
@@ -346,8 +357,9 @@ void qq_group_process_create_group_reply(guint8 *data, guint8 **cursor, gint len
g_return_if_fail(gc->proto_data != NULL);
qd = (qq_data *) gc->proto_data;
- read_packet_dw(data, cursor, len, &internal_group_id);
- read_packet_dw(data, cursor, len, &external_group_id);
+ bytes = 0;
+ bytes += qq_get32(&internal_group_id, data + bytes);
+ bytes += qq_get32(&external_group_id, data + bytes);
g_return_if_fail(internal_group_id > 0 && external_group_id);
group = qq_group_create_internal_record(gc, internal_group_id, external_group_id, NULL);
@@ -378,36 +390,29 @@ void qq_group_process_create_group_reply(guint8 *data, guint8 **cursor, gint len
/* we have to activate group after creation, otherwise the group can not be searched */
void qq_group_activate_group(PurpleConnection *gc, guint32 internal_group_id)
{
- gint data_len, data_written;
- guint8 *data, *cursor;
+ guint8 data[16] = {0};
+ gint bytes = 0;
g_return_if_fail(internal_group_id > 0);
- data_len = 5;
- data = g_newa(guint8, data_len);
- cursor = data;
-
- data_written = 0;
+ bytes = 0;
/* we create the simplest group, only group name is given */
/* 000 */
- data_written += create_packet_b(data, &cursor, QQ_GROUP_CMD_ACTIVATE_GROUP);
+ bytes += qq_put8(data + bytes, QQ_GROUP_CMD_ACTIVATE_GROUP);
/* 001-005 */
- data_written += create_packet_dw(data, &cursor, internal_group_id);
+ bytes += qq_put32(data + bytes, internal_group_id);
- if (data_written != data_len)
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create activate_group packet, expect %d bytes, written %d bytes\n",
- data_len, data_written);
- else
- qq_send_group_cmd(gc, NULL, data, data_len);
+ qq_send_group_cmd(gc, NULL, data, bytes);
}
-void qq_group_process_activate_group_reply(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_group_process_activate_group_reply(guint8 *data, gint len, PurpleConnection *gc)
{
+ gint bytes;
guint32 internal_group_id;
qq_group *group;
g_return_if_fail(data != NULL);
- read_packet_dw(data, cursor, len, &internal_group_id);
+ bytes = 0;
+ bytes += qq_get32(&internal_group_id, data + bytes);
g_return_if_fail(internal_group_id > 0);
/* we should have its info locally */
diff --git a/libpurple/protocols/qq/group_opt.h b/libpurple/protocols/qq/group_opt.h
index 4aa09a7e0d..7e176bf2b0 100644
--- a/libpurple/protocols/qq/group_opt.h
+++ b/libpurple/protocols/qq/group_opt.h
@@ -54,12 +54,12 @@ void qq_group_approve_application_with_struct(group_member_opt *g);
void qq_group_reject_application_with_struct(group_member_opt *g);
void qq_group_search_application_with_struct(group_member_opt *g);
-void qq_group_process_modify_info_reply(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
-void qq_group_process_modify_members_reply(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
+void qq_group_process_modify_info_reply(guint8 *data, gint len, PurpleConnection *gc);
+void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc);
void qq_group_manage_group(PurpleConnection *gc, GHashTable *data);
void qq_group_create_with_name(PurpleConnection *gc, const gchar *name);
void qq_group_activate_group(PurpleConnection *gc, guint32 internal_group_id);
-void qq_group_process_activate_group_reply(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
-void qq_group_process_create_group_reply(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
+void qq_group_process_activate_group_reply(guint8 *data, gint len, PurpleConnection *gc);
+void qq_group_process_create_group_reply(guint8 *data, gint len, PurpleConnection *gc);
#endif
diff --git a/libpurple/protocols/qq/group_search.c b/libpurple/protocols/qq/group_search.c
index fe5789b928..435b353af5 100644
--- a/libpurple/protocols/qq/group_search.c
+++ b/libpurple/protocols/qq/group_search.c
@@ -43,24 +43,18 @@ enum {
/* send packet to search for qq_group */
void qq_send_cmd_group_search_group(PurpleConnection *gc, guint32 external_group_id)
{
- guint8 *raw_data, *cursor, type;
- gint bytes, data_len;
+ guint8 raw_data[16] = {0};
+ gint bytes = 0;
+ guint8 type;
- data_len = 6;
- raw_data = g_newa(guint8, data_len);
- cursor = raw_data;
type = (external_group_id == 0x00000000) ? QQ_GROUP_SEARCH_TYPE_DEMO : QQ_GROUP_SEARCH_TYPE_BY_ID;
bytes = 0;
- bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_SEARCH_GROUP);
- bytes += create_packet_b(raw_data, &cursor, type);
- bytes += create_packet_dw(raw_data, &cursor, external_group_id);
-
- if (bytes != data_len)
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_SEARCH_GROUP));
- else
- qq_send_group_cmd(gc, NULL, raw_data, data_len);
+ bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_SEARCH_GROUP);
+ bytes += qq_put8(raw_data + bytes, type);
+ bytes += qq_put32(raw_data + bytes, external_group_id);
+
+ qq_send_group_cmd(gc, NULL, raw_data, bytes);
}
static void _qq_setup_roomlist(qq_data *qd, qq_group *group)
@@ -89,55 +83,50 @@ static void _qq_setup_roomlist(qq_data *qd, qq_group *group)
}
/* process group cmd reply "search group" */
-void qq_process_group_cmd_search_group(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+void qq_process_group_cmd_search_group(guint8 *data, gint len, PurpleConnection *gc)
{
+ gint bytes;
guint8 search_type;
guint16 unknown;
- gint bytes, pascal_len;
+ qq_group group;
qq_data *qd;
- qq_group *group;
GSList *pending_id;
g_return_if_fail(data != NULL && len > 0);
qd = (qq_data *) gc->proto_data;
- read_packet_b(data, cursor, len, &search_type);
- group = g_newa(qq_group, 1);
+ bytes = 0;
+ bytes += qq_get8(&search_type, data + bytes);
/* now it starts with group_info_entry */
- bytes = 0;
- bytes += read_packet_dw(data, cursor, len, &(group->internal_group_id));
- bytes += read_packet_dw(data, cursor, len, &(group->external_group_id));
- bytes += read_packet_b(data, cursor, len, &(group->group_type));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_dw(data, cursor, len, &(group->creator_uid));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_dw(data, cursor, len, &(group->group_category));
- pascal_len = convert_as_pascal_string(*cursor, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
- bytes += pascal_len;
- *cursor += pascal_len;
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_b(data, cursor, len, &(group->auth_type));
- pascal_len = convert_as_pascal_string(*cursor, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT);
- bytes += pascal_len;
- *cursor += pascal_len;
+ bytes += qq_get32(&(group.internal_group_id), data + bytes);
+ bytes += qq_get32(&(group.external_group_id), data + bytes);
+ bytes += qq_get8(&(group.group_type), data + bytes);
+ bytes += qq_get16(&(unknown), data + bytes);
+ bytes += qq_get16(&(unknown), data + bytes);
+ bytes += qq_get32(&(group.creator_uid), data + bytes);
+ bytes += qq_get16(&(unknown), data + bytes);
+ bytes += qq_get16(&(unknown), data + bytes);
+ bytes += qq_get16(&(unknown), data + bytes);
+ bytes += qq_get32(&(group.group_category), data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &(group.group_name_utf8), QQ_CHARSET_DEFAULT);
+ bytes += qq_get16(&(unknown), data + bytes);
+ bytes += qq_get8(&(group.auth_type), data + bytes);
+ bytes += convert_as_pascal_string(data + bytes, &(group.group_desc_utf8), QQ_CHARSET_DEFAULT);
/* end of one qq_group */
- if(*cursor != (data + len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "group_cmd_search_group: Dangerous error! maybe protocol changed, notify developers!");
- }
+ if(bytes != len) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "group_cmd_search_group: Dangerous error! maybe protocol changed, notify developers!");
+ }
- pending_id = qq_get_pending_id(qd->joining_groups, group->external_group_id);
+ pending_id = qq_get_pending_id(qd->joining_groups, group.external_group_id);
if (pending_id != NULL) {
- qq_set_pending_id(&qd->joining_groups, group->external_group_id, FALSE);
- if (qq_group_find_by_id(gc, group->internal_group_id, QQ_INTERNAL_ID) == NULL)
+ qq_set_pending_id(&qd->joining_groups, group.external_group_id, FALSE);
+ if (qq_group_find_by_id(gc, group.internal_group_id, QQ_INTERNAL_ID) == NULL)
qq_group_create_internal_record(gc,
- group->internal_group_id, group->external_group_id, group->group_name_utf8);
- qq_send_cmd_group_join_group(gc, group);
+ group.internal_group_id, group.external_group_id, group.group_name_utf8);
+ qq_send_cmd_group_join_group(gc, &group);
} else {
- _qq_setup_roomlist(qd, group);
+ _qq_setup_roomlist(qd, &group);
}
}
diff --git a/libpurple/protocols/qq/group_search.h b/libpurple/protocols/qq/group_search.h
index 46b889a2fc..c370a9341d 100644
--- a/libpurple/protocols/qq/group_search.h
+++ b/libpurple/protocols/qq/group_search.h
@@ -29,6 +29,6 @@
#include "connection.h"
void qq_send_cmd_group_search_group(PurpleConnection *gc, guint32 external_group_id);
-void qq_process_group_cmd_search_group(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc);
+void qq_process_group_cmd_search_group(guint8 *data, gint len, PurpleConnection *gc);
#endif
diff --git a/libpurple/protocols/qq/im.c b/libpurple/protocols/qq/im.c
index f63b7f6dbe..b416e1a57a 100644
--- a/libpurple/protocols/qq/im.c
+++ b/libpurple/protocols/qq/im.c
@@ -52,7 +52,7 @@ void _qq_show_packet(const gchar *desc, const guint8 *buf, gint len);
enum
{
- QQ_NORMAL_IM_TEXT = 0x000b,
+ QQ_NORMAL_IM_TEXT = 0x000b,
QQ_NORMAL_IM_FILE_REQUEST_TCP = 0x0001,
QQ_NORMAL_IM_FILE_APPROVE_TCP = 0x0003,
QQ_NORMAL_IM_FILE_REJECT_TCP = 0x0005,
@@ -121,9 +121,9 @@ struct _qq_recv_im_header {
#define DEFAULT_FONT_NAME "\0xcb\0xce\0xcc\0xe5"
guint8 *qq_get_send_im_tail(const gchar *font_color,
- const gchar *font_size,
- const gchar *font_name,
- gboolean is_bold, gboolean is_italic, gboolean is_underline, gint tail_len)
+ const gchar *font_size,
+ const gchar *font_name,
+ gboolean is_bold, gboolean is_italic, gboolean is_underline, gint tail_len)
{
gchar *s1;
unsigned char *rgb;
@@ -141,7 +141,7 @@ guint8 *qq_get_send_im_tail(const gchar *font_color,
send_im_tail = g_new0(guint8, tail_len);
g_strlcpy((gchar *) (send_im_tail + QQ_SEND_IM_AFTER_MSG_HEADER_LEN),
- font_name, tail_len - QQ_SEND_IM_AFTER_MSG_HEADER_LEN);
+ font_name, tail_len - QQ_SEND_IM_AFTER_MSG_HEADER_LEN);
send_im_tail[tail_len - 1] = (guint8) tail_len;
send_im_tail[0] = 0x00;
@@ -189,32 +189,32 @@ guint8 *qq_get_send_im_tail(const gchar *font_color,
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";
- default:
- return "QQ_RECV_IM_UNKNOWN";
+ 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";
+ default:
+ return "QQ_RECV_IM_UNKNOWN";
}
}
@@ -227,22 +227,21 @@ static void _qq_send_packet_recv_im_ack(PurpleConnection *gc, guint16 seq, guint
/* read the common parts of the normal_im,
* returns the bytes read if succeed, or -1 if there is any error */
-static gint _qq_normal_im_common_read(guint8 *data, guint8 **cursor, gint len, qq_recv_normal_im_common *common)
+static gint _qq_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 && common != NULL, -1);
bytes = 0;
/* now push data into common header */
- bytes += read_packet_w(data, cursor, len, &(common->sender_ver));
- bytes += read_packet_dw(data, cursor, len, &(common->sender_uid));
- bytes += read_packet_dw(data, cursor, len, &(common->receiver_uid));
+ bytes += qq_get16(&(common->sender_ver), data + bytes);
+ bytes += qq_get32(&(common->sender_uid), data + bytes);
+ bytes += qq_get32(&(common->receiver_uid), data + bytes);
- common->session_md5 = g_memdup(*cursor, QQ_KEY_LENGTH);
+ common->session_md5 = g_memdup(data + bytes, QQ_KEY_LENGTH);
bytes += QQ_KEY_LENGTH;
- *cursor += QQ_KEY_LENGTH;
- bytes += read_packet_w(data, cursor, len, &(common->normal_im_type));
+ bytes += qq_get16(&(common->normal_im_type), data + bytes);
if (bytes != 28) { /* read common place fail */
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Expect 28 bytes, read %d bytes\n", bytes);
@@ -253,8 +252,7 @@ static gint _qq_normal_im_common_read(guint8 *data, guint8 **cursor, gint len, q
}
/* process received normal text IM */
-static void _qq_process_recv_normal_im_text
- (guint8 *data, guint8 **cursor, gint len, qq_recv_normal_im_common *common, PurpleConnection *gc)
+static void _qq_process_recv_normal_im_text(guint8 *data, gint len, qq_recv_normal_im_common *common, PurpleConnection *gc)
{
guint16 purple_msg_type;
gchar *name;
@@ -262,50 +260,54 @@ static void _qq_process_recv_normal_im_text
gchar *msg_utf8_encoded;
qq_data *qd;
qq_recv_normal_im_text *im_text;
+ gint bytes = 0;
g_return_if_fail(common != NULL);
qd = (qq_data *) gc->proto_data;
/* now it is QQ_NORMAL_IM_TEXT */
- if (*cursor >= (data + len - 1)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received normal IM text is empty\n");
- return;
- } else
- im_text = g_newa(qq_recv_normal_im_text, 1);
+ /*
+ if (*cursor >= (data + len - 1)) {
+ purple_debug(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 */
- read_packet_w(data, cursor, len, &(im_text->msg_seq));
- read_packet_dw(data, cursor, len, &(im_text->send_time));
- read_packet_w(data, cursor, len, &(im_text->sender_icon));
- read_packet_data(data, cursor, len, (guint8 *) & (im_text->unknown2), 3);
- read_packet_b(data, cursor, len, &(im_text->is_there_font_attr));
+ 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();
+ * fragmentSequence = buf.get() & 255;
+ * messageId = buf.getChar();
*/
- read_packet_data(data, cursor, len, (guint8 *) & (im_text->unknown3), 4);
- read_packet_b(data, cursor, len, &(im_text->msg_type));
+ 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 **) cursor, data + len - *cursor);
+ 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 **) cursor);
- *cursor += strlen(im_text->msg) + 1;
- im_text->font_attr_len = data + len - *cursor;
- im_text->font_attr = g_memdup(*cursor, im_text->font_attr_len);
+ 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 **) cursor, data + len - *cursor);
+ im_text->msg = g_strndup((gchar *)(data + bytes), len - bytes);
} /* if im_text->msg_type */
- _qq_show_packet("QQ_MESG recv", data, *cursor - data);
+ /* XXX _qq_show_packet here should not be used here */
+ /* _qq_show_packet("QQ_MESG recv", data, *cursor - data); */
name = uid_to_purple_name(common->sender_uid);
if (purple_find_buddy(gc->account, name) == NULL)
@@ -315,9 +317,9 @@ static void _qq_process_recv_normal_im_text
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_to_utf8(msg_with_purple_smiley, QQ_CHARSET_DEFAULT);
+ 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);
/* send encoded to purple, note that we use im_text->send_time,
* not the time we receive the message
@@ -333,81 +335,72 @@ static void _qq_process_recv_normal_im_text
}
/* it is a normal IM, maybe text or video request */
-static void _qq_process_recv_normal_im(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc)
+static void _qq_process_recv_normal_im(guint8 *data, gint len, PurpleConnection *gc)
{
- gint bytes;
+ gint bytes = 0;
qq_recv_normal_im_common *common;
qq_recv_normal_im_unprocessed *im_unprocessed;
gchar *hex_dump;
g_return_if_fail (data != NULL && len != 0);
- if (*cursor >= (data + len - 1)) {
- purple_debug (PURPLE_DEBUG_WARNING, "QQ",
- "Received normal IM is empty\n");
- return;
- }
- else
- common = g_newa (qq_recv_normal_im_common, 1);
+ common = g_newa (qq_recv_normal_im_common, 1);
- bytes = _qq_normal_im_common_read (data, cursor, len, common);
+ bytes = _qq_normal_im_common_read(data, len, common);
if (bytes < 0) {
purple_debug (PURPLE_DEBUG_ERROR, "QQ",
- "Fail read the common part of normal IM\n");
+ "Fail read the common part of normal IM\n");
return;
}
switch (common->normal_im_type) {
- case QQ_NORMAL_IM_TEXT:
- purple_debug (PURPLE_DEBUG_INFO,
- "QQ",
- "Normal IM, text type:\n [%d] => [%d], src: %s\n",
- common->sender_uid, common->receiver_uid,
- qq_get_source_str (common->sender_ver));
- _qq_process_recv_normal_im_text (data, cursor, len, common,
- gc);
- break;
- case QQ_NORMAL_IM_FILE_REJECT_UDP:
- qq_process_recv_file_reject (data, cursor, len,
- common->sender_uid, gc);
- break;
- case QQ_NORMAL_IM_FILE_APPROVE_UDP:
- qq_process_recv_file_accept (data, cursor, len,
- common->sender_uid, gc);
- break;
- case QQ_NORMAL_IM_FILE_REQUEST_UDP:
- qq_process_recv_file_request (data, cursor, len,
- common->sender_uid, gc);
- break;
- case QQ_NORMAL_IM_FILE_CANCEL:
- qq_process_recv_file_cancel (data, cursor, len,
- common->sender_uid, gc);
- break;
- case QQ_NORMAL_IM_FILE_NOTIFY:
- qq_process_recv_file_notify (data, cursor, len,
- common->sender_uid, gc);
- break;
- default:
- im_unprocessed = g_newa (qq_recv_normal_im_unprocessed, 1);
- im_unprocessed->common = common;
- im_unprocessed->unknown = *cursor;
- im_unprocessed->length = data + len - *cursor;
- /* a simple process here, maybe more later */
- purple_debug (PURPLE_DEBUG_WARNING, "QQ",
- "Normal IM, unprocessed type [0x%04x]\n",
- common->normal_im_type);
- hex_dump = hex_dump_to_str(im_unprocessed->unknown, im_unprocessed->length);
- purple_debug (PURPLE_DEBUG_WARNING, "QQ", "Dump unknown part.\n%s", hex_dump);
- g_free(hex_dump);
- g_free (common->session_md5);
- return;
+ case QQ_NORMAL_IM_TEXT:
+ purple_debug (PURPLE_DEBUG_INFO, "QQ",
+ "Normal IM, text type:\n [%d] => [%d], src: %s\n",
+ common->sender_uid, common->receiver_uid,
+ qq_get_source_str (common->sender_ver));
+ if (bytes >= len - 1) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received normal IM text is empty\n");
+ return;
+ }
+ _qq_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, common->sender_uid, gc);
+ break;
+ case QQ_NORMAL_IM_FILE_APPROVE_UDP:
+ 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, common->sender_uid, gc);
+ break;
+ case QQ_NORMAL_IM_FILE_CANCEL:
+ 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, common->sender_uid, gc);
+ 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 */
+ purple_debug (PURPLE_DEBUG_WARNING, "QQ",
+ "Normal IM, unprocessed type [0x%04x]\n",
+ common->normal_im_type);
+ hex_dump = hex_dump_to_str(im_unprocessed->unknown, im_unprocessed->length);
+ purple_debug (PURPLE_DEBUG_WARNING, "QQ", "Dump unknown part.\n%s", hex_dump);
+ g_free(hex_dump);
+ g_free (common->session_md5);
+ return;
}
g_free (common->session_md5);
}
/* process im from system administrator */
-static void _qq_process_recv_sys_im(guint8 *data, guint8 **cursor, gint data_len, PurpleConnection *gc)
+static void _qq_process_recv_sys_im(guint8 *data, gint data_len, PurpleConnection *gc)
{
gint len;
guint8 reply;
@@ -415,14 +408,9 @@ static void _qq_process_recv_sys_im(guint8 *data, guint8 **cursor, gint data_len
g_return_if_fail(data != NULL && data_len != 0);
- if (*cursor >= (data + data_len - 1)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received sys IM is empty\n");
- return;
- }
+ len = data_len;
- len = data + data_len - *cursor;
-
- if (NULL == (segments = split_data(*cursor, len, "\x2f", 2)))
+ if (NULL == (segments = split_data(data, len, "\x2f", 2)))
return;
reply = strtol(segments[0], NULL, 10);
@@ -436,7 +424,7 @@ static void _qq_process_recv_sys_im(guint8 *data, guint8 **cursor, gint data_len
void qq_send_packet_im(PurpleConnection *gc, guint32 to_uid, gchar *msg, gint type)
{
qq_data *qd;
- guint8 *cursor, *raw_data, *send_im_tail;
+ guint8 *raw_data, *send_im_tail;
guint16 client_tag, normal_im_type;
gint msg_len, raw_len, font_name_len, tail_len, bytes;
time_t now;
@@ -500,52 +488,51 @@ void qq_send_packet_im(PurpleConnection *gc, guint32 to_uid, gchar *msg, gint ty
raw_len = QQ_SEND_IM_BEFORE_MSG_LEN + msg_len + tail_len;
raw_data = g_newa(guint8, raw_len);
- cursor = raw_data;
bytes = 0;
/* 000-003: receiver uid */
- bytes += create_packet_dw(raw_data, &cursor, qd->uid);
+ bytes += qq_put32(raw_data + bytes, qd->uid);
/* 004-007: sender uid */
- bytes += create_packet_dw(raw_data, &cursor, to_uid);
+ bytes += qq_put32(raw_data + bytes, to_uid);
/* 008-009: sender client version */
- bytes += create_packet_w(raw_data, &cursor, client_tag);
+ bytes += qq_put16(raw_data + bytes, client_tag);
/* 010-013: receiver uid */
- bytes += create_packet_dw(raw_data, &cursor, qd->uid);
+ bytes += qq_put32(raw_data + bytes, qd->uid);
/* 014-017: sender uid */
- bytes += create_packet_dw(raw_data, &cursor, to_uid);
+ bytes += qq_put32(raw_data + bytes, to_uid);
/* 018-033: md5 of (uid+session_key) */
- bytes += create_packet_data(raw_data, &cursor, qd->session_md5, 16);
+ bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16);
/* 034-035: message type */
- bytes += create_packet_w(raw_data, &cursor, normal_im_type);
+ bytes += qq_put16(raw_data + bytes, normal_im_type);
/* 036-037: sequence number */
- bytes += create_packet_w(raw_data, &cursor, qd->send_seq);
+ bytes += qq_put16(raw_data + bytes, qd->send_seq);
/* 038-041: send time */
- bytes += create_packet_dw(raw_data, &cursor, (guint32) now);
+ bytes += qq_put32(raw_data + bytes, (guint32) now);
/* 042-043: sender icon */
- bytes += create_packet_w(raw_data, &cursor, qd->my_icon);
+ bytes += qq_put16(raw_data + bytes, qd->my_icon);
/* 044-046: always 0x00 */
- bytes += create_packet_w(raw_data, &cursor, 0x0000);
- bytes += create_packet_b(raw_data, &cursor, 0x00);
+ bytes += qq_put16(raw_data + bytes, 0x0000);
+ bytes += qq_put8(raw_data + bytes, 0x00);
/* 047-047: we use font attr */
- bytes += create_packet_b(raw_data, &cursor, 0x01);
+ bytes += qq_put8(raw_data + bytes, 0x01);
/* 048-051: always 0x00 */
- bytes += create_packet_dw(raw_data, &cursor, 0x00000000);
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
/* 052-052: text message type (normal/auto-reply) */
- bytes += create_packet_b(raw_data, &cursor, type);
+ bytes += qq_put8(raw_data + bytes, type);
/* 053- : msg ends with 0x00 */
- bytes += create_packet_data(raw_data, &cursor, (guint8 *) msg_filtered, msg_len);
+ bytes += qq_putdata(raw_data + bytes, (guint8 *) msg_filtered, msg_len);
send_im_tail = qq_get_send_im_tail(font_color, font_size, font_name, is_bold,
- is_italic, is_underline, tail_len);
- _qq_show_packet("QQ_MESG debug", send_im_tail, tail_len);
- bytes += create_packet_data(raw_data, &cursor, send_im_tail, tail_len);
+ is_italic, is_underline, tail_len);
+ _qq_show_packet("QQ_send_im_tail debug", send_im_tail, tail_len);
+ bytes += qq_putdata(raw_data + bytes, send_im_tail, tail_len);
- _qq_show_packet("QQ_MESG raw", raw_data, cursor - raw_data);
+ _qq_show_packet("QQ_raw_data debug", raw_data, bytes);
if (bytes == raw_len) /* create packet OK */
- qq_send_cmd(gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, cursor - raw_data);
+ qq_send_cmd(gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
else
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail creating send_im packet, expect %d bytes, build %d bytes\n", raw_len, bytes);
+ "Fail creating send_im packet, expect %d bytes, build %d bytes\n", raw_len, bytes);
if (font_color)
g_free(font_color);
@@ -560,7 +547,8 @@ void qq_process_send_im_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
{
qq_data *qd;
gint len;
- guint8 *data, *cursor, reply;
+ guint8 *data, reply;
+ gint bytes = 0;
g_return_if_fail(buf != NULL && buf_len != 0);
@@ -569,8 +557,7 @@ void qq_process_send_im_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
data = g_newa(guint8, len);
if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- cursor = data;
- read_packet_b(data, &cursor, len, &reply);
+ bytes += qq_get8(&reply, data + bytes);
if (reply != QQ_SEND_IM_REPLY_OK) {
purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Send IM fail\n");
purple_notify_error(gc, _("Error"), _("Failed to send IM."), NULL);
@@ -588,7 +575,7 @@ void qq_process_recv_im(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection
{
qq_data *qd;
gint len, bytes;
- guint8 *data, *cursor;
+ guint8 *data;
qq_recv_im_header *im_header;
g_return_if_fail(buf != NULL && buf_len != 0);
@@ -597,98 +584,107 @@ void qq_process_recv_im(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection
len = buf_len;
data = g_newa(guint8, len);
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- if (len < 16) { /* we need to ack with the first 16 bytes */
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "IM is too short\n");
- return;
- } else
- _qq_send_packet_recv_im_ack(gc, seq, data);
-
- cursor = data;
- bytes = 0;
- im_header = g_newa(qq_recv_im_header, 1);
- bytes += read_packet_dw(data, &cursor, len, &(im_header->sender_uid));
- bytes += read_packet_dw(data, &cursor, len, &(im_header->receiver_uid));
- bytes += read_packet_dw(data, &cursor, len, &(im_header->server_im_seq));
- /* if the message is delivered via server, it is server IP/port */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) & (im_header->sender_ip), 4);
- bytes += read_packet_w(data, &cursor, len, &(im_header->sender_port));
- bytes += read_packet_w(data, &cursor, len, &(im_header->im_type));
-
- if (bytes != 20) { /* length of im_header */
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail read recv IM header, expect 20 bytes, read %d bytes\n", bytes);
- return;
- }
+ if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt rev im\n");
+ }
- if (im_header->receiver_uid != qd->uid) { /* should not happen */
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "IM to [%d], NOT me\n", im_header->receiver_uid);
- return;
- }
+ if (len < 16) { /* we need to ack with the first 16 bytes */
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "IM is too short\n");
+ return;
+ } else {
+ _qq_send_packet_recv_im_ack(gc, seq, data);
+ }
- switch (im_header->im_type) {
+ /* check len first */
+ if (len < 20) { /* length of im_header */
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Fail read recv IM header, len should longer than 20 bytes, read %d bytes\n", 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_getdata((guint8 *) & (im_header->sender_ip), 4, 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(PURPLE_DEBUG_ERROR, "QQ", "IM to [%d], NOT me\n", im_header->receiver_uid);
+ return;
+ }
+
+ /* check bytes */
+ if (bytes >= len - 1) {
+ purple_debug (PURPLE_DEBUG_WARNING, "QQ", "Received IM is empty\n");
+ return;
+ }
+
+ switch (im_header->im_type) {
case QQ_RECV_IM_TO_BUDDY:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "IM from buddy [%d], I am in his/her buddy list\n", im_header->sender_uid);
- _qq_process_recv_normal_im(data, &cursor, len, gc);
+ "IM from buddy [%d], I am in his/her buddy list\n", im_header->sender_uid);
+ _qq_process_recv_normal_im(data + bytes, len - bytes, gc); /* position and rest length */
break;
case QQ_RECV_IM_TO_UNKNOWN:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "IM from buddy [%d], I am a stranger to him/her\n", im_header->sender_uid);
- _qq_process_recv_normal_im(data, &cursor, len, gc);
+ "IM from buddy [%d], I am a stranger to him/her\n", im_header->sender_uid);
+ _qq_process_recv_normal_im(data + bytes, 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(PURPLE_DEBUG_INFO, "QQ", "IM from group, internal_id [%d]\n", im_header->sender_uid);
/* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im(data, &cursor, len, im_header->sender_uid, gc, im_header->im_type);
+ qq_process_recv_group_im(data + bytes, len - bytes, im_header->sender_uid, gc, im_header->im_type);
break;
case QQ_RECV_IM_ADD_TO_QUN:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "IM from group, added by group internal_id [%d]\n", im_header->sender_uid);
+ "IM from group, added by group internal_id [%d]\n", im_header->sender_uid);
/* sender_uid is in fact internal_group_id
* we need this to create a dummy group and add to blist */
- qq_process_recv_group_im_been_added(data, &cursor, len, im_header->sender_uid, gc);
+ qq_process_recv_group_im_been_added(data + bytes, len - bytes, im_header->sender_uid, gc);
break;
case QQ_RECV_IM_DEL_FROM_QUN:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "IM from group, removed by group internal_ID [%d]\n", im_header->sender_uid);
+ "IM from group, removed by group internal_ID [%d]\n", im_header->sender_uid);
/* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im_been_removed(data, &cursor, len, im_header->sender_uid, gc);
+ qq_process_recv_group_im_been_removed(data + bytes, len - bytes, im_header->sender_uid, gc);
break;
case QQ_RECV_IM_APPLY_ADD_TO_QUN:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "IM from group, apply to join group internal_ID [%d]\n", im_header->sender_uid);
+ "IM from group, apply to join group internal_ID [%d]\n", im_header->sender_uid);
/* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im_apply_join(data, &cursor, len, im_header->sender_uid, gc);
+ qq_process_recv_group_im_apply_join(data + bytes, len - bytes, im_header->sender_uid, gc);
break;
case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "IM for group system info, approved by group internal_id [%d]\n",
- im_header->sender_uid);
+ "IM for group system info, approved by group internal_id [%d]\n",
+ im_header->sender_uid);
/* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im_been_approved(data, &cursor, len, im_header->sender_uid, gc);
+ qq_process_recv_group_im_been_approved(data + bytes, len - bytes, im_header->sender_uid, gc);
break;
case QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "IM for group system info, rejected by group internal_id [%d]\n",
- im_header->sender_uid);
+ "IM for group system info, rejected by group internal_id [%d]\n",
+ im_header->sender_uid);
/* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im_been_rejected(data, &cursor, len, im_header->sender_uid, gc);
+ qq_process_recv_group_im_been_rejected(data + bytes, len - bytes, im_header->sender_uid, gc);
break;
case QQ_RECV_IM_SYS_NOTIFICATION:
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "IM from [%d], should be a system administrator\n", im_header->sender_uid);
- _qq_process_recv_sys_im(data, &cursor, len, gc);
+ "IM from [%d], should be a system administrator\n", im_header->sender_uid);
+ _qq_process_recv_sys_im(data + bytes, len - bytes, gc);
break;
default:
purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- "IM from [%d], [0x%02x] %s is not processed\n",
- im_header->sender_uid,
- im_header->im_type, qq_get_recv_im_type_str(im_header->im_type));
- }
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt rev im\n");
+ "IM from [%d], [0x%02x] %s is not processed\n",
+ im_header->sender_uid,
+ im_header->im_type, qq_get_recv_im_type_str(im_header->im_type));
}
}
+
diff --git a/libpurple/protocols/qq/keep_alive.c b/libpurple/protocols/qq/keep_alive.c
index 02c5f8ec95..001098102a 100644
--- a/libpurple/protocols/qq/keep_alive.c
+++ b/libpurple/protocols/qq/keep_alive.c
@@ -49,16 +49,15 @@
void qq_send_packet_keep_alive(PurpleConnection *gc)
{
qq_data *qd;
- guint8 *raw_data, *cursor;
+ guint8 raw_data[16] = {0};
+ gint bytes= 0;
qd = (qq_data *) gc->proto_data;
- raw_data = g_newa(guint8, 4);
- cursor = raw_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 */
- create_packet_dw(raw_data, &cursor, qd->uid);
+ bytes += qq_put32(raw_data + bytes, qd->uid);
qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, TRUE, 0, TRUE, raw_data, 4);
}
diff --git a/libpurple/protocols/qq/login_logout.c b/libpurple/protocols/qq/login_logout.c
index 3d8bfc7389..f7c2454dfa 100644
--- a/libpurple/protocols/qq/login_logout.c
+++ b/libpurple/protocols/qq/login_logout.c
@@ -70,6 +70,7 @@ static const guint8 login_23_51[29] = {
*/
/* for QQ 2005? copy from lumaqq */
+// Fixme: change to guint8
static const gint8 login_23_51[29] = {
0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, -122,
@@ -139,8 +140,8 @@ struct _qq_login_reply_redirect {
};
extern gint /* defined in send_core.c */
- _create_packet_head_seq(guint8 *buf,
- guint8 **cursor, PurpleConnection *gc, guint16 cmd, gboolean is_auto_seq, guint16 *seq);
+ _create_packet_head_seq(guint8 *buf, PurpleConnection *gc,
+ guint16 cmd, gboolean is_auto_seq, guint16 *seq);
extern gint /* defined in send_core.c */
_qq_send_packet(PurpleConnection *gc, guint8 *buf, gint len, guint16 cmd);
@@ -155,57 +156,54 @@ static guint8 *_gen_login_key(void)
static gint _qq_process_login_ok(PurpleConnection *gc, guint8 *data, gint len)
{
gint bytes;
- guint8 *cursor;
qq_data *qd;
qq_login_reply_ok_packet lrop;
qd = (qq_data *) gc->proto_data;
- cursor = data;
bytes = 0;
/* 000-000: reply code */
- bytes += read_packet_b(data, &cursor, len, &lrop.result);
+ bytes += qq_get8(&lrop.result, data + bytes);
/* 001-016: session key */
- lrop.session_key = g_memdup(cursor, QQ_KEY_LENGTH);
- cursor += QQ_KEY_LENGTH;
+ lrop.session_key = g_memdup(data + bytes, QQ_KEY_LENGTH);
bytes += QQ_KEY_LENGTH;
purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get session_key done\n");
/* 017-020: login uid */
- bytes += read_packet_dw(data, &cursor, len, &lrop.uid);
+ bytes += qq_get32(&lrop.uid, data + bytes);
/* 021-024: server detected user public IP */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.client_ip, 4);
+ bytes += qq_getdata((guint8 *) &lrop.client_ip, 4, data + bytes);
/* 025-026: server detected user port */
- bytes += read_packet_w(data, &cursor, len, &lrop.client_port);
+ bytes += qq_get16(&lrop.client_port, data + bytes);
/* 027-030: server detected itself ip 127.0.0.1 ? */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.server_ip, 4);
+ bytes += qq_getdata((guint8 *) &lrop.server_ip, 4, data + bytes);
/* 031-032: server listening port */
- bytes += read_packet_w(data, &cursor, len, &lrop.server_port);
+ bytes += qq_get16(&lrop.server_port, data + bytes);
/* 033-036: login time for current session */
- bytes += read_packet_time(data, &cursor, len, &lrop.login_time);
+ bytes += qq_getime(&lrop.login_time, data + bytes);
/* 037-062: 26 bytes, unknown */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown1, 26);
+ bytes += qq_getdata((guint8 *) &lrop.unknown1, 26, data + bytes);
/* 063-066: unknown server1 ip address */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown_server1_ip, 4);
+ bytes += qq_getdata((guint8 *) &lrop.unknown_server1_ip, 4, data + bytes);
/* 067-068: unknown server1 port */
- bytes += read_packet_w(data, &cursor, len, &lrop.unknown_server1_port);
+ bytes += qq_get16(&lrop.unknown_server1_port, data + bytes);
/* 069-072: unknown server2 ip address */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown_server2_ip, 4);
+ bytes += qq_getdata((guint8 *) &lrop.unknown_server2_ip, 4, data + bytes);
/* 073-074: unknown server2 port */
- bytes += read_packet_w(data, &cursor, len, &lrop.unknown_server2_port);
+ bytes += qq_get16(&lrop.unknown_server2_port, data + bytes);
/* 075-076: 2 bytes unknown */
- bytes += read_packet_w(data, &cursor, len, &lrop.unknown2);
+ bytes += qq_get16(&lrop.unknown2, data + bytes);
/* 077-078: 2 bytes unknown */
- bytes += read_packet_w(data, &cursor, len, &lrop.unknown3);
+ bytes += qq_get16(&lrop.unknown3, data + bytes);
/* 079-110: 32 bytes unknown */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown4, 32);
+ bytes += qq_getdata((guint8 *) &lrop.unknown4, 32, data + bytes);
/* 111-122: 12 bytes unknown */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown5, 12);
+ bytes += qq_getdata((guint8 *) &lrop.unknown5, 12, data + bytes);
/* 123-126: login IP of last session */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.last_client_ip, 4);
+ bytes += qq_getdata((guint8 *) &lrop.last_client_ip, 4, data + bytes);
/* 127-130: login time of last session */
- bytes += read_packet_time(data, &cursor, len, &lrop.last_login_time);
+ bytes += qq_getime(&lrop.last_login_time, data + bytes);
/* 131-138: 8 bytes unknown */
- bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown6, 8);
+ bytes += qq_getdata((guint8 *) &lrop.unknown6, 8, data + bytes);
if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */
purple_debug(PURPLE_DEBUG_WARNING, "QQ",
@@ -247,22 +245,20 @@ static gint _qq_process_login_ok(PurpleConnection *gc, guint8 *data, gint len)
static gint _qq_process_login_redirect(PurpleConnection *gc, guint8 *data, gint len)
{
gint bytes, ret;
- guint8 *cursor;
gchar *new_server_str;
qq_data *qd;
qq_login_reply_redirect_packet lrrp;
qd = (qq_data *) gc->proto_data;
- cursor = data;
bytes = 0;
/* 000-000: reply code */
- bytes += read_packet_b(data, &cursor, len, &lrrp.result);
+ bytes += qq_get8(&lrrp.result, data + bytes);
/* 001-004: login uid */
- bytes += read_packet_dw(data, &cursor, len, &lrrp.uid);
+ bytes += qq_get32(&lrrp.uid, data + bytes);
/* 005-008: redirected new server IP */
- bytes += read_packet_data(data, &cursor, len, lrrp.new_server_ip, 4);
+ bytes += qq_getdata(lrrp.new_server_ip, 4, data + bytes);
/* 009-010: redirected new server port */
- bytes += read_packet_w(data, &cursor, len, &lrrp.new_server_port);
+ bytes += qq_get16(&lrrp.new_server_port, data + bytes);
if (bytes != QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
@@ -299,83 +295,91 @@ static gint _qq_process_login_wrong_pwd(PurpleConnection *gc, guint8 *data, gint
void qq_send_packet_request_login_token(PurpleConnection *gc)
{
qq_data *qd;
- guint8 *buf, *cursor;
+ guint8 *buf;
guint16 seq_ret;
- gint bytes;
+ gint bytes, bytes_sent;
qd = (qq_data *) gc->proto_data;
buf = g_newa(guint8, MAX_PACKET_SIZE);
- cursor = buf;
bytes = 0;
- bytes += _create_packet_head_seq(buf, &cursor, gc, QQ_CMD_REQUEST_LOGIN_TOKEN, TRUE, &seq_ret);
- bytes += create_packet_dw(buf, &cursor, qd->uid);
- bytes += create_packet_b(buf, &cursor, 0);
- bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAIL);
-
- if (bytes == (cursor - buf)) /* packet creation OK */
- _qq_send_packet(gc, buf, bytes, QQ_CMD_REQUEST_LOGIN_TOKEN);
- else
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "=BEGIN= send_packet_request_login, bytes: %d\n", bytes);
+ bytes += _create_packet_head_seq(buf + bytes, gc, QQ_CMD_REQUEST_LOGIN_TOKEN, TRUE, &seq_ret);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "send_packet_request_login, bytes: %d\n", bytes);
+ if (bytes <= 0) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail create request login token packet\n");
+ return;
+ }
+ bytes += qq_put32(buf + bytes, qd->uid);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "send_packet_request_login, bytes: %d\n", bytes);
+ bytes += qq_put8(buf + bytes, 0);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "send_packet_request_login, bytes: %d\n", bytes);
+ bytes += qq_put8(buf + bytes, QQ_PACKET_TAIL);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "send_packet_request_login, bytes: %d\n", bytes);
+
+ /* debugging info, s3e, 20070628 */
+ bytes_sent = _qq_send_packet(gc, buf, bytes, QQ_CMD_REQUEST_LOGIN_TOKEN);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "world<==me %s, %d bytes\n",
+ qq_get_cmd_desc(QQ_CMD_REQUEST_LOGIN_TOKEN), bytes_sent);
+
}
/* send login packet to QQ server */
static void qq_send_packet_login(PurpleConnection *gc, guint8 token_length, guint8 *token)
{
qq_data *qd;
- guint8 *buf, *cursor, *raw_data, *encrypted_data;
+ guint8 *buf, *raw_data, *encrypted_data;
guint16 seq_ret;
gint encrypted_len, bytes;
- gint pos;
qd = (qq_data *) gc->proto_data;
buf = g_newa(guint8, MAX_PACKET_SIZE);
raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH);
+ memset(raw_data, 0, QQ_LOGIN_DATA_LENGTH);
+
encrypted_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */
qd->inikey = _gen_login_key();
+ bytes = 0;
/* now generate the encrypted data
* 000-015 use pwkey as key to encrypt empty string */
- qq_encrypt((guint8 *) "", 0, qd->pwkey, raw_data, &encrypted_len);
+ qq_encrypt((guint8 *) "", 0, qd->pwkey, raw_data + bytes, &encrypted_len);
+ bytes += 16;
/* 016-016 */
- raw_data[16] = 0x00;
+ bytes += qq_put8(raw_data + bytes, 0x00);
/* 017-020, used to be IP, now zero */
- *((guint32 *) (raw_data + 17)) = 0x00000000;
+ bytes += qq_put32(raw_data + bytes, 0x00000000);
/* 021-022, used to be port, now zero */
- *((guint16 *) (raw_data + 21)) = 0x0000;
+ bytes += qq_put16(raw_data + bytes, 0x0000);
/* 023-051, fixed value, unknown */
- g_memmove(raw_data + 23, login_23_51, 29);
+ bytes += qq_putdata(raw_data + bytes, login_23_51, 29);
/* 052-052, login mode */
- raw_data[52] = qd->login_mode;
+ bytes += qq_put8(raw_data + bytes, qd->login_mode);
/* 053-068, fixed value, maybe related to per machine */
- g_memmove(raw_data + 53, login_53_68, 16);
+ bytes += qq_putdata(raw_data + bytes, login_53_68, 16);
/* 069, login token length */
- raw_data[69] = token_length;
- pos = 70;
+ bytes += qq_put8(raw_data + bytes, token_length);
/* 070-093, login token, normally 24 bytes */
- g_memmove(raw_data + pos, token, token_length);
- pos += token_length;
+ bytes += qq_putdata(raw_data + bytes, token, token_length);
/* 100 bytes unknown */
- g_memmove(raw_data + pos, login_100_bytes, 100);
- pos += 100;
+ bytes += qq_putdata(raw_data + bytes, login_100_bytes, 100);
/* all zero left */
- memset(raw_data+pos, 0, QQ_LOGIN_DATA_LENGTH - pos);
qq_encrypt(raw_data, QQ_LOGIN_DATA_LENGTH, qd->inikey, encrypted_data, &encrypted_len);
- cursor = buf;
bytes = 0;
- bytes += _create_packet_head_seq(buf, &cursor, gc, QQ_CMD_LOGIN, TRUE, &seq_ret);
- bytes += create_packet_dw(buf, &cursor, qd->uid);
- bytes += create_packet_data(buf, &cursor, qd->inikey, QQ_KEY_LENGTH);
- bytes += create_packet_data(buf, &cursor, encrypted_data, encrypted_len);
- bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAIL);
-
- if (bytes == (cursor - buf)) /* packet creation OK */
- _qq_send_packet(gc, buf, bytes, QQ_CMD_LOGIN);
- else
+ bytes += _create_packet_head_seq(buf, gc, QQ_CMD_LOGIN, TRUE, &seq_ret);
+ if (bytes <= 0) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail create login packet\n");
+ return;
+ }
+ bytes += qq_put32(buf + bytes, qd->uid);
+ bytes += qq_putdata(buf + bytes, qd->inikey, QQ_KEY_LENGTH);
+ bytes += qq_putdata(buf + bytes, encrypted_data, encrypted_len);
+ bytes += qq_put8(buf + bytes, QQ_PACKET_TAIL);
+
+ _qq_send_packet(gc, buf, bytes, QQ_CMD_LOGIN);
}
void qq_process_request_login_token_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
diff --git a/libpurple/protocols/qq/packet_parse.c b/libpurple/protocols/qq/packet_parse.c
index a26192731b..b2e2b371f0 100644
--- a/libpurple/protocols/qq/packet_parse.c
+++ b/libpurple/protocols/qq/packet_parse.c
@@ -25,63 +25,184 @@
#include <string.h>
#include "packet_parse.h"
+#include "debug.h"
+
+
+/*------------------------------------------------PUT------------------------------------------------*/
+
+/* note:
+ * 1, in these functions, 'b' stands for byte, 'w' stands for word, 'dw' stands for double word.
+ * 2, we use '*cursor' and 'buf' as two addresses to calculate the length.
+ * 3, fixed obscure bugs, thanks ccpaging.
+ * 4, change '0' to '1', if want to get more info about the packet parsing.
+ * by s3e, 20070717 */
+
+#if 0
+#define PARSER_DEBUG
+#endif
/* read one byte from buf,
* return the number of bytes read if succeeds, otherwise return -1 */
+/*
gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b)
{
+ guint8 *b_ship = NULL;
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_b] buf addr: 0x%x\n", (gpointer)buf);
+#endif
if (*cursor <= buf + buflen - sizeof(*b)) {
- *b = **(guint8 **) cursor;
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_b] *cursor addr: 0x%x, buf expected addr: 0x%x\n",
+ (gpointer)*cursor, (gpointer)(buf + buflen - sizeof(*b)));
+#endif
+ b_ship = g_new0(guint8, sizeof(guint8));
+ g_memmove(b_ship, *cursor, sizeof(guint8));
+ *b = *b_ship;
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_b] data: 0x%02x->0x%02x\n",
+ **(guint8 **)cursor, *b);
+#endif
*cursor += sizeof(*b);
+ // free
+ g_free(b_ship);
+ b_ship = NULL;
+
return sizeof(*b);
} else {
return -1;
}
}
+*/
+gint qq_get8(guint8 *b, guint8 *buf)
+{
+ guint8 b_dest;
+ memcpy(&b_dest, buf, sizeof(b_dest));
+ *b = b_dest;
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get8] buf %d\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get8] b_dest 0x%2x, *b 0x%02x\n", b_dest, *b);
+ return sizeof(b_dest);
+}
+
/* read two bytes as "guint16" from buf,
* return the number of bytes read if succeeds, otherwise return -1 */
+/*
gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w)
{
+ guint8 *w_ship = NULL;
+ guint16 w_dest;
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_w] buf addr: 0x%x\n", (gpointer)buf);
+#endif
if (*cursor <= buf + buflen - sizeof(*w)) {
- *w = g_ntohs(**(guint16 **) cursor);
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_w] *cursor addr: 0x%x, buf expected addr: 0x%x\n",
+ (gpointer)*cursor, (gpointer)(buf + buflen - sizeof(*w)));
+#endif
+ // type should match memory buffer
+ w_ship = (guint8 *)g_new0(guint16, 1);
+ // copy bytes into temporary buffer
+ g_memmove(w_ship, *cursor, sizeof(guint16));
+ // type convert and assign value
+ w_dest = *(guint16 *)w_ship;
+ // ntohs
+ *w = g_ntohs(w_dest);
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_w] data: 0x%04x->0x%04x-g_ntohs->0x%04x\n",
+ **(guint16 **)cursor, w_dest, *w);
+#endif
+ // *cursor goes on
*cursor += sizeof(*w);
+
+ // free mem
+ g_free(w_ship);
+ w_ship = NULL;
+
return sizeof(*w);
} else {
return -1;
}
}
+*/
+gint qq_get16(guint16 *w, guint8 *buf)
+{
+ guint16 w_dest;
+ memcpy(&w_dest, buf, sizeof(w_dest));
+ *w = g_ntohs(w_dest);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get16] buf %d\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get16] w_dest 0x%04x, *w 0x%04x\n", w_dest, *w);
+ return sizeof(w_dest);
+}
+
/* read four bytes as "guint32" from buf,
* return the number of bytes read if succeeds, otherwise return -1 */
+/*
gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw)
{
+ guint8 *dw_ship = NULL;
+ guint32 dw_dest;
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_dw] buf addr: 0x%x\n", (gpointer)buf);
+#endif
if (*cursor <= buf + buflen - sizeof(*dw)) {
- *dw = g_ntohl(**(guint32 **) cursor);
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_dw] *cursor addr: 0x%x, buf expected addr: 0x%x\n",
+ (gpointer)*cursor, (gpointer)(buf + buflen - sizeof(*dw)));
+#endif
+ dw_ship = (guint8 *)g_new0(guint32, 1);
+ g_memmove(dw_ship, *cursor, sizeof(guint32));
+ dw_dest = *(guint32 *)dw_ship;
+ *dw = g_ntohl(dw_dest);
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_dw] data: 0x%08x->0x%08x-g_ntohl->0x%08x\n",
+ **(guint32 **)cursor, dw_dest, *dw);
+#endif
*cursor += sizeof(*dw);
+
+ g_free(dw_ship);
+ dw_ship = NULL;
+
return sizeof(*dw);
} else {
return -1;
}
}
-
-/* read four bytes as "time_t" from buf,
- * return the number of bytes read if succeeds, otherwise return -1
- * This function is a wrapper around read_packet_dw() to avoid casting. */
-gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t)
+*/
+gint qq_get32(guint32 *dw, guint8 *buf)
{
- guint32 time;
- gint ret = read_packet_dw(buf, cursor, buflen, &time);
- if (ret != -1 ) {
- *t = time;
- }
- return ret;
+ guint32 dw_dest;
+ memcpy(&dw_dest, buf, sizeof(dw_dest));
+ *dw = g_ntohl(dw_dest);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get32] buf %d\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][get32] dw_dest 0x%08x, *dw 0x%08x\n", dw_dest, *dw);
+ return sizeof(dw_dest);
}
+
/* read datalen bytes from buf,
* return the number of bytes read if succeeds, otherwise return -1 */
+/*
gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen) {
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_data] buf addr: 0x%x\n", (gpointer)buf);
+#endif
if (*cursor <= buf + buflen - datalen) {
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[read_data] *cursor addr: 0x%x, buf expected addr: 0x%x\n",
+ (gpointer)*cursor, (gpointer)(buf + buflen - datalen));
+#endif
g_memmove(data, *cursor, datalen);
*cursor += datalen;
return datalen;
@@ -89,51 +210,189 @@ gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, g
return -1;
}
}
+*/
+gint qq_getdata(guint8 *data, gint datalen, guint8 *buf)
+{
+ memcpy(data, buf, datalen);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][getdata] buf %d\n", (void *)buf);
+ return datalen;
+}
+
+/* read four bytes as "time_t" from buf,
+ * return the number of bytes read if succeeds, otherwise return -1
+ * This function is a wrapper around read_packet_dw() to avoid casting. */
+/*
+gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t)
+{
+ guint32 time;
+ gint ret = read_packet_dw(buf, cursor, buflen, &time);
+ if (ret != -1 ) {
+ *t = time;
+ }
+ return ret;
+}
+*/
+gint qq_getime(time_t *t, guint8 *buf)
+{
+ guint32 dw_dest;
+ memcpy(&dw_dest, buf, sizeof(dw_dest));
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][getime] buf %d\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][getime] dw_dest before 0x%08x\n", dw_dest);
+ dw_dest = g_ntohl(dw_dest);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][getime] dw_dest after 0x%08x\n", dw_dest);
+ memcpy(t, &dw_dest, sizeof(dw_dest));
+ return sizeof(dw_dest);
+}
+
+/*------------------------------------------------PUT------------------------------------------------*/
/* pack one byte into buf
* return the number of bytes packed, otherwise return -1 */
+/*
gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b)
{
- if (*cursor <= buf + MAX_PACKET_SIZE - sizeof(guint8)) {
- **(guint8 **) cursor = b;
+ guint8 b_dest;
+#ifdef PARSER_DEBUG
+ // show me the address!
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_b] buf addr: 0x%x\n", (gpointer)buf);
+#endif
+ // using gpointer is more safe, s3e, 20070704
+ if ((gpointer)*cursor <= (gpointer)(buf + MAX_PACKET_SIZE - sizeof(guint8))) {
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_b] *cursor addr: 0x%x, buf expected addr: 0x%x\n",
+ (gpointer)*cursor,
+ (gpointer)(buf + MAX_PACKET_SIZE - sizeof(guint8)));
+#endif
+ b_dest = b;
+ g_memmove(*cursor, &b_dest, sizeof(guint8));
+#ifdef PARSER_DEBUG
+ // show data
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_b] data: 0x%02x->0x%02x\n", b, **(guint8 **)cursor);
+#endif
*cursor += sizeof(guint8);
return sizeof(guint8);
} else {
return -1;
}
}
+*/
+gint qq_put8(guint8 *buf, guint8 b)
+{
+ memcpy(buf, &b, sizeof(b));
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put8] buf %d\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put8] b 0x%02x\n", b);
+ return sizeof(b);
+}
+
/* pack two bytes as "guint16" into buf
* return the number of bytes packed, otherwise return -1 */
+/*
gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w)
{
- if (*cursor <= buf + MAX_PACKET_SIZE - sizeof(guint16)) {
- **(guint16 **) cursor = g_htons(w);
+ guint16 w_dest;
+ guint8 *w_ship = NULL;
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_w] buf addr: 0x%x\n", (gpointer)buf);
+#endif
+ if ((gpointer)*cursor <= (gpointer)(buf + MAX_PACKET_SIZE - sizeof(guint16))) {
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_w] *cursor addr: 0x%x, buf expected addr: 0x%x\n",
+ (gpointer)*cursor,
+ (gpointer)(buf + MAX_PACKET_SIZE - sizeof(guint16)));
+#endif
+ // obscure bugs found by ccpaging, patches from him.
+ // similar bugs have been fixed, s3e, 20070710
+ w_dest = g_htons(w);
+ w_ship = (guint8 *)&w_dest;
+ g_memmove(*cursor, w_ship, sizeof(guint16));
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_w] data: 0x%04x-g_htons->0x%04x->0x%04x\n",
+ w, w_dest, **(guint16 **)cursor);
+#endif
*cursor += sizeof(guint16);
return sizeof(guint16);
} else {
return -1;
}
}
+*/
+gint qq_put16(guint8 *buf, guint16 w)
+{
+ guint16 w_porter;
+ w_porter = g_htons(w);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put16] buf %d\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put16] w 0x%04x, w_porter 0x%04x\n", w, w_porter);
+ memcpy(buf, &w_porter, sizeof(w_porter));
+ return sizeof(w_porter);
+}
+
/* pack four bytes as "guint32" into buf
* return the number of bytes packed, otherwise return -1 */
+/*
gint create_packet_dw(guint8 *buf, guint8 **cursor, guint32 dw)
{
- if (*cursor <= buf + MAX_PACKET_SIZE - sizeof(guint32)) {
- **(guint32 **) cursor = g_htonl(dw);
+ guint32 dw_dest;
+ guint8 *dw_ship = NULL;
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER", "[create_dw] buf addr: 0x%x\n", (gpointer)buf);
+#endif
+ if ((gpointer)*cursor <= (gpointer)(buf + MAX_PACKET_SIZE - sizeof(guint32))) {
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_dw] *cursor addr: 0x%x, buf expected addr: 0x%x\n",
+ (gpointer)*cursor,
+ (gpointer)(buf + MAX_PACKET_SIZE -sizeof(guint32)));
+#endif
+ dw_dest = g_htonl(dw);
+ dw_ship = (guint8 *)&dw_dest;
+ g_memmove(*cursor, dw_ship, sizeof(guint32));
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_dw] data: 0x%08x-g_htonl->0x%08x->0x%08x\n",
+ dw, dw_dest, **(guint32 **)cursor);
+#endif
*cursor += sizeof(guint32);
return sizeof(guint32);
} else {
return -1;
}
}
+*/
+gint qq_put32(guint8 *buf, guint32 dw)
+{
+ guint32 dw_porter;
+ dw_porter = g_htonl(dw);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put32] buf %d\n", (void *)buf);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][put32] dw 0x%08x, dw_porter 0x%08x\n", dw, dw_porter);
+ memcpy(buf, &dw_porter, sizeof(dw_porter));
+ return sizeof(dw_porter);
+}
+
/* pack datalen bytes into buf
* return the number of bytes packed, otherwise return -1 */
+/*
gint create_packet_data(guint8 *buf, guint8 **cursor, guint8 *data, gint datalen)
{
- if (*cursor <= buf + MAX_PACKET_SIZE - datalen) {
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_data] buf addr: 0x%x\n", (gpointer)buf);
+#endif
+ if ((gpointer)*cursor <= (gpointer)(buf + MAX_PACKET_SIZE - datalen)) {
+#ifdef PARSER_DEBUG
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_DEBUGGER",
+ "[create_data] *cursor addr: 0x%x, buf expected addr: 0x%x\n",
+ (gpointer)*cursor,
+ (gpointer)(buf + MAX_PACKET_SIZE - datalen));
+#endif
g_memmove(*cursor, data, datalen);
*cursor += datalen;
return datalen;
@@ -141,3 +400,12 @@ gint create_packet_data(guint8 *buf, guint8 **cursor, guint8 *data, gint datalen
return -1;
}
}
+*/
+gint qq_putdata(guint8 *buf, guint8 *data, const int datalen)
+{
+ memcpy(buf, data, datalen);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[DBG][putdata] buf %d\n", (void *)buf);
+ return datalen;
+}
+
+
diff --git a/libpurple/protocols/qq/packet_parse.h b/libpurple/protocols/qq/packet_parse.h
index 65cee7719c..9cd225f32c 100644
--- a/libpurple/protocols/qq/packet_parse.h
+++ b/libpurple/protocols/qq/packet_parse.h
@@ -37,14 +37,26 @@
*/
#define MAX_PACKET_SIZE 65535
-gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b);
-gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w);
-gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw);
-gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t);
-gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen);
-gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b);
-gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w);
-gint create_packet_dw(guint8 *buf, guint8 **cursor, guint32 dw);
-gint create_packet_data(guint8 *buf, guint8 **cursor, guint8 *data, gint datalen);
+gint qq_get8(guint8 *b, guint8 *buf);
+gint qq_get16(guint16 *w, guint8 *buf);
+gint qq_get32(guint32 *dw, guint8 *buf);
+gint qq_getime(time_t *t, guint8 *buf);
+gint qq_getdata(guint8 *data, gint datalen, guint8 *buf);
+
+gint qq_put8(guint8 *buf, guint8 b);
+gint qq_put16(guint8 *buf, guint16 w);
+gint qq_put32(guint8 *buf, guint32 dw);
+gint qq_putdata(guint8 *buf, guint8 *data, const int datalen);
+
+//gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b);
+//gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w);
+//gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw);
+//gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t);
+//gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen);
+
+//gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b);
+//gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w);
+//gint create_packet_dw(guint8 *buf, guint8 **cursor, guint32 dw);
+//gint create_packet_data(guint8 *buf, guint8 **cursor, guint8 *data, gint datalen);
#endif
diff --git a/libpurple/protocols/qq/qq_proxy.c b/libpurple/protocols/qq/qq_proxy.c
index 3c807f2b66..5992eded32 100644
--- a/libpurple/protocols/qq/qq_proxy.c
+++ b/libpurple/protocols/qq/qq_proxy.c
@@ -46,33 +46,40 @@
/* These functions are used only in development phase */
/*
-static void _qq_show_socket(gchar *desc, gint fd) {
- struct sockaddr_in sin;
- socklen_t len = sizeof(sin);
- getsockname(fd, (struct sockaddr *)&sin, &len);
- purple_debug(PURPLE_DEBUG_INFO, desc, "%s:%d\n",
- inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port));
-}
-*/
+ static void _qq_show_socket(gchar *desc, gint fd) {
+ struct sockaddr_in sin;
+ socklen_t len = sizeof(sin);
+ getsockname(fd, (struct sockaddr *)&sin, &len);
+ purple_debug(PURPLE_DEBUG_INFO, desc, "%s:%d\n",
+ inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port));
+ }
+ */
void _qq_show_packet(const gchar *desc, const guint8 *buf, gint len)
{
- char buf1[8*len+2], buf2[10];
- int i;
- buf1[0] = 0;
- for (i = 0; i < len; i++) {
- sprintf(buf2, " %02x(%d)", buf[i] & 0xff, buf[i] & 0xff);
- strcat(buf1, buf2);
- }
- strcat(buf1, "\n");
- purple_debug(PURPLE_DEBUG_INFO, desc, "%s", buf1);
+ /*
+ char buf1[8*len+2], buf2[10];
+ int i;
+ buf1[0] = 0;
+ for (i = 0; i < len; i++) {
+ sprintf(buf2, " %02x(%d)", buf[i] & 0xff, buf[i] & 0xff);
+ strcat(buf1, buf2);
+ }
+ strcat(buf1, "\n");
+ purple_debug(PURPLE_DEBUG_INFO, desc, "%s", buf1);
+ */
+
+ /* modified by s3e, 20080424 */
+ gchar *packet_dump = hex_dump_to_str(buf, len);
+ purple_debug(PURPLE_DEBUG_INFO, desc, "\n%s\n", packet_dump);
+ g_free(packet_dump);
}
/* QQ 2003iii uses double MD5 for the pwkey to get the session key */
static guint8 *_gen_pwkey(const gchar *pwd)
{
- PurpleCipher *cipher;
- PurpleCipherContext *context;
+ PurpleCipher *cipher;
+ PurpleCipherContext *context;
guchar pwkey_tmp[QQ_KEY_LENGTH];
@@ -114,10 +121,10 @@ static void _qq_start_services(PurpleConnection *gc)
{
/* start watching for IMs about to be sent */
/*
- purple_signal_connect(purple_conversations_get_handle(),
- "sending-im-msg", gc,
- PURPLE_CALLBACK(qq_sending_im_msg_cb), NULL);
- */
+ purple_signal_connect(purple_conversations_get_handle(),
+ "sending-im-msg", gc,
+ PURPLE_CALLBACK(qq_sending_im_msg_cb), NULL);
+ */
}
/* the callback function after socket is built
@@ -146,8 +153,8 @@ static void _qq_got_login(gpointer data, gint source, const gchar *error_message
qd = (qq_data *) gc->proto_data;
/*
- _qq_show_socket("Got login socket", source);
- */
+ _qq_show_socket("Got login socket", source);
+ */
/* QQ use random seq, to minimize duplicated packets */
srandom(time(NULL));
@@ -209,7 +216,7 @@ static void _qq_common_clean(PurpleConnection *gc)
static void no_one_calls(gpointer data, gint source, PurpleInputCondition cond)
{
- struct PHB *phb = data;
+ struct PHB *phb = data;
socklen_t len;
int error=0, ret;
@@ -218,16 +225,16 @@ static void no_one_calls(gpointer data, gint source, PurpleInputCondition cond)
len = sizeof(error);
/*
- * getsockopt after a non-blocking connect returns -1 if something is
- * really messed up (bad descriptor, usually). Otherwise, it returns 0 and
- * error holds what connect would have returned if it blocked until now.
- * Thus, error == 0 is success, error == EINPROGRESS means "try again",
- * and anything else is a real error.
- *
- * (error == EINPROGRESS can happen after a select because the kernel can
- * be overly optimistic sometimes. select is just a hint that you might be
- * able to do something.)
- */
+ * getsockopt after a non-blocking connect returns -1 if something is
+ * really messed up (bad descriptor, usually). Otherwise, it returns 0 and
+ * error holds what connect would have returned if it blocked until now.
+ * Thus, error == 0 is success, error == EINPROGRESS means "try again",
+ * and anything else is a real error.
+ *
+ * (error == EINPROGRESS can happen after a select because the kernel can
+ * be overly optimistic sometimes. select is just a hint that you might be
+ * able to do something.)
+ */
ret = getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len);
if (ret == 0 && error == EINPROGRESS)
return; /* we'll be called again later */
@@ -265,7 +272,7 @@ static gint _qq_proxy_none(struct PHB *phb, struct sockaddr *addr, socklen_t add
if (fd < 0) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ Redirect",
- "Unable to create socket: %s\n", g_strerror(errno));
+ "Unable to create socket: %s\n", g_strerror(errno));
return -1;
}
@@ -294,10 +301,10 @@ static gint _qq_proxy_none(struct PHB *phb, struct sockaddr *addr, socklen_t add
* The connection is established asynchronously.
*/
if ((errno == EINPROGRESS) || (errno == EINTR)) {
- purple_debug_warning("QQ", "Connect in asynchronous mode.\n");
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Connect in asynchronous mode.\n");
phb->inpa = purple_input_add(fd, PURPLE_INPUT_WRITE, no_one_calls, phb);
} else {
- purple_debug_error("QQ", "Connection failed: %s\n", g_strerror(errno));
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Connection failed: %d\n", g_strerror(errno));
close(fd);
return -1;
} /* if errno */
@@ -349,11 +356,11 @@ static void _qq_server_resolved(GSList *hosts, gpointer data, const char *error_
ret = -1;
} else {
/* as the destination is always QQ server during the session,
- * we can set dest_sin here, instead of _qq_s5_canread_again */
+ * we can set dest_sin here, instead of _qq_s5_canread_again */
memcpy(&qd->dest_sin, &addr, addr_size);
if (purple_dnsquery_a(purple_proxy_info_get_host(phb->gpi),
- purple_proxy_info_get_port(phb->gpi),
- _qq_proxy_resolved, phb) == NULL)
+ purple_proxy_info_get_port(phb->gpi),
+ _qq_proxy_resolved, phb) == NULL)
ret = -1;
}
break;
@@ -374,9 +381,9 @@ static void _qq_server_resolved(GSList *hosts, gpointer data, const char *error_
/* returns -1 if dns lookup fails, otherwise returns 0 */
static gint _qq_udp_proxy_connect(PurpleAccount *account,
- const gchar *server, guint16 port,
- void callback(gpointer, gint, const gchar *error_message),
- PurpleConnection *gc)
+ const gchar *server, guint16 port,
+ void callback(gpointer, gint, const gchar *error_message),
+ PurpleConnection *gc)
{
PurpleProxyInfo *info;
struct PHB *phb;
@@ -496,6 +503,7 @@ gint qq_proxy_write(qq_data *qd, guint8 *data, gint len)
errno = 0;
ret = send(qd->fd, data, len, 0);
}
+
if (ret == -1)
purple_connection_error_reason(qd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, g_strerror(errno));
diff --git a/libpurple/protocols/qq/recv_core.c b/libpurple/protocols/qq/recv_core.c
index 876f0a178b..15c3b623f8 100644
--- a/libpurple/protocols/qq/recv_core.c
+++ b/libpurple/protocols/qq/recv_core.c
@@ -94,8 +94,8 @@ static void _qq_process_packet_default(guint8 *buf, gint buf_len, guint16 cmd, g
if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
gchar *hex_dump = hex_dump_to_str(data, len);
purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- ">>> [%d] %s, %d bytes -> [default] decrypt and dump\n%s",
- seq, qq_get_cmd_desc(cmd), buf_len, hex_dump);
+ ">>> [%d] %s, %d bytes -> [default] decrypt and dump\n%s",
+ seq, qq_get_cmd_desc(cmd), buf_len, hex_dump);
g_free(hex_dump);
try_dump_as_gbk(data, len);
} else {
@@ -107,9 +107,8 @@ static void _qq_process_packet_default(guint8 *buf, gint buf_len, guint16 cmd, g
static void _qq_packet_process(guint8 *buf, gint buf_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len, bytes_expected, bytes_read;
+ gint bytes_notread, bytes_expected, bytes;
guint16 buf_len_read; /* two bytes in the begining of TCP packet */
- guint8 *cursor;
qq_recv_msg_header header;
packet_before_login *b4_packet;
@@ -121,51 +120,50 @@ static void _qq_packet_process(guint8 *buf, gint buf_len, PurpleConnection *gc)
if (buf_len < bytes_expected) {
gchar *hex_dump = hex_dump_to_str(buf, buf_len);
purple_debug(PURPLE_DEBUG_ERROR,
- "QQ", "Received packet is too short, dump and drop\n%s", hex_dump);
+ "QQ", "Received packet is too short, dump and drop\n%s", hex_dump);
g_free(hex_dump);
return;
}
- /* initialize */
- cursor = buf;
- bytes_read = 0;
+ /* initialize */
+ bytes = 0;
/* QQ TCP packet returns first 2 bytes the length of this packet */
if (qd->use_tcp) {
- bytes_read += read_packet_w(buf, &cursor, buf_len, &buf_len_read);
+ bytes += qq_get16(&buf_len_read, buf + bytes);
if (buf_len_read != buf_len) { /* wrong */
purple_debug
- (PURPLE_DEBUG_ERROR,
- "QQ",
- "TCP read %d bytes, header says %d bytes, use header anyway\n", buf_len, buf_len_read);
+ (PURPLE_DEBUG_ERROR,
+ "QQ",
+ "TCP read %d bytes, header says %d bytes, use header anyway\n", buf_len, buf_len_read);
buf_len = buf_len_read; /* we believe header is more accurate */
}
}
/* now goes the normal QQ packet as UDP packet */
- bytes_read += read_packet_b(buf, &cursor, buf_len, &header.header_tag);
- bytes_read += read_packet_w(buf, &cursor, buf_len, &header.source_tag);
- bytes_read += read_packet_w(buf, &cursor, buf_len, &header.cmd);
- bytes_read += read_packet_w(buf, &cursor, buf_len, &header.seq);
+ bytes += qq_get8(&header.header_tag, buf + bytes);
+ bytes += qq_get16(&header.source_tag, buf + bytes);
+ bytes += qq_get16(&header.cmd, buf + bytes);
+ bytes += qq_get16(&header.seq, buf + bytes);
- if (bytes_read != bytes_expected) { /* read error */
+ if (bytes != bytes_expected) { /* read error */
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail reading packet header, expect %d bytes, read %d bytes\n",
- bytes_expected, bytes_read);
+ "Fail reading packet header, expect %d bytes, read %d bytes\n",
+ bytes_expected, bytes);
return;
}
if ((buf[buf_len - 1] != QQ_PACKET_TAIL) || (header.header_tag != QQ_PACKET_TAG)) {
gchar *hex_dump = hex_dump_to_str(buf, buf_len);
purple_debug(PURPLE_DEBUG_ERROR,
- "QQ", "Unknown QQ proctocol, dump and drop\n%s", hex_dump);
+ "QQ", "Unknown QQ proctocol, dump and drop\n%s", hex_dump);
g_free(hex_dump);
return;
}
if (QQ_DEBUG)
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "==> [%05d] %s, from (%s)\n",
- header.seq, qq_get_cmd_desc(header.cmd), qq_get_source_str(header.source_tag));
+ "==> [%05d] %s, from (%s)\n",
+ header.seq, qq_get_cmd_desc(header.cmd), qq_get_source_str(header.source_tag));
if (header.cmd != QQ_CMD_LOGIN && header.cmd != QQ_CMD_REQUEST_LOGIN_TOKEN) {
if (!qd->logged_in) { /* packets before login */
@@ -180,7 +178,7 @@ static void _qq_packet_process(guint8 *buf, gint buf_len, PurpleConnection *gc)
} else if (!g_queue_is_empty(qd->before_login_packets)) {
/* logged_in, but we have packets before login */
b4_packet = (packet_before_login *)
- g_queue_pop_head(qd->before_login_packets);
+ g_queue_pop_head(qd->before_login_packets);
_qq_packet_process(b4_packet->buf, b4_packet->len, gc);
/* in fact this is a recursive call,
* all packets before login will be processed before goes on */
@@ -190,94 +188,94 @@ static void _qq_packet_process(guint8 *buf, gint buf_len, PurpleConnection *gc)
}
/* this is the length of all the encrypted data (also remove tail tag */
- len = buf_len - (bytes_read) - 1;
+ bytes_notread = buf_len - bytes - 1;
/* whether it is an ack */
switch (header.cmd) {
- case QQ_CMD_RECV_IM:
- case QQ_CMD_RECV_MSG_SYS:
- case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
- /* server intiated packet, we need to send ack and check duplicaion
- * this must be put after processing b4_packet
- * as these packets will be passed in twice */
- if (_qq_check_packet_set_window(header.seq, gc)) {
- purple_debug(PURPLE_DEBUG_WARNING,
- "QQ", "dup [%05d] %s, discard...\n", header.seq, qq_get_cmd_desc(header.cmd));
- return;
- }
- break;
- default:{ /* ack packet, we need to update sendqueue */
- /* we do not check duplication for server ack */
- qq_sendqueue_remove(qd, header.seq);
- if (QQ_DEBUG)
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "ack [%05d] %s, remove from sendqueue\n",
- header.seq, qq_get_cmd_desc(header.cmd));
- }
+ case QQ_CMD_RECV_IM:
+ case QQ_CMD_RECV_MSG_SYS:
+ case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
+ /* server intiated packet, we need to send ack and check duplicaion
+ * this must be put after processing b4_packet
+ * as these packets will be passed in twice */
+ if (_qq_check_packet_set_window(header.seq, gc)) {
+ purple_debug(PURPLE_DEBUG_WARNING,
+ "QQ", "dup [%05d] %s, discard...\n", header.seq, qq_get_cmd_desc(header.cmd));
+ return;
+ }
+ break;
+ default:{ /* ack packet, we need to update sendqueue */
+ /* we do not check duplication for server ack */
+ qq_sendqueue_remove(qd, header.seq);
+ if (QQ_DEBUG)
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "ack [%05d] %s, remove from sendqueue\n",
+ header.seq, qq_get_cmd_desc(header.cmd));
+ }
}
/* now process the packet */
switch (header.cmd) {
- case QQ_CMD_KEEP_ALIVE:
- qq_process_keep_alive_reply(cursor, len, gc);
- break;
- case QQ_CMD_UPDATE_INFO:
- qq_process_modify_info_reply(cursor, len, gc);
- break;
- case QQ_CMD_ADD_FRIEND_WO_AUTH:
- qq_process_add_buddy_reply(cursor, len, header.seq, gc);
- break;
- case QQ_CMD_DEL_FRIEND:
- qq_process_remove_buddy_reply(cursor, len, gc);
- break;
- case QQ_CMD_REMOVE_SELF:
- qq_process_remove_self_reply(cursor, len, gc);
- break;
- case QQ_CMD_BUDDY_AUTH:
- qq_process_add_buddy_auth_reply(cursor, len, gc);
- break;
- case QQ_CMD_GET_USER_INFO:
- qq_process_get_info_reply(cursor, len, gc);
- break;
- case QQ_CMD_CHANGE_ONLINE_STATUS:
- qq_process_change_status_reply(cursor, len, gc);
- break;
- case QQ_CMD_SEND_IM:
- qq_process_send_im_reply(cursor, len, gc);
- break;
- case QQ_CMD_RECV_IM:
- qq_process_recv_im(cursor, len, header.seq, gc);
- break;
- case QQ_CMD_LOGIN:
- qq_process_login_reply(cursor, len, gc);
- break;
- case QQ_CMD_GET_FRIENDS_LIST:
- qq_process_get_buddies_list_reply(cursor, len, gc);
- break;
- case QQ_CMD_GET_FRIENDS_ONLINE:
- qq_process_get_buddies_online_reply(cursor, len, gc);
- break;
- case QQ_CMD_GROUP_CMD:
- qq_process_group_cmd_reply(cursor, len, header.seq, gc);
- break;
- case QQ_CMD_GET_ALL_LIST_WITH_GROUP:
- qq_process_get_all_list_with_group_reply(cursor, len, gc);
- break;
- case QQ_CMD_GET_LEVEL:
- qq_process_get_level_reply(cursor, len, gc);
- break;
- case QQ_CMD_REQUEST_LOGIN_TOKEN:
- qq_process_request_login_token_reply(cursor, len, gc);
- break;
- case QQ_CMD_RECV_MSG_SYS:
- qq_process_msg_sys(cursor, len, header.seq, gc);
- break;
- case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
- qq_process_friend_change_status(cursor, len, gc);
- break;
- default:
- _qq_process_packet_default(cursor, len, header.cmd, header.seq, gc);
- break;
+ case QQ_CMD_KEEP_ALIVE:
+ qq_process_keep_alive_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_UPDATE_INFO:
+ qq_process_modify_info_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_ADD_FRIEND_WO_AUTH:
+ qq_process_add_buddy_reply(buf + bytes, bytes_notread, header.seq, gc);
+ break;
+ case QQ_CMD_DEL_FRIEND:
+ qq_process_remove_buddy_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_REMOVE_SELF:
+ qq_process_remove_self_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_BUDDY_AUTH:
+ qq_process_add_buddy_auth_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_GET_USER_INFO:
+ qq_process_get_info_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_CHANGE_ONLINE_STATUS:
+ qq_process_change_status_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_SEND_IM:
+ qq_process_send_im_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_RECV_IM:
+ qq_process_recv_im(buf + bytes, bytes_notread, header.seq, gc);
+ break;
+ case QQ_CMD_LOGIN:
+ qq_process_login_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_GET_FRIENDS_LIST:
+ qq_process_get_buddies_list_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_GET_FRIENDS_ONLINE:
+ qq_process_get_buddies_online_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_GROUP_CMD:
+ qq_process_group_cmd_reply(buf + bytes, bytes_notread, header.seq, gc);
+ break;
+ case QQ_CMD_GET_ALL_LIST_WITH_GROUP:
+ qq_process_get_all_list_with_group_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_GET_LEVEL:
+ qq_process_get_level_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_REQUEST_LOGIN_TOKEN:
+ qq_process_request_login_token_reply(buf + bytes, bytes_notread, gc);
+ break;
+ case QQ_CMD_RECV_MSG_SYS:
+ qq_process_msg_sys(buf + bytes, bytes_notread, header.seq, gc);
+ break;
+ case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
+ qq_process_friend_change_status(buf + bytes, bytes_notread, gc);
+ break;
+ default:
+ _qq_process_packet_default(buf + bytes, bytes_notread, header.cmd, header.seq, gc);
+ break;
}
}
@@ -307,7 +305,7 @@ void qq_input_pending(gpointer data, gint source, PurpleInputCondition cond)
if(cond != PURPLE_INPUT_READ) {
purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Socket error"));
+ _("Socket error"));
return;
}
@@ -318,7 +316,7 @@ void qq_input_pending(gpointer data, gint source, PurpleInputCondition cond)
len = qq_proxy_read(qd, buf, MAX_PACKET_SIZE);
if (len <= 0) {
purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Unable to read from socket"));
+ _("Unable to read from socket"));
return;
} else {
_qq_packet_process(buf, len, gc);
diff --git a/libpurple/protocols/qq/send_core.c b/libpurple/protocols/qq/send_core.c
index dec8205655..0d79ad6000 100644
--- a/libpurple/protocols/qq/send_core.c
+++ b/libpurple/protocols/qq/send_core.c
@@ -36,39 +36,38 @@
/* create qq packet header with given sequence
* return the number of bytes in header if succeeds
* return -1 if there is any error */
-gint _create_packet_head_seq(guint8 *buf, guint8 **cursor,
- PurpleConnection *gc, guint16 cmd, gboolean is_auto_seq, guint16 *seq)
+gint _create_packet_head_seq(guint8 *buf, PurpleConnection *gc,
+ guint16 cmd, gboolean is_auto_seq, guint16 *seq)
{
qq_data *qd;
- gint bytes_expected, bytes_written;
+ gint bytes_expected, bytes;
- g_return_val_if_fail(buf != NULL && cursor != NULL && *cursor != NULL, -1);
+ g_return_val_if_fail(buf != NULL, -1);
qd = (qq_data *) gc->proto_data;
if (is_auto_seq)
*seq = ++(qd->send_seq);
- *cursor = buf;
- bytes_written = 0;
+ bytes = 0;
bytes_expected = (qd->use_tcp) ? QQ_TCP_HEADER_LENGTH : QQ_UDP_HEADER_LENGTH;
/* QQ TCP packet has two bytes in the begining defines packet length
* so I leave room here for size */
- if (qd->use_tcp)
- bytes_written += create_packet_w(buf, cursor, 0x0000);
-
+ if (qd->use_tcp) {
+ bytes += qq_put16(buf + bytes, 0x0000);
+ }
/* now comes the normal QQ packet as UDP */
- bytes_written += create_packet_b(buf, cursor, QQ_PACKET_TAG);
- bytes_written += create_packet_w(buf, cursor, QQ_CLIENT);
- bytes_written += create_packet_w(buf, cursor, cmd);
- bytes_written += create_packet_w(buf, cursor, *seq);
+ bytes += qq_put8(buf + bytes, QQ_PACKET_TAG);
+ bytes += qq_put16(buf + bytes, QQ_CLIENT);
+ bytes += qq_put16(buf + bytes, cmd);
+ bytes += qq_put16(buf + bytes, *seq);
- if (bytes_written != bytes_expected) {
+ if (bytes != bytes_expected) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create qq header, expect %d bytes, written %d bytes\n", bytes_expected, bytes_written);
- bytes_written = -1;
+ "Fail create qq header, expect %d bytes, written %d bytes\n", bytes_expected, bytes);
+ bytes = -1;
}
- return bytes_written;
+ return bytes;
}
/* for those need ack and resend no ack feed back from server
@@ -78,26 +77,27 @@ gint _qq_send_packet(PurpleConnection *gc, guint8 *buf, gint len, guint16 cmd)
{
qq_data *qd;
qq_sendpacket *p;
- gint bytes_sent;
- guint8 *cursor;
+ gint bytes = 0;
qd = (qq_data *) gc->proto_data;
if (qd->use_tcp) {
if (len > MAX_PACKET_SIZE) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "xxx [%05d] %s, %d bytes is too large, do not send\n",
- qd->send_seq, qq_get_cmd_desc(cmd), len);
+ "xxx [%05d] %s, %d bytes is too large, do not send\n",
+ qq_get_cmd_desc(cmd), qd->send_seq, len);
return -1;
} else { /* I update the len for TCP packet */
- cursor = buf;
- create_packet_w(buf, &cursor, len);
+ /* set TCP packet length
+ * _create_packet_head_seq has reserved two byte for storing pkt length, ccpaging */
+ qq_put16(buf, len);
}
}
- bytes_sent = qq_proxy_write(qd, buf, len);
+ /* bytes actually returned */
+ bytes = qq_proxy_write(qd, buf, len);
- if (bytes_sent >= 0) { /* put to queue, for matching server ACK usage */
+ if (bytes >= 0) { /* put to queue, for matching server ACK usage */
p = g_new0(qq_sendpacket, 1);
p->fd = qd->fd;
p->cmd = cmd;
@@ -109,19 +109,23 @@ gint _qq_send_packet(PurpleConnection *gc, guint8 *buf, gint len, guint16 cmd)
qd->sendqueue = g_list_append(qd->sendqueue, p);
}
- return bytes_sent;
+ /* for debugging, s3e, 20070622 */
+ _qq_show_packet("QQ_SEND_PACKET", p->buf, p->len);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "%d bytes written to the socket.\n", bytes);
+
+ return bytes;
}
/* send the packet generated with the given cmd and data
* return the number of bytes sent to socket if succeeds
* return -1 if there is any error */
gint qq_send_cmd(PurpleConnection *gc, guint16 cmd,
- gboolean is_auto_seq, guint16 seq, gboolean need_ack, guint8 *data, gint len)
+ gboolean is_auto_seq, guint16 seq, gboolean need_ack, guint8 *data, gint len)
{
qq_data *qd;
- guint8 *buf, *cursor, *encrypted_data;
+ guint8 *buf, *encrypted_data;
guint16 seq_ret;
- gint encrypted_len, bytes_written, bytes_expected, bytes_sent;
+ gint encrypted_len, bytes, bytes_header, bytes_expected, bytes_sent;
qd = (qq_data *) gc->proto_data;
g_return_val_if_fail(qd->session_key != NULL, -1);
@@ -129,35 +133,39 @@ gint qq_send_cmd(PurpleConnection *gc, guint16 cmd,
buf = g_newa(guint8, MAX_PACKET_SIZE);
encrypted_len = len + 16; /* at most 16 bytes more */
encrypted_data = g_newa(guint8, encrypted_len);
- cursor = buf;
- bytes_written = 0;
qq_encrypt(data, len, qd->session_key, encrypted_data, &encrypted_len);
seq_ret = seq;
- if (_create_packet_head_seq(buf, &cursor, gc, cmd, is_auto_seq, &seq_ret) >= 0) {
- bytes_expected = 4 + encrypted_len + 1;
- bytes_written += create_packet_dw(buf, &cursor, (guint32) qd->uid);
- bytes_written += create_packet_data(buf, &cursor, encrypted_data, encrypted_len);
- bytes_written += create_packet_b(buf, &cursor, QQ_PACKET_TAIL);
- if (bytes_written == bytes_expected) { /* packet OK */
- /* if it does not need ACK, we send ACK manually several times */
- if (need_ack) /* my request, send it */
- bytes_sent = _qq_send_packet(gc, buf, cursor - buf, cmd);
- else /* server's request, send ACK */
- bytes_sent = qq_proxy_write(qd, buf, cursor - buf);
-
- if (QQ_DEBUG)
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "<== [%05d] %s, %d bytes\n", seq_ret, qq_get_cmd_desc(cmd), bytes_sent);
- return bytes_sent;
- } else { /* bad packet */
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail creating packet, expect %d bytes, written %d bytes\n",
- bytes_expected, bytes_written);
- return -1;
- }
+
+ bytes = 0;
+ bytes += _create_packet_head_seq(buf + bytes, gc, cmd, is_auto_seq, &seq_ret);
+ if (bytes <= 0) {
+ /* _create_packet_head_seq warned before */
+ return -1;
+ }
+
+ bytes_header = bytes;
+ bytes_expected = 4 + encrypted_len + 1;
+ bytes += qq_put32(buf + bytes, (guint32) qd->uid);
+ bytes += qq_putdata(buf + bytes, encrypted_data, encrypted_len);
+ bytes += qq_put8(buf + bytes, QQ_PACKET_TAIL);
+
+ if ((bytes - bytes_header) != bytes_expected) { /* bad packet */
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Fail creating packet, expect %d bytes, written %d bytes\n",
+ bytes_expected, bytes - bytes_header);
+ return -1;
}
- return -1;
+ /* if it does not need ACK, we send ACK manually several times */
+ if (need_ack) /* my request, send it */
+ bytes_sent = _qq_send_packet(gc, buf, bytes, cmd);
+ else /* server's request, send ACK */
+ bytes_sent = qq_proxy_write(qd, buf, bytes);
+
+ if (QQ_DEBUG)
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "<== [%05d] %s, %d bytes\n", seq_ret, qq_get_cmd_desc(cmd), bytes_sent);
+ return bytes_sent;
}
diff --git a/libpurple/protocols/qq/send_core.h b/libpurple/protocols/qq/send_core.h
index c93fa0a24a..1c3084dd7b 100644
--- a/libpurple/protocols/qq/send_core.h
+++ b/libpurple/protocols/qq/send_core.h
@@ -31,7 +31,7 @@
gint qq_send_cmd(PurpleConnection *gc, guint16 cmd, gboolean is_auto_seq, guint16 seq,
gboolean need_ack, guint8 *data, gint len);
gint _qq_send_packet(PurpleConnection * gc, guint8 *buf, gint len, guint16 cmd);
-gint _create_packet_head_seq(guint8 *buf, guint8 **cursor,
- PurpleConnection *gc, guint16 cmd, gboolean is_auto_seq, guint16 *seq);
+gint _create_packet_head_seq(guint8 *buf, PurpleConnection *gc,
+ guint16 cmd, gboolean is_auto_seq, guint16 *seq);
#endif
diff --git a/libpurple/protocols/qq/send_file.c b/libpurple/protocols/qq/send_file.c
index baaebc719b..afecca3943 100644
--- a/libpurple/protocols/qq/send_file.c
+++ b/libpurple/protocols/qq/send_file.c
@@ -103,6 +103,7 @@ static ssize_t _qq_xfer_udp_send(const char *buf, size_t len, PurpleXfer *xfer)
return send(info->sender_fd, buf, len, 0);
}
*/
+
static ssize_t _qq_xfer_udp_send(const guint8 *buf, size_t len, PurpleXfer *xfer)
{
struct sockaddr_in sin;
@@ -243,42 +244,45 @@ static void qq_show_conn_info(ft_info *info)
g_free(internet_ip_str);
}
-void qq_get_conn_info(guint8 *data, guint8 **cursor, gint data_len, ft_info *info)
+#define QQ_CONN_INFO_LEN 61
+gint qq_get_conn_info(ft_info *info, guint8 *data)
{
- read_packet_data(data, cursor, data_len, info->file_session_key, 16);
- *cursor += 30;
- read_packet_b(data, cursor, data_len, &info->conn_method);
- read_packet_dw(data, cursor, data_len, &info->remote_internet_ip);
- read_packet_w(data, cursor, data_len, &info->remote_internet_port);
- read_packet_w(data, cursor, data_len, &info->remote_major_port);
- read_packet_dw(data, cursor, data_len, &info->remote_real_ip);
- read_packet_w(data, cursor, data_len, &info->remote_minor_port);
+ gint bytes = 0;
+ /* 16 + 30 + 1 + 4 + 2 + 2 + 4 + 2 = 61 */
+ bytes += qq_getdata(info->file_session_key, 16, data + bytes);
+ bytes += 30; /* skip 30 bytes */
+ bytes += qq_get8(&info->conn_method, data + bytes);
+ bytes += qq_get32(&info->remote_internet_ip, data + bytes);
+ bytes += qq_get16(&info->remote_internet_port, data + bytes);
+ bytes += qq_get16(&info->remote_major_port, data + bytes);
+ bytes += qq_get32(&info->remote_real_ip, data + bytes);
+ bytes += qq_get16(&info->remote_minor_port, data + bytes);
qq_show_conn_info(info);
+ return bytes;
}
-gint qq_fill_conn_info(guint8 *raw_data, guint8 **cursor, ft_info *info)
+gint qq_fill_conn_info(guint8 *raw_data, ft_info *info)
{
- gint bytes;
- bytes = 0;
+ gint bytes = 0;
/* 064: connection method, UDP 0x00, TCP 0x03 */
- bytes += create_packet_b (raw_data, cursor, info->conn_method);
+ bytes += qq_put8 (raw_data + bytes, info->conn_method);
/* 065-068: outer ip address of sender (proxy address) */
- bytes += create_packet_dw (raw_data, cursor, info->local_internet_ip);
+ bytes += qq_put32 (raw_data + bytes, info->local_internet_ip);
/* 069-070: sender port */
- bytes += create_packet_w (raw_data, cursor, info->local_internet_port);
+ bytes += qq_put16 (raw_data + bytes, info->local_internet_port);
/* 071-072: the first listening port(TCP doesn't have this part) */
- bytes += create_packet_w (raw_data, cursor, info->local_major_port);
+ bytes += qq_put16 (raw_data + bytes, info->local_major_port);
/* 073-076: real ip */
- bytes += create_packet_dw (raw_data, cursor, info->local_real_ip);
+ bytes += qq_put32 (raw_data + bytes, info->local_real_ip);
/* 077-078: the second listening port */
- bytes += create_packet_w (raw_data, cursor, info->local_minor_port);
+ bytes += qq_put16 (raw_data + bytes, info->local_minor_port);
return bytes;
}
/* fill in the common information of file transfer */
static gint _qq_create_packet_file_header
-(guint8 *raw_data, guint8 **cursor, guint32 to_uid, guint16 message_type, qq_data *qd, gboolean seq_ack)
+(guint8 *raw_data, guint32 to_uid, guint16 message_type, qq_data *qd, gboolean seq_ack)
{
gint bytes;
time_t now;
@@ -294,42 +298,42 @@ static gint _qq_create_packet_file_header
}
/* 000-003: receiver uid */
- bytes += create_packet_dw (raw_data, cursor, qd->uid);
+ bytes += qq_put32 (raw_data + bytes, qd->uid);
/* 004-007: sender uid */
- bytes += create_packet_dw (raw_data, cursor, to_uid);
+ bytes += qq_put32 (raw_data + bytes, to_uid);
/* 008-009: sender client version */
- bytes += create_packet_w (raw_data, cursor, QQ_CLIENT);
+ bytes += qq_put16 (raw_data + bytes, QQ_CLIENT);
/* 010-013: receiver uid */
- bytes += create_packet_dw (raw_data, cursor, qd->uid);
+ bytes += qq_put32 (raw_data + bytes, qd->uid);
/* 014-017: sender uid */
- bytes += create_packet_dw (raw_data, cursor, to_uid);
+ bytes += qq_put32 (raw_data + bytes, to_uid);
/* 018-033: md5 of (uid+session_key) */
- bytes += create_packet_data (raw_data, cursor, qd->session_md5, 16);
+ bytes += qq_putdata (raw_data + bytes, qd->session_md5, 16);
/* 034-035: message type */
- bytes += create_packet_w (raw_data, cursor, message_type);
+ bytes += qq_put16 (raw_data + bytes, message_type);
/* 036-037: sequence number */
- bytes += create_packet_w (raw_data, cursor, seq);
+ bytes += qq_put16 (raw_data + bytes, seq);
/* 038-041: send time */
- bytes += create_packet_dw (raw_data, cursor, (guint32) now);
+ bytes += qq_put32 (raw_data + bytes, (guint32) now);
/* 042-042: always 0x00 */
- bytes += create_packet_b (raw_data, cursor, 0x00);
+ bytes += qq_put8 (raw_data + bytes, 0x00);
/* 043-043: sender icon */
- bytes += create_packet_b (raw_data, cursor, qd->my_icon);
+ bytes += qq_put8 (raw_data + bytes, qd->my_icon);
/* 044-046: always 0x00 */
- bytes += create_packet_w (raw_data, cursor, 0x0000);
- bytes += create_packet_b (raw_data, cursor, 0x00);
+ bytes += qq_put16 (raw_data + bytes, 0x0000);
+ bytes += qq_put8 (raw_data + bytes, 0x00);
/* 047-047: we use font attr */
- bytes += create_packet_b (raw_data, cursor, 0x01);
+ bytes += qq_put8 (raw_data + bytes, 0x01);
/* 048-051: always 0x00 */
- bytes += create_packet_dw (raw_data, cursor, 0x00000000);
+ bytes += qq_put32 (raw_data + bytes, 0x00000000);
/* 052-062: always 0x00 */
- bytes += create_packet_dw (raw_data, cursor, 0x00000000);
- bytes += create_packet_dw (raw_data, cursor, 0x00000000);
- bytes += create_packet_w (raw_data, cursor, 0x0000);
- bytes += create_packet_b (raw_data, cursor, 0x00);
+ bytes += qq_put32 (raw_data + bytes, 0x00000000);
+ bytes += qq_put32 (raw_data + bytes, 0x00000000);
+ bytes += qq_put16 (raw_data + bytes, 0x0000);
+ bytes += qq_put8 (raw_data + bytes, 0x00);
/* 063: transfer_type, 0x65: FILE 0x6b: FACE */
- bytes += create_packet_b (raw_data, cursor, QQ_FILE_TRANSFER_FILE); /* FIXME */
+ bytes += qq_put8 (raw_data + bytes, QQ_FILE_TRANSFER_FILE); /* FIXME */
return bytes;
}
@@ -433,7 +437,7 @@ static void _qq_xfer_init_socket(PurpleXfer *xfer)
static void _qq_send_packet_file_request (PurpleConnection *gc, guint32 to_uid, gchar *filename, gint filesize)
{
qq_data *qd;
- guint8 *cursor, *raw_data;
+ guint8 *raw_data;
gchar *filelen_str;
gint filename_len, filelen_strlen, packet_len, bytes;
ft_info *info;
@@ -455,27 +459,24 @@ static void _qq_send_packet_file_request (PurpleConnection *gc, guint32 to_uid,
packet_len = 82 + filename_len + filelen_strlen;
raw_data = g_newa(guint8, packet_len);
- cursor = raw_data;
+ bytes = 0;
- bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid,
+ bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid,
QQ_FILE_TRANS_REQ, qd, FALSE);
- bytes += qq_fill_conn_info(raw_data, &cursor, info);
+ bytes += qq_fill_conn_info(raw_data + bytes, info);
/* 079: 0x20 */
- bytes += create_packet_b (raw_data, &cursor, 0x20);
+ bytes += qq_put8 (raw_data + bytes, 0x20);
/* 080: 0x1f */
- bytes += create_packet_b (raw_data, &cursor, 0x1f);
+ bytes += qq_put8 (raw_data + bytes, 0x1f);
/* undetermined len: filename */
- bytes += create_packet_data (raw_data, &cursor, (guint8 *) filename,
- filename_len);
+ bytes += qq_putdata (raw_data + bytes, (guint8 *) filename, filename_len);
/* 0x1f */
- bytes += create_packet_b (raw_data, &cursor, 0x1f);
+ bytes += qq_put8 (raw_data + bytes, 0x1f);
/* file length */
- bytes += create_packet_data (raw_data, &cursor, (guint8 *) filelen_str,
- filelen_strlen);
+ bytes += qq_putdata (raw_data + bytes, (guint8 *) filelen_str, filelen_strlen);
if (packet_len == bytes)
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
- cursor - raw_data);
+ qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_request",
"%d bytes expected but got %d bytes\n",
@@ -488,7 +489,7 @@ static void _qq_send_packet_file_request (PurpleConnection *gc, guint32 to_uid,
static void _qq_send_packet_file_accept(PurpleConnection *gc, guint32 to_uid)
{
qq_data *qd;
- guint8 *cursor, *raw_data;
+ guint8 *raw_data;
guint16 minor_port;
guint32 real_ip;
gint packet_len, bytes;
@@ -502,22 +503,21 @@ static void _qq_send_packet_file_accept(PurpleConnection *gc, guint32 to_uid)
packet_len = 79;
raw_data = g_newa (guint8, packet_len);
- cursor = raw_data;
+ bytes = 0;
minor_port = info->local_minor_port;
real_ip = info->local_real_ip;
info->local_minor_port = 0;
info->local_real_ip = 0;
- bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_ACC_UDP, qd, TRUE);
- bytes += qq_fill_conn_info(raw_data, &cursor, info);
+ bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_ACC_UDP, qd, TRUE);
+ bytes += qq_fill_conn_info(raw_data + bytes, info);
info->local_minor_port = minor_port;
info->local_real_ip = real_ip;
if (packet_len == bytes)
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
- cursor - raw_data);
+ qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_accept",
"%d bytes expected but got %d bytes\n",
@@ -529,7 +529,7 @@ static void _qq_send_packet_file_notifyip(PurpleConnection *gc, guint32 to_uid)
PurpleXfer *xfer;
ft_info *info;
qq_data *qd;
- guint8 *cursor, *raw_data;
+ guint8 *raw_data;
gint packet_len, bytes;
qd = (qq_data *) gc->proto_data;
@@ -538,14 +538,13 @@ static void _qq_send_packet_file_notifyip(PurpleConnection *gc, guint32 to_uid)
packet_len = 79;
raw_data = g_newa (guint8, packet_len);
- cursor = raw_data;
+ bytes = 0;
purple_debug(PURPLE_DEBUG_INFO, "QQ", "<== sending qq file notify ip packet\n");
- bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_NOTIFY, qd, TRUE);
- bytes += qq_fill_conn_info(raw_data, &cursor, info);
+ bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_NOTIFY, qd, TRUE);
+ bytes += qq_fill_conn_info(raw_data + bytes, info);
if (packet_len == bytes)
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
- cursor - raw_data);
+ qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_notify",
"%d bytes expected but got %d bytes\n",
@@ -560,7 +559,7 @@ static void _qq_send_packet_file_notifyip(PurpleConnection *gc, guint32 to_uid)
static void _qq_send_packet_file_reject (PurpleConnection *gc, guint32 to_uid)
{
qq_data *qd;
- guint8 *cursor, *raw_data;
+ guint8 *raw_data;
gint packet_len, bytes;
purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_reject", "start");
@@ -568,14 +567,12 @@ static void _qq_send_packet_file_reject (PurpleConnection *gc, guint32 to_uid)
packet_len = 64;
raw_data = g_newa (guint8, packet_len);
- cursor = raw_data;
bytes = 0;
- bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_DENY_UDP, qd, TRUE);
+ bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_DENY_UDP, qd, TRUE);
if (packet_len == bytes)
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
- cursor - raw_data);
+ qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file",
"%d bytes expected but got %d bytes\n",
@@ -586,7 +583,7 @@ static void _qq_send_packet_file_reject (PurpleConnection *gc, guint32 to_uid)
static void _qq_send_packet_file_cancel (PurpleConnection *gc, guint32 to_uid)
{
qq_data *qd;
- guint8 *cursor, *raw_data;
+ guint8 *raw_data;
gint packet_len, bytes;
purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "start\n");
@@ -594,17 +591,15 @@ static void _qq_send_packet_file_cancel (PurpleConnection *gc, guint32 to_uid)
packet_len = 64;
raw_data = g_newa (guint8, packet_len);
- cursor = raw_data;
bytes = 0;
purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "before create header\n");
- bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_CANCEL, qd, TRUE);
+ bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_CANCEL, qd, TRUE);
purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "end create header\n");
if (packet_len == bytes) {
purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "before send cmd\n");
- qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
- cursor - raw_data);
+ qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data, bytes);
}
else
purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file",
@@ -688,7 +683,7 @@ static void _qq_xfer_recv_init(PurpleXfer *xfer)
}
/* process reject im for file transfer request */
-void qq_process_recv_file_reject (guint8 *data, guint8 **cursor, gint data_len,
+void qq_process_recv_file_reject (guint8 *data, gint data_len,
guint32 sender_uid, PurpleConnection *gc)
{
gchar *msg, *filename;
@@ -698,11 +693,13 @@ void qq_process_recv_file_reject (guint8 *data, guint8 **cursor, gint data_len,
qd = (qq_data *) gc->proto_data;
g_return_if_fail (qd->xfer != NULL);
+ /* border has been checked before
if (*cursor >= (data + data_len - 1)) {
purple_debug (PURPLE_DEBUG_WARNING, "QQ",
"Received file reject message is empty\n");
return;
}
+ */
filename = strrchr(purple_xfer_get_local_filename(qd->xfer), '/') + 1;
msg = g_strdup_printf(_("%d has declined the file %s"),
sender_uid, filename);
@@ -715,7 +712,7 @@ void qq_process_recv_file_reject (guint8 *data, guint8 **cursor, gint data_len,
}
/* process cancel im for file transfer request */
-void qq_process_recv_file_cancel (guint8 *data, guint8 **cursor, gint data_len,
+void qq_process_recv_file_cancel (guint8 *data, gint data_len,
guint32 sender_uid, PurpleConnection *gc)
{
gchar *msg, *filename;
@@ -726,11 +723,13 @@ void qq_process_recv_file_cancel (guint8 *data, guint8 **cursor, gint data_len,
g_return_if_fail (qd->xfer != NULL
&& purple_xfer_get_filename(qd->xfer) != NULL);
+ /* border has been checked before
if (*cursor >= (data + data_len - 1)) {
purple_debug (PURPLE_DEBUG_WARNING, "QQ",
"Received file reject message is empty\n");
return;
}
+ */
filename = strrchr(purple_xfer_get_local_filename(qd->xfer), '/') + 1;
msg = g_strdup_printf
(_("%d canceled the transfer of %s"),
@@ -744,27 +743,26 @@ void qq_process_recv_file_cancel (guint8 *data, guint8 **cursor, gint data_len,
}
/* process accept im for file transfer request */
-void qq_process_recv_file_accept(guint8 *data, guint8 **cursor, gint data_len,
- guint32 sender_uid, PurpleConnection *gc)
+void qq_process_recv_file_accept(guint8 *data, gint data_len, guint32 sender_uid, PurpleConnection *gc)
{
qq_data *qd;
+ gint bytes;
ft_info *info;
PurpleXfer *xfer;
g_return_if_fail (data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
xfer = qd->xfer;
+ info = (ft_info *) qd->xfer->data;
- if (*cursor >= (data + data_len - 1)) {
+ if (data_len <= 30 + QQ_CONN_INFO_LEN) {
purple_debug (PURPLE_DEBUG_WARNING, "QQ",
"Received file reject message is empty\n");
return;
}
- info = (ft_info *) qd->xfer->data;
-
- *cursor = data + 18 + 12;
- qq_get_conn_info(data, cursor, data_len, info);
+ bytes = 18 + 12; /* skip 30 bytes */
+ qq_get_conn_info(info, data + bytes);
_qq_xfer_init_socket(qd->xfer);
_qq_xfer_init_udp_channel(info);
@@ -772,8 +770,7 @@ void qq_process_recv_file_accept(guint8 *data, guint8 **cursor, gint data_len,
}
/* process request from buddy's im for file transfer request */
-void qq_process_recv_file_request(guint8 *data, guint8 **cursor, gint data_len,
- guint32 sender_uid, PurpleConnection * gc)
+void qq_process_recv_file_request(guint8 *data, gint data_len, guint32 sender_uid, PurpleConnection * gc)
{
qq_data *qd;
PurpleXfer *xfer;
@@ -781,25 +778,27 @@ void qq_process_recv_file_request(guint8 *data, guint8 **cursor, gint data_len,
ft_info *info;
PurpleBuddy *b;
qq_buddy *q_bud;
+ gint bytes;
g_return_if_fail (data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- if (*cursor >= (data + data_len - 1)) {
- purple_debug (PURPLE_DEBUG_WARNING, "QQ",
- "Received file reject message is empty\n");
- return;
- }
-
- info = g_new0(ft_info, 1);
+ info = g_newa(ft_info, 1);
info->local_internet_ip = g_ntohl(inet_addr(qd->my_ip));
info->local_internet_port = qd->my_port;
info->local_real_ip = 0x00000000;
info->to_uid = sender_uid;
- read_packet_w(data, cursor, data_len, &(info->send_seq));
+
+ if (data_len <= 2 + 30 + QQ_CONN_INFO_LEN) {
+ purple_debug (PURPLE_DEBUG_WARNING, "QQ",
+ "Received file request message is empty\n");
+ return;
+ }
+ bytes = 0;
+ bytes += qq_get16(&(info->send_seq), data + bytes);
- *cursor = data + 18 + 12;
- qq_get_conn_info(data, cursor, data_len, info);
+ bytes += 18 + 12; /* skip 30 bytes */
+ bytes += qq_get_conn_info(info, data + bytes);
fileinfo = g_strsplit((gchar *) (data + 81 + 12), "\x1f", 2);
g_return_if_fail (fileinfo != NULL && fileinfo[0] != NULL && fileinfo[1] != NULL);
@@ -880,9 +879,10 @@ static void _qq_xfer_send_notify_ip_ack(gpointer data, gint source, PurpleInputC
*/
}
-void qq_process_recv_file_notify(guint8 *data, guint8 **cursor, gint data_len,
+void qq_process_recv_file_notify(guint8 *data, gint data_len,
guint32 sender_uid, PurpleConnection *gc)
{
+ gint bytes;
qq_data *qd;
ft_info *info;
PurpleXfer *xfer;
@@ -890,19 +890,19 @@ void qq_process_recv_file_notify(guint8 *data, guint8 **cursor, gint data_len,
g_return_if_fail (data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- if (*cursor >= (data + data_len - 1)) {
+ xfer = qd->xfer;
+ info = (ft_info *) qd->xfer->data;
+ if (data_len <= 2 + 30 + QQ_CONN_INFO_LEN) {
purple_debug (PURPLE_DEBUG_WARNING, "QQ",
"Received file notify message is empty\n");
return;
}
+
+ bytes = 0;
+ bytes += qq_get16(&(info->send_seq), data + bytes);
- xfer = qd->xfer;
- info = (ft_info *) qd->xfer->data;
- /* FIXME */
- read_packet_w(data, cursor, data_len, &(info->send_seq));
-
- *cursor = data + 18 + 12;
- qq_get_conn_info(data, cursor, data_len, info);
+ bytes += 18 + 12;
+ bytes += qq_get_conn_info(info, data + bytes);
_qq_xfer_init_udp_channel(info);
diff --git a/libpurple/protocols/qq/send_file.h b/libpurple/protocols/qq/send_file.h
index 20295d596e..e3ed1723c9 100644
--- a/libpurple/protocols/qq/send_file.h
+++ b/libpurple/protocols/qq/send_file.h
@@ -66,20 +66,15 @@ typedef struct _ft_info {
gboolean use_major;
} ft_info;
-void qq_process_recv_file_accept(guint8 *data, guint8 **cursor, gint data_len,
- guint32 sender_uid, PurpleConnection *gc);
-void qq_process_recv_file_reject(guint8 *data, guint8 **cursor, gint data_len,
- guint32 sender_uid, PurpleConnection *gc);
-void qq_process_recv_file_cancel(guint8 *data, guint8 **cursor, gint data_len,
- guint32 sender_uid, PurpleConnection *gc);
-void qq_process_recv_file_request(guint8 *data, guint8 **cursor, gint data_len,
- guint32 sender_uid, PurpleConnection *gc);
-void qq_process_recv_file_notify(guint8 *data, guint8 **cursor, gint data_len,
- guint32 sender_uid, PurpleConnection *gc);
+void qq_process_recv_file_accept(guint8 *data, gint data_len, guint32 sender_uid, PurpleConnection *gc);
+void qq_process_recv_file_reject(guint8 *data, gint data_len, guint32 sender_uid, PurpleConnection *gc);
+void qq_process_recv_file_cancel(guint8 *data, gint data_len, guint32 sender_uid, PurpleConnection *gc);
+void qq_process_recv_file_request(guint8 *data, gint data_len, guint32 sender_uid, PurpleConnection *gc);
+void qq_process_recv_file_notify(guint8 *data, gint data_len, guint32 sender_uid, PurpleConnection *gc);
gboolean qq_can_receive_file(PurpleConnection *gc, const char *who);
void qq_send_file(PurpleConnection *gc, const char *who, const char *file);
-void qq_get_conn_info(guint8 *data, guint8 **cursor, gint data_len, ft_info *info);
-gint qq_fill_conn_info(guint8 *data, guint8 **cursor, ft_info *info);
+gint qq_get_conn_info(ft_info *info, guint8 *data);
+gint qq_fill_conn_info(guint8 *data, ft_info *info);
gssize _qq_xfer_write(const guint8 *buf, size_t len, PurpleXfer *xfer);
#endif
diff --git a/libpurple/protocols/qq/sys_msg.c b/libpurple/protocols/qq/sys_msg.c
index fe63606c40..a201a5716c 100644
--- a/libpurple/protocols/qq/sys_msg.c
+++ b/libpurple/protocols/qq/sys_msg.c
@@ -120,7 +120,7 @@ static void _qq_search_before_add_with_gc_and_uid(gc_and_uid *g)
/* Send ACK if the sys message needs an ACK */
static void _qq_send_packet_ack_msg_sys(PurpleConnection *gc, guint8 code, guint32 from, guint16 seq)
{
- guint8 bar, *ack, *cursor;
+ guint8 bar, *ack;
gchar *str;
gint ack_len, bytes;
@@ -128,14 +128,13 @@ static void _qq_send_packet_ack_msg_sys(PurpleConnection *gc, guint8 code, guint
bar = 0x1e;
ack_len = 1 + 1 + strlen(str) + 1 + 2;
ack = g_newa(guint8, ack_len);
- cursor = ack;
- bytes = 0;
- bytes += create_packet_b(ack, &cursor, code);
- bytes += create_packet_b(ack, &cursor, bar);
- bytes += create_packet_data(ack, &cursor, (guint8 *) str, strlen(str));
- bytes += create_packet_b(ack, &cursor, bar);
- bytes += create_packet_w(ack, &cursor, seq);
+ bytes = 0;
+ bytes += qq_put8(ack + bytes, code);
+ bytes += qq_put8(ack + bytes, bar);
+ bytes += qq_putdata(ack + bytes, (guint8 *) str, strlen(str));
+ bytes += qq_put8(ack + bytes, bar);
+ bytes += qq_put16(ack + bytes, seq);
g_free(str);