Skip to content

Commit

Permalink
lib: API change - var_expand_func_table.func() can now return error.
Browse files Browse the repository at this point in the history
None of the existing functions were changed to return errors (yet).
  • Loading branch information
sirainen committed Nov 2, 2016
1 parent 0f5dc4d commit bcf1cf2
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 61 deletions.
22 changes: 14 additions & 8 deletions src/auth/auth-request-var-expand.c
Expand Up @@ -195,29 +195,35 @@ 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, ':');
const char *value;

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[] = {
Expand Down
23 changes: 14 additions & 9 deletions src/auth/db-dict.c
Expand Up @@ -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();
}
Expand Down
48 changes: 32 additions & 16 deletions src/auth/db-ldap.c
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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[] = {
Expand Down
9 changes: 6 additions & 3 deletions src/lib-storage/mail-storage-service.c
Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions src/lib-storage/mail-user.c
Expand Up @@ -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)
Expand Down
51 changes: 42 additions & 9 deletions src/lib/test-var-expand.c
Expand Up @@ -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)
Expand All @@ -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 }
Expand All @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions src/lib/var-expand.c
Expand Up @@ -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);
Expand All @@ -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;
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions src/lib/var-expand.h
Expand Up @@ -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);
Expand Down

0 comments on commit bcf1cf2

Please sign in to comment.