* epg.el (epg--start): Make the process-buffer unibyte.
[elisp/epg.git] / epa.el
diff --git a/epa.el b/epa.el
index 4b06f5e..85421f2 100644 (file)
--- a/epa.el
+++ b/epa.el
 (require 'font-lock)
 (require 'widget)
 (eval-when-compile (require 'wid-edit))
 (require 'font-lock)
 (require 'widget)
 (eval-when-compile (require 'wid-edit))
+(require 'derived)
 
 (defgroup epa nil
   "The EasyPG Assistant"
   :group 'epg)
 
 
 (defgroup epa nil
   "The EasyPG Assistant"
   :group 'epg)
 
+(defcustom epa-protocol 'OpenPGP
+  "The default protocol."
+  :type '(choice (const :tag "OpenPGP" OpenPGP)
+                (const :tag "CMS" CMS))
+  :group 'epa)
+
 (defcustom epa-armor nil
   "If non-nil, epa commands create ASCII armored output."
   :type 'boolean
 (defcustom epa-armor nil
   "If non-nil, epa commands create ASCII armored output."
   :type 'boolean
@@ -42,7 +49,7 @@
   :type 'boolean
   :group 'epa)
 
   :type 'boolean
   :group 'epa)
 
-(defcustom epa-popup-info-window nil
+(defcustom epa-popup-info-window t
   "If non-nil, status information from epa commands is displayed on
 the separate window."
   :type 'boolean
   "If non-nil, status information from epa commands is displayed on
 the separate window."
   :type 'boolean
@@ -166,15 +173,15 @@ the separate window."
 (defvar epa-key nil)
 (defvar epa-list-keys-arguments nil)
 (defvar epa-info-buffer nil)
 (defvar epa-key nil)
 (defvar epa-list-keys-arguments nil)
 (defvar epa-info-buffer nil)
+(defvar epa-last-coding-system-specified nil)
 
 
-(defvar epa-keys-mode-map
+(defvar epa-key-list-mode-map
   (let ((keymap (make-sparse-keymap)))
     (define-key keymap "m" 'epa-mark)
     (define-key keymap "u" 'epa-unmark)
     (define-key keymap "d" 'epa-decrypt-file)
     (define-key keymap "v" 'epa-verify-file)
     (define-key keymap "s" 'epa-sign-file)
   (let ((keymap (make-sparse-keymap)))
     (define-key keymap "m" 'epa-mark)
     (define-key keymap "u" 'epa-unmark)
     (define-key keymap "d" 'epa-decrypt-file)
     (define-key keymap "v" 'epa-verify-file)
     (define-key keymap "s" 'epa-sign-file)
-    (define-key keymap "S" 'epa-sign-keys)
     (define-key keymap "e" 'epa-encrypt-file)
     (define-key keymap "r" 'epa-delete-keys)
     (define-key keymap "i" 'epa-import-keys)
     (define-key keymap "e" 'epa-encrypt-file)
     (define-key keymap "r" 'epa-delete-keys)
     (define-key keymap "i" 'epa-import-keys)
@@ -202,15 +209,15 @@ the separate window."
 (define-widget 'epa-key 'push-button
   "Button for representing a epg-key object."
   :format "%[%v%]"
 (define-widget 'epa-key 'push-button
   "Button for representing a epg-key object."
   :format "%[%v%]"
-  :button-face-get 'epa-key-widget-button-face-get
-  :value-create 'epa-key-widget-value-create
-  :action 'epa-key-widget-action
-  :help-echo 'epa-key-widget-help-echo)
+  :button-face-get 'epa--key-widget-button-face-get
+  :value-create 'epa--key-widget-value-create
+  :action 'epa--key-widget-action
+  :help-echo 'epa--key-widget-help-echo)
 
 
-(defun epa-key-widget-action (widget &optional event)
-  (epa-show-key (widget-get widget :value)))
+(defun epa--key-widget-action (widget &optional event)
+  (epa--show-key (widget-get widget :value)))
 
 
-(defun epa-key-widget-value-create (widget)
+(defun epa--key-widget-value-create (widget)
   (let* ((key (widget-get widget :value))
         (primary-sub-key (car (epg-key-sub-key-list key)))
         (primary-user-id (car (epg-key-user-id-list key))))
   (let* ((key (widget-get widget :value))
         (primary-sub-key (car (epg-key-sub-key-list key)))
         (primary-user-id (car (epg-key-user-id-list key))))
@@ -221,43 +228,51 @@ the separate window."
                      ? ))
            (epg-sub-key-id primary-sub-key)
            " "
                      ? ))
            (epg-sub-key-id primary-sub-key)
            " "
-           (if (stringp (epg-user-id-string primary-user-id))
-               (epg-user-id-string primary-user-id)
-             (epg-decode-dn (epg-user-id-string primary-user-id))))))
+           (if primary-user-id
+               (if (stringp (epg-user-id-string primary-user-id))
+                   (epg-user-id-string primary-user-id)
+                 (epg-decode-dn (epg-user-id-string primary-user-id)))
+             ""))))
 
 
-(defun epa-key-widget-button-face-get (widget)
+(defun epa--key-widget-button-face-get (widget)
   (let ((validity (epg-sub-key-validity (car (epg-key-sub-key-list
                                              (widget-get widget :value))))))
     (if validity
        (cdr (assq validity epa-validity-face-alist))
       'default)))
 
   (let ((validity (epg-sub-key-validity (car (epg-key-sub-key-list
                                              (widget-get widget :value))))))
     (if validity
        (cdr (assq validity epa-validity-face-alist))
       'default)))
 
-(defun epa-key-widget-help-echo (widget)
+(defun epa--key-widget-help-echo (widget)
   (format "Show %s"
          (epg-sub-key-id (car (epg-key-sub-key-list
                                (widget-get widget :value))))))
 
   (format "Show %s"
          (epg-sub-key-id (car (epg-key-sub-key-list
                                (widget-get widget :value))))))
 
-(defun epa-keys-mode ()
+(if (fboundp 'encode-coding-string)
+    (defalias 'epa--encode-coding-string 'encode-coding-string)
+  (defalias 'epa--encode-coding-string 'identity))
+
+(if (fboundp 'decode-coding-string)
+    (defalias 'epa--decode-coding-string 'decode-coding-string)
+  (defalias 'epa--decode-coding-string 'identity))
+
+(defun epa-key-list-mode ()
   "Major mode for `epa-list-keys'."
   (kill-all-local-variables)
   (buffer-disable-undo)
   "Major mode for `epa-list-keys'."
   (kill-all-local-variables)
   (buffer-disable-undo)
-  (setq major-mode 'epa-keys-mode
+  (setq major-mode 'epa-key-list-mode
        mode-name "Keys"
        truncate-lines t
        buffer-read-only t)
        mode-name "Keys"
        truncate-lines t
        buffer-read-only t)
-  (use-local-map epa-keys-mode-map)
-  (set-keymap-parent (current-local-map) widget-keymap)
+  (use-local-map epa-key-list-mode-map)
   (make-local-variable 'font-lock-defaults)
   (setq font-lock-defaults '(epa-font-lock-keywords t))
   ;; In XEmacs, auto-initialization of font-lock is not effective
   ;; if buffer-file-name is not set.
   (font-lock-set-defaults)
   (make-local-variable 'font-lock-defaults)
   (setq font-lock-defaults '(epa-font-lock-keywords t))
   ;; In XEmacs, auto-initialization of font-lock is not effective
   ;; if buffer-file-name is not set.
   (font-lock-set-defaults)
-  (widget-setup)
   (make-local-variable 'epa-exit-buffer-function)
   (make-local-variable 'epa-exit-buffer-function)
-  (run-hooks 'epa-keys-mode-hook))
+  (run-hooks 'epa-key-list-mode-hook))
 
 (defun epa-key-mode ()
 
 (defun epa-key-mode ()
-  "Major mode for `epa-show-key'."
+  "Major mode for a key description."
   (kill-all-local-variables)
   (buffer-disable-undo)
   (setq major-mode 'epa-key-mode
   (kill-all-local-variables)
   (buffer-disable-undo)
   (setq major-mode 'epa-key-mode
@@ -273,27 +288,70 @@ the separate window."
   (make-local-variable 'epa-exit-buffer-function)
   (run-hooks 'epa-key-mode-hook))
 
   (make-local-variable 'epa-exit-buffer-function)
   (run-hooks 'epa-key-mode-hook))
 
+(defun epa-info-mode ()
+  "Major mode for `epa-info-buffer'."
+  (kill-all-local-variables)
+  (buffer-disable-undo)
+  (setq major-mode 'epa-info-mode
+       mode-name "Info"
+       truncate-lines t
+       buffer-read-only t)
+  (use-local-map epa-info-mode-map)
+  (run-hooks 'epa-info-mode-hook))
+
+(defun epa-mark (&optional arg)
+  "Mark the current line.
+If ARG is non-nil, unmark the current line."
+  (interactive "P")
+  (let ((inhibit-read-only t)
+       buffer-read-only
+       properties)
+    (beginning-of-line)
+    (setq properties (text-properties-at (point)))
+    (delete-char 1)
+    (insert (if arg " " "*"))
+    (set-text-properties (1- (point)) (point) properties)
+    (forward-line)))
+
+(defun epa-unmark (&optional arg)
+  "Unmark the current line.
+If ARG is non-nil, mark the current line."
+  (interactive "P")
+  (epa-mark (not arg)))
+
+(defun epa-toggle-mark ()
+  "Toggle the mark the current line."
+  (interactive)
+  (epa-mark (eq (char-after (save-excursion (beginning-of-line) (point))) ?*)))
+
+(defun epa-exit-buffer ()
+  "Exit the current buffer.
+`epa-exit-buffer-function' is called if it is set."
+  (interactive)
+  (funcall epa-exit-buffer-function))
+
 ;;;###autoload
 ;;;###autoload
-(defun epa-list-keys (&optional name mode protocol)
+(defun epa-list-keys (&optional name mode)
+  "List all keys matched with NAME from the keyring.
+If MODE is non-nil, it reads the private keyring.  Otherwise, it
+reads the public keyring."
   (interactive
    (if current-prefix-arg
        (let ((name (read-string "Pattern: "
                                (if epa-list-keys-arguments
                                    (car epa-list-keys-arguments)))))
         (list (if (equal name "") nil name)
   (interactive
    (if current-prefix-arg
        (let ((name (read-string "Pattern: "
                                (if epa-list-keys-arguments
                                    (car epa-list-keys-arguments)))))
         (list (if (equal name "") nil name)
-              (y-or-n-p "Secret keys? ")
-              (intern (completing-read "Protocol? "
-                                       '(("OpenPGP") ("CMS"))
-                                       nil t))))
-     (or epa-list-keys-arguments (list nil nil nil))))
+              (y-or-n-p "Secret keys? ")))
+     (or epa-list-keys-arguments (list nil nil))))
   (unless (and epa-keys-buffer
               (buffer-live-p epa-keys-buffer))
     (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
   (set-buffer epa-keys-buffer)
   (unless (and epa-keys-buffer
               (buffer-live-p epa-keys-buffer))
     (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
   (set-buffer epa-keys-buffer)
+  (epa-key-list-mode)
   (let ((inhibit-read-only t)
        buffer-read-only
        (point (point-min))
   (let ((inhibit-read-only t)
        buffer-read-only
        (point (point-min))
-       (context (epg-make-context protocol)))
+       (context (epg-make-context epa-protocol)))
     (unless (get-text-property point 'epa-list-keys)
       (setq point (next-single-property-change point 'epa-list-keys)))
     (when point
     (unless (get-text-property point 'epa-list-keys)
       (setq point (next-single-property-change point 'epa-list-keys)))
     (when point
@@ -301,14 +359,15 @@ the separate window."
                     (or (next-single-property-change point 'epa-list-keys)
                         (point-max)))
       (goto-char point))
                     (or (next-single-property-change point 'epa-list-keys)
                         (point-max)))
       (goto-char point))
-    (epa-insert-keys context name mode)
-    (epa-keys-mode))
+    (epa--insert-keys context name mode)
+    (widget-setup)
+    (set-keymap-parent (current-local-map) widget-keymap))
   (make-local-variable 'epa-list-keys-arguments)
   (make-local-variable 'epa-list-keys-arguments)
-  (setq epa-list-keys-arguments (list name mode protocol))
+  (setq epa-list-keys-arguments (list name mode))
   (goto-char (point-min))
   (pop-to-buffer (current-buffer)))
 
   (goto-char (point-min))
   (pop-to-buffer (current-buffer)))
 
-(defun epa-insert-keys (context name mode)
+(defun epa--insert-keys (context name mode)
   (save-excursion
     (save-restriction
       (narrow-to-region (point) (point))
   (save-excursion
     (save-restriction
       (narrow-to-region (point) (point))
@@ -333,7 +392,7 @@ the separate window."
                                 'start-open t
                                 'end-open t)))))
 
                                 'start-open t
                                 'end-open t)))))
 
-(defun epa-marked-keys ()
+(defun epa--marked-keys ()
   (or (save-excursion
        (set-buffer epa-keys-buffer)
        (goto-char (point-min))
   (or (save-excursion
        (set-buffer epa-keys-buffer)
        (goto-char (point-min))
@@ -361,11 +420,15 @@ If SECRET is non-nil, list secret keys instead of public keys."
     (unless (and epa-keys-buffer
                 (buffer-live-p epa-keys-buffer))
       (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
     (unless (and epa-keys-buffer
                 (buffer-live-p epa-keys-buffer))
       (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
+    (set-buffer epa-keys-buffer)
+    (epa-key-list-mode)
     (let ((inhibit-read-only t)
          buffer-read-only)
     (let ((inhibit-read-only t)
          buffer-read-only)
-      (set-buffer epa-keys-buffer)
       (erase-buffer)
       (erase-buffer)
-      (insert prompt "\n")
+      (insert prompt "\n"
+             (substitute-command-keys "\
+- `\\[epa-mark]' to mark a key on the line
+- `\\[epa-unmark]' to unmark a key on the line\n"))
       (widget-create 'link
                     :notify (lambda (&rest ignore) (abort-recursive-edit))
                     :help-echo
       (widget-create 'link
                     :notify (lambda (&rest ignore) (abort-recursive-edit))
                     :help-echo
@@ -381,30 +444,51 @@ If SECRET is non-nil, list secret keys instead of public keys."
       (insert "\n\n")
       (if names
          (while names
       (insert "\n\n")
       (if names
          (while names
-           (epa-insert-keys context (car names) secret)
+           (epa--insert-keys context (car names) secret)
            (if (get-text-property (point) 'epa-list-keys)
                (epa-mark))
            (goto-char (point-max))
            (setq names (cdr names)))
        (if secret
            (progn
            (if (get-text-property (point) 'epa-list-keys)
                (epa-mark))
            (goto-char (point-max))
            (setq names (cdr names)))
        (if secret
            (progn
-             (epa-insert-keys context nil secret)
+             (epa--insert-keys context nil secret)
              (if (get-text-property (point) 'epa-list-keys)
                  (epa-mark)))
              (if (get-text-property (point) 'epa-list-keys)
                  (epa-mark)))
-         (epa-insert-keys context nil nil)))
-      (epa-keys-mode)
+         (epa--insert-keys context nil nil)))
+      (widget-setup)
+      (set-keymap-parent (current-local-map) widget-keymap)
       (setq epa-exit-buffer-function #'abort-recursive-edit)
       (goto-char (point-min))
       (pop-to-buffer (current-buffer)))
     (unwind-protect
        (progn
          (recursive-edit)
       (setq epa-exit-buffer-function #'abort-recursive-edit)
       (goto-char (point-min))
       (pop-to-buffer (current-buffer)))
     (unwind-protect
        (progn
          (recursive-edit)
-         (epa-marked-keys))
+         (epa--marked-keys))
       (if (get-buffer-window epa-keys-buffer)
          (delete-window (get-buffer-window epa-keys-buffer)))
       (kill-buffer epa-keys-buffer))))
 
       (if (get-buffer-window epa-keys-buffer)
          (delete-window (get-buffer-window epa-keys-buffer)))
       (kill-buffer epa-keys-buffer))))
 
-(defun epa-show-key (key)
+(defun epa--format-fingerprint-1 (fingerprint unit-size block-size)
+  (let ((unit 0))
+    (with-temp-buffer
+      (insert fingerprint)
+      (goto-char (point-min))
+      (while (progn
+              (goto-char (+ (point) unit-size))
+              (not (eobp)))
+       (setq unit (1+ unit))
+       (insert (if (= (% unit block-size) 0) "  " " ")))
+      (buffer-string))))
+
+(defun epa--format-fingerprint (fingerprint)
+  (if fingerprint
+      (if (= (length fingerprint) 40)
+         ;; 1234 5678 9ABC DEF0 1234  5678 9ABC DEF0 1234 5678
+         (epa--format-fingerprint-1 fingerprint 4 5)
+       ;; 12 34 56 78 9A BC DE F0  12 34 56 78 9A BC DE F0
+       (epa--format-fingerprint-1 fingerprint 2 8))))
+
+(defun epa--show-key (key)
   (let* ((primary-sub-key (car (epg-key-sub-key-list key)))
         (entry (assoc (epg-sub-key-id primary-sub-key)
                       epa-key-buffer-alist))
   (let* ((primary-sub-key (car (epg-key-sub-key-list key)))
         (entry (assoc (epg-sub-key-id primary-sub-key)
                       epa-key-buffer-alist))
@@ -419,22 +503,24 @@ If SECRET is non-nil, list secret keys instead of public keys."
       (setcdr entry (generate-new-buffer
                     (format "*Key*%s" (epg-sub-key-id primary-sub-key)))))
     (set-buffer (cdr entry))
       (setcdr entry (generate-new-buffer
                     (format "*Key*%s" (epg-sub-key-id primary-sub-key)))))
     (set-buffer (cdr entry))
+    (epa-key-mode)
     (make-local-variable 'epa-key)
     (setq epa-key key)
     (erase-buffer)
     (setq pointer (epg-key-user-id-list key))
     (while pointer
     (make-local-variable 'epa-key)
     (setq epa-key key)
     (erase-buffer)
     (setq pointer (epg-key-user-id-list key))
     (while pointer
-      (insert " "
-             (if (epg-user-id-validity (car pointer))
-                 (char-to-string
-                  (car (rassq (epg-user-id-validity (car pointer))
-                              epg-key-validity-alist)))
-               " ")
-             " "
-             (if (stringp (epg-user-id-string (car pointer)))
-                 (epg-user-id-string (car pointer))
-               (epg-decode-dn (epg-user-id-string (car pointer))))
-             "\n")
+      (if (car pointer)
+         (insert " "
+                 (if (epg-user-id-validity (car pointer))
+                     (char-to-string
+                      (car (rassq (epg-user-id-validity (car pointer))
+                                  epg-key-validity-alist)))
+                   " ")
+                 " "
+                 (if (stringp (epg-user-id-string (car pointer)))
+                     (epg-user-id-string (car pointer))
+                   (epg-decode-dn (epg-user-id-string (car pointer))))
+                 "\n"))
       (setq pointer (cdr pointer)))
     (setq pointer (epg-key-sub-key-list key))
     (while pointer
       (setq pointer (cdr pointer)))
     (setq pointer (epg-key-sub-key-list key))
     (while pointer
@@ -466,80 +552,65 @@ If SECRET is non-nil, list secret keys instead of public keys."
                         (epg-sub-key-capability (car pointer))
                         " ")
              "\n\tFingerprint: "
                         (epg-sub-key-capability (car pointer))
                         " ")
              "\n\tFingerprint: "
-             (epg-sub-key-fingerprint (car pointer))
+             (epa--format-fingerprint (epg-sub-key-fingerprint (car pointer)))
              "\n")
       (setq pointer (cdr pointer)))
     (goto-char (point-min))
              "\n")
       (setq pointer (cdr pointer)))
     (goto-char (point-min))
-    (pop-to-buffer (current-buffer))
-    (epa-key-mode)))
-
-(defun epa-show-key-notify (widget &rest ignore)
-  (epa-show-key (widget-get widget :value)))
-
-(defun epa-mark (&optional arg)
-  "Mark the current line.
-If ARG is non-nil, unmark the current line."
-  (interactive "P")
-  (let ((inhibit-read-only t)
-       buffer-read-only
-       properties)
-    (beginning-of-line)
-    (setq properties (text-properties-at (point)))
-    (delete-char 1)
-    (insert (if arg " " "*"))
-    (set-text-properties (1- (point)) (point) properties)
-    (forward-line)))
-
-(defun epa-unmark (&optional arg)
-  "Unmark the current line.
-If ARG is non-nil, mark the current line."
-  (interactive "P")
-  (epa-mark (not arg)))
-
-(defun epa-toggle-mark ()
-  "Toggle the mark the current line."
-  (interactive)
-  (epa-mark (eq (char-after (save-excursion (beginning-of-line) (point))) ?*)))
+    (pop-to-buffer (current-buffer))))
 
 
-(defun epa-exit-buffer ()
-  "Exit the current buffer.
-`epa-exit-buffer-function' is called if it is set."
-  (interactive)
-  (funcall epa-exit-buffer-function))
-
-(defun epa-display-verify-result (verify-result)
+(defun epa-display-info (info)
   (if epa-popup-info-window
   (if epa-popup-info-window
-      (progn
+      (save-selected-window
        (unless epa-info-buffer
          (setq epa-info-buffer (generate-new-buffer "*Info*")))
        (unless epa-info-buffer
          (setq epa-info-buffer (generate-new-buffer "*Info*")))
+       (if (get-buffer-window epa-info-buffer)
+           (delete-window (get-buffer-window epa-info-buffer)))
        (save-excursion
          (set-buffer epa-info-buffer)
          (let ((inhibit-read-only t)
                buffer-read-only)
            (erase-buffer)
        (save-excursion
          (set-buffer epa-info-buffer)
          (let ((inhibit-read-only t)
                buffer-read-only)
            (erase-buffer)
-           (insert (epg-verify-result-to-string verify-result)))
-         (epa-info-mode))
-       (pop-to-buffer epa-info-buffer)
-       (if (> (window-height) epa-info-window-height)
-           (shrink-window (- (window-height) epa-info-window-height)))
-       (goto-char (point-min)))
-    (message "%s" (epg-verify-result-to-string verify-result))))
+           (insert info))
+         (epa-info-mode)
+         (goto-char (point-min)))
+       (if (> (window-height)
+              epa-info-window-height)
+           (set-window-buffer (split-window nil (- (window-height)
+                                                   epa-info-window-height))
+                              epa-info-buffer)
+         (pop-to-buffer epa-info-buffer)
+         (if (> (window-height) epa-info-window-height)
+             (shrink-window (- (window-height) epa-info-window-height)))))
+    (message "%s" info)))
 
 
-(defun epa-info-mode ()
-  "Major mode for `epa-info-buffer'."
-  (kill-all-local-variables)
-  (buffer-disable-undo)
-  (setq major-mode 'epa-info-mode
-       mode-name "Info"
-       truncate-lines t
-       buffer-read-only t)
-  (use-local-map epa-info-mode-map)
-  (run-hooks 'epa-info-mode-hook))
+(defun epa-display-verify-result (verify-result)
+  (epa-display-info (epg-verify-result-to-string verify-result)))
+(make-obsolete 'epa-display-verify-result 'epa-display-info)
+
+(defun epa-passphrase-callback-function (context key-id handback)
+  (if (eq key-id 'SYM)
+      (read-passwd "Passphrase for symmetric encryption: "
+                  (eq (epg-context-operation context) 'encrypt))
+    (read-passwd
+     (if (eq key-id 'PIN)
+       "Passphrase for PIN: "
+       (let ((entry (assoc key-id epg-user-id-alist)))
+        (if entry
+            (format "Passphrase for %s %s: " key-id (cdr entry))
+          (format "Passphrase for %s: " key-id)))))))
+
+(defun epa-progress-callback-function (context what char current total
+                                              handback)
+  (message "%s%d%% (%d/%d)" (or handback
+                               (concat what ": "))
+          (if (> total 0) (floor (* (/ current (float total)) 100)) 0)
+          current total))
 
 ;;;###autoload
 (defun epa-decrypt-file (file)
   "Decrypt FILE."
   (interactive "fFile: ")
 
 ;;;###autoload
 (defun epa-decrypt-file (file)
   "Decrypt FILE."
   (interactive "fFile: ")
+  (setq file (expand-file-name file))
   (let* ((default-name (file-name-sans-extension file))
         (plain (expand-file-name
                 (read-file-name
   (let* ((default-name (file-name-sans-extension file))
         (plain (expand-file-name
                 (read-file-name
@@ -548,67 +619,127 @@ If ARG is non-nil, mark the current line."
                          ") ")
                  (file-name-directory default-name)
                  default-name)))
                          ") ")
                  (file-name-directory default-name)
                  default-name)))
-        (context (epg-make-context)))
+        (context (epg-make-context epa-protocol)))
+    (epg-context-set-passphrase-callback context
+                                        #'epa-passphrase-callback-function)
+    (epg-context-set-progress-callback context
+                                      #'epa-progress-callback-function
+                                      (format "Decrypting %s..."
+                                              (file-name-nondirectory file)))
     (message "Decrypting %s..." (file-name-nondirectory file))
     (epg-decrypt-file context file plain)
     (message "Decrypting %s..." (file-name-nondirectory file))
     (epg-decrypt-file context file plain)
-    (message "Decrypting %s...done" (file-name-nondirectory file))
+    (message "Decrypting %s...wrote %s" (file-name-nondirectory file)
+            (file-name-nondirectory plain))
     (if (epg-context-result-for context 'verify)
     (if (epg-context-result-for context 'verify)
-       (epa-display-verify-result (epg-context-result-for context 'verify)))))
+       (epa-display-info (epg-verify-result-to-string
+                          (epg-context-result-for context 'verify))))))
 
 ;;;###autoload
 (defun epa-verify-file (file)
   "Verify FILE."
   (interactive "fFile: ")
 
 ;;;###autoload
 (defun epa-verify-file (file)
   "Verify FILE."
   (interactive "fFile: ")
-  (let* ((context (epg-make-context))
+  (setq file (expand-file-name file))
+  (let* ((context (epg-make-context epa-protocol))
         (plain (if (equal (file-name-extension file) "sig")
                    (file-name-sans-extension file))))
         (plain (if (equal (file-name-extension file) "sig")
                    (file-name-sans-extension file))))
+    (epg-context-set-progress-callback context
+                                      #'epa-progress-callback-function
+                                      (format "Verifying %s..."
+                                              (file-name-nondirectory file)))
     (message "Verifying %s..." (file-name-nondirectory file))
     (epg-verify-file context file plain)
     (message "Verifying %s...done" (file-name-nondirectory file))
     (if (epg-context-result-for context 'verify)
     (message "Verifying %s..." (file-name-nondirectory file))
     (epg-verify-file context file plain)
     (message "Verifying %s...done" (file-name-nondirectory file))
     (if (epg-context-result-for context 'verify)
-       (epa-display-verify-result (epg-context-result-for context 'verify)))))
+       (epa-display-info (epg-verify-result-to-string
+                          (epg-context-result-for context 'verify))))))
+
+(defun epa--read-signature-type ()
+  (let (type c)
+    (while (null type)
+      (message "Signature type (n,c,d,?) ")
+      (setq c (read-char))
+      (cond ((eq c ?c)
+            (setq type 'clear))
+           ((eq c ?d)
+            (setq type 'detached))
+           ((eq c ??)
+            (with-output-to-temp-buffer "*Help*"
+              (save-excursion
+                (set-buffer standard-output)
+                (insert "\
+n - Create a normal signature
+c - Create a cleartext signature
+d - Create a detached signature
+? - Show this help
+"))))
+           (t
+            (setq type 'normal))))))
 
 ;;;###autoload
 (defun epa-sign-file (file signers mode)
   "Sign FILE by SIGNERS keys selected."
   (interactive
 
 ;;;###autoload
 (defun epa-sign-file (file signers mode)
   "Sign FILE by SIGNERS keys selected."
   (interactive
-   (list (expand-file-name (read-file-name "File: "))
-        (epa-select-keys (epg-make-context) "Select keys for signing.
+   (let ((verbose current-prefix-arg))
+     (list (expand-file-name (read-file-name "File: "))
+          (if verbose
+              (epa-select-keys (epg-make-context epa-protocol)
+                               "Select keys for signing.
 If no one is selected, default secret key is used.  "
 If no one is selected, default secret key is used.  "
-                         nil t)
-        (if (y-or-n-p "Make a detached signature? ")
-            'detached
-          (if (y-or-n-p "Make a cleartext signature? ")
-              'clear))))
+                               nil t))
+          (if verbose
+              (epa--read-signature-type)
+            'clear))))
   (let ((signature (concat file
   (let ((signature (concat file
-                          (if (or epa-armor
-                                  (not (memq mode '(nil t normal detached))))
-                              ".asc"
+                          (if (eq epa-protocol 'OpenPGP)
+                              (if (or epa-armor
+                                      (not (memq mode
+                                                 '(nil t normal detached))))
+                                  ".asc"
+                                (if (memq mode '(t detached))
+                                    ".sig"
+                                  ".gpg"))
                             (if (memq mode '(t detached))
                             (if (memq mode '(t detached))
-                                ".sig"
-                              ".gpg"))))
-       (context (epg-make-context)))
+                                ".p7s"
+                              ".p7m"))))
+       (context (epg-make-context epa-protocol)))
     (epg-context-set-armor context epa-armor)
     (epg-context-set-textmode context epa-textmode)
     (epg-context-set-signers context signers)
     (epg-context-set-armor context epa-armor)
     (epg-context-set-textmode context epa-textmode)
     (epg-context-set-signers context signers)
+    (epg-context-set-passphrase-callback context
+                                        #'epa-passphrase-callback-function)
+    (epg-context-set-progress-callback context
+                                      #'epa-progress-callback-function
+                                      (format "Signing %s..."
+                                              (file-name-nondirectory file)))
     (message "Signing %s..." (file-name-nondirectory file))
     (epg-sign-file context file signature mode)
     (message "Signing %s..." (file-name-nondirectory file))
     (epg-sign-file context file signature mode)
-    (message "Signing %s...done" (file-name-nondirectory file))))
+    (message "Signing %s...wrote %s" (file-name-nondirectory file)
+            (file-name-nondirectory signature))))
 
 ;;;###autoload
 (defun epa-encrypt-file (file recipients)
   "Encrypt FILE for RECIPIENTS."
   (interactive
    (list (expand-file-name (read-file-name "File: "))
 
 ;;;###autoload
 (defun epa-encrypt-file (file recipients)
   "Encrypt FILE for RECIPIENTS."
   (interactive
    (list (expand-file-name (read-file-name "File: "))
-        (epa-select-keys (epg-make-context) "Select recipients for encryption.
+        (epa-select-keys (epg-make-context epa-protocol)
+                         "Select recipients for encryption.
 If no one is selected, symmetric encryption will be performed.  ")))
 If no one is selected, symmetric encryption will be performed.  ")))
-  (let ((cipher (concat file (if epa-armor ".asc" ".gpg")))
-       (context (epg-make-context)))
+  (let ((cipher (concat file (if (eq epa-protocol 'OpenPGP)
+                                (if epa-armor ".asc" ".gpg")
+                              ".p7m")))
+       (context (epg-make-context epa-protocol)))
     (epg-context-set-armor context epa-armor)
     (epg-context-set-textmode context epa-textmode)
     (epg-context-set-armor context epa-armor)
     (epg-context-set-textmode context epa-textmode)
+    (epg-context-set-passphrase-callback context
+                                        #'epa-passphrase-callback-function)
+    (epg-context-set-progress-callback context
+                                      #'epa-progress-callback-function
+                                      (format "Encrypting %s..."
+                                              (file-name-nondirectory file)))
     (message "Encrypting %s..." (file-name-nondirectory file))
     (epg-encrypt-file context file recipients cipher)
     (message "Encrypting %s..." (file-name-nondirectory file))
     (epg-encrypt-file context file recipients cipher)
-    (message "Encrypting %s...done" (file-name-nondirectory file))))
+    (message "Encrypting %s...wrote %s" (file-name-nondirectory file)
+            (file-name-nondirectory cipher))))
 
 ;;;###autoload
 (defun epa-decrypt-region (start end)
 
 ;;;###autoload
 (defun epa-decrypt-region (start end)
@@ -617,16 +748,44 @@ If no one is selected, symmetric encryption will be performed.  ")))
 Don't use this command in Lisp programs!"
   (interactive "r")
   (save-excursion
 Don't use this command in Lisp programs!"
   (interactive "r")
   (save-excursion
-    (let ((context (epg-make-context))
+    (let ((context (epg-make-context epa-protocol))
          plain)
          plain)
+      (epg-context-set-passphrase-callback context
+                                          #'epa-passphrase-callback-function)
+      (epg-context-set-progress-callback context
+                                        #'epa-progress-callback-function
+                                        "Decrypting...")
       (message "Decrypting...")
       (setq plain (epg-decrypt-string context (buffer-substring start end)))
       (message "Decrypting...done")
       (message "Decrypting...")
       (setq plain (epg-decrypt-string context (buffer-substring start end)))
       (message "Decrypting...done")
-      (delete-region start end)
-      (goto-char start)
-      (insert (decode-coding-string plain coding-system-for-read))
+      (setq plain (epa--decode-coding-string
+                  plain
+                  (or coding-system-for-read
+                      (get-text-property start 'epa-coding-system-used))))
+      (if (y-or-n-p "Replace the original text? ")
+         (let ((inhibit-read-only t)
+               buffer-read-only)
+           (delete-region start end)
+           (goto-char start)
+           (insert plain))
+       (with-output-to-temp-buffer "*Temp*"
+         (set-buffer standard-output)
+         (insert plain)
+         (epa-info-mode)))
       (if (epg-context-result-for context 'verify)
       (if (epg-context-result-for context 'verify)
-         (epa-display-verify-result (epg-context-result-for context 'verify))))))
+         (epa-display-info (epg-verify-result-to-string
+                            (epg-context-result-for context 'verify)))))))
+
+(defun epa--find-coding-system-for-mime-charset (mime-charset)
+  (if (featurep 'xemacs)
+      (if (fboundp 'find-coding-system)
+         (find-coding-system mime-charset))
+    (let ((pointer (coding-system-list)))
+      (while (and pointer
+                 (eq (coding-system-get (car pointer) 'mime-charset)
+                     mime-charset))
+       (setq pointer (cdr pointer)))
+      pointer)))
 
 ;;;###autoload
 (defun epa-decrypt-armor-in-region (start end)
 
 ;;;###autoload
 (defun epa-decrypt-armor-in-region (start end)
@@ -638,7 +797,7 @@ Don't use this command in Lisp programs!"
     (save-restriction
       (narrow-to-region start end)
       (goto-char start)
     (save-restriction
       (narrow-to-region start end)
       (goto-char start)
-      (let (armor-start armor-end charset coding-system)
+      (let (armor-start armor-end)
        (while (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t)
          (setq armor-start (match-beginning 0)
                armor-end (re-search-forward "^-----END PGP MESSAGE-----$"
        (while (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t)
          (setq armor-start (match-beginning 0)
                armor-end (re-search-forward "^-----END PGP MESSAGE-----$"
@@ -646,15 +805,13 @@ Don't use this command in Lisp programs!"
          (unless armor-end
            (error "No armor tail"))
          (goto-char armor-start)
          (unless armor-end
            (error "No armor tail"))
          (goto-char armor-start)
-         (if (re-search-forward "^Charset: \\(.*\\)" armor-end t)
-             (setq charset (match-string 1)))
-         (if coding-system-for-read
-             (setq coding-system coding-system-for-read)
-           (if charset
-               (setq coding-system (intern (downcase charset)))
-             (setq coding-system 'utf-8)))
-         (let ((coding-system-for-read coding-system))
-           (epa-decrypt-region start end)))))))
+         (let ((coding-system-for-read
+                (or coding-system-for-read
+                    (if (re-search-forward "^Charset: \\(.*\\)" armor-end t)
+                        (epa--find-coding-system-for-mime-charset
+                         (intern (downcase (match-string 1))))))))
+           (goto-char armor-end)
+           (epa-decrypt-region armor-start armor-end)))))))
 
 ;;;###autoload
 (defun epa-verify-region (start end)
 
 ;;;###autoload
 (defun epa-verify-region (start end)
@@ -662,17 +819,24 @@ Don't use this command in Lisp programs!"
 
 Don't use this command in Lisp programs!"
   (interactive "r")
 
 Don't use this command in Lisp programs!"
   (interactive "r")
-  (let ((context (epg-make-context)))
+  (let ((context (epg-make-context epa-protocol)))
+    (epg-context-set-progress-callback context
+                                      #'epa-progress-callback-function
+                                      "Verifying...")
     (epg-verify-string context
     (epg-verify-string context
-                      (encode-coding-string
+                      (epa--encode-coding-string
                        (buffer-substring start end)
                        (buffer-substring start end)
-                       coding-system-for-write))
+                       (or coding-system-for-write
+                           (get-text-property start
+                                              'epa-coding-system-used))))
     (if (epg-context-result-for context 'verify)
     (if (epg-context-result-for context 'verify)
-       (epa-display-verify-result (epg-context-result-for context 'verify)))))
+       (epa-display-info (epg-verify-result-to-string
+                          (epg-context-result-for context 'verify))))))
 
 ;;;###autoload
 
 ;;;###autoload
-(defun epa-verify-armor-in-region (start end)
-  "Verify OpenPGP armors in the current region between START and END.
+(defun epa-verify-cleartext-in-region (start end)
+  "Verify OpenPGP cleartext signed messages in the current region
+between START and END.
 
 Don't use this command in Lisp programs!"
   (interactive "r")
 
 Don't use this command in Lisp programs!"
   (interactive "r")
@@ -681,88 +845,158 @@ Don't use this command in Lisp programs!"
       (narrow-to-region start end)
       (goto-char start)
       (let (armor-start armor-end)
       (narrow-to-region start end)
       (goto-char start)
       (let (armor-start armor-end)
-       (while (re-search-forward "-----BEGIN PGP\\( SIGNED\\)? MESSAGE-----$"
+       (while (re-search-forward "-----BEGIN PGP SIGNED MESSAGE-----$"
                                  nil t)
          (setq armor-start (match-beginning 0))
                                  nil t)
          (setq armor-start (match-beginning 0))
-         (if (match-beginning 1)       ;cleartext signed message
-             (progn
-               (unless (re-search-forward "^-----BEGIN PGP SIGNATURE-----$"
+         (unless (re-search-forward "^-----BEGIN PGP SIGNATURE-----$"
                                           nil t)
                                           nil t)
-                 (error "Invalid cleartext signed message"))
-               (setq armor-end (re-search-forward
-                                "^-----END PGP SIGNATURE-----$"
-                                nil t)))
-           (setq armor-end (re-search-forward
-                            "^-----END PGP MESSAGE-----$"
-                            nil t)))
+           (error "Invalid cleartext signed message"))
+         (setq armor-end (re-search-forward
+                          "^-----END PGP SIGNATURE-----$"
+                          nil t))
          (unless armor-end
            (error "No armor tail"))
          (epa-verify-region armor-start armor-end))))))
 
          (unless armor-end
            (error "No armor tail"))
          (epa-verify-region armor-start armor-end))))))
 
+(if (fboundp 'select-safe-coding-system)
+    (defalias 'epa--select-safe-coding-system 'select-safe-coding-system)
+  (defun epa--select-safe-coding-system (from to)
+    buffer-file-coding-system))
+
 ;;;###autoload
 (defun epa-sign-region (start end signers mode)
   "Sign the current region between START and END by SIGNERS keys selected.
 
 Don't use this command in Lisp programs!"
   (interactive
 ;;;###autoload
 (defun epa-sign-region (start end signers mode)
   "Sign the current region between START and END by SIGNERS keys selected.
 
 Don't use this command in Lisp programs!"
   (interactive
-   (list (region-beginning) (region-end)
-        (epa-select-keys (epg-make-context) "Select keys for signing.
+   (let ((verbose current-prefix-arg))
+     (setq epa-last-coding-system-specified
+          (or coding-system-for-write
+              (epa--select-safe-coding-system
+               (region-beginning) (region-end))))
+     (list (region-beginning) (region-end)
+          (if verbose
+              (epa-select-keys (epg-make-context epa-protocol)
+                               "Select keys for signing.
 If no one is selected, default secret key is used.  "
 If no one is selected, default secret key is used.  "
-                         nil t)
-        (if (y-or-n-p "Make a detached signature? ")
-            'detached
-          (if (y-or-n-p "Make a cleartext signature? ")
-              'clear))))
+                               nil t))
+          (if verbose
+              (epa--read-signature-type)
+            'clear))))
   (save-excursion
   (save-excursion
-    (let ((context (epg-make-context))
+    (let ((context (epg-make-context epa-protocol))
          signature)
          signature)
-      (epg-context-set-armor context epa-armor)
-      (epg-context-set-textmode context epa-textmode)
+      ;;(epg-context-set-armor context epa-armor)
+      (epg-context-set-armor context t)
+      ;;(epg-context-set-textmode context epa-textmode)
+      (epg-context-set-textmode context t)
       (epg-context-set-signers context signers)
       (epg-context-set-signers context signers)
+      (epg-context-set-passphrase-callback context
+                                          #'epa-passphrase-callback-function)
+      (epg-context-set-progress-callback context
+                                        #'epa-progress-callback-function
+                                        "Signing...")
       (message "Signing...")
       (setq signature (epg-sign-string context
       (message "Signing...")
       (setq signature (epg-sign-string context
-                                      (encode-coding-string
+                                      (epa--encode-coding-string
                                        (buffer-substring start end)
                                        (buffer-substring start end)
-                                       coding-system-for-write)
+                                       epa-last-coding-system-specified)
                                       mode))
       (message "Signing...done")
       (delete-region start end)
                                       mode))
       (message "Signing...done")
       (delete-region start end)
-      (insert (decode-coding-string signature coding-system-for-read)))))
+      (goto-char start)
+      (add-text-properties (point)
+                          (progn
+                            (insert (epa--decode-coding-string
+                                     signature
+                                     (or coding-system-for-read
+                                         epa-last-coding-system-specified)))
+                            (point))
+                          (list 'epa-coding-system-used
+                                epa-last-coding-system-specified
+                                'front-sticky nil
+                                'rear-nonsticky t
+                                'start-open t
+                                'end-open t)))))
+
+(if (fboundp 'derived-mode-p)
+    (defalias 'epa--derived-mode-p 'derived-mode-p)
+  (defun epa--derived-mode-p (&rest modes)
+    "Non-nil if the current major mode is derived from one of MODES.
+Uses the `derived-mode-parent' property of the symbol to trace backwards."
+    (let ((parent major-mode))
+      (while (and (not (memq parent modes))
+                 (setq parent (get parent 'derived-mode-parent))))
+      parent)))
 
 ;;;###autoload
 
 ;;;###autoload
-(defun epa-encrypt-region (start end recipients)
+(defun epa-encrypt-region (start end recipients sign signers)
   "Encrypt the current region between START and END for RECIPIENTS.
 
 Don't use this command in Lisp programs!"
   (interactive
   "Encrypt the current region between START and END for RECIPIENTS.
 
 Don't use this command in Lisp programs!"
   (interactive
-   (list (region-beginning) (region-end)
-        (epa-select-keys (epg-make-context) "Select recipients for encryption.
-If no one is selected, symmetric encryption will be performed.  ")))
+   (let ((verbose current-prefix-arg)
+        (context (epg-make-context epa-protocol))
+        sign)
+     (setq epa-last-coding-system-specified
+          (or coding-system-for-write
+              (epa--select-safe-coding-system
+               (region-beginning) (region-end))))
+     (list (region-beginning) (region-end)
+          (epa-select-keys context
+                           "Select recipients for encryption.
+If no one is selected, symmetric encryption will be performed.  ")
+          (setq sign (if verbose (y-or-n-p "Sign? ")))
+          (if sign
+              (epa-select-keys context
+                               "Select keys for signing.  ")))))
   (save-excursion
   (save-excursion
-    (let ((context (epg-make-context))
+    (let ((context (epg-make-context epa-protocol))
          cipher)
          cipher)
-      (epg-context-set-armor context epa-armor)
-      (epg-context-set-textmode context epa-textmode)
+      ;;(epg-context-set-armor context epa-armor)
+      (epg-context-set-armor context t)
+      ;;(epg-context-set-textmode context epa-textmode)
+      (epg-context-set-textmode context t)
+      (if sign
+         (epg-context-set-signers context signers))
+      (epg-context-set-passphrase-callback context
+                                          #'epa-passphrase-callback-function)
+      (epg-context-set-progress-callback context
+                                        #'epa-progress-callback-function
+                                        "Encrypting...")
       (message "Encrypting...")
       (setq cipher (epg-encrypt-string context
       (message "Encrypting...")
       (setq cipher (epg-encrypt-string context
-                                      (encode-coding-string
+                                      (epa--encode-coding-string
                                        (buffer-substring start end)
                                        (buffer-substring start end)
-                                       coding-system-for-write)
-                                      recipients))
+                                       epa-last-coding-system-specified)
+                                      recipients
+                                      sign))
       (message "Encrypting...done")
       (delete-region start end)
       (message "Encrypting...done")
       (delete-region start end)
-      (insert cipher))))
+      (goto-char start)
+      (add-text-properties (point)
+                          (progn
+                            (insert cipher)
+                            (point))
+                          (list 'epa-coding-system-used
+                                epa-last-coding-system-specified
+                                'front-sticky nil
+                                'rear-nonsticky t
+                                'start-open t
+                                'end-open t)))))
 
 ;;;###autoload
 (defun epa-delete-keys (keys &optional allow-secret)
 
 ;;;###autoload
 (defun epa-delete-keys (keys &optional allow-secret)
-  "Delete selected KEYS."
+  "Delete selected KEYS.
+
+Don't use this command in Lisp programs!"
   (interactive
   (interactive
-   (let ((keys (epa-marked-keys)))
+   (let ((keys (epa--marked-keys)))
      (unless keys
        (error "No keys selected"))
      (list keys
           (eq (nth 1 epa-list-keys-arguments) t))))
      (unless keys
        (error "No keys selected"))
      (list keys
           (eq (nth 1 epa-list-keys-arguments) t))))
-  (let ((context (epg-make-context)))
+  (let ((context (epg-make-context epa-protocol)))
     (message "Deleting...")
     (epg-delete-keys context keys allow-secret)
     (message "Deleting...done")
     (message "Deleting...")
     (epg-delete-keys context keys allow-secret)
     (message "Deleting...done")
@@ -770,19 +1004,73 @@ If no one is selected, symmetric encryption will be performed.  ")))
 
 ;;;###autoload
 (defun epa-import-keys (file)
 
 ;;;###autoload
 (defun epa-import-keys (file)
-  "Import keys from FILE."
+  "Import keys from FILE.
+
+Don't use this command in Lisp programs!"
   (interactive "fFile: ")
   (interactive "fFile: ")
-  (let ((context (epg-make-context)))
+  (setq file (expand-file-name file))
+  (let ((context (epg-make-context epa-protocol)))
     (message "Importing %s..." (file-name-nondirectory file))
     (message "Importing %s..." (file-name-nondirectory file))
-    (epg-import-keys-from-file context (expand-file-name file))
-    (message "Importing %s...done" (file-name-nondirectory file))
-    (apply #'epa-list-keys epa-list-keys-arguments)))
+    (condition-case nil
+       (progn
+         (epg-import-keys-from-file context file)
+         (message "Importing %s...done" (file-name-nondirectory file)))
+      (error
+       (message "Importing %s...failed" (file-name-nondirectory file))))
+    (if (epg-context-result-for context 'import)
+       (epa-display-info (epg-import-result-to-string
+                          (epg-context-result-for context 'import))))
+    (if (eq major-mode 'epa-key-list-mode)
+       (apply #'epa-list-keys epa-list-keys-arguments))))
+
+;;;###autoload
+(defun epa-import-keys-region (start end)
+  "Import keys from the region.
+
+Don't use this command in Lisp programs!"
+  (interactive "r")
+  (let ((context (epg-make-context epa-protocol)))
+    (message "Importing...")
+    (condition-case nil
+       (progn
+         (epg-import-keys-from-string context (buffer-substring start end))
+         (message "Importing...done"))
+      (error
+       (message "Importing...failed")))
+    (if (epg-context-result-for context 'import)
+       (epa-display-info (epg-import-result-to-string
+                          (epg-context-result-for context 'import))))))
+
+;;;###autoload
+(defun epa-import-armor-in-region (start end)
+  "Import keys in the OpenPGP armor format in the current region
+between START and END.
+
+Don't use this command in Lisp programs!"
+  (interactive "r")
+  (save-excursion
+    (save-restriction
+      (narrow-to-region start end)
+      (goto-char start)
+      (let (armor-start armor-end)
+       (while (re-search-forward
+               "-----BEGIN \\(PGP \\(PUBLIC\\|PRIVATE\\) KEY BLOCK\\)-----$"
+               nil t)
+         (setq armor-start (match-beginning 0)
+               armor-end (re-search-forward
+                          (concat "^-----END " (match-string 1) "-----$")
+                          nil t))
+         (unless armor-end
+           (error "No armor tail"))
+         (epa-import-keys-region armor-start armor-end))))))
 
 ;;;###autoload
 (defun epa-export-keys (keys file)
 
 ;;;###autoload
 (defun epa-export-keys (keys file)
-  "Export selected KEYS to FILE."
+  "Export selected KEYS to FILE.
+
+Don't use this command in Lisp programs!"
   (interactive
   (interactive
-   (let ((keys (epa-marked-keys))
+   (let ((keys (epa--marked-keys))
         default-name)
      (unless keys
        (error "No keys selected"))
         default-name)
      (unless keys
        (error "No keys selected"))
@@ -799,43 +1087,46 @@ If no one is selected, symmetric encryption will be performed.  ")))
                     ") ")
             (file-name-directory default-name)
             default-name)))))
                     ") ")
             (file-name-directory default-name)
             default-name)))))
-  (let ((context (epg-make-context)))
+  (let ((context (epg-make-context epa-protocol)))
     (epg-context-set-armor context epa-armor)
     (message "Exporting to %s..." (file-name-nondirectory file))
     (epg-export-keys-to-file context keys file)
     (message "Exporting to %s...done" (file-name-nondirectory file))))
 
 ;;;###autoload
     (epg-context-set-armor context epa-armor)
     (message "Exporting to %s..." (file-name-nondirectory file))
     (epg-export-keys-to-file context keys file)
     (message "Exporting to %s...done" (file-name-nondirectory file))))
 
 ;;;###autoload
+(defun epa-insert-keys (keys)
+  "Insert selected KEYS after the point.
+
+Don't use this command in Lisp programs!"
+  (interactive
+   (list (epa-select-keys (epg-make-context epa-protocol)
+                         "Select keys to export.  ")))
+  (let ((context (epg-make-context epa-protocol)))
+    ;;(epg-context-set-armor context epa-armor)
+    (epg-context-set-armor context t)
+    (insert (epg-export-keys-to-string context keys))))
+
+;;;###autoload
 (defun epa-sign-keys (keys &optional local)
   "Sign selected KEYS.
 (defun epa-sign-keys (keys &optional local)
   "Sign selected KEYS.
-If LOCAL is non-nil, the signature is marked as non exportable."
+If a prefix-arg is specified, the signature is marked as non exportable.
+
+Don't use this command in Lisp programs!"
   (interactive
   (interactive
-   (let ((keys (epa-marked-keys)))
+   (let ((keys (epa--marked-keys)))
      (unless keys
        (error "No keys selected"))
      (list keys current-prefix-arg)))
      (unless keys
        (error "No keys selected"))
      (list keys current-prefix-arg)))
-  (let ((context (epg-make-context)))
+  (let ((context (epg-make-context epa-protocol)))
+    (epg-context-set-passphrase-callback context
+                                        #'epa-passphrase-callback-function)
+    (epg-context-set-progress-callback context
+                                      #'epa-progress-callback-function
+                                      "Signing keys...")
     (message "Signing keys...")
     (epg-sign-keys context keys local)
     (message "Signing keys...done")))
     (message "Signing keys...")
     (epg-sign-keys context keys local)
     (message "Signing keys...done")))
-
-(defun epa-passphrase-callback-function (context key-id handback)
-  (if (eq key-id 'SYM)
-      (read-passwd "Passphrase for symmetric encryption: "
-                  (eq (epg-context-operation context) 'encrypt))
-    (read-passwd
-     (if (eq key-id 'PIN)
-       "Passphrase for PIN: "
-       (let ((entry (assoc key-id epg-user-id-alist)))
-        (if entry
-            (format "Passphrase for %s %s: " key-id (cdr entry))
-          (format "Passphrase for %s: " key-id)))))))
-
-(defun epa-progress-callback-function (context what char current total
-                                              handback)
-  (message "%s: %d%% (%d/%d)" what
-          (if (> total 0) (floor (* (/ current (float total)) 100)) 0)
-          current total))
+(make-obsolete 'epa-sign-keys "Do not use.")
 
 (provide 'epa)
 
 
 (provide 'epa)