diff --git a/install/apps/metronome-init b/install/apps/metronome-init
new file mode 100644
index 0000000000000000000000000000000000000000..78ba7ea14accccbc866cf1294c88f68f0821e8fc
--- /dev/null
+++ b/install/apps/metronome-init
@@ -0,0 +1,75 @@
+#! /bin/sh
+#
+# metronome        Start/stop metronome server
+#
+
+### BEGIN INIT INFO
+# Provides:          metronome
+# Required-Start:    $remote_fs $network $named $time
+# Required-Stop:     $remote_fs $network $named $time
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Starts metronome server
+# Description:       Starts metronome server, an XMPP server written in Lua.
+### END INIT INFO
+
+METRONOME=/usr/bin/metronomectl
+PIDDIR=/var/run/metronome
+NAME=metronome
+
+test -e $METRONOME || exit 0
+
+start()
+{
+        mkdir $PIDDIR -p
+        chown metronome:metronome $PIDDIR
+        chmod 750 $PIDDIR
+
+    $METRONOME start >> /dev/null
+}
+
+stop()
+{
+    $METRONOME stop >> /dev/null
+}
+
+reload()
+{
+    &METRONOME reload >> /dev/null
+}
+
+restart()
+{
+    &METRONOME restart >> /dev/null
+}
+
+case "$1" in
+    start)
+        echo -n "Starting Metronome..."
+        start &
+    ;;
+    stop)
+        echo -n "Stopping Metronome..."
+        stop &
+    ;;
+    reload)
+        echo -n "Reloading Metronome config..."
+        reload &
+    ;;
+    restart)
+        echo -n "Restarting Metronome..."
+        restart &
+    ;;
+    *)
+        echo "Usage: $0 {start|stop|reload|restart}" >&2
+        exit 1
+    ;;
+esac
+
+if [ $? -eq 0 ]; then
+    echo .
+else
+    echo " failed!"
+fi
+
+exit 0
diff --git a/install/apps/metronome_libs/mod_auth_external/authenticate_isp.sh b/install/apps/metronome_libs/mod_auth_external/authenticate_isp.sh
new file mode 100644
index 0000000000000000000000000000000000000000..c5a0c8e6846b85087bcc6f3f1ba3ae764f1a7a3c
--- /dev/null
+++ b/install/apps/metronome_libs/mod_auth_external/authenticate_isp.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+IFS=":"
+AUTH_OK=1
+AUTH_FAILED=0
+LOGFILE="/var/log/metronome/auth.log"
+USELOG=true
+
+while read ACTION USER HOST PASS ; do
+
+    [ $USELOG == true ] && { echo "Date: $(date) Action: $ACTION User: $USER Host: $HOST" >> $LOGFILE; }
+
+    case $ACTION in
+        "auth")
+            if [ `/usr/bin/php /usr/lib/metronome/isp-modules/mod_auth_external/db_auth.php $USER $HOST $PASS 2>/dev/null` == 1 ] ; then
+                echo $AUTH_OK
+                [ $USELOG == true ] && { echo "AUTH OK" >> $LOGFILE; }
+            else
+                echo $AUTH_FAILED
+                [ $USELOG == true ] && { echo "AUTH FAILED" >> $LOGFILE; }
+            fi
+        ;;
+        "isuser")
+             if [ `/usr/bin/php /usr/lib/metronome/isp-modules/mod_auth_external/db_isuser.php $USER $HOST 2>/dev/null` == 1 ] ; then
+                echo $AUTH_OK
+                [ $USELOG == true ] && { echo "ISUSER OK" >> $LOGFILE; }
+            else
+                echo $AUTH_FAILED
+                [ $USELOG == true ] && { echo "ISUSER FAILED" >> $LOGFILE; }
+            fi
+        ;;
+        *)
+            echo $AUTH_FAILED
+            [ $USELOG == true ] && { echo "UNKNOWN ACTION GIVEN: $ACTION" >> $LOGFILE; }
+        ;;
+    esac
+
+done
diff --git a/install/apps/metronome_libs/mod_auth_external/db_auth.php b/install/apps/metronome_libs/mod_auth_external/db_auth.php
new file mode 100644
index 0000000000000000000000000000000000000000..086dcf6a0143efbb8562f3817d0fc7c58c03d949
--- /dev/null
+++ b/install/apps/metronome_libs/mod_auth_external/db_auth.php
@@ -0,0 +1,58 @@
+<?php
+ini_set('display_errors', false);
+require_once('db_conf.inc.php');
+
+try{
+    // Connect database
+    $db = new mysqli($db_host, $db_user, $db_pass, $db_name);
+    result_false(mysqli_connect_errno());
+
+    // Get arguments
+    $arg_email = '';
+    $arg_password = '';
+
+    result_false(count($argv) != 4);
+    $arg_email = $argv[1].'@'.$argv[2];
+    $arg_password = $argv[3];
+
+    // check for existing user
+    $dbmail = $db->real_escape_string($arg_email);
+    $result = $db->query("SELECT jid, password FROM xmpp_user WHERE jid LIKE '".$dbmail."' AND active='y' AND server_id='".$isp_server_id."'");
+    result_false($result->num_rows != 1);
+
+    $user = $result->fetch_object();
+
+    // check for domain autologin api key
+    $domain_key = 'f47kmm5Yh5hJzSws2KTS';
+
+    checkAuth($argv[1], $argv[2], $arg_password, $user->password, $domain_key);
+}catch(Exception $ex){
+    echo 0;
+    exit();
+}
+
+function result_false($cond = true){
+    if(!$cond) return;
+    echo 0;
+    exit();
+}
+function result_true(){
+    echo 1;
+    exit();
+}
+function checkAuth($user, $domain, $pw_arg, $pw_db, $domain_key){
+    if(crypt($pw_arg, $pw_db) == $pw_db)
+        result_true();
+
+    if($domain_key){
+        $datetime = new DateTime();
+        $datetime->setTimezone(new DateTimeZone("UTC"));
+        for($t = $datetime->getTimestamp(); $t >= $datetime->getTimestamp()-30; $t--){
+            $pw_api = md5($domain.'@'.$domain_key.'@'.$user.'@'.$t);
+            if($pw_api == $pw_arg)
+                result_true();
+        }
+    }
+    result_false();
+}
+?>
\ No newline at end of file
diff --git a/install/apps/metronome_libs/mod_auth_external/db_conf.inc.php b/install/apps/metronome_libs/mod_auth_external/db_conf.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..1aba63d6ea051ff4826312757b10af2a1c590525
--- /dev/null
+++ b/install/apps/metronome_libs/mod_auth_external/db_conf.inc.php
@@ -0,0 +1,6 @@
+<?php
+$db_user = '{mysql_server_ispconfig_user}';
+$db_pass = '{mysql_server_ispconfig_password}';
+$db_name = '{mysql_server_database}';
+$db_host = '{mysql_server_ip}';
+$isp_server_id = '{server_id}';
\ No newline at end of file
diff --git a/install/apps/metronome_libs/mod_auth_external/db_isuser.php b/install/apps/metronome_libs/mod_auth_external/db_isuser.php
new file mode 100644
index 0000000000000000000000000000000000000000..7a7cf861bf88f38035535297672636f1518dca3a
--- /dev/null
+++ b/install/apps/metronome_libs/mod_auth_external/db_isuser.php
@@ -0,0 +1,37 @@
+<?php
+ini_set('display_errors', false);
+require_once('db_conf.inc.php');
+
+try{
+    // Connect database
+    $db = new mysqli($db_host, $db_user, $db_pass, $db_name);
+    result_false(mysqli_connect_errno());
+
+    // Get arguments
+    $arg_email = '';
+
+    result_false(count($argv) != 3);
+    $arg_email = $argv[1].'@'.$argv[2];
+
+    // check for existing user
+    $dbmail = $db->real_escape_string($arg_email);
+    $result = $db->query("SELECT jid, password FROM xmpp_user WHERE jid LIKE '".$dbmail."' AND active='y' AND server_id='".$isp_server_id."'");
+    result_false($result->num_rows != 1);
+    result_true();
+
+}catch(Exception $ex){
+    echo 0;
+    exit();
+}
+
+function result_false($cond = true){
+    if(!$cond) return;
+    echo 0;
+    exit();
+}
+function result_true(){
+    echo 1;
+    exit();
+}
+
+?>
\ No newline at end of file
diff --git a/install/apps/metronome_libs/mod_auth_external/mod_auth_external.lua b/install/apps/metronome_libs/mod_auth_external/mod_auth_external.lua
new file mode 100644
index 0000000000000000000000000000000000000000..c86400610e2389b61b502b52b6b277fdad9419e7
--- /dev/null
+++ b/install/apps/metronome_libs/mod_auth_external/mod_auth_external.lua
@@ -0,0 +1,118 @@
+local nodeprep = require "util.encodings".stringprep.nodeprep;
+local lpc = require "lpc";
+
+local config = require "core.configmanager";
+local log = module._log;
+local host = module.host;
+local script_type = config.get(host, "external_auth_protocol") or "generic";
+assert(script_type == "ejabberd" or script_type == "generic");
+local command = config.get(host, "external_auth_command") or "";
+assert(type(command) == "string");
+assert(not host:find(":"));
+local usermanager = require "core.usermanager";
+local jid_bare = require "util.jid".bare;
+local new_sasl = require "util.sasl".new;
+
+local pid;
+local readfile;
+local writefile;
+
+local function send_query(text)
+        if pid and lpc.wait(pid,1) ~= nil then
+            log("debug","error, process died, force reopen");
+            pid=nil;
+        end
+        if not pid then
+                log("debug", "Opening process " .. command);
+                pid, writefile, readfile = lpc.run(command);
+        end
+        if not pid then
+                log("debug", "Process failed to open");
+                return nil;
+        end
+
+        writefile:write(text);
+        writefile:flush();
+        if script_type == "ejabberd" then
+                return readfile:read(4);
+        elseif script_type == "generic" then
+                return readfile:read();
+        end
+end
+
+function do_query(kind, username, password)
+        if not username then return nil, "not-acceptable"; end
+        username = nodeprep(username);
+        if not username then return nil, "jid-malformed"; end
+
+        local query = (password and "%s:%s:%s:%s" or "%s:%s:%s"):format(kind, username, host, password);
+        local len = #query
+        if len > 1000 then return nil, "policy-violation"; end
+
+        if script_type == "ejabberd" then
+                local lo = len % 256;
+                local hi = (len - lo) / 256;
+                query = string.char(hi, lo)..query;
+        end
+        if script_type == "generic" then
+                query = query..'\n';
+        end
+
+        local response = send_query(query);
+        if (script_type == "ejabberd" and response == "\0\2\0\0") or
+                (script_type == "generic" and response == "0") then
+                        return nil, "not-authorized";
+        elseif (script_type == "ejabberd" and response == "\0\2\0\1") or
+                (script_type == "generic" and response == "1") then
+                        return true;
+        else
+                log("debug", "Nonsense back");
+                return nil, "internal-server-error";
+        end
+end
+
+function new_external_provider(host)
+        local provider = { name = "external" };
+
+        function provider.test_password(username, password)
+                return do_query("auth", username, password);
+        end
+
+        function provider.set_password(username, password)
+                return do_query("setpass", username, password);
+        end
+
+        function provider.user_exists(username)
+                return do_query("isuser", username);
+        end
+
+        function provider.create_user(username, password) return nil, "Account creation/modification not available."; end
+
+        function provider.get_sasl_handler()
+                local testpass_authentication_profile = {
+                        plain_test = function(sasl, username, password, realm)
+                                return usermanager.test_password(username, realm, password), true;
+                        end,
+                };
+                return new_sasl(module.host, testpass_authentication_profile);
+        end
+
+        function provider.is_admin(jid)
+                local admins = config.get(host, "admins");
+                if admins ~= config.get("*", "admins") then
+                        if type(admins) == "table" then
+                                jid = jid_bare(jid);
+                                for _,admin in ipairs(admins) do
+                                        if admin == jid then return true; end
+                                end
+                        elseif admins then
+                                log("error", "Option 'admins' for host '%s' is not a table", host);
+                        end
+                end
+                return usermanager.is_admin(jid);
+        end
+
+        return provider;
+end
+
+module:add_item("auth-provider", new_external_provider(host));
\ No newline at end of file
diff --git a/install/apps/metronome_libs/mod_discoitems.lua b/install/apps/metronome_libs/mod_discoitems.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f05b9049073f540cef8686f4ed80579e9fa9ed28
--- /dev/null
+++ b/install/apps/metronome_libs/mod_discoitems.lua
@@ -0,0 +1,24 @@
+-- * Metronome IM *
+--
+-- This file is part of the Metronome XMPP server and is released under the
+-- ISC License, please see the LICENSE file in this source package for more
+-- information about copyright and licensing.
+--
+-- As per the sublicensing clause, this file is also MIT/X11 Licensed.
+-- ** Copyright (c) 2009, Waqas Hussain
+
+local st = require "util.stanza";
+
+local result_query = st.stanza("query", {xmlns = "http://jabber.org/protocol/disco#items"});
+for _, item in ipairs(module:get_option("disco_items") or {}) do
+    result_query:tag("item", {jid = item[1], name = item[2]}):up();
+end
+
+module:hook("iq/host/http://jabber.org/protocol/disco#items:query", function(event)
+    local stanza = event.stanza;
+    local query = stanza.tags[1];
+    if stanza.attr.type == "get" and not query.attr.node then
+        event.origin.send(st.reply(stanza):add_child(result_query));
+        return true;
+    end
+end, 100);
diff --git a/install/apps/metronome_libs/mod_webpresence/icons/status_away.png b/install/apps/metronome_libs/mod_webpresence/icons/status_away.png
new file mode 100644
index 0000000000000000000000000000000000000000..0de5c6ab3d35e958b2c2c9fa9ee6e5876312b54b
Binary files /dev/null and b/install/apps/metronome_libs/mod_webpresence/icons/status_away.png differ
diff --git a/install/apps/metronome_libs/mod_webpresence/icons/status_chat.png b/install/apps/metronome_libs/mod_webpresence/icons/status_chat.png
new file mode 100644
index 0000000000000000000000000000000000000000..324f40baf379ec677e4b7b9791f94298481d7e86
Binary files /dev/null and b/install/apps/metronome_libs/mod_webpresence/icons/status_chat.png differ
diff --git a/install/apps/metronome_libs/mod_webpresence/icons/status_dnd.png b/install/apps/metronome_libs/mod_webpresence/icons/status_dnd.png
new file mode 100644
index 0000000000000000000000000000000000000000..015f3da95dfe2a6c9dcdf414951c277104ae6b2e
Binary files /dev/null and b/install/apps/metronome_libs/mod_webpresence/icons/status_dnd.png differ
diff --git a/install/apps/metronome_libs/mod_webpresence/icons/status_offline.png b/install/apps/metronome_libs/mod_webpresence/icons/status_offline.png
new file mode 100644
index 0000000000000000000000000000000000000000..12db2af7dd86308f5abed00e3930d7f961e1ecc3
Binary files /dev/null and b/install/apps/metronome_libs/mod_webpresence/icons/status_offline.png differ
diff --git a/install/apps/metronome_libs/mod_webpresence/icons/status_online.png b/install/apps/metronome_libs/mod_webpresence/icons/status_online.png
new file mode 100644
index 0000000000000000000000000000000000000000..fb257c3144736fd691d81ac82242f7d51f909679
Binary files /dev/null and b/install/apps/metronome_libs/mod_webpresence/icons/status_online.png differ
diff --git a/install/apps/metronome_libs/mod_webpresence/icons/status_xa.png b/install/apps/metronome_libs/mod_webpresence/icons/status_xa.png
new file mode 100644
index 0000000000000000000000000000000000000000..321d35b5a3f1c832669154c1bc8f4f000c42e761
Binary files /dev/null and b/install/apps/metronome_libs/mod_webpresence/icons/status_xa.png differ
diff --git a/install/apps/metronome_libs/mod_webpresence/mod_webpresence.lua b/install/apps/metronome_libs/mod_webpresence/mod_webpresence.lua
new file mode 100644
index 0000000000000000000000000000000000000000..c1de0e0d37eaecba6afb4244a12d6d4a5245912d
--- /dev/null
+++ b/install/apps/metronome_libs/mod_webpresence/mod_webpresence.lua
@@ -0,0 +1,118 @@
+module:depends("http");
+
+local jid_split = require "util.jid".prepped_split;
+local b64 = require "util.encodings".base64.encode;
+local sha1 = require "util.hashes".sha1;
+local stanza = require "util.stanza".stanza;
+local json = require "util.json".encode_ordered;
+
+local function require_resource(name)
+    local icon_path = module:get_option_string("presence_icons", "icons");
+    local f, err  = module:load_resource(icon_path.."/"..name);
+    if f then
+        return f:read("*a");
+    end
+    module:log("warn", "Failed to open image file %s", icon_path..name);
+    return "";
+end
+
+local statuses = { online = {}, away = {}, xa = {}, dnd = {}, chat = {}, offline = {} };
+
+local function handle_request(event, path)
+  local status, message;
+  local jid, type = path:match("([^/]+)/?(.*)$");
+  if jid then
+    local user, host = jid_split(jid);
+    if host and not user then
+        user, host = host, event.request.headers.host;
+        if host then host = host:gsub(":%d+$", ""); end
+    end
+    if user and host then
+      local user_sessions = hosts[host] and hosts[host].sessions[user];
+      if user_sessions then
+        status = user_sessions.top_resources[1];
+        if status and status.presence then
+          message = status.presence:child_with_name("status");
+          status = status.presence:child_with_name("show");
+          if not status then
+            status = "online";
+          else
+            status = status:get_text();
+          end
+          if message then
+            message = message:get_text();
+          end
+        end
+      end
+    end
+  end
+  status = status or "offline";
+
+  statuses[status].image = function()
+    return { status_code = 200, headers = { content_type = "image/png" },
+      body =  require_resource("status_"..status..".png")
+    };
+  end;
+  statuses[status].html = function()
+    local jid_hash = sha1(jid, true);
+    return { status_code = 200, headers = { content_type = "text/html" },
+      body =  [[<!DOCTYPE html>]]..
+        tostring(
+          stanza("html")
+            :tag("head")
+            :tag("title"):text("XMPP Status Page for "..jid):up():up()
+            :tag("body")
+            :tag("div", { id = jid_hash.."_status", class = "xmpp_status" })
+            :tag("img", { id = jid_hash.."_img", class = "xmpp_status_image xmpp_status_"..status,
+              src = "data:image/png;base64,"..b64(require_resource("status_"..status..".png")) }):up()
+            :tag("span", { id = jid_hash.."_status_name", class = "xmpp_status_name" })
+              :text("\194\160"..status):up()
+            :tag("span", { id = jid_hash.."_status_message", class = "xmpp_status_message" })
+              :text(message and "\194\160"..message.."" or "")
+        )
+    };
+  end;
+  statuses[status].text = function()
+    return { status_code = 200, headers = { content_type = "text/plain" },
+      body = status
+    };
+  end;
+  statuses[status].message = function()
+    return { status_code = 200, headers = { content_type = "text/plain" },
+      body = (message and message or "")
+    };
+  end;
+  statuses[status].json = function()
+    return { status_code = 200, headers = { content_type = "application/json" },
+      body = json({
+        jid    = jid,
+        show   = status,
+        status = (message and message or "null")
+      })
+    };
+  end;
+  statuses[status].xml = function()
+    return { status_code = 200, headers = { content_type = "application/xml" },
+      body = [[<?xml version="1.0" encoding="utf-8"?>]]..
+        tostring(
+          stanza("result")
+            :tag("jid"):text(jid):up()
+            :tag("show"):text(status):up()
+            :tag("status"):text(message)
+        )
+      };
+  end
+
+  if ((type == "") or (not statuses[status][type])) then
+    type = "image"
+  end;
+
+  return statuses[status][type]();
+end
+
+module:provides("http", {
+    default_path = "/status";
+    route = {
+        ["GET /*"] = handle_request;
+    };
+});
diff --git a/install/dist/conf/debian60.conf.php b/install/dist/conf/debian60.conf.php
index a3819966b9dc640d42723450d3869f5905c64639..e18faa4967e4c4f963c2faa329efbc6100bbc416 100644
--- a/install/dist/conf/debian60.conf.php
+++ b/install/dist/conf/debian60.conf.php
@@ -222,5 +222,9 @@ $conf['cron']['init_script'] = 'cron';
 $conf['cron']['crontab_dir'] = '/etc/cron.d';
 $conf['cron']['wget'] = '/usr/bin/wget';
 
+//* Metronome XMPP
+$conf['xmpp']['installed'] = false;
+$conf['xmpp']['init_script'] = 'metronome';
+
 
 ?>
diff --git a/install/dist/lib/debian60.lib.php b/install/dist/lib/debian60.lib.php
index 584e6aa91c19753b89210ec25df19253acc96bd1..fab5628a77cfe9b1e7da045adfebcf06f832b4a2 100644
--- a/install/dist/lib/debian60.lib.php
+++ b/install/dist/lib/debian60.lib.php
@@ -154,6 +154,10 @@ class installer extends installer_base {
 	*/
 	}
 
+    public function configure_xmpp() {
+        parent::configure_xmpp();
+    }
+
 }
 
 ?>
diff --git a/install/install.php b/install/install.php
index 91759f22844f4859c8ef9e83700f9ad225d51022..3aedfefa856c1c0ea05ae325f312130d2c3be834 100644
--- a/install/install.php
+++ b/install/install.php
@@ -347,6 +347,13 @@ if($install_mode == 'standard') {
 	}
 	*/
 
+    //* Configure XMPP
+    if($conf['xmpp']['installed'] == true){
+        $conf['services']['xmpp'] = true;
+        swriteln('Configuring Metronome XMPP Server');
+        $inst->configure_xmpp();
+    }
+
 	//* Configure ISPConfig
 	swriteln('Installing ISPConfig');
 
@@ -398,6 +405,7 @@ if($install_mode == 'standard') {
 	//if($conf['squid']['installed'] == true && $conf['squid']['init_script'] != '' && is_file($conf['init_scripts'].'/'.$conf['squid']['init_script']))     system($conf['init_scripts'].'/'.$conf['squid']['init_script'].' restart &> /dev/null');
 	if($conf['nginx']['installed'] == true && $conf['nginx']['init_script'] != '') system($inst->getinitcommand($conf['nginx']['init_script'], 'restart').' &> /dev/null');
 	if($conf['ufw']['installed'] == true && $conf['ufw']['init_script'] != '') system($inst->getinitcommand($conf['ufw']['init_script'], 'restart').' &> /dev/null');
+    if($conf['xmpp']['installed'] == true && $conf['xmpp']['init_script'] != '') system($inst->getinitcommand($conf['xmpp']['init_script'], 'restart').' &> /dev/null');
 
 } else {
 
@@ -408,6 +416,7 @@ if($install_mode == 'standard') {
 	$conf['services']['db'] = true;
 	$conf['services']['firewall'] = false;
 	$conf['services']['proxy'] = false;
+    $conf['services']['xmpp'] = false;
 
 
 	//** Get Server ID
@@ -639,6 +648,16 @@ if($install_mode == 'standard') {
 		$inst->configure_firewall();
 	}*/
 
+    //** Configure XMPP
+    if($conf['xmpp']['installed'] == true){
+        if(strtolower($inst->simple_query('Configure Metronome XMPP Server', array('y', 'n'), 'y', 'configure_xmpp')) == 'y'){
+            $conf['services']['xmpp'] = true;
+            swriteln('Configuring Metronome XMPP Server');
+            $inst->configure_xmpp();
+            if($conf['xmpp']['installed'] == true && $conf['xmpp']['init_script'] != '') system($inst->getinitcommand($conf['xmpp']['init_script'], 'restart').' &> /dev/null');
+        }
+    }
+
 	//** Configure ISPConfig :-)
 	$install_ispconfig_interface_default = ($conf['mysql']['master_slave_setup'] == 'y')?'n':'y';
 	if(strtolower($inst->simple_query('Install ISPConfig Web Interface', array('y', 'n'), $install_ispconfig_interface_default,'install_ispconfig_web_interface')) == 'y') {
diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php
index ae64463c1722e648e8101ae6392574fc3be66941..62ff8606a47458f05e291f62e06a0d0dd1b4af2e 100644
--- a/install/lib/installer_base.lib.php
+++ b/install/lib/installer_base.lib.php
@@ -155,6 +155,7 @@ class installer_base {
 		if(is_installed('fail2ban-server')) $conf['fail2ban']['installed'] = true;
 		if(is_installed('vzctl')) $conf['openvz']['installed'] = true;
 		if(is_dir("/etc/Bastille")) $conf['bastille']['installed'] = true;
+        if(is_installed('metronome') && is_installed('metronomectl')) $conf['xmpp']['installed'] = true;
 
 		if ($conf['services']['web'] && (($conf['apache']['installed'] && is_file($conf['apache']["vhost_conf_enabled_dir"]."/000-ispconfig.vhost")) || ($conf['nginx']['installed'] && is_file($conf['nginx']["vhost_conf_enabled_dir"]."/000-ispconfig.vhost")))) $this->ispconfig_interface_installed = true;
 	}
@@ -1308,6 +1309,125 @@ class installer_base {
 	}
 
 
+    public function configure_xmpp($options = '') {
+        global $conf;
+
+        if($conf['xmpp']['installed'] == false) return;
+        //* Create the logging directory for xmpp server
+        if(!@is_dir('/var/log/metronome')) mkdir('/var/log/metronome', 0755, true);
+        chown('/var/log/metronome', 'metronome');
+        if(!@is_dir('/var/run/metronome')) mkdir('/var/run/metronome', 0755, true);
+        chown('/var/run/metronome', 'metronome');
+        if(!@is_dir('/var/lib/metronome')) mkdir('/var/lib/metronome', 0755, true);
+        chown('/var/lib/metronome', 'metronome');
+        if(!@is_dir('/etc/metronome/hosts')) mkdir('/etc/metronome/hosts', 0755, true);
+        if(!@is_dir('/etc/metronome/status')) mkdir('/etc/metronome/status', 0755, true);
+        unlink('/etc/metronome/metronome.cfg.lua');
+
+        $row = $this->db->queryOneRecord("SELECT server_name FROM server WHERE server_id = ".$conf["server_id"]."");
+        $server_name = $row["server_name"];
+
+        $tpl = new tpl('metronome_conf_main.master');
+        wf('/etc/metronome/metronome.cfg.lua', $tpl->grab());
+        unset($tpl);
+
+        $tpl = new tpl('metronome_conf_global.master');
+        $tpl->setVar('xmpp_admins','');
+        wf('/etc/metronome/global.cfg.lua', $tpl->grab());
+        unset($tpl);
+
+        // Copy isp libs
+        if(!@is_dir('/usr/lib/metronome/isp-modules')) mkdir('/usr/lib/metronome/isp-modules', 0755, true);
+        caselog('cp -rf apps/metronome_libs/* /usr/lib/metronome/isp-modules/', __FILE__, __LINE__);
+        // Process db config
+        $full_file_name = '/usr/lib/metronome/isp-modules/mod_auth_external/db_conf.inc.php';
+        $content = rf($full_file_name);
+        $content = str_replace('{mysql_server_ispconfig_user}', $conf['mysql']['ispconfig_user'], $content);
+        $content = str_replace('{mysql_server_ispconfig_password}', $conf['mysql']['ispconfig_password'], $content);
+        $content = str_replace('{mysql_server_database}', $conf['mysql']['database'], $content);
+        $content = str_replace('{mysql_server_ip}', $conf['mysql']['ip'], $content);
+        $content = str_replace('{server_id}', $conf['server_id'], $content);
+        wf($full_file_name, $content);
+
+        if(!stristr($options, 'dont-create-certs')){
+            // Create SSL Certificate for localhost
+            echo "writing new private key to 'localhost.key'\n-----\n";
+            $ssl_country = $this->free_query('Country Name (2 letter code)', 'AU');
+            $ssl_locality = $this->free_query('Locality Name (eg, city)', '');
+            $ssl_organisation = $this->free_query('Organization Name (eg, company)', 'Internet Widgits Pty Ltd');
+            $ssl_organisation_unit = $this->free_query('Organizational Unit Name (eg, section)', '');
+            $ssl_domain = $this->free_query('Common Name (e.g. server FQDN or YOUR name)', $conf['hostname']);
+            $ssl_email = $this->free_query('Email Address', '');
+
+            $tpl = new tpl('metronome_conf_ssl.master');
+            $tpl->setVar('ssl_country',$ssl_country);
+            $tpl->setVar('ssl_locality',$ssl_locality);
+            $tpl->setVar('ssl_organisation',$ssl_organisation);
+            $tpl->setVar('ssl_organisation_unit',$ssl_organisation_unit);
+            $tpl->setVar('domain',$ssl_domain);
+            $tpl->setVar('ssl_email',$ssl_email);
+            wf('/etc/metronome/certs/localhost.cnf', $tpl->grab());
+            unset($tpl);
+            // Generate new key, csr and cert
+            exec("(cd /etc/metronome/certs && make localhost.key)");
+            exec("(cd /etc/metronome/certs && make localhost.csr)");
+            exec("(cd /etc/metronome/certs && make localhost.cert)");
+            exec('chmod 0400 /etc/metronome/certs/localhost.key');
+            exec('chown metronome /etc/metronome/certs/localhost.key');
+        }else{
+            echo "-----\n";
+            echo "Metronome XMPP SSL server certificate is not renewed. Run the following command manual as root to recreate it:\n";
+            echo "# (cd /etc/metronome/certs && make localhost.key && make localhost.csr && make localhost.cert && chmod 0400 localhost.key && chown metronome localhost.key)\n";
+            echo "-----\n";
+        }
+
+        // Copy init script
+        caselog('cp -f apps/metronome-init /etc/init.d/metronome', __FILE__, __LINE__);
+        caselog('chmod u+x /etc/init.d/metronome', __FILE__, __LINE__);
+        caselog('update-rc.d metronome defaults', __FILE__, __LINE__);
+
+        exec($this->getinitcommand('xmpp', 'restart'));
+
+/*
+writing new private key to 'smtpd.key'
+-----
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:
+State or Province Name (full name) [Some-State]:
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:
+Organizational Unit Name (eg, section) []:
+Common Name (e.g. server FQDN or YOUR name) []:
+Email Address []:
+ * */
+
+        /*// Dont just copy over the virtualhost template but add some custom settings
+        $tpl = new tpl('apache_apps.vhost.master');
+
+        $tpl->setVar('apps_vhost_port',$conf['web']['apps_vhost_port']);
+        $tpl->setVar('apps_vhost_dir',$conf['web']['website_basedir'].'/apps');
+        $tpl->setVar('apps_vhost_basedir',$conf['web']['website_basedir']);
+        $tpl->setVar('apps_vhost_servername',$apps_vhost_servername);
+        $tpl->setVar('apache_version',getapacheversion());
+
+
+        // comment out the listen directive if port is 80 or 443
+        if($conf['web']['apps_vhost_ip'] == 80 or $conf['web']['apps_vhost_ip'] == 443) {
+            $tpl->setVar('vhost_port_listen','#');
+        } else {
+            $tpl->setVar('vhost_port_listen','');
+        }
+
+        wf($vhost_conf_dir.'/apps.vhost', $tpl->grab());
+        unset($tpl);*/
+    }
+
 
 	public function configure_apache() {
 		global $conf;
@@ -1969,8 +2089,9 @@ class installer_base {
 		$vserver_server_enabled = ($conf['openvz']['installed'])?1:0;
 		$proxy_server_enabled = ($conf['services']['proxy'])?1:0;
 		$firewall_server_enabled = ($conf['services']['firewall'])?1:0;
+        $xmpp_server_enabled = ($conf['services']['xmpp'])?1:0;
 
-		$sql = "UPDATE `server` SET mail_server = '$mail_server_enabled', web_server = '$web_server_enabled', dns_server = '$dns_server_enabled', file_server = '$file_server_enabled', db_server = '$db_server_enabled', vserver_server = '$vserver_server_enabled', proxy_server = '$proxy_server_enabled', firewall_server = '$firewall_server_enabled' WHERE server_id = ".intval($conf['server_id']);
+		$sql = "UPDATE `server` SET mail_server = '$mail_server_enabled', web_server = '$web_server_enabled', dns_server = '$dns_server_enabled', file_server = '$file_server_enabled', db_server = '$db_server_enabled', vserver_server = '$vserver_server_enabled', proxy_server = '$proxy_server_enabled', firewall_server = '$firewall_server_enabled', xmpp_server = '.$xmpp_server_enabled.' WHERE server_id = ".intval($conf['server_id']);
 
 		if($conf['mysql']['master_slave_setup'] == 'y') {
 			$this->dbmaster->query($sql);
diff --git a/install/sql/incremental/upd_dev_collection.sql b/install/sql/incremental/upd_dev_collection.sql
index a05084ee4a7ee9852d628dcfa17edf79aa958ac1..6eea12b71af63f848737554fd43b8626140b8c48 100644
--- a/install/sql/incremental/upd_dev_collection.sql
+++ b/install/sql/incremental/upd_dev_collection.sql
@@ -40,3 +40,97 @@ ALTER TABLE `mail_user` ADD `greylisting` ENUM( 'n', 'y' ) NOT NULL DEFAULT 'n'
 ALTER TABLE `mail_forwarding` ADD `greylisting` ENUM( 'n', 'y' ) NOT NULL DEFAULT 'n' AFTER `active`;
 
 ALTER TABLE `openvz_ip` CHANGE `ip_address` `ip_address` VARCHAR(39) DEFAULT NULL;
+
+-- XMPP Support
+
+ALTER TABLE `server` ADD COLUMN `xmpp_server` tinyint(1) NOT NULL default '0' AFTER `firewall_server`;
+
+ALTER TABLE `client`
+  ADD COLUMN `default_xmppserver` int(11) unsigned NOT NULL DEFAULT '1',
+  ADD COLUMN `xmpp_servers` blob,
+  ADD COLUMN `limit_xmpp_domain` int(11) NOT NULL DEFAULT '-1',
+  ADD COLUMN `limit_xmpp_user` int(11) NOT NULL DEFAULT '-1',
+  ADD COLUMN `limit_xmpp_muc` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  ADD COLUMN `limit_xmpp_anon` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  ADD COLUMN `limit_xmpp_auth_options` varchar(255) NOT NULL DEFAULT 'plain,hashed,isp',
+  ADD COLUMN `limit_xmpp_vjud` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  ADD COLUMN `limit_xmpp_proxy` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  ADD COLUMN `limit_xmpp_status` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  ADD COLUMN `limit_xmpp_pastebin` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  ADD COLUMN `limit_xmpp_httparchive` ENUM( 'n', 'y' ) NOT NULL default 'n';
+
+
+CREATE TABLE `xmpp_domain` (
+  `domain_id` int(11) unsigned NOT NULL auto_increment,
+  `sys_userid` int(11) unsigned NOT NULL default '0',
+  `sys_groupid` int(11) unsigned NOT NULL default '0',
+  `sys_perm_user` varchar(5) NOT NULL default '',
+  `sys_perm_group` varchar(5) NOT NULL default '',
+  `sys_perm_other` varchar(5) NOT NULL default '',
+  `server_id` int(11) unsigned NOT NULL default '0',
+  `domain` varchar(255) NOT NULL default '',
+
+  `management_method` ENUM( 'normal', 'maildomain' ) NOT NULL default 'normal',
+  `public_registration` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  `registration_url` varchar(255) NOT NULL DEFAULT '',
+  `registration_message` varchar(255) NOT NULL DEFAULT '',
+  `domain_admins` text,
+
+  `use_pubsub` enum('n','y') NOT NULL DEFAULT 'n',
+  `use_proxy` enum('n','y') NOT NULL DEFAULT 'n',
+  `use_anon_host` enum('n','y') NOT NULL DEFAULT 'n',
+
+  `use_vjud` enum('n','y') NOT NULL DEFAULT 'n',
+  `vjud_opt_mode` enum('in', 'out') NOT NULL DEFAULT 'in',
+
+  `use_muc_host` enum('n','y') NOT NULL DEFAULT 'n',
+  `muc_name` varchar(30) NOT NULL DEFAULT ''
+  `muc_restrict_room_creation` enum('n', 'y', 'm') NOT NULL DEFAULT 'm',
+  `muc_admins` text,
+  `use_pastebin` enum('n','y') NOT NULL DEFAULT 'n',
+  `pastebin_expire_after` int(3) NOT NULL DEFAULT 48,
+  `pastebin_trigger` varchar(10) NOT NULL DEFAULT '!paste',
+  `use_http_archive` enum('n','y') NOT NULL DEFAULT 'n',
+  `http_archive_show_join` enum('n', 'y') NOT NULL DEFAULT 'n',
+  `http_archive_show_status` enum('n', 'y') NOT NULL DEFAULT 'n',
+  `use_status_host` enum('n','y') NOT NULL DEFAULT 'n',
+
+  `ssl_state` varchar(255) NULL,
+  `ssl_locality` varchar(255) NULL,
+  `ssl_organisation` varchar(255) NULL,
+  `ssl_organisation_unit` varchar(255) NULL,
+  `ssl_country` varchar(255) NULL,
+  `ssl_email` varchar(255) NULL,
+  `ssl_request` mediumtext NULL,
+  `ssl_cert` mediumtext NULL,
+  `ssl_bundle` mediumtext NULL,
+  `ssl_key` mediumtext NULL,
+  `ssl_action` varchar(16) NULL,
+
+  `active` enum('n','y') NOT NULL DEFAULT 'n',
+  PRIMARY KEY  (`domain_id`),
+  KEY `server_id` (`server_id`,`domain`),
+  KEY `domain_active` (`domain`,`active`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
+
+--
+-- Table structure for table  `xmpp_user`
+--
+
+CREATE TABLE `xmpp_user` (
+  `xmppuser_id` int(11) unsigned NOT NULL auto_increment,
+  `sys_userid` int(11) unsigned NOT NULL default '0',
+  `sys_groupid` int(11) unsigned NOT NULL default '0',
+  `sys_perm_user` varchar(5) NOT NULL default '',
+  `sys_perm_group` varchar(5) NOT NULL default '',
+  `sys_perm_other` varchar(5) NOT NULL default '',
+  `server_id` int(11) unsigned NOT NULL default '0',
+  `jid` varchar(255) NOT NULL default '',
+  `password` varchar(255) NOT NULL default '',
+  `active` enum('n','y') NOT NULL DEFAULT 'n',
+  PRIMARY KEY  (`xmppuser_id`),
+  KEY `server_id` (`server_id`,`jid`),
+  KEY `jid_active` (`jid`,`active`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
+
+-- --------------------------------------------------------
diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql
index 9060f36c1483eea20fc6150f6b7f2de91c37fba8..571d59d5fc0f6adeff60f59a3621075bf0cbc637 100644
--- a/install/sql/ispconfig3.sql
+++ b/install/sql/ispconfig3.sql
@@ -184,6 +184,18 @@ CREATE TABLE `client` (
   `limit_spamfilter_wblist` int(11) NOT NULL DEFAULT '0',
   `limit_spamfilter_user` int(11) NOT NULL DEFAULT '0',
   `limit_spamfilter_policy` int(11) NOT NULL DEFAULT '0',
+  `default_xmppserver` int(11) unsigned NOT NULL DEFAULT '1',
+  `xmpp_servers` blob,
+  `limit_xmpp_domain` int(11) NOT NULL DEFAULT '-1',
+  `limit_xmpp_user` int(11) NOT NULL DEFAULT '-1',
+  `limit_xmpp_muc` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  `limit_xmpp_anon` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  `limit_xmpp_auth_options` varchar(255) NOT NULL DEFAULT 'plain,hashed,isp',
+  `limit_xmpp_vjud` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  `limit_xmpp_proxy` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  `limit_xmpp_status` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  `limit_xmpp_pastebin` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  `limit_xmpp_httparchive` ENUM( 'n', 'y' ) NOT NULL default 'n',
   `default_webserver` int(11) unsigned NOT NULL DEFAULT '1',
   `web_servers` blob,
   `limit_web_ip` text,
@@ -1201,6 +1213,7 @@ CREATE TABLE `server` (
   `vserver_server` tinyint(1) NOT NULL default '0',
   `proxy_server` tinyint(1) NOT NULL default '0',
   `firewall_server` tinyint(1) NOT NULL default '0',
+  `xmpp_server` tinyint(1) NOT NULL default '0',
   `config` text,
   `updated` bigint(20) unsigned NOT NULL default '0',
   `mirror_server_id` int(11) unsigned NOT NULL default '0',
@@ -1950,6 +1963,89 @@ CREATE TABLE `web_traffic` (
   PRIMARY KEY  (`hostname`,`traffic_date`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
 
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `xmpp_domain`
+--
+
+CREATE TABLE `xmpp_domain` (
+  `domain_id` int(11) unsigned NOT NULL auto_increment,
+  `sys_userid` int(11) unsigned NOT NULL default '0',
+  `sys_groupid` int(11) unsigned NOT NULL default '0',
+  `sys_perm_user` varchar(5) NOT NULL default '',
+  `sys_perm_group` varchar(5) NOT NULL default '',
+  `sys_perm_other` varchar(5) NOT NULL default '',
+  `server_id` int(11) unsigned NOT NULL default '0',
+  `domain` varchar(255) NOT NULL default '',
+
+  `management_method` ENUM( 'normal', 'maildomain' ) NOT NULL default 'normal',
+  `public_registration` ENUM( 'n', 'y' ) NOT NULL default 'n',
+  `registration_url` varchar(255) NOT NULL DEFAULT '',
+  `registration_message` varchar(255) NOT NULL DEFAULT '',
+  `domain_admins` text,
+
+  `use_pubsub` enum('n','y') NOT NULL DEFAULT 'n',
+  `use_proxy` enum('n','y') NOT NULL DEFAULT 'n',
+  `use_anon_host` enum('n','y') NOT NULL DEFAULT 'n',
+
+  `use_vjud` enum('n','y') NOT NULL DEFAULT 'n',
+  `vjud_opt_mode` enum('in', 'out') NOT NULL DEFAULT 'in',
+
+  `use_muc_host` enum('n','y') NOT NULL DEFAULT 'n',
+  `muc_name` varchar(30) NOT NULL DEFAULT '',
+  `muc_restrict_room_creation` enum('n', 'y', 'm') NOT NULL DEFAULT 'm',
+  `muc_admins` text,
+  `use_pastebin` enum('n','y') NOT NULL DEFAULT 'n',
+  `pastebin_expire_after` int(3) NOT NULL DEFAULT 48,
+  `pastebin_trigger` varchar(10) NOT NULL DEFAULT '!paste',
+  `use_http_archive` enum('n','y') NOT NULL DEFAULT 'n',
+  `http_archive_show_join` enum('n', 'y') NOT NULL DEFAULT 'n',
+  `http_archive_show_status` enum('n', 'y') NOT NULL DEFAULT 'n',
+  `use_status_host` enum('n','y') NOT NULL DEFAULT 'n',
+
+  `ssl_state` varchar(255) NULL,
+  `ssl_locality` varchar(255) NULL,
+  `ssl_organisation` varchar(255) NULL,
+  `ssl_organisation_unit` varchar(255) NULL,
+  `ssl_country` varchar(255) NULL,
+  `ssl_email` varchar(255) NULL,
+  `ssl_request` mediumtext NULL,
+  `ssl_cert` mediumtext NULL,
+  `ssl_bundle` mediumtext NULL,
+  `ssl_key` mediumtext NULL,
+  `ssl_action` varchar(16) NULL,
+
+  `active` enum('n','y') NOT NULL DEFAULT 'n',
+  PRIMARY KEY  (`domain_id`),
+  KEY `server_id` (`server_id`,`domain`),
+  KEY `domain_active` (`domain`,`active`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table  `xmpp_user`
+--
+
+CREATE TABLE `xmpp_user` (
+  `xmppuser_id` int(11) unsigned NOT NULL auto_increment,
+  `sys_userid` int(11) unsigned NOT NULL default '0',
+  `sys_groupid` int(11) unsigned NOT NULL default '0',
+  `sys_perm_user` varchar(5) NOT NULL default '',
+  `sys_perm_group` varchar(5) NOT NULL default '',
+  `sys_perm_other` varchar(5) NOT NULL default '',
+  `server_id` int(11) unsigned NOT NULL default '0',
+  `jid` varchar(255) NOT NULL default '',
+  `password` varchar(255) NOT NULL default '',
+  `active` enum('n','y') NOT NULL DEFAULT 'n',
+  PRIMARY KEY  (`xmppuser_id`),
+  KEY `server_id` (`server_id`,`jid`),
+  KEY `jid_active` (`jid`,`active`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
+
+-- --------------------------------------------------------
+
 -- --------------------------------------------------------
 -- --------------------------------------------------------
 -- DB-DATA
diff --git a/install/tpl/metronome_conf_global.master b/install/tpl/metronome_conf_global.master
new file mode 100644
index 0000000000000000000000000000000000000000..68f4c59b6b34badb6abb216eccbbbd053ac897f0
--- /dev/null
+++ b/install/tpl/metronome_conf_global.master
@@ -0,0 +1,65 @@
+pidfile = "/var/run/metronome/metronome.pid";
+metronome_max_files_soft = 200000;
+metronome_max_files_hard = 300000;
+plugin_paths = {
+        "/usr/lib/metronome/isp-modules",
+};
+use_libevent = true;
+log = {
+        debug = "/var/log/metronome/metronome.dbg",
+        info = "/var/log/metronome/metronome.log",
+        error = "/var/log/metronome/metronome.err",
+};
+use_ipv6 = true;
+http_ports = {
+        5290,
+};
+https_ports = {
+        5291,
+};
+pastebin_ports = {
+        5292,
+};
+bosh_ports = {
+        5280,
+};
+admins = {
+        {tmpl_var xmpp_admins}
+};
+modules_enabled = {
+        "saslauth",
+        "tls",
+        "dialback",
+        "disco",
+        "discoitems",
+        "version",
+        "uptime",
+        "time",
+        "ping",
+        "admin_adhoc",
+        "admin_telnet",
+        "bosh",
+        "posix",
+        "announce",
+        "offline",
+        "webpresence",
+        "mam",
+        "stream_management",
+        "message_carbons"
+};
+modules_disabled = {
+};
+bosh_max_inactivity = 30;
+consider_bosh_secure = true;
+cross_domain_bosh = true;
+allow_registration = false;
+ssl = {
+        key = "/etc/metronome/certs/localhost.key",
+        certificate = "/etc/metronome/certs/localhost.cert",
+};
+c2s_require_encryption = false;
+s2s_secure = true;
+s2s_insecure_domains = {
+        "gmail.com",
+};
+authentication = "internal_plain";
diff --git a/install/tpl/metronome_conf_main.master b/install/tpl/metronome_conf_main.master
new file mode 100644
index 0000000000000000000000000000000000000000..f9c8fbdd655f0771c277df692916f5e1ba78cf5e
--- /dev/null
+++ b/install/tpl/metronome_conf_main.master
@@ -0,0 +1,3 @@
+Include "/etc/metronome/global.cfg.lua"
+Include "/etc/metronome/hosts/*.lua"
+Include "/etc/metronome/status/*.lua"
diff --git a/install/tpl/metronome_conf_ssl.master b/install/tpl/metronome_conf_ssl.master
new file mode 100644
index 0000000000000000000000000000000000000000..922dfd22a1ab6c4f726fcc4b0eb84cdd60f73ec4
--- /dev/null
+++ b/install/tpl/metronome_conf_ssl.master
@@ -0,0 +1,48 @@
+oid_section = new_oids
+
+[ new_oids ]
+
+# RFC 3920 section 5.1.1 defines this OID
+xmppAddr = 1.3.6.1.5.5.7.8.5
+
+# RFC 4985 defines this OID
+SRVName  = 1.3.6.1.5.5.7.8.7
+
+[ req ]
+
+default_bits       = 4096
+default_keyfile    = {tmpl_var name='domain'}.key
+distinguished_name = distinguished_name
+req_extensions     = v3_extensions
+x509_extensions    = v3_extensions
+
+# ask about the DN?
+prompt = no
+
+[ distinguished_name ]
+
+commonName             = {tmpl_var name='domain'}
+countryName            = {tmpl_var name='ssl_country'}
+localityName           = {tmpl_var name='ssl_locality'}
+organizationName       = {tmpl_var name='ssl_organisation'}
+organizationalUnitName = {tmpl_var name='ssl_organisation_unit'}
+emailAddress           = {tmpl_var name='ssl_email'}
+
+[ v3_extensions ]
+
+# for certificate requests (req_extensions)
+# and self-signed certificates (x509_extensions)
+
+basicConstraints = CA:FALSE
+keyUsage         = digitalSignature,keyEncipherment
+extendedKeyUsage = serverAuth,clientAuth
+subjectAltName   = @subject_alternative_name
+
+[ subject_alternative_name ]
+
+# See http://tools.ietf.org/html/draft-ietf-xmpp-3920bis#section-13.7.1.2 for more info.
+
+DNS.0       =                                           {tmpl_var name='domain'}
+otherName.0 =                 xmppAddr;FORMAT:UTF8,UTF8:{tmpl_var name='domain'}
+otherName.1 =            SRVName;IA5STRING:_xmpp-client.{tmpl_var name='domain'}
+otherName.2 =            SRVName;IA5STRING:_xmpp-server.{tmpl_var name='domain'}
\ No newline at end of file
diff --git a/install/tpl/server.ini.master b/install/tpl/server.ini.master
index 7805988a71d758a294c246daddbc4a119288b5a2..20dca2d42faaf5342aad8812d8e22333022d0dc5 100644
--- a/install/tpl/server.ini.master
+++ b/install/tpl/server.ini.master
@@ -145,3 +145,12 @@ do_not_try_rescue_httpd=n
 do_not_try_rescue_mysql=n
 do_not_try_rescue_mail=n
 
+[xmpp]
+xmpp_use_ispv6=n
+xmpp_bosh_max_inactivity=30
+xmpp_server_admins=admin@service.com, superuser@service.com
+xmpp_modules_enabled=saslauth, tls, dialback, disco, discoitems, version, uptime, time, ping, admin_adhoc, admin_telnet, bosh, posix, announce, offline, webpresence, mam, stream_management, message_carbons
+xmpp_port_http=5290
+xmpp_port_https=5291
+xmpp_port_pastebin=5292
+xmpp_port_bosh=5280
diff --git a/install/update.php b/install/update.php
index 311c070dfc8d1f7ecafc60564893eb3ce888270c..8e05318ae126f60557aca7830f7b5ae315efac48 100644
--- a/install/update.php
+++ b/install/update.php
@@ -392,6 +392,11 @@ if($reconfigure_services_answer == 'yes') {
 		$inst->configure_apps_vhost();
 	}
 
+    if($conf['services']['xmpp']) {
+        //** Configure Metronome XMPP
+        $inst->configure_xmpp('dont-create-certs');
+    }
+
 
 	//* Configure DBServer
 	swriteln('Configuring Database');
@@ -494,6 +499,10 @@ if($reconfigure_services_answer == 'yes') {
 		if($conf['bind']['installed'] == true && $conf['bind']['init_script'] != '') system($inst->getinitcommand($conf['bind']['init_script'], 'restart').' &> /dev/null');
 	}
 
+    if($conf['services']['xmpp']) {
+        if($conf['xmpp']['installed'] == true && $conf['xmpp']['init_script'] != '') system($inst->getinitcommand($conf['xmpp']['init_script'], 'restart').' &> /dev/null');
+    }
+
 	if($conf['services']['proxy']) {
 		// if($conf['squid']['installed'] == true && $conf['squid']['init_script'] != '' && is_executable($conf['init_scripts'].'/'.$conf['squid']['init_script']))     system($conf['init_scripts'].'/'.$conf['squid']['init_script'].' restart &> /dev/null');
 		if($conf['nginx']['installed'] == true && $conf['nginx']['init_script'] != '') system($inst->getinitcommand($conf['nginx']['init_script'], 'restart').' &> /dev/null');
diff --git a/interface/lib/classes/validate_client.inc.php b/interface/lib/classes/validate_client.inc.php
index 198701bc4cde14f3dcca5a089e2e395f5e610e41..c67601bfb7d7c080bd5d9f15d086ab63e06d38dc 100644
--- a/interface/lib/classes/validate_client.inc.php
+++ b/interface/lib/classes/validate_client.inc.php
@@ -122,6 +122,10 @@ class validate_client {
 			case 'mail_servers':
 				$used_servers = $app->db->queryAllRecords('SELECT domain_id FROM mail_domain INNER JOIN sys_user ON mail_domain.sys_userid = sys_user.userid WHERE client_id = ' . $client_id . ' AND server_id NOT IN (' . implode(', ', $field_value) . ');');
 				break;
+
+            case 'xmpp_servers':
+                $used_servers = $app->db->queryAllRecords('SELECT domain_id FROM xmpp_domain INNER JOIN sys_user ON xmpp_domain.sys_userid = sys_user.userid WHERE client_id = ' . $client_id . ' AND server_id NOT IN (' . implode(', ', $field_value) . ');');
+                break;
 			}
 
 			if ($used_servers === null || count($used_servers))
diff --git a/interface/web/admin/form/server.tform.php b/interface/web/admin/form/server.tform.php
index a2eac6c3b758e5e6ffe1c993f167d3104fd2be05..1bf079e1b0bb08791cdddb7f70b9797e5720e504 100644
--- a/interface/web/admin/form/server.tform.php
+++ b/interface/web/admin/form/server.tform.php
@@ -102,6 +102,12 @@ $form["tabs"]['services'] = array (
 			'default' => '0',
 			'value'  => array(0 => 0, 1 => 1)
 		),
+		'xmpp_server' => array (
+			'datatype' => 'INTEGER',
+			'formtype' => 'CHECKBOX',
+			'default' => '0',
+			'value'  => array(0 => 0, 1 => 1)
+		),
 		'mirror_server_id' => array (
 			'datatype' => 'INTEGER',
 			'formtype' => 'TEXT',
diff --git a/interface/web/admin/form/server_config.tform.php b/interface/web/admin/form/server_config.tform.php
index 6f1c889bb5a510d2a25b6f4b567c6a70e0137ecd..351d4de86c32d00f6055f9c5435fe67f51b10ede 100644
--- a/interface/web/admin/form/server_config.tform.php
+++ b/interface/web/admin/form/server_config.tform.php
@@ -1318,6 +1318,86 @@ $form["tabs"]['fastcgi'] = array(
 );
 
 
+$form["tabs"]['xmpp'] = array(
+    'title' => "XMPP",
+    'width' => 80,
+    'template' => "templates/server_config_xmpp_edit.htm",
+    'fields' => array(
+        //#################################
+        // Begin Datatable fields
+        //#################################
+        'xmpp_use_ipv6' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value' => array(0 => 'n', 1 => 'y')
+        ),
+        'xmpp_bosh_max_inactivity' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'default' => '30',
+            'validators' => array(0 => array('type' => 'ISINT',
+                'errmsg' => 'ip_address_error_wrong'),
+                array('type'=>'RANGE', 'range'=>'15:360', 'errmsg' => 'xmpp_bosh_timeout_range_wrong')
+            ),
+            'value' => '',
+            'width' => '15'
+        ),
+
+        'xmpp_server_admins' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'default' => 'admin@service.com, superuser@service.com',
+            'value' => '',
+            'width' => '15'
+        ),
+
+        'xmpp_modules_enabled' => array(
+            'datatype' => 'TEXT',
+            'formtype' => 'TEXT',
+            'default' => "saslauth, tls, dialback, disco, discoitems, version, uptime, time, ping, admin_adhoc, admin_telnet, bosh, posix, announce, offline, webpresence, mam, stream_management, message_carbons",
+            'value' => '',
+            'separator' => ","
+        ),
+
+        'xmpp_port_http' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'default' => '5290',
+            'validators' => array(0 => array('type' => 'ISINT')),
+            'value' => '5290',
+            'width' => '15'
+        ),
+        'xmpp_port_https' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'default' => '5291',
+            'validators' => array(0 => array('type' => 'ISINT')),
+            'value' => '5291',
+            'width' => '15'
+        ),
+        'xmpp_port_pastebin' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'default' => '5292',
+            'validators' => array(0 => array('type' => 'ISINT')),
+            'value' => '5292',
+            'width' => '15'
+        ),
+        'xmpp_port_bosh' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'default' => '5280',
+            'validators' => array(0 => array('type' => 'ISINT')),
+            'value' => '5280',
+            'width' => '15'
+        ),
+        //#################################
+        // ENDE Datatable fields
+        //#################################
+    )
+);
+
 $form["tabs"]['jailkit'] = array(
 	'title' => "Jailkit",
 	'width' => 80,
diff --git a/interface/web/admin/lib/lang/en_server.lng b/interface/web/admin/lib/lang/en_server.lng
index 4130201b7ce0ce0b45e11a4657dfe8ed3d65b649..1f36bc718ef1402b752c9f0d9326ae68cb35fb60 100644
--- a/interface/web/admin/lib/lang/en_server.lng
+++ b/interface/web/admin/lib/lang/en_server.lng
@@ -12,4 +12,6 @@ $wb["firewall_server_txt"] = 'Firewall-Server';
 $wb["active_txt"] = 'Active';
 $wb["mirror_server_id_txt"] = 'Is mirror of Server';
 $wb["- None -"] = '- None -';
+// New for XMPP
+$wb['xmpp_server_txt'] = 'XMPP Server';
 ?>
\ No newline at end of file
diff --git a/interface/web/admin/lib/lang/en_server_config.lng b/interface/web/admin/lib/lang/en_server_config.lng
index 8affba0c14e111dfefa7123131b3ea413569f1c0..aac73906595b5517d269726f8454d6bd99ad0a83 100644
--- a/interface/web/admin/lib/lang/en_server_config.lng
+++ b/interface/web/admin/lib/lang/en_server_config.lng
@@ -264,4 +264,18 @@ $wb['php_ini_check_minutes_txt'] = 'Check php.ini every X minutes for changes';
 $wb['php_ini_check_minutes_error_empty'] = 'Please specify a value how often php.ini should be checked for changes.';
 $wb['php_ini_check_minutes_info_txt'] = '0 = no check';
 $wb['enable_spdy_txt'] = 'Makes SPDY available';
+
+// New for XMPP
+$wb['xmpp_server_txt'] = 'XMPP Server';
+$wb['xmpp_use_ipv6_txt'] = 'Use IPv6';
+$wb['xmpp_bosh_max_inactivity_txt'] = 'Max. BOSH inactivity time';
+$wb['xmpp_bosh_timeout_range_wrong'] = 'Please enter a bosh timeout range between 15 - 360';
+$wb['xmpp_module_saslauth'] = 'saslauth';
+$wb['xmpp_server_admins_txt'] = 'Server Admins (JIDs)';
+$wb['xmpp_modules_enabled_txt'] = 'Serverwide enabled plugins (one per line)';
+$wb['xmpp_ports_txt'] = 'Component ports';
+$wb['xmpp_port_http_txt'] = 'HTTP';
+$wb['xmpp_port_https_txt'] = 'HTTPS';
+$wb['xmpp_port_pastebin_txt'] = 'Pastebin';
+$wb['xmpp_port_bosh_txt'] = 'BOSH';
 ?>
diff --git a/interface/web/admin/lib/lang/en_server_list.lng b/interface/web/admin/lib/lang/en_server_list.lng
index 164468e700bb699c24e823da7f3626e58d5257ed..89a81fa43b06af831857246ace6ed47bd1460b06 100644
--- a/interface/web/admin/lib/lang/en_server_list.lng
+++ b/interface/web/admin/lib/lang/en_server_list.lng
@@ -10,4 +10,6 @@ $wb["vserver_server_txt"] = 'VServer';
 $wb["proxy_server_txt"] = 'Proxy';
 $wb["firewall_server_txt"] = 'Firewall';
 $wb["add_new_record_txt"] = 'Add new Server';
+// New for XMPP
+$wb['xmpp_server_txt'] = 'XMPP';
 ?>
\ No newline at end of file
diff --git a/interface/web/admin/list/server.list.php b/interface/web/admin/list/server.list.php
index 0309b7a3c1a60c69ad152ff884a925743ac8bbe9..0290632405d948c77cdcb90eb741fa4617df2458 100644
--- a/interface/web/admin/list/server.list.php
+++ b/interface/web/admin/list/server.list.php
@@ -110,4 +110,13 @@ $liste['item'][] = array( 'field'  => 'vserver_server',
 	'width'  => '',
 	'value'  => array('1' => "<div id=\"ir-Yes\" class=\"swap\"><span>Yes</span></div>", '0' => "<div class=\"swap\" id=\"ir-No\"><span>No</span></div>"));
 
+$liste['item'][] = array( 'field'  => 'xmpp_server',
+	'datatype' => 'VARCHAR',
+	'formtype' => 'SELECT',
+	'op'  => 'like',
+	'prefix' => '%',
+	'suffix' => '%',
+	'width'  => '',
+	'value'  => array('1' => "<div id=\"ir-Yes\" class=\"swap\"><span>Yes</span></div>", '0' => "<div class=\"swap\" id=\"ir-No\"><span>No</span></div>"));
+
 ?>
diff --git a/interface/web/admin/templates/server_config_xmpp_edit.htm b/interface/web/admin/templates/server_config_xmpp_edit.htm
new file mode 100644
index 0000000000000000000000000000000000000000..acf019b9ff9910a4fd99af6e86731ebb8cf3e2d0
--- /dev/null
+++ b/interface/web/admin/templates/server_config_xmpp_edit.htm
@@ -0,0 +1,73 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+<p><tmpl_var name="list_desc_txt"></p>
+
+
+
+<div class="form-group">
+    <label class="col-sm-3 control-label">{tmpl_var name='xmpp_use_ipv6_txt'}</label>
+    <div class="col-sm-9">
+        {tmpl_var name='xmpp_use_ipv6'}
+    </div>
+</div>
+<div class="form-group">
+    <label class="col-sm-3 control-label">{tmpl_var name='xmpp_bosh_max_inactivity_txt'}</label>
+    <div class="col-sm-3">
+        <input type="number" name="xmpp_bosh_max_inactivity" id="xmpp_bosh_max_inactivity" value="{tmpl_var name='xmpp_bosh_max_inactivity'}" class="form-control" />
+    </div>
+</div>
+
+<div class="form-group">
+    <label class="col-sm-3 control-label">{tmpl_var name='xmpp_server_admins_txt'}</label>
+    <div class="col-sm-9">
+        <input type="text" name="xmpp_server_admins" id="xmpp_server_admins" value="{tmpl_var name='xmpp_server_admins'}" class="form-control" />
+    </div>
+</div>
+
+<div class="form-group">
+    <label class="col-sm-3 control-label">{tmpl_var name='xmpp_modules_enabled_txt'}</label>
+    <div class="col-sm-9"><textarea class="form-control" name="xmpp_modules_enabled" id="xmpp_modules_enabled" rows='3' cols='30'>{tmpl_var name='xmpp_modules_enabled'}</textarea></div>
+</div>
+<div class="col-sm-12">
+    <h4>{tmpl_var name='xmpp_ports_txt'}</h4>
+    <div class="col-sm-6">
+        <div class="form-group">
+            <label class="col-sm-6 control-label">{tmpl_var name='xmpp_port_http_txt'}</label>
+            <div class="col-sm-6">
+                <input type="number" name="xmpp_port_http" id="xmpp_port_http" value="{tmpl_var name='xmpp_port_http'}" class="form-control" />
+            </div>
+        </div>
+    </div>
+    <div class="col-sm-6">
+        <div class="form-group">
+            <label class="col-sm-6 control-label">{tmpl_var name='xmpp_port_https_txt'}</label>
+            <div class="col-sm-6">
+                <input type="number" name="xmpp_port_https" id="xmpp_port_https" value="{tmpl_var name='xmpp_port_https'}" class="form-control" />
+            </div>
+        </div>
+    </div>
+    <div class="col-sm-6">
+        <div class="form-group">
+            <label class="col-sm-6 control-label">{tmpl_var name='xmpp_port_pastebin_txt'}</label>
+            <div class="col-sm-6">
+                <input type="number" name="xmpp_port_pastebin" id="xmpp_port_pastebin" value="{tmpl_var name='xmpp_port_pastebin'}" class="form-control" />
+            </div>
+        </div>
+    </div>
+    <div class="col-sm-6">
+        <div class="form-group">
+            <label class="col-sm-6 control-label">{tmpl_var name='xmpp_port_bosh_txt'}</label>
+            <div class="col-sm-6">
+                <input type="number" name="xmpp_port_bosh" id="xmpp_port_bosh" value="{tmpl_var name='xmpp_port_bosh'}" class="form-control" />
+            </div>
+        </div>
+    </div>
+</div>
+
+<input type="hidden" name="id" value="{tmpl_var name='id'}">
+
+<div class="clear"><div class="right">
+    <button class="btn btn-default formbutton-success" type="button" value="{tmpl_var name='btn_save_txt'}" data-submit-form="pageForm" data-form-action="admin/server_config_edit.php">{tmpl_var name='btn_save_txt'}</button>
+    <button class="btn btn-default formbutton-default" type="button" value="{tmpl_var name='btn_cancel_txt'}" data-load-content="admin/server_config_list.php">{tmpl_var name='btn_cancel_txt'}</button>
+</div></div>
diff --git a/interface/web/admin/templates/server_edit_services.htm b/interface/web/admin/templates/server_edit_services.htm
index aca706a0f79c87d679a48e1b2aab4236f0cb1482..4a648f4591da4504f3ad7fb9e6206913f9eff2c3 100644
--- a/interface/web/admin/templates/server_edit_services.htm
+++ b/interface/web/admin/templates/server_edit_services.htm
@@ -44,6 +44,12 @@
                     {tmpl_var name='vserver_server'}
                 </div>
             </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='xmpp_server_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='xmpp_server'}
+                </div>
+            </div>
             <div class="form-group">
                 <label for="mirror_server_id" class="col-sm-3 control-label">{tmpl_var name='mirror_server_id_txt'}</label>
                 <div class="col-sm-9"><select name="mirror_server_id" id="server_id" class="form-control">
diff --git a/interface/web/admin/templates/server_list.htm b/interface/web/admin/templates/server_list.htm
index ce568b884e5a4c6fb091fcf810101efaf2595b81..016b0cd1df8a5f1263ffbdfecc68f5e5ec2805a8 100644
--- a/interface/web/admin/templates/server_list.htm
+++ b/interface/web/admin/templates/server_list.htm
@@ -16,6 +16,7 @@
                         <th data-column="file_server"><tmpl_var name="file_server_txt"></th>
                         <th data-column="db_server"><tmpl_var name="db_server_txt"></th>
                         <th data-column="vserver_server"><tmpl_var name="vserver_server_txt"></th>
+                        <th data-column="vserver_server"><tmpl_var name="xmpp_server_txt"></th>
                         <th class="small-col text-right">{tmpl_var name='search_limit'}</th>
                     </tr>
                     <tr>
@@ -26,6 +27,7 @@
                         <td><select class="form-control" name="search_active">{tmpl_var name='search_file_server'}</select></td>
                         <td><select class="form-control" name="search_active">{tmpl_var name='search_db_server'}</select></td>
                         <td><select class="form-control" name="search_active">{tmpl_var name='search_vserver_server'}</select></td>
+                        <td><select class="form-control" name="search_active">{tmpl_var name='search_xmpp_server'}</select></td>
                         <td class="text-right">
                             <button type="button" class="btn btn-default formbutton-default formbutton-narrow" name="Filter" id="Filter" value="{tmpl_var name="filter_txt"}" data-submit-form="pageForm" data-form-action="admin/server_list.php"><span class="icon icon-filter"></span></button>
                         </td>
@@ -41,6 +43,7 @@
                             <td>{tmpl_var name="file_server"}</td>
                             <td>{tmpl_var name="db_server"}</td>
                             <td>{tmpl_var name="vserver_server"}</td>
+                            <td>{tmpl_var name="xmpp_server"}</td>
                             <td class="text-right">
                                 <a class="btn btn-default formbutton-danger formbutton-narrow" href="javascript: ISPConfig.confirm_action('admin/server_del.php?id={tmpl_var name='id'}&phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span class="icon icon-delete"></span></button>
                             </td>
diff --git a/interface/web/client/form/client.tform.php b/interface/web/client/form/client.tform.php
index 8d2ce89855339e565e0d24ad50feba3020041c9d..7507c184357a7fa2ef58e4e5c60355678518835e 100644
--- a/interface/web/client/form/client.tform.php
+++ b/interface/web/client/form/client.tform.php
@@ -773,6 +773,105 @@ $form["tabs"]['limits'] = array (
 			'rows'  => '',
 			'cols'  => ''
 		),
+        'default_xmppserver' => array (
+            'datatype' => 'INTEGER',
+            'formtype' => 'SELECT',
+            'default' => '1',
+            'datasource' => array (  'type' => 'CUSTOM',
+                'class'=> 'custom_datasource',
+                'function'=> 'client_servers'
+            ),
+            'value'  => '',
+            'name'  => 'default_xmppserver'
+        ),
+        'xmpp_servers' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'MULTIPLE',
+            'separator' => ',',
+            'default' => '1',
+            'datasource' => array (  'type' => 'CUSTOM',
+                'class'=> 'custom_datasource',
+                'function'=> 'client_servers'
+            ),
+            'validators'    => array (
+                0 => array ( 'type' => 'CUSTOM',
+                    'class' => 'validate_client',
+                    'function' => 'check_used_servers',
+                    'errmsg'=> 'xmpp_servers_used'),
+            ),
+            'value'  => '',
+            'name'  => 'xmpp_servers'
+        ),
+        'limit_xmpp_domain' => array(
+            'datatype' => 'INTEGER',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'ISINT',
+                'errmsg'=> 'limit_xmpp_domain_error_notint'),
+            ),
+            'default' => '-1',
+            'value'  => '',
+            'separator' => '',
+            'width'  => '10',
+            'maxlength' => '10',
+            'rows'  => '',
+            'cols'  => ''
+        ),
+        'limit_xmpp_user' => array(
+            'datatype' => 'INTEGER',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'ISINT',
+                'errmsg'=> 'limit_xmpp_user_error_notint'),
+            ),
+            'default' => '-1',
+            'value'  => '',
+            'separator' => '',
+            'width'  => '10',
+            'maxlength' => '10',
+            'rows'  => '',
+            'cols'  => ''
+        ),
+        'limit_xmpp_muc' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_anon' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_vjud' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_proxy' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_status' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_pastebin' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_httparchive' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
 		'default_webserver' => array (
 			'datatype' => 'INTEGER',
 			'formtype' => 'SELECT',
diff --git a/interface/web/client/form/client_template.tform.php b/interface/web/client/form/client_template.tform.php
index b1fd7d350f5879365b5d79182843c07450613cad..21f85963ee84d3a0fd7940e09d51d03c22600fc0 100644
--- a/interface/web/client/form/client_template.tform.php
+++ b/interface/web/client/form/client_template.tform.php
@@ -322,6 +322,105 @@ $form["tabs"]['limits'] = array (
 			'rows'  => '',
 			'cols'  => ''
 		),
+        'default_xmppserver' => array (
+            'datatype' => 'INTEGER',
+            'formtype' => 'SELECT',
+            'default' => '1',
+            'datasource' => array (  'type' => 'CUSTOM',
+                'class'=> 'custom_datasource',
+                'function'=> 'client_servers'
+            ),
+            'value'  => '',
+            'name'  => 'default_xmppserver'
+        ),
+        'xmpp_servers' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'MULTIPLE',
+            'separator' => ',',
+            'default' => '1',
+            'datasource' => array (  'type' => 'CUSTOM',
+                'class'=> 'custom_datasource',
+                'function'=> 'client_servers'
+            ),
+            'validators'    => array (
+                0 => array ( 'type' => 'CUSTOM',
+                    'class' => 'validate_client',
+                    'function' => 'check_used_servers',
+                    'errmsg'=> 'xmpp_servers_used'),
+            ),
+            'value'  => '',
+            'name'  => 'xmpp_servers'
+        ),
+        'limit_xmpp_domain' => array(
+            'datatype' => 'INTEGER',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'ISINT',
+                'errmsg'=> 'limit_xmpp_domain_error_notint'),
+            ),
+            'default' => '-1',
+            'value'  => '',
+            'separator' => '',
+            'width'  => '10',
+            'maxlength' => '10',
+            'rows'  => '',
+            'cols'  => ''
+        ),
+        'limit_xmpp_user' => array(
+            'datatype' => 'INTEGER',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'ISINT',
+                'errmsg'=> 'limit_xmpp_user_error_notint'),
+            ),
+            'default' => '-1',
+            'value'  => '',
+            'separator' => '',
+            'width'  => '10',
+            'maxlength' => '10',
+            'rows'  => '',
+            'cols'  => ''
+        ),
+        'limit_xmpp_muc' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_anon' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_vjud' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_proxy' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_status' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_pastebin' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_httparchive' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
 		'default_webserver' => array (
 			'datatype' => 'INTEGER',
 			'formtype' => 'SELECT',
diff --git a/interface/web/client/form/reseller.tform.php b/interface/web/client/form/reseller.tform.php
index b70c765386759e6affd609f51fa9bd15c0dde346..75e9fa2e67fe37de78d6d57018279b20aaa5c940 100644
--- a/interface/web/client/form/reseller.tform.php
+++ b/interface/web/client/form/reseller.tform.php
@@ -769,6 +769,105 @@ $form["tabs"]['limits'] = array (
 			'rows'  => '',
 			'cols'  => ''
 		),
+        'default_xmppserver' => array (
+            'datatype' => 'INTEGER',
+            'formtype' => 'SELECT',
+            'default' => '1',
+            'datasource' => array (  'type' => 'CUSTOM',
+                'class'=> 'custom_datasource',
+                'function'=> 'client_servers'
+            ),
+            'value'  => '',
+            'name'  => 'default_xmppserver'
+        ),
+        'xmpp_servers' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'MULTIPLE',
+            'separator' => ',',
+            'default' => '1',
+            'datasource' => array (  'type' => 'CUSTOM',
+                'class'=> 'custom_datasource',
+                'function'=> 'client_servers'
+            ),
+            'validators'    => array (
+                0 => array ( 'type' => 'CUSTOM',
+                    'class' => 'validate_client',
+                    'function' => 'check_used_servers',
+                    'errmsg'=> 'xmpp_servers_used'),
+            ),
+            'value'  => '',
+            'name'  => 'xmpp_servers'
+        ),
+        'limit_xmpp_domain' => array(
+            'datatype' => 'INTEGER',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'ISINT',
+                'errmsg'=> 'limit_xmpp_domain_error_notint'),
+            ),
+            'default' => '-1',
+            'value'  => '',
+            'separator' => '',
+            'width'  => '10',
+            'maxlength' => '10',
+            'rows'  => '',
+            'cols'  => ''
+        ),
+        'limit_xmpp_user' => array(
+            'datatype' => 'INTEGER',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'ISINT',
+                'errmsg'=> 'limit_xmpp_user_error_notint'),
+            ),
+            'default' => '-1',
+            'value'  => '',
+            'separator' => '',
+            'width'  => '10',
+            'maxlength' => '10',
+            'rows'  => '',
+            'cols'  => ''
+        ),
+        'limit_xmpp_muc' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_anon' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_vjud' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_proxy' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_status' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_pastebin' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'limit_xmpp_httparchive' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'n',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
 		'default_webserver' => array (
 			'datatype' => 'INTEGER',
 			'formtype' => 'SELECT',
diff --git a/interface/web/client/lib/lang/en_client.lng b/interface/web/client/lib/lang/en_client.lng
index e7e634bf08d749ce7658c371dbdd6d23dd3124ff..663d27615a74809285043ecf1dd8510ce1f5ecbf 100644
--- a/interface/web/client/lib/lang/en_client.lng
+++ b/interface/web/client/lib/lang/en_client.lng
@@ -132,6 +132,7 @@ $wb["bank_account_iban_txt"] = 'IBAN';
 $wb["bank_account_swift_txt"] = 'BIC / Swift';
 $wb["web_limits_txt"] = 'Web Limits';
 $wb["email_limits_txt"] = 'Email Limits';
+$wb["xmpp_limits_txt"] = 'XMPP Limits';
 $wb["database_limits_txt"] = 'Database Limits';
 $wb["cron_job_limits_txt"] = 'Cron Job Limits';
 $wb["dns_limits_txt"] = 'DNS Limits';
@@ -170,6 +171,24 @@ $wb["mail_servers_txt"] = 'Mailservers';
 $wb["mail_servers_placeholder"] = 'Select mailservers';
 $wb['no_mail_server_error'] = 'At least one mailserver must be selected.';
 $wb['mail_servers_used'] = 'The server you are trying to remove from this client is used as a Mailserver. Be sure that this server is not used by this client before you remove it.';
+
+$wb["xmpp_servers_txt"] = 'XMPP Servers';
+$wb["xmpp_servers_placeholder"] = 'Select XMPP Servers';
+$wb['no_xmpp_server_error'] = 'At least one XMPP Server must be selected.';
+$wb['xmpp_servers_used'] = 'The server you are trying to remove from this client is used as a XMPP Server. Be sure that this server is not used by this client before you remove it.';
+$wb['limit_xmpp_domain_error_notint'] = 'The XMPP domain limit must be a number.';
+$wb['limit_xmpp_user_error_notint'] = 'The XMPP user limit must be a number.';
+$wb['limit_xmpp_domain_txt'] = 'Max. number of XMPP domains';
+$wb['limit_xmpp_user_txt'] = 'Max. number of XMPP accounts';
+$wb['limit_xmpp_muc_txt'] = 'Multiuser chat available';
+$wb['limit_xmpp_pastebin_txt'] = 'Pastebin for MUC available';
+$wb['limit_xmpp_httparchive_txt'] = 'HTTP archive for MUC available';
+$wb['limit_xmpp_anon_txt'] = 'Anonymous host available';
+$wb['limit_xmpp_vjud_txt'] = 'VJUD user directory available';
+$wb['limit_xmpp_proxy_txt'] = 'Bytestream proxy available';
+$wb['limit_xmpp_status_txt'] = 'Status host available';
+
+
 $wb['added_by_txt'] = 'Added by';
 $wb['added_date_txt'] = 'Added date';
 $wb['parent_client_id_txt'] = 'Client of reseller';
diff --git a/interface/web/client/lib/lang/en_client_template.lng b/interface/web/client/lib/lang/en_client_template.lng
index 9aacf40319d5504ba998e4c61f5f95be318f8fcd..a65c1a514b2c278b2afe7436c09d250af909fd9a 100644
--- a/interface/web/client/lib/lang/en_client_template.lng
+++ b/interface/web/client/lib/lang/en_client_template.lng
@@ -98,4 +98,21 @@ $wb['limit_domainmodule_txt'] = 'Domainmodule Limit';
 $wb['client_limits_txt'] = 'Client Limits';
 $wb['limit_database_quota_txt'] = 'Database quota';
 $wb['limit_database_quota_error_notint'] = 'The database quota limit must be a number.';
+
+$wb["xmpp_limits_txt"] = 'XMPP Limits';
+$wb["xmpp_servers_txt"] = 'XMPP Servers';
+$wb["xmpp_servers_placeholder"] = 'Select XMPP Servers';
+$wb['no_xmpp_server_error'] = 'At least one XMPP Server must be selected.';
+$wb['xmpp_servers_used'] = 'The server you are trying to remove from this client is used as a XMPP Server. Be sure that this server is not used by this client before you remove it.';
+$wb['limit_xmpp_domain_error_notint'] = 'The XMPP domain limit must be a number.';
+$wb['limit_xmpp_user_error_notint'] = 'The XMPP user limit must be a number.';
+$wb['limit_xmpp_domain_txt'] = 'Max. number of XMPP domains';
+$wb['limit_xmpp_user_txt'] = 'Max. number of XMPP accounts';
+$wb['limit_xmpp_muc_txt'] = 'Multiuser chat available';
+$wb['limit_xmpp_pastebin_txt'] = 'Pastebin for MUC available';
+$wb['limit_xmpp_httparchive_txt'] = 'HTTP archive for MUC available';
+$wb['limit_xmpp_anon_txt'] = 'Anonymous host available';
+$wb['limit_xmpp_vjud_txt'] = 'VJUD user directory available';
+$wb['limit_xmpp_proxy_txt'] = 'Bytestream proxy available';
+$wb['limit_xmpp_status_txt'] = 'Status host available';
 ?>
diff --git a/interface/web/client/lib/lang/en_reseller.lng b/interface/web/client/lib/lang/en_reseller.lng
index e23657c0556ee875e02afa1fe6db8c35a69c4fc6..eb47bfdecdd11a91a2361f273e6e3f08d4b13064 100644
--- a/interface/web/client/lib/lang/en_reseller.lng
+++ b/interface/web/client/lib/lang/en_reseller.lng
@@ -172,6 +172,24 @@ $wb['customer_no_template_txt'] = 'Customer No. template';
 $wb['customer_no_template_error_regex_txt'] = 'The customer No. template contains invalid characters';
 $wb['customer_no_start_txt'] = 'Customer No. start value';
 $wb['customer_no_counter_txt'] = 'Customer No. counter';
+
+$wb["xmpp_limits_txt"] = 'XMPP Limits';
+$wb["xmpp_servers_txt"] = 'XMPP Servers';
+$wb["xmpp_servers_placeholder"] = 'Select XMPP Servers';
+$wb['no_xmpp_server_error'] = 'At least one XMPP Server must be selected.';
+$wb['xmpp_servers_used'] = 'The server you are trying to remove from this client is used as a XMPP Server. Be sure that this server is not used by this client before you remove it.';
+$wb['limit_xmpp_domain_error_notint'] = 'The XMPP domain limit must be a number.';
+$wb['limit_xmpp_user_error_notint'] = 'The XMPP user limit must be a number.';
+$wb['limit_xmpp_domain_txt'] = 'Max. number of XMPP domains';
+$wb['limit_xmpp_user_txt'] = 'Max. number of XMPP accounts';
+$wb['limit_xmpp_muc_txt'] = 'Multiuser chat available';
+$wb['limit_xmpp_pastebin_txt'] = 'Pastebin for MUC available';
+$wb['limit_xmpp_httparchive_txt'] = 'HTTP archive for MUC available';
+$wb['limit_xmpp_anon_txt'] = 'Anonymous host available';
+$wb['limit_xmpp_vjud_txt'] = 'VJUD user directory available';
+$wb['limit_xmpp_proxy_txt'] = 'Bytestream proxy available';
+$wb['limit_xmpp_status_txt'] = 'Status host available';
+
 $wb['added_by_txt'] = 'Added by';
 $wb['added_date_txt'] = 'Added date';
 $wb['limit_domainmodule_error_notint'] = 'Domainmodule limit must be a number.';
diff --git a/interface/web/client/templates/client_edit_limits.htm b/interface/web/client/templates/client_edit_limits.htm
index b0dc73c144ffda9e4f769a14280e64b01433c918..ed150b4d12f9dbb6ae979e2aa1e3e7eaa25e4c40 100644
--- a/interface/web/client/templates/client_edit_limits.htm
+++ b/interface/web/client/templates/client_edit_limits.htm
@@ -209,6 +209,70 @@
                     <label for="limit_spamfilter_policy" class="col-sm-3 control-label">{tmpl_var name='limit_spamfilter_policy_txt'}</label>
                     <div class="col-sm-9"><input type="text" name="limit_spamfilter_policy" id="limit_spamfilter_policy" value="{tmpl_var name='limit_spamfilter_policy'}" class="form-control" /></div></div>
             </div>
+            <div class="col-sm-3"></div><div class="col-sm-9"><button class="btn btn-default formbutton-default" type="button" data-toggle="collapse" data-target="#toggle-xmpp_limits" aria-expanded="false" aria-controls="toggle-xmpp_limits">{tmpl_var name='xmpp_limits_txt'}</button></div>
+            <div id="toggle-xmpp_limits" class="collapse">
+                <div class="form-group">
+                    <label for="xmpp_servers" class="col-sm-3 control-label">{tmpl_var name='xmpp_servers_txt'}</label>
+                    <div class="col-sm-9"><select data-placeholder="{tmpl_var name='xmpp_servers_placeholder'}" multiple name="xmpp_servers[]" id="xmpp_servers" class="form-control">
+                        {tmpl_var name='xmpp_servers'}
+                    </select></div>
+                </div>
+                <div class="form-group">
+                    <label for="limit_xmpp_domain" class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_domain_txt'}</label>
+                    <div class="col-sm-9"><input type="text" name="limit_xmpp_domain" id="limit_xmpp_domain" value="{tmpl_var name='limit_xmpp_domain'}" class="form-control" /></div></div>
+                <div class="form-group">
+                    <label for="limit_xmpp_user" class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_user_txt'}</label>
+                    <div class="col-sm-9"><input type="text" name="limit_xmpp_user" id="limit_xmpp_user" value="{tmpl_var name='limit_xmpp_user'}" class="form-control" /></div></div>
+                <!--<div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='xmpp_auth_options_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='xmpp_auth_options'}
+                    </div>
+                </div>-->
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_muc_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_muc'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_pastebin_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_pastebin'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_httparchive_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_httparchive'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_anon_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_anon'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_vjud_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_vjud'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_proxy_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_proxy'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_status_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_status'}
+                    </div>
+                </div>
+
+            </div>
             <div class="col-sm-3"></div><div class="col-sm-9"><button class="btn btn-default formbutton-default" type="button" data-toggle="collapse" data-target="#toggle-database_limits" aria-expanded="false" aria-controls="toggle-database_limits">{tmpl_var name='database_limits_txt'}</button></div>
             <div id="toggle-database_limits" class="collapse">
                 <div class="form-group">
diff --git a/interface/web/client/templates/client_template_edit_limits.htm b/interface/web/client/templates/client_template_edit_limits.htm
index 6421d8f1b4d2696426e783365a3156e810c1bfdd..abb68792b343b9e705ee321849e6d49628c77707 100644
--- a/interface/web/client/templates/client_template_edit_limits.htm
+++ b/interface/web/client/templates/client_template_edit_limits.htm
@@ -163,6 +163,71 @@
                     <label for="limit_spamfilter_policy" class="col-sm-3 control-label">{tmpl_var name='limit_spamfilter_policy_txt'}</label>
                     <div class="col-sm-9"><input type="text" name="limit_spamfilter_policy" id="limit_spamfilter_policy" value="{tmpl_var name='limit_spamfilter_policy'}" class="form-control" /></div></div>
             </div>
+
+            <div class="col-sm-3"></div><div class="col-sm-9"><button class="btn btn-default formbutton-default" type="button" data-toggle="collapse" data-target="#toggle-xmpp_limits" aria-expanded="false" aria-controls="toggle-xmpp_limits">{tmpl_var name='xmpp_limits_txt'}</button></div>
+            <div id="toggle-xmpp_limits" class="collapse">
+                <div class="form-group">
+                    <label for="xmpp_servers" class="col-sm-3 control-label">{tmpl_var name='xmpp_servers_txt'}</label>
+                    <div class="col-sm-9"><select data-placeholder="{tmpl_var name='xmpp_servers_placeholder'}" multiple name="xmpp_servers[]" id="xmpp_servers" class="form-control">
+                        {tmpl_var name='xmpp_servers'}
+                    </select></div>
+                </div>
+                <div class="form-group">
+                    <label for="limit_xmpp_domain" class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_domain_txt'}</label>
+                    <div class="col-sm-9"><input type="text" name="limit_xmpp_domain" id="limit_xmpp_domain" value="{tmpl_var name='limit_xmpp_domain'}" class="form-control" /></div></div>
+                <div class="form-group">
+                    <label for="limit_xmpp_user" class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_user_txt'}</label>
+                    <div class="col-sm-9"><input type="text" name="limit_xmpp_user" id="limit_xmpp_user" value="{tmpl_var name='limit_xmpp_user'}" class="form-control" /></div></div>
+                <!--<div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='xmpp_auth_options_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='xmpp_auth_options'}
+                    </div>
+                </div>-->
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_muc_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_muc'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_pastebin_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_pastebin'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_httparchive_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_httparchive'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_anon_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_anon'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_vjud_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_vjud'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_proxy_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_proxy'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_status_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_status'}
+                    </div>
+                </div>
+
+            </div>
             <div class="col-sm-3"></div><div class="col-sm-9"><button class="btn btn-default formbutton-default" type="button" data-toggle="collapse" data-target="#toggle-database_limits" aria-expanded="false" aria-controls="toggle-database_limits">{tmpl_var name='database_limits_txt'}</button></div>
             <div id="toggle-database_limits" class="collapse">
                 <div class="form-group">
diff --git a/interface/web/client/templates/reseller_edit_limits.htm b/interface/web/client/templates/reseller_edit_limits.htm
index aaefaffd56506eb4bb2dcb57d32c8bd513112a2e..7644b95747c1987334cd548492001e3f1e0bb70b 100644
--- a/interface/web/client/templates/reseller_edit_limits.htm
+++ b/interface/web/client/templates/reseller_edit_limits.htm
@@ -211,6 +211,70 @@
                     <label for="limit_spamfilter_policy" class="col-sm-3 control-label">{tmpl_var name='limit_spamfilter_policy_txt'}</label>
                     <div class="col-sm-9"><input type="text" name="limit_spamfilter_policy" id="limit_spamfilter_policy" value="{tmpl_var name='limit_spamfilter_policy'}" class="form-control" /></div></div>
             </div>
+            <div class="col-sm-3"></div><div class="col-sm-9"><button class="btn btn-default formbutton-default" type="button" data-toggle="collapse" data-target="#toggle-xmpp_limits" aria-expanded="false" aria-controls="toggle-xmpp_limits">{tmpl_var name='xmpp_limits_txt'}</button></div>
+            <div id="toggle-xmpp_limits" class="collapse">
+                <div class="form-group">
+                    <label for="xmpp_servers" class="col-sm-3 control-label">{tmpl_var name='xmpp_servers_txt'}</label>
+                    <div class="col-sm-9"><select data-placeholder="{tmpl_var name='xmpp_servers_placeholder'}" multiple name="xmpp_servers[]" id="xmpp_servers" class="form-control">
+                        {tmpl_var name='xmpp_servers'}
+                    </select></div>
+                </div>
+                <div class="form-group">
+                    <label for="limit_xmpp_domain" class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_domain_txt'}</label>
+                    <div class="col-sm-9"><input type="text" name="limit_xmpp_domain" id="limit_xmpp_domain" value="{tmpl_var name='limit_xmpp_domain'}" class="form-control" /></div></div>
+                <div class="form-group">
+                    <label for="limit_xmpp_user" class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_user_txt'}</label>
+                    <div class="col-sm-9"><input type="text" name="limit_xmpp_user" id="limit_xmpp_user" value="{tmpl_var name='limit_xmpp_user'}" class="form-control" /></div></div>
+                <!--<div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='xmpp_auth_options_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='xmpp_auth_options'}
+                    </div>
+                </div>-->
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_muc_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_muc'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_pastebin_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_pastebin'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_httparchive_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_httparchive'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_anon_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_anon'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_vjud_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_vjud'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_proxy_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_proxy'}
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-3 control-label">{tmpl_var name='limit_xmpp_status_txt'}</label>
+                    <div class="col-sm-9">
+                        {tmpl_var name='limit_xmpp_status'}
+                    </div>
+                </div>
+
+            </div>
             <div class="col-sm-3"></div><div class="col-sm-9"><button class="btn btn-default formbutton-default" type="button" data-toggle="collapse" data-target="#toggle-database_limits" aria-expanded="false" aria-controls="toggle-database_limits">{tmpl_var name='database_limits_txt'}</button></div>
             <div id="toggle-database_limits" class="collapse">
                 <div class="form-group">
diff --git a/interface/web/js/xmpp_domain_muc.js b/interface/web/js/xmpp_domain_muc.js
new file mode 100644
index 0000000000000000000000000000000000000000..90189288e847ec62a4ebb0ab7d4334d20bcb9f33
--- /dev/null
+++ b/interface/web/js/xmpp_domain_muc.js
@@ -0,0 +1,26 @@
+$('document').ready(function(){
+    $('#use_muc_host').on('change', function(e){
+        if($(this).is(':checked')){
+            $('#toggle-use-muc').addClass('in');
+            $('#use_pastebin').trigger('change');
+            $('#use_http_archive').trigger('change');
+        }else{
+            $('#toggle-use-muc').removeClass('in');
+        }
+    });
+    $('#use_pastebin').on('change', function(e){
+        if($(this).is(':checked')){
+            $('#toggle-use-pastebin').addClass('in');
+        }else{
+            $('#toggle-use-pastebin').removeClass('in');
+        }
+    });
+    $('#use_http_archive').on('change', function(e){
+        if($(this).is(':checked')){
+            $('#toggle-use-archive').addClass('in');
+        }else{
+            $('#toggle-use-archive').removeClass('in');
+        }
+    });
+    $('#use_muc_host').trigger('change');
+})
\ No newline at end of file
diff --git a/interface/web/js/xmpp_domain_registration.js b/interface/web/js/xmpp_domain_registration.js
new file mode 100644
index 0000000000000000000000000000000000000000..1ce239e8c66a675c75a11aa1cf3ab9e6ea1cd15c
--- /dev/null
+++ b/interface/web/js/xmpp_domain_registration.js
@@ -0,0 +1,29 @@
+$('document').ready(function(){
+    // Not needed as long as maildomain hook is not implemented
+    return;
+    $('#management_method').on('select2-selecting', function(e){
+        val = e.choice ? e.choice.id : e.target.selectedIndex;
+        if(val == 0){
+            //normal
+            $('#toggle-management-normal').addClass('in');
+            $('#toggle-registration-closed').addClass('in');
+            $('#public_registration').trigger('change');
+        }else if(val != undefined){
+            //maildomain
+            $('#toggle-management-normal').removeClass('in');
+            $('#toggle-registration-closed').removeClass('in');
+        }else{
+            $('#toggle-management-normal').removeClass('in');
+            $('#toggle-registration-closed').removeClass('in');
+        }
+    });
+    $('#public_registration').on('change', function(e){
+        if($(this).is(':checked')){
+            $('#toggle-registration-closed').removeClass('in');
+        }else{
+            $('#toggle-registration-closed').addClass('in');
+        }
+    });
+    $('#public_registration').trigger('change');
+    $('#management_method').trigger('select2-selecting');
+})
\ No newline at end of file
diff --git a/interface/web/mail/form/xmpp_domain.tform.php b/interface/web/mail/form/xmpp_domain.tform.php
new file mode 100644
index 0000000000000000000000000000000000000000..3fe62a2ac3c335e0ec5fd7e026784e8423e3e16f
--- /dev/null
+++ b/interface/web/mail/form/xmpp_domain.tform.php
@@ -0,0 +1,432 @@
+<?php
+
+/*
+	Form Definition
+
+	Tabledefinition
+
+	Datatypes:
+	- INTEGER (Forces the input to Int)
+	- DOUBLE
+	- CURRENCY (Formats the values to currency notation)
+	- VARCHAR (no format check, maxlength: 255)
+	- TEXT (no format check)
+	- DATE (Dateformat, automatic conversion to timestamps)
+
+	Formtype:
+	- TEXT (Textfield)
+	- TEXTAREA (Textarea)
+	- PASSWORD (Password textfield, input is not shown when edited)
+	- SELECT (Select option field)
+	- RADIO
+	- CHECKBOX
+	- CHECKBOXARRAY
+	- FILE
+
+	VALUE:
+	- Wert oder Array
+
+	Hint:
+	The ID field of the database table is not part of the datafield definition.
+	The ID field must be always auto incement (int or bigint).
+
+	Search:
+	- searchable = 1 or searchable = 2 include the field in the search
+	- searchable = 1: this field will be the title of the search result
+	- searchable = 2: this field will be included in the description of the search result
+
+
+*/
+
+$form["title"]    = "XMPP Domain";
+$form["description"]  = "";
+$form["name"]    = "xmpp_domain";
+$form["action"]   = "xmpp_domain_edit.php";
+$form["db_table"]  = "xmpp_domain";
+$form["db_table_idx"] = "domain_id";
+$form["db_history"]  = "yes";
+$form["tab_default"] = "domain";
+$form["list_default"] = "xmpp_domain_list.php";
+$form["auth"]   = 'yes'; // yes / no
+
+$form["auth_preset"]["userid"]  = 0; // 0 = id of the user, > 0 id must match with id of current user
+$form["auth_preset"]["groupid"] = 0; // 0 = default groupid of the user, > 0 id must match with groupid of current user
+$form["auth_preset"]["perm_user"] = 'riud'; //r = read, i = insert, u = update, d = delete
+$form["auth_preset"]["perm_group"] = 'riud'; //r = read, i = insert, u = update, d = delete
+$form["auth_preset"]["perm_other"] = ''; //r = read, i = insert, u = update, d = delete
+
+$muc_available = $muc_pastebin_available = $muc_httparchive_available = $anon_available = $vjud_available = $proxy_available = $status_available = true;
+if(!$app->auth->is_admin()) {
+    $client_group_id = $_SESSION["s"]["user"]["default_group"];
+    $client = $app->db->queryOneRecord("SELECT limit_xmpp_muc, limit_xmpp_anon, limit_xmpp_vjud, limit_xmpp_proxy, limit_xmpp_status, limit_xmpp_pastebin, limit_xmpp_httparchive FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+
+    if($client['limit_xmpp_muc'] != 'y') $muc_available = false;
+    if($client['limit_xmpp_pastebin'] != 'y' || $client['limit_xmpp_muc'] != 'y') $muc_pastebin_available = false;
+    if($client['limit_xmpp_httparchive'] != 'y' || $client['limit_xmpp_muc'] != 'y') $muc_httparchive_available = false;
+    if($client['limit_xmpp_anon'] != 'y') $anon_available = false;
+    if($client['limit_xmpp_vjud'] != 'y') $vjud_available = false;
+    if($client['limit_xmpp_proxy'] != 'y') $proxy_available= false;
+    if($client['limit_xmpp_status'] != 'y') $status_available = false;
+}
+
+$form["tabs"]['domain'] = array (
+	'title'  => "Domain",
+	'width'  => 100,
+	'template'  => "templates/xmpp_domain_edit.htm",
+	'fields'  => array (
+		//#################################
+		// Begin Datatable fields
+		//#################################
+		'server_id' => array (
+			'datatype' => 'INTEGER',
+			'formtype' => 'SELECT',
+			'default' => '',
+			'datasource' => array (  'type' => 'SQL',
+				'querystring' => 'SELECT server_id,server_name FROM server WHERE xmpp_server = 1 AND mirror_server_id = 0 AND {AUTHSQL} ORDER BY server_name',
+				'keyfield'=> 'server_id',
+				'valuefield'=> 'server_name'
+			),
+			'value'  => ''
+		),
+		'domain' => array (
+			'datatype' => 'VARCHAR',
+			'formtype' => 'TEXT',
+			'filters'   => array( 0 => array( 'event' => 'SAVE',
+					'type' => 'IDNTOASCII'),
+				1 => array( 'event' => 'SHOW',
+					'type' => 'IDNTOUTF8'),
+				2 => array( 'event' => 'SAVE',
+					'type' => 'TOLOWER')
+			),
+			'validators' => array (  0 => array ( 'type' => 'NOTEMPTY',
+					'errmsg'=> 'domain_error_empty'),
+				1 => array ( 'type' => 'UNIQUE',
+					'errmsg'=> 'domain_error_unique'),
+				2 => array ( 'type' => 'REGEX',
+					'regex' => '/^[\w\.\-]{2,255}\.[a-zA-Z0-9\-]{2,30}$/',
+					'errmsg'=> 'domain_error_regex'),
+			),
+			'default' => '',
+			'value'  => '',
+			'width'  => '30',
+			'maxlength' => '255',
+			'searchable' => 1
+		),
+		'management_method' => array (
+			'datatype'      => 'VARCHAR',
+			'formtype'      => 'SELECT',
+			'default'       => '0',
+			'value'         => array(0 => 'Normal', 1 => 'By Mail Domain')
+		),
+        'public_registration' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'y',
+            'value'  => array(0 => 'n', 1 => 'y')
+        ),
+        'registration_url' => array (
+            'datatype' => 'VARCHAR',
+            'validators' => array (  0 => array ( 'type' => 'REGEX',
+                'regex' => '@^(([\.]{0})|((ftp|https?)://([-\w\.]+)+(:\d+)?(/([\w/_\.\,\-\+\?\~!:%]*(\?\S+)?)?)?)|(\[scheme\]://([-\w\.]+)+(:\d+)?(/([\w/_\.\-\,\+\?\~!:%]*(\?\S+)?)?)?)|(/(?!.*\.\.)[\w/_\.\-]{1,255}/))$@',
+                'errmsg'=> 'redirect_error_regex'),
+            ),
+            'formtype' => 'TEXT',
+            'default' => '',
+            'value'  => '',
+            'width'  => '30',
+            'maxlength' => '255'
+        ),
+        'registration_message' => array(
+            'datatype' => 'TEXT',
+            'formtype' => 'TEXT',
+            'default' => "",
+            'value' => ''
+        ),
+        'domain_admins' => array(
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'default' => '',
+            'value' => '',
+            'width' => '15',
+            'maxlength' => '3'
+        ),
+
+		'active' => array (
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'y',
+			'value'  => array(0 => 'n', 1 => 'y')
+		),
+		//#################################
+		// ENDE Datatable fields
+		//#################################
+	)
+);
+
+$form["tabs"]['features'] = array (
+    'title'  => "Modules",
+    'width'  => 100,
+    'template'  => "templates/xmpp_domain_edit_modules.htm",
+    'fields'  => array (
+        //#################################
+        // Begin Datatable fields
+        //#################################
+        'use_pubsub' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'CHECKBOX',
+            'default' => 'y',
+            'value'  => array(0 => 'n', 1 => 'y')
+        )
+        //#################################
+        // ENDE Datatable fields
+        //#################################
+    )
+);
+if($anon_available)
+    $form['tabs']['features']['fields']['use_anon_host'] = array (
+        'datatype' => 'VARCHAR',
+        'formtype' => 'CHECKBOX',
+        'default' => 'y',
+        'value'  => array(0 => 'n', 1 => 'y')
+    );
+if($vjud_available){
+    $form['tabs']['features']['fields']['use_vjud'] = array (
+        'datatype' => 'VARCHAR',
+        'formtype' => 'CHECKBOX',
+        'default' => 'y',
+        'value'  => array(0 => 'n', 1 => 'y')
+    );
+    $form['tabs']['features']['fields']['vjud_opt_mode'] = array (
+        'datatype'      => 'VARCHAR',
+        'formtype'      => 'SELECT',
+        'default'       => '0',
+        'value'         => array(0 => 'Opt-In', 1 => 'Opt-Out')
+    );
+}
+
+if($proxy_available)
+    $form['tabs']['features']['fields']['use_proxy'] = array (
+        'datatype' => 'VARCHAR',
+        'formtype' => 'CHECKBOX',
+        'default' => 'y',
+        'value'  => array(0 => 'n', 1 => 'y')
+    );
+if($status_available)
+    $form['tabs']['features']['fields']['use_status_host'] = array (
+        'datatype' => 'VARCHAR',
+        'formtype' => 'CHECKBOX',
+        'default' => 'y',
+        'value'  => array(0 => 'n', 1 => 'y')
+    );
+
+
+if($muc_available)
+    $form["tabs"]['muc'] = array (
+        'title'  => "MUC",
+        'width'  => 100,
+        'template'  => "templates/xmpp_domain_edit_muc.htm",
+        'fields'  => array (
+            //#################################
+            // Begin Datatable fields
+            //#################################
+            'use_muc_host' => array (
+                'datatype' => 'VARCHAR',
+                'formtype' => 'CHECKBOX',
+                'default' => 'y',
+                'value'  => array(0 => 'n', 1 => 'y')
+            ),
+            'muc_name' => array(
+                'datatype' => 'VARCHAR',
+                'formtype' => 'TEXT',
+                'default' => ''
+            ),
+            'muc_restrict_room_creation' => array (
+                'datatype'      => 'VARCHAR',
+                'formtype'      => 'SELECT',
+                'default'       => '1',
+                'value'         => array(0 => 'Everyone', 1 => 'Members', 2 => 'Admins')
+            ),
+            'muc_admins' => array(
+                'datatype' => 'VARCHAR',
+                'formtype' => 'TEXT',
+                'default' => 'admin@service.com, superuser@service.com',
+                'value' => '',
+                'width' => '15',
+                'maxlength' => '3'
+            ),
+            //#################################
+            // ENDE Datatable fields
+            //#################################
+        )
+    );
+if($muc_available && $muc_pastebin_available){
+    $form['tabs']['muc']['fields']['use_pastebin'] = array (
+        'datatype' => 'VARCHAR',
+        'formtype' => 'CHECKBOX',
+        'default' => 'y',
+        'value'  => array(0 => 'n', 1 => 'y')
+    );
+    $form['tabs']['muc']['fields']['pastebin_expire_after'] = array(
+        'datatype' => 'VARCHAR',
+        'formtype' => 'TEXT',
+        'default' => '48',
+        'validators' => array(0 => array('type' => 'ISINT'),
+            array('type'=>'RANGE', 'range'=>'1:168')
+        ),
+        'value' => '',
+        'width' => '15'
+    );
+    $form['tabs']['muc']['fields']['pastebin_trigger'] = array(
+        'datatype' => 'VARCHAR',
+        'formtype' => 'TEXT',
+        'default' => '!paste',
+        'value' => '',
+        'width' => '15'
+    );
+}
+if($muc_available && $muc_httparchive_available){
+    $form['tabs']['muc']['fields']['use_http_archive'] = array (
+        'datatype' => 'VARCHAR',
+        'formtype' => 'CHECKBOX',
+        'default' => 'y',
+        'value'  => array(0 => 'n', 1 => 'y')
+    );
+    $form['tabs']['muc']['fields']['http_archive_show_join'] = array (
+        'datatype' => 'VARCHAR',
+        'formtype' => 'CHECKBOX',
+        'default' => 'y',
+        'value'  => array(0 => 'n', 1 => 'y')
+    );
+    $form['tabs']['muc']['fields']['http_archive_show_status'] = array (
+        'datatype' => 'VARCHAR',
+        'formtype' => 'CHECKBOX',
+        'default' => 'y',
+        'value'  => array(0 => 'n', 1 => 'y')
+    );
+}
+
+$form["tabs"]['ssl'] = array (
+    'title'  => "SSL",
+    'width'  => 100,
+    'template'  => "templates/xmpp_domain_edit_ssl.htm",
+    'readonly' => false,
+    'fields'  => array (
+        //#################################
+        // Begin Datatable fields
+        //#################################
+        'ssl_state' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'REGEX',
+                'regex' => '/^(([\.]{0})|([-a-zA-Z0-9._,&äöüÄÖÜ ]{1,255}))$/',
+                'errmsg'=> 'ssl_state_error_regex'),
+            ),
+            'default' => '',
+            'value'  => '',
+            'width'  => '30',
+            'maxlength' => '255'
+        ),
+        'ssl_locality' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'REGEX',
+                'regex' => '/^(([\.]{0})|([-a-zA-Z0-9._,&äöüÄÖÜ ]{1,255}))$/',
+                'errmsg'=> 'ssl_locality_error_regex'),
+            ),
+            'default' => '',
+            'value'  => '',
+            'width'  => '30',
+            'maxlength' => '255'
+        ),
+        'ssl_organisation' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'REGEX',
+                'regex' => '/^(([\.]{0})|([-a-zA-Z0-9._,&äöüÄÖÜ ]{1,255}))$/',
+                'errmsg'=> 'ssl_organisation_error_regex'),
+            ),
+            'default' => '',
+            'value'  => '',
+            'width'  => '30',
+            'maxlength' => '255'
+        ),
+        'ssl_organisation_unit' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'validators' => array (  0 => array ( 'type' => 'REGEX',
+                'regex' => '/^(([\.]{0})|([-a-zA-Z0-9._,&äöüÄÖÜ ]{1,255}))$/',
+                'errmsg'=> 'ssl_organistaion_unit_error_regex'),
+            ),
+            'default' => '',
+            'value'  => '',
+            'width'  => '30',
+            'maxlength' => '255'
+        ),
+        'ssl_country' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'SELECT',
+            'default' => '',
+            'datasource' => array (  'type' => 'SQL',
+                'querystring' => 'SELECT iso,printable_name FROM country ORDER BY printable_name',
+                'keyfield'=> 'iso',
+                'valuefield'=> 'printable_name'
+            ),
+            'value'  => ''
+        ),
+        'ssl_email' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'TEXT',
+            'default' => '',
+            'value'  => '',
+            'width'  => '30',
+            'maxlength' => '255',
+            'validators' => array (  0 => array ( 'type' => 'ISEMAIL',
+                'errmsg'=> 'ssl_error_isemail')
+            ),
+        ),
+        'ssl_key' => array (
+            'datatype' => 'TEXT',
+            'formtype' => 'TEXTAREA',
+            'default' => '',
+            'value'  => '',
+            'cols'  => '30',
+            'rows'  => '10'
+        ),
+        'ssl_request' => array (
+            'datatype' => 'TEXT',
+            'formtype' => 'TEXTAREA',
+            'default' => '',
+            'value'  => '',
+            'cols'  => '30',
+            'rows'  => '10'
+        ),
+        'ssl_cert' => array (
+            'datatype' => 'TEXT',
+            'formtype' => 'TEXTAREA',
+            'default' => '',
+            'value'  => '',
+            'cols'  => '30',
+            'rows'  => '10'
+        ),
+        'ssl_bundle' => array (
+            'datatype' => 'TEXT',
+            'formtype' => 'TEXTAREA',
+            'default' => '',
+            'value'  => '',
+            'cols'  => '30',
+            'rows'  => '10'
+        ),
+        'ssl_action' => array (
+            'datatype' => 'VARCHAR',
+            'formtype' => 'SELECT',
+            'default' => '',
+            'value'  => array('' => 'none_txt', 'save' => 'save_certificate_txt', 'create' => 'create_certificate_txt', 'del' => 'delete_certificate_txt')
+        ),
+        //#################################
+        // ENDE Datatable fields
+        //#################################
+    )
+);
+
+
+?>
diff --git a/interface/web/mail/form/xmpp_user.tform.php b/interface/web/mail/form/xmpp_user.tform.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7360787349de587e6e13b7acb666951a96bfdea
--- /dev/null
+++ b/interface/web/mail/form/xmpp_user.tform.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+	Form Definition
+
+	Tabledefinition
+
+	Datatypes:
+	- INTEGER (Forces the input to Int)
+	- DOUBLE
+	- CURRENCY (Formats the values to currency notation)
+	- VARCHAR (no format check, maxlength: 255)
+	- TEXT (no format check)
+	- DATE (Dateformat, automatic conversion to timestamps)
+
+	Formtype:
+	- TEXT (Textfield)
+	- TEXTAREA (Textarea)
+	- PASSWORD (Password textfield, input is not shown when edited)
+	- SELECT (Select option field)
+	- RADIO
+	- CHECKBOX
+	- CHECKBOXARRAY
+	- FILE
+
+	VALUE:
+	- Wert oder Array
+
+	Hint:
+	The ID field of the database table is not part of the datafield definition.
+	The ID field must be always auto incement (int or bigint).
+
+	Search:
+	- searchable = 1 or searchable = 2 include the field in the search
+	- searchable = 1: this field will be the title of the search result
+	- searchable = 2: this field will be included in the description of the search result
+
+
+*/
+global $app;
+$app->uses('getconf');
+$global_config = $app->getconf->get_global_config();
+
+$form["title"]    = "XMPP Account";
+$form["description"]  = "";
+$form["name"]    = "xmpp_user";
+$form["action"]   = "xmpp_user_edit.php";
+$form["db_table"]  = "xmpp_user";
+$form["db_table_idx"] = "xmppuser_id";
+$form["db_history"]  = "yes";
+$form["tab_default"] = "xmppuser";
+$form["list_default"] = "xmpp_user_list.php";
+$form["auth"]   = 'yes'; // yes / no
+
+$form["auth_preset"]["userid"]  = 0; // 0 = id of the user, > 0 id must match with id of current user
+$form["auth_preset"]["groupid"] = 0; // 0 = default groupid of the user, > 0 id must match with groupid of current user
+$form["auth_preset"]["perm_user"] = 'riud'; //r = read, i = insert, u = update, d = delete
+$form["auth_preset"]["perm_group"] = 'riud'; //r = read, i = insert, u = update, d = delete
+$form["auth_preset"]["perm_other"] = ''; //r = read, i = insert, u = update, d = delete
+
+$form["tabs"]['xmppuser'] = array(
+	'title'  => "XMPP Account",
+	'width'  => 100,
+	'template'  => "templates/xmpp_user_edit.htm",
+	'fields'  => array (
+		//#################################
+		// Begin Datatable fields
+		//#################################
+		'server_id' => array (
+			'datatype' => 'INTEGER',
+			'formtype' => 'TEXT',
+			'default' => '',
+			'value'  => '',
+			'width'  => '30',
+			'maxlength' => '255'
+		),
+		'jid' => array (
+			'datatype' => 'VARCHAR',
+			'formtype' => 'TEXT',
+			'filters'   => array( 0 => array( 'event' => 'SAVE',
+					'type' => 'IDNTOASCII'),
+				1 => array( 'event' => 'SHOW',
+					'type' => 'IDNTOUTF8'),
+				2 => array( 'event' => 'SAVE',
+					'type' => 'TOLOWER')
+			),
+			'validators' => array (  0 => array ( 'type' => 'ISEMAIL',
+					'errmsg'=> 'jid_error_isemail'),
+				1 => array ( 'type' => 'UNIQUE',
+					'errmsg'=> 'jid_error_unique'),
+			),
+			'default' => '',
+			'value'  => '',
+			'width'  => '30',
+			'maxlength' => '255',
+			'searchable' => 1
+		),
+		'password' => array (
+			'datatype' => 'VARCHAR',
+			'formtype' => 'PASSWORD',
+			'validators' => array(
+				0 => array(
+					'type' => 'CUSTOM',
+					'class' => 'validate_password',
+					'function' => 'password_check',
+					'errmsg' => 'weak_password_txt'
+				)
+			),
+			'encryption'=> 'CRYPT',
+			'default' => '',
+			'value'  => '',
+			'width'  => '30',
+			'maxlength' => '255'
+		),
+		'active' => array (
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'y',
+			'value'  => array(1 => 'y', 0 => 'n')
+		),
+		//#################################
+		// END Datatable fields
+		//#################################
+	)
+);
+
+?>
diff --git a/interface/web/mail/lib/lang/en_xmpp_domain.lng b/interface/web/mail/lib/lang/en_xmpp_domain.lng
new file mode 100644
index 0000000000000000000000000000000000000000..f1da77ba2982cd082929d00250decf05d4bff728
--- /dev/null
+++ b/interface/web/mail/lib/lang/en_xmpp_domain.lng
@@ -0,0 +1,62 @@
+<?php
+$wb["server_id_txt"] = 'Server';
+$wb["client_group_id_txt"] = 'Client';
+$wb["domain_txt"] = 'Domain';
+$wb["type_txt"] = 'Type';
+$wb["active_txt"] = 'Active';
+$wb["client_txt"] = 'Client';
+$wb["management_method_txt"] = 'Management of user accounts';
+$wb["public_registration_txt"] = 'Enable public registration';
+$wb["registration_url_txt"] = 'Registration URL';
+$wb["registration_message_txt"] = 'Registration Message';
+$wb["domain_admins_txt"] = 'Domain Admins (JIDs)';
+$wb["use_pubsub_txt"] = 'Enable Pubsub';
+$wb["use_proxy_txt"] = 'Enable Bytestream Proxy';
+$wb["use_anon_host_txt"] = 'Enable Anonymous Host';
+$wb["use_vjud_txt"] = 'Enable VJUD User Directory';
+$wb["vjud_opt_mode_txt"] = 'VJUD Opt Mode';
+$wb["use_muc_host_txt"] = 'Enable Multi User Chatrooms';
+$wb["muc_name_txt"] = 'Name in MUC Service Discovery';
+$wb["muc_restrict_room_creation_txt"] = 'Permission to create chatrooms';
+$wb["muc_admins_txt"] = 'MUC Admins (JIDs)';
+$wb["use_pastebin_txt"] = 'Enable Pastebin';
+$wb["pastebin_expire_after_txt"] = 'Pastes expire after (hours)';
+$wb["pastebin_trigger_txt"] = 'Pastebin trigger';
+$wb["use_http_archive_txt"] = 'Enable HTTP chatroom archive';
+$wb["http_archive_show_join_txt"] = 'Show join messages in archive';
+$wb["http_archive_show_status_txt"] = 'Show status changes in archive';
+$wb["use_status_host_txt"] = 'Enable XML Status host';
+$wb["cant_change_domainname_txt"] = 'The Domain name of existing XMPP domain cannot be changed.';
+$wb["about_registration_url_txt"] = 'Link to your registration form.';
+$wb["about_registration_message_txt"] = 'Description about your account registration process.';
+$wb["no_corresponding_maildomain_txt"] = 'Corresponding mail domain for user management not found. Please create the mail domain first.';
+$wb['ssl_state_txt'] = 'State';
+$wb['ssl_locality_txt'] = 'Locality';
+$wb['ssl_organisation_txt'] = 'Organisation';
+$wb['ssl_organisation_unit_txt'] = 'Organisation Unit';
+$wb['ssl_country_txt'] = 'Country';
+$wb['ssl_key_txt'] = 'SSL Key';
+$wb['ssl_request_txt'] = 'SSL Request';
+$wb['ssl_cert_txt'] = 'SSL Certificate';
+$wb['ssl_bundle_txt'] = 'SSL Bundle';
+$wb['ssl_action_txt'] = 'SSL Action';
+$wb['ssl_email_txt'] = 'Email Address';
+$wb['ssl_txt'] = 'SSL';
+$wb['error_ssl_state_empty'] = 'SSL State is empty.';
+$wb['error_ssl_locality_empty'] = 'SSL Locality is empty.';
+$wb['error_ssl_organisation_empty'] = 'SSL Organisation is empty.';
+$wb['error_ssl_organisation_unit_empty'] = 'SSL Organisation Unit is empty.';
+$wb['error_ssl_country_empty'] = 'SSL Country is empty.';
+$wb['error_ssl_cert_empty'] = 'SSL Certificate field is empty';
+$wb['ssl_state_error_regex'] = 'Invalid SSL State. Valid characters are: a-z, 0-9 and .,-_&äöüÄÖÜ';
+$wb['ssl_locality_error_regex'] = 'Invalid SSL Locality. Valid characters are: a-z, 0-9 and .,-_&äöüÄÖÜ';
+$wb['ssl_organisation_error_regex'] = 'Invalid SSL Organisation. Valid characters are: a-z, 0-9 and .,-_&äöüÄÖÜ';
+$wb['ssl_organistaion_unit_error_regex'] = 'Invalid SSL Organisation Unit. Valid characters are: a-z, 0-9 and .,-_&äöüÄÖÜ';
+$wb['ssl_country_error_regex'] = 'Invalid SSL Country. Valid characters are: A-Z';
+$wb['none_txt'] = 'None';
+$wb['save_certificate_txt'] = 'Save certificate';
+$wb['create_certificate_txt'] = 'Create certificate';
+$wb['delete_certificate_txt'] = 'Delete certificate';
+$wb['ssl_error_isemail'] = 'Please enter a valid email adress for generation of the SSL certificate';
+$wb["limit_xmppdomain_txt"] = 'The max. number of XMPP domains for your account is reached.';
+?>
diff --git a/interface/web/mail/lib/lang/en_xmpp_domain_admin_list.lng b/interface/web/mail/lib/lang/en_xmpp_domain_admin_list.lng
new file mode 100644
index 0000000000000000000000000000000000000000..a3d1736d7b95807bc324217b299a534f20926560
--- /dev/null
+++ b/interface/web/mail/lib/lang/en_xmpp_domain_admin_list.lng
@@ -0,0 +1,8 @@
+<?php
+$wb["list_head_txt"] = 'XMPP Domain';
+$wb["server_id_txt"] = 'Server';
+$wb["domain_txt"] = 'Domain';
+$wb["add_new_record_txt"] = 'Add new Domain';
+$wb["active_txt"] = 'Active';
+$wb["sys_groupid_txt"] = 'Client';
+?>
\ No newline at end of file
diff --git a/interface/web/mail/lib/lang/en_xmpp_domain_list.lng b/interface/web/mail/lib/lang/en_xmpp_domain_list.lng
new file mode 100644
index 0000000000000000000000000000000000000000..f8c2fb9b8e1907d31390269e5e0df8ec3375e49b
--- /dev/null
+++ b/interface/web/mail/lib/lang/en_xmpp_domain_list.lng
@@ -0,0 +1,7 @@
+<?php
+$wb["list_head_txt"] = 'XMPP Domain';
+$wb["server_id_txt"] = 'Server';
+$wb["domain_txt"] = 'Domain';
+$wb["add_new_record_txt"] = 'Add new Domain';
+$wb["active_txt"] = 'Active';
+?>
\ No newline at end of file
diff --git a/interface/web/mail/lib/lang/en_xmpp_user.lng b/interface/web/mail/lib/lang/en_xmpp_user.lng
new file mode 100644
index 0000000000000000000000000000000000000000..1cc852e3cf8f9332cd168d10e82aa70fb6beaf7a
--- /dev/null
+++ b/interface/web/mail/lib/lang/en_xmpp_user.lng
@@ -0,0 +1,15 @@
+<?php
+$wb["list_head_txt"] = 'XMPP User Accounts';
+$wb["jid_txt"] = 'Jabber ID';
+$wb["active_txt"] = 'Active';
+$wb["cryptpwd_txt"] = 'Password';
+$wb["password_strength_txt"] = 'Password strength';
+$wb["error_no_pwd"] = 'Password is empty.';
+$wb["password_txt"] = 'Password';
+$wb['generate_password_txt'] = 'Generate Password';
+$wb['repeat_password_txt'] = 'Repeat Password';
+$wb['password_mismatch_txt'] = 'The passwords do not match.';
+$wb['password_match_txt'] = 'The passwords do match.';
+$wb["no_domain_perm"] = 'You have no permission for this domain.';
+$wb["limit_xmpp_user_txt"] = 'The max. number of xmpp accounts for your account is reached.';
+?>
\ No newline at end of file
diff --git a/interface/web/mail/lib/lang/en_xmpp_user_list.lng b/interface/web/mail/lib/lang/en_xmpp_user_list.lng
new file mode 100644
index 0000000000000000000000000000000000000000..db88b0d7e3ab295b1992f40dc0bf67abfc99f26a
--- /dev/null
+++ b/interface/web/mail/lib/lang/en_xmpp_user_list.lng
@@ -0,0 +1,8 @@
+<?php
+$wb["list_head_txt"] = 'XMPP User Accounts';
+$wb["jid_txt"] = 'Jabber ID';
+$wb["is_domain_admin_txt"] = 'Domain admin';
+$wb["is_muc_admin_txt"] = 'MUC admin';
+$wb["add_new_record_txt"] = 'Add new user';
+$wb["active_txt"] = 'Active';
+?>
\ No newline at end of file
diff --git a/interface/web/mail/lib/module.conf.php b/interface/web/mail/lib/module.conf.php
index 2ca9b7aca9b0a96454743428f60da8d81f92ec24..b6df07e97e1dfc6d6911e6e13a76baa091e76d0a 100644
--- a/interface/web/mail/lib/module.conf.php
+++ b/interface/web/mail/lib/module.conf.php
@@ -148,6 +148,30 @@ if($app->auth->get_client_limit($userid, 'fetchmail') != 0)
 		'items' => $items);
 }
 
+//**** XMPP Menu
+$items = array();
+
+if($app->auth->get_client_limit($userid, 'xmpp_domain') != 0)
+{
+    $items[] = array( 'title'  => 'XMPP Domain',
+        'target'  => 'content',
+        'link' => 'mail/xmpp_domain_list.php',
+        'html_id' => 'xmpp_domain_list');
+}
+
+if($app->auth->get_client_limit($userid, 'xmpp_user') != 0)
+{
+    $items[] = array( 'title'  => 'XMPP Account',
+        'target'  => 'content',
+        'link' => 'mail/xmpp_user_list.php',
+        'html_id' => 'xmpp_user_list');
+}
+
+if(count($items))
+    $module['nav'][] = array( 'title' => 'Jabber / XMPP',
+        'open'  => 1,
+        'items' => $items);
+
 
 
 //**** Statistics menu
diff --git a/interface/web/mail/list/xmpp_domain.list.php b/interface/web/mail/list/xmpp_domain.list.php
new file mode 100644
index 0000000000000000000000000000000000000000..21257e428312c11638025500f5c1662ea73e84a0
--- /dev/null
+++ b/interface/web/mail/list/xmpp_domain.list.php
@@ -0,0 +1,109 @@
+<?php
+
+/*
+	Datatypes:
+	- INTEGER
+	- DOUBLE
+	- CURRENCY
+	- VARCHAR
+	- TEXT
+	- DATE
+*/
+
+
+
+// Name of the list
+if($_SESSION['s']['user']['typ'] == 'admin') {
+	$liste["name"]     = "xmpp_domain_admin";
+} else {
+	$liste["name"]     = "xmpp_domain";
+}
+
+// Database table
+$liste["table"]    = "xmpp_domain";
+
+// Index index field of the database table
+$liste["table_idx"]   = "domain_id";
+
+// Search Field Prefix
+$liste["search_prefix"]  = "search_";
+
+// Records per page
+$liste["records_per_page"]  = "15";
+
+// Script File of the list
+$liste["file"]    = "xmpp_domain_list.php";
+
+// Script file of the edit form
+$liste["edit_file"]   = "xmpp_domain_edit.php";
+
+// Script File of the delete script
+$liste["delete_file"]  = "xmpp_domain_del.php";
+
+// Paging Template
+$liste["paging_tpl"]  = "templates/paging.tpl.htm";
+
+// Enable auth
+$liste["auth"]    = "yes";
+
+
+/*****************************************************
+* Suchfelder
+*****************************************************/
+
+
+$liste["item"][] = array( 'field'  => "active",
+	'datatype' => "VARCHAR",
+	'formtype' => "SELECT",
+	'op'  => "=",
+	'prefix' => "",
+	'suffix' => "",
+	'width'  => "",
+	'value'  => array('y' => "<div id=\"ir-Yes\" class=\"swap\"><span>Yes</span></div>", 'n' => "<div class=\"swap\" id=\"ir-No\"><span>No</span></div>"));
+
+
+if($_SESSION['s']['user']['typ'] == 'admin') {
+	$liste["item"][] = array( 'field'  => "sys_groupid",
+		'datatype' => "INTEGER",
+		'formtype' => "SELECT",
+		'op'  => "=",
+		'prefix' => "",
+		'suffix' => "",
+		'datasource' => array (  'type' => 'SQL',
+			'querystring' => 'SELECT groupid, name FROM sys_group WHERE groupid != 1 ORDER BY name',
+			'keyfield'=> 'groupid',
+			'valuefield'=> 'name'
+		),
+		'width'  => "",
+		'value'  => "");
+}
+
+
+$liste["item"][] = array( 'field'  => "server_id",
+	'datatype' => "INTEGER",
+	'formtype' => "SELECT",
+	'op'  => "like",
+	'prefix' => "",
+	'suffix' => "",
+	'datasource' => array (  'type' => 'SQL',
+		'querystring' => 'SELECT a.server_id, a.server_name FROM server a, xmpp_domain b WHERE (a.server_id = b.server_id) AND ({AUTHSQL-B}) ORDER BY a.server_name',
+		'keyfield'=> 'server_id',
+		'valuefield'=> 'server_name'
+	),
+	'width'  => "",
+	'value'  => "");
+
+$liste["item"][] = array( 'field'  => "domain",
+	'datatype' => "VARCHAR",
+	'filters'   => array( 0 => array( 'event' => 'SHOW',
+			'type' => 'IDNTOUTF8')
+	),
+	'formtype' => "TEXT",
+	'op'  => "like",
+	'prefix' => "%",
+	'suffix' => "%",
+	'width'  => "",
+	'value'  => "");
+
+
+?>
diff --git a/interface/web/mail/list/xmpp_user.list.php b/interface/web/mail/list/xmpp_user.list.php
new file mode 100644
index 0000000000000000000000000000000000000000..c1cdbb8d4d36b3282d7de9d6417982854e8e4171
--- /dev/null
+++ b/interface/web/mail/list/xmpp_user.list.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+	Datatypes:
+	- INTEGER
+	- DOUBLE
+	- CURRENCY
+	- VARCHAR
+	- TEXT
+	- DATE
+*/
+
+
+
+// Name of the list
+$liste["name"]    = "xmpp_user";
+
+// Database table
+$liste["table"]   = "xmpp_user";
+
+// Index index field of the database table
+$liste["table_idx"]  = "xmppuser_id";
+
+// Search Field Prefix
+$liste["search_prefix"]  = "search_";
+
+// Records per page
+$liste["records_per_page"]  = "15";
+
+// Script File of the list
+$liste["file"]   = "xmpp_user_list.php";
+
+// Script file of the edit form
+$liste["edit_file"]  = "xmpp_user_edit.php";
+
+// Script File of the delete script
+$liste["delete_file"]  = "xmpp_user_del.php";
+
+// Paging Template
+$liste["paging_tpl"]  = "templates/paging.tpl.htm";
+
+// Enable auth
+$liste["auth"]   = "yes";
+
+
+/*****************************************************
+* Suchfelder
+*****************************************************/
+
+$liste["item"][] = array(   'field'     => "JID",
+	'datatype'  => "VARCHAR",
+	'filters'   => array( 0 => array( 'event' => 'SHOW',
+			'type' => 'IDNTOUTF8')
+	),
+	'formtype'  => "TEXT",
+	'op'        => "like",
+	'prefix'    => "%",
+	'suffix'    => "%",
+	'width'     => "",
+	'value'     => "");
+
+?>
diff --git a/interface/web/mail/templates/xmpp_domain_admin_list.htm b/interface/web/mail/templates/xmpp_domain_admin_list.htm
new file mode 100644
index 0000000000000000000000000000000000000000..ccda2d503263caa1a1dc00f61294b6bfa61c8b3d
--- /dev/null
+++ b/interface/web/mail/templates/xmpp_domain_admin_list.htm
@@ -0,0 +1,60 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+
+
+        <p class="fieldset-legend">{tmpl_var name="toolsarea_head_txt"}</p>
+
+                <button class="btn btn-default formbutton-success" type="button" data-load-content="mail/xmpp_domain_edit.php">{tmpl_var name="add_new_record_txt"}</button>
+            
+        
+
+    
+        <p class="fieldset-legend"><tmpl_var name="list_head_txt"></p>
+            <div class="table-wrapper marginTop15">
+<table class="table">
+                <thead class="dark form-group-sm">
+                    <tr>
+                        <th class="tiny-col" data-column="active"><tmpl_var name="active_txt"></th>
+                        <th data-column="sys_groupid"><tmpl_var name="sys_groupid_txt"></th>
+                        <th data-column="server_id"><tmpl_var name="server_id_txt"></th>
+                        <th data-column="domain"><tmpl_var name="domain_txt"></th>
+                        <th class="small-col text-right">{tmpl_var name='search_limit'}</th>
+                    </tr>
+                    <tr>
+                        <td><select class="form-control" name="search_active">{tmpl_var name='search_active'}</select></td>
+                        <td><select class="form-control" name="search_sys_groupid">{tmpl_var name='search_sys_groupid'}</select></td>
+                        <td><select class="form-control" name="search_server_id">{tmpl_var name='search_server_id'}</select></td>
+                        <td><input class="form-control" type="text" name="search_domain" value="{tmpl_var name='search_domain'}" /></td>
+                        <td class="text-right">
+                            <button type="button" class="btn btn-default formbutton-default formbutton-narrow" name="Filter" id="Filter" value="{tmpl_var name="filter_txt"}" data-submit-form="pageForm" data-form-action="mail/xmpp_domain_list.php"><span class="icon icon-filter"></span></button>
+                        </td>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tmpl_loop name="records">
+                        <tr>
+                            <td><a href="#" data-load-content="mail/xmpp_domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="active"}</a></td>
+                            <td><a href="#" data-load-content="mail/xmpp_domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="sys_groupid"}</a></td>
+                            <td><a href="#" data-load-content="mail/xmpp_domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="server_id"}</a></td>
+                            <td><a href="#" data-load-content="mail/xmpp_domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="domain"}</a></td>
+                            <td class="text-right">
+                                <a class="btn btn-default formbutton-danger formbutton-narrow" href="javascript: ISPConfig.confirm_action('mail/xmpp_domain_del.php?id={tmpl_var name='id'}&phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span class="icon icon-delete"></span></button>
+                            </td>
+                        </tr>
+                    </tmpl_loop>
+                    <tmpl_unless name="records">
+                        <tr class="tbl_row_noresults tbl_row_<tmpl_if name='__EVEN__'}even<tmpl_else>uneven</tmpl_if>">
+                            <td colspan="5">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
+                        </tr>
+                    </tmpl_unless>
+                </tbody>
+                <tfoot>
+                    <tr>
+                        <td colspan="5"><tmpl_var name="paging"></td>
+                    </tr>
+                </tfoot>
+            </table>
+</div>
+        
+    
\ No newline at end of file
diff --git a/interface/web/mail/templates/xmpp_domain_edit.htm b/interface/web/mail/templates/xmpp_domain_edit.htm
new file mode 100644
index 0000000000000000000000000000000000000000..5c4e8d79a096fb594d574a7830479f0688139c0b
--- /dev/null
+++ b/interface/web/mail/templates/xmpp_domain_edit.htm
@@ -0,0 +1,130 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+<p><tmpl_var name="list_desc_txt"></p>
+
+
+        
+            <tmpl_if name="is_admin">
+                <div class="form-group">
+                    <tmpl_if name="edit_disabled">
+                        <label for="server_id_disabled" class="col-sm-3 control-label">{tmpl_var name='server_id_txt'}</label>
+                        <div class="col-sm-9"><select name="server_id_disabled" id="server_id_disabled" class="form-control" disabled="disabled">
+                            {tmpl_var name='server_id'}
+                        </select></div>
+                        <input type="hidden" name="server_id" value="{tmpl_var name='server_id_value'}" />
+                        <tmpl_else>
+                            <label for="server_id" class="col-sm-3 control-label">{tmpl_var name='server_id_txt'}</label>
+                            <div class="col-sm-9"><select name="server_id" id="server_id" class="form-control">
+                                {tmpl_var name='server_id'}
+                            </select></div>
+                    </tmpl_if>
+                </div>
+                <tmpl_unless name="domain_option">
+                    <div class="form-group">
+                        <label for="client_group_id" class="col-sm-3 control-label">{tmpl_var name='client_group_id_txt'}</label>
+                        <div class="col-sm-9"><select name="client_group_id" id="client_group_id" class="form-control">
+                            {tmpl_var name='client_group_id'}
+                        </select></div>
+                    </div>
+                </tmpl_unless>
+            <tmpl_else>
+                <tmpl_if name="only_one_server">
+                    <input type="hidden" id="server_id" name="server_id" value="{tmpl_var name='server_id_value'}" />
+                <tmpl_else>
+                    <div class="form-group">
+                        <tmpl_if name="edit_disabled">
+                            <label for="server_id_disabled" class="col-sm-3 control-label">{tmpl_var name='server_id_txt'}</label>
+                            <div class="col-sm-9"><select name="server_id_disabled" id="server_id_disabled" class="form-control" disabled="disabled">
+                                {tmpl_var name='client_server_id'}
+                            </select></div>
+                            <input type="hidden" name="server_id" value="{tmpl_var name='server_id_value'}" />
+                        <tmpl_else>
+                            <label for="server_id" class="col-sm-3 control-label">{tmpl_var name='server_id_txt'}</label>
+                            <div class="col-sm-9"><select name="server_id" id="server_id" class="form-control">
+                                {tmpl_var name='client_server_id'}
+                            </select></div>
+                        </tmpl_if>
+                    </div>
+                </tmpl_if>
+            </tmpl_if>
+
+            <tmpl_if name="is_reseller">
+                <tmpl_unless name="domain_option">
+                    <div class="form-group">
+                        <label for="client_group_id" class="col-sm-3 control-label">{tmpl_var name='client_group_id_txt'}</label>
+                        <div class="col-sm-9"><select name="client_group_id" id="client_group_id" class="form-control">
+                            {tmpl_var name='client_group_id'}
+                        </select></div>
+                    </div>
+                </tmpl_unless>
+            </tmpl_if>
+
+            <div class="form-group">
+                <label for="domain" class="col-sm-3 control-label">{tmpl_var name='domain_txt'}</label>
+                <tmpl_if name="domain_option">
+                    <div class="col-sm-9"><select name="domain" id="domain" class="form-control">
+                        {tmpl_var name='domain_option'}
+                    </select></div>
+                    <tmpl_else>
+                        <div class="col-sm-9"><input type="text" name="domain" id="domain" value="{tmpl_var name='domain'}" class="form-control" <tmpl_if name="edit_disabled">readonly="readonly"</tmpl_if>/></div></tmpl_if>
+            </div>
+
+
+
+
+<!--
+management by maildomain is currently not supported
+<div class="form-group">
+    <label for="management_method" class="col-sm-3 control-label">{tmpl_var name='management_method_txt'}</label>
+    <div class="col-sm-9"><select name="management_method" id="management_method" class="form-control">
+        {tmpl_var name='management_method'}
+    </select></div>
+</div>
+-->
+<input type="hidden" name="management_method" id="management_method" value="0" />
+
+<div id="toggle-management-normal" class="collapse">
+    <!--
+    Currently not supported
+    div class="form-group">
+        <label class="col-sm-3 control-label">{tmpl_var name='public_registration_txt'}</label>
+        <div class="col-sm-9">
+            {tmpl_var name='public_registration'}
+        </div>
+    </div-->
+</div>
+        <input type="hidden" name="public_registration" id="public_registration" value="n" />
+<div id="toggle-registration-closed" class="collapse in">
+    <div class="form-group">
+        <label for="registration_url" class="col-sm-3 control-label">{tmpl_var name='registration_url_txt'}</label>
+        <div class="col-sm-9">
+            <input type="text" name="registration_url" id="registration_url" value="{tmpl_var name='registration_url'}" class="form-control" placeholder="<tmpl_var name='about_registration_url_txt'>" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="col-sm-3 control-label">{tmpl_var name='registration_message_txt'}</label>
+        <div class="col-sm-9"><textarea class="form-control" name="registration_message" id="registration_message" rows='3' cols='30' placeholder="<tmpl_var name='about_registration_message_txt'>">{tmpl_var name='registration_message'}</textarea></div>
+    </div>
+</div>
+
+<div class="form-group">
+    <label class="col-sm-3 control-label">{tmpl_var name='domain_admins_txt'}</label>
+    <div class="col-sm-9"><textarea class="form-control" name="domain_admins" id="domain_admins" rows='3' cols='30' placeholder="admin@service.com, superuser@service.com">{tmpl_var name='domain_admins'}</textarea></div>
+</div>
+
+
+<div class="form-group">
+    <label class="col-sm-3 control-label">{tmpl_var name='active_txt'}</label>
+    <div class="col-sm-9">
+        {tmpl_var name='active'}
+    </div>
+</div>
+
+        <input type="hidden" name="id" value="{tmpl_var name='id'}">
+        <input type="hidden" name="type" value="domain">
+        <div class="clear"><div class="right">
+            <button class="btn btn-default formbutton-success" type="button" value="{tmpl_var name='btn_save_txt'}" data-submit-form="pageForm" data-form-action="mail/xmpp_domain_edit.php">{tmpl_var name='btn_save_txt'}</button>
+            <button class="btn btn-default formbutton-default" type="button" value="{tmpl_var name='btn_cancel_txt'}" data-load-content="mail/xmpp_domain_list.php">{tmpl_var name='btn_cancel_txt'}</button>
+        </div></div>
+<script language="JavaScript" type="text/javascript" src="js/xmpp_domain_registration.js"></script>
diff --git a/interface/web/mail/templates/xmpp_domain_edit_modules.htm b/interface/web/mail/templates/xmpp_domain_edit_modules.htm
new file mode 100644
index 0000000000000000000000000000000000000000..8efcf509760b533849287d79e2894d4ce0d57c49
--- /dev/null
+++ b/interface/web/mail/templates/xmpp_domain_edit_modules.htm
@@ -0,0 +1,59 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+<p><tmpl_var name="list_desc_txt"></p>
+
+
+<tmpl_if name="limit_xmpp_anon" value="y">
+    <div class="form-group">
+        <label class="col-sm-3 control-label">{tmpl_var name='use_anon_host_txt'}</label>
+        <div class="col-sm-9">
+            {tmpl_var name='use_anon_host'}
+        </div>
+    </div>
+</tmpl_if>
+<div class="form-group">
+    <label class="col-sm-3 control-label">{tmpl_var name='use_pubsub_txt'}</label>
+    <div class="col-sm-9">
+        {tmpl_var name='use_pubsub'}
+    </div>
+</div>
+<tmpl_if name="limit_xmpp_vjud" value="y">
+    <div class="form-group">
+        <label class="col-sm-3 control-label">{tmpl_var name='use_vjud_txt'}</label>
+        <div class="col-sm-9">
+            {tmpl_var name='use_vjud'}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="vjud_opt_mode" class="col-sm-3 control-label">{tmpl_var name='vjud_opt_mode_txt'}</label>
+        <div class="col-sm-3"><select name="vjud_opt_mode" id="vjud_opt_mode" class="form-control">
+            {tmpl_var name='vjud_opt_mode'}
+        </select></div>
+    </div>
+</tmpl_if>
+<tmpl_if name="limit_xmpp_proxy" value="y">
+    <div class="form-group">
+        <label class="col-sm-3 control-label">{tmpl_var name='use_proxy_txt'}</label>
+        <div class="col-sm-9">
+            {tmpl_var name='use_proxy'}
+        </div>
+    </div>
+</tmpl_if>
+<tmpl_if name="limit_xmpp_status" value="y">
+    <div class="form-group">
+        <label class="col-sm-3 control-label">{tmpl_var name='use_status_host_txt'}</label>
+        <div class="col-sm-9">
+            {tmpl_var name='use_status_host'}
+        </div>
+    </div>
+</tmpl_if>
+
+
+
+        <input type="hidden" name="id" value="{tmpl_var name='id'}">
+        <input type="hidden" name="type" value="modules" />
+        <div class="clear"><div class="right">
+            <button class="btn btn-default formbutton-success" type="button" value="{tmpl_var name='btn_save_txt'}" data-submit-form="pageForm" data-form-action="mail/xmpp_domain_edit.php">{tmpl_var name='btn_save_txt'}</button>
+            <button class="btn btn-default formbutton-default" type="button" value="{tmpl_var name='btn_cancel_txt'}" data-load-content="mail/xmpp_domain_list.php">{tmpl_var name='btn_cancel_txt'}</button>
+        </div></div>
diff --git a/interface/web/mail/templates/xmpp_domain_edit_muc.htm b/interface/web/mail/templates/xmpp_domain_edit_muc.htm
new file mode 100644
index 0000000000000000000000000000000000000000..dd46514cae130308cc87bcf26c1df50c879d0d90
--- /dev/null
+++ b/interface/web/mail/templates/xmpp_domain_edit_muc.htm
@@ -0,0 +1,91 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+<p><tmpl_var name="list_desc_txt"></p>
+
+
+
+<div class="form-group">
+    <label class="col-sm-3 control-label">{tmpl_var name='use_muc_host_txt'}</label>
+    <div class="col-sm-9">
+        {tmpl_var name='use_muc_host'}
+    </div>
+</div>
+
+<div id="toggle-use-muc" class="collapse">
+    <div class="form-group">
+        <label for="muc_name" class="col-sm-3 control-label">{tmpl_var name='muc_name_txt'}</label>
+        <div class="col-sm-9">
+            <input type="text" name="muc_name" id="muc_name" value="{tmpl_var name='muc_name'}" class="form-control" maxlength="30" />
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label for="muc_restrict_room_creation" class="col-sm-3 control-label">{tmpl_var name='muc_restrict_room_creation_txt'}</label>
+        <div class="col-sm-3"><select name="muc_restrict_room_creation" id="muc_restrict_room_creation" class="form-control">
+            {tmpl_var name='muc_restrict_room_creation'}
+        </select></div>
+    </div>
+    <div class="form-group">
+        <div class="form-group">
+            <label class="col-sm-3 control-label">{tmpl_var name='muc_admins_txt'}</label>
+            <div class="col-sm-9"><textarea class="form-control" name="muc_admins" id="muc_admins" rows='3' cols='30'>{tmpl_var name='muc_admins'}</textarea></div>
+        </div>
+    </div>
+
+    <tmpl_if name='limit_xmpp_pastebin' value="y">
+        <div class="form-group">
+            <label class="col-sm-3 control-label">{tmpl_var name='use_pastebin_txt'}</label>
+            <div class="col-sm-9">
+                {tmpl_var name='use_pastebin'}
+            </div>
+        </div>
+        <div id="toggle-use-pastebin" class="collapse">
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='pastebin_expire_after_txt'}</label>
+                <div class="col-sm-3">
+                    <input type="number" name="pastebin_expire_after" id="pastebin_expire_after" value="{tmpl_var name='pastebin_expire_after'}" class="form-control" />
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='pastebin_trigger_txt'}</label>
+                <div class="col-sm-3">
+                    <input type="text" name="pastebin_trigger" id="pastebin_trigger" value="{tmpl_var name='pastebin_trigger'}" class="form-control" />
+                </div>
+            </div>
+        </div>
+    </tmpl_if>
+
+    <tmpl_if name='limit_xmpp_httparchive' value="y">
+        <div class="form-group">
+            <label class="col-sm-3 control-label">{tmpl_var name='use_http_archive_txt'}</label>
+            <div class="col-sm-9">
+                {tmpl_var name='use_http_archive'}
+            </div>
+        </div>
+        <div id="toggle-use-archive" class="collapse">
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='http_archive_show_join_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='http_archive_show_join'}
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='http_archive_show_status_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='http_archive_show_status'}
+                </div>
+            </div>
+        </div>
+    </tmpl_if>
+
+</div>
+
+
+        <input type="hidden" name="id" value="{tmpl_var name='id'}">
+        <input type="hidden" name="type" value="muc" />
+        <div class="clear"><div class="right">
+            <button class="btn btn-default formbutton-success" type="button" value="{tmpl_var name='btn_save_txt'}" data-submit-form="pageForm" data-form-action="mail/xmpp_domain_edit.php">{tmpl_var name='btn_save_txt'}</button>
+            <button class="btn btn-default formbutton-default" type="button" value="{tmpl_var name='btn_cancel_txt'}" data-load-content="mail/xmpp_domain_list.php">{tmpl_var name='btn_cancel_txt'}</button>
+        </div></div>
+<script language="JavaScript" type="text/javascript" src="js/xmpp_domain_muc.js"></script>
diff --git a/interface/web/mail/templates/xmpp_domain_edit_ssl.htm b/interface/web/mail/templates/xmpp_domain_edit_ssl.htm
new file mode 100644
index 0000000000000000000000000000000000000000..2bb7d059aade1ee4015a8041c0df6f45f38cacf5
--- /dev/null
+++ b/interface/web/mail/templates/xmpp_domain_edit_ssl.htm
@@ -0,0 +1,100 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+<p><tmpl_var name="list_desc_txt"></p>
+
+<tmpl_if name="config_error_msg">
+<div style="background: #ffdfdf; border: 1px solid #df7d7d; border-width: 1px 0; margin: 1.5em 0 1.5em 0; padding: 7px;">
+                <p style="font-face:bold">{tmpl_var name='configuration_error_txt'}</p>
+				<div>
+				<div style="float:left;width:150px;">{tmpl_var name='config_error_tstamp'} :&nbsp;</div><div style="padding-left:150px;">{tmpl_var name='config_error_msg'}</div>
+				</div>
+</div>
+</tmpl_if>
+
+
+			<tmpl_if name='show_helper_links'>
+				<div id="show_helper_links" style="display:none;">
+					<label></label>
+					<div class="col-sm-9">
+					<a href="javascript:void(0);" id="load_data"><tmpl_if name='is_admin'>{tmpl_var name='load_client_data_txt'}</tmpl_else>{tmpl_var name='load_my_data_txt'}</tmpl_if></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="javascript:void(0);" id="reset_data">{tmpl_var name='reset_client_data_txt'}</a>
+					</div>
+				</div>
+			</tmpl_if>
+            <div class="form-group">
+                <label for="ssl_state" class="col-sm-3 control-label">{tmpl_var name='ssl_state_txt'}</label>
+                <div class="col-sm-9"><input type="text" name="ssl_state" id="ssl_state" value="{tmpl_var name='ssl_state'}" class="form-control" /></div></div>
+            <div class="form-group">
+                <label for="ssl_locality" class="col-sm-3 control-label">{tmpl_var name='ssl_locality_txt'}</label>
+                <div class="col-sm-9"><input type="text" name="ssl_locality" id="ssl_locality" value="{tmpl_var name='ssl_locality'}" class="form-control" /></div></div>
+            <div class="form-group">
+                <label for="ssl_organisation" class="col-sm-3 control-label">{tmpl_var name='ssl_organisation_txt'}</label>
+                <div class="col-sm-9"><input type="text" name="ssl_organisation" id="ssl_organisation" value="{tmpl_var name='ssl_organisation'}" class="form-control" /></div></div>
+            <div class="form-group">
+                <label for="ssl_organisation_unit" class="col-sm-3 control-label">{tmpl_var name='ssl_organisation_unit_txt'}</label>
+                <div class="col-sm-9"><input type="text" name="ssl_organisation_unit" id="ssl_organisation_unit" value="{tmpl_var name='ssl_organisation_unit'}" class="form-control" /></div></div>
+            <div class="form-group">
+                <label for="ssl_country" class="col-sm-3 control-label">{tmpl_var name='ssl_country_txt'}</label>
+                <div class="col-sm-9"><select name="ssl_country" id="ssl_country" class="form-control flags">
+                    {tmpl_var name='ssl_country'}
+                </select></div>
+            </div>
+            <div class="form-group">
+                <label for="ssl_email" class="col-sm-3 control-label">{tmpl_var name='ssl_email_txt'}</label>
+                <div class="col-sm-9"><input type="email" name="ssl_email" id="ssl_email" value="{tmpl_var name='ssl_email'}" class="form-control" /></div></div>
+			<div class="form-group">
+                <label for="ssl_request" class="col-sm-3 control-label">{tmpl_var name='ssl_key_txt'}</label>
+                <div class="col-sm-9"><textarea class="form-control" name="ssl_key" id="ssl_key" rows='10' cols='30'>{tmpl_var name='ssl_key'}</textarea></div>
+            </div>
+            <div class="form-group">
+                <label for="ssl_request" class="col-sm-3 control-label">{tmpl_var name='ssl_request_txt'}</label>
+                <div class="col-sm-9"><textarea class="form-control" name="ssl_request" id="ssl_request" rows='10' cols='30'>{tmpl_var name='ssl_request'}</textarea></div>
+            </div>
+            <div class="form-group">
+                <label for="ssl_cert" class="col-sm-3 control-label">{tmpl_var name='ssl_cert_txt'}</label>
+                <div class="col-sm-9"><textarea class="form-control" name="ssl_cert" id="ssl_cert" rows='10' cols='30'>{tmpl_var name='ssl_cert'}</textarea></div>
+            </div>
+            <div class="form-group">
+                <label for="ssl_action" class="col-sm-3 control-label">{tmpl_var name='ssl_action_txt'}</label>
+                <div class="col-sm-9"><select name="ssl_action" id="ssl_action" class="form-control">
+                    {tmpl_var name='ssl_action'}
+                </select></div>
+            </div>
+        
+
+        <input type="hidden" name="id" value="{tmpl_var name='id'}">
+        <input type="hidden" name="type" value="ssl">
+
+        <div class="clear"><div class="right">
+            <button class="btn btn-default formbutton-success" type="button" value="{tmpl_var name='btn_save_txt'}" data-submit-form="pageForm" data-form-action="mail/xmpp_domain_edit.php">{tmpl_var name='btn_save_txt'}</button>
+            <button class="btn btn-default formbutton-default" type="button" value="{tmpl_var name='btn_cancel_txt'}" data-load-content="mail/xmpp_domain_list.php">{tmpl_var name='btn_cancel_txt'}</button>
+        </div></div>
+
+<script>
+<!--
+	<tmpl_if name='show_helper_links'>
+	if($("input[name=id]").val() > 0) $('#show_helper_links:hidden').show();
+
+	$('#reset_data').click(function(){
+		$('#ssl_organisation').add('#ssl_locality').add('#ssl_state').add('#ssl_organisation_unit').val('');
+		$('#ssl_country').val($("#ssl_country option:first").val());
+	});
+	$('#load_data').click(function(){
+		loadClientData();
+	});
+	
+	
+	function loadClientData() {
+        var web_id = $("input[name=id]").val();
+        
+        jQuery.getJSON('sites/ajax_get_json.php'+ '?' + Math.round(new Date().getTime()), {'web_id': web_id, 'type': "getclientssldata"}, function(data) {
+			$('#ssl_organisation').val(data['company_name']);
+			$('#ssl_locality').val(data['city']);
+			$('#ssl_country').val(data['country']);
+			$('#ssl_state').val(data['state']);
+			$('#ssl_organisation_unit').val('IT');
+        });
+    }
+	</tmpl_if>
+//-->
+</script>
\ No newline at end of file
diff --git a/interface/web/mail/templates/xmpp_domain_list.htm b/interface/web/mail/templates/xmpp_domain_list.htm
new file mode 100644
index 0000000000000000000000000000000000000000..79579142d7e874d8a71524c4774ed163925892e3
--- /dev/null
+++ b/interface/web/mail/templates/xmpp_domain_list.htm
@@ -0,0 +1,74 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+<p><tmpl_var name="list_desc_txt"></p>
+
+
+        <tmpl_if name='datalog_changes_count' op='>' value='0'>
+        <div>
+            <div class="systemmonitor-state state-info">
+                <div class="status"></div>
+                <div class="statusMsg">
+                    {tmpl_var name="datalog_changes_txt"}
+                    <ul>
+                    <tmpl_loop name="datalog_changes">
+                        <li><strong>{tmpl_var name="text"}:</strong> {tmpl_var name="count"}</li>
+                    </tmpl_loop>
+                    </ul>
+                    {tmpl_var name="datalog_changes_end_txt"}
+                </div>
+            </div><br />
+        </div>
+        </tmpl_if>
+        <p class="fieldset-legend">{tmpl_var name="toolsarea_head_txt"}</p>
+            
+                <button class="btn btn-default formbutton-success" type="button" data-load-content="mail/xmpp_domain_edit.php">{tmpl_var name="add_new_record_txt"}</button>
+            
+        
+
+    
+        <p class="fieldset-legend"><tmpl_var name="list_head_txt"></p>
+            <div class="table-wrapper marginTop15">
+<table class="table">
+                <thead class="dark form-group-sm">
+                    <tr>
+                        <th class="tiny-col" data-column="active"><tmpl_var name="active_txt"></th>
+                        <th data-column="server_id"><tmpl_var name="server_id_txt"></th>
+                        <th data-column="domain"><tmpl_var name="domain_txt"></th>
+                        <th class="small-col text-right">{tmpl_var name='search_limit'}</th>
+                    </tr>
+                    <tr>
+                        <td><select class="form-control" name="search_active">{tmpl_var name='search_active'}</select></td>
+                        <td><select class="form-control" name="search_server_id">{tmpl_var name='search_server_id'}</select></td>
+                        <td><input class="form-control" type="text" name="search_domain" value="{tmpl_var name='search_domain'}" /></td>
+                        <td class="text-right">
+                            <button type="button" class="btn btn-default formbutton-default formbutton-narrow" name="Filter" id="Filter" value="{tmpl_var name="filter_txt"}" data-submit-form="pageForm" data-form-action="mail/xmpp_domain_list.php"><span class="icon icon-filter"></span></button>
+                        </td>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tmpl_loop name="records">
+                        <tr>
+                            <td><a href="#" data-load-content="mail/xmpp_domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="active"}</a></td>
+                            <td><a href="#" data-load-content="mail/xmpp_domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="server_id"}</a></td>
+                            <td><a href="#" data-load-content="mail/xmpp_domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="domain"}</a></td>
+                            <td class="text-right">
+                                <a class="btn btn-default formbutton-danger formbutton-narrow" href="javascript: ISPConfig.confirm_action('mail/xmpp_domain_del.php?id={tmpl_var name='id'}&phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span class="icon icon-delete"></span></button>
+                            </td>
+                        </tr>
+                    </tmpl_loop>
+                    <tmpl_unless name="records">
+                        <tr class="tbl_row_noresults tbl_row_<tmpl_if name='__EVEN__'}even<tmpl_else>uneven</tmpl_if>">
+                            <td colspan="4">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
+                        </tr>
+                    </tmpl_unless>
+                </tbody>
+                <tfoot>
+                    <tr>
+                        <td colspan="4"><tmpl_var name="paging"></td>
+                    </tr>
+                </tfoot>
+            </table>
+</div>
+        
+    
\ No newline at end of file
diff --git a/interface/web/mail/templates/xmpp_user_edit.htm b/interface/web/mail/templates/xmpp_user_edit.htm
new file mode 100644
index 0000000000000000000000000000000000000000..e155ec023106563eec7de3b896f62eb48f8bcfaf
--- /dev/null
+++ b/interface/web/mail/templates/xmpp_user_edit.htm
@@ -0,0 +1,47 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+<p><tmpl_var name="list_desc_txt"></p>
+
+
+        
+
+            <div class="form-group">
+                <label class="col-sm-3 control-label"><em>*</em> {tmpl_var name='jid_txt'}</label>
+                <div class="col-sm-4">
+                    <input type="text" id="jid_local_part" name="jid_local_part" value="{tmpl_var name='jid_local_part'}" class="form-control" />
+                </div>
+                <div class="col-sm-1 text-center">@</div>
+                <div class="col-sm-4">
+                    <select name="jid_domain" id="jid_domain" class="form-control">{tmpl_var name='jid_domain'}</select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="password" class="col-sm-3 control-label">{tmpl_var name='password_txt'}</label>
+                <div class="col-sm-6"><input type="password" name="password" id="password" value="{tmpl_var name='password'}" class="form-control" autocomplete="off" onkeyup="pass_check(this.value);checkPassMatch('password','repeat_password');" /></div><div class="col-sm-3 input-sm">&nbsp;</div><a href="javascript:void(0);" onclick="generatePassword('password','repeat_password');">{tmpl_var name='generate_password_txt'}</a>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='password_strength_txt'}</label>
+                <div id="passBar"></div>
+                <p class="formHint"><span id="passText">&nbsp;</span></p>
+            </div>
+            <div class="form-group">
+                <label for="repeat_password" class="col-sm-3 control-label">{tmpl_var name='repeat_password_txt'}</label>
+                <div class="col-sm-9"><input type="password" name="repeat_password" id="repeat_password" value="" class="form-control" autocomplete="off" onkeyup="checkPassMatch('password','repeat_password');" /></div></div>
+            <div id="confirmpasswordError" style="display:none;" class="confirmpassworderror">{tmpl_var name='password_mismatch_txt'}</div>
+            <div id="confirmpasswordOK" style="display:none;" class="confirmpasswordok">{tmpl_var name='password_match_txt'}</div>
+             <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='active_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='active'}
+                </div>
+            </div>
+        
+
+        <input type="hidden" name="id" value="{tmpl_var name='id'}">
+
+        <div class="clear"><div class="right">
+            <button class="btn btn-default formbutton-success" type="button" value="{tmpl_var name='btn_save_txt'}" data-submit-form="pageForm" data-form-action="mail/xmpp_user_edit.php">{tmpl_var name='btn_save_txt'}</button>
+            <button class="btn btn-default formbutton-default" type="button" value="{tmpl_var name='btn_cancel_txt'}" data-load-content="mail/xmpp_user_list.php">{tmpl_var name='btn_cancel_txt'}</button>
+        </div></div>
diff --git a/interface/web/mail/templates/xmpp_user_list.htm b/interface/web/mail/templates/xmpp_user_list.htm
new file mode 100644
index 0000000000000000000000000000000000000000..68668b4928975cc2ac21081e8b38de5fe95a6ce1
--- /dev/null
+++ b/interface/web/mail/templates/xmpp_user_list.htm
@@ -0,0 +1,74 @@
+<div class='page-header'>
+	<h1><tmpl_var name="list_head_txt"></h1>
+</div>
+<p><tmpl_var name="list_desc_txt"></p>
+
+
+        <tmpl_if name='datalog_changes_count' op='>' value='0'>
+        <div>
+            <div class="systemmonitor-state state-info">
+                <div class="status"></div>
+                <div class="statusMsg">
+                    {tmpl_var name="datalog_changes_txt"}
+                    <ul>
+                    <tmpl_loop name="datalog_changes">
+                        <li><strong>{tmpl_var name="text"}:</strong> {tmpl_var name="count"}</li>
+                    </tmpl_loop>
+                    </ul>
+                    {tmpl_var name="datalog_changes_end_txt"}
+                </div>
+            </div><br />
+        </div>
+        </tmpl_if>
+        <p class="fieldset-legend">{tmpl_var name="toolsarea_head_txt"}</p>
+            
+                <button class="btn btn-default formbutton-success" type="button" data-load-content="mail/xmpp_user_edit.php">{tmpl_var name="add_new_record_txt"}</button>
+            
+        
+
+    
+        <p class="fieldset-legend"><tmpl_var name="list_head_txt"></p>
+            <div class="table-wrapper marginTop15">
+<table class="table">
+                <thead class="dark form-group-sm">
+                    <tr>
+                        <th data-column="jid"><tmpl_var name="jid_txt"></th>
+                        <th class="small-col" data-column="is_domain_admin"><tmpl_var name="is_domain_admin_txt"></th>
+                        <th class="small-col" data-column="is_muc_admin"><tmpl_var name="is_muc_admin_txt"></th>
+                        <th class="small-col text-right">{tmpl_var name='search_limit'}</th>
+                    </tr>
+                    <tr>
+                        <td><input class="form-control" type="text" name="search_jid" value="{tmpl_var name='search_jid'}" /></td>
+                        <td><select class="form-control" name="search_is_domain_admin">{tmpl_var name='search_is_domain_admin'}</select></td>
+                        <td><select class="form-control" name="search_is_muc_admin">{tmpl_var name='search_is_muc_admin'}</select></td>
+                        <td class="text-right">
+                            <button type="button" class="btn btn-default formbutton-default formbutton-narrow" name="Filter" id="Filter" value="{tmpl_var name="filter_txt"}" data-submit-form="pageForm" data-form-action="mail/xmpp_user_list.php"><span class="icon icon-filter"></span></button>
+                        </td>
+                    </tr>
+                </thead>
+                <tbody>
+                <tmpl_loop name="records">
+                    <tr>
+                        <td><a href="#" data-load-content="mail/xmpp_user_edit.php?id={tmpl_var name='id'}">{tmpl_var name="jid"}</a></td>
+                        <td><a href="#" data-load-content="mail/xmpp_user_edit.php?id={tmpl_var name='id'}">{tmpl_var name="is_domain_admin"}</a></td>
+                        <td><a href="#" data-load-content="mail/xmpp_user_edit.php?id={tmpl_var name='id'}">{tmpl_var name="is_muc_admin"}</a></td>
+                        <td class="text-right">
+                            <a class="btn btn-default formbutton-danger formbutton-narrow" href="javascript: ISPConfig.confirm_action('mail/xmpp_user_del.php?id={tmpl_var name='id'}&phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span class="icon icon-delete"></span></button>
+                        </td>
+                    </tr>
+                </tmpl_loop>
+                <tmpl_unless name="records">
+                    <tr class="tbl_row_noresults tbl_row_<tmpl_if name='__EVEN__'}even<tmpl_else>uneven</tmpl_if>">
+                        <td colspan="4">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
+                    </tr>
+                </tmpl_unless>
+                </tbody>
+                <tfoot>
+                    <tr>
+                        <td colspan="4"><tmpl_var name="paging"></td>
+                    </tr>
+                </tfoot>
+            </table>
+</div>
+        
+    
\ No newline at end of file
diff --git a/interface/web/mail/xmpp_domain_del.php b/interface/web/mail/xmpp_domain_del.php
new file mode 100644
index 0000000000000000000000000000000000000000..da481c8f2b9d001e4b870d0bb6a65ee565c690b8
--- /dev/null
+++ b/interface/web/mail/xmpp_domain_del.php
@@ -0,0 +1,93 @@
+<?php
+
+/*
+Copyright (c) 2005, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/******************************************
+* Begin Form configuration
+******************************************/
+
+$list_def_file = "list/xmpp_domain.list.php";
+$tform_def_file = "form/xmpp_domain.tform.php";
+
+/******************************************
+* End Form configuration
+******************************************/
+
+require_once '../../lib/config.inc.php';
+require_once '../../lib/app.inc.php';
+
+//* Check permissions for module
+$app->auth->check_module_permissions('mail');
+
+// Loading classes
+$app->uses('tpl,tform,tform_actions');
+$app->load('tform_actions');
+
+class page_action extends tform_actions {
+
+	function onBeforeDelete() {
+		global $app, $conf;
+
+		$domain = $this->dataRecord['domain'];
+
+		// Before we delete the email domain,
+		// we will delete all depending records.
+        $this->delete_accounts($domain);
+        // and DNS entries
+        $soa = $app->db->queryOneRecord("SELECT id AS zone, sys_userid, sys_groupid, sys_perm_user, sys_perm_group, sys_perm_other, server_id, ttl, serial FROM dns_soa WHERE active = 'Y' AND origin = ?", $domain.'.');
+        if ( isset($soa) && !empty($soa) ) $this->remove_dns($soa);
+	}
+
+    private function delete_accounts($domain){
+        global $app;
+        // get all accounts
+        $sql = "SELECT * FROM xmpp_user WHERE jid LIKE ? AND ?";
+        $users = $app->db->queryAllRecords($sql, '%@'.$domain, $app->tform->getAuthSQL('d'));
+        foreach($users AS $u)
+            $app->db->datalogDelete('xmpp_user', 'xmppuser_id', $u['xmppuser_id']);
+    }
+
+    private function remove_dns($new_rr) {
+        global $app;
+
+        // purge all xmpp related rr-record
+        $sql = "SELECT * FROM dns_rr WHERE zone = ? AND (name IN ? AND type = 'CNAME' OR name LIKE ? AND type = 'SRV')  AND ? ORDER BY serial DESC";
+        $rec = $app->db->queryAllRecords($sql, $new_rr['zone'], array('xmpp', 'pubsub', 'proxy', 'anon', 'vjud', 'muc'), '_xmpp-%', $app->tform->getAuthSQL('r'));
+        if (is_array($rec[1])) {
+            for ($i=0; $i < count($rec); ++$i)
+                $app->db->datalogDelete('dns_rr', 'id', $rec[$i]['id']);
+        }
+    }
+
+}
+
+$page = new page_action;
+$page->onDelete();
+
+?>
diff --git a/interface/web/mail/xmpp_domain_edit.php b/interface/web/mail/xmpp_domain_edit.php
new file mode 100644
index 0000000000000000000000000000000000000000..1213a91e6ad3d6649fd5ce4255eca5f91d6f4cf8
--- /dev/null
+++ b/interface/web/mail/xmpp_domain_edit.php
@@ -0,0 +1,543 @@
+<?php
+/*
+Copyright (c) 2007, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/******************************************
+* Begin Form configuration
+******************************************/
+
+$tform_def_file = "form/xmpp_domain.tform.php";
+
+/******************************************
+* End Form configuration
+******************************************/
+
+require_once '../../lib/config.inc.php';
+require_once '../../lib/app.inc.php';
+
+//* Check permissions for module
+$app->auth->check_module_permissions('mail');
+
+// Loading classes
+$app->uses('tpl,tform,tform_actions,tools_sites');
+$app->load('tform_actions');
+
+class page_action extends tform_actions {
+    var $_xmpp_type = 'server';
+
+    function onLoad() {
+        $show_type = 'server';
+        if(isset($_REQUEST['type']) && $_REQUEST['type'] == 'modules') {
+            $show_type = 'modules';
+        } elseif(isset($_REQUEST['type']) && $_REQUEST['type'] == 'muc') {
+            $show_type = 'muc';
+        }elseif(isset($_REQUEST['type']) && $_REQUEST['type'] == 'ssl') {
+            $show_type = 'ssl';
+        }
+
+        $_SESSION['s']['var']['xmpp_type'] = $show_type;
+        $this->_xmpp_type = $show_type;
+
+        parent::onLoad();
+    }
+
+	function onShowNew() {
+		global $app, $conf;
+
+		// we will check only users, not admins
+		if($_SESSION["s"]["user"]["typ"] == 'user') {
+			if(!$app->tform->checkClientLimit('limit_xmpp_domain')) {
+				$app->error($app->tform->wordbook["limit_xmppdomain_txt"]);
+			}
+			if(!$app->tform->checkResellerLimit('limit_xmpp_domain')) {
+				$app->error('Reseller: '.$app->tform->wordbook["limit_xmppdomain_txt"]);
+			}
+		} else {
+			$settings = $app->getconf->get_global_config('xmpp');
+        }
+        $app->tform->formDef['tabs']['domain']['fields']['server_id']['default'] = intval($settings['default_xmppserver']);
+
+        parent::onShowNew();
+	}
+
+	function onShowEnd() {
+		global $app, $conf;
+
+		$app->uses('ini_parser,getconf');
+		$settings = $app->getconf->get_global_config('domains');
+
+        $read_limits = array('limit_xmpp_pastebin', 'limit_xmpp_httparchive', 'limit_xmpp_anon', 'limit_xmpp_vjud', 'limit_xmpp_proxy', 'limit_xmpp_status');
+        if($_SESSION["s"]["user"]["typ"] != 'admin') {
+            $client_group_id = $app->functions->intval($_SESSION["s"]["user"]["default_group"]);
+            $client = $app->db->queryOneRecord("SELECT client." . implode(", client.", $read_limits) . " FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+            // add limits to template to be able to hide settings
+            foreach($read_limits as $limit) $app->tpl->setVar($limit, $client[$limit]);
+        }else{
+            foreach($read_limits as $limit) $app->tpl->setVar($limit, 'y');
+        }
+
+
+		if($_SESSION["s"]["user"]["typ"] == 'admin' && $settings['use_domain_module'] != 'y') {
+			// Getting Clients of the user
+			$sql = "SELECT sys_group.groupid, sys_group.name, CONCAT(IF(client.company_name != '', CONCAT(client.company_name, ' :: '), ''), client.contact_name, ' (', client.username, IF(client.customer_no != '', CONCAT(', ', client.customer_no), ''), ')') as contactname FROM sys_group, client WHERE sys_group.client_id = client.client_id AND sys_group.client_id > 0 ORDER BY client.company_name, client.contact_name, sys_group.name";
+
+			$clients = $app->db->queryAllRecords($sql);
+			$client_select = '';
+			if($_SESSION["s"]["user"]["typ"] == 'admin') $client_select .= "<option value='0'></option>";
+			//$tmp_data_record = $app->tform->getDataRecord($this->id);
+			if(is_array($clients)) {
+				foreach( $clients as $client) {
+					$selected = @(is_array($this->dataRecord) && ($client["groupid"] == $this->dataRecord['client_group_id'] || $client["groupid"] == $this->dataRecord['sys_groupid']))?'SELECTED':'';
+					$client_select .= "<option value='$client[groupid]' $selected>$client[contactname]</option>\r\n";
+				}
+			}
+			$app->tpl->setVar("client_group_id", $client_select);
+
+		} elseif ($_SESSION["s"]["user"]["typ"] != 'admin' && $app->auth->has_clients($_SESSION['s']['user']['userid'])) {
+
+			// Get the limits of the client
+			$client_group_id = $_SESSION["s"]["user"]["default_group"];
+			$client = $app->db->queryOneRecord("SELECT client.client_id, client.contact_name, CONCAT(IF(client.company_name != '', CONCAT(client.company_name, ' :: '), ''), client.contact_name, ' (', client.username, IF(client.customer_no != '', CONCAT(', ', client.customer_no), ''), ')') as contactname, sys_group.name FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id order by client.contact_name");
+
+			if ($settings['use_domain_module'] != 'y') {
+				// Fill the client select field
+				$sql = "SELECT sys_group.groupid, sys_group.name, CONCAT(IF(client.company_name != '', CONCAT(client.company_name, ' :: '), ''), client.contact_name, ' (', client.username, IF(client.customer_no != '', CONCAT(', ', client.customer_no), ''), ')') as contactname FROM sys_group, client WHERE sys_group.client_id = client.client_id AND client.parent_client_id = ".$app->functions->intval($client['client_id'])." ORDER BY client.company_name, client.contact_name, sys_group.name";
+				$clients = $app->db->queryAllRecords($sql);
+				$tmp = $app->db->queryOneRecord("SELECT groupid FROM sys_group WHERE client_id = ".$app->functions->intval($client['client_id']));
+				$client_select = '<option value="'.$tmp['groupid'].'">'.$client['contactname'].'</option>';
+				//$tmp_data_record = $app->tform->getDataRecord($this->id);
+				if(is_array($clients)) {
+					foreach( $clients as $client) {
+						$selected = @(is_array($this->dataRecord) && ($client["groupid"] == $this->dataRecord['client_group_id'] || $client["groupid"] == $this->dataRecord['sys_groupid']))?'SELECTED':'';
+						$client_select .= "<option value='$client[groupid]' $selected>$client[contactname]</option>\r\n";
+					}
+				}
+				$app->tpl->setVar("client_group_id", $client_select);
+			}
+		}
+
+		if($_SESSION["s"]["user"]["typ"] != 'admin')
+		{
+			$client_group_id = $_SESSION["s"]["user"]["default_group"];
+			$client_xmpp = $app->db->queryOneRecord("SELECT xmpp_servers FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+
+			$client_xmpp['xmpp_servers_ids'] = explode(',', $client_xmpp['xmpp_servers']);
+
+			$only_one_server = count($client_xmpp['xmpp_servers_ids']) === 1;
+			$app->tpl->setVar('only_one_server', $only_one_server);
+
+			if ($only_one_server) {
+				$app->tpl->setVar('server_id_value', $client_xmpp['xmpp_servers_ids'][0]);
+			}
+
+			$sql = "SELECT server_id, server_name FROM server WHERE server_id IN (" . $client_xmpp['xmpp_servers'] . ");";
+			$xmpp_servers = $app->db->queryAllRecords($sql);
+
+			$options_xmpp_servers = "";
+
+			foreach ($xmpp_servers as $xmpp_server) {
+				$options_xmpp_servers .= "<option value='$xmpp_server[server_id]'>$xmpp_server[server_name]</option>";
+			}
+
+			$app->tpl->setVar("client_server_id", $options_xmpp_servers);
+			unset($options_xmpp_servers);
+
+		}
+
+		/*
+		 * Now we have to check, if we should use the domain-module to select the domain
+		 * or not
+		 */
+		if ($settings['use_domain_module'] == 'y') {
+			/*
+			 * The domain-module is in use.
+			*/
+			$domains = $app->tools_sites->getDomainModuleDomains("xmpp_domain", $this->dataRecord["domain"]);
+			$domain_select = '';
+			if(is_array($domains) && sizeof($domains) > 0) {
+				/* We have domains in the list, so create the drop-down-list */
+				foreach( $domains as $domain) {
+					$domain_select .= "<option value=" . $domain['domain_id'] ;
+					if ($domain['domain'] == $this->dataRecord["domain"]) {
+						$domain_select .= " selected";
+					}
+					$domain_select .= ">" . $app->functions->idn_decode($domain['domain']) . "</option>\r\n";
+				}
+			}
+			else {
+				/*
+				 * We have no domains in the domain-list. This means, we can not add ANY new domain.
+				 * To avoid, that the variable "domain_option" is empty and so the user can
+				 * free enter a domain, we have to create a empty option!
+				*/
+				$domain_select .= "<option value=''></option>\r\n";
+			}
+			$app->tpl->setVar("domain_option", $domain_select);
+			$app->tpl->setVar("domain_module", 1);
+		} else {
+			$app->tpl->setVar("domain_module", 0);
+		}
+
+
+		if($this->id > 0) {
+			//* we are editing a existing record
+			$app->tpl->setVar("edit_disabled", 1);
+			$app->tpl->setVar("server_id_value", $this->dataRecord["server_id"]);
+		} else {
+			$app->tpl->setVar("edit_disabled", 0);
+		}
+
+
+		parent::onShowEnd();
+	}
+
+	function onSubmit() {
+		global $app, $conf;
+
+		/* check if the domain module is used - and check if the selected domain can be used! */
+		$app->uses('ini_parser,getconf');
+		$settings = $app->getconf->get_global_config('domains');
+		if ($settings['use_domain_module'] == 'y') {
+			if ($_SESSION["s"]["user"]["typ"] == 'admin' || $app->auth->has_clients($_SESSION['s']['user']['userid'])) {
+				$this->dataRecord['client_group_id'] = $app->tools_sites->getClientIdForDomain($this->dataRecord['domain']);
+			}
+			$domain_check = $app->tools_sites->checkDomainModuleDomain($this->dataRecord['domain']);
+			if(!$domain_check) {
+				// invalid domain selected
+				$app->tform->errorMessage .= $app->tform->lng("domain_error_empty")."<br />";
+			} else {
+				$this->dataRecord['domain'] = $domain_check;
+			}
+		}
+
+		if($_SESSION["s"]["user"]["typ"] != 'admin') {
+			// Get the limits of the client
+			$client_group_id = $app->functions->intval($_SESSION["s"]["user"]["default_group"]);
+			$client = $app->db->queryOneRecord("SELECT limit_xmpp_domain FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+			// When the record is updated
+			if($this->id > 0) {
+				// restore the server ID if the user is not admin and record is edited
+				$tmp = $app->db->queryOneRecord("SELECT server_id FROM xmpp_domain WHERE domain_id = ".$app->functions->intval($this->id));
+				$this->dataRecord["server_id"] = $tmp["server_id"];
+				unset($tmp);
+				// When the record is inserted
+			} else {
+				$client['xmpp_servers_ids'] = explode(',', $client['xmpp_servers']);
+
+				// Check if chosen server is in authorized servers for this client
+				if (!(is_array($client['xmpp_servers_ids']) && in_array($this->dataRecord["server_id"], $client['xmpp_servers_ids']))) {
+					$app->error($app->tform->wordbook['error_not_allowed_server_id']);
+				}
+
+				if($client["limit_xmpp_domain"] >= 0) {
+					$tmp = $app->db->queryOneRecord("SELECT count(domain_id) as number FROM xmpp_domain WHERE sys_groupid = $client_group_id");
+					if($tmp["number"] >= $client["limit_xmpp_domain"]) {
+						$app->error($app->tform->wordbook["limit_xmppdomain_txt"]);
+					}
+				}
+			}
+
+			// Clients may not set the client_group_id, so we unset them if user is not a admin
+			if(!$app->auth->has_clients($_SESSION['s']['user']['userid'])) unset($this->dataRecord["client_group_id"]);
+		}
+
+		//* make sure that the xmpp domain is lowercase
+		if(isset($this->dataRecord["domain"])) $this->dataRecord["domain"] = strtolower($this->dataRecord["domain"]);
+
+        // Read management method
+        if(isset($this->dataRecord["management_method"]))
+            // Set management method to 0 as long as the mailaccount hook is not implemented
+            $this->dataRecord["management_method"] = 0;
+            switch($this->dataRecord["management_method"]){
+                case 0:
+                    $this->dataRecord["management_method"] = 'normal';
+                    break;
+                case 1:
+                    $this->dataRecord["management_method"] = 'maildomain';
+                    // Check for corresponding mail domain
+                    $tmp = $app->db->queryOneRecord("SELECT count(domain_id) AS number FROM mail_domain WHERE domain = '".$this->dataRecord["domain"]."' AND ".$app->tform->getAuthSQL('r')." ORDER BY domain");
+                    if($tmp['number']==0){
+                        $app->error($app->tform->wordbook["no_corresponding_maildomain_txt"]);
+                        break;
+                    }
+                    break;
+            }
+        // vjud opt mode
+        if(isset($this->dataRecord["vjud_opt_mode"]))
+            $this->dataRecord["vjud_opt_mode"] = $this->dataRecord["vjud_opt_mode"] == 0 ? 'in' : 'out';
+        if(isset($this->dataRecord["muc_restrict_room_creation"])){
+            switch($this->dataRecord["muc_restrict_room_creation"]){
+                case 0:
+                    $this->dataRecord["muc_restrict_room_creation"] = 'false';
+                    break;
+                case 1:
+                    $this->dataRecord["muc_restrict_room_creation"] = 'member';
+                    break;
+                case 2:
+                    $this->dataRecord["muc_restrict_room_creation"] = 'true';
+                    break;
+            }
+        }
+
+        // Reset public registration to 'n', is not yet supported
+        $this->dataRecord["public_registration"] = 'n';
+
+		parent::onSubmit();
+	}
+
+	function onAfterInsert() {
+        global $app, $conf;
+
+        // make sure that the record belongs to the client group and not the admin group when admin inserts it
+        // also make sure that the user can not delete domain created by a admin
+        if($_SESSION["s"]["user"]["typ"] == 'admin' && isset($this->dataRecord["client_group_id"])) {
+            $client_group_id = $app->functions->intval($this->dataRecord["client_group_id"]);
+            $app->db->query("UPDATE xmpp_domain SET sys_groupid = $client_group_id, sys_perm_group = 'ru' WHERE domain_id = ".$this->id);
+        }
+        if($app->auth->has_clients($_SESSION['s']['user']['userid']) && isset($this->dataRecord["client_group_id"])) {
+            $client_group_id = $app->functions->intval($this->dataRecord["client_group_id"]);
+            $app->db->query("UPDATE xmpp_domain SET sys_groupid = $client_group_id, sys_perm_group = 'riud' WHERE domain_id = ".$this->id);
+        }
+
+        //* make sure that the xmpp domain is lowercase
+        if(isset($this->dataRecord["domain"])) $this->dataRecord["domain"] = strtolower($this->dataRecord["domain"]);
+
+        // create new accounts from mail domain
+        //if($this->dataRecord['management_method']=='maildomain')
+        //    $this->syncMailusers($this->dataRecord['domain']);
+
+        // Insert DNS Records
+        $soa = $app->db->queryOneRecord("SELECT id AS zone, sys_userid, sys_groupid, sys_perm_user, sys_perm_group, sys_perm_other, server_id, ttl, serial FROM dns_soa WHERE active = 'Y' AND origin = ?", $this->dataRecord['domain'].'.');
+        if ( isset($soa) && !empty($soa) ) $this->update_dns($this->dataRecord, $soa);
+	}
+
+	function onBeforeUpdate() {
+        global $app, $conf;
+
+        if($this->_xmpp_type == 'server') {
+            // Check if the domain has been changed
+            $rec = $app->db->queryOneRecord("SELECT domain from xmpp_domain WHERE domain_id = ".$this->id);
+            if($this->dataRecord['domain']!=$rec['domain'])
+                $app->error($app->tform->wordbook["cant_change_domainname_txt"]);
+
+            //* Check if the server has been changed
+            // We do this only for the admin or reseller users, as normal clients can not change the server ID anyway
+            if($_SESSION["s"]["user"]["typ"] == 'admin' || $app->auth->has_clients($_SESSION['s']['user']['userid'])) {
+                if (isset($this->dataRecord["server_id"])) {
+                    $rec = $app->db->queryOneRecord("SELECT server_id from xmpp_domain WHERE domain_id = ".$this->id);
+                    if($rec['server_id'] != $this->dataRecord["server_id"]) {
+                        //* Add a error message and switch back to old server
+                        $app->tform->errorMessage .= $app->lng('The Server can not be changed.');
+                        $this->dataRecord["server_id"] = $rec['server_id'];
+                    }
+                    unset($rec);
+                }
+                //* If the user is neither admin nor reseller
+            } else {
+                //* We do not allow users to change a domain which has been created by the admin
+                $rec = $app->db->queryOneRecord("SELECT sys_perm_group, domain from xmpp_domain WHERE domain_id = ".$this->id);
+                if(isset($this->dataRecord["domain"]) && $rec['domain'] != $this->dataRecord["domain"] && $app->tform->checkPerm($this->id, 'u')) {
+                    //* Add a error message and switch back to old server
+                    $app->tform->errorMessage .= $app->lng('The Domain can not be changed. Please ask your Administrator if you want to change the domain name.');
+                    $this->dataRecord["domain"] = $rec['domain'];
+                }
+                unset($rec);
+            }
+        }
+
+        if($this->_xmpp_type == 'ssl'){
+            //* Check that all fields for the SSL cert creation are filled
+            if(isset($this->dataRecord['ssl_action']) && $this->dataRecord['ssl_action'] == 'create') {
+                if($this->dataRecord['ssl_state'] == '') $app->tform->errorMessage .= $app->tform->lng('error_ssl_state_empty').'<br />';
+                if($this->dataRecord['ssl_locality'] == '') $app->tform->errorMessage .= $app->tform->lng('error_ssl_locality_empty').'<br />';
+                if($this->dataRecord['ssl_organisation'] == '') $app->tform->errorMessage .= $app->tform->lng('error_ssl_organisation_empty').'<br />';
+                if($this->dataRecord['ssl_organisation_unit'] == '') $app->tform->errorMessage .= $app->tform->lng('error_ssl_organisation_unit_empty').'<br />';
+                if($this->dataRecord['ssl_country'] == '') $app->tform->errorMessage .= $app->tform->lng('error_ssl_country_empty').'<br />';
+            }
+
+            if(isset($this->dataRecord['ssl_action']) && $this->dataRecord['ssl_action'] == 'save') {
+                if(trim($this->dataRecord['ssl_cert']) == '') $app->tform->errorMessage .= $app->tform->lng('error_ssl_cert_empty').'<br />';
+            }
+        }
+
+        //* make sure that the xmpp domain is lowercase
+        if(isset($this->dataRecord["domain"])) $this->dataRecord["domain"] = strtolower($this->dataRecord["domain"]);
+
+	}
+
+	function onAfterUpdate() {
+		global $app, $conf;
+
+        // create new accounts from mail domain
+        //if($this->oldDataRecord['management_method'] != 'maildomain' && $this->dataRecord['management_method']=='maildomain')
+        //    $this->syncMailusers($this->dataRecord['domain']);
+        // or reset to normal permissions
+        //elseif($this->oldDataRecord['management_method'] == 'maildomain' && $this->dataRecord['management_method']!='maildomain')
+        //    $this->desyncMailusers($this->dataRecord['domain']);
+        // Update DNS Records
+        // TODO: Update gets only triggered from main form. WHY?
+        $soa = $app->db->queryOneRecord("SELECT id AS zone, sys_userid, sys_groupid, sys_perm_user, sys_perm_group, sys_perm_other FROM dns_soa WHERE active = 'Y' AND  = ?", $this->dataRecord['domain'].'.');
+        if ( isset($soa) && !empty($soa) ) $this->update_dns($this->dataRecord, $soa);
+	}
+
+
+
+    private function update_dns($dataRecord, $new_rr) {
+        global $app, $conf;
+
+        $rec = $app->db->queryOneRecord("SELECT use_pubsub, use_proxy, use_anon_host, use_vjud, use_muc_host from xmpp_domain WHERE domain_id = ".$this->id);
+        $required_hosts = array('xmpp');
+        if($rec['use_pubsub']=='y')
+            $required_hosts[] = 'pubsub';
+        if($rec['use_proxy']=='y')
+            $required_hosts[] = 'proxy';
+        if($rec['use_anon_host']=='y')
+            $required_hosts[] = 'anon';
+        if($rec['use_vjud']=='y')
+            $required_hosts[] = 'vjud';
+        if($rec['use_muc_host']=='y')
+            $required_hosts[] = 'muc';
+
+        // purge old rr-record
+        $sql = "SELECT * FROM dns_rr WHERE zone = ? AND (name IN ? AND type = 'CNAME' OR name LIKE ? AND type = 'SRV')  AND ? ORDER BY serial DESC";
+        $rec = $app->db->queryAllRecords($sql, $new_rr['zone'], array('xmpp', 'pubsub', 'proxy', 'anon', 'vjud', 'muc'), '_xmpp-%', $app->tform->getAuthSQL('r'));
+        if (is_array($rec[1])) {
+            for ($i=0; $i < count($rec); ++$i)
+                $app->db->datalogDelete('dns_rr', 'id', $rec[$i]['id']);
+        }
+
+        // create new cname rr-records
+        foreach($required_hosts AS $h){
+            $rr = $new_rr;
+            $rr['name'] = $h;
+            $rr['type'] = 'CNAME';
+            $rr['data'] = 'jalapeno.spicyweb.de.';
+            $rr['aux'] = 0;
+            $rr['active'] = 'Y';
+            $rr['stamp'] = date('Y-m-d H:i:s');
+            $rr['serial'] = $app->validate_dns->increase_serial($new_rr['serial']);
+            $app->db->datalogInsert('dns_rr', $rr, 'id', $rr['zone']);
+        }
+
+        //create new srv rr-records
+        $rr = $new_rr;
+        $rr['name'] = '_xmpp-client._tcp.'.$dataRecord['domain'].'.';
+        $rr['type'] = 'SRV';
+        $rr['data'] = '5 5222 jalapeno.spicyweb.de.';
+        $rr['aux'] = 0;
+        $rr['active'] = 'Y';
+        $rr['stamp'] = date('Y-m-d H:i:s');
+        $rr['serial'] = $app->validate_dns->increase_serial($new_rr['serial']);
+        $app->db->datalogInsert('dns_rr', $rr, 'id', $rr['zone']);
+        $rr = $new_rr;
+        $rr['name'] = '_xmpp-server._tcp.'.$dataRecord['domain'].'.';
+        $rr['type'] = 'SRV';
+        $rr['data'] = '5 5269 jalapeno.spicyweb.de.';
+        $rr['aux'] = 0;
+        $rr['active'] = 'Y';
+        $rr['stamp'] = date('Y-m-d H:i:s');
+        $rr['serial'] = $app->validate_dns->increase_serial($new_rr['serial']);
+        $app->db->datalogInsert('dns_rr', $rr, 'id', $rr['zone']);
+
+        // Refresh zone
+        $zone = $app->db->queryOneRecord("SELECT id, serial FROM dns_soa WHERE active = 'Y' AND id = ?", $new_rr['zone']);
+        $new_serial = $app->validate_dns->increase_serial($zone['serial']);
+        $app->db->datalogUpdate('dns_soa', "serial = '".$new_serial."'", 'id', $zone['id']);
+    }
+
+    /*
+     * NOT YET FINISHED
+
+    private function syncMailusers($domain){
+        global $app, $conf;
+        // get all mailusers
+        $db_mailusers = $app->db->queryAllRecords("SELECT email, password, sys_userid, sys_groupid, sys_perm_user, sys_perm_group, sys_perm_other FROM mail_user WHERE email like ?", '@'.$this->dataRecord['domain'].'.');
+        // get existing xmpp users
+        $db_xmppusers = $app->db->queryAllRecords("SELECT jid, password, sys_userid, sys_groupid, sys_perm_user, sys_perm_group, sys_perm_other FROM xmpp_user WHERE jid like ?", '@'.$this->dataRecord['domain'].'.');
+
+        // Migrate user accounts
+        $users_delete = array();
+        $users_update = array();
+        $users_create = array();
+        foreach($db_xmppusers AS $ix=>$x){
+            $matched = false;
+            foreach($db_mailusers AS $im=>$m){
+                if($x['jid']==$m['email']){
+                    // User matched, mark for update
+                    $x['password'] = $m['password'];
+                    $users_update[] = $x;
+                    unset($db_xmppusers[$ix]);
+                    unset($db_mailusers[$im]);
+                    $matched = true;
+                    break;
+                }
+            }
+            // XMPP user not matched, mark for deletion
+            if(!$matched){
+                $users_delete[] = $x;
+                unset($db_xmppusers[$ix]);
+            }
+        }
+        // Mark remaining mail users for creation
+        $users_create = $db_xmppusers;
+        foreach($users_create AS $u){
+            $u['server_id'] = $this->dataRecord['server_id'];
+            $u['sys_perm_user'] = 'r';
+            $u['sys_perm_group'] = 'r';
+            $app->db->datalogInsert('xmpp_user', $u, 'xmppuser_id');
+        }
+        foreach($users_update AS $u){
+            $u['sys_perm_user'] = 'r';
+            $u['sys_perm_group'] = 'r';
+            $app->db->datalogUpdate('xmpp_user', $u, 'xmppuser_id', $u['xmppuser_id']);
+        }
+        foreach($users_delete AS $u){
+            $app->db->datalogDelete('xmpp_user', 'xmppuser_id', $u['xmppuser_id']);
+        }
+
+    }
+
+    private function desyncMailusers($domain){
+        global $app, $conf;
+        // get existing xmpp users
+        $db_xmppusers = $app->db->queryAllRecords("SELECT jid, password, sys_userid, sys_groupid, sys_perm_user, sys_perm_group, sys_perm_other FROM xmpp_user WHERE jid like ?", '@'.$this->dataRecord['domain'].'.');
+        foreach($db_xmppusers AS $u){
+            $u['sys_perm_user'] = 'riud';
+            $u['sys_perm_group'] = 'riud';
+            $app->db->datalogUpdate('xmpp_user', $u, 'xmppuser_id', $u['xmppuser_id']);
+        }
+    }
+    */
+
+}
+
+$page = new page_action;
+$page->onLoad();
+
+?>
diff --git a/interface/web/mail/xmpp_domain_list.php b/interface/web/mail/xmpp_domain_list.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff632e38ca9422ec76125f128989e211ff8e2ee0
--- /dev/null
+++ b/interface/web/mail/xmpp_domain_list.php
@@ -0,0 +1,28 @@
+<?php
+require_once '../../lib/config.inc.php';
+require_once '../../lib/app.inc.php';
+
+/******************************************
+* Begin Form configuration
+******************************************/
+
+$list_def_file = "list/xmpp_domain.list.php";
+
+/******************************************
+* End Form configuration
+******************************************/
+
+
+//* Check permissions for module
+$app->auth->check_module_permissions('mail');
+
+$app->uses('listform_actions');
+
+// Limit the results to alias domains
+// $app->listform_actions->SQLExtWhere = "type = 'local'";
+
+$app->listform_actions->SQLOrderBy = 'ORDER BY xmpp_domain.domain';
+$app->listform_actions->onLoad();
+
+
+?>
diff --git a/interface/web/mail/xmpp_user_del.php b/interface/web/mail/xmpp_user_del.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf0cc62a104f397d6b0a390f79203e00a0f128f1
--- /dev/null
+++ b/interface/web/mail/xmpp_user_del.php
@@ -0,0 +1,72 @@
+<?php
+
+/*
+Copyright (c) 2005, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/******************************************
+* Begin Form configuration
+******************************************/
+
+$list_def_file = "list/xmpp_user.list.php";
+$tform_def_file = "form/xmpp_user.tform.php";
+
+/******************************************
+* End Form configuration
+******************************************/
+
+require_once '../../lib/config.inc.php';
+require_once '../../lib/app.inc.php';
+
+//* Check permissions for module
+$app->auth->check_module_permissions('mail');
+
+// Loading classes
+$app->uses('tpl,tform,tform_actions');
+$app->load('tform_actions');
+
+class page_action extends tform_actions {
+
+	function onBeforeDelete() {
+		global $app, $conf;
+
+        $jid_parts = explode("@", $this->dataRecord['jid']);
+		$domain = $jid_parts[1];
+
+        // check if domain is managed through mail domain
+        // if yes, manual deletion is not allowed
+        //$app->error('blubb');
+
+
+	}
+
+}
+
+$page = new page_action;
+$page->onDelete();
+
+?>
diff --git a/interface/web/mail/xmpp_user_edit.php b/interface/web/mail/xmpp_user_edit.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ad6161b4aeffa46bce2b4f4177c8dd79617fc12
--- /dev/null
+++ b/interface/web/mail/xmpp_user_edit.php
@@ -0,0 +1,172 @@
+<?php
+/*
+Copyright (c) 2005 - 2009, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/******************************************
+* Begin Form configuration
+******************************************/
+
+$tform_def_file = "form/xmpp_user.tform.php";
+
+/******************************************
+* End Form configuration
+******************************************/
+
+require_once '../../lib/config.inc.php';
+require_once '../../lib/app.inc.php';
+
+//* Check permissions for module
+$app->auth->check_module_permissions('mail');
+
+// Loading classes
+$app->uses('tpl,tform,tform_actions');
+$app->load('tform_actions');
+
+class page_action extends tform_actions {
+
+
+	function onShowNew() {
+		global $app, $conf;
+
+		// we will check only users, not admins
+		if($_SESSION["s"]["user"]["typ"] == 'user') {
+			if(!$app->tform->checkClientLimit('limit_xmpp_user')) {
+				$app->error($app->tform->wordbook["limit_xmpp_user_txt"]);
+			}
+			if(!$app->tform->checkResellerLimit('limit_xmpp_user')) {
+				$app->error('Reseller: '.$app->tform->wordbook["limit_xmpp_user_txt"]);
+			}
+		}
+
+		parent::onShowNew();
+	}
+
+	function onShowEnd() {
+		global $app, $conf;
+
+		$jid = $this->dataRecord["jid"];
+		$jid_parts = explode("@", $jid);
+		$app->tpl->setVar("jid_local_part", $jid_parts[0]);
+		$jid_parts[1] = $app->functions->idn_decode($jid_parts[1]);
+
+		// Getting Domains of the user
+		$sql = "SELECT domain, server_id FROM xmpp_domain WHERE ".$app->tform->getAuthSQL('r')." ORDER BY domain";
+		$domains = $app->db->queryAllRecords($sql);
+		$domain_select = '';
+		if(is_array($domains)) {
+			foreach( $domains as $domain) {
+				$domain['domain'] = $app->functions->idn_decode($domain['domain']);
+				$selected = ($domain["domain"] == @$jid_parts[1])?'SELECTED':'';
+				$domain_select .= "<option value='$domain[domain]' $selected>$domain[domain]</option>\r\n";
+			}
+		}
+		$app->tpl->setVar("jid_domain", $domain_select);
+		unset($domains);
+		unset($domain_select);
+
+
+		parent::onShowEnd();
+	}
+
+	function onSubmit() {
+		global $app, $conf;
+		//* Check if Domain belongs to user
+		if(isset($_POST["jid_domain"])) {
+			$domain = $app->db->queryOneRecord("SELECT server_id, domain FROM xmpp_domain WHERE domain = '".$app->db->quote($app->functions->idn_encode($_POST["jid_domain"]))."' AND ".$app->tform->getAuthSQL('r'));
+			if($domain["domain"] != $app->functions->idn_encode($_POST["jid_domain"])) $app->tform->errorMessage .= $app->tform->lng("no_domain_perm");
+		}
+
+
+		//* if its an insert, check that the password is not empty
+		if($this->id == 0 && $_POST["password"] == '') {
+			$app->tform->errorMessage .= $app->tform->lng("error_no_pwd")."<br>";
+		}
+
+		//* Check the client limits, if user is not the admin
+		if($_SESSION["s"]["user"]["typ"] != 'admin') { // if user is not admin
+			// Get the limits of the client
+			$client_group_id = $app->functions->intval($_SESSION["s"]["user"]["default_group"]);
+			$client = $app->db->queryOneRecord("SELECT limit_xmpp_user, parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+
+
+			// Check if the user may add another xmpp user.
+			if($this->id == 0 && $client["limit_xmpp_user"] >= 0) {
+				$tmp = $app->db->queryOneRecord("SELECT count(xmppuser_id) as number FROM xmpp_user WHERE sys_groupid = $client_group_id");
+				if($tmp["number"] >= $client["limit_xmpp_user"]) {
+					$app->tform->errorMessage .= $app->tform->lng("limit_xmpp_user_txt")."<br>";
+				}
+				unset($tmp);
+			}
+		} // end if user is not admin
+
+
+		$app->uses('getconf');
+		$xmpp_config = $app->getconf->get_server_config(!empty($domain["server_id"]) ? $domain["server_id"] : '', 'xmpp');
+
+		//* compose the xmpp field
+		if(isset($_POST["jid_local_part"]) && isset($_POST["jid_domain"])) {
+			$this->dataRecord["jid"] = strtolower($_POST["jid_local_part"]."@".$app->functions->idn_encode($_POST["jid_domain"]));
+
+			// Set the server id of the xmpp user = server ID of xmpp domain.
+			$this->dataRecord["server_id"] = $domain["server_id"];
+
+			unset($this->dataRecord["jid_local_part"]);
+			unset($this->dataRecord["jid_domain"]);
+
+		}
+
+		parent::onSubmit();
+	}
+
+	function onAfterInsert() {
+		global $app, $conf;
+
+		// Set the domain owner as xmpp user owner
+		$domain = $app->db->queryOneRecord("SELECT sys_groupid, server_id FROM xmpp_domain WHERE domain = '".$app->db->quote($app->functions->idn_encode($_POST["jid_domain"]))."' AND ".$app->tform->getAuthSQL('r'));
+		$app->db->query("UPDATE xmpp_user SET sys_groupid = ".$app->functions->intval($domain["sys_groupid"])." WHERE xmppuser_id = ".$this->id);
+
+	}
+
+	function onAfterUpdate() {
+		global $app, $conf;
+
+		// Set the domain owner as mailbox owner
+		if(isset($_POST["xmpp_domain"])) {
+			$domain = $app->db->queryOneRecord("SELECT sys_groupid, server_id FROM xmpp_domain WHERE domain = '".$app->db->quote($app->functions->idn_encode($_POST["jid_domain"]))."' AND ".$app->tform->getAuthSQL('r'));
+			$app->db->query("UPDATE xmpp_user SET sys_groupid = ".$app->functions->intval($domain["sys_groupid"])." WHERE xmppuser_id = ".$this->id);
+
+		}
+	}
+
+}
+
+$app->tform_actions = new page_action;
+$app->tform_actions->onLoad();
+
+?>
diff --git a/interface/web/mail/xmpp_user_list.php b/interface/web/mail/xmpp_user_list.php
new file mode 100644
index 0000000000000000000000000000000000000000..ea44e4dfc0cea3204b07362a8052253b4ef09cca
--- /dev/null
+++ b/interface/web/mail/xmpp_user_list.php
@@ -0,0 +1,39 @@
+<?php
+require_once '../../lib/config.inc.php';
+require_once '../../lib/app.inc.php';
+
+/******************************************
+* Begin Form configuration
+******************************************/
+
+$list_def_file = "list/xmpp_user.list.php";
+
+/******************************************
+* End Form configuration
+******************************************/
+
+//* Check permissions for module
+$app->auth->check_module_permissions('mail');
+
+$app->load('listform_actions');
+
+
+class list_action extends listform_actions {
+
+	function onShow() {
+		global $app, $conf;
+
+		$app->uses('getconf');
+		$global_config = $app->getconf->get_global_config('xmpp');
+
+		parent::onShow();
+	}
+
+}
+
+$list = new list_action;
+$list->SQLOrderBy = 'ORDER BY xmpp_user.jid';
+$list->onLoad();
+
+
+?>
diff --git a/server/conf/metronome_conf_global.master b/server/conf/metronome_conf_global.master
new file mode 100644
index 0000000000000000000000000000000000000000..71920caea101408f7c1cf8f0e77f2bf5a7c89763
--- /dev/null
+++ b/server/conf/metronome_conf_global.master
@@ -0,0 +1,48 @@
+pidfile = "/var/run/metronome/metronome.pid";
+metronome_max_files_soft = 200000;
+metronome_max_files_hard = 300000;
+plugin_paths = {
+        "/usr/lib/metronome/isp-modules",
+};
+use_libevent = true;
+log = {
+        debug = "/var/log/metronome/metronome.dbg",
+        info = "/var/log/metronome/metronome.log",
+        error = "/var/log/metronome/metronome.err",
+};
+use_ipv6 = {tmpl_var name='ipv6'};
+http_ports = {
+        {tmpl_var name='port_http'},
+};
+https_ports = {
+        {tmpl_var name='port_https'},
+};
+pastebin_ports = {
+        {tmpl_var name='port_pastebin'},
+};
+bosh_ports = {
+        {tmpl_var name='port_bosh'},
+};
+admins = {
+{tmpl_var name='server_admins'}
+};
+modules_enabled = {
+{tmpl_var name='modules_enabled'}
+};
+modules_disabled = {
+};
+bosh_max_inactivity = {tmpl_var name='bosh_timeout'};
+consider_bosh_secure = true;
+cross_domain_bosh = true;
+allow_registration = true;
+-- TODO generate ssl key during setup
+ssl = {
+        key = "/etc/metronome/certs/localhost.key",
+        certificate = "/etc/metronome/certs/localhost.cert",
+};
+c2s_require_encryption = false;
+s2s_secure = true;
+s2s_insecure_domains = {
+        "gmail.com",
+};
+authentication = "internal_plain";
\ No newline at end of file
diff --git a/server/conf/metronome_conf_host.master b/server/conf/metronome_conf_host.master
new file mode 100644
index 0000000000000000000000000000000000000000..179d533e19c532bdc498d938406a962cf877c437
--- /dev/null
+++ b/server/conf/metronome_conf_host.master
@@ -0,0 +1,135 @@
+VirtualHost "{tmpl_var name='domain'}"
+    enabled = {tmpl_var name='active'};
+    authentication = "external";
+    external_auth_command = "/usr/lib/metronome/isp-modules/mod_auth_external/authenticate_isp.sh";
+    allow_registration = {tmpl_var name='public_registration'};
+    <tmpl_if name='registration_url' op='!=' value=''>
+        registration_url = "{tmpl_var name='registration_url'}";
+        registration_text = "{tmpl_var name='registration_message'}";
+    </tmpl_if>
+        no_registration_whitelist = true;
+
+        modules_enabled = {
+                "roster",
+                "private",
+                "vcard",
+                "privacy",
+                "pep",
+<tmpl_if name='public_registration' op='==' value='true'>
+                "register",
+<tmpl_elseif name='registration_url' op='!=' value=''>
+                "register_redirect",
+</tmpl_if>
+                "admin_adhoc",
+        };
+        disco_items = {
+<tmpl_if name='use_muc' op='==' value='true'>
+                {
+                        "muc.{tmpl_var name='domain'}",
+                        "{tmpl_var name='muc_name'}",
+                },
+</tmpl_if>
+<tmpl_if name='use_pubsub' op='==' value='true'>
+                {
+                        "pubsub.{tmpl_var name='domain'}",
+                        "{tmpl_var name='domain'} Publish/Subscribe",
+                },
+</tmpl_if>
+<tmpl_if name='use_proxy' op='==' value='true'>
+                {
+                        "proxy.{tmpl_var name='domain'}",
+                        "{tmpl_var name='domain'} Bytestream Proxy",
+                },
+</tmpl_if>
+<tmpl_if name='use_vjud' op='==' value='true'>
+                {
+                        "vjud.{tmpl_var name='domain'}",
+                        "{tmpl_var name='domain'} User Directory",
+                },
+</tmpl_if>
+        };
+
+        admins = {
+{tmpl_var name='domain_admins'}
+        };
+<tmpl_if name='ssl_cert' op='==' value='true'>
+        ssl = {
+                key = "/etc/metronome/certs/{tmpl_var name='domain'}.key",
+                certificate = "/etc/metronome/certs/{tmpl_var name='domain'}.cert",
+        };
+</tmpl_if>
+
+<tmpl_if name='use_proxy' op='==' value='true'>
+VirtualHost "anon.{tmpl_var name='domain'}"
+        enabled = true;
+        authentication = "anonymous";
+        allow_anonymous_multiresourcing = true;
+        anonymous_jid_gentoken = "{tmpl_var name='domain'} Anonymous User";
+        admins = {
+        };
+</tmpl_if>
+
+
+<tmpl_if name='use_muc' op='==' value='true'>
+Component "muc.{tmpl_var name='domain'}" "muc"
+        modules_enabled = {
+                "muc_limits",
+                "muc_log",
+<tmpl_if name='use_archive' op='==' value='true'>
+                "muc_log_http",
+</tmpl_if>
+<tmpl_if name='use_pastebin' op='==' value='true'>
+                "pastebin",
+</tmpl_if>
+        };
+        muc_event_rate = 0.7;
+        muc_burst_factor = 13;
+        muc_log_presences = false;
+<tmpl_if name='use_archive' op='==' value='true'>
+        muc_log_http_config = {
+                show_join = {tmpl_var name='archive_join'},
+                show_status = {tmpl_var name='archive_status'},
+                theme = "metronome",
+                url_base = "logs",
+        };
+</tmpl_if>
+<tmpl_if name='use_pastebin' op='==' value='true'>
+        pastebin_path = "/pastes/";
+        pastebin_expire_after = {tmpl_var name='pastebin_expire'};
+        pastebin_trigger = "{tmpl_var name='pastebin_trigger'}";
+</tmpl_if>
+        name = "{tmpl_var name='muc_name'}";
+        restrict_room_creation = "{tmpl_var name='muc_restrict_room_creation'}";
+        admins = {
+{tmpl_var name='muc_admins'}
+        };
+</tmpl_if>
+
+
+<tmpl_if name='use_pubsub' op='==' value='true'>
+Component "pubsub.{tmpl_var name='domain'}" "pubsub"
+        name = "{tmpl_var name='domain'} Publish/Subscribe";
+        unrestricted_node_creation = false;
+</tmpl_if>
+
+<tmpl_if name='use_proxy' op='==' value='true'>
+Component "proxy.{tmpl_var name='domain'}" "proxy65"
+        proxy65_acl = {
+                "{tmpl_var name='domain'}",
+        };
+        proxy65_interfaces = {
+                "*",
+                "::",
+        };
+        proxy65_ports = {
+                5000,
+        };
+</tmpl_if>
+
+
+<tmpl_if name='use_vjud' op='==' value='true'>
+Component "vjud.{tmpl_var name='domain'}" "vjud"
+        ud_disco_name = "{tmpl_var name='domain'} User Directory";
+        synchronize_to_host_vcards = "{tmpl_var name='domain'}";
+        vjud_mode = "{tmpl_var name='vjud_opt_mode'}";
+</tmpl_if>
\ No newline at end of file
diff --git a/server/conf/metronome_conf_main.master b/server/conf/metronome_conf_main.master
new file mode 100644
index 0000000000000000000000000000000000000000..1103ca4d9cac30365ecdee92496a3424b98b3bfe
--- /dev/null
+++ b/server/conf/metronome_conf_main.master
@@ -0,0 +1,3 @@
+Include "/etc/metronome/global.cfg.lua"
+Include "/etc/metronome/hosts/*.lua"
+Include "/etc/metronome/status.cfg.lua"
diff --git a/server/conf/metronome_conf_ssl.master b/server/conf/metronome_conf_ssl.master
new file mode 100644
index 0000000000000000000000000000000000000000..73ab3a8a3580313f9879c5e50ccd6a01c6e71547
--- /dev/null
+++ b/server/conf/metronome_conf_ssl.master
@@ -0,0 +1,72 @@
+oid_section = new_oids
+
+[ new_oids ]
+
+# RFC 3920 section 5.1.1 defines this OID
+xmppAddr = 1.3.6.1.5.5.7.8.5
+
+# RFC 4985 defines this OID
+SRVName  = 1.3.6.1.5.5.7.8.7
+
+[ req ]
+
+default_bits       = 4096
+default_keyfile    = {tmpl_var name='domain'}.key
+distinguished_name = distinguished_name
+req_extensions     = v3_extensions
+x509_extensions    = v3_extensions
+
+# ask about the DN?
+prompt = no
+
+[ distinguished_name ]
+
+commonName             = {tmpl_var name='domain'}
+countryName            = {tmpl_var name='ssl_country'}
+localityName           = {tmpl_var name='ssl_locality'}
+organizationName       = {tmpl_var name='ssl_organisation'}
+organizationalUnitName = {tmpl_var name='ssl_organisation_unit'}
+emailAddress           = {tmpl_var name='ssl_email'}
+
+[ v3_extensions ]
+
+# for certificate requests (req_extensions)
+# and self-signed certificates (x509_extensions)
+
+basicConstraints = CA:FALSE
+keyUsage         = digitalSignature,keyEncipherment
+extendedKeyUsage = serverAuth,clientAuth
+subjectAltName   = @subject_alternative_name
+
+[ subject_alternative_name ]
+
+# See http://tools.ietf.org/html/draft-ietf-xmpp-3920bis#section-13.7.1.2 for more info.
+
+DNS.0       =                                           {tmpl_var name='domain'}
+otherName.0 =                 xmppAddr;FORMAT:UTF8,UTF8:{tmpl_var name='domain'}
+otherName.1 =            SRVName;IA5STRING:_xmpp-client.{tmpl_var name='domain'}
+otherName.2 =            SRVName;IA5STRING:_xmpp-server.{tmpl_var name='domain'}
+
+DNS.1       =                                       muc.{tmpl_var name='domain'}
+otherName.3 =             xmppAddr;FORMAT:UTF8,UTF8:muc.{tmpl_var name='domain'}
+otherName.4 =        SRVName;IA5STRING:_xmpp-server.muc.{tmpl_var name='domain'}
+
+DNS.2       =                                    pubsub.{tmpl_var name='domain'}
+otherName.5 =          xmppAddr;FORMAT:UTF8,UTF8:pubsub.{tmpl_var name='domain'}
+otherName.6 =     SRVName;IA5STRING:_xmpp-server.pubsub.{tmpl_var name='domain'}
+
+DNS.3       =                                      anon.{tmpl_var name='domain'}
+otherName.7 =            xmppAddr;FORMAT:UTF8,UTF8:anon.{tmpl_var name='domain'}
+otherName.8 =       SRVName;IA5STRING:_xmpp-server.anon.{tmpl_var name='domain'}
+
+DNS.4       =                                      xmpp.{tmpl_var name='domain'}
+otherName.9 =            xmppAddr;FORMAT:UTF8,UTF8:xmpp.{tmpl_var name='domain'}
+otherName.10=       SRVName;IA5STRING:_xmpp-server.xmpp.{tmpl_var name='domain'}
+
+DNS.5       =                                     proxy.{tmpl_var name='domain'}
+otherName.11=           xmppAddr;FORMAT:UTF8,UTF8:proxy.{tmpl_var name='domain'}
+otherName.12=      SRVName;IA5STRING:_xmpp-server.proxy.{tmpl_var name='domain'}
+
+DNS.6       =                                      vjud.{tmpl_var name='domain'}
+otherName.13=            xmppAddr;FORMAT:UTF8,UTF8:vjud.{tmpl_var name='domain'}
+otherName.14=       SRVName;IA5STRING:_xmpp-server.vjud.{tmpl_var name='domain'}
\ No newline at end of file
diff --git a/server/conf/metronome_conf_status.master b/server/conf/metronome_conf_status.master
new file mode 100644
index 0000000000000000000000000000000000000000..daa82054915da514e053059180ff4da34a5b929e
--- /dev/null
+++ b/server/conf/metronome_conf_status.master
@@ -0,0 +1,12 @@
+Component "xmpp.{tmpl_var name='domain'}" "http"
+        modules_enabled = {
+                "server_status",
+                "webpresence"
+        };
+        server_status_basepath = "/xmppd/";
+        server_status_show_hosts = {
+{tmpl_var name='status_hosts'}
+        };
+        server_status_show_comps = {
+{tmpl_var name='status_comps'}
+        };
\ No newline at end of file
diff --git a/server/mods-available/xmpp_module.inc.php b/server/mods-available/xmpp_module.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..aace2567d6bd29f7945526ea1c1a3b36d2646343
--- /dev/null
+++ b/server/mods-available/xmpp_module.inc.php
@@ -0,0 +1,130 @@
+<?php
+
+/*
+Copyright (c) 2007, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+class xmpp_module {
+
+    var $module_name = 'xmpp_module';
+    var $class_name = 'xmpp_module';
+    var $actions_available = array(
+        'xmpp_domain_insert',
+        'xmpp_domain_update',
+        'xmpp_domain_delete',
+        'xmpp_user_insert',
+        'xmpp_user_update',
+        'xmpp_user_delete'
+    );
+
+    //* This function is called during ispconfig installation to determine
+    //  if a symlink shall be created for this plugin.
+    function onInstall() {
+        global $conf;
+
+        if($conf['services']['xmpp'] == true) {
+            return true;
+        } else {
+            return false;
+        }
+
+    }
+
+    /*
+         This function is called when the module is loaded
+    */
+
+    function onLoad() {
+        global $app;
+
+        /*
+        Annonce the actions that where provided by this module, so plugins
+        can register on them.
+        */
+
+        $app->plugins->announceEvents($this->module_name, $this->actions_available);
+
+        /*
+        As we want to get notified of any changes on several database tables,
+        we register for them.
+
+        The following function registers the function "functionname"
+         to be executed when a record for the table "dbtable" is
+         processed in the sys_datalog. "classname" is the name of the
+         class that contains the function functionname.
+        */
+
+        $app->modules->registerTableHook('xmpp_domain', 'xmpp_module', 'process');
+        $app->services->registerService('metronome', 'xmpp_module', 'reloadXMPP');
+        $app->services->registerService('metronome', 'xmpp_module', 'restartXMPP');
+
+    }
+
+    /*
+     This function is called when a change in one of the registered tables is detected.
+     The function then raises the events for the plugins.
+    */
+
+    function process($tablename, $action, $data) {
+        global $app;
+
+        switch ($tablename) {
+            case 'xmpp_domain':
+                if($action == 'i') $app->plugins->raiseEvent('xmpp_domain_insert', $data);
+                if($action == 'u') $app->plugins->raiseEvent('xmpp_domain_update', $data);
+                if($action == 'd') $app->plugins->raiseEvent('xmpp_domain_delete', $data);
+                break;
+            case 'xmpp_user':
+                if($action == 'i') $app->plugins->raiseEvent('xmpp_user_insert', $data);
+                if($action == 'u') $app->plugins->raiseEvent('xmpp_user_update', $data);
+                if($action == 'd') $app->plugins->raiseEvent('xmpp_user_delete', $data);
+                break;
+        } // end switch
+    } // end function
+
+
+    function restartXMPP($action = 'restart') {
+        global $app, $conf;
+
+        // load the server configuration options
+        $app->uses('getconf,system');
+
+        $daemon = 'metronome';
+
+        $retval = array('output' => '', 'retval' => 0);
+        if($action == 'restart') {
+            $cmd = $app->system->getinitcommand($daemon, 'restart');
+        } else {
+            $cmd = $app->system->getinitcommand($daemon, 'reload');
+        }
+        exec($cmd.' 2>&1', $retval['output'], $retval['retval']);
+        $app->log("Restarting xmpp: $cmd", LOGLEVEL_DEBUG);
+        return $retval;
+    }
+} // end class
+
+?>
diff --git a/server/plugins-available/xmpp_plugin.inc.php b/server/plugins-available/xmpp_plugin.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..d5d36a05a78ee2c04f2c83b0d035ceaca1f1d77c
--- /dev/null
+++ b/server/plugins-available/xmpp_plugin.inc.php
@@ -0,0 +1,397 @@
+<?php
+
+/*
+Copyright (c) 2015 Michael Fürmann, Spicy Web (spicyweb.de)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+class xmpp_plugin {
+
+    var $plugin_name = 'xmpp_server_plugin';
+    var $class_name = 'xmpp_server_plugin';
+
+    var $xmpp_config_dir = '/etc/metronome';
+
+    var $ssl_certificate_changed = false;
+    var $ssl_certificate_deleted = false;
+
+
+    //* This function is called during ispconfig installation to determine
+    //  if a symlink shall be created for this plugin.
+    function onInstall() {
+        global $conf;
+
+        if($conf['services']['xmpp'] == true) {
+            return true;
+        } else {
+            return false;
+        }
+
+    }
+
+    /*
+         This function is called when the plugin is loaded
+    */
+
+    function onLoad() {
+        global $app;
+
+        /*
+        Register for the events
+        */
+
+        $app->plugins->registerEvent('server_insert', 'xmpp_plugin', 'insert');
+        $app->plugins->registerEvent('server_update', 'xmpp_plugin', 'update');
+
+        $app->plugins->registerEvent('xmpp_domain_insert', 'xmpp_plugin', 'ssl');
+        $app->plugins->registerEvent('xmpp_domain_update', 'xmpp_plugin', 'ssl');
+        $app->plugins->registerEvent('xmpp_domain_delete', 'xmpp_plugin', 'ssl');
+
+        $app->plugins->registerEvent('xmpp_domain_insert', 'xmpp_plugin', 'domainInsert');
+        $app->plugins->registerEvent('xmpp_domain_update', 'xmpp_plugin', 'domainUpdate');
+        $app->plugins->registerEvent('xmpp_domain_delete', 'xmpp_plugin', 'domainDelete');
+        $app->plugins->registerEvent('xmpp_user_insert', 'xmpp_plugin', 'userInsert');
+        $app->plugins->registerEvent('xmpp_user_update', 'xmpp_plugin', 'userUpdate');
+        $app->plugins->registerEvent('xmpp_user_delete', 'xmpp_plugin', 'userDelete');
+
+    }
+
+    function insert($event_name, $data) {
+        global $app, $conf;
+
+        $this->update($event_name, $data);
+
+    }
+
+    // The purpose of this plugin is to rewrite the main.cf file
+    function update($event_name, $data) {
+        global $app, $conf;
+
+        // get the config
+        $app->uses("getconf,system,tpl");
+
+
+        $old_ini_data = $app->ini_parser->parse_ini_string($data['old']['config']);
+        $xmpp_config = $app->getconf->get_server_config($conf['server_id'], 'xmpp');
+
+        // Global server config
+        $tpl = new tpl();
+        $tpl->newTemplate('metronome_conf_global.master');
+        $tpl->setVar('ipv6', $xmpp_config['xmpp_use_ipv6']=='y'?'true':'false');
+        $tpl->setVar('bosh_timeout', intval($xmpp_config['xmpp_bosh_max_inactivity']));
+        $tpl->setVar('port_http', intval($xmpp_config['xmpp_port_http']));
+        $tpl->setVar('port_https', intval($xmpp_config['xmpp_port_https']));
+        $tpl->setVar('port_pastebin', intval($xmpp_config['xmpp_port_pastebin']));
+        $tpl->setVar('port_bosh', intval($xmpp_config['xmpp_port_bosh']));
+        // Global server admins (for all hosted domains)
+        $admins = '';
+        foreach(explode(',', $xmpp_config['xmpp_server_admins']) AS $a)
+            $admins.= "\t\"".trim($a)."\",\n";
+        $tpl->setVar('server_admins', $admins);
+        unset($admins);
+        // enabled modules, so own modules or simmilar prosody-modules can easily be added
+        $modules = '';
+        foreach(explode(',', $xmpp_config['xmpp_modules_enabled']) AS $m)
+            $modules.= "\t\"".trim($m)."\",\n";
+        $tpl->setVar('modules_enabled', $modules);
+        unset($modules);
+        $app->system->file_put_contents($this->xmpp_config_dir.'/global.cfg.lua', $tpl->grab());
+        unset($tpl);
+
+        $app->services->restartServiceDelayed('metronome', 'restart');
+        return;
+    }
+
+    function domainInsert($event_name, $data) {
+        global $app, $conf;
+
+        $this->domainUpdate($event_name, $data);
+
+    }
+
+    function domainUpdate($event_name, $data){
+        global $app, $conf;
+
+        // get the config
+        $app->uses("getconf,system,tpl");
+
+        // Collections
+        $status_hosts = array($data['new']['domain']);
+        $status_comps = array();
+
+        // Create main host file
+        $tpl = new tpl();
+        $tpl->newTemplate('metronome_conf_host.master');
+        $tpl->setVar('domain', $data['new']['domain']);
+        $tpl->setVar('active', $data['new']['active'] == 'y' ? 'true' : 'false');
+        $tpl->setVar('public_registration', $data['new']['public_registration'] == 'y' ? 'true' : 'false');
+        // Domain admins
+        $admins = array();
+        foreach(explode(',',$data['new']['domain_admins']) AS $adm){
+            $admins[] = trim($adm);
+        }
+        $tpl->setVar('domain_admins', "\t\t\"".implode("\",\n\t\t\"",$admins)."\"\n");
+
+        // Enable / Disable features
+        if($data['new']['use_pubsub']=='y'){
+            $tpl->setVar('use_pubsub', 'true');
+            $status_comps[] = 'pubsub.'.$data['new']['domain'];
+        }else{
+            $tpl->setVar('use_pubsub', 'false');
+        }
+        if($data['new']['use_proxy']=='y'){
+            $tpl->setVar('use_proxy', 'true');
+            $status_comps[] = 'proxy.'.$data['new']['domain'];
+        }else{
+            $tpl->setVar('use_proxy', 'false');
+        }
+
+        if($data['new']['use_anon_host']=='y'){
+            $tpl->setVar('use_anon_host', 'true');
+            $status_hosts[] = 'anon.'.$data['new']['domain'];
+        }else{
+            $tpl->setVar('use_anon_host', 'false');
+        }
+        if($data['new']['use_vjud']=='y'){
+            $tpl->setVar('use_vjud', 'true');
+            $tpl->setVar('vjud_opt_mode', 'opt-'.$data['new']['vjud_opt_mode']);
+            $status_comps[] = 'vjud.'.$data['new']['domain'];
+        }else{
+            $tpl->setVar('use_vjud', 'false');
+        }
+
+        $tpl->setVar('use_muc', $data['new']['use_muc_host']=='y'?'true':'false');
+        if($data['new']['use_muc_host'] == 'y'){
+            $status_comps[] = 'muc.'.$data['new']['domain'];
+            $tpl->setVar('muc_restrict_room_creation', $data['new']['muc_restrict_room_creation']);
+            $tpl->setVar('muc_name', strlen($data['new']['muc_name']) ? $data['new']['muc_name'] : $data['new']['domain'].' Chatrooms');
+            // Admins for MUC channels
+            $admins = array();
+            foreach(explode(',',$data['new']['muc_admins']) AS $adm){
+                $admins[] = trim($adm);
+            }
+            $tpl->setVar('muc_admins', "\t\t\"".implode("\",\n\t\t\"",$admins)."\"\n");
+            $tpl->setVar('use_pastebin', $data['new']['use_pastebin']=='y'?'true':'false');
+            $tpl->setVar('pastebin_expire', intval($data['new']['pastebin_expire_after']));
+            $tpl->setVar('pastebin_trigger', $data['new']['pastebin_trigger']);
+            $tpl->setVar('use_archive', $data['new']['use_http_archive']=='y'?'true':'false');
+            $tpl->setVar('archive_join', $data['new']['http_archive_show_join']=='y'?'true':'false');
+            $tpl->setVar('archive_status', $data['new']['http_archive_show_status']=='y'?'true':'false');
+
+        }
+
+        // Check for SSL
+        if(strlen($data['new']['ssl_cert']) && strlen($data['new']['ssl_key']) && !$this->ssl_certificate_deleted || $this->ssl_certificate_changed)
+            $tpl->setVar('ssl_cert', true);
+
+        $app->system->file_put_contents($this->xmpp_config_dir.'/hosts/'.$data['new']['domain'].'.cfg.lua', $tpl->grab());
+        unset($tpl);
+
+        // Create status host file
+        if($data['new']['use_status_host']=='y'){
+            $tpl = new tpl;
+            $tpl->newTemplate('metronome_conf_status.master');
+            $tpl->setVar('domain', $data['new']['domain']);
+            $tpl->setVar('status_hosts', "\t\t\"".implode("\",\n\t\t\"",$status_hosts)."\"\n");
+            $tpl->setVar('status_comps', "\t\t\"".implode("\",\n\t\t\"",$status_comps)."\"\n");
+            $app->system->file_put_contents($this->xmpp_config_dir.'/status/'.$data['new']['domain'].'.cfg.lua', $tpl->grab());
+            unset($tpl);
+        }
+
+        $app->services->restartServiceDelayed('metronome', 'reload');
+    }
+
+    function domainDelete($event_name, $data){
+        global $app, $conf;
+
+        // get the config
+        $app->uses("system");
+        $domain = $data['old']['domain'];
+        $folder = str_replace('-', '%2d', str_replace('.', '%2e', $str = urlencode($domain)));
+
+        // Remove config files
+        $app->system->unlink("/etc/metronome/hosts/$domain.cfg.lua");
+        $app->system->unlink("/etc/metronome/status/$domain.cfg.lua");
+        $app->system->unlink("/etc/metronome/certs/$domain.cert");
+        $app->system->unlink("/etc/metronome/certs/$domain.key");
+        $app->system->unlink("/etc/metronome/certs/$domain.csr");
+        // Remove all stored data
+        var_dump('rm -rf /var/lib/metronome/'.$folder);
+        exec('rm -rf /var/lib/metronome/'.$folder);
+        exec('rm -rf /var/lib/metronome/*%2e'.$folder);
+
+        $app->services->restartServiceDelayed('metronome', 'reload');
+    }
+
+    function userInsert($event_name, $data){
+        //$data['new']['auth_method']
+        // Check domain for auth settings
+        // Don't allow manual user creation for mailaccount controlled domains
+
+        // maybe metronomectl adduser for new local users
+    }
+    function userUpdate($event_name, $data){
+        // Check domain for auth settings
+        // Don't allow manual user update for mailaccount controlled domains
+
+        // maybe metronomectl passwd for existing local users
+    }
+    function userDelete($event_name, $data){
+        // Check domain for auth settings
+        // Don't allow manual user deletion for mailaccount controlled domains
+
+        // Remove account from metronome
+        exec('metronomectl deluser '.$data['old']['jid']);
+    }
+
+    // Handle the creation of SSL certificates
+    function ssl($event_name, $data) {
+        global $app, $conf;
+
+        $app->uses('system,tpl');
+
+        // load the server configuration options
+        $app->uses('getconf');
+        $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
+
+        $ssl_dir = '/etc/metronome/certs';
+        $domain = $data['new']['domain'];
+        $cnf_file = $ssl_dir.'/'.$domain.'.cnf';
+        $key_file = $ssl_dir.'/'.$domain.'.key';
+        $csr_file = $ssl_dir.'/'.$domain.'.csr';
+        $crt_file = $ssl_dir.'/'.$domain.'.cert';
+
+        //* Create a SSL Certificate, but only if this is not a mirror server.
+        if($data['new']['ssl_action'] == 'create' && $conf['mirror_server_id'] == 0) {
+
+            $this->ssl_certificate_changed = true;
+
+            //* Rename files if they exist
+            if(file_exists($cnf_file)) $app->system->rename($cnf_file, $cnf_file.'.bak');
+            if(file_exists($key_file)){
+                $app->system->rename($key_file, $key_file.'.bak');
+                $app->system->chmod($key_file.'.bak', 0400);
+                $app->system->chown($key_file.'.bak', 'metronome');
+            }
+            if(file_exists($csr_file)) $app->system->rename($csr_file, $csr_file.'.bak');
+            if(file_exists($crt_file)) $app->system->rename($crt_file, $crt_file.'.bak');
+
+            // Write new CNF file
+            $tpl = new tpl();
+            $tpl->newTemplate('metronome_conf_ssl.master');
+            $tpl->setVar('domain', $domain);
+            $tpl->setVar('ssl_country', $data['new']['ssl_country']);
+            $tpl->setVar('ssl_locality', $data['new']['ssl_locality']);
+            $tpl->setVar('ssl_organisation', $data['new']['ssl_organisation']);
+            $tpl->setVar('ssl_organisation_unit', $data['new']['ssl_organisation_unit']);
+            $tpl->setVar('ssl_email', $data['new']['ssl_email']);
+            $app->system->file_put_contents($cnf_file, $tpl->grab());
+
+            // Generate new key, csr and cert
+            exec("(cd /etc/metronome/certs && make $domain.key)");
+            exec("(cd /etc/metronome/certs && make $domain.csr)");
+            exec("(cd /etc/metronome/certs && make $domain.cert)");
+
+            $ssl_key = $app->db->quote($app->system->file_get_contents($key_file));
+            $app->system->chmod($key_file, 0400);
+            $app->system->chown($key_file, 'metronome');
+            $ssl_request = $app->db->quote($app->system->file_get_contents($csr_file));
+            $ssl_cert = $app->db->quote($app->system->file_get_contents($crt_file));
+            /* Update the DB of the (local) Server */
+            $app->db->query("UPDATE xmpp_domain SET ssl_request = '$ssl_request', ssl_cert = '$ssl_cert', ssl_key = '$ssl_key' WHERE domain = '".$data['new']['domain']."'");
+            $app->db->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
+            /* Update also the master-DB of the Server-Farm */
+            $app->dbmaster->query("UPDATE xmpp_domain SET ssl_request = '$ssl_request', ssl_cert = '$ssl_cert', ssl_key = '$ssl_key' WHERE domain = '".$data['new']['domain']."'");
+            $app->dbmaster->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
+            $app->log('Creating XMPP SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
+        }
+
+        //* Save a SSL certificate to disk
+        if($data["new"]["ssl_action"] == 'save') {
+            $this->ssl_certificate_changed = true;
+
+            //* Rename files if they exist
+            if(file_exists($cnf_file)) $app->system->rename($cnf_file, $cnf_file.'.bak');
+            if(file_exists($key_file)){
+                $app->system->rename($key_file, $key_file.'.bak');
+                $app->system->chmod($key_file.'.bak', 0400);
+                $app->system->chown($key_file.'.bak', 'metronome');
+            }
+            if(file_exists($csr_file)) $app->system->rename($csr_file, $csr_file.'.bak');
+            if(file_exists($crt_file)) $app->system->rename($crt_file, $crt_file.'.bak');
+
+            //* Write new ssl files
+            if(trim($data["new"]["ssl_request"]) != '')
+                $app->system->file_put_contents($csr_file, $data["new"]["ssl_request"]);
+            if(trim($data["new"]["ssl_cert"]) != '')
+                $app->system->file_put_contents($crt_file, $data["new"]["ssl_cert"]);
+
+            //* Write the key file, if field is empty then import the key into the db
+            if(trim($data["new"]["ssl_key"]) != '') {
+                $app->system->file_put_contents($key_file, $data["new"]["ssl_key"]);
+                $app->system->chmod($key_file, 0400);
+                $app->system->chown($key_file, 'metronome');
+            } else {
+                $ssl_key = $app->db->quote($app->system->file_get_contents($key_file));
+                /* Update the DB of the (local) Server */
+                $app->db->query("UPDATE xmpp_domain SET ssl_key = '$ssl_key' WHERE domain = '".$data['new']['domain']."'");
+                /* Update also the master-DB of the Server-Farm */
+                $app->dbmaster->query("UPDATE xmpp_domain SET ssl_key = '$ssl_key' WHERE domain = '".$data['new']['domain']."'");
+            }
+
+            /* Update the DB of the (local) Server */
+            $app->db->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
+
+            /* Update also the master-DB of the Server-Farm */
+            $app->dbmaster->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
+            $app->log('Saving XMPP SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
+        }
+
+        //* Delete a SSL certificate
+        if($data['new']['ssl_action'] == 'del') {
+            $this->ssl_certificate_deleted = true;
+            $app->system->unlink($csr_file);
+            $app->system->unlink($crt_file);
+            $app->system->unlink($key_file);
+            $app->system->unlink($cnf_file);
+            $app->system->unlink($csr_file.'.bak');
+            $app->system->unlink($crt_file.'.bak');
+            $app->system->unlink($key_file.'.bak');
+            $app->system->unlink($cnf_file.'.bak');
+            /* Update the DB of the (local) Server */
+            $app->db->query("UPDATE xmpp_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = '".$data['new']['domain']."'");
+            $app->db->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
+            /* Update also the master-DB of the Server-Farm */
+            $app->dbmaster->query("UPDATE xmpp_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = '".$data['new']['domain']."'");
+            $app->dbmaster->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
+            $app->log('Deleting SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
+        }
+
+    }
+
+} // end class
+
+?>
diff --git a/server/server.sh b/server/server.sh
index 522e0d5f74bb56cf9544d073f05c9d0ed893b978..2f3d2fbb82222a5d061d147996cd652c38f0b480 100755
--- a/server/server.sh
+++ b/server/server.sh
@@ -1,5 +1,6 @@
 #!/bin/sh
 
+
 PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin
 
 . /etc/profile