diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example index a33dff219..9f2415f63 100644 --- a/src/ejabberd.cfg.example +++ b/src/ejabberd.cfg.example @@ -611,6 +611,12 @@ %% {static_modules, [ +%% {mod_adhoc, []}, +%% {mod_announce, []}, +%% {mod_disco, []}, +%% {mod_echo, [{prefix, "echo"}]}, +%% {mod_last, []}, +%% {mod_offline, []} ]}. diff --git a/src/gen_mod.erl b/src/gen_mod.erl index a60522eb3..ed51d7605 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -40,6 +40,7 @@ loaded_modules_with_opts/1, get_hosts/2, get_module_proc/2, + get_module_proc_existing/2, expand_host_name/3, is_loaded/2]). @@ -194,7 +195,13 @@ get_module_opt(Host, Module, Opt, Default) -> 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. @@ -260,6 +267,15 @@ get_hosts(Opts, Prefix) -> 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) -> @@ -269,8 +285,11 @@ get_module_proc(Host, {frontend, 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 diff --git a/src/gen_storage.erl b/src/gen_storage.erl index 472e0af0b..654a39850 100644 --- a/src/gen_storage.erl +++ b/src/gen_storage.erl @@ -118,6 +118,9 @@ table_info(Host, Tab, InfoKey) -> -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, diff --git a/src/gen_storage_migration.erl b/src/gen_storage_migration.erl index 1e58a0179..54afe6ad1 100644 --- a/src/gen_storage_migration.erl +++ b/src/gen_storage_migration.erl @@ -32,8 +32,9 @@ migrate_mnesia(Host, Table, Migrations) -> 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 diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index eb399470c..f1d525d71 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -47,8 +47,9 @@ -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, diff --git a/src/mod_announce.erl b/src/mod_announce.erl index 7482ce6e3..d0b0d08fa 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -57,8 +57,9 @@ -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()]}, @@ -73,7 +74,7 @@ start(Host, _Opts) -> 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() -> @@ -135,7 +136,7 @@ announce(From, To, Packet) -> 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}, @@ -541,7 +542,7 @@ handle_adhoc_form(From, To, 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; @@ -582,7 +583,7 @@ handle_adhoc_form(From, To, [] 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 -> diff --git a/src/mod_disco.erl b/src/mod_disco.erl index f140a3794..ab959896d 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -53,8 +53,9 @@ -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(), @@ -75,7 +76,7 @@ start(Host, Opts) -> 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]), @@ -106,7 +107,7 @@ stop(Host) -> 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}}). @@ -114,11 +115,11 @@ unregister_feature(HostB, Feature) -> 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}). @@ -242,14 +243,14 @@ get_local_services(Acc, _From, To, <<>>, _Lang) -> 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))) diff --git a/src/mod_last.erl b/src/mod_last.erl index f00c3f5ee..dc82c5a73 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -77,17 +77,18 @@ -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, @@ -97,8 +98,9 @@ start(Host, Opts) -> 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, @@ -252,9 +254,12 @@ remove_user(User, Server) when is_binary(User), is_binary(Server) -> 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 @@ -266,14 +271,14 @@ update_table(Host, mnesia) -> 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}]; _ -> diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 67f98813a..c59d500a6 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -112,12 +112,14 @@ %% 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}}, @@ -125,7 +127,7 @@ start(Host, Opts) -> {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, @@ -145,7 +147,7 @@ start(Host, Opts) -> 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) -> @@ -258,7 +260,7 @@ store_packet(From, To, Packet) -> 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, @@ -464,6 +466,9 @@ remove_user(User, Server) when is_binary(User), is_binary(Server) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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, @@ -720,8 +725,8 @@ get_messages_subset2(Max, Length, MsgsAll) -> 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")]. diff --git a/src/web/ejabberd_web_admin.erl b/src/web/ejabberd_web_admin.erl index 95ce59354..ab394f660 100644 --- a/src/web/ejabberd_web_admin.erl +++ b/src/web/ejabberd_web_admin.erl @@ -1658,8 +1658,7 @@ list_users_in_diapason(Host, Diap, Lang, URLFunc) -> 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', @@ -1672,7 +1671,7 @@ list_given_users(Host, Users, Prefix, Lang, URLFunc) -> 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)], @@ -1707,16 +1706,10 @@ list_given_users(Host, Users, Prefix, Lang, URLFunc) -> 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}) ->