From fb6267f38ee47f3f725f88324d132741c85dfb6a Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 1 Jun 2015 15:38:27 +0300 Subject: Add config validation at startup --- src/acl.erl | 11 ++++- src/cyrsasl.erl | 12 ++++- src/cyrsasl_digest.erl | 8 +++- src/ejabberd_app.erl | 18 ++++++- src/ejabberd_auth.erl | 11 ++++- src/ejabberd_auth_anonymous.erl | 21 +++++++-- src/ejabberd_auth_external.erl | 15 ++++-- src/ejabberd_auth_internal.erl | 8 +++- src/ejabberd_auth_ldap.erl | 100 +++++++++++++++++++++++++++++++++++++-- src/ejabberd_auth_odbc.erl | 11 +++-- src/ejabberd_auth_pam.erl | 24 ++++++---- src/ejabberd_c2s.erl | 37 ++++++++------- src/ejabberd_c2s_config.erl | 7 ++- src/ejabberd_captcha.erl | 15 +++++- src/ejabberd_config.erl | 59 ++++++++++++++++++++++- src/ejabberd_ctl.erl | 15 +++--- src/ejabberd_http.erl | 17 ++++++- src/ejabberd_http_ws.erl | 16 +++++-- src/ejabberd_listener.erl | 22 ++++----- src/ejabberd_node_groups.erl | 14 ++++-- src/ejabberd_odbc.erl | 27 ++++++++++- src/ejabberd_odbc_sup.erl | 19 +++++++- src/ejabberd_piefxis.erl | 9 +++- src/ejabberd_rdbms.erl | 12 ++++- src/ejabberd_riak_sup.erl | 28 +++++++---- src/ejabberd_router.erl | 9 +++- src/ejabberd_s2s.erl | 14 +++++- src/ejabberd_s2s_in.erl | 33 ++++++++++++- src/ejabberd_s2s_out.erl | 81 +++++++++++++++++++++++-------- src/ejabberd_service.erl | 13 ++++- src/ejabberd_sm.erl | 13 ++++- src/ejabberd_sm_redis.erl | 27 +++++++---- src/ejabberd_stun.erl | 13 ++++- src/ejabberd_system_monitor.erl | 14 +++++- src/ejabberd_web_admin.erl | 8 +++- src/ejabberd_xmlrpc.erl | 13 ++++- src/ejd2odbc.erl | 6 ++- src/eldap.erl | 24 +++++++++- src/eldap_utils.erl | 56 ++++++++++++++++++---- src/ext_mod.erl | 21 ++++++--- src/extauth.erl | 8 +++- src/gen_mod.erl | 92 +++++++++++++++++++++++++++--------- src/mod_adhoc.erl | 7 ++- src/mod_admin_extra.erl | 79 +++++++++---------------------- src/mod_announce.erl | 24 ++++------ src/mod_blocking.erl | 5 +- src/mod_caps.erl | 11 ++++- src/mod_carboncopy.erl | 13 +++-- src/mod_client_state.erl | 15 +++++- src/mod_configure.erl | 4 +- src/mod_configure2.erl | 23 ++++++++- src/mod_disco.erl | 17 ++++++- src/mod_echo.erl | 7 ++- src/mod_fail2ban.erl | 15 ++++-- src/mod_http_bind.erl | 8 +++- src/mod_http_fileserver.erl | 17 ++++++- src/mod_ip_blacklist.erl | 5 +- src/mod_irc.erl | 13 ++++- src/mod_last.erl | 17 +++++-- src/mod_muc.erl | 30 +++++++++++- src/mod_muc_admin.erl | 26 ++++------ src/mod_muc_log.erl | 47 +++++++++++++++++- src/mod_multicast.erl | 9 +++- src/mod_offline.erl | 12 ++++- src/mod_ping.erl | 15 +++++- src/mod_pres_counter.erl | 9 +++- src/mod_privacy.erl | 9 ++-- src/mod_private.erl | 7 ++- src/mod_proxy65.erl | 5 +- src/mod_proxy65_service.erl | 22 +++++++-- src/mod_proxy65_sm.erl | 10 +++- src/mod_proxy65_stream.erl | 15 +++++- src/mod_pubsub.erl | 25 +++++++++- src/mod_register.erl | 39 ++++++++++++++- src/mod_register_web.erl | 4 +- src/mod_roster.erl | 23 +++++++-- src/mod_service_log.erl | 17 +++++-- src/mod_shared_roster.erl | 24 ++++++---- src/mod_shared_roster_ldap.erl | 100 ++++++++++++++++++++++++++++++++++++++- src/mod_sic.erl | 5 +- src/mod_sip.erl | 47 ++++++++++++++++-- src/mod_sip_proxy.erl | 14 ++++-- src/mod_stats.erl | 6 ++- src/mod_time.erl | 6 ++- src/mod_vcard.erl | 20 +++++++- src/mod_vcard_ldap.erl | 102 +++++++++++++++++++++++++++++++++++++++- src/mod_vcard_xupdate.erl | 7 ++- src/mod_version.erl | 8 +++- src/odbc_queries.erl | 53 ++++++++++++--------- src/shaper.erl | 10 +++- 90 files changed, 1597 insertions(+), 390 deletions(-) diff --git a/src/acl.erl b/src/acl.erl index 8d9692ffb..021e4e2d4 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -25,11 +25,14 @@ -module(acl). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -export([start/0, to_record/3, add/3, add_list/3, - add_local/3, add_list_local/3, load_from_config/0, - match_rule/3, match_acl/3, transform_options/1]). + add_local/3, add_list_local/3, load_from_config/0, + match_rule/3, match_acl/3, transform_options/1, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -476,3 +479,7 @@ transform_options({access, Name, Rules}, Opts) -> [{access, [{Name, NewRules}]}|Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. + +opt_type(access) -> fun (V) -> V end; +opt_type(acl) -> fun (V) -> V end; +opt_type(_) -> [access, acl]. diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index 764473bab..970da5bb9 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -25,10 +25,13 @@ -module(cyrsasl). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -export([start/0, register_mechanism/3, listmech/1, - server_new/7, server_start/3, server_step/2]). + server_new/7, server_start/3, server_step/2, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -237,3 +240,10 @@ is_disabled(Mechanism) -> [str:to_upper(V)] end, []), lists:member(Mechanism, Disabled). + +opt_type(disable_sasl_mechanisms) -> + fun (V) when is_list(V) -> + lists:map(fun (M) -> str:to_upper(M) end, V); + (V) -> [str:to_upper(V)] + end; +opt_type(_) -> [disable_sasl_mechanisms]. diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl index 10f964130..4b14bafd3 100644 --- a/src/cyrsasl_digest.erl +++ b/src/cyrsasl_digest.erl @@ -25,9 +25,12 @@ -module(cyrsasl_digest). +-behaviour(ejabberd_config). + -author('alexey@sevcom.net'). --export([start/1, stop/0, mech_new/4, mech_step/2, parse/1]). +-export([start/1, stop/0, mech_new/4, mech_step/2, + parse/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -256,3 +259,6 @@ response(KeyVals, User, Passwd, Nonce, AuthzId, ":", NC/binary, ":", CNonce/binary, ":", QOP/binary, ":", (hex((erlang:md5(A2))))/binary>>, hex((erlang:md5(T))). + +opt_type(fqdn) -> fun iolist_to_binary/1; +opt_type(_) -> [fqdn]. diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index daf8919a6..46fbf81dc 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -24,11 +24,14 @@ %%%---------------------------------------------------------------------- -module(ejabberd_app). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(application). --export([start_modules/0,start/2, prep_stop/1, stop/1, init/0]). +-export([start_modules/0, start/2, prep_stop/1, stop/1, + init/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -248,3 +251,16 @@ start_apps() -> ejabberd:start_app(p1_stringprep), ejabberd:start_app(p1_zlib), ejabberd:start_app(p1_cache_tab). + +opt_type(cluster_nodes) -> + fun (Ns) -> true = lists:all(fun is_atom/1, Ns), Ns end; +opt_type(loglevel) -> + fun (P) when P >= 0, P =< 5 -> P end; +opt_type(modules) -> + fun (Mods) -> + lists:map(fun ({M, A}) when is_atom(M), is_list(A) -> + {M, A} + end, + Mods) + end; +opt_type(_) -> [cluster_nodes, loglevel, modules]. diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 991cb664b..03c117b6c 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -27,6 +27,8 @@ -module(ejabberd_auth). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). %% External exports @@ -42,7 +44,7 @@ remove_user/2, remove_user/3, plain_password_required/1, store_type/1, entropy/1]). --export([auth_modules/1]). +-export([auth_modules/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -453,3 +455,10 @@ import(Server, riak, Passwd) -> ejabberd_auth_riak:import(Server, riak, Passwd); import(_, _, _) -> pass. + +opt_type(auth_method) -> + fun (V) when is_list(V) -> + true = lists:all(fun is_atom/1, V), V; + (V) when is_atom(V) -> [V] + end; +opt_type(_) -> [auth_method]. diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index cb320dea5..c00fff0bd 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -24,6 +24,8 @@ %%%---------------------------------------------------------------------- -module(ejabberd_auth_anonymous). + +-behaviour(ejabberd_config). -author('mickael.remond@process-one.net'). -export([start/1, @@ -36,16 +38,15 @@ unregister_connection/3 ]). - -%% Function used by ejabberd_auth: -export([login/2, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, - get_vh_registered_users/2, get_vh_registered_users_number/1, - get_vh_registered_users_number/2, get_password_s/2, + get_vh_registered_users/2, + get_vh_registered_users_number/1, + get_vh_registered_users_number/2, get_password_s/2, get_password/2, get_password/3, is_user_exists/2, remove_user/2, remove_user/3, store_type/0, - plain_password_required/0]). + plain_password_required/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -269,3 +270,13 @@ plain_password_required() -> false. store_type() -> plain. + +opt_type(allow_multiple_connections) -> + fun (V) when is_boolean(V) -> V end; +opt_type(anonymous_protocol) -> + fun (sasl_anon) -> sasl_anon; + (login_anon) -> login_anon; + (both) -> both + end; +opt_type(_) -> + [allow_multiple_connections, anonymous_protocol]. diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 0aa825f73..67477f27a 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -25,11 +25,12 @@ -module(ejabberd_auth_external). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(ejabberd_auth). -%% External exports -export([start/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, @@ -37,8 +38,8 @@ get_vh_registered_users_number/1, get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, - remove_user/3, store_type/0, - plain_password_required/0]). + remove_user/3, store_type/0, plain_password_required/0, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -311,3 +312,11 @@ get_mod_last_configured(Server) -> is_configured(Host, Module) -> gen_mod:is_loaded(Host, Module). + +opt_type(extauth_cache) -> + fun (false) -> undefined; + (I) when is_integer(I), I >= 0 -> I + end; +opt_type(extauth_program) -> + fun (V) -> binary_to_list(iolist_to_binary(V)) end; +opt_type(_) -> [extauth_cache, extauth_program]. diff --git a/src/ejabberd_auth_internal.erl b/src/ejabberd_auth_internal.erl index fc128ac5a..d7f2a5ae5 100644 --- a/src/ejabberd_auth_internal.erl +++ b/src/ejabberd_auth_internal.erl @@ -25,11 +25,12 @@ -module(ejabberd_auth_internal). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(ejabberd_auth). -%% External exports -export([start/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, @@ -38,7 +39,7 @@ get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, remove_user/3, store_type/0, export/1, import/1, - import/3, plain_password_required/0]). + import/3, plain_password_required/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -484,3 +485,6 @@ import(_LServer, mnesia, #passwd{} = P) -> mnesia:dirty_write(P); import(_, _, _) -> pass. + +opt_type(auth_password_format) -> fun (V) -> V end; +opt_type(_) -> [auth_password_format]. diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index d08151e60..f2122805a 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -25,6 +25,8 @@ -module(ejabberd_auth_ldap). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -34,16 +36,15 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -%% External exports -export([start/1, stop/1, start_link/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, - get_vh_registered_users/2, - get_vh_registered_users_number/1, + get_vh_registered_users/2, + get_vh_registered_users_number/1, get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, - remove_user/3, store_type/0, - plain_password_required/0]). + remove_user/3, store_type/0, plain_password_required/0, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -418,3 +419,92 @@ check_filter(F) -> NewF = iolist_to_binary(F), {ok, _} = eldap_filter:parse(NewF), NewF. + +mod_opt_type(deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_backups) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_base) -> fun iolist_to_binary/1; +mod_opt_type(ldap_deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +mod_opt_type(ldap_password) -> fun iolist_to_binary/1; +mod_opt_type(ldap_port) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; +mod_opt_type(ldap_servers) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_tls_cacertfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_certfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I end; +mod_opt_type(ldap_tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +mod_opt_type(ldap_dn_filter) -> + fun ([{DNF, DNFA}]) -> + NewDNFA = case DNFA of + undefined -> []; + _ -> [iolist_to_binary(A) || A <- DNFA] + end, + NewDNF = check_filter(DNF), + {NewDNF, NewDNFA} + end; +mod_opt_type(ldap_filter) -> fun check_filter/1; +mod_opt_type(ldap_local_filter) -> fun (V) -> V end; +mod_opt_type(ldap_uids) -> + fun (Us) -> + lists:map(fun ({U, P}) -> + {iolist_to_binary(U), iolist_to_binary(P)}; + ({U}) -> {iolist_to_binary(U)}; + (U) -> {iolist_to_binary(U)} + end, + lists:flatten(Us)) + end; +mod_opt_type(_) -> + [ldap_dn_filter, ldap_filter, ldap_local_filter, + ldap_uids, deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, + ldap_tls_verify]. + +opt_type(ldap_dn_filter) -> + fun ([{DNF, DNFA}]) -> + NewDNFA = case DNFA of + undefined -> []; + _ -> [iolist_to_binary(A) || A <- DNFA] + end, + NewDNF = check_filter(DNF), + {NewDNF, NewDNFA} + end; +opt_type(ldap_filter) -> fun check_filter/1; +opt_type(ldap_local_filter) -> fun (V) -> V end; +opt_type(ldap_uids) -> + fun (Us) -> + lists:map(fun ({U, P}) -> + {iolist_to_binary(U), iolist_to_binary(P)}; + ({U}) -> {iolist_to_binary(U)}; + (U) -> {iolist_to_binary(U)} + end, + lists:flatten(Us)) + end; +opt_type(_) -> + [ldap_dn_filter, ldap_filter, ldap_local_filter, + ldap_uids]. diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index 881b86cca..45ff4d778 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -25,11 +25,12 @@ -module(ejabberd_auth_odbc). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(ejabberd_auth). -%% External exports -export([start/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, @@ -37,9 +38,8 @@ get_vh_registered_users_number/1, get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, - remove_user/3, store_type/0, - plain_password_required/0, - convert_to_scram/1]). + remove_user/3, store_type/0, plain_password_required/0, + convert_to_scram/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -467,3 +467,6 @@ convert_to_scram(Server) -> Error -> Error end end. + +opt_type(auth_password_format) -> fun (V) -> V end; +opt_type(_) -> [auth_password_format]. diff --git a/src/ejabberd_auth_pam.erl b/src/ejabberd_auth_pam.erl index f3fdf628d..312bcf46e 100644 --- a/src/ejabberd_auth_pam.erl +++ b/src/ejabberd_auth_pam.erl @@ -24,22 +24,21 @@ %%%------------------------------------------------------------------- -module(ejabberd_auth_pam). +-behaviour(ejabberd_config). + -author('xram@jabber.ru'). -behaviour(ejabberd_auth). -%% External exports -%%==================================================================== -%% API -%%==================================================================== -export([start/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, - get_vh_registered_users/2, get_vh_registered_users_number/1, - get_vh_registered_users_number/2, - get_password/2, get_password_s/2, is_user_exists/2, - remove_user/2, remove_user/3, store_type/0, - plain_password_required/0]). + get_vh_registered_users/2, + get_vh_registered_users_number/1, + get_vh_registered_users_number/2, get_password/2, + get_password_s/2, is_user_exists/2, remove_user/2, + remove_user/3, store_type/0, plain_password_required/0, + opt_type/1]). start(_Host) -> ejabberd:start_app(p1_pam). @@ -118,3 +117,10 @@ get_pam_userinfotype(Host) -> (jid) -> jid end, username). + +opt_type(pam_service) -> fun iolist_to_binary/1; +opt_type(pam_userinfotype) -> + fun (username) -> username; + (jid) -> jid + end; +opt_type(_) -> [pam_service, pam_userinfotype]. diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index b4cd28576..330660925 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -25,6 +25,8 @@ -module(ejabberd_c2s). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -protocol({xep, 78, '2.5'}). @@ -54,23 +56,12 @@ get_subscribed/1, transform_listen_option/2]). -%% gen_fsm callbacks --export([init/1, - wait_for_stream/2, - wait_for_auth/2, - wait_for_feature_request/2, - wait_for_bind/2, - wait_for_session/2, - wait_for_sasl_response/2, - wait_for_resume/2, - session_established/2, - handle_event/3, - handle_sync_event/4, - code_change/4, - handle_info/3, - terminate/3, - print_state/1 - ]). +-export([init/1, wait_for_stream/2, wait_for_auth/2, + wait_for_feature_request/2, wait_for_bind/2, + wait_for_session/2, wait_for_sasl_response/2, + wait_for_resume/2, session_established/2, + handle_event/3, handle_sync_event/4, code_change/4, + handle_info/3, terminate/3, print_state/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -3126,3 +3117,15 @@ pack_string(String, Pack) -> transform_listen_option(Opt, Opts) -> [Opt|Opts]. + +opt_type(domain_certfile) -> fun iolist_to_binary/1; +opt_type(max_fsm_queue) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(resource_conflict) -> + fun (setresource) -> setresource; + (closeold) -> closeold; + (closenew) -> closenew; + (acceptnew) -> acceptnew + end; +opt_type(_) -> + [domain_certfile, max_fsm_queue, resource_conflict]. diff --git a/src/ejabberd_c2s_config.erl b/src/ejabberd_c2s_config.erl index a971f0af4..43bba6726 100644 --- a/src/ejabberd_c2s_config.erl +++ b/src/ejabberd_c2s_config.erl @@ -26,9 +26,11 @@ -module(ejabberd_c2s_config). +-behaviour(ejabberd_config). + -author('mremond@process-one.net'). --export([get_c2s_limits/0]). +-export([get_c2s_limits/0, opt_type/1]). %% Get first c2s configuration limitations to apply it to other c2s %% connectors. @@ -63,3 +65,6 @@ select_opts_values([{max_stanza_size, Value} | Opts], [{max_stanza_size, Value} | SelectedValues]); select_opts_values([_Opt | Opts], SelectedValues) -> select_opts_values(Opts, SelectedValues). + +opt_type(listen) -> fun (V) -> V end; +opt_type(_) -> [listen]. diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index fc9f975f5..8a1de2ede 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -25,6 +25,8 @@ -module(ejabberd_captcha). +-behaviour(ejabberd_config). + -protocol({xep, 158, '1.0'}). -behaviour(gen_server). @@ -39,7 +41,7 @@ -export([create_captcha/6, build_captcha_html/2, check_captcha/2, process_reply/1, process/2, is_feature_available/0, create_captcha_x/5, - create_captcha_x/6]). + create_captcha_x/6, opt_type/1]). -include("jlib.hrl"). @@ -695,3 +697,14 @@ clean_treap(Treap, CleanPriority) -> now_priority() -> {MSec, Sec, USec} = now(), -((MSec * 1000000 + Sec) * 1000000 + USec). + +opt_type(captcha_cmd) -> + fun (FileName) -> + F = iolist_to_binary(FileName), if F /= <<"">> -> F end + end; +opt_type(captcha_host) -> fun iolist_to_binary/1; +opt_type(captcha_limit) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(listen) -> fun (V) -> V end; +opt_type(_) -> + [captcha_cmd, captcha_host, captcha_limit, listen]. diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index fb5063775..efc70ed57 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -36,13 +36,14 @@ prepare_opt_val/4, convert_table_to_binary/5, transform_options/1, collect_options/1, convert_to_yaml/1, convert_to_yaml/2, - env_binary_to_list/2]). + env_binary_to_list/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("ejabberd_config.hrl"). -include_lib("kernel/include/file.hrl"). +-callback opt_type(atom()) -> function() | [atom()]. %% @type macro() = {macro_key(), macro_value()} @@ -65,7 +66,8 @@ start() -> {attributes, record_info(fields, local_config)}]), mnesia:add_table_copy(local_config, node(), ram_copies), Config = get_ejabberd_config_path(), - State = read_file(Config), + State0 = read_file(Config), + State = validate_opts(State0), %% This start time is used by mod_last: {MegaSecs, Secs, _} = now(), UnixTime = MegaSecs*1000000 + Secs, @@ -712,6 +714,47 @@ get_option(Opt, F, Default) -> end end. +get_modules_with_options() -> + {ok, Mods} = application:get_key(ejabberd, modules), + lists:foldl( + fun(Mod, D) -> + Attrs = Mod:module_info(attributes), + Behavs = proplists:get_value(behaviour, Attrs, []), + case lists:member(ejabberd_config, Behavs) or (Mod == ?MODULE) of + true -> + Opts = Mod:opt_type(''), + lists:foldl( + fun(Opt, Acc) -> + dict:append(Opt, Mod, Acc) + end, D, Opts); + false -> + D + end + end, dict:new(), [?MODULE|Mods]). + +validate_opts(#state{opts = Opts} = State) -> + ModOpts = get_modules_with_options(), + NewOpts = lists:filter( + fun(#local_config{key = {Opt, _Host}, value = Val}) -> + case dict:find(Opt, ModOpts) of + {ok, [Mod|_]} -> + VFun = Mod:opt_type(Opt), + case catch VFun(Val) of + {'EXIT', _} -> + ?ERROR_MSG("ignoring option '~s' with " + "invalid value: ~p", + [Opt, Val]), + false; + _ -> + true + end; + _ -> + ?ERROR_MSG("ignoring uknown option '~s'", [Opt]), + false + end + end, Opts), + State#state{opts = NewOpts}. + -spec get_vh_by_auth_method(atom()) -> [binary()]. %% Return the list of hosts handled by a given module @@ -1098,3 +1141,15 @@ emit_deprecation_warning(Module, NewModule) -> ?WARNING_MSG("Module ~s is deprecated, use ~s instead", [Module, NewModule]) end. + +opt_type(hosts) -> + fun(L) when is_list(L) -> + lists:map( + fun(H) -> + iolist_to_binary(H) + end, L) + end; +opt_type(language) -> + fun iolist_to_binary/1; +opt_type(_) -> + [hosts, language]. diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 1eae7f758..82ac6b134 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -44,14 +44,13 @@ -module(ejabberd_ctl). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). --export([start/0, - init/0, - process/1, - process2/2, - register_commands/3, - unregister_commands/3]). +-export([start/0, init/0, process/1, process2/2, + register_commands/3, unregister_commands/3, + opt_type/1]). -include("ejabberd_ctl.hrl"). -include("ejabberd_commands.hrl"). @@ -801,3 +800,7 @@ print(Format, Args) -> %%format_usage_xmlrpc(ArgsDef, ResultDef) -> %% ["aaaa bbb ccc"]. + +opt_type(ejabberdctl_access_commands) -> + fun (V) when is_list(V) -> V end; +opt_type(_) -> [ejabberdctl_access_commands]. diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 4e7f4b554..b4de38c02 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -25,6 +25,8 @@ -module(ejabberd_http). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). %% External exports @@ -32,8 +34,7 @@ socket_type/0, receive_headers/1, url_encode/1, transform_listen_option/2]). -%% Callbacks --export([init/2]). +-export([init/2, mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -870,3 +871,15 @@ transform_listen_option({request_handlers, Hs}, Opts) -> [{request_handlers, Hs1} | Opts]; transform_listen_option(Opt, Opts) -> [Opt|Opts]. + +mod_opt_type(default_host) -> fun (A) -> A end; +mod_opt_type(request_handlers) -> + fun (Hs) -> + [{str:tokens(iolist_to_binary(Path), <<"/">>), Mod} + || {Path, Mod} <- Hs] + end; +mod_opt_type(_) -> [default_host, request_handlers]. + +opt_type(trusted_proxies) -> + fun (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end; +opt_type(_) -> [trusted_proxies]. diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index a0cc31e2a..66a0542d4 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -24,16 +24,17 @@ %%%---------------------------------------------------------------------- -module(ejabberd_http_ws). +-behaviour(ejabberd_config). + -author('ecestari@process-one.net'). -behaviour(gen_fsm). -% External exports -export([start/1, start_link/1, init/1, handle_event/3, handle_sync_event/4, code_change/4, handle_info/3, - terminate/3, send_xml/2, setopts/2, sockname/1, peername/1, - controlling_process/2, become_controller/2, close/1, - socket_handoff/6]). + terminate/3, send_xml/2, setopts/2, sockname/1, + peername/1, controlling_process/2, become_controller/2, + close/1, socket_handoff/6, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -353,3 +354,10 @@ parsed_items(List) -> after 0 -> lists:reverse(List) end. + +opt_type(websocket_ping_interval) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(websocket_timeout) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(_) -> + [websocket_ping_interval, websocket_timeout]. diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 0cfca0aa0..81256cc18 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -24,20 +24,15 @@ %%%---------------------------------------------------------------------- -module(ejabberd_listener). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). --export([start_link/0, init/1, start/3, - init/3, - start_listeners/0, - start_listener/3, - stop_listeners/0, - stop_listener/2, - parse_listener_portip/2, - add_listener/3, - delete_listener/2, - transform_options/1, - validate_cfg/1 - ]). +-export([start_link/0, init/1, start/3, init/3, + start_listeners/0, start_listener/3, stop_listeners/0, + stop_listener/2, parse_listener_portip/2, + add_listener/3, delete_listener/2, transform_options/1, + validate_cfg/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -660,3 +655,6 @@ prepare_mod(sip) -> esip_socket; prepare_mod(Mod) when is_atom(Mod) -> Mod. + +opt_type(listen) -> fun validate_cfg/1; +opt_type(_) -> [listen]. diff --git a/src/ejabberd_node_groups.erl b/src/ejabberd_node_groups.erl index da0bffe99..87942b793 100644 --- a/src/ejabberd_node_groups.erl +++ b/src/ejabberd_node_groups.erl @@ -24,6 +24,8 @@ %%%---------------------------------------------------------------------- -module(ejabberd_node_groups). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_server). @@ -35,9 +37,8 @@ get_members/1, get_closest_node/1]). -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, + handle_info/2, terminate/2, code_change/3, opt_type/1]). -define(PG2, pg2). @@ -163,3 +164,10 @@ code_change(_OldVsn, State, _Extra) -> %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- + +opt_type(node_type) -> + fun (frontend) -> frontend; + (backend) -> backend; + (generic) -> generic + end; +opt_type(_) -> [node_type]. diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index dbae9f49b..eca781951 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -25,6 +25,8 @@ -module(ejabberd_odbc). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -define(GEN_FSM, p1_fsm). @@ -51,9 +53,9 @@ handle_info/3, terminate/3, print_state/1, code_change/4]). -%% gen_fsm states -export([connecting/2, connecting/3, - session_established/2, session_established/3]). + session_established/2, session_established/3, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -692,3 +694,24 @@ fsm_limit_opts() -> N when is_integer(N) -> [{max_queue, N}]; _ -> [] end. + +opt_type(max_fsm_queue) -> + fun (N) when is_integer(N), N > 0 -> N end; +opt_type(odbc_database) -> fun iolist_to_binary/1; +opt_type(odbc_keepalive_interval) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(odbc_password) -> fun iolist_to_binary/1; +opt_type(odbc_port) -> + fun (P) when is_integer(P), P > 0, P < 65536 -> P end; +opt_type(odbc_server) -> fun iolist_to_binary/1; +opt_type(odbc_type) -> + fun (mysql) -> mysql; + (pgsql) -> pgsql; + (sqlite) -> sqlite; + (odbc) -> odbc + end; +opt_type(odbc_username) -> fun iolist_to_binary/1; +opt_type(_) -> + [max_fsm_queue, odbc_database, odbc_keepalive_interval, + odbc_password, odbc_port, odbc_server, odbc_type, + odbc_username]. diff --git a/src/ejabberd_odbc_sup.erl b/src/ejabberd_odbc_sup.erl index 37128e265..4a1498964 100644 --- a/src/ejabberd_odbc_sup.erl +++ b/src/ejabberd_odbc_sup.erl @@ -25,11 +25,13 @@ -module(ejabberd_odbc_sup). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -%% API -export([start_link/1, init/1, add_pid/2, remove_pid/2, - get_pids/1, get_random_pid/1, transform_options/1]). + get_pids/1, get_random_pid/1, transform_options/1, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -205,3 +207,16 @@ read_lines(Fd, File, Acc) -> ?ERROR_MSG("Failed read from lite.sql, reason: ~p", [Err]), [] end. + +opt_type(odbc_pool_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(odbc_start_interval) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(odbc_type) -> + fun (mysql) -> mysql; + (pgsql) -> pgsql; + (sqlite) -> sqlite; + (odbc) -> odbc + end; +opt_type(_) -> + [odbc_pool_size, odbc_start_interval, odbc_type]. diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 61e6595e3..3b29aeefe 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -38,10 +38,12 @@ -module(ejabberd_piefxis). +-behaviour(ejabberd_config). + -protocol({xep, 227, '1.0'}). -%% API --export([import_file/1, export_server/1, export_host/2]). +-export([import_file/1, export_server/1, export_host/2, + opt_type/1]). -define(CHUNK_SIZE, 1024*20). %20k @@ -737,3 +739,6 @@ print(Fd, String) -> %%%================================== %%% vim: set filetype=erlang tabstop=8 foldmarker=%%%%,%%%= foldmethod=marker: file:write(Fd, String). + +opt_type(auth_password_format) -> fun (X) -> X end; +opt_type(_) -> [auth_password_format]. diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl index 93bd9fc49..23f1a857e 100644 --- a/src/ejabberd_rdbms.erl +++ b/src/ejabberd_rdbms.erl @@ -25,9 +25,11 @@ -module(ejabberd_rdbms). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). --export([start/0]). +-export([start/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -83,3 +85,11 @@ needs_odbc(Host) -> odbc -> {true, odbc}; undefined -> false end. + +opt_type(odbc_type) -> + fun (mysql) -> mysql; + (pgsql) -> pgsql; + (sqlite) -> sqlite; + (odbc) -> odbc + end; +opt_type(_) -> [odbc_type]. diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl index bb36eb44d..8b6a8064d 100644 --- a/src/ejabberd_riak_sup.erl +++ b/src/ejabberd_riak_sup.erl @@ -24,17 +24,13 @@ %%%---------------------------------------------------------------------- -module(ejabberd_riak_sup). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). -%% API --export([start/0, - start_link/0, - init/1, - get_pids/0, - transform_options/1, - get_random_pid/0, - get_random_pid/1 - ]). +-export([start/0, start_link/0, init/1, get_pids/0, + transform_options/1, get_random_pid/0, get_random_pid/1, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -158,3 +154,17 @@ transform_options({riak_server, {S, P}}, Opts) -> [{riak_server, S}, {riak_port, P}|Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [db_type]. + +opt_type(modules) -> fun (L) when is_list(L) -> L end; +opt_type(riak_pool_size) -> + fun (N) when is_integer(N), N >= 1 -> N end; +opt_type(riak_port) -> fun (_) -> true end; +opt_type(riak_server) -> fun (_) -> true end; +opt_type(riak_start_interval) -> + fun (N) when is_integer(N), N >= 1 -> N end; +opt_type(_) -> + [modules, riak_pool_size, riak_port, riak_server, + riak_start_interval]. diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 76ef71dc4..6a56a22ea 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -25,6 +25,8 @@ -module(ejabberd_router). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -43,9 +45,8 @@ -export([start_link/0]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -406,3 +407,7 @@ update_tables() -> false -> ok end. + +opt_type(domain_balancing_component_number) -> + fun (N) when is_integer(N), N > 1 -> N end; +opt_type(_) -> [domain_balancing_component_number]. diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index a7b3234fd..d6729dd46 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -25,6 +25,8 @@ -module(ejabberd_s2s). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -44,8 +46,8 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -%% ejabberd API --export([get_info_s2s_connections/1, transform_options/1]). +-export([get_info_s2s_connections/1, + transform_options/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -771,3 +773,11 @@ match_labels([DL | DLabels], [PL | PLabels]) -> end; false -> false end. + +opt_type(route_subdomains) -> + fun (s2s) -> s2s; + (local) -> local + end; +opt_type(s2s_access) -> + fun (A) when is_atom(A) -> A end; +opt_type(_) -> [route_subdomains, s2s_access]. diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 1b40f03c2..067eb98b2 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -25,6 +25,8 @@ -module(ejabberd_s2s_in). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(p1_fsm). @@ -32,11 +34,10 @@ %% External exports -export([start/2, start_link/2, socket_type/0]). -%% gen_fsm callbacks -export([init/1, wait_for_stream/2, wait_for_feature_request/2, stream_established/2, handle_event/3, handle_sync_event/4, code_change/4, - handle_info/3, print_state/1, terminate/3]). + handle_info/3, print_state/1, terminate/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -710,3 +711,31 @@ fsm_limit_opts(Opts) -> N -> [{max_queue, N}] end end. + +opt_type(domain_certfile) -> fun iolist_to_binary/1; +opt_type(max_fsm_queue) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(s2s_certfile) -> fun iolist_to_binary/1; +opt_type(s2s_ciphers) -> fun iolist_to_binary/1; +opt_type(s2s_protocol_options) -> + fun (Options) -> + [_ | O] = lists:foldl(fun (X, Acc) -> X ++ Acc end, [], + [["|" | binary_to_list(Opt)] + || Opt <- Options, is_binary(Opt)]), + iolist_to_binary(O) + end; +opt_type(s2s_tls_compression) -> + fun (true) -> true; + (false) -> false + end; +opt_type(s2s_use_starttls) -> + fun (false) -> false; + (true) -> true; + (optional) -> optional; + (required) -> required; + (required_trusted) -> required_trusted + end; +opt_type(_) -> + [domain_certfile, max_fsm_queue, s2s_certfile, + s2s_ciphers, s2s_protocol_options, s2s_tls_compression, + s2s_use_starttls]. diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 6196f136f..733dbe0a7 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -25,6 +25,8 @@ -module(ejabberd_s2s_out). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(p1_fsm). @@ -37,26 +39,14 @@ stop_connection/1, transform_options/1]). -%% p1_fsm callbacks (same as gen_fsm) --export([init/1, - open_socket/2, - wait_for_stream/2, - wait_for_validation/2, - wait_for_features/2, - wait_for_auth_result/2, - wait_for_starttls_proceed/2, - relay_to_bridge/2, - reopen_socket/2, - wait_before_retry/2, - stream_established/2, - handle_event/3, - handle_sync_event/4, - handle_info/3, - terminate/3, - print_state/1, - code_change/4, - test_get_addr_port/1, - get_addr_port/1]). +-export([init/1, open_socket/2, wait_for_stream/2, + wait_for_validation/2, wait_for_features/2, + wait_for_auth_result/2, wait_for_starttls_proceed/2, + relay_to_bridge/2, reopen_socket/2, wait_before_retry/2, + stream_established/2, handle_event/3, + handle_sync_event/4, handle_info/3, terminate/3, + print_state/1, code_change/4, test_get_addr_port/1, + get_addr_port/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1365,3 +1355,54 @@ fsm_limit_opts() -> undefined -> []; N -> [{max_queue, N}] end. + +opt_type(domain_certfile) -> fun iolist_to_binary/1; +opt_type(max_fsm_queue) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(outgoing_s2s_families) -> + fun (Families) -> + true = lists:all(fun (ipv4) -> true; + (ipv6) -> true + end, + Families), + Families + end; +opt_type(outgoing_s2s_port) -> + fun (I) when is_integer(I), I > 0, I =< 65536 -> I end; +opt_type(outgoing_s2s_timeout) -> + fun (TimeOut) when is_integer(TimeOut), TimeOut > 0 -> + TimeOut; + (infinity) -> infinity + end; +opt_type(s2s_certfile) -> fun iolist_to_binary/1; +opt_type(s2s_ciphers) -> fun iolist_to_binary/1; +opt_type(s2s_dns_retries) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(s2s_dns_timeout) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(s2s_max_retry_delay) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(s2s_protocol_options) -> + fun (Options) -> + [_ | O] = lists:foldl(fun (X, Acc) -> X ++ Acc end, [], + [["|" | binary_to_list(Opt)] + || Opt <- Options, is_binary(Opt)]), + iolist_to_binary(O) + end; +opt_type(s2s_tls_compression) -> + fun (true) -> true; + (false) -> false + end; +opt_type(s2s_use_starttls) -> + fun (true) -> true; + (false) -> false; + (optional) -> optional; + (required) -> required; + (required_trusted) -> required_trusted + end; +opt_type(_) -> + [domain_certfile, max_fsm_queue, outgoing_s2s_families, + outgoing_s2s_port, outgoing_s2s_timeout, s2s_certfile, + s2s_ciphers, s2s_dns_retries, s2s_dns_timeout, + s2s_max_retry_delay, s2s_protocol_options, + s2s_tls_compression, s2s_use_starttls]. diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index b7cea0c36..3e283a0a2 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -25,6 +25,8 @@ -module(ejabberd_service). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -protocol({xep, 114, '1.6'}). @@ -37,11 +39,11 @@ -export([start/2, start_link/2, send_text/2, send_element/2, socket_type/0, transform_listen_option/2]). -%% gen_fsm callbacks -export([init/1, wait_for_stream/2, wait_for_handshake/2, stream_established/2, handle_event/3, handle_sync_event/4, code_change/4, - handle_info/3, terminate/3, print_state/1]). + handle_info/3, terminate/3, print_state/1, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -404,3 +406,10 @@ fsm_limit_opts(Opts) -> N -> [{max_queue, N}] end end. + +mod_opt_type(password) -> fun iolist_to_binary/1; +mod_opt_type(_) -> [password]. + +opt_type(max_fsm_queue) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(_) -> [max_fsm_queue]. diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index bfe6e934f..e25902374 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -25,6 +25,8 @@ -module(ejabberd_sm). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -64,9 +66,8 @@ is_existing_resource/3 ]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -805,3 +806,11 @@ kick_user(User, Server) -> PID ! kick end, Resources), length(Resources). + +opt_type(sm_db_type) -> + fun (mnesia) -> mnesia; + (internal) -> mnesia; + (odbc) -> odbc; + (redis) -> redis + end; +opt_type(_) -> [sm_db_type]. diff --git a/src/ejabberd_sm_redis.erl b/src/ejabberd_sm_redis.erl index 0283f9c3e..a92845b81 100644 --- a/src/ejabberd_sm_redis.erl +++ b/src/ejabberd_sm_redis.erl @@ -8,16 +8,13 @@ %%%------------------------------------------------------------------- -module(ejabberd_sm_redis). +-behaviour(ejabberd_config). + -behaviour(ejabberd_sm). -%% API --export([init/0, - set_session/1, - delete_session/4, - get_sessions/0, - get_sessions/1, - get_sessions/2, - get_sessions/3]). +-export([init/0, set_session/1, delete_session/4, + get_sessions/0, get_sessions/1, get_sessions/2, + get_sessions/3, opt_type/1]). -include("ejabberd.hrl"). -include("ejabberd_sm.hrl"). @@ -207,3 +204,17 @@ clean_table() -> "server ~s: ~p", [LServer, Err]) end end, ?MYHOSTS). + +opt_type(redis_connect_timeout) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(redis_db) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(redis_password) -> fun iolist_to_list/1; +opt_type(redis_port) -> + fun (P) when is_integer(P), P > 0, P < 65536 -> P end; +opt_type(redis_reconnect_timeout) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(redis_server) -> fun iolist_to_list/1; +opt_type(_) -> + [redis_connect_timeout, redis_db, redis_password, + redis_port, redis_reconnect_timeout, redis_server]. diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index 9435f7e63..3d5ab6bd7 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -27,8 +27,8 @@ -protocol({rfc, 5766}). -%% API --export([tcp_init/2, udp_init/2, udp_recv/5, start/2, socket_type/0]). +-export([tcp_init/2, udp_init/2, udp_recv/5, start/2, + socket_type/0, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -100,3 +100,12 @@ prepare_turn_opts(Opts, _UseTurn = true) -> MaxRate = shaper:get_max_rate(Shaper), Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} | lists:keydelete(shaper, 1, Opts)]. + +mod_opt_type(auth_realm) -> fun iolist_to_binary/1; +mod_opt_type(auth_type) -> + fun (anonymous) -> anonymous; + (user) -> user + end; +mod_opt_type(shaper) -> + fun (S) when is_atom(S) -> S end; +mod_opt_type(_) -> [auth_realm, auth_type, shaper]. diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index df8d9d51a..fe8c1d2bb 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -25,6 +25,8 @@ -module(ejabberd_system_monitor). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -33,9 +35,8 @@ -export([start_link/0, process_command/3, process_remote_command/1]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -331,3 +332,12 @@ process_remote_command([setlh, NewValue]) -> io_lib:format("Result of set large heap: ~p --> ~p", [OldLH, NewLH]); process_remote_command(_) -> throw(unknown_command). + +opt_type(watchdog_admins) -> + fun (JIDs) -> + [jlib:jid_tolower(jlib:string_to_jid(iolist_to_binary(S))) + || S <- JIDs] + end; +opt_type(watchdog_large_heap) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(_) -> [watchdog_admins, watchdog_large_heap]. diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 29ecb7346..239c8bac5 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -27,12 +27,13 @@ -module(ejabberd_web_admin). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -%% External exports -export([process/2, list_users/4, list_users_in_diapason/4, pretty_print_xml/1, - term_to_id/1]). + term_to_id/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -2877,3 +2878,6 @@ make_menu_item(item, 3, URI, Name, Lang) -> %%%================================== %%% vim: set foldmethod=marker foldmarker=%%%%,%%%=: + +opt_type(access) -> fun (V) -> V end; +opt_type(_) -> [access]. diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index c85211450..0a74fd47b 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -36,7 +36,7 @@ -author('badlop@process-one.net'). -export([start/2, handler/2, process/2, socket_type/0, - transform_listen_option/2]). + transform_listen_option/2, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -541,3 +541,14 @@ transform_listen_option({access_commands, ACOpts}, Opts) -> [{access_commands, NewACOpts}|Opts]; transform_listen_option(Opt, Opts) -> [Opt|Opts]. + +mod_opt_type(access_commands) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(commands) -> + fun (A) when is_atom(A) -> A; + (L) when is_list(L) -> + true = lists:all(fun is_atom/1, L), L + end; +mod_opt_type(options) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(_) -> [access_commands, commands, options]. diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index 907814813..cc6241925 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -29,7 +29,8 @@ -include("logger.hrl"). --export([export/2, export/3, import_file/2, import/2, import/3]). +-export([export/2, export/3, import_file/2, import/2, + import/3, mod_opt_type/1]). -define(MAX_RECORDS_PER_TRANSACTION, 100). @@ -279,3 +280,6 @@ flatten1([H|T], Acc) -> flatten1(T, [[H, $\n]|Acc]); flatten1([], Acc) -> Acc. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [db_type]. diff --git a/src/eldap.erl b/src/eldap.erl index a9edebdf0..f8f6d04a9 100644 --- a/src/eldap.erl +++ b/src/eldap.erl @@ -80,11 +80,10 @@ -export([get_status/1]). -%% gen_fsm callbacks -export([init/1, connecting/2, connecting/3, wait_bind_response/3, active/3, active_bind/3, handle_event/3, handle_sync_event/4, handle_info/3, - terminate/3, code_change/4]). + terminate/3, code_change/4, mod_opt_type/1]). -export_type([filter/0]). @@ -1194,3 +1193,24 @@ bump_id(#eldap{id = Id}) when Id > (?MAX_TRANSACTION_ID) -> ?MIN_TRANSACTION_ID; bump_id(#eldap{id = Id}) -> Id + 1. + +mod_opt_type(encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +mod_opt_type(tls_cacertfile) -> + fun (S) when is_binary(S) -> binary_to_list(S); + (undefined) -> undefined + end; +mod_opt_type(tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I; + (undefined) -> undefined + end; +mod_opt_type(tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +mod_opt_type(_) -> + [encrypt, tls_cacertfile, tls_depth, tls_verify]. diff --git a/src/eldap_utils.erl b/src/eldap_utils.erl index bdc98c202..3c475e20b 100644 --- a/src/eldap_utils.erl +++ b/src/eldap_utils.erl @@ -24,18 +24,14 @@ %%%---------------------------------------------------------------------- -module(eldap_utils). + +-behaviour(ejabberd_config). -author('mremond@process-one.net'). --export([generate_subfilter/1, - find_ldap_attrs/2, - get_ldap_attr/2, - get_user_part/2, - make_filter/2, - get_state/2, - case_insensitive_match/2, - get_config/2, - decode_octet_string/3, - uids_domain_subst/2]). +-export([generate_subfilter/1, find_ldap_attrs/2, + get_ldap_attr/2, get_user_part/2, make_filter/2, + get_state/2, case_insensitive_match/2, get_config/2, + decode_octet_string/3, uids_domain_subst/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -349,3 +345,43 @@ collect_parts_bit([{?N_BIT_STRING,<>}|Rest],Acc,Uacc) -> collect_parts_bit(Rest,[Bits|Acc],Unused+Uacc); collect_parts_bit([],Acc,Uacc) -> list_to_binary([Uacc|lists:reverse(Acc)]). + +opt_type(deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +opt_type(ldap_backups) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +opt_type(ldap_base) -> fun iolist_to_binary/1; +opt_type(ldap_deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +opt_type(ldap_encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +opt_type(ldap_password) -> fun iolist_to_binary/1; +opt_type(ldap_port) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(ldap_rootdn) -> fun iolist_to_binary/1; +opt_type(ldap_servers) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +opt_type(ldap_tls_cacertfile) -> fun iolist_to_binary/1; +opt_type(ldap_tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(ldap_tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +opt_type(_) -> + [deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_depth, ldap_tls_verify]. diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 473aeb4eb..bfc448dcf 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -24,16 +24,16 @@ %%%---------------------------------------------------------------------- -module(ext_mod). + +-behaviour(ejabberd_config). -author("Christophe Romain "). -%% Packaging service -export([start/0, stop/0, update/0, check/1, - available_command/0, available/0, available/1, - installed_command/0, installed/0, installed/1, - install/1, uninstall/1, - upgrade/0, upgrade/1, - add_sources/2, del_sources/1, - modules_dir/0]). + available_command/0, available/0, available/1, + installed_command/0, installed/0, installed/1, + install/1, uninstall/1, upgrade/0, upgrade/1, + add_sources/2, del_sources/1, modules_dir/0, + opt_type/1]). -include("ejabberd_commands.hrl"). @@ -517,3 +517,10 @@ format({Key, Val}) when is_binary(Val) -> {Key, binary_to_list(Val)}; format({Key, Val}) -> % TODO: improve Yaml parsing {Key, Val}. + +opt_type(allow_contrib_modules) -> + fun (false) -> false; + (no) -> false; + (_) -> true + end; +opt_type(_) -> [allow_contrib_modules]. diff --git a/src/extauth.erl b/src/extauth.erl index eb936ddf9..766d43340 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -25,11 +25,13 @@ -module(extauth). +-behaviour(ejabberd_config). + -author('leifj@it.su.se'). -export([start/2, stop/1, init/2, check_password/3, set_password/3, try_register/3, remove_user/2, - remove_user/3, is_user_exists/2]). + remove_user/3, is_user_exists/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -157,3 +159,7 @@ encode(L) -> str:join(L, <<":">>). decode([0, 0]) -> false; decode([0, 1]) -> true. + +opt_type(extauth_instances) -> + fun (V) when is_integer(V), V > 0 -> V end; +opt_type(_) -> [extauth_instances]. diff --git a/src/gen_mod.erl b/src/gen_mod.erl index 29d5dfb78..2f9d3dd9e 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -1,7 +1,6 @@ %%%---------------------------------------------------------------------- %%% File : gen_mod.erl %%% Author : Alexey Shchepin -%%% Purpose : %%% Purpose : %%% Created : 24 Jan 2003 by Alexey Shchepin %%% @@ -18,22 +17,26 @@ %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU %%% General Public License for more details. %%% -%%% You should have received a copy of the GNU General Public License along -%%% with this program; if not, write to the Free Software Foundation, Inc., -%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% You should have received a copy of the GNU General Public License +%%% along with this program; if not, write to the Free Software +%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +%%% 02111-1307 USA %%% %%%---------------------------------------------------------------------- -module(gen_mod). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). --export([start/0, start_module/2, start_module/3, stop_module/2, - stop_module_keep_config/2, get_opt/3, get_opt/4, - get_opt_host/3, db_type/1, db_type/2, get_module_opt/5, - get_module_opt_host/3, loaded_modules/1, - loaded_modules_with_opts/1, get_hosts/2, - get_module_proc/2, is_loaded/2, default_db/1]). +-export([start/0, start_module/2, start_module/3, + stop_module/2, stop_module_keep_config/2, get_opt/3, + get_opt/4, get_opt_host/3, db_type/1, db_type/2, + get_module_opt/4, get_module_opt/5, get_module_opt_host/3, + loaded_modules/1, loaded_modules_with_opts/1, + get_hosts/2, get_module_proc/2, is_loaded/2, + start_modules/1, default_db/1, v_db/1, opt_type/1]). %%-export([behaviour_info/1]). @@ -45,11 +48,13 @@ opts = [] :: opts() | '_' | '$2'}). -type opts() :: [{atom(), any()}]. +-type db_type() :: odbc | mnesia | riak. -callback start(binary(), opts()) -> any(). -callback stop(binary()) -> any(). -export_type([opts/0]). +-export_type([db_type/0]). %%behaviour_info(callbacks) -> [{start, 2}, {stop, 1}]; %%behaviour_info(_Other) -> undefined. @@ -60,6 +65,17 @@ start() -> {keypos, #ejabberd_module.module_host}]), ok. +-spec start_modules(binary()) -> any(). + +start_modules(Host) -> + Modules = ejabberd_config:get_option( + {modules, Host}, + fun(L) when is_list(L) -> L end, []), + lists:foreach( + fun({Module, Opts}) -> + start_module(Host, Module, Opts) + end, Modules). + -spec start_module(binary(), atom()) -> any(). start_module(Host, Module) -> @@ -75,7 +91,8 @@ start_module(Host, Module) -> -spec start_module(binary(), atom(), opts()) -> any(). -start_module(Host, Module, Opts) -> +start_module(Host, Module, Opts0) -> + Opts = validate_opts(Module, Opts0), ets:insert(ejabberd_modules, #ejabberd_module{module_host = {Module, Host}, opts = Opts}), @@ -107,18 +124,12 @@ is_app_running(AppName) -> -spec stop_module(binary(), atom()) -> error | {aborted, any()} | {atomic, any()}. -%% @doc Stop the module in a host, and forget its configuration. stop_module(Host, Module) -> case stop_module_keep_config(Host, Module) of error -> error; ok -> ok end. -%% @doc Stop the module in a host, but keep its configuration. -%% As the module configuration is kept in the Mnesia local_config table, -%% when ejabberd is restarted the module will be started again. -%% This function is useful when ejabberd is being stopped -%% and it stops all modules. -spec stop_module_keep_config(binary(), atom()) -> error | ok. stop_module_keep_config(Host, Module) -> @@ -177,6 +188,11 @@ get_opt(Opt, Opts, F, Default) -> ejabberd_config:prepare_opt_val(Opt, Val, F, Default) end. +-spec get_module_opt(global | binary(), atom(), atom(), check_fun()) -> any(). + +get_module_opt(Host, Module, Opt, F) -> + get_module_opt(Host, Module, Opt, F, undefined). + -spec get_module_opt(global | binary(), atom(), atom(), check_fun(), any()) -> any(). get_module_opt(global, Module, Opt, F, Default) -> @@ -216,26 +232,56 @@ get_opt_host(Host, Opts, Default) -> Val = get_opt(host, Opts, fun iolist_to_binary/1, Default), ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host). --spec v_db(odbc | mnesia | riak | internal) -> odbc | mnesia | riak. +validate_opts(Module, Opts) -> + lists:filter( + fun({Opt, Val}) -> + case catch Module:mod_opt_type(Opt) of + VFun when is_function(VFun) -> + case catch VFun(Val) of + {'EXIT', _} -> + ?ERROR_MSG("ignoring invalid value '~p' for " + "option '~s' of module '~s'", + [Val, Opt, Module]), + false; + _ -> + true + end; + L when is_list(L) -> + SOpts = str:join([[$', atom_to_list(A), $'] || A <- L], <<", ">>), + ?ERROR_MSG("ignoring unknown option '~s' for module '~s'," + " available options are: ~s", [Opt, Module, SOpts]), + false; + {'EXIT', {undef, _}} -> + ?WARNING_MSG("module '~s' doesn't export mod_opt_type/1", + [Module]), + true + end; + (Junk) -> + ?ERROR_MSG("failed to understand option ~p for module '~s'", + [Junk, Module]), + false + end, Opts). + +-spec v_db(db_type() | internal) -> db_type(). v_db(odbc) -> odbc; v_db(internal) -> mnesia; v_db(mnesia) -> mnesia; v_db(riak) -> riak. --spec db_type(opts()) -> odbc | mnesia | riak. +-spec db_type(opts()) -> db_type(). db_type(Opts) -> db_type(global, Opts). --spec db_type(binary() | global, atom() | opts()) -> odbc | mnesia | riak. +-spec db_type(binary() | global, atom() | opts()) -> db_type(). db_type(Host, Module) when is_atom(Module) -> get_module_opt(Host, Module, db_type, fun v_db/1, default_db(Host)); db_type(Host, Opts) when is_list(Opts) -> get_opt(db_type, Opts, fun v_db/1, default_db(Host)). --spec default_db(binary() | global) -> odbc | mnesia | riak. +-spec default_db(binary() | global) -> db_type(). default_db(Host) -> ejabberd_config:get_option({default_db, Host}, fun v_db/1, mnesia). @@ -285,3 +331,7 @@ get_module_proc(Host, Base) -> is_loaded(Host, Module) -> ets:member(ejabberd_modules, {Module, Host}). + +opt_type(default_db) -> fun v_db/1; +opt_type(modules) -> fun (L) when is_list(L) -> L end; +opt_type(_) -> [default_db, modules]. diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index db73ced54..f54804831 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -35,7 +35,7 @@ process_sm_iq/3, get_local_commands/5, get_local_identity/5, get_local_features/5, get_sm_commands/5, get_sm_identity/5, get_sm_features/5, - ping_item/4, ping_command/4]). + ping_item/4, ping_command/4, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -280,3 +280,8 @@ ping_command(_Acc, _From, _To, true -> {error, ?ERR_BAD_REQUEST} end; ping_command(Acc, _From, _To, _Request) -> Acc. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(report_commands_node) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> [iqdisc, report_commands_node]. diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index bc49bae47..c213efe42 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -30,64 +30,24 @@ -include("logger.hrl"). --export([start/2, stop/1, - %% Node - compile/1, - get_cookie/0, - remove_node/1, - export2odbc/2, - %% Accounts - set_password/3, - check_password_hash/4, - delete_old_users/1, - delete_old_users_vhost/2, - ban_account/3, - num_active_users/2, - %% Sessions - num_resources/2, - resource_num/3, - kick_session/4, - status_num/2, status_num/1, - status_list/2, status_list/1, - connected_users_info/0, - connected_users_vhost/1, - set_presence/7, - user_sessions_info/2, - %% Vcard - set_nickname/3, - get_vcard/3, - get_vcard/4, - get_vcard_multi/4, - set_vcard/4, - set_vcard/5, - %% Roster - add_rosteritem/7, - delete_rosteritem/4, - process_rosteritems/5, - get_roster/2, - push_roster/3, - push_roster_all/1, - push_alltoall/2, - %% mod_last - get_last/2, - %% mod_private - private_get/4, - private_set/3, - %% mod_shared_roster - srg_create/5, - srg_delete/2, - srg_list/1, - srg_get_info/2, - srg_get_members/2, - srg_user_add/4, - srg_user_del/4, - %% Stanza - send_message/5, - send_stanza_c2s/4, - privacy_set/3, - %% Stats - stats/1, stats/2 - ]). +-export([start/2, stop/1, compile/1, get_cookie/0, + remove_node/1, export2odbc/2, set_password/3, + check_password_hash/4, delete_old_users/1, + delete_old_users_vhost/2, ban_account/3, + num_active_users/2, num_resources/2, resource_num/3, + kick_session/4, status_num/2, status_num/1, + status_list/2, status_list/1, connected_users_info/0, + connected_users_vhost/1, set_presence/7, + user_sessions_info/2, set_nickname/3, get_vcard/3, + get_vcard/4, get_vcard_multi/4, set_vcard/4, + set_vcard/5, add_rosteritem/7, delete_rosteritem/4, + process_rosteritems/5, get_roster/2, push_roster/3, + push_roster_all/1, push_alltoall/2, get_last/2, + private_get/4, private_set/3, srg_create/5, + srg_delete/2, srg_list/1, srg_get_info/2, + srg_get_members/2, srg_user_add/4, srg_user_del/4, + send_message/5, send_stanza_c2s/4, privacy_set/3, + stats/1, stats/2, mod_opt_type/1]). -include("ejabberd.hrl"). @@ -1557,3 +1517,6 @@ is_glob_match(String, <<"!", Glob/binary>>) -> not is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)); is_glob_match(String, Glob) -> is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)). + +mod_opt_type(module_resource) -> fun (A) -> A end; +mod_opt_type(_) -> [module_resource]. diff --git a/src/mod_announce.erl b/src/mod_announce.erl index 542417ff3..8049dd4f6 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -31,20 +31,11 @@ -behaviour(gen_mod). --export([start/2, - init/0, - stop/1, - export/1, - import/1, - import/3, - announce/3, - send_motd/1, - disco_identity/5, - disco_features/5, - disco_items/5, - send_announcement_to_all/3, - announce_commands/4, - announce_items/4]). +-export([start/2, init/0, stop/1, export/1, import/1, + import/3, announce/3, send_motd/1, disco_identity/5, + disco_features/5, disco_items/5, + send_announcement_to_all/3, announce_commands/4, + announce_items/4, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1152,3 +1143,8 @@ import(_LServer, riak, #motd_users{us = {_, S}} = Users) -> [{'2i', [{<<"server">>, S}]}]); import(_, _, _) -> pass. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [access, db_type]. diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 1d3bf3c34..609f1664c 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -31,7 +31,7 @@ -protocol({xep, 191, '1.2'}). -export([start/2, stop/1, process_iq/3, - process_iq_set/4, process_iq_get/5]). + process_iq_set/4, process_iq_get/5, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -451,3 +451,6 @@ process_blocklist_get(LUser, LServer, odbc) -> end; {'EXIT', _} -> error end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 10fe29431..f10ed66c7 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -47,10 +47,9 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -%% hook handlers -export([user_send_packet/3, user_receive_packet/4, c2s_presence_in/2, c2s_filter_packet/6, - c2s_broadcast_recipients/6]). + c2s_broadcast_recipients/6, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -754,3 +753,11 @@ import_next(LServer, DBType, NodePair) -> ok end, import_next(LServer, DBType, ets:next(caps_features_tmp, NodePair)). + +mod_opt_type(cache_life_time) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> + [cache_life_time, cache_size, db_type]. diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index be9e30f9c..2cc495aec 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -34,13 +34,9 @@ -export([start/2, stop/1]). -%% Hooks: --export([user_send_packet/3, - user_receive_packet/4, - iq_handler2/3, - iq_handler1/3, - remove_connection/4, - is_carbon_copy/1]). +-export([user_send_packet/3, user_receive_packet/4, + iq_handler2/3, iq_handler1/3, remove_connection/4, + is_carbon_copy/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -288,3 +284,6 @@ is_chat_or_normal_message(_Packet) -> false. list(User, Server)-> mnesia:dirty_select(?TABLE, [{#carboncopy{us = {User, Server}, resource = '$2', version = '$3'}, [], [{{'$2','$3'}}]}]). + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index c5041ed04..1287d5687 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -29,8 +29,9 @@ -behavior(gen_mod). --export([start/2, stop/1, add_stream_feature/2, filter_presence/2, - filter_chat_states/2]). +-export([start/2, stop/1, add_stream_feature/2, + filter_presence/2, filter_chat_states/2, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -108,3 +109,13 @@ filter_chat_states(_Action, #xmlel{name = <<"message">>} = Stanza) -> {stop, send} end; filter_chat_states(Action, _Stanza) -> Action. + +mod_opt_type(drop_chat_states) -> + fun (true) -> true; + (false) -> false + end; +mod_opt_type(queue_presence) -> + fun (true) -> true; + (false) -> false + end; +mod_opt_type(_) -> [drop_chat_states, queue_presence]. diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 0941dcf28..8faf7be73 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -35,7 +35,7 @@ get_local_features/5, get_local_items/5, adhoc_local_items/4, adhoc_local_commands/4, get_sm_identity/5, get_sm_features/5, get_sm_items/5, - adhoc_sm_items/4, adhoc_sm_commands/4]). + adhoc_sm_items/4, adhoc_sm_commands/4, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -2148,3 +2148,5 @@ set_sm_form(User, Server, <<"config">>, end; set_sm_form(_User, _Server, _Node, _Request, _Fields) -> {error, ?ERR_SERVICE_UNAVAILABLE}. + +mod_opt_type(_) -> []. diff --git a/src/mod_configure2.erl b/src/mod_configure2.erl index b70f8fe51..efe665d23 100644 --- a/src/mod_configure2.erl +++ b/src/mod_configure2.erl @@ -25,11 +25,14 @@ -module(mod_configure2). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -195,3 +198,21 @@ process_get(#xmlel{name = <<"last">>, attrs = Attrs}) -> %%process_get({xmlelement, Name, Attrs, SubEls}) -> %% {result, }; process_get(_) -> {error, ?ERR_BAD_REQUEST}. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. + +opt_type(registration_watchers) -> + fun (JIDs) when is_list(JIDs) -> + lists:map(fun (J) -> + #xmlel{name = <<"jid">>, attrs = [], + children = + [{xmlcdata, iolist_to_binary(J)}]} + end, + JIDs) + end; +opt_type(welcome_message) -> + fun ({Subj, Body}) -> + {iolist_to_binary(Subj), iolist_to_binary(Body)} + end; +opt_type(_) -> [registration_watchers, welcome_message]. diff --git a/src/mod_disco.erl b/src/mod_disco.erl index c0ab9a9ac..afa7d3908 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -39,7 +39,7 @@ get_sm_identity/5, get_sm_features/5, get_sm_items/5, get_info/5, register_feature/2, unregister_feature/2, register_extra_domain/2, unregister_extra_domain/2, - transform_module_options/1]). + transform_module_options/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -519,3 +519,18 @@ values_to_xml(Values) -> children = [{xmlcdata, Value}]} end, Values). + +mod_opt_type(extra_domains) -> + fun (Hs) -> [iolist_to_binary(H) || H <- Hs] end; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(server_info) -> + fun (L) -> + lists:map(fun (Opts) -> + Mods = proplists:get_value(modules, Opts, all), + Name = proplists:get_value(name, Opts, <<>>), + URLs = proplists:get_value(urls, Opts, []), + {Mods, Name, URLs} + end, + L) + end; +mod_opt_type(_) -> [extra_domains, iqdisc, server_info]. diff --git a/src/mod_echo.erl b/src/mod_echo.erl index 63dc8c81b..cdd9a8856 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -35,9 +35,9 @@ -export([start_link/2, start/2, stop/1, do_client_version/3]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -196,3 +196,6 @@ do_client_version(enabled, From, To) -> Values_string2 = iolist_to_binary(Values_string1), ?INFO_MSG("Information of the client: ~s~s", [ToS, Values_string2]). + +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(_) -> [host]. diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index 63c09db26..67b705d9a 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -31,9 +31,9 @@ %% API -export([start_link/2, start/2, stop/1, c2s_auth_result/4, check_bl_c2s/3]). -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include_lib("stdlib/include/ms_transform.hrl"). -include("ejabberd.hrl"). @@ -187,3 +187,12 @@ is_loaded_at_other_hosts(Host) -> format_date({{Year, Month, Day}, {Hour, Minute, Second}}) -> io_lib:format("~2..0w:~2..0w:~2..0w ~2..0w.~2..0w.~4..0w", [Hour, Minute, Second, Day, Month, Year]). + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(c2s_auth_ban_lifetime) -> + fun (T) when is_integer(T), T > 0 -> T end; +mod_opt_type(c2s_max_auth_failures) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(_) -> + [access, c2s_auth_ban_lifetime, c2s_max_auth_failures]. diff --git a/src/mod_http_bind.erl b/src/mod_http_bind.erl index 773ef241f..1c772ce17 100644 --- a/src/mod_http_bind.erl +++ b/src/mod_http_bind.erl @@ -37,7 +37,7 @@ -behaviour(gen_mod). --export([start/2, stop/1, process/2]). +-export([start/2, stop/1, process/2, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -142,3 +142,9 @@ migrate_database() -> %% of actually migrating data, let's just destroy the table mnesia:delete_table(http_bind) end. + +mod_opt_type(max_inactivity) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(max_pause) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(_) -> [max_inactivity, max_pause]. diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index 97738355e..68ebf8835 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -43,8 +43,7 @@ %% request_handlers callbacks -export([process/2]). -%% ejabberd_hooks callbacks --export([reopen_log/1]). +-export([reopen_log/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -448,3 +447,17 @@ ip_to_string(Address) when size(Address) == 4 -> ip_to_string(Address) when size(Address) == 8 -> Parts = lists:map(fun (Int) -> io_lib:format("~.16B", [Int]) end, tuple_to_list(Address)), string:to_lower(lists:flatten(join(Parts, ":"))). + +mod_opt_type(accesslog) -> fun iolist_to_binary/1; +mod_opt_type(content_types) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(custom_headers) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(default_content_type) -> + fun iolist_to_binary/1; +mod_opt_type(directory_indices) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(docroot) -> fun (A) -> A end; +mod_opt_type(_) -> + [accesslog, content_types, custom_headers, + default_content_type, directory_indices, docroot]. diff --git a/src/mod_ip_blacklist.erl b/src/mod_ip_blacklist.erl index 6225343c0..b0777d28e 100644 --- a/src/mod_ip_blacklist.erl +++ b/src/mod_ip_blacklist.erl @@ -36,8 +36,7 @@ -export([update_bl_c2s/0]). -%% Hooks: --export([is_ip_in_c2s_blacklist/3]). +-export([is_ip_in_c2s_blacklist/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -129,3 +128,5 @@ is_ip_in_c2s_blacklist(_Val, _IP, _Lang) -> false. %% - For now, we do not kick user already logged on a given IP after %% we update the blacklist. + +mod_opt_type(_) -> []. diff --git a/src/mod_irc.erl b/src/mod_irc.erl index e96fc4dc1..255118483 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -35,9 +35,9 @@ -export([start_link/2, start/2, stop/1, export/1, import/1, import/3, closed_connection/3, get_connection_params/3]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1345,3 +1345,12 @@ import(_LServer, riak, #irc_custom{} = R) -> ejabberd_riak:put(R, irc_custom_schema()); import(_, _, _) -> pass. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(default_encoding) -> + fun iolist_to_binary/1; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(_) -> + [access, db_type, default_encoding, host]. diff --git a/src/mod_last.erl b/src/mod_last.erl index 4e96526e7..8904f78ce 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -25,6 +25,8 @@ -module(mod_last). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -protocol({xep, 12, '2.0'}). @@ -32,9 +34,10 @@ -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, export/1, - process_sm_iq/3, on_presence_update/4, import/1, import/3, - store_last_info/4, get_last_info/2, remove_user/2, - transform_options/1]). + process_sm_iq/3, on_presence_update/4, import/1, + import/3, store_last_info/4, get_last_info/2, + remove_user/2, transform_options/1, mod_opt_type/1, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -351,3 +354,11 @@ transform_options({node_start, {_, _, _} = Now}, Opts) -> [{node_start, now_to_seconds(Now)}|Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [db_type, iqdisc]. + +opt_type(node_start) -> + fun (S) when is_integer(S), S >= 0 -> S end; +opt_type(_) -> [node_start]. diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 0d9ed9750..81d232be7 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -50,9 +50,9 @@ import/3, can_use_nick/4]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1343,3 +1343,29 @@ import(_LServer, riak, [{'2i', [{<<"nick_host">>, {Nick, Host}}]}]); import(_, _, _) -> pass. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(access_admin) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(access_create) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(access_persistent) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(default_room_options) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(history_size) -> + fun (I) when is_integer(I), I >= 0 -> I end; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(max_room_id) -> + fun (infinity) -> infinity; + (I) when is_integer(I), I > 0 -> I + end; +mod_opt_type(persist_history) -> fun (X) -> X end; +mod_opt_type(room_shaper) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(_) -> + [access, access_admin, access_create, access_persistent, + db_type, default_room_options, history_size, host, + max_room_id, persist_history, room_shaper]. diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 1f8efe241..371b5e415 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -11,24 +11,16 @@ -behaviour(gen_mod). --export([ - start/2, stop/1, % gen_mod API - muc_online_rooms/1, - muc_unregister_nick/1, - create_room/3, destroy_room/3, +-export([start/2, stop/1, muc_online_rooms/1, + muc_unregister_nick/1, create_room/3, destroy_room/3, create_rooms_file/1, destroy_rooms_file/1, rooms_unused_list/2, rooms_unused_destroy/2, - get_user_rooms/2, - get_room_occupants/2, - get_room_occupants_number/2, - send_direct_invitation/4, - change_room_option/4, - get_room_options/2, - set_room_affiliation/4, - get_room_affiliations/2, - web_menu_main/2, web_page_main/2, % Web Admin API - web_menu_host/3, web_page_host/3 - ]). + get_user_rooms/2, get_room_occupants/2, + get_room_occupants_number/2, send_direct_invitation/4, + change_room_option/4, get_room_options/2, + set_room_affiliation/4, get_room_affiliations/2, + web_menu_main/2, web_page_main/2, web_menu_host/3, + web_page_host/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -918,3 +910,5 @@ find_host(ServerHost) when is_list(ServerHost) -> find_host(list_to_binary(ServerHost)); find_host(ServerHost) -> gen_mod:get_module_opt_host(ServerHost, mod_muc, <<"conference.@HOST@">>). + +mod_opt_type(_) -> []. diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index d94151418..14aef01e9 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -25,6 +25,8 @@ -module(mod_muc_log). +-behaviour(ejabberd_config). + -author('badlop@process-one.net'). -behaviour(gen_server). @@ -35,9 +37,9 @@ -export([start_link/2, start/2, stop/1, transform_module_options/1, check_access_log/2, add_to_log/5]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1252,3 +1254,44 @@ calc_hour_offset(TimeHere) -> fjoin(FileList) -> list_to_binary(filename:join([binary_to_list(File) || File <- FileList])). + +mod_opt_type(access_log) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(cssfile) -> fun iolist_to_binary/1; +mod_opt_type(dirname) -> + fun (room_jid) -> room_jid; + (room_name) -> room_name + end; +mod_opt_type(dirtype) -> + fun (subdirs) -> subdirs; + (plain) -> plain + end; +mod_opt_type(file_format) -> + fun (html) -> html; + (plaintext) -> plaintext + end; +mod_opt_type(file_permissions) -> + fun (SubOpts) -> + F = fun ({mode, Mode}, {_M, G}) -> {Mode, G}; + ({group, Group}, {M, _G}) -> {M, Group} + end, + lists:foldl(F, {644, 33}, SubOpts) + end; +mod_opt_type(outdir) -> fun iolist_to_binary/1; +mod_opt_type(spam_prevention) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(timezone) -> + fun (local) -> local; + (universal) -> universal + end; +mod_opt_type(top_link) -> + fun ([{S1, S2}]) -> + {iolist_to_binary(S1), iolist_to_binary(S2)} + end; +mod_opt_type(_) -> + [access_log, cssfile, dirname, dirtype, file_format, + file_permissions, outdir, spam_prevention, timezone, + top_link]. + +opt_type(language) -> fun iolist_to_binary/1; +opt_type(_) -> [language]. diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index b6699d103..b39a391be 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -22,7 +22,7 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). --export([purge_loop/1]). +-export([purge_loop/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1162,3 +1162,10 @@ make_reply(forbidden, Lang, ErrText) -> stj(String) -> jlib:string_to_jid(String). jts(String) -> jlib:jid_to_string(String). + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(limits) -> + fun (A) when is_list(A) -> A end; +mod_opt_type(_) -> [access, host, limits]. diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 7c18a7f98..280f39f6c 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -57,9 +57,9 @@ webadmin_user/4, webadmin_user_parse_query/5]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1140,3 +1140,11 @@ import(_LServer, riak, #offline_msg{us = US, timestamp = TS} = M) -> [{i, TS}, {'2i', [{<<"us">>, US}]}]); import(_, _, _) -> pass. + +mod_opt_type(access_max_user_messages) -> + fun (A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(store_empty_body) -> + fun (V) when is_boolean(V) -> V end; +mod_opt_type(_) -> + [access_max_user_messages, db_type, store_empty_body]. diff --git a/src/mod_ping.erl b/src/mod_ping.erl index 9ba9833ee..0b332edec 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -56,9 +56,8 @@ -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2, code_change/3]). -%% Hook callbacks -export([iq_ping/3, user_online/3, user_offline/3, - user_send/3]). + user_send/3, mod_opt_type/1]). -record(state, {host = <<"">>, @@ -246,3 +245,15 @@ cancel_timer(TRef) -> receive {timeout, TRef, _} -> ok after 0 -> ok end; _ -> ok end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(ping_interval) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(send_pings) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(timeout_action) -> + fun (none) -> none; + (kill) -> kill + end; +mod_opt_type(_) -> + [iqdisc, ping_interval, send_pings, timeout_action]. diff --git a/src/mod_pres_counter.erl b/src/mod_pres_counter.erl index e904ab95f..840c3aaea 100644 --- a/src/mod_pres_counter.erl +++ b/src/mod_pres_counter.erl @@ -27,7 +27,8 @@ -behavior(gen_mod). --export([start/2, stop/1, check_packet/6]). +-export([start/2, stop/1, check_packet/6, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -119,3 +120,9 @@ update(Server, JID, Dir) -> read(K) -> get({pres_counter, K}). write(K, V) -> put({pres_counter, K}, V). + +mod_opt_type(count) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(interval) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(_) -> [count, interval]. diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 35c3ed93b..81ea3dfcf 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -37,15 +37,14 @@ raw_to_item/1, is_list_needdb/1, updated_list/3, item_to_xml/1, get_user_lists/2, import/3]). -%% For mod_blocking -export([sql_add_privacy_list/2, sql_get_default_privacy_list/2, sql_get_default_privacy_list_t/1, sql_get_privacy_list_data/3, sql_get_privacy_list_data_by_id_t/1, sql_get_privacy_list_id_t/2, - sql_set_default_privacy_list/2, - sql_set_privacy_list/2, privacy_schema/0]). + sql_set_default_privacy_list/2, sql_set_privacy_list/2, + privacy_schema/0, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1257,3 +1256,7 @@ import(_LServer, riak, #privacy{} = P) -> ejabberd_riak:put(P, privacy_schema()); import(_, _, _) -> pass. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [db_type, iqdisc]. diff --git a/src/mod_private.erl b/src/mod_private.erl index 09182ded6..56d4b4937 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -32,7 +32,8 @@ -behaviour(gen_mod). -export([start/2, stop/1, process_sm_iq/3, import/3, - remove_user/2, get_data/2, export/1, import/1]). + remove_user/2, get_data/2, export/1, import/1, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -321,3 +322,7 @@ import(_LServer, riak, #private_storage{usns = {LUser, LServer, _}} = PS) -> [{'2i', [{<<"us">>, {LUser, LServer}}]}]); import(_, _, _) -> pass. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [db_type, iqdisc]. diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl index effe2f784..621189db2 100644 --- a/src/mod_proxy65.erl +++ b/src/mod_proxy65.erl @@ -39,8 +39,7 @@ %% supervisor callbacks. -export([init/1]). -%% API. --export([start_link/2]). +-export([start_link/2, mod_opt_type/1]). -define(PROCNAME, ejabberd_mod_proxy65). @@ -84,3 +83,5 @@ init([Host, Opts]) -> {ok, {{one_for_one, 10, 1}, [StreamManager, StreamSupervisor, Service]}}. + +mod_opt_type(_) -> []. diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 1e7735c58..32cd4443d 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -33,9 +33,9 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -%% API. --export([start_link/2, add_listener/2, transform_module_options/1, - delete_listener/1]). +-export([start_link/2, add_listener/2, + transform_module_options/1, delete_listener/1, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -292,3 +292,19 @@ get_my_ip() -> {ok, Addr} -> Addr; {error, _} -> {127, 0, 0, 1} end. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(hostname) -> fun iolist_to_binary/1; +mod_opt_type(ip) -> + fun (S) -> + {ok, Addr} = + inet_parse:address(binary_to_list(iolist_to_binary(S))), + Addr + end; +mod_opt_type(name) -> fun iolist_to_binary/1; +mod_opt_type(port) -> + fun (P) when is_integer(P), P > 0, P < 65536 -> P end; +mod_opt_type(_) -> + [access, host, hostname, ip, name, port]. diff --git a/src/mod_proxy65_sm.erl b/src/mod_proxy65_sm.erl index 367f7f0bd..895dd7d57 100644 --- a/src/mod_proxy65_sm.erl +++ b/src/mod_proxy65_sm.erl @@ -33,9 +33,9 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -%% API. -export([start_link/2, register_stream/1, - unregister_stream/1, activate_stream/4]). + unregister_stream/1, activate_stream/4, + mod_opt_type/1]). -record(state, {max_connections = infinity :: non_neg_integer() | infinity}). @@ -171,3 +171,9 @@ activate_stream(SHA1, IJid, TJid, Host) {atomic, false} -> false; _ -> error end. + +mod_opt_type(max_connections) -> + fun (I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end; +mod_opt_type(_) -> [max_connections]. diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl index 663fbf729..972faa76b 100644 --- a/src/mod_proxy65_stream.erl +++ b/src/mod_proxy65_stream.erl @@ -37,9 +37,8 @@ wait_for_request/2, wait_for_activation/2, stream_established/2]). -%% API. -export([start/2, stop/1, start_link/3, activate/2, - relay/3, socket_type/0]). + relay/3, socket_type/0, mod_opt_type/1]). -include("mod_proxy65.hrl"). @@ -289,3 +288,15 @@ find_maxrate(Shaper, JID1, JID2, Host) -> if MaxRate1 == none; MaxRate2 == none -> none; true -> lists:max([MaxRate1, MaxRate2]) end. + +mod_opt_type(auth_type) -> + fun (plain) -> plain; + (anonymous) -> anonymous + end; +mod_opt_type(recbuf) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(shaper) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(sndbuf) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(_) -> [auth_type, recbuf, shaper, sndbuf]. diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 1f625cd5d..a5e90531c 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -89,8 +89,7 @@ handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -%% calls for parallel sending of last items --export([send_loop/1]). +-export([send_loop/1, mod_opt_type/1]). -define(PROCNAME, ejabberd_mod_pubsub). -define(LOOPNAME, ejabberd_mod_pubsub_loop). @@ -4347,3 +4346,25 @@ purge_offline(Host, LJID, Node) -> Error -> Error end. + +mod_opt_type(access_createnode) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(ignore_pep_from_offline) -> + fun (A) when is_boolean(A) -> A end; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(last_item_cache) -> + fun (A) when is_boolean(A) -> A end; +mod_opt_type(max_items_node) -> + fun (A) when is_integer(A) andalso A >= 0 -> A end; +mod_opt_type(nodetree) -> + fun (A) when is_binary(A) -> A end; +mod_opt_type(pep_mapping) -> + fun (A) when is_list(A) -> A end; +mod_opt_type(plugins) -> + fun (A) when is_list(A) -> A end; +mod_opt_type(_) -> + [access_createnode, db_type, host, + ignore_pep_from_offline, iqdisc, last_item_cache, + max_items_node, nodetree, pep_mapping, plugins]. diff --git a/src/mod_register.erl b/src/mod_register.erl index 1ed950146..bb2a8fbe9 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -25,6 +25,8 @@ -module(mod_register). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -protocol({xep, 77, '2.4'}). @@ -34,7 +36,8 @@ -export([start/2, stop/1, stream_feature_register/2, unauthenticated_iq_register/4, try_register/5, process_iq/3, send_registration_notifications/3, - transform_options/1, transform_module_options/1]). + transform_options/1, transform_module_options/1, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -687,3 +690,37 @@ check_ip_access(undefined, _IPAccess) -> deny; check_ip_access(IPAddress, IPAccess) -> acl:match_rule(global, IPAccess, IPAddress). + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(access_from) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(captcha_protected) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(ip_access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(password_strength) -> + fun (N) when is_number(N), N >= 0 -> N end; +mod_opt_type(registration_watchers) -> + fun (Ss) -> + [#jid{} = jlib:string_to_jid(iolist_to_binary(S)) + || S <- Ss] + end; +mod_opt_type(welcome_message) -> + fun (Opts) -> + S = proplists:get_value(subject, Opts, <<>>), + B = proplists:get_value(body, Opts, <<>>), + {iolist_to_binary(S), iolist_to_binary(B)} + end; +mod_opt_type(_) -> + [access, access_from, captcha_protected, ip_access, + iqdisc, password_strength, registration_watchers, + welcome_message]. + +opt_type(registration_timeout) -> + fun (TO) when is_integer(TO), TO > 0 -> TO; + (infinity) -> infinity; + (unlimited) -> infinity + end; +opt_type(_) -> [registration_timeout]. diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index b9f799b41..32e06f142 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -55,7 +55,7 @@ -behaviour(gen_mod). --export([start/2, stop/1, process/2]). +-export([start/2, stop/1, process/2, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -574,3 +574,5 @@ get_error_text({error, passwords_not_identical}) -> <<"The passwords are different">>; get_error_text({error, wrong_parameters}) -> <<"Wrong parameters in the web formulary">>. + +mod_opt_type(_) -> []. diff --git a/src/mod_roster.erl b/src/mod_roster.erl index aa214b421..31fbeb1d2 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -41,15 +41,16 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_iq/3, export/1, import/1, - process_local_iq/3, get_user_roster/2, import/3, - get_subscription_lists/3, get_roster/2, +-export([start/2, stop/1, process_iq/3, export/1, + import/1, process_local_iq/3, get_user_roster/2, + import/3, get_subscription_lists/3, get_roster/2, get_in_pending_subscriptions/3, in_subscription/6, out_subscription/4, set_items/3, remove_user/2, get_jid_info/4, item_to_xml/1, webadmin_page/3, webadmin_user/4, get_versioning_feature/2, roster_versioning_enabled/1, roster_version/2, - record_to_string/1, groups_to_string/1]). + record_to_string/1, groups_to_string/1, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1767,3 +1768,17 @@ import(_LServer, riak, #roster_version{} = RV) -> ejabberd_riak:put(RV, roster_version_schema()); import(_, _, _) -> pass. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(managers) -> + fun (B) when is_list(B) -> B end; +mod_opt_type(store_current_id) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(versioning) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> + [access, db_type, iqdisc, managers, store_current_id, + versioning]. diff --git a/src/mod_service_log.erl b/src/mod_service_log.erl index 7a23b4013..e145c5ce6 100644 --- a/src/mod_service_log.erl +++ b/src/mod_service_log.erl @@ -29,10 +29,8 @@ -behaviour(gen_mod). --export([start/2, - stop/1, - log_user_send/3, - log_user_receive/4]). +-export([start/2, stop/1, log_user_send/3, + log_user_receive/4, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -95,3 +93,14 @@ log_packet(From, To, [FixedPacket]}) end, Loggers). + +mod_opt_type(loggers) -> + fun (L) -> + lists:map(fun (S) -> + B = iolist_to_binary(S), + N = jlib:nameprep(B), + if N /= error -> N end + end, + L) + end; +mod_opt_type(_) -> [loggers]. diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 4c3f177ef..ac285bfd9 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -29,16 +29,17 @@ -behaviour(gen_mod). --export([start/2, stop/1, item_to_xml/1, export/1, import/1, - webadmin_menu/3, webadmin_page/3, get_user_roster/2, - get_subscription_lists/3, get_jid_info/4, import/3, - process_item/2, in_subscription/6, out_subscription/4, - user_available/1, unset_presence/4, register_user/2, - remove_user/2, list_groups/1, create_group/2, - create_group/3, delete_group/2, get_group_opts/2, - set_group_opts/3, get_group_users/2, - get_group_explicit_users/2, is_user_in_group/3, - add_user_to_group/3, remove_user_from_group/3]). +-export([start/2, stop/1, item_to_xml/1, export/1, + import/1, webadmin_menu/3, webadmin_page/3, + get_user_roster/2, get_subscription_lists/3, + get_jid_info/4, import/3, process_item/2, + in_subscription/6, out_subscription/4, user_available/1, + unset_presence/4, register_user/2, remove_user/2, + list_groups/1, create_group/2, create_group/3, + delete_group/2, get_group_opts/2, set_group_opts/3, + get_group_users/2, get_group_explicit_users/2, + is_user_in_group/3, add_user_to_group/3, + remove_user_from_group/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1506,3 +1507,6 @@ import(_LServer, riak, #sr_user{us = US, group_host = {Group, Host}} = User) -> {<<"group_host">>, {Group, Host}}]}]); import(_, _, _) -> pass. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [db_type]. diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index a2d6f2fff..653c83ee2 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -26,6 +26,8 @@ %%%------------------------------------------------------------------- -module(mod_shared_roster_ldap). +-behaviour(ejabberd_config). + -behaviour(gen_server). -behaviour(gen_mod). @@ -39,7 +41,7 @@ -export([get_user_roster/2, get_subscription_lists/3, get_jid_info/4, process_item/2, in_subscription/6, - out_subscription/4]). + out_subscription/4, mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -599,3 +601,99 @@ check_filter(F) -> NewF = iolist_to_binary(F), {ok, _} = eldap_filter:parse(NewF), NewF. + +mod_opt_type(deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_backups) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_base) -> fun iolist_to_binary/1; +mod_opt_type(ldap_deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +mod_opt_type(ldap_password) -> fun iolist_to_binary/1; +mod_opt_type(ldap_port) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; +mod_opt_type(ldap_servers) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_tls_cacertfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_certfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I end; +mod_opt_type(ldap_tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +mod_opt_type(ldap_auth_check) -> + fun (on) -> true; + (off) -> false; + (false) -> false; + (true) -> true + end; +mod_opt_type(ldap_filter) -> fun check_filter/1; +mod_opt_type(ldap_gfilter) -> fun check_filter/1; +mod_opt_type(ldap_group_cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_group_cache_validity) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_groupattr) -> fun iolist_to_binary/1; +mod_opt_type(ldap_groupdesc) -> fun iolist_to_binary/1; +mod_opt_type(ldap_memberattr) -> fun iolist_to_binary/1; +mod_opt_type(ldap_memberattr_format) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_memberattr_format_re) -> + fun (S) -> + Re = iolist_to_binary(S), {ok, MP} = re:compile(Re), MP + end; +mod_opt_type(ldap_rfilter) -> fun check_filter/1; +mod_opt_type(ldap_ufilter) -> fun check_filter/1; +mod_opt_type(ldap_user_cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_user_cache_validity) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_userdesc) -> fun iolist_to_binary/1; +mod_opt_type(ldap_useruid) -> fun iolist_to_binary/1; +mod_opt_type(_) -> + [ldap_auth_check, ldap_filter, ldap_gfilter, + ldap_group_cache_size, ldap_group_cache_validity, + ldap_groupattr, ldap_groupdesc, ldap_memberattr, + ldap_memberattr_format, ldap_memberattr_format_re, + ldap_rfilter, ldap_ufilter, ldap_user_cache_size, + ldap_user_cache_validity, ldap_userdesc, ldap_useruid, + deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, + ldap_tls_verify]. + +opt_type(ldap_filter) -> fun check_filter/1; +opt_type(ldap_gfilter) -> fun check_filter/1; +opt_type(ldap_group_cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(ldap_group_cache_validity) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(ldap_rfilter) -> fun check_filter/1; +opt_type(ldap_ufilter) -> fun check_filter/1; +opt_type(ldap_user_cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(ldap_user_cache_validity) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(_) -> + [ldap_filter, ldap_gfilter, ldap_group_cache_size, + ldap_group_cache_validity, ldap_rfilter, ldap_ufilter, + ldap_user_cache_size, ldap_user_cache_validity]. diff --git a/src/mod_sic.erl b/src/mod_sic.erl index 273930ff0..3f5bf0dab 100644 --- a/src/mod_sic.erl +++ b/src/mod_sic.erl @@ -32,7 +32,7 @@ -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, - process_sm_iq/3]). + process_sm_iq/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -91,3 +91,6 @@ get_ip({User, Server, Resource}, IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_sip.erl b/src/mod_sip.erl index 8790cdfc0..7e7d2f307 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -32,9 +32,9 @@ %% API -export([start/2, stop/1, make_response/2, is_my_host/1, at_my_host/1]). -%% esip_callbacks --export([data_in/2, data_out/2, message_in/2, message_out/2, - request/2, request/3, response/2, locate/1]). +-export([data_in/2, data_out/2, message_in/2, + message_out/2, request/2, request/3, response/2, + locate/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -299,3 +299,44 @@ at_my_host(#uri{host = Host}) -> is_my_host(LServer) -> gen_mod:is_loaded(LServer, ?MODULE). + +mod_opt_type(always_record_route) -> + fun (true) -> true; + (false) -> false + end; +mod_opt_type(flow_timeout_tcp) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(flow_timeout_udp) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(record_route) -> + fun (IOList) -> + S = iolist_to_binary(IOList), + #uri{} = esip:decode_uri(S) + end; +mod_opt_type(routes) -> + fun (L) -> + lists:map(fun (IOList) -> + S = iolist_to_binary(IOList), + #uri{} = esip:decode_uri(S) + end, + L) + end; +mod_opt_type(via) -> + fun (L) -> + lists:map(fun (Opts) -> + Type = proplists:get_value(type, Opts), + Host = proplists:get_value(host, Opts), + Port = proplists:get_value(port, Opts), + true = (Type == tcp) or (Type == tls) or + (Type == udp), + true = is_binary(Host) and (Host /= <<"">>), + true = is_integer(Port) and (Port > 0) and + (Port < 65536) + or (Port == undefined), + {Type, {Host, Port}} + end, + L) + end; +mod_opt_type(_) -> + [always_record_route, flow_timeout_tcp, + flow_timeout_udp, record_route, routes, via]. diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl index 6168d997c..1dcf264ed 100644 --- a/src/mod_sip_proxy.erl +++ b/src/mod_sip_proxy.erl @@ -25,16 +25,18 @@ %%%------------------------------------------------------------------- -module(mod_sip_proxy). +-behaviour(ejabberd_config). + -define(GEN_FSM, p1_fsm). -behaviour(?GEN_FSM). %% API -export([start/2, start_link/2, route/3, route/4]). -%% gen_fsm callbacks --export([init/1, wait_for_request/2, wait_for_response/2, - handle_event/3, handle_sync_event/4, - handle_info/3, terminate/3, code_change/4]). +-export([init/1, wait_for_request/2, + wait_for_response/2, handle_event/3, + handle_sync_event/4, handle_info/3, terminate/3, + code_change/4, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -456,3 +458,7 @@ safe_nameprep(S) -> error -> S; S1 -> S1 end. + +opt_type(domain_certfile) -> fun iolist_to_binary/1; +opt_type(shared_key) -> fun (V) -> V end; +opt_type(_) -> [domain_certfile, shared_key]. diff --git a/src/mod_stats.erl b/src/mod_stats.erl index 4896a3c18..ce97dbdf0 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -31,7 +31,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -265,3 +266,6 @@ search_running_node(SNode, [Node | Nodes]) -> SNode -> Node; _ -> search_running_node(SNode, Nodes) end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_time.erl b/src/mod_time.erl index 111428070..e11468400 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -32,7 +32,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -84,3 +85,6 @@ process_local_iq(_From, _To, sign(N) when N < 0 -> <<"-">>; sign(_) -> <<"+">>. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 2c700af2f..306bd8445 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -34,7 +34,8 @@ -export([start/2, init/3, stop/1, get_sm_features/5, process_local_iq/3, process_sm_iq/3, reindex_vcards/0, - remove_user/2, export/1, import/1, import/3]). + remove_user/2, export/1, import/1, import/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1162,3 +1163,20 @@ import(_LServer, riak, #vcard_search{}) -> ok; import(_, _, _) -> pass. + +mod_opt_type(allow_return_all) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(matches) -> + fun (infinity) -> infinity; + (I) when is_integer(I), I > 0 -> I + end; +mod_opt_type(search) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(search_all_hosts) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> + [allow_return_all, db_type, host, iqdisc, matches, + search, search_all_hosts]. diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index a5cafc5e5..f75bb0712 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -25,6 +25,8 @@ -module(mod_vcard_ldap). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -37,7 +39,8 @@ -export([start/2, start_link/2, stop/1, get_sm_features/5, process_local_iq/3, process_sm_iq/3, - remove_user/1, route/4, transform_module_options/1]). + remove_user/1, route/4, transform_module_options/1, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -840,3 +843,100 @@ check_filter(F) -> NewF = iolist_to_binary(F), {ok, _} = eldap_filter:parse(NewF), NewF. + +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(ldap_filter) -> fun check_filter/1; +mod_opt_type(ldap_search_fields) -> + fun (Ls) -> + [{iolist_to_binary(S), iolist_to_binary(P)} + || {S, P} <- Ls] + end; +mod_opt_type(ldap_search_reported) -> + fun (Ls) -> + [{iolist_to_binary(S), iolist_to_binary(P)} + || {S, P} <- Ls] + end; +mod_opt_type(ldap_uids) -> + fun (Us) -> + lists:map(fun ({U, P}) -> + {iolist_to_binary(U), iolist_to_binary(P)}; + ({U}) -> {iolist_to_binary(U)} + end, + Us) + end; +mod_opt_type(ldap_vcard_map) -> + fun (Ls) -> + lists:map(fun ({S, [{P, L}]}) -> + {iolist_to_binary(S), iolist_to_binary(P), + [iolist_to_binary(E) || E <- L]} + end, + Ls) + end; +mod_opt_type(matches) -> + fun (infinity) -> 0; + (I) when is_integer(I), I > 0 -> I + end; +mod_opt_type(search) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_backups) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_base) -> fun iolist_to_binary/1; +mod_opt_type(ldap_deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +mod_opt_type(ldap_password) -> fun iolist_to_binary/1; +mod_opt_type(ldap_port) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; +mod_opt_type(ldap_servers) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_tls_cacertfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_certfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I end; +mod_opt_type(ldap_tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +mod_opt_type(_) -> + [host, iqdisc, ldap_filter, ldap_search_fields, + ldap_search_reported, ldap_uids, ldap_vcard_map, + matches, search, deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, + ldap_tls_verify]. + +opt_type(ldap_filter) -> fun check_filter/1; +opt_type(ldap_uids) -> + fun (Us) -> + lists:map(fun ({U, P}) -> + {iolist_to_binary(U), iolist_to_binary(P)}; + ({U}) -> {iolist_to_binary(U)} + end, + Us) + end; +opt_type(_) -> + [ldap_filter, ldap_uids, deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, + ldap_tls_verify]. diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index 41a07bbc3..96ee09d87 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -12,8 +12,8 @@ %% gen_mod callbacks -export([start/2, stop/1]). -%% hooks --export([update_presence/3, vcard_set/3, export/1, import/1, import/3]). +-export([update_presence/3, vcard_set/3, export/1, + import/1, import/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -231,3 +231,6 @@ import(_LServer, riak, #vcard_xupdate{} = R) -> ejabberd_riak:put(R, vcard_xupdate_schema()); import(_, _, _) -> pass. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [db_type]. diff --git a/src/mod_version.erl b/src/mod_version.erl index 669a401d4..55609d1ea 100644 --- a/src/mod_version.erl +++ b/src/mod_version.erl @@ -31,7 +31,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -90,3 +91,8 @@ get_os() -> OS = <>, #xmlel{name = <<"os">>, attrs = [], children = [{xmlcdata, OS}]}. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(show_os) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> [iqdisc, show_os]. diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index 7dee1a047..6d76610af 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -25,41 +25,38 @@ -module(odbc_queries). +-behaviour(ejabberd_config). + -author("mremond@process-one.net"). --export([get_db_type/0, update/5, update_t/4, sql_transaction/2, - get_last/2, set_last_t/4, del_last/2, - get_password/2, get_password_scram/2, - set_password_t/3, set_password_scram_t/6, - add_user/3, add_user_scram/6, del_user/2, - del_user_return_password/3, list_users/1, list_users/2, - users_number/1, users_number/2, add_spool_sql/2, - add_spool/2, get_and_del_spool_msg_t/2, del_spool_msg/2, - get_roster/2, get_roster_jid_groups/2, +-export([get_db_type/0, update/5, update_t/4, + sql_transaction/2, get_last/2, set_last_t/4, del_last/2, + get_password/2, get_password_scram/2, set_password_t/3, + set_password_scram_t/6, add_user/3, add_user_scram/6, + del_user/2, del_user_return_password/3, list_users/1, + list_users/2, users_number/1, users_number/2, + add_spool_sql/2, add_spool/2, get_and_del_spool_msg_t/2, + del_spool_msg/2, get_roster/2, get_roster_jid_groups/2, get_roster_groups/3, del_user_roster_t/2, get_roster_by_jid/3, get_rostergroup_by_jid/3, del_roster/3, del_roster_sql/2, update_roster/5, update_roster_sql/4, roster_subscribe/4, get_subscription/3, set_private_data/4, - set_private_data_sql/3, get_private_data/3, get_private_data/2, - del_user_private_storage/2, get_default_privacy_list/2, + set_private_data_sql/3, get_private_data/3, + get_private_data/2, del_user_private_storage/2, + get_default_privacy_list/2, get_default_privacy_list_t/1, get_privacy_list_names/2, get_privacy_list_names_t/1, get_privacy_list_id/3, get_privacy_list_id_t/2, get_privacy_list_data/3, - get_privacy_list_data_by_id/2, get_privacy_list_data_t/2, + get_privacy_list_data_by_id/2, + get_privacy_list_data_t/2, get_privacy_list_data_by_id_t/1, set_default_privacy_list/2, - unset_default_privacy_list/2, - remove_privacy_list/2, - add_privacy_list/2, - set_privacy_list/2, - del_privacy_lists/3, - set_vcard/26, - get_vcard/2, - escape/1, - count_records_where/3, - get_roster_version/2, - set_roster_version/2]). + unset_default_privacy_list/2, remove_privacy_list/2, + add_privacy_list/2, set_privacy_list/2, + del_privacy_lists/3, set_vcard/26, get_vcard/2, + escape/1, count_records_where/3, get_roster_version/2, + set_roster_version/2, opt_type/1]). %% We have only two compile time options for db queries: %-define(generic, true). @@ -990,3 +987,13 @@ set_roster_version(Username, Version) -> <<"', '">>, Version, <<"'">>]). -endif. + +opt_type(odbc_type) -> + fun (pgsql) -> pgsql; + (mysql) -> mysql; + (sqlite) -> sqlite; + (odbc) -> odbc + end; +opt_type(pgsql_users_number_estimate) -> + fun (V) when is_boolean(V) -> V end; +opt_type(_) -> [odbc_type, pgsql_users_number_estimate]. diff --git a/src/shaper.erl b/src/shaper.erl index a85c4f111..c8140703c 100644 --- a/src/shaper.erl +++ b/src/shaper.erl @@ -25,10 +25,13 @@ -module(shaper). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). --export([start/0, new/1, new1/1, update/2, get_max_rate/1, - transform_options/1, load_from_config/0]). +-export([start/0, new/1, new1/1, update/2, + get_max_rate/1, transform_options/1, load_from_config/0, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -140,3 +143,6 @@ transform_options(Opt, Opts) -> now_to_usec({MSec, Sec, USec}) -> (MSec * 1000000 + Sec) * 1000000 + USec. + +opt_type(shaper) -> fun (V) -> V end; +opt_type(_) -> [shaper]. -- cgit v1.2.3