Mercurial > dovecot > core-2.2
view src/lib/strescape.c @ 17112:9735c6fb7e39
liblib: Added str_unescape_next()
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 15 Jan 2014 16:44:04 -0500 |
parents | 36ef72481934 |
children | add8c00fb3cc |
line wrap: on
line source
/* Copyright (c) 2003-2013 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "str.h" #include "strescape.h" const char *str_escape(const char *str) { const char *p; string_t *ret; /* see if we need to quote it */ for (p = str; *p != '\0'; p++) { if (IS_ESCAPED_CHAR(*p)) break; } if (*p == '\0') return str; /* quote */ ret = t_str_new((size_t) (p - str) + 128); str_append_n(ret, str, (size_t) (p - str)); for (; *p != '\0'; p++) { if (IS_ESCAPED_CHAR(*p)) str_append_c(ret, '\\'); str_append_c(ret, *p); } return str_c(ret); } void str_append_unescaped(string_t *dest, const void *src, size_t src_size) { const unsigned char *src_c = src; size_t start = 0, i = 0; while (i < src_size) { for (; i < src_size; i++) { if (src_c[i] == '\\') break; } str_append_n(dest, src_c + start, i-start); if (i < src_size) { if (++i == src_size) break; str_append_c(dest, src_c[i++]); } start = i; } } char *str_unescape(char *str) { /* @UNSAFE */ char *dest, *start = str; while (*str != '\\') { if (*str == '\0') return start; str++; } for (dest = str; *str != '\0'; str++) { if (*str == '\\') { str++; if (*str == '\0') break; } *dest++ = *str; } *dest = '\0'; return start; } int str_unescape_next(const char **str, const char **unescaped_r) { const char *p; char *escaped; bool esc_found = FALSE; for (p = *str; *p != '\0'; p++) { if (*p == '"') break; else if (*p == '\\') { if (p[1] == '\0') return -1; esc_found = TRUE; p++; } } if (*p != '"') return -1; escaped = p_strdup_until(unsafe_data_stack_pool, *str, p); *str = p+1; *unescaped_r = !esc_found ? escaped : str_unescape(escaped); return 0; } void str_append_tabescaped(string_t *dest, const char *src) { for (; *src != '\0'; src++) { switch (*src) { case '\001': str_append_c(dest, '\001'); str_append_c(dest, '1'); break; case '\t': str_append_c(dest, '\001'); str_append_c(dest, 't'); break; case '\r': str_append_c(dest, '\001'); str_append_c(dest, 'r'); break; case '\n': str_append_c(dest, '\001'); str_append_c(dest, 'n'); break; default: str_append_c(dest, *src); break; } } } const char *str_tabescape(const char *str) { string_t *tmp; const char *p; for (p = str; *p != '\0'; p++) { if (*p <= '\r') { tmp = t_str_new(128); str_append_n(tmp, str, p-str); str_append_tabescaped(tmp, p); return str_c(tmp); } } return str; } void str_append_tabunescaped(string_t *dest, const void *src, size_t src_size) { const unsigned char *src_c = src; size_t start = 0, i = 0; while (i < src_size) { for (; i < src_size; i++) { if (src_c[i] == '\001') break; } str_append_n(dest, src_c + start, i-start); if (i < src_size) { i++; if (i < src_size) { switch (src_c[i]) { case '1': str_append_c(dest, '\001'); break; case 't': str_append_c(dest, '\t'); break; case 'r': str_append_c(dest, '\r'); break; case 'n': str_append_c(dest, '\n'); break; default: str_append_c(dest, src_c[i]); break; } i++; } } start = i; } } char *str_tabunescape(char *str) { /* @UNSAFE */ char *dest, *start = str; while (*str != '\001') { if (*str == '\0') return start; str++; } for (dest = str; *str != '\0'; str++) { if (*str != '\001') *dest++ = *str; else { str++; if (*str == '\0') break; switch (*str) { case '1': *dest++ = '\001'; break; case 't': *dest++ = '\t'; break; case 'r': *dest++ = '\r'; break; case 'n': *dest++ = '\n'; break; default: *dest++ = *str; break; } } } *dest = '\0'; return start; } char **p_strsplit_tabescaped(pool_t pool, const char *str) { char **args; unsigned int i; args = p_strsplit(pool, str, "\t"); for (i = 0; args[i] != NULL; i++) args[i] = str_tabunescape(args[i]); return args; } const char *const *t_strsplit_tabescaped(const char *str) { return (void *)p_strsplit_tabescaped(pool_datastack_create(), str); }