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>
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>
@ -77,6 +77,16 @@
* src/ejabberd_c2s.erl: Fix bug in handle_info/3 when dealing with
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>
* 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
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>
* 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"}]},
...
]}.
</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>,
you can perform several administrative tasks in <TT>ejabberd</TT>
with a Jabber client.

View File

@ -3943,6 +3943,18 @@ Examples:
\end{verbatim}
\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}

View File

@ -163,7 +163,7 @@ connect_nodes() ->
end.
%% @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'.
%% If not defined it checks the environment variable EJABBERD_LOG_PATH.
%% 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]).
%% @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.
remove_user(User, Server) ->
R = lists:foreach(
@ -274,7 +274,7 @@ remove_user(User, Server) ->
R.
%% @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:
%% when one returns 'ok' the loop stops;
%% 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.
%% @spec (User, Server) -> ok
%% Remove user.
%% @doc Remove user.
%% Note: it returns ok even if there was some problem removing the user.
remove_user(User, Server) ->
try
@ -272,7 +272,7 @@ remove_user(User, Server) ->
end.
%% @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) ->
try
LUser = exmpp_stringprep:nodeprep(User),

View File

@ -227,7 +227,7 @@ is_user_exists(User, Server) ->
end.
%% @spec (User, Server) -> ok | error
%% Remove user.
%% @doc Remove user.
%% Note: it may return ok even if there was some problem removing the user.
remove_user(User, Server) ->
try
@ -242,7 +242,7 @@ remove_user(User, Server) ->
end.
%% @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) ->
try
LUser = exmpp_stringprep:nodeprep(User),

View File

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

View File

@ -226,8 +226,7 @@ process2(Args) ->
%% Command calling
%%-----------------------------
%% @spec (Args::[string()]) ->
%% String::string() | Code::integer() | {String::string(), Code::integer()}
%% @spec (Args::[string()]) -> string() | integer() | {string(), integer()}
try_run_ctp(Args) ->
try ejabberd_hooks:run_fold(ejabberd_ctl_process, false, [Args]) of
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}
end.
%% @spec (Args::[string()]) ->
%% String::string() | Code::integer() | {String::string(), Code::integer()}
%% @spec (Args::[string()]) -> string() | integer() | {string(), integer()}
try_call_command(Args) ->
try call_command(Args) of
{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}
end.
%% @spec (Args::[string()]) ->
%% String::string() | Code::integer() | {String::string(), Code::integer()} | {error, ErrorType}
%% @spec (Args::[string()]) -> string() | integer() | {string(), integer()} | {error, ErrorType}
call_command([CmdString | Args]) ->
{ok, CmdStringU, _} = regexp:gsub(CmdString, "-", "_"),
Command = list_to_atom(CmdStringU),

View File

@ -16,7 +16,7 @@
%%% 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
@ -38,6 +38,9 @@
-include("ejabberd.hrl").
%% We do not block on send anymore.
-define(TCP_SEND_TIMEOUT, 15000).
start_link() ->
supervisor:start_link({local, ejabberd_listeners}, ?MODULE, []).
@ -96,10 +99,11 @@ init(Port, Module, Opts) ->
end, Opts),
Res = gen_tcp:listen(Port, [binary,
{packet, 0},
{packet, 0},
{active, false},
{reuseaddr, true},
{nodelay, true},
{send_timeout, ?TCP_SEND_TIMEOUT},
{keepalive, true} |
SockOpts]),
case Res of

View File

@ -16,7 +16,7 @@
%%% 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
@ -96,6 +96,9 @@
%% -define(FSMLIMITS, [{max_queue, 2000}]).
-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.
%% Specified in miliseconds. Default value is 5 minutes.
-define(MAX_RETRY_DELAY, 300000).
@ -259,6 +262,7 @@ open_socket2(Type, Addr, Port) ->
Timeout = outgoing_s2s_timeout(),
case (catch ejabberd_socket:connect(Addr, Port,
[binary, {packet, 0},
{send_timeout, ?TCP_SEND_TIMEOUT},
{active, false}, Type],
Timeout)) of
{ok, _Socket} = R -> R;

View File

@ -319,8 +319,10 @@ adhoc_local_items(Acc, From, To, Lang) ->
{result, Its} -> Its;
empty -> []
end,
PermLev = get_permission_level(From),
%% 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(
fun(N) ->
Nd = exmpp_xml:get_attribute(N, 'node', ""),
@ -337,15 +339,15 @@ adhoc_local_items(Acc, From, To, Lang) ->
Acc
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),
Items = case get_local_items(LServer, LNode, Server, Lang) of
Items = case get_local_items({PermLev, LServer}, LNode, Server, Lang) of
{result, Res} ->
Res;
{error, _Error} ->
@ -360,11 +362,17 @@ recursively_get_local_items(LServer, Node, Server, Lang) ->
[];
true ->
[N, recursively_get_local_items(
LServer, Nd, Server, Lang)]
PermLev, LServer, Nd, Server, Lang)]
end
end, Items)),
Nodes.
get_permission_level(JID) ->
case acl:match_rule(global, configure, JID) of
allow -> global;
deny -> vhost
end.
%%%-----------------------------------------------------------------------
-define(ITEMS_RESULT(Allow, LNode, Fallback),
@ -372,7 +380,8 @@ recursively_get_local_items(LServer, Node, Server, Lang) ->
deny ->
Fallback;
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
{result, Res} ->
{result, Res};
@ -396,7 +405,8 @@ get_local_items(Acc, From, To, <<>>, Lang) ->
deny ->
{result, Items};
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
{result, 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) ->
{result,
[?NODE("Configuration", <<"config">>),
@ -498,13 +511,13 @@ get_local_items(_Host, ["user"], Server, Lang) ->
get_local_items(_Host, ["http:" | _], _Server, _Lang) ->
{result, []};
get_local_items(Host, ["online users"], _Server, _Lang) ->
get_local_items({_, Host}, ["online users"], _Server, _Lang) ->
{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)};
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
{'EXIT', _Reason} ->
{error, 'internal-server-error'};
@ -528,10 +541,10 @@ get_local_items(Host, ["all users", [$@ | Diap]], _Server, _Lang) ->
end
end;
get_local_items(Host, ["outgoing s2s"], _Server, Lang) ->
get_local_items({_, Host}, ["outgoing s2s"], _Server, 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)};
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) ->
{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),
{result,
[?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">>)
]};
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) ->
{result, []};
@ -721,8 +739,8 @@ get_stopped_nodes(_Lang) ->
%%-------------------------------------------------------------------------
-define(COMMANDS_RESULT(Allow, From, To, Request),
case Allow of
-define(COMMANDS_RESULT(LServerOrGlobal, From, To, Request),
case acl:match_rule(LServerOrGlobal, configure, From) of
deny ->
{error, 'forbidden'};
allow ->
@ -732,24 +750,23 @@ get_stopped_nodes(_Lang) ->
adhoc_local_commands(Acc, From, To, #adhoc_request{node = Node} = Request) ->
LServer = exmpp_jid:ldomain_as_list(To),
LNode = tokenize(Node),
Allow = acl:match_rule(LServer, configure, From),
case LNode of
["running nodes", _ENode, "DB"] ->
?COMMANDS_RESULT(Allow, From, To, Request);
?COMMANDS_RESULT(global, From, To, Request);
["running nodes", _ENode, "modules", _] ->
?COMMANDS_RESULT(Allow, From, To, Request);
?COMMANDS_RESULT(LServer, From, To, Request);
["running nodes", _ENode, "backup", _] ->
?COMMANDS_RESULT(Allow, From, To, Request);
?COMMANDS_RESULT(global, From, To, Request);
["running nodes", _ENode, "import", _] ->
?COMMANDS_RESULT(Allow, From, To, Request);
?COMMANDS_RESULT(global, From, To, Request);
["running nodes", _ENode, "restart"] ->
?COMMANDS_RESULT(Allow, From, To, Request);
?COMMANDS_RESULT(global, From, To, Request);
["running nodes", _ENode, "shutdown"] ->
?COMMANDS_RESULT(Allow, From, To, Request);
?COMMANDS_RESULT(global, From, To, Request);
["config", _] ->
?COMMANDS_RESULT(Allow, From, To, Request);
?COMMANDS_RESULT(LServer, From, To, Request);
?NS_ADMINL(_) ->
?COMMANDS_RESULT(Allow, From, To, Request);
?COMMANDS_RESULT(LServer, From, To, Request);
_ ->
Acc
end.
@ -1545,7 +1562,7 @@ set_form(_From, Host, ["config", "access"], _Lang, XData) ->
{error, 'bad-request'}
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),
Password = get_value("password", 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),
Server = exmpp_jid:ldomain_as_list(AccountJID),
true = lists:member(Server, ?MYHOSTS),
true = (Server == Host) orelse (get_permission_level(From) == global),
ejabberd_auth:try_register(User, Server, Password),
{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,
ASL2 = lists:map(
fun(AccountString) ->
JID = exmpp_jid:list_to_jid(AccountString),
JID = exmpp_jid:parse_jid(AccountString),
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),
{User, Server}
end,
@ -1571,11 +1590,12 @@ set_form(_From, _Host, ?NS_ADMINL("delete-user"), _Lang, XData) ->
[ejabberd_auth:remove_user(User, Server) || {User, Server} <- ASL2],
{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),
JID = exmpp_jid:list_to_jid(AccountString),
LUser = [_|_] = exmpp_jid:lnode_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
case exmpp_jid:lresource_as_list(JID) of
undefined ->
@ -1589,11 +1609,12 @@ set_form(_From, _Host, ?NS_ADMINL("end-user-session"), _Lang, XData) ->
end,
{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),
JID = exmpp_jid:list_to_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_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),
true = is_list(Password),
{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))
]}]};
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),
Password = get_value("password", XData),
JID = exmpp_jid:list_to_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_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),
ejabberd_auth:set_password(User, Server, Password),
{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),
JID = exmpp_jid:list_to_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_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
%% 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))
]}]};
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),
JID = exmpp_jid:list_to_jid(AccountString),
User = [_|_] = exmpp_jid:lnode_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),
exmpp_jid:ldomain(JID)),

View File

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

View File

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

View File

@ -33,7 +33,7 @@
%%% This module uses version 1.12 of the specification as a base.
%%% Most of the specification is implemented.
%%% 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
%%% 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_items(Host, Node, LJID, last).
%% @spec (Host, Node, LJID) -> any()
%% @spec (Host, Node, LJID, Number) -> any()
%% Host = host()
%% Node = pubsubNode()
%% LJID = {U, S, []}
%% Number = last | integer()
%% @doc <p>Resend the items of a node to the user.</p>
%% @todo use cache-last-item feature
send_items(Host, Node, {LU, LS, LR} = LJID, Number) ->
@ -2157,10 +2158,9 @@ is_to_deliver({User, Server, _}, _, true) ->
end, false, Ss)
end.
%% @spec (Elem, Payload) -> int()
%% Elem = atom()
%% @spec (Payload) -> int()
%% 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([], Count) -> Count;
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()
%% Els = [xmlelement()]
%% @doc <p>Build pubsub event stanza
%% @doc <p>Build pubsub event stanza</p>
event_stanza(Els) ->
#xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children =
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'event', children = Els}]}.

View File

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

View File

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

View File

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

View File

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

View File

@ -883,10 +883,9 @@ user_roster(User, Server, Query, Lang) ->
[?C(Group), ?BR]
end, R#roster.groups),
Pending = ask_to_pending(R#roster.ask),
{U, S, R} = R#roster.jid,
TDJID = build_contact_jid_td(R#roster.jid),
?XE("tr",
[?XAC("td", [{"class", "valign"}],
catch exmpp_jid:jid_to_list(U, S, R)),
[TDJID,
?XAC("td", [{"class", "valign"}],
binary_to_list(R#roster.name)),
?XAC("td", [{"class", "valign"}],
@ -934,6 +933,26 @@ user_roster(User, Server, Query, Lang) ->
])]
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) ->
case lists:keysearch("addjid", 1, Query) of
{value, _} ->

View File

@ -922,10 +922,9 @@ user_roster(User, Server, Query, Lang) ->
[?C(Group), ?BR]
end, R#roster.groups),
Pending = ask_to_pending(R#roster.ask),
{U, S, R} = R#roster.jid,
TDJID = build_contact_jid_td(R#roster.jid),
?XE("tr",
[?XAC("td", [{"class", "valign"}],
catch exmpp_jid:jid_to_list(U, S, R)),
[TDJID,
?XAC("td", [{"class", "valign"}],
binary_to_list(R#roster.name)),
?XAC("td", [{"class", "valign"}],
@ -973,6 +972,26 @@ user_roster(User, Server, Query, Lang) ->
])]
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) ->
case lists:keysearch("addjid", 1, Query) of
{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
ok -> [?CT("Submitted"), ?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)] ++
case Res of
ok -> [?CT("Submitted"), ?P];

View File

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

View File

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

View File

@ -59,6 +59,7 @@
-define(GET_DECRYPTED_INPUT, 6).
-define(GET_PEER_CERTIFICATE, 7).
-define(GET_VERIFY_RESULT, 8).
-define(VERIFY_NONE, 16#10000).
-record(tlssock, {tcpsock, tlsport}).
@ -120,13 +121,20 @@ tcp_to_tls(TCPSocket, Options) ->
{error, already_loaded} -> ok
end,
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
true ->
?SET_CERTIFICATE_FILE_CONNECT;
false ->
?SET_CERTIFICATE_FILE_ACCEPT
end,
case port_control(Port, Command, CertFile ++ [0]) of
case port_control(Port, Command bor Flags, CertFile ++ [0]) of
<<0>> ->
{ok, #tlssock{tcpsock = TCPSocket, tlsport = Port}};
<<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_PEER_CERTIFICATE 7
#define GET_VERIFY_RESULT 8
#define VERIFY_NONE 0x10000
#define die_unless(cond, errstr) \
@ -312,6 +313,9 @@ static int tls_drv_control(ErlDrvData handle,
int size;
ErlDrvBinary *b;
X509 *cert;
unsigned int flags = command;
command &= 0xffff;
ERR_clear_error();
switch (command)
@ -354,6 +358,9 @@ static int tls_drv_control(ErlDrvData handle,
d->ssl = SSL_new(ssl_ctx);
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_write = BIO_new(BIO_s_mem());

View File

@ -40,6 +40,30 @@
-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) ->
Host = exmpp_stringprep:nameprep(SHost),
case lists:member(Host, ?MYHOSTS) of
@ -108,7 +132,7 @@ get_auth(Auth) ->
make_xhtml(Els, Host, Lang) ->
make_xhtml(Els, Host, cluster, Lang).
%% @spec (Els, Host, Node, Lang)
%% @spec (Els, Host, Node, Lang) -> {200, [html], xmlelement()}
%% where Host = global | string()
%% Node = cluster | atom()
make_xhtml(Els, Host, Node, Lang) ->
@ -513,8 +537,13 @@ h3 {
padding-top: 5px;
}
*.alignright {
div.guidelink {
text-align: right;
padding-right: 1em;
}
*.alignright {
font-size: 10pt;
}
".
@ -560,8 +589,8 @@ process_admin(global,
lang = Lang}) ->
Base = get_base_path(global, cluster),
MenuItems2 = make_menu_items(global, cluster, Base, Lang),
make_xhtml([?XCT('h1', "Administration"),
?XE('ul',
make_xhtml(?H1GL(?T("Administration"), "toc", "Contents") ++
[?XE('ul',
[?LI([?ACT("/admin/acls/", "Access Control Lists"), ?C(" "),
?ACT("/admin/acls-raw/", "(Raw)")]),
?LI([?ACT("/admin/access/", "Access Rules"), ?C(" "),
@ -635,7 +664,7 @@ process_admin(Host,
"~p.", [lists:keysort(
2, ets:select(acl, [{{acl, {'$1', Host}, '$2'},
[], [{{acl, '$1', '$2'}}]}]))])),
make_xhtml([?XCT('h1', "Access Control Lists")] ++
make_xhtml(?H1GL(?T("Access Control Lists"), "ACLDefinition", "ACL Definition") ++
case Res of
ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P];
@ -678,7 +707,7 @@ process_admin(Host,
ACLs = lists:keysort(
2, ets:select(acl, [{{acl, {'$1', Host}, '$2'},
[], [{{acl, '$1', '$2'}}]}])),
make_xhtml([?XCT('h1', "Access Control Lists")] ++
make_xhtml(?H1GL(?T("Access Control Lists"), "ACLDefinition", "ACL Definition") ++
case Res of
ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P];
@ -746,7 +775,7 @@ process_admin(Host,
[{{config, {access, '$1', Host}, '$2'},
[],
[{{access, '$1', '$2'}}]}])])),
make_xhtml([?XCT('h1', "Access Rules")] ++
make_xhtml(?H1GL(?T("Access Rules"), "AccessRights", "Access Rights") ++
case Res of
ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P];
@ -784,7 +813,7 @@ process_admin(Host,
[{{config, {access, '$1', Host}, '$2'},
[],
[{{access, '$1', '$2'}}]}]),
make_xhtml([?XCT('h1', "Access Rules")] ++
make_xhtml(?H1GL(?T("Access Rules"), "AccessRights", "Access Rights") ++
case Res of
ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P];
@ -841,7 +870,7 @@ process_admin(global,
#request{path = ["vhosts"],
lang = 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,
#request{path = ["users"],
@ -1791,7 +1820,8 @@ get_node(global, Node, ["ports"], Query, Lang) ->
end,
NewPorts = lists:sort(
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
ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P];
@ -1814,7 +1844,8 @@ get_node(Host, Node, ["modules"], Query, Lang) when is_list(Host) ->
end,
NewModules = lists:sort(
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
ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P];

View File

@ -52,3 +52,17 @@
#xmlattr{name = 'size', value = Size}])).
-define(INPUTST(Type, Name, Value, Size), ?INPUT(Type, Name, ?T(Value), Size)).
-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)]).