]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
pop3: Use new var_expand
authorAki Tuomi <aki.tuomi@open-xchange.com>
Thu, 29 Aug 2024 10:42:40 +0000 (13:42 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:40:00 +0000 (10:40 +0200)
src/lib-storage/mail-storage-settings.c
src/pop3/pop3-client.c
src/pop3/pop3-commands.c
src/pop3/pop3-settings.c
src/pop3/pop3-settings.h

index 0a03635ba49d6c3a39ac6410d35ce4c7be3c7a98..18c9dff2eaa8fd3a714ad30fce404596b30661e5 100644 (file)
@@ -183,7 +183,7 @@ const struct mail_storage_settings mail_storage_default_settings = {
        .maildir_stat_dirs = FALSE,
        .mail_shared_explicit_inbox = FALSE,
        .lock_method = "fcntl:flock:dotlock",
-       .pop3_uidl_format = "%{uid|number|hex(8)}%{uidvalidity|number|hex(8)}",
+       .pop3_uidl_format = "%{uid | hex(8)}%{uidvalidity | hex(8)}",
 
        .recipient_delimiter = "+",
 
index 33e695ff9a708c059d22dfdad716431da6c5ad32..d2539ad3223ea3c2d53880c17dde0bd8343364ef 100644 (file)
@@ -14,8 +14,8 @@
 #include "llist.h"
 #include "hostpid.h"
 #include "file-dotlock.h"
-#include "var-expand.h"
 #include "settings.h"
+#include "var-expand-new.h"
 #include "master-service.h"
 #include "mail-storage.h"
 #include "mail-storage-service.h"
@@ -301,32 +301,36 @@ static int init_mailbox(struct client *client, const char **error_r)
        return -1;
 }
 
-static enum uidl_keys parse_uidl_keymask(const char *format)
+static int parse_uidl_keymask(const char *format, enum uidl_keys *keys,
+                             const char **error_r)
 {
        enum uidl_keys mask = 0;
-
-       for (; *format != '\0'; format++) {
-               if (format[0] == '%' && format[1] != '\0') {
-                       switch (var_get_key(++format)) {
-                       case 'v':
-                               mask |= UIDL_UIDVALIDITY;
-                               break;
-                       case 'u':
-                               mask |= UIDL_UID;
-                               break;
-                       case 'm':
-                               mask |= UIDL_MD5;
-                               break;
-                       case 'f':
-                               mask |= UIDL_FILE_NAME;
-                               break;
-                       case 'g':
-                               mask |= UIDL_GUID;
-                               break;
-                       }
+       struct var_expand_program *prog;
+       if (var_expand_program_create(format, &prog, error_r) < 0)
+               return -1;
+       const char *const *vars = var_expand_program_variables(prog);
+       int ret = 0;
+
+       for (; *vars != NULL; vars++) {
+               if (strcmp(*vars, "uidvalidity") == 0)
+                       mask |= UIDL_UIDVALIDITY;
+               else if (strcmp(*vars, "uid") == 0)
+                       mask |= UIDL_UID;
+               else if (strcmp(*vars, "md5") == 0)
+                       mask |= UIDL_MD5;
+               else if (strcmp(*vars, "filename") == 0)
+                       mask |= UIDL_FILE_NAME;
+               else if (strcmp(*vars, "guid") == 0)
+                       mask |= UIDL_GUID;
+               else {
+                       *error_r = t_strdup_printf("Invalid key %%{%s}", *vars);
+                       ret = -1;
+                       break;
                }
        }
-       return mask;
+       if (ret == 0)
+               *keys = mask;
+       return ret;
 }
 
 static void pop3_lock_session_refresh(struct client *client)
@@ -416,7 +420,7 @@ struct client *client_create(int fd_in, int fd_out,
 
        client->user = user;
 
-       if (var_has_key(set->pop3_logout_format, 'u', "uidl_change")) {
+       if (set->parsed_want_uidl_change) {
                /* logging uidl_change. we need hashes of the UIDLs */
                client->message_uidls_save = TRUE;
        } else if (strcmp(set->pop3_uidl_duplicates, "allow") != 0) {
@@ -451,10 +455,11 @@ int client_init_mailbox(struct client *client, const char **error_r)
        /* refresh proctitle before a potentially long-running init_mailbox() */
        pop3_refresh_proctitle();
 
-       client->uidl_keymask =
-               parse_uidl_keymask(client->mail_set->pop3_uidl_format);
+       if (parse_uidl_keymask(client->mail_set->pop3_uidl_format,
+                              &client->uidl_keymask, &errmsg) < 0)
+               i_fatal("Invalid pop3_uidl_format: %s", errmsg);
        if (client->uidl_keymask == 0)
-               i_fatal("Invalid pop3_uidl_format");
+               i_fatal("Invalid pop3_uidl_format: Empty format");
 
        flags = MAILBOX_FLAG_POP3_SESSION;
        if (!client->set->pop3_no_flag_updates)
@@ -525,47 +530,55 @@ static const char *client_build_uidl_change_string(struct client *client)
 
 static const char *client_stats(struct client *client)
 {
-       const char *uidl_change = "";
-       if (var_has_key(client->set->pop3_logout_format,
-                       'u', "uidl_change"))
+       const char *error, *uidl_change = "";
+
+       if (client->set->parsed_want_uidl_change)
                uidl_change = client_build_uidl_change_string(client);
 
        const struct var_expand_table logout_tab[] = {
-               { 'p', dec2str(client->top_bytes), "top_bytes" },
-               { 't', dec2str(client->top_count), "top_count" },
-               { 'b', dec2str(client->retr_bytes), "retr_bytes" },
-               { 'r', dec2str(client->retr_count), "retr_count" },
-               { 'd', !client->delete_success ? "0" :
-                      dec2str(client->deleted_count), "deleted_count" },
-               { 'm', dec2str(client->messages_count), "message_count" },
-               { 's', dec2str(client->total_size), "message_bytes" },
-               { 'i', dec2str(i_stream_get_absolute_offset(client->input)),
-                 "input" },
-               { 'o', dec2str(client->output->offset), "output" },
-               { 'u', uidl_change, "uidl_change" },
-               { '\0', !client->delete_success ? "0" :
-                       dec2str(client->deleted_size), "deleted_bytes" },
-               { '\0', NULL, NULL }
+               { .key = "top_bytes", .value = dec2str(client->top_bytes) },
+               { .key = "top_count", .value = dec2str(client->top_count) },
+               { .key = "retr_bytes", .value = dec2str(client->retr_bytes) },
+               { .key = "retr_count", .value = dec2str(client->retr_count) },
+               { .key = "deleted_count",
+                 .value = !client->delete_success ? "0" :
+                          dec2str(client->deleted_count) },
+               { .key = "message_count", .value = dec2str(client->messages_count) },
+               { .key = "message_bytes", .value = dec2str(client->total_size) },
+               { .key = "input",
+                 .value = dec2str(i_stream_get_absolute_offset(client->input)), },
+               { .key = "output", .value = dec2str(client->output->offset) },
+               { .key = "uidl_change", .value = uidl_change },
+               { .key = "deleted_bytes", .value = !client->delete_success ? "0" :
+                       dec2str(client->deleted_size) },
+               VAR_EXPAND_TABLE_END
+       };
+
+       const struct var_expand_params *user_params =
+               mail_user_var_expand_params(client->user);
+       const struct var_expand_params params = {
+               .tables_arr = (const struct var_expand_table*[]) {
+                       user_params->table,
+                       logout_tab,
+                       NULL
+               },
+               .providers = user_params->providers,
+               .context =  user_params->context,
+               .event = client->event,
        };
-       const struct var_expand_table *user_tab =
-               mail_user_var_expand_table(client->user);
-       const struct var_expand_table *tab =
-               t_var_expand_merge_tables(logout_tab, user_tab);
        string_t *str;
-       const char *error;
+
+       event_add_int(client->event, "net_in_bytes", i_stream_get_absolute_offset(client->input));
+       event_add_int(client->event, "net_out_bytes", client->output->offset);
 
        str = t_str_new(128);
-       if (var_expand_with_funcs(str, client->set->pop3_logout_format,
-                                 tab, mail_user_var_expand_func_table,
-                                 client->user, &error) <= 0) {
+       if (var_expand_new(str, client->set->pop3_logout_format,
+                          &params, &error) < 0) {
                e_error(client->event,
                        "Failed to expand pop3_logout_format=%s: %s",
                        client->set->pop3_logout_format, error);
        }
 
-       event_add_int(client->event, "net_in_bytes", i_stream_get_absolute_offset(client->input));
-       event_add_int(client->event, "net_out_bytes", client->output->offset);
-
        return str_c(str);
 }
 
index 4e7718e6ddc5a2f3a41f08f8d764e0b8d09f97a5..8c6d9b3b9840df0aa45a42296df9d3d8cc9771cd 100644 (file)
@@ -7,7 +7,7 @@
 #include "hash.h"
 #include "str.h"
 #include "strfuncs.h"
-#include "var-expand.h"
+#include "var-expand-new.h"
 #include "message-size.h"
 #include "mail-storage.h"
 #include "mail-storage-settings.h"
@@ -635,7 +635,7 @@ pop3_get_uid(struct client *client, struct mail *mail, string_t *str,
                } else if (hdr_md5[0] == '\0') {
                        e_error(client->event,
                                "UIDL: Header MD5 not found "
-                               "(pop3_uidl_format=%%m not supported by storage?)");
+                               "(pop3_uidl_format=%%{md5} not supported by storage?)");
                        return -1;
                }
        }
@@ -649,7 +649,7 @@ pop3_get_uid(struct client *client, struct mail *mail, string_t *str,
                } else if (filename[0] == '\0') {
                        e_error(client->event,
                                "UIDL: File name not found "
-                               "(pop3_uidl_format=%%f not supported by storage?)");
+                               "(pop3_uidl_format=%%{filename} not supported by storage?)");
                        return -1;
                }
        }
@@ -663,23 +663,25 @@ pop3_get_uid(struct client *client, struct mail *mail, string_t *str,
                } else if (guid[0] == '\0') {
                        e_error(client->event,
                                "UIDL: Message GUID not found "
-                               "(pop3_uidl_format=%%g not supported by storage?)");
+                               "(pop3_uidl_format=%%{guid} not supported by storage?)");
                        return -1;
                }
        }
 
-       const struct var_expand_table tab[] = {
-               { 'v', dec2str(client->uid_validity), "uidvalidity" },
-               { 'u', uid_str, "uid" },
-               { 'm', hdr_md5, "md5" },
-               { 'f', filename, "filename" },
-               { 'g', guid, "guid" },
-               { '\0', NULL, NULL }
+       const struct var_expand_params params = {
+               .table = (const struct var_expand_table[]) {
+                       { .key = "uidvalidity", .value = dec2str(client->uid_validity) },
+                       { .key = "uid", .value = uid_str },
+                       { .key = "md5", .value = hdr_md5 },
+                       { .key = "filename", .value = filename },
+                       { .key = "guid", .value = guid },
+                       VAR_EXPAND_TABLE_END
+               },
        };
        const char *error;
 
-       if (var_expand_with_table(str, client->mail_set->pop3_uidl_format,
-                                 tab, &error) <= 0) {
+       if (var_expand_new(str, client->mail_set->pop3_uidl_format,
+                          &params, &error) < 0) {
                e_error(client->event,
                        "UIDL: Failed to expand pop3_uidl_format=%s: %s",
                        client->mail_set->pop3_uidl_format, error);
index 8cf867ea2dae9656baa83f55d9a81af45cb5ed86..a2cf9b99787078f78be72d9038dd38100076add3 100644 (file)
@@ -6,6 +6,7 @@
 #include "service-settings.h"
 #include "mail-storage-settings.h"
 #include "pop3-settings.h"
+#include "var-expand-new.h"
 
 #include <unistd.h>
 
@@ -82,7 +83,11 @@ static const struct pop3_settings pop3_default_settings = {
        .pop3_lock_session = FALSE,
        .pop3_fast_size_lookups = FALSE,
        .pop3_client_workarounds = ARRAY_INIT,
-       .pop3_logout_format = "top=%t/%p, retr=%r/%b, del=%d/%m, size=%s",
+       .pop3_logout_format =
+               "top=%{top_count}/%{top_bytes}, "
+               "retr=%{retr_count}/%{retr_bytes}, "
+               "del=%{deleted_count}/%{deleted_bytes}, "
+               "size=%{message_bytes}",
        .pop3_uidl_duplicates = "allow:rename",
        .pop3_deleted_flag = "",
        .pop3_delete_type = "default:expunge:flag"
@@ -163,6 +168,17 @@ pop3_settings_verify(void *_set, pool_t pool ATTR_UNUSED, const char **error_r)
                                           set->pop3_delete_type);
                return FALSE;
        }
+
+       struct var_expand_program *prog;
+       const char *error;
+       if (var_expand_program_create(set->pop3_logout_format, &prog, &error) < 0) {
+               *error_r = t_strdup_printf("Invalid pop3_logout_format: %s", error);
+               return FALSE;
+       }
+       const char *const *vars = var_expand_program_variables(prog);
+       set->parsed_want_uidl_change = str_array_find(vars, "uidl_change");
+       var_expand_program_free(&prog);
+
        return TRUE;
 }
 /* </settings checks> */
index adb4244e3ffe8e1199f027d9c622c791065bb305..527153dee67f23bfd4dd20776ed63a894c40bb50 100644 (file)
@@ -34,6 +34,7 @@ struct pop3_settings {
 
        enum pop3_client_workarounds parsed_workarounds;
        enum pop3_delete_type parsed_delete_type;
+       bool parsed_want_uidl_change;
 };
 
 extern const struct setting_parser_info pop3_setting_parser_info;