From 5165f76b7cbcc6db541b0c76f3e07cfe52ca71b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Sat, 30 Oct 2021 04:18:52 +0200 Subject: [PATCH] xC: quote text coming from a bracketed paste Not having this has caused me much annoyance over the years. --- xC.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/xC.c b/xC.c index 3de9f26..a5a8070 100644 --- a/xC.c +++ b/xC.c @@ -2445,6 +2445,10 @@ static struct config_schema g_config_behaviour[] = { .name = "editor_command", .comment = "VIM: \"vim +%Bgo %F\", Emacs: \"emacs -nw +%L:%C %F\"", .type = CONFIG_ITEM_STRING }, + { .name = "process_pasted_text", + .comment = "Normalize newlines and quote the command prefix in pastes", + .type = CONFIG_ITEM_BOOLEAN, + .default_ = "on" }, { .name = "date_change_line", .comment = "Input to strftime(3) for the date change line", .type = CONFIG_ITEM_STRING, @@ -12624,8 +12628,6 @@ process_input (struct app_context *ctx, char *user_input) else { struct strv lines = strv_make (); - - // XXX: this interprets commands in pasted text cstr_split (input, "\r\n", false, &lines); for (size_t i = 0; i < lines.len; i++) (void) process_input_utf8 (ctx, @@ -14234,6 +14236,40 @@ done: #define BRACKETED_PASTE_LIMIT 102400 ///< How much text can be pasted +static bool +insert_paste (struct app_context *ctx, char *paste, size_t len) +{ + if (!get_config_boolean (ctx->config.root, "behaviour.process_pasted_text")) + return CALL_ (ctx->input, insert, paste); + + // Without ICRNL, which Editline keeps but Readline doesn't, + // the terminal sends newlines as carriage returns (seen on urxvt) + for (size_t i = 0; i < len; i++) + if (paste[i] == '\r') + paste[i] = '\n'; + + int position = 0; + char *input = CALL_ (ctx->input, get_line, &position); + bool quote_first_slash = !position || strchr ("\r\n", input[position - 1]); + free (input); + + // Executing commands by accident is much more common than pasting them + // intentionally, although the latter may also have security consequences + struct str processed = str_make (); + str_reserve (&processed, len); + for (size_t i = 0; i < len; i++) + { + if (paste[i] == '/' + && ((!i && quote_first_slash) || (i && paste[i - 1] == '\n'))) + str_append_c (&processed, paste[i]); + str_append_c (&processed, paste[i]); + } + + bool success = CALL_ (ctx->input, insert, processed.str); + str_free (&processed); + return success; +} + static void process_bracketed_paste (const struct pollfd *fd, struct app_context *ctx) { @@ -14258,7 +14294,7 @@ process_bracketed_paste (const struct pollfd *fd, struct app_context *ctx) (int) (text_len = BRACKETED_PASTE_LIMIT)); buf->str[text_len] = '\0'; - if (CALL_ (ctx->input, insert, buf->str)) + if (insert_paste (ctx, buf->str, text_len)) goto done; error: