Mercurial > pidgin.yaz
diff libpurple/protocols/qq/buddy_opt.c @ 24048:d57928c9dd8f
2008.09.19 - ccpaging <ccpaging(at)gmail.com>
* Rewrite buddy modify info, there is a ticket for this problem
* Use ship32 to trans action code between request packet and reply packet process
author | SHiNE CsyFeK <csyfek@gmail.com> |
---|---|
date | Fri, 19 Sep 2008 14:46:41 +0000 |
parents | bcfc98c7a55f |
children | bdfcfd71449c |
line wrap: on
line diff
--- a/libpurple/protocols/qq/buddy_opt.c Mon Sep 15 12:55:33 2008 +0000 +++ b/libpurple/protocols/qq/buddy_opt.c Fri Sep 19 14:46:41 2008 +0000 @@ -26,6 +26,7 @@ #include "internal.h" #include "notify.h" #include "request.h" +#include "privacy.h" #include "buddy_info.h" #include "buddy_list.h" @@ -52,24 +53,19 @@ QQ_MY_AUTH_REQUEST = 0x32, /* ASCII value of "2" */ }; -typedef struct _qq_add_buddy_request { - guint32 uid; - guint16 seq; -} qq_add_buddy_request; - /* send packet to remove a buddy from my buddy list */ -static void _qq_send_packet_remove_buddy(PurpleConnection *gc, guint32 uid) +static void request_buddy_remove(PurpleConnection *gc, guint32 uid) { gchar uid_str[11]; g_return_if_fail(uid > 0); g_snprintf(uid_str, sizeof(uid_str), "%d", uid); - qq_send_cmd(gc, QQ_CMD_DEL_BUDDY, (guint8 *) uid_str, strlen(uid_str)); + qq_send_cmd(gc, QQ_CMD_BUDDY_REMOVE, (guint8 *) uid_str, strlen(uid_str)); } /* try to remove myself from someone's buddy list */ -static void _qq_send_packet_remove_self_from(PurpleConnection *gc, guint32 uid) +static void request_buddy_remove_me(PurpleConnection *gc, guint32 uid) { guint8 raw_data[16] = {0}; gint bytes = 0; @@ -78,31 +74,24 @@ bytes += qq_put32(raw_data + bytes, uid); - qq_send_cmd(gc, QQ_CMD_REMOVE_SELF, raw_data, bytes); + qq_send_cmd(gc, QQ_CMD_REMOVE_ME, raw_data, bytes); } /* try to add a buddy without authentication */ -static void _qq_send_packet_add_buddy(PurpleConnection *gc, guint32 uid) +static void request_buddy_add_no_auth(PurpleConnection *gc, guint32 uid) { - qq_data *qd = (qq_data *) gc->proto_data; - qq_add_buddy_request *req; gchar uid_str[11]; g_return_if_fail(uid > 0); /* we need to send the ascii code of this uid to qq server */ g_snprintf(uid_str, sizeof(uid_str), "%d", uid); - qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_WO_AUTH, (guint8 *) uid_str, strlen(uid_str)); - - /* must be set after sending packet to get the correct send_seq */ - req = g_new0(qq_add_buddy_request, 1); - req->seq = qd->send_seq; - req->uid = uid; - qd->add_buddy_request = g_list_append(qd->add_buddy_request, req); + qq_send_cmd_mess(gc, QQ_CMD_BUDDY_ADD_NO_AUTH, + (guint8 *) uid_str, strlen(uid_str), 0, uid); } /* this buddy needs authentication, text conversion is done at lowest level */ -static void _qq_send_packet_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text) +static void request_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text) { gchar *text_qq, uid_str[11]; guint8 bar, *raw_data; @@ -125,130 +114,256 @@ g_free(text_qq); } - qq_send_cmd(gc, QQ_CMD_BUDDY_AUTH, raw_data, bytes); + qq_send_cmd(gc, QQ_CMD_BUDDY_ADD_AUTH, raw_data, bytes); } -static void _qq_send_packet_add_buddy_auth_with_gc_and_uid(gc_and_uid *g, const gchar *text) +static void request_buddy_add_auth_cb(qq_add_request *add_req, const gchar *text) { - PurpleConnection *gc; - guint32 uid; - g_return_if_fail(g != NULL); + g_return_if_fail(add_req != NULL); + if (add_req->gc == NULL || add_req->uid == 0) { + g_free(add_req); + return; + } - gc = g->gc; - uid = g->uid; - g_return_if_fail(uid != 0); - - _qq_send_packet_buddy_auth(gc, uid, QQ_MY_AUTH_REQUEST, text); - g_free(g); + request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REQUEST, text); + g_free(add_req); } /* the real packet to reject and request is sent from here */ -static void _qq_reject_add_request_real(gc_and_uid *g, const gchar *reason) +static void buddy_add_deny_reason_cb(qq_add_request *add_req, const gchar *reason) { - gint uid; - PurpleConnection *gc; - - g_return_if_fail(g != NULL); + g_return_if_fail(add_req != NULL); + if (add_req->gc == NULL || add_req->uid == 0) { + g_free(add_req); + return; + } - gc = g->gc; - uid = g->uid; - g_return_if_fail(uid != 0); - - _qq_send_packet_buddy_auth(gc, uid, QQ_MY_AUTH_REJECT, reason); - g_free(g); + request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REJECT, reason); + g_free(add_req); } /* we approve other's request of adding me as friend */ -void qq_approve_add_request_with_gc_and_uid(gc_and_uid *g) +static void buddy_add_authorize_cb(qq_add_request *add_req) { - gint uid; - PurpleConnection *gc; - - g_return_if_fail(g != NULL); + g_return_if_fail(add_req != NULL); + if (add_req->gc == NULL || add_req->uid != 0) { + g_free(add_req); + return; + } - gc = g->gc; - uid = g->uid; - g_return_if_fail(uid != 0); - - _qq_send_packet_buddy_auth(gc, uid, QQ_MY_AUTH_APPROVE, NULL); - g_free(g); -} - -void qq_do_nothing_with_gc_and_uid(gc_and_uid *g, const gchar *msg) -{ - g_free(g); + request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_APPROVE, NULL); + g_free(add_req); } /* we reject other's request of adding me as friend */ -void qq_reject_add_request_with_gc_and_uid(gc_and_uid *g) +static void buddy_add_deny_cb(qq_add_request *add_req) { gint uid; gchar *msg1, *msg2; PurpleConnection *gc; - gc_and_uid *g2; - gchar *nombre; - - g_return_if_fail(g != NULL); + gchar *purple_name; - gc = g->gc; - uid = g->uid; - g_return_if_fail(uid != 0); + g_return_if_fail(add_req != NULL); + if (add_req->gc == NULL || add_req->uid == 0) { + g_free(add_req); + return; + } - g_free(g); - - g2 = g_new0(gc_and_uid, 1); - g2->gc = gc; - g2->uid = uid; + gc = add_req->gc; + uid = add_req->uid; msg1 = g_strdup_printf(_("You rejected %d's request"), uid); msg2 = g_strdup(_("Message:")); - nombre = uid_to_purple_name(uid); + purple_name = uid_to_purple_name(uid); purple_request_input(gc, _("Reject request"), msg1, msg2, _("Sorry, you are not my style..."), TRUE, FALSE, - NULL, _("Reject"), G_CALLBACK(_qq_reject_add_request_real), _("Cancel"), NULL, - purple_connection_get_account(gc), nombre, NULL, - g2); - g_free(nombre); + NULL, _("Reject"), G_CALLBACK(buddy_add_deny_reason_cb), _("Cancel"), NULL, + purple_connection_get_account(gc), purple_name, NULL, + add_req); + g_free(purple_name); +} + +/* suggested by rakescar@linuxsir, can still approve after search */ +static void buddy_add_check_info_cb(qq_add_request *add_req) +{ + PurpleConnection *gc; + guint32 uid; + gchar *purple_name; + + g_return_if_fail(add_req != NULL); + if (add_req->gc == NULL || add_req->uid == 0) { + g_free(add_req); + return; + } + + gc = add_req->gc; + uid = add_req->uid; + + qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); + + purple_name = uid_to_purple_name(uid); + purple_request_action + (gc, NULL, _("Do you approve the requestion?"), "", + PURPLE_DEFAULT_ACTION_NONE, + purple_connection_get_account(gc), purple_name, NULL, + add_req, 2, + _("Reject"), G_CALLBACK(buddy_add_deny_cb), + _("Approve"), G_CALLBACK(buddy_add_authorize_cb)); + g_free(purple_name); } -void qq_add_buddy_with_gc_and_uid(gc_and_uid *g) +/* add a buddy and send packet to QQ server + * note that when purple load local cached buddy list into its blist + * it also calls this funtion, so we have to + * define qd->is_login=TRUE AFTER serv_finish_login(gc) */ +void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) +{ + qq_data *qd; + guint32 uid; + PurpleBuddy *b; + + qd = (qq_data *) gc->proto_data; + if (!qd->is_login) + return; /* IMPORTANT ! */ + + uid = purple_name_to_uid(buddy->name); + if (uid > 0) { + request_buddy_add_no_auth(gc, uid); + return; + } + + b = purple_find_buddy(gc->account, buddy->name); + if (b != NULL) { + purple_blist_remove_buddy(b); + } + purple_notify_error(gc, NULL, _("QQ Number Error"), _("Invalid QQ Number")); +} + +void qq_change_buddys_group(PurpleConnection *gc, const char *who, + const char *old_group, const char *new_group) { gint uid; - PurpleConnection *gc; + g_return_if_fail(who != NULL); - g_return_if_fail(g != NULL); + if (strcmp(new_group, PURPLE_GROUP_QQ_UNKNOWN) == 0) { + if (purple_privacy_check(gc->account, who)) { + purple_privacy_deny(gc->account, who, TRUE, FALSE); + } else { + purple_privacy_deny_add(gc->account, who, TRUE); + } + return; + } - gc = g->gc; - uid = g->uid; + if (strcmp(old_group, PURPLE_GROUP_QQ_UNKNOWN) != 0) { + return; + } + + uid = purple_name_to_uid(who); g_return_if_fail(uid != 0); - _qq_send_packet_add_buddy(gc, uid); - g_free(g); + purple_privacy_deny_remove(gc->account, who, TRUE); + + purple_debug_info("QQ", "Add unknow buddy %d\n", uid); + request_buddy_add_no_auth(gc, uid); +} + +static void buddy_cancel_cb(qq_add_request *add_req, const gchar *msg) +{ + g_return_if_fail(add_req != NULL); + g_free(add_req); +} + +static void buddy_add_no_auth_cb(qq_add_request *add_req) +{ + g_return_if_fail(add_req != NULL); + if (add_req->gc == NULL || add_req->uid == 0) { + g_free(add_req); + return; + } + + request_buddy_add_no_auth(add_req->gc, add_req->uid); + g_free(add_req); } -void qq_block_buddy_with_gc_and_uid(gc_and_uid *g) +static void buddy_remove_both_cb(qq_add_request *add_req) { - guint32 uid; PurpleConnection *gc; - PurpleBuddy buddy; - PurpleGroup group; + qq_data *qd; + gchar *purple_name; + PurpleBuddy *buddy; + qq_buddy *q_buddy; + + g_return_if_fail(add_req != NULL); + if (add_req->gc == NULL || add_req->uid == 0) { + g_free(add_req); + return; + } + + gc = add_req->gc; + qd = (qq_data *) gc->proto_data; + + request_buddy_remove(gc, add_req->uid); + request_buddy_remove_me(gc, add_req->uid); + + purple_name = uid_to_purple_name(add_req->uid); + buddy = purple_find_buddy(gc->account, purple_name); + if (buddy == NULL) { + g_free(add_req); + return; + } - g_return_if_fail(g != NULL); + q_buddy = (qq_buddy *) buddy->proto_data; + if (q_buddy != NULL) + qd->buddies = g_list_remove(qd->buddies, q_buddy); + else + purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name); + + purple_blist_remove_buddy(buddy); + g_free(add_req); +} - gc = g->gc; - uid = g->uid; +/* remove a buddy from my list and remove myself from his list */ +/* TODO: re-enable this */ +void qq_remove_buddy_and_me(PurpleBlistNode * node) +{ + PurpleConnection *gc; + qq_data *qd; + guint32 uid; + qq_add_request *add_req; + PurpleBuddy *buddy; + const gchar *who; + + g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + + buddy = (PurpleBuddy *) node; + gc = purple_account_get_connection(buddy->account); + qd = (qq_data *) gc->proto_data; + if (!qd->is_login) + return; + + who = buddy->name; + g_return_if_fail(who != NULL); + + uid = purple_name_to_uid(who); g_return_if_fail(uid > 0); - buddy.name = uid_to_purple_name(uid); - group.name = PURPLE_GROUP_QQ_BLOCKED; + add_req = g_new0(qq_add_request, 1); + add_req->gc = gc; + add_req->uid = uid; - qq_remove_buddy(gc, &buddy, &group); - _qq_send_packet_remove_self_from(gc, uid); + purple_request_action(gc, _("Block Buddy"), + "Are you sure you want to block this buddy?", + NULL, + 1, + purple_connection_get_account(gc), NULL, NULL, + add_req, 2, + _("Cancel"), G_CALLBACK(buddy_cancel_cb), + _("Block"), G_CALLBACK(buddy_remove_both_cb)); } /* process reply to add_buddy_auth request */ -void qq_process_add_buddy_auth_reply(guint8 *data, gint data_len, PurpleConnection *gc) +void qq_process_buddy_add_auth(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; gchar **segments, *msg_utf8; @@ -271,7 +386,7 @@ } /* process the server reply for my request to remove a buddy */ -void qq_process_remove_buddy_reply(guint8 *data, gint data_len, PurpleConnection *gc) +void qq_process_buddy_remove(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; @@ -291,7 +406,7 @@ } /* process the server reply for my request to remove myself from a buddy */ -void qq_process_remove_self_reply(guint8 *data, gint data_len, PurpleConnection *gc) +void qq_process_buddy_remove_me(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; @@ -302,91 +417,75 @@ if (data[0] != QQ_REMOVE_SELF_REPLY_OK) { /* there is no reason return from server */ purple_debug_warning("QQ", "Remove self fails\n"); - purple_notify_info(gc, _("QQ Buddy"), _("Failed:"), _("Remove from other's buddy list")); + purple_notify_info(gc, _("QQ Buddy"), _("Failed:"), _("Remove me from other's buddy list")); } else { /* if reply */ purple_debug_info("QQ", "Remove from a buddy OK\n"); - /* TODO: Does the user really need to be notified about this? */ +#if 0 purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), _("Remove from other's buddy list")); +#endif } } -void qq_process_add_buddy_reply(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc) +void qq_process_buddy_add_no_auth(guint8 *data, gint data_len, guint32 uid, PurpleConnection *gc) { qq_data *qd; - gint for_uid; - gchar *msg, **segments, *uid, *reply; - GList *list; + gchar *msg, **segments, *dest_uid, *reply; PurpleBuddy *b; - gc_and_uid *g; - qq_add_buddy_request *req; + qq_add_request *add_req; gchar *nombre; g_return_if_fail(data != NULL && data_len != 0); - for_uid = 0; qd = (qq_data *) gc->proto_data; - list = qd->add_buddy_request; - while (list != NULL) { - req = (qq_add_buddy_request *) list->data; - if (req->seq == seq) { /* reply to this */ - for_uid = req->uid; - qd->add_buddy_request = g_list_remove(qd->add_buddy_request, qd->add_buddy_request->data); - g_free(req); - break; - } - list = list->next; - } - - if (for_uid == 0) { /* we have no record for this */ - purple_debug_error("QQ", "We have no record for add buddy reply [%d], discard\n", seq); + if (uid == 0) { /* we have no record for this */ + purple_debug_error("QQ", "Process buddy add, unknow id\n"); return; } else { - purple_debug_info("QQ", "Add buddy reply [%d] is for id [%d]\n", seq, for_uid); + purple_debug_info("QQ", "Process buddy add for id [%d]\n", uid); } if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) return; - uid = segments[0]; + dest_uid = segments[0]; reply = segments[1]; - if (strtol(uid, NULL, 10) != qd->uid) { /* should not happen */ - purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", uid); + if (strtol(dest_uid, NULL, 10) != qd->uid) { /* should not happen */ + purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", dest_uid); g_strfreev(segments); return; } if (strtol(reply, NULL, 10) > 0) { /* need auth */ purple_debug_warning("QQ", "Add buddy attempt fails, need authentication\n"); - nombre = uid_to_purple_name(for_uid); + nombre = uid_to_purple_name(uid); b = purple_find_buddy(gc->account, nombre); if (b != NULL) purple_blist_remove_buddy(b); - g = g_new0(gc_and_uid, 1); - g->gc = gc; - g->uid = for_uid; - msg = g_strdup_printf(_("%d needs authentication"), for_uid); + add_req = g_new0(qq_add_request, 1); + add_req->gc = gc; + add_req->uid = uid; + msg = g_strdup_printf(_("%d needs authentication"), uid); purple_request_input(gc, NULL, msg, _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */ _("Would you be my friend?"), TRUE, FALSE, NULL, _("Send"), - G_CALLBACK - (_qq_send_packet_add_buddy_auth_with_gc_and_uid), - _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), + G_CALLBACK(request_buddy_add_auth_cb), + _("Cancel"), G_CALLBACK(buddy_cancel_cb), purple_connection_get_account(gc), nombre, NULL, - g); + add_req); g_free(msg); g_free(nombre); } else { /* add OK */ - qq_add_buddy_by_recv_packet(gc, for_uid, TRUE, TRUE); - msg = g_strdup_printf(_("Add into %d's buddy list"), for_uid); + qq_create_buddy(gc, uid, TRUE, TRUE); + msg = g_strdup_printf(_("Add into %d's buddy list"), uid); purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), msg); g_free(msg); } g_strfreev(segments); } -PurpleGroup *qq_get_purple_group(const gchar *group_name) +PurpleGroup *qq_create_group(const gchar *group_name) { PurpleGroup *g; @@ -404,131 +503,93 @@ /* we add new buddy, if the received packet is from someone not in my list * return the PurpleBuddy that is just created */ -PurpleBuddy *qq_add_buddy_by_recv_packet(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create) +PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create) { - PurpleAccount *a; - PurpleBuddy *b; - PurpleGroup *g; + PurpleBuddy *buddy; + PurpleGroup *group; qq_data *qd; qq_buddy *q_bud; - gchar *name, *group_name; + gchar *buddy_name, *group_name; - a = gc->account; + g_return_val_if_fail(gc->account != NULL && uid != 0, NULL); qd = (qq_data *) gc->proto_data; - g_return_val_if_fail(a != NULL && uid != 0, NULL); - group_name = is_known ? - g_strdup_printf(PURPLE_GROUP_QQ_FORMAT, purple_account_get_username(a)) : g_strdup(PURPLE_GROUP_QQ_UNKNOWN); + if (is_known) { + group_name = g_strdup_printf(PURPLE_GROUP_QQ_FORMAT, + purple_account_get_username(gc->account)); + } else { + group_name = g_strdup(PURPLE_GROUP_QQ_UNKNOWN); + } - g = qq_get_purple_group(group_name); + group = qq_create_group(group_name); - name = uid_to_purple_name(uid); - b = purple_find_buddy(gc->account, name); + buddy_name = uid_to_purple_name(uid); + buddy = purple_find_buddy(gc->account, buddy_name); /* remove old, we can not simply return here * because there might be old local copy of this buddy */ - if (b != NULL) - purple_blist_remove_buddy(b); + if (buddy != NULL) + purple_blist_remove_buddy(buddy); - b = purple_buddy_new(a, name, NULL); + buddy = purple_buddy_new(gc->account, buddy_name, NULL); + if ( !is_known ) { + if (purple_privacy_check(gc->account, buddy_name)) { + purple_privacy_deny(gc->account, buddy_name, TRUE, FALSE); + } else { + purple_privacy_deny_add(gc->account, buddy_name, TRUE); + } + } if (!create) - b->proto_data = NULL; + buddy->proto_data = NULL; else { q_bud = g_new0(qq_buddy, 1); q_bud->uid = uid; - b->proto_data = q_bud; + buddy->proto_data = q_bud; qd->buddies = g_list_append(qd->buddies, q_bud); - qq_send_packet_get_info(gc, q_bud->uid, FALSE); + qq_request_buddy_info(gc, qd->uid, 0, 0); qq_request_get_buddies_online(gc, 0, 0); + qq_request_get_level(gc, qd->uid); } - purple_blist_add_buddy(b, NULL, g, NULL); - purple_debug_warning("QQ", "Add new buddy: [%s]\n", name); + purple_blist_add_buddy(buddy, NULL, group, NULL); + purple_debug_warning("QQ", "Add new buddy: [%s]\n", buddy_name); - g_free(name); + g_free(buddy_name); g_free(group_name); - return b; -} - -/* add a buddy and send packet to QQ server - * note that when purple load local cached buddy list into its blist - * it also calls this funtion, so we have to - * define qd->is_login=TRUE AFTER serv_finish_login(gc) */ -void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) -{ - qq_data *qd; - guint32 uid; - PurpleBuddy *b; - - qd = (qq_data *) gc->proto_data; - if (!qd->is_login) - return; /* IMPORTANT ! */ - - uid = purple_name_to_uid(buddy->name); - if (uid > 0) - _qq_send_packet_add_buddy(gc, uid); - else { - b = purple_find_buddy(gc->account, buddy->name); - if (b != NULL) - purple_blist_remove_buddy(b); - purple_notify_error(gc, NULL, - _("QQ Number Error"), - _("Invalid QQ Number")); - } + return buddy; } /* remove a buddy and send packet to QQ server accordingly */ void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { qq_data *qd; - PurpleBuddy *b; qq_buddy *q_bud; guint32 uid; + g_return_if_fail(gc != NULL && gc->proto_data != NULL); + g_return_if_fail(buddy != NULL); qd = (qq_data *) gc->proto_data; + uid = purple_name_to_uid(buddy->name); - if (!qd->is_login) return; - if (uid > 0) - _qq_send_packet_remove_buddy(gc, uid); + if (uid > 0) { + request_buddy_remove(gc, uid); + } - b = purple_find_buddy(gc->account, buddy->name); - if (b != NULL) { - q_bud = (qq_buddy *) b->proto_data; - if (q_bud != NULL) - qd->buddies = g_list_remove(qd->buddies, q_bud); - else - purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name); - /* remove buddy on blist, this does not trigger qq_remove_buddy again - * do this only if the request comes from block request, - * otherwise purple segmentation fault */ - if (g_ascii_strcasecmp(group->name, PURPLE_GROUP_QQ_BLOCKED) == 0) - purple_blist_remove_buddy(b); - } + q_bud = (qq_buddy *) buddy->proto_data; + if (q_bud != NULL) + qd->buddies = g_list_remove(qd->buddies, q_bud); + else + purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name); + + /* Do not call purple_blist_remove_buddy, + * otherwise purple segmentation fault */ } -/* free add buddy request queue */ -void qq_add_buddy_request_free(qq_data *qd) -{ - gint count; - qq_add_buddy_request *p; - - count = 0; - while (qd->add_buddy_request != NULL) { - p = (qq_add_buddy_request *) (qd->add_buddy_request->data); - qd->add_buddy_request = g_list_remove(qd->add_buddy_request, p); - g_free(p); - count++; - } - if (count > 0) { - purple_debug_info("QQ", "%d add buddy requests are freed!\n", count); - } -} - -/* free up all qq_buddy */ +/* free all qq_buddy */ void qq_buddies_list_free(PurpleAccount *account, qq_data *qd) { gint count; @@ -555,3 +616,149 @@ purple_debug_info("QQ", "%d qq_buddy structures are freed!\n", count); } } + +/* someone wants to add you to his buddy list */ +static void server_buddy_add_request(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) +{ + gchar *message, *reason; + guint32 uid; + qq_add_request *g, *g2; + PurpleBuddy *b; + gchar *name; + + g_return_if_fail(from != NULL && to != NULL); + + uid = strtol(from, NULL, 10); + g = g_new0(qq_add_request, 1); + g->gc = gc; + g->uid = uid; + + name = uid_to_purple_name(uid); + + /* TODO: this should go through purple_account_request_authorization() */ + message = g_strdup_printf(_("%s wants to add you [%s] as a friend"), from, to); + reason = g_strdup_printf(_("Message: %s"), msg_utf8); + + purple_request_action + (gc, NULL, message, reason, PURPLE_DEFAULT_ACTION_NONE, + purple_connection_get_account(gc), name, NULL, + g, 3, + _("Reject"), + G_CALLBACK(buddy_add_deny_cb), + _("Approve"), + G_CALLBACK(buddy_add_authorize_cb), + _("Search"), G_CALLBACK(buddy_add_check_info_cb)); + + g_free(message); + g_free(reason); + + /* XXX: Is this needed once the above goes through purple_account_request_authorization()? */ + b = purple_find_buddy(gc->account, name); + if (b == NULL) { /* the person is not in my list */ + g2 = g_new0(qq_add_request, 1); + g2->gc = gc; + g2->uid = strtol(from, NULL, 10); + message = g_strdup_printf(_("%s is not in buddy list"), from); + purple_request_action(gc, NULL, message, + _("Would you add?"), PURPLE_DEFAULT_ACTION_NONE, + purple_connection_get_account(gc), name, NULL, + g2, 3, + _("Cancel"), NULL, + _("Add"), G_CALLBACK(buddy_add_no_auth_cb), + _("Search"), G_CALLBACK(buddy_add_check_info_cb)); + g_free(message); + } + + g_free(name); +} + +/* when you are added by a person, QQ server will send sys message */ +static void server_buddy_added(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) +{ + gchar *message; + PurpleBuddy *b; + guint32 uid; + qq_add_request *add_req; + gchar *name; + + g_return_if_fail(from != NULL && to != NULL); + + uid = strtol(from, NULL, 10); + name = uid_to_purple_name(uid); + b = purple_find_buddy(gc->account, name); + + if (b == NULL) { /* the person is not in my list */ + add_req = g_new0(qq_add_request, 1); + add_req->gc = gc; + add_req->uid = uid; /* only need to get value */ + message = g_strdup_printf(_("You have been added by %s"), from); + purple_request_action(gc, NULL, message, + _("Would you like to add him?"), + PURPLE_DEFAULT_ACTION_NONE, + purple_connection_get_account(gc), name, NULL, + add_req, 3, + _("Cancel"), G_CALLBACK(buddy_cancel_cb), + _("Add"), G_CALLBACK(buddy_add_no_auth_cb), + _("Search"), G_CALLBACK(buddy_add_check_info_cb)); + } else { + message = g_strdup_printf(_("%s added you [%s] to buddy list"), from, to); + purple_notify_info(gc, _("QQ Budy"), _("Successed:"), message); + } + + g_free(name); + g_free(message); +} + +/* the buddy approves your request of adding him/her as your friend */ +static void server_buddy_added_me(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) +{ + gchar *message; + qq_data *qd; + + g_return_if_fail(from != NULL && to != NULL); + + qd = (qq_data *) gc->proto_data; + qq_create_buddy(gc, strtol(from, NULL, 10), TRUE, TRUE); + + message = g_strdup_printf(_("Requestion approved by %s"), from); + purple_notify_info(gc, _("QQ Buddy"), _("Notice:"), message); + + g_free(message); +} + +/* you are rejected by the person */ +static void server_buddy_rejected_me(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) +{ + gchar *message, *reason; + + g_return_if_fail(from != NULL && to != NULL); + + message = g_strdup_printf(_("Requestion rejected by %s"), from); + reason = g_strdup_printf(_("Message: %s"), msg_utf8); + + purple_notify_info(gc, _("QQ Buddy"), message, reason); + g_free(message); + g_free(reason); +} + +void qq_process_buddy_from_server(PurpleConnection *gc, int funct, + gchar *from, gchar *to, gchar *msg_utf8) +{ + switch (funct) { + case QQ_SERVER_BUDDY_ADDED: + server_buddy_added(gc, from, to, msg_utf8); + break; + case QQ_SERVER_BUDDY_ADD_REQUEST: + server_buddy_add_request(gc, from, to, msg_utf8); + break; + case QQ_SERVER_BUDDY_ADDED_ME: + server_buddy_added_me(gc, from, to, msg_utf8); + break; + case QQ_SERVER_BUDDY_REJECTED_ME: + server_buddy_rejected_me(gc, from, to, msg_utf8); + break; + default: + purple_debug_warning("QQ", "Unknow buddy operate (%d) from server\n", funct); + break; + } +}