[ejabberd] Updated mod_Admin_extra to work with R15B (see rhbz #840039)

Peter Lemenkov peter at fedoraproject.org
Sun Jul 15 07:06:56 UTC 2012


commit 17b4fc696481fd38f8f237e9ed5df1ecbd7bfe38
Author: Peter Lemenkov <lemenkov at gmail.com>
Date:   Sun Jul 15 11:06:44 2012 +0400

    Updated mod_Admin_extra to work with R15B (see rhbz #840039)
    
    Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>

 ...-service-example-name-to-match-actual-one.patch |    4 +-
 ...02-Add-mod_ctlextra-as-an-ejabberd-module.patch |  936 ---------------
 ...berd-0002-Fixed-delays-in-s2s-connections.patch |    6 +-
 ...ejabberd-0003-Introducing-mod_admin_extra.patch |  483 ++++++--
 ...04-Fedora-specific-changes-to-ejabberdctl.patch |    6 +-
 ...Install-.so-objects-with-0755-permissions.patch |    6 +-
 ...-Use-versioned-directory-for-storing-docs.patch |    6 +-
 ...L-GSSAPI-authentication-thanks-to-Mikael-.patch |    6 +-
 ...08-Disable-INET_DIST_INTERFACE-by-default.patch |    6 +-
 ...09-Added-old-modules-for-Active-Directory.patch | 1266 --------------------
 ejabberd.spec                                      |   49 +-
 11 files changed, 428 insertions(+), 2346 deletions(-)
---
diff --git a/ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch b/ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch
index bdffb3f..a7db2a3 100644
--- a/ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch
+++ b/ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch
@@ -1,7 +1,7 @@
 From 72718b8fcbb19b34e348efcb874fa480e83d7a02 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 01/10] Fix PAM service example name to match actual one
+Subject: [PATCH 1/8] Fix PAM service example name to match actual one
 
 Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
 ---
@@ -22,5 +22,5 @@ index a4068ad..9b24a4a 100644
  %%
  %% Authentication using LDAP
 -- 
-1.7.10.1
+1.7.10.4
 
diff --git a/ejabberd-0003-Fixed-delays-in-s2s-connections.patch b/ejabberd-0002-Fixed-delays-in-s2s-connections.patch
similarity index 93%
rename from ejabberd-0003-Fixed-delays-in-s2s-connections.patch
rename to ejabberd-0002-Fixed-delays-in-s2s-connections.patch
index 78ff318..d161c21 100644
--- a/ejabberd-0003-Fixed-delays-in-s2s-connections.patch
+++ b/ejabberd-0002-Fixed-delays-in-s2s-connections.patch
@@ -1,7 +1,7 @@
-From 95f2c9bb7654ea321f052bb29c905a71471d85c0 Mon Sep 17 00:00:00 2001
+From 30037ec8a73263f0d0524b2e1409736838cbb33b 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 03/10] Fixed delays in s2s connections.
+Subject: [PATCH 2/8] 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
@@ -49,5 +49,5 @@ index 65711fa..cab413f 100644
      end;
  open_socket(closed, StateData) ->
 -- 
-1.7.10.1
+1.7.10.4
 
diff --git a/ejabberd-0004-Introducing-mod_admin_extra.patch b/ejabberd-0003-Introducing-mod_admin_extra.patch
similarity index 72%
rename from ejabberd-0004-Introducing-mod_admin_extra.patch
rename to ejabberd-0003-Introducing-mod_admin_extra.patch
index bdc6eea..c2ed978 100644
--- a/ejabberd-0004-Introducing-mod_admin_extra.patch
+++ b/ejabberd-0003-Introducing-mod_admin_extra.patch
@@ -1,26 +1,26 @@
-From 35170f86c033624284a8ab85346a6fc0bfc8ed43 Mon Sep 17 00:00:00 2001
+From 35ddb138ec297a1b5c456fdca73b2ed0cc10c1cf 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 04/10] Introducing mod_admin_extra
+Subject: [PATCH 3/8] 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).
+
+svn export -r 1125 https://svn.process-one.net/ejabberd-modules/mod_admin_extra/trunk/src/mod_admin_extra.erl
 ---
  src/ejabberd.app        |    1 +
- src/mod_admin_extra.erl | 1279 +++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 1280 insertions(+)
+ src/mod_admin_extra.erl | 1568 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 1569 insertions(+)
  create mode 100644 src/mod_admin_extra.erl
 
 diff --git a/src/ejabberd.app b/src/ejabberd.app
-index 067b928..81edc09 100644
+index 2f08601..3d7ffe4 100644
 --- a/src/ejabberd.app
 +++ b/src/ejabberd.app
-@@ -106,6 +106,7 @@
+@@ -105,6 +105,7 @@
  	     mod_vcard_ldap,
  	     mod_vcard_odbc,
  	     mod_version,
@@ -30,10 +30,10 @@ index 067b928..81edc09 100644
  	     node_default,
 diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl
 new file mode 100644
-index 0000000..9f3ca14
+index 0000000..1cef25a
 --- /dev/null
 +++ b/src/mod_admin_extra.erl
-@@ -0,0 +1,1279 @@
+@@ -0,0 +1,1568 @@
 +%%%-------------------------------------------------------------------
 +%%% File    : mod_admin_extra.erl
 +%%% Author  : Badlop <badlop at process-one.net>
@@ -85,10 +85,15 @@ index 0000000..9f3ca14
 +	 kick_session/4,
 +	 status_num/2, status_num/1,
 +	 status_list/2, status_list/1,
++	 connected_users_info/0,
++	 connected_users_vhost/1,
++	 set_presence/7,
++	 user_sessions_info/2,
 +	 %% Vcard
 +	 set_nickname/3,
 +	 get_vcard/3,
 +	 get_vcard/4,
++	 get_vcard_multi/4,
 +	 set_vcard/4,
 +	 set_vcard/5,
 +	 %% Roster
@@ -99,6 +104,11 @@ index 0000000..9f3ca14
 +	 push_roster/3,
 +	 push_roster_all/1,
 +	 push_alltoall/2,
++	 %% mod_last
++	 set_last/4,
++	 %% mod_private
++	 private_get/4,
++	 private_set/3,
 +	 %% mod_shared_roster
 +	 srg_create/5,
 +	 srg_delete/2,
@@ -110,6 +120,8 @@ index 0000000..9f3ca14
 +	 %% Stanza
 +	 send_message_headline/4,
 +	 send_message_chat/3,
++	 send_stanza_c2s/4,
++	 privacy_set/3,
 +	 %% Stats
 +	 stats/1, stats/2
 +	]).
@@ -143,8 +155,8 @@ index 0000000..9f3ca14
 +	" FN		- Full Name\n"
 +	" NICKNAME	- Nickname\n"
 +	" BDAY		- Birthday\n"
-+	" TITLE		- Work: Position\n",
-+    " ROLE		- Work: Role",
++	" 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"
@@ -192,18 +204,18 @@ index 0000000..9f3ca14
 +			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",
++			desc = "Delete users that didn't log in last days, or that never logged",
 +			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",
++			desc = "Delete users that didn't log in last days in vhost, or that never logged",
 +			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",
++			desc = "Check if an account exists or not",
 +			module = ejabberd_auth, function = is_user_exists,
 +			args = [{user, string}, {host, string}],
 +			result = {res, rescode}},
@@ -280,9 +292,61 @@ index 0000000..9f3ca14
 +								{status, string}
 +							       ]}}
 +					 }}},
++     #ejabberd_commands{name = connected_users_info,
++			tags = [session],
++			desc = "List all established sessions and their information",
++			module = ?MODULE, function = connected_users_info,
++			args = [],
++			result = {connected_users_info,
++				  {list,
++				   {sessions, {tuple,
++					       [{jid, string},
++						{connection, string},
++						{ip, string},
++						{port, integer},
++						{priority, integer},
++						{node, string},
++						{uptime, integer}
++					       ]}}
++				  }}},
++     #ejabberd_commands{name = connected_users_vhost,
++                       tags = [session],
++                       desc = "Get the list of established sessions in a vhost",
++                       module = ?MODULE, function = connected_users_vhost,
++                       args = [{host, string}],
++                       result = {connected_users_vhost, {list, {sessions, string}}}},
++     #ejabberd_commands{name = user_sessions_info,
++			tags = [session],
++			desc = "Get information about all sessions of a user",
++			module = ?MODULE, function = user_sessions_info,
++			args = [{user, string}, {host, string}],
++			result = {sessions_info,
++				  {list,
++				   {session, {tuple,
++					      [{connection, string},
++					       {ip, string},
++					       {port, integer},
++					       {priority, integer},
++					       {node, string},
++					       {uptime, integer},
++					       {status, string},
++					       {resource, string},
++					       {statustext, string}
++					      ]}}
++				  }}},
++
++     #ejabberd_commands{name = set_presence,
++			tags = [session],
++			desc = "Set presence of a session",
++			module = ?MODULE, function = set_presence,
++			args = [{user, string}, {host, string},
++				{resource, string}, {type, string},
++				{show, string}, {status, string},
++				{priority, string}],
++			result = {res, rescode}},
 +
 +     #ejabberd_commands{name = set_nickname, tags = [vcard],
-+			desc = "Set nickname in a user's vcard",
++			desc = "Set nickname in a user's vCard",
 +			module = ?MODULE, function = set_nickname,
 +			args = [{user, string}, {host, string}, {nickname, string}],
 +			result = {res, rescode}},
@@ -299,6 +363,13 @@ index 0000000..9f3ca14
 +			module = ?MODULE, function = get_vcard,
 +			args = [{user, string}, {host, string}, {name, string}, {subname, string}],
 +			result = {content, string}},
++     #ejabberd_commands{name = get_vcard2_multi, tags = [vcard],
++			desc = "Get multiple contents from a vCard field (requires exmpp installed)",
++			longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
++			module = ?MODULE, function = get_vcard_multi,
++			args = [{user, string}, {host, string}, {name, string}, {subname, string}],
++			result = {contents, {list, string}}},
++
 +     #ejabberd_commands{name = set_vcard, tags = [vcard],
 +			desc = "Set content in a vCard field",
 +			longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
@@ -308,12 +379,18 @@ index 0000000..9f3ca14
 +     #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,
++			module = ?MODULE, function = set_vcard,
 +			args = [{user, string}, {host, string}, {name, string}, {subname, string}, {content, string}],
 +			result = {res, rescode}},
++     #ejabberd_commands{name = set_vcard2_multi, tags = [vcard],
++			desc = "Set multiple contents in a vCard subfield",
++			longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
++			module = ?MODULE, function = set_vcard,
++			args = [{user, string}, {host, string}, {name, string}, {subname, string}, {contents, {list, string}}],
++			result = {res, rescode}},
 +
 +     #ejabberd_commands{name = add_rosteritem, tags = [roster],
-+			desc = "Add an item to a user's roster",
++			desc = "Add an item to a user's roster (supports ODBC)",
 +			module = ?MODULE, function = add_rosteritem,
 +			args = [{localuser, string}, {localserver, string},
 +				{user, string}, {server, string},
@@ -324,7 +401,7 @@ index 0000000..9f3ca14
 +     %%{"", "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",
++			desc = "Delete an item from a user's roster (supports ODBC)",
 +			module = ?MODULE, function = delete_rosteritem,
 +			args = [{localuser, string}, {localserver, string},
 +				{user, string}, {server, string}],
@@ -348,7 +425,7 @@ index 0000000..9f3ca14
 +			"  USERS = JID[:JID]* | any\n"
 +			"  CONTACTS = JID[:JID]* | any\n"
 +			"  JID = characters valid in a JID, and can use the "
-+			"globs: *, ? and [...]\n"
++			"globs: *, ?, ! and [...]\n"
 +			"\n"
 +			"This example will list roster items with subscription "
 +			"'none', 'from' or 'to' that have any ask property, of "
@@ -369,6 +446,8 @@ index 0000000..9f3ca14
 +			result = {contacts, {list, {contact, {tuple, [
 +								      {jid, string},
 +								      {nick, string},
++								      {subscription, string},
++								      {ask, string},
 +								      {group, string}
 +								     ]}}}}},
 +     #ejabberd_commands{name = push_roster, tags = [roster],
@@ -387,6 +466,25 @@ index 0000000..9f3ca14
 +			args = [{host, string}, {group, string}],
 +			result = {res, rescode}},
 +
++     #ejabberd_commands{name = set_last, tags = [last],
++			desc = "Set last activity information",
++			longdesc = "Timestamp is the seconds since"
++			"1970-01-01 00:00:00 UTC, for example: date +%s",
++			module = ?MODULE, function = set_last,
++			args = [{user, string}, {host, string}, {timestamp, integer}, {status, string}],
++			result = {res, rescode}},
++
++     #ejabberd_commands{name = private_get, tags = [private],
++			desc = "Get some information from a user private storage",
++			module = ?MODULE, function = private_get,
++			args = [{user, string}, {host, string}, {element, string}, {ns, string}],
++			result = {res, string}},
++     #ejabberd_commands{name = private_set, tags = [private],
++			desc = "Set to the user private storage",
++			module = ?MODULE, function = private_set,
++			args = [{user, string}, {host, string}, {element, 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 "
@@ -442,6 +540,16 @@ index 0000000..9f3ca14
 +			args = [{from, string}, {to, string},
 +				{subject, string}, {body, string}],
 +			result = {res, rescode}},
++     #ejabberd_commands{name = send_stanza_c2s, tags = [stanza],
++			desc = "Send a stanza as if sent from a c2s session",
++			module = ?MODULE, function = send_stanza_c2s,
++			args = [{user, string}, {host, string}, {resource, string}, {stanza, string}],
++			result = {res, rescode}},
++     #ejabberd_commands{name = privacy_set, tags = [stanza],
++			desc = "Send a IQ set privacy stanza for a local account",
++			module = ?MODULE, function = privacy_set,
++			args = [{user, string}, {host, string}, {xmlquery, string}],
++			result = {res, rescode}},
 +
 +     #ejabberd_commands{name = stats, tags = [stats],
 +			desc = "Get statistical value: registeredusers onlineusers onlineusersnode uptimeseconds",
@@ -579,8 +687,6 @@ index 0000000..9f3ca14
 +    end.
 +
 +
-+-record(last_activity, {us, timestamp, status}).
-+
 +delete_old_users(Days) ->
 +    %% Get the list of registered users
 +    Users = ejabberd_auth:dirty_get_registered_users(),
@@ -610,10 +716,10 @@ index 0000000..9f3ca14
 +		    %% If it isnt
 +		    [] ->
 +			%% Look for his last_activity
-+			case mnesia:dirty_read(last_activity, {LUser, LServer}) of
++			case (get_lastactivity_module(LServer)):get_last_info(LUser, LServer) of
 +			    %% If it is
 +			    %% existent:
-+			    [#last_activity{timestamp = TimeStamp}] ->
++			    {ok, TimeStamp, _Status} ->
 +				%% get his age
 +				Sec = TimeStamp_now - TimeStamp,
 +				%% If he is
@@ -629,7 +735,7 @@ index 0000000..9f3ca14
 +					true
 +				end;
 +			    %% nonexistent:
-+			    [] ->
++			    not_found ->
 +				%% remove the user
 +				ejabberd_auth:remove_user(LUser, LServer),
 +				true
@@ -644,6 +750,12 @@ index 0000000..9f3ca14
 +    Users_removed = lists:filter(F, Users),
 +    {removed, length(Users_removed), Users_removed}.
 +
++get_lastactivity_module(Server) ->
++    case lists:member(mod_last, gen_mod:loaded_modules(Server)) of
++        true -> mod_last;
++        _ -> mod_last_odbc
++    end.
++
 +
 +%%
 +%% Ban account
@@ -762,10 +874,75 @@ index 0000000..9f3ca14
 +     || {{User, Resource, Status, Status_text}, Server, Priority} <- Sessions4,
 +	apply(Fstatus, [Status, Status_required])].
 +
++connected_users_info() ->
++    USRIs = dirty_get_sessions_list2(),
++    CurrentSec = calendar:datetime_to_gregorian_seconds({date(), time()}),
++    lists:map(
++      fun([{U, S, R}, {Now, Pid}, Priority, Info]) ->
++	      Conn = proplists:get_value(conn, Info),
++	      {Ip, Port} = proplists:get_value(ip, Info),
++	      IPS = inet_parse:ntoa(Ip),
++	      NodeS = atom_to_list(node(Pid)),
++	      Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds(
++				      calendar:now_to_local_time(Now)),
++	      {[U, $@, S, $/, R], atom_to_list(Conn), IPS, Port, Priority, NodeS, Uptime}
++      end,
++      USRIs).
++
++connected_users_vhost(Host) ->
++    USRs = ejabberd_sm:get_vh_session_list(Host),
++    [ [U, $@, S, $/, R] || {U, S, R} <- USRs].
++
++%% Code copied from ejabberd_sm.erl and customized
++dirty_get_sessions_list2() ->
++    mnesia:dirty_select(
++      session,
++      [{#session{usr = '$1', sid = '$2', priority = '$3', info = '$4', _ = '_'},
++	[],
++	[['$1', '$2', '$3', '$4']]}]).
++
 +%% Make string more print-friendly
 +stringize(String) ->
 +    %% Replace newline characters with other code
-+    element(2, regexp:gsub(String, "\n", "\\n")).
++    ejabberd_regexp:greplace(String, "\n", "\\n").
++
++set_presence(User, Host, Resource, Type, Show, Status, Priority) ->
++    Pid = ejabberd_sm:get_session_pid(User, Host, Resource),
++    USR = User ++ "@" ++ Host ++ "/" ++ Resource,
++    US = User ++ "@" ++ Host,
++    Message = {route_xmlstreamelement,
++	       {xmlelement, "presence",
++		[{"from", USR}, {"to", US}, {"type", Type}],
++		[{xmlelement, "show", [], [{xmlcdata, Show}]},
++		 {xmlelement, "status", [], [{xmlcdata, Status}]},
++		 {xmlelement, "priority", [], [{xmlcdata, Priority}]}]}},
++    Pid ! Message.
++
++user_sessions_info(User, Host) ->
++    CurrentSec = calendar:datetime_to_gregorian_seconds({date(), time()}),
++    US = {User, Host},
++    Sessions = case catch mnesia:dirty_index_read(session, US, #session.us) of
++		   {'EXIT', _Reason} ->
++		       [];
++		   Ss ->
++		       Ss
++	       end,
++    lists:map(
++      fun(Session) ->
++	      {_U, _S, Resource} = Session#session.usr,
++	      {Now, Pid} = Session#session.sid,
++	      {_U, _Resource, Status, StatusText} = ejabberd_c2s:get_presence(Pid),
++	      Info = Session#session.info,
++	      Priority = Session#session.priority,
++	      Conn = proplists:get_value(conn, Info),
++	      {Ip, Port} = proplists:get_value(ip, Info),
++	      IPS = inet_parse:ntoa(Ip),
++	      NodeS = atom_to_list(node(Pid)),
++	      Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds(
++				      calendar:now_to_local_time(Now)),
++	      {atom_to_list(Conn), IPS, Port, Priority, NodeS, Uptime, Status, Resource, StatusText}
++      end,
++      Sessions).
 +
 +
 +%%%
@@ -790,48 +967,79 @@ index 0000000..9f3ca14
 +    end.
 +
 +get_vcard(User, Host, Name) ->
-+    get_vcard_content(User, Host, [Name]).
++    [Res | _] = get_vcard_content(User, Host, [Name]),
++    Res.
 +
 +get_vcard(User, Host, Name, Subname) ->
++    [Res | _] = get_vcard_content(User, Host, [Name, Subname]),
++    Res.
++
++get_vcard_multi(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, SomeContent) ->
++    set_vcard_content(User, Host, [Name], SomeContent).
 +
-+set_vcard(User, Host, Name, Subname, Content) ->
-+    set_vcard_content(User, Host, [Name, Subname], Content).
++set_vcard(User, Host, Name, Subname, SomeContent) ->
++    set_vcard_content(User, Host, [Name, Subname], SomeContent).
 +
 +
 +%%
 +%% Internal vcard
 +
++get_module_resource(Server) ->
++    case gen_mod:get_module_opt(Server, ?MODULE, module_resource, none) of
++	none -> atom_to_list(?MODULE);
++	R when is_list(R) -> R
++    end.
++
 +get_vcard_content(User, Server, Data) ->
 +    [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}),
-+    JID = jlib:make_jid(User, Server, ""),
++    JID = jlib:make_jid(User, Server, get_module_resource(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)
++		[] -> throw(error_no_value_found_in_vcard);
++		ElemList -> [xml:get_tag_cdata(Elem) || Elem <- ElemList]
 +	    end;
 +	[] ->
-+	    "Error: no_vcard"
++	    throw(error_no_vcard_found)
 +    end.
 +
 +get_vcard([Data1, Data2], A1) ->
-+    case xml:get_subtag(A1, Data1) of
++    case get_subtag(A1, Data1) of
 +    	false -> false;
-+	A2 -> get_vcard([Data2], A2)
++	A2List -> lists:flatten([get_vcard([Data2], A2) || A2 <- A2List])
 +    end;
 +
 +get_vcard([Data], A1) ->
-+    xml:get_subtag(A1, Data).
++    get_subtag(A1, Data).
++
++get_subtag(Xmlelement, Name) ->
++    case code:ensure_loaded(exmpp_xml) of
++	{error, _} ->
++	    [get_subtag_xml(Xmlelement, Name)];
++	{module, exmpp_xml} ->
++	    get_subtag_exmpp(Xmlelement, Name)
++    end.
++
++get_subtag_xml(Xmlelement, Name) ->
++    xml:get_subtag(Xmlelement, Name).
 +
-+set_vcard_content(User, Server, Data, Content) ->
++get_subtag_exmpp(Xmlelement, Name) ->
++    Xmlel = exmpp_xml:xmlelement_to_xmlel(Xmlelement),
++    XmlelList = exmpp_xml:get_elements(Xmlel, Name),
++    [exmpp_xml:xmlel_to_xmlelement(Xmlel2) || Xmlel2 <- XmlelList].
++
++set_vcard_content(User, Server, Data, SomeContent) ->
++    ContentList = case SomeContent of
++	[Char | _] when not is_list(Char) -> [SomeContent];
++	[Char | _] when is_list(Char) -> SomeContent
++    end,
 +    [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}),
-+    JID = jlib:make_jid(User, Server, ""),
++    JID = jlib:make_jid(User, Server, get_module_resource(Server)),
 +    IQ = #iq{type = get, xmlns = ?NS_VCARD},
 +    IQr = Module:Function(JID, JID, IQ),
 +
@@ -839,9 +1047,9 @@ index 0000000..9f3ca14
 +    A4 = case IQr#iq.sub_el of
 +	     [A1] ->
 +		 {_, _, _, A2} = A1,
-+		 update_vcard_els(Data, Content, A2);
++		 update_vcard_els(Data, ContentList, A2);
 +	     [] ->
-+		 update_vcard_els(Data, Content, [])
++		 update_vcard_els(Data, ContentList, [])
 +	 end,
 +
 +    %% Build new vcard
@@ -851,26 +1059,26 @@ index 0000000..9f3ca14
 +    Module:Function(JID, JID, IQ2),
 +    ok.
 +
-+update_vcard_els(Data, Content, Els1) ->
++update_vcard_els(Data, ContentList, Els1) ->
 +    Els2 = lists:keysort(2, Els1),
 +    [Data1 | Data2] = Data,
-+    NewEl = case Data2 of
++    NewEls = case Data2 of
 +		[] ->
-+		    {xmlelement, Data1, [], [{xmlcdata,Content}]};
++		    [{xmlelement, Data1, [], [{xmlcdata,Content}]} || Content <- ContentList];
 +		[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),
++		    Content2 = [{xmlelement, D2, [], [{xmlcdata,Content}]} || Content <- ContentList],
++		    ContentOld2 = [A || {_, X, _, _} = A <- ContentOld1, X/=D2],
++		    ContentOld3 = lists:keysort(2, ContentOld2),
 +		    ContentNew = lists:keymerge(2, Content2, ContentOld3),
-+		    {xmlelement, Data1, [], ContentNew}
++		    [{xmlelement, Data1, [], ContentNew}]
 +	    end,
 +    Els3 = lists:keydelete(Data1, 2, Els2),
-+    lists:keymerge(2, [NewEl], Els3).
++    lists:keymerge(2, NewEls, Els3).
 +
 +
 +%%%
@@ -889,21 +1097,18 @@ index 0000000..9f3ca14
 +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).
++subscribe(LU, LS, User, Server, Nick, Group, Subscription, _Xattrs) ->
++    SubscriptionS = case is_atom(Subscription) of
++	true -> atom_to_list(Subscription);
++	false -> Subscription
++    end,
++    ItemEl = build_roster_item(User, Server, {add, Nick, SubscriptionS, Group}),
++    {ok, M} = loaded_module(LS,[mod_roster_odbc,mod_roster]),
++    M:set_items(
++	LU, LS,
++	{xmlelement,"query",
++            [{"xmlns","jabber:iq:roster"}],
++            [ItemEl]}).
 +
 +delete_rosteritem(LocalUser, LocalServer, User, Server) ->
 +    case unsubscribe(LocalUser, LocalServer, User, Server) of
@@ -915,34 +1120,30 @@ index 0000000..9f3ca14
 +    end.
 +
 +unsubscribe(LU, LS, User, Server) ->
-+    mnesia:transaction(
-+      fun() ->
-+              mnesia:delete({roster, {LU, LS, {User, Server, []}}})
-+      end).
-+
++    ItemEl = build_roster_item(User, Server, remove),
++    {ok, M} = loaded_module(LS,[mod_roster_odbc,mod_roster]),
++    M:set_items(
++	LU, LS,
++	{xmlelement,"query",
++            [{"xmlns","jabber:iq:roster"}],
++            [ItemEl]}).
++
++loaded_module(Domain,Options) ->
++    LoadedModules = gen_mod:loaded_modules(Domain),
++    case lists:filter(fun(Module) ->
++                              lists:member(Module, LoadedModules)
++                      end, Options) of
++        [M|_] -> {ok, M};
++        [] -> {error,not_found}
++    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}.
++    Items = ejabberd_hooks:run_fold(roster_get, Server, [], [{User, Server}]),
++    make_roster_xmlrpc(Items).
 +
 +%% Note: if a contact is in several groups, the contact is returned
 +%% several times, each one in a different group.
@@ -951,11 +1152,13 @@ index 0000000..9f3ca14
 +      fun(Item, Res) ->
 +	      JIDS = jlib:jid_to_string(Item#roster.jid),
 +	      Nick = Item#roster.name,
++	      Subs = atom_to_list(Item#roster.subscription),
++	      Ask = atom_to_list(Item#roster.ask),
 +	      Groups = case Item#roster.groups of
 +			   [] -> [""];
 +			   Gs -> Gs
 +		       end,
-+	      ItemsX = [{JIDS, Nick, Group}
++	      ItemsX = [{JIDS, Nick, Subs, Ask, Group}
 +			|| Group <- Groups],
 +	      ItemsX ++ Res
 +      end,
@@ -1014,9 +1217,11 @@ index 0000000..9f3ca14
 +		  end, ejabberd_sm:get_user_resources(LU, LS)).
 +
 +push_roster_item(LU, LS, R, U, S, Action) ->
++    LJID = jlib:make_jid(LU, LS, R),
++    BroadcastEl = build_broadcast(U, S, Action),
++    ejabberd_router:route(LJID, LJID, BroadcastEl),
 +    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}) ->
@@ -1043,13 +1248,76 @@ index 0000000..9f3ca14
 +     ]
 +    }.
 +
++build_broadcast(U, S, {add, _Nick, Subs, _Group}) ->
++    build_broadcast(U, S, list_to_atom(Subs));
++build_broadcast(U, S, remove) ->
++    build_broadcast(U, S, none);
++%% @spec (U::string(), S::string(), Subs::atom()) -> any()
++%% Subs = both | from | to | none
++build_broadcast(U, S, SubsAtom) when is_atom(SubsAtom) ->
++    {xmlelement, "broadcast", [],
++     [{item, {U, S, ""}, SubsAtom}]
++    }.
++
++%%%
++%%% Last Activity
++%%%
++
++set_last(User, Server, Timestamp, Status) ->
++    Mod = get_lastactivity_module(Server),
++    Mod:store_last_info(User, Server, Timestamp, Status).
++
++%%%
++%%% Private Storage
++%%%
++
++%% Example usage:
++%% $ ejabberdctl private_set badlop localhost "\<aa\ xmlns=\'bb\'\>Cluth\</aa\>"
++%% $ ejabberdctl private_get badlop localhost aa bb
++%% <aa xmlns='bb'>Cluth</aa>
++
++private_get(Username, Host, Element, Ns) ->
++    From = jlib:make_jid(Username, Host, ""),
++    To = jlib:make_jid(Username, Host, ""),
++    IQ = {iq, "", get, ?NS_PRIVATE, "",
++	  {xmlelement,"query",
++	   [{"xmlns",?NS_PRIVATE}],
++	   [{xmlelement, Element, [{"xmlns", Ns}], []}]}},
++    ResIq = mod_private:process_sm_iq(From, To, IQ),
++    [{xmlelement,"query",
++      [{"xmlns","jabber:iq:private"}],
++      [SubEl]}] = ResIq#iq.sub_el,
++    xml:element_to_string(SubEl).
++
++private_set(Username, Host, ElementString) ->
++    case xml_stream:parse_element(ElementString) of
++	{error, Error} ->
++	    io:format("Error found parsing the element:~n  ~p~nError: ~p~n",
++		      [ElementString, Error]),
++	    error;
++	Xml ->
++	    private_set2(Username, Host, Xml)
++    end.
++
++private_set2(Username, Host, Xml) ->
++    From = jlib:make_jid(Username, Host, ""),
++    To = jlib:make_jid(Username, Host, ""),
++    IQ = {iq, "", set, ?NS_PRIVATE, "",
++	  {xmlelement,"query",
++	   [{"xmlns",?NS_PRIVATE}],
++	   [Xml]}},
++    mod_private:process_sm_iq(From, To, IQ),
++    ok.
 +
 +%%%
 +%%% Shared Roster Groups
 +%%%
 +
 +srg_create(Group, Host, Name, Description, Display) ->
-+    {ok, DisplayList} = regexp:split(Display, "\\\\n"),
++    DisplayList = case Display of
++	[] -> [];
++	_ -> ejabberd_regexp:split(Display, "\\\\n")
++    end,
 +    Opts = [{name, Name},
 +	    {displayed_groups, DisplayList},
 +	    {description, Description}],
@@ -1138,17 +1406,36 @@ index 0000000..9f3ca14
 +
 +build_packet(message_chat, [Body]) ->
 +    {xmlelement, "message",
-+     [{"type", "chat"}],
++     [{"type", "chat"}, {"id", randoms:get_string()}],
 +     [{xmlelement, "body", [], [{xmlcdata, Body}]}]
 +    };
 +build_packet(message_headline, [Subject, Body]) ->
 +    {xmlelement, "message",
-+     [{"type", "headline"}],
++     [{"type", "headline"}, {"id", randoms:get_string()}],
 +     [{xmlelement, "subject", [], [{xmlcdata, Subject}]},
 +      {xmlelement, "body", [], [{xmlcdata, Body}]}
 +     ]
 +    }.
 +
++send_stanza_c2s(Username, Host, Resource, Stanza) ->
++    C2sPid = ejabberd_sm:get_session_pid(Username, Host, Resource),
++    XmlEl = xml_stream:parse_element(Stanza),
++    p1_fsm:send_event(C2sPid, {xmlstreamelement, XmlEl}).
++
++privacy_set(Username, Host, QueryS) ->
++    From = jlib:string_to_jid(Username ++ "@" ++ Host),
++    To = jlib:string_to_jid(Host),
++    QueryEl = xml_stream:parse_element(QueryS),
++    StanzaEl = {xmlelement, "iq", [{"type", "set"}], [QueryEl]},
++    IQ = jlib:iq_query_info(StanzaEl),
++    ejabberd_hooks:run_fold(
++		     privacy_iq_set,
++		     Host,
++		     {error, ?ERR_FEATURE_NOT_IMPLEMENTED},
++		     [From, To, IQ]
++		    ),
++    ok.
++
 +%%%
 +%%% Stats
 +%%%
@@ -1300,19 +1587,21 @@ index 0000000..9f3ca14
 +
 +%% Copied from ejabberd-2.0.0/src/acl.erl
 +is_regexp_match(String, RegExp) ->
-+    case regexp:first_match(String, RegExp) of
++    case ejabberd_regexp:run(String, RegExp) of
 +	nomatch ->
 +	    false;
-+	{match, _, _} ->
++	match ->
 +	    true;
 +	{error, ErrDesc} ->
 +	    io:format(
 +	      "Wrong regexp ~p in ACL: ~p",
-+	      [RegExp, lists:flatten(regexp:format_error(ErrDesc))]),
++	      [RegExp, ErrDesc]),
 +	    false
 +    end.
++is_glob_match(String, [$! | Glob]) ->
++    not is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob));
 +is_glob_match(String, Glob) ->
-+    is_regexp_match(String, regexp:sh_to_awk(Glob)).
++    is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
 -- 
-1.7.10.1
+1.7.10.4
 
diff --git a/ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch b/ejabberd-0004-Fedora-specific-changes-to-ejabberdctl.patch
similarity index 90%
rename from ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch
rename to ejabberd-0004-Fedora-specific-changes-to-ejabberdctl.patch
index 1f59760..71b6f0c 100644
--- a/ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch
+++ b/ejabberd-0004-Fedora-specific-changes-to-ejabberdctl.patch
@@ -1,7 +1,7 @@
-From 0012d3c968c2aef3cd658d84936bd51bee8e33ce Mon Sep 17 00:00:00 2001
+From 2c01b391dcfdc3cb34f5984a10a1bba3ca341c02 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 05/10] Fedora-specific changes to ejabberdctl
+Subject: [PATCH 4/8] Fedora-specific changes to ejabberdctl
 
 Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
 ---
@@ -44,5 +44,5 @@ index 0960f9a..c22478a 100644
  done
  if [ "$ID" -eq "$EJID" ] ; then
 -- 
-1.7.10.1
+1.7.10.4
 
diff --git a/ejabberd-0006-Install-.so-objects-with-0755-permissions.patch b/ejabberd-0005-Install-.so-objects-with-0755-permissions.patch
similarity index 79%
rename from ejabberd-0006-Install-.so-objects-with-0755-permissions.patch
rename to ejabberd-0005-Install-.so-objects-with-0755-permissions.patch
index ac1deb7..a2d0ec9 100644
--- a/ejabberd-0006-Install-.so-objects-with-0755-permissions.patch
+++ b/ejabberd-0005-Install-.so-objects-with-0755-permissions.patch
@@ -1,7 +1,7 @@
-From 8254e46cf2710edfc3c45f9da227e4613e342796 Mon Sep 17 00:00:00 2001
+From 924dab202126d7644a8e50e81d1b2de21875bb7f Mon Sep 17 00:00:00 2001
 From: Peter Lemenkov <lemenkov at gmail.com>
 Date: Sat, 12 Jun 2010 14:14:52 +0400
-Subject: [PATCH 06/10] Install *.so objects with 0755 permissions
+Subject: [PATCH 5/8] Install *.so objects with 0755 permissions
 
 Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
 ---
@@ -22,5 +22,5 @@ index 42af5b2..64ed856 100644
  	# Translated strings
  	install -d $(MSGSDIR)
 -- 
-1.7.10.1
+1.7.10.4
 
diff --git a/ejabberd-0007-Use-versioned-directory-for-storing-docs.patch b/ejabberd-0006-Use-versioned-directory-for-storing-docs.patch
similarity index 87%
rename from ejabberd-0007-Use-versioned-directory-for-storing-docs.patch
rename to ejabberd-0006-Use-versioned-directory-for-storing-docs.patch
index c6a4284..854ad81 100644
--- a/ejabberd-0007-Use-versioned-directory-for-storing-docs.patch
+++ b/ejabberd-0006-Use-versioned-directory-for-storing-docs.patch
@@ -1,7 +1,7 @@
-From ff5baa27c9bb0175e4bc4ae3862d8e639234a701 Mon Sep 17 00:00:00 2001
+From 889d68a28b4442cf71e8c4ad335a98718402f4a5 Mon Sep 17 00:00:00 2001
 From: Peter Lemenkov <lemenkov at gmail.com>
 Date: Sat, 12 Jun 2010 16:12:11 +0400
-Subject: [PATCH 07/10] Use versioned directory for storing docs
+Subject: [PATCH 6/8] Use versioned directory for storing docs
 
 It's also a good idea to store doc-files under the versioned directory.
 This may greatly simplify parallel installation of different versions of
@@ -31,5 +31,5 @@ index 64ed856..43b5e1f 100644
  DOCDIR = $(DESTDIR)@docdir@
  
 -- 
-1.7.10.1
+1.7.10.4
 
diff --git a/ejabberd-0008-Support-SASL-GSSAPI-authentication-thanks-to-Mikael-.patch b/ejabberd-0007-Support-SASL-GSSAPI-authentication-thanks-to-Mikael-.patch
similarity index 99%
rename from ejabberd-0008-Support-SASL-GSSAPI-authentication-thanks-to-Mikael-.patch
rename to ejabberd-0007-Support-SASL-GSSAPI-authentication-thanks-to-Mikael-.patch
index 67b0717..8795e99 100644
--- a/ejabberd-0008-Support-SASL-GSSAPI-authentication-thanks-to-Mikael-.patch
+++ b/ejabberd-0007-Support-SASL-GSSAPI-authentication-thanks-to-Mikael-.patch
@@ -1,7 +1,7 @@
-From b1dbc5224d000b62d405f4e82b6dd646f54997a1 Mon Sep 17 00:00:00 2001
+From f2a612dba3d6ab5dd5b522f74c493c78cdfed6c9 Mon Sep 17 00:00:00 2001
 From: Badlop <badlop at process-one.net>
 Date: Thu, 15 Apr 2010 17:20:16 +0200
-Subject: [PATCH 08/10] Support SASL GSSAPI authentication (thanks to Mikael
+Subject: [PATCH 7/8] Support SASL GSSAPI authentication (thanks to Mikael
  Magnusson)(EJAB-831)
 
 ---
@@ -501,5 +501,5 @@ index 254751b..3509018 100644
  %% Internal functions
  %%====================================================================
 -- 
-1.7.10.1
+1.7.10.4
 
diff --git a/ejabberd-0010-Disable-INET_DIST_INTERFACE-by-default.patch b/ejabberd-0008-Disable-INET_DIST_INTERFACE-by-default.patch
similarity index 81%
rename from ejabberd-0010-Disable-INET_DIST_INTERFACE-by-default.patch
rename to ejabberd-0008-Disable-INET_DIST_INTERFACE-by-default.patch
index 10be6cc..a9b0b5b 100644
--- a/ejabberd-0010-Disable-INET_DIST_INTERFACE-by-default.patch
+++ b/ejabberd-0008-Disable-INET_DIST_INTERFACE-by-default.patch
@@ -1,7 +1,7 @@
-From a5e1042ca338c81a5c75ef2c8d2fb4cab8b935e3 Mon Sep 17 00:00:00 2001
+From a6a1ee5a9d5a8400415a96456dbb79f4341c3410 Mon Sep 17 00:00:00 2001
 From: Peter Lemenkov <lemenkov at gmail.com>
 Date: Sat, 18 Jun 2011 23:24:28 +0400
-Subject: [PATCH 10/10] Disable INET_DIST_INTERFACE by default
+Subject: [PATCH 8/8] Disable INET_DIST_INTERFACE by default
 
 Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
 ---
@@ -22,5 +22,5 @@ index b72058a..5ee43cf 100644
  #.
  #' ERL_EPMD_ADDRESS: IP addresses where epmd listens for connections
 -- 
-1.7.10.1
+1.7.10.4
 
diff --git a/ejabberd.spec b/ejabberd.spec
index df00937..05c4cea 100644
--- a/ejabberd.spec
+++ b/ejabberd.spec
@@ -3,15 +3,15 @@
 # Currently, hevea available only in Fedora
 %if 0%{?fedora}
 # No hevea for ppc64
-# see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=250253
-%ifnarch ppc64 s390 s390x %{arm}
+# see https://bugzilla.redhat.com/bugzilla/250253
+%ifnarch ppc64 s390 s390x sparc64
 %define with_hevea 1
 %endif
 %endif
 
 Name:           ejabberd
 Version:        2.1.11
-Release:        1%{?dist}
+Release:        2%{?dist}
 Summary:        A distributed, fault-tolerant Jabber/XMPP server
 
 Group:          Applications/Internet
@@ -33,24 +33,20 @@ Source11:       ejabberd.pam
 
 # Use ejabberd as an example for PAM service name (fedora/epel-specific)
 Patch1: ejabberd-0001-Fix-PAM-service-example-name-to-match-actual-one.patch
-# Introducing mod_ctlextra
-Patch2: ejabberd-0002-Add-mod_ctlextra-as-an-ejabberd-module.patch
 # fixed delays in s2s connections
-Patch3: ejabberd-0003-Fixed-delays-in-s2s-connections.patch
+Patch2: ejabberd-0002-Fixed-delays-in-s2s-connections.patch
 # Introducing mod_admin_extra
-Patch4: ejabberd-0004-Introducing-mod_admin_extra.patch
+Patch3: ejabberd-0003-Introducing-mod_admin_extra.patch
 # BZ# 439583, 452326, 451554, 465196, 502361 (fedora/epel-specific)
-Patch5: ejabberd-0005-Fedora-specific-changes-to-ejabberdctl.patch
+Patch4: ejabberd-0004-Fedora-specific-changes-to-ejabberdctl.patch
 # Fix so-lib permissions while installing (fedora/epel-specific)
-Patch6:	ejabberd-0006-Install-.so-objects-with-0755-permissions.patch
+Patch5:	ejabberd-0005-Install-.so-objects-with-0755-permissions.patch
 # Will be proposed for inclusion into upstream
-Patch7: ejabberd-0007-Use-versioned-directory-for-storing-docs.patch
+Patch6: ejabberd-0006-Use-versioned-directory-for-storing-docs.patch
 # Backported from upstream
-Patch8: ejabberd-0008-Support-SASL-GSSAPI-authentication-thanks-to-Mikael-.patch
-# Introduce old AD stuff
-Patch9: ejabberd-0009-Added-old-modules-for-Active-Directory.patch
+Patch7: ejabberd-0007-Support-SASL-GSSAPI-authentication-thanks-to-Mikael-.patch
 # Disable IP restriction for ejabberdctl (seems that it doesn't work well)
-Patch10: ejabberd-0010-Disable-INET_DIST_INTERFACE-by-default.patch
+Patch8: ejabberd-0008-Disable-INET_DIST_INTERFACE-by-default.patch
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -116,15 +112,13 @@ Documentation for ejabberd.
 %setup -q
 
 %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 .fix_perms
-%patch7 -p1 -b .versioned_docdir
-%patch8 -p1 -b .gssapi
-%patch9 -p1 -b .ad_stuff
-%patch10 -p1 -b .disable_ip_restriction_for_ejabberdctl
+%patch2 -p1 -b .s2s_delays
+%patch3 -p1 -b .mod_admin_extra
+%patch4 -p1 -b .fedora_specific
+%patch5 -p1 -b .fix_perms
+%patch6 -p1 -b .versioned_docdir
+%patch7 -p1 -b .gssapi
+%patch8 -p1 -b .disable_ip_restriction_for_ejabberdctl
 
 # FIXME last-minute fix for 2.1.11 only
 sed -i -e "s,2.1.x,2.1.11,g" src/configure
@@ -134,7 +128,7 @@ touch -r src/configure.ac src/configure
 %build
 pushd src
 %configure --enable-odbc --enable-pam
-# doesn't builds on SMP currently
+# doesn't build on SMP currently
 make
 popd
 %if 0%{?with_hevea}
@@ -307,8 +301,6 @@ rm -rf %{buildroot}
 
 
 %files
-%defattr(-,root,root,-)
-
 %dir %{_docdir}/%{name}-%{version}
 %doc %{_docdir}/%{name}-%{version}/COPYING
 
@@ -387,7 +379,6 @@ rm -rf %{buildroot}
 %attr(750,ejabberd,ejabberd) %dir /var/log/ejabberd
 
 %files doc
-%defattr(-,root,root,-)
 %doc %{_docdir}/%{name}-%{version}/*.html
 %doc %{_docdir}/%{name}-%{version}/*.png
 %if 0%{?with_hevea}
@@ -396,6 +387,10 @@ rm -rf %{buildroot}
 %doc %{_docdir}/%{name}-%{version}/*.txt
 
 %changelog
+* Sun Jul 15 2012 Peter Lemenkov <lemenkov at gmail.com> - 2.1.11-2
+- Updated mod_Admin_extra to work with R15B (see rhbz #840039)
+- Updated list of arches where we don't have hevea
+
 * Sun May 06 2012 Peter Lemenkov <lemenkov at gmail.com> - 2.1.11-1
 - Ver. 2.1.11
 - Fixed systemd installation


More information about the scm-commits mailing list