From: sergey.kitov Date: Thu, 29 Aug 2024 09:51:10 +0000 (+0300) Subject: imap(-login): Change imap_capability to boollist. X-Git-Tag: 2.4.1~619 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=773e1b46dd4f388737432404066efbaebe8efb0d;p=thirdparty%2Fdovecot%2Fcore.git imap(-login): Change imap_capability to boollist. --- diff --git a/configure.ac b/configure.ac index da00162048..5d66fa00fe 100644 --- a/configure.ac +++ b/configure.ac @@ -757,17 +757,6 @@ SETTING_LINKED_FILES=`echo $libdovecot_c_files | $SED -e s,$srcdir/src,./src,g - AC_SUBST(SETTING_FILES) AC_SUBST(SETTING_LINKED_FILES) -dnl ** -dnl ** capabilities -dnl ** - -dnl IDLE doesn't really belong to banner. It's there just to make Blackberries -dnl happy, because otherwise BIS server disables push email. -capability_banner="IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE" -capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE SNIPPET=FUZZY PREVIEW=FUZZY PREVIEW STATUS=SIZE SAVEDATE COMPRESS=DEFLATE INPROGRESS${experimental_capabilities}" -AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", [IMAP capabilities]) -AC_DEFINE_UNQUOTED(CAPABILITY_BANNER_STRING, "$capability_banner", [IMAP capabilities advertised in banner]) - CFLAGS="$CFLAGS $EXTRA_CFLAGS" CXXFLAGS="$CXXFLAGS $EXTRA_CFLAGS" BINARY_LDFLAGS="$PIE_LDFLAGS $RELRO_LDFLAGS" diff --git a/src/imap-login/Makefile.am b/src/imap-login/Makefile.am index e69b8d4791..d58e3d062b 100644 --- a/src/imap-login/Makefile.am +++ b/src/imap-login/Makefile.am @@ -12,6 +12,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib-imap \ -I$(top_srcdir)/src/lib-master \ -I$(top_srcdir)/src/lib-login \ + -I$(top_srcdir)/src/lib-mail \ -I$(top_srcdir)/src/login-common \ $(BINARY_CFLAGS) diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c index a3be3c0e71..15ddd559b7 100644 --- a/src/imap-login/imap-login-client.c +++ b/src/imap-login/imap-login-client.c @@ -21,6 +21,7 @@ #include "imap-quote.h" #include "imap-login-commands.h" #include "imap-login-settings.h" +#include "imap-util.h" #if LOGIN_MAX_INBUF_SIZE < 1024+2 # error LOGIN_MAX_INBUF_SIZE too short to fit all ID command parameters @@ -89,24 +90,16 @@ static bool is_login_cmd_disabled(struct client *client) return FALSE; } +static int imap_client_reload_config(struct client *client, + const char **error_r); + static const char *get_capability(struct client *client) { struct imap_client *imap_client = container_of(client, struct imap_client, common); string_t *cap_str = t_str_new(256); - if (*imap_client->set->imap_capability == '\0') - str_append(cap_str, CAPABILITY_BANNER_STRING); - else { - str_append(cap_str, CAPABILITY_BANNER_STRING); - str_append_c(cap_str, ' '); - str_append(cap_str, imap_client->set->imap_capability + 1); - } - - if (imap_client->set->imap_literal_minus) - str_append(cap_str, " LITERAL-"); - else - str_append(cap_str, " LITERAL+"); + imap_write_capability(cap_str, &imap_client->set->imap_capability); if (client_is_tls_enabled(client) && !client->connection_tls_secured && !client->haproxy_terminated_tls) @@ -390,9 +383,27 @@ static int imap_client_create(struct client *client) imap_parser_create(imap_client->common.input, imap_client->common.output, IMAP_LOGIN_MAX_LINE_LENGTH); - if (imap_client->set->imap_literal_minus) + struct settings_instance *set_instance = settings_instance_find(client->event); + if (set_instance == NULL) { + set_instance = settings_instance_new( + master_service_get_settings_root(master_service)); + event_set_ptr(client->event, SETTINGS_EVENT_INSTANCE, set_instance); + } + + if (imap_client->set->imap_literal_minus) { + settings_override(set_instance, + "imap_capability/LITERAL+", + "no", SETTINGS_OVERRIDE_TYPE_CODE); imap_parser_enable_literal_minus(imap_client->parser); + } else + settings_override(set_instance, + "imap_capability/LITERAL-", + "no", SETTINGS_OVERRIDE_TYPE_CODE); client->io = io_add_istream(client->input, client_input, client); + if (imap_client_reload_config(client, &error) < 0) { + e_error(client->event, "%s", error); + return -1; + } return 0; } diff --git a/src/imap-login/imap-login-settings.c b/src/imap-login/imap-login-settings.c index c26dc26198..ba4e2dc3fd 100644 --- a/src/imap-login/imap-login-settings.c +++ b/src/imap-login/imap-login-settings.c @@ -51,7 +51,7 @@ const struct setting_keyvalue imap_login_service_settings_defaults[] = { SETTING_DEFINE_STRUCT_##type(#name, name, struct imap_login_settings) static const struct setting_define imap_login_setting_defines[] = { - DEF(STR, imap_capability), + DEF(BOOLLIST, imap_capability), DEF(BOOL, imap_literal_minus), DEF(BOOL, imap_id_retain), @@ -62,13 +62,23 @@ static const struct setting_define imap_login_setting_defines[] = { }; static const struct imap_login_settings imap_login_default_settings = { - .imap_capability = "", + .imap_capability = ARRAY_INIT, .imap_id_send = ARRAY_INIT, .imap_literal_minus = FALSE, .imap_id_retain = FALSE, }; static const struct setting_keyvalue imap_login_default_settings_keyvalue[] = { + {"service/imap-login/imap_capability/IMAP4rev1", "yes"}, + {"service/imap-login/imap_capability/LOGIN-REFERRALS", "yes"}, + {"service/imap-login/imap_capability/ID", "yes"}, + {"service/imap-login/imap_capability/ENABLE", "yes"}, + /* IDLE doesn't really belong to banner. It's there just to make + Blackberries happy, because otherwise BIS server disables push email. */ + { "service/imap-login/imap_capability/IDLE", "yes" }, + { "service/imap-login/imap_capability/SASL-IR", "yes" }, + { "service/imap-login/imap_capability/LITERAL+", "yes" }, + { "service/imap-login/imap_capability/LITERAL-", "yes" }, { "imap_id_send/name", DOVECOT_NAME }, { NULL, NULL }, }; diff --git a/src/imap-login/imap-login-settings.h b/src/imap-login/imap-login-settings.h index cfdf5b843e..3dd90ff237 100644 --- a/src/imap-login/imap-login-settings.h +++ b/src/imap-login/imap-login-settings.h @@ -3,7 +3,7 @@ struct imap_login_settings { pool_t pool; - const char *imap_capability; + ARRAY_TYPE(const_string) imap_capability; ARRAY_TYPE(const_string) imap_id_send; bool imap_literal_minus; bool imap_id_retain; diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c index 7e78e16ef9..186a863253 100644 --- a/src/imap/imap-client.c +++ b/src/imap/imap-client.c @@ -85,6 +85,14 @@ static void client_init_urlauth(struct client *client) client->urlauth_ctx = imap_urlauth_init(client->user, &config); } +static void +imap_unset_capability(struct settings_instance *set_instance, const char *capability) +{ + settings_override(set_instance, + t_strdup_printf("imap_capability/%s", capability), + "no", SETTINGS_OVERRIDE_TYPE_CODE); +} + struct client *client_create(int fd_in, int fd_out, enum client_create_flags flags, struct event *event, struct mail_user *user, @@ -138,30 +146,24 @@ struct client *client_create(int fd_in, int fd_out, client->notify_flag_changes = TRUE; p_array_init(&client->enabled_features, client->pool, 8); - client->capability_string = - str_new(client->pool, sizeof(CAPABILITY_STRING)+64); - - if (*set->imap_capability == '\0') - str_append(client->capability_string, CAPABILITY_STRING); - else - str_append(client->capability_string, set->imap_capability); + struct settings_instance *set_instance = + mail_storage_service_user_get_settings_instance( + client->user->service_user); + /* All capabilities are enabled by defaults. + Remove the capabilities here that can't work due current settings. */ if (client->set->imap_literal_minus) - client_add_capability(client, "LITERAL-"); - else - client_add_capability(client, "LITERAL+"); - if (user->fuzzy_search) { - /* Enable FUZZY capability only when it actually has - a chance of working */ - client_add_capability(client, "SEARCH=FUZZY"); - } + imap_unset_capability(set_instance, "LITERAL+"); + else + imap_unset_capability(set_instance, "LITERAL-"); + /* Enable FUZZY capability only when it actually has a chance of working */ + if (!user->fuzzy_search) + imap_unset_capability(set_instance, "SEARCH=FUZZY"); mail_set = mail_user_set_get_storage_set(user); - if (mail_set->mailbox_list_index) { - /* NOTIFY is enabled only when mailbox list indexes are - enabled, although even that doesn't necessarily guarantee - it always */ - client_add_capability(client, "NOTIFY"); - } + /* NOTIFY is enabled only when mailbox list indexes are enabled, + althoaugh even that doesn't necessarily guarantee it always */ + if (!mail_set->mailbox_list_index) + imap_unset_capability(set_instance, "NOTIFY"); const char *error; int ret = mailbox_attribute_dict_is_enabled(user, &error); @@ -169,19 +171,30 @@ struct client *client_create(int fd_in, int fd_out, client->init_error = p_strdup(user->pool, error); bool have_mailbox_attribute_dict = ret > 0; - if (*set->imap_urlauth_host != '\0' && have_mailbox_attribute_dict) { - /* Enable URLAUTH capability only when dict is - configured correctly */ + /* Enable URLAUTH capability only when dict is configured correctly */ + if (*set->imap_urlauth_host != '\0' && have_mailbox_attribute_dict) client_init_urlauth(client); - client_add_capability(client, "URLAUTH"); - client_add_capability(client, "URLAUTH=BINARY"); - } - if (set->imap_metadata && have_mailbox_attribute_dict) - client_add_capability(client, "METADATA"); - if (user->have_special_use_mailboxes) { - /* Advertise SPECIAL-USE only if there are actually some - SPECIAL-USE flags in mailbox configuration. */ - client_add_capability(client, "SPECIAL-USE"); + else { + imap_unset_capability(set_instance, "URLAUTH"); + imap_unset_capability(set_instance, "URLAUTH=BINARY"); + } + if (!set->imap_metadata || !have_mailbox_attribute_dict) + imap_unset_capability(set_instance, "METADATA"); + /* Advertise SPECIAL-USE only if there are actually some + SPECIAL-USE flags in mailbox configuration. */ + if (!user->have_special_use_mailboxes) + imap_unset_capability(set_instance, "SPECIAL-USE"); + + const struct imap_settings *modified_set; + if (settings_get(client->user->event, &imap_setting_parser_info, + 0, &modified_set, &error) < 0) { + if (client->init_error == NULL) + client->init_error = p_strdup(user->pool, error); + } else { + client->capability_string = str_new(client->pool, 256); + imap_write_capability(client->capability_string, + &modified_set->imap_capability); + settings_free(modified_set); } struct master_service_anvil_session anvil_session; @@ -590,8 +603,7 @@ void client_add_capability(struct client *client, const char *capability) { /* require a single capability at a time (feels cleaner) */ i_assert(strchr(capability, ' ') == NULL); - - if (client->set->imap_capability[0] != '\0') { + if (settings_boollist_is_stopped(&client->set->imap_capability)) { /* explicit capability - don't change it */ return; } diff --git a/src/imap/imap-settings.c b/src/imap/imap-settings.c index eb8610ccd8..04191d8daf 100644 --- a/src/imap/imap-settings.c +++ b/src/imap/imap-settings.c @@ -61,7 +61,7 @@ static const struct setting_define imap_setting_defines[] = { DEF(SIZE_HIDDEN, imap_max_line_length), DEF(TIME_HIDDEN, imap_idle_notify_interval), - DEF(STR, imap_capability), + DEF(BOOLLIST, imap_capability), DEF(BOOLLIST, imap_client_workarounds), DEF(STR_NOVARS, imap_logout_format), DEF(ENUM, imap_fetch_failure), @@ -89,7 +89,7 @@ static const struct imap_settings imap_default_settings = { liberal by default. */ .imap_max_line_length = 64*1024, .imap_idle_notify_interval = 2*60, - .imap_capability = "", + .imap_capability = ARRAY_INIT, .imap_client_workarounds = ARRAY_INIT, .imap_logout_format = "in=%i out=%o deleted=%{deleted} " "expunged=%{expunged} trashed=%{trashed} " @@ -110,6 +110,48 @@ static const struct imap_settings imap_default_settings = { }; static const struct setting_keyvalue imap_default_settings_keyvalue[] = { + { "service/imap/imap_capability/IMAP4rev1", "yes" }, + { "service/imap/imap_capability/SASL-IR", "yes" }, + { "service/imap/imap_capability/LOGIN-REFERRALS", "yes" }, + { "service/imap/imap_capability/ID", "yes" }, + { "service/imap/imap_capability/ENABLE", "yes" }, + { "service/imap/imap_capability/IDLE", "yes" }, + { "service/imap/imap_capability/SORT", "yes" }, + { "service/imap/imap_capability/SORT=DISPLAY", "yes" }, + { "service/imap/imap_capability/THREAD=REFERENCES", "yes" }, + { "service/imap/imap_capability/THREAD=REFS", "yes" }, + { "service/imap/imap_capability/THREAD=ORDEREDSUBJECT", "yes" }, + { "service/imap/imap_capability/MULTIAPPEND", "yes" }, + { "service/imap/imap_capability/URL-PARTIAL", "yes" }, + { "service/imap/imap_capability/CATENATE", "yes" }, + { "service/imap/imap_capability/UNSELECT", "yes" }, + { "service/imap/imap_capability/CHILDREN", "yes" }, + { "service/imap/imap_capability/NAMESPACE", "yes" }, + { "service/imap/imap_capability/UIDPLUS", "yes" }, + { "service/imap/imap_capability/LIST-EXTENDED", "yes" }, + { "service/imap/imap_capability/I18NLEVEL=1", "yes" }, + { "service/imap/imap_capability/CONDSTORE", "yes" }, + { "service/imap/imap_capability/QRESYNC", "yes" }, + { "service/imap/imap_capability/ESEARCH", "yes" }, + { "service/imap/imap_capability/ESORT", "yes" }, + { "service/imap/imap_capability/SEARCHRES", "yes" }, + { "service/imap/imap_capability/WITHIN", "yes" }, + { "service/imap/imap_capability/CONTEXT=SEARCH", "yes" }, + { "service/imap/imap_capability/LIST-STATUS", "yes" }, + { "service/imap/imap_capability/BINARY", "yes" }, + { "service/imap/imap_capability/MOVE", "yes" }, + { "service/imap/imap_capability/SNIPPET=FUZZY", "yes" }, + { "service/imap/imap_capability/PREVIEW=FUZZY", "yes" }, + { "service/imap/imap_capability/PREVIEW", "yes" }, + { "service/imap/imap_capability/STATUS=SIZE", "yes" }, + { "service/imap/imap_capability/SAVEDATE", "yes" }, + { "service/imap/imap_capability/COMPRESS=DEFLATE", "yes" }, + { "service/imap/imap_capability/INPROGRESS", "yes" }, + { "service/imap/imap_capability/NOTIFY", "yes" }, + { "service/imap/imap_capability/METADATA", "yes" }, + { "service/imap/imap_capability/SPECIAL-USE", "yes" }, + { "service/imap/imap_capability/LITERAL+", "yes" }, + { "service/imap/imap_capability/LITERAL-", "yes" }, { "imap_id_send/name", DOVECOT_NAME }, { NULL, NULL }, }; diff --git a/src/imap/imap-settings.h b/src/imap/imap-settings.h index e78a49bf95..90203bc482 100644 --- a/src/imap/imap-settings.h +++ b/src/imap/imap-settings.h @@ -27,7 +27,7 @@ struct imap_settings { /* imap: */ uoff_t imap_max_line_length; unsigned int imap_idle_notify_interval; - const char *imap_capability; + ARRAY_TYPE(const_string) imap_capability; ARRAY_TYPE(const_string) imap_client_workarounds; const char *imap_logout_format; const char *imap_fetch_failure; diff --git a/src/lib-settings/settings-parser.c b/src/lib-settings/settings-parser.c index 244730d4e4..fe4623693b 100644 --- a/src/lib-settings/settings-parser.c +++ b/src/lib-settings/settings-parser.c @@ -519,12 +519,9 @@ bool settings_boollist_is_stopped(const ARRAY_TYPE(const_string) *array) /* The first element after the visible array is NULL. If the next element after the NULL is set_array_stop, then the boollist is stopped. */ unsigned int count; - const char *const *values = - array_get(array, &count); + const char *const *values = array_get(array, &count); i_assert(values[count] == NULL); - if (values[count + 1] == set_array_stop) - return TRUE; - return FALSE; + return values[count + 1] == set_array_stop; } static int