changeset 27068:faed0a042558

merge of '592b4775fc1de5871564f3b61637c8f5776a3932' and '84f6765b71f2ad2d6c7cddd461114ab5fc758b72'
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sun, 07 Jun 2009 08:13:14 +0000
parents 01c91af62ab3 (current diff) b9c64694999d (diff)
children 08f5c5b12e7c
files
diffstat 6 files changed, 143 insertions(+), 227 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Jun 07 06:19:12 2009 +0000
+++ b/ChangeLog	Sun Jun 07 08:13:14 2009 +0000
@@ -20,6 +20,9 @@
 	  moved to a new network and the old servers are not accessible.
 	* Gadu-Gadu accounts can specify a server to which to connect.
 	  (Krzysztof "kreez" Tobola)
+	* Modifying the MSN privacy list for buddies not added by you (i.e.
+	  spammers and other generally unwanted users) should no longer cause
+	  a 240 error and disconnection.
 
 	XMPP:
 	* Voice & Video support with Jingle (XEP-0166, 0167, 0176, & 0177), voice
--- a/libpurple/protocols/msn/msn.c	Sun Jun 07 06:19:12 2009 +0000
+++ b/libpurple/protocols/msn/msn.c	Sun Jun 07 08:13:14 2009 +0000
@@ -1380,56 +1380,36 @@
 	msn_change_status(session);
 }
 
-#if 0
+/*
+ * Actually adds a buddy once we have the response from FQY
+ */
 static void
-fake_userlist_add_buddy(MsnUserList *userlist,
-					   const char *who, int list_id,
-					   const char *group_name)
+add_pending_buddy(MsnSession *session,
+                  const char *who,
+                  MsnNetwork network,
+                  MsnUser *user)
 {
-	MsnUser *user;
-	static int group_id_c = 1;
-	int group_id;
-
-	group_id = -1;
-
-	if (group_name != NULL)
-	{
-		MsnGroup *group;
-		group = msn_group_new(userlist, group_id_c, group_name);
-		group_id = group_id_c++;
-	}
-
-	user = msn_userlist_find_user(userlist, who);
-
-	if (user == NULL)
-	{
-		user = msn_user_new(userlist, who, NULL);
+	MsnUserList *userlist = session->userlist;
+	MsnUser *user2;
+	char *group;
+
+	g_return_if_fail(user != NULL);
+
+	group = msn_user_remove_pending_group(user);
+
+	user2 = msn_userlist_find_user(userlist, who);
+	if (user2 != NULL) {
+		/* User already in userlist, so just update it. */
+		msn_user_destroy(user);
+		user = user2;
+	} else {
 		msn_userlist_add_user(userlist, user);
 	}
-	else
-		if (user->list_op & (1 << list_id))
-		{
-			if (list_id == MSN_LIST_FL)
-			{
-				if (group_id >= 0)
-					if (g_list_find(user->group_ids,
-									GINT_TO_POINTER(group_id)))
-						return;
-			}
-			else
-				return;
-		}
-
-	if (group_id >= 0)
-	{
-		/* This is wrong... user->group_ids contains g_strdup()'d data now */
-		user->group_ids = g_list_append(user->group_ids,
-										GINT_TO_POINTER(group_id));
-	}
-
-	user->list_op |= (1 << list_id);
+
+	msn_user_set_network(user, network);
+	msn_userlist_add_buddy(userlist, who, group);
+	g_free(group);
 }
-#endif
 
 static void
 msn_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
@@ -1447,23 +1427,11 @@
 	purple_debug_info("msn", "Add user:%s to group:%s\n", who, gname ? gname : "(null)");
 	if (!session->logged_in)
 	{
-#if 0
-		fake_userlist_add_buddy(session->sync_userlist, who, MSN_LIST_FL,
-								group ? group->name : NULL);
-#else
 		purple_debug_error("msn", "msn_add_buddy called before connected\n");
-#endif
 
 		return;
 	}
 
-#if 0
-	if (group != NULL && group->name != NULL)
-		purple_debug_info("msn", "msn_add_buddy: %s, %s\n", who, group->name);
-	else
-		purple_debug_info("msn", "msn_add_buddy: %s\n", who);
-#endif
-
 	/* XXX - Would group ever be NULL here?  I don't think so...
 	 * shx: Yes it should; MSN handles non-grouped buddies, and this is only
 	 * internal. */
@@ -1476,13 +1444,15 @@
 		char **tokens;
 		char *fqy;
 		/* We need to check the network for this buddy first */
-		msn_userlist_save_pending_buddy(userlist, who, gname);
+		user = msn_user_new(userlist, who, NULL);
+		msn_user_set_pending_group(user, gname);
+		msn_user_set_network(user, MSN_NETWORK_UNKNOWN);
 		tokens = g_strsplit(who, "@", 2);
 		fqy = g_strdup_printf("<ml><d n=\"%s\"><c n=\"%s\"/></d></ml>",
 		                      tokens[1],
 		                      tokens[0]);
 		msn_notification_send_fqy(session, fqy, strlen(fqy),
-		                          (MsnFqyCb)msn_userlist_add_pending_buddy);
+		                          (MsnFqyCb)add_pending_buddy, user);
 		g_free(fqy);
 		g_strfreev(tokens);
 	}
--- a/libpurple/protocols/msn/notification.c	Sun Jun 07 06:19:12 2009 +0000
+++ b/libpurple/protocols/msn/notification.c	Sun Jun 07 08:13:14 2009 +0000
@@ -479,6 +479,12 @@
 /**************************************************************************
  * Buddy Lists
  **************************************************************************/
+
+typedef struct MsnFqyCbData {
+	MsnFqyCb cb;
+	gpointer data;
+} MsnFqyCbData;
+
 /* add contact to xmlnode */
 static void
 msn_add_contact_xml(MsnSession *session, xmlnode *mlNode,const char *passport, MsnListOp list_op, MsnNetwork networkId)
@@ -551,24 +557,40 @@
 	msn_cmdproc_send_trans(cmdproc, trans);
 }
 
+static void
+msn_notification_post_rml(MsnCmdProc *cmdproc, const char *payload, int payload_len)
+{
+	MsnTransaction *trans;
+	purple_debug_info("msn", "Sending RML with payload: %s\n", payload);
+	trans = msn_transaction_new(cmdproc, "RML", "%i", payload_len);
+	msn_transaction_set_payload(trans, payload, payload_len);
+	msn_cmdproc_send_trans(cmdproc, trans);
+}
+
 void
 msn_notification_send_fqy(MsnSession *session,
                           const char *payload, int payload_len,
-                          MsnFqyCb cb)
+                          MsnFqyCb cb,
+                          gpointer cb_data)
 {
 	MsnTransaction *trans;
 	MsnCmdProc *cmdproc;
+	MsnFqyCbData *data;
 
 	cmdproc = session->notification->cmdproc;
 
+	data = g_new(MsnFqyCbData, 1);
+	data->cb = cb;
+	data->data = cb_data;
+
 	trans = msn_transaction_new(cmdproc, "FQY", "%d", payload_len);
 	msn_transaction_set_payload(trans, payload, payload_len);
-	msn_transaction_set_data(trans, cb);
+	msn_transaction_set_data(trans, data);
 	msn_cmdproc_send_trans(cmdproc, trans);
 }
 
 static void
-update_contact_network(MsnSession *session, const char *passport, MsnNetwork network)
+update_contact_network(MsnSession *session, const char *passport, MsnNetwork network, gpointer unused)
 {
 	MsnUser *user;
 
@@ -684,7 +706,7 @@
 				payload = xmlnode_to_str(fqy_node, &payload_len);
 
 				msn_notification_send_fqy(session, payload, payload_len,
-				                          update_contact_network);
+				                          update_contact_network, NULL);
 
 				g_free(payload);
 				xmlnode_free(fqy_node);
@@ -709,7 +731,7 @@
 		payload = xmlnode_to_str(fqy_node, &payload_len);
 
 		msn_notification_send_fqy(session, payload, payload_len,
-		                          update_contact_network);
+		                          update_contact_network, NULL);
 
 		g_free(payload);
 	}
@@ -926,8 +948,13 @@
 
 			purple_debug_info("msn", "FQY response says %s is from network %d\n",
 			                  passport, network);
-			if (cmd->trans->data)
-				((MsnFqyCb)cmd->trans->data)(session, passport, network);
+			if (cmd->trans->data) {
+				MsnFqyCbData *fqy_data = cmd->trans->data;
+				fqy_data->cb(session, passport, network, fqy_data->data);
+				/* TODO: This leaks, but the server responds to FQY multiple times, so we
+				         can't free it yet. We need to figure out somewhere else to do so.
+				g_free(fqy_data); */
+			}
 
 			g_free(passport);
 		}
@@ -952,7 +979,7 @@
 	   FQY error, it's probably going to disconnect us. So it isn't necessary
 	   to tell the handler about it. */
 	else if (trans->data)
-		((MsnFqyCb)trans->data)(session, NULL, MSN_NETWORK_UNKNOWN); */
+		((MsnFqyCb)trans->data)(session, NULL, MSN_NETWORK_UNKNOWN, NULL);
 #endif
 }
 
@@ -981,85 +1008,6 @@
 }
 
 static void
-add_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
-{
-	MsnSession *session;
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	const char *list, *passport;
-	char *reason = NULL;
-	char *msg = NULL;
-	char **params;
-
-	session = cmdproc->session;
-	account = session->account;
-	gc = purple_account_get_connection(account);
-	params = g_strsplit(trans->params, " ", 0);
-
-	list     = params[0];
-	passport = params[1];
-
-	if (!strcmp(list, "FL"))
-		msg = g_strdup_printf(_("Unable to add user on %s (%s)"),
-							  purple_account_get_username(account),
-							  purple_account_get_protocol_name(account));
-	else if (!strcmp(list, "BL"))
-		msg = g_strdup_printf(_("Unable to block user on %s (%s)"),
-							  purple_account_get_username(account),
-							  purple_account_get_protocol_name(account));
-	else if (!strcmp(list, "AL"))
-		msg = g_strdup_printf(_("Unable to permit user on %s (%s)"),
-							  purple_account_get_username(account),
-							  purple_account_get_protocol_name(account));
-
-	if (!strcmp(list, "FL"))
-	{
-		if (error == 210)
-		{
-			reason = g_strdup_printf(_("%s could not be added because "
-									   "your buddy list is full."), passport);
-		}
-	}
-
-	if (reason == NULL)
-	{
-		if (error == 208)
-		{
-			reason = g_strdup_printf(_("%s is not a valid passport account."),
-									 passport);
-		}
-		else if (error == 500)
-		{
-			reason = g_strdup(_("Service Temporarily Unavailable."));
-		}
-		else
-		{
-			reason = g_strdup(_("Unknown error."));
-		}
-	}
-
-	if (msg != NULL)
-	{
-		purple_notify_error(gc, NULL, msg, reason);
-		g_free(msg);
-	}
-
-	if (!strcmp(list, "FL"))
-	{
-		PurpleBuddy *buddy;
-
-		buddy = purple_find_buddy(account, passport);
-
-		if (buddy != NULL)
-			purple_blist_remove_buddy(buddy);
-	}
-
-	g_free(reason);
-
-	g_strfreev(params);
-}
-
-static void
 qng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	/* TODO: Call PNG after the timeout specified. */
@@ -1946,10 +1894,54 @@
 	g_hash_table_destroy(table);
 }
 
+/**************************************************************************
+ * Dispatch server list management 
+ **************************************************************************/
+typedef struct MsnAddRemoveListData {
+	MsnCmdProc *cmdproc;
+	MsnUser *user;
+	MsnListOp list_op;
+	gboolean add;
+} MsnAddRemoveListData;
+
+static void
+modify_unknown_buddy_on_list(MsnSession *session, const char *passport,
+                             MsnNetwork network, gpointer data)
+{
+	MsnAddRemoveListData *addrem = data;
+	MsnCmdProc *cmdproc;
+	xmlnode *node;
+	char *payload;
+	int payload_len;
+
+	cmdproc = addrem->cmdproc;
+
+	/* Update user first */
+	msn_user_set_network(addrem->user, network);
+
+	node = xmlnode_new("ml");
+	node->child = NULL;
+
+	msn_add_contact_xml(session, node, passport,
+	                    addrem->list_op, network);
+
+	payload = xmlnode_to_str(node, &payload_len);
+	xmlnode_free(node);
+
+	if (addrem->add)
+		msn_notification_post_adl(cmdproc, payload, payload_len);
+	else
+		msn_notification_post_rml(cmdproc, payload, payload_len);
+
+	g_free(payload);
+	g_free(addrem);
+}
+
 void
 msn_notification_add_buddy_to_list(MsnNotification *notification, MsnListId list_id,
 							  MsnUser *user)
 {
+	MsnAddRemoveListData *addrem;
 	MsnCmdProc *cmdproc;
 	MsnListOp list_op = 1 << list_id;
 	xmlnode *adl_node;
@@ -1964,11 +1956,23 @@
 	msn_add_contact_xml(notification->session, adl_node, user->passport,
 	                    list_op, user->networkid);
 
-	payload = xmlnode_to_str(adl_node,&payload_len);
+	payload = xmlnode_to_str(adl_node, &payload_len);
 	xmlnode_free(adl_node);
 
-	msn_notification_post_adl(notification->servconn->cmdproc,
-						payload,payload_len);
+	if (user->networkid != MSN_NETWORK_UNKNOWN) {
+		msn_notification_post_adl(cmdproc, payload, payload_len);
+
+	} else {
+		addrem = g_new(MsnAddRemoveListData, 1);
+		addrem->cmdproc = cmdproc;
+		addrem->user = user;
+		addrem->list_op = list_op;
+		addrem->add = TRUE;
+
+		msn_notification_send_fqy(notification->session, payload, payload_len,
+		                          modify_unknown_buddy_on_list, addrem);
+	}
+
 	g_free(payload);
 }
 
@@ -1976,8 +1980,8 @@
 msn_notification_rem_buddy_from_list(MsnNotification *notification, MsnListId list_id,
 						   MsnUser *user)
 {
+	MsnAddRemoveListData *addrem;
 	MsnCmdProc *cmdproc;
-	MsnTransaction *trans;
 	MsnListOp list_op = 1 << list_id;
 	xmlnode *rml_node;
 	char *payload;
@@ -1994,10 +1998,20 @@
 	payload = xmlnode_to_str(rml_node, &payload_len);
 	xmlnode_free(rml_node);
 
-	purple_debug_info("msn", "Send RML with payload:\n%s\n", payload);
-	trans = msn_transaction_new(cmdproc, "RML","%" G_GSIZE_FORMAT, strlen(payload));
-	msn_transaction_set_payload(trans, payload, strlen(payload));
-	msn_cmdproc_send_trans(cmdproc, trans);
+	if (user->networkid != MSN_NETWORK_UNKNOWN) {
+		msn_notification_post_rml(cmdproc, payload, payload_len);
+
+	} else {
+		addrem = g_new(MsnAddRemoveListData, 1);
+		addrem->cmdproc = cmdproc;
+		addrem->user = user;
+		addrem->list_op = list_op;
+		addrem->add = FALSE;
+
+		msn_notification_send_fqy(notification->session, payload, payload_len,
+		                          modify_unknown_buddy_on_list, addrem);
+	}
+
 	g_free(payload);
 }
 
@@ -2052,7 +2066,6 @@
 
 	msn_table_add_cmd(cbs_table, NULL, "241", adl_241_error_cmd);
 
-	msn_table_add_error(cbs_table, "ADD", add_error);
 	msn_table_add_error(cbs_table, "ADL", adl_error);
 	msn_table_add_error(cbs_table, "FQY", fqy_error);
 	msn_table_add_error(cbs_table, "USR", usr_error);
--- a/libpurple/protocols/msn/notification.h	Sun Jun 07 06:19:12 2009 +0000
+++ b/libpurple/protocols/msn/notification.h	Sun Jun 07 08:13:14 2009 +0000
@@ -58,7 +58,7 @@
 	gboolean in_use;
 };
 
-typedef void (*MsnFqyCb)(MsnSession *session, const char *passport, MsnNetwork network);
+typedef void (*MsnFqyCb)(MsnSession *session, const char *passport, MsnNetwork network, gpointer data);
 
 #include "state.h"
 void uum_send_msg(MsnSession *session,MsnMessage *msg);
@@ -73,7 +73,7 @@
 
 void msn_notification_send_fqy(MsnSession *session,
                                const char *payload, int payload_len,
-                               MsnFqyCb cb);
+                               MsnFqyCb cb, gpointer cb_data);
 
 MsnNotification *msn_notification_new(MsnSession *session);
 void msn_notification_destroy(MsnNotification *notification);
--- a/libpurple/protocols/msn/userlist.c	Sun Jun 07 06:19:12 2009 +0000
+++ b/libpurple/protocols/msn/userlist.c	Sun Jun 07 08:13:14 2009 +0000
@@ -601,69 +601,6 @@
 	msn_add_contact_to_group(userlist->session, state, who, group_id);
 }
 
-/*
- * Save a buddy address/group until we get back response from FQY
- */
-void
-msn_userlist_save_pending_buddy(MsnUserList *userlist,
-                               const char *who,
-                               const char *group_name)
-{
-	MsnUser *user;
-
-	g_return_if_fail(userlist != NULL);
-
-	user = msn_user_new(userlist, who, NULL);
-	msn_user_set_pending_group(user, group_name);
-	msn_user_set_network(user, MSN_NETWORK_UNKNOWN);
-	userlist->pending = g_list_prepend(userlist->pending, user);
-}
-
-/*
- * Actually adds a buddy once we have the response from FQY
- */
-void
-msn_userlist_add_pending_buddy(MsnSession *session,
-                               const char *who,
-                               /*MsnNetwork*/ int network)
-{
-	MsnUserList *userlist = session->userlist;
-	MsnUser *user = NULL;
-	MsnUser *user2;
-	GList *l;
-	char *group;
-
-	for (l = userlist->pending; l != NULL; l = l->next)
-	{
-		user = (MsnUser *)l->data;
-
-		if (!g_ascii_strcasecmp(who, user->passport)) {
-			userlist->pending = g_list_delete_link(userlist->pending, l);
-			break;
-		}
-	}
-
-	if (user == NULL) {
-		purple_debug_error("msn", "Attempting to add a pending user that does not exist.\n");
-		return;
-	}
-
-	group = msn_user_remove_pending_group(user);
-
-	user2 = msn_userlist_find_user(userlist, who);
-	if (user2 != NULL) {
-		/* User already in userlist, so just update it. */
-		msn_user_destroy(user);
-		user = user2;
-	} else {
-		msn_userlist_add_user(userlist, user);
-	}
-
-	msn_user_set_network(user, network);
-	msn_userlist_add_buddy(userlist, who, group);
-	g_free(group);
-}
-
 void
 msn_userlist_add_buddy_to_list(MsnUserList *userlist, const char *who,
 							MsnListId list_id)
--- a/libpurple/protocols/msn/userlist.h	Sun Jun 07 06:19:12 2009 +0000
+++ b/libpurple/protocols/msn/userlist.h	Sun Jun 07 08:13:14 2009 +0000
@@ -47,7 +47,6 @@
 
 	GList *users; /* Contains MsnUsers */
 	GList *groups; /* Contains MsnGroups */
-	GList *pending; /* MsnUsers pending addition (waiting for FQY response) */
 
 	GQueue *buddy_icon_requests;
 	int buddy_icon_window;
@@ -87,12 +86,6 @@
 void msn_userlist_rem_buddy(MsnUserList *userlist, const char *who);
 void msn_userlist_add_buddy(MsnUserList *userlist,
 			    const char *who, const char *group_name);
-void msn_userlist_save_pending_buddy(MsnUserList *userlist,
-                                     const char *who,
-                                     const char *group_name);
-void msn_userlist_add_pending_buddy(MsnSession *session,
-                                    const char *who,
-                                    /*MsnNetwork*/ int network);
 void msn_userlist_move_buddy(MsnUserList *userlist, const char *who,
 						    const char *old_group_name,
 						    const char *new_group_name);