rpms/ejabberd/F-11 ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch, NONE, 1.1 ejabberd-0002-Mention-mod_ctlextra-as-an-ejabberd-module.patch, NONE, 1.1 ejabberd-0003-Fixed-delays-in-s2s-connections.patch, NONE, 1.1 ejabberd-0004-Introducing-mod_admin_extra.patch, NONE, 1.1 ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch, NONE, 1.1 ejabberd-0006-Support-to-authenticate-against-SASL-GSSAPI-http-www.patch, NONE, 1.1 ejabberd-0007-Fixed-typo.patch, NONE, 1.1 ejabberd-0008-Quick-fix-for-error-nxdomain.patch, NONE, 1.1 ejabberd-0009-Replace-MSG-with-DEBUG.patch, NONE, 1.1 .cvsignore, 1.17, 1.18 ejabberd.spec, 1.45, 1.46 import.log, 1.18, 1.19 sources, 1.19, 1.20 ejabberd-c2s_dos_fix.diff, 1.1, NONE ejabberd-ejabberd_cfg_pam_name.diff, 1.2, NONE ejabberd-ejabberdctl_fix.diff, 1.10, NONE ejabberd-fixed_delays_in_s2s.patch, 1.2, NONE ejabberd-mod_admin_extra.patch, 1.1, NONE ejabberd-mod_ctlextra_mentioning_in_ejabberd_app.diff, 1.1, NONE ejabberdctl-support-concurrent-connections.patch, 1.1, NONE

Peter Lemenkov peter at fedoraproject.org
Fri Mar 12 16:04:15 UTC 2010


Author: peter

Update of /cvs/pkgs/rpms/ejabberd/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv2394/F-11

Modified Files:
	.cvsignore ejabberd.spec import.log sources 
Added Files:
	ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch 
	ejabberd-0002-Mention-mod_ctlextra-as-an-ejabberd-module.patch 
	ejabberd-0003-Fixed-delays-in-s2s-connections.patch 
	ejabberd-0004-Introducing-mod_admin_extra.patch 
	ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch 
	ejabberd-0006-Support-to-authenticate-against-SASL-GSSAPI-http-www.patch 
	ejabberd-0007-Fixed-typo.patch 
	ejabberd-0008-Quick-fix-for-error-nxdomain.patch 
	ejabberd-0009-Replace-MSG-with-DEBUG.patch 
Removed Files:
	ejabberd-c2s_dos_fix.diff ejabberd-ejabberd_cfg_pam_name.diff 
	ejabberd-ejabberdctl_fix.diff 
	ejabberd-fixed_delays_in_s2s.patch 
	ejabberd-mod_admin_extra.patch 
	ejabberd-mod_ctlextra_mentioning_in_ejabberd_app.diff 
	ejabberdctl-support-concurrent-connections.patch 
Log Message:
Ver. 2.1.3

ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch:
 ejabberd.cfg.example |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- NEW FILE ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch ---
>From 53f8a296b0f83ea9dafc3aed8b49c34941f31454 Mon Sep 17 00:00:00 2001
From: Peter Lemenkov <lemenkov at gmail.com>
Date: Tue, 16 Feb 2010 16:03:38 +0300
Subject: [PATCH 1/9] Fix PAM service example name to match actual one

Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
---
 src/ejabberd.cfg.example |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example
index 4087947..b351cfc 100644
--- a/src/ejabberd.cfg.example
+++ b/src/ejabberd.cfg.example
@@ -235,7 +235,7 @@
 %% Authentication using PAM
 %%
 %%{auth_method, pam}.
-%%{pam_service, "pamservicename"}.
+%%{pam_service, "ejabberd"}.
 
 %%
 %% Authentication using LDAP
-- 
1.6.6.1


ejabberd-0002-Mention-mod_ctlextra-as-an-ejabberd-module.patch:
 ejabberd.app |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE ejabberd-0002-Mention-mod_ctlextra-as-an-ejabberd-module.patch ---
>From 6365359078925b436d1d3238a2dd6d6c11271fac Mon Sep 17 00:00:00 2001
From: Peter Lemenkov <lemenkov at gmail.com>
Date: Tue, 16 Feb 2010 16:05:53 +0300
Subject: [PATCH 2/9] Mention mod_ctlextra as an ejabberd module

Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
---
 src/ejabberd.app |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/ejabberd.app b/src/ejabberd.app
index 2f5f123..cc7e1f8 100644
--- a/src/ejabberd.app
+++ b/src/ejabberd.app
@@ -70,6 +70,7 @@
 	     mod_caps,
 	     mod_configure2,
 	     mod_configure,
+	     mod_ctlextra,
 	     mod_disco,
 	     mod_echo,
 	     mod_http_bind,
-- 
1.6.6.1


ejabberd-0003-Fixed-delays-in-s2s-connections.patch:
 ejabberd_s2s_in.erl  |    2 +-
 ejabberd_s2s_out.erl |    7 +++----
 2 files changed, 4 insertions(+), 5 deletions(-)

--- NEW FILE ejabberd-0003-Fixed-delays-in-s2s-connections.patch ---
>From 019bf239560925edd809bb7922a49b3737412067 Mon Sep 17 00:00:00 2001
From: Sergei Golovan <sgolovan at nes.ru>
Date: Tue, 16 Feb 2010 16:07:37 +0300
Subject: [PATCH 3/9] Fixed delays in s2s connections.

Patch by Sergei Golovan increases timeouts in S2S and removes horrible 5-minute
delay between remote server connection attempts after a falure (in case of
server is down it would be reasonable, but what happens much more often is a
network split when the delay is inadmissible).
---
 src/ejabberd_s2s_in.erl  |    2 +-
 src/ejabberd_s2s_out.erl |    6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl
index f221302..b55c805 100644
--- a/src/ejabberd_s2s_in.erl
+++ b/src/ejabberd_s2s_in.erl
@@ -352,7 +352,7 @@ stream_established({xmlstreamelement, El}, StateData) ->
             case {ejabberd_s2s:allow_host(To, From),
                   lists:member(LTo, ejabberd_router:dirty_get_all_domains())} of
                 {true, true} ->
-		    ejabberd_s2s_out:terminate_if_waiting_delay(To, From),
+		    %%ejabberd_s2s_out:terminate_if_waiting_delay(To, From),
 		    ejabberd_s2s_out:start(To, From,
 					   {verify, self(),
 					    Key, StateData#state.streamid}),
diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl
index ac7eee2..048d018 100644
--- a/src/ejabberd_s2s_out.erl
+++ b/src/ejabberd_s2s_out.erl
@@ -90,7 +90,7 @@
 						 [From, Host, Type])).
 -endif.
 
--define(FSMTIMEOUT, 30000).
+-define(FSMTIMEOUT, 60000).
 
 %% We do not block on send anymore.
 -define(TCP_SEND_TIMEOUT, 15000).
@@ -226,8 +226,8 @@ open_socket(init, StateData) ->
 	{error, _Reason} ->
 	    ?INFO_MSG("s2s connection: ~s -> ~s (remote server not found)",
 		      [StateData#state.myname, StateData#state.server]),
-	    wait_before_reconnect(StateData)
-	    %%{stop, normal, StateData}
+	    %%wait_before_reconnect(StateData)
+	    {stop, normal, StateData}
     end;
 open_socket(stop, StateData) ->
     ?INFO_MSG("s2s connection: ~s -> ~s (stopped in open socket)",
-- 
1.6.6.1


ejabberd-0004-Introducing-mod_admin_extra.patch:
 ejabberd.app        |    1 
 mod_admin_extra.erl | 1280 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 1280 insertions(+), 1 deletion(-)

--- NEW FILE ejabberd-0004-Introducing-mod_admin_extra.patch ---
>From 766c7603bff9d7548d43229f855e9ac7b79c63cd Mon Sep 17 00:00:00 2001
From: Badlop <badlop at process-one.net>
Date: Tue, 16 Feb 2010 16:12:17 +0300
Subject: [PATCH 4/9] Introducing mod_admin_extra

Adds the mod_admin_extra module to ejabberd.
This module extends the functionality provided by ejabberdctl
by adding several new commands.

The code is taken from the ProcessOne repository:
https://forge.process-one.net/browse/ejabberd-modules/mod_admin_extra
(trunk, revision 976).
---
 src/ejabberd.app        |    1 +
 src/mod_admin_extra.erl | 1279 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1280 insertions(+), 0 deletions(-)
 create mode 100644 src/mod_admin_extra.erl

diff --git a/src/ejabberd.app b/src/ejabberd.app
index cc7e1f8..ae8ce83 100644
--- a/src/ejabberd.app
+++ b/src/ejabberd.app
@@ -105,6 +105,7 @@
 	     mod_vcard_ldap,
 	     mod_vcard_odbc,
 	     mod_version,
+             mod_admin_extra,
 	     node_buddy,
 	     node_club,
 	     node_default,
diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl
new file mode 100644
index 0000000..9f3ca14
--- /dev/null
+++ b/src/mod_admin_extra.erl
@@ -0,0 +1,1279 @@
+%%%-------------------------------------------------------------------
+%%% File    : mod_admin_extra.erl
+%%% Author  : Badlop <badlop at process-one.net>
+%%% Purpose : Contributed administrative functions and commands
+%%% Created : 10 Aug 2008 by Badlop <badlop at process-one.net>
+%%%
+%%%
+%%% ejabberd, Copyright (C) 2002-2008   ProcessOne
+%%%
+%%% This program is free software; you can redistribute it and/or
+%%% modify it under the terms of the GNU General Public License as
+%%% published by the Free Software Foundation; either version 2 of the
+%%% License, or (at your option) any later version.
+%%%
+%%% This program is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%%% General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with this program; if not, write to the Free Software
+%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+%%% 02111-1307 USA
+%%%
+%%%-------------------------------------------------------------------
+
+-module(mod_admin_extra).
+-author('badlop at process-one.net').
+
+-behaviour(gen_mod).
+
+-export([start/2, stop/1,
+	 %% Node
+	 compile/1,
+	 load_config/1,
+	 get_cookie/0,
+	 remove_node/1,
+	 export2odbc/2,
+	 %% Accounts
+	 set_password/3,
+	 check_password_hash/4,
+	 delete_old_users/1,
+	 delete_old_users_vhost/2,
+	 ban_account/3,
+	 num_active_users/2,
+	 %% Sessions
+	 num_resources/2,
+	 resource_num/3,
+	 kick_session/4,
+	 status_num/2, status_num/1,
+	 status_list/2, status_list/1,
+	 %% Vcard
+	 set_nickname/3,
+	 get_vcard/3,
+	 get_vcard/4,
+	 set_vcard/4,
+	 set_vcard/5,
+	 %% Roster
+	 add_rosteritem/7,
+	 delete_rosteritem/4,
+	 process_rosteritems/5,
+	 get_roster/2,
+	 push_roster/3,
+	 push_roster_all/1,
+	 push_alltoall/2,
+	 %% mod_shared_roster
+	 srg_create/5,
+	 srg_delete/2,
+	 srg_list/1,
+	 srg_get_info/2,
+	 srg_get_members/2,
+	 srg_user_add/4,
+	 srg_user_del/4,
+	 %% Stanza
+	 send_message_headline/4,
+	 send_message_chat/3,
+	 %% Stats
+	 stats/1, stats/2
+	]).
+
+-include("ejabberd.hrl").
+-include("ejabberd_commands.hrl").
+-include("mod_roster.hrl").
+-include("jlib.hrl").
+
+%% Copied from ejabberd_sm.erl
+-record(session, {sid, usr, us, priority, info}).
+
+
+%%%
+%%% gen_mod
+%%%
+
+start(_Host, _Opts) ->
+    ejabberd_commands:register_commands(commands()).
+
+stop(_Host) ->
+    ejabberd_commands:unregister_commands(commands()).
+
+
+%%%
+%%% Register commands
+%%%
+
+commands() ->
+    Vcard1FieldsString = "Some vcard field names in get/set_vcard are:\n"
+	" FN		- Full Name\n"
+	" NICKNAME	- Nickname\n"
+	" BDAY		- Birthday\n"
+	" TITLE		- Work: Position\n",
+    " ROLE		- Work: Role",
+
+    Vcard2FieldsString = "Some vcard field names and subnames in get/set_vcard2 are:\n"
+	" N FAMILY	- Family name\n"
+	" N GIVEN	- Given name\n"
+	" N MIDDLE	- Middle name\n"
+	" ADR CTRY	- Address: Country\n"
+	" ADR LOCALITY	- Address: City\n"
+	" EMAIL USERID	- E-Mail Address\n"
+	" ORG ORGNAME	- Work: Company\n"
+	" ORG ORGUNIT	- Work: Department",
+
+    VcardXEP = "For a full list of vCard fields check XEP-0054: vcard-temp at "
+	"http://www.xmpp.org/extensions/xep-0054.html",
+
+    [
+     #ejabberd_commands{name = compile, tags = [erlang],
+			desc = "Recompile and reload Erlang source code file",
+			module = ?MODULE, function = compile,
+			args = [{file, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = load_config, tags = [server],
+			desc = "Load ejabberd configuration file",
+			module = ?MODULE, function = load_config,
+			args = [{file, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = get_cookie, tags = [erlang],
+			desc = "Get the Erlang cookie of this node",
+			module = ?MODULE, function = get_cookie,
+			args = [],
+			result = {cookie, string}},
+     #ejabberd_commands{name = remove_node, tags = [erlang],
+			desc = "Remove an ejabberd node from Mnesia clustering config",
+			module = ?MODULE, function = remove_node,
+			args = [{node, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = export2odbc, tags = [mnesia],
+			desc = "Export Mnesia tables to files in directory",
+			module = ?MODULE, function = export2odbc,
+			args = [{host, string}, {path, string}],
+			result = {res, rescode}},
+
+     #ejabberd_commands{name = num_active_users, tags = [accounts, stats],
+			desc = "Get number of users active in the last days",
+			module = ?MODULE, function = num_active_users,
+			args = [{host, string}, {days, integer}],
+			result = {users, integer}},
+     #ejabberd_commands{name = delete_old_users, tags = [accounts, purge],
+			desc = "Delete users that didn't log in last days",
+			module = ?MODULE, function = delete_old_users,
+			args = [{days, integer}],
+			result = {res, restuple}},
+     #ejabberd_commands{name = delete_old_users_vhost, tags = [accounts, purge],
+			desc = "Delete users that didn't log in last days in vhost",
+			module = ?MODULE, function = delete_old_users_vhost,
+			args = [{host, string}, {days, integer}],
+			result = {res, restuple}},
+
+     #ejabberd_commands{name = check_account, tags = [accounts],
+			desc = "Check if an acount exists or not",
+			module = ejabberd_auth, function = is_user_exists,
+			args = [{user, string}, {host, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = check_password, tags = [accounts],
+			desc = "Check if a password is correct",
+			module = ejabberd_auth, function = check_password,
+			args = [{user, string}, {host, string}, {password, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = check_password_hash, tags = [accounts],
+			desc = "Check if the password hash is correct",
+			longdesc = "Allowed hash methods: md5, sha.",
+			module = ?MODULE, function = check_password_hash,
+			args = [{user, string}, {host, string}, {passwordhash, string}, {hashmethod, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = change_password, tags = [accounts],
+			desc = "Change the password of an account",
+			module = ?MODULE, function = set_password,
+			args = [{user, string}, {host, string}, {newpass, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = ban_account, tags = [accounts],
+			desc = "Ban an account: kick sessions and set random password",
+			module = ?MODULE, function = ban_account,
+			args = [{user, string}, {host, string}, {reason, string}],
+			result = {res, rescode}},
+
+     #ejabberd_commands{name = num_resources, tags = [session],
+			desc = "Get the number of resources of a user",
+			module = ?MODULE, function = num_resources,
+			args = [{user, string}, {host, string}],
+			result = {resources, integer}},
+     #ejabberd_commands{name = resource_num, tags = [session],
+			desc = "Resource string of a session number",
+			module = ?MODULE, function = resource_num,
+			args = [{user, string}, {host, string}, {num, integer}],
+			result = {resource, string}},
+     #ejabberd_commands{name = kick_session, tags = [session],
+			desc = "Kick a user session",
+			module = ?MODULE, function = kick_session,
+			args = [{user, string}, {host, string}, {resource, string}, {reason, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = status_num_host, tags = [session, stats],
+			desc = "Number of logged users with this status in host",
+			module = ?MODULE, function = status_num,
+			args = [{host, string}, {status, string}],
+			result = {users, integer}},
+     #ejabberd_commands{name = status_num, tags = [session, stats],
+			desc = "Number of logged users with this status",
+			module = ?MODULE, function = status_num,
+			args = [{status, string}],
+			result = {users, integer}},
+     #ejabberd_commands{name = status_list_host, tags = [session],
+			desc = "List of users logged in host with their statuses",
+			module = ?MODULE, function = status_list,
+			args = [{host, string}, {status, string}],
+			result = {users, {list,
+					  {userstatus, {tuple, [
+								{user, string},
+								{host, string},
+								{resource, string},
+								{priority, integer},
+								{status, string}
+							       ]}}
+					 }}},
+     #ejabberd_commands{name = status_list, tags = [session],
+			desc = "List of logged users with this status",
+			module = ?MODULE, function = status_list,
+			args = [{status, string}],
+			result = {users, {list,
+					  {userstatus, {tuple, [
+								{user, string},
+								{host, string},
+								{resource, string},
+								{priority, integer},
+								{status, string}
+							       ]}}
+					 }}},
+
+     #ejabberd_commands{name = set_nickname, tags = [vcard],
+			desc = "Set nickname in a user's vcard",
+			module = ?MODULE, function = set_nickname,
+			args = [{user, string}, {host, string}, {nickname, string}],
+			result = {res, rescode}},
+
+     #ejabberd_commands{name = get_vcard, tags = [vcard],
+			desc = "Get content from a vCard field",
+			longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
+			module = ?MODULE, function = get_vcard,
+			args = [{user, string}, {host, string}, {name, string}],
+			result = {content, string}},
+     #ejabberd_commands{name = get_vcard2, tags = [vcard],
+			desc = "Get content from a vCard field",
+			longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
+			module = ?MODULE, function = get_vcard,
+			args = [{user, string}, {host, string}, {name, string}, {subname, string}],
+			result = {content, string}},
+     #ejabberd_commands{name = set_vcard, tags = [vcard],
+			desc = "Set content in a vCard field",
+			longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
+			module = ?MODULE, function = set_vcard,
+			args = [{user, string}, {host, string}, {name, string}, {content, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = set_vcard2, tags = [vcard],
+			desc = "Set content in a vCard subfield",
+			longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
+			module = ?MODULE, function = set_vcard2,
+			args = [{user, string}, {host, string}, {name, string}, {subname, string}, {content, string}],
+			result = {res, rescode}},
+
+     #ejabberd_commands{name = add_rosteritem, tags = [roster],
+			desc = "Add an item to a user's roster",
+			module = ?MODULE, function = add_rosteritem,
+			args = [{localuser, string}, {localserver, string},
+				{user, string}, {server, string},
+				{nick, string}, {group, string},
+				{subs, string}],
+			result = {res, rescode}},
+     %%{"", "subs= none, from, to or both"},
+     %%{"", "example: add-roster peter localhost mike server.com MiKe Employees both"},
+     %%{"", "will add mike at server.com to peter at localhost roster"},
+     #ejabberd_commands{name = delete_rosteritem, tags = [roster],
+			desc = "Delete an item from a user's roster",
+			module = ?MODULE, function = delete_rosteritem,
+			args = [{localuser, string}, {localserver, string},
+				{user, string}, {server, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = process_rosteritems, tags = [roster],
+			desc = "List or delete rosteritems that match filtering options",
+			longdesc = "Explanation of each argument:\n"
+			" - action: what to do with each rosteritem that "
+			"matches all the filtering options\n"
+			" - subs: subscription type\n"
+			" - asks: pending subscription\n"
+			" - users: the JIDs of the local user\n"
+			" - contacts: the JIDs of the contact in the roster\n"
+			"\n"
+			"Allowed values in the arguments:\n"
+			"  ACTION = list | delete\n"
+			"  SUBS = SUB[:SUB]* | any\n"
+			"  SUB = none | from | to | both\n"
+			"  ASKS = ASK[:ASK]* | any\n"
+			"  ASK = none | out | in\n"
+			"  USERS = JID[:JID]* | any\n"
+			"  CONTACTS = JID[:JID]* | any\n"
+			"  JID = characters valid in a JID, and can use the "
+			"globs: *, ? and [...]\n"
+			"\n"
+			"This example will list roster items with subscription "
+			"'none', 'from' or 'to' that have any ask property, of "
+			"local users which JID is in the virtual host "
+			"'example.org' and that the contact JID is either a "
+			"bare server name (without user part) or that has a "
+			"user part and the server part contains the word 'icq'"
+			":\n  list none:from:to any *@example.org *:*@*icq*",
+			module = ?MODULE, function = process_rosteritems,
+			args = [{action, string}, {subs, string},
+				{asks, string}, {users, string},
+				{contacts, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = get_roster, tags = [roster],
+			desc = "Get roster of a local user",
+			module = ?MODULE, function = get_roster,
+			args = [{user, string}, {host, string}],
+			result = {contacts, {list, {contact, {tuple, [
+								      {jid, string},
+								      {nick, string},
+								      {group, string}
+								     ]}}}}},
+     #ejabberd_commands{name = push_roster, tags = [roster],
+			desc = "Push template roster from file to a user",
+			module = ?MODULE, function = push_roster,
+			args = [{file, string}, {user, string}, {host, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = push_roster_all, tags = [roster],
+			desc = "Push template roster from file to all those users",
+			module = ?MODULE, function = push_roster_all,
+			args = [{file, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = push_alltoall, tags = [roster],
+			desc = "Add all the users to all the users of Host in Group",
+			module = ?MODULE, function = push_alltoall,
+			args = [{host, string}, {group, string}],
+			result = {res, rescode}},
+
+     #ejabberd_commands{name = srg_create, tags = [shared_roster_group],
+			desc = "Create a Shared Roster Group",
+			longdesc = "If you want to specify several group "
+			"identifiers in the Display argument,\n"
+			"put  \\ \" around the argument and\nseparate the "
+			"identifiers with \\ \\ n\n"
+			"For example:\n"
+			"  ejabberdctl srg_create group3 localhost "
+			"name desc \\\"group1\\\\ngroup2\\\"",
+			module = ?MODULE, function = srg_create,
+			args = [{group, string}, {host, string},
+				{name, string}, {description, string}, {display, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = srg_delete, tags = [shared_roster_group],
+			desc = "Delete a Shared Roster Group",
+			module = ?MODULE, function = srg_delete,
+			args = [{group, string}, {host, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = srg_list, tags = [shared_roster_group],
+			desc = "List the Shared Roster Groups in Host",
+			module = ?MODULE, function = srg_list,
+			args = [{host, string}],
+			result = {groups, {list, {id, string}}}},
+     #ejabberd_commands{name = srg_get_info, tags = [shared_roster_group],
+			desc = "Get info of a Shared Roster Group",
+			module = ?MODULE, function = srg_get_info,
+			args = [{group, string}, {host, string}],
+			result = {informations, {list, {information, {tuple, [{key, string}, {value, string}]}}}}},
+     #ejabberd_commands{name = srg_get_members, tags = [shared_roster_group],
+			desc = "Get members of a Shared Roster Group",
+			module = ?MODULE, function = srg_get_members,
+			args = [{group, string}, {host, string}],
+			result = {members, {list, {member, string}}}},
+     #ejabberd_commands{name = srg_user_add, tags = [shared_roster_group],
+			desc = "Add the JID user at host to the Shared Roster Group",
+			module = ?MODULE, function = srg_user_add,
+			args = [{user, string}, {host, string}, {group, string}, {grouphost, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = srg_user_del, tags = [shared_roster_group],
+			desc = "Delete this JID user at host from the Shared Roster Group",
+			module = ?MODULE, function = srg_user_del,
+			args = [{user, string}, {host, string}, {group, string}, {grouphost, string}],
+			result = {res, rescode}},
+
+     #ejabberd_commands{name = send_message_chat, tags = [stanza],
+			desc = "Send a chat message to a local or remote bare of full JID",
+			module = ?MODULE, function = send_message_chat,
+			args = [{from, string}, {to, string}, {body, string}],
+			result = {res, rescode}},
+     #ejabberd_commands{name = send_message_headline, tags = [stanza],
+			desc = "Send a headline message to a local or remote bare of full JID",
+			module = ?MODULE, function = send_message_headline,
+			args = [{from, string}, {to, string},
+				{subject, string}, {body, string}],
+			result = {res, rescode}},
+
+     #ejabberd_commands{name = stats, tags = [stats],
+			desc = "Get statistical value: registeredusers onlineusers onlineusersnode uptimeseconds",
+			module = ?MODULE, function = stats,
+			args = [{name, string}],
+			result = {stat, integer}},
+     #ejabberd_commands{name = stats_host, tags = [stats],
+			desc = "Get statistical value for this host: registeredusers onlineusers",
+			module = ?MODULE, function = stats,
+			args = [{name, string}, {host, string}],
+			result = {stat, integer}}
+    ].
+
+
+%%%
+%%% Node
+%%%
+
+compile(File) ->
+    case compile:file(File) of
+	ok -> ok;
+	_ -> error
+    end.
+
+load_config(Path) ->
+    ok = ejabberd_config:load_file(Path).
+
+get_cookie() ->
+    atom_to_list(erlang:get_cookie()).
+
+remove_node(Node) ->
+    mnesia:del_table_copy(schema, list_to_atom(Node)),
+    ok.
+
+export2odbc(Host, Directory) ->
+    Tables = [
+	      {export_last, last},
+	      {export_offline, offline},
+	      {export_passwd, passwd},
+	      {export_private_storage, private_storage},
+	      {export_roster, roster},
+	      {export_vcard, vcard},
+	      {export_vcard_search, vcard_search}],
+    Export = fun({TableFun, Table}) ->
+		     Filename = filename:join([Directory, atom_to_list(Table)++".txt"]),
+		     io:format("Trying to export Mnesia table '~p' on Host '~s' to file '~s'~n", [Table, Host, Filename]),
+		     Res = (catch ejd2odbc:TableFun(Host, Filename)),
+		     io:format("  Result: ~p~n", [Res])
+	     end,
+    lists:foreach(Export, Tables),
+    ok.
+
+
+%%%
+%%% Accounts
+%%%
+
+set_password(User, Host, Password) ->
+    case ejabberd_auth:set_password(User, Host, Password) of
+	ok ->
+	    ok;
+	_ ->
+	    error
+    end.
+
+%% Copied some code from ejabberd_commands.erl
+check_password_hash(User, Host, PasswordHash, HashMethod) ->
+    AccountPass = ejabberd_auth:get_password_s(User, Host),
+    AccountPassHash = case HashMethod of
+			  "md5" -> get_md5(AccountPass);
+			  "sha" -> get_sha(AccountPass);
+			  _ -> undefined
+		      end,
+    case AccountPassHash of
+	undefined -> error;
+	PasswordHash -> ok;
+	_ -> error
+    end.
+get_md5(AccountPass) ->
+    lists:flatten([io_lib:format("~.16B", [X])
+		   || X <- binary_to_list(crypto:md5(AccountPass))]).
+get_sha(AccountPass) ->
+    lists:flatten([io_lib:format("~.16B", [X])
+		   || X <- binary_to_list(crypto:sha(AccountPass))]).
+
+num_active_users(Host, Days) ->
+    list_last_activity(Host, true, Days).
+
+%% Code based on ejabberd/src/web/ejabberd_web_admin.erl
+list_last_activity(Host, Integral, Days) ->
+    {MegaSecs, Secs, _MicroSecs} = now(),
+    TimeStamp = MegaSecs * 1000000 + Secs,
+    TS = TimeStamp - Days * 86400,
+    case catch mnesia:dirty_select(
+		 last_activity, [{{last_activity, {'_', Host}, '$1', '_'},
+				  [{'>', '$1', TS}],
+				  [{'trunc', {'/',
+					      {'-', TimeStamp, '$1'},
+					      86400}}]}]) of
+							      {'EXIT', _Reason} ->
+		 [];
+	       Vals ->
+		 Hist = histogram(Vals, Integral),
+		 if
+		     Hist == [] ->
+			 0;
+		     true ->
+			 Left = Days - length(Hist),
+			 Tail = if
+				    Integral ->
+					lists:duplicate(Left, lists:last(Hist));
+				    true ->
+					lists:duplicate(Left, 0)
+				end,
+			 lists:nth(Days, Hist ++ Tail)
+		 end
+	 end.
+histogram(Values, Integral) ->
+    histogram(lists:sort(Values), Integral, 0, 0, []).
+histogram([H | T], Integral, Current, Count, Hist) when Current == H ->
+    histogram(T, Integral, Current, Count + 1, Hist);
+histogram([H | _] = Values, Integral, Current, Count, Hist) when Current < H ->
+    if
+	Integral ->
+	    histogram(Values, Integral, Current + 1, Count, [Count | Hist]);
+	true ->
+	    histogram(Values, Integral, Current + 1, 0, [Count | Hist])
+    end;
+histogram([], _Integral, _Current, Count, Hist) ->
+    if
+	Count > 0 ->
+	    lists:reverse([Count | Hist]);
+	true ->
+	    lists:reverse(Hist)
+    end.
+
+
+-record(last_activity, {us, timestamp, status}).
+
+delete_old_users(Days) ->
+    %% Get the list of registered users
+    Users = ejabberd_auth:dirty_get_registered_users(),
+
+    {removed, N, UR} = delete_old_users(Days, Users),
+    {ok, io_lib:format("Deleted ~p users: ~p", [N, UR])}.
+
+delete_old_users_vhost(Host, Days) ->
+    %% Get the list of registered users
+    Users = ejabberd_auth:get_vh_registered_users(Host),
+
+    {removed, N, UR} = delete_old_users(Days, Users),
+    {ok, io_lib:format("Deleted ~p users: ~p", [N, UR])}.
+
+delete_old_users(Days, Users) ->
+    %% Convert older time
+    SecOlder = Days*24*60*60,
+
+    %% Get current time
+    {MegaSecs, Secs, _MicroSecs} = now(),
+    TimeStamp_now = MegaSecs * 1000000 + Secs,
+
+    %% For a user, remove if required and answer true
+    F = fun({LUser, LServer}) ->
+		%% Check if the user is logged
+		case ejabberd_sm:get_user_resources(LUser, LServer) of
+		    %% If it isnt
+		    [] ->
+			%% Look for his last_activity
+			case mnesia:dirty_read(last_activity, {LUser, LServer}) of
+			    %% If it is
+			    %% existent:
+			    [#last_activity{timestamp = TimeStamp}] ->
+				%% get his age
+				Sec = TimeStamp_now - TimeStamp,
+				%% If he is
+				if
+				    %% younger than SecOlder:
+				    Sec < SecOlder ->
+					%% do nothing
+					false;
+				    %% older:
+				    true ->
+					%% remove the user
+					ejabberd_auth:remove_user(LUser, LServer),
+					true
+				end;
+			    %% nonexistent:
+			    [] ->
+				%% remove the user
+				ejabberd_auth:remove_user(LUser, LServer),
+				true
+			end;
+		    %% Else
+		    _ ->
+			%% do nothing
+			false
+		end
+	end,
+    %% Apply the function to every user in the list
+    Users_removed = lists:filter(F, Users),
+    {removed, length(Users_removed), Users_removed}.
+
+
+%%
+%% Ban account
+
+ban_account(User, Host, ReasonText) ->
+    Reason = prepare_reason(ReasonText),
+    kick_sessions(User, Host, Reason),
+    set_random_password(User, Host, Reason),
+    ok.
+
+kick_sessions(User, Server, Reason) ->
+    lists:map(
+      fun(Resource) ->
+	      kick_this_session(User, Server, Resource, Reason)
+      end,
+      get_resources(User, Server)).
+
+get_resources(User, Server) ->
+    lists:map(
+      fun(Session) ->
+	      element(3, Session#session.usr)
+      end,
+      get_sessions(User, Server)).
+
+get_sessions(User, Server) ->
+    LUser = jlib:nodeprep(User),
+    LServer = jlib:nameprep(Server),
+    Sessions =  mnesia:dirty_index_read(session, {LUser, LServer}, #session.us),
+    true = is_list(Sessions),
+    Sessions.
+
+set_random_password(User, Server, Reason) ->
+    NewPass = build_random_password(Reason),
+    set_password_auth(User, Server, NewPass).
+
+build_random_password(Reason) ->
+    Date = jlib:timestamp_to_iso(calendar:universal_time()),
+    RandomString = randoms:get_string(),
+    "BANNED_ACCOUNT--" ++ Date ++ "--" ++ RandomString ++ "--" ++ Reason.
+
+set_password_auth(User, Server, Password) ->
+    ok = ejabberd_auth:set_password(User, Server, Password).
+
+prepare_reason([]) ->
+    "Kicked by administrator";
+prepare_reason([Reason]) ->
+    Reason;
+prepare_reason(Reason) when is_list(Reason) ->
+    Reason;
+prepare_reason(StringList) ->
+    string:join(StringList, "_").
+
+
+%%%
+%%% Sessions
+%%%
+
+num_resources(User, Host) ->
+    length(ejabberd_sm:get_user_resources(User, Host)).
+
+resource_num(User, Host, Num) ->
+    Resources = ejabberd_sm:get_user_resources(User, Host),
+    case (0<Num) and (Num=<length(Resources)) of
+	true ->
+	    lists:nth(Num, Resources);
+	false ->
+	    lists:flatten(io_lib:format("Error: Wrong resource number: ~p", [Num]))
+    end.
+
+kick_session(User, Server, Resource, ReasonText) ->
+    kick_this_session(User, Server, Resource, prepare_reason(ReasonText)),
+    ok.
+
+kick_this_session(User, Server, Resource, Reason) ->
+    ejabberd_router:route(
+      jlib:make_jid("", "", ""),
+      jlib:make_jid(User, Server, Resource),
+      {xmlelement, "broadcast", [], [{exit, Reason}]}).
+
+
+status_num(Host, Status) ->
+    length(get_status_list(Host, Status)).
+status_num(Status) ->
+    status_num("all", Status).
+status_list(Host, Status) ->
+    Res = get_status_list(Host, Status),
+    [{U, S, R, P, St} || {U, S, R, P, St} <- Res].
+status_list(Status) ->
+    status_list("all", Status).
+
+
+get_status_list(Host, Status_required) ->
+    %% Get list of all logged users
+    Sessions = ejabberd_sm:dirty_get_my_sessions_list(),
+    %% Reformat the list
+    Sessions2 = [ {Session#session.usr, Session#session.sid, Session#session.priority} || Session <- Sessions],
+    Fhost = case Host of
+		"all" ->
+		    %% All hosts are requested, so dont filter at all
+		    fun(_, _) -> true end;
+		_ ->
+		    %% Filter the list, only Host is interesting
+		    fun(A, B) -> A == B end
+	    end,
+    Sessions3 = [ {Pid, Server, Priority} || {{_User, Server, _Resource}, {_, Pid}, Priority} <- Sessions2, apply(Fhost, [Server, Host])],
+    %% For each Pid, get its presence
+    Sessions4 = [ {ejabberd_c2s:get_presence(Pid), Server, Priority} || {Pid, Server, Priority} <- Sessions3],
+    %% Filter by status
+    Fstatus = case Status_required of
+		  "all" ->
+		      fun(_, _) -> true end;
+		  _ ->
+		      fun(A, B) -> A == B end
+	      end,
+    [{User, Server, Resource, Priority, stringize(Status_text)}
+     || {{User, Resource, Status, Status_text}, Server, Priority} <- Sessions4,
+	apply(Fstatus, [Status, Status_required])].
+
+%% Make string more print-friendly
+stringize(String) ->
+    %% Replace newline characters with other code
+    element(2, regexp:gsub(String, "\n", "\\n")).
+
+
+%%%
+%%% Vcard
+%%%
+
+set_nickname(User, Host, Nickname) ->
+    R = mod_vcard:process_sm_iq(
+	  {jid, User, Host, "", User, Host, ""},
+	  {jid, User, Host, "", User, Host, ""},
+	  {iq, "", set, "", "en",
+	   {xmlelement, "vCard",
+	    [{"xmlns", "vcard-temp"}], [
+					{xmlelement, "NICKNAME", [], [{xmlcdata, Nickname}]}
+				       ]
+	   }}),
+    case R of
+	{iq, [], result, [], _L, []} ->
+	    ok;
+	_ ->
+	    error
+    end.
+
+get_vcard(User, Host, Name) ->
+    get_vcard_content(User, Host, [Name]).
+
+get_vcard(User, Host, Name, Subname) ->
+    get_vcard_content(User, Host, [Name, Subname]).
+
+set_vcard(User, Host, Name, Content) ->
+    set_vcard_content(User, Host, [Name], Content).
+
+set_vcard(User, Host, Name, Subname, Content) ->
+    set_vcard_content(User, Host, [Name, Subname], Content).
+
+
+%%
+%% Internal vcard
+
+get_vcard_content(User, Server, Data) ->
+    [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}),
+    JID = jlib:make_jid(User, Server, ""),
+    IQ = #iq{type = get, xmlns = ?NS_VCARD},
+    IQr = Module:Function(JID, JID, IQ),
+    case IQr#iq.sub_el of
+	[A1] ->
+	    case get_vcard(Data, A1) of
+		false -> "Error: no_value";
+		Elem -> xml:get_tag_cdata(Elem)
+	    end;
+	[] ->
+	    "Error: no_vcard"
+    end.
+
+get_vcard([Data1, Data2], A1) ->
+    case xml:get_subtag(A1, Data1) of
+    	false -> false;
+	A2 -> get_vcard([Data2], A2)
+    end;
+
+get_vcard([Data], A1) ->
+    xml:get_subtag(A1, Data).
+
+set_vcard_content(User, Server, Data, Content) ->
+    [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}),
+    JID = jlib:make_jid(User, Server, ""),
+    IQ = #iq{type = get, xmlns = ?NS_VCARD},
+    IQr = Module:Function(JID, JID, IQ),
+
+    %% Get old vcard
+    A4 = case IQr#iq.sub_el of
+	     [A1] ->
+		 {_, _, _, A2} = A1,
+		 update_vcard_els(Data, Content, A2);
+	     [] ->
+		 update_vcard_els(Data, Content, [])
+	 end,
+
+    %% Build new vcard
+    SubEl = {xmlelement, "vCard", [{"xmlns","vcard-temp"}], A4},
+    IQ2 = #iq{type=set, sub_el = SubEl},
+
+    Module:Function(JID, JID, IQ2),
+    ok.
+
+update_vcard_els(Data, Content, Els1) ->
+    Els2 = lists:keysort(2, Els1),
+    [Data1 | Data2] = Data,
+    NewEl = case Data2 of
+		[] ->
+		    {xmlelement, Data1, [], [{xmlcdata,Content}]};
+		[D2] ->
+		    OldEl = case lists:keysearch(Data1, 2, Els2) of
+				{value, A} -> A;
+				false -> {xmlelement, Data1, [], []}
+			    end,
+		    {xmlelement, _, _, ContentOld1} = OldEl,
+		    Content2 = [{xmlelement, D2, [], [{xmlcdata,Content}]}],
+		    ContentOld2 = lists:keysort(2, ContentOld1),
+		    ContentOld3 = lists:keydelete(D2, 2, ContentOld2),
+		    ContentNew = lists:keymerge(2, Content2, ContentOld3),
+		    {xmlelement, Data1, [], ContentNew}
+	    end,
+    Els3 = lists:keydelete(Data1, 2, Els2),
+    lists:keymerge(2, [NewEl], Els3).
+
+
+%%%
+%%% Roster
+%%%
+
+add_rosteritem(LocalUser, LocalServer, User, Server, Nick, Group, Subs) ->
+    case add_rosteritem(LocalUser, LocalServer, User, Server, Nick, Group, list_to_atom(Subs), []) of
+	{atomic, ok} ->
+	    push_roster_item(LocalUser, LocalServer, User, Server, {add, Nick, Subs, Group}),
+	    ok;
+	_ ->
+	    error
+    end.
+
+add_rosteritem(LU, LS, User, Server, Nick, Group, Subscription, Xattrs) ->
+    subscribe(LU, LS, User, Server, Nick, Group, Subscription, Xattrs).
+
+subscribe(LU, LS, User, Server, Nick, Group, Subscription, Xattrs) ->
+    mnesia:transaction(
+      fun() ->
+	      mnesia:write({roster,
+			    {LU,LS,{User,Server,[]}}, % uj
+			    {LU,LS},                  % user
+			    {User,Server,[]},      % jid
+			    Nick,                  % name: "Mom", []
+			    Subscription,  % subscription: none, to=you see him, from=he sees you, both
+			    none,          % ask: out=send request, in=somebody requests you, none
+			    [Group],       % groups: ["Family"]
+			    Xattrs,        % xattrs: [{"category","conference"}]
+			    []             % xs: []
+			   })
+      end).
+
+delete_rosteritem(LocalUser, LocalServer, User, Server) ->
+    case unsubscribe(LocalUser, LocalServer, User, Server) of
+	{atomic, ok} ->
+	    push_roster_item(LocalUser, LocalServer, User, Server, remove),
+	    ok;
+	_  ->
+	    error
+    end.
+
+unsubscribe(LU, LS, User, Server) ->
+    mnesia:transaction(
+      fun() ->
+              mnesia:delete({roster, {LU, LS, {User, Server, []}}})
+      end).
+
+
+%% -----------------------------
+%% Get Roster
+%% -----------------------------
+
+get_roster(User, Server) ->
+    {ok, Roster} = get_roster2(User, Server),
+    make_roster_xmlrpc(Roster).
+
+get_roster2(User, Server) ->
+    Modules = gen_mod:loaded_modules(Server),
+    Roster = case lists:member(mod_roster, Modules) of
+		 true ->
+		     mod_roster:get_user_roster([], {User, Server});
+		 false ->
+		     case lists:member(mod_roster_odbc, Modules) of
+			 true ->
+			     mod_roster_odbc:get_user_roster([], {User, Server});
+			 false ->
+			     {error, "Neither mod_roster or mod_roster_odbc are enabled"}
+		     end
+	     end,
+    {ok, Roster}.
+
+%% Note: if a contact is in several groups, the contact is returned
+%% several times, each one in a different group.
+make_roster_xmlrpc(Roster) ->
+    lists:foldl(
+      fun(Item, Res) ->
+	      JIDS = jlib:jid_to_string(Item#roster.jid),
+	      Nick = Item#roster.name,
+	      Groups = case Item#roster.groups of
+			   [] -> [""];
+			   Gs -> Gs
+		       end,
+	      ItemsX = [{JIDS, Nick, Group}
+			|| Group <- Groups],
+	      ItemsX ++ Res
+      end,
+      [],
+      Roster).
+
+
+%%-----------------------------
+%% Push Roster from file
+%%-----------------------------
+
+push_roster(File, User, Server) ->
+    {ok, [Roster]} = file:consult(File),
+    subscribe_roster({User, Server, "", User}, Roster).
+
+push_roster_all(File) ->
+    {ok, [Roster]} = file:consult(File),
+    subscribe_all(Roster).
+
+subscribe_all(Roster) ->
+    subscribe_all(Roster, Roster).
+subscribe_all([], _) ->
+    ok;
+subscribe_all([User1 | Users], Roster) ->
+    subscribe_roster(User1, Roster),
+    subscribe_all(Users, Roster).
+
+subscribe_roster(_, []) ->
+    ok;
+%% Do not subscribe a user to itself
+subscribe_roster({Name, Server, Group, Nick}, [{Name, Server, _, _} | Roster]) ->
+    subscribe_roster({Name, Server, Group, Nick}, Roster);
+%% Subscribe Name2 to Name1
+subscribe_roster({Name1, Server1, Group1, Nick1}, [{Name2, Server2, Group2, Nick2} | Roster]) ->
+    subscribe(Name1, Server1, Name2, Server2, Nick2, Group2, both, []),
+    subscribe_roster({Name1, Server1, Group1, Nick1}, Roster).
+
+push_alltoall(S, G) ->
+    Users = ejabberd_auth:get_vh_registered_users(S),
+    Users2 = build_list_users(G, Users, []),
+    subscribe_all(Users2),
+    ok.
+
+build_list_users(_Group, [], Res) ->
+    Res;
+build_list_users(Group, [{User, Server}|Users], Res) ->
+    build_list_users(Group, Users, [{User, Server, Group, User}|Res]).
+
+%% @spec(LU, LS, U, S, Action) -> ok
+%%       Action = {add, Nick, Subs, Group} | remove
+%% @doc Push to the roster of account LU at LS the contact U at S.
+%% The specific action to perform is defined in Action.
+push_roster_item(LU, LS, U, S, Action) ->
+    lists:foreach(fun(R) ->
+			  push_roster_item(LU, LS, R, U, S, Action)
+		  end, ejabberd_sm:get_user_resources(LU, LS)).
+
+push_roster_item(LU, LS, R, U, S, Action) ->
+    Item = build_roster_item(U, S, Action),
+    ResIQ = build_iq_roster_push(Item),
+    LJID = jlib:make_jid(LU, LS, R),
+    ejabberd_router:route(LJID, LJID, ResIQ).
+
+build_roster_item(U, S, {add, Nick, Subs, Group}) ->
+    {xmlelement, "item",
+     [{"jid", jlib:jid_to_string(jlib:make_jid(U, S, ""))},
+      {"name", Nick},
+      {"subscription", Subs}],
+     [{xmlelement, "group", [], [{xmlcdata, Group}]}]
+    };
+build_roster_item(U, S, remove) ->
+    {xmlelement, "item",
+     [{"jid", jlib:jid_to_string(jlib:make_jid(U, S, ""))},
+      {"subscription", "remove"}],
+     []
+    }.
+
+build_iq_roster_push(Item) ->
+    {xmlelement, "iq",
+     [{"type", "set"}, {"id", "push"}],
+     [{xmlelement, "query",
+       [{"xmlns", ?NS_ROSTER}],
+       [Item]
+      }
+     ]
+    }.
+
+
+%%%
+%%% Shared Roster Groups
+%%%
+
+srg_create(Group, Host, Name, Description, Display) ->
+    {ok, DisplayList} = regexp:split(Display, "\\\\n"),
+    Opts = [{name, Name},
+	    {displayed_groups, DisplayList},
+	    {description, Description}],
+    {atomic, ok} = mod_shared_roster:create_group(Host, Group, Opts),
+    ok.
+
+srg_delete(Group, Host) ->
+    {atomic, ok} = mod_shared_roster:delete_group(Host, Group),
+    ok.
+
+srg_list(Host) ->
+    lists:sort(mod_shared_roster:list_groups(Host)).
+
+srg_get_info(Group, Host) ->
+    Opts = mod_shared_roster:get_group_opts(Host,Group),
+    [{io_lib:format("~p", [Title]),
+      io_lib:format("~p", [Value])} || {Title, Value} <- Opts].
+
+srg_get_members(Group, Host) ->
+    Members = mod_shared_roster:get_group_explicit_users(Host,Group),
+    [jlib:jid_to_string(jlib:make_jid(MUser, MServer, ""))
+     || {MUser, MServer} <- Members].
+
+srg_user_add(User, Host, Group, GroupHost) ->
+    {atomic, ok} = mod_shared_roster:add_user_to_group(GroupHost, {User, Host}, Group),
+    ok.
+
+srg_user_del(User, Host, Group, GroupHost) ->
+    {atomic, ok} = mod_shared_roster:remove_user_from_group(GroupHost, {User, Host}, Group),
+    ok.
+
+
+%%%
+%%% Stanza
+%%%
+
+%% @doc Send a chat message to a Jabber account.
+%% @spec (From::string(), To::string(), Body::string()) -> ok
+send_message_chat(From, To, Body) ->
+    Packet = build_packet(message_chat, [Body]),
+    send_packet_all_resources(From, To, Packet).
+
+%% @doc Send a headline message to a Jabber account.
+%% @spec (From::string(), To::string(), Subject::string(), Body::string()) -> ok
+send_message_headline(From, To, Subject, Body) ->
+    Packet = build_packet(message_headline, [Subject, Body]),
+    send_packet_all_resources(From, To, Packet).
+
+%% @doc Send a packet to a Jabber account.
+%% If a resource was specified in the JID,
+%% the packet is sent only to that specific resource.
+%% If no resource was specified in the JID,
+%% and the user is remote or local but offline,
+%% the packet is sent to the bare JID.
+%% If the user is local and is online in several resources,
+%% the packet is sent to all its resources.
+send_packet_all_resources(FromJIDString, ToJIDString, Packet) ->
+    FromJID = jlib:string_to_jid(FromJIDString),
+    ToJID = jlib:string_to_jid(ToJIDString),
+    ToUser = ToJID#jid.user,
+    ToServer = ToJID#jid.server,
+    case ToJID#jid.resource of
+	"" ->
+	    send_packet_all_resources(FromJID, ToUser, ToServer, Packet);
+	Res ->
+	    send_packet_all_resources(FromJID, ToUser, ToServer, Res, Packet)
+    end.
+
+send_packet_all_resources(FromJID, ToUser, ToServer, Packet) ->
+    case ejabberd_sm:get_user_resources(ToUser, ToServer) of
+	[] ->
+	    send_packet_all_resources(FromJID, ToUser, ToServer, "", Packet);
+	ToResources ->
+	    lists:foreach(
+	      fun(ToResource) ->
+		      send_packet_all_resources(FromJID, ToUser, ToServer,
+						ToResource, Packet)
+	      end,
+	      ToResources)
+    end.
+
+send_packet_all_resources(FromJID, ToU, ToS, ToR, Packet) ->
+    ToJID = jlib:make_jid(ToU, ToS, ToR),
+    ejabberd_router:route(FromJID, ToJID, Packet).
+
+
+build_packet(message_chat, [Body]) ->
+    {xmlelement, "message",
+     [{"type", "chat"}],
+     [{xmlelement, "body", [], [{xmlcdata, Body}]}]
+    };
+build_packet(message_headline, [Subject, Body]) ->
+    {xmlelement, "message",
+     [{"type", "headline"}],
+     [{xmlelement, "subject", [], [{xmlcdata, Subject}]},
+      {xmlelement, "body", [], [{xmlcdata, Body}]}
+     ]
+    }.
+
+%%%
+%%% Stats
+%%%
+
+stats(Name) ->
+    case Name of
+	"uptimeseconds" -> trunc(element(1, erlang:statistics(wall_clock))/1000);
+	"registeredusers" -> length(ejabberd_auth:dirty_get_registered_users());
+	"onlineusersnode" -> length(ejabberd_sm:dirty_get_my_sessions_list());
+	"onlineusers" -> length(ejabberd_sm:dirty_get_sessions_list())
+    end.
+
+stats(Name, Host) ->
+    case Name of
+	"registeredusers" -> length(ejabberd_auth:get_vh_registered_users(Host));
+	"onlineusers" -> length(ejabberd_sm:get_vh_session_list(Host))
+    end.
+
+
+
+%%-----------------------------
+%% Purge roster items
+%%-----------------------------
+
+process_rosteritems(ActionS, SubsS, AsksS, UsersS, ContactsS) ->
+    Action = case ActionS of
+		 "list" -> list;
+		 "delete" -> delete
+	     end,
+
+    Subs = lists:foldl(
+	     fun(any, _) -> [none, from, to, both];
+		(Sub, Subs) -> [Sub | Subs]
+	     end,
+	     [],
+	     [list_to_atom(S) || S <- string:tokens(SubsS, ":")]
+	    ),
+
+    Asks = lists:foldl(
+	     fun(any, _) -> [none, out, in];
+		(Ask, Asks) -> [Ask | Asks]
+	     end,
+	     [],
+	     [list_to_atom(S) || S <- string:tokens(AsksS, ":")]
+	    ),
+
+    Users = lists:foldl(
+	      fun("any", _) -> ["*", "*@*"];
+		 (U, Us) -> [U | Us]
+	      end,
+	      [],
+	      [S || S <- string:tokens(UsersS, ":")]
+	     ),
+
+    Contacts = lists:foldl(
+		 fun("any", _) -> ["*", "*@*"];
+		    (U, Us) -> [U | Us]
+		 end,
+		 [],
+		 [S || S <- string:tokens(ContactsS, ":")]
+		),
+
+    case rosteritem_purge({Action, Subs, Asks, Users, Contacts}) of
+	{atomic, ok} ->
+	    ok;
+	{error, Reason} ->
+	    io:format("Error purging rosteritems: ~p~n", [Reason]),
+	    error;
+	{badrpc, Reason} ->
+	    io:format("BadRPC purging rosteritems: ~p~n", [Reason]),
+	    error
+    end.
+
+%% @spec ({Action::atom(), Subs::[atom()], Asks::[atom()], User::string(), Contact::string()}) -> {atomic, ok}
+rosteritem_purge(Options) ->
+    Num_rosteritems = mnesia:table_info(roster, size),
+    io:format("There are ~p roster items in total.~n", [Num_rosteritems]),
+    Key = mnesia:dirty_first(roster),
+    ok = rip(Key, Options, {0, Num_rosteritems, 0, 0}),
+    {atomic, ok}.
+
+rip('$end_of_table', _Options, Counters) ->
+    print_progress_line(Counters),
+    ok;
+rip(Key, Options, {Pr, NT, NV, ND}) ->
+    Key_next = mnesia:dirty_next(roster, Key),
+    {Action, _, _, _, _} = Options,
+    ND2 = case decide_rip(Key, Options) of
+	      true ->
+		  apply_action(Action, Key),
+		  ND+1;
+	      false ->
+		  ND
+	  end,
+    NV2 = NV+1,
+    Pr2 = print_progress_line({Pr, NT, NV2, ND2}),
+    rip(Key_next, Options, {Pr2, NT, NV2, ND2}).
+
+apply_action(list, Key) ->
+    {User, Server, JID} = Key,
+    {RUser, RServer, _} = JID,
+    io:format("Matches: ~s@~s ~s@~s~n", [User, Server, RUser, RServer]);
+apply_action(delete, Key) ->
+    apply_action(list, Key),
+    mnesia:dirty_delete(roster, Key).
+
+print_progress_line({Pr, NT, NV, ND}) ->
+    Pr2 = trunc((NV/NT)*100),
+    case Pr == Pr2 of
+	true ->
+	    ok;
+	false ->
+	    io:format("Progress ~p% - visited ~p - deleted ~p~n", [Pr2, NV, ND])
+    end,
+    Pr2.
+
+decide_rip(Key, {_Action, Subs, Asks, User, Contact}) ->
+    case catch mnesia:dirty_read(roster, Key) of
+	[RI] ->
+	    lists:member(RI#roster.subscription, Subs)
+		andalso lists:member(RI#roster.ask, Asks)
+		andalso decide_rip_jid(RI#roster.us, User)
+		andalso decide_rip_jid(RI#roster.jid, Contact);
+	_ ->
+	    false
+    end.
+
+%% Returns true if the server of the JID is included in the servers
+decide_rip_jid({UName, UServer, _UResource}, Match_list) ->
+    decide_rip_jid({UName, UServer}, Match_list);
+decide_rip_jid({UName, UServer}, Match_list) ->
+    lists:any(
+      fun(Match_string) ->
+	      MJID = jlib:string_to_jid(Match_string),
+	      MName = MJID#jid.luser,
+	      MServer = MJID#jid.lserver,
+	      Is_server = is_glob_match(UServer, MServer),
+	      case MName of
+		  [] when UName == [] ->
+		      Is_server;
+		  [] ->
+		      false;
+		  _ ->
+		      Is_server
+			  andalso is_glob_match(UName, MName)
+	      end
+      end,
+      Match_list).
+
+%% Copied from ejabberd-2.0.0/src/acl.erl
+is_regexp_match(String, RegExp) ->
+    case regexp:first_match(String, RegExp) of
+	nomatch ->
+	    false;
+	{match, _, _} ->
+	    true;
+	{error, ErrDesc} ->
+	    io:format(
+	      "Wrong regexp ~p in ACL: ~p",
+	      [RegExp, lists:flatten(regexp:format_error(ErrDesc))]),
+	    false
+    end.
+is_glob_match(String, Glob) ->
+    is_regexp_match(String, regexp:sh_to_awk(Glob)).
-- 
1.6.6.1


ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch:
 ejabberdctl.template |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

--- NEW FILE ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch ---
>From 1a2f7fc0f4ba4ff9f9cf1ee409ce461000685eef Mon Sep 17 00:00:00 2001
From: Peter Lemenkov <lemenkov at gmail.com>
Date: Tue, 16 Feb 2010 16:30:05 +0300
Subject: [PATCH 5/9] Fedora-specific changes to ejabberdctl

Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
---
 src/ejabberdctl.template |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/ejabberdctl.template b/src/ejabberdctl.template
index 9ede77d..69c74d6 100644
--- a/src/ejabberdctl.template
+++ b/src/ejabberdctl.template
@@ -9,10 +9,10 @@ ERL_MAX_ETS_TABLES=1400
 
 # define default environment variables
 NODE=ejabberd
-HOST=localhost
+HOST=`hostname -s 2>/dev/null || echo "localhost"`
 ERLANG_NODE=$NODE@$HOST
 ERL=@erl@
-INSTALLUSER=@installuser@
+INSTALLUSER=ejabberd
 
 # parse command line parameters
 ARGS=
@@ -46,7 +46,7 @@ if [ "$LOGS_DIR" = "" ] ; then
     LOGS_DIR=@LOCALSTATEDIR@/log/ejabberd
 fi
 if [ "$SPOOLDIR" = "" ] ; then
-    SPOOLDIR=@LOCALSTATEDIR@/lib/ejabberd
+    SPOOLDIR=@LOCALSTATEDIR@/lib/ejabberd/spool
 fi
 if [ "$EJABBERD_DOC_PATH" = "" ] ; then
     EJABBERD_DOC_PATH=@DOCDIR@
@@ -62,7 +62,7 @@ EJID=`id -g $INSTALLUSER`
 EXEC_CMD="false"
 for GID in $GIDS; do
     if [ $GID -eq 0 ] ; then
-	EXEC_CMD="su ${INSTALLUSER} -p -c"
+	EXEC_CMD="/sbin/runuser -s /bin/bash -p ejabberd -c"
     fi
 done
 if [ "$ID" -eq "$EJID" ] ; then
-- 
1.6.6.1


ejabberd-0006-Support-to-authenticate-against-SASL-GSSAPI-http-www.patch:
 cyrsasl.erl           |   34 ++++++-----
 cyrsasl_anonymous.erl |    6 +-
 cyrsasl_digest.erl    |    4 -
 cyrsasl_gssapi.erl    |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++
 cyrsasl_plain.erl     |    5 +
 ejabberd.hrl          |    7 ++
 ejabberd_c2s.erl      |    8 ++
 ejabberd_net.erl      |   40 +++++++++++++
 8 files changed, 224 insertions(+), 23 deletions(-)

--- NEW FILE ejabberd-0006-Support-to-authenticate-against-SASL-GSSAPI-http-www.patch ---
>From 764adfa6bce78bc8615053a476c2bd38bdab349d Mon Sep 17 00:00:00 2001
From: Badlop <badlop at process-one.net>
Date: Tue, 29 Sep 2009 15:10:15 +0200
Subject: [PATCH 6/9] Support to authenticate against SASL GSSAPI http://www.ejabberd.im/cyrsasl_gssapi

---
 src/cyrsasl.erl           |   34 ++++++-----
 src/cyrsasl_anonymous.erl |    6 +-
 src/cyrsasl_digest.erl    |    4 +-
 src/cyrsasl_gssapi.erl    |  143 +++++++++++++++++++++++++++++++++++++++++++++
 src/cyrsasl_plain.erl     |    5 +-
 src/ejabberd.hrl          |    7 ++
 src/ejabberd_c2s.erl      |    8 ++-
 src/ejabberd_net.erl      |   39 ++++++++++++
 8 files changed, 224 insertions(+), 22 deletions(-)
 create mode 100644 src/cyrsasl_gssapi.erl
 create mode 100644 src/ejabberd_net.erl

diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl
index 121ef6d..192d5b5 100644
--- a/src/cyrsasl.erl
+++ b/src/cyrsasl.erl
@@ -30,19 +30,20 @@
 -export([start/0,
 	 register_mechanism/3,
 	 listmech/1,
-	 server_new/7,
+	 server_new/8,
 	 server_start/3,
 	 server_step/2]).
 
 -record(sasl_mechanism, {mechanism, module, require_plain_password}).
--record(sasl_state, {service, myname, realm,
-		     get_password, check_password, check_password_digest,
-		     mech_mod, mech_state}).
+-record(sasl_state, {service, myname,
+		     mech_mod, mech_state, ctx}).
+
+-include("ejabberd.hrl").
 
 -export([behaviour_info/1]).
 
 behaviour_info(callbacks) ->
-    [{mech_new, 4}, {mech_step, 2}];
+    [{mech_new, 1}, {mech_step, 2}];
 behaviour_info(_Other) ->
     undefined.
 
@@ -50,6 +51,7 @@ start() ->
     ets:new(sasl_mechanism, [named_table,
 			     public,
 			     {keypos, #sasl_mechanism.mechanism}]),
+    cyrsasl_gssapi:start([]),
     cyrsasl_plain:start([]),
     cyrsasl_digest:start([]),
     cyrsasl_anonymous:start([]),
@@ -113,24 +115,26 @@ listmech(Host) ->
     filter_anonymous(Host, Mechs).
 
 server_new(Service, ServerFQDN, UserRealm, _SecFlags,
-	   GetPassword, CheckPassword, CheckPasswordDigest) ->
+	   GetPassword, CheckPassword, CheckPasswordDigest, FQDN) ->
+    Ctx = #sasl_ctx{
+      host = ServerFQDN,
+      realm = UserRealm,
+      get_password = GetPassword,
+      check_password = CheckPassword,
+      check_password_digest= CheckPasswordDigest,
+      fqdn = FQDN
+     },
+     
     #sasl_state{service = Service,
 		myname = ServerFQDN,
-		realm = UserRealm,
-		get_password = GetPassword,
-		check_password = CheckPassword,
-		check_password_digest= CheckPasswordDigest}.
+		ctx = Ctx}.
 
 server_start(State, Mech, ClientIn) ->
     case lists:member(Mech, listmech(State#sasl_state.myname)) of
 	true ->
 	    case ets:lookup(sasl_mechanism, Mech) of
 		[#sasl_mechanism{module = Module}] ->
-		    {ok, MechState} = Module:mech_new(
-					State#sasl_state.myname,
-					State#sasl_state.get_password,
-					State#sasl_state.check_password,
-					State#sasl_state.check_password_digest),
+		    {ok, MechState} = Module:mech_new(State#sasl_state.ctx),
 		    server_step(State#sasl_state{mech_mod = Module,
 						 mech_state = MechState},
 				ClientIn);
diff --git a/src/cyrsasl_anonymous.erl b/src/cyrsasl_anonymous.erl
index 2b3ba36..ec75f40 100644
--- a/src/cyrsasl_anonymous.erl
+++ b/src/cyrsasl_anonymous.erl
@@ -27,12 +27,14 @@
 
 -module(cyrsasl_anonymous).
 
--export([start/1, stop/0, mech_new/4, mech_step/2]).
+-export([start/1, stop/0, mech_new/1, mech_step/2]).
 
 -behaviour(cyrsasl).
 
 -record(state, {server}).
 
+-include("ejabberd.hrl").
+
 start(_Opts) ->
     cyrsasl:register_mechanism("ANONYMOUS", ?MODULE, false),
     ok.
@@ -40,7 +42,7 @@ start(_Opts) ->
 stop() ->
     ok.
 
-mech_new(Host, _GetPassword, _CheckPassword, _CheckPasswordDigest) ->
+mech_new(#sasl_ctx{host=Host}) ->
     {ok, #state{server = Host}}.
 
 mech_step(State, _ClientIn) ->
diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl
index 2a7ce2a..a354778 100644
--- a/src/cyrsasl_digest.erl
+++ b/src/cyrsasl_digest.erl
@@ -29,7 +29,7 @@
 
 -export([start/1,
 	 stop/0,
-	 mech_new/4,
+	 mech_new/1,
 	 mech_step/2]).
 
 -include("ejabberd.hrl").
@@ -45,7 +45,7 @@ start(_Opts) ->
 stop() ->
     ok.
 
-mech_new(Host, GetPassword, _CheckPassword, CheckPasswordDigest) ->
+mech_new(#sasl_ctx{host=Host, get_password=GetPassword, check_password_digest=CheckPasswordDigest}) ->
     {ok, #state{step = 1,
 		nonce = randoms:get_string(),
 		host = Host,
diff --git a/src/cyrsasl_gssapi.erl b/src/cyrsasl_gssapi.erl
new file mode 100644
index 0000000..d292565
--- /dev/null
+++ b/src/cyrsasl_gssapi.erl
@@ -0,0 +1,143 @@
+%%%----------------------------------------------------------------------
+%%% File    : cyrsasl_gssapi.erl
+%%% Author  : Mikael Magnusson <mikma at users.sourceforge.net>
+%%% Purpose : GSSAPI SASL mechanism
+%%% Created : 1 June 2007 by Mikael Magnusson <mikma at users.sourceforge.net>
+%%% Id      : $Id: $
+%%%----------------------------------------------------------------------
+%%%
+%%% Copyright (C) 2007  Mikael Magnusson <mikma at users.sourceforge.net>
+%%%
+%%% Permission is hereby granted, free of charge, to any person
+%%% obtaining a copy of this software and associated documentation
+%%% files (the "Software"), to deal in the Software without
+%%% restriction, including without limitation the rights to use, copy,
+%%% modify, merge, publish, distribute, sublicense, and/or sell copies
+%%% of the Software, and to permit persons to whom the Software is
+%%% furnished to do so, subject to the following conditions:
+%%%
+%%% The above copyright notice and this permission notice shall be
+%%% included in all copies or substantial portions of the Software.
+%%%
+%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+%%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+%%% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+%%% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+%%% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+%%% SOFTWARE.
+%%%
+
+%%%
+%%% configuration options:
+%%% {sasl_realm, "<Kerberos realm>"}.
+%%%
+%%% environment variables:
+%%% KRB5_KTNAME
+%%%
+
+-module(cyrsasl_gssapi).
+-author('mikma at users.sourceforge.net').
+-vsn('$Revision: $ ').
+
+-include("ejabberd.hrl").
+
+-export([start/1,
+	 stop/0,
+	 mech_new/1,
+	 mech_step/2]).
+
+-behaviour(cyrsasl).
+
+-define(SERVER, cyrsasl_gssapi).
+-define(MSG, ?DEBUG).
+
+-record(state, {sasl,
+		needsmore=true,
+		step=0,
+		host,
+		authid,
+		authzid,
+		authrealm}).
+
+start(_Opts) ->
+    ChildSpec =
+	{?SERVER,
+	 {esasl, start_link, [{local, ?SERVER}]},
+	 transient,
+	 1000,
+	 worker,
+	 [esasl]},
+
+    {ok, _Pid} = supervisor:start_child(ejabberd_sup, ChildSpec),
+
+    cyrsasl:register_mechanism("GSSAPI", ?MODULE, false).
+
+stop() ->
+    esasl:stop(?SERVER),
+    supervisor:terminate_child(ejabberd_sup, ?SERVER),
+    supervisor:delete_child(ejabberd_sup, ?SERVER).
+
+mech_new(#sasl_ctx{host=Host, fqdn=FQDN}) ->
+    ?MSG("mech_new ~p ~p~n", [Host, FQDN]),
+    {ok, Sasl} = esasl:server_start(?SERVER, "GSSAPI", "xmpp", FQDN),
+    {ok, #state{sasl=Sasl,host=Host}}.
+
+mech_step(State, ClientIn) when is_list(ClientIn) ->
+    catch do_step(State, ClientIn).
+
+do_step(#state{needsmore=false}=State, _) ->
+    check_user(State);
+do_step(#state{needsmore=true,sasl=Sasl,step=Step}=State, ClientIn) ->
+    ?MSG("mech_step~n", []),
+    case esasl:step(Sasl, list_to_binary(ClientIn)) of
+	{ok, RspAuth} ->
+	    ?MSG("ok~n", []),
+	    {ok, Display_name} = esasl:property_get(Sasl, gssapi_display_name),
+	    {ok, Authzid} = esasl:property_get(Sasl, authzid),
+	    {Authid, [$@ | Auth_realm]} =
+		lists:splitwith(fun(E)->E =/= $@ end, Display_name),
+	    State1 = State#state{authid=Authid,
+				 authzid=Authzid,
+				 authrealm=Auth_realm},
+	    handle_step_ok(State1, binary_to_list(RspAuth));
+	{needsmore, RspAuth} ->
+	    ?MSG("needsmore~n", []),
+	    if (Step > 0) and (ClientIn =:= []) and (RspAuth =:= <<>>) ->
+		    {error, "not-authorized"};
+		true ->
+		    {continue, binary_to_list(RspAuth),
+		     State#state{step=Step+1}}
+	    end;
+	{error, _} ->
+	    {error, "not-authorized"}
+    end.
+
+handle_step_ok(State, []) ->
+    check_user(State);
+handle_step_ok(#state{step=Step}=State, RspAuth) ->
+    ?MSG("continue~n", []),
+    {continue, RspAuth, State#state{needsmore=false,step=Step+1}}.
+
+check_user(#state{authid=Authid,authzid=Authzid,
+		  authrealm=Auth_realm,host=Host}) ->
+    Realm = ejabberd_config:get_local_option({sasl_realm, Host}),
+
+    if Realm =/= Auth_realm ->
+	    ?MSG("bad realm ~p (expected ~p)~n",[Auth_realm, Realm]),
+	    throw({error, "not-authorized"});
+       true ->
+	    ok
+    end,
+
+    case ejabberd_auth:is_user_exists(Authid, Host) of
+	false ->
+	    ?MSG("bad user ~p~n",[Authid]),
+	    throw({error, "not-authorized"});
+	true ->
+	    ok
+    end,
+
+    ?MSG("GSSAPI authenticated ~p ~p~n", [Authid, Authzid]),
+    {ok, [{username, Authid}, {authzid, Authzid}]}.
diff --git a/src/cyrsasl_plain.erl b/src/cyrsasl_plain.erl
index 129fb8b..d920463 100644
--- a/src/cyrsasl_plain.erl
+++ b/src/cyrsasl_plain.erl
@@ -27,10 +27,11 @@
 -module(cyrsasl_plain).
 -author('alexey at process-one.net').
 
--export([start/1, stop/0, mech_new/4, mech_step/2, parse/1]).
+-export([start/1, stop/0, mech_new/1, mech_step/2, parse/1]).
 
 -behaviour(cyrsasl).
 
+-include("ejabberd.hrl").
 -record(state, {check_password}).
 
 start(_Opts) ->
@@ -40,7 +41,7 @@ start(_Opts) ->
 stop() ->
     ok.
 
-mech_new(_Host, _GetPassword, CheckPassword, _CheckPasswordDigest) ->
+mech_new(#sasl_ctx{check_password=CheckPassword}) ->
     {ok, #state{check_password = CheckPassword}}.
 
 mech_step(State, ClientIn) ->
diff --git a/src/ejabberd.hrl b/src/ejabberd.hrl
index e1f0cfd..39a41d5 100644
--- a/src/ejabberd.hrl
+++ b/src/ejabberd.hrl
@@ -59,3 +59,10 @@
 -define(CRITICAL_MSG(Format, Args),
     ejabberd_logger:critical_msg(?MODULE,?LINE,Format, Args)).
 
+-record(sasl_ctx, {
+	  host,
+	  realm,
+	  get_password,
+	  check_password,
+	  check_password_digest,
+	  fqdn}).
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 6df6766..8edc1a0 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -69,6 +69,7 @@
 -record(state, {socket,
 		sockmod,
 		socket_monitor,
+		fqdn,
 		xml_socket,
 		streamid,
 		sasl_state,
@@ -206,9 +207,11 @@ init([{SockMod, Socket}, Opts]) ->
 			Socket
 		end,
 	    SocketMonitor = SockMod:monitor(Socket1),
+	    {ok, FQDN} = ejabberd_net:gethostname(Socket),
 	    {ok, wait_for_stream, #state{socket         = Socket1,
 					 sockmod        = SockMod,
 					 socket_monitor = SocketMonitor,
+					 fqdn           = FQDN,
 					 xml_socket     = XMLSocket,
 					 zlib           = Zlib,
 					 tls            = TLS,
@@ -252,6 +255,8 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
 			    send_header(StateData, Server, "1.0", DefaultLang),
 			    case StateData#state.authenticated of
 				false ->
+				    FQDN = StateData#state.fqdn,
+				    ?INFO_MSG("FQDN: ~p~n", [FQDN]),
 				    SASLState =
 					cyrsasl:server_new(
 					  "jabber", Server, "", [],
@@ -266,7 +271,8 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
 					  fun(U, P, D, DG) ->
 						  ejabberd_auth:check_password_with_authmodule(
 						    U, Server, P, D, DG)
-					  end),
+					  end,
+					  FQDN),
 				    Mechs = lists:map(
 					      fun(S) ->
 						      {xmlelement, "mechanism", [],
diff --git a/src/ejabberd_net.erl b/src/ejabberd_net.erl
new file mode 100644
index 0000000..e9ab70a
--- /dev/null
+++ b/src/ejabberd_net.erl
@@ -0,0 +1,39 @@
+%%%----------------------------------------------------------------------
+%%% File    : ejabberd_net.erl
+%%% Author  : Mikael Magnusson <mikma at users.sourceforge.net>
+%%% Purpose : Serve C2S connection
+%%% Created : 6 June 2007 by Mikael Magnusson <mikma at users.sourceforge.net>
+%%% Id      : $Id: $
+%%%----------------------------------------------------------------------
+
+-module(ejabberd_net).
+-author('mikma at users.sourceforge.net').
+%% -update_info({update, 0}).
+
+-export([gethostname/1]).
+
+-include("ejabberd.hrl").
+-include_lib("kernel/include/inet.hrl").
+
+%% Copied from ejabberd_socket.erl of ejabberd 2.0.3
+-record(socket_state, {sockmod, socket, receiver}).
+
+%%
+%% gethostname(Socket)
+%%
+gethostname(Socket) ->
+    ?INFO_MSG("gethostname ~p~n", [Socket]),
+%%     {ok, "skinner.hem.za.org"}.
+
+    case ejabberd_config:get_local_option({sasl_fqdn, ?MYNAME}) of
+      undefined ->
+        {ok, {Addr, _Port}} = inet:sockname(Socket#socket_state.socket),
+        case inet:gethostbyaddr(Addr) of
+            {ok, HostEnt} when is_record(HostEnt, hostent) ->
+                {ok, HostEnt#hostent.h_name};
+            {error, What} ->
+                ?ERROR_MSG("Error in gethostname:~nSocket: ~p~nError: ~p", [What]),
+                error
+        end;
+      F -> {ok, F}
+    end.
-- 
1.6.6.1


ejabberd-0007-Fixed-typo.patch:
 ejabberd_net.erl |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- NEW FILE ejabberd-0007-Fixed-typo.patch ---
>From d4e215baf7edfb1fe534d91fc83eaeb9426589a0 Mon Sep 17 00:00:00 2001
From: Peter Lemenkov <lemenkov at gmail.com>
Date: Fri, 5 Mar 2010 17:48:51 +0300
Subject: [PATCH 7/9] Fixed typo

Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
---
 src/ejabberd_net.erl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/ejabberd_net.erl b/src/ejabberd_net.erl
index e9ab70a..d887c23 100644
--- a/src/ejabberd_net.erl
+++ b/src/ejabberd_net.erl
@@ -32,7 +32,7 @@ gethostname(Socket) ->
             {ok, HostEnt} when is_record(HostEnt, hostent) ->
                 {ok, HostEnt#hostent.h_name};
             {error, What} ->
-                ?ERROR_MSG("Error in gethostname:~nSocket: ~p~nError: ~p", [What]),
+                ?ERROR_MSG("Error in gethostname:~nSocket: ~p~nError: ~p at Addr ~p", [Socket, What, Addr]),
                 error
         end;
       F -> {ok, F}
-- 
1.6.6.1


ejabberd-0008-Quick-fix-for-error-nxdomain.patch:
 ejabberd_net.erl |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- NEW FILE ejabberd-0008-Quick-fix-for-error-nxdomain.patch ---
>From 2bbffda3b07c07b6abf5d28e0b6af4094b56d981 Mon Sep 17 00:00:00 2001
From: Peter Lemenkov <lemenkov at gmail.com>
Date: Fri, 5 Mar 2010 21:13:35 +0300
Subject: [PATCH 8/9] Quick fix for {error,nxdomain}

Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
---
 src/ejabberd_net.erl |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/src/ejabberd_net.erl b/src/ejabberd_net.erl
index d887c23..b6943e1 100644
--- a/src/ejabberd_net.erl
+++ b/src/ejabberd_net.erl
@@ -31,6 +31,9 @@ gethostname(Socket) ->
         case inet:gethostbyaddr(Addr) of
             {ok, HostEnt} when is_record(HostEnt, hostent) ->
                 {ok, HostEnt#hostent.h_name};
+	    {error, nxdomain} ->
+		    % Quick fix
+		    {ok, inet_parse:ntoa(Addr)};
             {error, What} ->
                 ?ERROR_MSG("Error in gethostname:~nSocket: ~p~nError: ~p at Addr ~p", [Socket, What, Addr]),
                 error
-- 
1.6.6.1


ejabberd-0009-Replace-MSG-with-DEBUG.patch:
 cyrsasl_gssapi.erl |   18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

--- NEW FILE ejabberd-0009-Replace-MSG-with-DEBUG.patch ---
>From 94d7e120d3ad6072774286df2d4b26ea2fcd34f7 Mon Sep 17 00:00:00 2001
From: Badlop <badlop at process-one.net>
Date: Mon, 8 Mar 2010 22:35:12 +0100
Subject: [PATCH 9/9] Replace MSG with DEBUG

---
 src/cyrsasl_gssapi.erl |   17 ++++++++---------
 1 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/src/cyrsasl_gssapi.erl b/src/cyrsasl_gssapi.erl
index d292565..24a3796 100644
--- a/src/cyrsasl_gssapi.erl
+++ b/src/cyrsasl_gssapi.erl
@@ -51,7 +51,6 @@
 -behaviour(cyrsasl).
 
 -define(SERVER, cyrsasl_gssapi).
--define(MSG, ?DEBUG).
 
 -record(state, {sasl,
 		needsmore=true,
@@ -80,7 +79,7 @@ stop() ->
     supervisor:delete_child(ejabberd_sup, ?SERVER).
 
 mech_new(#sasl_ctx{host=Host, fqdn=FQDN}) ->
-    ?MSG("mech_new ~p ~p~n", [Host, FQDN]),
+    ?DEBUG("mech_new ~p ~p~n", [Host, FQDN]),
     {ok, Sasl} = esasl:server_start(?SERVER, "GSSAPI", "xmpp", FQDN),
     {ok, #state{sasl=Sasl,host=Host}}.
 
@@ -90,10 +89,10 @@ mech_step(State, ClientIn) when is_list(ClientIn) ->
 do_step(#state{needsmore=false}=State, _) ->
     check_user(State);
 do_step(#state{needsmore=true,sasl=Sasl,step=Step}=State, ClientIn) ->
-    ?MSG("mech_step~n", []),
+    ?DEBUG("mech_step~n", []),
     case esasl:step(Sasl, list_to_binary(ClientIn)) of
 	{ok, RspAuth} ->
-	    ?MSG("ok~n", []),
+	    ?DEBUG("ok~n", []),
 	    {ok, Display_name} = esasl:property_get(Sasl, gssapi_display_name),
 	    {ok, Authzid} = esasl:property_get(Sasl, authzid),
 	    {Authid, [$@ | Auth_realm]} =
@@ -103,7 +102,7 @@ do_step(#state{needsmore=true,sasl=Sasl,step=Step}=State, ClientIn) ->
 				 authrealm=Auth_realm},
 	    handle_step_ok(State1, binary_to_list(RspAuth));
 	{needsmore, RspAuth} ->
-	    ?MSG("needsmore~n", []),
+	    ?DEBUG("needsmore~n", []),
 	    if (Step > 0) and (ClientIn =:= []) and (RspAuth =:= <<>>) ->
 		    {error, "not-authorized"};
 		true ->
@@ -117,7 +116,7 @@ do_step(#state{needsmore=true,sasl=Sasl,step=Step}=State, ClientIn) ->
 handle_step_ok(State, []) ->
     check_user(State);
 handle_step_ok(#state{step=Step}=State, RspAuth) ->
-    ?MSG("continue~n", []),
+    ?DEBUG("continue~n", []),
     {continue, RspAuth, State#state{needsmore=false,step=Step+1}}.
 
 check_user(#state{authid=Authid,authzid=Authzid,
@@ -125,7 +124,7 @@ check_user(#state{authid=Authid,authzid=Authzid,
     Realm = ejabberd_config:get_local_option({sasl_realm, Host}),
 
     if Realm =/= Auth_realm ->
-	    ?MSG("bad realm ~p (expected ~p)~n",[Auth_realm, Realm]),
+	    ?DEBUG("bad realm ~p (expected ~p)~n",[Auth_realm, Realm]),
 	    throw({error, "not-authorized"});
        true ->
 	    ok
@@ -133,11 +132,11 @@ check_user(#state{authid=Authid,authzid=Authzid,
 
     case ejabberd_auth:is_user_exists(Authid, Host) of
 	false ->
-	    ?MSG("bad user ~p~n",[Authid]),
+	    ?DEBUG("bad user ~p~n",[Authid]),
 	    throw({error, "not-authorized"});
 	true ->
 	    ok
     end,
 
-    ?MSG("GSSAPI authenticated ~p ~p~n", [Authid, Authzid]),
+    ?DEBUG("GSSAPI authenticated ~p ~p~n", [Authid, Authzid]),
     {ok, [{username, Authid}, {authzid, Authzid}]}.
-- 
1.6.6.1



Index: .cvsignore
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-11/.cvsignore,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -p -r1.17 -r1.18
--- .cvsignore	25 Jan 2010 12:48:52 -0000	1.17
+++ .cvsignore	12 Mar 2010 16:04:13 -0000	1.18
@@ -1 +1 @@
-ejabberd-2.1.2.tar.gz
+ejabberd-2.1.3.tar.gz


Index: ejabberd.spec
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-11/ejabberd.spec,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -p -r1.45 -r1.46
--- ejabberd.spec	29 Jan 2010 13:15:24 -0000	1.45
+++ ejabberd.spec	12 Mar 2010 16:04:15 -0000	1.46
@@ -11,8 +11,8 @@
 %endif
 
 Name:           ejabberd
-Version:        2.1.2
-Release:        2%{?dist}
+Version:        2.1.3
+Release:        1%{?dist}
 Summary:        A distributed, fault-tolerant Jabber/XMPP server
 
 Group:          Applications/Internet
@@ -39,21 +39,24 @@ Source9:        ejabberdctl.pam
 Source10:       ejabberdctl.apps
 Source11:       ejabberd.pam
 
-# BZ# 439583, 452326, 451554, 465196, 502361
-Patch2: ejabberd-ejabberdctl_fix.diff
 # Use ejabberd as an example for PAM service name
-Patch3: ejabberd-ejabberd_cfg_pam_name.diff
+Patch1: ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch
 # Mention mod_ctlextra as an ejabberd module
-Patch5: ejabberd-mod_ctlextra_mentioning_in_ejabberd_app.diff
+Patch2: ejabberd-0002-Mention-mod_ctlextra-as-an-ejabberd-module.patch
 # fixed delays in s2s connections
-Patch8: ejabberd-fixed_delays_in_s2s.patch
+Patch3: ejabberd-0003-Fixed-delays-in-s2s-connections.patch
 # Introducing mod_admin_extra
-Patch10: ejabberd-mod_admin_extra.patch
-# see https://support.process-one.net/browse/EJAB-1173
-# https://forge.process-one.net/rdiff/ejabberd/branches/ejabberd-2.1.x/src/ejabberd_c2s.erl?r1=2911&r2=2936&u&N
-Patch11: ejabberd-c2s_dos_fix.diff
-# See this link: http://lists.jabber.ru/pipermail/ejabberd/2010-January/005819.html
-Patch12: ejabberdctl-support-concurrent-connections.patch
+Patch4: ejabberd-0004-Introducing-mod_admin_extra.patch
+# BZ# 439583, 452326, 451554, 465196, 502361
+Patch5: ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch
+# http://www.ejabberd.im/cyrsasl_gssapi
+Patch6: ejabberd-0006-Support-to-authenticate-against-SASL-GSSAPI-http-www.patch
+# Typo in GSSAPI modules (sent upstream)
+Patch7: ejabberd-0007-Fixed-typo.patch
+# Quick fix for {error,nxdomain} issue
+Patch8: ejabberd-0008-Quick-fix-for-error-nxdomain.patch
+# Cleanup redundant defines
+Patch9: ejabberd-0009-Replace-MSG-with-DEBUG.patch
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -79,9 +82,14 @@ Provides: user(%{name}) = %{uid}
 Provides: group(%{name}) = %{uid}
 
 Requires:       erlang
+Requires:       erlang-esasl
 Requires:       usermode
 # for flock in ejabberdctl
+%if %{defined fedora}
 Requires:	util-linux-ng
+%else
+Requires:	util-linux
+%endif
 
 
 %description
@@ -99,13 +107,16 @@ Documentation for ejabberd.
 
 %prep
 %setup -q
-%patch3 -p0 -b .pam_name
-%patch5 -p0 -b .mod_ctlextra
-%patch8 -p0 -b .s2s
-%patch10 -p1 -b .mod_admin_extra
-%patch11 -p2 -b .EJAB_1173
-%patch12 -p1 -b .concurrent
-%patch2 -p0 -b .fix_ctl
+
+%patch1 -p1 -b .pam_name
+%patch2 -p1 -b .mod_ctlextra
+%patch3 -p1 -b .s2s_delays
+%patch4 -p1 -b .mod_admin_extra
+%patch5 -p1 -b .fedora_specific
+%patch6 -p1 -b .gssapi
+%patch7 -p1 -b .gssapi_typo
+%patch8 -p1 -b .nxdomain_fix
+%patch9 -p1 -b .gssapi_cleanup
 
 dos2unix src/odbc/mssql2000.sql
 
@@ -117,7 +128,7 @@ cp %{S:7} src
 
 %build
 pushd src
-%configure --enable-odbc --enable-debug --enable-pam
+%configure --enable-odbc --enable-pam
 # doesn't builds on SMP currently
 make
 popd
@@ -180,37 +191,42 @@ rm -rf %{buildroot}%{_docdir}/%{name}
 %{__fe_groupadd} %{uid} -r %{name} &>/dev/null || :
 %{__fe_useradd} %{uid} -r -s /sbin/nologin -d /var/lib/ejabberd -M \
 			-c 'ejabberd' -g %{name} %{name} &>/dev/null || :
-# we should backup DB in every upgrade
-if ejabberdctl status >/dev/null ; then
-	# Use timestamp to make database restoring easier
-	TIME=$(date +%Y-%m-%dT%H:%M:%S)
-	BACKUPDIR=$(mktemp -d -p /var/tmp/ ejabberd-$TIME.XXXXXX)
-	chown ejabberd:ejabberd $BACKUPDIR
-	BACKUP=$BACKUPDIR/ejabberd-database
-	ejabberdctl backup $BACKUP
-	# Change ownership to root:root because ejabberd user might be
-	# removed on package removal.
-	chown -R root:root $BACKUPDIR
-	chmod 700 $BACKUPDIR
-	echo
-	echo The ejabberd database has been backed up to $BACKUP.
-	echo
-fi
 
-# fix cookie path (since ver. 2.1.0 cookie stored in /var/lib/ejabberd/spool
-# rather than in /var/lib/ejabberd
-if [ -f /var/lib/ejabberd/.erlang.cookie ]; then
-	cp -pf /var/lib/ejabberd/{,spool/}.erlang.cookie
-	echo
-	echo The ejabberd cookie file was moved.
-	echo Please remove old one from /var/lib/ejabberd/.erlang.cookie
-	echo
+
+if [ $1 -gt 1 ]; then
+	# we should backup DB in every upgrade
+	if ejabberdctl status >/dev/null ; then
+		# Use timestamp to make database restoring easier
+		TIME=$(date +%Y-%m-%dT%H:%M:%S)
+		BACKUPDIR=$(mktemp -d -p /var/tmp/ ejabberd-$TIME.XXXXXX)
+		chown ejabberd:ejabberd $BACKUPDIR
+		BACKUP=$BACKUPDIR/ejabberd-database
+		ejabberdctl backup $BACKUP
+		# Change ownership to root:root because ejabberd user might be
+		# removed on package removal.
+		chown -R root:root $BACKUPDIR
+		chmod 700 $BACKUPDIR
+		echo
+		echo The ejabberd database has been backed up to $BACKUP.
+		echo
+	fi
+
+	# fix cookie path (since ver. 2.1.0 cookie stored in /var/lib/ejabberd/spool
+	# rather than in /var/lib/ejabberd
+	if [ -f /var/lib/ejabberd/.erlang.cookie ]; then
+		cp -pu /var/lib/ejabberd/{,spool/}.erlang.cookie
+		echo
+		echo The ejabberd cookie file was moved.
+		echo Please delete old one from /var/lib/ejabberd/.erlang.cookie
+		echo
+	fi
 fi
 
 
 %post
 /sbin/chkconfig --add %{name}
 
+# Create SSL certificate with default values if it doesn't exist
 (cd /etc/ejabberd
 if [ ! -f ejabberd.pem ]
 then
@@ -298,6 +314,7 @@ rm -rf %{buildroot}
 %{_libdir}/%{name}/include/mod_roster.hrl
 %{_libdir}/%{name}/include/web/ejabberd_http.hrl
 %{_libdir}/%{name}/include/web/ejabberd_web_admin.hrl
+%{_libdir}/%{name}/include/web/http_bind.hrl
 %{_libdir}/%{name}/priv/bin/captcha.sh
 %attr(4750,root,ejabberd) %{_libdir}/%{name}/priv/bin/epam
 %{_libdir}/%{name}/priv/lib/ejabberd_zlib_drv.so
@@ -345,14 +362,32 @@ rm -rf %{buildroot}
 %doc doc/release_notes_2.0.5.txt
 %doc doc/release_notes_2.1.0.txt
 %doc doc/release_notes_2.1.1.txt
+%doc doc/release_notes_2.1.2.txt
+%doc doc/release_notes_2.1.3.txt
 %doc doc/webadmmain.png
 %doc doc/webadmmainru.png
 %doc doc/yozhikheader.png
 
 %changelog
+* Fri Mar 12 2010 Peter Lemenkov <lemenkov at gmail.com> 2.1.3-1
+- Ver. 2.1.3
+- Patches rebased
+
+* Fri Mar  5 2010 Peter Lemenkov <lemenkov at gmail.com> 2.1.2-4
+- Fixed issue with {erorr,nxdomain}
+
+* Tue Feb 16 2010 Peter Lemenkov <lemenkov at gmail.com> 2.1.2-3
+- Do not try to backup DB on every fresh install
+- Do not force copying old erlang cookie file
+- Add missing release notes for ver. 2.1.2
+- Require erlang-esasl for krb5 support
+- No such %%configure option - --enable-debug
+- Patches were rebased and renumbered
+- Add new BR util-linux(-ng)
+
 * Fri Jan 29 2010 Peter Lemenkov <lemenkov at gmail.com> 2.1.2-2
 - Fixed BZ #559925 (EJAB-1173)
-- Changed order of rpmbuild targets in sthis spec to more natural one.
+- Changed order of rpmbuild targets in this spec to more natural one.
 
 * Mon Jan 18 2010 Peter Lemenkov <lemenkov at gmail.com> 2.1.2-1
 - Ver. 2.1.2


Index: import.log
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-11/import.log,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -p -r1.18 -r1.19
--- import.log	29 Jan 2010 13:15:24 -0000	1.18
+++ import.log	12 Mar 2010 16:04:15 -0000	1.19
@@ -16,3 +16,4 @@ ejabberd-2_1_0-2_fc12:F-11:ejabberd-2.1.
 ejabberd-2_1_1-1_fc12:F-11:ejabberd-2.1.1-1.fc12.src.rpm:1261656564
 ejabberd-2_1_2-1_fc12:F-11:ejabberd-2.1.2-1.fc12.src.rpm:1264423698
 ejabberd-2_1_2-2_fc12:F-11:ejabberd-2.1.2-2.fc12.src.rpm:1264770903
+ejabberd-2_1_3-1_fc12:F-11:ejabberd-2.1.3-1.fc12.src.rpm:1268409828


Index: sources
===================================================================
RCS file: /cvs/pkgs/rpms/ejabberd/F-11/sources,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -p -r1.19 -r1.20
--- sources	25 Jan 2010 12:48:52 -0000	1.19
+++ sources	12 Mar 2010 16:04:15 -0000	1.20
@@ -1 +1 @@
-9102802ae19312c26f85ceb977b519aa  ejabberd-2.1.2.tar.gz
+e5c87eda5312a6e8a53df0f9b4844b69  ejabberd-2.1.3.tar.gz


--- ejabberd-c2s_dos_fix.diff DELETED ---


--- ejabberd-ejabberd_cfg_pam_name.diff DELETED ---


--- ejabberd-ejabberdctl_fix.diff DELETED ---


--- ejabberd-fixed_delays_in_s2s.patch DELETED ---


--- ejabberd-mod_admin_extra.patch DELETED ---


--- ejabberd-mod_ctlextra_mentioning_in_ejabberd_app.diff DELETED ---


--- ejabberdctl-support-concurrent-connections.patch DELETED ---



More information about the scm-commits mailing list