pidgin: 6b89b377: 2008.08.10 - csyfek <csyfek(at)gmail.com...
csyfek at gmail.com
csyfek at gmail.com
Sun Aug 10 00:36:01 EDT 2008
-----------------------------------------------------------------
Revision: 6b89b377381e35b459936fd2f730f45b5558ae69
Ancestor: 4d36ca589250afa99189df464a7700bc0b38b3c4
Author: csyfek at gmail.com
Date: 2008-08-10T04:32:14
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/6b89b377381e35b459936fd2f730f45b5558ae69
Deleted entries:
libpurple/protocols/qq/crypt.c
libpurple/protocols/qq/crypt.h
libpurple/protocols/qq/group_network.c
libpurple/protocols/qq/group_network.h
Added files:
libpurple/protocols/qq/qq_crypt.c
libpurple/protocols/qq/qq_crypt.h
Modified files:
libpurple/protocols/qq/ChangeLog
libpurple/protocols/qq/Makefile.am
libpurple/protocols/qq/Makefile.mingw
libpurple/protocols/qq/buddy_info.c
libpurple/protocols/qq/buddy_info.h
libpurple/protocols/qq/buddy_list.c
libpurple/protocols/qq/buddy_list.h
libpurple/protocols/qq/buddy_opt.c
libpurple/protocols/qq/buddy_opt.h
libpurple/protocols/qq/file_trans.c
libpurple/protocols/qq/group.c
libpurple/protocols/qq/group.h
libpurple/protocols/qq/group_find.c
libpurple/protocols/qq/group_find.h
libpurple/protocols/qq/group_free.c
libpurple/protocols/qq/group_free.h
libpurple/protocols/qq/group_im.c
libpurple/protocols/qq/group_im.h
libpurple/protocols/qq/group_info.c
libpurple/protocols/qq/group_info.h
libpurple/protocols/qq/group_internal.c
libpurple/protocols/qq/group_internal.h
libpurple/protocols/qq/group_join.c
libpurple/protocols/qq/group_join.h
libpurple/protocols/qq/group_opt.c
libpurple/protocols/qq/group_opt.h
libpurple/protocols/qq/group_search.c
libpurple/protocols/qq/header_info.c
libpurple/protocols/qq/header_info.h
libpurple/protocols/qq/im.c libpurple/protocols/qq/im.h
libpurple/protocols/qq/packet_parse.h
libpurple/protocols/qq/qq.c libpurple/protocols/qq/qq.h
libpurple/protocols/qq/qq_base.c
libpurple/protocols/qq/qq_base.h
libpurple/protocols/qq/qq_network.c
libpurple/protocols/qq/qq_network.h
libpurple/protocols/qq/qq_process.c
libpurple/protocols/qq/qq_process.h
libpurple/protocols/qq/qq_trans.c
libpurple/protocols/qq/qq_trans.h
libpurple/protocols/qq/send_file.c
libpurple/protocols/qq/sys_msg.c
libpurple/protocols/qq/sys_msg.h
libpurple/protocols/qq/utils.c
ChangeLog:
2008.08.10 - csyfek <csyfek(at)gmail.com>
* Commit to Pidgin
2008.08.06 - ccpaging <ecc_hy(at)hotmail.com>
* Rename names of variables, Group, to Room
* Functions of group_network merged into qq_network and qq_process
* Canceled managing glist of group packet, add sub_cmdd and room_id to transaction
* Fixed error of demo group:
If 'room list' and 'room infor' are not setup, response received from server will emits
'room_id = 0' packet.
2008.08.04 - ccpaging <ecc_hy(at)hotmail.com>
* Use new crypt/decrypt functions
* Rename crypt.c/h to qq_crypt.c/h
* Clean code of decrypt functions
* Fixed decryption failure
2008.08.04 - csyfek <csyfek(at)gmail.com>
* Update AUTHORS
-------------- next part --------------
============================================================
--- libpurple/protocols/qq/qq_crypt.c cbc1c094ddb46b157dbc6d3a713fa879a941352b
+++ libpurple/protocols/qq/qq_crypt.c cbc1c094ddb46b157dbc6d3a713fa879a941352b
@@ -0,0 +1,330 @@
+/**
+ * @file qq_crypt.c
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * QQ encryption algorithm
+ * Convert from ASM code provided by PerlOICQ
+ *
+ * Puzzlebird, Nov-Dec 2002
+ */
+
+/* Notes: (QQ uses 16 rounds, and modified something...)
+
+IN : 64 bits of data in v[0] - v[1].
+OUT: 64 bits of data in w[0] - w[1].
+KEY: 128 bits of key in k[0] - k[3].
+
+delta is chosen to be the real part of
+the golden ratio: Sqrt(5/4) - 1/2 ~ 0.618034 multiplied by 2^32.
+
+0x61C88647 is what we can track on the ASM codes.!!
+*/
+
+#include <string.h>
+
+#include "debug.h"
+#include "qq_crypt.h"
+
+#if 0
+void show_binary(char *psztitle, const guint8 *const buffer, gint bytes)
+{
+ printf("== %s %d ==\r\n", psztitle, bytes);
+ gint i, j, ch;
+ for (i = 0; i < bytes; i += 16) {
+ /* length label */
+ printf("%07x: ", i);
+
+ /* dump hex value */
+ for (j = 0; j < 16; j++) {
+ if (j == 8) {
+ printf(" -");
+ }
+ if ((i + j) < bytes)
+ printf(" %02x", buffer[i + j]);
+ else
+ printf(" ");
+ }
+
+ printf(" ");
+
+
+ /* dump ascii value */
+ for (j = 0; j < 16 && (i + j) < bytes; j++) {
+ ch = buffer[i + j] & 127;
+ if (ch < ' ' || ch == 127)
+ printf(".");
+ else
+ printf("%c", ch);
+ }
+ printf("\r\n");
+ }
+ printf("========\r\n");
+}
+#else
+
+#define show_binary(args... ) /* nothing */
+
+#endif
+
+/********************************************************************
+ * encryption
+ *******************************************************************/
+
+/* Tiny Encryption Algorithm (TEA) */
+static inline void qq_encipher(guint32 *const v, const guint32 *const k, guint32 *const w)
+{
+ register guint32
+ y = g_ntohl(v[0]),
+ z = g_ntohl(v[1]),
+ a = g_ntohl(k[0]),
+ b = g_ntohl(k[1]),
+ c = g_ntohl(k[2]),
+ d = g_ntohl(k[3]),
+ n = 0x10,
+ sum = 0,
+ delta = 0x9E3779B9; /* 0x9E3779B9 - 0x100000000 = -0x61C88647 */
+
+ while (n-- > 0) {
+ sum += delta;
+ y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
+ z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
+ }
+
+ w[0] = g_htonl(y);
+ w[1] = g_htonl(z);
+}
+
+/* it can be the real random seed function */
+/* override with number, convenient for debug */
+#ifdef DEBUG
+static gint crypt_rand(void) {
+ return 0xdead;
+}
+#else
+#include <stdlib.h>
+#define crypt_rand() rand()
+#endif
+
+/* 64-bit blocks and some kind of feedback mode of operation */
+static inline void encrypt_out(guint8 *crypted, const gint crypted_len, const guint8 *key)
+{
+ /* ships in encipher */
+ guint32 plain32[2];
+ guint32 p32_prev[2];
+ guint32 key32[4];
+ guint32 crypted32[2];
+ guint32 c32_prev[2];
+
+ guint8 *crypted_ptr;
+ gint count64;
+
+ /* prepare at first */
+ crypted_ptr = crypted;
+
+ memcpy(crypted32, crypted_ptr, sizeof(crypted32));
+ c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1];
+
+ p32_prev[0] = 0; p32_prev[1] = 0;
+ plain32[0] = crypted32[0] ^ p32_prev[0]; plain32[1] = crypted32[1] ^ p32_prev[1];
+
+ g_memmove(key32, key, 16);
+ count64 = crypted_len / 8;
+ while (count64-- > 0){
+ /* encrypt it */
+ qq_encipher(plain32, key32, crypted32);
+
+ crypted32[0] ^= p32_prev[0]; crypted32[1] ^= p32_prev[1];
+
+ /* store curr 64 bits crypted */
+ g_memmove(crypted_ptr, crypted32, sizeof(crypted32));
+
+ /* set prev */
+ p32_prev[0] = plain32[0]; p32_prev[1] = plain32[1];
+ c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1];
+
+ /* set next 64 bits want to crypt*/
+ crypted_ptr += 8;
+ memcpy(crypted32, crypted_ptr, sizeof(crypted32));
+ plain32[0] = crypted32[0] ^ c32_prev[0]; plain32[1] = crypted32[1] ^ c32_prev[1];
+ }
+}
+
+/* length of crypted buffer must be plain_len + 16*/
+gint qq_encrypt(guint8* crypted, const guint8* const plain, const gint plain_len, const guint8* const key)
+{
+ guint8 *crypted_ptr = crypted; /* current position of dest */
+ gint pos, padding;
+
+ padding = (plain_len + 10) % 8;
+ if (padding) {
+ padding = 8 - padding;
+ }
+
+ pos = 0;
+
+ /* set first byte as padding len */
+ crypted_ptr[pos] = (rand() & 0xf8) | padding;
+ pos++;
+
+ /* extra 2 bytes */
+ padding += 2;
+
+ /* faster a little
+ memset(crypted_ptr + pos, rand() & 0xff, padding);
+ pos += padding;
+ */
+
+ /* more random */
+ while (padding--) {
+ crypted_ptr[pos++] = rand() & 0xff;
+ }
+
+ g_memmove(crypted_ptr + pos, plain, plain_len);
+ pos += plain_len;
+
+ /* header padding len + plain len must be multiple of 8
+ * tail pading len is always 8 - (1st byte)
+ */
+ memset(crypted_ptr + pos, 0x00, 7);
+ pos += 7;
+
+ show_binary("After padding", crypted, pos);
+
+ encrypt_out(crypted, pos, key);
+
+ show_binary("Encrypted", crypted, pos);
+ return pos;
+}
+
+/********************************************************************
+ * decryption
+ ********************************************************************/
+
+static inline void qq_decipher(guint32 *const v, const guint32 *const k, guint32 *const w)
+{
+ register guint32
+ y = g_ntohl(v[0]),
+ z = g_ntohl(v[1]),
+ a = g_ntohl(k[0]),
+ b = g_ntohl(k[1]),
+ c = g_ntohl(k[2]),
+ d = g_ntohl(k[3]),
+ n = 0x10,
+ sum = 0xE3779B90, /* why this ? must be related with n value */
+ delta = 0x9E3779B9;
+
+ /* sum = delta<<5, in general sum = delta * n */
+ while (n-- > 0) {
+ z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
+ y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
+ sum -= delta;
+ }
+
+ w[0] = g_htonl(y);
+ w[1] = g_htonl(z);
+}
+
+static inline gint decrypt_out(guint8 *dest, gint crypted_len, const guint8* const key)
+{
+ gint plain_len;
+ guint32 key32[4];
+ guint32 crypted32[2];
+ guint32 c32_prev[2];
+ guint32 plain32[2];
+ guint32 p32_prev[2];
+ gint count64;
+ gint padding;
+ guint8 *crypted_ptr = dest;
+
+ /* decrypt first 64 bit */
+ memcpy(key32, key, sizeof(key32));
+ memcpy(crypted32, crypted_ptr, sizeof(crypted32));
+ c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1];
+
+ qq_decipher(crypted32, key32, p32_prev);
+ memcpy(crypted_ptr, p32_prev, sizeof(p32_prev));
+
+ /* check padding len */
+ padding = 2 + (crypted_ptr[0] & 0x7);
+ if (padding < 2) {
+ padding += 8;
+ }
+ plain_len = crypted_len - 1 - padding - 7;
+ if( plain_len < 0 ) {
+ return -2;
+ }
+
+ count64 = crypted_len / 8;
+ while (count64-- > 0){
+ c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1];
+ crypted_ptr += 8;
+
+ memcpy(crypted32, crypted_ptr, sizeof(crypted32));
+ p32_prev[0] ^= crypted32[0]; p32_prev[1] ^= crypted32[1];
+
+ qq_decipher(p32_prev, key32, p32_prev);
+
+ plain32[0] = p32_prev[0] ^ c32_prev[0]; plain32[1] = p32_prev[1] ^ c32_prev[1];
+ memcpy(crypted_ptr, plain32, sizeof(plain32));
+ }
+
+ return plain_len;
+}
+
+/* length of plain buffer must be equal to crypted_len */
+gint qq_decrypt(guint8 *plain, const guint8* const crypted, const gint crypted_len, const guint8* const key)
+{
+ gint plain_len = 0;
+ gint hdr_padding;
+ gint pos;
+
+ /* at least 16 bytes and %8 == 0 */
+ if ((crypted_len % 8) || (crypted_len < 16)) {
+ return -1;
+ }
+
+ memcpy(plain, crypted, crypted_len);
+
+ plain_len = decrypt_out(plain, crypted_len, key);
+ if (plain_len < 0) {
+ return plain_len; /* invalid first 64 bits */
+ }
+
+ show_binary("Decrypted with padding", plain, crypted_len);
+
+ /* check last 7 bytes is zero or not? */
+ for (pos = crypted_len - 1; pos > crypted_len - 8; pos--) {
+ if (plain[pos] != 0) {
+ return -3;
+ }
+ }
+ if (plain_len == 0) {
+ return plain_len;
+ }
+
+ hdr_padding = crypted_len - plain_len - 7;
+ g_memmove(plain, plain + hdr_padding, plain_len);
+
+ return plain_len;
+}
+
============================================================
--- libpurple/protocols/qq/qq_crypt.h f8a5c4f188175d5e04e864b0160dad3006dd000c
+++ libpurple/protocols/qq/qq_crypt.h f8a5c4f188175d5e04e864b0160dad3006dd000c
@@ -0,0 +1,33 @@
+ /**
+ * @file qq_crypt.h
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _QQ_CRYPT_H_
+#define _QQ_CRYPT_H_
+
+#include <glib.h>
+
+gint qq_encrypt(guint8* crypted, const guint8* const plain, const gint plain_len, const guint8* const key);
+
+gint qq_decrypt(guint8 *plain, const guint8* const crypted, const gint crypted_len, const guint8* const key);
+#endif
============================================================
--- libpurple/protocols/qq/ChangeLog e8dd5eb3ab6025809bdca23140286e3b1c465b96
+++ libpurple/protocols/qq/ChangeLog 4ed95b382ab28c61dc0a3833a75d776e61952d5e
@@ -1,3 +1,22 @@
+2008.08.10 - csyfek <csyfek(at)gmail.com>
+ * Commit to Pidgin
+
+2008.08.06 - ccpaging <ecc_hy(at)hotmail.com>
+ * Rename names of variables, Group, to Room
+ * Functions of group_network merged into qq_network and qq_process
+ * Canceled managing glist of group packet, add sub_cmdd and room_id to transaction
+ * Fixed error of demo group:
+ If 'room list' and 'room infor' are not setup, response received from server will emits 'room_id = 0' packet.
+
+2008.08.04 - ccpaging <ecc_hy(at)hotmail.com>
+ * Use new crypt/decrypt functions
+ * Rename crypt.c/h to qq_crypt.c/h
+ * Clean code of decrypt functions
+ * Fixed decryption failure
+
+2008.08.04 - csyfek <csyfek(at)gmail.com>
+ * Update AUTHORS
+
2008.08.03 - csyfek <csyfek(at)gmail.com>
* Commit lost files to Pidgin
============================================================
--- libpurple/protocols/qq/Makefile.am ff326d6ead2597bd6b18c857daefd45e9451763b
+++ libpurple/protocols/qq/Makefile.am fed4df19dbb26165288380bca5a1690fc6080ec4
@@ -12,8 +12,8 @@ QQSOURCES = \
buddy_opt.h \
char_conv.c \
char_conv.h \
- crypt.c \
- crypt.h \
+ qq_crypt.c \
+ qq_crypt.h \
file_trans.c \
file_trans.h \
group.c \
@@ -32,8 +32,6 @@ QQSOURCES = \
group_info.h \
group_join.c \
group_join.h \
- group_network.c \
- group_network.h \
group_opt.c \
group_opt.h \
group_search.c \
============================================================
--- libpurple/protocols/qq/Makefile.mingw dc491660a61cc5a7e282872220d21bddaec33c70
+++ libpurple/protocols/qq/Makefile.mingw b552726dd7a32b1039c146293b39fbba60bda1d1
@@ -43,7 +43,7 @@ C_SRC = \
buddy_list.c \
buddy_opt.c \
char_conv.c \
- crypt.c \
+ qq_crypt.c \
file_trans.c \
group.c \
group_conv.c \
@@ -53,18 +53,17 @@ C_SRC = \
group_im.c \
group_info.c \
group_join.c \
- group_network.c \
group_opt.c \
group_search.c \
header_info.c \
im.c \
+ qq_process.c \
+ qq_base.c \
packet_parse.c \
qq.c \
- qq_base.c \
qq_network.c \
- qq_process.c \
+ send_file.c \
qq_trans.c \
- send_file.c \
sys_msg.c \
utils.c
============================================================
--- libpurple/protocols/qq/buddy_info.c 9d5e271dfec3c9a89f7470d2af373ba227d1f0f9
+++ libpurple/protocols/qq/buddy_info.c 83e9954420861fa2cae9a61edd172acad03bc383
@@ -32,7 +32,6 @@
#include "buddy_list.h"
#include "buddy_info.h"
#include "char_conv.h"
-#include "crypt.h"
#include "header_info.h"
#include "qq_base.h"
#include "qq_network.h"
@@ -688,26 +687,18 @@ static void create_modify_info_dialogue(
}
/* process the reply of modify_info packet */
-void qq_process_modify_info_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_modify_info_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len;
- guint8 *data;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- data[len] = '\0';
- if (qd->uid == atoi((gchar *) data)) { /* return should be my uid */
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Update info ACK OK\n");
- purple_notify_info(gc, NULL, _("Your information has been updated"), NULL);
- }
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt modify info reply\n");
+ data[data_len] = '\0';
+ if (qd->uid == atoi((gchar *) data)) { /* return should be my uid */
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Update info ACK OK\n");
+ purple_notify_info(gc, NULL, _("Your information has been updated"), NULL);
}
}
@@ -858,10 +849,8 @@ static void qq_refresh_buddy_and_myself(
}
/* process reply to get_info packet */
-void qq_process_get_info_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_get_info_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
- gint len;
- guint8 *data;
gchar **segments;
qq_info_query *query;
qq_data *qd;
@@ -869,52 +858,46 @@ void qq_process_get_info_reply(guint8 *b
GList *list, *query_list;
PurpleNotifyUserInfo *user_info;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
list = query_list = NULL;
- len = buf_len;
- data = g_newa(guint8, len);
info = NULL;
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- if (NULL == (segments = split_data(data, len, "\x1e", QQ_CONTACT_FIELDS)))
- return;
+ if (NULL == (segments = split_data(data, data_len, "\x1e", QQ_CONTACT_FIELDS)))
+ return;
- info = (contact_info *) segments;
- if (qd->modifying_face && strtol(info->face, NULL, 10) != qd->my_icon) {
- gchar *icon = g_strdup_printf("%d", qd->my_icon);
- qd->modifying_face = FALSE;
- g_free(info->face);
- info->face = icon;
- qq_send_packet_modify_info(gc, (contact_info *)segments);
- }
+ info = (contact_info *) segments;
+ if (qd->modifying_face && strtol(info->face, NULL, 10) != qd->my_icon) {
+ gchar *icon = g_strdup_printf("%d", qd->my_icon);
+ qd->modifying_face = FALSE;
+ g_free(info->face);
+ info->face = icon;
+ qq_send_packet_modify_info(gc, (contact_info *)segments);
+ }
- qq_refresh_buddy_and_myself(info, gc);
+ qq_refresh_buddy_and_myself(info, gc);
- query_list = qd->info_query;
- /* ensure we're processing the right query */
- while (query_list) {
- query = (qq_info_query *) query_list->data;
- if (query->uid == atoi(info->uid)) {
- if (query->show_window) {
- user_info = info_to_notify_user_info(info);
- purple_notify_userinfo(gc, info->uid, user_info, NULL, NULL);
- purple_notify_user_info_destroy(user_info);
- } else if (query->modify_info) {
- create_modify_info_dialogue(gc, info);
- }
- qd->info_query = g_list_remove(qd->info_query, qd->info_query->data);
- g_free(query);
- break;
+ query_list = qd->info_query;
+ /* ensure we're processing the right query */
+ while (query_list) {
+ query = (qq_info_query *) query_list->data;
+ if (query->uid == atoi(info->uid)) {
+ if (query->show_window) {
+ user_info = info_to_notify_user_info(info);
+ purple_notify_userinfo(gc, info->uid, user_info, NULL, NULL);
+ purple_notify_user_info_destroy(user_info);
+ } else if (query->modify_info) {
+ create_modify_info_dialogue(gc, info);
}
- query_list = query_list->next;
+ qd->info_query = g_list_remove(qd->info_query, qd->info_query->data);
+ g_free(query);
+ break;
}
+ query_list = query_list->next;
+ }
- g_strfreev(segments);
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt get info reply\n");
- }
+ g_strfreev(segments);
}
void qq_info_query_free(qq_data *qd)
@@ -975,25 +958,18 @@ void qq_send_packet_get_buddies_levels(P
qq_send_cmd(qd, QQ_CMD_GET_LEVEL, buf, size);
}
-void qq_process_get_level_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_get_level_reply(guint8 *decr_buf, gint decr_len, PurpleConnection *gc)
{
guint32 uid, onlineTime;
guint16 level, timeRemainder;
gchar *purple_name;
PurpleBuddy *b;
qq_buddy *q_bud;
- gint decr_len, i;
- guint8 *decr_buf;
+ gint i;
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)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Couldn't decrypt get level packet\n");
- }
-
decr_len--;
if (decr_len % 12 != 0) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
@@ -1014,25 +990,34 @@ void qq_process_get_level_reply(guint8 *
purple_debug(PURPLE_DEBUG_INFO, "QQ_LEVEL",
"%d, tmOnline: %d, level: %d, tmRemainder: %d\n",
uid, onlineTime, level, timeRemainder);
+ if (uid == qd->uid) {
+ qd->my_level = level;
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Got my levels as %d\n", qd->my_level);
+ continue;
+ }
+
purple_name = uid_to_purple_name(uid);
+ if (purple_name == NULL) {
+ continue;
+ }
+
b = purple_find_buddy(account, purple_name);
- q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
+ g_free(purple_name);
- if (q_bud != NULL || uid == qd->uid) {
- if (q_bud) {
- q_bud->onlineTime = onlineTime;
- q_bud->level = level;
- q_bud->timeRemainder = timeRemainder;
- }
- if (uid == qd->uid) {
- qd->my_level = level;
- }
- } else {
+ q_bud = NULL;
+ if (b != NULL) {
+ q_bud = (qq_buddy *) b->proto_data;
+ }
+
+ if (q_bud == NULL) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Got an online buddy %d, but not in my buddy list\n", uid);
+ "Got levels of %d not in my buddy list\n", uid);
+ continue;
}
- g_free(purple_name);
+
+ q_bud->onlineTime = onlineTime;
+ q_bud->level = level;
+ q_bud->timeRemainder = timeRemainder;
}
- g_free(decr_buf);
}
============================================================
--- libpurple/protocols/qq/buddy_info.h b63009733e1b5cca08c936c36e4f8cef73b61918
+++ libpurple/protocols/qq/buddy_info.h 62ff812350c859993cfed122110108f0d87b0b1b
@@ -71,8 +71,8 @@ void qq_prepare_modify_info(PurpleConnec
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);
void qq_prepare_modify_info(PurpleConnection *gc);
-void qq_process_modify_info_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
-void qq_process_get_info_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
+void qq_process_modify_info_reply(guint8 *data, gint data_len, PurpleConnection *gc);
+void qq_process_get_info_reply(guint8 *data, gint data_len, PurpleConnection *gc);
void qq_info_query_free(qq_data *qd);
void qq_send_packet_get_level(PurpleConnection *gc, guint32 uid);
void qq_send_packet_get_buddies_levels(PurpleConnection *gc);
============================================================
--- libpurple/protocols/qq/buddy_list.c 76d8307bbed0e359d116c9dc2ef1a14220fb68e0
+++ libpurple/protocols/qq/buddy_list.c 19f9e2ad310d5eb343b54d6bd41b75019994d0ff
@@ -34,7 +34,6 @@
#include "buddy_list.h"
#include "buddy_opt.h"
#include "char_conv.h"
-#include "crypt.h"
#include "header_info.h"
#include "qq_base.h"
#include "group.h"
@@ -103,7 +102,7 @@ void qq_send_packet_get_buddies_list(Pur
}
/* get all list, buddies & Quns with groupsid support */
-void qq_send_packet_get_all_list_with_group(PurpleConnection *gc, guint32 position)
+void qq_send_packet_get_buddies_and_rooms(PurpleConnection *gc, guint32 position)
{
qq_data *qd = (qq_data *) gc->proto_data;
guint8 raw_data[16] = {0};
@@ -117,7 +116,7 @@ void qq_send_packet_get_all_list_with_gr
bytes += qq_put32(raw_data + bytes, 0x00000000);
bytes += qq_put32(raw_data + bytes, position);
- qq_send_cmd(qd, QQ_CMD_GET_ALL_LIST_WITH_GROUP, raw_data, bytes);
+ qq_send_cmd(qd, QQ_CMD_GET_BUDDIES_AND_ROOMS, raw_data, bytes);
}
/* parse the data into qq_buddy_status */
@@ -158,40 +157,32 @@ static gint get_buddy_status(qq_buddy_st
#define QQ_ONLINE_BUDDY_ENTRY_LEN 38
/* process the reply packet for get_buddies_online packet */
-guint8 qq_process_get_buddies_online_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+guint8 qq_process_get_buddies_online_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len, bytes, bytes_buddy;
+ gint bytes, bytes_buddy;
gint count;
- guint8 *data, position;
+ guint8 position;
PurpleBuddy *b;
qq_buddy *q_bud;
qq_buddy_online bo;
+ gchar *purple_name;
- g_return_val_if_fail(buf != NULL && buf_len != 0, -1);
+ g_return_val_if_fail(data != NULL && data_len != 0, -1);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "processing get_buddies_online_reply\n");
-
- if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies online");
- return -1;
- }
-
/* qq_show_packet("Get buddies online reply packet", data, len); */
bytes = 0;
bytes += qq_get8(&position, data + bytes);
count = 0;
- while (bytes < len) {
- if (len - bytes < QQ_ONLINE_BUDDY_ENTRY_LEN) {
+ while (bytes < data_len) {
+ if (data_len - bytes < QQ_ONLINE_BUDDY_ENTRY_LEN) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
"[buddies online] only %d, need %d",
- (len - bytes), QQ_ONLINE_BUDDY_ENTRY_LEN);
+ (data_len - bytes), QQ_ONLINE_BUDDY_ENTRY_LEN);
break;
}
memset(&bo, 0 ,sizeof(bo));
@@ -219,9 +210,22 @@ guint8 qq_process_get_buddies_online_rep
continue;
} /* check if it is a valid entry */
+ if (bo.bs.uid == qd->uid) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "I am in online list %d\n", bo.bs.uid);
+ continue;
+ }
+
/* update buddy information */
- b = purple_find_buddy(purple_connection_get_account(gc),
- uid_to_purple_name(bo.bs.uid) );
+ purple_name = uid_to_purple_name(bo.bs.uid);
+ if (purple_name == NULL) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ",
+ "Got an online buddy %d, but not find purple name\n", bo.bs.uid);
+ continue;
+ }
+ b = purple_find_buddy(purple_connection_get_account(gc), purple_name);
+ g_free(purple_name);
+
q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
if (q_bud == NULL) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
@@ -242,7 +246,7 @@ guint8 qq_process_get_buddies_online_rep
count++;
}
- if(bytes > len) {
+ if(bytes > data_len) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
"qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n");
}
@@ -254,32 +258,31 @@ guint8 qq_process_get_buddies_online_rep
/* process reply for get_buddies_list */
-guint16 qq_process_get_buddies_list_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+guint16 qq_process_get_buddies_list_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
qq_buddy *q_bud;
- gint len, bytes_expected, count;
+ gint bytes_expected, count;
gint bytes, buddy_bytes;
guint16 position, unknown;
- guint8 *data, pascal_len;
+ guint8 pascal_len;
gchar *name;
PurpleBuddy *b;
- g_return_val_if_fail(buf != NULL && buf_len != 0, -1);
+ g_return_val_if_fail(data != NULL && data_len != 0, -1);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt buddies list");
+ if (data_len <= 2) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "empty buddies list");
return -1;
}
+ /* qq_show_packet("QQ get buddies list", data, data_len); */
bytes = 0;
bytes += qq_get16(&position, data + bytes);
/* the following data is buddy list in this packet */
count = 0;
- while (bytes < len) {
+ while (bytes < data_len) {
q_bud = g_new0(qq_buddy, 1);
/* set flag */
buddy_bytes = bytes;
@@ -311,11 +314,11 @@ guint16 qq_process_get_buddies_list_repl
count++;
}
- if (QQ_DEBUG) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "buddy [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n",
- q_bud->uid, q_bud->ext_flag, q_bud->comm_flag, q_bud->nickname);
- }
+#if 1
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "buddy [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n",
+ q_bud->uid, q_bud->ext_flag, q_bud->comm_flag, q_bud->nickname);
+#endif
name = uid_to_purple_name(q_bud->uid);
b = purple_find_buddy(gc->account, name);
@@ -330,7 +333,7 @@ guint16 qq_process_get_buddies_list_repl
qq_update_buddy_contact(gc, q_bud);
}
- if(bytes > len) {
+ if(bytes > data_len) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
"qq_process_get_buddies_list_reply: Dangerous error! maybe protocol changed, notify developers!");
}
@@ -340,36 +343,29 @@ guint16 qq_process_get_buddies_list_repl
return position;
}
-guint32 qq_process_get_all_list_with_group_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len, i, j;
- gint bytes = 0;
- guint8 *data;
+ gint i, j;
+ gint bytes;
guint8 sub_cmd, reply_code;
guint32 unknown, position;
guint32 uid;
guint8 type, groupid;
qq_group *group;
- g_return_val_if_fail(buf != NULL && buf_len != 0, -1);
+ g_return_val_if_fail(data != NULL && data_len != 0, -1);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt all list with group");
- return -1;
- }
-
+ bytes = 0;
bytes += qq_get8(&sub_cmd, data + bytes);
g_return_val_if_fail(sub_cmd == 0x01, -1);
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);
+ "qq_process_get_buddies_and_rooms, %d", reply_code);
}
bytes += qq_get32(&unknown, data + bytes);
@@ -377,7 +373,7 @@ guint32 qq_process_get_all_list_with_gro
/* the following data is all list in this packet */
i = 0;
j = 0;
- while (bytes < len) {
+ while (bytes < data_len) {
/* 00-03: uid */
bytes += qq_get32(&uid, data + bytes);
/* 04: type 0x1:buddy 0x4:Qun */
@@ -398,24 +394,24 @@ guint32 qq_process_get_all_list_with_gro
* qq_send_packet_get_buddies_list */
++i;
} else { /* a group */
- group = qq_group_find_by_id(gc, uid, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, uid);
if(group == NULL) {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "Not find room id %d in qq_process_get_buddies_and_rooms\n", uid);
qq_set_pending_id(&qd->adding_groups_from_server, uid, TRUE);
- group = g_newa(qq_group, 1);
- group->internal_group_id = uid;
- qq_send_cmd_group_get_group_info(gc, group);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, uid);
} else {
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
qq_group_refresh(gc, group);
- qq_send_cmd_group_get_group_info(gc, group);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id);
}
++j;
}
}
- if(bytes > len) {
+ if(bytes > data_len) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "qq_process_get_all_list_with_group_reply: Dangerous error! maybe protocol changed, notify developers!");
+ "qq_process_get_buddies_and_rooms: Dangerous error! maybe protocol changed, notify developers!");
}
purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position);
@@ -505,26 +501,19 @@ void qq_send_packet_change_status(Purple
}
/* parse the reply packet for change_status */
-void qq_process_change_status_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_change_status_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len, bytes;
- guint8 *data, reply;
+ gint bytes;
+ guint8 reply;
PurpleBuddy *b;
qq_buddy *q_bud;
gchar *name;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
-
- 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) {
@@ -543,29 +532,20 @@ void qq_process_change_status_reply(guin
}
/* it is a server message indicating that one of my buddies has changed its status */
-void qq_process_buddy_change_status(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
gint bytes;
guint32 my_uid;
- guint8 *data;
- gint data_len;
PurpleBuddy *b;
qq_buddy *q_bud;
qq_buddy_status bs;
gchar *name;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- data_len = buf_len;
- data = g_newa(guint8, data_len);
- if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &data_len) ) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[buddy status change] Failed decrypt\n");
- return;
- }
-
if (data_len < 35) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[buddy status change] only %d, need 35 bytes\n", data_len);
return;
@@ -606,18 +586,22 @@ void qq_update_buddy_contact(PurpleConne
/*TODO: maybe this should be qq_update_buddy_status() ?*/
void qq_update_buddy_contact(PurpleConnection *gc, qq_buddy *q_bud)
{
- gchar *name;
+ gchar *purple_name;
PurpleBuddy *bud;
gchar *status_id;
g_return_if_fail(q_bud != NULL);
- name = uid_to_purple_name(q_bud->uid);
- bud = purple_find_buddy(gc->account, name);
+ purple_name = uid_to_purple_name(q_bud->uid);
+ if (purple_name == NULL) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Not find purple name: %d\n", q_bud->uid);
+ return;
+ }
+ bud = purple_find_buddy(gc->account, purple_name);
if (bud == NULL) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "unknown buddy: %d\n", q_bud->uid);
- g_free(name);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Not find buddy: %d\n", q_bud->uid);
+ g_free(purple_name);
return;
}
@@ -650,19 +634,19 @@ void qq_update_buddy_contact(PurpleConne
break;
}
purple_debug(PURPLE_DEBUG_INFO, "QQ", "buddy %d %s\n", q_bud->uid, status_id);
- purple_prpl_got_user_status(gc->account, name, status_id, NULL);
+ purple_prpl_got_user_status(gc->account, purple_name, status_id, NULL);
if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE && q_bud->status != QQ_BUDDY_OFFLINE)
- purple_prpl_got_user_status(gc->account, name, "mobile", NULL);
+ purple_prpl_got_user_status(gc->account, purple_name, "mobile", NULL);
else
- purple_prpl_got_user_status_deactive(gc->account, name, "mobile");
+ purple_prpl_got_user_status_deactive(gc->account, purple_name, "mobile");
if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO && q_bud->status != QQ_BUDDY_OFFLINE)
- purple_prpl_got_user_status(gc->account, name, "video", NULL);
+ purple_prpl_got_user_status(gc->account, purple_name, "video", NULL);
else
- purple_prpl_got_user_status_deactive(gc->account, name, "video");
+ purple_prpl_got_user_status_deactive(gc->account, purple_name, "video");
- g_free(name);
+ g_free(purple_name);
}
/* refresh all buddies online/offline,
============================================================
--- libpurple/protocols/qq/buddy_list.h 77ac1b00f63233dda88e29b697645cc01f5493c4
+++ libpurple/protocols/qq/buddy_list.h d69cbb9b2e26383154467b6d47cacbe6d38eb005
@@ -49,13 +49,13 @@ void qq_send_packet_get_buddies_online(P
};
void qq_send_packet_get_buddies_online(PurpleConnection *gc, guint8 position);
-guint8 qq_process_get_buddies_online_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
+guint8 qq_process_get_buddies_online_reply(guint8 *data, gint data_len, PurpleConnection *gc);
void qq_send_packet_get_buddies_list(PurpleConnection *gc, guint16 position);
-guint16 qq_process_get_buddies_list_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
+guint16 qq_process_get_buddies_list_reply(guint8 *data, gint data_len, PurpleConnection *gc);
-void qq_send_packet_get_all_list_with_group(PurpleConnection *gc, guint32 position);
-guint32 qq_process_get_all_list_with_group_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
+void qq_send_packet_get_buddies_and_rooms(PurpleConnection *gc, guint32 position);
+guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConnection *gc);
void qq_refresh_all_buddy_status(PurpleConnection *gc);
@@ -64,8 +64,8 @@ void qq_send_packet_change_status(Purple
gint get_icon_offset(PurpleConnection *gc);
void qq_send_packet_change_status(PurpleConnection *gc);
-void qq_process_change_status_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
-void qq_process_buddy_change_status(guint8 *buf, gint buf_len, PurpleConnection *gc);
+void qq_process_change_status_reply(guint8 *data, gint data_len, PurpleConnection *gc);
+void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc);
void qq_refresh_all_buddy_status(PurpleConnection *gc);
void qq_update_buddy_contact(PurpleConnection *gc, qq_buddy *q_bud);
============================================================
--- libpurple/protocols/qq/buddy_opt.c fb4951e03720cc67cc1fc6cfb53f68a36324f5e6
+++ libpurple/protocols/qq/buddy_opt.c d19581650142be4fa3db797f2ca04efae553818e
@@ -31,7 +31,6 @@
#include "buddy_list.h"
#include "buddy_opt.h"
#include "char_conv.h"
-#include "crypt.h"
#include "header_info.h"
#include "im.h"
#include "qq_base.h"
@@ -252,29 +251,18 @@ void qq_block_buddy_with_gc_and_uid(gc_a
}
/* process reply to add_buddy_auth request */
-void qq_process_add_buddy_auth_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_add_buddy_auth_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len;
- gint bytes = 0;
- guint8 *data, reply;
gchar **segments, *msg_utf8;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- 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) {
+ if (data[0] != 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))) {
+ if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) {
return;
}
msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT);
@@ -286,26 +274,15 @@ void qq_process_add_buddy_auth_reply(gui
}
/* process the server reply for my request to remove a buddy */
-void qq_process_remove_buddy_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_remove_buddy_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len;
- gint bytes = 0;
- guint8 *data, reply;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- 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) {
+ if (data[0] != 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 */
@@ -316,26 +293,15 @@ void qq_process_remove_buddy_reply(guint
}
/* process the server reply for my request to remove myself from a buddy */
-void qq_process_remove_self_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_remove_self_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len;
- gint bytes = 0;
- guint8 *data, reply;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- 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) {
+ if (data[0] != 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 */
@@ -345,23 +311,21 @@ void qq_process_remove_self_reply(guint8
}
}
-void qq_process_add_buddy_reply(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection *gc)
+void qq_process_add_buddy_reply(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc)
{
qq_data *qd;
- gint len, for_uid;
+ gint for_uid;
gchar *msg, **segments, *uid, *reply;
- guint8 *data;
GList *list;
PurpleBuddy *b;
gc_and_uid *g;
qq_add_buddy_request *req;
gchar *nombre;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
for_uid = 0;
qd = (qq_data *) gc->proto_data;
- len = buf_len;
list = qd->add_buddy_request;
while (list != NULL) {
@@ -382,50 +346,45 @@ void qq_process_add_buddy_reply(guint8 *
purple_debug(PURPLE_DEBUG_INFO, "QQ", "Add buddy reply [%d] is for id [%d]\n", seq, for_uid);
}
- data = g_newa(guint8, len);
+ if (NULL == (segments = split_data(data, data_len, "\x1f", 2)))
+ return;
+
+ uid = segments[0];
+ reply = segments[1];
+ if (strtol(uid, NULL, 10) != qd->uid) { /* should not happen */
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Add buddy reply is to [%s], not me!", uid);
+ g_strfreev(segments);
+ return;
+ }
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- if (NULL == (segments = split_data(data, len, "\x1f", 2)))
- return;
- uid = segments[0];
- reply = segments[1];
- if (strtol(uid, NULL, 10) != qd->uid) { /* should not happen */
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Add buddy reply is to [%s], not me!", uid);
- g_strfreev(segments);
- return;
- }
-
- if (strtol(reply, NULL, 10) > 0) { /* need auth */
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add buddy attempt fails, need authentication\n");
- nombre = uid_to_purple_name(for_uid);
- b = purple_find_buddy(gc->account, nombre);
- if (b != NULL)
- purple_blist_remove_buddy(b);
- g = g_new0(gc_and_uid, 1);
- g->gc = gc;
- 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);
- g_free(msg);
- g_free(nombre);
- } else { /* add OK */
- qq_add_buddy_by_recv_packet(gc, for_uid, TRUE, TRUE);
- msg = g_strdup_printf(_("You have added %d to buddy list"), for_uid);
- purple_notify_info(gc, NULL, msg, NULL);
- g_free(msg);
- }
- g_strfreev(segments);
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt add buddy reply\n");
+ if (strtol(reply, NULL, 10) > 0) { /* need auth */
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add buddy attempt fails, need authentication\n");
+ nombre = uid_to_purple_name(for_uid);
+ b = purple_find_buddy(gc->account, nombre);
+ if (b != NULL)
+ purple_blist_remove_buddy(b);
+ g = g_new0(gc_and_uid, 1);
+ g->gc = gc;
+ 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);
+ g_free(msg);
+ g_free(nombre);
+ } else { /* add OK */
+ qq_add_buddy_by_recv_packet(gc, for_uid, TRUE, TRUE);
+ msg = g_strdup_printf(_("You have added %d to buddy list"), for_uid);
+ purple_notify_info(gc, NULL, msg, NULL);
+ g_free(msg);
}
+ g_strfreev(segments);
}
PurpleGroup *qq_get_purple_group(const gchar *group_name)
============================================================
--- libpurple/protocols/qq/buddy_opt.h 9313e5ed647288c5fa90480c5e552aa273cc9495
+++ libpurple/protocols/qq/buddy_opt.h ac9e37c18d7db3eb191f9096bdf6f3819a6a84f4
@@ -46,9 +46,9 @@ void qq_process_remove_buddy_reply(guint
void qq_do_nothing_with_gc_and_uid(gc_and_uid *g, const gchar *msg);
void qq_process_remove_buddy_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
-void qq_process_remove_self_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
-void qq_process_add_buddy_reply(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection *gc);
-void qq_process_add_buddy_auth_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
+void qq_process_remove_self_reply(guint8 *data, gint data_len, PurpleConnection *gc);
+void qq_process_add_buddy_reply(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc);
+void qq_process_add_buddy_auth_reply(guint8 *data, gint data_len, PurpleConnection *gc);
PurpleBuddy *qq_add_buddy_by_recv_packet(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create);
void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
============================================================
--- libpurple/protocols/qq/file_trans.c afa2d56d1161520729e657c6d4fa8e7f134decd5
+++ libpurple/protocols/qq/file_trans.c 6f016b37ef0b595dc8e1aa75c2177636c4eadba7
@@ -32,7 +32,7 @@
#include "ft.h"
#include "cipher.h"
-#include "crypt.h"
+#include "qq_crypt.h"
#include "file_trans.h"
#include "header_info.h"
#include "im.h"
@@ -338,32 +338,31 @@ void qq_send_file_ctl_packet(PurpleConne
raw_data, bytes,
"sending packet[%s]:", qq_get_file_cmd_desc(packet_type));
- encrypted_len = bytes + 16;
- encrypted_data = g_newa(guint8, encrypted_len);
- qq_encrypt(raw_data, bytes, info->file_session_key, encrypted_data, &encrypted_len);
+ encrypted_data = g_newa(guint8, bytes + 16);
+ encrypted_len = qq_encrypt(encrypted_data, raw_data, bytes, info->file_session_key);
/*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 0
+ 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", "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");
+ }
+#endif
+
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);
}
@@ -498,7 +497,7 @@ static void _qq_send_file_data_packet(Pu
*/
-static void _qq_process_recv_file_ctl_packet(PurpleConnection *gc, guint8 *data, gint len)
+static void _qq_process_recv_file_ctl_packet(PurpleConnection *gc, guint8 *data, gint data_len)
{
gint bytes ;
gint decryped_bytes;
@@ -514,10 +513,9 @@ static void _qq_process_recv_file_ctl_pa
bytes = 0;
bytes += _qq_get_file_header(&fh, data + bytes);
- decrypted_data = g_newa(guint8, len);
- decrypted_len = len;
-
- if ( !qq_decrypt(data, len, qd->session_md5, decrypted_data, &decrypted_len) ) {
+ decrypted_data = g_newa(guint8, data_len);
+ decrypted_len = qq_decrypt(decrypted_data, data, data_len, qd->session_md5);
+ if ( decrypted_len <= 0 ) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt rcv file ctrl packet\n");
return;
}
============================================================
--- libpurple/protocols/qq/group.c 61f79d9f10bbb3d0ed52ac7e9425464d28f78b9f
+++ libpurple/protocols/qq/group.c a3e4159f84756290c5fa166286e2f5353db574a4
@@ -32,17 +32,18 @@
#include "group_info.h"
#include "group_search.h"
#include "utils.h"
-
+#include "qq_network.h"
+#include "header_info.h"
#include "group.h"
static void _qq_group_search_callback(PurpleConnection *gc, const gchar *input)
{
- guint32 external_group_id;
+ guint32 ext_id;
g_return_if_fail(input != NULL);
- external_group_id = qq_string_to_dec_value(input);
+ ext_id = qq_string_to_dec_value(input);
/* 0x00000000 means search for demo group */
- qq_send_cmd_group_search_group(gc, external_group_id);
+ qq_send_cmd_group_search_group(gc, ext_id);
}
static void _qq_group_search_cancel_callback(PurpleConnection *gc, const gchar *input)
@@ -104,7 +105,7 @@ PurpleRoomlist *qq_roomlist_get_list(Pur
fields = g_list_append(fields, f);
f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_GROUP_KEY_INTERNAL_ID, TRUE);
fields = g_list_append(fields, f);
- f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_GROUP_KEY_GROUP_TYPE, TRUE);
+ f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_GROUP_KEY_TYPE, TRUE);
fields = g_list_append(fields, f);
f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Auth"), QQ_GROUP_KEY_AUTH_TYPE, TRUE);
fields = g_list_append(fields, f);
@@ -145,12 +146,12 @@ void qq_group_init(PurpleConnection *gc)
/* this should be called upon signin, even when we did not open group chat window */
void qq_group_init(PurpleConnection *gc)
{
- gint i;
PurpleAccount *account;
PurpleChat *chat;
PurpleGroup *purple_group;
PurpleBlistNode *node;
qq_group *group;
+ gint count;
account = purple_connection_get_account(gc);
@@ -160,18 +161,25 @@ void qq_group_init(PurpleConnection *gc)
return;
}
- i = 0;
- for (node = ((PurpleBlistNode *) purple_group)->child; node != NULL; node = node->next)
- if (PURPLE_BLIST_NODE_IS_CHAT(node)) { /* got one */
- chat = (PurpleChat *) node;
- if (account != chat->account)
- continue; /* very important here ! */
- group = qq_group_from_hashtable(gc, chat->components);
- if (group != NULL) {
- i++;
- qq_send_cmd_group_get_group_info(gc, group); /* get group info and members */
- }
+ count = 0;
+ for (node = ((PurpleBlistNode *) purple_group)->child; node != NULL; node = node->next) {
+ if ( !PURPLE_BLIST_NODE_IS_CHAT(node)) {
+ continue;
}
+ /* got one */
+ chat = (PurpleChat *) node;
+ if (account != chat->account) /* not qq account*/
+ continue;
+ group = qq_group_from_hashtable(gc, chat->components);
+ if (group == NULL)
+ continue;
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Load %d QQ Qun configurations\n", i);
+ if (group->id <= 0)
+ continue;
+
+ count++;
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id);
+ }
+
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Load %d QQ Qun configurations\n", count);
}
============================================================
--- libpurple/protocols/qq/group.h f4d2603c893adde8ec50d16668cccb9b6d756c21
+++ libpurple/protocols/qq/group.h 6d3c438063856a59dbc1f546de3e30ed96373e61
@@ -44,9 +44,9 @@ typedef struct _qq_group {
/* all these will be saved when we exit Purple */
qq_group_member_status my_status; /* my status for this group */
gchar *my_status_desc; /* my status description */
- guint32 internal_group_id;
- guint32 external_group_id;
- guint8 group_type; /* permanent or temporory */
+ guint32 id;
+ guint32 ext_id;
+ guint8 type8; /* permanent or temporory */
guint32 creator_uid;
guint32 group_category;
guint8 auth_type;
============================================================
--- libpurple/protocols/qq/group_find.c cb294c1cc3021fc018e4a39e8e7c9907d7faae3d
+++ libpurple/protocols/qq/group_find.c 30312495840bc0286f16541ac847a387638d5b3e
@@ -29,36 +29,8 @@
#include "util.h"
#include "group_find.h"
-#include "group_network.h"
#include "utils.h"
-/* find the internal_group_id by the reply packet sequence
- * return TRUE if we have a record of it, return FALSE if not */
-gboolean qq_group_find_internal_group_id_by_seq(PurpleConnection *gc, guint16 seq, guint32 *internal_group_id)
-{
- GList *list;
- qq_data *qd;
- group_packet *p;
-
- if (internal_group_id == NULL)
- return FALSE;
- qd = (qq_data *) gc->proto_data;
-
- list = qd->group_packets;
- while (list != NULL) {
- p = (group_packet *) (list->data);
- if (p->send_seq == seq) { /* found and remove */
- *internal_group_id = p->internal_group_id;
- qd->group_packets = g_list_remove(qd->group_packets, p);
- g_free(p);
- return TRUE;
- }
- list = list->next;
- }
-
- return FALSE;
-}
-
/* find a qq_buddy by uid, called by im.c */
qq_buddy *qq_group_find_member_by_uid(qq_group *group, guint32 uid)
{
@@ -150,7 +122,7 @@ qq_group *qq_group_find_by_channel(Purpl
}
/* find a qq_group by its id, flag is QQ_INTERNAL_ID or QQ_EXTERNAL_ID */
-qq_group *qq_group_find_by_id(PurpleConnection *gc, guint32 id, gboolean flag)
+qq_group *qq_room_search_ext_id(PurpleConnection *gc, guint32 ext_id)
{
GList *list;
qq_group *group;
@@ -158,17 +130,40 @@ qq_group *qq_group_find_by_id(PurpleConn
qd = (qq_data *) gc->proto_data;
- if (qd->groups == NULL || id <= 0)
+ if (qd->groups == NULL || ext_id <= 0)
return NULL;
list = qd->groups;
while (list != NULL) {
group = (qq_group *) list->data;
- if (flag == QQ_INTERNAL_ID ?
- (group->internal_group_id == id) : (group->external_group_id == id))
+ if (group->ext_id == ext_id) {
return group;
+ }
list = list->next;
}
return NULL;
}
+
+qq_group *qq_room_search_id(PurpleConnection *gc, guint32 room_id)
+{
+ GList *list;
+ qq_group *group;
+ qq_data *qd;
+
+ qd = (qq_data *) gc->proto_data;
+
+ if (qd->groups == NULL || room_id <= 0)
+ return NULL;
+
+ list = qd->groups;
+ while (list != NULL) {
+ group = (qq_group *) list->data;
+ if (group->id == room_id) {
+ return group;
+ }
+ list = list->next;
+ }
+
+ return NULL;
+}
============================================================
--- libpurple/protocols/qq/group_find.h e28cabe174344e874e43764619e549a6eafeef0c
+++ libpurple/protocols/qq/group_find.h 8978a58ba32f8e2fd770e56de5b84c1051e3d7c0
@@ -29,14 +29,13 @@
#include "connection.h"
#include "group.h"
-#define QQ_INTERNAL_ID 0
-#define QQ_EXTERNAL_ID 1
-
qq_buddy *qq_group_find_member_by_uid(qq_group *group, guint32 uid);
void qq_group_remove_member_by_uid(qq_group *group, guint32 uid);
qq_buddy *qq_group_find_or_add_member(PurpleConnection *gc, qq_group *group, guint32 member_uid);
-gboolean qq_group_find_internal_group_id_by_seq(PurpleConnection *gc, guint16 seq, guint32 *internal_group_id);
+gboolean qq_group_find_id_by_seq(PurpleConnection *gc, guint16 seq, guint32 *id);
qq_group *qq_group_find_by_channel(PurpleConnection *gc, gint channel);
-qq_group *qq_group_find_by_id(PurpleConnection *gc, guint32 id, gboolean flag);
+qq_group *qq_room_search_ext_id(PurpleConnection *gc, guint32 ext_id);
+qq_group *qq_room_search_id(PurpleConnection *gc, guint32 room_id);
+
#endif
============================================================
--- libpurple/protocols/qq/group_free.c 61ab0607233c10f6e75d2b19f436814edfc31b11
+++ libpurple/protocols/qq/group_free.c 3d3fb0dbfe4e3796b77a2d43596d330feaf73cd1
@@ -28,7 +28,6 @@
#include "buddy_list.h"
#include "group_free.h"
-#include "group_network.h"
/* gracefully free all members in a group */
static void qq_group_free_member(qq_group *group)
@@ -62,22 +61,6 @@ void qq_group_free(qq_group *group)
g_free(group);
}
-/* clean up group_packets and free all contents */
-void qq_group_packets_free(qq_data *qd)
-{
- group_packet *p;
- gint i;
-
- i = 0;
- while (qd->group_packets != NULL) {
- p = (group_packet *) (qd->group_packets->data);
- qd->group_packets = g_list_remove(qd->group_packets, p);
- g_free(p);
- i++;
- }
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "%d group packets are freed!\n", i);
-}
-
void qq_group_free_all(qq_data *qd)
{
qq_group *group;
============================================================
--- libpurple/protocols/qq/group_free.h b10de4071f1b311e181c18ac51b3c0f7ca241a98
+++ libpurple/protocols/qq/group_free.h 691a54cd69c887729661722b66cb04d2d7c98923
@@ -29,8 +29,6 @@
#include "qq.h"
#include "group.h"
-void qq_group_packets_free(qq_data *qd);
-
void qq_group_free(qq_group *group);
void qq_group_free_all(qq_data *qd);
============================================================
--- libpurple/protocols/qq/group_im.c a6e45f13c82a305174b6f5269c82585e2bd16faf
+++ libpurple/protocols/qq/group_im.c f9094b9361ff1fb22d670d6ddd1e937b9df0a7b4
@@ -36,15 +36,16 @@
#include "group_internal.h"
#include "group_info.h"
#include "group_im.h"
-#include "group_network.h"
#include "group_opt.h"
#include "im.h"
+#include "header_info.h"
#include "packet_parse.h"
+#include "qq_network.h"
#include "utils.h"
typedef struct _qq_recv_group_im {
- guint32 external_group_id;
- guint8 group_type;
+ guint32 ext_id;
+ guint8 type8;
guint32 member_uid;
guint16 msg_seq;
time_t send_time;
@@ -68,12 +69,10 @@ void qq_send_packet_group_im(PurpleConne
purple_debug_info("QQ_MESG", "Send qun mesg filterd: %s\n", msg_filtered);
msg_len = strlen(msg_filtered);
- data_len = 7 + msg_len + QQ_SEND_IM_AFTER_MSG_LEN;
+ data_len = 2 + msg_len + QQ_SEND_IM_AFTER_MSG_LEN;
raw_data = g_newa(guint8, data_len);
bytes = 0;
- 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,
@@ -84,7 +83,7 @@ void qq_send_packet_group_im(PurpleConne
g_free(msg_filtered);
if (bytes == data_len) /* create OK */
- qq_send_group_cmd(gc, group, raw_data, data_len);
+ qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_MSG, group->id, 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);
@@ -99,33 +98,33 @@ void qq_process_group_cmd_im(guint8 *dat
}
/* receive an application to join the group */
-void qq_process_recv_group_im_apply_join(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc)
+void qq_process_recv_group_im_apply_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc)
{
- guint32 external_group_id, user_uid;
- guint8 group_type;
+ guint32 ext_id, user_uid;
+ guint8 type8;
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);
+ g_return_if_fail(id > 0 && data != NULL && len > 0);
/* FIXME: check length here */
- bytes += qq_get32(&external_group_id, data + bytes);
- bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&ext_id, data + bytes);
+ bytes += qq_get8(&type8, data + bytes);
bytes += qq_get32(&user_uid, data + bytes);
- g_return_if_fail(external_group_id > 0 && user_uid > 0);
+ g_return_if_fail(ext_id > 0 && user_uid > 0);
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);
+ msg = g_strdup_printf(_("User %d requested to join group %d"), user_uid, ext_id);
reason = g_strdup_printf(_("Reason: %s"), reason_utf8);
g = g_new0(group_member_opt, 1);
g->gc = gc;
- g->internal_group_id = internal_group_id;
+ g->id = id;
g->member = user_uid;
nombre = uid_to_purple_name(user_uid);
@@ -150,10 +149,10 @@ 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, gint len, guint32 internal_group_id, PurpleConnection *gc)
+void qq_process_recv_group_im_been_rejected(guint8 *data, gint len, guint32 id, PurpleConnection *gc)
{
- guint32 external_group_id, admin_uid;
- guint8 group_type;
+ guint32 ext_id, admin_uid;
+ guint8 type8;
gchar *reason_utf8, *msg, *reason;
qq_group *group;
gint bytes = 0;
@@ -162,21 +161,21 @@ void qq_process_recv_group_im_been_rejec
/* FIXME: check length here */
- bytes += qq_get32(&external_group_id, data + bytes);
- bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&ext_id, data + bytes);
+ bytes += qq_get8(&type8, data + bytes);
bytes += qq_get32(&admin_uid, data + bytes);
- g_return_if_fail(external_group_id > 0 && admin_uid > 0);
+ g_return_if_fail(ext_id > 0 && admin_uid > 0);
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"), ext_id, admin_uid);
reason = g_strdup_printf(_("Reason: %s"), reason_utf8);
purple_notify_warning(gc, _("QQ Qun Operation"), msg, reason);
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
if (group != NULL) {
group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
qq_group_refresh(gc, group);
@@ -188,10 +187,10 @@ void qq_process_recv_group_im_been_rejec
}
/* the request to join a group is approved */
-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_approved(guint8 *data, gint len, guint32 id, PurpleConnection *gc)
{
- guint32 external_group_id, admin_uid;
- guint8 group_type;
+ guint32 ext_id, admin_uid;
+ guint8 type8;
gchar *reason_utf8, *msg;
qq_group *group;
gint bytes = 0;
@@ -200,20 +199,20 @@ void qq_process_recv_group_im_been_appro
/* FIXME: check length here */
- bytes += qq_get32(&external_group_id, data + bytes);
- bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&ext_id, data + bytes);
+ bytes += qq_get8(&type8, data + bytes);
bytes += qq_get32(&admin_uid, data + bytes);
- g_return_if_fail(external_group_id > 0 && admin_uid > 0);
+ g_return_if_fail(ext_id > 0 && admin_uid > 0);
/* it is also a "æ " here, so do not display */
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"), ext_id, admin_uid);
purple_notify_warning(gc, _("QQ Qun Operation"), msg, NULL);
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
if (group != NULL) {
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
qq_group_refresh(gc, group);
@@ -224,10 +223,10 @@ void qq_process_recv_group_im_been_appro
}
/* process the packet when removed from a group */
-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_removed(guint8 *data, gint len, guint32 id, PurpleConnection *gc)
{
- guint32 external_group_id, uid;
- guint8 group_type;
+ guint32 ext_id, uid;
+ guint8 type8;
gchar *msg;
qq_group *group;
gint bytes = 0;
@@ -236,16 +235,16 @@ void qq_process_recv_group_im_been_remov
/* FIXME: check length here */
- bytes += qq_get32(&external_group_id, data + bytes);
- bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&ext_id, data + bytes);
+ bytes += qq_get8(&type8, data + bytes);
bytes += qq_get32(&uid, data + bytes);
- g_return_if_fail(external_group_id > 0 && uid > 0);
+ g_return_if_fail(ext_id > 0 && uid > 0);
- msg = g_strdup_printf(_("You [%d] have left group \"%d\""), uid, external_group_id);
+ msg = g_strdup_printf(_("You [%d] have left group \"%d\""), uid, ext_id);
purple_notify_info(gc, _("QQ Qun Operation"), msg, NULL);
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
if (group != NULL) {
group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
qq_group_refresh(gc, group);
@@ -255,10 +254,10 @@ void qq_process_recv_group_im_been_remov
}
/* process the packet when added to a group */
-void qq_process_recv_group_im_been_added(guint8 *data, gint len, guint32 internal_group_id, PurpleConnection *gc)
+void qq_process_recv_group_im_been_added(guint8 *data, gint len, guint32 id, PurpleConnection *gc)
{
- guint32 external_group_id, uid;
- guint8 group_type;
+ guint32 ext_id, uid;
+ guint8 type8;
qq_group *group;
gchar *msg;
gint bytes = 0;
@@ -267,24 +266,24 @@ void qq_process_recv_group_im_been_added
/* FIXME: check length here */
- bytes += qq_get32(&external_group_id, data + bytes);
- bytes += qq_get8(&group_type, data + bytes);
+ bytes += qq_get32(&ext_id, data + bytes);
+ bytes += qq_get8(&type8, data + bytes);
bytes += qq_get32(&uid, data + bytes);
- g_return_if_fail(external_group_id > 0 && uid > 0);
+ g_return_if_fail(ext_id > 0 && uid > 0);
- msg = g_strdup_printf(_("You [%d] have been added to group \"%d\""), uid, external_group_id);
+ msg = g_strdup_printf(_("You [%d] have been added to group \"%d\""), uid, ext_id);
purple_notify_info(gc, _("QQ Qun Operation"), msg, _("This group has been added to your buddy list"));
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
if (group != NULL) {
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
qq_group_refresh(gc, group);
} else { /* no such group, try to create a dummy first, and then update */
- group = qq_group_create_internal_record(gc, internal_group_id, external_group_id, NULL);
+ group = qq_group_create_internal_record(gc, id, ext_id, NULL);
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
qq_group_refresh(gc, group);
- qq_send_cmd_group_get_group_info(gc, group);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id);
/* the return of this cmd will automatically update the group in blist */
}
@@ -292,7 +291,7 @@ void qq_process_recv_group_im_been_added
}
/* recv an IM from a group chat */
-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(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type)
{
gchar *msg_with_purple_smiley, *msg_utf8_encoded, *im_src_name;
guint16 unknown;
@@ -315,11 +314,11 @@ void qq_process_recv_group_im(guint8 *da
im_group = g_newa(qq_recv_group_im, 1);
- bytes += qq_get32(&(im_group->external_group_id), data + bytes);
- bytes += qq_get8(&(im_group->group_type), data + bytes);
+ bytes += qq_get32(&(im_group->ext_id), data + bytes);
+ bytes += qq_get8(&(im_group->type8), data + bytes);
if(QQ_RECV_IM_TEMP_QUN_IM == im_type) {
- bytes += qq_get32(&(internal_group_id), data + bytes);
+ bytes += qq_get32(&(id), data + bytes);
}
bytes += qq_get32(&(im_group->member_uid), bytes + data);
@@ -372,13 +371,13 @@ void qq_process_recv_group_im(guint8 *da
else
msg_utf8_encoded = qq_to_utf8(msg_with_purple_smiley, QQ_CHARSET_DEFAULT);
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
g_return_if_fail(group != NULL);
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->group_name_utf8, purple_connection_get_account(gc));
if (conv == NULL && purple_prefs_get_bool("/plugins/prpl/qq/prompt_group_msg_on_recv")) {
/* New conv should open, get group info*/
- qq_send_cmd_group_get_group_info(gc, group);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id);
serv_got_joined_chat(gc, qd->channel++, group->group_name_utf8);
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->group_name_utf8, purple_connection_get_account(gc));
============================================================
--- libpurple/protocols/qq/group_im.h 7d1e2fc8b103b68c616a2e27ad10d129a052f1ad
+++ libpurple/protocols/qq/group_im.h e031720f93defa4bf87c133d2d1640bf868f1ecd
@@ -35,26 +35,26 @@ void qq_process_group_cmd_im(guint8 *dat
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);
+ * gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type); */
+void qq_process_recv_group_im(guint8 *data, gint data_len, guint32 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);
+ * guint32 id, PurpleConnection *gc); */
+void qq_process_recv_group_im_apply_join(guint8 *data, gint len, guint32 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);
+ * guint32 id, PurpleConnection *gc); */
+void qq_process_recv_group_im_been_rejected(guint8 *data, gint len, guint32 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);
+ * guint32 id, PurpleConnection *gc); */
+void qq_process_recv_group_im_been_approved(guint8 *data, gint len, guint32 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);
+ * guint32 id, PurpleConnection *gc); */
+void qq_process_recv_group_im_been_removed(guint8 *data, gint len, guint32 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);
+ * guint32 id, PurpleConnection *gc); */
+void qq_process_recv_group_im_been_added(guint8 *data, gint len, guint32 id, PurpleConnection *gc);
#endif
============================================================
--- libpurple/protocols/qq/group_info.c 39bcdf25ad56aebdccc5a87ce8e1066e770c06b9
+++ libpurple/protocols/qq/group_info.c a1d15e05c9e82fd75464c23ac95f976054396e02
@@ -32,7 +32,10 @@
#include "group_internal.h"
#include "group_info.h"
#include "buddy_list.h"
-#include "group_network.h"
+#include "header_info.h"
+#include "packet_parse.h"
+#include "qq_network.h"
+#include "utils.h"
/* we check who needs to update member info every minutes
* this interval determines if their member info is outdated */
@@ -61,20 +64,6 @@ static void _qq_group_set_members_all_of
}
}
-/* 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[16] = {0};
- gint bytes = 0;
-
- g_return_if_fail(group != NULL);
-
- bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_GET_GROUP_INFO);
- bytes += qq_put32(raw_data + bytes, group->internal_group_id);
-
- 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_all_get_online_members(PurpleConnection *gc)
{
@@ -99,9 +88,6 @@ void qq_send_cmd_group_get_online_member
void qq_send_cmd_group_get_online_members(PurpleConnection *gc, qq_group *group)
{
- guint8 raw_data[16] = {0};
- gint bytes = 0;
-
g_return_if_fail(group != NULL);
/* only get online members when conversation window is on */
@@ -111,17 +97,14 @@ void qq_send_cmd_group_get_online_member
return;
}
- bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_GET_ONLINE_MEMBER);
- bytes += qq_put32(raw_data + bytes, group->internal_group_id);
-
- qq_send_group_cmd(gc, group, raw_data, bytes);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_ONLINES, group->id);
}
/* 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;
- gint bytes, num, data_len;
+ gint bytes, num;
GList *list;
qq_buddy *member;
@@ -137,12 +120,9 @@ void qq_send_cmd_group_get_members_info(
return;
}
- data_len = 5 + 4 * num;
- raw_data = g_newa(guint8, data_len);
+ raw_data = g_newa(guint8, 4 * num);
bytes = 0;
- 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) {
@@ -152,16 +132,10 @@ void qq_send_cmd_group_get_members_info(
list = list->next;
}
- 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));
- return;
- }
-
- qq_send_group_cmd(gc, group, raw_data, bytes);
+ qq_send_room_cmd(gc, QQ_ROOM_CMD_GET_MEMBER_INFO, group->id, raw_data, bytes);
}
-void qq_process_group_cmd_get_group_info(guint8 *data, gint len, PurpleConnection *gc)
+void qq_process_room_cmd_get_info(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_group *group;
qq_buddy *member;
@@ -169,33 +143,33 @@ void qq_process_group_cmd_get_group_info
PurpleConversation *purple_conv;
guint8 organization, role;
guint16 unknown, max_members;
- guint32 member_uid, internal_group_id, external_group_id;
+ guint32 member_uid, id, ext_id;
GSList *pending_id;
guint32 unknown4;
guint8 unknown1;
gint bytes, num;
gchar *notice;
- g_return_if_fail(data != NULL && len > 0);
+ g_return_if_fail(data != NULL && data_len > 0);
qd = (qq_data *) gc->proto_data;
bytes = 0;
- bytes += qq_get32(&(internal_group_id), data + bytes);
- g_return_if_fail(internal_group_id > 0);
+ bytes += qq_get32(&id, data + bytes);
+ g_return_if_fail(id > 0);
- bytes += qq_get32(&(external_group_id), data + bytes);
- g_return_if_fail(external_group_id > 0);
+ bytes += qq_get32(&ext_id, data + bytes);
+ g_return_if_fail(ext_id > 0);
- pending_id = qq_get_pending_id(qd->adding_groups_from_server, internal_group_id);
+ pending_id = qq_get_pending_id(qd->adding_groups_from_server, id);
if (pending_id != NULL) {
- qq_set_pending_id(&qd->adding_groups_from_server, internal_group_id, FALSE);
- qq_group_create_internal_record(gc, internal_group_id, external_group_id, NULL);
+ qq_set_pending_id(&qd->adding_groups_from_server, id, FALSE);
+ qq_group_create_internal_record(gc, id, ext_id, NULL);
}
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
g_return_if_fail(group != NULL);
- bytes += qq_get8(&(group->group_type), data + bytes);
+ bytes += qq_get8(&(group->type8), 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);
@@ -210,7 +184,7 @@ void qq_process_group_cmd_get_group_info
* qunDestLen(qunDestcontent)) */
bytes += qq_get8(&unknown1, data + bytes);
purple_debug(PURPLE_DEBUG_INFO, "QQ", "type=%u creatorid=%u category=%u maxmembers=%u\n",
- group->group_type, group->creator_uid, group->group_category, max_members);
+ group->type8, group->creator_uid, group->group_category, max_members);
/* strlen + <str content> */
bytes += convert_as_pascal_string(data + bytes, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
@@ -223,23 +197,25 @@ void qq_process_group_cmd_get_group_info
num = 0;
/* now comes the member list separated by 0x00 */
- while (bytes < len) {
+ while (bytes < data_len) {
bytes += qq_get32(&member_uid, data + bytes);
num++;
bytes += qq_get8(&organization, data + bytes);
bytes += qq_get8(&role, data + bytes);
- /*
+#if 0
if(organization != 0 || role != 0) {
purple_debug(PURPLE_DEBUG_INFO, "QQ_GRP", "%d, organization=%d, role=%d\n", member_uid, organization, role);
}
- */
+#endif
+
member = qq_group_find_or_add_member(gc, group, member_uid);
if (member != NULL)
member->role = role;
}
- if(bytes > len) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "group_cmd_get_group_info: Dangerous error! maybe protocol changed, notify me!");
+ if(bytes > data_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, num);
@@ -265,9 +241,9 @@ void qq_process_group_cmd_get_group_info
purple_conv_chat_set_topic(PURPLE_CONV_CHAT(purple_conv), NULL, group->notice_utf8);
}
-void qq_process_group_cmd_get_online_members(guint8 *data, gint len, PurpleConnection *gc)
+void qq_process_room_cmd_get_onlines(guint8 *data, gint len, PurpleConnection *gc)
{
- guint32 internal_group_id, member_uid;
+ guint32 id, member_uid;
guint8 unknown;
gint bytes, num;
qq_group *group;
@@ -281,14 +257,14 @@ void qq_process_group_cmd_get_online_mem
}
bytes = 0;
- bytes += qq_get32(&internal_group_id, data + bytes);
+ bytes += qq_get32(&id, data + bytes);
bytes += qq_get8(&unknown, data + bytes); /* 0x3c ?? */
- g_return_if_fail(internal_group_id > 0);
+ g_return_if_fail(id > 0);
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
if (group == NULL) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "We have no group info for internal id [%d]\n", internal_group_id);
+ "We have no group info for internal id [%d]\n", id);
return;
}
@@ -311,11 +287,11 @@ void qq_process_group_cmd_get_online_mem
}
/* process the reply to get_members_info packet */
-void qq_process_group_cmd_get_members_info(guint8 *data, gint len, PurpleConnection *gc)
+void qq_process_room_cmd_get_members(guint8 *data, gint len, PurpleConnection *gc)
{
gint bytes;
gint num;
- guint32 internal_group_id, member_uid;
+ guint32 id, member_uid;
guint16 unknown;
qq_group *group;
qq_buddy *member;
@@ -323,11 +299,15 @@ void qq_process_group_cmd_get_members_in
g_return_if_fail(data != NULL && len > 0);
+#if 0
+ qq_show_packet("qq_process_room_cmd_get_members", data, len);
+#endif
+
bytes = 0;
- bytes += qq_get32(&internal_group_id, data + bytes);
- g_return_if_fail(internal_group_id > 0);
+ bytes += qq_get32(&id, data + bytes);
+ g_return_if_fail(id > 0);
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
g_return_if_fail(group != NULL);
num = 0;
@@ -352,19 +332,18 @@ void qq_process_group_cmd_get_members_in
member->nickname = g_strdup(nick);
g_free(nick);
- /*
- if (QQ_DEBUG) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "member [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n",
- member_uid, member->ext_flag, member->comm_flag, member->nickname);
- }
- */
+#if 0
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "member [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n",
+ member_uid, member->ext_flag, member->comm_flag, member->nickname);
+#endif
member->last_refresh = time(NULL);
}
- if(bytes > len) {
+ 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);
}
+
============================================================
--- libpurple/protocols/qq/group_info.h 9127235043443f56f167c0789974d00f099ff9e8
+++ libpurple/protocols/qq/group_info.h ec4f93c82296b45db4f59a84f5d0502dd8c5d77a
@@ -29,14 +29,12 @@
#include "connection.h"
#include "group.h"
-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_all_get_online_members(PurpleConnection *gc);
void qq_send_cmd_group_get_members_info(PurpleConnection *gc, qq_group *group);
-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);
-
+void qq_process_room_cmd_get_info(guint8 *data, gint len, PurpleConnection *gc);
+void qq_process_room_cmd_get_onlines(guint8 *data, gint len, PurpleConnection *gc);
+void qq_process_room_cmd_get_members(guint8 *data, gint len, PurpleConnection *gc);
#endif
============================================================
--- libpurple/protocols/qq/group_internal.c 7557c6350e61dd1dc126cacd99c232e4bd820d8a
+++ libpurple/protocols/qq/group_internal.c 67db78e571818d3665ddd87635ef513d4657d957
@@ -68,12 +68,12 @@ static void _qq_group_add_to_blist(Purpl
purple_debug(PURPLE_DEBUG_INFO, "QQ", "You have added group \"%s\" to blist locally\n", group->group_name_utf8);
}
-/* Create a dummy qq_group, which includes only internal_id, external_id,
+/* Create a dummy qq_group, which includes only internal_id, ext_id,
* and potentially group_name_utf8, in case we need to call group_conv_show_window
* right after creation. All other attributes are set to empty.
* We need to send a get_group_info to the QQ server to update it right away */
qq_group *qq_group_create_internal_record(PurpleConnection *gc,
- guint32 internal_id, guint32 external_id, gchar *group_name_utf8)
+ guint32 internal_id, guint32 ext_id, gchar *group_name_utf8)
{
qq_group *group;
qq_data *qd;
@@ -84,9 +84,9 @@ qq_group *qq_group_create_internal_recor
group = g_new0(qq_group, 1);
group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
group->my_status_desc = _qq_group_set_my_status_desc(group);
- group->internal_group_id = internal_id;
- group->external_group_id = external_id;
- group->group_type = 0x01; /* assume permanent Qun */
+ group->id = internal_id;
+ group->ext_id = ext_id;
+ group->type8 = 0x01; /* assume permanent Qun */
group->creator_uid = 10000; /* assume by QQ admin */
group->group_category = 0x01;
group->auth_type = 0x02; /* assume need auth */
@@ -101,7 +101,7 @@ qq_group *qq_group_create_internal_recor
return group;
}
-void qq_group_delete_internal_record(qq_data *qd, guint32 internal_group_id)
+void qq_group_delete_internal_record(qq_data *qd, guint32 id)
{
qq_group *group;
GList *list;
@@ -109,7 +109,7 @@ void qq_group_delete_internal_record(qq_
list = qd->groups;
while (list != NULL) {
group = (qq_group *) qd->groups->data;
- if (internal_group_id == group->internal_group_id) {
+ if (id == group->id) {
qd->groups = g_list_remove(qd->groups, group);
qq_group_free(group);
break;
@@ -128,10 +128,10 @@ GHashTable *qq_group_to_hashtable(qq_gro
group->my_status_desc = _qq_group_set_my_status_desc(group);
g_hash_table_insert(components,
- g_strdup(QQ_GROUP_KEY_INTERNAL_ID), g_strdup_printf("%d", group->internal_group_id));
+ g_strdup(QQ_GROUP_KEY_INTERNAL_ID), g_strdup_printf("%d", group->id));
g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_EXTERNAL_ID),
- g_strdup_printf("%d", group->external_group_id));
- g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_GROUP_TYPE), g_strdup_printf("%d", group->group_type));
+ g_strdup_printf("%d", group->ext_id));
+ g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_TYPE), g_strdup_printf("%d", group->type8));
g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid));
g_hash_table_insert(components,
g_strdup(QQ_GROUP_KEY_GROUP_CATEGORY), g_strdup_printf("%d", group->group_category));
@@ -157,12 +157,11 @@ qq_group *qq_group_from_hashtable(Purple
(NULL ==
g_hash_table_lookup(data,
QQ_GROUP_KEY_MEMBER_STATUS) ?
- g_strdup_printf("%d",
- QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) :
+ g_strdup_printf("%d", QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) :
g_hash_table_lookup(data, QQ_GROUP_KEY_MEMBER_STATUS));
- group->internal_group_id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_INTERNAL_ID));
- group->external_group_id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_EXTERNAL_ID));
- group->group_type = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_TYPE));
+ group->id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_INTERNAL_ID));
+ group->ext_id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_EXTERNAL_ID));
+ group->type8 = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_TYPE));
group->creator_uid = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_CREATOR_UID));
group->group_category = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_CATEGORY));
group->auth_type = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_AUTH_TYPE));
@@ -179,12 +178,12 @@ void qq_group_refresh(PurpleConnection *
void qq_group_refresh(PurpleConnection *gc, qq_group *group)
{
PurpleChat *chat;
- gchar *external_group_id;
+ gchar *ext_id;
g_return_if_fail(group != NULL);
- external_group_id = g_strdup_printf("%d", group->external_group_id);
- chat = purple_blist_find_chat(purple_connection_get_account(gc), external_group_id);
- g_free(external_group_id);
+ ext_id = g_strdup_printf("%d", group->ext_id);
+ chat = purple_blist_find_chat(purple_connection_get_account(gc), ext_id);
+ g_free(ext_id);
if (chat == NULL && group->my_status != QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) {
_qq_group_add_to_blist(gc, group);
} else if (chat != NULL) { /* we have a local record, update its info */
@@ -198,12 +197,12 @@ void qq_group_refresh(PurpleConnection *
g_strdup(QQ_GROUP_KEY_MEMBER_STATUS_DESC), g_strdup(group->my_status_desc));
g_hash_table_replace(chat->components,
g_strdup(QQ_GROUP_KEY_INTERNAL_ID),
- g_strdup_printf("%d", group->internal_group_id));
+ g_strdup_printf("%d", group->id));
g_hash_table_replace(chat->components,
g_strdup(QQ_GROUP_KEY_EXTERNAL_ID),
- g_strdup_printf("%d", group->external_group_id));
+ g_strdup_printf("%d", group->ext_id));
g_hash_table_replace(chat->components,
- g_strdup(QQ_GROUP_KEY_GROUP_TYPE), g_strdup_printf("%d", group->group_type));
+ g_strdup(QQ_GROUP_KEY_TYPE), g_strdup_printf("%d", group->type8));
g_hash_table_replace(chat->components,
g_strdup(QQ_GROUP_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid));
g_hash_table_replace(chat->components,
============================================================
--- libpurple/protocols/qq/group_internal.h e21e3f579f9cb4ed8b0444f0cd1068801e1f75ed
+++ libpurple/protocols/qq/group_internal.h 9dbed22a6a1c7c44af8faacaece208c705c2491b
@@ -28,20 +28,20 @@
#include <glib.h>
#include "group.h"
-#define QQ_GROUP_KEY_MEMBER_STATUS "my_status_code"
-#define QQ_GROUP_KEY_MEMBER_STATUS_DESC "my_status_desc"
-#define QQ_GROUP_KEY_INTERNAL_ID "internal_group_id"
-#define QQ_GROUP_KEY_EXTERNAL_ID "external_group_id"
-#define QQ_GROUP_KEY_GROUP_TYPE "group_type"
-#define QQ_GROUP_KEY_CREATOR_UID "creator_uid"
-#define QQ_GROUP_KEY_GROUP_CATEGORY "group_category"
-#define QQ_GROUP_KEY_AUTH_TYPE "auth_type"
-#define QQ_GROUP_KEY_GROUP_NAME_UTF8 "group_name_utf8"
-#define QQ_GROUP_KEY_GROUP_DESC_UTF8 "group_desc_utf8"
+#define QQ_GROUP_KEY_MEMBER_STATUS "my_status_code"
+#define QQ_GROUP_KEY_MEMBER_STATUS_DESC "my_status_desc"
+#define QQ_GROUP_KEY_INTERNAL_ID "id"
+#define QQ_GROUP_KEY_EXTERNAL_ID "ext_id"
+#define QQ_GROUP_KEY_TYPE "type"
+#define QQ_GROUP_KEY_CREATOR_UID "creator_uid"
+#define QQ_GROUP_KEY_GROUP_CATEGORY "category"
+#define QQ_GROUP_KEY_AUTH_TYPE "auth_type"
+#define QQ_GROUP_KEY_GROUP_NAME_UTF8 "name_utf8"
+#define QQ_GROUP_KEY_GROUP_DESC_UTF8 "desc_utf8"
qq_group *qq_group_create_internal_record(PurpleConnection *gc,
- guint32 internal_id, guint32 external_id, gchar *group_name_utf8);
-void qq_group_delete_internal_record(qq_data *qd, guint32 internal_group_id);
+ guint32 internal_id, guint32 ext_id, gchar *group_name_utf8);
+void qq_group_delete_internal_record(qq_data *qd, guint32 id);
GHashTable *qq_group_to_hashtable(qq_group *group);
qq_group *qq_group_from_hashtable(PurpleConnection *gc, GHashTable *data);
============================================================
--- libpurple/protocols/qq/group_join.c 1ca4c86d88eaee4444f58263901258970f9b89e5
+++ libpurple/protocols/qq/group_join.c 792fdd633fd0b395d83701e185a7d007c26c76bd
@@ -38,8 +38,10 @@
#include "group_info.h"
#include "group_join.h"
#include "group_opt.h"
-#include "group_network.h"
#include "group_search.h"
+#include "header_info.h"
+#include "packet_parse.h"
+#include "qq_network.h"
enum {
QQ_GROUP_JOIN_OK = 0x01,
@@ -49,24 +51,21 @@ static void _qq_group_exit_with_gc_and_i
static void _qq_group_exit_with_gc_and_id(gc_and_uid *g)
{
PurpleConnection *gc;
- guint32 internal_group_id;
+ guint32 id;
qq_group *group;
gc = g->gc;
- internal_group_id = g->uid;
+ id = g->uid;
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
g_return_if_fail(group != NULL);
- qq_send_cmd_group_exit_group(gc, group);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_QUIT, group->id);
}
/* send packet to join a group without auth */
void qq_send_cmd_group_join_group(PurpleConnection *gc, qq_group *group)
{
- guint8 raw_data[16] = {0};
- gint bytes = 0;
-
g_return_if_fail(group != NULL);
if (group->my_status == QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) {
@@ -86,25 +85,21 @@ void qq_send_cmd_group_join_group(Purple
break;
}
- bytes = 0;
- bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_JOIN_GROUP);
- bytes += qq_put32(raw_data + bytes, group->internal_group_id);
-
- qq_send_group_cmd(gc, group, raw_data, bytes);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_JOIN, group->id);
}
static void _qq_group_join_auth_with_gc_and_id(gc_and_uid *g, const gchar *reason_utf8)
{
PurpleConnection *gc;
qq_group *group;
- guint32 internal_group_id;
+ guint32 id;
gc = g->gc;
- internal_group_id = g->uid;
+ id = g->uid;
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
if (group == NULL) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Can not find qq_group by internal_id: %d\n", internal_group_id);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Can not find qq_group by internal_id: %d\n", id);
return;
} else { /* everything is OK */
qq_send_cmd_group_auth(gc, group, QQ_GROUP_AUTH_REQUEST_APPLY, 0, reason_utf8);
@@ -118,12 +113,12 @@ static void _qq_group_join_auth(PurpleCo
g_return_if_fail(group != NULL);
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "Group (internal id: %d) needs authentication\n", group->internal_group_id);
+ "Group (internal id: %d) needs authentication\n", group->id);
msg = g_strdup_printf("Group \"%s\" needs authentication\n", group->group_name_utf8);
g = g_new0(gc_and_uid, 1);
g->gc = gc;
- g->uid = group->internal_group_id;
+ g->uid = group->id;
purple_request_input(gc, NULL, msg,
_("Input request here"),
_("Would you be my friend?"), TRUE, FALSE, NULL,
@@ -139,7 +134,7 @@ void qq_send_cmd_group_auth(PurpleConnec
{
guint8 *raw_data;
gchar *reason_qq;
- gint bytes, data_len;
+ gint bytes;
g_return_if_fail(group != NULL);
@@ -154,45 +149,22 @@ void qq_send_cmd_group_auth(PurpleConnec
uid = 0;
}
- data_len = 10 + strlen(reason_qq) + 1;
- raw_data = g_newa(guint8, data_len);
+ raw_data = g_newa(guint8, 6 + strlen(reason_qq));
bytes = 0;
- 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));
- return;
- }
-
- qq_send_group_cmd(gc, group, raw_data, data_len);
+ qq_send_room_cmd(gc, QQ_ROOM_CMD_AUTH, group->id, raw_data, bytes);
}
-/* send a packet to exit a group */
-void qq_send_cmd_group_exit_group(PurpleConnection *gc, qq_group *group)
-{
- guint8 raw_data[16] = {0};
- gint bytes = 0;
-
- g_return_if_fail(group != NULL);
-
- bytes += qq_put8(raw_data + bytes, QQ_GROUP_CMD_EXIT_GROUP);
- bytes += qq_put32(raw_data + bytes, group->internal_group_id);
-
- 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, gint len, PurpleConnection *gc)
{
gint bytes;
- guint32 internal_group_id;
+ guint32 id;
PurpleChat *chat;
qq_group *group;
qq_data *qd;
@@ -207,15 +179,15 @@ void qq_process_group_cmd_exit_group(gui
}
bytes = 0;
- bytes += qq_get32(&internal_group_id, data + bytes);
+ bytes += qq_get32(&id, data + bytes);
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
if (group != NULL) {
chat = purple_blist_find_chat
- (purple_connection_get_account(gc), g_strdup_printf("%d", group->external_group_id));
+ (purple_connection_get_account(gc), g_strdup_printf("%d", group->ext_id));
if (chat != NULL)
purple_blist_remove_chat(chat);
- qq_group_delete_internal_record(qd, internal_group_id);
+ qq_group_delete_internal_record(qd, id);
}
purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully left the group"), NULL);
}
@@ -224,7 +196,7 @@ void qq_process_group_cmd_join_group_aut
void qq_process_group_cmd_join_group_auth(guint8 *data, gint len, PurpleConnection *gc)
{
gint bytes;
- guint32 internal_group_id;
+ guint32 id;
qq_data *qd;
g_return_if_fail(data != NULL && len > 0);
@@ -236,8 +208,8 @@ void qq_process_group_cmd_join_group_aut
return;
}
bytes = 0;
- bytes += qq_get32(&internal_group_id, data + bytes);
- g_return_if_fail(internal_group_id > 0);
+ bytes += qq_get32(&id, data + bytes);
+ g_return_if_fail(id > 0);
purple_notify_info(gc, _("QQ Group Auth"),
_("Your authorization request has been accepted by the QQ server"), NULL);
@@ -247,7 +219,7 @@ void qq_process_group_cmd_join_group(gui
void qq_process_group_cmd_join_group(guint8 *data, gint len, PurpleConnection *gc)
{
gint bytes;
- guint32 internal_group_id;
+ guint32 id;
guint8 reply;
qq_group *group;
@@ -260,11 +232,11 @@ void qq_process_group_cmd_join_group(gui
}
bytes = 0;
- bytes += qq_get32(&internal_group_id, data + bytes);
+ bytes += qq_get32(&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);
+ group = qq_room_search_id(gc, id);
/* need to check if group is NULL or not. */
g_return_if_fail(group != NULL);
switch (reply) {
@@ -274,12 +246,12 @@ void qq_process_group_cmd_join_group(gui
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);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id);
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->ext_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);
@@ -287,7 +259,7 @@ void qq_process_group_cmd_join_group(gui
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);
+ group->ext_id, group->group_name_utf8, reply);
}
}
@@ -295,48 +267,48 @@ void qq_group_join(PurpleConnection *gc,
void qq_group_join(PurpleConnection *gc, GHashTable *data)
{
qq_data *qd;
- gchar *external_group_id_ptr;
- guint32 external_group_id;
+ gchar *ext_id_ptr;
+ guint32 ext_id;
qq_group *group;
g_return_if_fail(data != NULL);
qd = (qq_data *) gc->proto_data;
- external_group_id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_EXTERNAL_ID);
- g_return_if_fail(external_group_id_ptr != NULL);
+ ext_id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_EXTERNAL_ID);
+ g_return_if_fail(ext_id_ptr != NULL);
errno = 0;
- external_group_id = strtol(external_group_id_ptr, NULL, 10);
+ ext_id = strtol(ext_id_ptr, NULL, 10);
if (errno != 0) {
purple_notify_error(gc, _("Error"),
_("You entered a group ID outside the acceptable range"), NULL);
return;
}
- group = qq_group_find_by_id(gc, external_group_id, QQ_EXTERNAL_ID);
+ group = qq_room_search_ext_id(gc, ext_id);
if (group) {
qq_send_cmd_group_join_group(gc, group);
} else {
- qq_set_pending_id(&qd->joining_groups, external_group_id, TRUE);
- qq_send_cmd_group_search_group(gc, external_group_id);
+ qq_set_pending_id(&qd->joining_groups, ext_id, TRUE);
+ qq_send_cmd_group_search_group(gc, ext_id);
}
}
void qq_group_exit(PurpleConnection *gc, GHashTable *data)
{
- gchar *internal_group_id_ptr;
- guint32 internal_group_id;
+ gchar *id_ptr;
+ guint32 id;
gc_and_uid *g;
g_return_if_fail(data != NULL);
- internal_group_id_ptr = g_hash_table_lookup(data, "internal_group_id");
- internal_group_id = strtol(internal_group_id_ptr, NULL, 10);
+ id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_INTERNAL_ID);
+ id = strtol(id_ptr, NULL, 10);
- g_return_if_fail(internal_group_id > 0);
+ g_return_if_fail(id > 0);
g = g_new0(gc_and_uid, 1);
g->gc = gc;
- g->uid = internal_group_id;
+ g->uid = id;
purple_request_action(gc, _("QQ Qun Operation"),
_("Are you sure you want to leave this Qun?"),
============================================================
--- libpurple/protocols/qq/group_join.h 8629eb769bf9f78c1b458f1a754844340d15a860
+++ libpurple/protocols/qq/group_join.h 0825fbbfaae115b886258169f07d0512140d20cb
@@ -45,7 +45,6 @@ void qq_group_exit(PurpleConnection *gc,
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, 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);
============================================================
--- libpurple/protocols/qq/group_opt.c 36e23574e120c63e8cf0a8da7ba3e252f815b55d
+++ libpurple/protocols/qq/group_opt.c cfe88c8ff984e466debb1c62c877f54686a56ac7
@@ -34,9 +34,10 @@
#include "group_internal.h"
#include "group_info.h"
#include "group_join.h"
-#include "group_network.h"
#include "group_opt.h"
+#include "header_info.h"
#include "packet_parse.h"
+#include "qq_network.h"
#include "utils.h"
static int _compare_guint32(const void *a,
@@ -68,13 +69,11 @@ static void _qq_group_member_opt(PurpleC
data = g_newa(guint8, data_len);
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++)
bytes += qq_put32(data + bytes, members[i]);
- qq_send_group_cmd(gc, group, data, bytes);
+ qq_send_room_cmd(gc, QQ_ROOM_CMD_MEMBER_OPT, group->id, data, bytes);
}
static void _qq_group_do_nothing_with_struct(group_member_opt *g)
@@ -86,8 +85,8 @@ static void _qq_group_reject_application
static void _qq_group_reject_application_real(group_member_opt *g, gchar *msg_utf8)
{
qq_group *group;
- g_return_if_fail(g != NULL && g->gc != NULL && g->internal_group_id > 0 && g->member > 0);
- group = qq_group_find_by_id(g->gc, g->internal_group_id, QQ_INTERNAL_ID);
+ g_return_if_fail(g != NULL && g->gc != NULL && g->id > 0 && g->member > 0);
+ group = qq_room_search_id(g->gc, g->id);
g_return_if_fail(group != NULL);
qq_send_cmd_group_auth(g->gc, group, QQ_GROUP_AUTH_REQUEST_REJECT, g->member, msg_utf8);
g_free(g);
@@ -131,8 +130,8 @@ void qq_group_approve_application_with_s
void qq_group_approve_application_with_struct(group_member_opt *g)
{
qq_group *group;
- g_return_if_fail(g != NULL && g->gc != NULL && g->internal_group_id > 0 && g->member > 0);
- group = qq_group_find_by_id(g->gc, g->internal_group_id, QQ_INTERNAL_ID);
+ g_return_if_fail(g != NULL && g->gc != NULL && g->id > 0 && g->member > 0);
+ group = qq_room_search_id(g->gc, g->id);
g_return_if_fail(group != NULL);
qq_send_cmd_group_auth(g->gc, group, QQ_GROUP_AUTH_REQUEST_APPROVE, g->member, "");
qq_group_find_or_add_member(g->gc, group, g->member);
@@ -198,24 +197,24 @@ void qq_group_process_modify_members_rep
void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc)
{
gint bytes;
- guint32 internal_group_id;
+ guint32 id;
qq_group *group;
g_return_if_fail(data != NULL);
bytes = 0;
- bytes += qq_get32(&internal_group_id, data + bytes);
- g_return_if_fail(internal_group_id > 0);
+ bytes += qq_get32(&id, data + bytes);
+ g_return_if_fail(id > 0);
/* we should have its info locally */
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
g_return_if_fail(group != NULL);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify members for Qun %d\n", group->external_group_id);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify members for Qun %d\n", group->ext_id);
purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun member"), NULL);
}
-void qq_group_modify_info(PurpleConnection *gc, qq_group *group)
+void qq_room_change_info(PurpleConnection *gc, qq_group *group)
{
guint8 *data;
gint data_len;
@@ -228,16 +227,9 @@ void qq_group_modify_info(PurpleConnecti
group_desc = group->group_desc_utf8 == NULL ? "" : utf8_to_qq(group->group_desc_utf8, QQ_CHARSET_DEFAULT);
notice = group->notice_utf8 == NULL ? "" : utf8_to_qq(group->notice_utf8, QQ_CHARSET_DEFAULT);
- data_len = 13 + 1 + strlen(group_name)
- + 1 + strlen(group_desc)
- + 1 + strlen(notice);
-
+ data_len = 64 + strlen(group_name) + strlen(group_desc) + strlen(notice);
data = g_newa(guint8, data_len);
bytes = 0;
- /* 000-000 */
- bytes += qq_put8(data + bytes, QQ_GROUP_CMD_MODIFY_GROUP_INFO);
- /* 001-004 */
- bytes += qq_put32(data + bytes, group->internal_group_id);
/* 005-005 */
bytes += qq_put8(data + bytes, 0x01);
/* 006-006 */
@@ -258,54 +250,52 @@ void qq_group_modify_info(PurpleConnecti
bytes += qq_put8(data + bytes, strlen(group_desc));
bytes += qq_putdata(data + bytes, (guint8 *) group_desc, strlen(group_desc));
- if (bytes != 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",
+ "Overflow in qq_room_change_info, max %d bytes, now %d bytes\n",
data_len, bytes);
return;
}
-
- qq_send_group_cmd(gc, group, data, bytes);
+ qq_send_room_cmd(gc, QQ_ROOM_CMD_CHANGE_INFO, group->id, data, bytes);
}
void qq_group_process_modify_info_reply(guint8 *data, gint len, PurpleConnection *gc)
{
gint bytes;
- guint32 internal_group_id;
+ guint32 id;
qq_group *group;
g_return_if_fail(data != NULL);
bytes = 0;
- bytes += qq_get32(&internal_group_id, data + bytes);
- g_return_if_fail(internal_group_id > 0);
+ bytes += qq_get32(&id, data + bytes);
+ g_return_if_fail(id > 0);
/* we should have its info locally */
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
g_return_if_fail(group != NULL);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify info for Qun %d\n", group->external_group_id);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify info for Qun %d\n", group->ext_id);
qq_group_refresh(gc, group);
purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun information"), NULL);
}
/* 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)
+void qq_room_create_new(PurpleConnection *gc, const gchar *name)
{
+ guint8 *data;
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_len = 64 + strlen(name);
data = g_newa(guint8, data_len);
bytes = 0;
/* we create the simpleset group, only group name is given */
- /* 000 */
- bytes += qq_put8(data + bytes, QQ_GROUP_CMD_CREATE_GROUP);
/* 001 */
bytes += qq_put8(data + bytes, QQ_GROUP_TYPE_PERMANENT);
/* 002 */
@@ -322,14 +312,13 @@ void qq_group_create_with_name(PurpleCon
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) {
+ if (bytes > data_len) {
purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "Fail create create_group packet, expect %d bytes, written %d bytes\n",
+ "Overflow in qq_room_create, max %d bytes, now %d bytes\n",
data_len, bytes);
return;
}
-
- qq_send_group_cmd(gc, NULL, data, bytes);
+ qq_send_room_cmd_noid(gc, QQ_ROOM_CMD_CREATE, data, bytes);
}
static void qq_group_setup_with_gc_and_uid(gc_and_uid *g)
@@ -337,7 +326,7 @@ static void qq_group_setup_with_gc_and_u
qq_group *group;
g_return_if_fail(g != NULL && g->gc != NULL && g->uid > 0);
- group = qq_group_find_by_id(g->gc, g->uid, QQ_INTERNAL_ID);
+ group = qq_room_search_id(g->gc, g->uid);
g_return_if_fail(group != NULL);
/* TODO insert UI code here */
@@ -348,7 +337,7 @@ void qq_group_process_create_group_reply
void qq_group_process_create_group_reply(guint8 *data, gint len, PurpleConnection *gc)
{
gint bytes;
- guint32 internal_group_id, external_group_id;
+ guint32 id, ext_id;
qq_group *group;
gc_and_uid *g;
qq_data *qd;
@@ -358,23 +347,23 @@ void qq_group_process_create_group_reply
qd = (qq_data *) gc->proto_data;
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);
+ bytes += qq_get32(&id, data + bytes);
+ bytes += qq_get32(&ext_id, data + bytes);
+ g_return_if_fail(id > 0 && ext_id);
- group = qq_group_create_internal_record(gc, internal_group_id, external_group_id, NULL);
+ group = qq_group_create_internal_record(gc, id, ext_id, NULL);
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_ADMIN;
group->creator_uid = qd->uid;
qq_group_refresh(gc, group);
- qq_group_activate_group(gc, internal_group_id);
- qq_send_cmd_group_get_group_info(gc, group);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_ACTIVATE, id);
+ qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, id);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in create Qun, external ID %d\n", group->external_group_id);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in create Qun, external ID %d\n", group->ext_id);
g = g_new0(gc_and_uid, 1);
g->gc = gc;
- g->uid = internal_group_id;
+ g->uid = id;
purple_request_action(gc, _("QQ Qun Operation"),
_("You have successfully created a Qun"),
@@ -387,54 +376,37 @@ void qq_group_process_create_group_reply
_("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid));
}
-/* 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)
-{
- guint8 data[16] = {0};
- gint bytes = 0;
- g_return_if_fail(internal_group_id > 0);
-
- bytes = 0;
- /* we create the simplest group, only group name is given */
- /* 000 */
- bytes += qq_put8(data + bytes, QQ_GROUP_CMD_ACTIVATE_GROUP);
- /* 001-005 */
- bytes += qq_put32(data + bytes, internal_group_id);
-
- qq_send_group_cmd(gc, NULL, data, bytes);
-}
-
void qq_group_process_activate_group_reply(guint8 *data, gint len, PurpleConnection *gc)
{
gint bytes;
- guint32 internal_group_id;
+ guint32 id;
qq_group *group;
g_return_if_fail(data != NULL);
bytes = 0;
- bytes += qq_get32(&internal_group_id, data + bytes);
- g_return_if_fail(internal_group_id > 0);
+ bytes += qq_get32(&id, data + bytes);
+ g_return_if_fail(id > 0);
/* we should have its info locally */
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
g_return_if_fail(group != NULL);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in activate Qun %d\n", group->external_group_id);
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in activate Qun %d\n", group->ext_id);
}
void qq_group_manage_group(PurpleConnection *gc, GHashTable *data)
{
- gchar *internal_group_id_ptr;
- guint32 internal_group_id;
+ gchar *id_ptr;
+ guint32 id;
qq_group *group;
g_return_if_fail(data != NULL);
- internal_group_id_ptr = g_hash_table_lookup(data, "internal_group_id");
- internal_group_id = strtol(internal_group_id_ptr, NULL, 10);
- g_return_if_fail(internal_group_id > 0);
+ id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_INTERNAL_ID);
+ id = strtol(id_ptr, NULL, 10);
+ g_return_if_fail(id > 0);
- group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
+ group = qq_room_search_id(gc, id);
g_return_if_fail(group != NULL);
/* XXX insert UI code here */
============================================================
--- libpurple/protocols/qq/group_opt.h c478042d47483c53f0fdc3407b7951fba7fa2e51
+++ libpurple/protocols/qq/group_opt.h c4a0487f1ba87e92a56d484b63a0ccdbaeda83ef
@@ -33,7 +33,7 @@ typedef struct _group_member_opt {
typedef struct _group_member_opt {
PurpleConnection *gc;
- guint32 internal_group_id;
+ guint32 id;
guint32 member;
} group_member_opt;
@@ -48,7 +48,7 @@ void qq_group_modify_members(PurpleConne
};
void qq_group_modify_members(PurpleConnection *gc, qq_group *group, guint32 *new_members);
-void qq_group_modify_info(PurpleConnection *gc, qq_group *group);
+void qq_room_change_info(PurpleConnection *gc, qq_group *group);
void qq_group_approve_application_with_struct(group_member_opt *g);
void qq_group_reject_application_with_struct(group_member_opt *g);
@@ -57,8 +57,7 @@ void qq_group_manage_group(PurpleConnect
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_room_create_new(PurpleConnection *gc, const gchar *name);
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);
============================================================
--- libpurple/protocols/qq/group_search.c 299665a348236ce70082918e5cc95a21a736ec7b
+++ libpurple/protocols/qq/group_search.c fc5206710a5f2e134a0a97e1d59ae1a4f4be9a46
@@ -31,9 +31,11 @@
#include "group_free.h"
#include "group_internal.h"
#include "group_join.h"
-#include "group_network.h"
#include "group_search.h"
#include "utils.h"
+#include "header_info.h"
+#include "packet_parse.h"
+#include "qq_network.h"
enum {
QQ_GROUP_SEARCH_TYPE_BY_ID = 0x01,
@@ -41,20 +43,19 @@ enum {
};
/* send packet to search for qq_group */
-void qq_send_cmd_group_search_group(PurpleConnection *gc, guint32 external_group_id)
+void qq_send_cmd_group_search_group(PurpleConnection *gc, guint32 ext_id)
{
guint8 raw_data[16] = {0};
gint bytes = 0;
guint8 type;
- type = (external_group_id == 0x00000000) ? QQ_GROUP_SEARCH_TYPE_DEMO : QQ_GROUP_SEARCH_TYPE_BY_ID;
+ type = (ext_id == 0x00000000) ? QQ_GROUP_SEARCH_TYPE_DEMO : QQ_GROUP_SEARCH_TYPE_BY_ID;
bytes = 0;
- 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);
+ bytes += qq_put32(raw_data + bytes, ext_id);
- qq_send_group_cmd(gc, NULL, raw_data, bytes);
+ qq_send_room_cmd_noid(gc, QQ_ROOM_CMD_SEARCH, raw_data, bytes);
}
static void _qq_setup_roomlist(qq_data *qd, qq_group *group)
@@ -63,14 +64,14 @@ static void _qq_setup_roomlist(qq_data *
gchar field[11];
room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, group->group_name_utf8, NULL);
- g_snprintf(field, sizeof(field), "%d", group->external_group_id);
+ g_snprintf(field, sizeof(field), "%d", group->ext_id);
purple_roomlist_room_add_field(qd->roomlist, room, field);
g_snprintf(field, sizeof(field), "%d", group->creator_uid);
purple_roomlist_room_add_field(qd->roomlist, room, field);
purple_roomlist_room_add_field(qd->roomlist, room, group->group_desc_utf8);
- g_snprintf(field, sizeof(field), "%d", group->internal_group_id);
+ g_snprintf(field, sizeof(field), "%d", group->id);
purple_roomlist_room_add_field(qd->roomlist, room, field);
- g_snprintf(field, sizeof(field), "%d", group->group_type);
+ g_snprintf(field, sizeof(field), "%d", group->type8);
purple_roomlist_room_add_field(qd->roomlist, room, field);
g_snprintf(field, sizeof(field), "%d", group->auth_type);
purple_roomlist_room_add_field(qd->roomlist, room, field);
@@ -99,9 +100,9 @@ void qq_process_group_cmd_search_group(g
bytes += qq_get8(&search_type, data + bytes);
/* now it starts with group_info_entry */
- 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_get32(&(group.id), data + bytes);
+ bytes += qq_get32(&(group.ext_id), data + bytes);
+ bytes += qq_get8(&(group.type8), data + bytes);
bytes += qq_get16(&(unknown), data + bytes);
bytes += qq_get16(&(unknown), data + bytes);
bytes += qq_get32(&(group.creator_uid), data + bytes);
@@ -119,12 +120,12 @@ void qq_process_group_cmd_search_group(g
"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.ext_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.ext_id, FALSE);
+ if (qq_room_search_id(gc, group.id) == NULL)
qq_group_create_internal_record(gc,
- group.internal_group_id, group.external_group_id, group.group_name_utf8);
+ group.id, group.ext_id, group.group_name_utf8);
qq_send_cmd_group_join_group(gc, &group);
} else {
_qq_setup_roomlist(qd, &group);
============================================================
--- libpurple/protocols/qq/header_info.c c6c9cf5f72e960b0a7772174c2a14cbedcf9f011
+++ libpurple/protocols/qq/header_info.c 3b81718aecc45aa7425e5da435eeab9b0096a99b
@@ -61,58 +61,6 @@
#define QQ_SERVER_0100 0x0100 /* server */
-/* given command alias, return the command name accordingly */
-const gchar *qq_get_cmd_desc(gint type)
-{
- switch (type) {
- case QQ_CMD_LOGOUT:
- return "QQ_CMD_LOGOUT";
- case QQ_CMD_KEEP_ALIVE:
- return "QQ_CMD_KEEP_ALIVE";
- case QQ_CMD_UPDATE_INFO:
- return "QQ_CMD_UPDATE_INFO";
- case QQ_CMD_SEARCH_USER:
- return "QQ_CMD_SEARCH_USER";
- case QQ_CMD_GET_USER_INFO:
- return "QQ_CMD_GET_USER_INFO";
- case QQ_CMD_ADD_BUDDY_WO_AUTH:
- return "QQ_CMD_ADD_BUDDY_WO_AUTH";
- case QQ_CMD_DEL_BUDDY:
- return "QQ_CMD_DEL_BUDDY";
- case QQ_CMD_BUDDY_AUTH:
- return "QQ_CMD_BUDDY_AUTH";
- case QQ_CMD_CHANGE_ONLINE_STATUS:
- return "QQ_CMD_CHANGE_ONLINE_STATUS";
- case QQ_CMD_ACK_SYS_MSG:
- return "QQ_CMD_ACK_SYS_MSG";
- case QQ_CMD_SEND_IM:
- return "QQ_CMD_SEND_IM";
- case QQ_CMD_RECV_IM:
- return "QQ_CMD_RECV_IM";
- case QQ_CMD_REMOVE_SELF:
- return "QQ_CMD_REMOVE_SELF";
- case QQ_CMD_LOGIN:
- return "QQ_CMD_LOGIN";
- case QQ_CMD_GET_BUDDIES_LIST:
- return "QQ_CMD_GET_BUDDIES_LIST";
- case QQ_CMD_GET_BUDDIES_ONLINE:
- return "QQ_CMD_GET_BUDDIES_ONLINE";
- case QQ_CMD_GROUP_CMD:
- return "QQ_CMD_GROUP_CMD";
- case QQ_CMD_GET_ALL_LIST_WITH_GROUP:
- return "QQ_CMD_GET_ALL_LIST_WITH_GROUP";
- case QQ_CMD_GET_LEVEL:
- return "QQ_CMD_GET_LEVEL";
- case QQ_CMD_TOKEN:
- return "QQ_CMD_TOKEN";
- case QQ_CMD_RECV_MSG_SYS:
- return "QQ_CMD_RECV_MSG_SYS";
- case QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS:
- return "QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS";
- default:
- return "Unknown";
- }
-}
/* given source tag, return its description accordingly */
const gchar *qq_get_ver_desc(gint source)
@@ -177,3 +125,112 @@ const gchar *qq_get_ver_desc(gint source
return "Unknown";
}
}
+
+/* given command alias, return the command name accordingly */
+const gchar *qq_get_cmd_desc(gint cmd)
+{
+ switch (cmd) {
+ case QQ_CMD_LOGOUT:
+ return "QQ_CMD_LOGOUT";
+ case QQ_CMD_KEEP_ALIVE:
+ return "QQ_CMD_KEEP_ALIVE";
+ case QQ_CMD_UPDATE_INFO:
+ return "QQ_CMD_UPDATE_INFO";
+ case QQ_CMD_SEARCH_USER:
+ return "QQ_CMD_SEARCH_USER";
+ case QQ_CMD_GET_USER_INFO:
+ return "QQ_CMD_GET_USER_INFO";
+ case QQ_CMD_ADD_BUDDY_WO_AUTH:
+ return "QQ_CMD_ADD_BUDDY_WO_AUTH";
+ case QQ_CMD_DEL_BUDDY:
+ return "QQ_CMD_DEL_BUDDY";
+ case QQ_CMD_BUDDY_AUTH:
+ return "QQ_CMD_BUDDY_AUTH";
+ case QQ_CMD_CHANGE_ONLINE_STATUS:
+ return "QQ_CMD_CHANGE_ONLINE_STATUS";
+ case QQ_CMD_ACK_SYS_MSG:
+ return "QQ_CMD_ACK_SYS_MSG";
+ case QQ_CMD_SEND_IM:
+ return "QQ_CMD_SEND_IM";
+ case QQ_CMD_RECV_IM:
+ return "QQ_CMD_RECV_IM";
+ case QQ_CMD_REMOVE_SELF:
+ return "QQ_CMD_REMOVE_SELF";
+ case QQ_CMD_LOGIN:
+ return "QQ_CMD_LOGIN";
+ case QQ_CMD_GET_BUDDIES_LIST:
+ return "QQ_CMD_GET_BUDDIES_LIST";
+ case QQ_CMD_GET_BUDDIES_ONLINE:
+ return "QQ_CMD_GET_BUDDIES_ONLINE";
+ case QQ_CMD_ROOM:
+ return "QQ_CMD_ROOM";
+ case QQ_CMD_GET_BUDDIES_AND_ROOMS:
+ return "QQ_CMD_GET_BUDDIES_AND_ROOMS";
+ case QQ_CMD_GET_LEVEL:
+ return "QQ_CMD_GET_LEVEL";
+ case QQ_CMD_TOKEN:
+ return "QQ_CMD_TOKEN";
+ case QQ_CMD_RECV_MSG_SYS:
+ return "QQ_CMD_RECV_MSG_SYS";
+ case QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS:
+ return "QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS";
+ default:
+ return "Unknown";
+ }
+}
+
+const gchar *qq_get_room_cmd_desc(gint room_cmd)
+{
+ switch (room_cmd) {
+ case QQ_ROOM_CMD_CREATE:
+ return "QQ_ROOM_CMD_CREATE";
+ case QQ_ROOM_CMD_MEMBER_OPT:
+ return "QQ_ROOM_CMD_MEMBER_OPT";
+ case QQ_ROOM_CMD_CHANGE_INFO:
+ return "QQ_ROOM_CMD_CHANGE_INFO";
+ case QQ_ROOM_CMD_GET_INFO:
+ return "QQ_ROOM_CMD_GET_INFO";
+ case QQ_ROOM_CMD_ACTIVATE:
+ return "QQ_ROOM_CMD_ACTIVATE";
+ case QQ_ROOM_CMD_SEARCH:
+ return "QQ_ROOM_CMD_SEARCH";
+ case QQ_ROOM_CMD_JOIN:
+ return "QQ_ROOM_CMD_JOIN";
+ case QQ_ROOM_CMD_AUTH:
+ return "QQ_ROOM_CMD_AUTH";
+ case QQ_ROOM_CMD_QUIT:
+ return "QQ_ROOM_CMD_QUIT";
+ case QQ_ROOM_CMD_SEND_MSG:
+ return "QQ_ROOM_CMD_SEND_MSG";
+ case QQ_ROOM_CMD_GET_ONLINES:
+ return "QQ_ROOM_CMD_GET_ONLINES";
+ case QQ_ROOM_CMD_GET_MEMBER_INFO:
+ return "QQ_ROOM_CMD_GET_MEMBER_INFO";
+ case QQ_ROOM_CMD_CHANGE_CARD:
+ return "QQ_ROOM_CMD_CHANGE_CARD";
+ case QQ_ROOM_CMD_GET_REALNAMES:
+ return "QQ_ROOM_CMD_GET_REALNAMES";
+ case QQ_ROOM_CMD_GET_CARD:
+ return "QQ_ROOM_CMD_GET_CARD";
+ case QQ_ROOM_CMD_SEND_IM_EX:
+ return "QQ_ROOM_CMD_SEND_IM_EX";
+ case QQ_ROOM_CMD_ADMIN:
+ return "QQ_ROOM_CMD_ADMIN";
+ case QQ_ROOM_CMD_TRANSFER:
+ return "QQ_ROOM_CMD_TRANSFER";
+ case QQ_ROOM_CMD_TEMP_CREATE:
+ return "QQ_ROOM_CMD_TEMP_CREATE";
+ case QQ_ROOM_CMD_TEMP_CHANGE_MEMBER:
+ return "QQ_ROOM_CMD_TEMP_CHANGE_MEMBER";
+ case QQ_ROOM_CMD_TEMP_QUIT:
+ return "QQ_ROOM_CMD_TEMP_QUIT";
+ case QQ_ROOM_CMD_TEMP_GET_INFO:
+ return "QQ_ROOM_CMD_TEMP_GET_INFO";
+ case QQ_ROOM_CMD_TEMP_SEND_IM:
+ return "QQ_ROOM_CMD_TEMP_SEND_IM";
+ case QQ_ROOM_CMD_TEMP_GET_MEMBERS:
+ return "QQ_ROOM_CMD_TEMP_GET_MEMBERS";
+ default:
+ return "Unknown QQ Room Command";
+ }
+}
============================================================
--- libpurple/protocols/qq/header_info.h f85e775fc860c2e17409a57da6220bfbaec4b545
+++ libpurple/protocols/qq/header_info.h b6c6b91c69672f9605fd6dbed3c27a930319b774
@@ -35,6 +35,8 @@
#define QQ_CLIENT 0x0d55
+const gchar *qq_get_ver_desc(gint source);
+
/* list of known QQ commands */
enum {
QQ_CMD_LOGOUT = 0x0001, /* log out */
@@ -56,8 +58,8 @@ enum {
QQ_CMD_GET_BUDDIES_LIST = 0x0026, /* get buddies list */
QQ_CMD_GET_BUDDIES_ONLINE = 0x0027, /* get online buddies list */
QQ_CMD_CELL_PHONE_2 = 0x0029, /* cell phone 2 */
- QQ_CMD_GROUP_CMD = 0x0030, /* group command */
- QQ_CMD_GET_ALL_LIST_WITH_GROUP = 0x0058,
+ QQ_CMD_ROOM = 0x0030, /* room command */
+ QQ_CMD_GET_BUDDIES_AND_ROOMS = 0x0058,
QQ_CMD_GET_LEVEL = 0x005C, /* get level for one or more buddies */
QQ_CMD_TOKEN = 0x0062, /* get login token */
QQ_CMD_RECV_MSG_SYS = 0x0080, /* receive a system message */
@@ -66,6 +68,34 @@ const gchar *qq_get_cmd_desc(gint type);
const gchar *qq_get_cmd_desc(gint type);
-const gchar *qq_get_ver_desc(gint source);
+enum {
+ QQ_ROOM_CMD_CREATE = 0x01,
+ QQ_ROOM_CMD_MEMBER_OPT = 0x02,
+ QQ_ROOM_CMD_CHANGE_INFO = 0x03,
+ QQ_ROOM_CMD_GET_INFO = 0x04,
+ QQ_ROOM_CMD_ACTIVATE = 0x05,
+ QQ_ROOM_CMD_SEARCH = 0x06,
+ QQ_ROOM_CMD_JOIN = 0x07,
+ QQ_ROOM_CMD_AUTH = 0x08,
+ QQ_ROOM_CMD_QUIT = 0x09,
+ QQ_ROOM_CMD_SEND_MSG = 0x0a,
+ QQ_ROOM_CMD_GET_ONLINES = 0x0b,
+ QQ_ROOM_CMD_GET_MEMBER_INFO = 0x0c,
+ QQ_ROOM_CMD_CHANGE_CARD = 0x0E,
+ QQ_ROOM_CMD_GET_REALNAMES = 0x0F,
+ QQ_ROOM_CMD_GET_CARD = 0x10,
+ QQ_ROOM_CMD_SEND_IM_EX = 0x1A,
+ QQ_ROOM_CMD_ADMIN = 0x1B,
+ QQ_ROOM_CMD_TRANSFER = 0x1C,
+ QQ_ROOM_CMD_TEMP_CREATE = 0x30,
+ QQ_ROOM_CMD_TEMP_CHANGE_MEMBER = 0x31,
+ QQ_ROOM_CMD_TEMP_QUIT = 0x32,
+ QQ_ROOM_CMD_TEMP_GET_INFO = 0x33,
+ QQ_ROOM_CMD_TEMP_SEND_IM = 0x35,
+ QQ_ROOM_CMD_TEMP_GET_MEMBERS = 0x37,
+};
+
+const gchar *qq_get_room_cmd_desc(gint room_cmd);
+
#endif
============================================================
--- libpurple/protocols/qq/im.c 2cd45a4fefd3dc05b7a4da3220e19254b8fff42b
+++ libpurple/protocols/qq/im.c 90e409aba8c08748d11f8702874197fa1f8c6a3d
@@ -35,7 +35,6 @@
#include "buddy_list.h"
#include "buddy_opt.h"
#include "char_conv.h"
-#include "crypt.h"
#include "group_im.h"
#include "header_info.h"
#include "im.h"
@@ -541,52 +540,35 @@ void qq_send_packet_im(PurpleConnection
}
/* parse the reply to send_im */
-void qq_process_send_im_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+void qq_process_send_im_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len;
- guint8 *data, reply;
- gint bytes = 0;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- 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);
- }
- else
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "IM ACK OK\n");
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt send im reply\n");
+ if (data[0] != 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);
+ } else {
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "IM ACK OK\n");
}
}
/* I receive a message, mainly it is text msg,
* but we need to proess other types (group etc) */
-void qq_process_recv_im(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection *gc)
+void qq_process_recv_im(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc)
{
qq_data *qd;
- gint len, bytes;
- guint8 *data;
+ gint bytes;
qq_recv_im_header *im_header;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- if (!qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt rev im\n");
- }
-
- if (len < 16) { /* we need to ack with the first 16 bytes */
+ if (data_len < 16) { /* we need to ack with the first 16 bytes */
purple_debug(PURPLE_DEBUG_ERROR, "QQ", "IM is too short\n");
return;
} else {
@@ -594,9 +576,9 @@ void qq_process_recv_im(guint8 *buf, gin
}
/* check len first */
- if (len < 20) { /* length of im_header */
+ if (data_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);
+ "Fail read recv IM header, len should longer than 20 bytes, read %d bytes\n", data_len);
return;
}
@@ -617,7 +599,7 @@ void qq_process_recv_im(guint8 *buf, gin
}
/* check bytes */
- if (bytes >= len - 1) {
+ if (bytes >= data_len - 1) {
purple_debug (PURPLE_DEBUG_WARNING, "QQ", "Received IM is empty\n");
return;
}
@@ -626,57 +608,57 @@ void qq_process_recv_im(guint8 *buf, gin
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 + bytes, len - bytes, gc); /* position and rest length */
+ _qq_process_recv_normal_im(data + bytes, data_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 + bytes, len - bytes, gc);
+ _qq_process_recv_normal_im(data + bytes, data_len - bytes, gc);
break;
case QQ_RECV_IM_UNKNOWN_QUN_IM:
case QQ_RECV_IM_TEMP_QUN_IM:
case QQ_RECV_IM_QUN_IM:
purple_debug(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 + bytes, len - bytes, im_header->sender_uid, gc, im_header->im_type);
+ /* sender_uid is in fact id */
+ qq_process_recv_group_im(data + bytes, data_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);
- /* sender_uid is in fact internal_group_id
+ /* sender_uid is group id
* we need this to create a dummy group and add to blist */
- qq_process_recv_group_im_been_added(data + bytes, len - bytes, im_header->sender_uid, gc);
+ qq_process_recv_group_im_been_added(data + bytes, data_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);
- /* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im_been_removed(data + bytes, len - bytes, im_header->sender_uid, gc);
+ /* sender_uid is group id */
+ qq_process_recv_group_im_been_removed(data + bytes, data_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);
- /* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im_apply_join(data + bytes, len - bytes, im_header->sender_uid, gc);
+ /* sender_uid is group id */
+ qq_process_recv_group_im_apply_join(data + bytes, data_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);
- /* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im_been_approved(data + bytes, len - bytes, im_header->sender_uid, gc);
+ /* sender_uid is group id */
+ qq_process_recv_group_im_been_approved(data + bytes, data_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);
- /* sender_uid is in fact internal_group_id */
- qq_process_recv_group_im_been_rejected(data + bytes, len - bytes, im_header->sender_uid, gc);
+ /* sender_uid is group id */
+ qq_process_recv_group_im_been_rejected(data + bytes, data_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 + bytes, len - bytes, gc);
+ _qq_process_recv_sys_im(data + bytes, data_len - bytes, gc);
break;
default:
purple_debug(PURPLE_DEBUG_WARNING, "QQ",
============================================================
--- libpurple/protocols/qq/im.h 702fe1fc15e0706681450b66dba0cb3d3bf7f0b7
+++ libpurple/protocols/qq/im.h 9bb66bca43da19dfdcd526333228f8dd7648de75
@@ -59,7 +59,7 @@ void qq_send_packet_im(PurpleConnection
gboolean is_bold, gboolean is_italic, gboolean is_underline, gint len);
void qq_send_packet_im(PurpleConnection *gc, guint32 to_uid, gchar *msg, gint type);
-void qq_process_recv_im(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection *gc);
-void qq_process_send_im_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
+void qq_process_recv_im(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc);
+void qq_process_send_im_reply(guint8 *data, gint data_len, PurpleConnection *gc);
#endif
============================================================
--- libpurple/protocols/qq/packet_parse.h 2a60f02107e0c4e04f2c8186e1adf8f0466b36e9
+++ libpurple/protocols/qq/packet_parse.h 90c1324d256d6a85ad0baf0f7aa577c52dae4234
@@ -37,11 +37,7 @@
*/
#define MAX_PACKET_SIZE 65535
-#ifndef _WIN32
#include <netinet/in.h>
-#else
-#include "win32dep.h"
-#endif
gint qq_get8(guint8 *b, guint8 *buf);
gint qq_get16(guint16 *w, guint8 *buf);
============================================================
--- libpurple/protocols/qq/qq.c d8f4f5b8cbd423c27fe98736d82c6fd9d757b5ca
+++ libpurple/protocols/qq/qq.c e34e81013f55c32cb9d3ce1dc596d88c8ef356aa
@@ -42,7 +42,6 @@
#include "buddy_opt.h"
#include "buddy_list.h"
#include "char_conv.h"
-#include "crypt.h"
#include "group.h"
#include "group_find.h"
#include "group_im.h"
@@ -551,7 +550,7 @@ static void _qq_menu_create_permanent_gr
_("Input Qun name here"),
_("Only QQ members can create permanent Qun"),
"OpenQ", FALSE, FALSE, NULL,
- _("Create"), G_CALLBACK(qq_group_create_with_name), _("Cancel"), NULL, gc);
+ _("Create"), G_CALLBACK(qq_room_create_new), _("Cancel"), NULL, gc);
}
*/
@@ -689,8 +688,8 @@ static gchar *_qq_get_chat_buddy_real_na
return chat_name_to_purple_name(who);
}
-static PurplePluginProtocolInfo prpl_info =
-{
+PurplePlugin *my_protocol = NULL;
+static PurplePluginProtocolInfo prpl_info = {
OPT_PROTO_CHAT_TOPIC | OPT_PROTO_USE_POINTSIZE,
NULL, /* user_splits */
NULL, /* protocol_options */
@@ -753,11 +752,11 @@ static PurplePluginProtocolInfo prpl_inf
NULL, /* PurpleWhiteboardPrplOps */
NULL, /* send_raw */
NULL, /* roomlist_room_serialize */
- NULL, /* unregister_user */
- NULL, /* send_attention */
- NULL, /* get attention_types */
- sizeof(PurplePluginProtocolInfo), /* struct_size */
+ /* padding */
+ NULL,
+ NULL,
+ NULL,
NULL
};
@@ -820,6 +819,8 @@ static void init_plugin(PurplePlugin *pl
option = purple_account_option_int_new(_("Update interval(s)"), "update_interval", 300);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+ my_protocol = plugin;
+
purple_prefs_add_none("/plugins/prpl/qq");
purple_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE);
purple_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE);
============================================================
--- libpurple/protocols/qq/qq.h d7c03768b041fdfbecb593d720bdf9e795b2e56b
+++ libpurple/protocols/qq/qq.h 974b192d233ebed29ca2e79a6beb63d54167215e
@@ -35,7 +35,6 @@
#include "roomlist.h"
#define QQ_KEY_LENGTH 16
-#define QQ_DEBUG 1 /* whether we are doing DEBUG */
#ifdef _WIN32
const char *qq_win32_buddy_icon_dir(void);
@@ -138,7 +137,6 @@ struct _qq_data {
gint channel; /* the id for opened chat conversation */
GList *groups;
- GList *group_packets;
GSList *joining_groups;
GSList *adding_groups_from_server; /* internal ids of groups the server wants in my blist */
GList *buddies;
============================================================
--- libpurple/protocols/qq/qq_base.c 4e74703569de34e00044f6a36aed04c6cb784a26
+++ libpurple/protocols/qq/qq_base.c 529b343ed51bb7740d680c11e73b2f473bca9d48
@@ -30,7 +30,7 @@
#include "buddy_info.h"
#include "buddy_list.h"
#include "char_conv.h"
-#include "crypt.h"
+#include "qq_crypt.h"
#include "group.h"
#include "header_info.h"
#include "qq_base.h"
@@ -161,7 +161,7 @@ static gint8 process_login_ok(PurpleConn
bytes += qq_get8(&lrop.result, data + bytes);
/* 001-016: session key */
bytes += qq_getdata(lrop.session_key, sizeof(lrop.session_key), data + bytes);
- purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get session_key done\n");
+ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Got session_key\n");
/* 017-020: login uid */
bytes += qq_get32(&lrop.uid, data + bytes);
/* 021-024: server detected user public IP */
@@ -300,23 +300,26 @@ void qq_send_packet_login(PurpleConnecti
g_return_if_fail(qd->token != NULL && qd->token_len > 0);
- 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 */
#ifdef DEBUG
memset(qd->inikey, 0x01, sizeof(qd->inikey));
#else
for (bytes = 0; bytes < sizeof(qd->inikey); bytes++) {
- qd->inikey[bytes] = (guint8) (g_random_int_range(0, 255) % 256);
+ qd->inikey[bytes] = (guint8) (rand() & 0xff);
}
#endif
+ 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 */
+
bytes = 0;
/* now generate the encrypted data
* 000-015 use password_twice_md5 as key to encrypt empty string */
- qq_encrypt((guint8 *) "", 0, qd->password_twice_md5, raw_data + bytes, &encrypted_len);
- bytes += 16;
+ encrypted_len = qq_encrypt(raw_data + bytes, (guint8 *) "", 0, qd->password_twice_md5);
+ g_return_if_fail(encrypted_len == 16);
+ bytes += encrypted_len;
+
/* 016-016 */
bytes += qq_put8(raw_data + bytes, 0x00);
/* 017-020, used to be IP, now zero */
@@ -337,7 +340,7 @@ void qq_send_packet_login(PurpleConnecti
bytes += qq_putdata(raw_data + bytes, login_100_bytes, 100);
/* all zero left */
- qq_encrypt(raw_data, QQ_LOGIN_DATA_LENGTH, qd->inikey, encrypted_data, &encrypted_len);
+ encrypted_len = qq_encrypt(encrypted_data, raw_data, QQ_LOGIN_DATA_LENGTH, qd->inikey);
buf = g_newa(guint8, MAX_PACKET_SIZE);
memset(buf, 0, MAX_PACKET_SIZE);
@@ -405,36 +408,15 @@ void qq_send_packet_logout(PurpleConnect
}
/* process the login reply packet */
-guint8 qq_process_login_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
+guint8 qq_process_login_reply(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- guint8 *data;
- gint data_len;
gchar* error_msg;
- g_return_val_if_fail(buf != NULL && buf_len != 0, QQ_LOGIN_REPLY_ERR_MISC);
+ g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR_MISC);
qd = (qq_data *) gc->proto_data;
- data_len = buf_len;
- data = g_newa(guint8, data_len);
-
- if (qq_decrypt(buf, buf_len, qd->inikey, data, &data_len)) {
- purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- "Decrypt login reply packet with inikey, %d bytes\n", data_len);
- } else {
- /* reset data_len since it may changed */
- data_len = buf_len;
- if (qq_decrypt(buf, buf_len, qd->password_twice_md5, data, &data_len)) {
- purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "Decrypt login reply packet with password_twice_md5, %d bytes\n", data_len);
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ",
- "No idea how to decrypt login reply\n");
- return QQ_LOGIN_REPLY_ERR_MISC;
- }
- }
-
switch (data[0]) {
case QQ_LOGIN_REPLY_OK:
purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is OK\n");
@@ -452,7 +434,7 @@ guint8 qq_process_login_reply(guint8 *bu
break;
}
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown reply code: %d\n", data[0]);
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown reply code: 0x%02X\n", data[0]);
qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ",
data, data_len,
">>> [default] decrypt and dump");
@@ -482,28 +464,19 @@ void qq_send_packet_keep_alive(PurpleCon
}
/* parse the return of keep-alive packet, it includes some system information */
-gboolean qq_process_keep_alive(guint8 *buf, gint buf_len, PurpleConnection *gc)
+gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc)
{
qq_data *qd;
- gint len;
gchar **segments;
- guint8 *data;
- g_return_val_if_fail(buf != NULL && buf_len != 0, FALSE);
+ g_return_val_if_fail(data != NULL && data_len != 0, FALSE);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &len) ) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt keep alive reply\n");
- return FALSE;
- }
-
/* qq_show_packet("Keep alive reply packet", data, len); */
/* the last one is 60, don't know what it is */
- if (NULL == (segments = split_data(data, len, "\x1f", 6)))
+ if (NULL == (segments = split_data(data, data_len, "\x1f", 6)))
return TRUE;
/* segments[0] and segment[1] are all 0x30 ("0") */
============================================================
--- libpurple/protocols/qq/qq_base.h 1432e2c23df0251a58eeec56798e3281bf94cd17
+++ libpurple/protocols/qq/qq_base.h 6d6f1ef5450dc8bc5c06af0135bf2e1573835b04
@@ -47,10 +47,10 @@ void qq_send_packet_login(PurpleConnecti
guint8 qq_process_token_reply(PurpleConnection *gc, gchar *error_msg, guint8 *buf, gint buf_len);
void qq_send_packet_login(PurpleConnection *gc);
-guint8 qq_process_login_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
+guint8 qq_process_login_reply(guint8 *data, gint data_len, PurpleConnection *gc);
void qq_send_packet_logout(PurpleConnection *gc);
void qq_send_packet_keep_alive(PurpleConnection *gc);
-gboolean qq_process_keep_alive(guint8 *buf, gint buf_len, PurpleConnection *gc);
+gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc);
#endif
============================================================
--- libpurple/protocols/qq/qq_network.c 07fffe30f3c3831cb1fd50cc4b4bc2d1a8223510
+++ libpurple/protocols/qq/qq_network.c a7ce5c867d6fa1cc30b1f50a11ba2b7652496b19
@@ -34,7 +34,7 @@
#include "buddy_info.h"
#include "group_info.h"
#include "group_free.h"
-#include "crypt.h"
+#include "qq_crypt.h"
#include "header_info.h"
#include "qq_base.h"
#include "buddy_list.h"
@@ -167,6 +167,9 @@ static void packet_process(PurpleConnect
guint16 source_tag;
guint16 cmd;
guint16 seq; /* May be ack_seq or send_seq, depends on cmd */
+
+ guint8 room_cmd;
+ guint32 room_id;
qq_transaction *trans;
@@ -180,12 +183,11 @@ static void packet_process(PurpleConnect
bytes = 0;
bytes += packet_get_header(&header_tag, &source_tag, &cmd, &seq, buf + bytes);
- if (QQ_DEBUG) {
+#if 1
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "==> [%05d] 0x%04X %s, from (0x%04X %s)\n",
- seq, cmd, qq_get_cmd_desc(cmd), source_tag, qq_get_ver_desc(source_tag));
- }
-
+ "==> [%05d] 0x%04X %s, from (0x%04X %s) len %d\n",
+ seq, cmd, qq_get_cmd_desc(cmd), source_tag, qq_get_ver_desc(source_tag), buf_len);
+#endif
bytes_not_read = buf_len - bytes - 1;
/* ack packet, we need to update send tranactions */
@@ -214,8 +216,19 @@ static void packet_process(PurpleConnect
}
/* this is the length of all the encrypted data (also remove tail tag */
- qq_proc_cmd_reply(gc, cmd, seq, buf + bytes, bytes_not_read);
-
+ if (cmd == QQ_CMD_ROOM) {
+ room_cmd = qq_trans_get_room_cmd(trans);
+ room_id = qq_trans_get_room_id(trans);
+#if 1
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "%s (0x%02X ) for room %d, len %d\n",
+ qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len);
+#endif
+ qq_proc_room_cmd_reply(gc, seq, room_cmd, room_id, buf + bytes, bytes_not_read);
+ } else {
+ qq_proc_cmd_reply(gc, cmd, seq, buf + bytes, bytes_not_read);
+ }
+
/* check is redirect or not, and do it now */
if (qd->is_redirect) {
/* free resource except real_hostname and port */
@@ -933,7 +946,6 @@ void qq_disconnect(PurpleConnection *gc)
qd->my_ip.s_addr = 0;
- qq_group_packets_free(qd);
qq_group_free_all(qd);
qq_add_buddy_request_free(qd);
qq_info_query_free(qd);
@@ -945,16 +957,8 @@ static gint encap(qq_data *qd, guint8 *b
{
gint bytes = 0;
g_return_val_if_fail(qd != NULL && buf != NULL && maxlen > 0, -1);
+ g_return_val_if_fail(data != NULL && data_len > 0, -1);
- if (data == NULL) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail encap packet, data is NULL\n");
- return -1;
- }
- if (data_len <= 0) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail encap packet, data len <= 0\n");
- return -1;
- }
-
/* QQ TCP packet has two bytes in the begining defines packet length
* so leave room here to store packet size */
if (qd->use_tcp) {
@@ -1007,12 +1011,12 @@ gint qq_send_data(qq_data *qd, guint16 c
qq_trans_add_client_cmd(qd, cmd, seq, data, data_len);
}
- if (QQ_DEBUG) {
+#if 1
/* qq_show_packet("QQ_SEND_DATA", buf, buf_len); */
purple_debug(PURPLE_DEBUG_INFO, "QQ",
- "<== [%05d], %s, total %d bytes is sent %d\n",
- seq, qq_get_cmd_desc(cmd), buf_len, bytes_sent);
- }
+ "<== [%05d], 0x%04X %s, total %d bytes is sent %d\n",
+ seq, cmd, qq_get_cmd_desc(cmd), buf_len, bytes_sent);
+#endif
return bytes_sent;
}
@@ -1026,11 +1030,26 @@ gint qq_send_cmd_detail(qq_data *qd, gui
g_return_val_if_fail(qd != NULL, -1);
g_return_val_if_fail(data != NULL && data_len > 0, -1);
- encrypted_len = data_len + 16; /* at most 16 bytes more */
- encrypted_data = g_newa(guint8, encrypted_len);
+ /* at most 16 bytes more */
+ encrypted_data = g_newa(guint8, data_len + 16);
+#if 0
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_ENCRYPT",
+ "Before %d: [%05d] 0x%04X %s\n",
+ data_len, seq, cmd, qq_get_cmd_desc(cmd));
+#endif
+ encrypted_len = qq_encrypt(encrypted_data, data, data_len, qd->session_key);
+ if (encrypted_len < 16) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ_ENCRYPT",
+ "Error len %d: [%05d] 0x%04X %s\n",
+ encrypted_len, seq, cmd, qq_get_cmd_desc(cmd));
+ return -1;
+ }
- qq_encrypt(data, data_len, qd->session_key, encrypted_data, &encrypted_len);
-
+#if 0
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_ENCRYPT",
+ "After %d: [%05d] 0x%04X %s\n",
+ encrypted_len, seq, cmd, qq_get_cmd_desc(cmd));
+#endif
return qq_send_data(qd, cmd, seq, need_ack, encrypted_data, encrypted_len);
}
@@ -1043,3 +1062,81 @@ gint qq_send_cmd(qq_data *qd, guint16 cm
qd->send_seq++;
return qq_send_cmd_detail(qd, cmd, qd->send_seq, TRUE, data, data_len);
}
+
+gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd,
+ guint8 *data, gint data_len)
+{
+ return qq_send_room_cmd(gc, room_cmd, 0, data, data_len);
+}
+
+gint qq_send_room_cmd_only(PurpleConnection *gc, guint8 room_cmd, guint32 room_id)
+{
+ g_return_val_if_fail(room_cmd > 0 && room_id > 0, -1);
+ return qq_send_room_cmd(gc, room_cmd, room_id, NULL, 0);
+}
+
+gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id,
+ guint8 *data, gint data_len)
+{
+ qq_data *qd;
+
+ guint8 *buf;
+ gint buf_len;
+ guint8 *encrypted_data;
+ gint encrypted_len;
+ gint bytes_sent;
+ guint16 seq;
+
+ g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
+ qd = (qq_data *) gc->proto_data;
+
+ buf = g_newa(guint8, MAX_PACKET_SIZE);
+ memset(buf, 0, MAX_PACKET_SIZE);
+
+ /* encap room_cmd and room id to buf*/
+ buf_len = 0;
+ buf_len += qq_put8(buf + buf_len, room_cmd);
+ if (room_id != 0) {
+ /* id 0 is for QQ Demo Group, now there are not existed*/
+ buf_len += qq_put32(buf + buf_len, room_id);
+ }
+ if (data != NULL && data_len > 0) {
+ buf_len += qq_putdata(buf + buf_len, data, data_len);
+ }
+ qd->send_seq++;
+ seq = qd->send_seq;
+
+ /* Encrypt to encrypted_data with session_key */
+ /* at most 16 bytes more */
+ encrypted_data = g_newa(guint8, buf_len + 16);
+ encrypted_len = qq_encrypt(encrypted_data, buf, buf_len, qd->session_key);
+ if (encrypted_len < 16) {
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ_ENCRYPT",
+ "Error len %d: [%05d] QQ_CMD_ROOM.(0x%02X %s)\n",
+ encrypted_len, seq, room_cmd, qq_get_room_cmd_desc(room_cmd));
+ return -1;
+ }
+
+ /* Encap header to buf */
+ buf_len = encap(qd, buf, MAX_PACKET_SIZE, QQ_CMD_ROOM, seq, encrypted_data, encrypted_len);
+ if (buf_len <= 0) {
+ return -1;
+ }
+
+ if (qd->use_tcp) {
+ bytes_sent = tcp_send_out(qd, buf, buf_len);
+ } else {
+ bytes_sent = udp_send_out(qd, buf, buf_len);
+ }
+
+ qq_trans_add_room_cmd(qd, seq, room_cmd, room_id, buf, buf_len);
+
+#if 1
+ /* qq_show_packet("QQ_SEND_DATA", buf, buf_len); */
+ purple_debug(PURPLE_DEBUG_INFO, "QQ",
+ "<== [%05d], QQ_CMD_ROOM.(0x%02X %s) to room %d, total %d bytes is sent %d\n",
+ seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id,
+ buf_len, bytes_sent);
+#endif
+ return bytes_sent;
+}
============================================================
--- libpurple/protocols/qq/qq_network.h 2f70387ea9748845a277706943610bed929cac2f
+++ libpurple/protocols/qq/qq_network.h 2cdd0ad833eabce487e648a3199219fd25f6492e
@@ -42,4 +42,9 @@ gint qq_send_cmd_detail(qq_data *qd, gui
gint qq_send_cmd_detail(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack,
guint8 *data, gint data_len);
+gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id,
+ guint8 *data, gint data_len);
+gint qq_send_room_cmd_only(PurpleConnection *gc, guint8 room_cmd, guint32 room_id);
+gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd,
+ guint8 *data, gint data_len);
#endif
============================================================
--- libpurple/protocols/qq/qq_process.c a24508526586bd07038097496793a0bb4a9d4a64
+++ libpurple/protocols/qq/qq_process.c 888aabf106970c4e995a155900b5655529807776
@@ -37,8 +37,17 @@
#include "group_info.h"
#include "group_free.h"
#include "char_conv.h"
-#include "crypt.h"
-#include "group_network.h"
+#include "qq_crypt.h"
+
+#include "group_conv.h"
+#include "group_find.h"
+#include "group_internal.h"
+#include "group_im.h"
+#include "group_info.h"
+#include "group_join.h"
+#include "group_opt.h"
+#include "group_search.h"
+
#include "header_info.h"
#include "qq_base.h"
#include "im.h"
@@ -49,28 +58,24 @@
#include "sys_msg.h"
#include "utils.h"
+enum {
+ QQ_ROOM_CMD_REPLY_OK = 0x00,
+ QQ_ROOM_CMD_REPLY_SEARCH_ERROR = 0x02,
+ QQ_ROOM_CMD_REPLY_NOT_MEMBER = 0x0a
+};
+
/* default process, decrypt and dump */
-static void process_cmd_unknow(PurpleConnection *gc,gchar *title, guint8 *buf, gint buf_len, guint16 cmd, guint16 seq)
+static void process_cmd_unknow(PurpleConnection *gc,gchar *title, guint8 *data, gint data_len, guint16 cmd, guint16 seq)
{
qq_data *qd;
- guint8 *data;
- gint data_len;
gchar *msg_utf8 = NULL;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
- qq_show_packet(title, buf, buf_len);
+ qq_show_packet(title, data, data_len);
qd = (qq_data *) gc->proto_data;
- data_len = buf_len;
- data = g_newa(guint8, data_len);
- memset(data, 0, data_len);
- if ( !qq_decrypt(buf, buf_len, qd->session_key, data, &data_len )) {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail decrypt packet with default process\n");
- return;
- }
-
qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ",
data, data_len,
">>> [%d] %s -> [default] decrypt and dump",
@@ -78,13 +83,39 @@ static void process_cmd_unknow(PurpleCon
msg_utf8 = try_dump_as_gbk(data, data_len);
if (msg_utf8) {
+ purple_notify_info(gc, NULL, msg_utf8, NULL);
g_free(msg_utf8);
}
}
void qq_proc_cmd_server(PurpleConnection *gc,
- guint16 cmd, guint16 seq, guint8 *data, gint data_len)
+ guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len)
{
+ qq_data *qd;
+
+ guint8 *data;
+ gint data_len;
+
+ g_return_if_fail (gc != NULL && gc->proto_data != NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ data = g_newa(guint8, rcved_len);
+ data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
+ if (data_len < 0) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Can not decrypt server cmd by session key, [%05d], 0x%04X %s, len %d\n",
+ seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
+ qq_show_packet("Can not decrypted", rcved, rcved_len);
+ return;
+ }
+
+ if (data_len <= 0) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Server cmd decrypted is empty, [%05d], 0x%04X %s, len %d\n",
+ seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
+ return;
+ }
+
/* now process the packet */
switch (cmd) {
case QQ_CMD_RECV_IM:
@@ -134,7 +165,7 @@ static void process_cmd_login(PurpleConn
qq_send_packet_get_buddies_list(gc, 0);
/* refresh groups */
- qq_send_packet_get_all_list_with_group(gc, 0);
+ qq_send_packet_get_buddies_and_rooms(gc, 0);
return;
}
@@ -168,14 +199,223 @@ static void process_cmd_login(PurpleConn
}
}
+static void process_room_cmd_notify(PurpleConnection *gc,
+ guint8 room_cmd, guint8 room_id, guint8 reply_cmd, guint8 reply, guint8 *data, gint data_len)
+{
+ gchar *msg, *msg_utf8;
+ g_return_if_fail(data != NULL && data_len > 0);
+
+ msg = g_strndup((gchar *) data, data_len); /* it will append 0x00 */
+ msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
+ g_free(msg);
+
+ msg = g_strdup_printf(_(
+ "Reply %s(0x%02X )\n"
+ "Sent %s(0x%02X )\n"
+ "Room id %d, reply [0x%02X]: \n"
+ "%s"),
+ qq_get_room_cmd_desc(reply_cmd), reply_cmd,
+ qq_get_room_cmd_desc(room_cmd), room_cmd,
+ room_id, reply, msg_utf8);
+
+ purple_notify_error(gc, NULL, _("Failed room reply"), msg);
+ g_free(msg);
+ g_free(msg_utf8);
+}
+
+void qq_proc_room_cmd_reply(PurpleConnection *gc,
+ guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len)
+{
+ qq_data *qd;
+ guint8 *data;
+ gint data_len;
+ qq_group *group;
+ gint bytes;
+ guint8 reply_cmd, reply;
+
+ g_return_if_fail (gc != NULL && gc->proto_data != NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ data = g_newa(guint8, rcved_len);
+ data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
+ if (data_len < 0) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Can not decrypt room cmd by session key, [%05d], 0x%02X %s for %d, len %d\n",
+ seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+ qq_show_packet("Can not decrypted", rcved, rcved_len);
+ return;
+ }
+
+ if (room_id <= 0) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Invaild room id, [%05d], 0x%02X %s for %d, len %d\n",
+ seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+ return;
+ }
+
+ if (data_len <= 2) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Invaild len of room cmd decrypted, [%05d], 0x%02X %s for %d, len %d\n",
+ seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+ return;
+ }
+
+ group = qq_room_search_id(gc, room_id);
+ if (group == NULL) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Missing room id in [%05d], 0x%02X %s for %d, len %d\n",
+ seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+ }
+
+ bytes = 0;
+ bytes += qq_get8(&reply_cmd, data + bytes);
+ bytes += qq_get8(&reply, data + bytes);
+
+ if (reply_cmd != room_cmd) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Missing room cmd in reply 0x%02X %s, [%05d], 0x%02X %s for %d, len %d\n",
+ reply_cmd, qq_get_room_cmd_desc(reply_cmd),
+ seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len);
+ }
+
+ /* now process the packet */
+ if (reply != QQ_ROOM_CMD_REPLY_OK) {
+ if (group != NULL) {
+ qq_set_pending_id(&qd->joining_groups, group->ext_id, FALSE);
+ }
+
+ switch (reply) { /* this should be all errors */
+ case QQ_ROOM_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_ROOM_CMD_REPLY_SEARCH_ERROR:
+ if (qd->roomlist != NULL) {
+ if (purple_roomlist_get_in_progress(qd->roomlist))
+ purple_roomlist_set_in_progress(qd->roomlist, FALSE);
+ }
+ default:
+ process_room_cmd_notify(gc, room_cmd, room_id, reply_cmd, reply, data + bytes, data_len - bytes);
+ }
+ return;
+ }
+
+ /* seems ok so far, so we process the reply according to sub_cmd */
+ switch (reply_cmd) {
+ case QQ_ROOM_CMD_GET_INFO:
+ qq_process_room_cmd_get_info(data + bytes, data_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_ROOM_CMD_CREATE:
+ qq_group_process_create_group_reply(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_CHANGE_INFO:
+ qq_group_process_modify_info_reply(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_MEMBER_OPT:
+ qq_group_process_modify_members_reply(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_ACTIVATE:
+ qq_group_process_activate_group_reply(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_SEARCH:
+ qq_process_group_cmd_search_group(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_JOIN:
+ qq_process_group_cmd_join_group(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_AUTH:
+ qq_process_group_cmd_join_group_auth(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_QUIT:
+ qq_process_group_cmd_exit_group(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_SEND_MSG:
+ qq_process_group_cmd_im(data + bytes, data_len - bytes, gc);
+ break;
+ case QQ_ROOM_CMD_GET_ONLINES:
+ qq_process_room_cmd_get_onlines(data + bytes, data_len - bytes, gc);
+ if (group != NULL)
+ qq_group_conv_refresh_online_member(gc, group);
+ break;
+ case QQ_ROOM_CMD_GET_MEMBER_INFO:
+ qq_process_room_cmd_get_members(data + bytes, data_len - bytes, gc);
+ if (group != NULL)
+ qq_group_conv_refresh_online_member(gc, group);
+ break;
+ default:
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Unknow room cmd 0x%02X %s\n",
+ reply_cmd, qq_get_room_cmd_desc(reply_cmd));
+ }
+}
+
void qq_proc_cmd_reply(PurpleConnection *gc,
- guint16 cmd, guint16 seq, guint8 *data, gint data_len)
+ guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len)
{
+ qq_data *qd;
+
+ guint8 *data;
+ gint data_len;
+
+ gboolean ret_bool = FALSE;
guint8 ret_8 = 0;
guint16 ret_16 = 0;
guint32 ret_32 = 0;
gchar *error_msg = NULL;
+ g_return_if_fail(rcved_len > 0);
+
+ g_return_if_fail (gc != NULL && gc->proto_data != NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ data = g_newa(guint8, rcved_len);
+ if (cmd == QQ_CMD_TOKEN) {
+ g_memmove(data, rcved, rcved_len);
+ data_len = rcved_len;
+ } else if (cmd == QQ_CMD_LOGIN) {
+ /* May use password_twice_md5 in the past version like QQ2005*/
+ data_len = qq_decrypt(data, rcved, rcved_len, qd->inikey);
+ if (data_len >= 0) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Decrypt login reply packet with inikey, %d bytes\n", data_len);
+ } else {
+ data_len = qq_decrypt(data, rcved, rcved_len, qd->password_twice_md5);
+ if (data_len >= 0) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Decrypt login reply packet with password_twice_md5, %d bytes\n", data_len);
+ } else {
+ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+ _("Can not decrypt login reply"));
+ return;
+ }
+ }
+ } else {
+ data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key);
+ if (data_len < 0) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Can not reply by session key, [%05d], 0x%04X %s, len %d\n",
+ seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
+ qq_show_packet("Can not decrypted", rcved, rcved_len);
+ return;
+ }
+ }
+
+ if (data_len <= 0) {
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "Reply decrypted is empty, [%05d], 0x%04X %s, len %d\n",
+ seq, cmd, qq_get_cmd_desc(cmd), rcved_len);
+ return;
+ }
+
switch (cmd) {
case QQ_CMD_TOKEN:
ret_8 = qq_process_token_reply(gc, error_msg, data, data_len);
@@ -246,14 +486,11 @@ void qq_proc_cmd_reply(PurpleConnection
qq_send_packet_get_buddies_online(gc, 0);
}
break;
- case QQ_CMD_GROUP_CMD:
- qq_process_group_cmd_reply(data, data_len, seq, gc);
- break;
- case QQ_CMD_GET_ALL_LIST_WITH_GROUP:
- ret_32 = qq_process_get_all_list_with_group_reply(data, data_len, gc);
+ case QQ_CMD_GET_BUDDIES_AND_ROOMS:
+ ret_32 = qq_process_get_buddies_and_rooms(data, data_len, gc);
if (ret_32 > 0 && ret_32 < 0xffffffff) {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n");
- qq_send_packet_get_all_list_with_group(gc, ret_32);
+ qq_send_packet_get_buddies_and_rooms(gc, ret_32);
} else {
purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies and groups received\n");
}
============================================================
--- libpurple/protocols/qq/qq_process.h 3c6cc46da9190a223a0e1397d4f01cc3876a6cef
+++ libpurple/protocols/qq/qq_process.h 85481566d6e1810595242ecd79f2cdd00533b4c1
@@ -31,8 +31,11 @@ void qq_proc_cmd_reply(PurpleConnection
#include "qq.h"
void qq_proc_cmd_reply(PurpleConnection *gc,
- guint16 cmd, guint16 seq, guint8 *data, gint data_len);
+ guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len);
+void qq_proc_room_cmd_reply(PurpleConnection *gc,
+ guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len);
+
void qq_proc_cmd_server(PurpleConnection *gc,
- guint16 cmd, guint16 seq, guint8 *data, gint data_len);
+ guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len);
#endif
============================================================
--- libpurple/protocols/qq/qq_trans.c da3d12ff33f5c9faaf6581a4b60a3ee9bda911bc
+++ libpurple/protocols/qq/qq_trans.c 5428a1f0f85c64a6e38cab4fc2777c98a2e4a853
@@ -90,6 +90,18 @@ gboolean qq_trans_is_dup(qq_transaction
return FALSE;
}
+guint8 qq_trans_get_room_cmd(qq_transaction *trans)
+{
+ g_return_val_if_fail(trans != NULL, 0);
+ return trans->room_cmd;
+}
+
+guint32 qq_trans_get_room_id(qq_transaction *trans)
+{
+ g_return_val_if_fail(trans != NULL, 0);
+ return trans->room_id;
+}
+
/* Remove a packet with seq from send trans */
static void trans_remove(qq_data *qd, qq_transaction *trans)
{
@@ -120,21 +132,53 @@ void qq_trans_add_client_cmd(qq_data *qd
trans->fd = qd->fd;
trans->cmd = cmd;
trans->seq = seq;
+ trans->room_cmd = 0;
+ trans->room_id = 0;
trans->send_retries = QQ_RESEND_MAX;
trans->rcved_times = 0;
trans->scan_times = 0;
+
trans->data = NULL;
trans->data_len = 0;
if (data != NULL && data_len > 0) {
trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */
trans->data_len = data_len;
}
- purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS",
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS",
"Add client cmd, seq = %d, data = %p, len = %d\n",
trans->seq, trans->data, trans->data_len);
qd->transactions = g_list_append(qd->transactions, trans);
}
+void qq_trans_add_room_cmd(qq_data *qd, guint16 seq, guint8 room_cmd, guint32 room_id,
+ guint8 *data, gint data_len)
+{
+ qq_transaction *trans = g_new0(qq_transaction, 1);
+
+ g_return_if_fail(trans != NULL);
+
+ trans->flag = 0;
+ trans->fd = qd->fd;
+ trans->seq = seq;
+ trans->cmd = QQ_CMD_ROOM;
+ trans->room_cmd = room_cmd;
+ trans->room_id = room_id;
+ trans->send_retries = QQ_RESEND_MAX;
+ trans->rcved_times = 0;
+ trans->scan_times = 0;
+
+ trans->data = NULL;
+ trans->data_len = 0;
+ if (data != NULL && data_len > 0) {
+ trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */
+ trans->data_len = data_len;
+ }
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS",
+ "Add room cmd, seq = %d, data = %p, len = %d\n",
+ trans->seq, trans->data, trans->data_len);
+ qd->transactions = g_list_append(qd->transactions, trans);
+}
+
void qq_trans_add_server_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len)
{
qq_transaction *trans = g_new0(qq_transaction, 1);
@@ -148,6 +192,8 @@ void qq_trans_add_server_cmd(qq_data *qd
trans->fd = qd->fd;
trans->cmd = cmd;
trans->seq = seq;
+ trans->room_cmd = 0;
+ trans->room_id = 0;
trans->send_retries = 0;
trans->rcved_times = 1;
trans->scan_times = 0;
@@ -157,7 +203,7 @@ void qq_trans_add_server_cmd(qq_data *qd
trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */
trans->data_len = data_len;
}
- purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS",
+ purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS",
"Add server cmd, seq = %d, data = %p, len = %d\n",
trans->seq, trans->data, trans->data_len);
qd->transactions = g_list_append(qd->transactions, trans);
============================================================
--- libpurple/protocols/qq/qq_trans.h 152a4c325a00e270481adb20c678c261adad8e1b
+++ libpurple/protocols/qq/qq_trans.h f4ace6ce706004259974c5198b24d9ac5daaa541
@@ -40,6 +40,10 @@ typedef struct _qq_transaction {
guint8 flag;
guint16 seq;
guint16 cmd;
+
+ guint8 room_cmd;
+ guint32 room_id;
+
guint8 *data;
gint data_len;
@@ -52,8 +56,14 @@ gboolean qq_trans_is_dup(qq_transaction
qq_transaction *qq_trans_find_rcved(qq_data *qd, guint16 cmd, guint16 seq);
gboolean qq_trans_is_server(qq_transaction *trans) ;
gboolean qq_trans_is_dup(qq_transaction *trans);
+guint8 qq_trans_get_room_cmd(qq_transaction *trans);
+guint32 qq_trans_get_room_id(qq_transaction *trans);
+
void qq_trans_add_client_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len);
void qq_trans_add_server_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len);
+void qq_trans_add_room_cmd(qq_data *qd, guint16 seq, guint8 room_cmd, guint32 room_id,
+ guint8 *data, gint data_len);
+
void qq_trans_process_before_login(qq_data *qd);
gboolean qq_trans_scan(qq_data *qd);
void qq_trans_remove_all(qq_data *qd);
============================================================
--- libpurple/protocols/qq/send_file.c 5a7c5b24f8d233f6da1d169dd27f54bb9011e3c5
+++ libpurple/protocols/qq/send_file.c 0501115925eb21fe09a235296b4263922edd7046
@@ -30,7 +30,6 @@
#include "notify.h"
#include "buddy_list.h"
-#include "crypt.h"
#include "file_trans.h"
#include "header_info.h"
#include "im.h"
============================================================
--- libpurple/protocols/qq/sys_msg.c 612ba2d5f58891f8a8d660600c5b4f1196d1699d
+++ libpurple/protocols/qq/sys_msg.c 6e80379b474adc9cdf0823a8a8985f65678fdc0c
@@ -31,7 +31,6 @@
#include "buddy_list.h"
#include "buddy_opt.h"
#include "char_conv.h"
-#include "crypt.h"
#include "header_info.h"
#include "packet_parse.h"
#include "qq.h"
@@ -292,64 +291,55 @@ static void _qq_process_msg_sys_notice(P
g_free(content);
}
-void qq_process_msg_sys(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection *gc)
+void qq_process_msg_sys(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc)
{
qq_data *qd;
- gint len;
- guint8 *data;
gchar **segments, *code, *from, *to, *msg, *msg_utf8;
- g_return_if_fail(buf != NULL && buf_len != 0);
+ g_return_if_fail(data != NULL && data_len != 0);
qd = (qq_data *) gc->proto_data;
- len = buf_len;
- data = g_newa(guint8, len);
- if (qq_decrypt(buf, buf_len, qd->session_key, data, &len)) {
- if (NULL == (segments = split_data(data, len, "\x1f", 4)))
- return;
- code = segments[0];
- from = segments[1];
- to = segments[2];
- msg = segments[3];
+ if (NULL == (segments = split_data(data, data_len, "\x1f", 4)))
+ return;
+ code = segments[0];
+ from = segments[1];
+ to = segments[2];
+ msg = segments[3];
- _qq_send_packet_ack_msg_sys(gc, code[0], strtol(from, NULL, 10), seq);
+ _qq_send_packet_ack_msg_sys(gc, code[0], strtol(from, NULL, 10), seq);
- if (strtol(to, NULL, 10) != qd->uid) { /* not to me */
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Recv sys msg to [%s], not me!, discard\n", to);
- g_strfreev(segments);
- return;
- }
-
- msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
- switch (strtol(code, NULL, 10)) {
- case QQ_MSG_SYS_BEING_ADDED:
- _qq_process_msg_sys_being_added(gc, from, to, msg_utf8);
- break;
- case QQ_MSG_SYS_ADD_CONTACT_REQUEST:
- _qq_process_msg_sys_add_contact_request(gc, from, to, msg_utf8);
- break;
- case QQ_MSG_SYS_ADD_CONTACT_APPROVED:
- _qq_process_msg_sys_add_contact_approved(gc, from, to, msg_utf8);
- break;
- case QQ_MSG_SYS_ADD_CONTACT_REJECTED:
- _qq_process_msg_sys_add_contact_rejected(gc, from, to, msg_utf8);
- break;
- case QQ_MSG_SYS_NOTICE:
- _qq_process_msg_sys_notice(gc, from, to, msg_utf8);
- break;
- case QQ_MSG_SYS_NEW_VERSION:
- purple_debug(PURPLE_DEBUG_WARNING, "QQ",
- "QQ server says there is newer version than %s\n", qq_get_ver_desc(QQ_CLIENT));
- break;
- default:
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Recv unknown sys msg code: %s\n", code);
- purple_debug(PURPLE_DEBUG_WARNING, "QQ", "the msg is : %s\n", msg_utf8);
- }
- g_free(msg_utf8);
+ if (strtol(to, NULL, 10) != qd->uid) { /* not to me */
+ purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Recv sys msg to [%s], not me!, discard\n", to);
g_strfreev(segments);
+ return;
+ }
- } else {
- purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt recv msg sys\n");
+ msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
+ switch (strtol(code, NULL, 10)) {
+ case QQ_MSG_SYS_BEING_ADDED:
+ _qq_process_msg_sys_being_added(gc, from, to, msg_utf8);
+ break;
+ case QQ_MSG_SYS_ADD_CONTACT_REQUEST:
+ _qq_process_msg_sys_add_contact_request(gc, from, to, msg_utf8);
+ break;
+ case QQ_MSG_SYS_ADD_CONTACT_APPROVED:
+ _qq_process_msg_sys_add_contact_approved(gc, from, to, msg_utf8);
+ break;
+ case QQ_MSG_SYS_ADD_CONTACT_REJECTED:
+ _qq_process_msg_sys_add_contact_rejected(gc, from, to, msg_utf8);
+ break;
+ case QQ_MSG_SYS_NOTICE:
+ _qq_process_msg_sys_notice(gc, from, to, msg_utf8);
+ break;
+ case QQ_MSG_SYS_NEW_VERSION:
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ",
+ "QQ server says there is newer version than %s\n", qq_get_ver_desc(QQ_CLIENT));
+ break;
+ default:
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Recv unknown sys msg code: %s\n", code);
+ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "the msg is : %s\n", msg_utf8);
}
+ g_free(msg_utf8);
+ g_strfreev(segments);
}
============================================================
--- libpurple/protocols/qq/sys_msg.h 371700dc601dba95fd2467e2761bd01b63f2fc1a
+++ libpurple/protocols/qq/sys_msg.h 33bfebe75d096bc266d51022362391932fd5eb37
@@ -28,6 +28,6 @@
#include <glib.h>
#include "connection.h"
-void qq_process_msg_sys(guint8 *buf, gint buf_len, guint16 seq, PurpleConnection *gc);
+void qq_process_msg_sys(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc);
#endif
============================================================
--- libpurple/protocols/qq/utils.c e62d6b6fabdb3e5595da57a860caf125293a0c23
+++ libpurple/protocols/qq/utils.c 9dc69d41de8ced4739e415b0894c7f9a52832847
@@ -314,7 +314,7 @@ static gchar *hex_dump_to_str(const guin
if ((i + j) < bytes)
g_string_append_printf(str, " %02x", buffer[i + j]);
else
- g_string_append(str, " ");
+ g_string_append(str, " --");
g_string_append(str, " ");
/* dump ascii value */
More information about the Commits
mailing list