diff options
author | Kevin McCarthy <kevin@8t8.us> | 2020-06-26 12:31:22 -0700 |
---|---|---|
committer | Kevin McCarthy <kevin@8t8.us> | 2020-06-26 14:07:37 -0700 |
commit | e53ae9edaf0b863eba5461d50f1aabc8c7321c82 (patch) | |
tree | bad2c36dd9c0a2b1da80208b7e2e6b19b19dceee /init.c | |
parent | e5a32a61ba659f57025111982e86d652fe53f649 (diff) |
Escape config vars when expanding hook "command" argument.
The "command" parameter of folder, send, send2, account, reply, and
message hooks is run through mutt_extract_token() twice. Once when
parsing the hook command initially, and once via mutt_parse_rc_line()
when the actual hook fires.
In theory, Mutt users should be aware of this, and should place all
their command strings with configuration variables in single-quotes,
to delay expansion until execution.
But in reality Mutt has been escaping configuration variables as part
of mutt_extract_token() for many years.
The previous commit turned the escaping off, because it damages
"backup" assignments to a $my_ variable, and I believe is confusing
behavior.
But for hooks, users now expect the escaping behavior (for
double-quoted or unquoted command strings).
Note that mutt_parse_hook() also passed the MUTT_TOKEN_SPACE flag, but
neglected to do so for message-hook. Since all other "command"
argument hooks were included, and were added to the list over the
years, I believe this was an accidental oversight.
Diffstat (limited to 'init.c')
-rw-r--r-- | init.c | 44 |
1 files changed, 43 insertions, 1 deletions
@@ -72,6 +72,7 @@ typedef struct myvar static myvar_t* MyVars; static int var_to_string (int idx, BUFFER *val); +static void escape_string_to_buffer (BUFFER *dst, const char *src); static void myvar_set (const char* var, const char* val); static const char* myvar_get (const char* var); @@ -311,7 +312,18 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int flags) BUFFER *val = mutt_buffer_pool_get (); if (var_to_string (idx, val)) - mutt_buffer_addstr (dest, mutt_b2s (val)); + { + if (flags & MUTT_TOKEN_ESC_VARS) + { + BUFFER *escval = mutt_buffer_pool_get (); + + escape_string_to_buffer (escval, mutt_b2s (val)); + mutt_buffer_addstr (dest, mutt_b2s (escval)); + mutt_buffer_pool_release (&escval); + } + else + mutt_buffer_addstr (dest, mutt_b2s (val)); + } mutt_buffer_pool_release (&val); } FREE (&var); @@ -1888,6 +1900,36 @@ static void mutt_restore_default (struct option_t *p) mutt_set_current_menu_redraw_full (); } +static void escape_string_to_buffer (BUFFER *dst, const char *src) +{ + mutt_buffer_clear (dst); + + if (!src || !*src) + return; + + for (; *src; src++) + { + switch (*src) + { + case '\n': + mutt_buffer_addstr (dst, "\\n"); + break; + case '\r': + mutt_buffer_addstr (dst, "\\r"); + break; + case '\t': + mutt_buffer_addstr (dst, "\\t"); + break; + case '\\': + case '"': + mutt_buffer_addch (dst, '\\'); + /* fall through */ + default: + mutt_buffer_addch (dst, *src); + } + } +} + static size_t escape_string (char *dst, size_t len, const char* src) { char* p = dst; |