Mercurial > pidgin
comparison libpurple/protocols/qq/group_join.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_join.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 "debug.h" | |
26 #include "notify.h" | |
27 #include "request.h" | |
28 #include "server.h" | |
29 | |
30 #include "buddy_opt.h" | |
31 #include "char_conv.h" | |
32 #include "group_conv.h" | |
33 #include "group_find.h" | |
34 #include "group_free.h" | |
35 #include "group_internal.h" | |
36 #include "group_info.h" | |
37 #include "group_join.h" | |
38 #include "group_opt.h" | |
39 #include "group_network.h" | |
40 #include "group_search.h" | |
41 | |
42 enum { | |
43 QQ_GROUP_JOIN_OK = 0x01, | |
44 QQ_GROUP_JOIN_NEED_AUTH = 0x02, | |
45 }; | |
46 | |
47 static void _qq_group_exit_with_gc_and_id(gc_and_uid *g) | |
48 { | |
49 GaimConnection *gc; | |
50 guint32 internal_group_id; | |
51 qq_group *group; | |
52 | |
53 gc = g->gc; | |
54 internal_group_id = g->uid; | |
55 | |
56 group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID); | |
57 g_return_if_fail(group != NULL); | |
58 | |
59 qq_send_cmd_group_exit_group(gc, group); | |
60 } | |
61 | |
62 /* send packet to join a group without auth */ | |
63 void qq_send_cmd_group_join_group(GaimConnection *gc, qq_group *group) | |
64 { | |
65 guint8 *raw_data, *cursor; | |
66 gint bytes, data_len; | |
67 | |
68 g_return_if_fail(group != NULL); | |
69 | |
70 if (group->my_status == QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) { | |
71 group->my_status = QQ_GROUP_MEMBER_STATUS_APPLYING; | |
72 qq_group_refresh(gc, group); | |
73 } | |
74 | |
75 switch (group->auth_type) { | |
76 case QQ_GROUP_AUTH_TYPE_NO_AUTH: | |
77 case QQ_GROUP_AUTH_TYPE_NEED_AUTH: | |
78 break; | |
79 case QQ_GROUP_AUTH_TYPE_NO_ADD: | |
80 gaim_notify_warning(gc, NULL, _("This group does not allow others to join"), NULL); | |
81 return; | |
82 default: | |
83 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Unknown group auth type: %d\n", group->auth_type); | |
84 break; | |
85 } | |
86 | |
87 data_len = 5; | |
88 raw_data = g_newa(guint8, data_len); | |
89 cursor = raw_data; | |
90 | |
91 bytes = 0; | |
92 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_JOIN_GROUP); | |
93 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id); | |
94 | |
95 if (bytes != data_len) | |
96 gaim_debug(GAIM_DEBUG_ERROR, "QQ", | |
97 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_JOIN_GROUP)); | |
98 else | |
99 qq_send_group_cmd(gc, group, raw_data, data_len); | |
100 } | |
101 | |
102 static void _qq_group_join_auth_with_gc_and_id(gc_and_uid *g, const gchar *reason_utf8) | |
103 { | |
104 GaimConnection *gc; | |
105 qq_group *group; | |
106 guint32 internal_group_id; | |
107 | |
108 gc = g->gc; | |
109 internal_group_id = g->uid; | |
110 | |
111 group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID); | |
112 if (group == NULL) { | |
113 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Can not find qq_group by internal_id: %d\n", internal_group_id); | |
114 return; | |
115 } else { /* everything is OK */ | |
116 qq_send_cmd_group_auth(gc, group, QQ_GROUP_AUTH_REQUEST_APPLY, 0, reason_utf8); | |
117 } | |
118 } | |
119 | |
120 static void _qq_group_join_auth(GaimConnection *gc, qq_group *group) | |
121 { | |
122 gchar *msg; | |
123 gc_and_uid *g; | |
124 g_return_if_fail(group != NULL); | |
125 | |
126 gaim_debug(GAIM_DEBUG_INFO, "QQ", | |
127 "Group (internal id: %d) needs authentication\n", group->internal_group_id); | |
128 | |
129 msg = g_strdup_printf("Group \"%s\" needs authentication\n", group->group_name_utf8); | |
130 g = g_new0(gc_and_uid, 1); | |
131 g->gc = gc; | |
132 g->uid = group->internal_group_id; | |
133 gaim_request_input(gc, NULL, msg, | |
134 _("Input request here"), | |
135 _("Would you be my friend?"), TRUE, FALSE, NULL, | |
136 _("Send"), | |
137 G_CALLBACK(_qq_group_join_auth_with_gc_and_id), | |
138 _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), g); | |
139 g_free(msg); | |
140 } | |
141 | |
142 void qq_send_cmd_group_auth(GaimConnection *gc, qq_group *group, guint8 opt, guint32 uid, const gchar *reason_utf8) | |
143 { | |
144 guint8 *raw_data, *cursor; | |
145 gchar *reason_qq; | |
146 gint bytes, data_len; | |
147 | |
148 g_return_if_fail(group != NULL); | |
149 | |
150 if (reason_utf8 == NULL || strlen(reason_utf8) == 0) | |
151 reason_qq = g_strdup(""); | |
152 else | |
153 reason_qq = utf8_to_qq(reason_utf8, QQ_CHARSET_DEFAULT); | |
154 | |
155 if (opt == QQ_GROUP_AUTH_REQUEST_APPLY) { | |
156 group->my_status = QQ_GROUP_MEMBER_STATUS_APPLYING; | |
157 qq_group_refresh(gc, group); | |
158 uid = 0; | |
159 } | |
160 | |
161 data_len = 10 + strlen(reason_qq) + 1; | |
162 raw_data = g_newa(guint8, data_len); | |
163 cursor = raw_data; | |
164 | |
165 bytes = 0; | |
166 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_JOIN_GROUP_AUTH); | |
167 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id); | |
168 bytes += create_packet_b(raw_data, &cursor, opt); | |
169 bytes += create_packet_dw(raw_data, &cursor, uid); | |
170 bytes += create_packet_b(raw_data, &cursor, strlen(reason_qq)); | |
171 bytes += create_packet_data(raw_data, &cursor, (guint8 *) reason_qq, strlen(reason_qq)); | |
172 | |
173 if (bytes != data_len) | |
174 gaim_debug(GAIM_DEBUG_ERROR, "QQ", | |
175 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_JOIN_GROUP_AUTH)); | |
176 else | |
177 qq_send_group_cmd(gc, group, raw_data, data_len); | |
178 } | |
179 | |
180 /* send a packet to exit a group */ | |
181 void qq_send_cmd_group_exit_group(GaimConnection *gc, qq_group *group) | |
182 { | |
183 guint8 *raw_data, *cursor; | |
184 gint bytes, data_len; | |
185 | |
186 g_return_if_fail(group != NULL); | |
187 | |
188 data_len = 5; | |
189 raw_data = g_newa(guint8, data_len); | |
190 cursor = raw_data; | |
191 | |
192 bytes = 0; | |
193 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_EXIT_GROUP); | |
194 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id); | |
195 | |
196 if (bytes != data_len) | |
197 gaim_debug(GAIM_DEBUG_ERROR, "QQ", | |
198 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_EXIT_GROUP)); | |
199 else | |
200 qq_send_group_cmd(gc, group, raw_data, data_len); | |
201 } | |
202 | |
203 /* If comes here, cmd is OK already */ | |
204 void qq_process_group_cmd_exit_group(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc) | |
205 { | |
206 gint bytes, expected_bytes; | |
207 guint32 internal_group_id; | |
208 GaimChat *chat; | |
209 qq_group *group; | |
210 qq_data *qd; | |
211 | |
212 g_return_if_fail(data != NULL && len > 0); | |
213 qd = (qq_data *) gc->proto_data; | |
214 | |
215 bytes = 0; | |
216 expected_bytes = 4; | |
217 bytes += read_packet_dw(data, cursor, len, &internal_group_id); | |
218 | |
219 if (bytes == expected_bytes) { | |
220 group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID); | |
221 if (group != NULL) { | |
222 chat = | |
223 gaim_blist_find_chat | |
224 (gaim_connection_get_account(gc), g_strdup_printf("%d", group->external_group_id)); | |
225 if (chat != NULL) | |
226 gaim_blist_remove_chat(chat); | |
227 qq_group_delete_internal_record(qd, internal_group_id); | |
228 } | |
229 gaim_notify_info(gc, _("QQ Qun Operation"), _("You have successfully exited the group"), NULL); | |
230 } else { | |
231 gaim_debug(GAIM_DEBUG_ERROR, "QQ", | |
232 "Invalid exit group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes); | |
233 } | |
234 } | |
235 | |
236 /* Process the reply to group_auth subcmd */ | |
237 void qq_process_group_cmd_join_group_auth(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc) | |
238 { | |
239 gint bytes, expected_bytes; | |
240 guint32 internal_group_id; | |
241 qq_data *qd; | |
242 | |
243 g_return_if_fail(data != NULL && len > 0); | |
244 qd = (qq_data *) gc->proto_data; | |
245 | |
246 bytes = 0; | |
247 expected_bytes = 4; | |
248 bytes += read_packet_dw(data, cursor, len, &internal_group_id); | |
249 g_return_if_fail(internal_group_id > 0); | |
250 | |
251 if (bytes == expected_bytes) | |
252 gaim_notify_info | |
253 (gc, _("QQ Group Auth"), | |
254 _("Your authorization operation has been accepted by the QQ server"), NULL); | |
255 else | |
256 gaim_debug(GAIM_DEBUG_ERROR, "QQ", | |
257 "Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes); | |
258 } | |
259 | |
260 /* process group cmd reply "join group" */ | |
261 void qq_process_group_cmd_join_group(guint8 *data, guint8 **cursor, gint len, GaimConnection *gc) | |
262 { | |
263 gint bytes, expected_bytes; | |
264 guint32 internal_group_id; | |
265 guint8 reply; | |
266 qq_group *group; | |
267 | |
268 g_return_if_fail(data != NULL && len > 0); | |
269 | |
270 bytes = 0; | |
271 expected_bytes = 5; | |
272 bytes += read_packet_dw(data, cursor, len, &internal_group_id); | |
273 bytes += read_packet_b(data, cursor, len, &reply); | |
274 | |
275 if (bytes != expected_bytes) { | |
276 gaim_debug(GAIM_DEBUG_ERROR, "QQ", | |
277 "Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes); | |
278 return; | |
279 } else { /* join group OK */ | |
280 group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID); | |
281 /* need to check if group is NULL or not. */ | |
282 g_return_if_fail(group != NULL); | |
283 switch (reply) { | |
284 case QQ_GROUP_JOIN_OK: | |
285 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Succeed joining group \"%s\"\n", group->group_name_utf8); | |
286 group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER; | |
287 qq_group_refresh(gc, group); | |
288 /* this must be shown before getting online members */ | |
289 qq_group_conv_show_window(gc, group); | |
290 qq_send_cmd_group_get_group_info(gc, group); | |
291 break; | |
292 case QQ_GROUP_JOIN_NEED_AUTH: | |
293 gaim_debug(GAIM_DEBUG_INFO, "QQ", | |
294 "Fail joining group [%d] %s, needs authentication\n", | |
295 group->external_group_id, group->group_name_utf8); | |
296 group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER; | |
297 qq_group_refresh(gc, group); | |
298 _qq_group_join_auth(gc, group); | |
299 break; | |
300 default: | |
301 gaim_debug(GAIM_DEBUG_INFO, "QQ", | |
302 "Error joining group [%d] %s, unknown reply: 0x%02x\n", | |
303 group->external_group_id, group->group_name_utf8, reply); | |
304 } | |
305 } | |
306 } | |
307 | |
308 /* Attempt to join a group without auth */ | |
309 void qq_group_join(GaimConnection *gc, GHashTable *data) | |
310 { | |
311 qq_data *qd; | |
312 gchar *external_group_id_ptr; | |
313 guint32 external_group_id; | |
314 qq_group *group; | |
315 | |
316 g_return_if_fail(data != NULL); | |
317 qd = (qq_data *) gc->proto_data; | |
318 | |
319 external_group_id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_EXTERNAL_ID); | |
320 g_return_if_fail(external_group_id_ptr != NULL); | |
321 errno = 0; | |
322 external_group_id = strtol(external_group_id_ptr, NULL, 10); | |
323 if (errno != 0) { | |
324 gaim_notify_error(gc, _("Error"), | |
325 _("You inputted a group id outside the acceptable range"), NULL); | |
326 return; | |
327 } | |
328 | |
329 group = qq_group_find_by_id(gc, external_group_id, QQ_EXTERNAL_ID); | |
330 if (group) { | |
331 qq_send_cmd_group_join_group(gc, group); | |
332 } else { | |
333 qq_set_pending_id(&qd->joining_groups, external_group_id, TRUE); | |
334 qq_send_cmd_group_search_group(gc, external_group_id); | |
335 } | |
336 } | |
337 | |
338 void qq_group_exit(GaimConnection *gc, GHashTable *data) | |
339 { | |
340 gchar *internal_group_id_ptr; | |
341 guint32 internal_group_id; | |
342 gc_and_uid *g; | |
343 | |
344 g_return_if_fail(data != NULL); | |
345 | |
346 internal_group_id_ptr = g_hash_table_lookup(data, "internal_group_id"); | |
347 internal_group_id = strtol(internal_group_id_ptr, NULL, 10); | |
348 | |
349 g_return_if_fail(internal_group_id > 0); | |
350 | |
351 g = g_new0(gc_and_uid, 1); | |
352 g->gc = gc; | |
353 g->uid = internal_group_id; | |
354 | |
355 gaim_request_action(gc, _("QQ Qun Operation"), | |
356 _("Are you sure to exit this Qun?"), | |
357 _ | |
358 ("Note, if you are the creator, \nthis operation will eventually remove this Qun."), | |
359 1, g, 2, _("Cancel"), | |
360 G_CALLBACK(qq_do_nothing_with_gc_and_uid), | |
361 _("Go ahead"), G_CALLBACK(_qq_group_exit_with_gc_and_id)); | |
362 } |