Revision: 17112
http://svn.sourceforge.net/gaim/?rev=17112&view=rev
Author: markhuetsch
Date: 2006-09-01 04:03:18 -0700 (Fri, 01 Sep 2006)
Log Message:
-----------
Fixed chat support.
Modified Paths:
--------------
trunk/libgaim/protocols/qq/Makefile.am
trunk/libgaim/protocols/qq/Makefile.mingw
trunk/libgaim/protocols/qq/buddy_list.c
trunk/libgaim/protocols/qq/group.c
trunk/libgaim/protocols/qq/group.h
trunk/libgaim/protocols/qq/group_conv.c
trunk/libgaim/protocols/qq/group_find.c
trunk/libgaim/protocols/qq/group_find.h
trunk/libgaim/protocols/qq/group_free.c
trunk/libgaim/protocols/qq/group_free.h
trunk/libgaim/protocols/qq/group_im.c
trunk/libgaim/protocols/qq/group_info.c
trunk/libgaim/protocols/qq/group_info.h
trunk/libgaim/protocols/qq/group_join.c
trunk/libgaim/protocols/qq/group_join.h
trunk/libgaim/protocols/qq/group_network.c
trunk/libgaim/protocols/qq/group_opt.c
trunk/libgaim/protocols/qq/group_search.c
trunk/libgaim/protocols/qq/login_logout.c
trunk/libgaim/protocols/qq/qq.c
trunk/libgaim/protocols/qq/qq.h
trunk/libgaim/protocols/qq/utils.c
trunk/libgaim/protocols/qq/utils.h
Added Paths:
-----------
trunk/libgaim/protocols/qq/group_internal.c
trunk/libgaim/protocols/qq/group_internal.h
Removed Paths:
-------------
trunk/libgaim/protocols/qq/group_hash.c
trunk/libgaim/protocols/qq/group_hash.h
Modified: trunk/libgaim/protocols/qq/Makefile.am
===================================================================
--- trunk/libgaim/protocols/qq/Makefile.am 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/Makefile.am 2006-09-01 11:03:18 UTC (rev 17112)
@@ -22,15 +22,15 @@
crypt.c \
crypt.h \
group.c \
+ group.h \
group_conv.c \
group_conv.h \
group_find.c \
group_find.h \
group_free.c \
group_free.h \
- group.h \
- group_hash.c \
- group_hash.h \
+ group_internal.c \
+ group_internal.h \
group_im.c \
group_im.h \
group_info.c \
Modified: trunk/libgaim/protocols/qq/Makefile.mingw
===================================================================
--- trunk/libgaim/protocols/qq/Makefile.mingw 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/Makefile.mingw 2006-09-01 11:03:18 UTC (rev 17112)
@@ -54,7 +54,7 @@
group_conv.c \
group_find.c \
group_free.c \
- group_hash.c \
+ group_internal.c \
group_im.c \
group_info.c \
group_join.c \
Modified: trunk/libgaim/protocols/qq/buddy_list.c
===================================================================
--- trunk/libgaim/protocols/qq/buddy_list.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/buddy_list.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -37,7 +37,7 @@
#include "qq.h"
#include "group.h"
#include "group_find.h"
-#include "group_hash.h"
+#include "group_internal.h"
#include "group_info.h"
#include "qq_proxy.h"
@@ -222,7 +222,7 @@
}
else {
gaim_debug(GAIM_DEBUG_ERROR, "QQ",
- "Got an online buddy %d, but not in my buddy list", fe->s->uid);
+ "Got an online buddy %d, but not in my buddy list\n", fe->s->uid);
}
g_free(fe->s->ip);
@@ -231,11 +231,11 @@
if(cursor > (data + len)) {
gaim_debug(GAIM_DEBUG_ERROR, "QQ",
- "qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!");
+ "qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n");
}
if (position != QQ_FRIENDS_ONLINE_POSITION_END) {
- gaim_debug(GAIM_DEBUG_INFO, "QQ", "Has more online buddies, position from %d", position);
+ gaim_debug(GAIM_DEBUG_INFO, "QQ", "Has more online buddies, position from %d\n", position);
qq_send_packet_get_buddies_online(gc, position);
}
@@ -352,10 +352,6 @@
guint32 unknown, position;
guint32 uid;
guint8 type, groupid;
-
- qq_buddy *q_bud;
- gchar *name;
- GaimBuddy *b;
qq_group *group;
g_return_if_fail(gc != NULL && gc->proto_data != NULL);
@@ -384,41 +380,28 @@
read_packet_dw(data, &cursor, len, &uid);
/* 04: type 0x1:buddy 0x4:Qun */
read_packet_b(data, &cursor, len, &type);
- /* 05: groupid*4 */
+ /* 05: groupid*4 */ /* seems to always be 0 */
read_packet_b(data, &cursor, len, &groupid);
- groupid >>= 2; /* these 2 bits might not be 0, faint! */
+ /*
+ gaim_debug(GAIM_DEBUG_INFO, "QQ", "groupid: %i\n", groupid);
+ groupid >>= 2;
+ */
if (uid == 0 || (type != 0x1 && type != 0x4)) {
- gaim_debug(GAIM_DEBUG_WARNING, "QQ",
+ gaim_debug(GAIM_DEBUG_INFO, "QQ",
"Buddy entry, uid=%d, type=%d", uid, type);
continue;
}
if(0x1 == type) { /* a buddy */
- name = uid_to_gaim_name(uid);
- b = gaim_find_buddy(gc->account, name);
- g_free(name);
-
- if (b == NULL) {
- b = qq_add_buddy_by_recv_packet(gc, uid, TRUE, TRUE);
- q_bud = b->proto_data;
- }
- else {
- q_bud = NULL;
- b->proto_data = q_bud; /* wrong !!!! */
- }
- qd->buddies = g_list_append(qd->buddies, q_bud);
- qq_update_buddy_contact(gc, q_bud);
+ /* don't do anything but count - buddies are handled by
+ * qq_send_packet_get_buddies_list */
++i;
} else { /* a group */
- group = qq_group_find_by_internal_group_id(gc, uid);
+ group = qq_group_find_by_id(gc, uid, QQ_INTERNAL_ID);
if(group == NULL) {
- /*XXX not working
- group = qq_group_create_by_id(gc, uid, 0);
+ 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);
- */
- gaim_debug(GAIM_DEBUG_ERROR, "QQ",
- "Get a Qun with internal group %d\n", uid);
- gaim_notify_info(gc, _("QQ Qun Operation"),
- _("Find one Qun in the server list, but i don't know its external id, please re-rejoin it manually"), NULL);
} else {
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
qq_group_refresh(gc, group);
Modified: trunk/libgaim/protocols/qq/group.c
===================================================================
--- trunk/libgaim/protocols/qq/group.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -26,7 +26,7 @@
#include "prpl.h"
#include "request.h"
-#include "group_hash.h"
+#include "group_internal.h"
#include "group_info.h"
#include "group_search.h"
#include "utils.h"
@@ -43,6 +43,15 @@
qq_send_cmd_group_search_group(gc, external_group_id);
}
+static void _qq_group_search_cancel_callback(GaimConnection *gc, const gchar *input)
+{
+ qq_data *qd;
+ g_return_if_fail(gc != NULL && gc->proto_data != NULL);
+
+ qd = (qq_data *) gc->proto_data;
+ gaim_roomlist_set_in_progress(qd->roomlist, FALSE);
+}
+
/* This is needed for GaimChat node to be valid */
GList *qq_chat_info(GaimConnection *gc)
{
@@ -55,18 +64,20 @@
pce->label = _("ID: ");
pce->identifier = QQ_GROUP_KEY_EXTERNAL_ID;
m = g_list_append(m, pce);
+
+ return m;
+}
- pce = g_new0(struct proto_chat_entry, 1);
- pce->label = _("Admin: ");
- pce->identifier = QQ_GROUP_KEY_CREATOR_UID;
- m = g_list_append(m, pce);
+GHashTable *qq_chat_info_defaults(GaimConnection *gc, const gchar *chat_name)
+{
+ GHashTable *defaults;
- pce = g_new0(struct proto_chat_entry, 1);
- pce->label = _("Status: ");
- pce->identifier = QQ_GROUP_KEY_MEMBER_STATUS_DESC;
- m = g_list_append(m, pce);
+ defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
- return m;
+ if (chat_name != NULL)
+ g_hash_table_insert(defaults, QQ_GROUP_KEY_EXTERNAL_ID, g_strdup(chat_name));
+
+ return defaults;
}
/* get a list of qq groups */
@@ -107,9 +118,11 @@
gaim_request_input(gc, _("QQ Qun"),
_("Please input external group ID"),
- _("You can only search for permanent QQ group\nInput 0 or leave it blank to search for demo groups"),
- NULL, FALSE, FALSE, NULL, _("Search"),
- G_CALLBACK(_qq_group_search_callback), _("Cancel"), NULL, gc);
+ _("You can only search for permanent QQ groups\n"),
+ NULL, FALSE, FALSE, NULL,
+ _("Search"), G_CALLBACK(_qq_group_search_callback),
+ _("Cancel"), G_CALLBACK(_qq_group_search_cancel_callback),
+ gc);
return qd->roomlist;
}
Modified: trunk/libgaim/protocols/qq/group.h
===================================================================
--- trunk/libgaim/protocols/qq/group.h 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -39,7 +39,7 @@
} qq_group_member_status;
typedef struct _qq_group {
- /* all these will be saved when exit GAIM */
+ /* all these will be saved when we exit Gaim */
qq_group_member_status my_status; /* my status for this group */
gchar *my_status_desc; /* my status description */
guint32 internal_group_id;
@@ -50,12 +50,13 @@
guint8 auth_type;
gchar *group_name_utf8;
gchar *group_desc_utf8;
- /* all these will loaded from network only */
+ /* all these will be loaded from the network */
gchar *notice_utf8; /* group notice by admin */
- GList *members; /* those evert appear in the group */
+ GList *members;
} qq_group;
GList *qq_chat_info(GaimConnection *gc);
+GHashTable *qq_chat_info_defaults(GaimConnection *gc, const gchar *chat_name);
void qq_group_init(GaimConnection *gc);
Modified: trunk/libgaim/protocols/qq/group_conv.c
===================================================================
--- trunk/libgaim/protocols/qq/group_conv.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_conv.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -37,7 +37,8 @@
g_return_if_fail(gc != NULL && gc->proto_data != NULL && group != NULL);
qd = (qq_data *) gc->proto_data;
- conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, group->group_name_utf8, gaim_connection_get_account(gc));
+ conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT,
+ group->group_name_utf8, gaim_connection_get_account(gc));
if (conv == NULL) /* show only one window per group */
serv_got_joined_chat(gc, qd->channel++, group->group_name_utf8);
}
@@ -54,17 +55,19 @@
names = NULL;
flags = NULL;
- conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, group->group_name_utf8, gaim_connection_get_account(gc));
+ conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT,
+ group->group_name_utf8, gaim_connection_get_account(gc));
if (conv != NULL && group->members != NULL) {
list = group->members;
while (list != NULL) {
member = (qq_buddy *) list->data;
/* always put it even offline */
names = g_list_append(names,
- (member->nickname !=
- NULL) ?
- g_strdup(member->nickname) : uid_to_gaim_name(member->uid));
-
+ /* we need unique identifiers for everyone in the chat or else we'll
+ * run into problems with functions like get_cb_real_name from qq.c */
+ (member->nickname != NULL && *(member->nickname) != '\0') ?
+ g_strdup_printf("%s (qq-%u)", member->nickname, member->uid) :
+ g_strdup_printf("(qq-%u)", member->uid));
flag = 0;
/* TYPING to put online above OP and FOUNDER */
if (is_online(member->status)) flag |= (GAIM_CBFLAGS_TYPING | GAIM_CBFLAGS_VOICE);
Modified: trunk/libgaim/protocols/qq/group_find.c
===================================================================
--- trunk/libgaim/protocols/qq/group_find.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_find.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -29,38 +29,6 @@
#include "qq.h"
#include "utils.h"
-/* find a chat member's valid gaim_name of its nickname and chat room channel */
-gchar *qq_group_find_member_by_channel_and_nickname(GaimConnection *gc, gint channel, const gchar *who)
-{
- qq_group *group;
- qq_buddy *member;
- GList *list;
-
- g_return_val_if_fail(gc != NULL && who != NULL, NULL);
-
- /* TODO checkbox for this in UI */
- /* if it starts with QQ_NAME_PREFIX, we think it is valid name already
- * otherwise we think it is nickname and try to find the matching gaim_name */
- /*
- if (gaim_str_has_prefix(who, QQ_NAME_PREFIX) && gaim_name_to_uid(who) > 0)
- return (gchar *) who;
- */
-
- group = qq_group_find_by_channel(gc, channel);
- g_return_val_if_fail(group != NULL, NULL);
-
- list = group->members;
- member = NULL;
- while (list != NULL) {
- member = (qq_buddy *) list->data;
- if (member->nickname != NULL && !g_ascii_strcasecmp(member->nickname, who))
- break;
- list = list->next;
- }
-
- return (member == NULL) ? NULL : uid_to_gaim_name(member->uid);
-}
-
/* 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(GaimConnection *gc, guint16 seq, guint32 *internal_group_id)
@@ -69,7 +37,10 @@
qq_data *qd;
group_packet *p;
- g_return_val_if_fail(gc != NULL && gc->proto_data != NULL && internal_group_id != NULL, FALSE);
+ g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE);
+
+ if (internal_group_id == NULL)
+ return FALSE;
qd = (qq_data *) gc->proto_data;
list = qd->group_packets;
@@ -87,7 +58,7 @@
return FALSE;
}
-/* find a qq_buddy by uid, called by qq_im.c */
+/* find a qq_buddy by uid, called by im.c */
qq_buddy *qq_group_find_member_by_uid(qq_group *group, guint32 uid)
{
GList *list;
@@ -138,7 +109,7 @@
buddy = gaim_find_buddy(gaim_connection_get_account(gc), uid_to_gaim_name(member_uid));
if (buddy != NULL) {
q_bud = (qq_buddy *) buddy->proto_data;
- if (q_bud != NULL)
+ if (q_bud != NULL && q_bud->nickname != NULL)
member->nickname = g_strdup(q_bud->nickname);
else if (buddy->alias != NULL)
member->nickname = g_strdup(buddy->alias);
@@ -175,23 +146,24 @@
return group;
}
-/* find a qq_group by internal_group_id */
-qq_group *qq_group_find_by_internal_group_id(GaimConnection *gc, guint32 internal_group_id)
+/* find a qq_group by its id, flag is QQ_INTERNAL_ID or QQ_EXTERNAL_ID */
+qq_group *qq_group_find_by_id(GaimConnection *gc, guint32 id, gboolean flag)
{
GList *list;
qq_group *group;
qq_data *qd;
- g_return_val_if_fail(gc != NULL && gc->proto_data != NULL && internal_group_id > 0, NULL);
-
+ g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL);
qd = (qq_data *) gc->proto_data;
- if (qd->groups == NULL)
+
+ if (qd->groups == NULL || id <= 0)
return NULL;
list = qd->groups;
while (list != NULL) {
group = (qq_group *) list->data;
- if (group->internal_group_id == internal_group_id)
+ if (flag == QQ_INTERNAL_ID ?
+ (group->internal_group_id == id) : (group->external_group_id == id))
return group;
list = list->next;
}
Modified: trunk/libgaim/protocols/qq/group_find.h
===================================================================
--- trunk/libgaim/protocols/qq/group_find.h 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_find.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -27,12 +27,14 @@
#include "connection.h"
#include "group.h"
-gchar *qq_group_find_member_by_channel_and_nickname(GaimConnection *gc, gint channel, const gchar *who);
+#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(GaimConnection *gc, qq_group *group, guint32 member_uid);
gboolean qq_group_find_internal_group_id_by_seq(GaimConnection *gc, guint16 seq, guint32 *internal_group_id);
qq_group *qq_group_find_by_channel(GaimConnection *gc, gint channel);
-qq_group *qq_group_find_by_internal_group_id(GaimConnection *gc, guint32 internal_group_id);
+qq_group *qq_group_find_by_id(GaimConnection *gc, guint32 id, gboolean flag);
#endif
Modified: trunk/libgaim/protocols/qq/group_free.c
===================================================================
--- trunk/libgaim/protocols/qq/group_free.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_free.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -23,12 +23,11 @@
#include "debug.h"
#include "buddy_status.h"
-#include "group.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)
+static void qq_group_free_member(qq_group *group)
{
gint i;
GList *list;
@@ -48,10 +47,10 @@
}
/* gracefully free the memory for one qq_group */
-static void _qq_group_free(qq_group *group)
+void qq_group_free(qq_group *group)
{
g_return_if_fail(group != NULL);
- _qq_group_free_member(group);
+ qq_group_free_member(group);
g_free(group->group_name_utf8);
g_free(group->group_desc_utf8);
g_free(group);
@@ -73,25 +72,6 @@
gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d group packets are freed!\n", i);
}
-void qq_group_remove_by_internal_group_id(qq_data *qd, guint32 internal_group_id)
-{
- qq_group *group;
- GList *list;
- g_return_if_fail(qd != NULL);
-
- list = qd->groups;
- while (list != NULL) {
- group = (qq_group *) qd->groups->data;
- if (internal_group_id == group->internal_group_id) {
- qd->groups = g_list_remove(qd->groups, group);
- _qq_group_free(group);
- break;
- } else {
- list = list->next;
- }
- }
-}
-
void qq_group_free_all(qq_data *qd)
{
qq_group *group;
@@ -103,7 +83,7 @@
i++;
group = (qq_group *) qd->groups->data;
qd->groups = g_list_remove(qd->groups, group);
- _qq_group_free(group);
+ qq_group_free(group);
}
gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d groups are freed\n", i);
Modified: trunk/libgaim/protocols/qq/group_free.h
===================================================================
--- trunk/libgaim/protocols/qq/group_free.h 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_free.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -25,11 +25,11 @@
#include <glib.h>
#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);
-void qq_group_remove_by_internal_group_id(qq_data *qd, guint32 internal_group_id);
-
#endif
Deleted: trunk/libgaim/protocols/qq/group_hash.c
===================================================================
--- trunk/libgaim/protocols/qq/group_hash.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_hash.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -1,195 +0,0 @@
-/**
-* The QQ2003C protocol plugin
- *
- * for gaim
- *
- * Copyright (C) 2004 Puzzlebird
- *
- * 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
- */
-
-#include "blist.h"
-#include "debug.h"
-
-#include "buddy_opt.h"
-#include "group_hash.h"
-#include "group_misc.h"
-#include "utils.h"
-
-static gchar *_qq_group_set_my_status_desc(qq_group *group)
-{
- const char *status_desc;
- g_return_val_if_fail(group != NULL, g_strdup(""));
-
- switch (group->my_status) {
- case QQ_GROUP_MEMBER_STATUS_NOT_MEMBER:
- status_desc = _("I am not member");
- break;
- case QQ_GROUP_MEMBER_STATUS_IS_MEMBER:
- status_desc = _("I am a member");
- break;
- case QQ_GROUP_MEMBER_STATUS_APPLYING:
- status_desc = _("I am applying to join");
- break;
- case QQ_GROUP_MEMBER_STATUS_IS_ADMIN:
- status_desc = _("I am the admin");
- break;
- default:
- status_desc = _("Unknown status");
- }
-
- return g_strdup(status_desc);
-}
-
-static void _qq_group_add_to_blist(GaimConnection *gc, qq_group *group)
-{
- GHashTable *components;
- GaimGroup *g;
- GaimChat *chat;
- components = qq_group_to_hashtable(group);
- chat = gaim_chat_new(gaim_connection_get_account(gc), group->group_name_utf8, components);
- g = qq_get_gaim_group(GAIM_GROUP_QQ_QUN);
- gaim_blist_add_chat(chat, g, NULL);
- gaim_debug(GAIM_DEBUG_INFO, "QQ", "You have add group \"%s\" to blist locally\n", group->group_name_utf8);
-}
-
-/* create a dummy qq_group, which includes only internal_id and external_id
- * all other attributes should be set to empty.
- * and we need to send a get_group_info to QQ server to update it right away */
-qq_group *qq_group_create_by_id(GaimConnection *gc, guint32 internal_id, guint32 external_id)
-{
- qq_group *group;
- qq_data *qd;
-
- g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL);
- g_return_val_if_fail(internal_id > 0, NULL);
- qd = (qq_data *) gc->proto_data;
-
- 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->creator_uid = 10000; /* assume by QQ admin */
- group->group_category = 0x01;
- group->auth_type = 0x02; /* assume need auth */
- group->group_name_utf8 = g_strdup("");
- group->group_desc_utf8 = g_strdup("");
- group->notice_utf8 = g_strdup("");
- group->members = NULL;
-
- qd->groups = g_list_append(qd->groups, group);
- _qq_group_add_to_blist(gc, group);
-
- return group;
-}
-
-/* convert a qq_group to hash-table, which could be component of GaimChat */
-GHashTable *qq_group_to_hashtable(qq_group *group)
-{
- GHashTable *components;
- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_MEMBER_STATUS), g_strdup_printf("%d", group->my_status));
- 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_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_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));
- g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type));
- g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_MEMBER_STATUS_DESC), g_strdup(group->my_status_desc));
- g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_GROUP_NAME_UTF8), g_strdup(group->group_name_utf8));
- g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_GROUP_DESC_UTF8), g_strdup(group->group_desc_utf8));
- return components;
-}
-
-/* create a qq_group from hashtable */
-qq_group *qq_group_from_hashtable(GaimConnection *gc, GHashTable *data)
-{
- qq_data *qd;
- qq_group *group;
-
- g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL);
- g_return_val_if_fail(data != NULL, NULL);
- qd = (qq_data *) gc->proto_data;
-
- group = g_new0(qq_group, 1);
- group->my_status =
- qq_string_to_dec_value
- (NULL ==
- g_hash_table_lookup(data,
- QQ_GROUP_KEY_MEMBER_STATUS) ?
- 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->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));
- group->group_name_utf8 = g_strdup(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_NAME_UTF8));
- group->group_desc_utf8 = g_strdup(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_DESC_UTF8));
- group->my_status_desc = _qq_group_set_my_status_desc(group);
-
- qd->groups = g_list_append(qd->groups, group);
-
- return group;
-}
-
-/* refresh group local subscription */
-void qq_group_refresh(GaimConnection *gc, qq_group *group)
-{
- GaimChat *chat;
- g_return_if_fail(gc != NULL && group != NULL);
-
- chat = gaim_blist_find_chat(gaim_connection_get_account(gc), g_strdup_printf("%d", group->external_group_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 */
- /* if there is group_name_utf8, we update the group name */
- if (group->group_name_utf8 != NULL && strlen(group->group_name_utf8) > 0)
- gaim_blist_alias_chat(chat, group->group_name_utf8);
- g_hash_table_replace(chat->components,
- g_strdup(QQ_GROUP_KEY_MEMBER_STATUS), g_strdup_printf("%d", group->my_status));
- group->my_status_desc = _qq_group_set_my_status_desc(group);
- g_hash_table_replace(chat->components,
- 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_hash_table_replace(chat->components,
- g_strdup(QQ_GROUP_KEY_EXTERNAL_ID),
- g_strdup_printf("%d", group->external_group_id));
- g_hash_table_replace(chat->components,
- g_strdup(QQ_GROUP_KEY_GROUP_TYPE), g_strdup_printf("%d", group->group_type));
- 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,
- g_strdup(QQ_GROUP_KEY_GROUP_CATEGORY),
- g_strdup_printf("%d", group->group_category));
- g_hash_table_replace(chat->components,
- g_strdup(QQ_GROUP_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type));
- g_hash_table_replace(chat->components,
- g_strdup(QQ_GROUP_KEY_GROUP_NAME_UTF8), g_strdup(group->group_name_utf8));
- g_hash_table_replace(chat->components,
- g_strdup(QQ_GROUP_KEY_GROUP_DESC_UTF8), g_strdup(group->group_desc_utf8));
- }
-}
Deleted: trunk/libgaim/protocols/qq/group_hash.h
===================================================================
--- trunk/libgaim/protocols/qq/group_hash.h 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_hash.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -1,46 +0,0 @@
-/**
-* The QQ2003C protocol plugin
- *
- * for gaim
- *
- * Copyright (C) 2004 Puzzlebird
- *
- * 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_GROUP_HASH_H_
-#define _QQ_GROUP_HASH_H_
-
-#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"
-
-qq_group *qq_group_create_by_id(GaimConnection *gc, guint32 internal_id, guint32 external_id);
-GHashTable *qq_group_to_hashtable(qq_group *group);
-
-qq_group *qq_group_from_hashtable(GaimConnection *gc, GHashTable *data);
-void qq_group_refresh(GaimConnection *gc, qq_group *group);
-
-#endif
Modified: trunk/libgaim/protocols/qq/group_im.c
===================================================================
--- trunk/libgaim/protocols/qq/group_im.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_im.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -29,7 +29,7 @@
#include "char_conv.h"
#include "group_find.h"
-#include "group_hash.h"
+#include "group_internal.h"
#include "group_info.h"
#include "group_im.h"
#include "group_network.h"
@@ -171,7 +171,7 @@
gaim_notify_warning(gc, _("QQ Qun Operation"), msg, reason);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
if (group != NULL) {
group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
qq_group_refresh(gc, group);
@@ -211,7 +211,7 @@
gaim_notify_warning(gc, _("QQ Qun Operation"), msg, NULL);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
if (group != NULL) {
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
qq_group_refresh(gc, group);
@@ -246,7 +246,7 @@
msg = g_strdup_printf(_("You [%d] has exit group \"%d\""), uid, external_group_id);
gaim_notify_info(gc, _("QQ Qun Operation"), msg, NULL);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
if (group != NULL) {
group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
qq_group_refresh(gc, group);
@@ -278,14 +278,14 @@
g_return_if_fail(external_group_id > 0 && uid > 0);
msg = g_strdup_printf(_("You [%d] has been added by group \"%d\""), uid, external_group_id);
- gaim_notify_info(gc, _("QQ Qun Operation"), msg, _("OpenQ has added this group to your buddy list"));
+ gaim_notify_info(gc, _("QQ Qun Operation"), msg, _("This group has been added to your buddy list"));
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_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_by_id(gc, internal_group_id, external_group_id);
+ group = qq_group_create_internal_record(gc, internal_group_id, external_group_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);
@@ -379,7 +379,7 @@
else
msg_utf8_encoded = qq_to_utf8(msg_with_gaim_smiley, QQ_CHARSET_DEFAULT);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, group->group_name_utf8, gaim_connection_get_account(gc));
Modified: trunk/libgaim/protocols/qq/group_info.c
===================================================================
--- trunk/libgaim/protocols/qq/group_info.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_info.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -26,7 +26,7 @@
#include "buddy_status.h"
#include "char_conv.h"
#include "group_find.h"
-#include "group_hash.h"
+#include "group_internal.h"
#include "group_info.h"
#include "buddy_status.h"
#include "group_network.h"
@@ -42,7 +42,7 @@
(time(NULL) - member->last_refresh) > QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL;
}
-/* this is done when we receive the reply to get_online_member sub_cmd
+/* this is done when we receive the reply to get_online_members sub_cmd
* all member are set offline, and then only those in reply packets are online */
static void _qq_group_set_members_all_offline(qq_group *group)
{
@@ -82,7 +82,7 @@
}
/* send packet to get online group member, called by keep_alive */
-void qq_send_cmd_group_get_online_member(GaimConnection *gc, qq_group *group)
+void qq_send_cmd_group_get_online_members(GaimConnection *gc, qq_group *group)
{
guint8 *raw_data, *cursor;
gint bytes, data_len;
@@ -111,8 +111,8 @@
qq_send_group_cmd(gc, group, raw_data, data_len);
}
-/* send packet to get group member info */
-void qq_send_cmd_group_get_member_info(GaimConnection *gc, qq_group *group)
+/* send packet to get info for each group member */
+void qq_send_cmd_group_get_members_info(GaimConnection *gc, qq_group *group)
{
guint8 *raw_data, *cursor;
gint bytes, data_len, i;
@@ -160,9 +160,10 @@
qq_buddy *member;
qq_data *qd;
GaimConversation *gaim_conv;
- guint8 orgnization, role;
- guint16 unknown;
- guint32 member_uid, internal_group_id;
+ guint8 organization, role;
+ guint16 unknown, max_members;
+ guint32 member_uid, internal_group_id, external_group_id;
+ GSList *pending_id;
gint pascal_len, i;
guint32 unknown4;
guint8 unknown1;
@@ -173,11 +174,18 @@
read_packet_dw(data, cursor, len, &(internal_group_id));
g_return_if_fail(internal_group_id > 0);
+ read_packet_dw(data, cursor, len, &(external_group_id));
+ g_return_if_fail(internal_group_id > 0);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ pending_id = qq_get_pending_id(qd->adding_groups_from_server, internal_group_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);
+ }
+
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
- read_packet_dw(data, cursor, len, &(group->external_group_id));
read_packet_b(data, cursor, len, &(group->group_type));
read_packet_dw(data, cursor, len, &unknown4); /* unknown 4 bytes */
read_packet_dw(data, cursor, len, &(group->creator_uid));
@@ -185,7 +193,7 @@
read_packet_dw(data, cursor, len, &unknown4); /* oldCategory */
read_packet_w(data, cursor, len, &unknown);
read_packet_dw(data, cursor, len, &(group->group_category));
- read_packet_w(data, cursor, len, &(unknown)); /* 0x0000 */
+ read_packet_w(data, cursor, len, &max_members);
read_packet_b(data, cursor, len, &unknown1);
read_packet_dw(data, cursor, len, &(unknown4)); /* versionID */
@@ -202,17 +210,18 @@
while (*cursor < data + len) {
read_packet_dw(data, cursor, len, &member_uid);
i++;
- read_packet_b(data, cursor, len, &orgnization);
+ read_packet_b(data, cursor, len, &organization);
read_packet_b(data, cursor, len, &role);
- if(orgnization != 0 || role != 0) {
- gaim_debug(GAIM_DEBUG_INFO, "QQ", "group member %d: orgnizatio=%d, role=%d\n", member_uid, orgnization, role);
+ if(organization != 0 || role != 0) {
+ gaim_debug(GAIM_DEBUG_INFO, "QQ", "group member %d: organization=%d, role=%d\n", member_uid, organization, role);
}
member = qq_group_find_or_add_member(gc, group, member_uid);
- member->role = role;
+ if (member != NULL)
+ member->role = role;
}
if(*cursor > (data + len)) {
- gaim_debug(GAIM_DEBUG_ERROR, "QQ", "group_cmd_get_group_info: Dangerous error! maybe protocal changed, notify me!");
+ gaim_debug(GAIM_DEBUG_ERROR, "QQ", "group_cmd_get_group_info: Dangerous error! maybe protocol changed, notify me!");
}
gaim_debug(GAIM_DEBUG_INFO, "QQ", "group \"%s\" has %d members\n", group->group_name_utf8, i);
@@ -233,7 +242,7 @@
}
}
-void qq_process_group_cmd_get_online_member(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc)
+void qq_process_group_cmd_get_online_members(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc)
{
guint32 internal_group_id, member_uid;
guint8 unknown;
@@ -254,7 +263,7 @@
bytes += read_packet_b(data, cursor, len, &unknown); /* 0x3c ?? */
g_return_if_fail(internal_group_id > 0);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
if (group == NULL) {
gaim_debug(GAIM_DEBUG_ERROR, "QQ",
"We have no group info for internal id [%d]\n", internal_group_id);
@@ -272,14 +281,14 @@
}
if(*cursor > (data + len)) {
gaim_debug(GAIM_DEBUG_ERROR, "QQ",
- "group_cmd_get_online_member: Dangerous error! maybe protocol changed, notify developers!");
+ "group_cmd_get_online_members: Dangerous error! maybe protocol changed, notify developers!");
}
gaim_debug(GAIM_DEBUG_INFO, "QQ", "Group \"%s\" has %d online members\n", group->group_name_utf8, i);
}
-/* process the reply to get_member_info packet */
-void qq_process_group_cmd_get_member_info(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc)
+/* process the reply to get_members_info packet */
+void qq_process_group_cmd_get_members_info(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc)
{
guint32 internal_group_id, member_uid;
guint16 unknown;
@@ -292,10 +301,13 @@
read_packet_dw(data, cursor, len, &internal_group_id);
g_return_if_fail(internal_group_id > 0);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
i = 0;
+ /* TODO: Something is off. I get an entry with strange values
+ * (including a nick of "") buried in here. I need to find more
+ * groups to join before I can figure this out */
/* now starts the member info, as get buddy list reply */
while (*cursor < data + len) {
read_packet_dw(data, cursor, len, &member_uid);
@@ -317,7 +329,7 @@
}
if(*cursor > (data + len)) {
gaim_debug(GAIM_DEBUG_ERROR, "QQ",
- "group_cmd_get_member_info: Dangerous error! maybe protocol changed, notify developers!");
+ "group_cmd_get_members_info: Dangerous error! maybe protocol changed, notify developers!");
}
gaim_debug(GAIM_DEBUG_INFO, "QQ", "Group \"%s\" obtained %d member info\n", group->group_name_utf8, i);
}
Modified: trunk/libgaim/protocols/qq/group_info.h
===================================================================
--- trunk/libgaim/protocols/qq/group_info.h 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_info.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -28,10 +28,10 @@
#include "group.h"
void qq_send_cmd_group_get_group_info(GaimConnection *gc, qq_group *group);
-void qq_send_cmd_group_get_online_member(GaimConnection *gc, qq_group *group);
-void qq_send_cmd_group_get_member_info(GaimConnection *gc, qq_group *group);
+void qq_send_cmd_group_get_online_members(GaimConnection *gc, qq_group *group);
+void qq_send_cmd_group_get_members_info(GaimConnection *gc, qq_group *group);
void qq_process_group_cmd_get_group_info(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc);
-void qq_process_group_cmd_get_online_member(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc);
-void qq_process_group_cmd_get_member_info(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc);
+void qq_process_group_cmd_get_online_members(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc);
+void qq_process_group_cmd_get_members_info(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc);
#endif
Added: trunk/libgaim/protocols/qq/group_internal.c
===================================================================
--- trunk/libgaim/protocols/qq/group_internal.c (rev 0)
+++ trunk/libgaim/protocols/qq/group_internal.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -0,0 +1,238 @@
+/**
+* The QQ2003C protocol plugin
+ *
+ * for gaim
+ *
+ * Copyright (C) 2004 Puzzlebird
+ *
+ * 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
+ */
+
+#include "blist.h"
+#include "debug.h"
+
+#include "buddy_opt.h"
+#include "group_free.h"
+#include "group_internal.h"
+#include "group_misc.h"
+#include "utils.h"
+
+static gchar *_qq_group_set_my_status_desc(qq_group *group)
+{
+ const char *status_desc;
+ g_return_val_if_fail(group != NULL, g_strdup(""));
+
+ switch (group->my_status) {
+ case QQ_GROUP_MEMBER_STATUS_NOT_MEMBER:
+ status_desc = _("I am not member");
+ break;
+ case QQ_GROUP_MEMBER_STATUS_IS_MEMBER:
+ status_desc = _("I am a member");
+ break;
+ case QQ_GROUP_MEMBER_STATUS_APPLYING:
+ status_desc = _("I am applying to join");
+ break;
+ case QQ_GROUP_MEMBER_STATUS_IS_ADMIN:
+ status_desc = _("I am the admin");
+ break;
+ default:
+ status_desc = _("Unknown status");
+ }
+
+ return g_strdup(status_desc);
+}
+
+static void _qq_group_add_to_blist(GaimConnection *gc, qq_group *group)
+{
+ GHashTable *components;
+ GaimGroup *g;
+ GaimChat *chat;
+ components = qq_group_to_hashtable(group);
+ chat = gaim_chat_new(gaim_connection_get_account(gc), group->group_name_utf8, components);
+ g = qq_get_gaim_group(GAIM_GROUP_QQ_QUN);
+ gaim_blist_add_chat(chat, g, NULL);
+ gaim_debug(GAIM_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,
+ * 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(GaimConnection *gc,
+ guint32 internal_id, guint32 external_id, gchar *group_name_utf8)
+{
+ qq_group *group;
+ qq_data *qd;
+
+ g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL);
+ g_return_val_if_fail(internal_id > 0, NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ 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->creator_uid = 10000; /* assume by QQ admin */
+ group->group_category = 0x01;
+ group->auth_type = 0x02; /* assume need auth */
+ group->group_name_utf8 = g_strdup(group_name_utf8 == NULL ? "" : group_name_utf8);
+ group->group_desc_utf8 = g_strdup("");
+ group->notice_utf8 = g_strdup("");
+ group->members = NULL;
+
+ qd->groups = g_list_append(qd->groups, group);
+ _qq_group_add_to_blist(gc, group);
+
+ return group;
+}
+
+void qq_group_delete_internal_record(qq_data *qd, guint32 internal_group_id)
+{
+ qq_group *group;
+ GList *list;
+ g_return_if_fail(qd != NULL);
+
+ list = qd->groups;
+ while (list != NULL) {
+ group = (qq_group *) qd->groups->data;
+ if (internal_group_id == group->internal_group_id) {
+ qd->groups = g_list_remove(qd->groups, group);
+ qq_group_free(group);
+ break;
+ } else {
+ list = list->next;
+ }
+ }
+}
+
+/* convert a qq_group to hash-table, which could be component of GaimChat */
+GHashTable *qq_group_to_hashtable(qq_group *group)
+{
+ GHashTable *components;
+ components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_MEMBER_STATUS), g_strdup_printf("%d", group->my_status));
+ 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_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_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));
+ g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type));
+ g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_MEMBER_STATUS_DESC), g_strdup(group->my_status_desc));
+ g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_GROUP_NAME_UTF8), g_strdup(group->group_name_utf8));
+ g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_GROUP_DESC_UTF8), g_strdup(group->group_desc_utf8));
+ return components;
+}
+
+/* create a qq_group from hashtable */
+qq_group *qq_group_from_hashtable(GaimConnection *gc, GHashTable *data)
+{
+ qq_data *qd;
+ qq_group *group;
+
+ g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL);
+ g_return_val_if_fail(data != NULL, NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ group = g_new0(qq_group, 1);
+ group->my_status =
+ qq_string_to_dec_value
+ (NULL ==
+ g_hash_table_lookup(data,
+ QQ_GROUP_KEY_MEMBER_STATUS) ?
+ 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->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));
+ group->group_name_utf8 = g_strdup(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_NAME_UTF8));
+ group->group_desc_utf8 = g_strdup(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_DESC_UTF8));
+ group->my_status_desc = _qq_group_set_my_status_desc(group);
+
+ qd->groups = g_list_append(qd->groups, group);
+
+ return group;
+}
+
+/* refresh group local subscription */
+void qq_group_refresh(GaimConnection *gc, qq_group *group)
+{
+ GaimChat *chat;
+ gchar *external_group_id;
+ g_return_if_fail(gc != NULL && group != NULL);
+
+ external_group_id = g_strdup_printf("%d", group->external_group_id);
+ chat = gaim_blist_find_chat(gaim_connection_get_account(gc), external_group_id);
+ g_free(external_group_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 */
+ /* if there is group_name_utf8, we update the group name */
+ if (group->group_name_utf8 != NULL && strlen(group->group_name_utf8) > 0)
+ gaim_blist_alias_chat(chat, group->group_name_utf8);
+ g_hash_table_replace(chat->components,
+ g_strdup(QQ_GROUP_KEY_MEMBER_STATUS), g_strdup_printf("%d", group->my_status));
+ group->my_status_desc = _qq_group_set_my_status_desc(group);
+ g_hash_table_replace(chat->components,
+ 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_hash_table_replace(chat->components,
+ g_strdup(QQ_GROUP_KEY_EXTERNAL_ID),
+ g_strdup_printf("%d", group->external_group_id));
+ g_hash_table_replace(chat->components,
+ g_strdup(QQ_GROUP_KEY_GROUP_TYPE), g_strdup_printf("%d", group->group_type));
+ 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,
+ g_strdup(QQ_GROUP_KEY_GROUP_CATEGORY),
+ g_strdup_printf("%d", group->group_category));
+ g_hash_table_replace(chat->components,
+ g_strdup(QQ_GROUP_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type));
+ g_hash_table_replace(chat->components,
+ g_strdup(QQ_GROUP_KEY_GROUP_NAME_UTF8), g_strdup(group->group_name_utf8));
+ g_hash_table_replace(chat->components,
+ g_strdup(QQ_GROUP_KEY_GROUP_DESC_UTF8), g_strdup(group->group_desc_utf8));
+ }
+}
+
+/* NOTE: If we knew how to convert between an external and internal group id, as the official
+ * client seems to, the following would be unnecessary. That would be ideal. */
+
+/* Use list to specify if id's alternate id is pending discovery. */
+void qq_set_pending_id(GSList **list, guint32 id, gboolean pending)
+{
+ if (pending)
+ *list = g_slist_prepend(*list, GINT_TO_POINTER(id));
+ else
+ *list = g_slist_remove(*list, GINT_TO_POINTER(id));
+}
+
+/* Return the location of id in list, or NULL if not found */
+GSList *qq_get_pending_id(GSList *list, guint32 id)
+{
+ return g_slist_find(list, GINT_TO_POINTER(id));
+}
Property changes on: trunk/libgaim/protocols/qq/group_internal.c
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Added: trunk/libgaim/protocols/qq/group_internal.h
===================================================================
--- trunk/libgaim/protocols/qq/group_internal.h (rev 0)
+++ trunk/libgaim/protocols/qq/group_internal.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -0,0 +1,52 @@
+/**
+* The QQ2003C protocol plugin
+ *
+ * for gaim
+ *
+ * Copyright (C) 2004 Puzzlebird
+ *
+ * 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_GROUP_HASH_H_
+#define _QQ_GROUP_HASH_H_
+
+#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"
+
+qq_group *qq_group_create_internal_record(GaimConnection *gc,
+ guint32 internal_id, guint32 external_id, gchar *group_name_utf8);
+void qq_group_delete_internal_record(qq_data *qd, guint32 internal_group_id);
+
+GHashTable *qq_group_to_hashtable(qq_group *group);
+qq_group *qq_group_from_hashtable(GaimConnection *gc, GHashTable *data);
+
+void qq_group_refresh(GaimConnection *gc, qq_group *group);
+
+void qq_set_pending_id(GSList **list, guint32 id, gboolean pending);
+GSList *qq_get_pending_id(GSList *list, guint32 id);
+
+#endif
Property changes on: trunk/libgaim/protocols/qq/group_internal.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Modified: trunk/libgaim/protocols/qq/group_join.c
===================================================================
--- trunk/libgaim/protocols/qq/group_join.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_join.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -30,11 +30,12 @@
#include "group_conv.h"
#include "group_find.h"
#include "group_free.h"
-#include "group_hash.h"
+#include "group_internal.h"
#include "group_info.h"
#include "group_join.h"
#include "group_opt.h"
#include "group_network.h"
+#include "group_search.h"
enum {
QQ_GROUP_JOIN_OK = 0x01,
@@ -51,24 +52,37 @@
gc = g->gc;
internal_group_id = g->uid;
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
qq_send_cmd_group_exit_group(gc, group);
}
/* send packet to join a group without auth */
-static void _qq_send_cmd_group_join_group(GaimConnection *gc, qq_group *group)
+void qq_send_cmd_group_join_group(GaimConnection *gc, qq_group *group)
{
guint8 *raw_data, *cursor;
gint bytes, data_len;
g_return_if_fail(gc != NULL && group != NULL);
+
if (group->my_status == QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) {
group->my_status = QQ_GROUP_MEMBER_STATUS_APPLYING;
qq_group_refresh(gc, group);
}
+ switch (group->auth_type) {
+ case QQ_GROUP_AUTH_TYPE_NO_AUTH:
+ case QQ_GROUP_AUTH_TYPE_NEED_AUTH:
+ break;
+ case QQ_GROUP_AUTH_TYPE_NO_ADD:
+ gaim_notify_warning(gc, NULL, _("This group does not allow others to join"), NULL);
+ return;
+ default:
+ gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Unknown group auth type: %d\n", group->auth_type);
+ break;
+ }
+
data_len = 5;
raw_data = g_newa(guint8, data_len);
cursor = raw_data;
@@ -94,7 +108,7 @@
gc = g->gc;
internal_group_id = g->uid;
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
if (group == NULL) {
gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Can not find qq_group by internal_id: %d\n", internal_group_id);
return;
@@ -163,15 +177,7 @@
qq_send_group_cmd(gc, group, raw_data, data_len);
}
-/* send packet to exit one group
- * In fact, this will never be used for GAIM
- * when we remove a GaimChat node, there is no user controlable callback
- * so we only remove the GaimChat node,
- * but we never use this cmd to update the server side
- * anyway, it is function, as when we remove the GaimChat node,
- * user has no way to start up the chat conversation window
- * therefore even we are still in it,
- * the group IM will not show up to bother us. (Limited by GAIM) */
+/* send a packet to exit a group */
void qq_send_cmd_group_exit_group(GaimConnection *gc, qq_group *group)
{
guint8 *raw_data, *cursor;
@@ -212,16 +218,16 @@
bytes += read_packet_dw(data, cursor, len, &internal_group_id);
if (bytes == expected_bytes) {
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
if (group != NULL) {
chat =
gaim_blist_find_chat
(gaim_connection_get_account(gc), g_strdup_printf("%d", group->external_group_id));
if (chat != NULL)
gaim_blist_remove_chat(chat);
- qq_group_remove_by_internal_group_id(qd, internal_group_id);
+ qq_group_delete_internal_record(qd, internal_group_id);
}
- gaim_notify_info(gc, _("QQ Qun Operation"), _("You have successfully exit group"), NULL);
+ gaim_notify_info(gc, _("QQ Qun Operation"), _("You have successfully exited the group"), NULL);
} else {
gaim_debug(GAIM_DEBUG_ERROR, "QQ",
"Invalid exit group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
@@ -246,7 +252,8 @@
if (bytes == expected_bytes)
gaim_notify_info
- (gc, _("QQ Group Auth"), _("You authorization operation has been accepted by QQ server"), NULL);
+ (gc, _("QQ Group Auth"),
+ _("Your authorization operation has been accepted by the QQ server"), NULL);
else
gaim_debug(GAIM_DEBUG_ERROR, "QQ",
"Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
@@ -272,7 +279,7 @@
"Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
return;
} else { /* join group OK */
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
/* need to check if group is NULL or not. */
g_return_if_fail(group != NULL);
switch (reply) {
@@ -280,7 +287,7 @@
gaim_debug(GAIM_DEBUG_INFO, "QQ", "Succeed joining group \"%s\"\n", group->group_name_utf8);
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
qq_group_refresh(gc, group);
- /* this must be show before getting online member */
+ /* this must be shown before getting online members */
qq_group_conv_show_window(gc, group);
qq_send_cmd_group_get_group_info(gc, group);
break;
@@ -300,38 +307,33 @@
}
}
-/* Apply to join one group without auth */
+/* Attempt to join a group without auth */
void qq_group_join(GaimConnection *gc, GHashTable *data)
{
- gchar *internal_group_id_ptr;
- guint32 internal_group_id;
+ qq_data *qd;
+ gchar *external_group_id_ptr;
+ guint32 external_group_id;
qq_group *group;
- g_return_if_fail(gc != NULL && data != NULL);
+ g_return_if_fail(gc != NULL && gc->proto_data != NULL && data != NULL);
+ qd = (qq_data *) gc->proto_data;
- internal_group_id_ptr = g_hash_table_lookup(data, "internal_group_id");
- internal_group_id = strtol(internal_group_id_ptr, NULL, 10);
+ external_group_id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_EXTERNAL_ID);
+ g_return_if_fail(external_group_id_ptr != NULL);
+ errno = 0;
+ external_group_id = strtol(external_group_id_ptr, NULL, 10);
+ if (errno != 0) {
+ gaim_notify_error(gc, _("Error"),
+ _("You inputted a group id outside the acceptable range"), NULL);
+ return;
+ }
- g_return_if_fail(internal_group_id > 0);
-
- /* for those we have subscribed, they should have been put into
- * qd->groups in qq_group_init subroutine */
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
- if (group == NULL)
- group = qq_group_from_hashtable(gc, data);
-
- g_return_if_fail(group != NULL);
-
- switch (group->auth_type) {
- case QQ_GROUP_AUTH_TYPE_NO_AUTH:
- case QQ_GROUP_AUTH_TYPE_NEED_AUTH:
- _qq_send_cmd_group_join_group(gc, group);
- break;
- case QQ_GROUP_AUTH_TYPE_NO_ADD:
- gaim_notify_warning(gc, NULL, _("This group does not allow others to join"), NULL);
- break;
- default:
- gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Unknown group auth type: %d\n", group->auth_type);
+ group = qq_group_find_by_id(gc, external_group_id, QQ_EXTERNAL_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);
}
}
Modified: trunk/libgaim/protocols/qq/group_join.h
===================================================================
--- trunk/libgaim/protocols/qq/group_join.h 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_join.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -41,6 +41,7 @@
void qq_send_cmd_group_auth(GaimConnection *gc, qq_group *group, guint8 opt, guint32 uid, const gchar *reason_utf8);
void qq_group_join(GaimConnection *gc, GHashTable *data);
+void qq_send_cmd_group_join_group(GaimConnection *gc, qq_group *group);
void qq_group_exit(GaimConnection *gc, GHashTable *data);
void qq_send_cmd_group_exit_group(GaimConnection *gc, qq_group *group);
void qq_process_group_cmd_exit_group(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc);
Modified: trunk/libgaim/protocols/qq/group_network.c
===================================================================
--- trunk/libgaim/protocols/qq/group_network.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_network.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -27,7 +27,7 @@
#include "crypt.h"
#include "group_conv.h"
#include "group_find.h"
-#include "group_hash.h"
+#include "group_internal.h"
#include "group_im.h"
#include "group_info.h"
#include "group_join.h"
@@ -40,6 +40,7 @@
enum {
QQ_GROUP_CMD_REPLY_OK = 0x00,
+ QQ_GROUP_CMD_REPLY_SEARCH_ERROR = 0x02,
QQ_GROUP_CMD_REPLY_NOT_MEMBER = 0x0a
};
@@ -154,11 +155,15 @@
bytes += read_packet_b(data, &cursor, len, &sub_cmd);
bytes += read_packet_b(data, &cursor, len, &reply);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
if (reply != QQ_GROUP_CMD_REPLY_OK) {
gaim_debug(GAIM_DEBUG_WARNING, "QQ",
"Group cmd reply says cmd %s fails\n", qq_group_cmd_get_desc(sub_cmd));
+
+ if (group != NULL)
+ qq_set_pending_id(&qd->joining_groups, group->external_group_id, FALSE);
+
switch (reply) { /* this should be all errors */
case QQ_GROUP_CMD_REPLY_NOT_MEMBER:
if (group != NULL) {
@@ -169,19 +174,26 @@
qq_group_refresh(gc, group);
}
break;
+ case QQ_GROUP_CMD_REPLY_SEARCH_ERROR:
+ if (qd->roomlist != NULL) {
+ if (gaim_roomlist_get_in_progress(qd->roomlist))
+ gaim_roomlist_set_in_progress(qd->roomlist, FALSE);
+ }
+ _qq_process_group_cmd_reply_error_default(reply, cursor, len - bytes, gc);
+ break;
default:
_qq_process_group_cmd_reply_error_default(reply, cursor, len - bytes, gc);
}
return;
}
- /* seems to ok so far, so we process the reply according to sub_cmd */
+ /* seems ok so far, so we process the reply according to sub_cmd */
switch (sub_cmd) {
case QQ_GROUP_CMD_GET_GROUP_INFO:
qq_process_group_cmd_get_group_info(data, &cursor, len, gc);
if (group != NULL) {
- qq_send_cmd_group_get_member_info(gc, group);
- qq_send_cmd_group_get_online_member(gc, group);
+ qq_send_cmd_group_get_members_info(gc, group);
+ qq_send_cmd_group_get_online_members(gc, group);
}
break;
case QQ_GROUP_CMD_CREATE_GROUP:
@@ -212,12 +224,12 @@
qq_process_group_cmd_im(data, &cursor, len, gc);
break;
case QQ_GROUP_CMD_GET_ONLINE_MEMBER:
- qq_process_group_cmd_get_online_member(data, &cursor, len, gc);
+ qq_process_group_cmd_get_online_members(data, &cursor, len, gc);
if (group != NULL)
qq_group_conv_refresh_online_member(gc, group);
break;
case QQ_GROUP_CMD_GET_MEMBER_INFO:
- qq_process_group_cmd_get_member_info(data, &cursor, len, gc);
+ qq_process_group_cmd_get_members_info(data, &cursor, len, gc);
if (group != NULL)
qq_group_conv_refresh_online_member(gc, group);
break;
Modified: trunk/libgaim/protocols/qq/group_opt.c
===================================================================
--- trunk/libgaim/protocols/qq/group_opt.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_opt.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -26,9 +26,8 @@
#include "buddy_info.h"
#include "char_conv.h"
-/*#include "group_admindlg.h" */
#include "group_find.h"
-#include "group_hash.h"
+#include "group_internal.h"
#include "group_info.h"
#include "group_join.h"
#include "group_network.h"
@@ -108,7 +107,7 @@
{
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_internal_group_id(g->gc, g->internal_group_id);
+ group = qq_group_find_by_id(g->gc, g->internal_group_id, QQ_INTERNAL_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);
@@ -148,7 +147,7 @@
{
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_internal_group_id(g->gc, g->internal_group_id);
+ group = qq_group_find_by_id(g->gc, g->internal_group_id, QQ_INTERNAL_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);
@@ -221,7 +220,7 @@
g_return_if_fail(internal_group_id > 0);
/* we should have its info locally */
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
gaim_debug(GAIM_DEBUG_INFO, "QQ", "Succeed in modify members for Qun %d\n", group->external_group_id);
@@ -290,7 +289,7 @@
g_return_if_fail(internal_group_id > 0);
/* we should have its info locally */
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
gaim_debug(GAIM_DEBUG_INFO, "QQ", "Succeed in modify info for Qun %d\n", group->external_group_id);
@@ -345,10 +344,10 @@
qq_group *group;
g_return_if_fail(g != NULL && g->gc != NULL && g->uid > 0);
- group = qq_group_find_by_internal_group_id(g->gc, g->uid);
+ group = qq_group_find_by_id(g->gc, g->uid, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
- /* XXX insert UI code here */
+ /* TODO insert UI code here */
/* qq_group_detail_window_show(g->gc, group); */
g_free(g);
}
@@ -368,7 +367,7 @@
read_packet_dw(data, cursor, len, &external_group_id);
g_return_if_fail(internal_group_id > 0 && external_group_id);
- group = qq_group_create_by_id(gc, internal_group_id, external_group_id);
+ group = qq_group_create_internal_record(gc, internal_group_id, external_group_id, NULL);
group->my_status = QQ_GROUP_MEMBER_STATUS_IS_ADMIN;
group->creator_uid = qd->uid;
qq_group_refresh(gc, group);
@@ -427,7 +426,7 @@
g_return_if_fail(internal_group_id > 0);
/* we should have its info locally */
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
gaim_debug(GAIM_DEBUG_INFO, "QQ", "Succeed in activate Qun %d\n", group->external_group_id);
@@ -445,7 +444,7 @@
internal_group_id = strtol(internal_group_id_ptr, NULL, 10);
g_return_if_fail(internal_group_id > 0);
- group = qq_group_find_by_internal_group_id(gc, internal_group_id);
+ group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
g_return_if_fail(group != NULL);
/* XXX insert UI code here */
Modified: trunk/libgaim/protocols/qq/group_search.c
===================================================================
--- trunk/libgaim/protocols/qq/group_search.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/group_search.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -23,7 +23,10 @@
#include "debug.h"
#include "char_conv.h"
+#include "group_find.h"
#include "group_free.h"
+#include "group_internal.h"
+#include "group_join.h"
#include "group_network.h"
#include "group_search.h"
#include "utils.h"
@@ -58,6 +61,37 @@
qq_send_group_cmd(gc, NULL, raw_data, data_len);
}
+static void _qq_setup_roomlist(qq_data *qd, qq_group *group)
+{
+ GaimRoomlistRoom *room;
+ gchar *field;
+
+ room = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_ROOM, group->group_name_utf8, NULL);
+ field = g_strdup_printf("%d", group->external_group_id);
+ gaim_roomlist_room_add_field(qd->roomlist, room, field);
+ g_free(field);
+ field = g_strdup_printf("%d", group->creator_uid);
+ gaim_roomlist_room_add_field(qd->roomlist, room, field);
+ g_free(field);
+ gaim_roomlist_room_add_field(qd->roomlist, room, group->group_desc_utf8);
+ field = g_strdup_printf("%d", group->internal_group_id);
+ gaim_roomlist_room_add_field(qd->roomlist, room, field);
+ g_free(field);
+ field = g_strdup_printf("%d", group->group_type);
+ gaim_roomlist_room_add_field(qd->roomlist, room, field);
+ g_free(field);
+ field = g_strdup_printf("%d", group->auth_type);
+ gaim_roomlist_room_add_field(qd->roomlist, room, field);
+ g_free(field);
+ field = g_strdup_printf("%d", group->group_category);
+ gaim_roomlist_room_add_field(qd->roomlist, room, field);
+ g_free(field);
+ gaim_roomlist_room_add_field(qd->roomlist, room, group->group_name_utf8);
+ gaim_roomlist_room_add(qd->roomlist, room);
+
+ gaim_roomlist_set_in_progress(qd->roomlist, FALSE);
+}
+
/* process group cmd reply "search group" */
void qq_process_group_cmd_search_group(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc)
{
@@ -65,56 +99,51 @@
guint16 unknown;
gint bytes, pascal_len, i;
qq_data *qd;
- GaimRoomlistRoom *room;
qq_group *group;
+ GSList *pending_id;
g_return_if_fail(gc != NULL && gc->proto_data != NULL);
g_return_if_fail(data != NULL && len > 0);
qd = (qq_data *) gc->proto_data;
- i = 0;
read_packet_b(data, cursor, len, &search_type);
group = g_newa(qq_group, 1);
/* now it starts with group_info_entry */
- while (*cursor < (data + len)) { /* still have data to read */
- /* begin of one qq_group */
- bytes = 0;
- i++;
- bytes += read_packet_dw(data, cursor, len, &(group->internal_group_id));
- bytes += read_packet_dw(data, cursor, len, &(group->external_group_id));
- bytes += read_packet_b(data, cursor, len, &(group->group_type));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_dw(data, cursor, len, &(group->creator_uid));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_dw(data, cursor, len, &(group->group_category));
- pascal_len = convert_as_pascal_string(*cursor, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
- bytes += pascal_len;
- *cursor += pascal_len;
- bytes += read_packet_w(data, cursor, len, &(unknown));
- bytes += read_packet_b(data, cursor, len, &(group->auth_type));
- pascal_len = convert_as_pascal_string(*cursor, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT);
- bytes += pascal_len;
- *cursor += pascal_len;
- /* end of one qq_group */
- room = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_ROOM, group->group_name_utf8, NULL);
- gaim_roomlist_room_add_field(qd->roomlist, room, g_strdup_printf("%d", group->external_group_id));
- gaim_roomlist_room_add_field(qd->roomlist, room, g_strdup_printf("%d", group->creator_uid));
- gaim_roomlist_room_add_field(qd->roomlist, room, group->group_desc_utf8);
- gaim_roomlist_room_add_field(qd->roomlist, room, g_strdup_printf("%d", group->internal_group_id));
- gaim_roomlist_room_add_field(qd->roomlist, room, g_strdup_printf("%d", group->group_type));
- gaim_roomlist_room_add_field(qd->roomlist, room, g_strdup_printf("%d", group->auth_type));
- gaim_roomlist_room_add_field(qd->roomlist, room, g_strdup_printf("%d", group->group_category));
- gaim_roomlist_room_add_field(qd->roomlist, room, group->group_name_utf8);
- gaim_roomlist_room_add(qd->roomlist, room);
- }
- if(*cursor > (data + len)) {
+ bytes = 0;
+ i++;
+ bytes += read_packet_dw(data, cursor, len, &(group->internal_group_id));
+ bytes += read_packet_dw(data, cursor, len, &(group->external_group_id));
+ bytes += read_packet_b(data, cursor, len, &(group->group_type));
+ bytes += read_packet_w(data, cursor, len, &(unknown));
+ bytes += read_packet_w(data, cursor, len, &(unknown));
+ bytes += read_packet_dw(data, cursor, len, &(group->creator_uid));
+ bytes += read_packet_w(data, cursor, len, &(unknown));
+ bytes += read_packet_w(data, cursor, len, &(unknown));
+ bytes += read_packet_w(data, cursor, len, &(unknown));
+ bytes += read_packet_dw(data, cursor, len, &(group->group_category));
+ pascal_len = convert_as_pascal_string(*cursor, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
+ bytes += pascal_len;
+ *cursor += pascal_len;
+ bytes += read_packet_w(data, cursor, len, &(unknown));
+ bytes += read_packet_b(data, cursor, len, &(group->auth_type));
+ pascal_len = convert_as_pascal_string(*cursor, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT);
+ bytes += pascal_len;
+ *cursor += pascal_len;
+ /* end of one qq_group */
+ if(*cursor != (data + len)) {
gaim_debug(GAIM_DEBUG_ERROR, "QQ",
"group_cmd_search_group: Dangerous error! maybe protocol changed, notify developers!");
}
- gaim_roomlist_set_in_progress(qd->roomlist, FALSE);
- gaim_debug(GAIM_DEBUG_INFO, "QQ", "Search group reply: %d groups\n", i);
+
+ pending_id = qq_get_pending_id(qd->joining_groups, group->external_group_id);
+ if (pending_id != NULL) {
+ qq_set_pending_id(&qd->joining_groups, group->external_group_id, FALSE);
+ if (qq_group_find_by_id(gc, group->internal_group_id, QQ_INTERNAL_ID) == NULL)
+ qq_group_create_internal_record(gc,
+ group->internal_group_id, group->external_group_id, group->group_name_utf8);
+ qq_send_cmd_group_join_group(gc, group);
+ } else {
+ _qq_setup_roomlist(qd, group);
+ }
}
Modified: trunk/libgaim/protocols/qq/login_logout.c
===================================================================
--- trunk/libgaim/protocols/qq/login_logout.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/login_logout.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -234,10 +234,10 @@
qq_send_packet_change_status(gc);
- /* now refresh buddy list */
- /* changed by gfhuang, using With Qun version, error, not working still */
+ /* refresh buddies */
qq_send_packet_get_buddies_list(gc, QQ_FRIENDS_LIST_POSITION_START);
- /* qq_send_packet_get_all_list_with_group(gc, QQ_FRIENDS_LIST_POSITION_START); */
+ /* refresh groups */
+ qq_send_packet_get_all_list_with_group(gc, QQ_FRIENDS_LIST_POSITION_START);
return QQ_LOGIN_REPLY_OK;
}
Modified: trunk/libgaim/protocols/qq/qq.c
===================================================================
--- trunk/libgaim/protocols/qq/qq.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/qq.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -153,7 +153,7 @@
/* do not use g_return_val_if_fail, as it is not assertion */
if (b == NULL || b->proto_data == NULL)
return "qq";
-
+
q_bud = (qq_buddy *) b->proto_data;
filename = get_icon_name(q_bud->icon / 3 + 1);
@@ -565,7 +565,6 @@
}
*/
-/* XXX re-enable this
static void _qq_menu_unsubscribe_group(GaimBlistNode * node)
{
GaimChat *chat = (GaimChat *)node;
@@ -578,7 +577,7 @@
qq_group_exit(gc, components);
}
-// XXX re-enable this
+/*
static void _qq_menu_manage_group(GaimBlistNode * node)
{
GaimChat *chat = (GaimChat *)node;
@@ -860,7 +859,6 @@
}
/* chat-related (QQ Qun) menu shown up with right-click */
-/* TODO re-enable this
static GList *_qq_chat_menu(GaimBlistNode *node)
{
GList *m;
@@ -870,14 +868,15 @@
act = gaim_menu_action_new(_("Exit this QQ Qun"), GAIM_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL);
m = g_list_append(m, act);
+ /* TODO: enable this
act = gaim_menu_action_new(_("Show Details"), GAIM_CALLBACK(_qq_menu_manage_group), NULL, NULL);
m = g_list_append(m, act);
+ */
return m;
}
-*/
+
/* buddy-related menu shown up with right-click */
-/* TODO re-enable this
static GList *_qq_buddy_menu(GaimBlistNode * node)
{
GList *m;
@@ -886,7 +885,9 @@
return _qq_chat_menu(node);
m = NULL;
-*/
+ return m;
+}
+
/* TODO : not working, temp commented out by gfhuang
act = gaim_menu_action_new(_("Block this buddy"), GAIM_CALLBACK(_qq_menu_block_buddy), NULL, NULL); //add NULL by gfhuang
@@ -918,7 +919,7 @@
if (group->my_status == QQ_GROUP_MEMBER_STATUS_IS_MEMBER ||
group->my_status == QQ_GROUP_MEMBER_STATUS_IS_ADMIN)
/* no need to get info time and time again, online members enough */
- qq_send_cmd_group_get_online_member(gc, group);
+ qq_send_cmd_group_get_online_members(gc, group);
list = list->next;
}
@@ -934,7 +935,7 @@
gchar *gaim_name;
g_return_if_fail(gc != NULL && gc->proto_data != NULL && who != NULL);
- gaim_name = qq_group_find_member_by_channel_and_nickname(gc, channel, who);
+ gaim_name = chat_name_to_gaim_name(who);
if (gaim_name != NULL)
_qq_get_info(gc, gaim_name);
}
@@ -944,7 +945,7 @@
static gchar *_qq_get_chat_buddy_real_name(GaimConnection *gc, gint channel, const gchar *who)
{
g_return_val_if_fail(gc != NULL && gc->proto_data != NULL && who != NULL, NULL);
- return qq_group_find_member_by_channel_and_nickname(gc, channel, who);
+ return chat_name_to_gaim_name(who);
}
void qq_function_not_implemented(GaimConnection *gc)
@@ -964,9 +965,9 @@
_qq_status_text, /* status_text */
_qq_tooltip_text, /* tooltip_text */
_qq_away_states, /* away_states */
- NULL, /* blist_node_menu */
- NULL, /* chat_info */
- NULL, /* chat_info_defaults */
+ _qq_buddy_menu, /* blist_node_menu */
+ qq_chat_info, /* chat_info */
+ qq_chat_info_defaults, /* chat_info_defaults */
_qq_login, /* login */
_qq_close, /* close */
_qq_send_im, /* send_im */
@@ -1043,7 +1044,7 @@
NULL, /**< ui_info */
&prpl_info, /**< extra_info */
- NULL, /**< prefs_info */
+ NULL, /**< prefs_info */
_qq_actions
};
Modified: trunk/libgaim/protocols/qq/qq.h
===================================================================
--- trunk/libgaim/protocols/qq/qq.h 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/qq.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -95,9 +95,11 @@
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;
GList *contact_info_window;
- GList *qun_info_window;
+ GList *group_info_window;
GList *sendqueue;
GList *info_query;
GList *add_buddy_request;
Modified: trunk/libgaim/protocols/qq/utils.c
===================================================================
--- trunk/libgaim/protocols/qq/utils.c 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/utils.c 2006-09-01 11:03:18 UTC (rev 17112)
@@ -164,13 +164,6 @@
return g_strdup_printf("qq_%d", set);
}
-/* convert a QQ UID to a unique name of Gaim
- * the return needs to be freed */
-gchar *uid_to_gaim_name(guint32 uid)
-{
- return g_strdup_printf(QQ_NAME_FORMAT, uid);
-}
-
/* convert Gaim name to original QQ UID */
guint32 gaim_name_to_uid(const gchar *const name)
{
@@ -184,6 +177,27 @@
return ret;
}
+/* convert a QQ UID to a unique name of Gaim
+ * the return needs to be freed */
+gchar *uid_to_gaim_name(guint32 uid)
+{
+ return g_strdup_printf(QQ_NAME_FORMAT, uid);
+}
+
+/* convert name displayed in a chat channel to original QQ UID */
+gchar *chat_name_to_gaim_name(const gchar *const name)
+{
+ const gchar *tmp;
+ gchar *ret;
+
+ g_return_val_if_fail(name != NULL, NULL);
+
+ tmp = (gchar *) gaim_strcasestr(name, "(qq-");
+ ret = g_strndup(tmp + 4, strlen(name) - (tmp - name) - 4 - 1);
+
+ return ret;
+}
+
/* try to dump the data as GBK */
void try_dump_as_gbk(const guint8 *const data, gint len)
{
Modified: trunk/libgaim/protocols/qq/utils.h
===================================================================
--- trunk/libgaim/protocols/qq/utils.h 2006-09-01 10:05:30 UTC (rev 17111)
+++ trunk/libgaim/protocols/qq/utils.h 2006-09-01 11:03:18 UTC (rev 17112)
@@ -32,11 +32,13 @@
gchar **split_data(guint8 *data, gint len, const gchar *delimit, gint expected_fields);
guint8 *_gen_session_md5(gint uid, guint8 *session_key);
+
gchar *gen_ip_str(guint8 *ip);
guint8 *str_ip_gen(gchar *str);
-gchar *uid_to_gaim_name(guint32 uid);
guint32 gaim_name_to_uid(const gchar *name);
+gchar *uid_to_gaim_name(guint32 uid);
+gchar *chat_name_to_gaim_name(const gchar *const name);
gchar *get_icon_name(gint set);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|