|
| 1 | +--- |
| 2 | +layout: doc |
| 3 | +title: Variable expansion design |
| 4 | +dovecotlinks: |
| 5 | + var_expand: variable expansion design |
| 6 | +--- |
| 7 | + |
| 8 | +# Variable expansion design |
| 9 | + |
| 10 | +Dovecot comes with powerful variable expansion system, which allows constructing reusable text templates. |
| 11 | +This has been upgraded since v2.3 to a more flexible systemt . |
| 12 | + |
| 13 | +## Syntax |
| 14 | + |
| 15 | +``` |
| 16 | +<var> ::= <expression-list> |
| 17 | +<expression-list> ::= <expression-list> <expression> |
| 18 | +<expression> ::= <VALUE>, "{" <filter-list> "}", "%" |
| 19 | +<filter-list> ::= <filter-list> "|" <filter>, <filter> |
| 20 | +<filter> ::= <func> <math-list> |
| 21 | +<math-list> ::= <math> |
| 22 | +<math> ::= <operator> <number>, <operator> <NAME> |
| 23 | +<number> ::= "-" <NUMBER>, <NUMBER> |
| 24 | +<operator> ::= "+", "-", "*", "/" |
| 25 | +<func> ::= <NAME> <arguments> |
| 26 | +<arguments> ::= "(" <argument-list> ")" |
| 27 | +<argument-list> ::= <argument-list> "," <argument> |
| 28 | +<argument> ::= <VALUE>, <NAME>, <number>, <key> "=" <number>, <key> "=" <NAME>, <key> "=" <VALUE> |
| 29 | +
|
| 30 | +NAME = string |
| 31 | +VALUE = "string" or 'string' |
| 32 | +NUMBER = [0-9]+ |
| 33 | +``` |
| 34 | + |
| 35 | +## Design |
| 36 | + |
| 37 | +Internally, everything is stored in a binary-safe string container. There is no other data type internally. |
| 38 | +This buffer can be set and unset, and the content can be tagged by filters to be binary or string. |
| 39 | + |
| 40 | +The system uses programs to perform the actual expansion. The given input is always first parsed into a list of programs. |
| 41 | +Input that consists from multiple expansions separated by non-expansion strings is split into multiple programs. |
| 42 | +Once program is compiled, it can be executed multiple times with different parameters. |
| 43 | + |
| 44 | +Program parameters consists from variable table(s), provider(s) and escape function. A program can be executed with different parameters. |
| 45 | + |
| 46 | +## Parameters |
| 47 | + |
| 48 | +Parameters are provided via `struct var_expand_params`. Variable mappings are provided via `struct var_expand_table` array, which is `VAR_EXPAND_TABLE_END` terminated list of |
| 49 | +key-value mappings. Key's value can also be provided by a function. |
| 50 | + |
| 51 | +Providers are used to handle scoped variables, such as passdb, ldap etc. There are also global providers which are always available. |
| 52 | + |
| 53 | +Providers can be provide with `struct var_expand_provider` array which contains prefix and provider function, and is `VAR_EXPAND_TABLE_END` terminated. |
| 54 | + |
| 55 | +It is also possible to provide escape function, which is applied to each %{pipeline} output. |
| 56 | + |
| 57 | +Key functions and providers use the same context. |
| 58 | + |
| 59 | +Key-value tables and providers can also be provided as arrays of arrays, which must be NULL terminated. |
| 60 | +Contexts for these must be provided in an array that is `VAR_EXPAND_CONTEXTS_END` terminated. |
| 61 | + |
| 62 | +When these arrays are used, first match wins. |
| 63 | + |
| 64 | +## Filters |
| 65 | + |
| 66 | +Filters are functions that accept input from left side and emit output to right side. They can accept positional and named parameters. |
| 67 | +Some filters can start expressions, namely ones that do not require any input. |
| 68 | + |
| 69 | +## Variables |
| 70 | + |
| 71 | +Variables are always considered to be strings. NULL value is considered same as empty value. Variable names are unique, and if table contains |
| 72 | +multiple variables with same name, the first is always used. |
| 73 | + |
| 74 | +Variable can exist as parameter to filters or as the first token in expression. |
| 75 | + |
| 76 | +## Output handling |
| 77 | + |
| 78 | +If a program ends up with binary tagged output, the output is automatically hex-encoded. |
| 79 | +If there is no key in table or provider, error will occur. |
| 80 | +This error can be negated with `default(value)` filter, which clears error. |
0 commit comments