diff options
Diffstat (limited to 'pigeonhole/src/lib-managesieve/managesieve-quote.c')
-rw-r--r-- | pigeonhole/src/lib-managesieve/managesieve-quote.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-managesieve/managesieve-quote.c b/pigeonhole/src/lib-managesieve/managesieve-quote.c new file mode 100644 index 0000000..a86818c --- /dev/null +++ b/pigeonhole/src/lib-managesieve/managesieve-quote.c @@ -0,0 +1,121 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "unichar.h" +#include "managesieve-parser.h" +#include "managesieve-quote.h" + +/* Turn the value string into a valid MANAGESIEVE string or literal, no matter + * what. QUOTED-SPECIALS are escaped, but any invalid (UTF-8) character + * is simply removed. Linebreak characters are not considered invalid, but + * they do force the generation of a string literal. + */ +void managesieve_quote_append(string_t *str, const unsigned char *value, + size_t value_len, bool compress_lwsp) +{ + size_t i, extra = 0, escape = 0; + string_t *tmp; + bool + last_lwsp = TRUE, + literal = FALSE, + modify = FALSE; + + if (value == NULL) { + str_append(str, "\"\""); + return; + } + + if (value_len == (size_t)-1) + value_len = strlen((const char *) value); + + for (i = 0; i < value_len; i++) { + switch (value[i]) { + case ' ': + case '\t': + if (last_lwsp && compress_lwsp) { + modify = TRUE; + extra++; + } + last_lwsp = TRUE; + break; + case '"': + case '\\': + escape++; + last_lwsp = FALSE; + break; + case 13: + case 10: + literal = TRUE; + last_lwsp = TRUE; + break; + default: + last_lwsp = FALSE; + } + } + + if (!literal) { + /* no linebreak chars, return as (escaped) "string" */ + str_append_c(str, '"'); + } else { + /* return as literal */ + str_printfa(str, "{%zu}\r\n", value_len - extra); + } + + tmp = t_str_new(value_len+escape+4); + if (!modify && (literal || escape == 0)) + str_append_data(tmp, value, value_len); + else { + last_lwsp = TRUE; + for (i = 0; i < value_len; i++) { + switch (value[i]) { + case '"': + case '\\': + last_lwsp = FALSE; + if (!literal) + str_append_c(tmp, '\\'); + str_append_c(tmp, value[i]); + break; + case ' ': + case '\t': + if (!last_lwsp || !compress_lwsp) + str_append_c(tmp, ' '); + last_lwsp = TRUE; + break; + case 13: + case 10: + last_lwsp = TRUE; + str_append_c(tmp, value[i]); + break; + default: + last_lwsp = FALSE; + str_append_c(tmp, value[i]); + break; + } + } + } + + if ( uni_utf8_get_valid_data(str_data(tmp), str_len(tmp), str) ) + str_append_str(str, tmp); + + if (!literal) + str_append_c(str, '"'); +} + +char *managesieve_quote(pool_t pool, const unsigned char *value, size_t value_len) +{ + string_t *str; + char *ret; + + if (value == NULL) + return "\"\""; + + T_BEGIN { + str = t_str_new(value_len + MAX_INT_STRLEN + 5); + managesieve_quote_append(str, value, value_len, TRUE); + ret = p_strndup(pool, str_data(str), str_len(str)); + } T_END; + + return ret; +} |