summaryrefslogtreecommitdiffstats
path: root/init.c
diff options
context:
space:
mode:
authorKevin McCarthy <kevin@8t8.us>2020-06-26 12:31:22 -0700
committerKevin McCarthy <kevin@8t8.us>2020-06-26 14:07:37 -0700
commite53ae9edaf0b863eba5461d50f1aabc8c7321c82 (patch)
treebad2c36dd9c0a2b1da80208b7e2e6b19b19dceee /init.c
parente5a32a61ba659f57025111982e86d652fe53f649 (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.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/init.c b/init.c
index 499eefd7..ef83648a 100644
--- a/init.c
+++ b/init.c
@@ -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;