From f12d007414a7f64c43373806ff487b25fffacb3b Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 29 Sep 2015 19:48:18 -0400 Subject: [PATCH] Account for 'shellslash' being set on Windows If a user has 'shellslash' set in Windows, then filename related functionality uses forward slashes instead of backslashes. This breaks running of external commands because some external commands in Windows treat any forward slash as a command line switch. This change adds s:shellescape(), which wraps Vim's shellescape(), but ensures 'noshellslash' is set first in Windows command prompt (not Cygwin or msys) environments. Having 'noshellslash' set when shellescape() is called causes the string to be quoted, regardless of whether there is whitespace or typical special characters, thus avoiding the interpretation of the string as being command line switches. Closes jamessan/vim-gnupg#41 Signed-off-by: James McCoy --- plugin/gnupg.vim | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/plugin/gnupg.vim b/plugin/gnupg.vim index 3faadcc..926705d 100644 --- a/plugin/gnupg.vim +++ b/plugin/gnupg.vim @@ -214,6 +214,29 @@ highlight default link GPGHighlightUnknownRecipient ErrorMsg " Section: Functions {{{1 +" Function: s:shellescape(s[, special]) {{{2 +" +" Calls shellescape(), also taking into account 'shellslash' +" when on Windows and using $COMSPEC as the shell. +" +" Returns: shellescaped string +" +function s:shellescape(s, ...) + let special = a:0 ? a:1 : 0 + if exists('+shellslash') && &shell == $COMSPEC + let ssl = &shellslash + set noshellslash + + let escaped = shellescape(a:s, special) + + let &shellslash = ssl + else + let escaped = shellescape(a:s, special) + endif + + return escaped +endfunction + " Function: s:GPGInit(bufread) {{{2 " " initialize the plugin @@ -447,7 +470,7 @@ function s:GPGDecrypt(bufread) " find the recipients of the file let cmd = { 'level': 3 } - let cmd.args = '--verbose --decrypt --list-only --dry-run --no-use-agent --logger-fd 1 ' . shellescape(filename) + let cmd.args = '--verbose --decrypt --list-only --dry-run --no-use-agent --logger-fd 1 ' . s:shellescape(filename) let output = s:GPGSystem(cmd) " Suppress the "N more lines" message when editing a file, not when reading @@ -530,7 +553,7 @@ function s:GPGDecrypt(bufread) " we must redirect stderr (using shell temporarily) call s:GPGDebug(1, "decrypting file") let cmd = { 'level': 1, 'ex': silent . 'r !' } - let cmd.args = '--quiet --decrypt ' . shellescape(filename, 1) + let cmd.args = '--quiet --decrypt ' . s:shellescape(filename, 1) call s:GPGExecute(cmd) if (v:shell_error) " message could not be decrypted @@ -666,7 +689,7 @@ function s:GPGEncrypt() let destfile = tempname() let cmd = { 'level': 1, 'ex': "'[,']w !" } let cmd.args = '--quiet --no-encrypt-to ' . options - let cmd.redirect = '>' . shellescape(destfile, 1) + let cmd.redirect = '>' . s:shellescape(destfile, 1) silent call s:GPGExecute(cmd) " restore encoding @@ -1157,7 +1180,7 @@ function s:GPGNameToID(name) " ask gpg for the id for a name let cmd = { 'level': 2 } - let cmd.args = '--quiet --with-colons --fixed-list-mode --list-keys ' . shellescape(a:name) + let cmd.args = '--quiet --with-colons --fixed-list-mode --list-keys ' . s:shellescape(a:name) let output = s:GPGSystem(cmd) " when called with "--with-colons" gpg encodes its output _ALWAYS_ as UTF-8, @@ -1322,7 +1345,7 @@ endfunction function s:GPGSystem(dict) let commandline = s:GPGCommand if (!empty(g:GPGHomedir)) - let commandline .= ' --homedir ' . shellescape(g:GPGHomedir) + let commandline .= ' --homedir ' . s:shellescape(g:GPGHomedir) endif let commandline .= ' ' . a:dict.args let commandline .= ' ' . s:stderrredirnull @@ -1349,7 +1372,7 @@ endfunction function s:GPGExecute(dict) let commandline = printf('%s%s', a:dict.ex, s:GPGCommand) if (!empty(g:GPGHomedir)) - let commandline .= ' --homedir ' . shellescape(g:GPGHomedir, 1) + let commandline .= ' --homedir ' . s:shellescape(g:GPGHomedir, 1) endif let commandline .= ' ' . a:dict.args if (has_key(a:dict, 'redirect'))