]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: API change - var_expand_func_table.func() can now return error.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 31 Oct 2016 20:05:11 +0000 (22:05 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 2 Nov 2016 12:11:27 +0000 (14:11 +0200)
None of the existing functions were changed to return errors (yet).

src/auth/auth-request-var-expand.c
src/auth/db-dict.c
src/auth/db-ldap.c
src/lib-storage/mail-storage-service.c
src/lib-storage/mail-user.c
src/lib/test-var-expand.c
src/lib/var-expand.c
src/lib/var-expand.h
src/login-common/client-common.c

index ccc49f1f17a25c235ba4970e8a0ca0ae8698e1d3..3cbfc96c461628f16458a71c947dbc2c050a13a0 100644 (file)
@@ -195,20 +195,25 @@ static const char *field_get_default(const char *data)
        }
 }
 
-static const char *
-auth_request_var_expand_func_passdb(const char *data, void *context)
+static int
+auth_request_var_expand_func_passdb(const char *data, void *context,
+                                   const char **value_r,
+                                   const char **error_r ATTR_UNUSED)
 {
        struct auth_request_var_expand_ctx *ctx = context;
        const char *field_name = t_strcut(data, ':');
        const char *value;
 
        value = auth_fields_find(ctx->auth_request->extra_fields, field_name);
-       return ctx->escape_func(value != NULL ? value : field_get_default(data),
-                               ctx->auth_request);
+       *value_r = ctx->escape_func(value != NULL ? value : field_get_default(data),
+                                   ctx->auth_request);
+       return 1;
 }
 
-static const char *
-auth_request_var_expand_func_userdb(const char *data, void *context)
+static int
+auth_request_var_expand_func_userdb(const char *data, void *context,
+                                   const char **value_r,
+                                   const char **error_r ATTR_UNUSED)
 {
        struct auth_request_var_expand_ctx *ctx = context;
        const char *field_name = t_strcut(data, ':');
@@ -216,8 +221,9 @@ auth_request_var_expand_func_userdb(const char *data, void *context)
 
        value = ctx->auth_request->userdb_reply == NULL ? NULL :
                auth_fields_find(ctx->auth_request->userdb_reply, field_name);
-       return ctx->escape_func(value != NULL ? value : field_get_default(data),
-                               ctx->auth_request);
+       *value_r = ctx->escape_func(value != NULL ? value : field_get_default(data),
+                                   ctx->auth_request);
+       return 1;
 }
 
 const struct var_expand_func_table auth_request_var_funcs_table[] = {
index c10a5e3f2511934ab71a114a9c4229bd200f318a..4559e556e78fbffb7886c43434fa4b4abda6a9da 100644 (file)
@@ -567,38 +567,43 @@ db_dict_value_iter_object_next(struct db_dict_value_iter *iter,
        i_unreached();
 }
 
-static const char *
-db_dict_field_find(const char *data, void *context)
+static int
+db_dict_field_find(const char *data, void *context,
+                  const char **value_r,
+                  const char **error_r ATTR_UNUSED)
 {
        struct db_dict_value_iter *iter = context;
        struct db_dict_iter_key *key;
-       const char *name, *value, *ret, *dotname = strchr(data, '.');
+       const char *name, *value, *dotname = strchr(data, '.');
        string_t *tmpstr;
 
+       *value_r = NULL;
+
        if (dotname != NULL)
                data = t_strdup_until(data, dotname++);
        key = db_dict_iter_find_key(iter, data);
        if (key == NULL)
-               return NULL;
+               return 1;
 
        switch (key->key->parsed_format) {
        case DB_DICT_VALUE_FORMAT_VALUE:
-               return dotname != NULL ? NULL :
+               *value_r = dotname != NULL ? NULL :
                        (key->value == NULL ? "" : key->value);
+               return 1;
        case DB_DICT_VALUE_FORMAT_JSON:
                if (dotname == NULL)
-                       return NULL;
+                       return 1;
                db_dict_value_iter_json_init(iter, key->value);
-               ret = "";
+               *value_r = "";
                tmpstr = t_str_new(64);
                while (db_dict_value_iter_json_next(iter, tmpstr, &name, &value)) {
                        if (strcmp(name, dotname) == 0) {
-                               ret = t_strdup(value);
+                               *value_r = t_strdup(value);
                                break;
                        }
                }
                (void)json_parser_deinit(&iter->json_parser, &iter->error);
-               return ret;
+               return 1;
        }
        i_unreached();
 }
index 9fd4ac33f0c2b4a7d2eee8b52c251283211dc99e..efdb4139fea2a5a7b1aacc190b56eacab22d4caa 100644 (file)
@@ -593,8 +593,10 @@ struct ldap_field_find_subquery_context {
        const char *name;
 };
 
-static const char *
-db_ldap_field_subquery_find(const char *data, void *context)
+static int
+db_ldap_field_subquery_find(const char *data, void *context,
+                           const char **value_r,
+                           const char **error_r ATTR_UNUSED)
 {
        struct ldap_field_find_subquery_context *ctx = context;
        char *ldap_attr;
@@ -609,10 +611,10 @@ db_ldap_field_subquery_find(const char *data, void *context)
                        array_append(&ctx->attr_names, &ldap_attr, 1);
                }
        }
-       return NULL;
+       *value_r = NULL;
+       return 1;
 }
 
-
 static int
 ldap_request_send_subquery(struct ldap_connection *conn,
                           struct ldap_request_search *request,
@@ -1349,8 +1351,10 @@ struct ldap_field_find_context {
        pool_t pool;
 };
 
-static const char *
-db_ldap_field_find(const char *data, void *context)
+static int
+db_ldap_field_find(const char *data, void *context,
+                  const char **value_r,
+                  const char **error_r ATTR_UNUSED)
 {
        struct ldap_field_find_context *ctx = context;
        char *ldap_attr;
@@ -1360,7 +1364,8 @@ db_ldap_field_find(const char *data, void *context)
                if (strchr(ldap_attr, '@') == NULL)
                        array_append(&ctx->attr_names, &ldap_attr, 1);
        }
-       return NULL;
+       *value_r = NULL;
+       return 1;
 }
 
 void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
@@ -1624,7 +1629,9 @@ static const char *db_ldap_field_get_default(const char *data)
        }
 }
 
-static const char *db_ldap_field_expand(const char *data, void *context)
+static int
+db_ldap_field_expand(const char *data, void *context,
+                    const char **value_r, const char **error_r ATTR_UNUSED)
 {
        struct db_ldap_result_iterate_context *ctx = context;
        struct db_ldap_value *ldap_value;
@@ -1635,33 +1642,42 @@ static const char *db_ldap_field_expand(const char *data, void *context)
                /* requested ldap attribute wasn't returned at all */
                if (ctx->debug != NULL)
                        str_printfa(ctx->debug, "; %s missing", field_name);
-               return db_ldap_field_get_default(data);
+               *value_r = db_ldap_field_get_default(data);
+               return 1;
        }
        ldap_value->used = TRUE;
 
        if (ldap_value->values[0] == NULL) {
                /* no value for ldap attribute */
-               return db_ldap_field_get_default(data);
+               *value_r = db_ldap_field_get_default(data);
+               return 1;
        }
        if (ldap_value->values[1] != NULL) {
                auth_request_log_warning(ctx->auth_request, AUTH_SUBSYS_DB,
                        "Multiple values found for '%s', using value '%s'",
                        field_name, ldap_value->values[0]);
        }
-       return ldap_value->values[0];
+       *value_r = ldap_value->values[0];
+       return 1;
 }
 
-static const char *db_ldap_field_ptr_expand(const char *data, void *context)
+static int
+db_ldap_field_ptr_expand(const char *data, void *context,
+                        const char **value_r, const char **error_r)
 {
        struct db_ldap_result_iterate_context *ctx = context;
        const char *field_name, *suffix;
+       int ret;
 
        suffix = strchr(t_strcut(data, ':'), '@');
-       field_name = db_ldap_field_expand(data, ctx);
-       if (field_name[0] == '\0')
-               return "";
+       if ((ret = db_ldap_field_expand(data, ctx, &field_name, error_r)) <= 0)
+               return ret;
+       if (field_name[0] == '\0') {
+               *value_r = "";
+               return 1;
+       }
        field_name = t_strconcat(field_name, suffix, NULL);
-       return db_ldap_field_expand(field_name, ctx);
+       return db_ldap_field_expand(field_name, ctx, value_r, error_r);
 }
 
 static struct var_expand_func_table ldap_var_funcs_table[] = {
index 74b89c3fc8362cafb5193a39bffddf81376c868a..725eb78f8db65d436e91c56cf760f33857009c53 100644 (file)
@@ -793,13 +793,16 @@ const char *mail_storage_service_fields_var_expand(const char *data,
        return field_get_default(data);
 }
 
-static const char *
-mail_storage_service_input_var_userdb(const char *data, void *context)
+static int
+mail_storage_service_input_var_userdb(const char *data, void *context,
+                                     const char **value_r,
+                                     const char **error_r ATTR_UNUSED)
 {
        struct mail_storage_service_user *user = context;
 
-       return mail_storage_service_fields_var_expand(data,
+       *value_r = mail_storage_service_fields_var_expand(data,
                        user == NULL ? NULL : user->input.userdb_fields);
+       return 1;
 }
 
 static int
index 5083b1bce202718a76a56e6e61c280c02046baad..f3ddd772f858498d21467e633a4b1538de108c9a 100644 (file)
@@ -272,12 +272,15 @@ mail_user_var_expand_table(struct mail_user *user)
        return user->var_expand_table;
 }
 
-static const char *
-mail_user_var_expand_func_userdb(const char *data, void *context)
+static int
+mail_user_var_expand_func_userdb(const char *data, void *context,
+                                const char **value_r,
+                                const char **error_r ATTR_UNUSED)
 {
        struct mail_user *user = context;
 
-       return mail_storage_service_fields_var_expand(data, user->userdb_fields);
+       *value_r = mail_storage_service_fields_var_expand(data, user->userdb_fields);
+       return 1;
 }
 
 void mail_user_set_home(struct mail_user *user, const char *home)
index 8b23f7ce3d2f00959e1a16d16ef5c71dc8c0000e..93d8b60dae174465515cd1a498b5da0c7477b4be 100644 (file)
@@ -106,22 +106,49 @@ static void test_var_get_key_range(void)
        test_end();
 }
 
-static const char *test_var_expand_func1(const char *data, void *context)
+static int test_var_expand_func1(const char *data, void *context,
+                                const char **value_r,
+                                const char **error_r ATTR_UNUSED)
 {
        test_assert(*(int *)context == 0xabcdef);
-       return t_strdup_printf("<%s>", data);
+       *value_r = t_strdup_printf("<%s>", data);
+       return 1;
 }
 
-static const char *test_var_expand_func2(const char *data ATTR_UNUSED,
-                                        void *context ATTR_UNUSED)
+static int test_var_expand_func2(const char *data ATTR_UNUSED,
+                                void *context ATTR_UNUSED,
+                                const char **value_r,
+                                const char **error_r ATTR_UNUSED)
 {
-       return "";
+       *value_r = "";
+       return 1;
 }
 
-static const char *test_var_expand_func3(const char *data ATTR_UNUSED,
-                                        void *context ATTR_UNUSED)
+static int test_var_expand_func3(const char *data ATTR_UNUSED,
+                                void *context ATTR_UNUSED,
+                                const char **value_r,
+                                const char **error_r ATTR_UNUSED)
 {
-       return NULL;
+       *value_r = NULL;
+       return 1;
+}
+
+static int test_var_expand_func4(const char *data,
+                                void *context ATTR_UNUSED,
+                                const char **value_r ATTR_UNUSED,
+                                const char **error_r)
+{
+       *error_r = t_strdup_printf("Unknown data %s", data == NULL ? "" : data);
+       return 0;
+}
+
+static int test_var_expand_func5(const char *data ATTR_UNUSED,
+                                void *context ATTR_UNUSED,
+                                const char **value_r ATTR_UNUSED,
+                                const char **error_r)
+{
+       *error_r = "Internal error";
+       return -1;
 }
 
 static void test_var_expand_with_funcs(void)
@@ -130,7 +157,11 @@ static void test_var_expand_with_funcs(void)
                { "%{func1}", "<>", 1 },
                { "%{func1:foo}", "<foo>", 1 },
                { "%{func2}", "", 1 },
-               { "%{func3}", "", 1 }
+               { "%{func3}", "", 1 },
+               { "%{func4}", "", 0 },
+               { "%{func5}", "", -1 },
+               { "%{func4}%{func5}", "", -1 },
+               { "%{func5}%{func4}%{func3}", "", -1 },
        };
        static struct var_expand_table table[] = {
                { '\0', NULL, NULL }
@@ -139,6 +170,8 @@ static void test_var_expand_with_funcs(void)
                { "func1", test_var_expand_func1 },
                { "func2", test_var_expand_func2 },
                { "func3", test_var_expand_func3 },
+               { "func4", test_var_expand_func4 },
+               { "func5", test_var_expand_func5 },
                { NULL, NULL }
        };
        string_t *str = t_str_new(128);
index 2483cbf047d6cf1f6ae25ba936ac1605b1a28692..405e9f798865f84565d2ac12b5635e93d4ef50b6 100644 (file)
@@ -196,7 +196,8 @@ var_expand_func(const struct var_expand_func_table *func_table,
                const char *key, const char *data, void *context,
                const char **var_r, const char **error_r)
 {
-       const char *value;
+       const char *value = NULL;
+       int ret;
 
        if (strcmp(key, "env") == 0) {
                value = getenv(data);
@@ -206,9 +207,9 @@ var_expand_func(const struct var_expand_func_table *func_table,
        if (func_table != NULL) {
                for (; func_table->key != NULL; func_table++) {
                        if (strcmp(func_table->key, key) == 0) {
-                               value = func_table->func(data, context);
+                               ret = func_table->func(data, context, &value, error_r);
                                *var_r = value != NULL ? value : "";
-                               return 1;
+                               return ret;
                        }
                }
        }
index e93884fd80f78bbb54902f5e815691776e0d8cf6..40798b0a58089a268fc3f61ea11fa72adc8d4ca9 100644 (file)
@@ -9,14 +9,17 @@ struct var_expand_table {
 
 struct var_expand_func_table {
        const char *key;
-       /* %{key:data}, or data is "" with %{key}, */
-       const char *(*func)(const char *data, void *context);
+       /* %{key:data}, or data is "" with %{key}.
+          Returns 1 on success, 0 if data is invalid, -1 on temporary error. */
+       int (*func)(const char *data, void *context,
+                   const char **value_r, const char **error_r);
 };
 
 /* Expand % variables in src and append the string in dest.
    table must end with key = 0. Returns 1 on success, 0 if the format string
-   contained invalid/unknown %variables. Even in case of errors the dest string
-   is still written as fully as possible. */
+   contained invalid/unknown %variables, -1 if one of the functions returned
+   temporary error. Even in case of errors the dest string is still written as
+   fully as possible. */
 int var_expand(string_t *dest, const char *str,
               const struct var_expand_table *table,
               const char **error_r);
index 44377998ae0ebfc533d669d0c42b424172a563b8..b08cddc4e06ed2ade9dfead7e66cd4f2c3493bf3 100644 (file)
@@ -600,24 +600,30 @@ static bool have_username_key(const char *str)
        return FALSE;
 }
 
-static const char *
-client_var_expand_func_passdb(const char *data, void *context)
+static int
+client_var_expand_func_passdb(const char *data, void *context,
+                             const char **value_r,
+                             const char **error_r ATTR_UNUSED)
 {
        struct client *client = context;
        const char *field_name = data;
        unsigned int i, field_name_len;
 
+       *value_r = NULL;
+
        if (client->auth_passdb_args == NULL)
-               return NULL;
+               return 1;
 
        field_name_len = strlen(field_name);
        for (i = 0; client->auth_passdb_args[i] != NULL; i++) {
                if (strncmp(client->auth_passdb_args[i], field_name,
                            field_name_len) == 0 &&
-                   client->auth_passdb_args[i][field_name_len] == '=')
-                       return client->auth_passdb_args[i] + field_name_len+1;
+                   client->auth_passdb_args[i][field_name_len] == '=') {
+                       *value_r = client->auth_passdb_args[i] + field_name_len+1;
+                       return 1;
+               }
        }
-       return NULL;
+       return 1;
 }
 
 static const char *