diff libpurple/protocols/qq/buddy_opt.c @ 24161:7c0a56c5fea0

2008.10.14 - ccpaging <ccpaging(at)gmail.com> * 2007 remove buddy ok * Removed group_search.c/h
author SHiNE CsyFeK <csyfek@gmail.com>
date Tue, 28 Oct 2008 16:44:09 +0000
parents d35672443baa
children f4f29fac96c6
line wrap: on
line diff
--- a/libpurple/protocols/qq/buddy_opt.c	Tue Oct 28 16:42:46 2008 +0000
+++ b/libpurple/protocols/qq/buddy_opt.c	Tue Oct 28 16:44:09 2008 +0000
@@ -42,7 +42,6 @@
 #define PURPLE_GROUP_QQ_FORMAT          "QQ (%s)"
 
 #define QQ_REMOVE_SELF_REPLY_OK       0x00
-#define QQ_ADD_BUDDY_AUTH_REPLY_OK    0x30	/* ASCII value of "0" */
 
 enum {
 	QQ_MY_AUTH_APPROVE = 0x30,	/* ASCII value of "0" */
@@ -202,6 +201,82 @@
 	qq_send_cmd_mess(gc, QQ_CMD_BUDDY_REMOVE, (guint8 *) uid_str, bytes, 0, uid);
 }
 
+static void request_buddy_remove_2007(PurpleConnection *gc,
+		guint32 uid, guint8 *auth, guint8 auth_len)
+{
+	gint bytes;
+	guint8 *raw_data;
+	gchar uid_str[16];
+
+	g_return_if_fail(uid != 0);
+	g_return_if_fail(auth != NULL && auth_len > 0);
+
+	raw_data = g_newa(guint8, auth_len + sizeof(uid_str) );
+	bytes = 0;
+	bytes += qq_put8(raw_data + bytes, auth_len);
+	bytes += qq_putdata(raw_data + bytes, auth, auth_len);
+
+	g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
+	bytes += qq_putdata(raw_data + bytes, (guint8 *)uid_str, strlen(uid_str));
+
+	qq_send_cmd_mess(gc, QQ_CMD_BUDDY_REMOVE, raw_data, bytes, 0, uid);
+}
+
+void qq_request_auth_info(PurpleConnection *gc, guint8 cmd, guint16 sub_cmd, guint32 uid)
+{
+	guint8 raw_data[16];
+	gint bytes;
+
+	g_return_if_fail(uid > 0);
+	bytes = 0;
+	bytes += qq_put8(raw_data + bytes, cmd);
+	bytes += qq_put16(raw_data + bytes, sub_cmd);
+	bytes += qq_put32(raw_data + bytes, uid);
+
+	qq_send_cmd_mess(gc, QQ_CMD_AUTH_INFO, raw_data, bytes, 0, uid);
+}
+
+void qq_process_auth_info(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid)
+{
+	qq_data *qd;
+	gint bytes;
+	guint8 cmd, reply;
+	guint16 sub_cmd;
+	guint8 *auth = NULL;
+	guint8 auth_len = 0;
+
+	g_return_if_fail(data != NULL && data_len != 0);
+	g_return_if_fail(uid != 0);
+
+	qd = (qq_data *) gc->proto_data;
+
+	qq_show_packet("qq_process_auth_info", data, data_len);
+	bytes = 0;
+	bytes += qq_get8(&cmd, data + bytes);
+	bytes += qq_get16(&sub_cmd, data + bytes);
+	bytes += qq_get8(&reply, data + bytes);
+	if (bytes + 2 <= data_len) {
+		bytes += 1;	/* skip 1 byte, 0x00 */
+		bytes += qq_get8(&auth_len, data + bytes);
+		if (auth_len > 0) {
+			g_return_if_fail(bytes + auth_len <= data_len);
+			auth = g_newa(guint8, auth_len);
+			bytes += qq_getdata(auth, auth_len, data + bytes);
+		}
+	} else {
+		qq_show_packet("No auth info", data, data_len);
+	}
+
+	if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_REMOVE_BUDDY) {
+		g_return_if_fail(auth != NULL && auth_len > 0);
+		request_buddy_remove_2007(gc, uid, auth, auth_len);
+	}
+	if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_ADD_BUDDY) {
+	}
+	purple_debug_info("QQ", "Got auth info cmd 0x%x, sub 0x%x, reply 0x%x\n",
+			cmd, sub_cmd, reply);
+}
+
 /* try to remove myself from someone's buddy list */
 static void request_buddy_remove_me(PurpleConnection *gc, guint32 uid)
 {
@@ -280,11 +355,18 @@
 	g_free(add_req);
 }
 
-/* we approve other's request of adding me as friend */
-static void buddy_add_authorize_cb(qq_buddy_req *add_req)
+static void buddy_add_deny_noreason_cb(qq_buddy_req *add_req)
 {
+	buddy_add_deny_reason_cb(add_req, NULL);
+}
+
+/* we approve other's request of adding me as friend */
+static void buddy_add_authorize_cb(gpointer data)
+{
+	qq_buddy_req *add_req = (qq_buddy_req *)data;
+
 	g_return_if_fail(add_req != NULL);
-	if (add_req->gc == NULL || add_req->uid != 0) {
+	if (add_req->gc == NULL || add_req->uid == 0) {
 		g_free(add_req);
 		return;
 	}
@@ -294,61 +376,17 @@
 }
 
 /* we reject other's request of adding me as friend */
-static void buddy_add_deny_cb(qq_buddy_req *add_req)
+static void buddy_add_deny_cb(gpointer data)
 {
-	gint uid;
-	gchar *msg1, *msg2;
-	PurpleConnection *gc;
-	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;
-
-	msg1 = g_strdup_printf(_("You rejected %d's request"), uid);
-	msg2 = g_strdup(_("Message:"));
-
-	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(buddy_add_deny_reason_cb), _("Cancel"), NULL,
-			purple_connection_get_account(gc), purple_name, NULL,
+	qq_buddy_req *add_req = (qq_buddy_req *)data;
+	gchar *who = uid_to_purple_name(add_req->uid);
+	purple_request_input(add_req->gc, NULL, _("Authorization denied message:"),
+			NULL, _("Sorry, You are not my style."), TRUE, FALSE, NULL,
+			_("OK"), G_CALLBACK(buddy_add_deny_reason_cb),
+			_("Cancel"), G_CALLBACK(buddy_add_deny_noreason_cb),
+			purple_connection_get_account(add_req->gc), who, NULL,
 			add_req);
-	g_free(purple_name);
-}
-
-/* suggested by rakescar@linuxsir, can still approve after search */
-static void buddy_add_check_info_cb(qq_buddy_req *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);
+	g_free(who);
 }
 
 /* add a buddy and send packet to QQ server
@@ -410,17 +448,18 @@
 
 	qd = (qq_data *) gc->proto_data;
 
-	if (data[0] != QQ_ADD_BUDDY_AUTH_REPLY_OK) {
-		if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) {
-			purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), NULL);
-			return;
-		}
-		msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT);
-		purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), msg_utf8);
-		g_free(msg_utf8);
-	} else {
-		qq_got_attention(gc, _("Successed sending authorize"));
+	if (data[0] == '0') {
+		purple_debug_info("QQ", "Reply OK for sending authorize\n");
+		return;
 	}
+
+	if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) {
+		purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), NULL);
+		return;
+	}
+	msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT);
+	purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), msg_utf8);
+	g_free(msg_utf8);
 }
 
 /* process the server reply for my request to remove a buddy */
@@ -436,19 +475,14 @@
 	if (data[0] != 0) {
 		msg = g_strdup_printf(_("Failed removing buddy %d"), uid);
 		purple_notify_info(gc, _("QQ Buddy"), msg, NULL);
-		if (buddy == NULL) {
-			/* Add buddy with no-auth */
-			qq_buddy_new(gc, uid);
-		}
-	} else {
-		msg = g_strdup_printf(_("Successed removing buddy %d"), uid);
-		qq_got_attention(gc, _("Successed removing budy."));
-		if (buddy != NULL) {
-			/* remove buddy again */
-			qq_buddy_free(buddy);
-		}
+		g_free(msg);
 	}
-	g_free(msg);
+
+	purple_debug_info("QQ", "Reply OK for removing buddy\n");
+	/* remove buddy again */
+	if (buddy != NULL) {
+		qq_buddy_free(buddy);
+	}
 }
 
 /* process the server reply for my request to remove myself from a buddy */
@@ -460,13 +494,12 @@
 	g_return_if_fail(data != NULL && data_len != 0);
 	qd = (qq_data *) gc->proto_data;
 
-	if (data[0] != 0) {
-		msg = g_strdup_printf(_("Failed removing me from %d's buddy list"), uid);
-		purple_notify_info(gc, _("QQ Buddy"), msg, NULL);
-	} else {
-		msg = g_strdup_printf(_("Successed removing me from %d's buddy list"), uid);
-		qq_got_attention(gc, msg);
+	if (data[0] == 0) {
+		purple_debug_info("QQ", "Reply OK for removing me from %d's buddy list\n", uid);
+		return;
 	}
+	msg = g_strdup_printf(_("Failed removing me from %d's buddy list"), uid);
+	purple_notify_info(gc, _("QQ Buddy"), msg, NULL);
 	g_free(msg);
 }
 
@@ -482,7 +515,7 @@
 
 	qd = (qq_data *) gc->proto_data;
 
-	if (uid == 0) {	/* we have no record for this */
+	if (uid == 0) {
 		purple_debug_error("QQ", "Process buddy add, unknow id\n");
 		return;
 	}
@@ -512,9 +545,7 @@
 		}
 		qq_request_get_buddies_online(gc, 0, 0);
 
-		msg = g_strdup_printf(_("Successed adding into %d's buddy list"), uid);
-		qq_got_attention(gc, msg);
-		g_free(msg);
+		purple_debug_info("QQ", "Successed adding into %d's buddy list", uid);
 		g_strfreev(segments);
 		return;
 	}
@@ -538,10 +569,10 @@
 	add_req->uid = uid;
 	msg = g_strdup_printf(_("%d needs authentication"), uid);
 	purple_request_input(gc, _("Add buddy authorize"), msg,
-			_("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */
+			_("Input request here"),
 			_("Would you be my friend?"),
-			TRUE, FALSE, NULL, _("Send"),
-			G_CALLBACK(request_buddy_add_auth_cb),
+			TRUE, FALSE, NULL,
+			_("Send"), G_CALLBACK(request_buddy_add_auth_cb),
 			_("Cancel"), G_CALLBACK(buddy_cancel_cb),
 			purple_connection_get_account(gc), who, NULL,
 			add_req);
@@ -565,9 +596,13 @@
 		return;
 
 	uid = purple_name_to_uid(buddy->name);
-	if (uid > 0) {
-		request_buddy_remove(gc, uid);
-		request_buddy_remove_me(gc, uid);
+	if (uid > 0 && uid != qd->uid) {
+		if (qd->client_version > 2005) {
+			qq_request_auth_info(gc, QQ_AUTH_INFO_BUDDY, QQ_AUTH_INFO_REMOVE_BUDDY, uid);
+		} else {
+			request_buddy_remove(gc, uid);
+			request_buddy_remove_me(gc, uid);
+		}
 	}
 
 	if (buddy->proto_data) {
@@ -582,99 +617,85 @@
 }
 
 /* someone wants to add you to his buddy list */
-static void server_buddy_add_request(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8)
+static void server_buddy_add_request(PurpleConnection *gc, gchar *from, gchar *to,
+		guint8 *data, gint data_len)
 {
-	gchar *message, *reason;
+	PurpleAccount *account = purple_connection_get_account(gc);
+	qq_buddy_req *add_req;
+	gchar *who;
+	gchar *msg, *reason;
+
+	g_return_if_fail(from != NULL && to != NULL);
+
+	add_req = g_new0(qq_buddy_req, 1);
+	add_req->gc = gc;
+	add_req->uid = strtol(from, NULL, 10);;
+
+	if (purple_prefs_get_bool("/plugins/prpl/qq/auto_get_authorize_info")) {
+		qq_request_buddy_info(gc, add_req->uid, 0, QQ_BUDDY_INFO_DISPLAY);
+	}
+	who = uid_to_purple_name(add_req->uid);
+
+	if (data_len <= 0) {
+		reason = g_strdup( _("No reason given") );
+	} else {
+		msg = g_strndup((gchar *)data, data_len);
+		reason = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
+		if (reason == NULL)	reason = g_strdup( _("Unknown reason") );
+		g_free(msg);
+	}
+	purple_account_request_authorization(account,
+	 		from, NULL,
+			NULL, reason,
+			purple_find_buddy(account, who) != NULL,
+			buddy_add_authorize_cb,
+			buddy_add_deny_cb,
+			add_req);
+
+	g_free(reason);
+	g_free(who);
+}
+
+/* when you are added by a person, QQ server will send sys message */
+static void server_buddy_added(PurpleConnection *gc, gchar *from, gchar *to,
+		guint8 *data, gint data_len)
+{
+	PurpleAccount *account = purple_connection_get_account(gc);
+	PurpleBuddy *buddy;
 	guint32 uid;
-	qq_buddy_req *g, *g2;
-	PurpleBuddy *b;
-	gchar *name;
+	qq_buddy_req *add_req;
+	gchar *who;
+	gchar *primary;
 
 	g_return_if_fail(from != NULL && to != NULL);
 
 	uid = strtol(from, NULL, 10);
-	g = g_new0(qq_buddy_req, 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);
+	who = uid_to_purple_name(uid);
 
-	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_buddy_req, 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);
+	buddy = purple_find_buddy(account, who);
+	if (buddy != NULL) {
+		purple_account_notify_added(account, from, to, NULL, NULL);
 	}
 
-	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_buddy_req *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);
+	add_req = g_new0(qq_buddy_req, 1);
+	add_req->gc = gc;
+	add_req->uid = uid;	/* only need to get value */
+	primary = g_strdup_printf(_("You have been added by %s"), from);
+	purple_request_action(gc, NULL, primary,
+			_("Would you like to add him?"),
+			PURPLE_DEFAULT_ACTION_NONE,
+			purple_connection_get_account(gc), who, NULL,
+			add_req, 2,
+			_("Cancel"), G_CALLBACK(buddy_cancel_cb),
+			_("Add"), G_CALLBACK(buddy_add_no_auth_cb));
 
-	if (b == NULL) {	/* the person is not in my list */
-		add_req = g_new0(qq_buddy_req, 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(_("Successed adding into %s's buddy list"), from);
-		qq_got_attention(gc, message);
-	}
-
-	g_free(name);
-	g_free(message);
+	g_free(who);
+	g_free(primary);
 }
 
 /* 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)
+static void server_buddy_added_me(PurpleConnection *gc, gchar *from, gchar *to,
+		guint8 *data, gint data_len)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
 	qq_data *qd;
@@ -696,28 +717,43 @@
 		qq_request_get_level(gc, uid);
 	}
 
-	purple_account_notify_added(account, from, to, NULL, msg_utf8);
+	purple_account_notify_added(account, to, from, NULL, NULL);
 }
 
 /* you are rejected by the person */
-static void server_buddy_rejected_me(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8)
+static void server_buddy_rejected_me(PurpleConnection *gc, gchar *from, gchar *to,
+		guint8 *data, gint data_len)
 {
-	gchar *message, *reason;
 	guint32 uid;
 	PurpleBuddy *buddy;
+	gchar *msg, *msg_utf8;
+	gchar *primary, *secondary;
 
 	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);
+	if (data_len <= 0) {
+		msg = g_strdup( _("No reason given") );
+	} else {
+		msg = g_strndup((gchar *)data, data_len);
+	}
+	msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
+	if (msg_utf8 == NULL) {
+		msg_utf8 = g_strdup( _("Unknown reason") );
+	}
+	g_free(msg);
 
-	purple_notify_info(gc, _("QQ Buddy"), message, reason);
-	g_free(message);
-	g_free(reason);
-	
+	primary = g_strdup_printf(_("Rejected by %s"), from);
+	secondary = g_strdup_printf(_("Message: %s"), msg_utf8);
+
+	purple_notify_info(gc, _("QQ Buddy"), primary, secondary);
+
+	g_free(msg_utf8);
+	g_free(primary);
+	g_free(secondary);
+
 	uid = strtol(from, NULL, 10);
 	g_return_if_fail(uid != 0);
-	
+
 	buddy = qq_buddy_find(gc, uid);
 	if (buddy != NULL && buddy->proto_data != NULL) {
 		/* Not authorized now, free buddy data */
@@ -727,20 +763,23 @@
 }
 
 void qq_process_buddy_from_server(PurpleConnection *gc, int funct,
-		gchar *from, gchar *to, gchar *msg_utf8)
+		gchar *from, gchar *to, guint8 *data, gint data_len)
 {
 	switch (funct) {
 	case QQ_SERVER_BUDDY_ADDED:
-		server_buddy_added(gc, from, to, msg_utf8);
+		server_buddy_added(gc, from, to, data, data_len);
 		break;
 	case QQ_SERVER_BUDDY_ADD_REQUEST:
-		server_buddy_add_request(gc, from, to, msg_utf8);
+		server_buddy_add_request(gc, from, to, data, data_len);
+		break;
+	case QQ_MSG_SYS_ADD_FRIEND_REQUEST_EX:
+		// server_buddy_add_request_ex(gc, from, to, data, data_len);
 		break;
 	case QQ_SERVER_BUDDY_ADDED_ME:
-		server_buddy_added_me(gc, from, to, msg_utf8);
+		server_buddy_added_me(gc, from, to, data, data_len);
 		break;
 	case QQ_SERVER_BUDDY_REJECTED_ME:
-		server_buddy_rejected_me(gc, from, to, msg_utf8);
+		server_buddy_rejected_me(gc, from, to, data, data_len);
 		break;
 	default:
 		purple_debug_warning("QQ", "Unknow buddy operate (%d) from server\n", funct);