HideIfDef mode bug fixes and enhancements. This is #2 of 3 patches based
[bpt/emacs.git] / lisp / epa-file.el
index 3c6cf07..20d34f8 100644 (file)
@@ -1,5 +1,5 @@
-;;; epa-file.el --- the EasyPG Assistant, transparent file encryption
-;; Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;;; epa-file.el --- the EasyPG Assistant, transparent file encryption -*- lexical-binding: t -*-
+;; Copyright (C) 2006-2014 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG
   "If non-nil, cache passphrase for symmetric encryption.
 
 For security reasons, this option is turned off by default and
-not recommended to use.  Instead, consider using public-key
-encryption with gpg-agent which does the same job in a safer
-way."
+not recommended to use.  Instead, consider using gpg-agent which
+does the same job in a safer way.  See Info node `(epa) Caching
+Passphrases' for more information.
+
+Note that this option has no effect if you use GnuPG 2.0."
   :type 'boolean
   :group 'epa-file)
 
 (defcustom epa-file-select-keys nil
-  "If non-nil, always asks user to select recipients."
-  :type 'boolean
+  "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 `epa-file-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 'epa-file)
 
 (defvar epa-file-passphrase-alist nil)
@@ -67,10 +76,11 @@ way."
                        (cons entry
                              epa-file-passphrase-alist)))
                (setq passphrase (epa-passphrase-callback-function context
-                                                                  key-id nil))
+                                                                  key-id
+                                                                  file))
                (setcdr entry (copy-sequence passphrase))
                passphrase))))
-    (epa-passphrase-callback-function context key-id nil)))
+    (epa-passphrase-callback-function context key-id file)))
 
 ;;;###autoload
 (defun epa-file-handler (operation &rest args)
@@ -122,6 +132,7 @@ way."
            (error)))
         (local-file (or local-copy file))
         (context (epg-make-context))
+         (buf (current-buffer))
         string length entry)
     (if visit
        (setq buffer-file-name file))
@@ -129,8 +140,10 @@ way."
      context
      (cons #'epa-file-passphrase-callback-function
           local-file))
-    (epg-context-set-progress-callback context
-                                      #'epa-progress-callback-function)
+    (epg-context-set-progress-callback
+     context
+     (cons #'epa-progress-callback-function
+          (format "Decrypting %s" file)))
     (unwind-protect
        (progn
          (if replace
@@ -145,16 +158,16 @@ way."
             ;; where `find-file-not-found-functions' are called in
             ;; `find-file-noselect-1'.
             (when (file-exists-p local-file)
-              (make-local-variable 'epa-file-error)
-              (setq epa-file-error error)
+              (setq-local epa-file-error error)
               (add-hook 'find-file-not-found-functions
                         'epa-file--find-file-not-found-function
                         nil t))
             (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)))
+          (set-buffer buf) ;In case timer/filter changed/killed it (bug#16029)!
+         (setq-local 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
@@ -198,13 +211,16 @@ way."
         (recipients
          (cond
           ((listp epa-file-encrypt-to) epa-file-encrypt-to)
-          ((stringp epa-file-encrypt-to) (list epa-file-encrypt-to)))))
+          ((stringp epa-file-encrypt-to) (list epa-file-encrypt-to))))
+        buffer)
     (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-progress-callback
+     context
+     (cons #'epa-progress-callback-function
+          (format "Encrypting %s" file)))
     (epg-context-set-armor context epa-armor)
     (condition-case error
        (setq string
@@ -215,14 +231,25 @@ way."
                 (unless start
                   (setq start (point-min)
                         end (point-max)))
-                (epa-file--encode-coding-string (buffer-substring start end)
-                                                coding-system))
-              (if (or epa-file-select-keys
-                      (not (local-variable-p 'epa-file-encrypt-to
-                                             (current-buffer))))
+                (setq buffer (current-buffer))
+                (with-temp-buffer
+                  (insert-buffer-substring buffer start end)
+                  ;; Translate the region according to
+                  ;; `buffer-file-format', as `write-region' would.
+                  ;; We can't simply do `write-region' (into a
+                  ;; temporary file) here, since it writes out
+                  ;; decrypted contents.
+                  (format-encode-buffer (with-current-buffer buffer
+                                          buffer-file-format))
+                  (epa-file--encode-coding-string (buffer-string)
+                                                  coding-system)))
+              (if (or (eq epa-file-select-keys t)
+                      (and (null epa-file-select-keys)
+                           (not (local-variable-p 'epa-file-encrypt-to
+                                                  (current-buffer)))))
                   (epa-select-keys
                    context
-                   "Select recipents for encryption.
+                   "Select recipients for encryption.
 If no one is selected, symmetric encryption will be performed.  "
                    recipients)
                 (if epa-file-encrypt-to
@@ -253,14 +280,13 @@ If no one is selected, symmetric encryption will be performed.  "
 (defun epa-file-select-keys ()
   "Select recipients for encryption."
   (interactive)
-  (make-local-variable 'epa-file-encrypt-to)
-  (setq epa-file-encrypt-to
-       (mapcar
-        (lambda (key)
-          (epg-sub-key-id (car (epg-key-sub-key-list key))))
-       (epa-select-keys
-        (epg-make-context)
-        "Select recipents for encryption.
+  (setq-local epa-file-encrypt-to
+              (mapcar
+               (lambda (key)
+                 (epg-sub-key-id (car (epg-key-sub-key-list key))))
+               (epa-select-keys
+                (epg-make-context)
+                "Select recipients for encryption.
 If no one is selected, symmetric encryption will be performed.  "))))
 
 ;;;###autoload
@@ -289,5 +315,4 @@ If no one is selected, symmetric encryption will be performed.  "))))
 
 (provide 'epa-file)
 
-;; arch-tag: 5715152f-0eb1-4dbc-9008-07098775314d
 ;;; epa-file.el ends here