summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBertrand Jacquin <beber@meleeweb.net>2006-09-28 21:56:03 +0200
committerBertrand Jacquin <beber@meleeweb.net>2006-09-28 21:56:03 +0200
commit7d299f1efeecd3cb69d6ce76a9486dbb26971a19 (patch)
treea184b2cb2994d65a818a0a4f72498b13869bd6e6
parentejabberd: more patch for new release (diff)
downloadportage-7d299f1efeecd3cb69d6ce76a9486dbb26971a19.tar.xz
ejabberd: add patch from http://bugs.gentoo.org/show_bug.cgi?id=137724 and http://bugs.gentoo.org/show_bug.cgi?id=145373
-rw-r--r--net-im/ejabberd/Manifest23
-rw-r--r--net-im/ejabberd/ejabberd-1.1.2-r1.ebuild213
-rw-r--r--net-im/ejabberd/files/digest-ejabberd-1.1.2-r19
-rw-r--r--net-im/ejabberd/files/ejabberd-1.1.2-mod-proxy.patch423
-rw-r--r--net-im/ejabberd/files/ejabberd-1.1.2-statsdx-web.patch318
-rw-r--r--net-im/ejabberd/files/ejabberd-1.1.2-statsdx.patch742
-rw-r--r--net-im/ejabberd/files/ejabberd-1.1.2.initd59
7 files changed, 1787 insertions, 0 deletions
diff --git a/net-im/ejabberd/Manifest b/net-im/ejabberd/Manifest
index 917c7870..99f645d0 100644
--- a/net-im/ejabberd/Manifest
+++ b/net-im/ejabberd/Manifest
@@ -1,3 +1,19 @@
+AUX ejabberd-1.1.2-mod-proxy.patch 14771 RMD160 4a3d817fd103aebfb8e76fc9f23396b57da5f473 SHA1 023ab0fe368bd6de78ad21a977b1d5a09818cab3 SHA256 3c130d4d76fcc6e51014c4ef7db2939d3d6ee911f59fe17bd580ca914a07d6e3
+MD5 c9f267fcc007f5a0a92834fc63d9cb3e files/ejabberd-1.1.2-mod-proxy.patch 14771
+RMD160 4a3d817fd103aebfb8e76fc9f23396b57da5f473 files/ejabberd-1.1.2-mod-proxy.patch 14771
+SHA256 3c130d4d76fcc6e51014c4ef7db2939d3d6ee911f59fe17bd580ca914a07d6e3 files/ejabberd-1.1.2-mod-proxy.patch 14771
+AUX ejabberd-1.1.2-statsdx-web.patch 9287 RMD160 e98789d5b29f6fcb55c383e551239378c8ce3eb6 SHA1 4e35a28d7692ae3d36bd0c5590b482c9f8266309 SHA256 4036facbe4bd712784e5964b1e422b1f3f60aeff8ec1058b3358c45535b4e8d9
+MD5 ae2346c4c0a0540b3236a80a2bf12451 files/ejabberd-1.1.2-statsdx-web.patch 9287
+RMD160 e98789d5b29f6fcb55c383e551239378c8ce3eb6 files/ejabberd-1.1.2-statsdx-web.patch 9287
+SHA256 4036facbe4bd712784e5964b1e422b1f3f60aeff8ec1058b3358c45535b4e8d9 files/ejabberd-1.1.2-statsdx-web.patch 9287
+AUX ejabberd-1.1.2-statsdx.patch 24201 RMD160 e04d36746649e435a68c32f2705a27fc9107009e SHA1 6d621b54addfcdb047ec7b4314573ec4aa161ef9 SHA256 27dfeaa59ab901c9c08d7dca9fc667252cec64fa08d8e43adaa7e72f961f864f
+MD5 a5fc80bf820a7d5ef93354895bd2928a files/ejabberd-1.1.2-statsdx.patch 24201
+RMD160 e04d36746649e435a68c32f2705a27fc9107009e files/ejabberd-1.1.2-statsdx.patch 24201
+SHA256 27dfeaa59ab901c9c08d7dca9fc667252cec64fa08d8e43adaa7e72f961f864f files/ejabberd-1.1.2-statsdx.patch 24201
+AUX ejabberd-1.1.2.initd 1405 RMD160 104068f4a53db32a713c7e12c3e5eaa6f0ed6545 SHA1 0ff5afe2a0994f36168a2df319c0dfaf9813aa81 SHA256 2d1aa6e50eaa090b2e5897fd5d72112a3848811f6886041fdb8903f85ea18daf
+MD5 df620170a91b83b4a45c79d2d736dd22 files/ejabberd-1.1.2.initd 1405
+RMD160 104068f4a53db32a713c7e12c3e5eaa6f0ed6545 files/ejabberd-1.1.2.initd 1405
+SHA256 2d1aa6e50eaa090b2e5897fd5d72112a3848811f6886041fdb8903f85ea18daf files/ejabberd-1.1.2.initd 1405
AUX mod_archive.erl 29560 RMD160 6c628ca4f1d82cd826c2a4d11c87d6b3344f3f24 SHA1 b934e9a9ed1ab7dc700b589177dc9425aa535a6f SHA256 b46976ca86a43cb13ed71009a5fadf7a2ca231e51da83150cdff0d646fbed00f
MD5 c3c630a783edc22b0d81646f2c2eb829 files/mod_archive.erl 29560
RMD160 6c628ca4f1d82cd826c2a4d11c87d6b3344f3f24 files/mod_archive.erl 29560
@@ -14,6 +30,10 @@ EBUILD ejabberd-1.1.1-r1.ebuild 3886 RMD160 688617ec68dd542758b695d18d57c6d123c5
MD5 151e7780af1a89705e11cdae74358821 ejabberd-1.1.1-r1.ebuild 3886
RMD160 688617ec68dd542758b695d18d57c6d123c5e2f7 ejabberd-1.1.1-r1.ebuild 3886
SHA256 04236fb5a30476d6b05bbfc8be4e0eb4abad407194204fa8729f3481c0e4bd53 ejabberd-1.1.1-r1.ebuild 3886
+EBUILD ejabberd-1.1.2-r1.ebuild 5727 RMD160 32735f6451a7204f3018b7abd7ad593743104a51 SHA1 2eaca4da4fc79219ee6307ffd3191608068d695c SHA256 e7e6687d67bcb5d9731738ecf8e92034bbacd00ef22256ad2738d58ff3ebdfbc
+MD5 502ee5bd89b264cd8a5be6d37cb79b87 ejabberd-1.1.2-r1.ebuild 5727
+RMD160 32735f6451a7204f3018b7abd7ad593743104a51 ejabberd-1.1.2-r1.ebuild 5727
+SHA256 e7e6687d67bcb5d9731738ecf8e92034bbacd00ef22256ad2738d58ff3ebdfbc ejabberd-1.1.2-r1.ebuild 5727
EBUILD ejabberd-1.1.2.ebuild 3886 RMD160 688617ec68dd542758b695d18d57c6d123c5e2f7 SHA1 42051242370093ccff3ecd35fcfa4bda4140ddd3 SHA256 04236fb5a30476d6b05bbfc8be4e0eb4abad407194204fa8729f3481c0e4bd53
MD5 151e7780af1a89705e11cdae74358821 ejabberd-1.1.2.ebuild 3886
RMD160 688617ec68dd542758b695d18d57c6d123c5e2f7 ejabberd-1.1.2.ebuild 3886
@@ -24,3 +44,6 @@ SHA256 f57333e151bec1d584876aade6dc4fec76e8deffdd240d7aa2d2ec947d6dbba8 files/di
MD5 f10adb4f04e5543f5410c8a2e1081c96 files/digest-ejabberd-1.1.2 723
RMD160 7eeb128a9c425adfe020101bef8a0278e1bd0211 files/digest-ejabberd-1.1.2 723
SHA256 811fc4d85d4bcd926bdce37a5ecade163afb5b14663d747842375c8ffdc5100d files/digest-ejabberd-1.1.2 723
+MD5 f10adb4f04e5543f5410c8a2e1081c96 files/digest-ejabberd-1.1.2-r1 723
+RMD160 7eeb128a9c425adfe020101bef8a0278e1bd0211 files/digest-ejabberd-1.1.2-r1 723
+SHA256 811fc4d85d4bcd926bdce37a5ecade163afb5b14663d747842375c8ffdc5100d files/digest-ejabberd-1.1.2-r1 723
diff --git a/net-im/ejabberd/ejabberd-1.1.2-r1.ebuild b/net-im/ejabberd/ejabberd-1.1.2-r1.ebuild
new file mode 100644
index 00000000..85f7e1cb
--- /dev/null
+++ b/net-im/ejabberd/ejabberd-1.1.2-r1.ebuild
@@ -0,0 +1,213 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit eutils multilib ssl-cert versionator autotools
+
+JABBER_ETC="/etc/jabber"
+JABBER_RUN="/var/run/jabber"
+JABBER_SPOOL="/var/spool/jabber"
+JABBER_LOG="/var/log/jabber"
+
+E_MYSQL_V="5"
+E_MYSQL_N="mysql"
+E_MYSQL=${E_MYSQL_N}-${E_MYSQL_V}
+
+E_PGSQL_V="0.0.1"
+E_PGSQL_N="pgsql-cvs"
+E_PGSQL=${E_PGSQL_N}-${E_PGSQL_V}
+
+DESCRIPTION="The Erlang Jabber Daemon"
+HOMEPAGE="http://ejabberd.jabber.ru/"
+SRC_URI="http://process-one.net/en/projects/${PN}/download/${PV}/${P}.tar.gz
+ pam? ( http://beber.meleeweb.net/jabber/check_pam.diff.gz )
+ mod_presence? ( http://www.goryachev.org/jabber/mod_presence-0.0.3.tar.gz )"
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="x86 ~amd64"
+IUSE="${IUSE} mod_archive mod_irc mod_muc mod_pubsub mod_presence mod_proxy statsdx ldap odbc pam web mysql postgres"
+
+DEPEND="${RDEPEND}
+ >=net-im/jabber-base-0.01
+ >=dev-libs/expat-1.95
+ >=dev-lang/erlang-10.2.0
+ odbc? ( dev-db/unixODBC )
+ ldap? ( =net-nds/openldap-2* )
+ postgres? ( =dev-erl/${E_PGSQL} )
+ mysql? ( =dev-erl/${E_MYSQL} )
+ pam? ( sys-libs/pam)"
+RDEPEND="postgres? ( dev-db/postgresql )
+ mysql? ( dev-db/mysql )"
+
+RESTRICT="nomirror"
+
+PROVIDE="virtual/jabber-server"
+S=${WORKDIR}/${P}/src
+
+src_unpack() {
+ unpack ${A}
+ cd ${S}
+
+ MYSQL_P=$(best_version dev-db/mysql)
+ MYSQL_PV=${MYSQL_P/dev-db\/mysql-/}
+
+ #
+ # If we have to work with MySQL 4.1 or greater, ejabberd's native
+ # MySQL-driver has to be patched to query "SET NAMES 'utf8'" on connecting
+ # the database.
+ #
+ if use mysql && \
+ (( \
+ [ $(get_major_version ${MYSQL_PV}) -eq 4 ] && \
+ [ $(get_major_version $(get_after_major_version ${MYSQL_PV})) -ge 1] \
+ ) \
+ || \
+ [ $(get_major_version ${MYSQL_PV}) -ge 5 ] \
+ ); then
+ epatch ${FILESDIR}/${P}-mysql-connect-utf8.patch
+ fi
+
+ if use statsdx; then
+ epatch ${FILESDIR}/${P}-statsdx.patch
+ epatch ${FILESDIR}/${P}-statsdx-web.patch
+ fi
+
+ if use mod_proxy; then
+ epatch ${FILESDIR}/${P}-mod-proxy.patch
+ fi
+
+ if use mod_presence; then
+ epatch ${WORKDIR}/mod_presence/mod_presence.diff
+ cp -r ${WORKDIR}/mod_presence/pixmaps .
+ fi
+
+ if use pam; then
+ patch -p0 < ${WORKDIR}/check_pam.diff
+ fi
+
+ if use mod_archive; then
+ cp ${FILESDIR}/mod_archive.erl .
+ fi
+}
+
+src_compile() {
+ local myconf
+
+ if ! use mysql && ! use postgres && ! use odbc; then
+ myconf="--disable-odbc"
+ else
+ myconf="--enable-odbc"
+ fi
+
+ eautoconf
+ econf ${myconf} \
+ --enable-roster-gateway-workaround \
+ $(use_enable mod_irc) \
+ $(use_enable ldap eldap) \
+ $(use_enable mod_muc) \
+ $(use_enable mod_pubsub) \
+ $(use_enable ssl tls) \
+ $(use_enable web) \
+ $(use_enable odbc) \
+ $(use_enable mod_presence) \
+ || die "econf failed"
+
+ emake || die "compiling ejabberd core failed"
+}
+
+src_install() {
+ make \
+ DESTDIR=${D} \
+ EJABBERDDIR=${D}/usr/$(get_libdir)/erlang/lib/${P} \
+ ETCDIR=${D}${JABBER_ETC} \
+ LOGDIR=${D}${JABBER_LOG} \
+ install \
+ || die "install failed"
+
+ insinto /usr/share/doc/${PF}
+ use postgres && doins odbc/pg.sql
+ use mysql && doins odbc/mysql.sql
+ cd ${S}/..
+ dodoc doc/release_notes_${PV}.txt
+ dohtml doc/*.{html,png}
+
+ use postgres && {
+ pa="-pa /usr/$(get_libdir)/erlang/lib/${E_PGSQL}/ebin"
+ }
+
+ use mysql && {
+ pa=${pa}" -pa /usr/$(get_libdir)/erlang/lib/${E_MYSQL}/ebin"
+ }
+
+ #
+ # Create /usr/bin/ejabberd
+ #
+ cat <<EOF > ${T}/ejabberd
+#!/bin/bash
+
+erl -pa /usr/$(get_libdir)/erlang/lib/${P}/ebin \\
+ ${pa} \\
+ -sname ejabberd \\
+ -s ejabberd \\
+ -ejabberd config \"${JABBER_ETC}/ejabberd.cfg\" \\
+ log_path \"${JABBER_LOG}/ejabberd.log\" \\
+ -kernel inetrc \"${JABBER_ETC}/inetrc\" \\
+ -sasl sasl_error_logger \{file,\"${JABBER_LOG}/sasl.log\"\} \\
+ -mnesia dir \"${JABBER_SPOOL}\" \\
+ \$@
+EOF
+
+ #
+ # Create /usr/bin/ejabberdctl
+ #
+ cat <<EOF > ${T}/ejabberdctl
+#!/bin/sh
+
+exec env HOME=${JABBER_RUN} \\
+ erl -pa /usr/$(get_libdir)/erlang/lib/${P}/ebin \\
+ ${pa} \\
+ -noinput \\
+ -sname ejabberdctl \\
+ -s ejabberd_ctl \\
+ -extra \$@
+EOF
+
+ dobin ${T}/ejabberdctl
+ dobin ${T}/ejabberd
+
+ newinitd ${FILESDIR}/${P}.initd ${PN}
+ newconfd ${FILESDIR}/${P}.confd ${PN}
+
+ insinto ${JABBER_ETC}
+ if use ssl; then
+ docert ssl
+ rm -f ${D}${JABBER_ETC}/ssl.{crt,csr,key}
+ fowners jabber:jabber ${JABBER_ETC}/ssl.pem
+ fi
+ doins ${FILESDIR}/inetrc
+}
+
+pkg_postinst() {
+ if [ ! -e ${JABBER_ETC}/ejabberd.cfg ]
+ then
+ einfo "Configuration file has been installed in ${JABBER_ETC}/ejabberd.cfg."
+ einfo "Edit it according to your needs. For configuration instructions,"
+ einfo "please see /usr/share/doc/${PF}/html/guide.html"
+ fi
+ if use ssl ; then
+ einfo "A script to generate a ssl key has been installed in"
+ einfo "${JABBER_ETC}/self-cert.sh . Use it and change the config file to"
+ einfo "point to the full path"
+ fi
+ if ! use web ; then
+ einfo "The web USE flag is off, this will disable the web admin interface,"
+ einfo "if this was not the intention then add web to your USE flags."
+ fi
+
+ if use modproxy ; then
+ einfo "mod_proxy enabled ! http://www.jabber.ru/bugzilla/show_bug.cgi?id=25"
+ fi
+ if use statsdx ; then
+ einfo "Advanced stats enabled ! http://ejabberd.jabber.ru/mod_statsdx"
+ fi
+}
diff --git a/net-im/ejabberd/files/digest-ejabberd-1.1.2-r1 b/net-im/ejabberd/files/digest-ejabberd-1.1.2-r1
new file mode 100644
index 00000000..2e59e9e3
--- /dev/null
+++ b/net-im/ejabberd/files/digest-ejabberd-1.1.2-r1
@@ -0,0 +1,9 @@
+MD5 6b78cb824b35a7f651ab33790cf841c7 check_pam.diff.gz 3865
+RMD160 86d6ff263d216c63662ef1078f947f9f7a6c1fce check_pam.diff.gz 3865
+SHA256 c474adefeefd6e2d18fff531dc4c2f3c149ba003dbd606655656a95ca72ee62a check_pam.diff.gz 3865
+MD5 5b947e19e18a6b554bf31d1c95176eb6 ejabberd-1.1.2.tar.gz 836240
+RMD160 e763752e6c5fb46c51b71e265ab2ceda6d043a0d ejabberd-1.1.2.tar.gz 836240
+SHA256 029129a6bcb5d15dbccc5aa756f61c52692eb6882ec7aad0193aa940b6a20bb6 ejabberd-1.1.2.tar.gz 836240
+MD5 fa9a979f5e3530a2b3143416934d989b mod_presence-0.0.3.tar.gz 51392
+RMD160 adb6444dcef2fead52c1510fc247f7af20aa62c7 mod_presence-0.0.3.tar.gz 51392
+SHA256 5fc2a97576f33965d07bb1f803a8fe48647479da37cd58333aea6a7e48ebc4a1 mod_presence-0.0.3.tar.gz 51392
diff --git a/net-im/ejabberd/files/ejabberd-1.1.2-mod-proxy.patch b/net-im/ejabberd/files/ejabberd-1.1.2-mod-proxy.patch
new file mode 100644
index 00000000..1981aee1
--- /dev/null
+++ b/net-im/ejabberd/files/ejabberd-1.1.2-mod-proxy.patch
@@ -0,0 +1,423 @@
+diff -Naur ejabberd-1.1.1/src/ejabberd.cfg.example ejabberd-1.1.1-r1/src/ejabberd.cfg.example
+--- ejabberd-1.1.1/src/ejabberd.cfg.example 2006-04-22 15:50:30.000000000 +0200
++++ ejabberd-1.1.1-r1/src/ejabberd.cfg.example 2006-06-23 09:38:17.000000000 +0200
+@@ -125,6 +125,7 @@
+ {max_stanza_size, 131072}
+ ]},
+ {5280, ejabberd_http, [http_poll, web_admin]},
++ %{7777, proxy65_listener, [{shaper, c2s_shaper}]},
+ {8888, ejabberd_service, [{access, all},
+ {hosts, ["icq.localhost", "sms.localhost"],
+ [{password, "secret"}]}]}
+@@ -171,6 +172,11 @@
+ {mod_pubsub, []},
+ {mod_time, []},
+ {mod_last, []},
++ %% Simple configuration (hostname:7777)
++ %%{mod_proxy65, []},
++ %% Several possible hostnames
++ %%{mod_proxy65, [{access, all},
++ %% {streamhosts, [{"example.com", 7777}, {"192.168.0.42", 7777}]}]},
+ {mod_version, []}
+ ]}.
+
+diff -Naur ejabberd-1.1.1/src/jlib.hrl ejabberd-1.1.1-r1/src/jlib.hrl
+--- ejabberd-1.1.1/src/jlib.hrl 2006-01-20 17:21:39.000000000 +0100
++++ ejabberd-1.1.1-r1/src/jlib.hrl 2006-06-23 09:38:17.000000000 +0200
+@@ -34,6 +34,7 @@
+ -define(NS_PUBSUB_OWNER, "http://jabber.org/protocol/pubsub#owner").
+ -define(NS_PUBSUB_NMI, "http://jabber.org/protocol/pubsub#node-meta-info").
+ -define(NS_COMMANDS, "http://jabber.org/protocol/commands").
++-define(NS_BYTESTREAMS, "http://jabber.org/protocol/bytestreams").
+
+ -define(NS_EJABBERD_CONFIG, "ejabberd:config").
+
+diff -Naur ejabberd-1.1.1/src/mod_proxy65.erl ejabberd-1.1.1-r1/src/mod_proxy65.erl
+--- ejabberd-1.1.1/src/mod_proxy65.erl 1970-01-01 01:00:00.000000000 +0100
++++ ejabberd-1.1.1-r1/src/mod_proxy65.erl 2006-06-23 09:38:17.000000000 +0200
+@@ -0,0 +1,189 @@
++%%%----------------------------------------------------------------------
++%%% File : mod_proxy65.erl
++%%% Author : Magnus Henoch <henoch@dtek.chalmers.se>
++%%% Purpose : Handle Jabber communications for JEP-0065 proxy
++%%% Created : 27 Dec 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
++%%% Id : $Id: ejabberd_c2s.erl 440 2005-11-22 18:00:56Z alexey $
++%%%----------------------------------------------------------------------
++
++-module(mod_proxy65).
++-author('henoch@dtek.chalmers.se').
++-vsn('$Revision$ ').
++
++-behaviour(gen_mod).
++
++-export([start/2,
++ init/1,
++ stop/1]).
++
++-include("ejabberd.hrl").
++-include("jlib.hrl").
++
++-record(proxy65_connection, {cookie, firstpid = none, secondpid = none}).
++
++-record(proxy65_options, {host, access, streamhosts}).
++
++-define(PROCNAME, ejabberd_mod_proxy65).
++
++start(Host, Opts) ->
++ mnesia:create_table(proxy65_connection,
++ [{ram_copies, [node()]},
++ {attributes, record_info(fields, proxy65_connection)}]),
++ MyHost = gen_mod:get_opt(host, Opts, "proxy." ++ Host),
++ Access = gen_mod:get_opt(access, Opts, all),
++ Streamhosts = gen_mod:get_opt(streamhosts, Opts, [{Host, 7777}]),
++
++ register(gen_mod:get_module_proc(Host, ?PROCNAME),
++ spawn(?MODULE, init, [#proxy65_options{host = MyHost, access = Access,
++ streamhosts = Streamhosts}])).
++
++
++stop(Host) ->
++ Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
++ Proc ! stop,
++ {wait, Proc}.
++
++init(#proxy65_options{host = Host} = Opts) ->
++ ejabberd_router:register_route(Host),
++ loop(Opts).
++
++loop(#proxy65_options{host = Host} = Opts) ->
++ receive
++ {route, From, To, Packet} ->
++ case catch do_route(Opts, From, To, Packet) of
++ {'EXIT', Reason} ->
++ ?ERROR_MSG("~p", [Reason]);
++ _ ->
++ ok
++ end,
++ loop(Opts);
++ stop ->
++ ejabberd_router:unregister_route(Host),
++ ok;
++ _ ->
++ loop(Opts)
++ end.
++
++do_route(#proxy65_options{host = Host, access = Access} = Opts,
++ From, To, Packet) ->
++ case acl:match_rule(Host, Access, From) of
++ allow ->
++ do_route1(Opts, From, To, Packet);
++ _ ->
++ {xmlelement, _Name, Attrs, _Els} = Packet,
++ Lang = xml:get_attr_s("xml:lang", Attrs),
++ ErrText = "Access denied by service policy",
++ Err = jlib:make_error_reply(Packet,
++ ?ERRT_FORBIDDEN(Lang, ErrText)),
++ ejabberd_router:route(To, From, Err)
++ end.
++
++do_route1(#proxy65_options{host = Host, streamhosts = Streamhosts}, From, To, Packet) ->
++ {xmlelement, Name, _Attrs, _Els} = Packet,
++ case Name of
++ "iq" ->
++ case jlib:iq_query_info(Packet) of
++ #iq{type = get, xmlns = ?NS_DISCO_INFO = XMLNS,
++ lang = Lang, sub_el = SubEl} = IQ ->
++ Node = xml:get_tag_attr_s("node", SubEl),
++ if Node == [] ->
++ Res = IQ#iq{type = result,
++ sub_el = [{xmlelement, "query",
++ [{"xmlns", XMLNS}],
++ [{xmlelement, "identity",
++ [{"category", "proxy"},
++ {"type", "bytestreams"},
++ {"name", translate:translate(Lang, "SOCKS5 bytestreams proxy")}],
++ []},
++ {xmlelement, "feature",
++ [{"var", ?NS_BYTESTREAMS}], []}]}]};
++ true ->
++ Res = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND)
++ end;
++ #iq{type = get, xmlns = ?NS_DISCO_ITEMS = XMLNS} = IQ ->
++ Res = IQ#iq{type = result,
++ sub_el = [{xmlelement, "query",
++ [{"xmlns", XMLNS}], []}]};
++ #iq{type = get, xmlns = ?NS_VERSION} = IQ ->
++ OSType = case os:type() of
++ {Osfamily, Osname} ->
++ atom_to_list(Osfamily) ++ "/" ++
++ atom_to_list(Osname);
++ Osfamily ->
++ atom_to_list(Osfamily)
++ end,
++ OSVersion = case os:version() of
++ {Major, Minor, Release} ->
++ lists:flatten(
++ io_lib:format("~w.~w.~w",
++ [Major, Minor, Release]));
++ VersionString ->
++ VersionString
++ end,
++ OS = OSType ++ " " ++ OSVersion,
++ Res = IQ#iq{type = result,
++ sub_el = [{xmlelement, "query",
++ [{"xmlns", ?NS_VERSION}],
++ [{xmlelement, "name", [],
++ [{xmlcdata, "ejabberd mod_proxy65 (unofficial)"}]},
++ {xmlelement, "version", [],
++ [{xmlcdata, "0.1"}]},
++ {xmlelement, "os", [],
++ [{xmlcdata, OS}]}
++ ]}]};
++ #iq{type = get, xmlns = ?NS_BYTESTREAMS = XMLNS} = IQ ->
++ Res = IQ#iq{type = result,
++ sub_el = [{xmlelement, "query",
++ [{"xmlns", XMLNS}],
++ return_streamhosts(Host, Streamhosts)}]};
++ #iq{type = set, xmlns = ?NS_BYTESTREAMS} = IQ ->
++ Res = activate(Packet, From, To, IQ);
++ _ ->
++ Res = jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED)
++ end,
++ case Res of
++ #iq{} ->
++ ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
++ _ ->
++ ejabberd_router:route(To, From, Res)
++ end;
++ _ ->
++ ejabberd_router:route(To, From, jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED))
++ end.
++
++return_streamhosts(_JID, []) ->
++ [];
++return_streamhosts(JID, [{Host, Port} | Streamhosts]) ->
++ %% This is not tail-recursive, but it doesn't matter.
++ [{xmlelement, "streamhost",
++ [{"jid", JID},
++ {"host", Host},
++ {"port", integer_to_list(Port)}],
++ []} | return_streamhosts(JID, Streamhosts)].
++
++activate(Packet, From, _To, #iq{sub_el = SubEl} = IQ) ->
++ case SubEl of
++ {xmlelement, "query", Attrs, _SubEls} ->
++ Sid = xml:get_attr_s("sid", Attrs),
++ ActivateTag = xml:get_subtag(SubEl, "activate"),
++ if ActivateTag /= false ->
++ TargetJID = jlib:string_to_jid(xml:get_tag_cdata(ActivateTag));
++ true ->
++ TargetJID = false
++ end,
++
++ if Sid /= [], TargetJID /= false, TargetJID /= error ->
++ case proxy65_listener:activate(From, TargetJID, Sid) of
++ ok ->
++ ?INFO_MSG("Activated connection between ~s and ~s",
++ [jlib:jid_to_string(From), TargetJID]),
++ IQ#iq{type = result, sub_el = []};
++ _ ->
++ jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR)
++ end;
++ true ->
++ jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST)
++ end;
++ _ ->
++ jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST)
++ end.
+diff -Naur ejabberd-1.1.1/src/proxy65_listener.erl ejabberd-1.1.1-r1/src/proxy65_listener.erl
+--- ejabberd-1.1.1/src/proxy65_listener.erl 1970-01-01 01:00:00.000000000 +0100
++++ ejabberd-1.1.1-r1/src/proxy65_listener.erl 2006-06-23 09:38:17.000000000 +0200
+@@ -0,0 +1,192 @@
++%%%----------------------------------------------------------------------
++%%% File : proxy65_listener.erl
++%%% Author : Magnus Henoch <henoch@dtek.chalmers.se>
++%%% Purpose : Handle SOCKS5 connections for JEP-0065 proxy
++%%% Created : 27 Dec 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
++%%% Id : $Id: ejabberd_c2s.erl 440 2005-11-22 18:00:56Z alexey $
++%%%----------------------------------------------------------------------
++
++-module(proxy65_listener).
++-author('henoch@dtek.chalmers.se').
++-vsn('$Revision$ ').
++
++-export([start/2, handle_connection/2, activate/3]).
++
++-include("ejabberd.hrl").
++-include("jlib.hrl").
++
++-record(proxy65_connection, {cookie, firstpid = none, secondpid = none}).
++
++start({SockMod, Socket}, Opts) ->
++ {ok, proc_lib:spawn(?MODULE, handle_connection, [{SockMod, Socket}, Opts])}.
++
++read_bytes(_SockOpts, 0, Data) ->
++ lists:flatten(Data);
++read_bytes({SockMod, Socket} = SockOpts, N, Data) ->
++ Timeout = 1000,
++ case SockMod:recv(Socket, N, Timeout) of
++ {error, closed} ->
++ %% On closed connection, return everything we have,
++ %% but not if we have nothing.
++ if Data == [] ->
++ erlang:error(closed);
++ true ->
++ lists:flatten(Data)
++ end;
++ {ok, MoreData} ->
++ ?DEBUG("read ~p", [MoreData]),
++ DataList = binary_to_list(MoreData),
++ read_bytes(SockOpts, N - length(DataList), [Data, DataList])
++ end.
++
++handle_connection({SockMod, Socket}, Opts) ->
++ ?DEBUG("in handle_connection", []),
++ case catch handle_auth({SockMod, Socket}, Opts) of
++ {'EXIT', Reason} ->
++ ?ERROR_MSG("~p abnormal termination:~n\t~p~n",
++ [?MODULE, Reason]),
++ SockMod:close(Socket);
++ _ ->
++ ok
++ end.
++
++handle_auth({SockMod, Socket} = SockOpts, Opts) ->
++ ?DEBUG("in handle_auth", []),
++ %% SOCKS protocol stuff...
++ [5, NAuthMethods] = read_bytes(SockOpts, 2, []),
++ AuthMethods = read_bytes(SockOpts, NAuthMethods, []),
++ SupportsNoAuth = lists:member(0, AuthMethods),
++
++ %% Must support no authentication, otherwise crash
++ true = SupportsNoAuth,
++
++ SockMod:send(Socket, [5, 0]),
++
++ %% And done.
++ handle_connect(SockOpts, Opts).
++
++handle_connect({SockMod, Socket} = SockOpts, Opts) ->
++ ?DEBUG("in handle_connect", []),
++ %% Expect a CONNECT command and nothing else
++ [5, 1, _, 3, AddressLength] = read_bytes(SockOpts, 5, []),
++ Cookie = read_bytes(SockOpts, AddressLength, []),
++ [0, 0] = read_bytes(SockOpts, 2, []),
++
++ %% Make sure no more than two connections claim the same cookie.
++ F = fun() ->
++ case mnesia:read({proxy65_connection, Cookie}) of
++ [] ->
++ mnesia:write(#proxy65_connection{cookie = Cookie,
++ firstpid = self()}),
++ ok;
++ [#proxy65_connection{secondpid = none} = C] ->
++ mnesia:write(C#proxy65_connection{secondpid = self()}),
++ ok
++ end
++ end,
++
++ case mnesia:transaction(F) of
++ {atomic, ok} ->
++ SockMod:send(Socket, [5, 0, 0, 3, AddressLength, Cookie, 0, 0]),
++ wait_for_activation(SockOpts, Opts);
++ Error ->
++ %% conflict. send "general SOCKS server failure".
++ SockMod:send(Socket, [5, 1, 0, 3, AddressLength, Cookie, 0, 0]),
++ erlang:error({badconnect, Error})
++ end.
++
++wait_for_activation(SockOpts, Opts) ->
++ ?DEBUG("in wait_for_activation", []),
++ receive
++ {get_socket, ReplyTo} ->
++ ReplyTo ! SockOpts,
++ wait_for_activation(SockOpts, Opts);
++ {activate, TargetSocket, Initiator, Target} ->
++ ?DEBUG("activated", []),
++
++ %% We have no way of knowing which connection belongs to
++ %% which participant, so give both the maximum traffic
++ %% allowed to either.
++ Shapers = case lists:keysearch(shaper, 1, Opts) of
++ {value, {_, S}} -> S;
++ _ -> none
++ end,
++ ?DEBUG("we have shapers: ~p", [Shapers]),
++ Shaper1 = acl:match_rule(global, Shapers, jlib:string_to_jid(Initiator)),
++ Shaper2 = acl:match_rule(global, Shapers, jlib:string_to_jid(Target)),
++ if Shaper1 == none; Shaper2 == none ->
++ MaxShaper = none;
++ true ->
++ ShaperValue1 = ejabberd_config:get_global_option({shaper, Shaper1}),
++ ShaperValue2 = ejabberd_config:get_global_option({shaper, Shaper2}),
++
++ if ShaperValue1 > ShaperValue2 ->
++ MaxShaper = Shaper1;
++ true ->
++ MaxShaper = Shaper2
++ end,
++ ?DEBUG("shapers have values ~p and ~p~nusing ~p", [ShaperValue1, ShaperValue2, MaxShaper]),
++ ok
++ end,
++
++ transfer_data(SockOpts, TargetSocket, shaper:new(MaxShaper))
++ end.
++
++transfer_data({SockMod, Socket} = SockOpts, {TargetSockMod, TargetSocket} = TargetSockOpts,
++ Shaper) ->
++ case SockMod:recv(Socket, 0, infinity) of
++ {ok, Data} ->
++ if Data /= <<>> ->
++ NewShaper = case Shaper of
++ none -> none;
++ _ ->
++ shaper:update(Shaper, size(Data))
++ end,
++ ok = TargetSockMod:send(TargetSocket, Data);
++ true ->
++ NewShaper = Shaper
++ end,
++ transfer_data(SockOpts, TargetSockOpts, NewShaper);
++ {error, _} ->
++ TargetSockMod:shutdown(TargetSocket, read_write)
++ end.
++
++get_socket(PID) ->
++ PID ! {get_socket, self()},
++ receive
++ {_SockMod, _Socket} = SockOpts ->
++ SockOpts
++ end.
++
++%% If any argument is a jid record, convert it to normalized string form...
++activate(#jid{} = Initiator, Target, SessionID) ->
++ NormalizedInitiator = jlib:jid_to_string(jlib:make_jid(jlib:jid_tolower(Initiator))),
++ activate(NormalizedInitiator, Target, SessionID);
++activate(Initiator, #jid{} = Target, SessionID) ->
++ NormalizedTarget = jlib:jid_to_string(jlib:make_jid(jlib:jid_tolower(Target))),
++ activate(Initiator, NormalizedTarget, SessionID);
++%% ...and get on with the activation.
++activate(Initiator, Target, SessionID) ->
++ Cookie = sha:sha(SessionID ++ Initiator ++ Target),
++ F = fun() ->
++ case mnesia:read({proxy65_connection, Cookie}) of
++ [#proxy65_connection{firstpid = FirstPID,
++ secondpid = SecondPID}]
++ when is_pid(FirstPID), is_pid(SecondPID) ->
++ mnesia:delete({proxy65_connection, Cookie}),
++ {FirstPID, SecondPID};
++ _ ->
++ error
++ end
++ end,
++ case mnesia:transaction(F) of
++ {atomic, {FirstPID, SecondPID}} ->
++ FirstSocket = get_socket(FirstPID),
++ SecondSocket = get_socket(SecondPID),
++ FirstPID ! {activate, SecondSocket, Initiator, Target},
++ SecondPID ! {activate, FirstSocket, Initiator, Target},
++ ok;
++ Error ->
++ ?ERROR_MSG("Proxy activation failed: ~p", [Error]),
++ error
++ end.
diff --git a/net-im/ejabberd/files/ejabberd-1.1.2-statsdx-web.patch b/net-im/ejabberd/files/ejabberd-1.1.2-statsdx-web.patch
new file mode 100644
index 00000000..2182fb04
--- /dev/null
+++ b/net-im/ejabberd/files/ejabberd-1.1.2-statsdx-web.patch
@@ -0,0 +1,318 @@
+--- ejabberd-1.1.1/src/web/ejabberd_web_admin.erl 2006-04-03 16:14:35.000000000 +0200
++++ ejabberd-1.1.1-r1/src/web/ejabberd_web_admin.erl 2006-06-23 09:32:54.000000000 +0200
+@@ -905,7 +905,10 @@
+ path = ["stats"],
+ q = Query,
+ lang = Lang} = Request) ->
+- Res = get_stats(Host, Lang),
++ Res = case whereis(ejabberd_mod_statsdx) of
++ undefined -> get_stats(Host, Lang);
++ _ -> get_statsdx(Host, Lang)
++ end,
+ make_xhtml([?XCT("h1", "Statistics")] ++ Res, Host, Lang);
+
+ process_admin(Host,
+@@ -1397,6 +1400,165 @@
+ ])].
+
+
++get_statsdx(global, Lang) ->
++ [
++ ?XC("h3", "Accounts"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "registeredusers")
++ ])
++ ]),
++ ?XC("h3", "Roster"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "totalrosteritems"),
++ do_stat(global, Lang, "meanitemsinroster")
++ ])
++ ]),
++ ?XC("h3", "Users"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "authusers"),
++ do_stat(global, Lang, "onlineusers"),
++ do_stat(global, Lang, "offlinemsg"),
++ do_stat(global, Lang, "vcards")
++ ])
++ ]),
++ ?XC("h3", "MUC"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "totalmucrooms"),
++ do_stat(global, Lang, "permmucrooms"),
++ do_stat(global, Lang, "regmucrooms")
++ ])
++ ]),
++ ?XC("h3", "Pub/Sub"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "regpubsubnodes")
++ ])
++ ]),
++ ?XC("h3", "IRC"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "ircconns")
++ ])
++ ]),
++ ?XC("h3", "Ratios"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ ])
++ ]),
++ ?XC("h3", "Sessions: " ++ get_stat_n("client")),
++ ?XAE("table", [],
++ [?XE("tbody",
++ do_stat_table(global, Lang, "client", server)
++ )
++ ]),
++ ?XC("h3", "Sessions: " ++ get_stat_n("os")),
++ ?XAE("table", [],
++ [?XE("tbody",
++ do_stat_table(global, Lang, "os", server)
++ )
++ ]),
++ ?XC("h3", "Sessions: " ++ get_stat_n("client") ++ "/" ++ get_stat_n("os")),
++ ?XAE("table", [],
++ [?XE("tbody",
++ do_stat_table(global, Lang, "client_os", server)
++ )
++ ]),
++ ?XC("h3", "Sessions: " ++ get_stat_n("languages")),
++ ?XAE("table", [],
++ [?XE("tbody",
++ do_stat_table(global, Lang, "languages", server)
++ )
++ ])
++ ];
++
++get_statsdx(Host, Lang) ->
++ [
++ ?XC("h2", Host),
++ ?XC("h3", "Accounts"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "registeredusers", Host)
++ ])
++ ]),
++ ?XC("h3", "Roster"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "totalrosteritems", Host),
++ do_stat(global, Lang, "meanitemsinroster", Host)
++ ])
++ ]),
++ ?XC("h3", "Users"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "authusers", Host),
++ do_stat(global, Lang, "onlineusers", Host),
++ do_stat(global, Lang, "offlinemsg", Host),
++ do_stat(global, Lang, "vcards", Host)
++ ])
++ ]),
++ ?XC("h3", "Connections"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "s2sconnections", Host)
++ ])
++ ]),
++ ?XC("h3", "MUC"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "totalmucrooms", Host),
++ do_stat(global, Lang, "permmucrooms", Host),
++ do_stat(global, Lang, "regmucrooms", Host)
++ ])
++ ]),
++ ?XC("h3", "IRC"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "ircconns", Host)
++ ])
++ ]),
++ %?XC("h3", "Pub/Sub"),
++ %?XAE("table", [],
++ % [?XE("tbody", [
++ % do_stat(global, Lang, "regpubsubnodes", Host)
++ % ])
++ %]),
++ ?XC("h3", "Ratios"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ ])
++ ]),
++ ?XC("h3", "Sessions: " ++ get_stat_n("client")),
++ ?XAE("table", [],
++ [?XE("tbody",
++ do_stat_table(global, Lang, "client", Host)
++ )
++ ]),
++ ?XC("h3", "Sessions: " ++ get_stat_n("os")),
++ ?XAE("table", [],
++ [?XE("tbody",
++ do_stat_table(global, Lang, "os", Host)
++ )
++ ]),
++ ?XC("h3", "Sessions: " ++ get_stat_n("client") ++ "/" ++ get_stat_n("os")),
++ ?XAE("table", [],
++ [?XE("tbody",
++ do_stat_table(global, Lang, "client_os", Host)
++ )
++ ]),
++ ?XC("h3", "Sessions: " ++ get_stat_n("languages")),
++ ?XAE("table", [],
++ [?XE("tbody",
++ do_stat_table(global, Lang, "languages", Host)
++ )
++ ])
++ ].
++
++
++
+ list_online_users(Host, _Lang) ->
+ Users = [{S, U} || {U, S, R} <- ejabberd_sm:get_vh_session_list(Host)],
+ SUsers = lists:usort(Users),
+@@ -2015,6 +2177,12 @@
+ ];
+
+ get_node(global, Node, ["stats"], Query, Lang) ->
++ Res = case whereis(ejabberd_mod_statsdx) of
++ undefined -> get_node(global, Node, ["statslight"], Query, Lang);
++ _ -> get_node(global, Node, ["statsdx"], Query, Lang)
++ end;
++
++get_node(global, Node, ["statslight"], Query, Lang) ->
+ UpTime = rpc:call(Node, erlang, statistics, [wall_clock]),
+ UpTimeS = io_lib:format("~.3f", [element(1, UpTime)/1000]),
+ CPUTime = rpc:call(Node, erlang, statistics, [runtime]),
+@@ -2089,9 +2257,124 @@
+ ?XCT("h3", "Script check"), ?C(atom_to_list(Check))])
+ ];
+
++get_node(global, Node, ["statsdx"], Query, Lang) ->
++ TransactionsCommited =
++ rpc:call(Node, mnesia, system_info, [transaction_commits]),
++ TransactionsAborted =
++ rpc:call(Node, mnesia, system_info, [transaction_failures]),
++ TransactionsRestarted =
++ rpc:call(Node, mnesia, system_info, [transaction_restarts]),
++ TransactionsLogged =
++ rpc:call(Node, mnesia, system_info, [transaction_log_writes]),
++
++ [?XC("h1", io_lib:format(?T("~p statistics"), [Node])),
++ ?XC("h3", "Connections"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(global, Lang, "authusers"),
++ do_stat(Node, Lang, "httppollusers"),
++ do_stat(Node, Lang, "s2sconnections"),
++ do_stat(Node, Lang, "s2sservers")
++ ])
++ ]),
++ ?XC("h3", "Erlang"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(Node, Lang, "operatingsystem"),
++ do_stat(Node, Lang, "erlangmachine"),
++ do_stat(Node, Lang, "erlangmachinetarget"),
++ do_stat(Node, Lang, "maxprocallowed"),
++ do_stat(Node, Lang, "procqueue"),
++ do_stat(Node, Lang, "totalerlproc")
++ ])
++ ]),
++ ?XC("h3", "Times"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(Node, Lang, "uptime"),
++ do_stat(Node, Lang, "uptimehuman"),
++ do_stat(Node, Lang, "lastrestart"),
++ do_stat(Node, Lang, "cputime")
++ ])
++ ]),
++ ?XC("h3", "CPU"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ do_stat(Node, Lang, "cpu_avg1"),
++ do_stat(Node, Lang, "cpu_avg5"),
++ do_stat(Node, Lang, "cpu_avg15"),
++ do_stat(Node, Lang, "cpu_nprocs")%,
++ %do_stat(Node, Lang, "cpu_util_user"),
++ %do_stat(Node, Lang, "cpu_nice_user"),
++ %do_stat(Node, Lang, "cpu_kernel"),
++ %do_stat(Node, Lang, "cpu_idle"),
++ %do_stat(Node, Lang, "cpu_wait")
++ ])
++ ]),
++ %?XC("h3", "RAM"),
++ %?XAE("table", [],
++ % [?XE("tbody", [
++ %do_stat(Node, Lang, "memsup_system"),
++ %do_stat(Node, Lang, "memsup_free"),
++ %do_stat(Node, Lang, "reductions")
++ % ])
++ % ]),
++ ?XC("h3", "Database"),
++ ?XAE("table", [],
++ [?XE("tbody", [
++ ?XE("tr", [?XCT("td", "Transactions commited"),
++ ?XAC("td", [{"class", "alignright"}],
++ integer_to_list(TransactionsCommited))]),
++ ?XE("tr", [?XCT("td", "Transactions aborted"),
++ ?XAC("td", [{"class", "alignright"}],
++ integer_to_list(TransactionsAborted))]),
++ ?XE("tr", [?XCT("td", "Transactions restarted"),
++ ?XAC("td", [{"class", "alignright"}],
++ integer_to_list(TransactionsRestarted))]),
++ ?XE("tr", [?XCT("td", "Transactions logged"),
++ ?XAC("td", [{"class", "alignright"}],
++ integer_to_list(TransactionsLogged))])
++ ])
++ ])];
++
+ get_node(Host, Node, NPath, Query, Lang) ->
+ [?XCT("h1", "Not Found")].
+
++do_table_element(Lang, L, N) ->
++ ?XE("tr", [
++ ?XCT("td", L),
++ ?XAC("td", [{"class", "alignright"}],
++ N)
++ ]).
++
++do_stat_table(global, Lang, Stat, Host) ->
++ Os = mod_statsdx:get(global, [Stat, Host]),
++ lists:map(
++ fun({L, N}) ->
++ do_table_element(Lang, L, io_lib:format("~p", [N]))
++ end,
++ Os
++ ).
++
++do_stat(Node, Lang, Stat) ->
++ ?XE("tr", [
++ ?XCT("td", get_stat_n(Stat)),
++ ?XAC("td", [{"class", "alignright"}],
++ get_stat_v(Node, [Stat]))]).
++
++do_stat(Node, Lang, Stat, Host) ->
++ %[Res] = get_stat_v(Node, [Stat, Host]),
++ %do_table_element(Lang, get_stat_n(Stat), Res).
++ do_table_element(Lang, get_stat_n(Stat), get_stat_v(Node, [Stat, Host])).
++
++% Get a stat name
++get_stat_n(Stat) ->
++ mod_statsdx:get(foo, [Stat, title]).
++% Get a stat value
++get_stat_v(Node, Stat) -> get_stat_v2(mod_statsdx:get(Node, Stat)).
++get_stat_v2(Value) when is_list(Value) -> Value;
++get_stat_v2(Value) when is_float(Value) -> io_lib:format("~.4f", [Value]);
++get_stat_v2(Value) -> io_lib:format("~p", [Value]).
+
+ node_parse_query(Node, Query) ->
+ case lists:keysearch("restart", 1, Query) of
diff --git a/net-im/ejabberd/files/ejabberd-1.1.2-statsdx.patch b/net-im/ejabberd/files/ejabberd-1.1.2-statsdx.patch
new file mode 100644
index 00000000..38383542
--- /dev/null
+++ b/net-im/ejabberd/files/ejabberd-1.1.2-statsdx.patch
@@ -0,0 +1,742 @@
+diff -Naur ejabberd-1.1.1/src/mod_statsdx.erl ejabberd-1.1.1-r1/src/mod_statsdx.erl
+--- ejabberd-1.1.1/src/mod_statsdx.erl 1970-01-01 01:00:00.000000000 +0100
++++ ejabberd-1.1.1-r1/src/mod_statsdx.erl 2006-05-12 23:14:17.000000000 +0200
+@@ -0,0 +1,738 @@
++%%%----------------------------------------------------------------------
++%%% File : mod_statsdx.erl
++%%% Author : Badlop <badlop@ono.com>
++%%% Purpose : Calculates and gathers statistics actively
++%%% Created :
++%%% Id : 0.2.3
++%%%----------------------------------------------------------------------
++
++%%% INSTALL:
++%%% 1 Copy this file to ejabberd/src/mod_statsdx.erl
++%%% 2 Recompile ejabberd
++%%% 3 Add to ejabberd.cfg, 'modules' section the basic configuration:
++%%% {mod_statsdx, []},
++
++%%% CONFIGURE:
++%%% hooks: Set to 'false' to remove hooks and related statistics if you don't need them (default: true)
++
++%%% EXAMPLE CONFIGURATION:
++%%% {mod_statsdx, [{hooks, false}]},
++
++%%% FEATURE REQUESTS:
++%%% - fix the problem with plain/ssl/tlsusers, it crashes ejabberd
++%%% - traffic: send bytes per second, received bps
++%%% - connections to a transport
++%%% - traffic: send presence per second, received mps
++%%% - Number of SASL c2s connections
++%%% - improve to work in distributed server
++
++-module(mod_statsdx).
++-author('').
++-vsn('').
++
++-behaviour(gen_mod).
++
++-export([start/2, loop/0, stop/1, get/2,
++ remove_user/2, user_send_packet/3, user_receive_packet/4,
++ user_login/1, user_logout/4]).
++
++-include("ejabberd.hrl").
++-include("jlib.hrl").
++-include("mod_roster.hrl").
++
++-define(PROCNAME, ejabberd_mod_statsdx).
++-define(T(Text), translate:translate("Lang", Text)).
++
++%% -------------------
++%% Module control
++%% -------------------
++
++start(Host, Opts) ->
++ Hooks = gen_mod:get_opt(hooks, Opts, true),
++ % Default value for the counters
++ CD = case Hooks of
++ true -> 0;
++ false -> "disabled"
++ end,
++ case whereis(?PROCNAME) of
++ undefined ->
++ application:start(os_mon),
++ ets:new(stats, [named_table, public]),
++ ets:insert(stats, {{user_login, server}, CD}),
++ ets:insert(stats, {{user_logout, server}, CD}),
++ ets:insert(stats, {{remove_user, server}, CD}),
++ lists:foreach(
++ fun(E) -> ets:insert(stats, {{client, server, E}, CD}) end,
++ list_elem(clients, id)
++ ),
++ lists:foreach(
++ fun(E) -> ets:insert(stats, {{os, server, E}, CD}) end,
++ list_elem(oss, id)
++ ),
++ register(?PROCNAME, spawn(?MODULE, loop, []));
++ _ ->
++ ok
++ end,
++ ets:insert(stats, {{user_login, Host}, CD}),
++ ets:insert(stats, {{user_logout, Host}, CD}),
++ ets:insert(stats, {{remove_user, Host}, CD}),
++ ets:insert(stats, {{send, Host, iq, in}, CD}),
++ ets:insert(stats, {{send, Host, iq, out}, CD}),
++ ets:insert(stats, {{send, Host, message, in}, CD}),
++ ets:insert(stats, {{send, Host, message, out}, CD}),
++ ets:insert(stats, {{send, Host, presence, in}, CD}),
++ ets:insert(stats, {{send, Host, presence, out}, CD}),
++ ets:insert(stats, {{recv, Host, iq, in}, CD}),
++ ets:insert(stats, {{recv, Host, iq, out}, CD}),
++ ets:insert(stats, {{recv, Host, message, in}, CD}),
++ ets:insert(stats, {{recv, Host, message, out}, CD}),
++ ets:insert(stats, {{recv, Host, presence, in}, CD}),
++ ets:insert(stats, {{recv, Host, presence, out}, CD}),
++ lists:foreach(
++ fun(E) -> ets:insert(stats, {{client, Host, E}, CD}) end,
++ list_elem(clients, id)
++ ),
++ lists:foreach(
++ fun(E) -> ets:insert(stats, {{os, Host, E}, CD}) end,
++ list_elem(oss, id)
++ ),
++ case Hooks of
++ true ->
++ ejabberd_hooks:add(user_send_packet, Host, ?MODULE, user_send_packet, 90),
++ ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, user_receive_packet, 90),
++ ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 90),
++ ejabberd_hooks:add(user_available_hook, Host, ?MODULE, user_login, 90),
++ ejabberd_hooks:add(unset_presence_hook, Host, ?MODULE, user_logout, 90);
++ false ->
++ ok
++ end.
++
++loop() ->
++ receive
++ stop -> ok
++ end.
++
++stop(Host) ->
++ ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, user_send_packet, 60),
++ ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, user_receive_packet, 60),
++ ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 60),
++ ets:delete(stats),
++ case whereis(?PROCNAME) of
++ undefined -> ok;
++ _ ->
++ ?PROCNAME ! stop
++ end.
++
++
++remove_user(_User, Server) ->
++ ets:update_counter(stats, {remove_user, Server}, 1),
++ ets:update_counter(stats, {remove_user, server}, 1).
++
++user_send_packet(FromJID, ToJID, NewEl) ->
++ Host = FromJID#jid.lserver,
++ HostTo = ToJID#jid.lserver,
++ {xmlelement, Type, _, _} = NewEl,
++ Type2 = case Type of
++ "iq" -> iq;
++ "message" -> message;
++ "presence" -> presence
++ end,
++ Dest = case is_host(HostTo, Host) of
++ true -> in;
++ false -> out
++ end,
++ ets:update_counter(stats, {send, Host, Type2, Dest}, 1),
++
++ % Registrarse para tramitar Host/mod_stats2file
++ case list_to_atom(ToJID#jid.lresource) of
++ ?MODULE -> received_response(FromJID, ToJID, NewEl);
++ _ -> ok
++ end.
++
++user_receive_packet(_JID, From, To, FixedPacket) ->
++ HostFrom = From#jid.lserver,
++ Host = To#jid.lserver,
++ {xmlelement, Type, _, _} = FixedPacket,
++ Type2 = case Type of
++ "iq" -> iq;
++ "message" -> message;
++ "presence" -> presence
++ end,
++ Dest = case is_host(HostFrom, Host) of
++ true -> in;
++ false -> out
++ end,
++ ets:update_counter(stats, {recv, Host, Type2, Dest}, 1).
++
++
++%% -------------------
++%% get(*
++%% -------------------
++
++%gett(Arg) -> get(node(), [Arg, title]).
++getl(Args) -> get(node(), [Args]).
++getl(Args, Host) -> get(node(), [Args, Host]).
++
++%get(_Node, ["", title]) -> "";
++
++get(global, A) -> get(node(), A);
++
++get(_, [{"reductions", _}, title]) -> "Reductions (per minute)";
++get(_, [{"reductions", I}]) -> calc_avg(element(2, statistics(reductions)), I); %+++
++
++get(_, ["cpu_avg1", title]) -> "Average system load (1 min)";
++get(N, ["cpu_avg1"]) -> rpc:call(N, cpu_sup, avg1, [])/256;
++get(_, ["cpu_avg5", title]) -> "Average system load (5 min)";
++get(N, ["cpu_avg5"]) -> rpc:call(N, cpu_sup, avg1, [])/256;
++get(_, ["cpu_avg15", title]) -> "Average system load (15 min)";
++get(N, ["cpu_avg15"]) -> rpc:call(N, cpu_sup, avg15, [])/256;
++get(_, ["cpu_nprocs", title]) -> "Number of UNIX processes running on this machine";
++get(N, ["cpu_nprocs"]) -> rpc:call(N, cpu_sup, nprocs, []);
++get(_, ["cpu_util", title]) -> "CPU utilization";
++get(N, ["cpu_util"]) -> rpc:call(N, cpu_sup, util, []);
++
++get(_, [{"cpu_util_user", _}, title]) -> "CPU utilization - user";
++get(_, [{"cpu_util_nice_user", _}, title]) -> "CPU utilization - nice_user";
++get(_, [{"cpu_util_kernel", _}, title]) -> "CPU utilization - kernel";
++get(_, [{"cpu_util_wait", _}, title]) -> "CPU utilization - wait";
++get(_, [{"cpu_util_idle", _}, title]) -> "CPU utilization - idle";
++get(_, [{"cpu_util_user", U}]) -> [{user, Us}, _, _] = element(2, U), Us;
++get(_, [{"cpu_util_nice_user", U}]) -> [_, {nice_user, NU}, _] = element(2, U), NU;
++get(_, [{"cpu_util_kernel", U}]) -> [_, _, {kernel, K}] = element(2, U), K;
++get(_, [{"cpu_util_wait", U}]) ->
++ case element(3, U) of
++ [{wait, W}, {idle, _}] -> W; % Solaris
++ [{idle, _}] -> 0
++ end;
++get(_, [{"cpu_util_idle", U}]) ->
++ case element(3, U) of
++ [{wait, _}, {idle, I}] -> I; % Solaris
++ [{idle, I}] -> I
++ end;
++
++get(_, [{"client", Id}, title]) -> atom_to_list(Id);
++get(_, [{"client", Id}, Host]) -> [{_, C}] = ets:lookup(stats, {client, Host, Id}), C;
++get(_, ["client", title]) -> "Client";
++get(N, ["client", Host]) ->
++ lists:map(
++ fun(Id) ->
++ [Id_string] = io_lib:format("~p", [Id]),
++ {Id_string, get(N, [{"client", Id}, Host])}
++ end,
++ lists:usort(list_elem(clients, id))
++ );
++
++get(_, [{"os", Id}, title]) -> atom_to_list(Id);
++get(_, [{"os", Id}, list]) -> lists:usort(list_elem(oss, Id));
++get(_, [{"os", Id}, Host]) -> [{_, C}] = ets:lookup(stats, {os, Host, Id}), C;
++get(_, ["os", title]) -> "Operating System";
++get(N, ["os", Host]) ->
++ lists:map(
++ fun(Id) ->
++ [Id_string] = io_lib:format("~p", [Id]),
++ {Id_string, get(N, [{"os", Id}, Host])}
++ end,
++ lists:usort(list_elem(oss, id))
++ );
++
++get(_, [{"memsup_system", _}, title]) -> "Memory physical (bytes)";
++get(_, [{"memsup_system", M}]) -> [_, _, {system_total_memory, R}] = M, R;
++get(_, [{"memsup_free", _}, title]) -> "Memory free (bytes)";
++get(_, [{"memsup_free", M}]) -> [_, {free_memory, R}, _] = M, R;
++
++get(_, [{"user_login", _}, title]) -> "Logins (per minute)";
++get(_, [{"user_login", I}, Host]) -> get_stat({user_login, Host}, I);
++get(_, [{"user_logout", _}, title]) -> "Logouts (per minute)";
++get(_, [{"user_logout", I}, Host]) -> get_stat({user_logout, Host}, I);
++get(_, [{"remove_user", _}, title]) -> "Accounts deleted (per minute)";
++get(_, [{"remove_user", I}, Host]) -> get_stat({remove_user, Host}, I);
++get(_, [{Table, Type, Dest, _}, title]) -> filename:flatten([Table, Type, Dest]);
++get(_, [{Table, Type, Dest, I}, Host]) -> get_stat({Table, Host, Type, Dest}, I);
++
++get(_, ["localtime", title]) -> "Local time";
++get(N, ["localtime"]) ->
++ localtime_to_string(rpc:call(N, erlang, localtime, []));
++
++get(_, ["vhost", title]) -> "Virtual host";
++get(_, ["vhost", Host]) -> Host;
++
++get(_, ["totalerlproc", title]) -> "Total Erlang processes running";
++get(N, ["totalerlproc"]) -> rpc:call(N, erlang, system_info, [process_count]);
++get(_, ["operatingsystem", title]) -> "Operating System";
++get(N, ["operatingsystem"]) -> {rpc:call(N, os, type, []), rpc:call(N, os, version, [])};
++get(_, ["erlangmachine", title]) -> "Erlang machine";
++get(N, ["erlangmachine"]) -> rpc:call(N, erlang, system_info, [system_version]);
++get(_, ["erlangmachinetarget", title]) -> "Erlang machine target";
++get(N, ["erlangmachinetarget"]) -> rpc:call(N, erlang, system_info, [system_architecture]);
++get(_, ["maxprocallowed", title]) -> "Maximum processes allowed";
++get(N, ["maxprocallowed"]) -> rpc:call(N, erlang, system_info, [process_limit]);
++get(_, ["procqueue", title]) -> "Number of processes on the running queue";
++get(N, ["procqueue"]) -> rpc:call(N, erlang, statistics, [run_queue]);
++get(_, ["uptimehuman", title]) -> "Uptime";
++get(N, ["uptimehuman"]) ->
++ io_lib:format("~w days ~w hours ~w minutes ~p seconds", ms_to_time(get(N, ["uptime"])));
++get(_, ["lastrestart", title]) -> "Last restart";
++get(N, ["lastrestart"]) ->
++ Now = calendar:datetime_to_gregorian_seconds(rpc:call(N, erlang, localtime, [])),
++ UptimeMS = get(N, ["uptime"]),
++ Last_restartS = trunc(Now - (UptimeMS/1000)),
++ Last_restart = calendar:gregorian_seconds_to_datetime(Last_restartS),
++ localtime_to_string(Last_restart);
++
++get(_, ["plainusers", title]) -> "Plain users";
++get(_, ["plainusers"]) -> {R, _, _} = get_connectiontype(), R;
++get(_, ["tlsusers", title]) -> "TLS users";
++get(_, ["tlsusers"]) -> {_, R, _} = get_connectiontype(), R;
++get(_, ["sslusers", title]) -> "SSL users";
++get(_, ["sslusers"]) -> {_, _, R} = get_connectiontype(), R;
++get(_, ["registeredusers", title]) -> "Registered users";
++get(N, ["registeredusers"]) -> rpc:call(N, mnesia, table_info, [passwd, size]);
++get(_, ["registeredusers", Host]) -> length(ejabberd_auth:get_vh_registered_users(Host));
++get(_, ["authusers", title]) -> "Authenticated users";
++get(N, ["authusers"]) -> rpc:call(N, mnesia, table_info, [session, size]);
++get(_, ["authusers", Host]) -> get_authusers(Host);
++get(_, ["onlineusers", title]) -> "Online users";
++get(N, ["onlineusers"]) -> rpc:call(N, mnesia, table_info, [presence, size]);
++get(_, ["onlineusers", Host]) -> length(ejabberd_sm:get_vh_session_list(Host));
++get(_, ["httppollusers", title]) -> "HTTP-Poll users (aprox)";
++get(N, ["httppollusers"]) -> rpc:call(N, mnesia, table_info, [http_poll, size]);
++
++get(_, ["s2sconnections", title]) -> "Outgoing S2S connections";
++get(_, ["s2sconnections"]) -> length(get_S2SConns());
++get(_, ["s2sconnections", Host]) -> get_s2sconnections(Host);
++get(_, ["s2sservers", title]) -> "Outgoing S2S servers";
++get(_, ["s2sservers"]) -> length(lists:usort([element(2, C) || C <- get_S2SConns()]));
++
++get(_, ["offlinemsg", title]) -> "Offline messages";
++get(N, ["offlinemsg"]) -> rpc:call(N, mnesia, table_info, [offline_msg, size]);
++get(_, ["offlinemsg", Host]) -> get_offlinemsg(Host);
++get(_, ["totalrosteritems", title]) -> "Total roster items";
++get(N, ["totalrosteritems"]) -> rpc:call(N, mnesia, table_info, [roster, size]);
++get(_, ["totalrosteritems", Host]) -> get_totalrosteritems(Host);
++
++get(_, ["meanitemsinroster", title]) -> "Mean items in roster";
++get(_, ["meanitemsinroster"]) -> get_meanitemsinroster();
++get(_, ["meanitemsinroster", Host]) -> get_meanitemsinroster(Host);
++
++get(_, ["totalmucrooms", title]) -> "Total MUC rooms";
++get(_, ["totalmucrooms"]) -> ets:info(muc_online_room, size);
++get(_, ["totalmucrooms", Host]) -> get_totalmucrooms(Host);
++get(_, ["permmucrooms", title]) -> "Permanent MUC rooms";
++get(N, ["permmucrooms"]) -> rpc:call(N, mnesia, table_info, [muc_room, size]);
++get(_, ["permmucrooms", Host]) -> get_permmucrooms(Host);
++get(_, ["regmucrooms", title]) -> "Users registered at MUC service";
++get(N, ["regmucrooms"]) -> rpc:call(N, mnesia, table_info, [muc_registered, size]);
++get(_, ["regmucrooms", Host]) -> get_regmucrooms(Host);
++get(_, ["regpubsubnodes", title]) -> "Registered nodes at Pub/Sub";
++get(N, ["regpubsubnodes"]) -> rpc:call(N, mnesia, table_info, [pubsub_node, size]);
++get(_, ["vcards", title]) -> "Total vCards published";
++get(N, ["vcards"]) -> rpc:call(N, mnesia, table_info, [vcard, size]);
++get(_, ["vcards", Host]) -> get_vcards(Host);
++
++get(_, ["ircconns", title]) -> "IRC connections";
++get(_, ["ircconns"]) -> ets:info(irc_connection, size);
++get(_, ["ircconns", Host]) -> get_irccons(Host);
++get(_, ["uptime", title]) -> "Uptime";
++get(N, ["uptime"]) -> element(1, rpc:call(N, erlang, statistics, [wall_clock]));
++get(_, ["cputime", title]) -> "CPU Time";
++get(N, ["cputime"]) -> element(1, rpc:call(N, erlang, statistics, [runtime]));
++
++get(_, ["languages", title]) -> "Languages";
++get(_, ["languages", Server]) -> get_languages(Server);
++
++get(_, ["client_os", title]) -> "Client/OS";
++get(_, ["client_os", Server]) -> get_client_os(Server);
++
++get(N, A) ->
++ io:format(" ----- node: '~p', A: '~p'~n", [N, A]),
++ "666".
++
++%% -------------------
++%% get_*
++%% -------------------
++
++get_S2SConns() -> ejabberd_s2s:dirty_get_connections().
++
++get_tls_drv() ->
++ R = lists:filter(
++ fun(P) ->
++ case erlang:port_info(P, name) of
++ {name, "tls_drv"} -> true;
++ _ -> false
++ end
++ end, erlang:ports()),
++ length(R).
++
++get_connections(Port) ->
++ R = lists:filter(
++ fun(P) ->
++ case inet:port(P) of
++ {ok, Port} -> true;
++ _ -> false
++ end
++ end, erlang:ports()),
++ length(R).
++
++get_totalrosteritems(Host) ->
++ F = fun() ->
++ F2 = fun(R, {H, A}) ->
++ {_LUser, LServer, _LJID} = R#roster.usj,
++ A2 = case LServer of
++ H -> A+1;
++ _ -> A
++ end,
++ {H, A2}
++ end,
++ mnesia:foldl(F2, {Host, 0}, roster)
++ end,
++ {atomic, {Host, Res}} = mnesia:transaction(F),
++ Res.
++
++% Copied from ejabberd_sm.erl
++-record(session, {sid, usr, us, priority}).
++
++get_authusers(Host) ->
++ F = fun() ->
++ F2 = fun(R, {H, A}) ->
++ {_LUser, LServer, _LResource} = R#session.usr,
++ A2 = case LServer of
++ H -> A+1;
++ _ -> A
++ end,
++ {H, A2}
++ end,
++ mnesia:foldl(F2, {Host, 0}, session)
++ end,
++ {atomic, {Host, Res}} = mnesia:transaction(F),
++ Res.
++
++-record(offline_msg, {us, timestamp, expire, from, to, packet}).
++
++get_offlinemsg(Host) ->
++ F = fun() ->
++ F2 = fun(R, {H, A}) ->
++ {_LUser, LServer} = R#offline_msg.us,
++ A2 = case LServer of
++ H -> A+1;
++ _ -> A
++ end,
++ {H, A2}
++ end,
++ mnesia:foldl(F2, {Host, 0}, offline_msg)
++ end,
++ {atomic, {Host, Res}} = mnesia:transaction(F),
++ Res.
++
++-record(vcard, {us, vcard}).
++
++get_vcards(Host) ->
++ F = fun() ->
++ F2 = fun(R, {H, A}) ->
++ {_LUser, LServer} = R#vcard.us,
++ A2 = case LServer of
++ H -> A+1;
++ _ -> A
++ end,
++ {H, A2}
++ end,
++ mnesia:foldl(F2, {Host, 0}, vcard)
++ end,
++ {atomic, {Host, Res}} = mnesia:transaction(F),
++ Res.
++
++-record(s2s, {fromto, pid, key}).
++
++get_s2sconnections(Host) ->
++ F = fun() ->
++ F2 = fun(R, {H, A}) ->
++ {MyServer, _Server} = R#s2s.fromto,
++ A2 = case MyServer of
++ H -> A+1;
++ _ -> A
++ end,
++ {H, A2}
++ end,
++ mnesia:foldl(F2, {Host, 0}, s2s)
++ end,
++ {atomic, {Host, Res}} = mnesia:transaction(F),
++ Res.
++
++-record(irc_connection, {jid_server_host, pid}).
++
++get_irccons(Host) ->
++ F2 = fun(R, {H, A}) ->
++ {From, _Server, _Host} = R#irc_connection.jid_server_host,
++ A2 = case From#jid.lserver of
++ H -> A+1;
++ _ -> A
++ end,
++ {H, A2}
++ end,
++ {Host, Res} = ets:foldl(F2, {Host, 0}, irc_connection),
++ Res.
++
++is_host(Host, Subhost) ->
++ Pos = string:len(Host)-string:len(Subhost)+1,
++ case string:rstr(Host, Subhost) of
++ Pos -> true;
++ _ -> false
++ end.
++
++-record(muc_online_room, {name_host, pid}).
++
++get_totalmucrooms(Host) ->
++ F2 = fun(R, {H, A}) ->
++ {_Name, MUCHost} = R#muc_online_room.name_host,
++ A2 = case is_host(MUCHost, H) of
++ true -> A+1;
++ false -> A
++ end,
++ {H, A2}
++ end,
++ {Host, Res} = ets:foldl(F2, {Host, 0}, muc_online_room),
++ Res.
++
++-record(muc_room, {name_host, opts}).
++
++get_permmucrooms(Host) ->
++ F = fun() ->
++ F2 = fun(R, {H, A}) ->
++ {_Name, MUCHost} = R#muc_room.name_host,
++ A2 = case is_host(MUCHost, H) of
++ true -> A+1;
++ false -> A
++ end,
++ {H, A2}
++ end,
++ mnesia:foldl(F2, {Host, 0}, muc_room)
++ end,
++ {atomic, {Host, Res}} = mnesia:transaction(F),
++ Res.
++
++-record(muc_registered, {us_host, nick}).
++
++get_regmucrooms(Host) ->
++ F = fun() ->
++ F2 = fun(R, {H, A}) ->
++ {_User, MUCHost} = R#muc_registered.us_host,
++ A2 = case is_host(MUCHost, H) of
++ true -> A+1;
++ false -> A
++ end,
++ {H, A2}
++ end,
++ mnesia:foldl(F2, {Host, 0}, muc_registered)
++ end,
++ {atomic, {Host, Res}} = mnesia:transaction(F),
++ Res.
++
++get_stat(Stat, Ims) ->
++ Res = ets:lookup(stats, Stat),
++ ets:update_counter(stats, Stat, {2,1,0,0}),
++ [{_, C}] = Res,
++ calc_avg(C, Ims).
++ %C.
++
++calc_avg(Count, TimeMS) ->
++ TimeMIN = TimeMS/(1000*60),
++ Count/TimeMIN.
++
++%% -------------------
++%% utilities
++%% -------------------
++
++get_connectiontype() ->
++ C2 = get_connections(5222) -1,
++ C3 = get_connections(5223) -1,
++ NUplain = C2 + C3 - get_tls_drv(),
++ NUtls = C2 - NUplain,
++ NUssl = C3,
++ {NUplain, NUtls, NUssl}.
++
++ms_to_time(T) ->
++ DMS = 24*60*60*1000,
++ HMS = 60*60*1000,
++ MMS = 60*1000,
++ SMS = 1000,
++ D = trunc(T/DMS),
++ H = trunc((T - (D*DMS)) / HMS),
++ M = trunc((T - (D*DMS) - (H*HMS)) / MMS),
++ S = trunc((T - (D*DMS) - (H*HMS) - (M*MMS)) / SMS),
++ [D, H, M, S].
++
++
++% Cuando un usuario conecta, pedirle iq:version a nombre de Host/mod_stats2file
++user_login(U) ->
++ User = U#jid.luser,
++ Host = U#jid.lserver,
++ Resource = U#jid.lresource,
++ ets:update_counter(stats, {user_login, server}, 1),
++ ets:update_counter(stats, {user_login, Host}, 1),
++ request_iqversion(User, Host, Resource).
++
++% cuando un usuario desconecta, buscar en la tabla su JID/USR y quitarlo
++user_logout(User, Host, Resource, _Status) ->
++ ets:update_counter(stats, {user_logout, server}, 1),
++ ets:update_counter(stats, {user_logout, Host}, 1),
++
++ JID = jlib:make_jid(User, Host, Resource),
++ case ets:lookup(stats, {session, JID}) of
++ [{_, Client_id, OS_id, Lang}] ->
++ ets:delete(stats, {session, JID}),
++ ets:update_counter(stats, {client, Host, Client_id}, -1),
++ ets:update_counter(stats, {client, server, Client_id}, -1),
++ ets:update_counter(stats, {os, Host, OS_id}, -1),
++ ets:update_counter(stats, {os, server, OS_id}, -1),
++ update_counter_create(stats, {client_os, Host, Client_id, OS_id}, -1),
++ update_counter_create(stats, {client_os, server, Client_id, OS_id}, -1),
++ update_counter_create(stats, {lang, Host, Lang}, -1),
++ update_counter_create(stats, {lang, server, Lang}, -1);
++ [] ->
++ ok
++ end.
++
++request_iqversion(User, Host, Resource) ->
++ From = jlib:make_jid("", Host, atom_to_list(?MODULE)),
++ FromStr = jlib:jid_to_string(From),
++ To = jlib:make_jid(User, Host, Resource),
++ ToStr = jlib:jid_to_string(To),
++ Packet = {xmlelement,"iq",
++ [{"from",FromStr}, {"to",ToStr}, {"type","get"}, {"xml:lang","es"}],
++ [{xmlcdata,"\n"}, {xmlcdata," "}, {xmlelement, "query", [{"xmlns","jabber:iq:version"}], []}, {xmlcdata,"\n"}]},
++ ejabberd_local:route(From, To, Packet).
++
++% cuando el virtualJID recibe una respuesta iqversion,
++% almacenar su JID/USR + client + OS en una tabla
++received_response(From, _To, {xmlelement, "iq", Attrs, Elc}) ->
++ User = From#jid.luser,
++ Host = From#jid.lserver,
++ Resource = From#jid.lresource,
++
++ "result" = xml:get_attr_s("type", Attrs),
++ Lang = case xml:get_attr_s("xml:lang", Attrs) of
++ [] -> "unknown";
++ L -> L
++ end,
++ update_counter_create(stats, {lang, Host, Lang}, 1),
++ update_counter_create(stats, {lang, server, Lang}, 1),
++
++ [El] = xml:remove_cdata(Elc),
++ {xmlelement, _, Attrs2, _Els2} = El,
++ ?NS_VERSION = xml:get_attr_s("xmlns", Attrs2),
++
++ Client = get_tag_cdata_subtag(El, "name"),
++ %Version = get_tag_cdata_subtag(El, "version"),
++ OS = get_tag_cdata_subtag(El, "os"),
++ {Client_id, OS_id} = identify(Client, OS),
++
++ ets:update_counter(stats, {client, Host, Client_id}, 1),
++ ets:update_counter(stats, {client, server, Client_id}, 1),
++ ets:update_counter(stats, {os, Host, OS_id}, 1),
++ ets:update_counter(stats, {os, server, OS_id}, 1),
++ update_counter_create(stats, {client_os, Host, Client_id, OS_id}, 1),
++ update_counter_create(stats, {client_os, server, Client_id, OS_id}, 1),
++
++ JID = jlib:make_jid(User, Host, Resource),
++ ets:insert(stats, {{session, JID}, Client_id, OS_id, Lang}).
++
++update_counter_create(Table, Element, C) ->
++ case ets:lookup(Table, Element) of
++ [] -> ets:insert(Table, {Element, 1});
++ _ -> ets:update_counter(Table, Element, C)
++ end.
++
++get_tag_cdata_subtag(E, T) ->
++ E2 = xml:get_subtag(E, T),
++ case E2 of
++ false -> "unknown";
++ _ -> xml:get_tag_cdata(E2)
++ end.
++
++list_elem(Type, id) ->
++ {_, Ids} = lists:unzip(list_elem(Type, full)),
++ Ids;
++list_elem(clients, full) ->
++ [
++ {"gaim", gaim},
++ {"Gajim", gajim},
++ {"Tkabber", tkabber},
++ {"Psi", psi},
++ {"Pandion", pandion},
++ {"Kopete", kopete},
++ {"Exodus", exodus},
++ {"libgaim", libgaim},
++ {"JBother", jbother},
++ {"iChat", ichat},
++ {"Miranda", miranda},
++ {"Trillian", trillian},
++ {"JAJC", jajc},
++ {"Coccinella", coccinella},
++ {"Gabber", gabber},
++ {"BitlBee", bitlbee},
++ {"jabber.el", jabberel},
++ {"unknown", unknown}
++ ];
++list_elem(oss, full) ->
++ [
++ {"Linux", linux},
++ {"Win", windows},
++ {"Gentoo", linux},
++ {"Mac", mac},
++ {"BSD", bsd},
++ {"SunOS", linux},
++ {"Ubuntu", linux},
++ {"unknown", unknown}
++ ].
++
++identify(Client, OS) ->
++ Res = {try_match(Client, list_elem(clients, full)), try_match(OS, list_elem(oss, full))},
++ case Res of
++ {libgaim, mac} -> {adium, mac};
++ _ -> Res
++ end.
++
++try_match(_E, []) -> unknown;
++try_match(E, [{Str, Id} | L]) ->
++ case string:str(E, Str) of
++ 0 -> try_match(E, L);
++ _ -> Id
++ end.
++
++get_client_os(Server) ->
++ CO1 = ets:match(stats, {{client_os, Server, '$1', '$2'}, '$3'}),
++ CO2 = lists:map(
++ fun([Cl, Os, A3]) ->
++ {lists:flatten([atom_to_list(Cl), "/", atom_to_list(Os)]), A3}
++ end,
++ CO1
++ ),
++ lists:keysort(1, CO2).
++
++get_languages(Server) ->
++ L1 = ets:match(stats, {{lang, Server, '$1'}, '$2'}),
++ L2 = lists:map(
++ fun([La, C]) ->
++ {La, C}
++ end,
++ L1
++ ),
++ lists:keysort(1, L2).
++
++get_meanitemsinroster() ->
++ get_meanitemsinroster2(getl("totalrosteritems"), getl("registeredusers")).
++get_meanitemsinroster(Host) ->
++ get_meanitemsinroster2(getl("totalrosteritems", Host), getl("registeredusers", Host)).
++get_meanitemsinroster2(Items, Users) ->
++ case Users of
++ 0 -> 0;
++ _ -> Items/Users
++ end.
++
++localtime_to_string({{Y, Mo, D},{H, Mi, S}}) ->
++ lists:concat([H, ":", Mi, ":", S, " ", D, "/", Mo, "/", Y]).
++
++% cuando toque mostrar estadisticas
++%get_iqversion() ->
++ % contar en la tabla cuantos tienen cliente: *psi*
++ %buscar en la tabla iqversion
++ %ok.
diff --git a/net-im/ejabberd/files/ejabberd-1.1.2.initd b/net-im/ejabberd/files/ejabberd-1.1.2.initd
new file mode 100644
index 00000000..4291e39a
--- /dev/null
+++ b/net-im/ejabberd/files/ejabberd-1.1.2.initd
@@ -0,0 +1,59 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-im/ejabberd/files/ejabberd-1.1.1.initd,v 1.1 2006/06/19 14:07:20 chainsaw Exp $
+
+opts="${opts} reload"
+
+depend() {
+ use dns
+ need net
+ provide jabber-server
+}
+
+checkconfig() {
+ if [ ! -e /etc/jabber/ejabberd.cfg ] ; then
+ eerror "You need an /etc/jabber/ejabberd.cfg file to run ejabberd"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting eJabberd"
+ su jabber -c "HOME=/var/run/jabber /usr/bin/ejabberd -noshell -detached"
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping eJabberd"
+ if [ -z "$EJABBERD_NODE" ];
+ then
+ EJABBERD_NODE="ejabberd@`hostname -s`"
+ fi
+ /usr/bin/ejabberdctl $EJABBERD_NODE stop
+ eend $?
+}
+
+# Work around a bug in /sbin/runscript.sh - it won't run our custom
+# restart() unless it finds these two strings in the file.
+# svc_start svc_stop
+restart() {
+ ebegin "Restarting eJabberd"
+ if [ -z "$EJABBERD_NODE" ];
+ then
+ EJABBERD_NODE="ejabberd@`hostname -s`"
+ fi
+ /usr/bin/ejabberdctl $EJABBERD_NODE restart
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading eJabberd"
+ if [ -z "$EJABBERD_NODE" ];
+ then
+ EJABBERD_NODE="ejabberd@`hostname -s`"
+ fi
+ /usr/bin/ejabberdctl $EJABBERD_NODE reopen-log
+ eend $?
+}