:type 'integer
:group 'epa)
+(defcustom epa-mail-modes '(mail-mode message-mode)
+ "List of major-modes to compose mails."
+ :type 'list
+ :group 'epa)
+
(defgroup epa-faces nil
"Faces for epa-mode."
:group 'epa)
(save-selected-window
(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)
(defun epa-progress-callback-function (context what char current total
handback)
- (message "%s: %d%% (%d/%d)" what
+ (message "%s%d%% (%d/%d)" (or handback
+ (concat what ": "))
(if (> total 0) (floor (* (/ current (float total)) 100)) 0)
current total))
(epg-context-set-passphrase-callback context
#'epa-passphrase-callback-function)
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'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...wrote %s" (file-name-nondirectory file)
(plain (if (equal (file-name-extension file) "sig")
(file-name-sans-extension file))))
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'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))
(defun epa-sign-file (file signers mode)
"Sign FILE by SIGNERS keys selected."
(interactive
- (list (expand-file-name (read-file-name "File: "))
- (if current-prefix-arg
- (epa-select-keys (epg-make-context epa-protocol)
- "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. "
- nil t))
- (if current-prefix-arg
- (epa--read-signature-type)
- 'clear)))
+ nil t))
+ (if verbose
+ (epa--read-signature-type)
+ 'clear))))
(let ((signature (concat file
(if (eq epa-protocol 'OpenPGP)
(if (or epa-armor
(epg-context-set-passphrase-callback context
#'epa-passphrase-callback-function)
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'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...wrote %s" (file-name-nondirectory file)
(epg-context-set-passphrase-callback context
#'epa-passphrase-callback-function)
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'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...wrote %s" (file-name-nondirectory file)
(epg-context-set-passphrase-callback context
#'epa-passphrase-callback-function)
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'epa-progress-callback-function
+ "Decrypting...")
(message "Decrypting...")
(setq plain (epg-decrypt-string context (buffer-substring start end)))
(message "Decrypting...done")
- (delete-region start end)
- (goto-char start)
- (insert (epa--decode-coding-string plain
- (or coding-system-for-read
- (get-text-property
- start 'epa-coding-system-used))))
+ (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))
+ (let ((epa-popup-info-window t))
+ (epa-display-info plain)))
(if (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)
"Decrypt OpenPGP armors in the current region between START and END.
(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-----$"
(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))
+ (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))))))))
(epa-decrypt-region armor-start armor-end)))))))
;;;###autoload
(interactive "r")
(let ((context (epg-make-context epa-protocol)))
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'epa-progress-callback-function
+ "Verifying...")
(epg-verify-string context
(epa--encode-coding-string
(buffer-substring start end)
"Verify OpenPGP cleartext signed messages in the current buffer.
Don't use this command in Lisp programs!"
+ (interactive)
(epa-verify-cleartext-in-region (point-min) (point-max)))
;;;###autoload
Don't use this command in Lisp programs!"
(interactive
- (progn
+ (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 current-prefix-arg
+ (if verbose
(epa-select-keys (epg-make-context epa-protocol)
"Select keys for signing.
If no one is selected, default secret key is used. "
nil t))
- (if current-prefix-arg
+ (if verbose
(epa--read-signature-type)
'clear))))
(save-excursion
(epg-context-set-passphrase-callback context
#'epa-passphrase-callback-function)
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'epa-progress-callback-function
+ "Signing...")
(message "Signing...")
(setq signature (epg-sign-string context
(epa--encode-coding-string
mode))
(message "Signing...done")
(delete-region start end)
+ (goto-char start)
(add-text-properties (point)
(progn
(insert (epa--decode-coding-string
'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)))
+
+(defun epa--mail-mode-p ()
+ (let ((pointer epa-mail-modes))
+ (while (and pointer
+ (epa--derived-mode-p (car pointer)))
+ (setq pointer (cdr pointer)))
+ pointer))
+
;;;###autoload
(defun epa-sign (start end signers mode)
"Sign the current buffer.
Don't use this command in Lisp programs!"
(interactive
- (progn
+ (save-excursion
(goto-char (point-min))
- (if (and (or (eq major-mode 'mail-mode)
- (eq (derived-mode-class major-mode) 'mail-mode))
+ (if (and (epa--mail-mode-p)
(search-forward mail-header-separator nil t))
(forward-line))
(setq epa-last-coding-system-specified
(or coding-system-for-write
(epa--select-safe-coding-system (point) (point-max))))
- (list (point) (point-max)
- (if current-prefix-arg
- (epa-select-keys (epg-make-context epa-protocol)
- "Select keys for signing.
+ (let ((verbose current-prefix-arg))
+ (list (point) (point-max)
+ (if verbose
+ (epa-select-keys (epg-make-context epa-protocol)
+ "Select keys for signing.
If no one is selected, default secret key is used. "
- nil t))
- (if current-prefix-arg
- (epa--read-signature-type)
- 'clear))))
+ nil t))
+ (if verbose
+ (epa--read-signature-type)
+ 'clear)))))
(epa-sign-region start end signers mode))
;;;###autoload
(epg-context-set-passphrase-callback context
#'epa-passphrase-callback-function)
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'epa-progress-callback-function
+ "Encrypting...")
(message "Encrypting...")
(setq cipher (epg-encrypt-string context
(epa--encode-coding-string
recipients))
(message "Encrypting...done")
(delete-region start end)
+ (goto-char start)
(add-text-properties (point)
(progn
(insert cipher)
Don't use this command in Lisp programs!"
(interactive
- (let (recipients)
- (goto-char (point-min))
- (when (or (eq major-mode 'mail-mode)
- (eq (derived-mode-class major-mode) 'mail-mode))
- (save-restriction
- (narrow-to-region (point)
- (progn
- (search-forward mail-header-separator nil 0)
- (match-beginning 0)))
- (setq recipients
- (mail-strip-quoted-names
- (mapconcat #'identity
- (nconc (mail-fetch-field "to" nil nil t)
- (mail-fetch-field "cc" nil nil t)
- (mail-fetch-field "bcc" nil nil t))
- ","))))
- (if recipients
- (setq recipients (delete "" (split-string recipients "[ \t\n]+"))))
+ (save-excursion
+ (let (recipients)
(goto-char (point-min))
- (if (search-forward mail-header-separator nil t)
- (forward-line)))
- (setq epa-last-coding-system-specified
- (or coding-system-for-write
- (epa--select-safe-coding-system (point) (point-max))))
- (list (point) (point-max)
- (if current-prefix-arg
- (epa-select-keys
- (epg-make-context epa-protocol)
- "Select recipients for encryption.
+ (when (epa--mail-mode-p)
+ (save-restriction
+ (narrow-to-region (point)
+ (if (search-forward mail-header-separator nil 0)
+ (match-beginning 0)
+ (point)))
+ (setq recipients
+ (mail-strip-quoted-names
+ (mapconcat #'identity
+ (nconc (mail-fetch-field "to" nil nil t)
+ (mail-fetch-field "cc" nil nil t)
+ (mail-fetch-field "bcc" nil nil t))
+ ","))))
+ (if recipients
+ (setq recipients (delete ""
+ (split-string recipients "[ \t\n]+"))))
+ (goto-char (point-min))
+ (if (search-forward mail-header-separator nil t)
+ (forward-line)))
+ (setq epa-last-coding-system-specified
+ (or coding-system-for-write
+ (epa--select-safe-coding-system (point) (point-max))))
+ (list (point) (point-max)
+ (if current-prefix-arg
+ (epa-select-keys
+ (epg-make-context epa-protocol)
+ "Select recipients for encryption.
If no one is selected, symmetric encryption will be performed. "
- recipients)
- (if recipients
- (delq nil
- (apply #'nconc
- (mapcar
- (lambda (recipient)
- (epg-list-keys (epg-make-context epa-protocol)
- (concat "<" recipient ">")))
- recipients))))))))
+ recipients)
+ (if recipients
+ (delq nil
+ (apply #'nconc
+ (mapcar
+ (lambda (recipient)
+ (epg-list-keys
+ (epg-make-context epa-protocol)
+ (concat "<" recipient ">")))
+ recipients)))))))))
(epa-encrypt-region start end recipients))
;;;###autoload
(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-import ()
+ "Import keys in the OpenPGP armor format in the current buffer.
+
+Don't use this command in Lisp programs!"
+ (interactive)
+ (epa-import-armor-in-region (point-min) (point-max)))
+
+;;;###autoload
(defun epa-export-keys (keys file)
"Export selected KEYS to FILE.
(epg-context-set-passphrase-callback context
#'epa-passphrase-callback-function)
(epg-context-set-progress-callback context
- #'epa-progress-callback-function)
+ #'epa-progress-callback-function
+ "Signing keys...")
(message "Signing keys...")
(epg-sign-keys context keys local)
(message "Signing keys...done")))