Mercurial > pidgin
comparison libpurple/protocols/qq/buddy_opt.c @ 24162:f4f29fac96c6
2008.10.20 - ccpaging <ccpaging(at)gmail.com>
* Support incoming authorization of 'buddy_adding' protocol of QQ2007/2008
author | SHiNE CsyFeK <csyfek@gmail.com> |
---|---|
date | Tue, 28 Oct 2008 16:45:10 +0000 |
parents | 7c0a56c5fea0 |
children | 7f5433ffbf8d |
comparison
equal
deleted
inserted
replaced
24161:7c0a56c5fea0 | 24162:f4f29fac96c6 |
---|---|
48 QQ_MY_AUTH_REJECT = 0x31, /* ASCII value of "1" */ | 48 QQ_MY_AUTH_REJECT = 0x31, /* ASCII value of "1" */ |
49 QQ_MY_AUTH_REQUEST = 0x32, /* ASCII value of "2" */ | 49 QQ_MY_AUTH_REQUEST = 0x32, /* ASCII value of "2" */ |
50 }; | 50 }; |
51 | 51 |
52 typedef struct _qq_buddy_req { | 52 typedef struct _qq_buddy_req { |
53 PurpleConnection *gc; | |
53 guint32 uid; | 54 guint32 uid; |
54 PurpleConnection *gc; | 55 guint8 *auth; |
56 guint8 auth_len; | |
55 } qq_buddy_req; | 57 } qq_buddy_req; |
58 | |
59 void buddy_add_authorize_input(PurpleConnection *gc, guint32 uid, | |
60 guint8 *auth, guint8 auth_len); | |
61 | |
62 static void buddy_add_req_free(qq_buddy_req *add_req) | |
63 { | |
64 g_return_if_fail(add_req != NULL); | |
65 if (add_req->auth) g_free(add_req->auth); | |
66 g_free(add_req); | |
67 } | |
56 | 68 |
57 PurpleGroup *qq_group_find_or_new(const gchar *group_name) | 69 PurpleGroup *qq_group_find_or_new(const gchar *group_name) |
58 { | 70 { |
59 PurpleGroup *g; | 71 PurpleGroup *g; |
60 | 72 |
268 } | 280 } |
269 | 281 |
270 if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_REMOVE_BUDDY) { | 282 if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_REMOVE_BUDDY) { |
271 g_return_if_fail(auth != NULL && auth_len > 0); | 283 g_return_if_fail(auth != NULL && auth_len > 0); |
272 request_buddy_remove_2007(gc, uid, auth, auth_len); | 284 request_buddy_remove_2007(gc, uid, auth, auth_len); |
285 return; | |
273 } | 286 } |
274 if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_ADD_BUDDY) { | 287 if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_ADD_BUDDY) { |
288 buddy_add_authorize_input(gc, uid, auth, auth_len); | |
289 return; | |
275 } | 290 } |
276 purple_debug_info("QQ", "Got auth info cmd 0x%x, sub 0x%x, reply 0x%x\n", | 291 purple_debug_info("QQ", "Got auth info cmd 0x%x, sub 0x%x, reply 0x%x\n", |
277 cmd, sub_cmd, reply); | 292 cmd, sub_cmd, reply); |
278 } | 293 } |
279 | 294 |
298 g_return_if_fail(uid > 0); | 313 g_return_if_fail(uid > 0); |
299 | 314 |
300 /* we need to send the ascii code of this uid to qq server */ | 315 /* we need to send the ascii code of this uid to qq server */ |
301 g_snprintf(uid_str, sizeof(uid_str), "%d", uid); | 316 g_snprintf(uid_str, sizeof(uid_str), "%d", uid); |
302 qq_send_cmd_mess(gc, QQ_CMD_BUDDY_ADD_NO_AUTH, | 317 qq_send_cmd_mess(gc, QQ_CMD_BUDDY_ADD_NO_AUTH, |
318 (guint8 *) uid_str, strlen(uid_str), 0, uid); | |
319 } | |
320 | |
321 static void request_buddy_add_no_auth_ex(PurpleConnection *gc, guint32 uid) | |
322 { | |
323 gchar uid_str[11]; | |
324 | |
325 g_return_if_fail(uid > 0); | |
326 | |
327 /* we need to send the ascii code of this uid to qq server */ | |
328 g_snprintf(uid_str, sizeof(uid_str), "%d", uid); | |
329 qq_send_cmd_mess(gc, QQ_CMD_BUDDY_ADD_NO_AUTH_EX, | |
303 (guint8 *) uid_str, strlen(uid_str), 0, uid); | 330 (guint8 *) uid_str, strlen(uid_str), 0, uid); |
304 } | 331 } |
305 | 332 |
306 /* this buddy needs authentication, text conversion is done at lowest level */ | 333 /* this buddy needs authentication, text conversion is done at lowest level */ |
307 static void request_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text) | 334 static void request_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text) |
328 } | 355 } |
329 | 356 |
330 qq_send_cmd(gc, QQ_CMD_BUDDY_ADD_AUTH, raw_data, bytes); | 357 qq_send_cmd(gc, QQ_CMD_BUDDY_ADD_AUTH, raw_data, bytes); |
331 } | 358 } |
332 | 359 |
360 static void request_buddy_auth_2007(PurpleConnection *gc, guint32 uid, | |
361 const gchar *text, guint8 *auth, guint8 auth_len) | |
362 { | |
363 guint8 *raw_data; | |
364 gint bytes = 0; | |
365 gchar *msg; | |
366 | |
367 g_return_if_fail(uid != 0); | |
368 | |
369 raw_data = g_newa(guint8, QQ_MSG_IM_MAX); | |
370 bytes = 0; | |
371 bytes += qq_put8(raw_data + bytes, 0x02); | |
372 bytes += qq_put32(raw_data + bytes, uid); | |
373 bytes += qq_put16(raw_data + bytes, 0); | |
374 | |
375 bytes += qq_put8(raw_data + bytes, 0); | |
376 if (auth == NULL || auth_len <= 0) { | |
377 bytes += qq_put8(raw_data + bytes, 0); | |
378 } else { | |
379 bytes += qq_put8(raw_data + bytes, auth_len); | |
380 bytes += qq_putdata(raw_data + bytes, auth, auth_len); | |
381 } | |
382 bytes += qq_put8(raw_data + bytes, 1); /* ALLOW ADD ME FLAG */ | |
383 bytes += qq_put8(raw_data + bytes, 0); /* Destination group */ | |
384 if (text == NULL) { | |
385 bytes += qq_put8(raw_data + bytes, 0); | |
386 } else { | |
387 msg = utf8_to_qq(text, QQ_CHARSET_DEFAULT); | |
388 bytes += qq_put8(raw_data + bytes, strlen(msg)); | |
389 bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); | |
390 g_free(msg); | |
391 } | |
392 qq_send_cmd(gc, QQ_CMD_BUDDY_ADD_AUTH_EX, raw_data, bytes); | |
393 } | |
394 | |
333 static void request_buddy_add_auth_cb(qq_buddy_req *add_req, const gchar *text) | 395 static void request_buddy_add_auth_cb(qq_buddy_req *add_req, const gchar *text) |
334 { | 396 { |
397 qq_data *qd; | |
335 g_return_if_fail(add_req != NULL); | 398 g_return_if_fail(add_req != NULL); |
336 if (add_req->gc == NULL || add_req->uid == 0) { | 399 if (add_req->gc == NULL || add_req->uid == 0) { |
337 g_free(add_req); | 400 buddy_add_req_free(add_req); |
338 return; | 401 return; |
339 } | 402 } |
340 | 403 |
341 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REQUEST, text); | 404 qd = (qq_data *)add_req->gc->proto_data; |
342 g_free(add_req); | 405 if (qd->client_version > 2005) { |
406 request_buddy_auth_2007(add_req->gc, add_req->uid, | |
407 text, add_req->auth, add_req->auth_len); | |
408 } else { | |
409 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REQUEST, text); | |
410 } | |
411 buddy_add_req_free(add_req); | |
343 } | 412 } |
344 | 413 |
345 /* the real packet to reject and request is sent from here */ | 414 /* the real packet to reject and request is sent from here */ |
346 static void buddy_add_deny_reason_cb(qq_buddy_req *add_req, const gchar *reason) | 415 static void buddy_add_deny_reason_cb(qq_buddy_req *add_req, const gchar *reason) |
347 { | 416 { |
348 g_return_if_fail(add_req != NULL); | 417 g_return_if_fail(add_req != NULL); |
349 if (add_req->gc == NULL || add_req->uid == 0) { | 418 if (add_req->gc == NULL || add_req->uid == 0) { |
350 g_free(add_req); | 419 buddy_add_req_free(add_req); |
351 return; | 420 return; |
352 } | 421 } |
353 | 422 |
354 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REJECT, reason); | 423 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REJECT, reason); |
355 g_free(add_req); | 424 buddy_add_req_free(add_req); |
356 } | 425 } |
357 | 426 |
358 static void buddy_add_deny_noreason_cb(qq_buddy_req *add_req) | 427 static void buddy_add_deny_noreason_cb(qq_buddy_req *add_req) |
359 { | 428 { |
360 buddy_add_deny_reason_cb(add_req, NULL); | 429 buddy_add_deny_reason_cb(add_req, NULL); |
365 { | 434 { |
366 qq_buddy_req *add_req = (qq_buddy_req *)data; | 435 qq_buddy_req *add_req = (qq_buddy_req *)data; |
367 | 436 |
368 g_return_if_fail(add_req != NULL); | 437 g_return_if_fail(add_req != NULL); |
369 if (add_req->gc == NULL || add_req->uid == 0) { | 438 if (add_req->gc == NULL || add_req->uid == 0) { |
370 g_free(add_req); | 439 buddy_add_req_free(add_req); |
371 return; | 440 return; |
372 } | 441 } |
373 | 442 |
374 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_APPROVE, NULL); | 443 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_APPROVE, NULL); |
375 g_free(add_req); | 444 buddy_add_req_free(add_req); |
376 } | 445 } |
377 | 446 |
378 /* we reject other's request of adding me as friend */ | 447 /* we reject other's request of adding me as friend */ |
379 static void buddy_add_deny_cb(gpointer data) | 448 static void buddy_add_deny_cb(gpointer data) |
380 { | 449 { |
387 purple_connection_get_account(add_req->gc), who, NULL, | 456 purple_connection_get_account(add_req->gc), who, NULL, |
388 add_req); | 457 add_req); |
389 g_free(who); | 458 g_free(who); |
390 } | 459 } |
391 | 460 |
392 /* add a buddy and send packet to QQ server | 461 static void buddy_cancel_cb(qq_buddy_req *add_req, const gchar *msg) |
393 * note that when purple load local cached buddy list into its blist | 462 { |
394 * it also calls this funtion, so we have to | 463 g_return_if_fail(add_req != NULL); |
395 * define qd->is_login=TRUE AFTER LOGIN */ | 464 buddy_add_req_free(add_req); |
396 void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) | 465 } |
466 | |
467 static void buddy_add_no_auth_cb(qq_buddy_req *add_req) | |
397 { | 468 { |
398 qq_data *qd; | 469 qq_data *qd; |
399 guint32 uid; | |
400 | |
401 g_return_if_fail(NULL != gc && NULL != gc->proto_data); | |
402 g_return_if_fail(buddy != NULL); | |
403 | |
404 qd = (qq_data *) gc->proto_data; | |
405 if (!qd->is_login) | |
406 return; /* IMPORTANT ! */ | |
407 | |
408 uid = purple_name_to_uid(buddy->name); | |
409 if (uid > 0) { | |
410 request_buddy_add_no_auth(gc, uid); | |
411 return; | |
412 } | |
413 | |
414 purple_notify_error(gc, _("QQ Buddy"), _("Add buddy"), _("Invalid QQ Number")); | |
415 if (buddy == NULL) { | |
416 return; | |
417 } | |
418 | |
419 purple_debug_info("QQ", "Remove buddy with invalid QQ number %d\n", uid); | |
420 qq_buddy_free(buddy); | |
421 } | |
422 | |
423 static void buddy_cancel_cb(qq_buddy_req *add_req, const gchar *msg) | |
424 { | |
425 g_return_if_fail(add_req != NULL); | |
426 g_free(add_req); | |
427 } | |
428 | |
429 static void buddy_add_no_auth_cb(qq_buddy_req *add_req) | |
430 { | |
431 g_return_if_fail(add_req != NULL); | 470 g_return_if_fail(add_req != NULL); |
432 if (add_req->gc == NULL || add_req->uid == 0) { | 471 if (add_req->gc == NULL || add_req->uid == 0) { |
433 g_free(add_req); | 472 buddy_add_req_free(add_req); |
434 return; | 473 return; |
435 } | 474 } |
436 | 475 |
437 request_buddy_add_no_auth(add_req->gc, add_req->uid); | 476 qd = (qq_data *) add_req->gc->proto_data; |
438 g_free(add_req); | 477 if (qd->client_version > 2005) { |
439 } | 478 request_buddy_add_no_auth_ex(add_req->gc, add_req->uid); |
440 | 479 } else { |
441 /* process reply to add_buddy_auth request */ | 480 request_buddy_add_no_auth(add_req->gc, add_req->uid); |
442 void qq_process_buddy_add_auth(guint8 *data, gint data_len, PurpleConnection *gc) | 481 } |
443 { | 482 buddy_add_req_free(add_req); |
444 qq_data *qd; | 483 } |
445 gchar **segments, *msg_utf8; | 484 |
446 | 485 void buddy_add_authorize_input(PurpleConnection *gc, guint32 uid, |
447 g_return_if_fail(data != NULL && data_len != 0); | 486 guint8 *auth, guint8 auth_len) |
448 | 487 { |
449 qd = (qq_data *) gc->proto_data; | 488 gchar *who, *msg; |
450 | |
451 if (data[0] == '0') { | |
452 purple_debug_info("QQ", "Reply OK for sending authorize\n"); | |
453 return; | |
454 } | |
455 | |
456 if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) { | |
457 purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), NULL); | |
458 return; | |
459 } | |
460 msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT); | |
461 purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), msg_utf8); | |
462 g_free(msg_utf8); | |
463 } | |
464 | |
465 /* process the server reply for my request to remove a buddy */ | |
466 void qq_process_buddy_remove(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid) | |
467 { | |
468 PurpleBuddy *buddy = NULL; | |
469 gchar *msg; | |
470 | |
471 g_return_if_fail(data != NULL && data_len != 0); | |
472 g_return_if_fail(uid != 0); | |
473 | |
474 buddy = qq_buddy_find(gc, uid); | |
475 if (data[0] != 0) { | |
476 msg = g_strdup_printf(_("Failed removing buddy %d"), uid); | |
477 purple_notify_info(gc, _("QQ Buddy"), msg, NULL); | |
478 g_free(msg); | |
479 } | |
480 | |
481 purple_debug_info("QQ", "Reply OK for removing buddy\n"); | |
482 /* remove buddy again */ | |
483 if (buddy != NULL) { | |
484 qq_buddy_free(buddy); | |
485 } | |
486 } | |
487 | |
488 /* process the server reply for my request to remove myself from a buddy */ | |
489 void qq_process_buddy_remove_me(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid) | |
490 { | |
491 qq_data *qd; | |
492 gchar *msg; | |
493 | |
494 g_return_if_fail(data != NULL && data_len != 0); | |
495 qd = (qq_data *) gc->proto_data; | |
496 | |
497 if (data[0] == 0) { | |
498 purple_debug_info("QQ", "Reply OK for removing me from %d's buddy list\n", uid); | |
499 return; | |
500 } | |
501 msg = g_strdup_printf(_("Failed removing me from %d's buddy list"), uid); | |
502 purple_notify_info(gc, _("QQ Buddy"), msg, NULL); | |
503 g_free(msg); | |
504 } | |
505 | |
506 void qq_process_buddy_add_no_auth(guint8 *data, gint data_len, guint32 uid, PurpleConnection *gc) | |
507 { | |
508 qq_data *qd; | |
509 gchar *msg, **segments, *dest_uid, *reply; | |
510 PurpleBuddy *buddy; | |
511 qq_buddy_req *add_req; | 489 qq_buddy_req *add_req; |
512 gchar *who; | 490 g_return_if_fail(uid != 0); |
513 | 491 |
514 g_return_if_fail(data != NULL && data_len != 0); | |
515 | |
516 qd = (qq_data *) gc->proto_data; | |
517 | |
518 if (uid == 0) { | |
519 purple_debug_error("QQ", "Process buddy add, unknow id\n"); | |
520 return; | |
521 } | |
522 purple_debug_info("QQ", "Process buddy add for id [%d]\n", uid); | |
523 qq_show_packet("buddy_add_no_auth", data, data_len); | |
524 | |
525 if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) | |
526 return; | |
527 | |
528 dest_uid = segments[0]; | |
529 reply = segments[1]; | |
530 if (strtol(dest_uid, NULL, 10) != qd->uid) { /* should not happen */ | |
531 purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", dest_uid); | |
532 g_strfreev(segments); | |
533 return; | |
534 } | |
535 | |
536 if (strtol(reply, NULL, 10) == 0) { | |
537 /* add OK */ | |
538 qq_buddy_find_or_new(gc, uid); | |
539 | |
540 qq_request_buddy_info(gc, uid, 0, 0); | |
541 if (qd->client_version >= 2007) { | |
542 qq_request_get_level_2007(gc, uid); | |
543 } else { | |
544 qq_request_get_level(gc, uid); | |
545 } | |
546 qq_request_get_buddies_online(gc, 0, 0); | |
547 | |
548 purple_debug_info("QQ", "Successed adding into %d's buddy list", uid); | |
549 g_strfreev(segments); | |
550 return; | |
551 } | |
552 | |
553 /* need auth */ | |
554 purple_debug_warning("QQ", "Failed adding buddy, need authorize\n"); | |
555 | |
556 buddy = qq_buddy_find(gc, uid); | |
557 if (buddy == NULL) { | |
558 buddy = qq_buddy_new(gc, uid); | |
559 } | |
560 if (buddy != NULL && buddy->proto_data != NULL) { | |
561 /* Not authorized now, free buddy data */ | |
562 qq_buddy_data_free(buddy->proto_data); | |
563 buddy->proto_data = NULL; | |
564 } | |
565 | |
566 who = uid_to_purple_name(uid); | |
567 add_req = g_new0(qq_buddy_req, 1); | 492 add_req = g_new0(qq_buddy_req, 1); |
568 add_req->gc = gc; | 493 add_req->gc = gc; |
569 add_req->uid = uid; | 494 add_req->uid = uid; |
495 add_req->auth = NULL; | |
496 add_req->auth_len = 0; | |
497 if (auth != NULL && auth_len > 0) { | |
498 add_req->auth = g_new0(guint8, auth_len); | |
499 g_memmove(add_req->auth, auth, auth_len); | |
500 add_req->auth_len = auth_len; | |
501 } | |
502 | |
503 who = uid_to_purple_name(uid); | |
570 msg = g_strdup_printf(_("%d needs authentication"), uid); | 504 msg = g_strdup_printf(_("%d needs authentication"), uid); |
571 purple_request_input(gc, _("Add buddy authorize"), msg, | 505 purple_request_input(gc, _("Add buddy authorize"), msg, |
572 _("Input request here"), | 506 _("Input request here"), |
573 _("Would you be my friend?"), | 507 _("Would you be my friend?"), |
574 TRUE, FALSE, NULL, | 508 TRUE, FALSE, NULL, |
577 purple_connection_get_account(gc), who, NULL, | 511 purple_connection_get_account(gc), who, NULL, |
578 add_req); | 512 add_req); |
579 | 513 |
580 g_free(msg); | 514 g_free(msg); |
581 g_free(who); | 515 g_free(who); |
516 } | |
517 | |
518 /* add a buddy and send packet to QQ server | |
519 * note that when purple load local cached buddy list into its blist | |
520 * it also calls this funtion, so we have to | |
521 * define qd->is_login=TRUE AFTER LOGIN */ | |
522 void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) | |
523 { | |
524 qq_data *qd; | |
525 guint32 uid; | |
526 | |
527 g_return_if_fail(NULL != gc && NULL != gc->proto_data); | |
528 g_return_if_fail(buddy != NULL); | |
529 | |
530 qd = (qq_data *) gc->proto_data; | |
531 if (!qd->is_login) | |
532 return; /* IMPORTANT ! */ | |
533 | |
534 uid = purple_name_to_uid(buddy->name); | |
535 if (uid > 0) { | |
536 if (qd->client_version > 2005) { | |
537 request_buddy_add_no_auth_ex(gc, uid); | |
538 } else { | |
539 request_buddy_add_no_auth(gc, uid); | |
540 } | |
541 return; | |
542 } | |
543 | |
544 purple_notify_error(gc, _("QQ Buddy"), _("Add buddy"), _("Invalid QQ Number")); | |
545 if (buddy == NULL) { | |
546 return; | |
547 } | |
548 | |
549 purple_debug_info("QQ", "Remove buddy with invalid QQ number %d\n", uid); | |
550 qq_buddy_free(buddy); | |
551 } | |
552 | |
553 /* process reply to add_buddy_auth request */ | |
554 void qq_process_buddy_add_auth(guint8 *data, gint data_len, PurpleConnection *gc) | |
555 { | |
556 qq_data *qd; | |
557 gchar **segments, *msg_utf8; | |
558 | |
559 g_return_if_fail(data != NULL && data_len != 0); | |
560 | |
561 qd = (qq_data *) gc->proto_data; | |
562 | |
563 if (data[0] == '0') { | |
564 purple_debug_info("QQ", "Reply OK for sending authorize\n"); | |
565 return; | |
566 } | |
567 | |
568 if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) { | |
569 purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), NULL); | |
570 return; | |
571 } | |
572 msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT); | |
573 purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), msg_utf8); | |
574 g_free(msg_utf8); | |
575 } | |
576 | |
577 /* process the server reply for my request to remove a buddy */ | |
578 void qq_process_buddy_remove(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid) | |
579 { | |
580 PurpleBuddy *buddy = NULL; | |
581 gchar *msg; | |
582 | |
583 g_return_if_fail(data != NULL && data_len != 0); | |
584 g_return_if_fail(uid != 0); | |
585 | |
586 buddy = qq_buddy_find(gc, uid); | |
587 if (data[0] != 0) { | |
588 msg = g_strdup_printf(_("Failed removing buddy %d"), uid); | |
589 purple_notify_info(gc, _("QQ Buddy"), msg, NULL); | |
590 g_free(msg); | |
591 } | |
592 | |
593 purple_debug_info("QQ", "Reply OK for removing buddy\n"); | |
594 /* remove buddy again */ | |
595 if (buddy != NULL) { | |
596 qq_buddy_free(buddy); | |
597 } | |
598 } | |
599 | |
600 /* process the server reply for my request to remove myself from a buddy */ | |
601 void qq_process_buddy_remove_me(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid) | |
602 { | |
603 qq_data *qd; | |
604 gchar *msg; | |
605 | |
606 g_return_if_fail(data != NULL && data_len != 0); | |
607 qd = (qq_data *) gc->proto_data; | |
608 | |
609 if (data[0] == 0) { | |
610 purple_debug_info("QQ", "Reply OK for removing me from %d's buddy list\n", uid); | |
611 return; | |
612 } | |
613 msg = g_strdup_printf(_("Failed removing me from %d's buddy list"), uid); | |
614 purple_notify_info(gc, _("QQ Buddy"), msg, NULL); | |
615 g_free(msg); | |
616 } | |
617 | |
618 void qq_process_buddy_add_no_auth(PurpleConnection *gc, | |
619 guint8 *data, gint data_len, guint32 uid) | |
620 { | |
621 qq_data *qd; | |
622 gchar **segments; | |
623 gchar *dest_uid, *reply; | |
624 PurpleBuddy *buddy; | |
625 | |
626 g_return_if_fail(data != NULL && data_len != 0); | |
627 g_return_if_fail(uid != 0); | |
628 | |
629 qd = (qq_data *) gc->proto_data; | |
630 | |
631 purple_debug_info("QQ", "Process buddy add for id [%d]\n", uid); | |
632 qq_show_packet("buddy_add_no_auth", data, data_len); | |
633 | |
634 if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) | |
635 return; | |
636 | |
637 dest_uid = segments[0]; | |
638 reply = segments[1]; | |
639 if (strtol(dest_uid, NULL, 10) != qd->uid) { /* should not happen */ | |
640 purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", dest_uid); | |
641 g_strfreev(segments); | |
642 return; | |
643 } | |
644 | |
645 if (strtol(reply, NULL, 10) == 0) { | |
646 /* add OK */ | |
647 qq_buddy_find_or_new(gc, uid); | |
648 | |
649 qq_request_buddy_info(gc, uid, 0, 0); | |
650 if (qd->client_version >= 2007) { | |
651 qq_request_get_level_2007(gc, uid); | |
652 } else { | |
653 qq_request_get_level(gc, uid); | |
654 } | |
655 qq_request_get_buddies_online(gc, 0, 0); | |
656 | |
657 purple_debug_info("QQ", "Successed adding into %d's buddy list", uid); | |
658 g_strfreev(segments); | |
659 return; | |
660 } | |
661 | |
662 /* need auth */ | |
663 purple_debug_warning("QQ", "Failed adding buddy, need authorize\n"); | |
664 | |
665 buddy = qq_buddy_find(gc, uid); | |
666 if (buddy == NULL) { | |
667 buddy = qq_buddy_new(gc, uid); | |
668 } | |
669 if (buddy != NULL && buddy->proto_data != NULL) { | |
670 /* Not authorized now, free buddy data */ | |
671 qq_buddy_data_free(buddy->proto_data); | |
672 buddy->proto_data = NULL; | |
673 } | |
674 | |
675 buddy_add_authorize_input(gc, uid, NULL, 0); | |
582 g_strfreev(segments); | 676 g_strfreev(segments); |
677 } | |
678 | |
679 void qq_process_buddy_add_no_auth_ex(PurpleConnection *gc, | |
680 guint8 *data, gint data_len, guint32 uid) | |
681 { | |
682 qq_data *qd; | |
683 gint bytes; | |
684 guint32 dest_uid; | |
685 guint8 reply; | |
686 | |
687 g_return_if_fail(data != NULL && data_len >= 5); | |
688 g_return_if_fail(uid != 0); | |
689 | |
690 qd = (qq_data *) gc->proto_data; | |
691 | |
692 purple_debug_info("QQ", "Process buddy add no auth for id [%d]\n", uid); | |
693 qq_show_packet("buddy_add_no_auth_2007", data, data_len); | |
694 | |
695 bytes = 0; | |
696 bytes += qq_get32(&dest_uid, data + bytes); | |
697 bytes += qq_get8(&reply, data + bytes); | |
698 | |
699 g_return_if_fail(dest_uid == qd->uid); | |
700 | |
701 if (reply == 0) { | |
702 /* need auth */ | |
703 purple_debug_warning("QQ", "Failed adding buddy, need authorize\n"); | |
704 qq_request_auth_info(gc, QQ_AUTH_INFO_BUDDY, QQ_AUTH_INFO_ADD_BUDDY, uid); | |
705 return; | |
706 } | |
707 | |
708 /* add OK */ | |
709 qq_buddy_find_or_new(gc, uid); | |
710 | |
711 qq_request_buddy_info(gc, uid, 0, 0); | |
712 if (qd->client_version >= 2007) { | |
713 qq_request_get_level_2007(gc, uid); | |
714 } else { | |
715 qq_request_get_level(gc, uid); | |
716 } | |
717 qq_request_get_buddies_online(gc, 0, 0); | |
718 | |
719 purple_debug_info("QQ", "Successed adding into %d's buddy list", uid); | |
720 return; | |
583 } | 721 } |
584 | 722 |
585 /* remove a buddy and send packet to QQ server accordingly */ | 723 /* remove a buddy and send packet to QQ server accordingly */ |
586 void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) | 724 void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) |
587 { | 725 { |
614 | 752 |
615 /* Do not call purple_blist_remove_buddy, | 753 /* Do not call purple_blist_remove_buddy, |
616 * otherwise purple segmentation fault */ | 754 * otherwise purple segmentation fault */ |
617 } | 755 } |
618 | 756 |
757 static void buddy_add_request(PurpleConnection *gc, guint32 uid, gchar *reason) | |
758 { | |
759 PurpleAccount *account = purple_connection_get_account(gc); | |
760 qq_buddy_req *add_req; | |
761 gchar *who; | |
762 | |
763 g_return_if_fail(uid != 0 && reason != NULL); | |
764 | |
765 purple_debug_info("QQ", "Buddy %d request adding, msg: %s\n", uid, reason); | |
766 | |
767 add_req = g_new0(qq_buddy_req, 1); | |
768 add_req->gc = gc; | |
769 add_req->uid = uid; | |
770 | |
771 if (purple_prefs_get_bool("/plugins/prpl/qq/auto_get_authorize_info")) { | |
772 qq_request_buddy_info(gc, add_req->uid, 0, QQ_BUDDY_INFO_DISPLAY); | |
773 } | |
774 who = uid_to_purple_name(add_req->uid); | |
775 | |
776 purple_account_request_authorization(account, | |
777 who, NULL, | |
778 NULL, reason, | |
779 purple_find_buddy(account, who) != NULL, | |
780 buddy_add_authorize_cb, | |
781 buddy_add_deny_cb, | |
782 add_req); | |
783 | |
784 g_free(who); | |
785 } | |
786 | |
619 /* someone wants to add you to his buddy list */ | 787 /* someone wants to add you to his buddy list */ |
620 static void server_buddy_add_request(PurpleConnection *gc, gchar *from, gchar *to, | 788 static void server_buddy_add_request(PurpleConnection *gc, gchar *from, gchar *to, |
621 guint8 *data, gint data_len) | 789 guint8 *data, gint data_len) |
622 { | 790 { |
623 PurpleAccount *account = purple_connection_get_account(gc); | 791 guint32 uid; |
624 qq_buddy_req *add_req; | |
625 gchar *who; | |
626 gchar *msg, *reason; | 792 gchar *msg, *reason; |
627 | 793 |
628 g_return_if_fail(from != NULL && to != NULL); | 794 g_return_if_fail(from != NULL && to != NULL); |
629 | 795 uid = strtol(from, NULL, 10); |
630 add_req = g_new0(qq_buddy_req, 1); | 796 g_return_if_fail(uid != 0); |
631 add_req->gc = gc; | |
632 add_req->uid = strtol(from, NULL, 10);; | |
633 | 797 |
634 if (purple_prefs_get_bool("/plugins/prpl/qq/auto_get_authorize_info")) { | 798 if (purple_prefs_get_bool("/plugins/prpl/qq/auto_get_authorize_info")) { |
635 qq_request_buddy_info(gc, add_req->uid, 0, QQ_BUDDY_INFO_DISPLAY); | 799 qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); |
636 } | 800 } |
637 who = uid_to_purple_name(add_req->uid); | |
638 | 801 |
639 if (data_len <= 0) { | 802 if (data_len <= 0) { |
640 reason = g_strdup( _("No reason given") ); | 803 reason = g_strdup( _("No reason given") ); |
641 } else { | 804 } else { |
642 msg = g_strndup((gchar *)data, data_len); | 805 msg = g_strndup((gchar *)data, data_len); |
643 reason = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); | 806 reason = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); |
644 if (reason == NULL) reason = g_strdup( _("Unknown reason") ); | 807 if (reason == NULL) reason = g_strdup( _("Unknown reason") ); |
645 g_free(msg); | 808 g_free(msg); |
646 } | 809 } |
647 purple_account_request_authorization(account, | 810 |
648 from, NULL, | 811 buddy_add_request(gc, uid, reason); |
649 NULL, reason, | |
650 purple_find_buddy(account, who) != NULL, | |
651 buddy_add_authorize_cb, | |
652 buddy_add_deny_cb, | |
653 add_req); | |
654 | |
655 g_free(reason); | 812 g_free(reason); |
656 g_free(who); | 813 } |
814 | |
815 void qq_process_buddy_check_code(PurpleConnection *gc, guint8 *data, gint data_len, guint32 ship32) | |
816 { | |
817 qq_data *qd; | |
818 gint bytes; | |
819 guint8 cmd; | |
820 guint8 reply; | |
821 guint32 uid; | |
822 guint16 flag1, flag2; | |
823 | |
824 g_return_if_fail(data != NULL && data_len >= 5); | |
825 g_return_if_fail(uid != 0); | |
826 | |
827 qd = (qq_data *) gc->proto_data; | |
828 | |
829 qq_show_packet("buddy_check_code", data, data_len); | |
830 | |
831 bytes = 0; | |
832 bytes += qq_get8(&cmd, data + bytes); /* 0x03 */ | |
833 bytes += qq_get8(&reply, data + bytes); | |
834 | |
835 if (reply == 0) { | |
836 purple_debug_info("QQ", "Failed checking code\n"); | |
837 return; | |
838 } | |
839 | |
840 bytes += qq_get32(&uid, data + bytes); | |
841 g_return_if_fail(uid != 0); | |
842 bytes += qq_get16(&flag1, data + bytes); | |
843 bytes += qq_get16(&flag2, data + bytes); | |
844 purple_debug_info("QQ", "Check code reply Ok, uid %d, flag 0x%04X-0x%04X\n", | |
845 uid, flag1, flag2); | |
846 return; | |
847 } | |
848 | |
849 static void request_buddy_check_code(PurpleConnection *gc, | |
850 gchar *from, guint8 *code, gint code_len) | |
851 { | |
852 guint8 *raw_data; | |
853 gint bytes; | |
854 guint32 uid; | |
855 | |
856 g_return_if_fail(code != NULL && code_len > 0 && from != NULL); | |
857 | |
858 uid = strtol(from, NULL, 10); | |
859 raw_data = g_newa(guint8, code_len + 16); | |
860 bytes = 0; | |
861 bytes += qq_put8(raw_data + bytes, 0x03); | |
862 bytes += qq_put8(raw_data + bytes, 0x01); | |
863 bytes += qq_put32(raw_data + bytes, uid); | |
864 bytes += qq_put16(raw_data + bytes, code_len); | |
865 bytes += qq_putdata(raw_data + bytes, code, code_len); | |
866 | |
867 qq_send_cmd(gc, QQ_CMD_BUDDY_CHECK_CODE, raw_data, bytes); | |
868 } | |
869 | |
870 static gint server_buddy_check_code(PurpleConnection *gc, | |
871 gchar *from, guint8 *data, gint data_len) | |
872 { | |
873 gint bytes; | |
874 guint8 *code; | |
875 guint16 code_len; | |
876 | |
877 g_return_val_if_fail(data != NULL && data_len > 0, 0); | |
878 | |
879 bytes = 0; | |
880 bytes += qq_get16(&code_len, data + bytes); | |
881 if (code_len <= 0) { | |
882 purple_debug_info("QQ", "Server msg for buddy has no code\n"); | |
883 return bytes; | |
884 } | |
885 if (bytes + code_len < data_len) { | |
886 purple_debug_error("QQ", "Code len error in server msg for buddy\n"); | |
887 qq_show_packet("server_buddy_check_code", data, data_len); | |
888 code_len = data_len - bytes; | |
889 } | |
890 code = g_newa(guint8, code_len); | |
891 bytes += qq_getdata(code, code_len, data + bytes); | |
892 | |
893 request_buddy_check_code(gc, from, code, code_len); | |
894 return bytes; | |
895 } | |
896 | |
897 static void server_buddy_add_request_ex(PurpleConnection *gc, gchar *from, gchar *to, | |
898 guint8 *data, gint data_len) | |
899 { | |
900 gint bytes; | |
901 guint32 uid; | |
902 gchar *msg; | |
903 guint8 allow_reverse; | |
904 | |
905 g_return_if_fail(from != NULL && to != NULL); | |
906 g_return_if_fail(data != NULL && data_len >= 3); | |
907 uid = strtol(from, NULL, 10); | |
908 g_return_if_fail(uid != 0); | |
909 | |
910 /* qq_show_packet("server_buddy_add_request_ex", data, data_len); */ | |
911 | |
912 bytes = 0; | |
913 bytes += qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data+bytes); | |
914 bytes += qq_get8(&allow_reverse, data + bytes); /* allow_reverse = 0x01, allowed */ | |
915 server_buddy_check_code(gc, from, data + bytes, data_len - bytes); | |
916 | |
917 if (strlen(msg) <= 0) { | |
918 g_free(msg); | |
919 msg = g_strdup( _("No reason given") ); | |
920 } | |
921 buddy_add_request(gc, uid, msg); | |
922 g_free(msg); | |
657 } | 923 } |
658 | 924 |
659 /* when you are added by a person, QQ server will send sys message */ | 925 /* when you are added by a person, QQ server will send sys message */ |
660 static void server_buddy_added(PurpleConnection *gc, gchar *from, gchar *to, | 926 static void server_buddy_added(PurpleConnection *gc, gchar *from, gchar *to, |
661 guint8 *data, gint data_len) | 927 guint8 *data, gint data_len) |
691 | 957 |
692 g_free(who); | 958 g_free(who); |
693 g_free(primary); | 959 g_free(primary); |
694 } | 960 } |
695 | 961 |
962 static void server_buddy_added_ex(PurpleConnection *gc, gchar *from, gchar *to, | |
963 guint8 *data, gint data_len) | |
964 { | |
965 gint bytes; | |
966 guint8 allow_reverse; | |
967 gchar *msg; | |
968 | |
969 g_return_if_fail(from != NULL && to != NULL); | |
970 g_return_if_fail(data != NULL && data_len >= 3); | |
971 | |
972 qq_show_packet("server_buddy_added_ex", data, data_len); | |
973 | |
974 bytes = 0; | |
975 bytes += qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data+bytes); /* always empty msg */ | |
976 purple_debug_info("QQ", "Buddy added msg: %s\n", msg); | |
977 bytes += qq_get8(&allow_reverse, data + bytes); /* allow_reverse = 0x01, allowed */ | |
978 server_buddy_check_code(gc, from, data + bytes, data_len - bytes); | |
979 | |
980 g_free(msg); | |
981 } | |
982 | |
983 static void server_buddy_adding_ex(PurpleConnection *gc, gchar *from, gchar *to, | |
984 guint8 *data, gint data_len) | |
985 { | |
986 gint bytes; | |
987 guint8 allow_reverse; | |
988 | |
989 g_return_if_fail(from != NULL && to != NULL); | |
990 g_return_if_fail(data != NULL && data_len >= 3); | |
991 | |
992 qq_show_packet("server_buddy_adding_ex", data, data_len); | |
993 | |
994 bytes = 0; | |
995 bytes += qq_get8(&allow_reverse, data + bytes); /* allow_reverse = 0x01, allowed */ | |
996 server_buddy_check_code(gc, from, data + bytes, data_len - bytes); | |
997 } | |
998 | |
696 /* the buddy approves your request of adding him/her as your friend */ | 999 /* the buddy approves your request of adding him/her as your friend */ |
697 static void server_buddy_added_me(PurpleConnection *gc, gchar *from, gchar *to, | 1000 static void server_buddy_added_me(PurpleConnection *gc, gchar *from, gchar *to, |
698 guint8 *data, gint data_len) | 1001 guint8 *data, gint data_len) |
699 { | 1002 { |
700 PurpleAccount *account = purple_connection_get_account(gc); | 1003 PurpleAccount *account = purple_connection_get_account(gc); |
702 guint32 uid; | 1005 guint32 uid; |
703 | 1006 |
704 g_return_if_fail(from != NULL && to != NULL); | 1007 g_return_if_fail(from != NULL && to != NULL); |
705 | 1008 |
706 qd = (qq_data *) gc->proto_data; | 1009 qd = (qq_data *) gc->proto_data; |
1010 | |
707 uid = strtol(from, NULL, 10); | 1011 uid = strtol(from, NULL, 10); |
708 | |
709 g_return_if_fail(uid > 0); | 1012 g_return_if_fail(uid > 0); |
1013 | |
1014 server_buddy_check_code(gc, from, data, data_len); | |
710 | 1015 |
711 qq_buddy_find_or_new(gc, uid); | 1016 qq_buddy_find_or_new(gc, uid); |
712 qq_request_buddy_info(gc, uid, 0, 0); | 1017 qq_request_buddy_info(gc, uid, 0, 0); |
713 qq_request_get_buddies_online(gc, 0, 0); | 1018 qq_request_get_buddies_online(gc, 0, 0); |
714 if (qd->client_version >= 2007) { | 1019 if (qd->client_version >= 2007) { |
725 guint8 *data, gint data_len) | 1030 guint8 *data, gint data_len) |
726 { | 1031 { |
727 guint32 uid; | 1032 guint32 uid; |
728 PurpleBuddy *buddy; | 1033 PurpleBuddy *buddy; |
729 gchar *msg, *msg_utf8; | 1034 gchar *msg, *msg_utf8; |
1035 gint bytes; | |
1036 gchar **segments; | |
730 gchar *primary, *secondary; | 1037 gchar *primary, *secondary; |
731 | 1038 |
732 g_return_if_fail(from != NULL && to != NULL); | 1039 g_return_if_fail(from != NULL && to != NULL); |
1040 | |
1041 qq_show_packet("server_buddy_rejected_me", data, data_len); | |
733 | 1042 |
734 if (data_len <= 0) { | 1043 if (data_len <= 0) { |
735 msg = g_strdup( _("No reason given") ); | 1044 msg = g_strdup( _("No reason given") ); |
736 } else { | 1045 } else { |
737 msg = g_strndup((gchar *)data, data_len); | 1046 segments = g_strsplit((gchar *)data, "\x1f", 1); |
1047 if (segments != NULL && segments[0] != NULL) { | |
1048 msg = g_strdup(segments[0]); | |
1049 g_strfreev(segments); | |
1050 bytes = strlen(msg) + 1; | |
1051 if (bytes < data_len) { | |
1052 server_buddy_check_code(gc, from, data + bytes, data_len - bytes); | |
1053 } | |
1054 } else { | |
1055 msg = g_strdup( _("No reason given") ); | |
1056 } | |
738 } | 1057 } |
739 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); | 1058 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); |
740 if (msg_utf8 == NULL) { | 1059 if (msg_utf8 == NULL) { |
741 msg_utf8 = g_strdup( _("Unknown reason") ); | 1060 msg_utf8 = g_strdup( _("Unknown reason") ); |
742 } | 1061 } |
770 server_buddy_added(gc, from, to, data, data_len); | 1089 server_buddy_added(gc, from, to, data, data_len); |
771 break; | 1090 break; |
772 case QQ_SERVER_BUDDY_ADD_REQUEST: | 1091 case QQ_SERVER_BUDDY_ADD_REQUEST: |
773 server_buddy_add_request(gc, from, to, data, data_len); | 1092 server_buddy_add_request(gc, from, to, data, data_len); |
774 break; | 1093 break; |
775 case QQ_MSG_SYS_ADD_FRIEND_REQUEST_EX: | 1094 case QQ_SERVER_BUDDY_ADD_REQUEST_EX: |
776 // server_buddy_add_request_ex(gc, from, to, data, data_len); | 1095 server_buddy_add_request_ex(gc, from, to, data, data_len); |
777 break; | 1096 break; |
778 case QQ_SERVER_BUDDY_ADDED_ME: | 1097 case QQ_SERVER_BUDDY_ADDED_ME: |
779 server_buddy_added_me(gc, from, to, data, data_len); | 1098 server_buddy_added_me(gc, from, to, data, data_len); |
780 break; | 1099 break; |
781 case QQ_SERVER_BUDDY_REJECTED_ME: | 1100 case QQ_SERVER_BUDDY_REJECTED_ME: |
782 server_buddy_rejected_me(gc, from, to, data, data_len); | 1101 server_buddy_rejected_me(gc, from, to, data, data_len); |
783 break; | 1102 break; |
1103 case QQ_SERVER_BUDDY_ADDED_EX: | |
1104 server_buddy_added_ex(gc, from, to, data, data_len); | |
1105 break; | |
1106 case QQ_SERVER_BUDDY_ADDING_EX: | |
1107 case QQ_SERVER_BUDDY_ADDED_ANSWER: | |
1108 server_buddy_adding_ex(gc, from, to, data, data_len); | |
1109 break; | |
784 default: | 1110 default: |
785 purple_debug_warning("QQ", "Unknow buddy operate (%d) from server\n", funct); | 1111 purple_debug_warning("QQ", "Unknow buddy operate (%d) from server\n", funct); |
786 break; | 1112 break; |
787 } | 1113 } |
788 } | 1114 } |