From c4a2f8d64fe94fdc0f6ae2d854b3fe46b222e79f Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 1 Feb 2023 11:52:47 +0100 Subject: [PATCH] captcha_url option now accepts 'auto' value, and it's the default --- src/ejabberd_captcha.erl | 55 +++++++++++++++++++++++++++++++++++- src/ejabberd_option.erl | 2 +- src/ejabberd_options.erl | 6 ++-- src/ejabberd_options_doc.erl | 14 ++++++--- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 69ad752b9..12ab5abb8 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -441,18 +441,37 @@ do_create_image(Key, FileName) when is_binary(FileName) -> get_prog_name() -> case ejabberd_option:captcha_cmd() of undefined -> - ?DEBUG("The option captcha_cmd is not configured, " + ?WARNING_MSG("The option captcha_cmd is not configured, " "but some module wants to use the CAPTCHA " "feature.", []), false; FileName -> + maybe_warning_norequesthandler(), FileName end. +maybe_warning_norequesthandler() -> + Host = hd(ejabberd_option:hosts()), + URL = get_auto_url(any, ?MODULE, Host), + case URL of + undefined -> + ?WARNING_MSG("The option captcha_cmd is configured, " + "but there is NO request_handler in listen option " + "configured with ejabberd_captcha. Please check " + "https://docs.ejabberd.im/admin/configuration/basic/#captcha", + []); + _ -> + ok + end. + -spec get_url(binary()) -> binary(). get_url(Str) -> case ejabberd_option:captcha_url() of + auto -> + Host = ejabberd_config:get_myname(), + URL = get_auto_url(any, ?MODULE, Host), + <>; undefined -> URL = parse_captcha_host(), <>; @@ -477,6 +496,40 @@ parse_captcha_host() -> <<"http://", (ejabberd_config:get_myname())/binary>> end. +get_auto_url(Tls, Module, Host) -> + case find_handler_port_path(Tls, Module) of + [] -> undefined; + TPPs -> + {ThisTls, Port, Path} = case lists:keyfind(true, 1, TPPs) of + false -> + lists:keyfind(false, 1, TPPs); + TPP -> + TPP + end, + Protocol = case ThisTls of + false -> <<"http">>; + true -> <<"https">> + end, + <>))/binary>> + end. + +find_handler_port_path(Tls, Module) -> + lists:filtermap( + fun({{Port, _, _}, + ejabberd_http, + #{tls := ThisTls, request_handlers := Handlers}}) + when (Tls == any) or (Tls == ThisTls) -> + case lists:keyfind(Module, 2, Handlers) of + false -> false; + {Path, Module} -> {true, {ThisTls, Port, Path}} + end; + (_) -> false + end, ets:tab2list(ejabberd_listener)). + get_transfer_protocol(PortString) -> PortNumber = binary_to_integer(PortString), PortListeners = get_port_listeners(PortNumber), diff --git a/src/ejabberd_option.erl b/src/ejabberd_option.erl index 4ac2e88a4..b71f088c6 100644 --- a/src/ejabberd_option.erl +++ b/src/ejabberd_option.erl @@ -329,7 +329,7 @@ captcha_host() -> captcha_limit() -> ejabberd_config:get_option({captcha_limit, global}). --spec captcha_url() -> 'undefined' | binary(). +-spec captcha_url() -> 'auto' | 'undefined' | binary(). captcha_url() -> ejabberd_config:get_option({captcha_url, global}). diff --git a/src/ejabberd_options.erl b/src/ejabberd_options.erl index ed3720291..c2af225cf 100644 --- a/src/ejabberd_options.erl +++ b/src/ejabberd_options.erl @@ -123,7 +123,9 @@ opt_type(captcha_host) -> opt_type(captcha_limit) -> econf:pos_int(infinity); opt_type(captcha_url) -> - econf:url(); + econf:either( + econf:url(), + econf:enum([auto, undefined])); opt_type(certfiles) -> econf:list(econf:binary()); opt_type(cluster_backend) -> @@ -546,7 +548,7 @@ options() -> {captcha_cmd, undefined}, {captcha_host, <<"">>}, {captcha_limit, infinity}, - {captcha_url, undefined}, + {captcha_url, auto}, {certfiles, undefined}, {cluster_backend, mnesia}, {cluster_nodes, []}, diff --git a/src/ejabberd_options_doc.erl b/src/ejabberd_options_doc.erl index ba4b585b3..cbf98c88d 100644 --- a/src/ejabberd_options_doc.erl +++ b/src/ejabberd_options_doc.erl @@ -458,8 +458,8 @@ doc() -> note => "improved in 23.01", desc => ?T("Full path to a script that generates http://../basic/#captcha[CAPTCHA] images. " - "@VERSION@ is replaced with ejabberd version number in XX.YY format. " - "@SEMVER@ is replaced with ejabberd version number in semver format " + "'@VERSION@' is replaced with ejabberd version number in 'XX.YY' format. " + "'@SEMVER@' is replaced with ejabberd version number in semver format " "when compiled with Elixir's mix, or XX.YY format otherwise. " "Alternatively, it can be the name of a module that implements ejabberd CAPTCHA support. " "There is no default value: when this option is not " @@ -477,11 +477,17 @@ doc() -> #{value => "String", desc => ?T("Deprecated. Use _`captcha_url`_ instead.")}}, {captcha_url, - #{value => ?T("URL"), + #{value => ?T("URL | auto | undefined"), + note => "improved in 23.xx", desc => ?T("An URL where http://../basic/#captcha[CAPTCHA] requests should be sent. NOTE: you need " "to configure 'request_handlers' for 'ejabberd_http' listener " - "as well. There is no default value.")}}, + "as well. " + "If set to 'auto', it builds the URL using a 'request_handler' " + "already enabled, with encryption if available. " + "If set to 'undefined', it builds the URL using " + "the deprecated _`captcha_host`_ + /captcha. " + "The default value is 'auto'.")}}, {certfiles, #{value => "[Path, ...]", desc =>