Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c942e31e0 | |||
| 9912e1b548 | |||
| 09a5fafc8a | |||
| 64036bc121 | |||
| 33973677f2 | |||
| c4c0b45ced | |||
| 4e9c81b66a | |||
| 7a53b66e46 | |||
| d5ebef1362 | |||
| 26b814e367 | |||
| f675ae1e8c | |||
| b03828d2f7 | |||
| df2e050780 | |||
| 089331caf0 | |||
| db834ca421 | |||
| 5594e1470f | |||
| f7076f49b6 | |||
| 5c40d38b69 | |||
| e2763b7d11 | |||
| 80188d3a52 | |||
| 6575f899b6 | |||
| 3cd9cd0e36 | |||
| 576dda5c87 | |||
| 35a71fc493 | |||
| 1a3abf15c0 | |||
| c7c59766b2 | |||
| e681f4d4cf | |||
| b2a6eccded |
+13
-22
@@ -112,11 +112,11 @@
|
||||
\newcommand{\iqdiscitem}[1]{\titem{\{iqdisc, Discipline\}} \ind{options!iqdisc}This specifies
|
||||
the processing discipline for #1 IQ queries (see section~\ref{modiqdiscoption}).}
|
||||
\newcommand{\hostitem}[1]{
|
||||
\titem{\{host, HostName\} or \{prefix, PrefixName\}} \ind{options!host}
|
||||
Those options define the Jabber ID of the service.
|
||||
If no option is specified, the Jabber ID of the service will be the
|
||||
\titem{\{host, HostName\}} \ind{options!host}
|
||||
This option defines the Jabber ID of the service.
|
||||
If the option is not specified, the Jabber ID of the service will be the
|
||||
hostname of the virtual host preceded with `\jid{#1.}'.
|
||||
For more details see \ref{modhostoption} and \ref{modprefixoption}.
|
||||
For more details see \ref{modhostoption}.
|
||||
}
|
||||
\newcommand{\backend}[1]{\titem{\{backend, mnesia|odbc\}} \ind{options!backend}
|
||||
Specify the backend used to store the tables: #1.
|
||||
@@ -2628,7 +2628,7 @@ Examples:
|
||||
]}.
|
||||
{static_modules,
|
||||
[
|
||||
{mod_echo, [{prefix, "echostatic"}]}
|
||||
{mod_echo, [{host, "echostatic.@HOST@"}]}
|
||||
{mod_time, []},
|
||||
{mod_version, []}
|
||||
]}.
|
||||
@@ -2768,15 +2768,14 @@ Example:
|
||||
\makesubsubsection{modhostoption}{\option{host}}
|
||||
\ind{options!host}
|
||||
|
||||
This option defines the Jabber ID of a service provided by a dynamic \ejabberd{} module.
|
||||
This option defines the Jabber ID of a service provided by an \ejabberd{} module.
|
||||
|
||||
The syntax is:
|
||||
\esyntax{\{host, HostName\}}
|
||||
|
||||
If you include the keyword "@HOST@" in the HostName,
|
||||
it is replaced at start time with the real virtual host string.
|
||||
|
||||
If the module is started statically, use the option \term{prefix} instead (see~\ref{modprefixoption}).
|
||||
If you configure the module to be started statically, then the keyword @HOST@ is mandatory.
|
||||
|
||||
This example configures
|
||||
the \ind{modules!\modecho{}}echo module to provide its echoing service
|
||||
@@ -2801,16 +2800,6 @@ the "@HOST@" keyword must be used:
|
||||
]}.
|
||||
\end{verbatim}
|
||||
|
||||
\makesubsubsection{modprefixoption}{\option{prefix}}
|
||||
\ind{options!prefix}
|
||||
|
||||
This option defines the prefix that will be used to build the Jabber ID of a service provided by a static \ejabberd{} module.
|
||||
|
||||
The syntax is:
|
||||
\esyntax{\{prefix, PrefixName\}}
|
||||
|
||||
If the module is started dynamically, use the option \term{host} instead (see~\ref{modhostoption}).
|
||||
|
||||
This example configures
|
||||
the \ind{modules!\modecho{}}echo module to provide its echoing service
|
||||
in Jabber IDs like
|
||||
@@ -2820,7 +2809,7 @@ in Jabber IDs like
|
||||
{static_modules,
|
||||
[
|
||||
...
|
||||
{mod_echo, [{prefix, "mirror"}]},
|
||||
{mod_echo, [{host, "mirror.@HOST@"}]},
|
||||
...
|
||||
]}.
|
||||
\end{verbatim}
|
||||
@@ -4212,8 +4201,9 @@ has a unique identification and the following parameters:
|
||||
which is only recommended for a small server with just a few hundred users.
|
||||
The special member directive \term{@online@}
|
||||
represents the online users in the virtual host.
|
||||
\item[Displayed groups] A list of groups that will be in the rosters of this
|
||||
group's members.
|
||||
\item[Displayed groups]
|
||||
A list of groups that will be in the rosters of this group's members.
|
||||
A group of other vhost can be identified with \term{groupid@vhost}
|
||||
\end{description}
|
||||
|
||||
Examples:
|
||||
@@ -5779,7 +5769,8 @@ domain.
|
||||
\makesection{servicelb}{Service Load-Balancing}
|
||||
\ind{component load-balancing}
|
||||
|
||||
\makesubsection{componentlb}{Components Load-Balancing}
|
||||
% This section never had content, should it?
|
||||
% \makesubsection{componentlb}{Components Load-Balancing}
|
||||
|
||||
\makesubsection{domainlb}{Domain Load-Balancing Algorithm}
|
||||
\ind{options!domain\_balancing}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{application, ejabberd,
|
||||
[{description, "ejabberd"},
|
||||
{vsn, "3.0.0-alpha-4"},
|
||||
{vsn, "3.0.0-alpha-5"},
|
||||
{modules, [acl,
|
||||
adhoc,
|
||||
configure,
|
||||
|
||||
@@ -312,14 +312,15 @@ update_list() ->
|
||||
[atom_to_list(Beam) || Beam <- UpdatedBeams].
|
||||
|
||||
update("all") ->
|
||||
[update_module(ModStr) || ModStr <- update_list()];
|
||||
[update_module(ModStr) || ModStr <- update_list()],
|
||||
{ok, []};
|
||||
update(ModStr) ->
|
||||
update_module(ModStr).
|
||||
|
||||
update_module(ModuleNameString) ->
|
||||
ModuleName = list_to_atom(ModuleNameString),
|
||||
case ejabberd_update:update([ModuleName]) of
|
||||
{ok, Res} -> {ok, io_lib:format("Updated: ~p", [Res])};
|
||||
{ok, _Res} -> {ok, []};
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
|
||||
+16
-16
@@ -49,16 +49,16 @@
|
||||
is_user_exists_in_other_modules/3,
|
||||
remove_user/2,
|
||||
remove_user/3,
|
||||
remove_host/1,
|
||||
plain_password_required/1,
|
||||
store_type/1,
|
||||
entropy/1
|
||||
]).
|
||||
|
||||
-export([start/1
|
||||
,stop/1
|
||||
,start_modules/2
|
||||
,stop_modules/2
|
||||
,start_methods/2
|
||||
,stop_methods/2
|
||||
]).
|
||||
|
||||
-export([auth_modules/1]).
|
||||
@@ -80,8 +80,20 @@ start() ->
|
||||
lists:foreach(fun start/1, ?MYHOSTS).
|
||||
|
||||
start(Host) ->
|
||||
ejabberd_hooks:add(remove_host, list_to_binary(Host), ?MODULE, remove_host, 150),
|
||||
start_modules(Host, auth_modules(Host)).
|
||||
|
||||
stop(Host) ->
|
||||
ejabberd_hooks:delete(remove_host, list_to_binary(Host), ?MODULE, remove_host, 150),
|
||||
stop_modules(Host, auth_modules(Host)).
|
||||
|
||||
remove_host(HostB) when is_binary(HostB) ->
|
||||
lists:foreach(
|
||||
fun({Username, Host}) ->
|
||||
ejabberd_auth:remove_user(Username, Host)
|
||||
end,
|
||||
ejabberd_auth:get_vh_registered_users(binary_to_list(HostB))).
|
||||
|
||||
start_modules(Host, Modules) when is_list(Modules) ->
|
||||
lists:foreach(fun (M) -> start_modules(Host, M) end, Modules);
|
||||
start_modules(Host, Module) when is_atom(Module) ->
|
||||
@@ -92,17 +104,6 @@ stop_modules(Host, Modules) when is_list(Modules) ->
|
||||
stop_modules(Host, Module) when is_atom(Module) ->
|
||||
Module:stop(Host).
|
||||
|
||||
start_methods(Host, Methods) when is_list(Methods) ->
|
||||
lists:foreach(fun (M) -> start_methods(Host, M) end, Methods);
|
||||
start_methods(Host, Method) when is_atom(Method) ->
|
||||
start_modules(Host, module_name(Method)).
|
||||
|
||||
stop_methods(Host, Methods) when is_list(Methods) ->
|
||||
lists:foreach(fun (M) -> stop_methods(Host, M) end, Methods);
|
||||
stop_methods(Host, Method) when is_atom(Method) ->
|
||||
stop_modules(Host, module_name(Method)).
|
||||
|
||||
|
||||
%% @spec (Server) -> bool()
|
||||
%% Server = string()
|
||||
|
||||
@@ -517,9 +518,8 @@ auth_modules() ->
|
||||
%% Server = string()
|
||||
%% @doc Return the list of authenticated modules for a given host.
|
||||
|
||||
auth_modules(Server) when is_list(Server) ->
|
||||
LServer = exmpp_stringprep:nameprep(Server),
|
||||
Method = ejabberd_config:get_local_option({auth_method, ejabberd:normalize_host(LServer)}),
|
||||
auth_modules(Server) ->
|
||||
Method = ejabberd_config:get_local_option({auth_method, Server}),
|
||||
Methods = if
|
||||
Method == undefined -> [];
|
||||
is_list(Method) -> Method;
|
||||
|
||||
@@ -127,7 +127,6 @@ start(Host) ->
|
||||
[{ram_copies, [node()]},
|
||||
{attributes, record_info(fields, reg_users_counter)}]),
|
||||
update_reg_users_counter_table(Host),
|
||||
maybe_alert_password_scrammed_without_option(HostB),
|
||||
ok.
|
||||
|
||||
stop(_Host) ->
|
||||
@@ -146,13 +145,13 @@ update_reg_users_counter_table(Server) ->
|
||||
%% @spec () -> bool()
|
||||
|
||||
plain_password_required() ->
|
||||
case is_scrammed(?MYNAME) of
|
||||
case is_option_scram(?MYNAME) of
|
||||
false -> false;
|
||||
true -> true
|
||||
end.
|
||||
|
||||
store_type() ->
|
||||
case is_scrammed(?MYNAME) of
|
||||
case is_option_scram(?MYNAME) of
|
||||
false -> plain; %% allows: PLAIN DIGEST-MD5 SCRAM
|
||||
true -> scram %% allows: PLAIN SCRAM
|
||||
end.
|
||||
@@ -232,7 +231,7 @@ set_password(User, Server, Password) ->
|
||||
US ->
|
||||
%% TODO: why is this a transaction?
|
||||
F = fun() ->
|
||||
Passwd = case is_scrammed(LServer) and (Password /= "") of
|
||||
Passwd = case is_option_scram(LServer) and (Password /= "") of
|
||||
true -> password_to_scram(Password, #passwd{user_host=US});
|
||||
false -> #passwd{user_host = US, password = Password}
|
||||
end,
|
||||
@@ -259,7 +258,7 @@ try_register(User, Server, Password) ->
|
||||
F = fun() ->
|
||||
case gen_storage:read(LServer, {passwd, US}) of
|
||||
[] ->
|
||||
Passwd = case is_scrammed(LServer) and (Password /= "") of
|
||||
Passwd = case is_option_scram(LServer) and (Password /= "") of
|
||||
true -> password_to_scram(Password, #passwd{user_host=US});
|
||||
false -> #passwd{user_host = US, password = Password}
|
||||
end,
|
||||
@@ -536,23 +535,18 @@ remove_user(User, Server, Password) ->
|
||||
|
||||
%% The passwords are stored scrammed in the table either if the option says so,
|
||||
%% or if at least the first password is empty.
|
||||
is_scrammed(Host) ->
|
||||
case action_password_format(Host) of
|
||||
scram -> true;
|
||||
must_scram -> true;
|
||||
plain -> false;
|
||||
forced_scram -> true
|
||||
end.
|
||||
|
||||
action_password_format(HostB) ->
|
||||
OptionScram = is_option_scram(),
|
||||
case {OptionScram, get_format_first_element(HostB)} of
|
||||
action_password_format(Host) ->
|
||||
OptionScram = is_option_scram(Host),
|
||||
case {OptionScram, get_format_first_element(Host)} of
|
||||
{true, scram} -> scram;
|
||||
{true, any} -> scram;
|
||||
{true, plain} -> must_scram;
|
||||
{false, plain} -> plain;
|
||||
{false, any} -> plain;
|
||||
{false, scram} -> forced_scram
|
||||
{false, scram} ->
|
||||
set_option_password_format(scram),
|
||||
forced_scram
|
||||
end.
|
||||
|
||||
get_format_first_element(HostB) ->
|
||||
@@ -562,44 +556,40 @@ get_format_first_element(HostB) ->
|
||||
[#passwd{} | _] -> plain
|
||||
end.
|
||||
|
||||
is_option_scram() ->
|
||||
scram == ejabberd_config:get_local_option({auth_password_format, ?MYNAME}).
|
||||
is_option_scram(Host) when is_list(Host) ->
|
||||
scram == ejabberd_config:get_local_option({auth_password_format, Host}).
|
||||
|
||||
maybe_alert_password_scrammed_without_option(Host) ->
|
||||
case is_scrammed(Host) andalso not is_option_scram() of
|
||||
true ->
|
||||
?ERROR_MSG("Some passwords were stored in the database as SCRAM, "
|
||||
"but 'auth_password_format' is not configured 'scram'. "
|
||||
"The option will now be considered to be 'scram'.", []);
|
||||
false ->
|
||||
ok
|
||||
end.
|
||||
set_option_password_format(Value) ->
|
||||
?ERROR_MSG("Some passwords are stored in the database as SCRAM bits, "
|
||||
"but the option 'auth_password_format' is not configured 'scram'. "
|
||||
"The option will now be considered to be 'scram'.", []),
|
||||
ejabberd_config:add_local_option({auth_password_format, ?MYNAME}, Value).
|
||||
|
||||
maybe_scram_passwords(Host) ->
|
||||
case action_password_format(Host) of
|
||||
must_scram -> scram_passwords(Host);
|
||||
maybe_scram_passwords(HostB) ->
|
||||
case action_password_format(binary_to_list(HostB)) of
|
||||
must_scram -> scram_passwords(HostB);
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
scram_passwords(Host) ->
|
||||
scram_passwords(HostB) ->
|
||||
Backend =
|
||||
case ejabberd_config:get_local_option({auth_storage, Host}) of
|
||||
case ejabberd_config:get_local_option({auth_storage, binary_to_list(HostB)}) of
|
||||
undefined -> mnesia;
|
||||
B -> B
|
||||
end,
|
||||
scram_passwords(Host, Backend).
|
||||
scram_passwords(Host, mnesia) ->
|
||||
?INFO_MSG("Converting the passwords stored in mnesia for host ~p into SCRAM bits", [Host]),
|
||||
scram_passwords(HostB, Backend).
|
||||
scram_passwords(HostB, mnesia) ->
|
||||
?INFO_MSG("Converting the passwords stored in mnesia for host ~p into SCRAM bits", [HostB]),
|
||||
gen_storage_migration:migrate_mnesia(
|
||||
Host, passwd,
|
||||
HostB, passwd,
|
||||
[{passwd, [user_host, password, storedkey, serverkey, salt, iterationcount],
|
||||
fun(#passwd{password = Password} = Passwd) ->
|
||||
password_to_scram(Password, Passwd)
|
||||
end}]);
|
||||
scram_passwords(Host, odbc) ->
|
||||
?INFO_MSG("Converting the passwords stored in odbc for host ~p into SCRAM bits", [Host]),
|
||||
scram_passwords(HostB, odbc) ->
|
||||
?INFO_MSG("Converting the passwords stored in odbc for host ~p into SCRAM bits", [HostB]),
|
||||
gen_storage_migration:migrate_odbc(
|
||||
Host, [passwd],
|
||||
HostB, [passwd],
|
||||
[{"passwd", ["user", "host", "password", "storedkey", "serverkey", "salt", "iterationcount"],
|
||||
fun(_, User, Host2, Password, _Storedkey, _Serverkey, _Iterationcount, _Salt) ->
|
||||
password_to_scram(Password, #passwd{user_host = {User, Host2}})
|
||||
|
||||
@@ -1867,9 +1867,9 @@ presence_update(From, Packet, StateData) ->
|
||||
update_priority(NewPriority, Packet, StateData),
|
||||
FromUnavail = (StateData#state.pres_last == undefined),
|
||||
?DEBUG("from unavail = ~p~n", [FromUnavail]),
|
||||
NewStateData = StateData#state{pres_last = Packet,
|
||||
pres_timestamp = Timestamp},
|
||||
NewState =
|
||||
NewStateData = StateData#state{pres_last = Packet,
|
||||
pres_timestamp = Timestamp},
|
||||
if
|
||||
FromUnavail ->
|
||||
ejabberd_hooks:run(user_available_hook,
|
||||
|
||||
+9
-20
@@ -101,13 +101,18 @@ update_host_conf(Host, Config) when is_list(Host), is_list(Config) ->
|
||||
case registered(Host) of
|
||||
false -> {error, host_process_not_registered};
|
||||
true ->
|
||||
remove(Host),
|
||||
remove_host_info(Host),
|
||||
?MODULE:register(Host, Config)
|
||||
end.
|
||||
|
||||
|
||||
%% Removes a vhost from the system,
|
||||
%% XXX deleting all ODBC data.
|
||||
remove(Host) when is_list(Host) ->
|
||||
HostB = list_to_binary(Host),
|
||||
ejabberd_hooks:run(remove_host, HostB, [HostB]),
|
||||
remove_host_info(Host).
|
||||
|
||||
remove_host_info(Host) ->
|
||||
true = exmpp_stringprep:is_node(Host),
|
||||
ID = get_clusterid(),
|
||||
gen_storage:dirty_delete_where(
|
||||
@@ -346,10 +351,7 @@ start_host(Host) when is_list(Host) ->
|
||||
gen_mod:start_module(Host, Module, Args)
|
||||
end, Modules)
|
||||
end,
|
||||
case auth_method(Host) of
|
||||
{host_method, HostMethod} ->
|
||||
ejabberd_auth:start_methods(Host, HostMethod)
|
||||
end,
|
||||
ejabberd_auth:start(Host),
|
||||
ok.
|
||||
|
||||
|
||||
@@ -366,10 +368,7 @@ stop_host(Host) when is_list(Host) ->
|
||||
lists:foreach(fun(Module) ->
|
||||
gen_mod:stop_module_keep_config(Host, Module)
|
||||
end, gen_mod:loaded_modules(Host)),
|
||||
case auth_method(Host) of
|
||||
{host_method, Method} ->
|
||||
ejabberd_auth:stop_methods(Host, Method)
|
||||
end.
|
||||
ejabberd_auth:stop(Host).
|
||||
|
||||
%% Get the current vhost list from a variety of sources (ODBC, internal)
|
||||
get_hosts(ejabberd) -> ?MYHOSTS;
|
||||
@@ -417,16 +416,6 @@ diff_hosts(NewHosts, OldHosts) ->
|
||||
AddHosts = NewHosts -- OldHosts,
|
||||
{AddHosts,RemoveHosts}.
|
||||
|
||||
%% XXX - this should be part of auth, not hosts.
|
||||
auth_method(Host) ->
|
||||
case ejabberd_config:get_host_option(Host, auth_method) of
|
||||
undefined ->
|
||||
[Default] = ejabberd_config:get_host_option(global, auth_method),
|
||||
{host_method, Default};
|
||||
Other ->
|
||||
{host_method, Other}
|
||||
end.
|
||||
|
||||
configure_static_hosts() ->
|
||||
?DEBUG("Node startup - configuring hosts: ~p", [?MYHOSTS]),
|
||||
%% Add a null configuration for all MYHOSTS - this ensures
|
||||
|
||||
+38
-1
@@ -42,7 +42,11 @@
|
||||
allow_host/2,
|
||||
incoming_s2s_number/0,
|
||||
outgoing_s2s_number/0,
|
||||
migrate/1
|
||||
migrate/1,
|
||||
clean_temporarily_blocked_table/0,
|
||||
list_temporarily_blocked_hosts/0,
|
||||
external_host_overloaded/1,
|
||||
is_temporarly_blocked/1
|
||||
]).
|
||||
|
||||
%% gen_server callbacks
|
||||
@@ -65,9 +69,14 @@
|
||||
-define(PREFIXED_NS,
|
||||
[{?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx}]).
|
||||
|
||||
-define(S2S_OVERLOAD_BLOCK_PERIOD, 60).
|
||||
%% once a server is temporarly blocked, it stay blocked for 60 seconds
|
||||
|
||||
-record(s2s, {fromto, pid, key}).
|
||||
-record(state, {}).
|
||||
|
||||
-record(temporarily_blocked, {host, timestamp}).
|
||||
|
||||
%%====================================================================
|
||||
%% API
|
||||
%%====================================================================
|
||||
@@ -98,6 +107,31 @@ route(From, To, Packet) ->
|
||||
ok
|
||||
end.
|
||||
|
||||
clean_temporarily_blocked_table() ->
|
||||
mnesia:clear_table(temporarily_blocked).
|
||||
list_temporarily_blocked_hosts() ->
|
||||
ets:tab2list(temporarily_blocked).
|
||||
|
||||
external_host_overloaded(Host) ->
|
||||
?INFO_MSG("Disabling connections from ~s for ~s seconds", [Host, ?S2S_OVERLOAD_BLOCK_PERIOD]),
|
||||
mnesia:transaction( fun() ->
|
||||
mnesia:write(#temporarily_blocked{host = Host, timestamp = now()})
|
||||
end).
|
||||
|
||||
is_temporarly_blocked(Host) ->
|
||||
case mnesia:dirty_read(temporarily_blocked, Host) of
|
||||
[] -> false;
|
||||
[#temporarily_blocked{timestamp = T}=Entry] ->
|
||||
case timer:now_diff(now(), T) of
|
||||
N when N > ?S2S_OVERLOAD_BLOCK_PERIOD * 1000 * 1000 ->
|
||||
mnesia:dirty_delete_object(Entry),
|
||||
false;
|
||||
_ ->
|
||||
true
|
||||
end
|
||||
end.
|
||||
|
||||
|
||||
remove_connection(FromTo, Pid, Key) ->
|
||||
case catch mnesia:dirty_match_object(s2s, #s2s{fromto = FromTo,
|
||||
pid = Pid,
|
||||
@@ -248,6 +282,7 @@ init([]) ->
|
||||
mnesia:add_table_copy(s2s, node(), ram_copies),
|
||||
ejabberd_hooks:add(node_hash_update, ?MODULE, migrate, 100),
|
||||
ejabberd_commands:register_commands(commands()),
|
||||
mnesia:create_table(temporarily_blocked, [{ram_copies, [node()]}, {attributes, record_info(fields, temporarily_blocked)}]),
|
||||
{ok, #state{}}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
@@ -576,6 +611,8 @@ update_tables() ->
|
||||
|
||||
%% Check if host is in blacklist or white list
|
||||
allow_host(MyServer, S2SHost) ->
|
||||
allow_host2(MyServer, S2SHost) andalso (not is_temporarly_blocked(S2SHost)).
|
||||
allow_host2(MyServer, S2SHost) ->
|
||||
Hosts = ?MYHOSTS,
|
||||
case lists:dropwhile(
|
||||
fun(ParentDomain) ->
|
||||
|
||||
+37
-5
@@ -27,7 +27,7 @@
|
||||
-module(ejabberd_s2s_in).
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-behaviour(gen_fsm).
|
||||
-behaviour(p1_fsm).
|
||||
|
||||
%% External exports
|
||||
-export([start/2,
|
||||
@@ -44,6 +44,7 @@
|
||||
handle_sync_event/4,
|
||||
code_change/4,
|
||||
handle_info/3,
|
||||
print_state/1,
|
||||
terminate/3]).
|
||||
|
||||
-include_lib("exmpp/include/exmpp.hrl").
|
||||
@@ -80,10 +81,12 @@
|
||||
-define(FSMOPTS, []).
|
||||
-endif.
|
||||
|
||||
-define(FSMLIMITS, [{max_queue, 2000}]). %% if queue grows more than this, we shutdown this connection.
|
||||
|
||||
%% Module start with or without supervisor:
|
||||
-ifdef(NO_TRANSIENT_SUPERVISORS).
|
||||
-define(SUPERVISOR_START, gen_fsm:start(ejabberd_s2s_in, [SockData, Opts],
|
||||
?FSMOPTS)).
|
||||
-define(SUPERVISOR_START, p1_fsm:start(ejabberd_s2s_in, [SockData, Opts],
|
||||
?FSMOPTS ++ ?FSMLIMITS)).
|
||||
-else.
|
||||
-define(SUPERVISOR_START, supervisor:start_child(ejabberd_s2s_in_sup,
|
||||
[SockData, Opts])).
|
||||
@@ -102,7 +105,7 @@ start(SockData, Opts) ->
|
||||
?SUPERVISOR_START.
|
||||
|
||||
start_link(SockData, Opts) ->
|
||||
gen_fsm:start_link(ejabberd_s2s_in, [SockData, Opts], ?FSMOPTS).
|
||||
p1_fsm:start_link(ejabberd_s2s_in, [SockData, Opts], ?FSMOPTS ++ ?FSMLIMITS).
|
||||
|
||||
socket_type() ->
|
||||
xml_stream.
|
||||
@@ -322,14 +325,20 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
||||
_ ->
|
||||
false
|
||||
end,
|
||||
AllowRemoteHost = ejabberd_s2s:allow_host("", AuthDomain),
|
||||
if
|
||||
AuthRes ->
|
||||
AuthRes andalso AllowRemoteHost ->
|
||||
(StateData#state.sockmod):reset_stream(
|
||||
StateData#state.socket),
|
||||
send_element(StateData,
|
||||
exmpp_server_sasl:success()),
|
||||
?DEBUG("(~w) Accepted s2s authentication for ~s",
|
||||
[StateData#state.socket, AuthDomain]),
|
||||
%% acess rules are first checked against the globally defined ones, that have precedence over
|
||||
%% domain-specific ones.. http://www.process-one.net/docs/ejabberd/guide_en.html#AccessRights
|
||||
%% since there is allways a shaper defined globally for s2s, it doesn't matter the actual
|
||||
%% local host, since the globall one will be used, even if this domain has a special rule
|
||||
change_shaper(StateData, "", exmpp_jid:make(AuthDomain)),
|
||||
{next_state, wait_for_stream,
|
||||
StateData#state{streamid = new_id(),
|
||||
authenticated = true,
|
||||
@@ -617,9 +626,32 @@ handle_info(_, StateName, StateData) ->
|
||||
%%----------------------------------------------------------------------
|
||||
terminate(Reason, _StateName, StateData) ->
|
||||
?DEBUG("terminated: ~p", [Reason]),
|
||||
case Reason of
|
||||
{process_limit, _} ->
|
||||
[ejabberd_s2s:external_host_overloaded(Host) || Host <- get_external_hosts(StateData)];
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
(StateData#state.sockmod):close(StateData#state.socket),
|
||||
ok.
|
||||
|
||||
get_external_hosts(StateData) ->
|
||||
case StateData#state.authenticated of
|
||||
true ->
|
||||
[StateData#state.auth_domain];
|
||||
false ->
|
||||
Connections = StateData#state.connections,
|
||||
[D || {{D, _}, established} <- dict:to_list(Connections)]
|
||||
end.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: print_state/1
|
||||
%% Purpose: Prepare the state to be printed on error log
|
||||
%% Returns: State to print
|
||||
%%----------------------------------------------------------------------
|
||||
print_state(State) ->
|
||||
State.
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Internal functions
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
+22
-6
@@ -41,10 +41,10 @@ update() ->
|
||||
case update_info() of
|
||||
{ok, Dir, _UpdatedBeams, _Script, LowLevelScript, _Check} ->
|
||||
Eval =
|
||||
release_handler_1:eval_script(
|
||||
eval_script(
|
||||
LowLevelScript, [],
|
||||
[{ejabberd, "", filename:join(Dir, "..")}]),
|
||||
?INFO_MSG("eval: ~p~n", [Eval]),
|
||||
?DEBUG("eval: ~p~n", [Eval]),
|
||||
Eval;
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
@@ -58,15 +58,25 @@ update(ModulesToUpdate) ->
|
||||
[A || A <- UpdatedBeamsAll, B <- ModulesToUpdate, A == B],
|
||||
{_, LowLevelScript, _} = build_script(Dir, UpdatedBeamsNow),
|
||||
Eval =
|
||||
release_handler_1:eval_script(
|
||||
eval_script(
|
||||
LowLevelScript, [],
|
||||
[{ejabberd, "", filename:join(Dir, "..")}]),
|
||||
?INFO_MSG("eval: ~p~n", [Eval]),
|
||||
?DEBUG("eval: ~p~n", [Eval]),
|
||||
Eval;
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
%% OTP R14B03 and older provided release_handler_1:eval_script/3
|
||||
%% But OTP R14B04 and newer provide release_handler_1:eval_script/5
|
||||
eval_script(Script, Apps, LibDirs) ->
|
||||
case lists:member({eval_script, 5}, release_handler_1:module_info(exports)) of
|
||||
true ->
|
||||
release_handler_1:eval_script(Script, Apps, LibDirs, [], []);
|
||||
false ->
|
||||
release_handler_1:eval_script(Script, Apps, LibDirs)
|
||||
end.
|
||||
|
||||
%% Get information about the modified modules
|
||||
update_info() ->
|
||||
Dir = filename:dirname(code:which(ejabberd)),
|
||||
@@ -118,8 +128,10 @@ get_new_version(Module) ->
|
||||
|
||||
get_current_version(Module) ->
|
||||
Attrs = Module:module_info(attributes),
|
||||
{value, {vsn, CurVsn}} = lists:keysearch(vsn, 1, Attrs),
|
||||
CurVsn.
|
||||
case lists:keysearch(vsn, 1, Attrs) of
|
||||
{value, {vsn, CurVsn}} -> CurVsn;
|
||||
_ -> unknown_version
|
||||
end.
|
||||
|
||||
%% @spec(Dir::string(), UpdatedBeams::[atom()]) -> {Script,LowLevelScript,Check}
|
||||
build_script(Dir, UpdatedBeams) ->
|
||||
@@ -134,6 +146,10 @@ build_script(Dir, UpdatedBeams) ->
|
||||
?DEBUG("script: ~p~n", [Script]),
|
||||
?DEBUG("low level script: ~p~n", [LowLevelScript]),
|
||||
?DEBUG("check: ~p~n", [Check]);
|
||||
{ok, []} ->
|
||||
?DEBUG("script: ~p~n", [Script]),
|
||||
?DEBUG("low level script: ~p~n", [LowLevelScript]),
|
||||
?DEBUG("check: ~p~n", [Check]);
|
||||
_ ->
|
||||
?ERROR_MSG("script: ~p~n", [Script]),
|
||||
?ERROR_MSG("low level script: ~p~n", [LowLevelScript]),
|
||||
|
||||
@@ -4,7 +4,7 @@ CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
|
||||
ASN_FLAGS = -bber_bin +optimize +driver
|
||||
ASN_FLAGS = -bber_bin +optimize
|
||||
|
||||
ERLANG_CFLAGS = @ERLANG_CFLAGS@
|
||||
ERLANG_LIBS = @ERLANG_LIBS@
|
||||
|
||||
@@ -6,7 +6,7 @@ EFLAGS = -I .. -pz ..
|
||||
OUTDIR = ..
|
||||
BEAMS = ..\eldap.beam ..\eldap_filter.beam ..\eldap_pool.beam ..\eldap_utils.beam ..\eldap_filter_yecc.beam
|
||||
|
||||
ASN_FLAGS = -bber_bin +optimize +driver
|
||||
ASN_FLAGS = -bber_bin +optimize
|
||||
|
||||
ALL : $(BEAMS)
|
||||
|
||||
|
||||
+1
-1
@@ -438,7 +438,7 @@ init([]) ->
|
||||
end;
|
||||
init({Hosts, Port, Rootdn, Passwd, Opts}) ->
|
||||
catch ssl:start(),
|
||||
ssl:seed(randoms:get_string()),
|
||||
catch ssl:seed(randoms:get_string()),
|
||||
Encrypt = case proplists:get_value(encrypt, Opts) of
|
||||
tls -> tls;
|
||||
_ -> none
|
||||
|
||||
+8
-12
@@ -41,7 +41,6 @@
|
||||
get_hosts/2,
|
||||
get_module_proc/2,
|
||||
get_module_proc_existing/2,
|
||||
expand_host_name/3,
|
||||
is_loaded/2]).
|
||||
|
||||
-export([behaviour_info/1]).
|
||||
@@ -211,8 +210,14 @@ get_module_opt_host(Host, Module, Default) ->
|
||||
re:replace(Val, "@HOST@", Host, [global,{return,list}]).
|
||||
|
||||
get_opt_host(Host, Opts, Default) ->
|
||||
Val = get_opt(host, Opts, Default),
|
||||
re:replace(Val, "@HOST@", Host, [global,{return,list}]).
|
||||
case Host of
|
||||
global ->
|
||||
Val = get_opt(host, Opts, Default),
|
||||
{global, re:replace(Val, ".@HOST@", "", [global,{return,list}])};
|
||||
Host ->
|
||||
Val = get_opt(host, Opts, Default),
|
||||
re:replace(Val, "@HOST@", Host, [global,{return,list}])
|
||||
end.
|
||||
|
||||
loaded_modules(Host) ->
|
||||
ets:select(ejabberd_modules,
|
||||
@@ -290,12 +295,3 @@ get_module_proc(Host, Base) ->
|
||||
is_loaded(Host, Module) ->
|
||||
ets:member(ejabberd_modules, {Module, Host})
|
||||
orelse ets:member(ejabberd_modules, {Module, global}).
|
||||
|
||||
expand_host_name(Host, Opts, DefaultPrefix) ->
|
||||
case Host of
|
||||
global ->
|
||||
{global, gen_mod:get_opt(prefix, Opts, DefaultPrefix)};
|
||||
_ ->
|
||||
gen_mod:get_opt_host(Host, Opts, DefaultPrefix ++ ".@HOST@")
|
||||
end.
|
||||
|
||||
|
||||
+19
-12
@@ -67,9 +67,9 @@ process_iq_get(_, From, _To, #iq{ns = ?NS_BLOCKING, payload = SubEl}, _) ->
|
||||
true ->
|
||||
LUser = exmpp_jid:prep_node(From),
|
||||
LServer = exmpp_jid:prep_domain(From),
|
||||
process_blocklist_get(LUser, LServer);
|
||||
{stop, process_blocklist_get(LUser, LServer)};
|
||||
false ->
|
||||
{error, 'bad-request'}
|
||||
{stop, {error, 'bad-request'}}
|
||||
end;
|
||||
|
||||
process_iq_get(Acc, _, _, _, _) ->
|
||||
@@ -80,7 +80,7 @@ process_iq_set(_, From, _To, #iq{ns = ?NS_BLOCKING,
|
||||
children = SubEls}}) ->
|
||||
LUser = exmpp_jid:prep_node(From),
|
||||
LServer = exmpp_jid:prep_domain(From),
|
||||
case {SubElName, exmpp_xml:remove_cdata_from_list(SubEls)} of
|
||||
Res = case {SubElName, exmpp_xml:remove_cdata_from_list(SubEls)} of
|
||||
{block, []} ->
|
||||
{error, 'bad-request'};
|
||||
{block, Els} ->
|
||||
@@ -93,7 +93,8 @@ process_iq_set(_, From, _To, #iq{ns = ?NS_BLOCKING,
|
||||
process_blocklist_unblock(LUser, LServer, JIDs);
|
||||
_ ->
|
||||
{error, 'bad-request'}
|
||||
end;
|
||||
end,
|
||||
{stop, Res};
|
||||
|
||||
process_iq_set(Acc, _, _, _) ->
|
||||
Acc.
|
||||
@@ -199,9 +200,10 @@ process_blocklist_block(LUser, LServer, JIDs) ->
|
||||
%% [{'=', user_host, {LUser, LServer}},
|
||||
%% {'=', name, Default}]),
|
||||
List = list_data_to_items(Data),
|
||||
broadcast_list_update(LUser, LServer, Default, List),
|
||||
UserList = make_userlist(Default, List),
|
||||
broadcast_list_update(LUser, LServer, Default, UserList),
|
||||
broadcast_blocklist_event(LUser, LServer, {block, JIDs}),
|
||||
{result, []};
|
||||
{result, [], UserList};
|
||||
Error ->
|
||||
?DEBUG("Error ~n~p", [Error]),
|
||||
{error, 'internal-server-error'}
|
||||
@@ -260,9 +262,10 @@ process_blocklist_unblock_all(LUser, LServer) ->
|
||||
{result, []};
|
||||
{atomic, {ok, Default, Data}} ->
|
||||
List = list_data_to_items(Data),
|
||||
broadcast_list_update(LUser, LServer, Default, List),
|
||||
UserList = make_userlist(Default, List),
|
||||
broadcast_list_update(LUser, LServer, Default, UserList),
|
||||
broadcast_blocklist_event(LUser, LServer, unblock_all),
|
||||
{result, []};
|
||||
{result, [], UserList};
|
||||
_ ->
|
||||
{error, 'internal-server-error'}
|
||||
end.
|
||||
@@ -305,17 +308,21 @@ process_blocklist_unblock(LUser, LServer, JIDs) ->
|
||||
{result, []};
|
||||
{atomic, {ok, Default, Data}} ->
|
||||
List = list_data_to_items(Data),
|
||||
broadcast_list_update(LUser, LServer, Default, List),
|
||||
UserList = make_userlist(Default, List),
|
||||
broadcast_list_update(LUser, LServer, Default, UserList),
|
||||
broadcast_blocklist_event(LUser, LServer, {unblock, JIDs}),
|
||||
{result, []};
|
||||
{result, [], UserList};
|
||||
_ ->
|
||||
{error, 'internal-server-error'}
|
||||
end.
|
||||
|
||||
broadcast_list_update(LUser, LServer, Name, List) ->
|
||||
make_userlist(Name, List) ->
|
||||
NeedDb = is_list_needdb(List),
|
||||
#userlist{name = Name, list = List, needdb = NeedDb}.
|
||||
|
||||
broadcast_list_update(LUser, LServer, Name, UserList) ->
|
||||
JID = exmpp_jid:make(LUser, LServer),
|
||||
ListString = lists:flatten(io_lib:format("~p.", [#userlist{name = Name, list = List, needdb = NeedDb}])),
|
||||
ListString = lists:flatten(io_lib:format("~p.", [UserList])),
|
||||
ejabberd_router:route(
|
||||
JID,
|
||||
JID,
|
||||
|
||||
+1
-1
@@ -227,7 +227,7 @@ c2s_presence_in(C2SState, {From, To, #xmlel{attrs = Attrs, children = Els}}) ->
|
||||
Subscription = ejabberd_c2s:get_subscription(From, C2SState),
|
||||
Insert = ((Type == <<>>) or (Type == <<"available">>))
|
||||
and ((Subscription == both) or (Subscription == to)),
|
||||
Delete = (Type == <<"unavailable">>) or (Type == <<"error">>) or (Type == <<"invisible">>),
|
||||
Delete = (Type == <<"unavailable">>) or (Type == <<"error">>),
|
||||
if Insert or Delete ->
|
||||
LFrom = exmpp_jid:to_lower(From),
|
||||
Rs = case ejabberd_c2s:get_aux_field(caps_resources, C2SState) of
|
||||
|
||||
@@ -73,7 +73,6 @@ start(HostB, Opts) ->
|
||||
catch ets:new(disco_features, [named_table, ordered_set, public]),
|
||||
register_feature(HostB, "iq"),
|
||||
register_feature(HostB, "presence"),
|
||||
register_feature(HostB, "presence-invisible"),
|
||||
|
||||
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
|
||||
ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ stop(Host) ->
|
||||
%% Description: Initiates the server
|
||||
%%--------------------------------------------------------------------
|
||||
init([Host, Opts]) ->
|
||||
MyHost = gen_mod:expand_host_name(Host, Opts, "echo"),
|
||||
MyHost = gen_mod:get_opt_host(Host, Opts, "echo.@HOST@"),
|
||||
ClientVersion = gen_mod:get_opt(client_version, Opts, false),
|
||||
ejabberd_router:register_route(MyHost),
|
||||
{ok, #state{host = MyHost, client_version = ClientVersion}}.
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
%% API:
|
||||
-export([start/2,
|
||||
preinit/2,
|
||||
init/1,
|
||||
stop/1]).
|
||||
-export([update_bl_c2s/0]).
|
||||
@@ -49,14 +50,20 @@
|
||||
-record(bl_c2s, {ip}).
|
||||
|
||||
%% Start once for all vhost
|
||||
start(Host, Opts) ->
|
||||
case whereis(?PROCNAME) of
|
||||
undefined ->
|
||||
?DEBUG("Starting mod_ip_blacklist ~p ~p~n", [Host, Opts]),
|
||||
register(?PROCNAME,
|
||||
spawn(?MODULE, init, [#state{}]));
|
||||
_ ->
|
||||
ok
|
||||
start(_Host, _Opts) ->
|
||||
Pid = spawn(?MODULE, preinit, [self(), #state{}]),
|
||||
receive {ok, Pid, PreinitResult} ->
|
||||
PreinitResult
|
||||
end.
|
||||
|
||||
preinit(Parent, State) ->
|
||||
Pid = self(),
|
||||
try register(?PROCNAME, Pid) of
|
||||
true ->
|
||||
Parent ! {ok, Pid, true},
|
||||
init(State)
|
||||
catch error:_ ->
|
||||
Parent ! {ok, Pid, true}
|
||||
end.
|
||||
|
||||
%% TODO:
|
||||
@@ -85,7 +92,7 @@ loop(_State) ->
|
||||
%% TODO: Support comment lines starting by %
|
||||
update_bl_c2s() ->
|
||||
?INFO_MSG("Updating C2S Blacklist", []),
|
||||
case http:request(?BLC2S) of
|
||||
case httpc:request(?BLC2S) of
|
||||
{ok, {{_Version, 200, _Reason}, _Headers, Body}} ->
|
||||
IPs = string:tokens(Body,"\n"),
|
||||
ets:delete_all_objects(bl_c2s),
|
||||
|
||||
+14
-1
@@ -91,6 +91,7 @@
|
||||
register_room/3,
|
||||
migrate/1,
|
||||
get_vh_rooms/1,
|
||||
remove_host/1,
|
||||
can_use_nick/3]).
|
||||
|
||||
%% gen_server callbacks
|
||||
@@ -298,6 +299,16 @@ migrate(After) ->
|
||||
end
|
||||
end, Rs).
|
||||
|
||||
remove_host(MyHostB) when is_binary(MyHostB) ->
|
||||
Host = gen_mod:get_module_opt_host(binary_to_list(MyHostB), ?MODULE, "conference.@HOST@"),
|
||||
?INFO_MSG("Removing rooms of MUC service ~p", [Host]),
|
||||
lists:foreach(
|
||||
fun(#muc_online_room{name_host = {NameB, HostB}, pid = Pid}) ->
|
||||
gen_fsm:send_all_state_event(Pid, destroy),
|
||||
forget_room(HostB, NameB)
|
||||
end,
|
||||
get_vh_rooms(list_to_binary(Host))).
|
||||
|
||||
%%====================================================================
|
||||
%% gen_server callbacks
|
||||
%%====================================================================
|
||||
@@ -310,7 +321,7 @@ migrate(After) ->
|
||||
%% Description: Initiates the server
|
||||
%%--------------------------------------------------------------------
|
||||
init([Host, Opts]) ->
|
||||
MyHostStr = gen_mod:expand_host_name(Host, Opts, "conference"),
|
||||
MyHostStr = gen_mod:get_opt_host(Host, Opts, "conference.@HOST@"),
|
||||
MyHost = l2b(MyHostStr),
|
||||
Backend = gen_mod:get_opt(backend, Opts, mnesia),
|
||||
gen_storage:create_table(Backend, MyHost, muc_room_opt,
|
||||
@@ -355,6 +366,7 @@ init([Host, Opts]) ->
|
||||
RoomShaper = gen_mod:get_opt(room_shaper, Opts, none),
|
||||
ejabberd_router:register_route(MyHostStr),
|
||||
ejabberd_hooks:add(node_hash_update, ?MODULE, migrate, 100),
|
||||
ejabberd_hooks:add(remove_host, Host, ?MODULE, remove_host, 50),
|
||||
load_permanent_rooms(MyHost, Host,
|
||||
{Access, AccessCreate, AccessAdmin, AccessPersistent},
|
||||
HistorySize,
|
||||
@@ -456,6 +468,7 @@ handle_info(_Info, State) ->
|
||||
%%--------------------------------------------------------------------
|
||||
terminate(_Reason, State) ->
|
||||
ejabberd_hooks:delete(node_hash_update, ?MODULE, migrate, 100),
|
||||
ejabberd_hooks:delete(remove_host, State#state.server_host, ?MODULE, remove_host, 50),
|
||||
ejabberd_router:unregister_route(binary_to_list(State#state.host)),
|
||||
ok.
|
||||
|
||||
|
||||
@@ -3849,8 +3849,7 @@ check_decline_invitation(Packet) ->
|
||||
%% The original stanza must be slightly modified.
|
||||
send_decline_invitation({Packet, XEl, DEl = #xmlel{name='decline'}, ToJID},
|
||||
RoomJID, FromJID) ->
|
||||
FromString = exmpp_jid:to_binary(FromJID),
|
||||
|
||||
FromString = exmpp_jid:bare_to_binary(FromJID),
|
||||
DEl1 = exmpp_xml:remove_attribute(DEl, <<"to">>),
|
||||
DEl2 = exmpp_xml:set_attribute(DEl1, <<"from">>,FromString),
|
||||
XEl2 = replace_subelement(XEl,DEl2),
|
||||
|
||||
@@ -114,6 +114,7 @@
|
||||
updated_list/3]).
|
||||
|
||||
-include_lib("exmpp/include/exmpp.hrl").
|
||||
-include_lib("exmpp/include/exmpp_jid.hrl").
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("mod_privacy.hrl").
|
||||
@@ -674,6 +675,27 @@ get_user_list(_, LUser, LServer)
|
||||
%% From is the sender, To is the destination.
|
||||
%% If Dir = out, User@Server is the sender account (From).
|
||||
%% If Dir = in, User@Server is the destination account (To).
|
||||
check_packet(_, _User, _Server,
|
||||
_UserList,
|
||||
{#jid{node = "", domain = Server} = _From,
|
||||
#jid{domain = Server} = _To,
|
||||
_},
|
||||
in) ->
|
||||
allow;
|
||||
check_packet(_, _User, _Server,
|
||||
_UserList,
|
||||
{#jid{domain = Server} = _From,
|
||||
#jid{node = "", domain = Server} = _To,
|
||||
_},
|
||||
out) ->
|
||||
allow;
|
||||
check_packet(_, _User, _Server,
|
||||
_UserList,
|
||||
{#jid{node = User, domain = Server} = _From,
|
||||
#jid{node = User, domain = Server} = _To,
|
||||
_},
|
||||
_Dir) ->
|
||||
allow;
|
||||
check_packet(_, User, Server,
|
||||
#userlist{list = List, needdb = NeedDb},
|
||||
{From, To, #xmlel{name = PName} = El},
|
||||
|
||||
@@ -222,7 +222,7 @@ iq_vcard(Lang) ->
|
||||
"\nCopyright (c) 2003-2011 ProcessOne")}]}].
|
||||
|
||||
parse_options(ServerHost, Opts) ->
|
||||
MyHost = gen_mod:expand_host_name(ServerHost, Opts, "proxy"),
|
||||
MyHost = gen_mod:get_opt_host(ServerHost, Opts, "proxy.@HOST@"),
|
||||
Port = gen_mod:get_opt(port, Opts, 7777),
|
||||
ACL = gen_mod:get_opt(access, Opts, all),
|
||||
Name = gen_mod:get_opt(name, Opts, "SOCKS5 Bytestreams"),
|
||||
|
||||
@@ -203,7 +203,7 @@ stop(Host) ->
|
||||
|
||||
init([ServerHost, Opts]) ->
|
||||
?DEBUG("pubsub init ~p ~p",[ServerHost,Opts]),
|
||||
Host = gen_mod:expand_host_name(ServerHost, Opts, "pubsub"),
|
||||
Host = gen_mod:get_opt_host(ServerHost, Opts, "pubsub.@HOST@"),
|
||||
Access = gen_mod:get_opt('access_createnode', Opts, 'all'),
|
||||
PepOffline = gen_mod:get_opt('ignore_pep_from_offline', Opts, true),
|
||||
IQDisc = gen_mod:get_opt('iqdisc', Opts, 'one_queue'),
|
||||
@@ -250,6 +250,7 @@ init([ServerHost, Opts]) ->
|
||||
ejabberd_router:register_route(Host),
|
||||
update_node_database(Host, ServerHost),
|
||||
update_state_database(Host, ServerHost),
|
||||
put(server_host, ServerHost),
|
||||
init_nodes(Host, ServerHost, NodeTree, Plugins),
|
||||
State = #state{host = Host,
|
||||
server_host = ServerHost,
|
||||
@@ -2170,13 +2171,16 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
|
||||
case transaction(CreateNode, transaction) of
|
||||
{result, {NodeId, {Result, broadcast}}} ->
|
||||
broadcast_created_node(Host, Node, NodeId, Type, NodeOptions),
|
||||
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
|
||||
case Result of
|
||||
default -> {result, Reply};
|
||||
_ -> {result, Result}
|
||||
end;
|
||||
{result, {_NodeId, default}} ->
|
||||
{result, {NodeId, default}} ->
|
||||
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
|
||||
{result, Reply};
|
||||
{result, {_NodeId, Result}} ->
|
||||
{result, {NodeId, Result}} ->
|
||||
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
|
||||
{result, Result};
|
||||
Error ->
|
||||
%% in case we change transaction to sync_dirty...
|
||||
@@ -2219,6 +2223,7 @@ delete_node(Host, Node, Owner) ->
|
||||
end
|
||||
end,
|
||||
Reply = [],
|
||||
ServerHost = get(server_host),
|
||||
case transaction(Host, Node, Action, transaction) of
|
||||
{result, {_, {Result, broadcast, Removed}}} ->
|
||||
lists:foreach(fun({RNode, _RSubscriptions}) ->
|
||||
@@ -2227,20 +2232,31 @@ delete_node(Host, Node, Owner) ->
|
||||
Type = RNode#pubsub_node.type,
|
||||
Options = RNode#pubsub_node.options,
|
||||
broadcast_removed_node(RH, RN, Nidx, Type, Options),
|
||||
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, Nidx]),
|
||||
unset_cached_item(RH, Nidx)
|
||||
end, Removed),
|
||||
case Result of
|
||||
default -> {result, Reply};
|
||||
_ -> {result, Result}
|
||||
end;
|
||||
{result, {_, {Result, _Removed}}} ->
|
||||
{result, {_, {Result, Removed}}} ->
|
||||
lists:foreach(fun({RNode, _RSubscriptions}) ->
|
||||
{RH, RN} = RNode#pubsub_node.id,
|
||||
Nidx = RNode#pubsub_node.idx,
|
||||
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, Nidx]),
|
||||
unset_cached_item(RH, Nidx)
|
||||
end, Removed),
|
||||
case Result of
|
||||
default -> {result, Reply};
|
||||
_ -> {result, Result}
|
||||
end;
|
||||
{result, {_, default}} ->
|
||||
{result, {TNode, default}} ->
|
||||
Nidx = TNode#pubsub_node.idx,
|
||||
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, Nidx]),
|
||||
{result, Reply};
|
||||
{result, {_, Result}} ->
|
||||
{result, {TNode, Result}} ->
|
||||
Nidx = TNode#pubsub_node.idx,
|
||||
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, Nidx]),
|
||||
{result, Result};
|
||||
Error ->
|
||||
Error
|
||||
|
||||
@@ -203,7 +203,7 @@ stop(Host) ->
|
||||
|
||||
init([ServerHost, Opts]) ->
|
||||
?DEBUG("pubsub init ~p ~p",[ServerHost,Opts]),
|
||||
Host = gen_mod:expand_host_name(ServerHost, Opts, "pubsub"),
|
||||
Host = gen_mod:get_opt_host(ServerHost, Opts, "pubsub.@HOST@"),
|
||||
Access = gen_mod:get_opt('access_createnode', Opts, 'all'),
|
||||
PepOffline = gen_mod:get_opt('ignore_pep_from_offline', Opts, true),
|
||||
IQDisc = gen_mod:get_opt('iqdisc', Opts, 'one_queue'),
|
||||
@@ -248,6 +248,7 @@ init([ServerHost, Opts]) ->
|
||||
ok
|
||||
end,
|
||||
ejabberd_router:register_route(Host),
|
||||
put(server_host, ServerHost),
|
||||
init_nodes(Host, ServerHost, NodeTree, Plugins),
|
||||
State = #state{host = Host,
|
||||
server_host = ServerHost,
|
||||
@@ -1964,13 +1965,16 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) ->
|
||||
case transaction(Host, CreateNode, transaction) of
|
||||
{result, {NodeId, {Result, broadcast}}} ->
|
||||
broadcast_created_node(Host, Node, NodeId, Type, NodeOptions),
|
||||
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
|
||||
case Result of
|
||||
default -> {result, Reply};
|
||||
_ -> {result, Result}
|
||||
end;
|
||||
{result, {_NodeId, default}} ->
|
||||
{result, {NodeId, default}} ->
|
||||
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
|
||||
{result, Reply};
|
||||
{result, {_NodeId, Result}} ->
|
||||
{result, {NodeId, Result}} ->
|
||||
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
|
||||
{result, Result};
|
||||
Error ->
|
||||
%% in case we change transaction to sync_dirty...
|
||||
@@ -2013,6 +2017,7 @@ delete_node(Host, Node, Owner) ->
|
||||
end
|
||||
end,
|
||||
Reply = [],
|
||||
ServerHost = get(server_host),
|
||||
case transaction(Host, Node, Action, transaction) of
|
||||
{result, {_, {Result, broadcast, Removed}}} ->
|
||||
lists:foreach(fun({RNode, _RSubscriptions}) ->
|
||||
@@ -2021,20 +2026,31 @@ delete_node(Host, Node, Owner) ->
|
||||
Type = RNode#pubsub_node.type,
|
||||
Options = RNode#pubsub_node.options,
|
||||
broadcast_removed_node(RH, RN, Nidx, Type, Options),
|
||||
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, Nidx]),
|
||||
unset_cached_item(RH, Nidx)
|
||||
end, Removed),
|
||||
case Result of
|
||||
default -> {result, Reply};
|
||||
_ -> {result, Result}
|
||||
end;
|
||||
{result, {_, {Result, _Removed}}} ->
|
||||
{result, {_, {Result, Removed}}} ->
|
||||
lists:foreach(fun({RNode, _RSubscriptions}) ->
|
||||
{RH, RN} = RNode#pubsub_node.id,
|
||||
Nidx = RNode#pubsub_node.idx,
|
||||
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, Nidx]),
|
||||
unset_cached_item(RH, Nidx)
|
||||
end, Removed),
|
||||
case Result of
|
||||
default -> {result, Reply};
|
||||
_ -> {result, Result}
|
||||
end;
|
||||
{result, {_, default}} ->
|
||||
{result, {TNode, default}} ->
|
||||
Nidx = TNode#pubsub_node.idx,
|
||||
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, Nidx]),
|
||||
{result, Reply};
|
||||
{result, {_, Result}} ->
|
||||
{result, {TNode, Result}} ->
|
||||
Nidx = TNode#pubsub_node.idx,
|
||||
ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, Nidx]),
|
||||
{result, Result};
|
||||
Error ->
|
||||
Error
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--- mod_pubsub.erl 2011-09-21 14:40:16.000000000 +0200
|
||||
+++ mod_pubsub_odbc.erl 2011-09-21 14:40:29.000000000 +0200
|
||||
--- mod_pubsub.erl 2011-11-29 15:46:28.000000000 +0100
|
||||
+++ mod_pubsub_odbc.erl 2011-11-29 15:47:30.000000000 +0100
|
||||
@@ -42,7 +42,7 @@
|
||||
%%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see
|
||||
%%% XEP-0060 section 12.18.
|
||||
@@ -46,10 +46,10 @@
|
||||
ejabberd_router:register_route(Host),
|
||||
- update_node_database(Host, ServerHost),
|
||||
- update_state_database(Host, ServerHost),
|
||||
put(server_host, ServerHost),
|
||||
init_nodes(Host, ServerHost, NodeTree, Plugins),
|
||||
State = #state{host = Host,
|
||||
server_host = ServerHost,
|
||||
@@ -351,229 +349,15 @@
|
||||
@@ -352,229 +350,15 @@
|
||||
|
||||
init_nodes(Host, ServerHost, _NodeTree, Plugins) ->
|
||||
%% TODO, this call should be done plugin side
|
||||
@@ -282,7 +282,7 @@
|
||||
-spec(send_loop/1 ::
|
||||
(
|
||||
State::#state{})
|
||||
@@ -590,14 +374,17 @@
|
||||
@@ -591,14 +375,17 @@
|
||||
%% for each node From is subscribed to
|
||||
%% and if the node is so configured, send the last published item to From
|
||||
lists:foreach(fun(PType) ->
|
||||
@@ -303,7 +303,7 @@
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
@@ -646,7 +433,7 @@
|
||||
@@ -647,7 +434,7 @@
|
||||
spawn(fun() ->
|
||||
Host = State#state.host,
|
||||
Owner = {U,S,undefined},
|
||||
@@ -312,7 +312,7 @@
|
||||
case get_option(Options, 'send_last_published_item') of
|
||||
'on_sub_and_presence' ->
|
||||
lists:foreach(fun(Resource) ->
|
||||
@@ -660,7 +447,7 @@
|
||||
@@ -661,7 +448,7 @@
|
||||
RosterGroups = get_option(Options, 'roster_groups_allowed', []),
|
||||
element(2, get_roster_info(U, S, LJID, RosterGroups))
|
||||
end,
|
||||
@@ -321,7 +321,7 @@
|
||||
true -> ok
|
||||
end
|
||||
end, Resources);
|
||||
@@ -763,8 +550,9 @@
|
||||
@@ -764,8 +551,9 @@
|
||||
[#xmlel{name = 'identity', ns = ?NS_DISCO_INFO,
|
||||
attrs = [?XMLATTR(<<"category">>, <<"pubsub">>), ?XMLATTR(<<"type">>, <<"pep">>)]}];
|
||||
disco_identity(#jid{node = U, domain = S, resource = R} = Host, NodeId, From) ->
|
||||
@@ -333,7 +333,7 @@
|
||||
{result, _} ->
|
||||
{result,
|
||||
[#xmlel{name = 'identity', ns = ?NS_DISCO_INFO,
|
||||
@@ -813,8 +601,9 @@
|
||||
@@ -814,8 +602,9 @@
|
||||
[?NS_PUBSUB_s
|
||||
| [?NS_PUBSUB_s++"#"++Feature || Feature <- features("pep")]];
|
||||
disco_features(#jid{node = U, domain = S, resource = R} = Host, NodeId, From) ->
|
||||
@@ -345,7 +345,7 @@
|
||||
{result, _} ->
|
||||
{result, [?NS_PUBSUB_s
|
||||
| [?NS_PUBSUB_s ++ "#" ++ Feature || Feature <- features("pep")]]};
|
||||
@@ -853,8 +642,9 @@
|
||||
@@ -854,8 +643,9 @@
|
||||
).
|
||||
|
||||
disco_items(#jid{raw = JID, node = U, domain = S, resource = R} = Host, <<>>, From) ->
|
||||
@@ -357,7 +357,7 @@
|
||||
{result, _} ->
|
||||
[#xmlel{name = 'item', ns = ?NS_DISCO_INFO,
|
||||
attrs = [?XMLATTR(<<"jid">>, JID),
|
||||
@@ -867,14 +657,15 @@
|
||||
@@ -868,14 +658,15 @@
|
||||
_ -> Acc
|
||||
end
|
||||
end,
|
||||
@@ -376,7 +376,7 @@
|
||||
{result, Items} ->
|
||||
{result,
|
||||
[#xmlel{name = 'item', ns = ?NS_DISCO_INFO,
|
||||
@@ -982,10 +773,10 @@
|
||||
@@ -983,10 +774,10 @@
|
||||
lists:foreach(fun(PType) ->
|
||||
{result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]),
|
||||
lists:foreach(fun
|
||||
@@ -389,7 +389,7 @@
|
||||
true ->
|
||||
node_action(Host, PType, unsubscribe_node, [Nidx, Entity, JID, all]);
|
||||
false ->
|
||||
@@ -1183,9 +974,10 @@
|
||||
@@ -1184,9 +975,10 @@
|
||||
end,
|
||||
ejabberd_router:route(To, From, Res);
|
||||
%% Service discovery : disco#items
|
||||
@@ -402,7 +402,7 @@
|
||||
{result, IQRes} ->
|
||||
Result = #xmlel{ns = ?NS_DISCO_ITEMS,
|
||||
name = 'query',
|
||||
@@ -1331,11 +1123,11 @@
|
||||
@@ -1332,11 +1124,11 @@
|
||||
).
|
||||
|
||||
node_disco_info(Host, NodeId, From) ->
|
||||
@@ -416,7 +416,7 @@
|
||||
{result, []} -> ["collection"];
|
||||
{result, _} -> ["leaf", "collection"];
|
||||
_ -> []
|
||||
@@ -1353,10 +1145,15 @@
|
||||
@@ -1354,10 +1146,15 @@
|
||||
[#xmlel{ns = ?NS_DISCO_INFO,
|
||||
name = 'feature',
|
||||
attrs = [?XMLATTR(<<"var">>, ?NS_PUBSUB_b)]} |
|
||||
@@ -436,7 +436,7 @@
|
||||
end,
|
||||
case transaction(Host, NodeId, Action, sync_dirty) of
|
||||
{result, {_, Result}} -> {result, Result};
|
||||
@@ -1400,10 +1197,10 @@
|
||||
@@ -1401,10 +1198,10 @@
|
||||
name = 'feature',
|
||||
attrs = [?XMLATTR(<<"var">>, ?NS_VCARD_b)]}]
|
||||
++
|
||||
@@ -451,7 +451,7 @@
|
||||
iq_disco_info(Host, NodeId, From, _Lang)
|
||||
when NodeId == ?NS_ADHOC_b orelse NodeId == ?NS_PUBSUB_GET_PENDING_b ->
|
||||
command_disco_info(Host, NodeId, From);
|
||||
@@ -1411,16 +1208,17 @@
|
||||
@@ -1412,16 +1209,17 @@
|
||||
node_disco_info(Host, NodeId, From).
|
||||
|
||||
|
||||
@@ -472,7 +472,7 @@
|
||||
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
|
||||
Nodes when is_list(Nodes) ->
|
||||
{result, lists:map(
|
||||
@@ -1437,7 +1235,7 @@
|
||||
@@ -1438,7 +1236,7 @@
|
||||
Other ->
|
||||
Other
|
||||
end;
|
||||
@@ -481,7 +481,7 @@
|
||||
%% TODO: support localization of this string
|
||||
{result,
|
||||
[#xmlel{ns = ?NS_DISCO_ITEMS,
|
||||
@@ -1445,14 +1243,15 @@
|
||||
@@ -1446,14 +1244,15 @@
|
||||
attrs = [?XMLATTR(<<"jid">>, Host),
|
||||
?XMLATTR(<<"node">>, ?NS_PUBSUB_GET_PENDING_b),
|
||||
?XMLATTR(<<"name">>, "Get Pending")]}]};
|
||||
@@ -502,7 +502,7 @@
|
||||
end,
|
||||
Nodes = lists:map(
|
||||
fun(#pubsub_node{id = {_, SubNodeId}, options = SubOptions}) ->
|
||||
@@ -1475,7 +1274,7 @@
|
||||
@@ -1476,7 +1275,7 @@
|
||||
attrs = [?XMLATTR(<<"jid">>, Host),
|
||||
?XMLATTR(<<"name">>, Name)]}
|
||||
end, NodeItems),
|
||||
@@ -511,7 +511,7 @@
|
||||
end,
|
||||
case transaction(Host, NodeId, Action, sync_dirty) of
|
||||
{result, {_, Result}} -> {result, Result};
|
||||
@@ -1484,12 +1283,6 @@
|
||||
@@ -1485,12 +1284,6 @@
|
||||
|
||||
|
||||
|
||||
@@ -524,7 +524,7 @@
|
||||
get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups) ->
|
||||
if (AccessModel == presence) or (AccessModel == roster) ->
|
||||
case Host of
|
||||
@@ -1645,7 +1438,7 @@
|
||||
@@ -1646,7 +1439,7 @@
|
||||
end;
|
||||
(_, Acc) -> Acc
|
||||
end, [], exmpp_xml:remove_cdata_from_list(SubEls)),
|
||||
@@ -533,7 +533,7 @@
|
||||
{'get', 'subscriptions'} ->
|
||||
get_subscriptions(Host, NodeId, From, Plugins);
|
||||
{'get', 'affiliations'} ->
|
||||
@@ -1836,7 +1629,8 @@
|
||||
@@ -1837,7 +1630,8 @@
|
||||
_ -> []
|
||||
end
|
||||
end,
|
||||
@@ -543,7 +543,7 @@
|
||||
sync_dirty) of
|
||||
{result, Res} -> Res;
|
||||
Err -> Err
|
||||
@@ -1880,7 +1674,7 @@
|
||||
@@ -1881,7 +1675,7 @@
|
||||
|
||||
%%% authorization handling
|
||||
|
||||
@@ -552,7 +552,7 @@
|
||||
Lang = <<"en">>, %% TODO fix
|
||||
{U, S, R} = Subscriber,
|
||||
Stanza = #xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children =
|
||||
@@ -1910,7 +1704,7 @@
|
||||
@@ -1911,7 +1705,7 @@
|
||||
lists:foreach(fun(Owner) ->
|
||||
{U, S, R} = Owner,
|
||||
ejabberd_router:route(service_jid(Host), exmpp_jid:make(U, S, R), Stanza)
|
||||
@@ -561,7 +561,7 @@
|
||||
|
||||
find_authorization_response(Packet) ->
|
||||
Els = Packet#xmlel.children,
|
||||
@@ -1969,8 +1763,8 @@
|
||||
@@ -1970,8 +1764,8 @@
|
||||
"true" -> true;
|
||||
_ -> false
|
||||
end,
|
||||
@@ -572,7 +572,7 @@
|
||||
{result, Subscriptions} = node_call(Type, get_subscriptions, [Nidx, Subscriber]),
|
||||
if
|
||||
not IsApprover ->
|
||||
@@ -2167,7 +1961,7 @@
|
||||
@@ -2168,7 +1962,7 @@
|
||||
end,
|
||||
Reply = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children =
|
||||
[#xmlel{ns = ?NS_PUBSUB, name = 'create', attrs = nodeAttr(Node)}]},
|
||||
@@ -580,8 +580,8 @@
|
||||
+ case transaction(Host, CreateNode, transaction) of
|
||||
{result, {NodeId, {Result, broadcast}}} ->
|
||||
broadcast_created_node(Host, Node, NodeId, Type, NodeOptions),
|
||||
case Result of
|
||||
@@ -2269,7 +2063,7 @@
|
||||
ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]),
|
||||
@@ -2285,7 +2079,7 @@
|
||||
%%<li>The node does not exist.</li>
|
||||
%%</ul>
|
||||
subscribe_node(Host, Node, From, JID, Configuration) ->
|
||||
@@ -590,7 +590,7 @@
|
||||
{result, GoodSubOpts} -> GoodSubOpts;
|
||||
_ -> invalid
|
||||
end,
|
||||
@@ -2279,7 +2073,7 @@
|
||||
@@ -2295,7 +2089,7 @@
|
||||
_:_ ->
|
||||
{undefined, undefined, undefined}
|
||||
end,
|
||||
@@ -599,7 +599,7 @@
|
||||
Features = features(Type),
|
||||
SubscribeFeature = lists:member("subscribe", Features),
|
||||
OptionsFeature = lists:member("subscription-options", Features),
|
||||
@@ -2288,6 +2082,7 @@
|
||||
@@ -2304,6 +2098,7 @@
|
||||
AccessModel = get_option(Options, access_model),
|
||||
SendLast = get_option(Options, send_last_published_item),
|
||||
AllowedGroups = get_option(Options, roster_groups_allowed, []),
|
||||
@@ -607,7 +607,7 @@
|
||||
{PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, Subscriber, Owners, AccessModel, AllowedGroups),
|
||||
if
|
||||
not SubscribeFeature ->
|
||||
@@ -2417,12 +2212,9 @@
|
||||
@@ -2433,12 +2228,9 @@
|
||||
Features = features(Type),
|
||||
PublishFeature = lists:member("publish", Features),
|
||||
PublishModel = get_option(Options, publish_model),
|
||||
@@ -621,7 +621,7 @@
|
||||
{PayloadCount, PayloadNS} = payload_els_ns(Payload),
|
||||
PayloadSize = size(term_to_binary(Payload))-2, % size(term_to_binary([])) == 2
|
||||
PayloadMaxSize = get_option(Options, max_payload_size),
|
||||
@@ -2645,7 +2437,7 @@
|
||||
@@ -2661,7 +2453,7 @@
|
||||
%% <p>The permission are not checked in this function.</p>
|
||||
%% @todo We probably need to check that the user doing the query has the right
|
||||
%% to read the items.
|
||||
@@ -630,7 +630,7 @@
|
||||
MaxItems =
|
||||
if
|
||||
SMaxItems == "" -> get_max_items_node(Host);
|
||||
@@ -2659,12 +2451,13 @@
|
||||
@@ -2675,12 +2467,13 @@
|
||||
{error, Error} ->
|
||||
{error, Error};
|
||||
_ ->
|
||||
@@ -645,7 +645,7 @@
|
||||
{PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups),
|
||||
if
|
||||
not RetreiveFeature ->
|
||||
@@ -2677,11 +2470,11 @@
|
||||
@@ -2693,11 +2486,11 @@
|
||||
node_call(Type, get_items,
|
||||
[Nidx, From,
|
||||
AccessModel, PresenceSubscription, RosterGroup,
|
||||
@@ -659,7 +659,7 @@
|
||||
SendItems = case ItemIds of
|
||||
[] ->
|
||||
Items;
|
||||
@@ -2694,7 +2487,7 @@
|
||||
@@ -2710,7 +2503,7 @@
|
||||
%% number of items sent to MaxItems:
|
||||
{result, #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children =
|
||||
[#xmlel{ns = ?NS_PUBSUB, name = 'items', attrs = nodeAttr(Node), children =
|
||||
@@ -668,7 +668,7 @@
|
||||
Error ->
|
||||
Error
|
||||
end
|
||||
@@ -2710,8 +2503,8 @@
|
||||
@@ -2726,8 +2519,8 @@
|
||||
).
|
||||
|
||||
get_items(Host, NodeId) ->
|
||||
@@ -679,7 +679,7 @@
|
||||
end,
|
||||
case transaction(Host, NodeId, Action, sync_dirty) of
|
||||
{result, {_, Items}} -> Items
|
||||
@@ -2728,13 +2521,24 @@
|
||||
@@ -2744,13 +2537,24 @@
|
||||
).
|
||||
|
||||
get_item(Host, NodeId, ItemId) ->
|
||||
@@ -706,7 +706,7 @@
|
||||
|
||||
%% @spec (Host, Node, NodeId, Type, LJID, Number) -> any()
|
||||
%% Host = pubsubHost()
|
||||
@@ -2745,32 +2549,32 @@
|
||||
@@ -2761,32 +2565,32 @@
|
||||
%% Number = last | integer()
|
||||
%% @doc <p>Resend the items of a node to the user.</p>
|
||||
%% @todo use cache-last-item feature
|
||||
@@ -761,7 +761,7 @@
|
||||
{result, []} ->
|
||||
[];
|
||||
{result, Items} ->
|
||||
@@ -2792,20 +2596,7 @@
|
||||
@@ -2808,20 +2612,7 @@
|
||||
[#xmlel{ns = ?NS_PUBSUB_EVENT, name = 'items', attrs = nodeAttr(Node), children =
|
||||
itemsEls(ToSend)}])
|
||||
end,
|
||||
@@ -783,7 +783,7 @@
|
||||
|
||||
%% @spec (Host, JID, Plugins) -> {error, Reason} | {result, Response}
|
||||
%% Host = host()
|
||||
@@ -2908,7 +2699,8 @@
|
||||
@@ -2924,7 +2715,8 @@
|
||||
error ->
|
||||
{error, 'bad-request'};
|
||||
_ ->
|
||||
@@ -793,7 +793,7 @@
|
||||
case lists:member(Owner, Owners) of
|
||||
true ->
|
||||
OwnerJID = exmpp_jid:make(Owner),
|
||||
@@ -2918,24 +2710,8 @@
|
||||
@@ -2934,24 +2726,8 @@
|
||||
end,
|
||||
lists:foreach(
|
||||
fun({JID, Affiliation}) ->
|
||||
@@ -820,7 +820,7 @@
|
||||
end, FilteredEntities),
|
||||
{result, []};
|
||||
_ ->
|
||||
@@ -2964,7 +2740,7 @@
|
||||
@@ -2980,7 +2756,7 @@
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
Subscriber = try exmpp_jid:parse(JID) of
|
||||
J -> jlib:short_jid(J)
|
||||
catch
|
||||
@@ -2972,7 +2748,7 @@
|
||||
@@ -2988,7 +2764,7 @@
|
||||
exmpp_jid:make("", "", "") %% TODO, check if use <<>> instead of ""
|
||||
end,
|
||||
{result, Subs} = node_call(Type, get_subscriptions,
|
||||
@@ -838,7 +838,7 @@
|
||||
SubIds = lists:foldl(fun({subscribed, SID}, Acc) ->
|
||||
[SID | Acc];
|
||||
(_, Acc) ->
|
||||
@@ -2982,17 +2758,17 @@
|
||||
@@ -2998,17 +2774,17 @@
|
||||
{_, []} ->
|
||||
{error, extended_error('not-acceptable', "not-subscribed")};
|
||||
{[], [SID]} ->
|
||||
@@ -861,7 +861,7 @@
|
||||
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
|
||||
attrs = [ ?XMLATTR(<<"jid">>, exmpp_jid:to_binary(Subscriber)),
|
||||
?XMLATTR(<<"subid">>, SubId) | nodeAttr(Node)],
|
||||
@@ -3024,8 +2800,8 @@
|
||||
@@ -3040,8 +2816,8 @@
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
@@ -872,7 +872,7 @@
|
||||
{result, GoodSubOpts} -> GoodSubOpts;
|
||||
_ -> invalid
|
||||
end,
|
||||
@@ -3035,7 +2811,7 @@
|
||||
@@ -3051,7 +2827,7 @@
|
||||
_ -> exmpp_jid:make("", "", "") %% TODO, check if use <<>> instead of ""
|
||||
end,
|
||||
{result, Subs} = node_call(Type, get_subscriptions,
|
||||
@@ -881,7 +881,7 @@
|
||||
SubIds = lists:foldl(fun({subscribed, SID}, Acc) ->
|
||||
[SID | Acc];
|
||||
(_, Acc) ->
|
||||
@@ -3045,19 +2821,19 @@
|
||||
@@ -3061,19 +2837,19 @@
|
||||
{_, []} ->
|
||||
{error, extended_error('not-acceptable', "not-subscribed")};
|
||||
{[], [SID]} ->
|
||||
@@ -907,7 +907,7 @@
|
||||
{result, _} ->
|
||||
{result, []};
|
||||
{error, _} ->
|
||||
@@ -3231,8 +3007,8 @@
|
||||
@@ -3247,8 +3023,8 @@
|
||||
?XMLATTR(<<"subsription">>, subscription_to_string(Sub)) | nodeAttr(Node)]}]}]},
|
||||
ejabberd_router:route(service_jid(Host), JID, Stanza)
|
||||
end,
|
||||
@@ -918,7 +918,7 @@
|
||||
true ->
|
||||
Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) ->
|
||||
|
||||
@@ -3586,7 +3362,7 @@
|
||||
@@ -3602,7 +3378,7 @@
|
||||
Collection = tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]),
|
||||
{result, [{Depth, [{N, sub_with_options(N)} || N <- Nodes]} || {Depth, Nodes} <- Collection]}
|
||||
end,
|
||||
@@ -927,7 +927,7 @@
|
||||
{result, CollSubs} -> subscribed_nodes_by_jid(NotifyType, CollSubs);
|
||||
_ -> []
|
||||
end.
|
||||
@@ -3644,19 +3420,19 @@
|
||||
@@ -3660,19 +3436,19 @@
|
||||
{_, JIDSubs} = lists:foldl(DepthsToDeliver, {[], []}, SubsByDepth),
|
||||
JIDSubs.
|
||||
|
||||
@@ -953,7 +953,7 @@
|
||||
_ -> {JID, SubId, []}
|
||||
end.
|
||||
|
||||
@@ -3768,6 +3544,30 @@
|
||||
@@ -3784,6 +3560,30 @@
|
||||
Result
|
||||
end.
|
||||
|
||||
@@ -984,7 +984,7 @@
|
||||
%% @spec (Host, Options) -> MaxItems
|
||||
%% Host = host()
|
||||
%% Options = [Option]
|
||||
@@ -4291,9 +4091,14 @@
|
||||
@@ -4307,9 +4107,14 @@
|
||||
|
||||
tree_action(Host, Function, Args) ->
|
||||
?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]),
|
||||
@@ -1002,7 +1002,7 @@
|
||||
|
||||
%% @doc <p>node plugin call.</p>
|
||||
-spec(node_call/3 ::
|
||||
@@ -4331,7 +4136,7 @@
|
||||
@@ -4347,7 +4152,7 @@
|
||||
|
||||
node_action(Host, Type, Function, Args) ->
|
||||
?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]),
|
||||
@@ -1011,7 +1011,7 @@
|
||||
node_call(Type, Function, Args)
|
||||
end, sync_dirty).
|
||||
|
||||
@@ -4346,7 +4151,7 @@
|
||||
@@ -4362,7 +4167,7 @@
|
||||
).
|
||||
|
||||
transaction(Host, NodeId, Action, Trans) ->
|
||||
@@ -1020,7 +1020,7 @@
|
||||
case tree_call(Host, get_node, [Host, NodeId]) of
|
||||
#pubsub_node{} = Node ->
|
||||
case Action(Node) of
|
||||
@@ -4360,7 +4165,7 @@
|
||||
@@ -4376,7 +4181,7 @@
|
||||
end, Trans).
|
||||
|
||||
|
||||
@@ -1029,7 +1029,7 @@
|
||||
(
|
||||
Host :: string() | host(),
|
||||
Action :: fun(),
|
||||
@@ -4368,21 +4173,28 @@
|
||||
@@ -4384,21 +4189,28 @@
|
||||
-> {'result', Nodes :: [] | [Node::pubsubNode()]}
|
||||
).
|
||||
|
||||
@@ -1063,7 +1063,7 @@
|
||||
{result, Result} -> {result, Result};
|
||||
{error, Error} -> {error, Error};
|
||||
{atomic, {result, Result}} -> {result, Result};
|
||||
@@ -4390,6 +4202,15 @@
|
||||
@@ -4406,6 +4218,15 @@
|
||||
{aborted, Reason} ->
|
||||
?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]),
|
||||
{error, 'internal-server-error'};
|
||||
@@ -1079,7 +1079,7 @@
|
||||
{'EXIT', Reason} ->
|
||||
?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]),
|
||||
{error, 'internal-server-error'};
|
||||
@@ -4398,6 +4219,16 @@
|
||||
@@ -4414,6 +4235,16 @@
|
||||
{error, 'internal-server-error'}
|
||||
end.
|
||||
|
||||
|
||||
@@ -175,9 +175,9 @@ get_user_roster(Items, US) ->
|
||||
|
||||
%% Export items in roster format:
|
||||
ModVcard = get_vcard_module(S),
|
||||
SRItems = [#roster{usj = {list_to_binary(U), list_to_binary(S), {list_to_binary(U1), list_to_binary(S1), undefined}},
|
||||
us = {list_to_binary(U), list_to_binary(S)},
|
||||
jid = {list_to_binary(U1), list_to_binary(S1), undefined},
|
||||
SRItems = [ #roster{usj = {U, S, {U1, S1, undefined}},
|
||||
us = {U, S},
|
||||
jid = {U1, S1, undefined},
|
||||
name = get_rosteritem_name(ModVcard, U1, S1),
|
||||
subscription = both,
|
||||
ask = none,
|
||||
@@ -496,7 +496,8 @@ get_user_groups(US) ->
|
||||
[]
|
||||
end ++ get_special_users_groups(Host).
|
||||
|
||||
is_group_enabled(Host, Group) ->
|
||||
is_group_enabled(Host1, Group1) ->
|
||||
{Host, Group} = split_grouphost(Host1, Group1),
|
||||
case catch mnesia:dirty_read(sr_group, {Group, Host}) of
|
||||
[#sr_group{opts = Opts}] ->
|
||||
not lists:member(disabled, Opts);
|
||||
@@ -527,7 +528,8 @@ get_online_users(Host) ->
|
||||
get_group_users(HostB, Group) when is_binary(HostB) ->
|
||||
get_group_users(binary_to_list(HostB), Group);
|
||||
|
||||
get_group_users(Host, Group) ->
|
||||
get_group_users(Host1, Group1) ->
|
||||
{Host, Group} = split_grouphost(Host1, Group1),
|
||||
case get_group_opt(Host, Group, all_users, false) of
|
||||
true ->
|
||||
ejabberd_auth:get_vh_registered_users(Host);
|
||||
@@ -573,7 +575,8 @@ get_group_explicit_users(Host, Group) ->
|
||||
[]
|
||||
end.
|
||||
|
||||
get_group_name(Host, Group) ->
|
||||
get_group_name(Host1, Group1) ->
|
||||
{Host, Group} = split_grouphost(Host1, Group1),
|
||||
get_group_opt(Host, Group, name, Group).
|
||||
|
||||
%% @spec(Host::string)
|
||||
@@ -1135,3 +1138,11 @@ get_opt(Opts, Opt, Default) ->
|
||||
|
||||
us_to_list({User, Server}) ->
|
||||
exmpp_jid:bare_to_list(User, Server).
|
||||
|
||||
split_grouphost(Host, Group) ->
|
||||
case string:tokens(Group, "@") of
|
||||
[GroupName, HostName] ->
|
||||
{HostName, GroupName};
|
||||
[_] ->
|
||||
{Host, Group}
|
||||
end.
|
||||
|
||||
+2
-3
@@ -148,7 +148,7 @@ start(HostB, Opts) ->
|
||||
gen_iq_handler:add_iq_handler(ejabberd_sm, HostB, ?NS_VCARD,
|
||||
?MODULE, process_sm_iq, IQDisc),
|
||||
ejabberd_hooks:add(disco_sm_features, HostB, ?MODULE, get_sm_features, 50),
|
||||
MyHost = gen_mod:expand_host_name(HostB, Opts, "vjud"),
|
||||
MyHost = gen_mod:get_opt_host(HostB, Opts, "vjud.@HOST@"),
|
||||
Search = gen_mod:get_opt(search, Opts, true),
|
||||
register(gen_mod:get_module_proc(HostB, ?PROCNAME),
|
||||
spawn(?MODULE, init, [MyHost, HostB, Search])).
|
||||
@@ -444,9 +444,8 @@ do_route(ServerHost, From, To, Packet) ->
|
||||
Err = exmpp_iq:error(Packet, 'not-allowed'),
|
||||
ejabberd_router:route(To, From, Err);
|
||||
{get, ?NS_DISCO_INFO} ->
|
||||
ServerHostB = list_to_binary(ServerHost),
|
||||
Info = ejabberd_hooks:run_fold(
|
||||
disco_info, ServerHostB, [],
|
||||
disco_info, ServerHost, [],
|
||||
[ServerHost, ?MODULE, <<>>, ""]),
|
||||
Result = #xmlel{ns = ?NS_DISCO_INFO, name = 'query',
|
||||
children = Info ++ [
|
||||
|
||||
@@ -650,7 +650,7 @@ find_xdata_el1([_ | Els]) ->
|
||||
find_xdata_el1(Els).
|
||||
|
||||
parse_options(Host, Opts) ->
|
||||
MyHost = gen_mod:expand_host_name(Host, Opts, "vjud"),
|
||||
MyHost = gen_mod:get_opt_host(Host, Opts, "vjud.@HOST@"),
|
||||
Search = gen_mod:get_opt(search, Opts, true),
|
||||
Matches = case gen_mod:get_opt(matches, Opts, 30) of
|
||||
infinity -> 0;
|
||||
|
||||
+26
-4
@@ -24,16 +24,26 @@
|
||||
#include <openssl/md2.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* R15B changed several driver callbacks to use ErlDrvSizeT and
|
||||
* ErlDrvSSizeT typedefs instead of int.
|
||||
* This provides missing typedefs on older OTP versions.
|
||||
*/
|
||||
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
|
||||
typedef int ErlDrvSizeT;
|
||||
typedef int ErlDrvSSizeT;
|
||||
#endif
|
||||
|
||||
static ErlDrvData sha_drv_start(ErlDrvPort port, char *buf)
|
||||
{
|
||||
set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int sha_drv_control(ErlDrvData handle,
|
||||
static ErlDrvSSizeT sha_drv_control(ErlDrvData handle,
|
||||
unsigned int command,
|
||||
char *buf, int len,
|
||||
char **rbuf, int rlen)
|
||||
char *buf, ErlDrvSizeT len,
|
||||
char **rbuf, ErlDrvSizeT rlen)
|
||||
{
|
||||
ErlDrvBinary *b = NULL;
|
||||
|
||||
@@ -89,7 +99,19 @@ ErlDrvEntry sha_driver_entry = {
|
||||
NULL, /* handle */
|
||||
sha_drv_control, /* F_PTR control, port_command callback */
|
||||
NULL, /* F_PTR timeout, reserved */
|
||||
NULL /* F_PTR outputv, reserved */
|
||||
NULL, /* F_PTR outputv, reserved */
|
||||
/* Added in Erlang/OTP R15B: */
|
||||
NULL, /* ready_async */
|
||||
NULL, /* flush */
|
||||
NULL, /* call */
|
||||
NULL, /* event */
|
||||
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
|
||||
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
|
||||
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
|
||||
0, /* driver_flags */
|
||||
NULL, /* handle2 */
|
||||
NULL, /* process_exit */
|
||||
NULL /* stop_select */
|
||||
};
|
||||
|
||||
DRIVER_INIT(sha_drv) /* must match name in driver_entry */
|
||||
|
||||
+26
-4
@@ -44,6 +44,16 @@ typedef unsigned __int32 uint32_t;
|
||||
#define SSL_OP_NO_TICKET 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* R15B changed several driver callbacks to use ErlDrvSizeT and
|
||||
* ErlDrvSSizeT typedefs instead of int.
|
||||
* This provides missing typedefs on older OTP versions.
|
||||
*/
|
||||
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
|
||||
typedef int ErlDrvSizeT;
|
||||
typedef int ErlDrvSSizeT;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* str_hash is based on the public domain code from
|
||||
* http://www.burtleburtle.net/bob/hash/doobs.html
|
||||
@@ -305,10 +315,10 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
||||
}
|
||||
|
||||
|
||||
static int tls_drv_control(ErlDrvData handle,
|
||||
static ErlDrvSSizeT tls_drv_control(ErlDrvData handle,
|
||||
unsigned int command,
|
||||
char *buf, int len,
|
||||
char **rbuf, int rlen)
|
||||
char *buf, ErlDrvSizeT len,
|
||||
char **rbuf, ErlDrvSizeT rlen)
|
||||
{
|
||||
tls_data *d = (tls_data *)handle;
|
||||
int res;
|
||||
@@ -503,7 +513,19 @@ ErlDrvEntry tls_driver_entry = {
|
||||
NULL, /* handle */
|
||||
tls_drv_control, /* F_PTR control, port_command callback */
|
||||
NULL, /* F_PTR timeout, reserved */
|
||||
NULL /* F_PTR outputv, reserved */
|
||||
NULL, /* F_PTR outputv, reserved */
|
||||
/* Added in Erlang/OTP R15B: */
|
||||
NULL, /* ready_async */
|
||||
NULL, /* flush */
|
||||
NULL, /* call */
|
||||
NULL, /* event */
|
||||
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
|
||||
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
|
||||
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
|
||||
0, /* driver_flags */
|
||||
NULL, /* handle2 */
|
||||
NULL, /* process_exit */
|
||||
NULL /* stop_select */
|
||||
};
|
||||
|
||||
DRIVER_INIT(tls_drv) /* must match name in driver_entry */
|
||||
|
||||
@@ -91,7 +91,7 @@ extract_lang_all ()
|
||||
cd $MSGS_DIR
|
||||
for i in $( ls *.msg ) ; do
|
||||
MISSING=`cat $i.translate | grep "\", \"\"}." | wc -l`
|
||||
LANGUAGE=`grep "Language:" $i.translate | sed 's/% Language: //g'`
|
||||
LANGUAGE=`grep "X-Language:" $i.translate | sed 's/% Language: //g'`
|
||||
LASTAUTH=`grep "Author:" $i.translate | head -n 1 | sed 's/% Author: //g'`
|
||||
echo -e "$i\t$MISSING\t$LANGUAGE\t$LASTAUTH"
|
||||
done
|
||||
@@ -258,7 +258,7 @@ extract_lang_updateall ()
|
||||
MISSING=`msgfmt --statistics $PO 2>&1 | awk '{printf "%5s", $4 }'`
|
||||
echo -n " $MISSING"
|
||||
|
||||
LANGUAGE=`grep "Language:" $PO | sed 's/\"X-Language: //g' | sed 's/\\\\n\"//g' | awk '{printf "%-12s", $1}'`
|
||||
LANGUAGE=`grep "X-Language:" $PO | sed 's/\"X-Language: //g' | sed 's/\\\\n\"//g' | awk '{printf "%-12s", $1}'`
|
||||
echo -n " $LANGUAGE"
|
||||
|
||||
LASTAUTH=`grep "Last-Translator" $PO | sed 's/\"Last-Translator: //g' | sed 's/\\\\n\"//g'`
|
||||
|
||||
Reference in New Issue
Block a user