changeset 18703:033b128f7c21

Added unregistering XMPP accounts. This requires a new prpl-struct entry, but I got an ok for that on the mailing list.
author Andreas Monitzer <pidgin@monitzer.com>
date Mon, 30 Jul 2007 00:01:08 +0000
parents 413103ddeaac
children 177552010f1d
files libpurple/account.c libpurple/account.h libpurple/connection.c libpurple/connection.h libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/jabber.h libpurple/protocols/jabber/libxmpp.c libpurple/prpl.h
diffstat 8 files changed, 150 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/account.c	Thu Jul 26 01:32:21 2007 +0000
+++ b/libpurple/account.c	Mon Jul 30 00:01:08 2007 +0000
@@ -932,6 +932,17 @@
 	purple_connection_new(account, TRUE, purple_account_get_password(account));
 }
 
+void
+purple_account_unregister(PurpleAccount *account)
+{
+	g_return_if_fail(account != NULL);
+	
+	purple_debug_info("account", "Unregistering account %s\n",
+					  purple_account_get_username(account));
+	
+	purple_connection_new_unregister(account, purple_account_get_password(account));
+}
+
 static void
 request_password_ok_cb(PurpleAccount *account, PurpleRequestFields *fields)
 {
--- a/libpurple/account.h	Thu Jul 26 01:32:21 2007 +0000
+++ b/libpurple/account.h	Mon Jul 30 00:01:08 2007 +0000
@@ -161,6 +161,13 @@
 void purple_account_register(PurpleAccount *account);
 
 /**
+ * Unregisters an account (deleting it from the server).
+ *
+ * @param account The account to unregister.
+ */
+void purple_account_unregister(PurpleAccount *account);
+
+/**
  * Disconnects from an account.
  *
  * @param account The account to disconnect from.
--- a/libpurple/connection.c	Thu Jul 26 01:32:21 2007 +0000
+++ b/libpurple/connection.c	Mon Jul 30 00:01:08 2007 +0000
@@ -158,6 +158,62 @@
 }
 
 void
+purple_connection_new_unregister(PurpleAccount *account, const char *password)
+{
+	/* Lots of copy/pasted code to avoid API changes. You might want to integrate that into the previous function when posssible. */
+	PurpleConnection *gc;
+	PurplePlugin *prpl;
+	PurplePluginProtocolInfo *prpl_info;
+	
+	g_return_if_fail(account != NULL);
+		
+	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
+	
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+	else {
+		gchar *message;
+		
+		message = g_strdup_printf(_("Missing protocol plugin for %s"),
+								  purple_account_get_username(account));
+		purple_notify_error(NULL, _("Unregistration Error"), message, NULL);
+		g_free(message);
+		return;
+	}
+
+	if (!purple_account_is_disconnected(account)) {
+		prpl_info->unregister_user(account);
+		return;
+	}
+	
+	if (((password == NULL) || (*password == '\0')) &&
+		!(prpl_info->options & OPT_PROTO_NO_PASSWORD) &&
+		!(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
+	{
+		purple_debug_error("connection", "Can not connect to account %s without "
+						   "a password.\n", purple_account_get_username(account));
+		return;
+	}
+	
+	gc = g_new0(PurpleConnection, 1);
+	PURPLE_DBUS_REGISTER_POINTER(gc, PurpleConnection);
+	
+	gc->prpl = prpl;
+	if ((password != NULL) && (*password != '\0'))
+		gc->password = g_strdup(password);
+	purple_connection_set_account(gc, account);
+	purple_connection_set_state(gc, PURPLE_CONNECTING);
+	connections = g_list_append(connections, gc);
+	purple_account_set_connection(account, gc);
+	
+	purple_signal_emit(purple_connections_get_handle(), "signing-on", gc);
+	
+	purple_debug_info("connection", "Unregistering.  gc = %p\n", gc);
+	
+	prpl_info->unregister_user(account);
+}
+
+void
 purple_connection_destroy(PurpleConnection *gc)
 {
 	PurpleAccount *account;
--- a/libpurple/connection.h	Thu Jul 26 01:32:21 2007 +0000
+++ b/libpurple/connection.h	Mon Jul 30 00:01:08 2007 +0000
@@ -134,6 +134,18 @@
 									const char *password);
 
 /**
+ * This function should only be called by purple_account_unregister()
+ * in account.c.
+ *
+ * Tries to unregister the account on the server. If the account is not
+ * connected, also creates a new connection.
+ *
+ * @param account  The account to unregister
+ * @param password The password to use.
+ */
+void purple_connection_new_unregister(PurpleAccount *account, const char *password);
+
+/**
  * Disconnects and destroys a PurpleConnection.
  *
  * This function should only be called by purple_account_disconnect()
--- a/libpurple/protocols/jabber/jabber.c	Thu Jul 26 01:32:21 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Jul 30 00:01:08 2007 +0000
@@ -64,6 +64,8 @@
 static PurplePlugin *my_protocol = NULL;
 GList *jabber_features;
 
+static void jabber_unregister_account_cb(JabberStream *js);
+
 static void jabber_stream_init(JabberStream *js)
 {
 	char *open_stream;
@@ -86,6 +88,8 @@
 	const char *type = xmlnode_get_attrib(packet, "type");
 	if(type && !strcmp(type, "result")) {
 		jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
+		if(js->unregistration)
+			jabber_unregister_account_cb(js);
 	} else {
 		purple_connection_error(js->gc, _("Error initializing session"));
 	}
@@ -1115,6 +1119,56 @@
 	}
 }
 
+static void jabber_unregister_account_iq_cb(JabberStream *js, xmlnode *packet, gpointer data) {
+	const char *type = xmlnode_get_attrib(packet,"type");
+	if(!strcmp(type,"error")) {
+		char *msg = jabber_parse_error(js, packet);
+		
+		purple_notify_error(js->gc, _("Error unregistering account"),
+							_("Error unregistering account"), msg);
+		g_free(msg);
+	} else if(!strcmp(type,"result")) {
+		purple_notify_info(js->gc, _("Account successfully unregistered"),
+						   _("Account successfully unregistered"), NULL);
+	}
+}
+
+static void jabber_unregister_account_cb(JabberStream *js) {
+	JabberIq *iq;
+	xmlnode *query;
+	assert(js->unregistration);
+	
+	iq = jabber_iq_new_query(js,JABBER_IQ_SET,"jabber:iq:register");
+	assert(iq);
+	query = xmlnode_get_child_with_namespace(iq->node,"query","jabber:iq:register");
+	assert(query);
+	xmlnode_new_child(query,"remove");
+	
+	xmlnode_set_attrib(iq->node,"to",js->user->domain);
+	jabber_iq_set_callback(iq,jabber_unregister_account_iq_cb,NULL);
+	
+	jabber_iq_send(iq);
+}
+
+void jabber_unregister_account(PurpleAccount *account) {
+	PurpleConnection *gc = purple_account_get_connection(account);
+	JabberStream *js;
+	
+	if(gc->state != PURPLE_CONNECTED) {
+		if(gc->state != PURPLE_CONNECTING)
+			jabber_login(account);
+		js = gc->proto_data;
+		js->unregistration = TRUE;
+		return;
+	}
+	
+	js = gc->proto_data;
+	assert(!js->unregistration); /* don't allow multiple calls */
+	js->unregistration = TRUE;
+	
+	jabber_unregister_account_cb(js);
+}
+
 void jabber_close(PurpleConnection *gc)
 {
 	JabberStream *js = gc->proto_data;
--- a/libpurple/protocols/jabber/jabber.h	Thu Jul 26 01:32:21 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Mon Jul 30 00:01:08 2007 +0000
@@ -159,6 +159,8 @@
 	GString *sasl_mechs;
 	char *serverFQDN;
 	
+	gboolean unregistration;
+	
 	gboolean vcard_fetched;
 	
 	/* does the local server support PEP? */
@@ -225,6 +227,7 @@
 void jabber_keepalive(PurpleConnection *gc);
 void jabber_register_gateway(JabberStream *js, const char *gateway);
 void jabber_register_account(PurpleAccount *account);
+void jabber_unregister_account(PurpleAccount *account);
 void jabber_convo_closed(PurpleConnection *gc, const char *who);
 PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name);
 gboolean jabber_offline_message(const PurpleBuddy *buddy);
--- a/libpurple/protocols/jabber/libxmpp.c	Thu Jul 26 01:32:21 2007 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Mon Jul 30 00:01:08 2007 +0000
@@ -114,11 +114,11 @@
 	NULL,							/* whiteboard_prpl_ops */
 	jabber_prpl_send_raw,			/* send_raw */
 	jabber_roomlist_room_serialize, /* roomlist_room_serialize */
+	jabber_unregister_account,		/* unregister_user */
 
 	/* padding */
 	NULL,
 	NULL,
-	NULL,
 	NULL
 };
 
--- a/libpurple/prpl.h	Thu Jul 26 01:32:21 2007 +0000
+++ b/libpurple/prpl.h	Mon Jul 30 00:01:08 2007 +0000
@@ -323,11 +323,16 @@
 
 	/* room list serialize */
 	char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room);
+
+	/* Remove the user from the server. (This is only at the bottom to keep binary compatibility.)
+	 * The account can either be connected or disconnected. After the removal is finished,
+	 * the connection will stay open and has to be closed!
+	 */
+	void (*unregister_user)(PurpleAccount *);
 	
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
 	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
 };
 
 #define PURPLE_IS_PROTOCOL_PLUGIN(plugin) \