Mercurial > pidgin
comparison libpurple/protocols/qq/group_info.c @ 15373: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
15372:f79e0f4df793 | 15373: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 } |