Marius Cramer
2015-03-31 cab4ba3af9dfd02c303d3b4714700269133f35bf
Merge branch 'Quest/ispconfig3-master'

Conflicts:
install/sql/incremental/upd_dev_collection.sql
28 files modified
50 files added
4980 ■■■■■ changed files
install/apps/metronome-init 75 ●●●●● patch | view | raw | blame | history
install/apps/metronome_libs/mod_auth_external/authenticate_isp.sh 38 ●●●●● patch | view | raw | blame | history
install/apps/metronome_libs/mod_auth_external/db_auth.php 58 ●●●●● patch | view | raw | blame | history
install/apps/metronome_libs/mod_auth_external/db_conf.inc.php 6 ●●●●● patch | view | raw | blame | history
install/apps/metronome_libs/mod_auth_external/db_isuser.php 37 ●●●●● patch | view | raw | blame | history
install/apps/metronome_libs/mod_auth_external/mod_auth_external.lua 118 ●●●●● patch | view | raw | blame | history
install/apps/metronome_libs/mod_discoitems.lua 24 ●●●●● patch | view | raw | blame | history
install/apps/metronome_libs/mod_webpresence/icons/status_away.png patch | view | raw | blame | history
install/apps/metronome_libs/mod_webpresence/icons/status_chat.png patch | view | raw | blame | history
install/apps/metronome_libs/mod_webpresence/icons/status_dnd.png patch | view | raw | blame | history
install/apps/metronome_libs/mod_webpresence/icons/status_offline.png patch | view | raw | blame | history
install/apps/metronome_libs/mod_webpresence/icons/status_online.png patch | view | raw | blame | history
install/apps/metronome_libs/mod_webpresence/icons/status_xa.png patch | view | raw | blame | history
install/apps/metronome_libs/mod_webpresence/mod_webpresence.lua 118 ●●●●● patch | view | raw | blame | history
install/dist/conf/debian60.conf.php 4 ●●●● patch | view | raw | blame | history
install/dist/lib/debian60.lib.php 4 ●●●● patch | view | raw | blame | history
install/install.php 19 ●●●●● patch | view | raw | blame | history
install/lib/installer_base.lib.php 123 ●●●●● patch | view | raw | blame | history
install/sql/incremental/upd_dev_collection.sql 94 ●●●●● patch | view | raw | blame | history
install/sql/ispconfig3.sql 96 ●●●●● patch | view | raw | blame | history
install/tpl/metronome_conf_global.master 65 ●●●●● patch | view | raw | blame | history
install/tpl/metronome_conf_main.master 3 ●●●●● patch | view | raw | blame | history
install/tpl/metronome_conf_ssl.master 48 ●●●●● patch | view | raw | blame | history
install/tpl/server.ini.master 9 ●●●●● patch | view | raw | blame | history
install/update.php 9 ●●●●● patch | view | raw | blame | history
interface/lib/classes/validate_client.inc.php 4 ●●●● patch | view | raw | blame | history
interface/web/admin/form/server.tform.php 6 ●●●●● patch | view | raw | blame | history
interface/web/admin/form/server_config.tform.php 80 ●●●●● patch | view | raw | blame | history
interface/web/admin/lib/lang/en_server.lng 2 ●●●●● patch | view | raw | blame | history
interface/web/admin/lib/lang/en_server_config.lng 14 ●●●●● patch | view | raw | blame | history
interface/web/admin/lib/lang/en_server_list.lng 2 ●●●●● patch | view | raw | blame | history
interface/web/admin/list/server.list.php 9 ●●●●● patch | view | raw | blame | history
interface/web/admin/templates/server_config_xmpp_edit.htm 73 ●●●●● patch | view | raw | blame | history
interface/web/admin/templates/server_edit_services.htm 6 ●●●●● patch | view | raw | blame | history
interface/web/admin/templates/server_list.htm 3 ●●●●● patch | view | raw | blame | history
interface/web/client/form/client.tform.php 99 ●●●●● patch | view | raw | blame | history
interface/web/client/form/client_template.tform.php 99 ●●●●● patch | view | raw | blame | history
interface/web/client/form/reseller.tform.php 99 ●●●●● patch | view | raw | blame | history
interface/web/client/lib/lang/en_client.lng 19 ●●●●● patch | view | raw | blame | history
interface/web/client/lib/lang/en_client_template.lng 17 ●●●●● patch | view | raw | blame | history
interface/web/client/lib/lang/en_reseller.lng 18 ●●●●● patch | view | raw | blame | history
interface/web/client/templates/client_edit_limits.htm 64 ●●●●● patch | view | raw | blame | history
interface/web/client/templates/client_template_edit_limits.htm 65 ●●●●● patch | view | raw | blame | history
interface/web/client/templates/reseller_edit_limits.htm 64 ●●●●● patch | view | raw | blame | history
interface/web/js/xmpp_domain_muc.js 26 ●●●●● patch | view | raw | blame | history
interface/web/js/xmpp_domain_registration.js 29 ●●●●● patch | view | raw | blame | history
interface/web/mail/form/xmpp_domain.tform.php 432 ●●●●● patch | view | raw | blame | history
interface/web/mail/form/xmpp_user.tform.php 127 ●●●●● patch | view | raw | blame | history
interface/web/mail/lib/lang/en_xmpp_domain.lng 62 ●●●●● patch | view | raw | blame | history
interface/web/mail/lib/lang/en_xmpp_domain_admin_list.lng 8 ●●●●● patch | view | raw | blame | history
interface/web/mail/lib/lang/en_xmpp_domain_list.lng 7 ●●●●● patch | view | raw | blame | history
interface/web/mail/lib/lang/en_xmpp_user.lng 15 ●●●●● patch | view | raw | blame | history
interface/web/mail/lib/lang/en_xmpp_user_list.lng 8 ●●●●● patch | view | raw | blame | history
interface/web/mail/lib/module.conf.php 24 ●●●●● patch | view | raw | blame | history
interface/web/mail/list/xmpp_domain.list.php 109 ●●●●● patch | view | raw | blame | history
interface/web/mail/list/xmpp_user.list.php 62 ●●●●● patch | view | raw | blame | history
interface/web/mail/templates/xmpp_domain_admin_list.htm 60 ●●●●● patch | view | raw | blame | history
interface/web/mail/templates/xmpp_domain_edit.htm 130 ●●●●● patch | view | raw | blame | history
interface/web/mail/templates/xmpp_domain_edit_modules.htm 59 ●●●●● patch | view | raw | blame | history
interface/web/mail/templates/xmpp_domain_edit_muc.htm 91 ●●●●● patch | view | raw | blame | history
interface/web/mail/templates/xmpp_domain_edit_ssl.htm 100 ●●●●● patch | view | raw | blame | history
interface/web/mail/templates/xmpp_domain_list.htm 74 ●●●●● patch | view | raw | blame | history
interface/web/mail/templates/xmpp_user_edit.htm 47 ●●●●● patch | view | raw | blame | history
interface/web/mail/templates/xmpp_user_list.htm 74 ●●●●● patch | view | raw | blame | history
interface/web/mail/xmpp_domain_del.php 93 ●●●●● patch | view | raw | blame | history
interface/web/mail/xmpp_domain_edit.php 543 ●●●●● patch | view | raw | blame | history
interface/web/mail/xmpp_domain_list.php 28 ●●●●● patch | view | raw | blame | history
interface/web/mail/xmpp_user_del.php 72 ●●●●● patch | view | raw | blame | history
interface/web/mail/xmpp_user_edit.php 172 ●●●●● patch | view | raw | blame | history
interface/web/mail/xmpp_user_list.php 39 ●●●●● patch | view | raw | blame | history
server/conf/metronome_conf_global.master 48 ●●●●● patch | view | raw | blame | history
server/conf/metronome_conf_host.master 135 ●●●●● patch | view | raw | blame | history
server/conf/metronome_conf_main.master 3 ●●●●● patch | view | raw | blame | history
server/conf/metronome_conf_ssl.master 72 ●●●●● patch | view | raw | blame | history
server/conf/metronome_conf_status.master 12 ●●●●● patch | view | raw | blame | history
server/mods-available/xmpp_module.inc.php 130 ●●●●● patch | view | raw | blame | history
server/plugins-available/xmpp_plugin.inc.php 397 ●●●●● patch | view | raw | blame | history
server/server.sh 1 ●●●● patch | view | raw | blame | history
install/apps/metronome-init
New file
@@ -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
install/apps/metronome_libs/mod_auth_external/authenticate_isp.sh
New file
@@ -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
install/apps/metronome_libs/mod_auth_external/db_auth.php
New file
@@ -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();
}
?>
install/apps/metronome_libs/mod_auth_external/db_conf.inc.php
New file
@@ -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}';
install/apps/metronome_libs/mod_auth_external/db_isuser.php
New file
@@ -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();
}
?>
install/apps/metronome_libs/mod_auth_external/mod_auth_external.lua
New file
@@ -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));
install/apps/metronome_libs/mod_discoitems.lua
New file
@@ -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);
install/apps/metronome_libs/mod_webpresence/icons/status_away.png
install/apps/metronome_libs/mod_webpresence/icons/status_chat.png
install/apps/metronome_libs/mod_webpresence/icons/status_dnd.png
install/apps/metronome_libs/mod_webpresence/icons/status_offline.png
install/apps/metronome_libs/mod_webpresence/icons/status_online.png
install/apps/metronome_libs/mod_webpresence/icons/status_xa.png
install/apps/metronome_libs/mod_webpresence/mod_webpresence.lua
New file
@@ -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;
    };
});
install/dist/conf/debian60.conf.php
@@ -222,5 +222,9 @@
$conf['cron']['crontab_dir'] = '/etc/cron.d';
$conf['cron']['wget'] = '/usr/bin/wget';
//* Metronome XMPP
$conf['xmpp']['installed'] = false;
$conf['xmpp']['init_script'] = 'metronome';
?>
install/dist/lib/debian60.lib.php
@@ -154,6 +154,10 @@
    */
    }
    public function configure_xmpp() {
        parent::configure_xmpp();
    }
}
?>
install/install.php
@@ -347,6 +347,13 @@
    }
    */
    //* 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($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 @@
    $conf['services']['db'] = true;
    $conf['services']['firewall'] = false;
    $conf['services']['proxy'] = false;
    $conf['services']['xmpp'] = false;
    //** Get Server ID
@@ -639,6 +648,16 @@
        $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') {
install/lib/installer_base.lib.php
@@ -155,6 +155,7 @@
        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 @@
    }
    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 @@
        $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);
install/sql/incremental/upd_dev_collection.sql
@@ -40,3 +40,97 @@
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 ;
-- --------------------------------------------------------
install/sql/ispconfig3.sql
@@ -184,6 +184,18 @@
  `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 @@
  `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',
@@ -1951,6 +1964,89 @@
) 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
-- --------------------------------------------------------
install/tpl/metronome_conf_global.master
New file
@@ -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";
install/tpl/metronome_conf_main.master
New file
@@ -0,0 +1,3 @@
Include "/etc/metronome/global.cfg.lua"
Include "/etc/metronome/hosts/*.lua"
Include "/etc/metronome/status/*.lua"
install/tpl/metronome_conf_ssl.master
New file
@@ -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'}
install/tpl/server.ini.master
@@ -145,3 +145,12 @@
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
install/update.php
@@ -392,6 +392,11 @@
        $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($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');
interface/lib/classes/validate_client.inc.php
@@ -122,6 +122,10 @@
            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))
interface/web/admin/form/server.tform.php
@@ -102,6 +102,12 @@
            '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',
interface/web/admin/form/server_config.tform.php
@@ -1318,6 +1318,86 @@
);
$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,
interface/web/admin/lib/lang/en_server.lng
@@ -12,4 +12,6 @@
$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';
?>
interface/web/admin/lib/lang/en_server_config.lng
@@ -264,4 +264,18 @@
$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';
?>
interface/web/admin/lib/lang/en_server_list.lng
@@ -10,4 +10,6 @@
$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';
?>
interface/web/admin/list/server.list.php
@@ -110,4 +110,13 @@
    '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>"));
?>
interface/web/admin/templates/server_config_xmpp_edit.htm
New file
@@ -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>
interface/web/admin/templates/server_edit_services.htm
@@ -45,6 +45,12 @@
                </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">
                    {tmpl_var name='mirror_server_id'}
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>
interface/web/client/form/client.tform.php
@@ -773,6 +773,105 @@
            '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',
interface/web/client/form/client_template.tform.php
@@ -322,6 +322,105 @@
            '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',
interface/web/client/form/reseller.tform.php
@@ -769,6 +769,105 @@
            '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',
interface/web/client/lib/lang/en_client.lng
@@ -132,6 +132,7 @@
$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_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';
interface/web/client/lib/lang/en_client_template.lng
@@ -98,4 +98,21 @@
$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';
?>
interface/web/client/lib/lang/en_reseller.lng
@@ -172,6 +172,24 @@
$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.';
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">
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">
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">
interface/web/js/xmpp_domain_muc.js
New file
@@ -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');
})
interface/web/js/xmpp_domain_registration.js
New file
@@ -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');
})
interface/web/mail/form/xmpp_domain.tform.php
New file
@@ -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
        //#################################
    )
);
?>
interface/web/mail/form/xmpp_user.tform.php
New file
@@ -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
        //#################################
    )
);
?>
interface/web/mail/lib/lang/en_xmpp_domain.lng
New file
@@ -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.';
?>
interface/web/mail/lib/lang/en_xmpp_domain_admin_list.lng
New file
@@ -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';
?>
interface/web/mail/lib/lang/en_xmpp_domain_list.lng
New file
@@ -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';
?>
interface/web/mail/lib/lang/en_xmpp_user.lng
New file
@@ -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.';
?>
interface/web/mail/lib/lang/en_xmpp_user_list.lng
New file
@@ -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';
?>
interface/web/mail/lib/module.conf.php
@@ -148,6 +148,30 @@
        '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
interface/web/mail/list/xmpp_domain.list.php
New file
@@ -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'  => "");
?>
interface/web/mail/list/xmpp_user.list.php
New file
@@ -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'     => "");
?>
interface/web/mail/templates/xmpp_domain_admin_list.htm
New file
@@ -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>
interface/web/mail/templates/xmpp_domain_edit.htm
New file
@@ -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>
interface/web/mail/templates/xmpp_domain_edit_modules.htm
New file
@@ -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>
interface/web/mail/templates/xmpp_domain_edit_muc.htm
New file
@@ -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>
interface/web/mail/templates/xmpp_domain_edit_ssl.htm
New file
@@ -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>
interface/web/mail/templates/xmpp_domain_list.htm
New file
@@ -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>
interface/web/mail/templates/xmpp_user_edit.htm
New file
@@ -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>
interface/web/mail/templates/xmpp_user_list.htm
New file
@@ -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>
interface/web/mail/xmpp_domain_del.php
New file
@@ -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();
?>
interface/web/mail/xmpp_domain_edit.php
New file
@@ -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();
?>
interface/web/mail/xmpp_domain_list.php
New file
@@ -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();
?>
interface/web/mail/xmpp_user_del.php
New file
@@ -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();
?>
interface/web/mail/xmpp_user_edit.php
New file
@@ -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();
?>
interface/web/mail/xmpp_user_list.php
New file
@@ -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();
?>
server/conf/metronome_conf_global.master
New file
@@ -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";
server/conf/metronome_conf_host.master
New file
@@ -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>
server/conf/metronome_conf_main.master
New file
@@ -0,0 +1,3 @@
Include "/etc/metronome/global.cfg.lua"
Include "/etc/metronome/hosts/*.lua"
Include "/etc/metronome/status.cfg.lua"
server/conf/metronome_conf_ssl.master
New file
@@ -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'}
server/conf/metronome_conf_status.master
New file
@@ -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'}
        };
server/mods-available/xmpp_module.inc.php
New file
@@ -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
?>
server/plugins-available/xmpp_plugin.inc.php
New file
@@ -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
?>
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