releasing gnupg.vim 1933

- changed parsin to work with gpg2 correctly
- save/restore view of saved window
- fix a bug when encoding and fileencoding is different
- restructured autocommand triggers
- added a debug command and debug messages
This commit is contained in:
Markus Braun 2008-01-23 09:49:33 -05:00 committed by James Vega
parent 66fdaa0558
commit 77df8bb864

View File

@ -1,10 +1,10 @@
" Name: gnupg.vim " Name: gnupg.vim
" Version: $Id: gnupg.vim 1605 2007-03-01 09:58:04Z mbr $ " Version: $Id: gnupg.vim 1933 2008-01-23 09:49:33Z mbr $
" Author: Markus Braun <markus.braun@krawel.de> " Author: Markus Braun <markus.braun@krawel.de>
" Summary: Vim plugin for transparent editing of gpg encrypted files. " Summary: Vim plugin for transparent editing of gpg encrypted files.
" Licence: This program is free software; you can redistribute it and/or " Licence: This program is free software; you can redistribute it and/or
" modify it under the terms of the GNU General Public License. " modify it under the terms of the GNU General Public License.
" See http://www.gnu.org/copyleft/gpl.txt " See http://www.gnu.org/copyleft/gpl.txt
" Section: Documentation {{{1 " Section: Documentation {{{1
" Description: " Description:
" "
@ -56,56 +56,52 @@
" Richard Bronosky for patch to enable ".pgp" suffix. " Richard Bronosky for patch to enable ".pgp" suffix.
" Erik Remmelzwaal for patch to enable windows support and patient beta " Erik Remmelzwaal for patch to enable windows support and patient beta
" testing. " testing.
" Lars Becker for patch to make gpg2 working.
" "
" Section: Plugin header {{{1 " 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 finish
endi endi
let loaded_gnupg = 1 let g:loaded_gnupg = "$Revision: 1933 $"
" Section: Autocmd setup {{{1 " Section: Autocmd setup {{{1
augroup GnuPG augroup GnuPG
au! autocmd!
" First make sure nothing is written to ~/.viminfo while editing " initialize the internal variables
" 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
autocmd BufNewFile,BufReadPre,FileReadPre *.\(gpg\|asc\|pgp\) call s:GPGInit() 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 " keys are preferred
autocmd BufNewFile *.\(gpg\|asc\|pgp\) if (exists("g:GPGPreferSymmetric") && g:GPGPreferSymmetric == 0) | call s:GPGEditRecipients() | endi 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 " do the decryption
autocmd BufReadPre,FileReadPre *.\(gpg\|asc\|pgp\) set bin
autocmd BufReadPost,FileReadPost *.\(gpg\|asc\|pgp\) call s:GPGDecrypt() 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 " convert all text to encrypted text before writing
autocmd BufWritePre,FileWritePre *.\(gpg\|asc\|pgp\) set bin
" Convert all text to encrypted text before writing
autocmd BufWritePre,FileWritePre *.\(gpg\|asc\|pgp\) call s:GPGEncrypt() 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. " after the file has been written.
autocmd BufWritePost,FileWritePost *.\(gpg\|asc\|pgp\) if (exists("b:GPGEncrypted") && b:GPGEncrypted == 1) | silent u | endi autocmd BufWritePost,FileWritePost *.\(gpg\|asc\|pgp\) call s:GPGEncryptPost()
" Switch back to normal mode for editing
autocmd BufWritePost,FileWritePost *.\(gpg\|asc\|pgp\) set nobin
augroup END augroup END
" Section: Highlight setup {{{1 " Section: Highlight setup {{{1
highlight default link GPGWarning WarningMsg highlight default link GPGWarning WarningMsg
highlight default link GPGError ErrorMsg highlight default link GPGError ErrorMsg
highlight default link GPGHighlightUnknownRecipient ErrorMsg highlight default link GPGHighlightUnknownRecipient ErrorMsg
" Section: Functions {{{1 " Section: Functions {{{1
" Function: s:GPGInit() {{{2 " Function: s:GPGInit() {{{2
" "
" initialize the plugin " initialize the plugin
" "
fun s:GPGInit() 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 " check if gpg-agent is allowed
if (!exists("g:GPGUseAgent")) if (!exists("g:GPGUseAgent"))
let g:GPGUseAgent = 1 let g:GPGUseAgent = 1
@ -121,6 +117,14 @@ fun s:GPGInit()
let g:GPGPreferArmor = 0 let g:GPGPreferArmor = 0
endif 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 " determine if gnupg can use the gpg-agent
if (exists("$GPG_AGENT_INFO") && g:GPGUseAgent == 1) if (exists("$GPG_AGENT_INFO") && g:GPGUseAgent == 1)
if (!exists("$GPG_TTY")) if (!exists("$GPG_TTY"))
@ -175,6 +179,9 @@ endf
" decrypt the buffer and find all recipients of the encrypted file " decrypt the buffer and find all recipients of the encrypted file
" "
fun s:GPGDecrypt() fun s:GPGDecrypt()
" switch to binary mode to read the encrypted file
set bin
" get the filename of the current buffer " get the filename of the current buffer
let filename=escape(expand("%:p"), '\"') let filename=escape(expand("%:p"), '\"')
@ -187,58 +194,68 @@ fun s:GPGDecrypt()
" find the recipients of the file " find the recipients of the file
let &shellredir=s:shellredir let &shellredir=s:shellredir
let &shell=s:shell 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 &shellredir=s:shellredirsave
let &shell=s:shellsave 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 " 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 " file is symmetric encrypted
let b:GPGEncrypted=1 let b:GPGEncrypted=1
call s:GPGDebug(1, "this file is symmetric encrypted")
let b:GPGOptions=b:GPGOptions . "symmetric:" let b:GPGOptions=b:GPGOptions . "symmetric:"
let cipher=substitute(output, ".*gpg: \\([^ ]\\+\\) encrypted data.*", "\\1", "") let cipher=substitute(output, ".*gpg: \\([^ ]\\+\\) encrypted data.*", "\\1", "")
if (match(s:GPGCipher, "\\<" . cipher . "\\>") >= 0) if (match(s:GPGCipher, "\\<" . cipher . "\\>") >= 0)
let b:GPGOptions=b:GPGOptions . "cipher-algo " . cipher . ":" let b:GPGOptions=b:GPGOptions . "cipher-algo " . cipher . ":"
call s:GPGDebug(1, "cipher-algo is " . cipher)
else else
echohl GPGWarning echohl GPGWarning
echo "The cipher " . cipher . " is not known by the local gpg command. Using default!" echo "The cipher " . cipher . " is not known by the local gpg command. Using default!"
echo echo
echohl None echohl None
endi endi
elseif (match(output, "gpg: public key decryption") >= 0) elseif (match(output, "gpg: public key is [[:xdigit:]]\\{8}") >= 0)
" file is asymmetric encrypted " file is asymmetric encrypted
let b:GPGEncrypted=1 let b:GPGEncrypted=1
call s:GPGDebug(1, "this file is asymmetric encrypted")
let b:GPGOptions=b:GPGOptions . "encrypt:" 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) while (start >= 0)
let start=start+3 let start=start + strlen("gpg: public key is ")
let recipient=strpart(output, start, 8) let recipient=strpart(output, start, 8)
call s:GPGDebug(1, "recipient is " . recipient)
let name=s:GPGNameToID(recipient) let name=s:GPGNameToID(recipient)
if (strlen(name) > 0) if (strlen(name) > 0)
let b:GPGRecipients=b:GPGRecipients . name . ":" let b:GPGRecipients=b:GPGRecipients . name . ":"
call s:GPGDebug(1, "name of recipient is " . name)
else else
let b:GPGUnknownRecipients=b:GPGUnknownRecipients . recipient . ":" let b:GPGUnknownRecipients=b:GPGUnknownRecipients . recipient . ":"
echohl GPGWarning echohl GPGWarning
echo "The recipient " . recipient . " is not in your public keyring!" echo "The recipient " . recipient . " is not in your public keyring!"
echohl None echohl None
end end
let start=match(output, "ID [[:xdigit:]]\\{8}", start) let start=match(output, "gpg: public key is [[:xdigit:]]\\{8}", start)
endw endw
elseif (match(output, "gpg: no valid OpenPGP data found") >= 0) else
" file is not encrypted " file is not encrypted
let b:GPGEncrypted=0 let b:GPGEncrypted=0
call s:GPGDebug(1, "this file is not encrypted")
echohl GPGWarning echohl GPGWarning
echo "File is not encrypted, all GPG functions disabled!" echo "File is not encrypted, all GPG functions disabled!"
echohl None echohl None
set nobin
return return
endi endi
" check if the message is armored " 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:" let b:GPGOptions=b:GPGOptions . "armor:"
endi endi
@ -256,8 +273,19 @@ fun s:GPGDecrypt()
let asd=input("Message could not be decrypted! (Press ENTER)") let asd=input("Message could not be decrypted! (Press ENTER)")
echohl None echohl None
bwipeout bwipeout
set nobin
return return
endi 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 endf
" Function: s:GPGEncrypt() {{{2 " Function: s:GPGEncrypt() {{{2
@ -265,6 +293,23 @@ endf
" encrypts the buffer to all previous recipients " encrypts the buffer to all previous recipients
" "
fun s:GPGEncrypt() 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 " guard for unencrypted files
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0) if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
echohl GPGWarning echohl GPGWarning
@ -287,6 +332,7 @@ fun s:GPGEncrypt()
if (exists("g:GPGPreferArmor") && g:GPGPreferArmor == 1) if (exists("g:GPGPreferArmor") && g:GPGPreferArmor == 1)
let b:GPGOptions=b:GPGOptions . "armor:" let b:GPGOptions=b:GPGOptions . "armor:"
endi endi
call s:GPGDebug(1, "no options set, so using default options: " . b:GPGOptions)
endi endi
let field=0 let field=0
let option=s:GetField(b:GPGOptions, ":", field) let option=s:GetField(b:GPGOptions, ":", field)
@ -303,10 +349,12 @@ fun s:GPGEncrypt()
echo "Please use GPGEditRecipients to correct!!" echo "Please use GPGEditRecipients to correct!!"
echo echo
echohl None echohl None
call s:GPGDebug(1, "unknown recipients are: " . b:GPGUnknownRecipients)
endi endi
" built list of recipients " built list of recipients
if (exists("b:GPGRecipients") && strlen(b:GPGRecipients) > 0) if (exists("b:GPGRecipients") && strlen(b:GPGRecipients) > 0)
call s:GPGDebug(1, "recipients are: " . b:GPGRecipients)
let field=0 let field=0
let gpgid=s:GetField(b:GPGRecipients, ":", field) let gpgid=s:GetField(b:GPGRecipients, ":", field)
while (strlen(gpgid)) while (strlen(gpgid))
@ -330,6 +378,7 @@ fun s:GPGEncrypt()
silent exec "'[,']!" . s:GPGCommand . " --quiet --no-encrypt-to " . options . recipients . " " . s:stderrredirnull silent exec "'[,']!" . s:GPGCommand . " --quiet --no-encrypt-to " . options . recipients . " " . s:stderrredirnull
let &shellredir=s:shellredirsave let &shellredir=s:shellredirsave
let &shell=s:shellsave 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 if (v:shell_error) " message could not be encrypted
silent u silent u
echohl GPGError echohl GPGError
@ -339,7 +388,36 @@ fun s:GPGEncrypt()
return return
endi 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 endf
" Function: s:GPGViewRecipients() {{{2 " Function: s:GPGViewRecipients() {{{2
@ -870,10 +948,20 @@ fun s:GetField(line, separator, field)
return "" return ""
endi endi
endf 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 " Section: Command definitions {{{1
com! GPGViewRecipients call s:GPGViewRecipients() com! GPGViewRecipients call s:GPGViewRecipients()
com! GPGEditRecipients call s:GPGEditRecipients() com! GPGEditRecipients call s:GPGEditRecipients()
com! GPGViewOptions call s:GPGViewOptions() com! GPGViewOptions call s:GPGViewOptions()
com! GPGEditOptions call s:GPGEditOptions() com! GPGEditOptions call s:GPGEditOptions()
" vim600: set foldmethod=marker: " vim600: foldmethod=marker:foldlevel=0