comparison libpurple/protocols/qq/group_info.c @ 15374:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children 32c366eeeb99
comparison
equal deleted inserted replaced
15373:f79e0f4df793 15374:5fe8042783c1
1 /**
2 * @file group_info.c
3 *
4 * gaim
5 *
6 * Gaim is the legal property of its developers, whose names are too numerous
7 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * source distribution.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25 #include "conversation.h"
26 #include "debug.h"
27
28 #include "buddy_status.h"
29 #include "char_conv.h"
30 #include "group_find.h"
31 #include "group_internal.h"
32 #include "group_info.h"
33 #include "buddy_status.h"
34 #include "group_network.h"
35
36 /* we check who needs to update member info every minutes
37 * this interval determines if their member info is outdated */
38 #define QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL 180
39
40 static gboolean _is_group_member_need_update_info(qq_buddy *member)
41 {
42 g_return_val_if_fail(member != NULL, FALSE);
43 return (member->nickname == NULL) ||
44 (time(NULL) - member->last_refresh) > QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL;
45 }
46
47 /* this is done when we receive the reply to get_online_members sub_cmd
48 * all member are set offline, and then only those in reply packets are online */
49 static void _qq_group_set_members_all_offline(qq_group *group)
50 {
51 GList *list;
52 qq_buddy *member;
53 g_return_if_fail(group != NULL);
54
55 list = group->members;
56 while (list != NULL) {
57 member = (qq_buddy *) list->data;
58 member->status = QQ_BUDDY_ONLINE_OFFLINE;
59 list = list->next;
60 }
61 }
62
63 /* send packet to get detailed information of one group */
64 void qq_send_cmd_group_get_group_info(GaimConnection *gc, qq_group *group)
65 {
66 guint8 *raw_data, *cursor;
67 gint bytes, data_len;
68
69 g_return_if_fail(group != NULL);
70
71 data_len = 5;
72 raw_data = g_newa(guint8, data_len);
73 cursor = raw_data;
74
75 bytes = 0;
76 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_GET_GROUP_INFO);
77 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
78
79 if (bytes != data_len)
80 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
81 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_GET_GROUP_INFO));
82 else
83 qq_send_group_cmd(gc, group, raw_data, data_len);
84 }
85
86 /* send packet to get online group member, called by keep_alive */
87 void qq_send_cmd_group_get_online_members(GaimConnection *gc, qq_group *group)
88 {
89 guint8 *raw_data, *cursor;
90 gint bytes, data_len;
91
92 g_return_if_fail(group != NULL);
93
94 /* only get online members when conversation window is on */
95 if (NULL == gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT,group->group_name_utf8, gaim_connection_get_account(gc))) {
96 gaim_debug(GAIM_DEBUG_WARNING, "QQ",
97 "Conv windows for \"%s\" is not on, do not get online members\n", group->group_name_utf8);
98 return;
99 }
100
101 data_len = 5;
102 raw_data = g_newa(guint8, data_len);
103 cursor = raw_data;
104
105 bytes = 0;
106 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_GET_ONLINE_MEMBER);
107 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
108
109 if (bytes != data_len)
110 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
111 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_GET_ONLINE_MEMBER));
112 else
113 qq_send_group_cmd(gc, group, raw_data, data_len);
114 }
115
116 /* send packet to get info for each group member */
117 void qq_send_cmd_group_get_members_info(GaimConnection *gc, qq_group *group)
118 {
119 guint8 *raw_data, *cursor;
120 gint bytes, data_len, i;
121 GList *list;
122 qq_buddy *member;
123
124 g_return_if_fail(group != NULL);
125 for (i = 0, list = group->members; list != NULL; list = list->next) {
126 member = (qq_buddy *) list->data;
127 if (_is_group_member_need_update_info(member))
128 i++;
129 }
130
131 if (i <= 0) {
132 gaim_debug(GAIM_DEBUG_INFO, "QQ", "No group member needs to to update info now.\n");
133 return;
134 }
135
136 data_len = 5 + 4 * i;
137 raw_data = g_newa(guint8, data_len);
138 cursor = raw_data;
139
140 bytes = 0;
141 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_GET_MEMBER_INFO);
142 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
143
144 list = group->members;
145 while (list != NULL) {
146 member = (qq_buddy *) list->data;
147 if (_is_group_member_need_update_info(member))
148 bytes += create_packet_dw(raw_data, &cursor, member->uid);
149 list = list->next;
150 }
151
152 if (bytes != data_len)
153 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
154 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_GET_MEMBER_INFO));
155 else
156 qq_send_group_cmd(gc, group, raw_data, data_len);
157 }
158
159 void qq_process_group_cmd_get_group_info(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc)
160 {
161 qq_group *group;
162 qq_buddy *member;
163 qq_data *qd;
164 GaimConversation *gaim_conv;
165 guint8 organization, role;
166 guint16 unknown, max_members;
167 guint32 member_uid, internal_group_id, external_group_id;
168 GSList *pending_id;
169 gint pascal_len, i;
170 guint32 unknown4;
171 guint8 unknown1;
172
173 g_return_if_fail(data != NULL && len > 0);
174 qd = (qq_data *) gc->proto_data;
175
176 read_packet_dw(data, cursor, len, &(internal_group_id));
177 g_return_if_fail(internal_group_id > 0);
178 read_packet_dw(data, cursor, len, &(external_group_id));
179 g_return_if_fail(internal_group_id > 0);
180
181 pending_id = qq_get_pending_id(qd->adding_groups_from_server, internal_group_id);
182 if (pending_id != NULL) {
183 qq_set_pending_id(&qd->adding_groups_from_server, internal_group_id, FALSE);
184 qq_group_create_internal_record(gc, internal_group_id, external_group_id, NULL);
185 }
186
187 group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
188 g_return_if_fail(group != NULL);
189
190 read_packet_b(data, cursor, len, &(group->group_type));
191 read_packet_dw(data, cursor, len, &unknown4); /* unknown 4 bytes */
192 read_packet_dw(data, cursor, len, &(group->creator_uid));
193 read_packet_b(data, cursor, len, &(group->auth_type));
194 read_packet_dw(data, cursor, len, &unknown4); /* oldCategory */
195 read_packet_w(data, cursor, len, &unknown);
196 read_packet_dw(data, cursor, len, &(group->group_category));
197 read_packet_w(data, cursor, len, &max_members);
198 read_packet_b(data, cursor, len, &unknown1);
199 read_packet_dw(data, cursor, len, &(unknown4)); /* versionID */
200
201 pascal_len = convert_as_pascal_string(*cursor, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
202 *cursor += pascal_len;
203 read_packet_w(data, cursor, len, &(unknown)); /* 0x0000 */
204 pascal_len = convert_as_pascal_string(*cursor, &(group->notice_utf8), QQ_CHARSET_DEFAULT);
205 *cursor += pascal_len;
206 pascal_len = convert_as_pascal_string(*cursor, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT);
207 *cursor += pascal_len;
208
209 i = 0;
210 /* now comes the member list separated by 0x00 */
211 while (*cursor < data + len) {
212 read_packet_dw(data, cursor, len, &member_uid);
213 i++;
214 read_packet_b(data, cursor, len, &organization);
215 read_packet_b(data, cursor, len, &role);
216
217 if(organization != 0 || role != 0) {
218 gaim_debug(GAIM_DEBUG_INFO, "QQ", "group member %d: organization=%d, role=%d\n", member_uid, organization, role);
219 }
220 member = qq_group_find_or_add_member(gc, group, member_uid);
221 if (member != NULL)
222 member->role = role;
223 }
224 if(*cursor > (data + len)) {
225 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "group_cmd_get_group_info: Dangerous error! maybe protocol changed, notify me!");
226 }
227
228 gaim_debug(GAIM_DEBUG_INFO, "QQ", "group \"%s\" has %d members\n", group->group_name_utf8, i);
229
230 if (group->creator_uid == qd->uid)
231 group->my_status = QQ_GROUP_MEMBER_STATUS_IS_ADMIN;
232
233 qq_group_refresh(gc, group);
234
235 gaim_conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT,
236 group->group_name_utf8, gaim_connection_get_account(gc));
237 if(NULL == gaim_conv) {
238 gaim_debug(GAIM_DEBUG_WARNING, "QQ",
239 "Conv windows for \"%s\" is not on, do not set topic\n", group->group_name_utf8);
240 }
241 else {
242 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(gaim_conv), NULL, group->notice_utf8);
243 }
244 }
245
246 void qq_process_group_cmd_get_online_members(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc)
247 {
248 guint32 internal_group_id, member_uid;
249 guint8 unknown;
250 gint bytes, i;
251 qq_group *group;
252 qq_buddy *member;
253
254 g_return_if_fail(data != NULL && len > 0);
255
256 if (data + len - *cursor < 4) {
257 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid group online member reply, discard it!\n");
258 return;
259 }
260
261 bytes = 0;
262 i = 0;
263 bytes += read_packet_dw(data, cursor, len, &internal_group_id);
264 bytes += read_packet_b(data, cursor, len, &unknown); /* 0x3c ?? */
265 g_return_if_fail(internal_group_id > 0);
266
267 group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
268 if (group == NULL) {
269 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
270 "We have no group info for internal id [%d]\n", internal_group_id);
271 return;
272 }
273
274 /* set all offline first, then update those online */
275 _qq_group_set_members_all_offline(group);
276 while (*cursor < data + len) {
277 bytes += read_packet_dw(data, cursor, len, &member_uid);
278 i++;
279 member = qq_group_find_or_add_member(gc, group, member_uid);
280 if (member != NULL)
281 member->status = QQ_BUDDY_ONLINE_NORMAL;
282 }
283 if(*cursor > (data + len)) {
284 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
285 "group_cmd_get_online_members: Dangerous error! maybe protocol changed, notify developers!");
286 }
287
288 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Group \"%s\" has %d online members\n", group->group_name_utf8, i);
289 }
290
291 /* process the reply to get_members_info packet */
292 void qq_process_group_cmd_get_members_info(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc)
293 {
294 guint32 internal_group_id, member_uid;
295 guint16 unknown;
296 gint pascal_len, i;
297 qq_group *group;
298 qq_buddy *member;
299
300 g_return_if_fail(data != NULL && len > 0);
301
302 read_packet_dw(data, cursor, len, &internal_group_id);
303 g_return_if_fail(internal_group_id > 0);
304
305 group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
306 g_return_if_fail(group != NULL);
307
308 i = 0;
309 /* now starts the member info, as get buddy list reply */
310 while (*cursor < data + len) {
311 read_packet_dw(data, cursor, len, &member_uid);
312 g_return_if_fail(member_uid > 0);
313 member = qq_group_find_member_by_uid(group, member_uid);
314 g_return_if_fail(member != NULL);
315
316 i++;
317 read_packet_w(data, cursor, len, &(member->face));
318 read_packet_b(data, cursor, len, &(member->age));
319 read_packet_b(data, cursor, len, &(member->gender));
320 pascal_len = convert_as_pascal_string(*cursor, &(member->nickname), QQ_CHARSET_DEFAULT);
321 *cursor += pascal_len;
322 read_packet_w(data, cursor, len, &unknown);
323 read_packet_b(data, cursor, len, &(member->flag1));
324 read_packet_b(data, cursor, len, &(member->comm_flag));
325
326 member->last_refresh = time(NULL);
327 }
328 if(*cursor > (data + len)) {
329 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
330 "group_cmd_get_members_info: Dangerous error! maybe protocol changed, notify developers!");
331 }
332 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Group \"%s\" obtained %d member info\n", group->group_name_utf8, i);
333 }