24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-08 21:43:07 +02:00

Merge from trunk (r1764 to r1787).

Warning: Ejabberd may be broken until the merge is completly finished.

PR:		EJABP-1

SVN Revision: 1827
This commit is contained in:
Jean-Sébastien Pédron 2009-01-19 11:59:40 +00:00
parent bc51bd0dbd
commit 25009ff9f4
28 changed files with 289 additions and 98 deletions

View File

@ -1,6 +1,6 @@
2009-01-19 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2009-01-19 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
Merge from trunk (r1752 to r1764). Merge from trunk (r1752 to r1787).
2009-01-19 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2009-01-19 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
@ -77,6 +77,16 @@
* src/ejabberd_c2s.erl: Fix bug in handle_info/3 when dealing with * src/ejabberd_c2s.erl: Fix bug in handle_info/3 when dealing with
VCARD requests: convert to IQ struct before invoking gen_iq_handler. VCARD requests: convert to IQ struct before invoking gen_iq_handler.
2009-01-09 Badlop <badlop@process-one.net>
* src/mod_configure.erl: Fix access check for vhost configuration
2009-01-08 Mickael Remond <mremond@process-one.net>
* src/ejabberd_listener.erl: Define send timeout option to avoid
blocking on socket send (EJAB-746).
* src/ejabberd_s2s_out.erl: Likewise.
2009-01-08 Christophe Romain <christophe.romain@process-one.net> 2009-01-08 Christophe Romain <christophe.romain@process-one.net>
* src/mod_pubsub/mod_pubsub.erl: completely support subscription using * src/mod_pubsub/mod_pubsub.erl: completely support subscription using
@ -143,6 +153,35 @@
ejabberd_sm, ejabberd_router, ejabberd_hooks, mod_last, mod_roster to ejabberd_sm, ejabberd_router, ejabberd_hooks, mod_last, mod_roster to
use binary() storage. use binary() storage.
2009-01-07 Badlop <badlop@process-one.net>
* src/mod_roster.erl: Show hyperlinks to local contacts when
browsing roster of account in Web Admin (EJAB-480)
* src/mod_roster_odbc.erl: Likewise
* src/web/ejabberd_web_admin.erl: WebAdmin serves Guide and links
to related sections; the path to guide.html can be configured with
option doc_path (EJAB-837)
* src/web/ejabberd_web_admin.hrl: Likewise
* src/mod_shared_roster.erl: Likewise
* doc/guide.tex: Likewise
* doc/guide.html: Likewise
2009-01-06 Badlop <badlop@process-one.net>
* src/msgs/ru.po: Fix typo (thanks to Dominges)
* src/msgs/ru.msg: Likewise
2009-01-05 Alexey Shchepin <alexey@process-one.net>
* src/tls/tls_drv.c: Added a flag to avoid certificate validation
* src/tls/tls.erl: Likewise
* src/ejabberd_c2s.erl: Likewise
2009-01-03 Badlop <badlop@process-one.net>
* src/*.erl: Fix EDoc comments
2009-01-03 Christophe Romain <christophe.romain@process-one.net> 2009-01-03 Christophe Romain <christophe.romain@process-one.net>
* src/mod_pubsub/mod_pubsub.erl: deliver notification depending on * src/mod_pubsub/mod_pubsub.erl: deliver notification depending on

View File

@ -3072,7 +3072,17 @@ web browser to <CODE>https://192.168.1.1:5280/admin/</CODE>:
tls, {certfile, "/usr/local/etc/server.pem"}]}, tls, {certfile, "/usr/local/etc/server.pem"}]},
... ...
]}. ]}.
</PRE></LI></UL><P> <A NAME="adhoccommands"></A> </P><!--TOC section Ad-hoc Commands--> </PRE></LI></UL><P>Certain pages in the ejabberd Web Admin contain a link to a related
section in the ejabberd Installation and Operation Guide.
In order to view such links, a copy in HTML format of the Guide must
be installed in the system.
The file is searched by default in
<TT>"/share/doc/ejabberd/guide.html"</TT>.
The directory of the documentation can be specified in
<TT>ejabberd.cfg</TT> with the option <TT>doc_path</TT>.
For example:
</P><PRE CLASS="verbatim">{doc_path, "/usr/local/share/doc/ejabberd/"}.
</PRE><P> <A NAME="adhoccommands"></A> </P><!--TOC section Ad-hoc Commands-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc65">4.3</A>&#XA0;&#XA0;<A HREF="#adhoccommands">Ad-hoc Commands</A></H2><!--SEC END --><P> <A NAME="adhoccommands"></A> </P><P>If you enable <TT>mod_configure</TT> and <TT>mod_adhoc</TT>, <H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc65">4.3</A>&#XA0;&#XA0;<A HREF="#adhoccommands">Ad-hoc Commands</A></H2><!--SEC END --><P> <A NAME="adhoccommands"></A> </P><P>If you enable <TT>mod_configure</TT> and <TT>mod_adhoc</TT>,
you can perform several administrative tasks in <TT>ejabberd</TT> you can perform several administrative tasks in <TT>ejabberd</TT>
with a Jabber client. with a Jabber client.

View File

@ -3943,6 +3943,18 @@ Examples:
\end{verbatim} \end{verbatim}
\end{itemize} \end{itemize}
Certain pages in the ejabberd Web Admin contain a link to a related
section in the ejabberd Installation and Operation Guide.
In order to view such links, a copy in HTML format of the Guide must
be installed in the system.
The file is searched by default in
\term{"/share/doc/ejabberd/guide.html"}.
The directory of the documentation can be specified in
\term{ejabberd.cfg} with the option \term{doc\_path}.
For example:
\begin{verbatim}
{doc_path, "/usr/local/share/doc/ejabberd/"}.
\end{verbatim}
\makesection{adhoccommands}{Ad-hoc Commands} \makesection{adhoccommands}{Ad-hoc Commands}

View File

@ -163,7 +163,7 @@ connect_nodes() ->
end. end.
%% @spec () -> string() %% @spec () -> string()
%% Returns the full path to the ejabberd log file. %% @doc Returns the full path to the ejabberd log file.
%% It first checks for application configuration parameter 'log_path'. %% It first checks for application configuration parameter 'log_path'.
%% If not defined it checks the environment variable EJABBERD_LOG_PATH. %% If not defined it checks the environment variable EJABBERD_LOG_PATH.
%% And if that one is neither defined, returns the default value: %% And if that one is neither defined, returns the default value:

View File

@ -260,7 +260,7 @@ is_user_exists_in_other_modules(Module, User, Server) ->
end, auth_modules(Server)--[Module]). end, auth_modules(Server)--[Module]).
%% @spec (User, Server) -> ok | error | {error, not_allowed} %% @spec (User, Server) -> ok | error | {error, not_allowed}
%% Remove user. %% @doc Remove user.
%% Note: it may return ok even if there was some problem removing the user. %% Note: it may return ok even if there was some problem removing the user.
remove_user(User, Server) -> remove_user(User, Server) ->
R = lists:foreach( R = lists:foreach(
@ -274,7 +274,7 @@ remove_user(User, Server) ->
R. R.
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error %% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error
%% Try to remove user if the provided password is correct. %% @doc Try to remove user if the provided password is correct.
%% The removal is attempted in each auth method provided: %% The removal is attempted in each auth method provided:
%% when one returns 'ok' the loop stops; %% when one returns 'ok' the loop stops;
%% if no method returns 'ok' then it returns the error message indicated by the last method attempted. %% if no method returns 'ok' then it returns the error message indicated by the last method attempted.

View File

@ -254,7 +254,7 @@ is_user_exists(User, Server) ->
end. end.
%% @spec (User, Server) -> ok %% @spec (User, Server) -> ok
%% Remove user. %% @doc Remove user.
%% Note: it returns ok even if there was some problem removing the user. %% Note: it returns ok even if there was some problem removing the user.
remove_user(User, Server) -> remove_user(User, Server) ->
try try
@ -272,7 +272,7 @@ remove_user(User, Server) ->
end. end.
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request %% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request
%% Remove user if the provided password is correct. %% @doc Remove user if the provided password is correct.
remove_user(User, Server, Password) -> remove_user(User, Server, Password) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),

View File

@ -227,7 +227,7 @@ is_user_exists(User, Server) ->
end. end.
%% @spec (User, Server) -> ok | error %% @spec (User, Server) -> ok | error
%% Remove user. %% @doc Remove user.
%% Note: it may return ok even if there was some problem removing the user. %% Note: it may return ok even if there was some problem removing the user.
remove_user(User, Server) -> remove_user(User, Server) ->
try try
@ -242,7 +242,7 @@ remove_user(User, Server) ->
end. end.
%% @spec (User, Server, Password) -> ok | error | not_exists | not_allowed %% @spec (User, Server, Password) -> ok | error | not_exists | not_allowed
%% Remove user if the provided password is correct. %% @doc Remove user if the provided password is correct.
remove_user(User, Server, Password) -> remove_user(User, Server, Password) ->
try try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),

View File

@ -175,9 +175,11 @@ init([{SockMod, Socket}, Opts]) ->
StartTLSRequired = lists:member(starttls_required, Opts), StartTLSRequired = lists:member(starttls_required, Opts),
TLSEnabled = lists:member(tls, Opts), TLSEnabled = lists:member(tls, Opts),
TLS = StartTLS orelse StartTLSRequired orelse TLSEnabled, TLS = StartTLS orelse StartTLSRequired orelse TLSEnabled,
TLSOpts = lists:filter(fun({certfile, _}) -> true; TLSOpts1 =
(_) -> false lists:filter(fun({certfile, _}) -> true;
end, Opts), (_) -> false
end, Opts),
TLSOpts = [verify_none | TLSOpts1],
IP = peerip(SockMod, Socket), IP = peerip(SockMod, Socket),
%% Check if IP is blacklisted: %% Check if IP is blacklisted:
case is_ip_blacklisted(IP) of case is_ip_blacklisted(IP) of

View File

@ -226,8 +226,7 @@ process2(Args) ->
%% Command calling %% Command calling
%%----------------------------- %%-----------------------------
%% @spec (Args::[string()]) -> %% @spec (Args::[string()]) -> string() | integer() | {string(), integer()}
%% String::string() | Code::integer() | {String::string(), Code::integer()}
try_run_ctp(Args) -> try_run_ctp(Args) ->
try ejabberd_hooks:run_fold(ejabberd_ctl_process, false, [Args]) of try ejabberd_hooks:run_fold(ejabberd_ctl_process, false, [Args]) of
false when Args /= [] -> false when Args /= [] ->
@ -248,8 +247,7 @@ try_run_ctp(Args) ->
{io_lib:format("Error in ejabberd ctl process: '~p' ~p", [Error, Why]), ?STATUS_USAGE} {io_lib:format("Error in ejabberd ctl process: '~p' ~p", [Error, Why]), ?STATUS_USAGE}
end. end.
%% @spec (Args::[string()]) -> %% @spec (Args::[string()]) -> string() | integer() | {string(), integer()}
%% String::string() | Code::integer() | {String::string(), Code::integer()}
try_call_command(Args) -> try_call_command(Args) ->
try call_command(Args) of try call_command(Args) of
{error, command_unknown} -> {error, command_unknown} ->
@ -264,8 +262,7 @@ try_call_command(Args) ->
{io_lib:format("Problem '~p ~p' occurred executing the command.~nStacktrace: ~p", [A, Why, Stack]), ?STATUS_ERROR} {io_lib:format("Problem '~p ~p' occurred executing the command.~nStacktrace: ~p", [A, Why, Stack]), ?STATUS_ERROR}
end. end.
%% @spec (Args::[string()]) -> %% @spec (Args::[string()]) -> string() | integer() | {string(), integer()} | {error, ErrorType}
%% String::string() | Code::integer() | {String::string(), Code::integer()} | {error, ErrorType}
call_command([CmdString | Args]) -> call_command([CmdString | Args]) ->
{ok, CmdStringU, _} = regexp:gsub(CmdString, "-", "_"), {ok, CmdStringU, _} = regexp:gsub(CmdString, "-", "_"),
Command = list_to_atom(CmdStringU), Command = list_to_atom(CmdStringU),

View File

@ -16,7 +16,7 @@
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details. %%% General Public License for more details.
%%% %%%
%%% You should have received a copy of the GNU General Public License %%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software %%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA %%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@ -38,6 +38,9 @@
-include("ejabberd.hrl"). -include("ejabberd.hrl").
%% We do not block on send anymore.
-define(TCP_SEND_TIMEOUT, 15000).
start_link() -> start_link() ->
supervisor:start_link({local, ejabberd_listeners}, ?MODULE, []). supervisor:start_link({local, ejabberd_listeners}, ?MODULE, []).
@ -96,10 +99,11 @@ init(Port, Module, Opts) ->
end, Opts), end, Opts),
Res = gen_tcp:listen(Port, [binary, Res = gen_tcp:listen(Port, [binary,
{packet, 0}, {packet, 0},
{active, false}, {active, false},
{reuseaddr, true}, {reuseaddr, true},
{nodelay, true}, {nodelay, true},
{send_timeout, ?TCP_SEND_TIMEOUT},
{keepalive, true} | {keepalive, true} |
SockOpts]), SockOpts]),
case Res of case Res of

View File

@ -16,7 +16,7 @@
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details. %%% General Public License for more details.
%%% %%%
%%% You should have received a copy of the GNU General Public License %%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software %%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA %%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@ -96,6 +96,9 @@
%% -define(FSMLIMITS, [{max_queue, 2000}]). %% -define(FSMLIMITS, [{max_queue, 2000}]).
-define(FSMTIMEOUT, 30000). -define(FSMTIMEOUT, 30000).
%% We do not block on send anymore.
-define(TCP_SEND_TIMEOUT, 15000).
%% Maximum delay to wait before retrying to connect after a failed attempt. %% Maximum delay to wait before retrying to connect after a failed attempt.
%% Specified in miliseconds. Default value is 5 minutes. %% Specified in miliseconds. Default value is 5 minutes.
-define(MAX_RETRY_DELAY, 300000). -define(MAX_RETRY_DELAY, 300000).
@ -259,6 +262,7 @@ open_socket2(Type, Addr, Port) ->
Timeout = outgoing_s2s_timeout(), Timeout = outgoing_s2s_timeout(),
case (catch ejabberd_socket:connect(Addr, Port, case (catch ejabberd_socket:connect(Addr, Port,
[binary, {packet, 0}, [binary, {packet, 0},
{send_timeout, ?TCP_SEND_TIMEOUT},
{active, false}, Type], {active, false}, Type],
Timeout)) of Timeout)) of
{ok, _Socket} = R -> R; {ok, _Socket} = R -> R;

View File

@ -319,8 +319,10 @@ adhoc_local_items(Acc, From, To, Lang) ->
{result, Its} -> Its; {result, Its} -> Its;
empty -> [] empty -> []
end, end,
PermLev = get_permission_level(From),
%% Recursively get all configure commands %% Recursively get all configure commands
Nodes = recursively_get_local_items(LServer, "", exmpp_jid:domain(To), Lang), Nodes = recursively_get_local_items(PermLev, LServer, "", exmpp_jid:domain_as_list(Server),
Lang),
Nodes1 = lists:filter( Nodes1 = lists:filter(
fun(N) -> fun(N) ->
Nd = exmpp_xml:get_attribute(N, 'node', ""), Nd = exmpp_xml:get_attribute(N, 'node', ""),
@ -337,15 +339,15 @@ adhoc_local_items(Acc, From, To, Lang) ->
Acc Acc
end. end.
recursively_get_local_items(_LServer, "online users", _Server, _Lang) -> recursively_get_local_items(_PermLev, _LServer, "online users", _Server, _Lang) ->
[]; [];
recursively_get_local_items(_LServer, "all users", _Server, _Lang) -> recursively_get_local_items(_PermLev, _LServer, "all users", _Server, _Lang) ->
[]; [];
recursively_get_local_items(LServer, Node, Server, Lang) -> recursively_get_local_items(PermLev, LServer, Node, Server, Lang) ->
LNode = tokenize(Node), LNode = tokenize(Node),
Items = case get_local_items(LServer, LNode, Server, Lang) of Items = case get_local_items({PermLev, LServer}, LNode, Server, Lang) of
{result, Res} -> {result, Res} ->
Res; Res;
{error, _Error} -> {error, _Error} ->
@ -360,11 +362,17 @@ recursively_get_local_items(LServer, Node, Server, Lang) ->
[]; [];
true -> true ->
[N, recursively_get_local_items( [N, recursively_get_local_items(
LServer, Nd, Server, Lang)] PermLev, LServer, Nd, Server, Lang)]
end end
end, Items)), end, Items)),
Nodes. Nodes.
get_permission_level(JID) ->
case acl:match_rule(global, configure, JID) of
allow -> global;
deny -> vhost
end.
%%%----------------------------------------------------------------------- %%%-----------------------------------------------------------------------
-define(ITEMS_RESULT(Allow, LNode, Fallback), -define(ITEMS_RESULT(Allow, LNode, Fallback),
@ -372,7 +380,8 @@ recursively_get_local_items(LServer, Node, Server, Lang) ->
deny -> deny ->
Fallback; Fallback;
allow -> allow ->
case get_local_items(LServer, LNode, PermLev = get_permission_level(From),
case get_local_items({PermLev, LServer}, LNode,
exmpp_jid:jid_to_binary(To), Lang) of exmpp_jid:jid_to_binary(To), Lang) of
{result, Res} -> {result, Res} ->
{result, Res}; {result, Res};
@ -396,7 +405,8 @@ get_local_items(Acc, From, To, <<>>, Lang) ->
deny -> deny ->
{result, Items}; {result, Items};
allow -> allow ->
case get_local_items(LServer, [], PermLev = get_permission_level(From),
case get_local_items({PermLev, LServer}, [],
exmpp_jid:jid_to_binary(To), Lang) of exmpp_jid:jid_to_binary(To), Lang) of
{result, Res} -> {result, Res} ->
{result, Items ++ Res}; {result, Items ++ Res};
@ -462,6 +472,9 @@ get_local_items(Acc, From, To, Node, Lang) ->
%%%----------------------------------------------------------------------- %%%-----------------------------------------------------------------------
%% @spec ({PermissionLevel, Host}, [string()], Server::string(), Lang)
%% -> {result, [xmlelement()]}
%% PermissionLevel = global | vhost
get_local_items(_Host, [], Server, Lang) -> get_local_items(_Host, [], Server, Lang) ->
{result, {result,
[?NODE("Configuration", <<"config">>), [?NODE("Configuration", <<"config">>),
@ -498,13 +511,13 @@ get_local_items(_Host, ["user"], Server, Lang) ->
get_local_items(_Host, ["http:" | _], _Server, _Lang) -> get_local_items(_Host, ["http:" | _], _Server, _Lang) ->
{result, []}; {result, []};
get_local_items(Host, ["online users"], _Server, _Lang) -> get_local_items({_, Host}, ["online users"], _Server, _Lang) ->
{result, get_online_vh_users(Host)}; {result, get_online_vh_users(Host)};
get_local_items(Host, ["all users"], _Server, _Lang) -> get_local_items({_, Host}, ["all users"], _Server, _Lang) ->
{result, get_all_vh_users(Host)}; {result, get_all_vh_users(Host)};
get_local_items(Host, ["all users", [$@ | Diap]], _Server, _Lang) -> get_local_items({_, Host}, ["all users", [$@ | Diap]], _Server, _Lang) ->
case catch ejabberd_auth:get_vh_registered_users(Host) of case catch ejabberd_auth:get_vh_registered_users(Host) of
{'EXIT', _Reason} -> {'EXIT', _Reason} ->
{error, 'internal-server-error'}; {error, 'internal-server-error'};
@ -528,10 +541,10 @@ get_local_items(Host, ["all users", [$@ | Diap]], _Server, _Lang) ->
end end
end; end;
get_local_items(Host, ["outgoing s2s"], _Server, Lang) -> get_local_items({_, Host}, ["outgoing s2s"], _Server, Lang) ->
{result, get_outgoing_s2s(Host, Lang)}; {result, get_outgoing_s2s(Host, Lang)};
get_local_items(Host, ["outgoing s2s", To], _Server, Lang) -> get_local_items({_, Host}, ["outgoing s2s", To], _Server, Lang) ->
{result, get_outgoing_s2s(Host, Lang, To)}; {result, get_outgoing_s2s(Host, Lang, To)};
get_local_items(_Host, ["running nodes"], Server, Lang) -> get_local_items(_Host, ["running nodes"], Server, Lang) ->
@ -540,7 +553,7 @@ get_local_items(_Host, ["running nodes"], Server, Lang) ->
get_local_items(_Host, ["stopped nodes"], _Server, Lang) -> get_local_items(_Host, ["stopped nodes"], _Server, Lang) ->
{result, get_stopped_nodes(Lang)}; {result, get_stopped_nodes(Lang)};
get_local_items(_Host, ["running nodes", ENode], Server, Lang) -> get_local_items({global, _Host}, ["running nodes", ENode], Server, Lang) ->
ENodeB = list_to_binary(ENode), ENodeB = list_to_binary(ENode),
{result, {result,
[?NODE("Database", <<"running nodes/", ENodeB/binary, "/DB">>), [?NODE("Database", <<"running nodes/", ENodeB/binary, "/DB">>),
@ -552,6 +565,11 @@ get_local_items(_Host, ["running nodes", ENode], Server, Lang) ->
?NODE("Shut Down Service", <<"running nodes/", ENodeB/binary, "/shutdown">>) ?NODE("Shut Down Service", <<"running nodes/", ENodeB/binary, "/shutdown">>)
]}; ]};
get_local_items({vhost, _Host}, ["running nodes", ENode], Server, Lang) ->
{result,
[?NODE("Modules", "running nodes/" ++ ENode ++ "/modules")
]};
get_local_items(_Host, ["running nodes", _ENode, "DB"], _Server, _Lang) -> get_local_items(_Host, ["running nodes", _ENode, "DB"], _Server, _Lang) ->
{result, []}; {result, []};
@ -721,8 +739,8 @@ get_stopped_nodes(_Lang) ->
%%------------------------------------------------------------------------- %%-------------------------------------------------------------------------
-define(COMMANDS_RESULT(Allow, From, To, Request), -define(COMMANDS_RESULT(LServerOrGlobal, From, To, Request),
case Allow of case acl:match_rule(LServerOrGlobal, configure, From) of
deny -> deny ->
{error, 'forbidden'}; {error, 'forbidden'};
allow -> allow ->
@ -732,24 +750,23 @@ get_stopped_nodes(_Lang) ->
adhoc_local_commands(Acc, From, To, #adhoc_request{node = Node} = Request) -> adhoc_local_commands(Acc, From, To, #adhoc_request{node = Node} = Request) ->
LServer = exmpp_jid:ldomain_as_list(To), LServer = exmpp_jid:ldomain_as_list(To),
LNode = tokenize(Node), LNode = tokenize(Node),
Allow = acl:match_rule(LServer, configure, From),
case LNode of case LNode of
["running nodes", _ENode, "DB"] -> ["running nodes", _ENode, "DB"] ->
?COMMANDS_RESULT(Allow, From, To, Request); ?COMMANDS_RESULT(global, From, To, Request);
["running nodes", _ENode, "modules", _] -> ["running nodes", _ENode, "modules", _] ->
?COMMANDS_RESULT(Allow, From, To, Request); ?COMMANDS_RESULT(LServer, From, To, Request);
["running nodes", _ENode, "backup", _] -> ["running nodes", _ENode, "backup", _] ->
?COMMANDS_RESULT(Allow, From, To, Request); ?COMMANDS_RESULT(global, From, To, Request);
["running nodes", _ENode, "import", _] -> ["running nodes", _ENode, "import", _] ->
?COMMANDS_RESULT(Allow, From, To, Request); ?COMMANDS_RESULT(global, From, To, Request);
["running nodes", _ENode, "restart"] -> ["running nodes", _ENode, "restart"] ->
?COMMANDS_RESULT(Allow, From, To, Request); ?COMMANDS_RESULT(global, From, To, Request);
["running nodes", _ENode, "shutdown"] -> ["running nodes", _ENode, "shutdown"] ->
?COMMANDS_RESULT(Allow, From, To, Request); ?COMMANDS_RESULT(global, From, To, Request);
["config", _] -> ["config", _] ->
?COMMANDS_RESULT(Allow, From, To, Request); ?COMMANDS_RESULT(LServer, From, To, Request);
?NS_ADMINL(_) -> ?NS_ADMINL(_) ->
?COMMANDS_RESULT(Allow, From, To, Request); ?COMMANDS_RESULT(LServer, From, To, Request);
_ -> _ ->
Acc Acc
end. end.
@ -1545,7 +1562,7 @@ set_form(_From, Host, ["config", "access"], _Lang, XData) ->
{error, 'bad-request'} {error, 'bad-request'}
end; end;
set_form(_From, _Host, ?NS_ADMINL("add-user"), _Lang, XData) -> set_form(From, Host, ?NS_ADMINL("add-user"), _Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
Password = get_value("password", XData), Password = get_value("password", XData),
Password = get_value("password-verify", XData), Password = get_value("password-verify", XData),
@ -1553,17 +1570,19 @@ set_form(_From, _Host, ?NS_ADMINL("add-user"), _Lang, XData) ->
User = exmpp_jid:lnode_as_list(AccountJID), User = exmpp_jid:lnode_as_list(AccountJID),
Server = exmpp_jid:ldomain_as_list(AccountJID), Server = exmpp_jid:ldomain_as_list(AccountJID),
true = lists:member(Server, ?MYHOSTS), true = lists:member(Server, ?MYHOSTS),
true = (Server == Host) orelse (get_permission_level(From) == global),
ejabberd_auth:try_register(User, Server, Password), ejabberd_auth:try_register(User, Server, Password),
{result, []}; {result, []};
set_form(_From, _Host, ?NS_ADMINL("delete-user"), _Lang, XData) -> set_form(From, Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
AccountStringList = get_values("accountjids", XData), AccountStringList = get_values("accountjids", XData),
[_|_] = AccountStringList, [_|_] = AccountStringList,
ASL2 = lists:map( ASL2 = lists:map(
fun(AccountString) -> fun(AccountString) ->
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:parse_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_as_list(JID), User = [_|_] = exmpp_jid:lnode_as_list(JID),
Server = exmpp_jid:ldomain_as_list(JID), Server = exmpp_jid:ldomain_as_list(JID),
true = (Server == Host) orelse (get_permission_level(From) == global),
true = ejabberd_auth:is_user_exists(User, Server), true = ejabberd_auth:is_user_exists(User, Server),
{User, Server} {User, Server}
end, end,
@ -1571,11 +1590,12 @@ set_form(_From, _Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
[ejabberd_auth:remove_user(User, Server) || {User, Server} <- ASL2], [ejabberd_auth:remove_user(User, Server) || {User, Server} <- ASL2],
{result, []}; {result, []};
set_form(_From, _Host, ?NS_ADMINL("end-user-session"), _Lang, XData) -> set_form(From, Host, ?NS_ADMINL("end-user-session"), _Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
LUser = [_|_] = exmpp_jid:lnode_as_list(JID), LUser = [_|_] = exmpp_jid:lnode_as_list(JID),
LServer = exmpp_jid:ldomain_as_list(JID), LServer = exmpp_jid:ldomain_as_list(JID),
true = (LServer == Host) orelse (get_permission_level(From) == global),
%% Code copied from ejabberd_sm.erl %% Code copied from ejabberd_sm.erl
case exmpp_jid:lresource_as_list(JID) of case exmpp_jid:lresource_as_list(JID) of
undefined -> undefined ->
@ -1589,11 +1609,12 @@ set_form(_From, _Host, ?NS_ADMINL("end-user-session"), _Lang, XData) ->
end, end,
{result, []}; {result, []};
set_form(_From, _Host, ?NS_ADMINL("get-user-password"), Lang, XData) -> set_form(From, Host, ?NS_ADMINL("get-user-password"), Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_as_list(JID), User = [_|_] = exmpp_jid:lnode_as_list(JID),
Server = exmpp_jid:ldomain_as_list(JID), Server = exmpp_jid:ldomain_as_list(JID),
true = (Server == Host) orelse (get_permission_level(From) == global),
Password = ejabberd_auth:get_password(User, Server), Password = ejabberd_auth:get_password(User, Server),
true = is_list(Password), true = is_list(Password),
{result, [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children = {result, [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', children =
@ -1602,21 +1623,23 @@ set_form(_From, _Host, ?NS_ADMINL("get-user-password"), Lang, XData) ->
?XFIELD(<<"text-single">>, "Password", <<"password">>, list_to_binary(Password)) ?XFIELD(<<"text-single">>, "Password", <<"password">>, list_to_binary(Password))
]}]}; ]}]};
set_form(_From, _Host, ?NS_ADMINL("change-user-password"), _Lang, XData) -> set_form(From, Host, ?NS_ADMINL("change-user-password"), _Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
Password = get_value("password", XData), Password = get_value("password", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_as_list(JID), User = [_|_] = exmpp_jid:lnode_as_list(JID),
Server = exmpp_jid:ldomain_as_list(JID), Server = exmpp_jid:ldomain_as_list(JID),
true = (Server == Host) orelse (get_permission_level(From) == global),
true = ejabberd_auth:is_user_exists(User, Server), true = ejabberd_auth:is_user_exists(User, Server),
ejabberd_auth:set_password(User, Server, Password), ejabberd_auth:set_password(User, Server, Password),
{result, []}; {result, []};
set_form(_From, _Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) -> set_form(From, Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_as_list(JID), User = [_|_] = exmpp_jid:lnode_as_list(JID),
Server = exmpp_jid:ldomain_as_list(JID), Server = exmpp_jid:ldomain_as_list(JID),
true = (Server == Host) orelse (get_permission_level(From) == global),
%% Code copied from web/ejabberd_web_admin.erl %% Code copied from web/ejabberd_web_admin.erl
%% TODO: Update time format to XEP-0202: Entity Time %% TODO: Update time format to XEP-0202: Entity Time
@ -1649,11 +1672,12 @@ set_form(_From, _Host, ?NS_ADMINL("get-user-lastlogin"), Lang, XData) ->
?XFIELD(<<"text-single">>, "Last login", <<"lastlogin">>, list_to_binary(FLast)) ?XFIELD(<<"text-single">>, "Last login", <<"lastlogin">>, list_to_binary(FLast))
]}]}; ]}]};
set_form(_From, _Host, ?NS_ADMINL("user-stats"), Lang, XData) -> set_form(From, Host, ?NS_ADMINL("user-stats"), Lang, XData) ->
AccountString = get_value("accountjid", XData), AccountString = get_value("accountjid", XData),
JID = exmpp_jid:list_to_jid(AccountString), JID = exmpp_jid:list_to_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_as_list(JID), User = [_|_] = exmpp_jid:lnode_as_list(JID),
Server = exmpp_jid:ldomain_as_list(JID), Server = exmpp_jid:ldomain_as_list(JID),
true = (Server == Host) orelse (get_permission_level(From) == global),
Resources = ejabberd_sm:get_user_resources(exmpp_jid:lnode(JID), Resources = ejabberd_sm:get_user_resources(exmpp_jid:lnode(JID),
exmpp_jid:ldomain(JID)), exmpp_jid:ldomain(JID)),

View File

@ -168,7 +168,7 @@ store_last_info(User, Server, TimeStamp, Status)
ok ok
end. end.
%% @spec (LUser::string(), LServer::string() -> %% @spec (LUser::string(), LServer::string()) ->
%% {ok, Timestamp::integer(), Status::string()} | not_found %% {ok, Timestamp::integer(), Status::string()} | not_found
get_last_info(LUser, LServer) when is_binary(LUser), is_binary(LServer) -> get_last_info(LUser, LServer) when is_binary(LUser), is_binary(LServer) ->
case catch mnesia:dirty_read(last_activity, {LUser, LServer}) of case catch mnesia:dirty_read(last_activity, {LUser, LServer}) of

View File

@ -168,7 +168,7 @@ store_last_info(User, Server, TimeStamp, Status)
ok ok
end. end.
%% @spec (LUser::string(), LServer::string() -> %% @spec (LUser::string(), LServer::string()) ->
%% {ok, Timestamp::integer(), Status::string()} | not_found %% {ok, Timestamp::integer(), Status::string()} | not_found
get_last_info(LUser, LServer) -> get_last_info(LUser, LServer) ->
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),

View File

@ -33,7 +33,7 @@
%%% This module uses version 1.12 of the specification as a base. %%% This module uses version 1.12 of the specification as a base.
%%% Most of the specification is implemented. %%% Most of the specification is implemented.
%%% Functions concerning configuration should be rewritten. %%% Functions concerning configuration should be rewritten.
%%% Code is derivated from the original pubsub v1.7, by Alexey Shchepin <alexey@process-one.net> %%% Code is derivated from the original pubsub v1.7, by Alexey Shchepin
%%% TODO %%% TODO
%%% plugin: generate Reply (do not use broadcast atom anymore) %%% plugin: generate Reply (do not use broadcast atom anymore)
@ -1749,10 +1749,11 @@ get_items(Host, Node, From) ->
send_last_item(Host, Node, LJID) -> send_last_item(Host, Node, LJID) ->
send_items(Host, Node, LJID, last). send_items(Host, Node, LJID, last).
%% @spec (Host, Node, LJID) -> any() %% @spec (Host, Node, LJID, Number) -> any()
%% Host = host() %% Host = host()
%% Node = pubsubNode() %% Node = pubsubNode()
%% LJID = {U, S, []} %% LJID = {U, S, []}
%% Number = last | integer()
%% @doc <p>Resend the items of a node to the user.</p> %% @doc <p>Resend the items of a node to the user.</p>
%% @todo use cache-last-item feature %% @todo use cache-last-item feature
send_items(Host, Node, {LU, LS, LR} = LJID, Number) -> send_items(Host, Node, {LU, LS, LR} = LJID, Number) ->
@ -2157,10 +2158,9 @@ is_to_deliver({User, Server, _}, _, true) ->
end, false, Ss) end, false, Ss)
end. end.
%% @spec (Elem, Payload) -> int() %% @spec (Payload) -> int()
%% Elem = atom()
%% Payload = term() %% Payload = term()
%% @doc <p>Count occurence of given element in payload.</p> %% @doc <p>Count occurence of XML elements in payload.</p>
payload_xmlelements(Payload) -> payload_xmlelements(Payload, 0). payload_xmlelements(Payload) -> payload_xmlelements(Payload, 0).
payload_xmlelements([], Count) -> Count; payload_xmlelements([], Count) -> Count;
payload_xmlelements([#xmlel{}|Tail], Count) -> payload_xmlelements(Tail, Count+1); payload_xmlelements([#xmlel{}|Tail], Count) -> payload_xmlelements(Tail, Count+1);
@ -2168,7 +2168,7 @@ payload_xmlelements([_|Tail], Count) -> payload_xmlelements(Tail, Count).
%% @spec (Els) -> stanza() %% @spec (Els) -> stanza()
%% Els = [xmlelement()] %% Els = [xmlelement()]
%% @doc <p>Build pubsub event stanza %% @doc <p>Build pubsub event stanza</p>
event_stanza(Els) -> event_stanza(Els) ->
#xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children = #xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children =
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'event', children = Els}]}. [#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'event', children = Els}]}.

View File

@ -677,7 +677,7 @@ set_state(_) ->
del_state(StateId) -> del_state(StateId) ->
mnesia:delete({pubsub_state, StateId}). mnesia:delete({pubsub_state, StateId}).
%% @spec (Host, Node) -> [Items] | [] %% @spec (Host, Node, From) -> [Items] | []
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% Items = mod_pubsub:pubsubItems() %% Items = mod_pubsub:pubsubItems()
@ -784,7 +784,7 @@ set_item(Item) when is_record(Item, pubsub_item) ->
set_item(_) -> set_item(_) ->
{error, 'internal-server-error'}. {error, 'internal-server-error'}.
%% @spec (ItemId) -> ok | {error, Reason::stanzaError()} %% @spec (Host, Node, ItemId) -> ok | {error, Reason::stanzaError()}
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% ItemId = string() %% ItemId = string()

View File

@ -30,6 +30,7 @@
%%% {plugins, ["default", "pep","mb"]}, %%% {plugins, ["default", "pep","mb"]},
%%% {pep_mapping, [{"urn:xmpp:microblog", "mb"}]} %%% {pep_mapping, [{"urn:xmpp:microblog", "mb"}]}
%%% ]}, %%% ]},
%%% </p>
%%% <p>PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.</p> %%% <p>PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.</p>
-module(node_mb). -module(node_mb).

View File

@ -97,12 +97,12 @@ set_node(Record) when is_record(Record, pubsub_node) ->
set_node(_) -> set_node(_) ->
{error, 'internal-server-error'}. {error, 'internal-server-error'}.
%% @spec (Host, Node) -> pubsubNode() | {error, Reason}
%% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode()
get_node(Host, Node, _From) -> get_node(Host, Node, _From) ->
get_node(Host, Node). get_node(Host, Node).
%% @spec (Host, Node) -> pubsubNode() | {error, Reason}
%% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode()
get_node(Host, Node) -> get_node(Host, Node) ->
case catch mnesia:read({pubsub_node, {Host, Node}}) of case catch mnesia:read({pubsub_node, {Host, Node}}) of
[Record] when is_record(Record, pubsub_node) -> Record; [Record] when is_record(Record, pubsub_node) -> Record;
@ -110,11 +110,11 @@ get_node(Host, Node) ->
Error -> Error Error -> Error
end. end.
%% @spec (Key) -> [pubsubNode()] | {error, Reason}
%% Key = mod_pubsub:host() | mod_pubsub:jid()
get_nodes(Key, _From) -> get_nodes(Key, _From) ->
get_nodes(Key). get_nodes(Key).
%% @spec (Key) -> [pubsubNode()] | {error, Reason}
%% Key = mod_pubsub:host() | mod_pubsub:jid()
get_nodes(Key) -> get_nodes(Key) ->
mnesia:match_object(#pubsub_node{nodeid = {Key, '_'}, _ = '_'}). mnesia:match_object(#pubsub_node{nodeid = {Key, '_'}, _ = '_'}).

View File

@ -84,24 +84,24 @@ options() ->
set_node(_NodeRecord) -> set_node(_NodeRecord) ->
ok. ok.
get_node(Host, Node, _From) ->
get_node(Host, Node).
%% @spec (Host, Node) -> pubsubNode() %% @spec (Host, Node) -> pubsubNode()
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered %% @doc <p>Virtual node tree does not handle a node database. Any node is considered
%% as existing. Node record contains default values.</p> %% as existing. Node record contains default values.</p>
get_node(Host, Node, _From) ->
get_node(Host, Node).
get_node(Host, Node) -> get_node(Host, Node) ->
#pubsub_node{nodeid = {Host, Node}}. #pubsub_node{nodeid = {Host, Node}}.
get_nodes(Key, _From) ->
get_nodes(Key).
%% @spec (Key) -> [pubsubNode()] %% @spec (Key) -> [pubsubNode()]
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | mod_pubsub:jid()
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered %% @doc <p>Virtual node tree does not handle a node database. Any node is considered
%% as existing. Nodes list can not be determined.</p> %% as existing. Nodes list can not be determined.</p>
get_nodes(Key, _From) ->
get_nodes(Key).
get_nodes(_Key) -> get_nodes(_Key) ->
[]. [].

View File

@ -883,10 +883,9 @@ user_roster(User, Server, Query, Lang) ->
[?C(Group), ?BR] [?C(Group), ?BR]
end, R#roster.groups), end, R#roster.groups),
Pending = ask_to_pending(R#roster.ask), Pending = ask_to_pending(R#roster.ask),
{U, S, R} = R#roster.jid, TDJID = build_contact_jid_td(R#roster.jid),
?XE("tr", ?XE("tr",
[?XAC("td", [{"class", "valign"}], [TDJID,
catch exmpp_jid:jid_to_list(U, S, R)),
?XAC("td", [{"class", "valign"}], ?XAC("td", [{"class", "valign"}],
binary_to_list(R#roster.name)), binary_to_list(R#roster.name)),
?XAC("td", [{"class", "valign"}], ?XAC("td", [{"class", "valign"}],
@ -934,6 +933,26 @@ user_roster(User, Server, Query, Lang) ->
])] ])]
end. end.
build_contact_jid_td({U, S, R}) ->
%% Convert {U, S, R} into {jid, U, S, R, U, S, R}:
ContactJID = exmpp_jid:make_jid(U, S, R),
JIDURI = case {exmpp_jid:lnode(ContactJID), exmpp_jid:ldomain(ContactJID)} of
{undefined, _} -> "";
{CUser, CServer} ->
CUser_S = binary_to_list(CUser),
CServer_S = binary_to_list(CServer),
case lists:member(CServer_S, ?MYHOSTS) of
false -> "";
true -> "/admin/server/" ++ CServer_S ++ "/user/" ++ CUser_S ++ "/"
end
end,
case JIDURI of
[] ->
?XAC('td', [#xmlattr{name = 'class', value = <<"valign">>}], exmpp_jid:jid_to_list(ContactJID));
URI when is_list(URI) ->
?XAE('td', [#xmlattr{name = 'class', value = <<"valign">>}], [?AC(JIDURI, exmpp_jid:jid_to_list(ContactJID))])
end.
user_roster_parse_query(User, Server, Items, Query) -> user_roster_parse_query(User, Server, Items, Query) ->
case lists:keysearch("addjid", 1, Query) of case lists:keysearch("addjid", 1, Query) of
{value, _} -> {value, _} ->

View File

@ -922,10 +922,9 @@ user_roster(User, Server, Query, Lang) ->
[?C(Group), ?BR] [?C(Group), ?BR]
end, R#roster.groups), end, R#roster.groups),
Pending = ask_to_pending(R#roster.ask), Pending = ask_to_pending(R#roster.ask),
{U, S, R} = R#roster.jid, TDJID = build_contact_jid_td(R#roster.jid),
?XE("tr", ?XE("tr",
[?XAC("td", [{"class", "valign"}], [TDJID,
catch exmpp_jid:jid_to_list(U, S, R)),
?XAC("td", [{"class", "valign"}], ?XAC("td", [{"class", "valign"}],
binary_to_list(R#roster.name)), binary_to_list(R#roster.name)),
?XAC("td", [{"class", "valign"}], ?XAC("td", [{"class", "valign"}],
@ -973,6 +972,26 @@ user_roster(User, Server, Query, Lang) ->
])] ])]
end. end.
build_contact_jid_td({U, S, R}) ->
%% Convert {U, S, R} into {jid, U, S, R, U, S, R}:
ContactJID = exmpp_jid:make_jid(U, S, R),
JIDURI = case {exmpp_jid:lnode(ContactJID), exmpp_jid:ldomain(ContactJID)} of
{undefined, _} -> "";
{CUser, CServer} ->
CUser_S = binary_to_list(CUser),
CServer_S = binary_to_list(CServer),
case lists:member(CServer_S, ?MYHOSTS) of
false -> "";
true -> "/admin/server/" ++ CServer_S ++ "/user/" ++ CUser_S ++ "/"
end
end,
case JIDURI of
[] ->
?XAC('td', [#xmlattr{name = 'class', value = <<"valign">>}], exmpp_jid:jid_to_list(ContactJID));
URI when is_list(URI) ->
?XAE('td', [#xmlattr{name = 'class', value = <<"valign">>}], [?AC(JIDURI, exmpp_jid:jid_to_list(ContactJID))])
end.
user_roster_parse_query(User, Server, Items, Query) -> user_roster_parse_query(User, Server, Items, Query) ->
case lists:keysearch("addjid", 1, Query) of case lists:keysearch("addjid", 1, Query) of
{value, _} -> {value, _} ->

View File

@ -740,7 +740,7 @@ list_shared_roster_groups(Host, Query, Lang) ->
] ]
)] )]
)]), )]),
[?XC("h1", ?T("Shared Roster Groups"))] ++ ?H1GL(?T("Shared Roster Groups"), "modsharedroster", "mod_shared_roster") ++
case Res of case Res of
ok -> [?CT("Submitted"), ?P]; ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P]; error -> [?CT("Bad format"), ?P];
@ -839,7 +839,7 @@ shared_roster_group(Host, Group, Query, Lang) ->
] ]
)] )]
)]), )]),
[?XC("h1", ?T("Shared Roster Groups"))] ++ ?H1GL(?T("Shared Roster Groups"), "modsharedroster", "mod_shared_roster") ++
[?XC("h2", ?T("Group ") ++ Group)] ++ [?XC("h2", ?T("Group ") ++ Group)] ++
case Res of case Res of
ok -> [?CT("Submitted"), ?P]; ok -> [?CT("Submitted"), ?P];

View File

@ -166,7 +166,7 @@
{"Name","Название"}. {"Name","Название"}.
{"Never","Никогда"}. {"Never","Никогда"}.
{"Nickname is already in use by another occupant","Псевдоним занят кем-то из присутствующих"}. {"Nickname is already in use by another occupant","Псевдоним занят кем-то из присутствующих"}.
{"Nickname is registered by another person","Псевдоним зарегистирован кем-то другим"}. {"Nickname is registered by another person","Псевдоним зарегистрирован кем-то другим"}.
{"Nickname Registration at ","Регистрация псевдонима на "}. {"Nickname Registration at ","Регистрация псевдонима на "}.
{"Nickname ~s does not exist in the room","Псевдоним ~s в комнате отсутствует"}. {"Nickname ~s does not exist in the room","Псевдоним ~s в комнате отсутствует"}.
{"Nickname","Псевдоним"}. {"Nickname","Псевдоним"}.

View File

@ -723,7 +723,7 @@ msgstr "Псевдоним занят кем-то из присутствующ
#: mod_muc/mod_muc_room.erl:973 mod_muc/mod_muc_room.erl:1492 #: mod_muc/mod_muc_room.erl:973 mod_muc/mod_muc_room.erl:1492
msgid "Nickname is registered by another person" msgid "Nickname is registered by another person"
msgstr "Псевдоним зарегистирован кем-то другим" msgstr "Псевдоним зарегистрирован кем-то другим"
#: mod_muc/mod_muc_room.erl:1473 #: mod_muc/mod_muc_room.erl:1473
msgid "You have been banned from this room" msgid "You have been banned from this room"

View File

@ -59,6 +59,7 @@
-define(GET_DECRYPTED_INPUT, 6). -define(GET_DECRYPTED_INPUT, 6).
-define(GET_PEER_CERTIFICATE, 7). -define(GET_PEER_CERTIFICATE, 7).
-define(GET_VERIFY_RESULT, 8). -define(GET_VERIFY_RESULT, 8).
-define(VERIFY_NONE, 16#10000).
-record(tlssock, {tcpsock, tlsport}). -record(tlssock, {tcpsock, tlsport}).
@ -120,13 +121,20 @@ tcp_to_tls(TCPSocket, Options) ->
{error, already_loaded} -> ok {error, already_loaded} -> ok
end, end,
Port = open_port({spawn, tls_drv}, [binary]), Port = open_port({spawn, tls_drv}, [binary]),
Flags =
case lists:member(verify_none, Options) of
true ->
?VERIFY_NONE;
false ->
0
end,
Command = case lists:member(connect, Options) of Command = case lists:member(connect, Options) of
true -> true ->
?SET_CERTIFICATE_FILE_CONNECT; ?SET_CERTIFICATE_FILE_CONNECT;
false -> false ->
?SET_CERTIFICATE_FILE_ACCEPT ?SET_CERTIFICATE_FILE_ACCEPT
end, end,
case port_control(Port, Command, CertFile ++ [0]) of case port_control(Port, Command bor Flags, CertFile ++ [0]) of
<<0>> -> <<0>> ->
{ok, #tlssock{tcpsock = TCPSocket, tlsport = Port}}; {ok, #tlssock{tcpsock = TCPSocket, tlsport = Port}};
<<1, Error/binary>> -> <<1, Error/binary>> ->

View File

@ -272,6 +272,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
#define GET_DECRYPTED_INPUT 6 #define GET_DECRYPTED_INPUT 6
#define GET_PEER_CERTIFICATE 7 #define GET_PEER_CERTIFICATE 7
#define GET_VERIFY_RESULT 8 #define GET_VERIFY_RESULT 8
#define VERIFY_NONE 0x10000
#define die_unless(cond, errstr) \ #define die_unless(cond, errstr) \
@ -312,6 +313,9 @@ static int tls_drv_control(ErlDrvData handle,
int size; int size;
ErlDrvBinary *b; ErlDrvBinary *b;
X509 *cert; X509 *cert;
unsigned int flags = command;
command &= 0xffff;
ERR_clear_error(); ERR_clear_error();
switch (command) switch (command)
@ -354,6 +358,9 @@ static int tls_drv_control(ErlDrvData handle,
d->ssl = SSL_new(ssl_ctx); d->ssl = SSL_new(ssl_ctx);
die_unless(d->ssl, "SSL_new failed"); die_unless(d->ssl, "SSL_new failed");
if (flags & VERIFY_NONE)
SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback);
d->bio_read = BIO_new(BIO_s_mem()); d->bio_read = BIO_new(BIO_s_mem());
d->bio_write = BIO_new(BIO_s_mem()); d->bio_write = BIO_new(BIO_s_mem());

View File

@ -40,6 +40,30 @@
-include("ejabberd_web_admin.hrl"). -include("ejabberd_web_admin.hrl").
process(["doc", LocalFile], _Request) ->
DocPath = case ejabberd_config:get_global_option(doc_path) of
P when is_list(P) -> P;
_ -> "/share/doc/ejabberd/"
end,
%% Code based in mod_http_fileserver
FileName = filename:join(DocPath, LocalFile),
case file:read_file(FileName) of
{ok, FileContents} ->
?DEBUG("Delivering content.", []),
{200,
[{"Server", "ejabberd"}],
FileContents};
{error, Error} ->
?DEBUG("Delivering error: ~p", [Error]),
Help = " " ++ FileName ++ " - Try to specify the path to ejabberd guide.html "
"with the option doc_path. Check the ejabberd Guide for more information",
case Error of
eacces -> {403, [], "Forbidden"++Help};
enoent -> {404, [], "Not found"++Help};
_Else -> {404, [], atom_to_list(Error)++Help}
end
end;
process(["server", SHost | RPath], #request{auth = Auth} = Request) -> process(["server", SHost | RPath], #request{auth = Auth} = Request) ->
Host = exmpp_stringprep:nameprep(SHost), Host = exmpp_stringprep:nameprep(SHost),
case lists:member(Host, ?MYHOSTS) of case lists:member(Host, ?MYHOSTS) of
@ -108,7 +132,7 @@ get_auth(Auth) ->
make_xhtml(Els, Host, Lang) -> make_xhtml(Els, Host, Lang) ->
make_xhtml(Els, Host, cluster, Lang). make_xhtml(Els, Host, cluster, Lang).
%% @spec (Els, Host, Node, Lang) %% @spec (Els, Host, Node, Lang) -> {200, [html], xmlelement()}
%% where Host = global | string() %% where Host = global | string()
%% Node = cluster | atom() %% Node = cluster | atom()
make_xhtml(Els, Host, Node, Lang) -> make_xhtml(Els, Host, Node, Lang) ->
@ -513,8 +537,13 @@ h3 {
padding-top: 5px; padding-top: 5px;
} }
*.alignright { div.guidelink {
text-align: right; text-align: right;
padding-right: 1em;
}
*.alignright {
font-size: 10pt;
} }
". ".
@ -560,8 +589,8 @@ process_admin(global,
lang = Lang}) -> lang = Lang}) ->
Base = get_base_path(global, cluster), Base = get_base_path(global, cluster),
MenuItems2 = make_menu_items(global, cluster, Base, Lang), MenuItems2 = make_menu_items(global, cluster, Base, Lang),
make_xhtml([?XCT('h1', "Administration"), make_xhtml(?H1GL(?T("Administration"), "toc", "Contents") ++
?XE('ul', [?XE('ul',
[?LI([?ACT("/admin/acls/", "Access Control Lists"), ?C(" "), [?LI([?ACT("/admin/acls/", "Access Control Lists"), ?C(" "),
?ACT("/admin/acls-raw/", "(Raw)")]), ?ACT("/admin/acls-raw/", "(Raw)")]),
?LI([?ACT("/admin/access/", "Access Rules"), ?C(" "), ?LI([?ACT("/admin/access/", "Access Rules"), ?C(" "),
@ -635,7 +664,7 @@ process_admin(Host,
"~p.", [lists:keysort( "~p.", [lists:keysort(
2, ets:select(acl, [{{acl, {'$1', Host}, '$2'}, 2, ets:select(acl, [{{acl, {'$1', Host}, '$2'},
[], [{{acl, '$1', '$2'}}]}]))])), [], [{{acl, '$1', '$2'}}]}]))])),
make_xhtml([?XCT('h1', "Access Control Lists")] ++ make_xhtml(?H1GL(?T("Access Control Lists"), "ACLDefinition", "ACL Definition") ++
case Res of case Res of
ok -> [?CT("Submitted"), ?P]; ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P]; error -> [?CT("Bad format"), ?P];
@ -678,7 +707,7 @@ process_admin(Host,
ACLs = lists:keysort( ACLs = lists:keysort(
2, ets:select(acl, [{{acl, {'$1', Host}, '$2'}, 2, ets:select(acl, [{{acl, {'$1', Host}, '$2'},
[], [{{acl, '$1', '$2'}}]}])), [], [{{acl, '$1', '$2'}}]}])),
make_xhtml([?XCT('h1', "Access Control Lists")] ++ make_xhtml(?H1GL(?T("Access Control Lists"), "ACLDefinition", "ACL Definition") ++
case Res of case Res of
ok -> [?CT("Submitted"), ?P]; ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P]; error -> [?CT("Bad format"), ?P];
@ -746,7 +775,7 @@ process_admin(Host,
[{{config, {access, '$1', Host}, '$2'}, [{{config, {access, '$1', Host}, '$2'},
[], [],
[{{access, '$1', '$2'}}]}])])), [{{access, '$1', '$2'}}]}])])),
make_xhtml([?XCT('h1', "Access Rules")] ++ make_xhtml(?H1GL(?T("Access Rules"), "AccessRights", "Access Rights") ++
case Res of case Res of
ok -> [?CT("Submitted"), ?P]; ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P]; error -> [?CT("Bad format"), ?P];
@ -784,7 +813,7 @@ process_admin(Host,
[{{config, {access, '$1', Host}, '$2'}, [{{config, {access, '$1', Host}, '$2'},
[], [],
[{{access, '$1', '$2'}}]}]), [{{access, '$1', '$2'}}]}]),
make_xhtml([?XCT('h1', "Access Rules")] ++ make_xhtml(?H1GL(?T("Access Rules"), "AccessRights", "Access Rights") ++
case Res of case Res of
ok -> [?CT("Submitted"), ?P]; ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P]; error -> [?CT("Bad format"), ?P];
@ -841,7 +870,7 @@ process_admin(global,
#request{path = ["vhosts"], #request{path = ["vhosts"],
lang = Lang}) -> lang = Lang}) ->
Res = list_vhosts(Lang), Res = list_vhosts(Lang),
make_xhtml([?XCT('h1', "ejabberd virtual hosts")] ++ Res, global, Lang); make_xhtml(?H1GL(?T("ejabberd virtual hosts"), "virtualhost", "Virtual Hosting") ++ Res, global, Lang);
process_admin(Host, process_admin(Host,
#request{path = ["users"], #request{path = ["users"],
@ -1791,7 +1820,8 @@ get_node(global, Node, ["ports"], Query, Lang) ->
end, end,
NewPorts = lists:sort( NewPorts = lists:sort(
rpc:call(Node, ejabberd_config, get_local_option, [listen])), rpc:call(Node, ejabberd_config, get_local_option, [listen])),
[?XC('h1', ?T("Listened Ports at ") ++ atom_to_list(Node))] ++ H1String = ?T("Listened Ports at ") ++ atom_to_list(Node),
?H1GL(H1String, "listened", "Listening Ports") ++
case Res of case Res of
ok -> [?CT("Submitted"), ?P]; ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P]; error -> [?CT("Bad format"), ?P];
@ -1814,7 +1844,8 @@ get_node(Host, Node, ["modules"], Query, Lang) when is_list(Host) ->
end, end,
NewModules = lists:sort( NewModules = lists:sort(
rpc:call(Node, gen_mod, loaded_modules_with_opts, [Host])), rpc:call(Node, gen_mod, loaded_modules_with_opts, [Host])),
[?XC('h1', ?T("Modules at ") ++ atom_to_list(Node))] ++ H1String = ?T("Modules at ") ++ atom_to_list(Node),
?H1GL(H1String, "modoverview", "Modules Overview") ++
case Res of case Res of
ok -> [?CT("Submitted"), ?P]; ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P]; error -> [?CT("Bad format"), ?P];

View File

@ -52,3 +52,17 @@
#xmlattr{name = 'size', value = Size}])). #xmlattr{name = 'size', value = Size}])).
-define(INPUTST(Type, Name, Value, Size), ?INPUT(Type, Name, ?T(Value), Size)). -define(INPUTST(Type, Name, Value, Size), ?INPUT(Type, Name, ?T(Value), Size)).
-define(ACLINPUT(Text), ?XE('td', [?INPUT("text", "value" ++ ID, Text)])). -define(ACLINPUT(Text), ?XE('td', [?INPUT("text", "value" ++ ID, Text)])).
%% Guide Link
-define(GL(Ref, Title),
?XAE('div',
[#xmlattr{name = 'class', value = <<"guidelink">>}],
[?XAE('a',
[#xmlattr{name = "href", value = list_to_binary("/admin/doc/guide.html#"++ Ref)},
#xmlattr{name = "target", value = <<"_blank">>}],
[?C("[Guide: " ++ Title ++ "]")])
])).
%% h1 with a Guide Link
-define(H1GL(Name, Ref, Title), [?XC('h1', Name), ?GL(Ref, Title)]).