diff --git a/libpurple/protocols/jabber/resources/icons/16x16/apps/im-jabber.png b/protocols/xmpp/resources/icons/16x16/apps/im-xmpp.png
copy from libpurple/protocols/jabber/resources/icons/16x16/apps/im-jabber.png
copy to protocols/xmpp/resources/icons/16x16/apps/im-xmpp.png
diff --git a/libpurple/protocols/jabber/resources/icons/16x16/apps/scalable/im-jabber.svg b/protocols/xmpp/resources/icons/16x16/apps/scalable/im-xmpp.svg
copy from libpurple/protocols/jabber/resources/icons/16x16/apps/scalable/im-jabber.svg
copy to protocols/xmpp/resources/icons/16x16/apps/scalable/im-xmpp.svg
diff --git a/libpurple/protocols/jabber/resources/icons/22x22/apps/im-jabber.png b/protocols/xmpp/resources/icons/22x22/apps/im-xmpp.png
copy from libpurple/protocols/jabber/resources/icons/22x22/apps/im-jabber.png
copy to protocols/xmpp/resources/icons/22x22/apps/im-xmpp.png
diff --git a/libpurple/protocols/jabber/resources/icons/22x22/apps/scalable/im-jabber.svg b/protocols/xmpp/resources/icons/22x22/apps/scalable/im-xmpp.svg
copy from libpurple/protocols/jabber/resources/icons/22x22/apps/scalable/im-jabber.svg
copy to protocols/xmpp/resources/icons/22x22/apps/scalable/im-xmpp.svg
diff --git a/libpurple/protocols/jabber/resources/icons/48x48/apps/im-jabber.png b/protocols/xmpp/resources/icons/48x48/apps/im-xmpp.png
copy from libpurple/protocols/jabber/resources/icons/48x48/apps/im-jabber.png
copy to protocols/xmpp/resources/icons/48x48/apps/im-xmpp.png
diff --git a/libpurple/protocols/jabber/resources/icons/scalable/apps/im-jabber.svg b/protocols/xmpp/resources/icons/scalable/apps/im-xmpp.svg
copy from libpurple/protocols/jabber/resources/icons/scalable/apps/im-jabber.svg
copy to protocols/xmpp/resources/icons/scalable/apps/im-xmpp.svg
diff --git a/libpurple/protocols/jabber/resources/xmpp.gresource.xml b/protocols/xmpp/resources/xmpp.gresource.xml
copy from libpurple/protocols/jabber/resources/xmpp.gresource.xml
copy to protocols/xmpp/resources/xmpp.gresource.xml
--- a/libpurple/protocols/jabber/resources/xmpp.gresource.xml
+++ b/protocols/xmpp/resources/xmpp.gresource.xml
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
-  <gresource prefix="/im/pidgin/libpurple/xmpp">
-    <file>icons/16x16/apps/im-jabber.png</file>
-    <file>icons/16x16/apps/scalable/im-jabber.svg</file>
-    <file>icons/22x22/apps/im-jabber.png</file>
-    <file>icons/22x22/apps/scalable/im-jabber.svg</file>
-    <file>icons/48x48/apps/im-jabber.png</file>
-    <file>icons/scalable/apps/im-jabber.svg</file>
+  <gresource prefix="/im/pidgin/libpurple/protocols/xmpp">
+    <file>icons/16x16/apps/im-xmpp.png</file>
+    <file compressed="true" preprocess="xml-stripblanks">icons/16x16/apps/scalable/im-xmpp.svg</file>
+    <file>icons/22x22/apps/im-xmpp.png</file>
+    <file compressed="true" preprocess="xml-stripblanks">icons/22x22/apps/scalable/im-xmpp.svg</file>
+    <file>icons/48x48/apps/im-xmpp.png</file>
+    <file compressed="true" preprocess="xml-stripblanks">icons/scalable/apps/im-xmpp.svg</file>
   </gresource>
 </gresources>
# HG changeset patch
# Node ID e0b7793f782d
# Parent  6aaf9a66f9d9
diff --git a/meson.build b/meson.build
--- a/meson.build
+++ b/meson.build
@@ -288,9 +288,14 @@
 	endif
 endif
 
+#######################################################################
+# Check for Xeme XMPP Library
+#######################################################################
+xeme = dependency('xeme')
+
 dependency('shoes', required : false)
 
-DEFAULT_PRPLS = ['bonjour', 'demo', 'gg', 'ircv3', 'jabber']
+DEFAULT_PRPLS = ['bonjour', 'demo', 'gg', 'ircv3', 'jabber', 'xmpp']
 
 dynamic_list = get_option('dynamic-prpls').split(',')
 if dynamic_list == ['all']
@@ -300,10 +305,12 @@
 foreach prpl : dynamic_list
 	if prpl == ''
 		# The list was empty; do nothing.
-	elif prpl == 'bonjour' and not enable_avahi
+	elif prpl == 'bonjour' and not enable_avahi and not xeme.found()
 		# Do nothing.
 	elif prpl == 'gg' and not libgadu.found()
 		# Do nothing.
+	elif prpl == 'xmpp' and not xeme.found()
+		# Do nothing.
 	else
 		DYNAMIC_PRPLS += [prpl]
 	endif
@@ -314,7 +321,7 @@
 DYNAMIC_GG  = DYNAMIC_PRPLS.contains('gg')
 DYNAMIC_IRCV3 = DYNAMIC_PRPLS.contains('ircv3')
 DYNAMIC_JABBER = DYNAMIC_PRPLS.contains('jabber')
-
+DYNAMIC_XMPP = DYNAMIC_PRPLS.contains('xmpp')
 
 add_project_arguments(
     '-DPURPLE_DISABLE_DEPRECATED',
@@ -462,6 +469,7 @@
 subdir('purple-history')
 subdir('finch')
 subdir('pidgin')
+subdir('protocols')
 subdir('doc')
 subdir('po')
 
diff --git a/protocols/meson.build b/protocols/meson.build
new file mode 100644
--- /dev/null
+++ b/protocols/meson.build
@@ -0,0 +1,1 @@
+subdir('xmpp')
diff --git a/protocols/xmpp/meson.build b/protocols/xmpp/meson.build
new file mode 100644
--- /dev/null
+++ b/protocols/xmpp/meson.build
@@ -0,0 +1,29 @@
+XMPP_SOURCES = [
+	'purplexmppcore.c',
+	'purplexmppprotocol.c',
+]
+
+XMPP_HEADERS = [
+	'purplexmppcore.h',
+	'purplexmppprotocol.h',
+]
+
+if not DYNAMIC_XMPP
+	subdir_done()
+endif
+
+xmpp_resources = gnome.compile_resources('xmppresource',
+	'resources/xmpp.gresource.xml',
+	source_dir : 'resources',
+	c_name : 'purple_xmpp')
+XMPP_SOURCES += xmpp_resources
+
+xmpp_prpl = library('xmpp',
+	XMPP_SOURCES + XMPP_HEADERS,
+	c_args : ['-DPURPLE_XMPP_COMPILATION', '-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-XMPP"'],
+	gnu_symbol_visibility : 'hidden',
+	dependencies : [libpurple_dep, glib, gio, hasl, xeme],
+	install : true,
+	install_dir : PURPLE_PLUGINDIR)
+
+devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
diff --git a/protocols/xmpp/purplexmppcore.h b/protocols/xmpp/purplexmppcore.h
new file mode 100644
--- /dev/null
+++ b/protocols/xmpp/purplexmppcore.h
@@ -0,0 +1,25 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef PURPLE_XMPP_CORE_H
+#define PURPLE_XMPP_CORE_H
+
+#include <glib.h>
+
+#define PURPLE_XMPP_DOMAIN (g_quark_from_static_string("xmpp-plugin"))
+
+#endif /* PURPLE_XMPP_CORE_H */
diff --git a/protocols/xmpp/purplexmppcore.c b/protocols/xmpp/purplexmppcore.c
new file mode 100644
--- /dev/null
+++ b/protocols/xmpp/purplexmppcore.c
@@ -0,0 +1,117 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+#include "purplexmppcore.h"
+
+#include "purplexmppprotocol.h"
+
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
+static PurpleProtocol *xmpp_protocol = NULL;
+
+/******************************************************************************
+ * GPlugin Exports
+ *****************************************************************************/
+static GPluginPluginInfo *
+purple_xmpp_query(G_GNUC_UNUSED GError **error) {
+	PurplePluginInfoFlags flags = PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
+	                              PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD;
+	const gchar * const authors[] = {
+		"Pidgin Developers <devel@pidgin.im>",
+		NULL
+	};
+
+	return purple_plugin_info_new(
+		"id", "prpl-xmpp",
+		"name", "XMPP Protocol",
+		"authors", authors,
+		"version", DISPLAY_VERSION,
+		"category", N_("Protocol"),
+		"summary", N_("XMPP Protocol Plugin"),
+		"description", N_("Modern XMPP Support"),
+		"website", PURPLE_WEBSITE,
+		"abi-version", PURPLE_ABI_VERSION,
+		"flags", flags,
+		NULL);
+}
+
+static gboolean
+purple_xmpp_load(GPluginPlugin *plugin, GError **error) {
+	PurpleProtocolManager *manager = NULL;
+
+	if(PURPLE_IS_PROTOCOL(xmpp_protocol)) {
+		g_set_error_literal(error, PURPLE_XMPP_DOMAIN, 0,
+		                    "plugin was not cleaned up properly");
+
+		return FALSE;
+	}
+
+	purple_xmpp_protocol_register(GPLUGIN_NATIVE_PLUGIN(plugin));
+
+	xmpp_protocol = purple_xmpp_protocol_new();
+
+	manager = purple_protocol_manager_get_default();
+	if(PURPLE_IS_PROTOCOL_MANAGER(manager)) {
+		if(!purple_protocol_manager_register(manager, xmpp_protocol, error)) {
+			g_clear_object(&xmpp_protocol);
+
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+static gboolean
+purple_xmpp_unload(G_GNUC_UNUSED GPluginPlugin *plugin,
+                   G_GNUC_UNUSED gboolean shutdown,
+                   GError **error)
+{
+	PurpleProtocolManager *manager = NULL;
+
+	if(!PURPLE_IS_PROTOCOL(xmpp_protocol)) {
+		g_set_error_literal(error, PURPLE_XMPP_DOMAIN, 0,
+		                    "plugin was not setup properly");
+
+		return FALSE;
+	}
+
+	manager = purple_protocol_manager_get_default();
+	if(PURPLE_IS_PROTOCOL_MANAGER(manager)) {
+		if(!purple_protocol_manager_unregister(manager, xmpp_protocol,
+		                                       error))
+		{
+			return FALSE;
+		}
+	}
+
+	g_clear_object(&xmpp_protocol);
+
+	return TRUE;
+}
+
+GPLUGIN_NATIVE_PLUGIN_DECLARE(purple_xmpp)
diff --git a/protocols/xmpp/purplexmppprotocol.h b/protocols/xmpp/purplexmppprotocol.h
new file mode 100644
--- /dev/null
+++ b/protocols/xmpp/purplexmppprotocol.h
@@ -0,0 +1,50 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef PURPLE_XMPP_PROTOCOL_H
+#define PURPLE_XMPP_PROTOCOL_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+#define PURPLE_XMPP_TYPE_PROTOCOL (purple_xmpp_protocol_get_type())
+
+G_DECLARE_FINAL_TYPE(PurpleXmppProtocol, purple_xmpp_protocol, PURPLE_XMPP,
+                     PROTOCOL, PurpleProtocol)
+
+/**
+ * purple_xmpp_protocol_register: (skip)
+ * @plugin: The GTypeModule
+ *
+ * Registers the dynamic type using @plugin.
+ *
+ * Since: 3.0.0
+ */
+G_GNUC_INTERNAL void purple_xmpp_protocol_register(GPluginNativePlugin *plugin);
+
+G_GNUC_INTERNAL PurpleProtocol *purple_xmpp_protocol_new(void);
+
+G_END_DECLS
+
+#endif /* PURPLE_XMPP_PROTOCOL_H */
diff --git a/protocols/xmpp/purplexmppprotocol.c b/protocols/xmpp/purplexmppprotocol.c
new file mode 100644
--- /dev/null
+++ b/protocols/xmpp/purplexmppprotocol.c
@@ -0,0 +1,102 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n-lib.h>
+
+#include "purplexmppprotocol.h"
+
+struct _PurpleXmppProtocol {
+	PurpleProtocol parent;
+};
+
+/******************************************************************************
+ * PurpleProtocol Implementation
+ *****************************************************************************/
+static GList *
+purple_xmpp_protocol_get_user_splits(G_GNUC_UNUSED PurpleProtocol *protocol) {
+	PurpleAccountUserSplit *split = NULL;
+	GList *splits = NULL;
+
+	split = purple_account_user_split_new(_("Server"), NULL, '@');
+	splits = g_list_append(splits, split);
+
+	return splits;
+}
+
+static GList *
+purple_xmpp_protocol_status_types(G_GNUC_UNUSED PurpleProtocol *protocol,
+                                  G_GNUC_UNUSED PurpleAccount *account)
+{
+	PurpleStatusType *type = NULL;
+	GList *types = NULL;
+
+	type = purple_status_type_new(PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE);
+	types = g_list_append(types, type);
+
+	type = purple_status_type_new(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE);
+	types = g_list_append(types, type);
+
+	return types;
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(
+	PurpleXmppProtocol,
+	purple_xmpp_protocol,
+	PURPLE_TYPE_PROTOCOL,
+	0,
+	)
+
+static void
+purple_xmpp_protocol_init(G_GNUC_UNUSED PurpleXmppProtocol *protocol) {
+}
+
+static void
+purple_xmpp_protocol_class_finalize(G_GNUC_UNUSED PurpleXmppProtocolClass *klass) {
+}
+
+static void
+purple_xmpp_protocol_class_init(PurpleXmppProtocolClass *klass) {
+	PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
+
+	protocol_class->get_user_splits = purple_xmpp_protocol_get_user_splits;
+	protocol_class->status_types = purple_xmpp_protocol_status_types;
+}
+
+/******************************************************************************
+ * Internal API
+ *****************************************************************************/
+void
+purple_xmpp_protocol_register(GPluginNativePlugin *plugin) {
+	purple_xmpp_protocol_register_type(G_TYPE_MODULE(plugin));
+}
+
+PurpleProtocol *
+purple_xmpp_protocol_new(void) {
+	return g_object_new(
+		PURPLE_XMPP_TYPE_PROTOCOL,
+		"id", "prpl-xmpp",
+		"name", "XMPP",
+		"description", _("Modern Extensible Messaging and Presence Protocol."),
+		"icon-name", "im-xmpp",
+		"icon-resource-path", "/im/pidgin/libpurple/protocols/xmpp/icons",
+		"options", OPT_PROTO_PASSWORD_OPTIONAL,
+		NULL);
+}
diff --git a/subprojects/xeme.wrap b/subprojects/xeme.wrap
new file mode 100644
--- /dev/null
+++ b/subprojects/xeme.wrap
@@ -0,0 +1,4 @@
+[wrap-hg]
+directory = xeme
+url = https://keep.imfreedom.org/xeme/xeme/
+revision = 29f9d1d3dc73
