X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=epa-file.el;h=a6a800ee5be56a5eef2f0f6f7e640275eaf94aad;hb=d4f3669df50ff298206afb87e4d73f1b4d65f185;hp=f086f90930f45c355d8cb449a0d93675f14f2996;hpb=4e7dbafd0b7b928719a4f18ecd8fcbe7bf452465;p=elisp%2Fepg.git diff --git a/epa-file.el b/epa-file.el index f086f90..a6a800e 100644 --- a/epa-file.el +++ b/epa-file.el @@ -29,13 +29,34 @@ "The EasyPG Assistant hooks for transparent file encryption" :group 'epa) -(defcustom epa-file-name-regexp "\\.gpg\\'" - "Regexp which matches filenames to be encrypted with GnuPG." +(defun epa-file--file-name-regexp-set (variable value) + (set-default variable value) + (if (fboundp 'epa-file-name-regexp-update) + (epa-file-name-regexp-update))) + +(defcustom epa-file-name-regexp "\\.gpg\\(~\\|\\.~[0-9]+~\\)?\\'" + "Regexp which matches filenames to be encrypted with GnuPG. + +If you set this outside Custom while epa-file is already enabled, you +have to call `epa-file-name-regexp-update' after setting it to +properly update file-name-handler-alist. Setting this through Custom +does that automatically." :type 'regexp - :group 'epa-file) + :group 'epa-file + :set 'epa-file--file-name-regexp-set) (defcustom epa-file-cache-passphrase-for-symmetric-encryption nil - "If t, cache passphrase for symmetric encryption." + "If non-nil, cache passphrase for symmetric encryption." + :type 'boolean + :group 'epa-file) + +(defcustom epa-file-inhibit-auto-save t + "If non-nil, disable auto-saving when opening an encrypted file." + :type 'boolean + :group 'epa-file) + +(defcustom epa-file-select-keys nil + "If non-nil, always asks user to select recipients." :type 'boolean :group 'epa-file) @@ -55,18 +76,28 @@ May either be a string or a list of strings.") val) t))))) +;;;###autoload +(put 'epa-file-encrypt-to 'permanent-local t) + (defvar epa-file-handler (cons epa-file-name-regexp 'epa-file-handler)) (defvar epa-file-passphrase-alist nil) -(if (fboundp 'encode-coding-string) - (defalias 'epa-file--encode-coding-string 'encode-coding-string) - (defalias 'epa-file--encode-coding-string 'identity)) +(eval-and-compile + (if (fboundp 'encode-coding-string) + (defalias 'epa-file--encode-coding-string 'encode-coding-string) + (defalias 'epa-file--encode-coding-string 'identity))) -(if (fboundp 'decode-coding-string) - (defalias 'epa-file--decode-coding-string 'decode-coding-string) - (defalias 'epa-file--decode-coding-string 'identity)) +(eval-and-compile + (if (fboundp 'decode-coding-string) + (defalias 'epa-file--decode-coding-string 'decode-coding-string) + (defalias 'epa-file--decode-coding-string 'identity))) + +(defun epa-file-name-regexp-update () + (interactive) + (unless (equal (car epa-file-handler) epa-file-name-regexp) + (setcar epa-file-handler epa-file-name-regexp))) (defun epa-file-passphrase-callback-function (context key-id file) (if (and epa-file-cache-passphrase-for-symmetric-encryption @@ -121,15 +152,19 @@ May either be a string or a list of strings.") (if (and visit (or beg end)) (error "Attempt to visit less than an entire file")) (setq file (expand-file-name file)) - (let ((local-copy (epa-file-run-real-handler #'file-local-copy (list file))) - (context (epg-make-context)) - string length entry) + (let* ((local-copy + (condition-case inl + (epa-file-run-real-handler #'file-local-copy (list file)) + (error))) + (local-file (or local-copy file)) + (context (epg-make-context)) + string length entry) (if visit (setq buffer-file-name file)) (epg-context-set-passphrase-callback context (cons #'epa-file-passphrase-callback-function - file)) + local-file)) (epg-context-set-progress-callback context #'epa-progress-callback-function) (unwind-protect @@ -137,12 +172,15 @@ May either be a string or a list of strings.") (if replace (goto-char (point-min))) (condition-case error - (setq string (epg-decrypt-file context file nil)) + (setq string (epg-decrypt-file context local-file nil)) (error (if (setq entry (assoc file epa-file-passphrase-alist)) (setcdr entry nil)) (signal 'file-error (cons "Opening input file" (cdr error))))) + (make-local-variable 'epa-file-encrypt-to) + (setq epa-file-encrypt-to + (mapcar #'car (epg-context-result-for context 'encrypted-to))) (if (or beg end) (setq string (substring string (or beg 0) end))) (save-excursion @@ -164,20 +202,29 @@ May either be a string or a list of strings.") (error "Can't append to the file.")) (setq file (expand-file-name file)) (let* ((coding-system (or coding-system-for-write - (if (boundp 'last-coding-system-used) - (condition-case nil - (write-region (point-min) (point-max) "/") - (error last-coding-system-used)) + (if (fboundp 'select-safe-coding-system) + ;; This is needed since Emacs 22 has + ;; no-conversion setting for *.gpg in + ;; `auto-coding-alist'. + (let ((buffer-file-name + (file-name-sans-extension file))) + (select-safe-coding-system + (point-min) (point-max))) buffer-file-coding-system))) (context (epg-make-context)) (coding-system-for-write 'binary) - string entry) + string entry + (recipients + (cond + ((listp epa-file-encrypt-to) epa-file-encrypt-to) + ((stringp epa-file-encrypt-to) (list epa-file-encrypt-to))))) (epg-context-set-passphrase-callback context (cons #'epa-file-passphrase-callback-function file)) (epg-context-set-progress-callback context #'epa-progress-callback-function) + (epg-context-set-armor context epa-armor) (condition-case error (setq string (epg-encrypt-string @@ -186,14 +233,16 @@ May either be a string or a list of strings.") (epa-file--encode-coding-string start coding-system) (epa-file--encode-coding-string (buffer-substring start end) coding-system)) - (unless (assoc file epa-file-passphrase-alist) - (epa-select-keys - context - "Select recipents for encryption. + (if (or epa-file-select-keys + (not (local-variable-p 'epa-file-encrypt-to + (current-buffer)))) + (epa-select-keys + context + "Select recipents for encryption. If no one is selected, symmetric encryption will be performed. " - (cond - ((listp epa-file-encrypt-to) epa-file-encrypt-to) - ((stringp epa-file-encrypt-to) (list epa-file-encrypt-to))))))) + recipients) + (if epa-file-encrypt-to + (epg-list-keys context recipients))))) (error (if (setq entry (assoc file epa-file-passphrase-alist)) (setcdr entry nil)) @@ -217,6 +266,23 @@ If no one is selected, symmetric encryption will be performed. " (message "Wrote %s" buffer-file-name)))) (put 'write-region 'epa-file 'epa-file-write-region) +(defun epa-file-find-file-hook () + (if (and buffer-file-name + (string-match epa-file-name-regexp buffer-file-name) + epa-file-inhibit-auto-save) + (auto-save-mode 0)) + (set-buffer-modified-p nil)) + +(defun epa-file-select-keys () + "Select recipients for encryption." + (interactive) + (make-local-variable 'epa-file-encrypt-to) + (setq epa-file-encrypt-to + (epa-select-keys + (epg-make-context) + "Select recipents for encryption. +If no one is selected, symmetric encryption will be performed. "))) + ;;;###autoload (defun epa-file-enable () (interactive) @@ -224,6 +290,7 @@ If no one is selected, symmetric encryption will be performed. " (message "`epa-file' already enabled") (setq file-name-handler-alist (cons epa-file-handler file-name-handler-alist)) + (add-hook 'find-file-hooks 'epa-file-find-file-hook) (message "`epa-file' enabled"))) ;;;###autoload @@ -233,6 +300,7 @@ If no one is selected, symmetric encryption will be performed. " (progn (setq file-name-handler-alist (delq epa-file-handler file-name-handler-alist)) + (remove-hook 'find-file-hooks 'epa-file-find-file-hook) (message "`epa-file' disabled")) (message "`epa-file' already disabled")))