comparison libpurple/protocols/qq/buddy_opt.c @ 24091:d35672443baa

2008.10.10 - ccpaging <ccpaging(at)gmail.com> * Support part of 'buddy' protocol of QQ2007/2008
author SHiNE CsyFeK <csyfek@gmail.com>
date Tue, 28 Oct 2008 16:42:46 +0000
parents 9be95f0b9472
children 7c0a56c5fea0
comparison
equal deleted inserted replaced
24090:9be95f0b9472 24091:d35672443baa
38 #include "packet_parse.h" 38 #include "packet_parse.h"
39 #include "qq_network.h" 39 #include "qq_network.h"
40 #include "utils.h" 40 #include "utils.h"
41 41
42 #define PURPLE_GROUP_QQ_FORMAT "QQ (%s)" 42 #define PURPLE_GROUP_QQ_FORMAT "QQ (%s)"
43 #define PURPLE_GROUP_QQ_UNKNOWN "QQ Unknown" 43
44
45 #define QQ_REMOVE_BUDDY_REPLY_OK 0x00
46 #define QQ_REMOVE_SELF_REPLY_OK 0x00 44 #define QQ_REMOVE_SELF_REPLY_OK 0x00
47 #define QQ_ADD_BUDDY_AUTH_REPLY_OK 0x30 /* ASCII value of "0" */ 45 #define QQ_ADD_BUDDY_AUTH_REPLY_OK 0x30 /* ASCII value of "0" */
48 46
49 enum { 47 enum {
50 QQ_MY_AUTH_APPROVE = 0x30, /* ASCII value of "0" */ 48 QQ_MY_AUTH_APPROVE = 0x30, /* ASCII value of "0" */
55 typedef struct _qq_buddy_req { 53 typedef struct _qq_buddy_req {
56 guint32 uid; 54 guint32 uid;
57 PurpleConnection *gc; 55 PurpleConnection *gc;
58 } qq_buddy_req; 56 } qq_buddy_req;
59 57
58 PurpleGroup *qq_group_find_or_new(const gchar *group_name)
59 {
60 PurpleGroup *g;
61
62 g_return_val_if_fail(group_name != NULL, NULL);
63
64 g = purple_find_group(group_name);
65 if (g == NULL) {
66 g = purple_group_new(group_name);
67 purple_blist_add_group(g, NULL);
68 purple_debug_warning("QQ", "Add new group: %s\n", group_name);
69 }
70
71 return g;
72 }
73
74 static qq_buddy_data *qq_buddy_data_new(guint32 uid)
75 {
76 qq_buddy_data *bd = g_new0(qq_buddy_data, 1);
77 memset(bd, 0, sizeof(qq_buddy_data));
78 bd->uid = uid;
79 bd->status = QQ_BUDDY_OFFLINE;
80 return bd;
81 }
82
83 qq_buddy_data *qq_buddy_data_find(PurpleConnection *gc, guint32 uid)
84 {
85 gchar *who;
86 PurpleBuddy *buddy;
87
88 g_return_val_if_fail(gc != NULL, NULL);
89
90 who = uid_to_purple_name(uid);
91 if (who == NULL) return NULL;
92 buddy = purple_find_buddy(purple_connection_get_account(gc), who);
93 g_free(who);
94
95 if (buddy == NULL) {
96 purple_debug_error("QQ", "Can not find purple buddy of %d\n", uid);
97 return NULL;
98 }
99 if (buddy->proto_data == NULL) {
100 purple_debug_error("QQ", "Can not find buddy data of %d\n", uid);
101 return NULL;
102 }
103 return (qq_buddy_data *)buddy->proto_data;
104 }
105
106 void qq_buddy_data_free(qq_buddy_data *bd)
107 {
108 g_return_if_fail(bd != NULL);
109
110 if (bd->nickname) g_free(bd->nickname);
111 g_free(bd);
112 }
113
114 /* create purple buddy without data and display with no-auth icon */
115 PurpleBuddy *qq_buddy_new(PurpleConnection *gc, guint32 uid)
116 {
117 PurpleBuddy *buddy;
118 PurpleGroup *group;
119 gchar *who;
120 gchar *group_name;
121
122 g_return_val_if_fail(gc->account != NULL && uid != 0, NULL);
123
124 group_name = g_strdup_printf(PURPLE_GROUP_QQ_FORMAT,
125 purple_account_get_username(gc->account));
126 group = qq_group_find_or_new(group_name);
127 if (group == NULL) {
128 purple_debug_error("QQ", "Failed creating group %s\n", group_name);
129 return NULL;
130 }
131
132 who = uid_to_purple_name(uid);
133
134 purple_debug_info("QQ", "Add new purple buddy: [%s]\n", who);
135 buddy = purple_buddy_new(gc->account, who, NULL); /* alias is NULL */
136 buddy->proto_data = NULL;
137
138 g_free(who);
139
140 purple_blist_add_buddy(buddy, NULL, group, NULL);
141
142 g_free(group_name);
143
144 return buddy;
145 }
146
147 static void qq_buddy_free(PurpleBuddy *buddy)
148 {
149 g_return_if_fail(buddy);
150 if (buddy->proto_data) {
151 qq_buddy_data_free(buddy->proto_data);
152 }
153 buddy->proto_data = NULL;
154 purple_blist_remove_buddy(buddy);
155 }
156
157 PurpleBuddy *qq_buddy_find(PurpleConnection *gc, guint32 uid)
158 {
159 PurpleBuddy *buddy;
160 gchar *who;
161
162 g_return_val_if_fail(gc->account != NULL && uid != 0, NULL);
163
164 who = uid_to_purple_name(uid);
165 buddy = purple_find_buddy(gc->account, who);
166 g_free(who);
167 return buddy;
168 }
169
170 PurpleBuddy *qq_buddy_find_or_new(PurpleConnection *gc, guint32 uid)
171 {
172 PurpleBuddy *buddy;
173
174 g_return_val_if_fail(gc->account != NULL && uid != 0, NULL);
175
176 buddy = qq_buddy_find(gc, uid);
177 if (buddy == NULL) {
178 buddy = qq_buddy_new(gc, uid);
179 if (buddy == NULL) {
180 return NULL;
181 }
182 }
183
184 if (buddy->proto_data != NULL) {
185 return buddy;
186 }
187
188 buddy->proto_data = qq_buddy_data_new(uid);
189 return buddy;
190 }
191
60 /* send packet to remove a buddy from my buddy list */ 192 /* send packet to remove a buddy from my buddy list */
61 static void request_buddy_remove(PurpleConnection *gc, guint32 uid) 193 static void request_buddy_remove(PurpleConnection *gc, guint32 uid)
62 { 194 {
63 gchar uid_str[11]; 195 gchar uid_str[11];
196 gint bytes;
64 197
65 g_return_if_fail(uid > 0); 198 g_return_if_fail(uid > 0);
66 199
67 g_snprintf(uid_str, sizeof(uid_str), "%d", uid); 200 g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
68 qq_send_cmd(gc, QQ_CMD_BUDDY_REMOVE, (guint8 *) uid_str, strlen(uid_str)); 201 bytes = strlen(uid_str);
202 qq_send_cmd_mess(gc, QQ_CMD_BUDDY_REMOVE, (guint8 *) uid_str, bytes, 0, uid);
69 } 203 }
70 204
71 /* try to remove myself from someone's buddy list */ 205 /* try to remove myself from someone's buddy list */
72 static void request_buddy_remove_me(PurpleConnection *gc, guint32 uid) 206 static void request_buddy_remove_me(PurpleConnection *gc, guint32 uid)
73 { 207 {
76 210
77 g_return_if_fail(uid > 0); 211 g_return_if_fail(uid > 0);
78 212
79 bytes += qq_put32(raw_data + bytes, uid); 213 bytes += qq_put32(raw_data + bytes, uid);
80 214
81 qq_send_cmd(gc, QQ_CMD_REMOVE_ME, raw_data, bytes); 215 qq_send_cmd_mess(gc, QQ_CMD_REMOVE_ME, raw_data, bytes, 0, uid);
82 } 216 }
83 217
84 /* try to add a buddy without authentication */ 218 /* try to add a buddy without authentication */
85 static void request_buddy_add_no_auth(PurpleConnection *gc, guint32 uid) 219 static void request_buddy_add_no_auth(PurpleConnection *gc, guint32 uid)
86 { 220 {
218 } 352 }
219 353
220 /* add a buddy and send packet to QQ server 354 /* add a buddy and send packet to QQ server
221 * note that when purple load local cached buddy list into its blist 355 * note that when purple load local cached buddy list into its blist
222 * it also calls this funtion, so we have to 356 * it also calls this funtion, so we have to
223 * define qd->is_login=TRUE AFTER serv_finish_login(gc) */ 357 * define qd->is_login=TRUE AFTER LOGIN */
224 void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) 358 void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
225 { 359 {
226 qq_data *qd; 360 qq_data *qd;
227 guint32 uid; 361 guint32 uid;
228 PurpleBuddy *b; 362
363 g_return_if_fail(NULL != gc && NULL != gc->proto_data);
364 g_return_if_fail(buddy != NULL);
229 365
230 qd = (qq_data *) gc->proto_data; 366 qd = (qq_data *) gc->proto_data;
231 if (!qd->is_login) 367 if (!qd->is_login)
232 return; /* IMPORTANT ! */ 368 return; /* IMPORTANT ! */
233 369
235 if (uid > 0) { 371 if (uid > 0) {
236 request_buddy_add_no_auth(gc, uid); 372 request_buddy_add_no_auth(gc, uid);
237 return; 373 return;
238 } 374 }
239 375
240 b = purple_find_buddy(gc->account, buddy->name); 376 purple_notify_error(gc, _("QQ Buddy"), _("Add buddy"), _("Invalid QQ Number"));
241 if (b != NULL) { 377 if (buddy == NULL) {
242 purple_blist_remove_buddy(b); 378 return;
243 } 379 }
244 purple_notify_error(gc, _("QQ Buddy"), _("QQ Number Error"), _("Invalid QQ Number")); 380
245 } 381 purple_debug_info("QQ", "Remove buddy with invalid QQ number %d\n", uid);
246 382 qq_buddy_free(buddy);
247 void qq_change_buddys_group(PurpleConnection *gc, const char *who,
248 const char *old_group, const char *new_group)
249 {
250 gint uid;
251 g_return_if_fail(who != NULL);
252
253 if (strcmp(new_group, PURPLE_GROUP_QQ_UNKNOWN) == 0) {
254 if (purple_privacy_check(gc->account, who)) {
255 purple_privacy_deny(gc->account, who, TRUE, FALSE);
256 } else {
257 purple_privacy_deny_add(gc->account, who, TRUE);
258 }
259 return;
260 }
261
262 if (strcmp(old_group, PURPLE_GROUP_QQ_UNKNOWN) != 0) {
263 return;
264 }
265
266 uid = purple_name_to_uid(who);
267 g_return_if_fail(uid != 0);
268
269 purple_privacy_deny_remove(gc->account, who, TRUE);
270
271 purple_debug_info("QQ", "Add unknow buddy %d\n", uid);
272 request_buddy_add_no_auth(gc, uid);
273 } 383 }
274 384
275 static void buddy_cancel_cb(qq_buddy_req *add_req, const gchar *msg) 385 static void buddy_cancel_cb(qq_buddy_req *add_req, const gchar *msg)
276 { 386 {
277 g_return_if_fail(add_req != NULL); 387 g_return_if_fail(add_req != NULL);
288 398
289 request_buddy_add_no_auth(add_req->gc, add_req->uid); 399 request_buddy_add_no_auth(add_req->gc, add_req->uid);
290 g_free(add_req); 400 g_free(add_req);
291 } 401 }
292 402
293 static void buddy_remove_both_cb(qq_buddy_req *add_req)
294 {
295 PurpleConnection *gc;
296 qq_data *qd;
297 gchar *purple_name;
298 PurpleBuddy *buddy;
299
300 g_return_if_fail(add_req != NULL);
301 if (add_req->gc == NULL || add_req->uid == 0) {
302 g_free(add_req);
303 return;
304 }
305
306 gc = add_req->gc;
307 qd = (qq_data *) gc->proto_data;
308
309 request_buddy_remove(gc, add_req->uid);
310 request_buddy_remove_me(gc, add_req->uid);
311
312 purple_name = uid_to_purple_name(add_req->uid);
313 buddy = purple_find_buddy(gc->account, purple_name);
314 if (buddy == NULL) {
315 g_free(add_req);
316 return;
317 }
318
319 if (buddy->proto_data != NULL) {
320 qq_buddy_data_free(buddy->proto_data);
321 buddy->proto_data = NULL;
322 } else {
323 purple_debug_warning("QQ", "We have no qq_buddy_data record for %s\n", buddy->name);
324 }
325
326 purple_blist_remove_buddy(buddy);
327 g_free(add_req);
328 }
329
330 /* remove a buddy from my list and remove myself from his list */
331 /* TODO: re-enable this */
332 void qq_remove_buddy_and_me(PurpleBlistNode * node)
333 {
334 PurpleConnection *gc;
335 qq_data *qd;
336 guint32 uid;
337 qq_buddy_req *add_req;
338 PurpleBuddy *buddy;
339 const gchar *who;
340
341 g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
342
343 buddy = (PurpleBuddy *) node;
344 gc = purple_account_get_connection(buddy->account);
345 qd = (qq_data *) gc->proto_data;
346 if (!qd->is_login)
347 return;
348
349 who = buddy->name;
350 g_return_if_fail(who != NULL);
351
352 uid = purple_name_to_uid(who);
353 g_return_if_fail(uid > 0);
354
355 if (uid == qd->uid) {
356 return;
357 }
358
359 add_req = g_new0(qq_buddy_req, 1);
360 add_req->gc = gc;
361 add_req->uid = uid;
362
363 purple_request_action(gc, _("Block Buddy"),
364 "Are you sure you want to block this buddy?",
365 NULL,
366 1,
367 purple_connection_get_account(gc), NULL, NULL,
368 add_req, 2,
369 _("Cancel"), G_CALLBACK(buddy_cancel_cb),
370 _("Block"), G_CALLBACK(buddy_remove_both_cb));
371 }
372
373 /* process reply to add_buddy_auth request */ 403 /* process reply to add_buddy_auth request */
374 void qq_process_buddy_add_auth(guint8 *data, gint data_len, PurpleConnection *gc) 404 void qq_process_buddy_add_auth(guint8 *data, gint data_len, PurpleConnection *gc)
375 { 405 {
376 qq_data *qd; 406 qq_data *qd;
377 gchar **segments, *msg_utf8; 407 gchar **segments, *msg_utf8;
379 g_return_if_fail(data != NULL && data_len != 0); 409 g_return_if_fail(data != NULL && data_len != 0);
380 410
381 qd = (qq_data *) gc->proto_data; 411 qd = (qq_data *) gc->proto_data;
382 412
383 if (data[0] != QQ_ADD_BUDDY_AUTH_REPLY_OK) { 413 if (data[0] != QQ_ADD_BUDDY_AUTH_REPLY_OK) {
384 purple_debug_warning("QQ", "Failed authorizing of adding requestion\n");
385 if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) { 414 if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) {
415 purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), NULL);
386 return; 416 return;
387 } 417 }
388 msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT); 418 msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT);
389 purple_notify_error(gc, _("QQ Buddy"), _("Failed authorizing of adding requestion"), msg_utf8); 419 purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), msg_utf8);
390 g_free(msg_utf8); 420 g_free(msg_utf8);
391 } else { 421 } else {
392 qq_got_attention(gc, _("Successed authorizing of adding requestion")); 422 qq_got_attention(gc, _("Successed sending authorize"));
393 } 423 }
394 } 424 }
395 425
396 /* process the server reply for my request to remove a buddy */ 426 /* process the server reply for my request to remove a buddy */
397 void qq_process_buddy_remove(guint8 *data, gint data_len, PurpleConnection *gc) 427 void qq_process_buddy_remove(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid)
428 {
429 PurpleBuddy *buddy = NULL;
430 gchar *msg;
431
432 g_return_if_fail(data != NULL && data_len != 0);
433 g_return_if_fail(uid != 0);
434
435 buddy = qq_buddy_find(gc, uid);
436 if (data[0] != 0) {
437 msg = g_strdup_printf(_("Failed removing buddy %d"), uid);
438 purple_notify_info(gc, _("QQ Buddy"), msg, NULL);
439 if (buddy == NULL) {
440 /* Add buddy with no-auth */
441 qq_buddy_new(gc, uid);
442 }
443 } else {
444 msg = g_strdup_printf(_("Successed removing buddy %d"), uid);
445 qq_got_attention(gc, _("Successed removing budy."));
446 if (buddy != NULL) {
447 /* remove buddy again */
448 qq_buddy_free(buddy);
449 }
450 }
451 g_free(msg);
452 }
453
454 /* process the server reply for my request to remove myself from a buddy */
455 void qq_process_buddy_remove_me(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid)
398 { 456 {
399 qq_data *qd; 457 qq_data *qd;
458 gchar *msg;
400 459
401 g_return_if_fail(data != NULL && data_len != 0); 460 g_return_if_fail(data != NULL && data_len != 0);
402
403 qd = (qq_data *) gc->proto_data; 461 qd = (qq_data *) gc->proto_data;
404 462
405 if (data[0] != QQ_REMOVE_BUDDY_REPLY_OK) { 463 if (data[0] != 0) {
406 /* there is no reason return from server */ 464 msg = g_strdup_printf(_("Failed removing me from %d's buddy list"), uid);
407 purple_debug_warning("QQ", "Remove buddy fails\n"); 465 purple_notify_info(gc, _("QQ Buddy"), msg, NULL);
408 purple_notify_info(gc, _("QQ Buddy"), _("Failed:"), _("Remove buddy")); 466 } else {
409 } else { /* if reply */ 467 msg = g_strdup_printf(_("Successed removing me from %d's buddy list"), uid);
410 qq_got_attention(gc, _("Successed removing budy.")); 468 qq_got_attention(gc, msg);
411 } 469 }
412 } 470 g_free(msg);
413
414 /* process the server reply for my request to remove myself from a buddy */
415 void qq_process_buddy_remove_me(guint8 *data, gint data_len, PurpleConnection *gc)
416 {
417 qq_data *qd;
418
419 g_return_if_fail(data != NULL && data_len != 0);
420
421 qd = (qq_data *) gc->proto_data;
422
423 if (data[0] != QQ_REMOVE_SELF_REPLY_OK) {
424 /* there is no reason return from server */
425 purple_debug_warning("QQ", "Remove self fails\n");
426 purple_notify_info(gc, _("QQ Buddy"), _("Failed:"), _("Remove me from other's buddy list"));
427 } else { /* if reply */
428 qq_got_attention(gc, _("Successed removing me from other's budy list."));
429 }
430 } 471 }
431 472
432 void qq_process_buddy_add_no_auth(guint8 *data, gint data_len, guint32 uid, PurpleConnection *gc) 473 void qq_process_buddy_add_no_auth(guint8 *data, gint data_len, guint32 uid, PurpleConnection *gc)
433 { 474 {
434 qq_data *qd; 475 qq_data *qd;
435 gchar *msg, **segments, *dest_uid, *reply; 476 gchar *msg, **segments, *dest_uid, *reply;
436 PurpleBuddy *b; 477 PurpleBuddy *buddy;
437 qq_buddy_req *add_req; 478 qq_buddy_req *add_req;
438 gchar *nombre; 479 gchar *who;
439 480
440 g_return_if_fail(data != NULL && data_len != 0); 481 g_return_if_fail(data != NULL && data_len != 0);
441 482
442 qd = (qq_data *) gc->proto_data; 483 qd = (qq_data *) gc->proto_data;
443 484
444 if (uid == 0) { /* we have no record for this */ 485 if (uid == 0) { /* we have no record for this */
445 purple_debug_error("QQ", "Process buddy add, unknow id\n"); 486 purple_debug_error("QQ", "Process buddy add, unknow id\n");
446 return; 487 return;
447 } else { 488 }
448 purple_debug_info("QQ", "Process buddy add for id [%d]\n", uid); 489 purple_debug_info("QQ", "Process buddy add for id [%d]\n", uid);
449 } 490 qq_show_packet("buddy_add_no_auth", data, data_len);
450 491
451 if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) 492 if (NULL == (segments = split_data(data, data_len, "\x1f", 2)))
452 return; 493 return;
453 494
454 dest_uid = segments[0]; 495 dest_uid = segments[0];
457 purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", dest_uid); 498 purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", dest_uid);
458 g_strfreev(segments); 499 g_strfreev(segments);
459 return; 500 return;
460 } 501 }
461 502
462 if (strtol(reply, NULL, 10) > 0) { /* need auth */ 503 if (strtol(reply, NULL, 10) == 0) {
463 purple_debug_warning("QQ", "Add buddy attempt fails, need authentication\n"); 504 /* add OK */
464 nombre = uid_to_purple_name(uid);
465 b = purple_find_buddy(gc->account, nombre);
466 if (b != NULL)
467 purple_blist_remove_buddy(b);
468 add_req = g_new0(qq_buddy_req, 1);
469 add_req->gc = gc;
470 add_req->uid = uid;
471 msg = g_strdup_printf(_("%d needs authentication"), uid);
472 purple_request_input(gc, NULL, msg,
473 _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */
474 _("Would you be my friend?"),
475 TRUE, FALSE, NULL, _("Send"),
476 G_CALLBACK(request_buddy_add_auth_cb),
477 _("Cancel"), G_CALLBACK(buddy_cancel_cb),
478 purple_connection_get_account(gc), nombre, NULL,
479 add_req);
480 g_free(msg);
481 g_free(nombre);
482 } else { /* add OK */
483 qq_buddy_find_or_new(gc, uid); 505 qq_buddy_find_or_new(gc, uid);
506
484 qq_request_buddy_info(gc, uid, 0, 0); 507 qq_request_buddy_info(gc, uid, 0, 0);
485 qq_request_get_buddies_online(gc, 0, 0);
486 if (qd->client_version >= 2007) { 508 if (qd->client_version >= 2007) {
487 qq_request_get_level_2007(gc, uid); 509 qq_request_get_level_2007(gc, uid);
488 } else { 510 } else {
489 qq_request_get_level(gc, uid); 511 qq_request_get_level(gc, uid);
490 } 512 }
513 qq_request_get_buddies_online(gc, 0, 0);
491 514
492 msg = g_strdup_printf(_("Successed adding into %d's buddy list"), uid); 515 msg = g_strdup_printf(_("Successed adding into %d's buddy list"), uid);
493 qq_got_attention(gc, msg); 516 qq_got_attention(gc, msg);
494 g_free(msg); 517 g_free(msg);
495 } 518 g_strfreev(segments);
496 g_strfreev(segments); 519 return;
497 } 520 }
498 521
499 PurpleGroup *qq_group_find_or_new(const gchar *group_name) 522 /* need auth */
500 { 523 purple_debug_warning("QQ", "Failed adding buddy, need authorize\n");
501 PurpleGroup *g;
502
503 g_return_val_if_fail(group_name != NULL, NULL);
504
505 g = purple_find_group(group_name);
506 if (g == NULL) {
507 g = purple_group_new(group_name);
508 purple_blist_add_group(g, NULL);
509 purple_debug_warning("QQ", "Add new group: %s\n", group_name);
510 }
511
512 return g;
513 }
514
515 static qq_buddy_data *qq_buddy_data_new(guint32 uid)
516 {
517 qq_buddy_data *bd = g_new0(qq_buddy_data, 1);
518 memset(bd, 0, sizeof(qq_buddy_data));
519 bd->uid = uid;
520 bd->status = QQ_BUDDY_ONLINE_NORMAL;
521 return bd;
522 }
523
524 qq_buddy_data *qq_buddy_data_find(PurpleConnection *gc, guint32 uid)
525 {
526 gchar *who;
527 PurpleBuddy *buddy;
528
529 g_return_val_if_fail(gc != NULL, NULL);
530
531 who = uid_to_purple_name(uid);
532 if (who == NULL) return NULL;
533 buddy = purple_find_buddy(purple_connection_get_account(gc), who);
534 g_free(who);
535
536 if (buddy == NULL) {
537 purple_debug_error("QQ", "Can not find purple buddy of %d\n", uid);
538 return NULL;
539 }
540 if (buddy->proto_data == NULL) {
541 purple_debug_error("QQ", "Can not find buddy data of %d\n", uid);
542 return NULL;
543 }
544 return (qq_buddy_data *)buddy->proto_data;
545 }
546
547 void qq_buddy_data_free(qq_buddy_data *bd)
548 {
549 g_return_if_fail(bd != NULL);
550
551 if (bd->nickname) g_free(bd->nickname);
552 g_free(bd);
553 }
554
555 /* create purple buddy without data and display with no-auth icon */
556 PurpleBuddy *qq_buddy_new(PurpleConnection *gc, guint32 uid)
557 {
558 PurpleBuddy *buddy;
559 PurpleGroup *group;
560 gchar *who;
561 gchar *group_name;
562
563 g_return_val_if_fail(gc->account != NULL && uid != 0, NULL);
564
565 group_name = g_strdup_printf(PURPLE_GROUP_QQ_FORMAT,
566 purple_account_get_username(gc->account));
567 group = qq_group_find_or_new(group_name);
568 if (group == NULL) {
569 purple_debug_error("QQ", "Failed creating group %s\n", group_name);
570 return NULL;
571 }
572
573 who = uid_to_purple_name(uid);
574 buddy = purple_buddy_new(gc->account, who, NULL); /* alias is NULL */
575 g_free(who);
576 buddy->proto_data = NULL;
577
578 purple_blist_add_buddy(buddy, NULL, group, NULL);
579 purple_debug_info("QQ", "Add new purple buddy: [%s]\n", who);
580
581 g_free(group_name);
582
583 return buddy;
584 }
585
586 PurpleBuddy *qq_buddy_find(PurpleConnection *gc, guint32 uid)
587 {
588 PurpleBuddy *buddy;
589 gchar *who;
590
591 g_return_val_if_fail(gc->account != NULL && uid != 0, NULL);
592
593 who = uid_to_purple_name(uid);
594 buddy = purple_find_buddy(gc->account, who);
595 g_free(who);
596 return buddy;
597 }
598
599 PurpleBuddy *qq_buddy_find_or_new(PurpleConnection *gc, guint32 uid)
600 {
601 PurpleBuddy *buddy;
602
603 g_return_val_if_fail(gc->account != NULL && uid != 0, NULL);
604 524
605 buddy = qq_buddy_find(gc, uid); 525 buddy = qq_buddy_find(gc, uid);
606 if (buddy == NULL) { 526 if (buddy == NULL) {
607 buddy = qq_buddy_new(gc, uid); 527 buddy = qq_buddy_new(gc, uid);
608 if (buddy == NULL) { 528 }
609 return NULL; 529 if (buddy != NULL && buddy->proto_data != NULL) {
610 } 530 /* Not authorized now, free buddy data */
611 } 531 qq_buddy_data_free(buddy->proto_data);
612 532 buddy->proto_data = NULL;
613 if (buddy->proto_data != NULL) { 533 }
614 return buddy; 534
615 } 535 who = uid_to_purple_name(uid);
616 536 add_req = g_new0(qq_buddy_req, 1);
617 buddy->proto_data = qq_buddy_data_new(uid); 537 add_req->gc = gc;
618 return buddy; 538 add_req->uid = uid;
539 msg = g_strdup_printf(_("%d needs authentication"), uid);
540 purple_request_input(gc, _("Add buddy authorize"), msg,
541 _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */
542 _("Would you be my friend?"),
543 TRUE, FALSE, NULL, _("Send"),
544 G_CALLBACK(request_buddy_add_auth_cb),
545 _("Cancel"), G_CALLBACK(buddy_cancel_cb),
546 purple_connection_get_account(gc), who, NULL,
547 add_req);
548
549 g_free(msg);
550 g_free(who);
551 g_strfreev(segments);
619 } 552 }
620 553
621 /* remove a buddy and send packet to QQ server accordingly */ 554 /* remove a buddy and send packet to QQ server accordingly */
622 void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) 555 void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
623 { 556 {
624 qq_data *qd; 557 qq_data *qd;
625 guint32 uid; 558 guint32 uid;
626 559
627 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 560 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
628 g_return_if_fail(buddy != NULL); 561 g_return_if_fail(buddy != NULL);
562
629 qd = (qq_data *) gc->proto_data; 563 qd = (qq_data *) gc->proto_data;
564 if (!qd->is_login)
565 return;
630 566
631 uid = purple_name_to_uid(buddy->name); 567 uid = purple_name_to_uid(buddy->name);
632 if (!qd->is_login)
633 return;
634
635 if (uid > 0) { 568 if (uid > 0) {
636 request_buddy_remove(gc, uid); 569 request_buddy_remove(gc, uid);
570 request_buddy_remove_me(gc, uid);
637 } 571 }
638 572
639 if (buddy->proto_data) { 573 if (buddy->proto_data) {
640 qq_buddy_data_free(buddy->proto_data); 574 qq_buddy_data_free(buddy->proto_data);
641 buddy->proto_data = NULL; 575 buddy->proto_data = NULL;
642 } else { 576 } else {
643 purple_debug_warning("QQ", "We have no qq_buddy_data record for %s\n", buddy->name); 577 purple_debug_warning("QQ", "Empty buddy data of %s\n", buddy->name);
644 } 578 }
645 579
646 /* Do not call purple_blist_remove_buddy, 580 /* Do not call purple_blist_remove_buddy,
647 * otherwise purple segmentation fault */ 581 * otherwise purple segmentation fault */
648 } 582 }
767 701
768 /* you are rejected by the person */ 702 /* you are rejected by the person */
769 static void server_buddy_rejected_me(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) 703 static void server_buddy_rejected_me(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8)
770 { 704 {
771 gchar *message, *reason; 705 gchar *message, *reason;
706 guint32 uid;
707 PurpleBuddy *buddy;
772 708
773 g_return_if_fail(from != NULL && to != NULL); 709 g_return_if_fail(from != NULL && to != NULL);
774 710
775 message = g_strdup_printf(_("Requestion rejected by %s"), from); 711 message = g_strdup_printf(_("Requestion rejected by %s"), from);
776 reason = g_strdup_printf(_("Message: %s"), msg_utf8); 712 reason = g_strdup_printf(_("Message: %s"), msg_utf8);
777 713
778 purple_notify_info(gc, _("QQ Buddy"), message, reason); 714 purple_notify_info(gc, _("QQ Buddy"), message, reason);
779 g_free(message); 715 g_free(message);
780 g_free(reason); 716 g_free(reason);
717
718 uid = strtol(from, NULL, 10);
719 g_return_if_fail(uid != 0);
720
721 buddy = qq_buddy_find(gc, uid);
722 if (buddy != NULL && buddy->proto_data != NULL) {
723 /* Not authorized now, free buddy data */
724 qq_buddy_data_free(buddy->proto_data);
725 buddy->proto_data = NULL;
726 }
781 } 727 }
782 728
783 void qq_process_buddy_from_server(PurpleConnection *gc, int funct, 729 void qq_process_buddy_from_server(PurpleConnection *gc, int funct,
784 gchar *from, gchar *to, gchar *msg_utf8) 730 gchar *from, gchar *to, gchar *msg_utf8)
785 { 731 {