| 1 /** |
|
| 2 * @file group_opt.c |
|
| 3 * |
|
| 4 * purple |
|
| 5 * |
|
| 6 * Purple 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
|
| 23 */ |
|
| 24 |
|
| 25 #include "qq.h" |
|
| 26 |
|
| 27 #include "debug.h" |
|
| 28 #include "notify.h" |
|
| 29 #include "request.h" |
|
| 30 |
|
| 31 #include "buddy_info.h" |
|
| 32 #include "char_conv.h" |
|
| 33 #include "group_internal.h" |
|
| 34 #include "group_info.h" |
|
| 35 #include "group_join.h" |
|
| 36 #include "group_im.h" |
|
| 37 #include "group_opt.h" |
|
| 38 #include "qq_define.h" |
|
| 39 #include "packet_parse.h" |
|
| 40 #include "qq_network.h" |
|
| 41 #include "qq_process.h" |
|
| 42 #include "utils.h" |
|
| 43 |
|
| 44 static int _compare_guint32(const void *a, |
|
| 45 const void *b) |
|
| 46 { |
|
| 47 const guint32 *x = a; |
|
| 48 const guint32 *y = b; |
|
| 49 return (*x - *y); |
|
| 50 } |
|
| 51 |
|
| 52 static void _sort(guint32 *list) |
|
| 53 { |
|
| 54 gint i; |
|
| 55 for (i = 0; list[i] < 0xffffffff; i++) {; |
|
| 56 } |
|
| 57 qsort (list, i, sizeof (guint32), _compare_guint32); |
|
| 58 } |
|
| 59 |
|
| 60 static void _qq_group_member_opt(PurpleConnection *gc, qq_room_data *rmd, gint operation, guint32 *members) |
|
| 61 { |
|
| 62 guint8 *data; |
|
| 63 gint i, count, data_len; |
|
| 64 gint bytes; |
|
| 65 g_return_if_fail(members != NULL); |
|
| 66 |
|
| 67 for (count = 0; members[count] != 0xffffffff; count++) {; |
|
| 68 } |
|
| 69 data_len = 6 + count * 4; |
|
| 70 data = g_newa(guint8, data_len); |
|
| 71 |
|
| 72 bytes = 0; |
|
| 73 bytes += qq_put8(data + bytes, operation); |
|
| 74 for (i = 0; i < count; i++) |
|
| 75 bytes += qq_put32(data + bytes, members[i]); |
|
| 76 |
|
| 77 qq_send_room_cmd(gc, QQ_ROOM_CMD_MEMBER_OPT, rmd->id, data, bytes); |
|
| 78 } |
|
| 79 |
|
| 80 static void room_req_cancel_cb(qq_room_req *add_req) |
|
| 81 { |
|
| 82 if (add_req != NULL) |
|
| 83 g_free(add_req); |
|
| 84 } |
|
| 85 |
|
| 86 static void member_join_authorize_cb(gpointer data) |
|
| 87 { |
|
| 88 qq_room_req *add_req = (qq_room_req *)data; |
|
| 89 qq_room_data *rmd; |
|
| 90 g_return_if_fail(add_req != NULL && add_req->gc != NULL); |
|
| 91 g_return_if_fail(add_req->id > 0 && add_req->member > 0); |
|
| 92 rmd = qq_room_data_find(add_req->gc, add_req->id); |
|
| 93 g_return_if_fail(rmd != NULL); |
|
| 94 |
|
| 95 qq_send_cmd_group_auth(add_req->gc, rmd, QQ_ROOM_AUTH_REQUEST_APPROVE, add_req->member, ""); |
|
| 96 qq_room_buddy_find_or_new(add_req->gc, rmd, add_req->member); |
|
| 97 g_free(add_req); |
|
| 98 } |
|
| 99 |
|
| 100 static void member_join_deny_reason_cb(qq_room_req *add_req, gchar *msg_utf8) |
|
| 101 { |
|
| 102 qq_room_data *rmd; |
|
| 103 g_return_if_fail(add_req != NULL && add_req->gc != NULL); |
|
| 104 g_return_if_fail(add_req->id > 0 && add_req->member > 0); |
|
| 105 rmd = qq_room_data_find(add_req->gc, add_req->id); |
|
| 106 g_return_if_fail(rmd != NULL); |
|
| 107 qq_send_cmd_group_auth(add_req->gc, rmd, QQ_ROOM_AUTH_REQUEST_REJECT, add_req->member, msg_utf8); |
|
| 108 g_free(add_req); |
|
| 109 } |
|
| 110 |
|
| 111 static void member_join_deny_noreason_cb(qq_room_req *add_req, gchar *msg_utf8) |
|
| 112 { |
|
| 113 member_join_deny_reason_cb(add_req, NULL); |
|
| 114 } |
|
| 115 |
|
| 116 static void member_join_deny_cb(gpointer data) |
|
| 117 { |
|
| 118 qq_room_req *add_req = (qq_room_req *)data; |
|
| 119 gchar *who; |
|
| 120 g_return_if_fail(add_req != NULL && add_req->gc != NULL); |
|
| 121 g_return_if_fail(add_req->id > 0 && add_req->member > 0); |
|
| 122 |
|
| 123 who = uid_to_purple_name(add_req->member); |
|
| 124 purple_request_input(add_req->gc, NULL, _("Authorization denied message:"), |
|
| 125 NULL, _("Sorry, you are not our style"), TRUE, FALSE, NULL, |
|
| 126 _("OK"), G_CALLBACK(member_join_deny_reason_cb), |
|
| 127 _("Cancel"), G_CALLBACK(member_join_deny_noreason_cb), |
|
| 128 purple_connection_get_account(add_req->gc), who, NULL, |
|
| 129 add_req); |
|
| 130 g_free(who); |
|
| 131 } |
|
| 132 |
|
| 133 void qq_group_modify_members(PurpleConnection *gc, qq_room_data *rmd, guint32 *new_members) |
|
| 134 { |
|
| 135 guint32 *old_members, *del_members, *add_members; |
|
| 136 qq_buddy_data *bd; |
|
| 137 qq_data *qd; |
|
| 138 gint i = 0, old = 0, new = 0, del = 0, add = 0; |
|
| 139 GList *list; |
|
| 140 |
|
| 141 g_return_if_fail(rmd != NULL); |
|
| 142 qd = (qq_data *) gc->proto_data; |
|
| 143 if (new_members[0] == 0xffffffff) |
|
| 144 return; |
|
| 145 |
|
| 146 old_members = g_newa(guint32, QQ_QUN_MEMBER_MAX); |
|
| 147 del_members = g_newa(guint32, QQ_QUN_MEMBER_MAX); |
|
| 148 add_members = g_newa(guint32, QQ_QUN_MEMBER_MAX); |
|
| 149 |
|
| 150 /* construct the old member list */ |
|
| 151 list = rmd->members; |
|
| 152 while (list != NULL) { |
|
| 153 bd = (qq_buddy_data *) list->data; |
|
| 154 if (bd != NULL) |
|
| 155 old_members[i++] = bd->uid; |
|
| 156 list = list->next; |
|
| 157 } |
|
| 158 old_members[i] = 0xffffffff; /* this is the end */ |
|
| 159 |
|
| 160 /* sort to speed up making del_members and add_members list */ |
|
| 161 _sort(old_members); |
|
| 162 _sort(new_members); |
|
| 163 |
|
| 164 for (old = 0, new = 0; old_members[old] < 0xffffffff || new_members[new] < 0xffffffff;) { |
|
| 165 if (old_members[old] > new_members[new]) { |
|
| 166 add_members[add++] = new_members[new++]; |
|
| 167 } else if (old_members[old] < new_members[new]) { |
|
| 168 del_members[del++] = old_members[old++]; |
|
| 169 } else { |
|
| 170 if (old_members[old] < 0xffffffff) |
|
| 171 old++; |
|
| 172 if (new_members[new] < 0xffffffff) |
|
| 173 new++; |
|
| 174 } |
|
| 175 } |
|
| 176 del_members[del] = add_members[add] = 0xffffffff; |
|
| 177 |
|
| 178 for (i = 0; i < del; i++) |
|
| 179 qq_room_buddy_remove(rmd, del_members[i]); |
|
| 180 for (i = 0; i < add; i++) |
|
| 181 qq_room_buddy_find_or_new(gc, rmd, add_members[i]); |
|
| 182 |
|
| 183 if (del > 0) |
|
| 184 _qq_group_member_opt(gc, rmd, QQ_ROOM_MEMBER_DEL, del_members); |
|
| 185 if (add > 0) |
|
| 186 _qq_group_member_opt(gc, rmd, QQ_ROOM_MEMBER_ADD, add_members); |
|
| 187 } |
|
| 188 |
|
| 189 void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc) |
|
| 190 { |
|
| 191 gint bytes; |
|
| 192 guint32 id; |
|
| 193 time_t now = time(NULL); |
|
| 194 qq_room_data *rmd; |
|
| 195 g_return_if_fail(data != NULL); |
|
| 196 |
|
| 197 bytes = 0; |
|
| 198 bytes += qq_get32(&id, data + bytes); |
|
| 199 g_return_if_fail(id > 0); |
|
| 200 |
|
| 201 /* we should have its info locally */ |
|
| 202 rmd = qq_room_data_find(gc, id); |
|
| 203 g_return_if_fail(rmd != NULL); |
|
| 204 |
|
| 205 purple_debug_info("QQ", "Succeed in modify members for room %u\n", rmd->ext_id); |
|
| 206 |
|
| 207 qq_room_got_chat_in(gc, id, 0, _("Successfully changed Qun members"), now); |
|
| 208 } |
|
| 209 |
|
| 210 void qq_room_change_info(PurpleConnection *gc, qq_room_data *rmd) |
|
| 211 { |
|
| 212 guint8 data[MAX_PACKET_SIZE - 16]; |
|
| 213 gint bytes; |
|
| 214 |
|
| 215 g_return_if_fail(rmd != NULL); |
|
| 216 |
|
| 217 bytes = 0; |
|
| 218 /* 005-005 */ |
|
| 219 bytes += qq_put8(data + bytes, 0x01); |
|
| 220 /* 006-006 */ |
|
| 221 bytes += qq_put8(data + bytes, rmd->auth_type); |
|
| 222 /* 007-008 */ |
|
| 223 bytes += qq_put16(data + bytes, 0x0000); |
|
| 224 /* 009-010 */ |
|
| 225 bytes += qq_put16(data + bytes, rmd->category); |
|
| 226 |
|
| 227 bytes += qq_put_vstr(data + bytes, rmd->title_utf8, QQ_CHARSET_DEFAULT); |
|
| 228 |
|
| 229 bytes += qq_put16(data + bytes, 0x0000); |
|
| 230 |
|
| 231 bytes += qq_put_vstr(data + bytes, rmd->notice_utf8, QQ_CHARSET_DEFAULT); |
|
| 232 bytes += qq_put_vstr(data + bytes, rmd->desc_utf8, QQ_CHARSET_DEFAULT); |
|
| 233 |
|
| 234 qq_send_room_cmd(gc, QQ_ROOM_CMD_CHANGE_INFO, rmd->id, data, bytes); |
|
| 235 } |
|
| 236 |
|
| 237 void qq_group_process_modify_info_reply(guint8 *data, gint len, PurpleConnection *gc) |
|
| 238 { |
|
| 239 gint bytes; |
|
| 240 guint32 id; |
|
| 241 time_t now = time(NULL); |
|
| 242 |
|
| 243 g_return_if_fail(data != NULL); |
|
| 244 |
|
| 245 bytes = 0; |
|
| 246 bytes += qq_get32(&id, data + bytes); |
|
| 247 g_return_if_fail(id > 0); |
|
| 248 |
|
| 249 purple_debug_info("QQ", "Successfully modified room info of %u\n", id); |
|
| 250 |
|
| 251 qq_room_got_chat_in(gc, id, 0, _("Successfully changed Qun information"), now); |
|
| 252 } |
|
| 253 |
|
| 254 /* we create a very simple room first, and then let the user to modify */ |
|
| 255 void qq_create_room(PurpleConnection *gc, const gchar *name) |
|
| 256 { |
|
| 257 guint8 *data; |
|
| 258 gint data_len; |
|
| 259 gint bytes; |
|
| 260 qq_data *qd; |
|
| 261 g_return_if_fail(name != NULL); |
|
| 262 |
|
| 263 qd = (qq_data *) gc->proto_data; |
|
| 264 |
|
| 265 data_len = 64 + strlen(name); |
|
| 266 data = g_newa(guint8, data_len); |
|
| 267 |
|
| 268 bytes = 0; |
|
| 269 /* we create the simpleset group, only group name is given */ |
|
| 270 /* 001 */ |
|
| 271 bytes += qq_put8(data + bytes, QQ_ROOM_TYPE_PERMANENT); |
|
| 272 /* 002 */ |
|
| 273 bytes += qq_put8(data + bytes, QQ_ROOM_AUTH_TYPE_NEED_AUTH); |
|
| 274 /* 003-004 */ |
|
| 275 bytes += qq_put16(data + bytes, 0x0000); |
|
| 276 /* 005-006 */ |
|
| 277 bytes += qq_put16(data + bytes, 0x0003); |
|
| 278 /* 007 */ |
|
| 279 bytes += qq_put8(data + bytes, strlen(name)); |
|
| 280 bytes += qq_putdata(data + bytes, (guint8 *) name, strlen(name)); |
|
| 281 bytes += qq_put16(data + bytes, 0x0000); |
|
| 282 bytes += qq_put8(data + bytes, 0x00); /* no group notice */ |
|
| 283 bytes += qq_put8(data + bytes, 0x00); /* no group desc */ |
|
| 284 bytes += qq_put32(data + bytes, qd->uid); /* I am member of coz */ |
|
| 285 |
|
| 286 if (bytes > data_len) { |
|
| 287 purple_debug_error("QQ", |
|
| 288 "Overflow in qq_room_create, max %d bytes, now %d bytes\n", |
|
| 289 data_len, bytes); |
|
| 290 return; |
|
| 291 } |
|
| 292 qq_send_room_cmd_noid(gc, QQ_ROOM_CMD_CREATE, data, bytes); |
|
| 293 } |
|
| 294 |
|
| 295 static void room_create_cb(qq_room_req *add_req) |
|
| 296 { |
|
| 297 qq_room_data *rmd; |
|
| 298 g_return_if_fail(add_req != NULL); |
|
| 299 if (add_req->gc == NULL || add_req->id == 0) { |
|
| 300 g_free(add_req); |
|
| 301 return; |
|
| 302 } |
|
| 303 |
|
| 304 rmd = qq_room_data_find(add_req->gc, add_req->id); |
|
| 305 if (rmd == NULL) { |
|
| 306 g_free(add_req); |
|
| 307 return; |
|
| 308 } |
|
| 309 |
|
| 310 /* TODO insert UI code here */ |
|
| 311 /* qq_group_detail_window_show(g->gc, rmd); */ |
|
| 312 g_free(add_req); |
|
| 313 } |
|
| 314 |
|
| 315 void qq_group_process_create_group_reply(guint8 *data, gint len, PurpleConnection *gc) |
|
| 316 { |
|
| 317 gint bytes; |
|
| 318 guint32 id, ext_id; |
|
| 319 qq_room_data *rmd; |
|
| 320 qq_room_req *add_req; |
|
| 321 qq_data *qd; |
|
| 322 |
|
| 323 g_return_if_fail(data != NULL); |
|
| 324 g_return_if_fail(gc->proto_data != NULL); |
|
| 325 qd = (qq_data *) gc->proto_data; |
|
| 326 |
|
| 327 bytes = 0; |
|
| 328 bytes += qq_get32(&id, data + bytes); |
|
| 329 bytes += qq_get32(&ext_id, data + bytes); |
|
| 330 g_return_if_fail(id > 0 && ext_id); |
|
| 331 |
|
| 332 qq_room_find_or_new(gc, id, ext_id); |
|
| 333 rmd = qq_room_data_find(gc, id); |
|
| 334 g_return_if_fail(rmd != NULL); |
|
| 335 |
|
| 336 rmd->my_role = QQ_ROOM_ROLE_ADMIN; |
|
| 337 rmd->creator_uid = qd->uid; |
|
| 338 |
|
| 339 qq_send_room_cmd_only(gc, QQ_ROOM_CMD_ACTIVATE, id); |
|
| 340 qq_update_room(gc, 0, rmd->id); |
|
| 341 |
|
| 342 purple_debug_info("QQ", "Succeed in create Qun, ext id %u\n", rmd->ext_id); |
|
| 343 |
|
| 344 add_req = g_new0(qq_room_req, 1); |
|
| 345 add_req->gc = gc; |
|
| 346 add_req->id = id; |
|
| 347 |
|
| 348 purple_request_action(gc, _("QQ Qun Operation"), |
|
| 349 _("You have successfully created a Qun"), |
|
| 350 _("Would you like to set up detailed information now?"), |
|
| 351 1, |
|
| 352 purple_connection_get_account(gc), NULL, NULL, |
|
| 353 add_req, 2, |
|
| 354 _("Setup"), G_CALLBACK(room_create_cb), |
|
| 355 _("Cancel"), G_CALLBACK(room_req_cancel_cb)); |
|
| 356 } |
|
| 357 |
|
| 358 void qq_group_process_activate_group_reply(guint8 *data, gint len, PurpleConnection *gc) |
|
| 359 { |
|
| 360 gint bytes; |
|
| 361 guint32 id; |
|
| 362 qq_room_data *rmd; |
|
| 363 g_return_if_fail(data != NULL); |
|
| 364 |
|
| 365 bytes = 0; |
|
| 366 bytes += qq_get32(&id, data + bytes); |
|
| 367 g_return_if_fail(id > 0); |
|
| 368 |
|
| 369 /* we should have its info locally */ |
|
| 370 rmd = qq_room_data_find(gc, id); |
|
| 371 g_return_if_fail(rmd != NULL); |
|
| 372 |
|
| 373 purple_debug_info("QQ", "Succeed in activate Qun %u\n", rmd->ext_id); |
|
| 374 } |
|
| 375 |
|
| 376 void qq_group_manage_group(PurpleConnection *gc, GHashTable *data) |
|
| 377 { |
|
| 378 gchar *id_ptr; |
|
| 379 guint32 id; |
|
| 380 qq_room_data *rmd; |
|
| 381 |
|
| 382 g_return_if_fail(data != NULL); |
|
| 383 |
|
| 384 id_ptr = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID); |
|
| 385 id = strtoul(id_ptr, NULL, 10); |
|
| 386 g_return_if_fail(id > 0); |
|
| 387 |
|
| 388 rmd = qq_room_data_find(gc, id); |
|
| 389 g_return_if_fail(rmd != NULL); |
|
| 390 |
|
| 391 /* XXX insert UI code here */ |
|
| 392 /* qq_group_detail_window_show(gc, rmd); */ |
|
| 393 } |
|
| 394 |
|
| 395 /* receive an application to join the group */ |
|
| 396 void qq_process_room_buddy_request_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc) |
|
| 397 { |
|
| 398 guint32 ext_id, member_id; |
|
| 399 guint8 type8; |
|
| 400 gchar *msg, *reason; |
|
| 401 qq_room_req *add_req; |
|
| 402 gchar *who; |
|
| 403 gint bytes = 0; |
|
| 404 qq_room_data *rmd; |
|
| 405 time_t now = time(NULL); |
|
| 406 |
|
| 407 g_return_if_fail(id > 0 && data != NULL && len > 0); |
|
| 408 |
|
| 409 /* FIXME: check length here */ |
|
| 410 |
|
| 411 bytes += qq_get32(&ext_id, data + bytes); |
|
| 412 bytes += qq_get8(&type8, data + bytes); |
|
| 413 bytes += qq_get32(&member_id, data + bytes); |
|
| 414 |
|
| 415 g_return_if_fail(ext_id > 0 && member_id > 0); |
|
| 416 |
|
| 417 bytes += qq_get_vstr(&reason, QQ_CHARSET_DEFAULT, data + bytes); |
|
| 418 |
|
| 419 purple_debug_info("QQ", "%u requested to join room, ext id %u\n", member_id, ext_id); |
|
| 420 |
|
| 421 rmd = qq_room_data_find(gc, id); |
|
| 422 g_return_if_fail(rmd != NULL); |
|
| 423 if (qq_room_buddy_find(rmd, member_id)) { |
|
| 424 purple_debug_info("QQ", "Approve join, buddy joined before\n"); |
|
| 425 msg = g_strdup_printf(_("%u requested to join Qun %u for %s"), |
|
| 426 member_id, ext_id, reason); |
|
| 427 qq_room_got_chat_in(gc, id, 0, msg, now); |
|
| 428 qq_send_cmd_group_auth(gc, rmd, QQ_ROOM_AUTH_REQUEST_APPROVE, member_id, ""); |
|
| 429 g_free(msg); |
|
| 430 g_free(reason); |
|
| 431 return; |
|
| 432 } |
|
| 433 |
|
| 434 if (purple_prefs_get_bool("/plugins/prpl/qq/auto_get_authorize_info")) { |
|
| 435 qq_request_buddy_info(gc, member_id, 0, QQ_BUDDY_INFO_DISPLAY); |
|
| 436 } |
|
| 437 who = uid_to_purple_name(member_id); |
|
| 438 msg = g_strdup_printf(_("%u request to join Qun %u"), member_id, ext_id); |
|
| 439 |
|
| 440 add_req = g_new0(qq_room_req, 1); |
|
| 441 add_req->gc = gc; |
|
| 442 add_req->id = id; |
|
| 443 add_req->member = member_id; |
|
| 444 |
|
| 445 purple_request_action(gc, _("QQ Qun Operation"), |
|
| 446 msg, reason, |
|
| 447 PURPLE_DEFAULT_ACTION_NONE, |
|
| 448 purple_connection_get_account(gc), who, NULL, |
|
| 449 add_req, 2, |
|
| 450 _("Deny"), G_CALLBACK(member_join_deny_cb), |
|
| 451 _("Authorize"), G_CALLBACK(member_join_authorize_cb)); |
|
| 452 |
|
| 453 g_free(who); |
|
| 454 g_free(msg); |
|
| 455 g_free(reason); |
|
| 456 } |
|
| 457 |
|
| 458 /* the request to join a group is rejected */ |
|
| 459 void qq_process_room_buddy_rejected(guint8 *data, gint len, guint32 id, PurpleConnection *gc) |
|
| 460 { |
|
| 461 guint32 ext_id, admin_uid; |
|
| 462 guint8 type8; |
|
| 463 gchar *msg, *reason; |
|
| 464 qq_room_data *rmd; |
|
| 465 gint bytes; |
|
| 466 |
|
| 467 g_return_if_fail(data != NULL && len > 0); |
|
| 468 |
|
| 469 /* FIXME: check length here */ |
|
| 470 bytes = 0; |
|
| 471 bytes += qq_get32(&ext_id, data + bytes); |
|
| 472 bytes += qq_get8(&type8, data + bytes); |
|
| 473 bytes += qq_get32(&admin_uid, data + bytes); |
|
| 474 |
|
| 475 g_return_if_fail(ext_id > 0 && admin_uid > 0); |
|
| 476 |
|
| 477 bytes += qq_get_vstr(&reason, QQ_CHARSET_DEFAULT, data + bytes); |
|
| 478 |
|
| 479 msg = g_strdup_printf |
|
| 480 (_("Failed to join Qun %u, operated by admin %u"), ext_id, admin_uid); |
|
| 481 |
|
| 482 purple_notify_warning(gc, _("QQ Qun Operation"), msg, reason); |
|
| 483 |
|
| 484 qq_room_find_or_new(gc, id, ext_id); |
|
| 485 rmd = qq_room_data_find(gc, id); |
|
| 486 if (rmd != NULL) { |
|
| 487 rmd->my_role = QQ_ROOM_ROLE_NO; |
|
| 488 } |
|
| 489 |
|
| 490 g_free(msg); |
|
| 491 g_free(reason); |
|
| 492 } |
|
| 493 |
|
| 494 /* the request to join a group is approved */ |
|
| 495 void qq_process_room_buddy_approved(guint8 *data, gint len, guint32 id, PurpleConnection *gc) |
|
| 496 { |
|
| 497 guint32 ext_id, admin_uid; |
|
| 498 guint8 type8; |
|
| 499 gchar *msg, *reason; |
|
| 500 qq_room_data *rmd; |
|
| 501 gint bytes; |
|
| 502 time_t now; |
|
| 503 |
|
| 504 g_return_if_fail(data != NULL && len > 0); |
|
| 505 |
|
| 506 /* FIXME: check length here */ |
|
| 507 bytes = 0; |
|
| 508 bytes += qq_get32(&ext_id, data + bytes); |
|
| 509 bytes += qq_get8(&type8, data + bytes); |
|
| 510 bytes += qq_get32(&admin_uid, data + bytes); |
|
| 511 |
|
| 512 g_return_if_fail(ext_id > 0 && admin_uid > 0); |
|
| 513 /* it is also a "无" here, so do not display */ |
|
| 514 bytes += qq_get_vstr(&reason, QQ_CHARSET_DEFAULT, data + bytes); |
|
| 515 |
|
| 516 qq_room_find_or_new(gc, id, ext_id); |
|
| 517 rmd = qq_room_data_find(gc, id); |
|
| 518 if (rmd != NULL) { |
|
| 519 rmd->my_role = QQ_ROOM_ROLE_YES; |
|
| 520 } |
|
| 521 |
|
| 522 msg = g_strdup_printf(_("<b>Joining Qun %u is approved by admin %u for %s</b>"), |
|
| 523 ext_id, admin_uid, reason); |
|
| 524 now = time(NULL); |
|
| 525 qq_room_got_chat_in(gc, id, 0, msg, now); |
|
| 526 |
|
| 527 g_free(msg); |
|
| 528 g_free(reason); |
|
| 529 } |
|
| 530 |
|
| 531 /* process the packet when removed from a group */ |
|
| 532 void qq_process_room_buddy_removed(guint8 *data, gint len, guint32 id, PurpleConnection *gc) |
|
| 533 { |
|
| 534 guint32 ext_id, uid; |
|
| 535 guint8 type8; |
|
| 536 gchar *msg; |
|
| 537 qq_room_data *rmd; |
|
| 538 gint bytes = 0; |
|
| 539 time_t now = time(NULL); |
|
| 540 |
|
| 541 g_return_if_fail(data != NULL && len > 0); |
|
| 542 |
|
| 543 /* FIXME: check length here */ |
|
| 544 bytes = 0; |
|
| 545 bytes += qq_get32(&ext_id, data + bytes); |
|
| 546 bytes += qq_get8(&type8, data + bytes); |
|
| 547 bytes += qq_get32(&uid, data + bytes); |
|
| 548 |
|
| 549 g_return_if_fail(ext_id > 0 && uid > 0); |
|
| 550 |
|
| 551 qq_room_find_or_new(gc, id, ext_id); |
|
| 552 rmd = qq_room_data_find(gc, id); |
|
| 553 if (rmd != NULL) { |
|
| 554 rmd->my_role = QQ_ROOM_ROLE_NO; |
|
| 555 } |
|
| 556 |
|
| 557 msg = g_strdup_printf(_("<b>Removed buddy %u.</b>"), uid); |
|
| 558 qq_room_got_chat_in(gc, id, 0, msg, now); |
|
| 559 g_free(msg); |
|
| 560 } |
|
| 561 |
|
| 562 /* process the packet when added to a group */ |
|
| 563 void qq_process_room_buddy_joined(guint8 *data, gint len, guint32 id, PurpleConnection *gc) |
|
| 564 { |
|
| 565 guint32 ext_id, uid; |
|
| 566 guint8 type8; |
|
| 567 qq_room_data *rmd; |
|
| 568 gint bytes; |
|
| 569 gchar *msg; |
|
| 570 time_t now = time(NULL); |
|
| 571 |
|
| 572 g_return_if_fail(data != NULL && len > 0); |
|
| 573 |
|
| 574 /* FIXME: check length here */ |
|
| 575 bytes = 0; |
|
| 576 bytes += qq_get32(&ext_id, data + bytes); |
|
| 577 bytes += qq_get8(&type8, data + bytes); |
|
| 578 bytes += qq_get32(&uid, data + bytes); |
|
| 579 |
|
| 580 g_return_if_fail(ext_id > 0 && id > 0); |
|
| 581 |
|
| 582 qq_room_find_or_new(gc, id, ext_id); |
|
| 583 rmd = qq_room_data_find(gc, id); |
|
| 584 g_return_if_fail(rmd != NULL); |
|
| 585 |
|
| 586 rmd->my_role = QQ_ROOM_ROLE_YES; |
|
| 587 |
|
| 588 qq_update_room(gc, 0, rmd->id); |
|
| 589 |
|
| 590 msg = g_strdup_printf(_("<b>New buddy %u joined.</b>"), uid); |
|
| 591 qq_room_got_chat_in(gc, id, 0, msg, now); |
|
| 592 g_free(msg); |
|
| 593 } |
|
| 594 |
|