From: Daiki Ueno Date: Fri, 1 Jul 2011 01:34:38 +0000 (+0900) Subject: Add public key encryption support to plstore. X-Git-Tag: emacs-pretest-24.0.90~104^2~152^2~287^2~7 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=cdf4d4551d9e2b91fb0127ba8162e94910f514bf;p=emacs.git Add public key encryption support to plstore. * plstore.el (plstore-select-keys, plstore-encrypt-to): New variable. (plstore-save): Support public key encryption. (plstore--init-from-buffer): New function. (plstore-open): Use it; fix error when opening a non-existent file. (plstore-revert): Use plstore--init-from-buffer. --- diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index bd7c81f5624..50082d6039b 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog @@ -1,3 +1,11 @@ +2011-07-01 Daiki Ueno + + * plstore.el (plstore-select-keys, plstore-encrypt-to): New variable. + (plstore-save): Support public key encryption. + (plstore--init-from-buffer): New function. + (plstore-open): Use it; fix error when opening a non-existent file. + (plstore-revert): Use plstore--init-from-buffer. + 2011-07-01 Daiki Ueno * auth-source.el (auth-source-backend): Fix :initarg for data slot. diff --git a/lisp/gnus/plstore.el b/lisp/gnus/plstore.el index 392437d1dea..8111c4c226e 100644 --- a/lisp/gnus/plstore.el +++ b/lisp/gnus/plstore.el @@ -44,6 +44,40 @@ (require 'epg) +(defgroup plstore nil + "Searchable, partially encrypted, persistent plist store" + :version "24.1" + :group 'files) + +(defcustom plstore-select-keys 'silent + "Control whether or not to pop up the key selection dialog. + +If t, always asks user to select recipients. +If nil, query user only when `plstore-encrypt-to' is not set. +If neither t nor nil, doesn't ask user. In this case, symmetric +encryption is used." + :type '(choice (const :tag "Ask always" t) + (const :tag "Ask when recipients are not set" nil) + (const :tag "Don't ask" silent)) + :group 'plstore) + +(defvar plstore-encrypt-to nil + "*Recipient(s) used for encrypting secret entries. +May either be a string or a list of strings.") + +(put 'plstore-encrypt-to 'safe-local-variable + (lambda (val) + (or (stringp val) + (and (listp val) + (catch 'safe + (mapc (lambda (elt) + (unless (stringp elt) + (throw 'safe nil))) + val) + t))))) + +(put 'plstore-encrypt-to 'permanent-local t) + (defvar plstore-cache-passphrase-for-symmetric-encryption nil) (defvar plstore-passphrase-alist nil) @@ -107,35 +141,39 @@ (defun plstore-get-file (this) (buffer-file-name (plstore--get-buffer this))) +(defun plstore--init-from-buffer (plstore) + (goto-char (point-min)) + (when (looking-at ";;; public entries\n") + (forward-line) + (plstore--set-alist plstore (read (point-marker))) + (forward-sexp) + (forward-char) + (when (looking-at ";;; secret entries\n") + (forward-line) + (plstore--set-encrypted-data plstore (read (point-marker)))) + (plstore--merge-secret plstore))) + ;;;###autoload (defun plstore-open (file) "Create a plstore instance associated with FILE." - (let ((store (vector - (find-file-noselect file) - nil ;plist (plist) - nil ;encrypted data (string) - nil ;secret plist (plist) - nil ;merged plist (plist) - ))) - (plstore-revert store) - store)) + (with-current-buffer (find-file-noselect file) + ;; make the buffer invisible from user + (rename-buffer (format " plstore %s" (buffer-file-name))) + (let ((store (vector + (current-buffer) + nil ;plist (plist) + nil ;encrypted data (string) + nil ;secret plist (plist) + nil ;merged plist (plist) + ))) + (plstore--init-from-buffer store) + store))) (defun plstore-revert (plstore) "Replace current data in PLSTORE with the file on disk." (with-current-buffer (plstore--get-buffer plstore) (revert-buffer t t) - ;; make the buffer invisible from user - (rename-buffer (format " plstore %s" (buffer-file-name))) - (goto-char (point-min)) - (when (looking-at ";;; public entries\n") - (forward-line) - (plstore--set-alist plstore (read (point-marker))) - (forward-sexp) - (forward-char) - (when (looking-at ";;; secret entries\n") - (forward-line) - (plstore--set-encrypted-data plstore (read (point-marker)))) - (plstore--merge-secret plstore)))) + (plstore--init-from-buffer plstore))) (defun plstore-close (plstore) "Destroy a plstore instance PLSTORE." @@ -304,20 +342,36 @@ SECRET-KEYS is a plist containing secret data." "Save the contents of PLSTORE associated with a FILE." (with-current-buffer (plstore--get-buffer plstore) (erase-buffer) - (insert ";;; public entries\n" (pp-to-string (plstore--get-alist plstore))) + (insert ";;; public entries -*- mode: emacs-lisp -*- \n" + (pp-to-string (plstore--get-alist plstore))) (if (plstore--get-secret-alist plstore) (let ((context (epg-make-context 'OpenPGP)) (pp-escape-newlines nil) + (recipients + (cond + ((listp plstore-encrypt-to) plstore-encrypt-to) + ((stringp plstore-encrypt-to) (list plstore-encrypt-to)))) cipher) (epg-context-set-armor context t) (epg-context-set-passphrase-callback context (cons #'plstore-passphrase-callback-function plstore)) - (setq cipher (epg-encrypt-string context - (pp-to-string - (plstore--get-secret-alist plstore)) - nil)) + (setq cipher (epg-encrypt-string + context + (pp-to-string + (plstore--get-secret-alist plstore)) + (if (or (eq plstore-select-keys t) + (and (null plstore-select-keys) + (not (local-variable-p 'plstore-encrypt-to + (current-buffer))))) + (epa-select-keys + context + "Select recipents for encryption. +If no one is selected, symmetric encryption will be performed. " + recipients) + (if plstore-encrypt-to + (epg-list-keys context recipients))))) (insert ";;; secret entries\n" (pp-to-string cipher)))) (save-buffer)))