None of the existing functions were changed to return errors (yet).
}
}
-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, ':');
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[] = {
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();
}
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;
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,
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;
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,
}
}
-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;
/* 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[] = {
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
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)
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)
{ "%{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 }
{ "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);
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);
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;
}
}
}
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);
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 *