#include "hash.h"
#include "str.h"
#include "strescape.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "auth-request.h"
#include "auth-cache.h"
#define AUTH_COMMON_H
#include "lib.h"
-#include "var-expand-new.h"
#include "auth.h"
#include "connection.h"
.event = auth_request->event,
};
- return var_expand_new(dest, str, ¶ms, error_r);
+ return var_expand(dest, str, ¶ms, error_r);
}
int t_auth_request_var_expand(const char *str,
#include "array.h"
#include "net.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "mech.h"
#include "userdb.h"
#include "passdb.h"
#define DB_LDAP_IDLE_RECONNECT_SECS 60
#include <ldap.h>
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "db-ldap-settings.h"
#define DB_LDAP_ATTR_MULTI_PREFIX "+"
.event = req->auth_request->event,
};
- if (var_expand_new(username_val, req->db->set->username_validation_format,
- ¶ms, &error) < 0) {
+ if (var_expand(username_val, req->db->set->username_validation_format,
+ ¶ms, &error) < 0) {
*error_r = t_strdup_printf("var_expand(%s) failed: %s",
req->db->set->username_validation_format, error);
*result_r = PASSDB_RESULT_INTERNAL_FAILURE;
VAR_EXPAND_TABLE_END
},
};
- return var_expand_new(dest, str, ¶ms, error_r);
+ return var_expand(dest, str, ¶ms, error_r);
}
static void test_auth_cache_parse_key(void)
const char *error;
str_truncate(str, 0);
- test_assert(var_expand_new(str, input, ¶ms, &error) == 0);
+ test_assert(var_expand(str, input, ¶ms, &error) == 0);
return strspn(str_c(str), "\n0") == str_len(str);
}
.escape_context = &test_request,
};
- test_assert(var_expand_new(str, test_input_long, ¶ms, &error) == 0);
+ test_assert(var_expand(str, test_input_long, ¶ms, &error) == 0);
test_assert_strcmp(str_c(str), test_output);
/* test with empty input that it won't crash */
.escape_func = (var_expand_escape_func_t *)test_escape,
.escape_context = &test_request
};
- test_assert(var_expand_new(str, test_input, ¶ms, &error) == 0);
+ test_assert(var_expand(str, test_input, ¶ms, &error) == 0);
test_assert_strcmp(str_c(str), "40\n\n\n");
test_request.userdb_lookup = TRUE;
params.table = auth_request_get_var_expand_table(&test_request);
str_truncate(str, 0);
- test_assert(var_expand_new(str, test_input, ¶ms, &error) == 0);
+ test_assert(var_expand(str, test_input, ¶ms, &error) == 0);
test_assert_strcmp(str_c(str), "41\nsecured\nvalid\n");
test_assert(test_empty_request(str, test_input));
.escape_context = &test_request,
};
- test_assert(var_expand_new(str, test_input, ¶ms, &error) == 0);
+ test_assert(var_expand(str, test_input, ¶ms, &error) == 0);
test_assert_strcmp(str_c(str), test_output);
test_assert(test_empty_request(str, test_input));
.escape_context = &test_request,
};
str_truncate(str, 0);
- test_assert(var_expand_new(str, test_input, ¶ms, &error) == 0);
+ test_assert(var_expand(str, test_input, ¶ms, &error) == 0);
test_assert_idx(strcmp(str_c(str), tests[i].output) == 0, i);
}
test_request.fields.user = default_test_request.fields.user;
print '#include "array.h"'."\n";
print '#include "str.h"'."\n";
print '#include "ipwd.h"'."\n";
-print '#include "var-expand-new.h"'."\n";
+print '#include "var-expand.h"'."\n";
print '#include "file-lock.h"'."\n";
print '#include "fsync-mode.h"'."\n";
print '#include "hash-format.h"'."\n";
#include "ioloop.h"
#include "array.h"
#include "str.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "wildcard-match.h"
#include "settings-parser.h"
#include "master-service.h"
string_t *str = t_str_new(128);
const struct var_expand_params *params =
mail_user_var_expand_params(user);
- if (var_expand_new(str, expand_field, params, &error) < 0) {
+ if (var_expand(str, expand_field, params, &error) < 0) {
json_ostream_nwritef_string(json_output,
"error", "Failed to expand field: %s", error);
} else {
#include "hex-binary.h"
#include "str.h"
#include "strescape.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "wildcard-match.h"
#include "dsasl-client.h"
#include "settings-parser.h"
string_t *str = t_str_new(128);
const struct var_expand_params *params =
mail_user_var_expand_params(user);
- if (var_expand_new(str, expand_field, params, &error) < 0) {
+ if (var_expand(str, expand_field, params, &error) < 0) {
e_error(event, "Failed to expand %s: %s", expand_field, error);
} else {
printf("%s\n", str_c(str));
#include "strescape.h"
#include "str-parse.h"
#include "env-util.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "process-title.h"
#include "settings.h"
#include "imap-util.h"
text in the parameter, skip it. */
str_truncate(str, 0);
str_truncate(str2, 0);
- if (var_expand_new(str, *args, ¶ms, &error) < 0 ||
- var_expand_new(str2, *args, &static_params, &error) < 0) {
+ if (var_expand(str, *args, ¶ms, &error) < 0 ||
+ var_expand(str2, *args, &static_params, &error) < 0) {
e_error(event,
"Failed to expand dsync_remote_cmd=%s: %s",
*args, error);
#include "doveadm-print.h"
#include "doveadm-print-private.h"
#include "client-connection.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
struct doveadm_print_formatted_context {
pool_t pool;
const struct var_expand_params params = {
.table = array_front(&ctx.headers),
};
- if (var_expand_new(ctx.buf, ctx.format, ¶ms, &error) < 0) {
+ if (var_expand(ctx.buf, ctx.format, ¶ms, &error) < 0) {
i_error("Failed to expand print format '%s': %s",
ctx.format, error);
}
#include "str.h"
#include "strescape.h"
#include "time-util.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "imap-keepalive.h"
string_t *str;
str = t_str_new(256);
- if (var_expand_new(str, state->mail_log_prefix, ¶ms, &error) < 0) {
+ if (var_expand(str, state->mail_log_prefix, ¶ms, &error) < 0) {
e_error(client->event,
"Failed to expand mail_log_prefix=%s: %s",
state->mail_log_prefix, error);
#include "ostream-multiplex.h"
#include "time-util.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "master-service.h"
#include "imap-resp-code.h"
#include "imap-util.h"
event_add_int(client->event, "net_out_bytes", client->output->offset);
str = t_str_new(128);
- if (var_expand_new(str, client->set->imap_logout_format,
+ if (var_expand(str, client->set->imap_logout_format,
¶ms, &error) < 0) {
e_error(client->event,
"Failed to expand imap_logout_format=%s: %s",
#include "str.h"
#include "istream.h"
#include "ostream.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "connection.h"
#include "llist.h"
#include "ldap-client.h"
.table = array_front(&exp),
};
- if (var_expand_new(query_r, template, ¶ms, &error) < 0) {
+ if (var_expand(query_r, template, ¶ms, &error) < 0) {
*error_r = t_strdup_printf("Failed to expand %s: %s", template, error);
return FALSE;
}
#include "mail-storage-settings.h"
#include "smtp-submit-settings.h"
#include "lda-settings.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
static bool lda_settings_check(void *_set, pool_t pool, const char **error_r);
#include "str-sanitize.h"
#include "time-util.h"
#include "unichar.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "message-address.h"
#include "smtp-address.h"
#include "lda-settings.h"
.table = mail_deliver_ctx_get_log_var_expand_table(ctx, msg),
.event = ctx->event,
};
- if (var_expand_new(str, ctx->set->deliver_log_format,
+ if (var_expand(str, ctx->set->deliver_log_format,
¶ms, &error) < 0) {
e_error(ctx->event,
"Failed to expand deliver_log_format=%s: %s",
#include "ostream.h"
#include "str.h"
#include "str-sanitize.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "message-date.h"
#include "message-size.h"
#include "message-address.h"
ctx->dsn ? "delivery-status" : "disposition-notification",
boundary);
str_append(str, "Subject: ");
- if (var_expand_new(str, ctx->set->rejection_subject,
- ¶ms, &error) < 0) {
+ if (var_expand(str, ctx->set->rejection_subject,
+ ¶ms, &error) < 0) {
e_error(ctx->event,
"Failed to expand rejection_subject=%s: %s",
ctx->set->rejection_subject, error);
str_append(str, "Content-Disposition: inline\r\n");
str_append(str, "Content-Transfer-Encoding: 8bit\r\n\r\n");
- if (var_expand_new(str, ctx->set->rejection_reason,
- ¶ms, &error) < 0) {
+ if (var_expand(str, ctx->set->rejection_reason,
+ ¶ms, &error) < 0) {
e_error(ctx->event,
"Failed to expand rejection_reason=%s: %s",
ctx->set->rejection_reason, error);
#include "master-service-ssl.h"
#include "master-service-settings.h"
#include "iostream-ssl.h"
-#include "var-expand-new.h"
#include <getopt.h>
#include <unistd.h>
key = *envs;
else {
key = t_strdup_until(*envs, value++);
- if (var_expand_new(expanded, value, NULL, &error) < 0)
+ if (var_expand(expanded, value, NULL, &error) < 0)
i_fatal("Cannot expand variable %s", value);
if (str_len(expanded) > 0) {
value = str_c(expanded);
#include "wildcard-match.h"
#include "mmap-util.h"
#include "settings.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
enum set_seen_type {
/* Setting has not been changed */
/* Make sure only the file path is var-expanded. */
value = file.path;
}
- if (var_expand_new(ctx->str, value, &ctx->var_params, &error) < 0 &&
+ if (var_expand(ctx->str, value, &ctx->var_params, &error) < 0 &&
(ctx->flags & SETTINGS_GET_FLAG_FAKE_EXPAND) == 0) {
*error_r = t_strdup_printf(
"Failed to expand %s setting variables: %s",
if ((ctx->flags & SETTINGS_GET_FLAG_NO_EXPAND) == 0) {
const char *error;
str_truncate(ctx->str, 0);
- if (var_expand_new(ctx->str, value, &ctx->var_params, &error) < 0 &&
+ if (var_expand(ctx->str, value, &ctx->var_params, &error) < 0 &&
(ctx->flags & SETTINGS_GET_FLAG_FAKE_EXPAND) == 0) {
*error_r = t_strdup_printf(
"Failed to expand default setting %s=%s variables: %s",
or with SETTINGS_OVERRIDE_TYPE_2ND_DEFAULT. */
const char *error;
str_truncate(ctx->str, 0);
- if (var_expand_new(ctx->str, value, &ctx->var_params, &error) < 0 &&
+ if (var_expand(ctx->str, value, &ctx->var_params, &error) < 0 &&
(ctx->flags & SETTINGS_GET_FLAG_FAKE_EXPAND) == 0) {
*error_r = t_strdup_printf(
"Failed to expand default setting %s=%s variables: %s",
#ifndef SETTINGS_H
#define SETTINGS_H
+#include "var-expand.h"
#include "settings-parser.h"
-typedef const char *var_expand_escape_func_t(const char *str, void *context);
-
struct settings_root;
struct settings_mmap;
struct settings_instance;
-struct var_expand_params_new;
+struct var_expand_params;
enum settings_override_type {
/* Setting is a built-in default. This is used only when the defaults
"settings_var_expand_callback_context"
/* Callback function used with SETTINGS_EVENT_VAR_EXPAND_CALLBACK. */
typedef void
-settings_var_expand_t(void *context, struct var_expand_params_new *params_r);
+settings_var_expand_t(void *context, struct var_expand_params *params_r);
/* Get the wanted settings and check that the settings are valid.
The settings struct must have pool_t (info->pool_offset1), which the caller
#include "lib.h"
#include "array.h"
#include "net.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "settings-parser.h"
#include "test-common.h"
#include "time-util.h"
#include "safe-memset.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "ssl-settings.h"
#include "sql-api-private.h"
.event = db->api.event,
};
- if (var_expand_new(path, db->set->metrics_path, ¶ms, &error) < 0) {
+ if (var_expand(path, db->set->metrics_path, ¶ms, &error) < 0) {
e_error(db->api.event, "Failed to expand metrics_path=%s: %s",
db->set->metrics_path, error);
return;
#include "str.h"
#include "ioloop.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "index-storage.h"
#include "mail-storage-service.h"
#include "mailbox-list-private.h"
#include "sleep.h"
#include "dict.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "auth-master.h"
#include "master-service-private.h"
#include "mail-user.h"
#include "unichar.h"
#include "hostpid.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "message-address.h"
#include "message-header-parser.h"
#include "smtp-address.h"
#include "mkdir-parents.h"
#include "time-util.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "dsasl-client.h"
#include "imap-date.h"
#include "mail-index-private.h"
#include "str.h"
#include "istream.h"
#include "array.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "dlua-script.h"
#include "dlua-script-private.h"
#include "mail-storage.h"
const char *format = luaL_checkstring(L, 2);
const struct var_expand_params *params = mail_user_var_expand_params(user);
string_t *str = t_str_new(128);
- if (var_expand_new(str, format, params, &error) < 0) {
+ if (var_expand(str, format, params, &error) < 0) {
return luaL_error(L, "var_expand(%s) failed: %s",
format, error);
}
#include "strescape.h"
#include "strfuncs.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "fs-api.h"
#include "auth-master.h"
#include "master-service.h"
for (i = 0; i < count; i += 2) {
str_truncate(str, 0);
- if (var_expand_new(str, envs[i+1], params, &error) < 0) {
+ if (var_expand(str, envs[i+1], params, &error) < 0) {
user->error = p_strdup_printf(user->pool,
"Failed to expand plugin setting %s = '%s': %s",
envs[i], envs[i+1], error);
this stays the same after IMAP client is hibernated and restored. */
time_t session_create_time;
- const struct var_expand_params_new *var_expand_params;
+ const struct var_expand_params *var_expand_params;
/* If non-NULL, fail the user initialization with this error.
This could be set by plugins that need to fail the initialization. */
const char *error;
void mail_user_set_vars(struct mail_user *user, const char *service,
const struct mail_user_connection_data *conn);
/* Return %variable expansion table for the user. */
-const struct var_expand_params_new *
+const struct var_expand_params *
mail_user_var_expand_params(struct mail_user *user);
/* Specify the user's home directory. This should be called also with home=NULL
expansion.h
headers = \
- var-expand-new.h \
+ var-expand.h \
var-expand-private.h
pkginc_libdir=$(pkgincludedir)
const struct var_expand_test tests[],
size_t test_count)
{
- string_t *dest = str_new(default_pool, 128);
+ string_t *dest= str_new(default_pool, 128);
for (size_t i = 0; i < test_count; i++) {
const struct var_expand_test *test = &tests[i];
const char *error = NULL;
str_truncate(dest, 0);
- int ret = var_expand_new(dest, test->in, params, &error);
+ int ret = var_expand(dest, test->in, params, &error);
test_assert_cmp_idx(test->ret, ==, ret, i);
if (ret < 0) {
}
-static void test_var_expand_new_builtin_filters(void) {
+static void test_var_expand_builtin_filters(void) {
test_begin("var_expand(buildin filters)");
const struct var_expand_table table[] = {
test_end();
}
-static void test_var_expand_new_math(void) {
+static void test_var_expand_math(void) {
test_begin("var_expand(math)");
const struct var_expand_table table[] = {
test_end();
}
-static void test_var_expand_new_if(void)
+static void test_var_expand_if(void)
{
test_begin("var_expand(if)");
return 0;
}
-static void test_var_expand_new_providers(void) {
+static void test_var_expand_providers(void) {
test_begin("var_expand(providers)");
int ncpus;
const char *error ATTR_UNUSED;
if (uname(&utsname_result) == 0) {
string_t *dest = t_str_new(32);
str_truncate(dest, 0);
- test_assert(var_expand_new(dest, "%{system:os}", ¶ms, &error) == 0);
+ test_assert(var_expand(dest, "%{system:os}", ¶ms, &error) == 0);
test_assert_strcmp(utsname_result.sysname, str_c(dest));
str_truncate(dest, 0);
- test_assert(var_expand_new(dest, "%{system:os-version}", ¶ms, &error) == 0);
+ test_assert(var_expand(dest, "%{system:os-version}", ¶ms, &error) == 0);
test_assert_strcmp(utsname_result.release, str_c(dest));
}
test_end();
}
-static void test_var_expand_new_provider_arr(void)
+static void test_var_expand_provider_arr(void)
{
test_begin("var_expand(provider arr)");
const struct var_expand_test tests[] = {
test_end();
}
-static void test_var_expand_new_tables_arr(void)
+static void test_var_expand_tables_arr(void)
{
test_begin("var_expand(tables_arr)");
string_t *dest = t_str_new(32);
const char *error;
- int ret = var_expand_new(dest, "I am %{name} and %{age} years old",
+ int ret = var_expand(dest, "I am %{name} and %{age} years old",
¶ms, &error);
test_assert(ret == 0);
return str_c(dest);
}
-static void test_var_expand_new_escape(void)
+static void test_var_expand_escape(void)
{
const struct var_expand_table table[] = {
{ .key = "clean", .value = "hello world", },
.escape_context = "'",
};
- test_begin("var_expand_new(escape)");
+ test_begin("var_expand(escape)");
run_var_expand_tests(¶ms, tests, N_ELEMENTS(tests));
return 0;
}
-static void test_var_expand_new_value_func(void)
+static void test_var_expand_value_func(void)
{
const struct var_expand_table table[] = {
{ .key = "first", .value = "hello", },
.context = "test",
};
- test_begin("var_expand_new(value func)");
+ test_begin("var_expand(value func)");
run_var_expand_tests(¶ms, tests, N_ELEMENTS(tests));
test_end();
}
-static void test_var_expand_new_value_func_arr(void)
+static void test_var_expand_value_func_arr(void)
{
const struct var_expand_table table[] = {
{ .key = "first", .value = "hello", },
test_begin("var_expand_merge_tables");
- merged = var_expand_merge_tables_new(pool_datastack_create(), one, two);
+ merged = var_expand_merge_tables(pool_datastack_create(), one, two);
- test_assert(var_expand_table_size_new(merged) == 4);
- for (unsigned int i = 0; i < var_expand_table_size_new(merged); i++) {
+ test_assert(var_expand_table_size(merged) == 4);
+ for (unsigned int i = 0; i < var_expand_table_size(merged); i++) {
if (i < 2) {
test_assert_idx(merged[i].value == one[i].value || strcmp(merged[i].value, one[i].value) == 0, i);
test_assert_idx(merged[i].key == one[i].key || strcmp(merged[i].key, one[i].key) == 0, i);
test_end();
}
-static void test_var_expand_new_variables(void)
+static void test_var_expand_variables(void)
{
test_begin("var_expand(variables)");
}
-static void test_var_expand_new_parameter_sorted(void)
+static void test_var_expand_parameter_sorted(void)
{
const struct var_expand_test tests[] = {
{ .in = "%{test_filter}", .out ="done", .ret = 0 },
test_end();
}
-static void test_var_expand_new_perc(void)
+static void test_var_expand_perc(void)
{
test_begin("var_expand(percentage handling)");
test_end();
}
-static void test_var_expand_new_set_copy(void)
+static void test_var_expand_set_copy(void)
{
test_begin("var_expand(set, copy)");
struct var_expand_table tab[] = {
{
void (*const tests[])(void) = {
test_var_expand_merge_tables,
- test_var_expand_new_builtin_filters,
- test_var_expand_new_math,
- test_var_expand_new_if,
- test_var_expand_new_providers,
- test_var_expand_new_provider_arr,
- test_var_expand_new_tables_arr,
- test_var_expand_new_escape,
- test_var_expand_new_value_func,
- test_var_expand_new_value_func_arr,
- test_var_expand_new_variables,
- test_var_expand_new_parameter_sorted,
- test_var_expand_new_perc,
- test_var_expand_new_set_copy,
+ test_var_expand_builtin_filters,
+ test_var_expand_math,
+ test_var_expand_if,
+ test_var_expand_providers,
+ test_var_expand_provider_arr,
+ test_var_expand_tables_arr,
+ test_var_expand_escape,
+ test_var_expand_value_func,
+ test_var_expand_value_func_arr,
+ test_var_expand_variables,
+ test_var_expand_parameter_sorted,
+ test_var_expand_perc,
+ test_var_expand_set_copy,
NULL
};
#ifndef VAR_EXPAND_PRIVATE_H
#define VAR_EXPAND_PRIVATE_H 1
-#include "var-expand-new.h"
+#include "var-expand.h"
/* Macro for filters to error our with unsupported key */
#define ERROR_UNSUPPORTED_KEY(key) STMT_START { \
}
struct var_expand_table *
-var_expand_merge_tables_new(pool_t pool, const struct var_expand_table *a,
+var_expand_merge_tables(pool_t pool, const struct var_expand_table *a,
const struct var_expand_table *b)
{
ARRAY(struct var_expand_table) table;
- size_t a_size = var_expand_table_size_new(a);
- size_t b_size = var_expand_table_size_new(b);
+ size_t a_size = var_expand_table_size(a);
+ size_t b_size = var_expand_table_size(b);
p_array_init(&table, pool, a_size + b_size + 1);
for (size_t i = 0; i < a_size; i++) {
struct var_expand_table *entry =
}
}
-int var_expand_new(string_t *dest, const char *str,
- const struct var_expand_params *params,
- const char **error_r)
+int var_expand(string_t *dest, const char *str,
+ const struct var_expand_params *params,
+ const char **error_r)
{
struct var_expand_program *program = NULL;
if (var_expand_program_create(str, &program, error_r) != 0)
#define VAR_EXPAND_TABLE_END { .key = NULL }
#define VAR_EXPAND_CONTEXTS_END (void*)var_expand_contexts_end
-struct var_expand_table_new {
+struct var_expand_table {
/* Key name, as in %{key} */
const char *key;
/* Value to expand into */
/* Or function that provides the value */
value_provider_func_t *func;
};
-#define var_expand_table var_expand_table_new
struct var_expand_provider {
/* key as in %{key:name} */
extern const void *const var_expand_contexts_end;
-struct var_expand_params_new {
+struct var_expand_params {
/* Variables to use, must end with VAR_EXPAND_TABLE_END,
asserts that tables_arr is non-NULL. */
const struct var_expand_table *table;
will be attempted if this is NULL. */
struct event *event;
};
-#define var_expand_params var_expand_params_new
/* Creates a new expansion program for reusing */
int var_expand_program_create(const char *str, struct var_expand_program **program_r,
/* Creates a new program, executes it and frees it. Params can be left NULL, in which
case empty parameters are used. */
-int var_expand_new(string_t *dest, const char *str, const struct var_expand_params *params,
- const char **error_r) ATTR_NULL(3);
+int var_expand(string_t *dest, const char *str, const struct var_expand_params *params,
+ const char **error_r) ATTR_NULL(3);
/* Wrapper for var_expand(), places the result into result_r. */
int t_var_expand(const char *str, const struct var_expand_params *params,
/* Merge two tables together, keys in table a will be overwritten with keys
* from table b in collision. */
struct var_expand_table *
-var_expand_merge_tables_new(pool_t pool, const struct var_expand_table *a,
- const struct var_expand_table *b);
+var_expand_merge_tables(pool_t pool, const struct var_expand_table *a,
+ const struct var_expand_table *b);
/* Returns true if provider is a built-in provider */
bool var_expand_provider_is_builtin(const char *prefix);
/* Provides size of a table */
static inline size_t ATTR_PURE
-var_expand_table_size_new(const struct var_expand_table *table)
+var_expand_table_size(const struct var_expand_table *table)
{
size_t n = 0;
while (table != NULL && table[n].key != NULL)
uri-util.c \
utc-offset.c \
utc-mktime.c \
- var-expand.c \
- var-expand-if.c \
wildcard-match.c \
write-full.c
uri-util.h \
utc-offset.h \
utc-mktime.h \
- var-expand.h \
- var-expand-private.h \
wildcard-match.h \
write-full.h
test-unichar.c \
test-utc-mktime.c \
test-uri.c \
- test-var-expand.c \
test-wildcard-match.c
test_headers = \
#include "ipwd.h"
#include "process-title.h"
#include "restrict-access.h"
-#include "var-expand-private.h"
#include "randgen.h"
#include <fcntl.h>
lib_open_non_stdio_dev_null();
lib_event_init();
event_filter_init();
- var_expand_extensions_init();
/* Default to clean exit. Otherwise there would be too many accidents
with e.g. command line parsing errors that try to return instead
lib_atexit_run();
ipwd_deinit();
hostpid_deinit();
- var_expand_extensions_deinit();
event_filter_deinit();
data_stack_deinit_event();
lib_event_deinit();
TEST(test_unichar)
TEST(test_uri)
TEST(test_utc_mktime)
-TEST(test_var_expand)
TEST(test_wildcard_match)
+++ /dev/null
-/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
-
-#include "test-lib.h"
-#include "cpu-count.h"
-#include "str.h"
-#include "env-util.h"
-#include "hostpid.h"
-#include "var-expand.h"
-#include "var-expand-private.h"
-#include "dovecot-version.h"
-
-#include <unistd.h>
-#ifdef HAVE_SYS_UTSNAME_H
-# include <sys/utsname.h>
-#endif
-
-struct var_expand_test {
- const char *in;
- const char *out;
- int ret;
-};
-
-struct var_get_key_range_test {
- const char *in;
- unsigned int idx, size;
-};
-
-static void test_var_expand_ranges(void)
-{
- static const struct var_expand_test tests[] = {
- { "%v", "value1234", 1 },
- { "%3v", "val", 1 },
- { "%3.2v", "ue", 1 },
- { "%3.-2v", "ue12", 1 },
- { "%-3.2v", "23", 1 },
- { "%0.-1v", "value123", 1 },
- { "%-4.-1v", "123", 1 }
- };
- static const struct var_expand_table table[] = {
- { 'v', "value1234", NULL },
- { '\0', NULL, NULL }
- };
- string_t *str = t_str_new(128);
- const char *error;
- unsigned int i;
-
- test_begin("var_expand - ranges");
- for (i = 0; i < N_ELEMENTS(tests); i++) {
- str_truncate(str, 0);
- test_assert(var_expand_with_table(str, tests[i].in, table, &error) == tests[i].ret);
- test_assert(strcmp(tests[i].out, str_c(str)) == 0);
- }
- test_end();
-}
-
-static void test_var_expand_builtin(void)
-{
- static struct var_expand_test tests[] = {
- { "%{system:hostname}", NULL, 1 },
- { "%{process:pid}", NULL, 1 },
- { "%{process:uid}", NULL, 1 },
- { "%{process:gid}", NULL, 1 },
- { "a%{env:FOO}b", "abaRb", 1 },
- { "%50Hv", "1f", 1 },
- { "%50Hw", "2e", 1 },
- { "%50Nv", "25", 1 },
- { "%50Nw", "e", 1 },
-
- { "%{nonexistent}", "UNSUPPORTED_VARIABLE_nonexistent", 0 },
- { "%1.2M{nonexistent:default}", "UNSUPPORTED_VARIABLE_nonexistent", 0 },
- { "%x", "UNSUPPORTED_VARIABLE_x", 0 },
- { "%5Mm", "UNSUPPORTED_VARIABLE_m", 0 },
-
- { "%", "", -1 },
- };
- static const struct var_expand_table table[] = {
- { 'v', "value", NULL },
- { 'w', "value2", NULL },
- { '\0', NULL, NULL }
- };
- string_t *str = t_str_new(128);
- const char *error;
- unsigned int i;
-
- tests[0].out = my_hostname;
- tests[1].out = my_pid;
- tests[2].out = dec2str(geteuid());
- tests[3].out = dec2str(getegid());
- env_put("FOO", "baR");
-
- test_begin("var_expand - builtin");
- for (i = 0; i < N_ELEMENTS(tests); i++) {
- str_truncate(str, 0);
- test_assert_idx(var_expand_with_table(str, tests[i].in, table, &error) == tests[i].ret, i);
- test_assert_strcmp_idx(tests[i].out, str_c(str), i);
- }
- test_end();
-}
-
-static void test_var_get_key_range(void)
-{
- static const struct var_get_key_range_test tests[] = {
- { "", 0, 0 },
- { "{", 1, 0 },
- { "k", 0, 1 },
- { "{key}", 1, 3 },
- { "5.5Rk", 4, 1 },
- { "5.5R{key}", 5, 3 },
- { "{key", 1, 3 },
- { "{if;%{if;%{value};eq;value;t;f};eq;t;t;f}", 1, 39 },
- };
- unsigned int i, idx, size;
-
- test_begin("var_get_key_range");
- for (i = 0; i < N_ELEMENTS(tests); i++) {
- var_get_key_range(tests[i].in, &idx, &size);
- test_assert_idx(tests[i].idx == idx, i);
- test_assert_idx(tests[i].size == size, i);
-
- if (tests[i].size == 1)
- test_assert_idx(tests[i].in[idx] == var_get_key(tests[i].in), i);
- }
- test_end();
-}
-
-static int test_var_expand_func0(const char *data ATTR_UNUSED,
- void *context ATTR_UNUSED,
- const char **value_r,
- const char **error_r ATTR_UNUSED)
-{
- *value_r = "0";
- return 1;
-}
-
-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);
- *value_r = t_strdup_printf("<%s>", data);
- return 1;
-}
-
-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)
-{
- *value_r = "";
- return 1;
-}
-
-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)
-{
- *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)
-{
- static const struct var_expand_test tests[] = {
- { "%f", "0", 1 },
- { "%{func1}", "<>", 1 },
- { "%{func1:foo}", "<foo>", 1 },
- { "%{func2}", "", 1 },
- { "%{func3}", "", 1 },
- { "%{func4}", "", 0 },
- { "%{func5}", "", -1 },
- { "%{func4}%{func5}", "", -1 },
- { "%{func5}%{func4}%{func3}", "", -1 },
- };
- static const struct var_expand_table table[] = {
- { '\0', NULL, NULL }
- };
- static const struct var_expand_func_table func_table[] = {
- { "f", test_var_expand_func0 },
- { "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 *error;
- unsigned int i;
- int ctx = 0xabcdef;
-
- test_begin("var_expand_with_funcs");
- for (i = 0; i < N_ELEMENTS(tests); i++) {
- str_truncate(str, 0);
- test_assert_idx(var_expand_with_funcs(str, tests[i].in, table, func_table, &ctx, &error) == tests[i].ret, i);
- test_assert_idx(strcmp(tests[i].out, str_c(str)) == 0, i);
- }
- test_end();
-}
-
-static int
-test_var_expand_arrays_func1(const char *data ATTR_UNUSED, void *context,
- const char **value_r,
- const char **error_r ATTR_UNUSED)
-{
- test_assert(strcmp(context, "context1") == 0);
- *value_r = context;
- return 1;
-}
-
-static int
-test_var_expand_arrays_func2(const char *data ATTR_UNUSED, void *context,
- const char **value_r,
- const char **error_r ATTR_UNUSED)
-{
- test_assert(strcmp(context, "context2") == 0);
- *value_r = context;
- return 1;
-}
-
-static void test_var_expand_with_arrays(void)
-{
- static const struct var_expand_table table1[] = {
- { 'f', "firstvalue", "first" },
- { '\0', NULL, NULL }
- };
- static const struct var_expand_table table2[] = {
- { 's', "secondvalue", "second" },
- { '\0', NULL, NULL }
- };
- static const struct var_expand_func_table func_table1[] = {
- { "func1", test_var_expand_arrays_func1 },
- { NULL, NULL }
- };
- static const struct var_expand_func_table func_table2[] = {
- { "func2", test_var_expand_arrays_func2 },
- { NULL, NULL }
- };
-
- static const struct var_expand_table *tables[] = {
- table1, table2, NULL
- };
- static const struct var_expand_params_func funcs[] = {
- { func_table1, "context1", },
- { func_table2, "context2", },
- { NULL, NULL }
- };
- const char *input = "%f, %s, %{first}, %{second}, %{func1}, %{func2}";
- const char *output = "firstvalue, secondvalue, firstvalue, secondvalue, context1, context2";
- string_t *str = t_str_new(128);
- const char *error;
-
- test_begin("var_expand_with_arrays");
- test_assert(var_expand_with_arrays(str, input, tables, funcs, &error) == 1);
- test_assert_strcmp(str_c(str), output);
- test_end();
-}
-
-static void test_var_get_key(void)
-{
- static const struct {
- const char *str;
- char key;
- } tests[] = {
- { "x", 'x' },
- { "2.5Mx", 'x' },
- { "200MDx", 'x' },
- { "200MD{foo}", '{' },
- { "{foo}", '{' },
- { "", '\0' },
- };
-
- test_begin("var_get_key");
- for (unsigned int i = 0; i < N_ELEMENTS(tests); i++)
- test_assert_idx(var_get_key(tests[i].str) == tests[i].key, i);
- test_end();
-}
-
-static void test_var_has_key(void)
-{
- static const struct {
- const char *str;
- char key;
- const char *long_key;
- bool result;
- } tests[] = {
- { "%x%y", 'x', NULL, TRUE },
- { "%x%y", 'y', NULL, TRUE },
- { "%x%y", 'z', NULL, FALSE },
- { "%{foo}", 'f', NULL, FALSE },
- { "%{foo}", 'o', NULL, FALSE },
- { "%{foo}", '\0', "foo", TRUE },
- { "%{foo}", 'o', "foo", TRUE },
- { "%2.5Mx%y", 'x', NULL, TRUE },
- { "%2.5M{foo}", '\0', "foo", TRUE },
- };
-
- test_begin("var_has_key");
- for (unsigned int i = 0; i < N_ELEMENTS(tests); i++)
- test_assert_idx(var_has_key(tests[i].str, tests[i].key, tests[i].long_key) == tests[i].result, i);
- test_end();
-}
-
-static int test_var_expand_hashing_func1(const char *data,
- void *context ATTR_UNUSED,
- const char **value_r,
- const char **error_r ATTR_UNUSED)
-{
- *value_r = data;
- return 1;
-}
-
-static int test_var_expand_bad_func(struct var_expand_context *ctx ATTR_UNUSED,
- const char *key,
- const char *field ATTR_UNUSED,
- const char **result_r ATTR_UNUSED,
- const char **error_r)
-{
- if (strcmp(key, "notfound") == 0) {
- *error_r = "Invalid field";
- return 0;
- }
- *error_r = "Bad parameters";
- return -1;
-}
-
-static const struct var_expand_extension_func_table test_extension_funcs[] = {
- { "notfound", test_var_expand_bad_func },
- { "badparam", test_var_expand_bad_func },
- { NULL, NULL }
-};
-
-static void test_var_expand_extensions(void)
-{
- const char *error;
- test_begin("var_expand_extensions");
-
- var_expand_register_func_array(test_extension_funcs);
-
- static const struct var_expand_table table[] = {
- {'\0', "example", "value" },
- {'\0', "other-example", "other-value" },
- {'\0', NULL, NULL}
- };
-
- static const struct {
- const char *in;
- const char *out;
- } tests[] = {
- { "md5: %M{value} %{md5:value}", "md5: 1a79a4d60de6718e8e5b326e338ae533 1a79a4d60de6718e8e5b326e338ae533" },
- { "sha1: %{sha1:value}", "sha1: c3499c2729730a7f807efb8676a92dcb6f8a3f8f" },
- { "sha1: %{sha1:func1:example}", "sha1: c3499c2729730a7f807efb8676a92dcb6f8a3f8f" },
- { "truncate: %{sha1;truncate=12:value}", "truncate: 0c34" },
- { "truncate: %{sha1;truncate=16:value}", "truncate: c349" },
- { "rounds,salt: %{sha1;rounds=1000,salt=seawater:value}", "rounds,salt: b515c85884f6b82dc7588279f3643a73e55d2289" },
- { "rounds,salt,expand: %{sha1;rounds=1000,salt=%{other-value}:value} %{other-value}", "rounds,salt,expand: 49a598ee110af615e175f2e4511cc5d7ccff96ab other-example" },
- { "format: %4.8{sha1:value}", "format: 9c272973" },
- { "base64: %{sha1;format=base64:value}", "base64: w0mcJylzCn+AfvuGdqkty2+KP48=" },
- { "base64url: %{sha1;format=base64url:value}", "base64url: w0mcJylzCn-AfvuGdqkty2-KP48" },
- };
-
- static const struct var_expand_func_table func_table[] = {
- { "func1", test_var_expand_hashing_func1 },
- { NULL, NULL }
- };
-
- string_t *str = t_str_new(128);
-
- for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
- str_truncate(str, 0);
- error = NULL;
- test_assert(var_expand_with_funcs(str, tests[i].in, table,
- func_table, NULL, &error) == 1);
- test_assert_idx(strcmp(str_c(str), tests[i].out) == 0, i);
- if (error != NULL) {
- i_debug("Error: %s", error);
- }
- }
-
- test_assert(var_expand_with_funcs(str, "notfound: %{notfound:field}",
- table, func_table, NULL, &error) == 0);
- error = NULL;
- test_assert(var_expand_with_funcs(str, "notfound: %{badparam:field}",
- table, func_table, NULL, &error) == -1);
- test_assert(error != NULL);
-
- var_expand_unregister_func_array(test_extension_funcs);
-
- test_end();
-}
-
-static void test_var_expand_if(void)
-{
- static const struct var_expand_table table[] = {
- { 'a', "alpha", "alpha" },
- { 'b', "beta", "beta" },
- { 'o', "1", "one" },
- { 't', "2", "two" },
- { '\0', ";:", "evil1" },
- { '\0', ";test;", "evil2" },
- { '\0', NULL, NULL }
- };
- const char *error;
- string_t *dest = t_str_new(64);
- test_begin("var_expand_if");
-
- static const struct var_expand_test tests[] = {
- /* basic numeric operand test */
- { "%{if;1;==;1;yes;no}", "yes", 1 },
- { "%{if;1;==;2;yes;no}", "no", 1 },
- { "%{if;1;<;1;yes;no}", "no", 1 },
- { "%{if;1;<;2;yes;no}", "yes", 1 },
- { "%{if;1;<=;1;yes;no}", "yes", 1 },
- { "%{if;1;<=;2;yes;no}", "yes", 1 },
- { "%{if;1;>;1;yes;no}", "no", 1 },
- { "%{if;1;>;2;yes;no}", "no", 1 },
- { "%{if;1;>=;1;yes;no}", "yes", 1 },
- { "%{if;1;>=;2;yes;no}", "no", 1 },
- { "%{if;1;!=;1;yes;no}", "no", 1 },
- { "%{if;1;!=;2;yes;no}", "yes", 1 },
- /* basic string operand test */
- { "%{if;a;eq;a;yes;no}", "yes", 1 },
- { "%{if;a;eq;b;yes;no}", "no", 1 },
- { "%{if;a;lt;a;yes;no}", "no", 1 },
- { "%{if;a;lt;b;yes;no}", "yes", 1 },
- { "%{if;a;le;a;yes;no}", "yes", 1 },
- { "%{if;a;le;b;yes;no}", "yes", 1 },
- { "%{if;a;gt;a;yes;no}", "no", 1 },
- { "%{if;a;gt;b;yes;no}", "no", 1 },
- { "%{if;a;ge;a;yes;no}", "yes", 1 },
- { "%{if;a;ge;b;yes;no}", "no", 1 },
- { "%{if;a;ne;a;yes;no}", "no", 1 },
- { "%{if;a;ne;b;yes;no}", "yes", 1 },
- { "%{if;a;*;a;yes;no}", "yes", 1 },
- { "%{if;a;*;b;yes;no}", "no", 1 },
- { "%{if;a;*;*a*;yes;no}", "yes", 1 },
- { "%{if;a;*;*b*;yes;no}", "no", 1 },
- { "%{if;a;*;*;yes;no}", "yes", 1 },
- { "%{if;a;!*;a;yes;no}", "no", 1 },
- { "%{if;a;!*;b;yes;no}", "yes", 1 },
- { "%{if;a;!*;*a*;yes;no}", "no", 1 },
- { "%{if;a;!*;*b*;yes;no}", "yes", 1 },
- { "%{if;a;!*;*;yes;no}", "no", 1 },
- { "%{if;a;~;a;yes;no}", "yes", 1 },
- { "%{if;a;~;b;yes;no}", "no", 1 },
- { "%{if;a;~;.*a.*;yes;no}", "yes", 1 },
- { "%{if;a;~;.*b.*;yes;no}", "no", 1 },
- { "%{if;a;~;.*;yes;no}", "yes", 1 },
- { "%{if;a;!~;a;yes;no}", "no", 1 },
- { "%{if;a;!~;b;yes;no}", "yes", 1 },
- { "%{if;a;!~;.*a.*;yes;no}", "no", 1 },
- { "%{if;a;!~;.*b.*;yes;no}", "yes", 1 },
- { "%{if;a;!~;.*;yes;no}", "no", 1 },
- { "%{if;this is test;~;^test;yes;no}", "no", 1 },
- { "%{if;this is test;~;.*test;yes;no}", "yes", 1 },
- /* variable expansion */
- { "%{if;%a;eq;%a;yes;no}", "yes", 1 },
- { "%{if;%a;eq;%b;yes;no}", "no", 1 },
- { "%{if;%{alpha};eq;%{alpha};yes;no}", "yes", 1 },
- { "%{if;%{alpha};eq;%{beta};yes;no}", "no", 1 },
- { "%{if;%o;eq;%o;yes;no}", "yes", 1 },
- { "%{if;%o;eq;%t;yes;no}", "no", 1 },
- { "%{if;%{one};eq;%{one};yes;no}", "yes", 1 },
- { "%{if;%{one};eq;%{two};yes;no}", "no", 1 },
- { "%{if;%{one};eq;%{one};%{one};%{two}}", "1", 1 },
- { "%{if;%{one};gt;%{two};%{one};%{two}}", "2", 1 },
- { "%{if;%{evil1};eq;\\;\\:;%{evil2};no}", ";test;", 1 },
- /* inner if */
- { "%{if;%{if;%{one};eq;1;1;0};eq;%{if;%{two};eq;2;2;3};yes;no}", "no", 1 },
- /* no false */
- { "%{if;1;==;1;yes}", "yes", 1 },
- { "%{if;1;==;2;yes}", "", 1 },
- /* invalid input */
- { "%{if;}", "", -1 },
- { "%{if;1;}", "", -1 },
- { "%{if;1;==;}", "", -1 },
- { "%{if;1;==;2;}", "", -1 },
- { "%{if;1;fu;2;yes;no}", "", -1 },
- /* missing variables */
- { "%{if;%{missing1};==;%{missing2};yes;no}", "", 0 },
- };
-
- for(size_t i = 0; i < N_ELEMENTS(tests); i++) {
- int ret;
- error = NULL;
- str_truncate(dest, 0);
- ret = var_expand_with_table(dest, tests[i].in, table, &error);
- test_assert_idx(tests[i].ret == ret, i);
- test_assert_idx(strcmp(tests[i].out, str_c(dest)) == 0, i);
- }
-
- test_end();
-}
-
-static void test_var_expand_merge_tables(void)
-{
- const struct var_expand_table one[] = {
- { 'a', "1", "alpha" },
- { '\0', "2", "beta" },
- { '\0', NULL, NULL }
- },
- two[] = {
- { 't', "3", "theta" },
- { '\0', "4", "phi" },
- { '\0', NULL, NULL }
- },
- *merged = NULL;
-
-
- test_begin("var_expand_merge_tables");
-
- merged = t_var_expand_merge_tables(one, two);
-
- test_assert(var_expand_table_size(merged) == 4);
- for(unsigned int i = 0; i < var_expand_table_size(merged); i++) {
- if (i < 2) {
- test_assert_idx(merged[i].key == one[i].key, i);
- test_assert_idx(merged[i].value == one[i].value || strcmp(merged[i].value, one[i].value) == 0, i);
- test_assert_idx(merged[i].long_key == one[i].long_key || strcmp(merged[i].long_key, one[i].long_key) == 0, i);
- } else if (i < 4) {
- test_assert_idx(merged[i].key == two[i-2].key, i);
- test_assert_idx(merged[i].value == two[i-2].value || strcmp(merged[i].value, two[i-2].value) == 0, i);
- test_assert_idx(merged[i].long_key == two[i-2].long_key || strcmp(merged[i].long_key, two[i-2].long_key) == 0, i);
- } else {
- break;
- }
- }
- test_end();
-}
-
-static void test_var_expand_system()
-{
- test_begin("var_expand_system");
- int ncpus;
- const char *error ATTR_UNUSED;
- int ret = cpu_count_get(&ncpus, &error) == 0 ? 1 : -1;
- const struct var_expand_test tests[] = {
- { "%{system:cpu_count}", dec2str(ncpus), ret },
- };
-
- const struct var_expand_table table[] = {
- { '\0', NULL, NULL }
- };
- string_t *dest = t_str_new(64);
- for (size_t i = 0; i < N_ELEMENTS(tests); i++) {
- const struct var_expand_test *test = &tests[i];
- const char *error ATTR_UNUSED;
- str_truncate(dest, 0);
- int ret = var_expand_with_table(dest, test->in, table, &error);
- test_assert_cmp_idx(ret, ==, test->ret, i);
- test_assert_strcmp_idx(str_c(dest), test->out, i);
- }
-
- /* Check the expansion of os/os-version depending on whether uname()
- succeeds. */
- struct utsname utsname_result;
- if (uname(&utsname_result) == 0) {
- str_truncate(dest, 0);
- test_assert(var_expand_with_table(dest, "%{system:os}", table, &error) == 1);
- test_assert(strcmp(utsname_result.sysname, str_c(dest)) == 0);
-
- str_truncate(dest, 0);
- test_assert(var_expand_with_table(dest, "%{system:os-version}", table, &error) == 1);
- test_assert(strcmp(utsname_result.release, str_c(dest)) == 0);
- }
-
- test_end();
-}
-
-static void
-test_var_expand_dovecot(void)
-{
- static const struct var_expand_table table[] = {
- { '\0', NULL, NULL }
- };
-
- int ret;
- const char *error;
- string_t *dest = t_str_new(64);
- test_begin("var_expand_dovecot");
-
- /* Available keys should be correctly expanded. */
- static const struct var_expand_test tests[] = {
- { "%{dovecot:name}", PACKAGE_NAME, 1 },
- { "%{dovecot:version}", PACKAGE_VERSION, 1 },
- { "%{dovecot:support-url}", PACKAGE_WEBPAGE, 1 },
- { "%{dovecot:support-email}", PACKAGE_BUGREPORT, 1 },
- { "%{dovecot:revision}", DOVECOT_REVISION, 1 },
- };
-
- for (size_t i = 0; i < N_ELEMENTS(tests); i++) {
- str_truncate(dest, 0);
-
- ret = var_expand_with_table(dest, tests[i].in, table, &error);
- test_assert_idx(tests[i].ret == ret, i);
- test_assert_idx(strcmp(tests[i].out, str_c(dest)) == 0, i);
- }
-
- /* Make sure invalid keys are rejected. */
- str_truncate(dest, 0);
- test_assert(var_expand_with_table(dest, "%{dovecot:invalid}", table, &error) == 0);
- test_assert(strcmp(error, "Unsupported dovecot key 'invalid'") == 0);
-
- test_end();
-}
-
-void test_var_expand(void)
-{
- test_var_expand_ranges();
- test_var_expand_builtin();
- test_var_get_key_range();
- test_var_expand_with_funcs();
- test_var_expand_with_arrays();
- test_var_get_key();
- test_var_has_key();
- test_var_expand_extensions();
- test_var_expand_if();
- test_var_expand_merge_tables();
- test_var_expand_system();
- test_var_expand_dovecot();
-}
+++ /dev/null
-/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "array.h"
-#include "str.h"
-#include "var-expand.h"
-#include "var-expand-private.h"
-#include "wildcard-match.h"
-
-#include <regex.h>
-
-enum var_expand_if_op {
- OP_UNKNOWN,
- OP_NUM_EQ,
- OP_NUM_LT,
- OP_NUM_LE,
- OP_NUM_GT,
- OP_NUM_GE,
- OP_NUM_NE,
-/* put all numeric comparisons before this line */
- OP_STR_EQ,
- OP_STR_LT,
- OP_STR_LE,
- OP_STR_GT,
- OP_STR_GE,
- OP_STR_NE,
- OP_STR_LIKE,
- OP_STR_NOT_LIKE,
- OP_STR_REGEXP,
- OP_STR_NOT_REGEXP,
-/* keep this as last */
- OP_COUNT
-};
-
-static enum var_expand_if_op var_expand_if_str_to_comp(const char *op)
-{
- const char *ops[] = {
- NULL,
- "==",
- "<",
- "<=",
- ">",
- ">=",
- "!=",
- "eq",
- "lt",
- "le",
- "gt",
- "ge",
- "ne",
- "*",
- "!*",
- "~",
- "!~",
- };
- static_assert_array_size(ops, OP_COUNT);
- for(enum var_expand_if_op i = 1; i < OP_COUNT; i++) {
- i_assert(ops[i] != NULL);
- if (strcmp(op, ops[i]) == 0)
- return i;
- }
- return OP_UNKNOWN;
-}
-
-static int var_expand_if_comp(const char *lhs, const char *_op, const char *rhs,
- bool *result_r, const char **error_r)
-{
- bool neg = FALSE;
- enum var_expand_if_op op = var_expand_if_str_to_comp(_op);
-
- *result_r = FALSE;
- if (op == OP_UNKNOWN) {
- *error_r = t_strdup_printf("if: Unsupported comparator '%s'", _op);
- return -1;
- }
-
- if (op < OP_STR_EQ) {
- intmax_t a;
- intmax_t b;
- if (str_to_intmax(lhs, &a) < 0) {
- *error_r = t_strdup_printf("if: %s (lhs) is not a number", lhs);
- return -1;
- }
- if (str_to_intmax(rhs, &b) < 0) {
- *error_r = t_strdup_printf("if: %s (rhs) is not a number", rhs);
- return -1;
- }
- switch(op) {
- case OP_NUM_EQ:
- *result_r = a==b;
- return 0;
- case OP_NUM_LT:
- *result_r = a<b;
- return 0;
- case OP_NUM_LE:
- *result_r = a<=b;
- return 0;
- case OP_NUM_GT:
- *result_r = a>b;
- return 0;
- case OP_NUM_GE:
- *result_r = a>=b;
- return 0;
- case OP_NUM_NE:
- *result_r = a!=b;
- return 0;
- default:
- i_panic("Missing numeric comparator %u", op);
- }
- }
-
- switch(op) {
- case OP_STR_EQ:
- *result_r = strcmp(lhs,rhs)==0;
- return 0;
- case OP_STR_LT:
- *result_r = strcmp(lhs,rhs)<0;
- return 0;
- case OP_STR_LE:
- *result_r = strcmp(lhs,rhs)<=0;
- return 0;
- case OP_STR_GT:
- *result_r = strcmp(lhs,rhs)>0;
- return 0;
- case OP_STR_GE:
- *result_r = strcmp(lhs,rhs)>=0;
- return 0;
- case OP_STR_NE:
- *result_r = strcmp(lhs,rhs)!=0;
- return 0;
- case OP_STR_LIKE:
- *result_r = wildcard_match(lhs, rhs);
- return 0;
- case OP_STR_NOT_LIKE:
- *result_r = !wildcard_match(lhs, rhs);
- return 0;
- case OP_STR_NOT_REGEXP:
- neg = TRUE;
- /* fall through */
- case OP_STR_REGEXP: {
- int ec;
- bool res;
- regex_t reg;
- if ((ec = regcomp(®, rhs, REG_EXTENDED)) != 0) {
- size_t siz;
- char *errbuf;
- siz = regerror(ec, ®, NULL, 0);
- errbuf = t_malloc_no0(siz);
- (void)regerror(ec, ®, errbuf, siz);
- *error_r = t_strdup_printf("if: regex failed: %s",
- errbuf);
- return -1;
- }
- if ((ec = regexec(®, lhs, 0, 0, 0)) != 0) {
- i_assert(ec == REG_NOMATCH);
- res = FALSE;
- } else {
- res = TRUE;
- }
- regfree(®);
- /* this should be same as neg.
- if NOT_REGEXP, neg == TRUE and res should be FALSE
- if REGEXP, ned == FALSE, and res should be TRUE
- */
- *result_r = res != neg;
- return 0;
- }
- default:
- i_panic("Missing generic comparator %u", op);
- }
-}
-
-int var_expand_if(struct var_expand_context *ctx,
- const char *key, const char *field,
- const char **result_r, const char **error_r)
-{
- /* in case the original input had :, we need to fix that
- by concatenating the key and field together. */
- const char *input = t_strconcat(key, ":", field, NULL);
- const char *p = strchr(input, ';');
- const char *par_end;
- string_t *parbuf;
- const char *const *parms;
- unsigned int depth = 0;
- int ret;
- bool result, escape = FALSE, maybe_var = FALSE;
-
- if (p == NULL) {
- *error_r = "if: missing parameter(s)";
- return -1;
- }
- ARRAY_TYPE(const_string) params;
- t_array_init(¶ms, 6);
-
- parbuf = t_str_new(64);
- /* we need to skip any %{} parameters here, so we can split the string
- correctly from , without breaking any inner expansions */
- for(par_end = p+1; *par_end != '\0'; par_end++) {
- if (*par_end == '\\') {
- escape = TRUE;
- continue;
- } else if (escape) {
- str_append_c(parbuf, *par_end);
- escape = FALSE;
- continue;
- }
- if (*par_end == '%') {
- maybe_var = TRUE;
- } else if (maybe_var && *par_end == '{') {
- depth++;
- maybe_var = FALSE;
- } else if (depth > 0 && *par_end == '}') {
- depth--;
- } else if (depth == 0 && *par_end == ';') {
- const char *par = str_c(parbuf);
- array_push_back(¶ms, &par);
- parbuf = t_str_new(64);
- continue;
- /* if there is a unescaped : at top level it means
- that the key + arguments end here. it's probably
- a by-product of the t_strconcat at top of function,
- which is best handled here. */
- } else if (depth == 0 && *par_end == ':') {
- break;
- }
- str_append_c(parbuf, *par_end);
- }
-
- if (str_len(parbuf) > 0) {
- const char *par = str_c(parbuf);
- array_push_back(¶ms, &par);
- }
-
- if (array_count(¶ms) != 5) {
- if (array_count(¶ms) == 4) {
- const char *empty = "";
- array_push_back(¶ms, &empty);
- } else {
- *error_r = t_strdup_printf("if: requires four or five parameters, got %u",
- array_count(¶ms));
- return -1;
- }
- }
-
- array_append_zero(¶ms);
- parms = array_front(¶ms);
- t_array_init(¶ms, 6);
-
- for(;*parms != NULL; parms++) {
- /* expand the parameters */
- string_t *param = t_str_new(64);
- ret = var_expand_with_arrays(param, *parms, ctx->tables,
- ctx->funcs, error_r);
- if (ret <= 0)
- return ret;
- const char *p = str_c(param);
- array_push_back(¶ms, &p);
- }
-
- i_assert(array_count(¶ms) == 5);
-
- /* execute comparison */
- const char *const *args = array_front(¶ms);
- if (var_expand_if_comp(args[0], args[1], args[2], &result, error_r)<0)
- return -1;
- *result_r = result ? args[3] : args[4];
- return 1;
-}
-
+++ /dev/null
-#ifndef VAR_EXPAND_PRIVATE_H
-#define VAR_EXPAND_PRIVATE_H 1
-
-struct var_expand_context {
- /* NULL-terminated array of variable tables */
- const struct var_expand_table *const *tables;
- /* table=NULL-terminated array of function tables */
- const struct var_expand_params_func *funcs;
-
- /* last offset, negative counts from end*/
- int offset;
- /* last width, negative counts from end */
- int width;
- /* last zero padding */
- bool zero_padding:1;
-};
-
-/* this can be used to register a *global* function that is
- prepended to function table. These can be used to register some
- special handling for keys.
-
- you can call var_expand_with_funcs if you need to
- expand something inside here.
-
- return -1 on error, 0 on unknown variable, 1 on success
-*/
-typedef int
-var_expand_extension_func_t(struct var_expand_context *ctx,
- const char *key, const char *field,
- const char **result_r, const char **error_r);
-
-struct var_expand_extension_func_table {
- const char *key;
- var_expand_extension_func_t *func;
-};
-
-int var_expand_long(struct var_expand_context *ctx,
- const void *key_start, size_t key_len,
- const char **var_r, const char **error_r);
-
-void var_expand_extensions_init(void);
-void var_expand_extensions_deinit(void);
-
-/* Functions registered here are placed before in-built functions,
- so you can include your own implementation of something.
- Be careful. Use NULL terminated list.
-*/
-void var_expand_register_func_array(const struct var_expand_extension_func_table *funcs);
-void var_expand_unregister_func_array(const struct var_expand_extension_func_table *funcs);
-
-int var_expand_if(struct var_expand_context *ctx,
- const char *key, const char *field,
- const char **result_r, const char **error_r);
-
-#endif
+++ /dev/null
-/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "array.h"
-#include "cpu-count.h"
-#include "md5.h"
-#include "hash.h"
-#include "hex-binary.h"
-#include "base64.h"
-#include "hostpid.h"
-#include "hmac.h"
-#include "pkcs5.h"
-#include "hash-method.h"
-#include "str.h"
-#include "strescape.h"
-#include "var-expand.h"
-#include "var-expand-private.h"
-#include "dovecot-version.h"
-
-#include <unistd.h>
-#include <ctype.h>
-
-#ifdef HAVE_SYS_UTSNAME_H
-# include <sys/utsname.h>
-#endif
-
-#define ENV_CPU_COUNT "NCPU"
-
-#define TABLE_LAST(t) \
- ((t)->key == '\0' && (t)->long_key == NULL)
-
-struct var_expand_modifier {
- char key;
- const char *(*func)(const char *, struct var_expand_context *);
-};
-
-static ARRAY(struct var_expand_extension_func_table) var_expand_extensions;
-
-enum os_default_type {
- OS_DEFAULT_TYPE_SYSNAME,
- OS_DEFAULT_TYPE_RELEASE,
-};
-
-static const char *
-m_str_lcase(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
-{
- return t_str_lcase(str);
-}
-
-static const char *
-m_str_ucase(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
-{
- return t_str_ucase(str);
-}
-
-static const char *
-m_str_escape(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
-{
- return str_escape(str);
-}
-
-static const char *
-m_str_hex(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
-{
- unsigned long long l;
-
- if (str_to_ullong(str, &l) < 0)
- l = 0;
- return t_strdup_printf("%llx", l);
-}
-
-static const char *
-m_str_reverse(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
-{
- size_t len = strlen(str);
- char *p, *rev;
-
- rev = t_malloc_no0(len + 1);
- rev[len] = '\0';
-
- for (p = rev + len - 1; *str != '\0'; str++)
- *p-- = *str;
- return rev;
-}
-
-static const char *m_str_hash(const char *str, struct var_expand_context *ctx)
-{
- unsigned int value = str_hash(str);
- string_t *hash = t_str_new(20);
-
- if (ctx->width != 0) {
- value %= ctx->width;
- ctx->width = 0;
- }
-
- str_printfa(hash, "%x", value);
- while ((int)str_len(hash) < ctx->offset)
- str_insert(hash, 0, "0");
- ctx->offset = 0;
-
- return str_c(hash);
-}
-
-static const char *
-m_str_newhash(const char *str, struct var_expand_context *ctx)
-{
- string_t *hash = t_str_new(20);
- unsigned char result[MD5_RESULTLEN];
- unsigned int i;
- uint64_t value = 0;
-
- md5_get_digest(str, strlen(str), result);
- for (i = 0; i < sizeof(value); i++) {
- value <<= 8;
- value |= result[i];
- }
-
- if (ctx->width != 0) {
- value %= ctx->width;
- ctx->width = 0;
- }
-
- str_printfa(hash, "%x", (unsigned int)value);
- while ((int)str_len(hash) < ctx->offset)
- str_insert(hash, 0, "0");
- ctx->offset = 0;
-
- return str_c(hash);
-}
-
-static const char *
-m_str_md5(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
-{
- unsigned char digest[16];
-
- md5_get_digest(str, strlen(str), digest);
-
- return binary_to_hex(digest, sizeof(digest));
-}
-
-static const char *
-m_str_ldap_dn(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
-{
- string_t *ret = t_str_new(256);
-
- while (*str != '\0') {
- if (*str == '.')
- str_append(ret, ",dc=");
- else
- str_append_c(ret, *str);
- str++;
- }
-
- return str_free_without_data(&ret);
-}
-
-static const char *
-m_str_trim(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
-{
- size_t len;
-
- len = strlen(str);
- while (len > 0 && i_isspace(str[len-1]))
- len--;
- return t_strndup(str, len);
-}
-
-#define MAX_MODIFIER_COUNT 10
-static const struct var_expand_modifier modifiers[] = {
- { 'L', m_str_lcase },
- { 'U', m_str_ucase },
- { 'E', m_str_escape },
- { 'X', m_str_hex },
- { 'R', m_str_reverse },
- { 'H', m_str_hash },
- { 'N', m_str_newhash },
- { 'M', m_str_md5 },
- { 'D', m_str_ldap_dn },
- { 'T', m_str_trim },
- { '\0', NULL }
-};
-
-static int
-var_expand_short(const struct var_expand_context *ctx, char key,
- const char **var_r, const char **error_r)
-{
- const struct var_expand_table *t;
-
- for (unsigned int i = 0; ctx->tables[i] != NULL; i++) {
- for (t = ctx->tables[i]; !TABLE_LAST(t); t++) {
- if (t->key == key) {
- *var_r = t->value != NULL ? t->value : "";
- return 1;
- }
- }
- }
-
- for (unsigned int j = 0; ctx->funcs[j].table != NULL; j++) {
- const struct var_expand_func_table *func_table = ctx->funcs[j].table;
- for (unsigned int i = 0; func_table[i].key != NULL; i++) {
- if (func_table[i].key[0] == key &&
- func_table[i].key[1] == '\0') {
- const char *value;
- int ret = func_table->func(
- "", ctx->funcs[j].context, &value, error_r);
- *var_r = value != NULL ? value : "";
- return ret;
- }
- }
- }
-
- /* not found */
- if (key == '%') {
- *var_r = "%";
- return 1;
- }
- if (*error_r == NULL)
- *error_r = t_strdup_printf("Unknown variable '%%%c'", key);
- *var_r = t_strdup_printf("UNSUPPORTED_VARIABLE_%c", key);
- return 0;
-}
-
-static int
-var_expand_hash(struct var_expand_context *ctx,
- const char *key, const char *field,
- const char **result_r, const char **error_r)
-{
- enum {
- FORMAT_HEX,
- FORMAT_HEX_UC,
- FORMAT_BASE64,
- FORMAT_BASE64_URL,
- } format = FORMAT_HEX;
-
- const char *p = strchr(key, ';');
- const char *const *args = NULL;
- const char *algo = key;
- const char *value;
- int ret;
-
- if (p != NULL) {
- algo = t_strcut(key, ';');
- args = t_strsplit(p+1, ",");
- }
-
- const struct hash_method *method;
- if (strcmp(algo, "pkcs5") == 0) {
- method = hash_method_lookup("sha256");
- } else {
- method = hash_method_lookup(algo);
- }
-
- /* since this can get called only by registered algorithms
- it's not really possible for them to be suddenly missing */
- i_assert(method != NULL);
-
- string_t *field_value = t_str_new(64);
- string_t *salt = t_str_new(64);
- string_t *tmp = t_str_new(method->digest_size);
-
- if ((ret = var_expand_long(ctx, field, strlen(field),
- &value, error_r)) <= 0) {
- return ret;
- }
-
- str_append(field_value, value);
-
- /* default values */
- unsigned int rounds = 1;
- unsigned int truncbits = 0;
-
- if (strcmp(algo, "pkcs5") == 0) {
- rounds = 2048;
- str_append(salt, field);
- }
-
- while(args != NULL && *args != NULL) {
- const char *k = t_strcut(*args, '=');
- const char *value = strchr(*args, '=');
- if (value == NULL) {
- args++;
- continue;
- } else {
- value++;
- }
- if (strcmp(k, "rounds") == 0) {
- if (str_to_uint(value, &rounds)<0) {
- *error_r = t_strdup_printf(
- "Cannot parse hash arguments:"
- "'%s' is not number for rounds",
- value);
- return -1;
- }
- if (rounds < 1) {
- *error_r = t_strdup_printf(
- "Cannot parse hash arguments:"
- "rounds must be at least 1");
- return -1;
- }
- } else if (strcmp(k, "truncate") == 0) {
- if (str_to_uint(value, &truncbits)<0) {
- *error_r = t_strdup_printf(
- "Cannot parse hash arguments:"
- "'%s' is not number for truncbits",
- value);
- return -1;
- }
- truncbits = I_MIN(truncbits, method->digest_size*8);
- } else if (strcmp(k, "salt") == 0) {
- str_truncate(salt, 0);
- ret = var_expand_with_arrays(salt, value, ctx->tables,
- ctx->funcs, error_r);
- if (ret <= 0)
- return ret;
- break;
- } else if (strcmp(k, "format") == 0) {
- if (strcmp(value, "hex") == 0) {
- format = FORMAT_HEX;
- } else if (strcmp(value, "hexuc") == 0){
- format = FORMAT_HEX_UC;
- } else if (strcmp(value, "base64") == 0) {
- format = FORMAT_BASE64;
- } else if (strcmp(value, "base64url") == 0) {
- format = FORMAT_BASE64_URL;
- } else {
- *error_r = t_strdup_printf(
- "Cannot parse hash arguments:"
- "'%s' is not supported format",
- value);
- return -1;
- }
- }
- args++;
- }
-
- str_truncate(tmp, 0);
-
- if (strcmp(algo, "pkcs5") == 0) {
- if (pkcs5_pbkdf(PKCS5_PBKDF2, method,
- field_value->data, field_value->used,
- salt->data, salt->used,
- rounds, HMAC_MAX_CONTEXT_SIZE, tmp) != 0) {
- *error_r = "Cannot hash: PKCS5_PBKDF2 failed";
- return -1;
- }
- } else {
- void *context = t_malloc_no0(method->context_size);
-
- str_append_str(tmp, field_value);
-
- for(;rounds>0;rounds--) {
- method->init(context);
- if (salt->used > 0)
- method->loop(context, salt->data, salt->used);
- method->loop(context, tmp->data, tmp->used);
- unsigned char *digest =
- buffer_get_modifiable_data(tmp, NULL);
- method->result(context, digest);
- if (tmp->used != method->digest_size)
- buffer_set_used_size(tmp, method->digest_size);
- }
- }
-
- if (truncbits > 0)
- buffer_truncate_rshift_bits(tmp, truncbits);
-
- switch(format) {
- case FORMAT_HEX:
- *result_r = binary_to_hex(tmp->data, tmp->used);
- return 1;
- case FORMAT_HEX_UC:
- *result_r = binary_to_hex(tmp->data, tmp->used);
- return 1;
- case FORMAT_BASE64: {
- string_t *dest = t_str_new(64);
- base64_encode(tmp->data, tmp->used, dest);
- *result_r = str_c(dest);
- return 1;
- }
- case FORMAT_BASE64_URL: {
- string_t *dest = t_str_new(64);
- base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, 0,
- tmp->data, tmp->used, dest);
- *result_r = str_c(dest);
- return 1;
- }
- }
-
- i_unreached();
-}
-
-static int
-var_expand_process(struct var_expand_context *ctx ATTR_UNUSED,
- const char *key, const char *field,
- const char **result_r, const char **error_r)
-{
- i_assert(strcmp(key, "process") == 0);
- if (strcmp(field, "pid") == 0)
- *result_r = my_pid;
- else if (strcmp(field, "uid") == 0)
- *result_r = dec2str(geteuid());
- else if (strcmp(field, "gid") == 0)
- *result_r = dec2str(getegid());
- else {
- *error_r = t_strdup_printf("Unsupported process field '%s'",
- field);
- return 0;
- }
- return 1;
-}
-
-static struct utsname utsname_result;
-static bool utsname_set = FALSE;
-
-static int
-var_expand_system_os(enum os_default_type type,
- const char **value_r, const char **error_r)
-{
- if (!utsname_set) {
- utsname_set = TRUE;
-
- if (uname(&utsname_result) < 0) {
- *error_r = t_strdup_printf("uname() failed: %m");
- i_zero(&utsname_result);
- return -1;
- }
- }
-
- switch (type) {
- case OS_DEFAULT_TYPE_SYSNAME:
- *value_r = utsname_result.sysname;
- return 1;
- case OS_DEFAULT_TYPE_RELEASE:
- *value_r = utsname_result.release;
- return 1;
- default:
- break;
- }
-
- i_unreached();
-}
-
-static int
-var_expand_system(struct var_expand_context *ctx ATTR_UNUSED,
- const char *key, const char *field,
- const char **result_r, const char **error_r)
-{
- i_assert(strcmp(key, "system") == 0);
- if (strcmp(field, "cpu_count") == 0) {
- int ncpus;
- const char *cpuenv = getenv(ENV_CPU_COUNT);
- if (cpuenv != NULL) {
- *result_r = cpuenv;
- return 1;
- }
- if (cpu_count_get(&ncpus, error_r) < 0)
- return -1;
- *result_r = dec2str(ncpus);
- return 1;
- } else if (strcmp(field, "hostname") == 0) {
- *result_r = my_hostname;
- return 1;
- } else if (strcmp(field, "os") == 0)
- return var_expand_system_os(OS_DEFAULT_TYPE_SYSNAME, result_r,
- error_r);
- else if (strcmp(field, "os-version") == 0)
- return var_expand_system_os(OS_DEFAULT_TYPE_RELEASE, result_r,
- error_r);
- *error_r = t_strdup_printf("Unsupported system key '%s'", field);
- return 0;
-}
-
-static int
-var_expand_dovecot(struct var_expand_context *ctx ATTR_UNUSED,
- const char *key, const char *field,
- const char **result_r, const char **error_r)
-{
- i_assert(strcmp(key, "dovecot") == 0);
-
- if (strcmp(field, "name") == 0) {
- *result_r = PACKAGE_NAME;
- return 1;
- } else if (strcmp(field, "version") == 0) {
- *result_r = PACKAGE_VERSION;
- return 1;
- } else if (strcmp(field, "support-url") == 0) {
- *result_r = PACKAGE_WEBPAGE;
- return 1;
- } else if (strcmp(field, "support-email") == 0) {
- *result_r = PACKAGE_BUGREPORT;
- return 1;
- } else if (strcmp(field, "revision") == 0) {
- *result_r = DOVECOT_REVISION;
- return 1;
- }
-
- *error_r = t_strdup_printf("Unsupported dovecot key '%s'", field);
- return 0;
-}
-
-static int
-var_expand_func(const struct var_expand_params_func *funcs,
- const char *key, const char *data,
- const char **var_r, const char **error_r)
-{
- const char *value = NULL;
- int ret;
-
- if (strcmp(key, "env") == 0) {
- value = getenv(data);
- *var_r = value != NULL ? value : "";
- return 1;
- }
- for (unsigned int i = 0; funcs[i].table != NULL; i++) {
- const struct var_expand_func_table *func_table = funcs[i].table;
- for (; func_table->key != NULL; func_table++) {
- if (strcmp(func_table->key, key) == 0) {
- ret = func_table->func(data, funcs[i].context, &value, error_r);
- if (*error_r == NULL)
- *error_r = t_strdup_printf("Unknown variables in function %%%s", key);
- *var_r = value != NULL ? value : "";
- return ret;
- }
- }
- }
- if (*error_r == NULL)
- *error_r = t_strdup_printf("Unknown variable '%%%s'", key);
- *var_r = t_strdup_printf("UNSUPPORTED_VARIABLE_%s", key);
- return 0;
-}
-
-static int
-var_expand_try_extension(struct var_expand_context *ctx,
- const char *key, const char *data,
- const char **var_r, const char **error_r)
-{
- int ret;
- const char *sep = strchr(key, ';');
-
- if (sep == NULL) sep = key + strlen(key);
-
- /* try with extensions */
- const struct var_expand_extension_func_table *f;
- array_foreach(&var_expand_extensions, f) {
- /* ensure we won't match abbreviations */
- size_t len = sep-key;
- if (strncasecmp(key, f->key, len) == 0 && f->key[len] == '\0') {
- ret = f->func(ctx, key, data, var_r, error_r);
- i_assert(ret == 1 || *error_r != NULL);
- return ret;
- }
- }
- return var_expand_func(ctx->funcs, key, data, var_r, error_r);
-}
-
-
-int
-var_expand_long(struct var_expand_context *ctx,
- const void *key_start, size_t key_len,
- const char **var_r, const char **error_r)
-{
- const struct var_expand_table *t;
- const char *key, *value = NULL;
- int ret = 1;
-
- for (unsigned int i = 0; ctx->tables[i] != NULL; i++) {
- for (t = ctx->tables[i]; !TABLE_LAST(t); t++) {
- if (t->long_key != NULL &&
- strncmp(t->long_key, key_start, key_len) == 0 &&
- t->long_key[key_len] == '\0') {
- *var_r = t->value != NULL ? t->value : "";
- return 1;
- }
- }
- }
- key = t_strndup(key_start, key_len);
-
- const char *data = strchr(key, ':');
-
- if (data != NULL)
- key = t_strdup_until(key, data++);
- else
- data = "";
-
- ret = var_expand_try_extension(ctx, key, data, &value, error_r);
-
- if (ret <= 0 && value == NULL)
- value = "";
-
- *var_r = value;
- return ret;
-}
-
-int var_expand_with_funcs(string_t *dest, const char *str,
- const struct var_expand_table *table,
- const struct var_expand_func_table *func_table,
- void *context, const char **error_r)
-{
- const struct var_expand_params params = {
- .table = table,
- .func_table = func_table,
- .func_context = context,
- };
- return var_expand(dest, str, ¶ms, error_r);
-}
-
-int var_expand_with_arrays(string_t *dest, const char *str,
- const struct var_expand_table *const *tables,
- const struct var_expand_params_func *funcs,
- const char **error_r)
-{
- const struct var_expand_params params = {
- .tables_arr = tables,
- .funcs_arr = funcs,
- };
- return var_expand(dest, str, ¶ms, error_r);
-}
-
-int var_expand(string_t *dest, const char *str,
- const struct var_expand_params *params, const char **error_r)
-{
- static const struct var_expand_table *empty_table = NULL;
- static const struct var_expand_params_func empty_funcs = { NULL, NULL };
- const struct var_expand_table *tables[2] = { NULL, NULL };
- struct var_expand_params_func funcs[2] = {
- { NULL, NULL }, { NULL, NULL } };
- const struct var_expand_modifier *m;
- const char *var;
- struct var_expand_context ctx;
- const char *(*modifier[MAX_MODIFIER_COUNT])
- (const char *, struct var_expand_context *);
- const char *end;
- unsigned int i, modifier_count;
- size_t len;
- int ret, final_ret = 1;
-
- *error_r = NULL;
-
- i_zero(&ctx);
- if (params->table != NULL) {
- i_assert(params->tables_arr == NULL);
- tables[0] = params->table;
- ctx.tables = tables;
- } else if (params->tables_arr != NULL)
- ctx.tables = params->tables_arr;
- else
- ctx.tables = &empty_table;
-
- if (params->func_table != NULL) {
- i_assert(params->funcs_arr == NULL);
- funcs[0].table = params->func_table;
- funcs[0].context = params->func_context;
- ctx.funcs = funcs;
- } else if (params->funcs_arr != NULL)
- ctx.funcs = params->funcs_arr;
- else
- ctx.funcs = &empty_funcs;
-
- for (; *str != '\0'; str++) {
- if (*str != '%')
- str_append_c(dest, *str);
- else {
- int sign = 1;
-
- str++;
-
- /* reset per-field modifiers */
- ctx.offset = 0;
- ctx.width = 0;
- ctx.zero_padding = FALSE;
-
- /* [<offset>.]<width>[<modifiers>]<variable> */
- if (*str == '-') {
- sign = -1;
- str++;
- }
- if (*str == '0') {
- ctx.zero_padding = TRUE;
- str++;
- }
- while (*str >= '0' && *str <= '9') {
- ctx.width = ctx.width*10 + (*str - '0');
- str++;
- }
-
- if (*str == '.') {
- ctx.offset = sign * ctx.width;
- sign = 1;
- ctx.width = 0;
- str++;
-
- /* if offset was prefixed with zero (or it was
- plain zero), just ignore that. zero padding
- is done with the width. */
- ctx.zero_padding = FALSE;
- if (*str == '0') {
- ctx.zero_padding = TRUE;
- str++;
- }
- if (*str == '-') {
- sign = -1;
- str++;
- }
-
- while (*str >= '0' && *str <= '9') {
- ctx.width = ctx.width*10 + (*str - '0');
- str++;
- }
- ctx.width = sign * ctx.width;
- }
-
- modifier_count = 0;
- while (modifier_count < MAX_MODIFIER_COUNT) {
- modifier[modifier_count] = NULL;
- for (m = modifiers; m->key != '\0'; m++) {
- if (m->key == *str) {
- /* @UNSAFE */
- modifier[modifier_count] =
- m->func;
- str++;
- break;
- }
- }
- if (modifier[modifier_count] == NULL)
- break;
- modifier_count++;
- }
-
- var = "";
- if (*str == '{' && strchr(str, '}') != NULL) {
- /* %{long_key} */
- unsigned int ctr = 1;
- bool escape = FALSE;
- end = str;
- while(*++end != '\0' && ctr > 0) {
- if (!escape && *end == '\\') {
- escape = TRUE;
- continue;
- }
- if (escape) {
- escape = FALSE;
- continue;
- }
- if (*end == '{') ctr++;
- if (*end == '}') ctr--;
- }
- if (ctr == 0)
- /* it needs to come back a bit */
- end--;
- /* if there is no } it will consume rest of the
- string */
- len = end - (str + 1);
- ret = var_expand_long(&ctx, str+1, len,
- &var, error_r);
- str = end;
- } else {
- ret = var_expand_short(&ctx, *str,
- &var, error_r);
- }
- i_assert(var != NULL);
-
- if (*str == '\0') {
- *error_r = "%variable ends unexpectedly";
- return -1;
- }
- if (final_ret > ret)
- final_ret = ret;
-
- if (params->escape_func != NULL) {
- var = params->escape_func(var,
- params->escape_context);
- }
-
- if (ret <= 0)
- str_append(dest, var);
- else {
- for (i = 0; i < modifier_count; i++)
- var = modifier[i](var, &ctx);
-
- if (ctx.offset < 0) {
- /* if offset is < 0 then we want to
- start at the end */
- size_t len = strlen(var);
- size_t offset_from_end = -ctx.offset;
-
- if (len > offset_from_end)
- var += len - offset_from_end;
- } else {
- while (*var != '\0' && ctx.offset > 0) {
- ctx.offset--;
- var++;
- }
- }
- if (ctx.width == 0)
- str_append(dest, var);
- else if (!ctx.zero_padding) {
- if (ctx.width < 0)
- ctx.width = strlen(var) - (-ctx.width);
- str_append_max(dest, var, ctx.width);
- } else {
- /* %05d -like padding. no truncation. */
- ssize_t len = strlen(var);
- while (len < ctx.width) {
- str_append_c(dest, '0');
- ctx.width--;
- }
- str_append(dest, var);
- }
- }
- }
- }
- return final_ret;
-}
-
-int var_expand_with_table(string_t *dest, const char *str,
- const struct var_expand_table *table,
- const char **error_r)
-{
- const struct var_expand_params params = {
- .table = table,
- };
- return var_expand(dest, str, ¶ms, error_r);
-}
-
-static bool
-var_get_key_range_full(const char *str, unsigned int *idx_r,
- unsigned int *size_r)
-{
- const struct var_expand_modifier *m;
- unsigned int i = 0;
-
- /* [<offset>.]<width>[<modifiers>]<variable> */
- while ((str[i] >= '0' && str[i] <= '9') || str[i] == '-')
- i++;
-
- if (str[i] == '.') {
- i++;
- while ((str[i] >= '0' && str[i] <= '9') || str[i] == '-')
- i++;
- }
-
- do {
- for (m = modifiers; m->key != '\0'; m++) {
- if (m->key == str[i]) {
- i++;
- break;
- }
- }
- } while (m->key != '\0');
-
- if (str[i] != '{') {
- /* short key */
- *idx_r = i;
- *size_r = str[i] == '\0' ? 0 : 1;
- return FALSE;
- } else {
- unsigned int depth = 1;
- bool escape = FALSE;
- /* long key */
- *idx_r = ++i;
- for (; str[i] != '\0'; i++) {
- if (!escape && str[i] == '\\') {
- escape = TRUE;
- continue;
- }
- if (escape) {
- escape = FALSE;
- continue;
- }
- if (str[i] == '{')
- depth++;
- if (str[i] == '}') {
- if (--depth==0)
- break;
- }
- }
- *size_r = i - *idx_r;
- return TRUE;
- }
-}
-
-char var_get_key(const char *str)
-{
- unsigned int idx, size;
-
- if (var_get_key_range_full(str, &idx, &size))
- return '{';
- return str[idx];
-}
-
-void var_get_key_range(const char *str, unsigned int *idx_r,
- unsigned int *size_r)
-{
- (void)var_get_key_range_full(str, idx_r, size_r);
-}
-
-static bool var_has_long_key(const char **str, const char *long_key)
-{
- const char *start, *end;
-
- start = strchr(*str, '{');
- i_assert(start != NULL);
-
- end = strchr(++start, '}');
- if (end == NULL)
- return FALSE;
-
- if (strncmp(start, long_key, end-start) == 0 &&
- long_key[end-start] == '\0')
- return TRUE;
-
- *str = end;
- return FALSE;
-}
-
-bool var_has_key(const char *str, char key, const char *long_key)
-{
- char c;
-
- for (; *str != '\0'; str++) {
- if (*str == '%' && str[1] != '\0') {
- str++;
- c = var_get_key(str);
- if (c == key && key != '\0')
- return TRUE;
-
- if (c == '{' && long_key != NULL) {
- if (var_has_long_key(&str, long_key))
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-
-void var_expand_extensions_deinit(void)
-{
- array_free(&var_expand_extensions);
-}
-
-void var_expand_extensions_init(void)
-{
- i_array_init(&var_expand_extensions, 32);
-
- /* put all hash methods there */
- for(const struct hash_method **meth = hash_methods;
- *meth != NULL;
- meth++) {
- struct var_expand_extension_func_table *func =
- array_append_space(&var_expand_extensions);
- func->key = (*meth)->name;
- func->func = var_expand_hash;
- }
-
- /* pkcs5 */
- struct var_expand_extension_func_table *func =
- array_append_space(&var_expand_extensions);
- func->key = "pkcs5";
- func->func = var_expand_hash;
-
- /* if */
- func = array_append_space(&var_expand_extensions);
- func->key = "if";
- func->func = var_expand_if;
-
- /* system */
- func = array_append_space(&var_expand_extensions);
- func->key = "system";
- func->func = var_expand_system;
-
- /* process */
- func = array_append_space(&var_expand_extensions);
- func->key = "process";
- func->func = var_expand_process;
-
- /* dovecot */
- func = array_append_space(&var_expand_extensions);
- func->key = "dovecot";
- func->func = var_expand_dovecot;
-}
-
-void
-var_expand_register_func_array(const struct var_expand_extension_func_table *funcs)
-{
- for(const struct var_expand_extension_func_table *ptr = funcs;
- ptr->key != NULL;
- ptr++) {
- i_assert(*ptr->key != '\0');
- array_push_front(&var_expand_extensions, ptr);
- }
-}
-
-void
-var_expand_unregister_func_array(const struct var_expand_extension_func_table *funcs)
-{
- for(const struct var_expand_extension_func_table *ptr = funcs;
- ptr->key != NULL;
- ptr++) {
- i_assert(ptr->func != NULL);
- for(unsigned int i = 0; i < array_count(&var_expand_extensions); i++) {
- const struct var_expand_extension_func_table *func =
- array_idx(&var_expand_extensions, i);
- if (strcasecmp(func->key, ptr->key) == 0) {
- array_delete(&var_expand_extensions, i, 1);
- }
- }
- }
-}
-
-struct var_expand_table *
-var_expand_merge_tables(pool_t pool, const struct var_expand_table *a,
- const struct var_expand_table *b)
-{
- ARRAY(struct var_expand_table) table;
- size_t a_size = var_expand_table_size(a);
- size_t b_size = var_expand_table_size(b);
- p_array_init(&table, pool, a_size + b_size + 1);
- for(size_t i=0; i<a_size; i++) {
- struct var_expand_table *entry =
- array_append_space(&table);
- entry->key = a[i].key;
- entry->value = p_strdup(pool, a[i].value);
- entry->long_key = p_strdup(pool, a[i].long_key);
- }
- for(size_t i=0; i<b_size; i++) {
- struct var_expand_table *entry =
- array_append_space(&table);
- entry->key = b[i].key;
- entry->value = p_strdup(pool, b[i].value);
- entry->long_key = p_strdup(pool, b[i].long_key);
- }
- array_append_zero(&table);
- return array_front_modifiable(&table);
-}
+++ /dev/null
-#ifndef VAR_EXPAND_H
-#define VAR_EXPAND_H
-
-typedef const char *var_expand_escape_t(const char *str, void *context);
-
-struct var_expand_table {
- char key;
- const char *value;
- const char *long_key;
-};
-
-struct var_expand_func_table {
- const char *key;
- /* %{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);
-};
-
-struct var_expand_params_func {
- const struct var_expand_func_table *table;
- void *context;
-};
-
-struct var_expand_params {
- /* If non-NULL, all variables are escaped with this function. */
- var_expand_escape_t *escape_func;
- void *escape_context;
-
- /* Single table: */
- const struct var_expand_table *table;
- const struct var_expand_func_table *func_table;
- void *func_context;
-
- /* Alternatively, multiple tables: */
- const struct var_expand_table *const *tables_arr;
- const struct var_expand_params_func *funcs_arr;
-};
-
-/* Expand % variables in src and append the string in dest. Returns 1 on
- success, 0 if the format string 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_params *params, 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, -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_with_table(string_t *dest, const char *str,
- const struct var_expand_table *table,
- const char **error_r);
-/* Like var_expand_with_table(), but support also callback functions for
- variable expansion. */
-int var_expand_with_funcs(string_t *dest, const char *str,
- const struct var_expand_table *table,
- const struct var_expand_func_table *func_table,
- void *func_context, const char **error_r) ATTR_NULL(3, 4, 5);
-/* Like var_expand_with_funcs(), but multiple separate tables can be given.
- Each func_table[n] has a matching func_context[n] */
-int var_expand_with_arrays(string_t *dest, const char *str,
- const struct var_expand_table *const *tables,
- const struct var_expand_params_func *funcs,
- const char **error_r);
-
-/* Returns the actual key character for given string, ie. skip any modifiers
- that are before it. The string should be the data after the '%' character.
- For %{long_variable}, '{' is returned. */
-char var_get_key(const char *str) ATTR_PURE;
-/* Similar to var_get_key(), but works for long keys as well. For single char
- keys size=1, while for e.g. %{key} size=3 and idx points to 'k'. */
-void var_get_key_range(const char *str, unsigned int *idx_r,
- unsigned int *size_r);
-/* Returns TRUE if key variable is used in the string.
- If key is '\0', it's ignored. If long_key is NULL, it's ignored. */
-bool var_has_key(const char *str, char key, const char *long_key) ATTR_PURE;
-
-static inline size_t ATTR_PURE
-var_expand_table_size(const struct var_expand_table *table)
-{
- size_t n = 0;
- while(table != NULL && (table[n].key != '\0' ||
- table[n].long_key != NULL))
- n++;
- return n;
-}
-
-struct var_expand_table *
-var_expand_merge_tables(pool_t pool, const struct var_expand_table *a,
- const struct var_expand_table *b);
-#define t_var_expand_merge_tables(a, b) \
- (const struct var_expand_table *)var_expand_merge_tables(pool_datastack_create(), (a), (b))
-#endif
#include "safe-memset.h"
#include "time-util.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "master-interface.h"
#include "master-service.h"
#include "login-client.h"
};
str_truncate(str, 0);
- if (var_expand_new(str, client->set->login_log_format, ¶ms2,
+ if (var_expand(str, client->set->login_log_format, ¶ms2,
&error) < 0) {
/* NOTE: Don't log via client->event - it would cause
recursion */
#include "restrict-access.h"
#include "restrict-process-size.h"
#include "eacces-error.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "dup2-array.h"
};
str_truncate(path, 0);
- return var_expand_new(path, l->set.fileset.set->path, ¶ms, error_r);
+ return var_expand(path, l->set.fileset.set->path, ¶ms, error_r);
}
static void
#include "array.h"
#include "json-generator.h"
#include "str.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "mail-user.h"
#include "mail-storage.h"
#include "mail-storage-private.h"
json_append_escaped(username, user->username);
json_append_escaped(mboxname, mailbox_get_vname(box));
- const struct var_expand_table_new values[] = {
+ const struct var_expand_table values[] = {
{ .key = "username", .value = str_c(username) },
{ .key = "mailbox", .value = str_c(mboxname) },
{ .key = "messages", .value = dec2str(status.messages) },
const char *key =
t_strdup_printf(NOTIFY_STATUS_KEY, mailbox_get_vname(box));
string_t *dest = t_str_new(64);
- if (var_expand_new(dest, nuser->set->notify_status_value,
+ if (var_expand(dest, nuser->set->notify_status_value,
¶ms, &error) < 0) {
e_error(box->event, "notify-status: var_expand(%s) failed: %s",
nuser->set->notify_status_value, error);
#include "lib.h"
#include "test-common.h"
#include "str.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "randgen.h"
#include "dcrypt.h"
for(i=0; i < N_ELEMENTS(test_cases); i++) T_BEGIN {
const char *error;
string_t *dest = t_str_new(32);
- int ret = var_expand_new(dest, test_cases[i].input, ¶ms, &error);
+ int ret = var_expand(dest, test_cases[i].input, ¶ms, &error);
if (ret < 0) {
if (test_cases[i].expect_ret == -1)
i_info("Expected: var_expand(%s): %s", test_cases[i].input, error);
str_truncate(input, 0);
str_truncate(output, 0);
- test_assert_idx(var_expand_new(input, "%{decrypted|encrypt(algorithm='aes-128-cbc',key=key)}", ¶ms, &error) == 0, i);
+ test_assert_idx(var_expand(input, "%{decrypted|encrypt(algorithm='aes-128-cbc',key=key)}", ¶ms, &error) == 0, i);
table[5].value = str_c(input);
- test_assert_idx(var_expand_new(output, "%{encrypted2|decrypt(algorithm='aes-128-cbc',key=key)}", ¶ms, &error) == 0, i);
+ test_assert_idx(var_expand(output, "%{encrypted2|decrypt(algorithm='aes-128-cbc',key=key)}", ¶ms, &error) == 0, i);
test_assert_strcmp_idx(str_c(output), table[4].value, i);
};
#include "hostpid.h"
#include "file-dotlock.h"
#include "settings.h"
-#include "var-expand-new.h"
#include "master-service.h"
#include "mail-storage.h"
#include "mail-storage-service.h"
event_add_int(client->event, "net_out_bytes", client->output->offset);
str = t_str_new(128);
- if (var_expand_new(str, client->set->pop3_logout_format,
+ if (var_expand(str, client->set->pop3_logout_format,
¶ms, &error) < 0) {
e_error(client->event,
"Failed to expand pop3_logout_format=%s: %s",
#include "hash.h"
#include "str.h"
#include "strfuncs.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "message-size.h"
#include "mail-storage.h"
#include "mail-storage-settings.h"
};
const char *error;
- if (var_expand_new(str, client->mail_set->pop3_uidl_format,
+ if (var_expand(str, client->mail_set->pop3_uidl_format,
¶ms, &error) < 0) {
e_error(client->event,
"UIDL: Failed to expand pop3_uidl_format=%s: %s",
#include "service-settings.h"
#include "mail-storage-settings.h"
#include "pop3-settings.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include <unistd.h>
#include "str-sanitize.h"
#include "stats-dist.h"
#include "time-util.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
#include "event-filter.h"
#include "event-exporter.h"
#include "settings.h"
},
};
string_t *str = t_str_new(128);
- if (var_expand_new(str, group_by->discrete_modifier, ¶ms, &error) < 0) {
+ if (var_expand(str, group_by->discrete_modifier, ¶ms, &error) < 0) {
i_error("Failed to expand discrete modifier for %s: %s",
group_by->field, error);
}
#include "event-exporter.h"
#include "array.h"
#include "str.h"
-#include "var-expand-new.h"
+#include "var-expand.h"
/* <settings checks> */
#include "event-filter.h"
};
const char *error;
string_t *str = t_str_new(128);
- if (var_expand_new(str, group_by->discrete_modifier, &vparams, &error) < 0) {
+ if (var_expand(str, group_by->discrete_modifier, &vparams, &error) < 0) {
*error_r = t_strdup_printf(
"Failed to expand discrete modifier for %s: %s",
group_by->field, error);
event_add_int(client->event, "net_out_bytes", stats->output);
str = t_str_new(128);
- if (var_expand_new(str, client->set->submission_logout_format,
+ if (var_expand(str, client->set->submission_logout_format,
¶ms, &error) < 0) {
e_error(client->event,
"Failed to expand submission_logout_format=%s: %s",