%%
{static_modules,
[
+%% {mod_adhoc, []},
+%% {mod_announce, []},
+%% {mod_disco, []},
+%% {mod_echo, [{prefix, "echo"}]},
+%% {mod_last, []},
+%% {mod_offline, []}
]}.
loaded_modules_with_opts/1,
get_hosts/2,
get_module_proc/2,
+ get_module_proc_existing/2,
expand_host_name/3,
is_loaded/2]).
OptsList = ets:lookup(ejabberd_modules, {Module, Host}),
case OptsList of
[] ->
- Default;
+ OptsList2 = ets:lookup(ejabberd_modules, {Module, global}),
+ case OptsList2 of
+ [] ->
+ Default;
+ [#ejabberd_module{opts = Opts} | _] ->
+ get_opt(Opt, Opts, Default)
+ end;
[#ejabberd_module{opts = Opts} | _] ->
get_opt(Opt, Opts, Default)
end.
Hosts
end.
+get_module_proc_existing(Host, Base) ->
+ Proc = get_module_proc(Host, Base),
+ %% If the process doesn't exist for Host, it may exist for global
+ case {whereis(Proc), Host == global} of
+ {undefined, false} -> get_module_proc(global, Base);
+ {undefined, true} -> not_existing;
+ {_, _} -> Proc
+ end.
+
get_module_proc(Host, Base) when is_binary(Host) ->
get_module_proc(binary_to_list(Host), Base);
get_module_proc(global, Base) ->
get_module_proc(Host, Base) ->
list_to_atom(atom_to_list(Base) ++ "_" ++ Host).
+%% @spec(Host::string() | global, Module::atom()) -> true | false
+%% @doc Check if the module is loaded in this host (or global), or not.
is_loaded(Host, Module) ->
- ets:member(ejabberd_modules, {Module, Host}).
+ ets:member(ejabberd_modules, {Module, Host})
+ orelse ets:member(ejabberd_modules, {Module, global}).
expand_host_name(Host, Opts, DefaultPrefix) ->
case Host of
-spec create_table(atom(), storage_host(), storage_table(), list()) ->
tuple().
+create_table(Backend, global, Tab, Def) ->
+ [create_table(Backend, list_to_binary(Host), Tab, Def) || Host <- ejabberd_hosts:get_hosts(ejabberd)];
+
create_table(mnesia, Host, Tab, Def) ->
MDef = filter_mnesia_tabdef(Def),
define_table(mnesia, Host, Tab, #mnesia_def{table = Tab,
end
end, DifferentTableName).
-migrate_mnesia1(Host, Table, {OldTable, OldAttributes, MigrateFun}) ->
- HostB = list_to_binary(Host),
+migrate_mnesia1(Host, Table, {OldTable, OldAttributes, MigrateFun}) when is_list(Host) ->
+ migrate_mnesia1(list_to_binary(Host), Table, {OldTable, OldAttributes, MigrateFun});
+migrate_mnesia1(HostB, Table, {OldTable, OldAttributes, MigrateFun}) ->
case (catch mnesia:table_info(OldTable, attributes)) of
OldAttributes ->
if
-include("ejabberd.hrl").
-include("adhoc.hrl").
-start(Host, Opts) ->
- HostB = list_to_binary(Host),
+start(Host, Opts) when is_list(Host) ->
+ start(list_to_binary(Host), Opts);
+start(HostB, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_local, HostB, ?NS_ADHOC,
-define(NS_ADMINL(Sub), ["http:","jabber.org","protocol","admin", Sub]).
tokenize(Node) -> string:tokens(Node, "/#").
-start(Host, _Opts) ->
- HostB = list_to_binary(Host),
+start(Host, Opts) when is_list(Host) ->
+ start(list_to_binary(Host), Opts);
+start(HostB, _Opts) ->
mnesia:create_table(motd, [{disc_copies, [node()]},
{attributes, record_info(fields, motd)}]),
mnesia:create_table(motd_users, [{disc_copies, [node()]},
ejabberd_hooks:add(adhoc_local_commands, HostB, ?MODULE, announce_commands, 50),
ejabberd_hooks:add(user_available_hook, HostB,
?MODULE, send_motd, 50),
- register(gen_mod:get_module_proc(Host, ?PROCNAME),
+ register(gen_mod:get_module_proc(HostB, ?PROCNAME),
proc_lib:spawn(?MODULE, init, [])).
init() ->
case {exmpp_jid:prep_node(To), exmpp_jid:prep_resource(To)} of
{undefined, Res} ->
Name = Packet#xmlel.name,
- Proc = gen_mod:get_module_proc(exmpp_jid:prep_domain_as_list(To), ?PROCNAME),
+ Proc = gen_mod:get_module_proc_existing(exmpp_jid:prep_domain_as_list(To), ?PROCNAME),
case {Res, Name} of
{<<"announce/all">>, 'message'} ->
Proc ! {announce_all, From, To, Packet},
node = Node,
sessionid = SessionID},
Fields) ->
- LServer = exmpp_jid:prep_domain_as_list(To),
+ LServerB = exmpp_jid:prep_domain(To),
Confirm = case lists:keysearch("confirm", 1, Fields) of
{value, {"confirm", ["true"]}} ->
true;
[]
end},
- Proc = gen_mod:get_module_proc(LServer, ?PROCNAME),
+ Proc = gen_mod:get_module_proc_existing(LServerB, ?PROCNAME),
case {Node, Body} of
{?NS_ADMIN_s ++ "#delete-motd", _} ->
if Confirm ->
-include("ejabberd.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-start(Host, Opts) ->
- HostB = list_to_binary(Host),
+start(Host, Opts) when is_list(Host) ->
+ start(list_to_binary(Host), Opts);
+start(HostB, Opts) ->
ejabberd_local:refresh_iq_handlers(),
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
- lists:foreach(fun(Domain) -> register_extra_domain(list_to_binary(Host), Domain) end,
+ lists:foreach(fun(Domain) -> register_extra_domain(HostB, Domain) end,
ExtraDomains),
catch ets:new(disco_sm_features, [named_table, ordered_set, public]),
catch ets:new(disco_sm_nodes, [named_table, ordered_set, public]),
ok.
-register_feature(HostB, Feature) when is_binary(HostB) ->
+register_feature(HostB, Feature) ->
catch ets:new(disco_features, [named_table, ordered_set, public]),
ets:insert(disco_features, {{Feature, HostB}}).
catch ets:new(disco_features, [named_table, ordered_set, public]),
ets:delete(disco_features, {Feature, HostB}).
-register_extra_domain(HostB, Domain) when is_binary(HostB) ->
+register_extra_domain(HostB, Domain) ->
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
ets:insert(disco_extra_domains, {{Domain, HostB}}).
-unregister_extra_domain(HostB, Domain) when is_binary(HostB) ->
+unregister_extra_domain(HostB, Domain) ->
catch ets:new(disco_extra_domains, [named_table, ordered_set, public]),
ets:delete(disco_extra_domains, {Domain, HostB}).
empty -> []
end,
Host = exmpp_jid:prep_domain_as_list(To),
- NHost = ejabberd:normalize_host(Host),
+ NHostB = list_to_binary(ejabberd:normalize_host(Host)),
{result,
lists:usort(
lists:map(fun domain_to_xml/1,
get_vh_services(Host) ++
ets:select(disco_extra_domains,
ets:fun2ms(fun ({{Service, H}})
- when H =:= NHost;
+ when H =:= NHostB;
H =:= global ->
Service
end)))
-record(last_activity, {user_host, timestamp, status}).
-start(Host, Opts) ->
- HostB = list_to_binary(Host),
+start(Host, Opts) when is_list(Host) ->
+ start(list_to_binary(Host), Opts);
+start(HostB, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
Backend = gen_mod:get_opt(backend, Opts, mnesia),
gen_storage:create_table(Backend, HostB, last_activity,
[{disc_copies, [node()]},
- {odbc_host, Host},
+ {odbc_host, HostB},
{attributes, record_info(fields, last_activity)},
{types, [{user_host, {text, text}},
{timestamp, bigint}]}]),
- update_table(Host, Backend),
+ update_table(HostB, Backend),
gen_iq_handler:add_iq_handler(ejabberd_local, HostB, ?NS_LAST_ACTIVITY,
?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, HostB, ?NS_LAST_ACTIVITY,
ejabberd_hooks:add(unset_presence_hook, HostB,
?MODULE, on_presence_update, 50).
-stop(Host) ->
- HostB = list_to_binary(Host),
+stop(Host) when is_list(Host) ->
+ stop(list_to_binary(Host));
+stop(HostB) ->
ejabberd_hooks:delete(remove_user, HostB,
?MODULE, remove_user, 50),
ejabberd_hooks:delete(unset_presence_hook, HostB,
ok
end.
-update_table(Host, mnesia) ->
+update_table(global, Storage) ->
+ [update_table(HostB, Storage) || HostB <- ejabberd_hosts:get_hosts(ejabberd)];
+
+update_table(HostB, mnesia) ->
gen_storage_migration:migrate_mnesia(
- Host, last_activity,
+ HostB, last_activity,
[{last_activity, [us, timestamp, status],
fun({last_activity, {U, S}, Timestamp, Status}) ->
U1 = case U of
timestamp = Timestamp,
status = list_to_binary(Status)}
end}]);
-update_table(Host, odbc) ->
+update_table(HostB, odbc) ->
gen_storage_migration:migrate_odbc(
- Host, [last_activity],
+ HostB, [last_activity],
[{"last", ["username", "seconds", "state"],
fun(_, Username, STimeStamp, Status) ->
case catch list_to_integer(STimeStamp) of
TimeStamp when is_integer(TimeStamp) ->
- [#last_activity{user_host = {Username, Host},
+ [#last_activity{user_host = {Username, HostB},
timestamp = TimeStamp,
status = Status}];
_ ->
%% default value for the maximum number of user messages
-define(MAX_USER_MESSAGES, infinity).
-start(Host, Opts) ->
- HostB = list_to_binary(Host),
+start(Host, Opts) when is_list(Host) ->
+ start(list_to_binary(Host), Opts);
+start(HostB, Opts) ->
+% Host = binary_to_list(HostB),
Backend = gen_mod:get_opt(backend, Opts, mnesia),
gen_storage:create_table(Backend, HostB, offline_msg,
[{disc_only_copies, [node()]},
- {odbc_host, Host},
+ {odbc_host, HostB},
{type, bag},
{attributes, record_info(fields, offline_msg)},
{types, [{user_host, {text, text}},
{expire, bigint},
{from, jid},
{to, jid}]}]),
- update_table(Host, Backend),
+ update_table(HostB, Backend),
ejabberd_hooks:add(offline_message_hook, HostB,
?MODULE, store_packet, 50),
ejabberd_hooks:add(resend_offline_messages_hook, HostB,
ejabberd_hooks:add(webadmin_user_parse_query, HostB,
?MODULE, webadmin_user_parse_query, 50),
AccessMaxOfflineMsgs = gen_mod:get_opt(access_max_user_messages, Opts, max_user_offline_messages),
- register(gen_mod:get_module_proc(Host, ?PROCNAME),
+ register(gen_mod:get_module_proc(HostB, ?PROCNAME),
spawn(?MODULE, loop, [AccessMaxOfflineMsgs])).
stanza_to_store(Stanza) ->
LServer = exmpp_jid:prep_domain(To),
TimeStamp = make_timestamp(),
Expire = find_x_expire(TimeStamp, Packet#xmlel.children),
- gen_mod:get_module_proc(LServer, ?PROCNAME) !
+ gen_mod:get_module_proc_existing(LServer, ?PROCNAME) !
#offline_msg{user_host = {LUser, LServer},
timestamp = TimeStamp,
expire = Expire,
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+update_table(global, Storage) ->
+ [update_table(HostB, Storage) || HostB <- ejabberd_hosts:get_hosts(ejabberd)];
+
update_table(Host, mnesia) ->
gen_storage_migration:migrate_mnesia(
Host, offline_msg,
MsgsFirstN ++ [IntermediateMsg] ++ MsgsLastN.
webadmin_user(Acc, User, Server, Lang) ->
- LUser = exmpp_stringprep:nodeprep(User),
- LServer = exmpp_stringprep:nameprep(Server),
+ LUser = list_to_binary(exmpp_stringprep:nodeprep(User)),
+ LServer = list_to_binary(exmpp_stringprep:nameprep(Server)),
QueueLen = get_queue_length(LUser, LServer),
FQueueLen = [?AC("queue/", integer_to_list(QueueLen))],
Acc ++ [?XCT("h3", "Offline Messages:")] ++ FQueueLen ++ [?C(" "), ?INPUTT("submit", "removealloffline", "Remove All Offline Messages")].
Sub = lists:sublist(SUsers, N1, N2 - N1 + 1),
[list_given_users(Host, Sub, "../../", Lang, URLFunc)].
-list_given_users(Host, Users, Prefix, Lang, URLFunc) ->
- ModOffline = get_offlinemsg_module(Host),
+list_given_users(_Host, Users, Prefix, Lang, URLFunc) ->
?XE('table',
[?XE('thead',
[?XE('tr',
ServerB = list_to_binary(Server),
UserB = list_to_binary(User),
US = {UserB, ServerB},
- QueueLenStr = get_offlinemsg_length(ModOffline, User, Server),
+ QueueLenStr = get_offlinemsg_length(User, Server),
FQueueLen = [?AC(URLFunc({users_queue, Prefix,
User, Server}),
QueueLenStr)],
end, Users)
)]).
-get_offlinemsg_length(ModOffline, User, Server) ->
- case ModOffline of
- none -> "disabled";
- _ -> pretty_string_int(ModOffline:get_queue_length(list_to_binary(User), list_to_binary(Server)))
- end.
-
-get_offlinemsg_module(Server) ->
- case [mod_offline] -- gen_mod:loaded_modules(Server) of
- [mod_offline] -> none;
- [] -> mod_offline
+get_offlinemsg_length(User, Server) ->
+ case gen_mod:is_loaded(Server, mod_offline) of
+ false -> "disabled";
+ true -> pretty_string_int(mod_offline:get_queue_length(list_to_binary(User), list_to_binary(Server)))
end.
us_to_list({User, Server}) ->