bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
bb979386852c7689dc66c0fce03319382f66d501Timo Sirainen const char *(*func)(const char *, struct var_expand_context *);
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomistatic ARRAY(struct var_expand_extension_func_table) var_expand_extensions;
bb979386852c7689dc66c0fce03319382f66d501Timo Sirainenstatic const char *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenm_str_lcase(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
bb979386852c7689dc66c0fce03319382f66d501Timo Sirainenstatic const char *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenm_str_ucase(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
bb979386852c7689dc66c0fce03319382f66d501Timo Sirainenstatic const char *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenm_str_escape(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
bb979386852c7689dc66c0fce03319382f66d501Timo Sirainenstatic const char *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenm_str_hex(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
7cd08c67fde5371f662d8c95b30c341741950420Timo Sirainen unsigned long long l;
8e0f89885f2ce60961da9ae2d96d71c7109e6032Timo Sirainenstatic const char *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenm_str_reverse(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
bb979386852c7689dc66c0fce03319382f66d501Timo Sirainenstatic const char *m_str_hash(const char *str, struct var_expand_context *ctx)
e95bc848767afa2e52cb988a6d3f5e5cc5933885Timo Sirainenstatic const char *
e95bc848767afa2e52cb988a6d3f5e5cc5933885Timo Sirainenm_str_newhash(const char *str, struct var_expand_context *ctx)
9217571849eb99d1003e150e3165aedf06b07521Timo Sirainen unsigned int i;
9217571849eb99d1003e150e3165aedf06b07521Timo Sirainen for (i = 0; i < sizeof(value); i++) {
546d3609e0811a147269ee9979eb90649445f5acTimo Sirainenstatic const char *
546d3609e0811a147269ee9979eb90649445f5acTimo Sirainenm_str_md5(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
546d3609e0811a147269ee9979eb90649445f5acTimo Sirainenstatic const char *
546d3609e0811a147269ee9979eb90649445f5acTimo Sirainenm_str_ldap_dn(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
546d3609e0811a147269ee9979eb90649445f5acTimo Sirainenstatic const char *
546d3609e0811a147269ee9979eb90649445f5acTimo Sirainenm_str_trim(const char *str, struct var_expand_context *ctx ATTR_UNUSED)
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainenstatic const struct var_expand_modifier modifiers[] = {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenvar_expand_short(const struct var_expand_table *table, char key,
2c2bcffb5d26ebf0c7cc0c6586feda4ce7967e98Aki Tuomi const struct var_expand_table *t;
7c3a801caa8daa9a7f57e61b4d1e63f02a51e7e4Timo Sirainen /* not found */
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen *error_r = t_strdup_printf("Unknown variable '%%%c'", key);
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi } else if ((method = hash_method_lookup(algo)) == NULL) {
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi if ((ret = var_expand_long(ctx, field, strlen(field),
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi /* default values */
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi "Cannot parse hash arguments:"
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi "'%s' is not number for rounds",
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi "Cannot parse hash arguments:"
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi "rounds must be at least 1");
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi "Cannot parse hash arguments:"
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi "'%s' is not number for truncbits",
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi truncbits = I_MIN(truncbits, method->digest_size*8);
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi if (var_expand_with_funcs(salt, value, ctx->table,
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi "Cannot parse hash arguments:"
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi "'%s' is not supported format",
7c4af1fdcb1aa5ece9fd6c8a893789666ae29dbbAki Tuomi void *context = t_malloc_no0(method->context_size);
e130dc7c712a10215b1e6be56403bbb934826251Timo Sirainenvar_expand_func(const struct var_expand_func_table *func_table,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const char *key, const char *data, void *context,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen for (; func_table->key != NULL; func_table++) {
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen ret = func_table->func(data, context, &value, error_r);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen *error_r = t_strdup_printf("Unknown variable '%%%s'", key);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen *var_r = t_strdup_printf("UNSUPPORTED_VARIABLE_%s", key);
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomivar_expand_try_extension(struct var_expand_context *ctx,
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi /* try with extensions */
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi /* ensure we won't match abbreviations */
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi if (strncasecmp(key, f->key, len) == 0 && f->key[len] == '\0')
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi if ((ret = var_expand_func(ctx->func_table, key, data,
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi *error_r = t_strdup_printf("Unknown variable '%%%s'", key);
2c2bcffb5d26ebf0c7cc0c6586feda4ce7967e98Aki Tuomi const struct var_expand_table *t;
93794594bc682b12353d2d0db08d91ae3e7c56c6Timo Sirainen strncmp(t->long_key, key_start, key_len) == 0 &&
927d3977d5598f12ae18d4fa3f22b9e913f7dd46Timo Sirainen /* built-in variables: */
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi ret = var_expand_try_extension(ctx, key, data, &value, error_r);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenint var_expand_with_funcs(string_t *dest, const char *str,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const struct var_expand_func_table *func_table,
2c2bcffb5d26ebf0c7cc0c6586feda4ce7967e98Aki Tuomi const struct var_expand_modifier *m;
bb979386852c7689dc66c0fce03319382f66d501Timo Sirainen (const char *, struct var_expand_context *);
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi /* reset per-field modifiers */
7cd08c67fde5371f662d8c95b30c341741950420Timo Sirainen /* [<offset>.]<width>[<modifiers>]<variable> */
d35364f4d7d139b4150d290e14717e10f1ede4cdTimo Sirainen /* if offset was prefixed with zero (or it was
d35364f4d7d139b4150d290e14717e10f1ede4cdTimo Sirainen plain zero), just ignore that. zero padding
d35364f4d7d139b4150d290e14717e10f1ede4cdTimo Sirainen is done with the width. */
7cd08c67fde5371f662d8c95b30c341741950420Timo Sirainen /* @UNSAFE */
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen if (*str == '{' && (end = strchr(str, '}')) != NULL) {
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen /* %{long_key} */
e0dddec702cceb77536a659c71b1973a71c09192Aki Tuomi /* it needs to come back a bit */
e0dddec702cceb77536a659c71b1973a71c09192Aki Tuomi /* if there is no } it will consume rest of the
7cd08c67fde5371f662d8c95b30c341741950420Timo Sirainen for (i = 0; i < modifier_count; i++)
a40649829bce4c8de6210a2cb4a4b4cf5bb40da8Timo Sirainen /* if offset is < 0 then we want to
a40649829bce4c8de6210a2cb4a4b4cf5bb40da8Timo Sirainen start at the end */
d35364f4d7d139b4150d290e14717e10f1ede4cdTimo Sirainen /* %05d -like padding. no truncation. */
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenint var_expand(string_t *dest, const char *str,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const struct var_expand_table *table, const char **error_r)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return var_expand_with_funcs(dest, str, table, NULL, NULL, error_r);
7a556ac46f1f51ee29bc8aa92b5ffe05b004a8b8Timo Sirainenvar_get_key_range_full(const char *str, unsigned int *idx_r,
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainen unsigned int *size_r)
ee3cb11d230d549367a1213aefe4598345796256Timo Sirainen const struct var_expand_modifier *m;
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainen unsigned int i = 0;
7cd08c67fde5371f662d8c95b30c341741950420Timo Sirainen /* [<offset>.]<width>[<modifiers>]<variable> */
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainen while ((str[i] >= '0' && str[i] <= '9') || str[i] == '-')
6eb191b58bc8553a516bd1c9b0eccaa696d0f41fTimo Sirainen while ((str[i] >= '0' && str[i] <= '9') || str[i] == '-')
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainen /* short key */
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainen /* long key */
7a556ac46f1f51ee29bc8aa92b5ffe05b004a8b8Timo Sirainenvoid var_get_key_range(const char *str, unsigned int *idx_r,
7a556ac46f1f51ee29bc8aa92b5ffe05b004a8b8Timo Sirainen unsigned int *size_r)
7a556ac46f1f51ee29bc8aa92b5ffe05b004a8b8Timo Sirainen (void)var_get_key_range_full(str, idx_r, size_r);
771178a5c5285aa596723591271c8936c4007f1bTimo Sirainenstatic bool var_has_long_key(const char **str, const char *long_key)
771178a5c5285aa596723591271c8936c4007f1bTimo Sirainen if (strncmp(start, long_key, end-start) == 0 &&
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainenbool var_has_key(const char *str, char key, const char *long_key)
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi /* put all hash methods there */
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi for(const struct hash_method **meth = hash_methods;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi func = array_append_space(&var_expand_extensions);
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomivar_expand_register_func_array(const struct var_expand_extension_func_table *funcs)
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi for(const struct var_expand_extension_func_table *ptr = funcs;
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomivar_expand_unregister_func_array(const struct var_expand_extension_func_table *funcs)
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi for(const struct var_expand_extension_func_table *ptr = funcs;
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi for(unsigned int i = 0; i < array_count(&var_expand_extensions); i++) {
5c00a22fcca7f68479a8768fec7ace7f679b344dAki Tuomi const struct var_expand_extension_func_table *func =
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomivar_expand_merge_tables(pool_t pool, const struct var_expand_table *a,
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi const struct var_expand_table *b)