diff --git a/plugin/gnupg.vim b/plugin/gnupg.vim index 1172b67..be7d9f6 100644 --- a/plugin/gnupg.vim +++ b/plugin/gnupg.vim @@ -1,10 +1,10 @@ " Name: gnupg.vim -" Version: $Id: gnupg.vim 1605 2007-03-01 09:58:04Z mbr $ -" Author: Markus Braun -" Summary: Vim plugin for transparent editing of gpg encrypted files. -" Licence: This program is free software; you can redistribute it and/or -" modify it under the terms of the GNU General Public License. -" See http://www.gnu.org/copyleft/gpl.txt +" Version: $Id: gnupg.vim 1933 2008-01-23 09:49:33Z mbr $ +" Author: Markus Braun +" Summary: Vim plugin for transparent editing of gpg encrypted files. +" Licence: This program is free software; you can redistribute it and/or +" modify it under the terms of the GNU General Public License. +" See http://www.gnu.org/copyleft/gpl.txt " Section: Documentation {{{1 " Description: " @@ -56,56 +56,52 @@ " Richard Bronosky for patch to enable ".pgp" suffix. " Erik Remmelzwaal for patch to enable windows support and patient beta " testing. +" Lars Becker for patch to make gpg2 working. " " Section: Plugin header {{{1 -if (exists("loaded_gnupg") || &cp || exists("#BufReadPre#*.\(gpg\|asc\|pgp\)")) +if (exists("g:loaded_gnupg") || &cp || exists("#BufReadPre#*.\(gpg\|asc\|pgp\)")) finish endi -let loaded_gnupg = 1 +let g:loaded_gnupg = "$Revision: 1933 $" " Section: Autocmd setup {{{1 augroup GnuPG -au! +autocmd! -" First make sure nothing is written to ~/.viminfo while editing -" an encrypted file. -autocmd BufNewFile,BufReadPre,FileReadPre *.\(gpg\|asc\|pgp\) set viminfo= -" We don't want a swap file, as it writes unencrypted data to disk -autocmd BufNewFile,BufReadPre,FileReadPre *.\(gpg\|asc\|pgp\) set noswapfile -" Initialize the internal variables +" initialize the internal variables autocmd BufNewFile,BufReadPre,FileReadPre *.\(gpg\|asc\|pgp\) call s:GPGInit() -" Force the user to edit the recipient list if he opens a new file and public +" force the user to edit the recipient list if he opens a new file and public " keys are preferred autocmd BufNewFile *.\(gpg\|asc\|pgp\) if (exists("g:GPGPreferSymmetric") && g:GPGPreferSymmetric == 0) | call s:GPGEditRecipients() | endi -" Switch to binary mode to read the encrypted file -autocmd BufReadPre,FileReadPre *.\(gpg\|asc\|pgp\) set bin +" do the decryption autocmd BufReadPost,FileReadPost *.\(gpg\|asc\|pgp\) call s:GPGDecrypt() -" Switch to normal mode for editing -autocmd BufReadPost,FileReadPost *.\(gpg\|asc\|pgp\) set nobin -" Call the autocommand for the file minus .gpg$ -autocmd BufReadPost,FileReadPost *.\(gpg\|asc\|pgp\) execute ":doautocmd BufReadPost " . escape(expand("%:r"), ' *?\"'."'") -autocmd BufReadPost,FileReadPost *.\(gpg\|asc\|pgp\) execute ":redraw!" -" Switch to binary mode before encrypt the file -autocmd BufWritePre,FileWritePre *.\(gpg\|asc\|pgp\) set bin -" Convert all text to encrypted text before writing +" convert all text to encrypted text before writing autocmd BufWritePre,FileWritePre *.\(gpg\|asc\|pgp\) call s:GPGEncrypt() -" Undo the encryption so we are back in the normal text, directly +" undo the encryption so we are back in the normal text, directly " after the file has been written. -autocmd BufWritePost,FileWritePost *.\(gpg\|asc\|pgp\) if (exists("b:GPGEncrypted") && b:GPGEncrypted == 1) | silent u | endi -" Switch back to normal mode for editing -autocmd BufWritePost,FileWritePost *.\(gpg\|asc\|pgp\) set nobin +autocmd BufWritePost,FileWritePost *.\(gpg\|asc\|pgp\) call s:GPGEncryptPost() + augroup END + " Section: Highlight setup {{{1 highlight default link GPGWarning WarningMsg highlight default link GPGError ErrorMsg highlight default link GPGHighlightUnknownRecipient ErrorMsg + " Section: Functions {{{1 " Function: s:GPGInit() {{{2 " " initialize the plugin " fun s:GPGInit() + " first make sure nothing is written to ~/.viminfo while editing + " an encrypted file. + set viminfo= + + " we don't want a swap file, as it writes unencrypted data to disk + set noswapfile + " check if gpg-agent is allowed if (!exists("g:GPGUseAgent")) let g:GPGUseAgent = 1 @@ -121,6 +117,14 @@ fun s:GPGInit() let g:GPGPreferArmor = 0 endif + " check if debugging is turned on + if (!exists("g:GPGDebugLevel")) + let g:GPGDebugLevel = 0 + endif + + " print version + call s:GPGDebug(1, "gnupg.vim ". g:loaded_gnupg) + " determine if gnupg can use the gpg-agent if (exists("$GPG_AGENT_INFO") && g:GPGUseAgent == 1) if (!exists("$GPG_TTY")) @@ -175,6 +179,9 @@ endf " decrypt the buffer and find all recipients of the encrypted file " fun s:GPGDecrypt() + " switch to binary mode to read the encrypted file + set bin + " get the filename of the current buffer let filename=escape(expand("%:p"), '\"') @@ -187,58 +194,68 @@ fun s:GPGDecrypt() " find the recipients of the file let &shellredir=s:shellredir let &shell=s:shell - let output=system(s:GPGCommand . " --decrypt --dry-run --batch --no-use-agent --logger-fd 1 \"" . filename . "\"") + let output=system(s:GPGCommand . " --verbose --decrypt --list-only --dry-run --batch --no-use-agent --logger-fd 1 \"" . filename . "\"") let &shellredir=s:shellredirsave let &shell=s:shellsave + call s:GPGDebug(1, "output of command '" . s:GPGCommand . " --verbose --decrypt --list-only --dry-run --batch --no-use-agent --logger-fd 1 \"" . filename . "\"' is:") + call s:GPGDebug(1, ">>>>> " . output . " <<<<<") " check if the file is symmetric/asymmetric encrypted - if (match(output, "gpg: [^ ]\\+ encrypted data") >= 0) + if (match(output, "gpg: encrypted with [[:digit:]]\\+ passphrase") >= 0) " file is symmetric encrypted let b:GPGEncrypted=1 + call s:GPGDebug(1, "this file is symmetric encrypted") let b:GPGOptions=b:GPGOptions . "symmetric:" let cipher=substitute(output, ".*gpg: \\([^ ]\\+\\) encrypted data.*", "\\1", "") if (match(s:GPGCipher, "\\<" . cipher . "\\>") >= 0) let b:GPGOptions=b:GPGOptions . "cipher-algo " . cipher . ":" + call s:GPGDebug(1, "cipher-algo is " . cipher) else echohl GPGWarning echo "The cipher " . cipher . " is not known by the local gpg command. Using default!" echo echohl None endi - elseif (match(output, "gpg: public key decryption") >= 0) + elseif (match(output, "gpg: public key is [[:xdigit:]]\\{8}") >= 0) " file is asymmetric encrypted let b:GPGEncrypted=1 + call s:GPGDebug(1, "this file is asymmetric encrypted") let b:GPGOptions=b:GPGOptions . "encrypt:" - let start=match(output, "ID [[:xdigit:]]\\{8}") + let start=match(output, "gpg: public key is [[:xdigit:]]\\{8}") while (start >= 0) - let start=start+3 + let start=start + strlen("gpg: public key is ") let recipient=strpart(output, start, 8) + call s:GPGDebug(1, "recipient is " . recipient) let name=s:GPGNameToID(recipient) if (strlen(name) > 0) let b:GPGRecipients=b:GPGRecipients . name . ":" + call s:GPGDebug(1, "name of recipient is " . name) else let b:GPGUnknownRecipients=b:GPGUnknownRecipients . recipient . ":" echohl GPGWarning echo "The recipient " . recipient . " is not in your public keyring!" echohl None end - let start=match(output, "ID [[:xdigit:]]\\{8}", start) + let start=match(output, "gpg: public key is [[:xdigit:]]\\{8}", start) endw - elseif (match(output, "gpg: no valid OpenPGP data found") >= 0) + else " file is not encrypted let b:GPGEncrypted=0 + call s:GPGDebug(1, "this file is not encrypted") echohl GPGWarning echo "File is not encrypted, all GPG functions disabled!" echohl None + set nobin return endi " check if the message is armored - if (stridx(getline(1), "-----BEGIN PGP MESSAGE-----") >= 0) + if (match(output, "gpg: armor header") >= 0) + call s:GPGDebug(1, "this file is armored") let b:GPGOptions=b:GPGOptions . "armor:" endi @@ -256,8 +273,19 @@ fun s:GPGDecrypt() let asd=input("Message could not be decrypted! (Press ENTER)") echohl None bwipeout + set nobin return endi + + " turn off binary mode + set nobin + + " call the autocommand for the file minus .gpg$ + execute ":doautocmd BufReadPost " . escape(expand("%:r"), ' *?\"'."'") + call s:GPGDebug(2, "called autocommand for " . escape(expand("%:r"), ' *?\"'."'")) + + " refresh screen + redraw! endf " Function: s:GPGEncrypt() {{{2 @@ -265,6 +293,23 @@ endf " encrypts the buffer to all previous recipients " fun s:GPGEncrypt() + " save window view + let s:GPGWindowView = winsaveview() + call s:GPGDebug(2, "saved window view " . string(s:GPGWindowView)) + + " store encoding and switch to a safe one + if &fileencoding != &encoding + let s:GPGEncoding = &encoding + let &encoding = &fileencoding + call s:GPGDebug(2, "encoding was \"" . s:GPGEncoding . "\", switched to \"" . &encoding . "\"") + else + let s:GPGEncoding = "" + call s:GPGDebug(2, "encoding and fileencoding are the same (\"" . &encoding . "\"), not switching") + endi + + " switch buffer to binary mode + set bin + " guard for unencrypted files if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0) echohl GPGWarning @@ -287,6 +332,7 @@ fun s:GPGEncrypt() if (exists("g:GPGPreferArmor") && g:GPGPreferArmor == 1) let b:GPGOptions=b:GPGOptions . "armor:" endi + call s:GPGDebug(1, "no options set, so using default options: " . b:GPGOptions) endi let field=0 let option=s:GetField(b:GPGOptions, ":", field) @@ -303,10 +349,12 @@ fun s:GPGEncrypt() echo "Please use GPGEditRecipients to correct!!" echo echohl None + call s:GPGDebug(1, "unknown recipients are: " . b:GPGUnknownRecipients) endi " built list of recipients if (exists("b:GPGRecipients") && strlen(b:GPGRecipients) > 0) + call s:GPGDebug(1, "recipients are: " . b:GPGRecipients) let field=0 let gpgid=s:GetField(b:GPGRecipients, ":", field) while (strlen(gpgid)) @@ -330,6 +378,7 @@ fun s:GPGEncrypt() silent exec "'[,']!" . s:GPGCommand . " --quiet --no-encrypt-to " . options . recipients . " " . s:stderrredirnull let &shellredir=s:shellredirsave let &shell=s:shellsave + call s:GPGDebug(1, "called gpg command is: " . "'[,']!" . s:GPGCommand . " --quiet --no-encrypt-to " . options . recipients . " " . s:stderrredirnull) if (v:shell_error) " message could not be encrypted silent u echohl GPGError @@ -339,7 +388,36 @@ fun s:GPGEncrypt() return endi - "redraw! +endf + +" Function: s:GPGEncryptPost() {{{2 +" +" undo changes don by encrypt, after writing +" +fun s:GPGEncryptPost() + + if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0) + return + endi + + " undo encryption of buffer content + silent u + + " switch back from binary mode + set nobin + + " restore encoding + if s:GPGEncoding != "" + let &encoding = s:GPGEncoding + call s:GPGDebug(2, "restored encoding \"" . &encoding . "\"") + endi + + " restore window view + call winrestview(s:GPGWindowView) + call s:GPGDebug(2, "restored window view" . string(s:GPGWindowView)) + + " refresh screen + redraw! endf " Function: s:GPGViewRecipients() {{{2 @@ -870,10 +948,20 @@ fun s:GetField(line, separator, field) return "" endi endf + +" Function: s:GPGDebug(level, text) {{{2 +" +" output debug message, if this message has high enough importance +fun s:GPGDebug(level, text) + if (g:GPGDebugLevel >= a:level) + echom a:text + endi +endf + " Section: Command definitions {{{1 com! GPGViewRecipients call s:GPGViewRecipients() com! GPGEditRecipients call s:GPGEditRecipients() com! GPGViewOptions call s:GPGViewOptions() com! GPGEditOptions call s:GPGEditOptions() -" vim600: set foldmethod=marker: +" vim600: foldmethod=marker:foldlevel=0