libpurple/protocols/jabber/xmpp.c

branch
soc.2013.gobjectification.plugins
changeset 36665
5bef44ba334a
parent 36653
4084c34c051d
child 36668
15719256474a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/jabber/xmpp.c	Wed Sep 04 01:21:18 2013 +0530
@@ -0,0 +1,228 @@
+/* purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ *
+ */
+
+/* libxmpp is the XMPP protocol plugin. It is linked against libjabbercommon,
+ * which may be used to support other protocols (Bonjour) which may need to
+ * share code.
+ */
+
+#include "internal.h"
+#include "chat.h"
+#include "core.h"
+#include "plugins.h"
+
+#include "xmpp.h"
+
+static PurpleProtocol *my_protocol = NULL;
+
+static PurpleAccount *find_acct(const char *protocol, const char *acct_id)
+{
+	PurpleAccount *acct = NULL;
+
+	/* If we have a specific acct, use it */
+	if (acct_id) {
+		acct = purple_accounts_find(acct_id, protocol);
+		if (acct && !purple_account_is_connected(acct))
+			acct = NULL;
+	} else { /* Otherwise find an active account for the protocol */
+		GList *l = purple_accounts_get_all();
+		while (l) {
+			if (!strcmp(protocol, purple_account_get_protocol_id(l->data))
+					&& purple_account_is_connected(l->data)) {
+				acct = l->data;
+				break;
+			}
+			l = l->next;
+		}
+	}
+
+	return acct;
+}
+
+static gboolean xmpp_uri_handler(const char *proto, const char *user, GHashTable *params)
+{
+	char *acct_id = params ? g_hash_table_lookup(params, "account") : NULL;
+	PurpleAccount *acct;
+
+	if (g_ascii_strcasecmp(proto, "xmpp"))
+		return FALSE;
+
+	acct = find_acct(purple_protocol_get_id(my_protocol), acct_id);
+
+	if (!acct)
+		return FALSE;
+
+	/* xmpp:romeo@montague.net?message;subject=Test%20Message;body=Here%27s%20a%20test%20message */
+	/* params is NULL if the URI has no '?' (or anything after it) */
+	if (!params || g_hash_table_lookup_extended(params, "message", NULL, NULL)) {
+		char *body = g_hash_table_lookup(params, "body");
+		if (user && *user) {
+			PurpleIMConversation *im =
+					purple_im_conversation_new(acct, user);
+			purple_conversation_present(PURPLE_CONVERSATION(im));
+			if (body && *body)
+				purple_conversation_send_confirm(PURPLE_CONVERSATION(im), body);
+		}
+	} else if (g_hash_table_lookup_extended(params, "roster", NULL, NULL)) {
+		char *name = g_hash_table_lookup(params, "name");
+		if (user && *user)
+			purple_blist_request_add_buddy(acct, user, NULL, name);
+	} else if (g_hash_table_lookup_extended(params, "join", NULL, NULL)) {
+		PurpleConnection *gc = purple_account_get_connection(acct);
+		if (user && *user) {
+			GHashTable *params = jabber_chat_info_defaults(gc, user);
+			jabber_chat_join(gc, params);
+		}
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+xmpp_protocol_base_init(XMPPProtocolClass *klass)
+{
+	PurpleProtocolClass *proto_class = PURPLE_PROTOCOL_CLASS(klass);
+	PurpleAccountUserSplit *split;
+	PurpleAccountOption *option;
+	GList *encryption_values = NULL;
+
+	/* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */
+	split = purple_account_user_split_new(_("Domain"), NULL, '@');
+	purple_account_user_split_set_reverse(split, FALSE);
+	proto_class->user_splits = g_list_append(proto_class->user_splits, split);
+
+	split = purple_account_user_split_new(_("Resource"), "", '/');
+	purple_account_user_split_set_reverse(split, FALSE);
+	proto_class->user_splits = g_list_append(proto_class->user_splits, split);
+
+#define ADD_VALUE(list, desc, v) { \
+	PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
+	kvp->key = g_strdup((desc)); \
+	kvp->value = g_strdup((v)); \
+	list = g_list_prepend(list, kvp); \
+}
+
+	ADD_VALUE(encryption_values, _("Require encryption"), "require_tls");
+	ADD_VALUE(encryption_values, _("Use encryption if available"), "opportunistic_tls");
+	ADD_VALUE(encryption_values, _("Use old-style SSL"), "old_ssl");
+#if 0
+	ADD_VALUE(encryption_values, "None", "none");
+#endif
+	encryption_values = g_list_reverse(encryption_values);
+
+#undef ADD_VALUE
+
+	option = purple_account_option_list_new(_("Connection security"), "connection_security", encryption_values);
+	proto_class->protocol_options = g_list_append(proto_class->protocol_options,
+						   option);
+
+	option = purple_account_option_bool_new(
+						_("Allow plaintext auth over unencrypted streams"),
+						"auth_plain_in_clear", FALSE);
+	proto_class->protocol_options = g_list_append(proto_class->protocol_options,
+						   option);
+
+	option = purple_account_option_int_new(_("Connect port"), "port", 5222);
+	proto_class->protocol_options = g_list_append(proto_class->protocol_options,
+						   option);
+
+	option = purple_account_option_string_new(_("Connect server"),
+						  "connect_server", NULL);
+	proto_class->protocol_options = g_list_append(proto_class->protocol_options,
+						  option);
+
+	option = purple_account_option_string_new(_("File transfer proxies"),
+						  "ft_proxies",
+						/* TODO: Is this an acceptable default?
+						 * Also, keep this in sync as they add more servers */
+						  JABBER_DEFAULT_FT_PROXIES);
+	proto_class->protocol_options = g_list_append(proto_class->protocol_options,
+						  option);
+
+	option = purple_account_option_string_new(_("BOSH URL"),
+						  "bosh_url", NULL);
+	proto_class->protocol_options = g_list_append(proto_class->protocol_options,
+						  option);
+
+	/* this should probably be part of global smiley theme settings later on,
+	  shared with MSN */
+	option = purple_account_option_bool_new(_("Show Custom Smileys"),
+		"custom_smileys", TRUE);
+	proto_class->protocol_options = g_list_append(proto_class->protocol_options,
+		option);
+
+	purple_prefs_remove("/protocols/jabber");
+}
+
+static void xmpp_protocol_base_finalize(XMPPProtocolClass *klass) { }
+static void xmpp_protocol_interface_init(PurpleProtocolInterface *iface) { }
+
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "protocol-xmpp",
+		"name",         "XMPP Protocol",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("XMPP Protocol Plugin"),
+		"description",  N_("XMPP Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
+		                PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
+		NULL
+	);
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
+{
+	my_protocol = purple_protocols_add(XMPP_TYPE_PROTOCOL, error);
+	if (!my_protocol)
+		return FALSE;
+
+	purple_signal_connect(purple_get_core(), "uri-handler", my_protocol,
+		PURPLE_CALLBACK(xmpp_uri_handler), NULL);
+
+	jabber_protocol_init(my_protocol);
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	jabber_protocol_uninit(my_protocol);
+	if (!purple_protocols_remove(my_protocol, error))
+		return FALSE;
+
+	return TRUE;
+}
+
+extern PurplePlugin *_jabber_plugin;
+
+PURPLE_PROTOCOL_DEFINE_EXTENDED(_jabber_plugin, XMPPProtocol, xmpp_protocol,
+                                JABBER_TYPE_PROTOCOL, 0);
+
+PURPLE_PLUGIN_INIT_VAL(_jabber_plugin, jabber, plugin_query, plugin_load,
+                       plugin_unload);

mercurial