]> granicus.if.org Git - ejabberd/commitdiff
Add config validation at startup
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Mon, 1 Jun 2015 12:38:27 +0000 (15:38 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Mon, 1 Jun 2015 12:38:27 +0000 (15:38 +0300)
90 files changed:
src/acl.erl
src/cyrsasl.erl
src/cyrsasl_digest.erl
src/ejabberd_app.erl
src/ejabberd_auth.erl
src/ejabberd_auth_anonymous.erl
src/ejabberd_auth_external.erl
src/ejabberd_auth_internal.erl
src/ejabberd_auth_ldap.erl
src/ejabberd_auth_odbc.erl
src/ejabberd_auth_pam.erl
src/ejabberd_c2s.erl
src/ejabberd_c2s_config.erl
src/ejabberd_captcha.erl
src/ejabberd_config.erl
src/ejabberd_ctl.erl
src/ejabberd_http.erl
src/ejabberd_http_ws.erl
src/ejabberd_listener.erl
src/ejabberd_node_groups.erl
src/ejabberd_odbc.erl
src/ejabberd_odbc_sup.erl
src/ejabberd_piefxis.erl
src/ejabberd_rdbms.erl
src/ejabberd_riak_sup.erl
src/ejabberd_router.erl
src/ejabberd_s2s.erl
src/ejabberd_s2s_in.erl
src/ejabberd_s2s_out.erl
src/ejabberd_service.erl
src/ejabberd_sm.erl
src/ejabberd_sm_redis.erl
src/ejabberd_stun.erl
src/ejabberd_system_monitor.erl
src/ejabberd_web_admin.erl
src/ejabberd_xmlrpc.erl
src/ejd2odbc.erl
src/eldap.erl
src/eldap_utils.erl
src/ext_mod.erl
src/extauth.erl
src/gen_mod.erl
src/mod_adhoc.erl
src/mod_admin_extra.erl
src/mod_announce.erl
src/mod_blocking.erl
src/mod_caps.erl
src/mod_carboncopy.erl
src/mod_client_state.erl
src/mod_configure.erl
src/mod_configure2.erl
src/mod_disco.erl
src/mod_echo.erl
src/mod_fail2ban.erl
src/mod_http_bind.erl
src/mod_http_fileserver.erl
src/mod_ip_blacklist.erl
src/mod_irc.erl
src/mod_last.erl
src/mod_muc.erl
src/mod_muc_admin.erl
src/mod_muc_log.erl
src/mod_multicast.erl
src/mod_offline.erl
src/mod_ping.erl
src/mod_pres_counter.erl
src/mod_privacy.erl
src/mod_private.erl
src/mod_proxy65.erl
src/mod_proxy65_service.erl
src/mod_proxy65_sm.erl
src/mod_proxy65_stream.erl
src/mod_pubsub.erl
src/mod_register.erl
src/mod_register_web.erl
src/mod_roster.erl
src/mod_service_log.erl
src/mod_shared_roster.erl
src/mod_shared_roster_ldap.erl
src/mod_sic.erl
src/mod_sip.erl
src/mod_sip_proxy.erl
src/mod_stats.erl
src/mod_time.erl
src/mod_vcard.erl
src/mod_vcard_ldap.erl
src/mod_vcard_xupdate.erl
src/mod_version.erl
src/odbc_queries.erl
src/shaper.erl

index 8d9692ffbd74eca699818f3b40f147f7efbfcc1b..021e4e2d43ab35941dae8b658a037bf83f5ddb18 100644 (file)
 
 -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].
index 764473bab09210e85f12c93524601d90999d5f02..970da5bb9bc1d21b92f08107f8309703ff05dba4 100644 (file)
 
 -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].
index 10f9641308d90c026aa8574f6b86b175895d0bf4..4b14bafd35a12f0499c39b9f29c849b12398783f 100644 (file)
 
 -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].
index daf8919a6fda696048653fb09456b9fa35d6e509..46fbf81dc9e456e91f6dd44344b4f68bff922ed2 100644 (file)
 %%%----------------------------------------------------------------------
 
 -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].
index 991cb664b91fd113bb353c4ce01fc74e1cf8ce7a..03c117b6c65f30fe5a4f4ef310fd5983d318f33f 100644 (file)
@@ -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].
index cb320dea5570ed1b8584df5c6ec87ea99d4b7362..c00fff0bd47bae15db0c9d3fe5b3ff0ad68ebf5f 100644 (file)
@@ -24,6 +24,8 @@
 %%%----------------------------------------------------------------------
 
 -module(ejabberd_auth_anonymous).
+
+-behaviour(ejabberd_config).
 -author('mickael.remond@process-one.net').
 
 -export([start/1,
         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].
index 0aa825f73bfdfecc49a080dfcc6c96ce482a4100..67477f27aafaf5d0eb48e338c683fca042ff060c 100644 (file)
 
 -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].
index fc128ac5a54fad21066607c9cb3d3ccd55cbb227..d7f2a5ae5af0155af584f1cd565aef7e71955b9b 100644 (file)
 
 -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].
index d08151e60e407da82ccfd552dc7292b4ce194475..f2122805aeaabdb62105e16c4776fd3d7c01ecdc 100644 (file)
@@ -25,6 +25,8 @@
 
 -module(ejabberd_auth_ldap).
 
+-behaviour(ejabberd_config).
+
 -author('alexey@process-one.net').
 
 -behaviour(gen_server).
 -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].
index 881b86ccad9d67e497ce6aafe006aa8652cbdb13..45ff4d7786c3da2c7ac2809d86891351e43b58a9 100644 (file)
 
 -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].
index f3fdf628dd4c024db1ffe233bf239308dd2d6ffa..312bcf46ecadbb49a9f9b5ed4712e37a896fba4e 100644 (file)
 %%%-------------------------------------------------------------------
 -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].
index b4cd285768741ae7f22cce2619c0b444a86c88d0..330660925fa6bd7f7a88f8ee45552853c412abcc 100644 (file)
@@ -25,6 +25,8 @@
 
 -module(ejabberd_c2s).
 
+-behaviour(ejabberd_config).
+
 -author('alexey@process-one.net').
 
 -protocol({xep, 78, '2.5'}).
         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].
index a971f0af4f7d0dc72d6b7b9248809660565b9dac..43bba6726caed282c48375f346a014bda957c5cc 100644 (file)
 
 -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].
index fc9f975f53a2427614d705a1651805e74a64f553..8a1de2ede8d2f4e2a272b4318e8271c523e9bcb3 100644 (file)
@@ -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].
index fb506377568d69e83a5776f2dd9d0bc126f926ba..efc70ed5789a03d257ba370a119b203ff32de9b4 100644 (file)
          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].
index 1eae7f758ed00911b8c4894cdedba3373af42735..82ac6b134f9fb2bbe6b8c3e1989c99818b1d1557 100644 (file)
 
 
 -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].
index 4e7f4b554ebd7cc97fbb4694912315f783233420..b4de38c02ee0450e497dcb457a4696a21839026d 100644 (file)
@@ -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].
index a0cc31e2a005b608ec609bc1d966d65143c2ada5..66a0542d4ac7f49f857f80f0924395b4903db2a6 100644 (file)
 %%%----------------------------------------------------------------------
 -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].
index 0cfca0aa0b2f481fb9f88001585608c321a94add..81256cc18529b98481cc414e74a1e137252e2fdd 100644 (file)
 %%%----------------------------------------------------------------------
 
 -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].
index da0bffe997dd0e3992146d0e3e31e799cd4a84e3..87942b7937b79d52189e4d5729e7650dee9f15e6 100644 (file)
@@ -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].
index dbae9f49b5c5c81a5fc18af6f9464a3d20565be2..eca781951f4b866f761b16e23b7d5086fa9b9ca7 100644 (file)
@@ -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].
index 37128e2657576f4b786b8f7916c8feb72b002902..4a1498964d5186d7f142f15dedbab8334f2972b1 100644 (file)
 
 -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].
index 61e6595e342569646e357a2a2770aa73856f1b51..3b29aeefe5a6759b788d64355ff551d3f0424309 100644 (file)
 
 -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].
index 93bd9fc494acabfdc114c0d14cb2277f793a21c7..23f1a857e1a4d407d94d5fed3a2170f1d434a3ca 100644 (file)
 
 -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].
index bb36eb44d1ef46334375c4bb62f320ace0d73c4a..8b6a8064ddb6725878febf1a662aef21498af579 100644 (file)
 %%%----------------------------------------------------------------------
 
 -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].
index 76ef71dc47754bc88120e4c8ccfd6d84d8f6c664..6a56a22eae27088bf35d107bc9a08ecfeaddfe41 100644 (file)
@@ -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].
index a7b3234fd5503837bce6e4a330bfc604fc0f0673..d6729dd46e09eeffff0150b7a0502bd8ba53622d 100644 (file)
@@ -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].
index 1b40f03c23085c156b17697764773fc1a629606a..067eb98b23f899ab97f85be9cc7342553ebf7365 100644 (file)
@@ -25,6 +25,8 @@
 
 -module(ejabberd_s2s_in).
 
+-behaviour(ejabberd_config).
+
 -author('alexey@process-one.net').
 
 -behaviour(p1_fsm).
 %% 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].
index 6196f136f2d92b8fed7f9107295be2fafab9b743..733dbe0a7035d00a30db0da6245ae3a3eb1a9444 100644 (file)
@@ -25,6 +25,8 @@
 
 -module(ejabberd_s2s_out).
 
+-behaviour(ejabberd_config).
+
 -author('alexey@process-one.net').
 
 -behaviour(p1_fsm).
         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].
index b7cea0c36ba2e57093c20ba83af2b1c9aabbccfb..3e283a0a211a8f8120d1b345d5f00b50eefdf219 100644 (file)
@@ -25,6 +25,8 @@
 
 -module(ejabberd_service).
 
+-behaviour(ejabberd_config).
+
 -author('alexey@process-one.net').
 
 -protocol({xep, 114, '1.6'}).
 -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].
index bfe6e934f95fb7d2b0c9e808e02fabbd81923e30..e259023744186bf13f67dc8788bd30f042d295e0 100644 (file)
@@ -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].
index 0283f9c3e33ed962c796936f49f2ca11d66363b7..a92845b81c21aabafb738a10735ee9def68fa8e8 100644 (file)
@@ -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].
index 9435f7e635d912481670f694fdc33786a47c213a..3d5ab6bd71caddaf8a29199605c33f13b2f721b1 100644 (file)
@@ -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].
index df8d9d51a44c8b29162f55b403d44c5057ab53bf..fe8c1d2bbbbe6473a5b3c23b90467703c74034f9 100644 (file)
@@ -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].
index 29ecb7346ea31293c3e27c5db42fe516a890c5a3..239c8bac556b31e032571717be9cb786866b7d39 100644 (file)
 
 -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].
index c852114506d91e1ec24db69500f0cd113775d4ea..0a74fd47b69c4b2b8ac65e7a006cac137e514631 100644 (file)
@@ -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].
index 9078148133275f73dba1e83194fb1bfda3c352ec..cc6241925e2547f7adf83f17f3dcaf2885487c84 100644 (file)
@@ -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].
index a9edebdf03c66a93430950f0e05b8fbbec8308a2..f8f6d04a99e8198411f722369ae540c965878174 100644 (file)
 
 -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].
index bdc98c202fd484b19c5ea7942a1e66243bdad503..3c475e20b764073d078adb0581474d5d9f423753 100644 (file)
 %%%----------------------------------------------------------------------
 
 -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,<<Unused,Bits/binary>>}|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].
index 473aeb4ebee107bdab1343454594f18241e9b577..bfc448dcfa1164401d6cd7cf594f1910d4630188 100644 (file)
 %%%----------------------------------------------------------------------
 
 -module(ext_mod).
+
+-behaviour(ejabberd_config).
 -author("Christophe Romain <christophe.romain@process-one.net>").
 
-%% 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].
index eb936ddf9539729aacfa643225aeaeb4832c7868..766d43340c05ca6a6bd05cfe0dad6f727ba86de5 100644 (file)
 
 -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].
index 29d5dfb784dd38be3f32d26421c16f40810a7279..2f9d3dd9ee553f0b472d59962f6b4c638fd0fe66 100644 (file)
@@ -1,7 +1,6 @@
 %%%----------------------------------------------------------------------
 %%% File    : gen_mod.erl
 %%% Author  : Alexey Shchepin <alexey@process-one.net>
-%%% Purpose : 
 %%% Purpose :
 %%% Created : 24 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
 %%%
 %%% 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]).
 
          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].
index db73ced54d46699c94e966313693af6e7dd1056d..f54804831712af3d31b4d67856aae31042bae093 100644 (file)
@@ -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].
index bc49bae47b472c5cc65310279439c667d56ad8c5..c213efe42211ee87fcfb0ff61bb2cd812cd7cfb6 100644 (file)
 
 -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].
index 542417ff378d73027d6cf389cf03be87a9024ce3..8049dd4f638dc74a9da42268d592fca1928b10e5 100644 (file)
 
 -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].
index 1d3bf3c3483f9c3e3fd6ae3ae72ba3d0b6707d25..609f1664c534a61c9cf2ed6c55320291ead7c509 100644 (file)
@@ -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].
index 10fe2943107dff8ce445d0767494f29738f9d507..f10ed66c7b5c89ea751b384f2c6a529d04817887 100644 (file)
 -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].
index be9e30f9c3f760965d940d918e6bad02a86c7da1..2cc495aecde90cd68de8ded45f6d032276c0f788 100644 (file)
 -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].
index c5041ed04c980015f7ce2e540313147046b55273..1287d5687b512ba4085c6205581f0451202bb5df 100644 (file)
@@ -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].
index 0941dcf284117202910b3e9e685e299d821e02da..8faf7be735cdb3c9f5f2457e0378d85024503cad 100644 (file)
@@ -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(_) -> [].
index b70f8fe51953adc0cb1d16cad48693860e672583..efe665d2305b2b4e258118765586095b201a19d1 100644 (file)
 
 -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].
index c0ab9a9ac5a4c03e7ef08b51d7d089e033efcdd9..afa7d39081ecd7ad9c721872130112e46d05daf2 100644 (file)
@@ -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].
index 63dc8c81bcc9d558d78d6c1b4204e04b23fa01ec..cdd9a8856d7cd7d4dc629baedd28ffd8b5afcd72 100644 (file)
@@ -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].
index 63c09db26f51644923002af407bfafdfddaa7352..67b705d9a0b60bbd3b301a9ae8f6444b383050c9 100644 (file)
@@ -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].
index 773ef241fdb11c8f9067089c142db29fd22a61f2..1c772ce17389873f77d64780d62f46b3b325f9f6 100644 (file)
@@ -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].
index 97738355e04bf58f45a86564ffd8a085dbaa09cd..68ebf8835b20c9eb68bd80b8fee9fdf82c201235 100644 (file)
@@ -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].
index 6225343c02e704d94772da4949b98a783113814e..b0777d28ec6ec23a104853ba946cb2d0dbbf92cc 100644 (file)
@@ -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(_) -> [].
index e96fc4dc1391aed62bfd681974db7f64d91aaa2f..255118483063605cfba801fd16f907843cfd61e0 100644 (file)
@@ -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].
index 4e96526e7c24d21177c661ab5cd877e1e4fd8b6f..8904f78ce6cd9143457dbca7c5469c796338d680 100644 (file)
@@ -25,6 +25,8 @@
 
 -module(mod_last).
 
+-behaviour(ejabberd_config).
+
 -author('alexey@process-one.net').
 
 -protocol({xep, 12, '2.0'}).
 -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].
index 0d9ed97500f201dc404416cda06c9b8d7e3f13ff..81d232be74da204fbf2b4376198af977c33991fc 100644 (file)
@@ -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].
index 1f8efe241db684da8336df644f0cb568aec67b4e..371b5e415148d06d623055ec0ae6fcab7b17c193 100644 (file)
 
 -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(_) -> [].
index d94151418dbd2a57bb29502c33202ab75df99f67..14aef01e91c07a4527f56e3ece48b737f14ad5fe 100644 (file)
@@ -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].
index b6699d1039d340041c9065a6e51040bb51b99c49..b39a391be4a8017ed66b97cbed575feae5bb73f8 100644 (file)
@@ -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].
index 7c18a7f9873e39d96c002a659296ed00b223408d..280f39f6c4d038ea8838d4296147ea0d65216152 100644 (file)
@@ -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].
index 9ba9833ee9b58b330b1e80211cbbc206c270fb52..0b332edec3b85406c249c51fe05e5262948f15fa 100644 (file)
@@ -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].
index e904ab95f4c0646797c7cc950a413410bcc55929..840c3aaea2c254605954511378f6e73a3984ff74 100644 (file)
@@ -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].
index 35c3ed93b6fe891851d9cd0ea5a791f108d8e0e8..81ea3dfcfe9a2d16b0d17627825a0231781be0d4 100644 (file)
         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].
index 09182ded6266a87ab0e86f439ccbe90f729927bf..56d4b49371965a37e9049e28e3857fe4ca85f64c 100644 (file)
@@ -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].
index effe2f784d649ca157fd46af5e4df9469a168f9e..621189db216e021b8d47221c019879991d269b32 100644 (file)
@@ -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(_) -> [].
index 1e7735c586c45da9ca59e92f05c17da73edbb84b..32cd4443d49e3f99fb5e71a065810a667197d4d2 100644 (file)
@@ -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].
index 367f7f0bddabaf6f5216ab9c5a62b0a99e293704..895dd7d57dd6020a8ae9ae5933e915163bf064be 100644 (file)
@@ -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].
index 663fbf72989813d8d2954d1aa86d076f792fc91f..972faa76b608f9c2560ee2b5b8af4c45428afa07 100644 (file)
@@ -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].
index 1f625cd5d6fe5711057262783c1c926964a3643e..a5e90531caadfa6ea1acf52b12a4489d45ac9822 100644 (file)
@@ -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].
index 1ed950146ef130b2a698154678a930bfad8b6bee..bb2a8fbe97f0e3f5ca47ba2cae81d7f53c6750ae 100644 (file)
@@ -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].
index b9f799b41b9b60ed0e2935c53a9f87c03b498812..32e06f142b32833301dc0c331baa8a132b485399 100644 (file)
@@ -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(_) -> [].
index aa214b4216a50237dc0fda1344d300f098684744..31fbeb1d26e9dc5a0e549b261c1d6009e7411d76 100644 (file)
 
 -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].
index 7a23b40131a7952447d468975321b07a560192dd..e145c5ce6b0890220c16501b7e54357be0c63464 100644 (file)
 
 -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].
index 4c3f177efa4f848d48f5228d8ff20ff3bab25806..ac285bfd9c02221d2485841844319181b8bb07b8 100644 (file)
 
 -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].
index a2d6f2fff5e024854986fdb12e1ccceb5bb3e71f..653c83ee2540637309f69a09be5f24b7d75341df 100644 (file)
@@ -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].
index 273930ff04d909b59ec53b0c7811955c065c6f2d..3f5bf0dab084d58875e2f72865855d460e90ec43 100644 (file)
@@ -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].
index 8790cdfc04718a4dee44655918e08d442a1b6d4e..7e7d2f307395157780f18e457a7be7e69f80a979 100644 (file)
@@ -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].
index 6168d997c275086196967608b00dc225d5047c19..1dcf264ede6358e6deca1c1dc8b7a09817004858 100644 (file)
 %%%-------------------------------------------------------------------
 -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].
index 4896a3c18b20987eb8c21eacde362f0c1e15344c..ce97dbdf09b88e2884bd59df4994ac19d3fdc9ac 100644 (file)
@@ -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].
index 111428070ca5e4d5a0725e1eeda448f86365d747..e11468400938b6f89a0b41d392a08808882c5fbc 100644 (file)
@@ -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].
index 2c700af2f4ce56d8e8775a0f644ac85c541122a7..306bd84458ee17adfb0be5a0658f49d68bef644c 100644 (file)
@@ -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].
index a5cafc5e54aec965f19cbf53af04fbfd4668e53a..f75bb07124fc6292829e07f10c005104d322ebd2 100644 (file)
@@ -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].
index 41a07bbc3dbe7ed172a9fe2161c27e8cdaf7b562..96ee09d8730b0f179c3cdd72aa8bb5ce8aabf9c4 100644 (file)
@@ -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].
index 669a401d42ebc2366c2f898fd7c8e0ce431922b0..55609d1ea04d2ee71faf63896a49972be4650cca 100644 (file)
@@ -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 = <<OSType/binary, " ", OSVersion/binary>>,
     #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].
index 7dee1a047e2b5eecca7218e5c58f715559ea59d3..6d76610af87208db099fed0644c5ffb3e3549c5c 100644 (file)
 
 -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].
index a85c4f11187d28a03edc83f8a421cbeb8b54e452..c8140703c3530cc4ba5775f2801e1150700c63dc 100644 (file)
 
 -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].