diff options
author | Randy Barlow <randy@electronsweatshop.com> | 2016-03-14 00:05:41 -0400 |
---|---|---|
committer | Randy Barlow <randy@electronsweatshop.com> | 2016-03-14 00:05:41 -0400 |
commit | e8604398be965e0d09bda2a4742cca151feae9e9 (patch) | |
tree | ce7a35b24988d4701fc7995fbb9827cd71b325df | |
parent | 95ac9cc3877d2eac0e8c3765e7a8c8f628cef6ce (diff) | |
download | ejabberd-e8604398be965e0d09bda2a4742cca151feae9e9.tar.gz ejabberd-e8604398be965e0d09bda2a4742cca151feae9e9.tar.xz ejabberd-e8604398be965e0d09bda2a4742cca151feae9e9.zip |
Update to ejabberd-16.02.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | 0014-Remove-the-xmlrpc-dependency-as-it-s-only-used-for-t.patch | 46 | ||||
-rw-r--r-- | ejabberd-0002-Introducing-mod_admin_extra.patch | 1608 | ||||
-rw-r--r-- | ejabberd-0006-Enable-polkit-support.patch | 17 | ||||
-rw-r--r-- | ejabberd.spec | 38 | ||||
-rw-r--r-- | sources | 2 |
6 files changed, 21 insertions, 1691 deletions
@@ -12,3 +12,4 @@ ejabberd-2.1.5.tar.gz /ejabberd-src-deps.tar /15.11.tar.gz /16.01.tar.gz +/16.02.tar.gz diff --git a/0014-Remove-the-xmlrpc-dependency-as-it-s-only-used-for-t.patch b/0014-Remove-the-xmlrpc-dependency-as-it-s-only-used-for-t.patch deleted file mode 100644 index 8df9f6d..0000000 --- a/0014-Remove-the-xmlrpc-dependency-as-it-s-only-used-for-t.patch +++ /dev/null @@ -1,46 +0,0 @@ -From d5b4665affa50342bbb8de7d4b22372de5dbfc7c Mon Sep 17 00:00:00 2001 -From: Randy Barlow <randy@electronsweatshop.com> -Date: Sun, 14 Feb 2016 17:11:31 -0500 -Subject: [PATCH] Remove dependency on xmlrpc. - ---- - mix.exs | 3 +-- - rebar.config | 1 - - 2 files changed, 1 insertion(+), 3 deletions(-) - -diff --git a/mix.exs b/mix.exs -index b002e36..011bb0e 100644 ---- a/mix.exs -+++ b/mix.exs -@@ -20,7 +20,7 @@ defmodule Ejabberd.Mixfile do - included_applications: [:lager, :p1_utils, :cache_tab, - :p1_tls, :p1_stringprep, :p1_xml, - :p1_stun, :p1_yaml, :p1_zlib, :p1_iconv, -- :esip, :jiffy, :oauth2, :xmlrpc, :eredis, -+ :esip, :jiffy, :oauth2, :eredis, - :p1_mysql, :p1_pgsql, :sqlite3]] - end - -@@ -42,7 +42,6 @@ defmodule Ejabberd.Mixfile do - {:p1_yaml, git: "https://github.com/processone/p1_yaml", tag: "1.0.0"}, - {:jiffy, git: "https://github.com/davisp/jiffy", tag: "0.14.5"}, - {:oauth2, git: "https://github.com/kivra/oauth2", "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}, -- {:xmlrpc, git: "https://github.com/rds13/xmlrpc.git", tag: "1.15"}, - {:p1_mysql, git: "https://github.com/processone/mysql", tag: "1.0.0"}, - {:p1_pgsql, git: "https://github.com/processone/pgsql", tag: "1.0.0"}, - {:sqlite3, git: "https://github.com/alexeyr/erlang-sqlite3", "cbc3505f7a131254265d3ef56191b2581b8cc172"}, -diff --git a/rebar.config b/rebar.config -index 30c0360..5fb5340 100644 ---- a/rebar.config -+++ b/rebar.config -@@ -19,7 +19,6 @@ - {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml", {tag, "1.0.0"}}}, - {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.5"}}}, - {oauth2, ".*", {git, "https://github.com/kivra/oauth2", "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}}, -- {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc", {tag, "1.15"}}}, - {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/mysql", {tag, "1.0.0"}}}}, - {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/pgsql", {tag, "1.0.0"}}}}, - {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3", "cbc3505f7a131254265d3ef56191b2581b8cc172"}}}, --- -2.7.1 - diff --git a/ejabberd-0002-Introducing-mod_admin_extra.patch b/ejabberd-0002-Introducing-mod_admin_extra.patch deleted file mode 100644 index 586cefb..0000000 --- a/ejabberd-0002-Introducing-mod_admin_extra.patch +++ /dev/null @@ -1,1608 +0,0 @@ -From: Badlop <badlop@process-one.net> -Date: Tue, 16 Feb 2010 16:12:17 +0300 -Subject: [PATCH] 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: - -wget https://raw.githubusercontent.com/processone/ejabberd-contrib/e23bf94/mod_admin_extra/src/mod_admin_extra.erl - -diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl -new file mode 100644 -index 0000000..63703ec ---- /dev/null -+++ b/src/mod_admin_extra.erl -@@ -0,0 +1,1590 @@ -+%%%------------------------------------------------------------------- -+%%% File : mod_admin_extra.erl -+%%% Author : Badlop <badlop@process-one.net> -+%%% Purpose : Contributed administrative functions and commands -+%%% Created : 10 Aug 2008 by Badlop <badlop@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@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, -+ 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 -+ add_rosteritem/7, -+ delete_rosteritem/4, -+ process_rosteritems/5, -+ get_roster/2, -+ push_roster/3, -+ push_roster_all/1, -+ push_alltoall/2, -+ %% mod_last -+ get_last/2, -+ set_last/4, -+ %% mod_private -+ private_get/4, -+ private_set/3, -+ %% 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, -+ send_stanza_c2s/4, -+ privacy_set/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], %% Copied to ejabberd 2.1.x after 11 -+ 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, binary}, {days, integer}], -+ result = {users, integer}}, -+ #ejabberd_commands{name = delete_old_users, tags = [accounts, purge], -+ 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, or that never logged", -+ module = ?MODULE, function = delete_old_users_vhost, -+ args = [{host, binary}, {days, integer}], -+ result = {res, restuple}}, -+ -+ #ejabberd_commands{name = check_account, tags = [accounts], -+ desc = "Check if an account exists or not", -+ module = ejabberd_auth, function = is_user_exists, -+ args = [{user, binary}, {host, binary}], -+ 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, binary}, {host, binary}, {password, binary}], -+ 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, binary}, {host, binary}, {passwordhash, binary}, {hashmethod, binary}], -+ result = {res, rescode}}, -+ #ejabberd_commands{name = change_password, tags = [accounts], -+ desc = "Change the password of an account", -+ module = ?MODULE, function = set_password, -+ args = [{user, binary}, {host, binary}, {newpass, binary}], -+ 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, binary}, {host, binary}, {reason, binary}], -+ 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, binary}, {host, binary}], -+ result = {resources, integer}}, -+ #ejabberd_commands{name = resource_num, tags = [session], -+ desc = "Resource string of a session number", -+ module = ?MODULE, function = resource_num, -+ args = [{user, binary}, {host, binary}, {num, integer}], -+ result = {resource, string}}, -+ #ejabberd_commands{name = kick_session, tags = [session], -+ desc = "Kick a user session", -+ module = ?MODULE, function = kick_session, -+ args = [{user, binary}, {host, binary}, {resource, binary}, {reason, binary}], -+ 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, binary}, {status, binary}], -+ 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, binary}], -+ 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, binary}, {status, binary}], -+ 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, binary}], -+ result = {users, {list, -+ {userstatus, {tuple, [ -+ {user, string}, -+ {host, string}, -+ {resource, string}, -+ {priority, integer}, -+ {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", -+ 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, binary}, {host, binary}, {name, binary}], -+ 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, binary}, {host, binary}, {name, binary}, {subname, binary}], -+ 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, binary}, {host, binary}, {name, binary}, {subname, binary}], -+ 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, -+ module = ?MODULE, function = set_vcard, -+ args = [{user, binary}, {host, binary}, {name, binary}, {content, binary}], -+ 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_vcard, -+ args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {content, binary}], -+ 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, binary}, {host, binary}, {name, binary}, {subname, binary}, {contents, {list, binary}}], -+ result = {res, rescode}}, -+ -+ #ejabberd_commands{name = add_rosteritem, tags = [roster], -+ desc = "Add an item to a user's roster (supports ODBC)", -+ module = ?MODULE, function = add_rosteritem, -+ args = [{localuser, binary}, {localserver, binary}, -+ {user, binary}, {server, binary}, -+ {nick, binary}, {group, binary}, -+ {subs, binary}], -+ result = {res, rescode}}, -+ %%{"", "subs= none, from, to or both"}, -+ %%{"", "example: add-roster peter localhost mike server.com MiKe Employees both"}, -+ %%{"", "will add mike@server.com to peter@localhost roster"}, -+ #ejabberd_commands{name = delete_rosteritem, tags = [roster], -+ desc = "Delete an item from a user's roster (supports ODBC)", -+ module = ?MODULE, function = delete_rosteritem, -+ args = [{localuser, binary}, {localserver, binary}, -+ {user, binary}, {server, binary}], -+ 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 = {response, -+ {list, -+ {pairs, {tuple, -+ [{user, string}, -+ {contact, string} -+ ]}} -+ }}}, -+ #ejabberd_commands{name = get_roster, tags = [roster], -+ desc = "Get roster of a local user", -+ module = ?MODULE, function = get_roster, -+ args = [{user, binary}, {host, binary}], -+ result = {contacts, {list, {contact, {tuple, [ -+ {jid, string}, -+ {nick, string}, -+ {subscription, string}, -+ {ask, 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 = get_last, tags = [last], -+ desc = "Get last activity information", -+ longdesc = "Timestamp is the seconds since" -+ "1970-01-01 00:00:00 UTC, for example: date +%s", -+ module = ?MODULE, function = get_last, -+ args = [{user, binary}, {host, binary}], -+ result = {last_activity, string}}, -+ #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 " -+ "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, binary}, {host, binary}, -+ {name, binary}, {description, binary}, {display, binary}], -+ 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, binary}, {host, binary}], -+ 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, binary}], -+ 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, binary}, {host, binary}], -+ 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, binary}, {host, binary}], -+ result = {members, {list, {member, string}}}}, -+ #ejabberd_commands{name = srg_user_add, tags = [shared_roster_group], -+ desc = "Add the JID user@host to the Shared Roster Group", -+ module = ?MODULE, function = srg_user_add, -+ args = [{user, binary}, {host, binary}, {group, binary}, {grouphost, binary}], -+ result = {res, rescode}}, -+ #ejabberd_commands{name = srg_user_del, tags = [shared_roster_group], -+ desc = "Delete this JID user@host from the Shared Roster Group", -+ module = ?MODULE, function = srg_user_del, -+ args = [{user, binary}, {host, binary}, {group, binary}, {grouphost, binary}], -+ 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, binary}, {to, binary}, {body, binary}], -+ 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, binary}, {to, binary}, -+ {subject, binary}, {body, binary}], -+ 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, binary}, {host, binary}, {resource, binary}, {stanza, binary}], -+ 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, binary}, {host, binary}, {xmlquery, binary}], -+ result = {res, rescode}}, -+ -+ #ejabberd_commands{name = stats, tags = [stats], -+ desc = "Get statistical value: registeredusers onlineusers onlineusersnode uptimeseconds", -+ module = ?MODULE, function = stats, -+ args = [{name, binary}], -+ 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, binary}, {host, binary}], -+ 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. -+ -+ -+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 (get_lastactivity_module(LServer)):get_last_info(LUser, LServer) of -+ %% If it is -+ %% existent: -+ {ok, TimeStamp, _Status} -> -+ %% 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: -+ not_found -> -+ %% 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}. -+ -+get_lastactivity_module(Server) -> -+ case lists:member(mod_last, gen_mod:loaded_modules(Server)) of -+ true -> mod_last; -+ _ -> mod_last_odbc -+ end. -+ -+ -+%% -+%% 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_binary(Reason) -> -+ Reason. -+ -+%%% -+%%% 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), -+ {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])]. -+ -+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 -+ 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, -+ {xmlel, <<"presence">>, -+ [{<<"from">>, USR}, {<<"to">>, US}, {<<"type">>, Type}], -+ [{xmlel, <<"show">>, [], [{xmlcdata, Show}]}, -+ {xmlel, <<"status">>, [], [{xmlcdata, Status}]}, -+ {xmlel, <<"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). -+ -+ -+%%% -+%%% 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">>, -+ {xmlel, <<"vCard">>, [ -+ {<<"xmlns">>, <<"vcard-temp">>}], [ -+ {xmlel, <<"NICKNAME">>, [], [{xmlcdata, Nickname}]} -+ ] -+ }}), -+ case R of -+ {iq, [], result, [], _L, []} -> -+ ok; -+ _ -> -+ error -+ end. -+ -+get_vcard(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, SomeContent) -> -+ set_vcard_content(User, Host, [Name], SomeContent). -+ -+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, fun(A) -> A end, none) of -+ none -> list_to_binary(atom_to_list(?MODULE)); -+ R when is_binary(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, 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 -+ [] -> throw(error_no_value_found_in_vcard); -+ ElemList -> [xml:get_tag_cdata(Elem) || Elem <- ElemList] -+ end; -+ [] -> -+ throw(error_no_vcard_found) -+ end. -+ -+get_vcard([Data1, Data2], A1) -> -+ case get_subtag(A1, Data1) of -+ false -> false; -+ A2List -> lists:flatten([get_vcard([Data2], A2) || A2 <- A2List]) -+ end; -+ -+get_vcard([Data], A1) -> -+ 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). -+ -+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 -+ [Bin | _] when is_binary(Bin) -> SomeContent; -+ Bin when is_binary(Bin) -> [SomeContent] -+ end, -+ [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}), -+ JID = jlib:make_jid(User, Server, get_module_resource(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, ContentList, A2); -+ [] -> -+ update_vcard_els(Data, ContentList, []) -+ end, -+ -+ %% Build new vcard -+ SubEl = {xmlel, <<"vCard">>, [{<<"xmlns">>,<<"vcard-temp">>}], A4}, -+ IQ2 = #iq{type=set, sub_el = SubEl}, -+ -+ Module:Function(JID, JID, IQ2), -+ ok. -+ -+update_vcard_els(Data, ContentList, Els1) -> -+ Els2 = lists:keysort(2, Els1), -+ [Data1 | Data2] = Data, -+ NewEls = case Data2 of -+ [] -> -+ [{xmlel, Data1, [], [{xmlcdata,Content}]} || Content <- ContentList]; -+ [D2] -> -+ OldEl = case lists:keysearch(Data1, 2, Els2) of -+ {value, A} -> A; -+ false -> {xmlel, Data1, [], []} -+ end, -+ {xmlel, _, _, ContentOld1} = OldEl, -+ Content2 = [{xmlel, D2, [], [{xmlcdata,Content}]} || Content <- ContentList], -+ ContentOld2 = [A || {_, X, _, _} = A <- ContentOld1, X/=D2], -+ ContentOld3 = lists:keysort(2, ContentOld2), -+ ContentNew = lists:keymerge(2, Content2, ContentOld3), -+ [{xmlel, Data1, [], ContentNew}] -+ end, -+ Els3 = lists:keydelete(Data1, 2, Els2), -+ lists:keymerge(2, NewEls, Els3). -+ -+ -+%%% -+%%% Roster -+%%% -+ -+add_rosteritem(LocalUser, LocalServer, User, Server, Nick, Group, Subs) -> -+ case add_rosteritem(LocalUser, LocalServer, User, Server, Nick, Group, 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) -> -+ ItemEl = build_roster_item(User, Server, {add, Nick, Subscription, Group}), -+ mod_roster:set_items( -+ LU, LS, -+ {xmlel, <<"query">>, -+ [{<<"xmlns">>, <<"jabber:iq:roster">>}], -+ [ItemEl]}). -+ -+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) -> -+ ItemEl = build_roster_item(User, Server, remove), -+ mod_roster:set_items( -+ LU, LS, -+ {xmlel, <<"query">>, -+ [{<<"xmlns">>, <<"jabber:iq:roster">>}], -+ [ItemEl]}). -+ -+%% ----------------------------- -+%% Get Roster -+%% ----------------------------- -+ -+get_roster(User, Server) -> -+ 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. -+make_roster_xmlrpc(Roster) -> -+ lists:foldl( -+ 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, Subs, Ask, 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@LS the contact U@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) -> -+ 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), -+ ejabberd_router:route(LJID, LJID, ResIQ). -+ -+build_roster_item(U, S, {add, Nick, Subs, Group}) -> -+ {xmlel, <<"item">>, -+ [{<<"jid">>, jlib:jid_to_string(jlib:make_jid(U, S, <<>>))}, -+ {<<"name">>, Nick}, -+ {<<"subscription">>, Subs}], -+ [{xmlel, <<"group">>, [], [{xmlcdata, Group}]}] -+ }; -+build_roster_item(U, S, remove) -> -+ {xmlel, <<"item">>, -+ [{<<"jid">>, jlib:jid_to_string(jlib:make_jid(U, S, <<>>))}, -+ {<<"subscription">>, <<"remove">>}], -+ [] -+ }. -+ -+build_iq_roster_push(Item) -> -+ {xmlel, <<"iq">>, -+ [{<<"type">>, <<"set">>}, {<<"id">>, <<"push">>}], -+ [{xmlel, <<"query">>, -+ [{<<"xmlns">>, ?NS_ROSTER}], -+ [Item] -+ } -+ ] -+ }. -+ -+build_broadcast(U, S, {add, _Nick, Subs, _Group}) -> -+ build_broadcast(U, S, list_to_atom(binary_to_list(Subs))); -+build_broadcast(U, S, remove) -> -+ build_broadcast(U, S, none); -+%% @spec (U::binary(), S::binary(), Subs::atom()) -> any() -+%% Subs = both | from | to | none -+build_broadcast(U, S, SubsAtom) when is_atom(SubsAtom) -> -+ {broadcast, {item, {U, S, <<>>}, SubsAtom}}. -+ -+%%% -+%%% Last Activity -+%%% -+ -+get_last(User, Server) -> -+ Mod = get_lastactivity_module(Server), -+ case ejabberd_sm:get_user_resources(User, Server) of -+ [] -> -+ case Mod:get_last_info(User, Server) of -+ not_found -> -+ "Never"; -+ {ok, Shift, _Status} -> -+ TimeStamp = {Shift div 1000000, -+ Shift rem 1000000, -+ 0}, -+ {{Year, Month, Day}, {Hour, Minute, Second}} = -+ calendar:now_to_local_time(TimeStamp), -+ lists:flatten( -+ io_lib:format( -+ "~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w", -+ [Year, Month, Day, Hour, Minute, Second])) -+ end; -+ _ -> -+ "Online" -+ end. -+ -+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, <<>>, -+ {xmlel, <<"query">>, -+ [{<<"xmlns">>,?NS_PRIVATE}], -+ [{xmlel, Element, [{<<"xmlns">>, Ns}], []}]}}, -+ ResIq = mod_private:process_sm_iq(From, To, IQ), -+ [{xmlel, <<"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, <<>>, -+ {xmlel, <<"query">>, -+ [{<<"xmlns">>, ?NS_PRIVATE}], -+ [Xml]}}, -+ mod_private:process_sm_iq(From, To, IQ), -+ ok. -+ -+%%% -+%%% Shared Roster Groups -+%%% -+ -+srg_create(Group, Host, Name, Description, Display) -> -+ DisplayList = case Display of -+ [] -> []; -+ _ -> ejabberd_regexp:split(Display, <<"\\\\n">>) -+ end, -+ 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 = case mod_shared_roster:get_group_opts(Host,Group) of -+ Os when is_list(Os) -> Os; -+ error -> [] -+ end, -+ [{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::binary(), To::binary(), Body::binary()) -> 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::binary(), To::binary(), Subject::binary(), Body::binary()) -> 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]) -> -+ {xmlel, <<"message">>, -+ [{<<"type">>, <<"chat">>}, {<<"id">>, randoms:get_string()}], -+ [{xmlel, <<"body">>, [], [{xmlcdata, Body}]}] -+ }; -+build_packet(message_headline, [Subject, Body]) -> -+ {xmlel, <<"message">>, -+ [{<<"type">>, <<"headline">>}, {<<"id">>, randoms:get_string()}], -+ [{xmlel, <<"subject">>, [], [{xmlcdata, Subject}]}, -+ {xmlel, <<"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 = {xmlel, <<"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 -+%%% -+ -+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, Res} -> -+ Res; -+ {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), -+ Res = rip(Key, Options, {0, Num_rosteritems, 0, 0}, []), -+ {atomic, Res}. -+ -+rip('$end_of_table', _Options, Counters, Res) -> -+ print_progress_line(Counters), -+ Res; -+rip(Key, Options, {Pr, NT, NV, ND}, Res) -> -+ Key_next = mnesia:dirty_next(roster, Key), -+ {Action, _, _, _, _} = Options, -+ {ND2, Res2} = case decide_rip(Key, Options) of -+ true -> -+ Jids = apply_action(Action, Key), -+ {ND+1, [Jids | Res]}; -+ false -> -+ {ND, Res} -+ end, -+ NV2 = NV+1, -+ Pr2 = print_progress_line({Pr, NT, NV2, ND2}), -+ rip(Key_next, Options, {Pr2, NT, NV2, ND2}, Res2). -+ -+apply_action(list, Key) -> -+ {User, Server, JID} = Key, -+ {RUser, RServer, _} = JID, -+ Jid1string = User ++ "@" ++ Server, -+ Jid2string = RUser ++ "@" ++ RServer, -+ io:format("Matches: ~s ~s~n", [Jid1string, Jid2string]), -+ {Jid1string, Jid2string}; -+apply_action(delete, Key) -> -+ R = apply_action(list, Key), -+ mnesia:dirty_delete(roster, Key), -+ R. -+ -+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 ejabberd_regexp:run(String, RegExp) of -+ nomatch -> -+ false; -+ match -> -+ true; -+ {error, ErrDesc} -> -+ io:format( -+ "Wrong regexp ~p in ACL: ~p", -+ [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, ejabberd_regexp:sh_to_awk(Glob)). diff --git a/ejabberd-0006-Enable-polkit-support.patch b/ejabberd-0006-Enable-polkit-support.patch index ae349f5..b203ead 100644 --- a/ejabberd-0006-Enable-polkit-support.patch +++ b/ejabberd-0006-Enable-polkit-support.patch @@ -1,16 +1,23 @@ -From: Peter Lemenkov <lemenkov@gmail.com> -Date: Wed, 17 Jul 2013 14:51:04 +0400 +From 561da3443e0d09029b3e60d1bd1aa9cfacf0c53d Mon Sep 17 00:00:00 2001 +From: Randy Barlow <randy@electronsweatshop.com> +Date: Sun, 6 Mar 2016 19:53:05 -0500 Subject: [PATCH] Enable polkit support -Signed-off-by: Peter Lemenkov <lemenkov@gmail.com> +Patch originally by Peter Lemenkov <lemenkov@gmail.com>. +--- + ejabberdctl.template | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template -index 09b9947..0fd33fe 100755 +index 07395aa..b5bcbb0 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/pkexec /bin/sh - + # define default configuration POLL=true +-- +2.7.2 + diff --git a/ejabberd.spec b/ejabberd.spec index f18b57e..ed109ca 100644 --- a/ejabberd.spec +++ b/ejabberd.spec @@ -11,8 +11,8 @@ Name: ejabberd -Version: 16.01 -Release: 4%{?dist} +Version: 16.02 +Release: 1%{?dist} Summary: A distributed, fault-tolerant Jabber/XMPP server License: GPLv2+ @@ -36,9 +36,6 @@ Source13: ejabberdctl.polkit.rules # 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_admin_extra -# rbarlow: it seems that mod_admin_extra already exists upstream in 15.11 -#Patch2: ejabberd-0002-Introducing-mod_admin_extra.patch # BZ# 439583, 452326, 451554, 465196, 502361 (fedora/epel-specific) # rbarlow: i'm not sure what this patch is for, but it does not apply cleanly #Patch3: ejabberd-0003-Fedora-specific-changes-to-ejabberdctl.patch @@ -63,7 +60,6 @@ Patch10:ejabberd-0010-Enable-systemd-notification-if-available.patch #Patch11: ejabberd-0011-aarch64.patch Patch13: 0013-Do-not-manage-deps-during-build.patch -Patch14: 0014-Remove-the-xmlrpc-dependency-as-it-s-only-used-for-t.patch BuildRequires: elixir >= 1.1.0 BuildRequires: erlang >= 17.1 @@ -162,7 +158,6 @@ Windows NT/2000/XP). %setup -q %patch1 -p1 -b .pam_name -# %patch2 -p1 -b .mod_admin_extra # %patch3 -p1 -b .fedora_specific # %patch4 -p1 -b .so_lib_755 # %patch5 -p1 -b .false_security @@ -172,35 +167,19 @@ Windows NT/2000/XP). # %patch9 -p1 -b .captcha_perms #%patch10 -p1 -b .systemd_notify -#tar xvf %{S:1} #%patch11 -p1 #%patch13 -p1 -%patch14 -p1 -#touch deps/.got -#touch deps/.built %build autoreconf -ivf -#./autogen.sh -# Disabled: --enable-hipe --enable-roster-gateway-workaround --enable-transient_supervisors --enable-full-xml --enable-mssql --enable-tools --enable-riak --enable-http +# Disabled: --enable-hipe --enable-roster-gateway-workaround --enable-transient_supervisors +# --enable-full-xml --enable-mssql --enable-tools --enable-riak --enable-http %configure --enable-odbc --enable-mysql --enable-pgsql --enable-pam --enable-zlib --enable-iconv --enable-debug --enable-lager --libdir=%{_libdir}/erlang/lib/ --with-erlang=%{_libdir}/erlang/ mkdir deps make -t deps make src REBAR=%__rebar -#pushd doc -#%ifarch %{power64} -#ulimit -a -#ulimit -Hs 65536 -#ulimit -Ss 65536 -#%endif -# remove pre-built docs -#rm -f dev.html features.html -## See this link - http://thread.gmane.org/gmane.linux.redhat.fedora.devel/198954/focus=198957 -#make release -#make html pdf -#popd # make edoc @@ -352,14 +331,11 @@ fi) %attr(750,ejabberd,ejabberd) %dir /var/lock/ejabberdctl %attr(750,ejabberd,ejabberd) %dir /var/log/ejabberd -#%files doc -#%doc doc/*.html -#%doc doc/*.png -#%doc doc/*.pdf -#%doc doc/*.txt - %changelog +* Sun Mar 06 2016 Randy Barlow <rbarlow@redhat.com> - 16.02-1 +- Update to 16.02 + * Sun Mar 06 2016 Randy Barlow <rbarlow@redhat.com> - 16.01-4 - Run ejabberdctl with bash when stopping in the unit file (#1314753). @@ -1 +1 @@ -ef7bd609e06aea11a7abb6a178016b7e 16.01.tar.gz +163cda9b8ee0baaab6b154de678b18c7 16.02.tar.gz |