diff options
-rw-r--r-- | include/mailutils/wordsplit.h | 6 | ||||
-rw-r--r-- | libmailutils/string/wordsplit.c | 55 | ||||
-rw-r--r-- | libmailutils/tests/wordsplit.at | 17 |
3 files changed, 66 insertions, 12 deletions
diff --git a/include/mailutils/wordsplit.h b/include/mailutils/wordsplit.h index 3ddedb67a..0ce33a33e 100644 --- a/include/mailutils/wordsplit.h +++ b/include/mailutils/wordsplit.h @@ -28,6 +28,7 @@ struct mu_wordsplit int ws_flags; const char *ws_delim; const char *ws_comment; + const char *ws_escape; void (*ws_alloc_die) (struct mu_wordsplit *wsp); void (*ws_error) (const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2))); @@ -110,6 +111,9 @@ struct mu_wordsplit stored in the element that follows its name. */ #define MU_WRDSF_ENV_KV 0x4000000 +/* ws_escape is set */ +#define MU_WRDSF_ESCAPE 0x8000000 + #define MU_WRDSF_DEFFLAGS \ (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | \ MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS | MU_WRDSF_CESCAPES) @@ -132,6 +136,8 @@ int mu_wordsplit_c_unquote_char (int c); int mu_wordsplit_c_quote_char (int c); size_t mu_wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote); +void mu_wordsplit_general_unquote_copy (char *dst, const char *src, size_t n, + const char *escapable); void mu_wordsplit_sh_unquote_copy (char *dst, const char *src, size_t n); void mu_wordsplit_c_unquote_copy (char *dst, const char *src, size_t n); void mu_wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex); diff --git a/libmailutils/string/wordsplit.c b/libmailutils/string/wordsplit.c index 26342dc3c..4536cc214 100644 --- a/libmailutils/string/wordsplit.c +++ b/libmailutils/string/wordsplit.c @@ -500,7 +500,12 @@ wsnode_quoteremoval (struct mu_wordsplit *wsp) p->v.word = newstr; p->flags |= _WSNF_WORD; } - uqfn (p->v.word, str, slen); + + if (wsp->ws_flags & MU_WRDSF_ESCAPE) + mu_wordsplit_general_unquote_copy (p->v.word, str, slen, + wsp->ws_escape); + else + uqfn (p->v.word, str, slen); } } return 0; @@ -906,32 +911,39 @@ node_expand_vars (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node) return 0; } -static int -mu_wordsplit_varexp (struct mu_wordsplit *wsp) +/* Remove NULL lists */ +static void +wsnode_nullelim (struct mu_wordsplit *wsp) { struct mu_wordsplit_node *p; for (p = wsp->ws_head; p;) { struct mu_wordsplit_node *next = p->next; - if (!(p->flags & _WSNF_NOEXPAND)) - if (node_expand_vars (wsp, p)) - return 1; + if (p->flags & _WSNF_NULL) + { + wsnode_remove (wsp, p); + wsnode_free (p); + } p = next; } +} + +static int +mu_wordsplit_varexp (struct mu_wordsplit *wsp) +{ + struct mu_wordsplit_node *p; - /* Remove NULL lists */ for (p = wsp->ws_head; p;) { struct mu_wordsplit_node *next = p->next; - if (p->flags & _WSNF_NULL) - { - wsnode_remove (wsp, p); - wsnode_free (p); - } + if (!(p->flags & _WSNF_NOEXPAND)) + if (node_expand_vars (wsp, p)) + return 1; p = next; } + wsnode_nullelim (wsp); return 0; } @@ -959,7 +971,11 @@ mu_wordsplit_trimws (struct mu_wordsplit *wsp) for (n = p->v.segm.end; n > p->v.segm.beg && ISWS (wsp->ws_input[n-1]); n--); p->v.segm.end = n; + if (p->v.segm.beg == p->v.segm.end) + p->flags |= _WSNF_NULL; } + + wsnode_nullelim (wsp); } static int @@ -1217,6 +1233,21 @@ mu_wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote) } void +mu_wordsplit_general_unquote_copy (char *dst, const char *src, size_t n, + const char *escapable) +{ + int i; + + for (i = 0; i < n;) + { + if (src[i] == '\\' && i < n && strchr (escapable, src[i+1])) + i++; + *dst++ = src[i++]; + } + *dst = 0; +} + +void mu_wordsplit_sh_unquote_copy (char *dst, const char *src, size_t n) { int i; diff --git a/libmailutils/tests/wordsplit.at b/libmailutils/tests/wordsplit.at index 8625f9538..99b0dcb72 100644 --- a/libmailutils/tests/wordsplit.at +++ b/libmailutils/tests/wordsplit.at @@ -313,6 +313,15 @@ TESTWSP([C escapes off],[],[-cescapes], 3: newnline ]) +TESTWSP([ws elimination],[],[delim ' ()' ws return_delims], +[( list items )], +[NF: 4 +0: ( +1: list +2: items +3: ) +]) + TESTWSP([empty quotes],[],[delim : ws return_delims], [t=""], [NF: 1 @@ -338,4 +347,12 @@ TESTWSP([suppress ws trimming within quotes],[], 4: "formatfield=In message %{text}, " ]) +TESTWSP([unescape],[],[-default novar nocmd quote escape '\"'], +[\Seen "quote \"" "bs \\"], +[NF: 3 +0: \\Seen +1: "quote \"" +2: "bs \\" +]) + m4_popdef([TESTWSP]) |