| 36 #include "group_join.h" |
36 #include "group_join.h" |
| 37 #include "group_opt.h" |
37 #include "group_opt.h" |
| 38 #include "header_info.h" |
38 #include "header_info.h" |
| 39 #include "packet_parse.h" |
39 #include "packet_parse.h" |
| 40 #include "qq_network.h" |
40 #include "qq_network.h" |
| |
41 #include "qq_process.h" |
| 41 #include "utils.h" |
42 #include "utils.h" |
| 42 |
43 |
| 43 static int _compare_guint32(const void *a, |
44 static int _compare_guint32(const void *a, |
| 44 const void *b) |
45 const void *b) |
| 45 { |
46 { |
| 65 |
66 |
| 66 for (count = 0; members[count] != 0xffffffff; count++) {; |
67 for (count = 0; members[count] != 0xffffffff; count++) {; |
| 67 } |
68 } |
| 68 data_len = 6 + count * 4; |
69 data_len = 6 + count * 4; |
| 69 data = g_newa(guint8, data_len); |
70 data = g_newa(guint8, data_len); |
| 70 |
71 |
| 71 bytes = 0; |
72 bytes = 0; |
| 72 bytes += qq_put8(data + bytes, operation); |
73 bytes += qq_put8(data + bytes, operation); |
| 73 for (i = 0; i < count; i++) |
74 for (i = 0; i < count; i++) |
| 74 bytes += qq_put32(data + bytes, members[i]); |
75 bytes += qq_put32(data + bytes, members[i]); |
| 75 |
76 |
| 86 { |
87 { |
| 87 qq_group *group; |
88 qq_group *group; |
| 88 g_return_if_fail(g != NULL && g->gc != NULL && g->id > 0 && g->member > 0); |
89 g_return_if_fail(g != NULL && g->gc != NULL && g->id > 0 && g->member > 0); |
| 89 group = qq_room_search_id(g->gc, g->id); |
90 group = qq_room_search_id(g->gc, g->id); |
| 90 g_return_if_fail(group != NULL); |
91 g_return_if_fail(group != NULL); |
| 91 qq_send_cmd_group_auth(g->gc, group, QQ_GROUP_AUTH_REQUEST_REJECT, g->member, msg_utf8); |
92 qq_send_cmd_group_auth(g->gc, group, QQ_ROOM_AUTH_REQUEST_REJECT, g->member, msg_utf8); |
| 92 g_free(g); |
93 g_free(g); |
| 93 } |
94 } |
| 94 |
95 |
| 95 void qq_group_search_application_with_struct(group_member_opt *g) |
96 void qq_group_search_application_with_struct(group_member_opt *g) |
| 96 { |
97 { |
| 109 { |
110 { |
| 110 gchar *msg1, *msg2, *nombre; |
111 gchar *msg1, *msg2, *nombre; |
| 111 g_return_if_fail(g != NULL && g->gc != NULL && g->member > 0); |
112 g_return_if_fail(g != NULL && g->gc != NULL && g->member > 0); |
| 112 |
113 |
| 113 msg1 = g_strdup_printf(_("You rejected %d's request"), g->member); |
114 msg1 = g_strdup_printf(_("You rejected %d's request"), g->member); |
| 114 msg2 = g_strdup(_("Enter your reason:")); |
115 msg2 = g_strdup(_("Message:")); |
| 115 |
116 |
| 116 nombre = uid_to_purple_name(g->member); |
117 nombre = uid_to_purple_name(g->member); |
| 117 purple_request_input(g->gc, /* title */ NULL, msg1, msg2, |
118 purple_request_input(g->gc, /* title */ NULL, msg1, msg2, |
| 118 _("Sorry, you are not my type..."), /* multiline */ TRUE, /* masked */ FALSE, |
119 _("Sorry, you are not my style..."), /* multiline */ TRUE, /* masked */ FALSE, |
| 119 /* hint */ NULL, |
120 /* hint */ NULL, |
| 120 _("Send"), G_CALLBACK(_qq_group_reject_application_real), |
121 _("Send"), G_CALLBACK(_qq_group_reject_application_real), |
| 121 _("Cancel"), G_CALLBACK(_qq_group_do_nothing_with_struct), |
122 _("Cancel"), G_CALLBACK(_qq_group_do_nothing_with_struct), |
| 122 purple_connection_get_account(g->gc), nombre, NULL, |
123 purple_connection_get_account(g->gc), nombre, NULL, |
| 123 g); |
124 g); |
| 131 { |
132 { |
| 132 qq_group *group; |
133 qq_group *group; |
| 133 g_return_if_fail(g != NULL && g->gc != NULL && g->id > 0 && g->member > 0); |
134 g_return_if_fail(g != NULL && g->gc != NULL && g->id > 0 && g->member > 0); |
| 134 group = qq_room_search_id(g->gc, g->id); |
135 group = qq_room_search_id(g->gc, g->id); |
| 135 g_return_if_fail(group != NULL); |
136 g_return_if_fail(group != NULL); |
| 136 qq_send_cmd_group_auth(g->gc, group, QQ_GROUP_AUTH_REQUEST_APPROVE, g->member, ""); |
137 qq_send_cmd_group_auth(g->gc, group, QQ_ROOM_AUTH_REQUEST_APPROVE, g->member, ""); |
| 137 qq_group_find_or_add_member(g->gc, group, g->member); |
138 qq_group_find_or_add_member(g->gc, group, g->member); |
| 138 g_free(g); |
139 g_free(g); |
| 139 } |
140 } |
| 140 |
141 |
| 141 void qq_group_modify_members(PurpleConnection *gc, qq_group *group, guint32 *new_members) |
142 void qq_group_modify_members(PurpleConnection *gc, qq_group *group, guint32 *new_members) |
| 187 qq_group_remove_member_by_uid(group, del_members[i]); |
188 qq_group_remove_member_by_uid(group, del_members[i]); |
| 188 for (i = 0; i < add; i++) |
189 for (i = 0; i < add; i++) |
| 189 qq_group_find_or_add_member(gc, group, add_members[i]); |
190 qq_group_find_or_add_member(gc, group, add_members[i]); |
| 190 |
191 |
| 191 if (del > 0) |
192 if (del > 0) |
| 192 _qq_group_member_opt(gc, group, QQ_GROUP_MEMBER_DEL, del_members); |
193 _qq_group_member_opt(gc, group, QQ_ROOM_MEMBER_DEL, del_members); |
| 193 if (add > 0) |
194 if (add > 0) |
| 194 _qq_group_member_opt(gc, group, QQ_GROUP_MEMBER_ADD, add_members); |
195 _qq_group_member_opt(gc, group, QQ_ROOM_MEMBER_ADD, add_members); |
| 195 } |
196 } |
| 196 |
197 |
| 197 void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc) |
198 void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc) |
| 198 { |
199 { |
| 199 gint bytes; |
200 gint bytes; |
| 207 |
208 |
| 208 /* we should have its info locally */ |
209 /* we should have its info locally */ |
| 209 group = qq_room_search_id(gc, id); |
210 group = qq_room_search_id(gc, id); |
| 210 g_return_if_fail(group != NULL); |
211 g_return_if_fail(group != NULL); |
| 211 |
212 |
| 212 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify members for Qun %d\n", group->ext_id); |
213 purple_debug_info("QQ", "Succeed in modify members for room %d\n", group->ext_id); |
| 213 |
214 |
| 214 purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun member"), NULL); |
215 purple_notify_info(gc, _("QQ Qun Operation"), |
| |
216 _("You have successfully modified Qun member"), NULL); |
| 215 } |
217 } |
| 216 |
218 |
| 217 void qq_room_change_info(PurpleConnection *gc, qq_group *group) |
219 void qq_room_change_info(PurpleConnection *gc, qq_group *group) |
| 218 { |
220 { |
| 219 guint8 *data; |
221 guint8 *data; |
| 221 gint bytes; |
223 gint bytes; |
| 222 gchar *group_name, *group_desc, *notice; |
224 gchar *group_name, *group_desc, *notice; |
| 223 |
225 |
| 224 g_return_if_fail(group != NULL); |
226 g_return_if_fail(group != NULL); |
| 225 |
227 |
| 226 group_name = group->group_name_utf8 == NULL ? "" : utf8_to_qq(group->group_name_utf8, QQ_CHARSET_DEFAULT); |
228 group_name = group->title_utf8 == NULL ? "" : utf8_to_qq(group->title_utf8, QQ_CHARSET_DEFAULT); |
| 227 group_desc = group->group_desc_utf8 == NULL ? "" : utf8_to_qq(group->group_desc_utf8, QQ_CHARSET_DEFAULT); |
229 group_desc = group->desc_utf8 == NULL ? "" : utf8_to_qq(group->desc_utf8, QQ_CHARSET_DEFAULT); |
| 228 notice = group->notice_utf8 == NULL ? "" : utf8_to_qq(group->notice_utf8, QQ_CHARSET_DEFAULT); |
230 notice = group->notice_utf8 == NULL ? "" : utf8_to_qq(group->notice_utf8, QQ_CHARSET_DEFAULT); |
| 229 |
231 |
| 230 data_len = 64 + strlen(group_name) + strlen(group_desc) + strlen(notice); |
232 data_len = 64 + strlen(group_name) + strlen(group_desc) + strlen(notice); |
| 231 data = g_newa(guint8, data_len); |
233 data = g_newa(guint8, data_len); |
| 232 bytes = 0; |
234 bytes = 0; |
| 235 /* 006-006 */ |
237 /* 006-006 */ |
| 236 bytes += qq_put8(data + bytes, group->auth_type); |
238 bytes += qq_put8(data + bytes, group->auth_type); |
| 237 /* 007-008 */ |
239 /* 007-008 */ |
| 238 bytes += qq_put16(data + bytes, 0x0000); |
240 bytes += qq_put16(data + bytes, 0x0000); |
| 239 /* 009-010 */ |
241 /* 009-010 */ |
| 240 bytes += qq_put16(data + bytes, group->group_category); |
242 bytes += qq_put16(data + bytes, group->category); |
| 241 |
243 |
| 242 bytes += qq_put8(data + bytes, strlen(group_name)); |
244 bytes += qq_put8(data + bytes, strlen(group_name)); |
| 243 bytes += qq_putdata(data + bytes, (guint8 *) group_name, strlen(group_name)); |
245 bytes += qq_putdata(data + bytes, (guint8 *) group_name, strlen(group_name)); |
| 244 |
246 |
| 245 bytes += qq_put16(data + bytes, 0x0000); |
247 bytes += qq_put16(data + bytes, 0x0000); |
| 249 |
251 |
| 250 bytes += qq_put8(data + bytes, strlen(group_desc)); |
252 bytes += qq_put8(data + bytes, strlen(group_desc)); |
| 251 bytes += qq_putdata(data + bytes, (guint8 *) group_desc, strlen(group_desc)); |
253 bytes += qq_putdata(data + bytes, (guint8 *) group_desc, strlen(group_desc)); |
| 252 |
254 |
| 253 if (bytes > data_len) { |
255 if (bytes > data_len) { |
| 254 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
256 purple_debug_error("QQ", |
| 255 "Overflow in qq_room_change_info, max %d bytes, now %d bytes\n", |
257 "Overflow in qq_room_change_info, max %d bytes, now %d bytes\n", |
| 256 data_len, bytes); |
258 data_len, bytes); |
| 257 return; |
259 return; |
| 258 } |
260 } |
| 259 qq_send_room_cmd(gc, QQ_ROOM_CMD_CHANGE_INFO, group->id, data, bytes); |
261 qq_send_room_cmd(gc, QQ_ROOM_CMD_CHANGE_INFO, group->id, data, bytes); |
| 272 |
274 |
| 273 /* we should have its info locally */ |
275 /* we should have its info locally */ |
| 274 group = qq_room_search_id(gc, id); |
276 group = qq_room_search_id(gc, id); |
| 275 g_return_if_fail(group != NULL); |
277 g_return_if_fail(group != NULL); |
| 276 |
278 |
| 277 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify info for Qun %d\n", group->ext_id); |
279 purple_debug_info("QQ", "Succeed in modify info for Qun %d\n", group->ext_id); |
| 278 qq_group_refresh(gc, group); |
280 qq_group_refresh(gc, group); |
| 279 |
281 |
| 280 purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun information"), NULL); |
282 purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun information"), NULL); |
| 281 } |
283 } |
| 282 |
284 |
| 295 data = g_newa(guint8, data_len); |
297 data = g_newa(guint8, data_len); |
| 296 |
298 |
| 297 bytes = 0; |
299 bytes = 0; |
| 298 /* we create the simpleset group, only group name is given */ |
300 /* we create the simpleset group, only group name is given */ |
| 299 /* 001 */ |
301 /* 001 */ |
| 300 bytes += qq_put8(data + bytes, QQ_GROUP_TYPE_PERMANENT); |
302 bytes += qq_put8(data + bytes, QQ_ROOM_TYPE_PERMANENT); |
| 301 /* 002 */ |
303 /* 002 */ |
| 302 bytes += qq_put8(data + bytes, QQ_GROUP_AUTH_TYPE_NEED_AUTH); |
304 bytes += qq_put8(data + bytes, QQ_ROOM_AUTH_TYPE_NEED_AUTH); |
| 303 /* 003-004 */ |
305 /* 003-004 */ |
| 304 bytes += qq_put16(data + bytes, 0x0000); |
306 bytes += qq_put16(data + bytes, 0x0000); |
| 305 /* 005-006 */ |
307 /* 005-006 */ |
| 306 bytes += qq_put16(data + bytes, 0x0003); |
308 bytes += qq_put16(data + bytes, 0x0003); |
| 307 /* 007 */ |
309 /* 007 */ |
| 311 bytes += qq_put8(data + bytes, 0x00); /* no group notice */ |
313 bytes += qq_put8(data + bytes, 0x00); /* no group notice */ |
| 312 bytes += qq_put8(data + bytes, 0x00); /* no group desc */ |
314 bytes += qq_put8(data + bytes, 0x00); /* no group desc */ |
| 313 bytes += qq_put32(data + bytes, qd->uid); /* I am member of coz */ |
315 bytes += qq_put32(data + bytes, qd->uid); /* I am member of coz */ |
| 314 |
316 |
| 315 if (bytes > data_len) { |
317 if (bytes > data_len) { |
| 316 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
318 purple_debug_error("QQ", |
| 317 "Overflow in qq_room_create, max %d bytes, now %d bytes\n", |
319 "Overflow in qq_room_create, max %d bytes, now %d bytes\n", |
| 318 data_len, bytes); |
320 data_len, bytes); |
| 319 return; |
321 return; |
| 320 } |
322 } |
| 321 qq_send_room_cmd_noid(gc, QQ_ROOM_CMD_CREATE, data, bytes); |
323 qq_send_room_cmd_noid(gc, QQ_ROOM_CMD_CREATE, data, bytes); |
| 350 bytes += qq_get32(&id, data + bytes); |
352 bytes += qq_get32(&id, data + bytes); |
| 351 bytes += qq_get32(&ext_id, data + bytes); |
353 bytes += qq_get32(&ext_id, data + bytes); |
| 352 g_return_if_fail(id > 0 && ext_id); |
354 g_return_if_fail(id > 0 && ext_id); |
| 353 |
355 |
| 354 group = qq_group_create_internal_record(gc, id, ext_id, NULL); |
356 group = qq_group_create_internal_record(gc, id, ext_id, NULL); |
| 355 group->my_status = QQ_GROUP_MEMBER_STATUS_IS_ADMIN; |
357 group->my_role = QQ_ROOM_ROLE_ADMIN; |
| 356 group->creator_uid = qd->uid; |
358 group->creator_uid = qd->uid; |
| 357 qq_group_refresh(gc, group); |
359 qq_group_refresh(gc, group); |
| 358 |
360 |
| 359 qq_send_room_cmd_only(gc, QQ_ROOM_CMD_ACTIVATE, id); |
361 qq_send_room_cmd_only(gc, QQ_ROOM_CMD_ACTIVATE, id); |
| 360 qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, id); |
362 qq_room_update(gc, 0, group->id); |
| 361 |
363 |
| 362 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in create Qun, external ID %d\n", group->ext_id); |
364 purple_debug_info("QQ", "Succeed in create Qun, external ID %d\n", group->ext_id); |
| 363 |
365 |
| 364 g = g_new0(gc_and_uid, 1); |
366 g = g_new0(gc_and_uid, 1); |
| 365 g->gc = gc; |
367 g->gc = gc; |
| 366 g->uid = id; |
368 g->uid = id; |
| 367 |
369 |
| 368 purple_request_action(gc, _("QQ Qun Operation"), |
370 purple_request_action(gc, _("QQ Qun Operation"), |
| 369 _("You have successfully created a Qun"), |
371 _("You have successfully created a Qun"), |
| 370 _ |
372 _ |
| 371 ("Would you like to set up the Qun details now?"), |
373 ("Would you like to set up the detail information now?"), |
| 372 1, |
374 1, |
| 373 purple_connection_get_account(gc), NULL, NULL, |
375 purple_connection_get_account(gc), NULL, NULL, |
| 374 g, 2, |
376 g, 2, |
| 375 _("Setup"), G_CALLBACK(qq_group_setup_with_gc_and_uid), |
377 _("Setup"), G_CALLBACK(qq_group_setup_with_gc_and_uid), |
| 376 _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid)); |
378 _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid)); |
| 389 |
391 |
| 390 /* we should have its info locally */ |
392 /* we should have its info locally */ |
| 391 group = qq_room_search_id(gc, id); |
393 group = qq_room_search_id(gc, id); |
| 392 g_return_if_fail(group != NULL); |
394 g_return_if_fail(group != NULL); |
| 393 |
395 |
| 394 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in activate Qun %d\n", group->ext_id); |
396 purple_debug_info("QQ", "Succeed in activate Qun %d\n", group->ext_id); |
| 395 } |
397 } |
| 396 |
398 |
| 397 void qq_group_manage_group(PurpleConnection *gc, GHashTable *data) |
399 void qq_group_manage_group(PurpleConnection *gc, GHashTable *data) |
| 398 { |
400 { |
| 399 gchar *id_ptr; |
401 gchar *id_ptr; |
| 400 guint32 id; |
402 guint32 id; |
| 401 qq_group *group; |
403 qq_group *group; |
| 402 |
404 |
| 403 g_return_if_fail(data != NULL); |
405 g_return_if_fail(data != NULL); |
| 404 |
406 |
| 405 id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_INTERNAL_ID); |
407 id_ptr = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID); |
| 406 id = strtol(id_ptr, NULL, 10); |
408 id = strtol(id_ptr, NULL, 10); |
| 407 g_return_if_fail(id > 0); |
409 g_return_if_fail(id > 0); |
| 408 |
410 |
| 409 group = qq_room_search_id(gc, id); |
411 group = qq_room_search_id(gc, id); |
| 410 g_return_if_fail(group != NULL); |
412 g_return_if_fail(group != NULL); |