diff options
| author | Paul Eggert | 2011-08-15 22:58:30 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-08-15 22:58:30 -0700 |
| commit | 3f74064edab68e5620fade9b802e863cb110afd2 (patch) | |
| tree | 5631c5c98220f0a63f8552996e576b435e5b41ae | |
| parent | fe5c5d37807dbf2d224de5fe9cf821d8292112b1 (diff) | |
| parent | 04963aa8ff62058b9795c3e3217630515470fcff (diff) | |
| download | emacs-3f74064edab68e5620fade9b802e863cb110afd2.tar.gz emacs-3f74064edab68e5620fade9b802e863cb110afd2.zip | |
Merge from trunk.
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/ChangeLog | 17 | ||||
| -rw-r--r-- | lisp/epa-mail.el | 75 | ||||
| -rw-r--r-- | lisp/epa.el | 41 | ||||
| -rw-r--r-- | lisp/mail/rmail.el | 106 |
5 files changed, 227 insertions, 17 deletions
| @@ -820,6 +820,11 @@ on a D-Bus without simultaneously registering a property or a method. | |||
| 820 | *** The option `ange-ftp-binary-file-name-regexp' has changed its | 820 | *** The option `ange-ftp-binary-file-name-regexp' has changed its |
| 821 | default value to "". | 821 | default value to "". |
| 822 | 822 | ||
| 823 | ** Rmail | ||
| 824 | |||
| 825 | *** The command `rmail-epa-decrypt' decrypts OpenPGP data | ||
| 826 | in the Rmail incoming message. | ||
| 827 | |||
| 823 | ** VC and related modes | 828 | ** VC and related modes |
| 824 | 829 | ||
| 825 | *** Support for pulling on distributed version control systems. | 830 | *** Support for pulling on distributed version control systems. |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 7116a152605..70d34fb7117 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,20 @@ | |||
| 1 | 2011-08-16 Richard Stallman <rms@gnu.org> | ||
| 2 | |||
| 3 | * epa-mail.el: Handle GnuPG group definitions. | ||
| 4 | (epa-mail-group-alist, epa-mail-group-modtime) | ||
| 5 | (epa-mail-gnupg-conf-file): New variables. | ||
| 6 | (epa-mail-parse-groups, epa-mail-sync-groups) | ||
| 7 | (epa-mail-expand-recipient-1, epa-mail-expand-recipients-2) | ||
| 8 | (epa-mail-expand-recipients): New functions. | ||
| 9 | (epa-mail-encrypt): Call epa-mail-expand-recipients. | ||
| 10 | |||
| 11 | * mail/rmail.el (rmail-epa-decrypt): New command. | ||
| 12 | |||
| 13 | * epa.el (epa-decrypt-region): New arg MAKE-BUFFER-FUNCTION. | ||
| 14 | Don't bind buffer-read-only, just inhibit-read-only. | ||
| 15 | (epa--find-coding-system-for-mime-charset): Fix the non-xemacs case. | ||
| 16 | (epa-decrypt-armor-in-region): Make error message clearer. | ||
| 17 | |||
| 1 | 2011-08-15 Stefan Monnier <monnier@iro.umontreal.ca> | 18 | 2011-08-15 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 19 | ||
| 3 | * minibuffer.el (completion-pcm--merge-completions): Don't merge "a1b" | 20 | * minibuffer.el (completion-pcm--merge-completions): Don't merge "a1b" |
diff --git a/lisp/epa-mail.el b/lisp/epa-mail.el index a3f11f78675..e6f6c0ec2b1 100644 --- a/lisp/epa-mail.el +++ b/lisp/epa-mail.el | |||
| @@ -50,6 +50,9 @@ | |||
| 50 | "A minor-mode for composing encrypted/clearsigned mails." | 50 | "A minor-mode for composing encrypted/clearsigned mails." |
| 51 | nil " epa-mail" epa-mail-mode-map) | 51 | nil " epa-mail" epa-mail-mode-map) |
| 52 | 52 | ||
| 53 | ;;; ??? Could someone please clarify this doc string? | ||
| 54 | ;;; In particular, what does USAGE look like | ||
| 55 | ;;; and what does it mean? -- rms | ||
| 53 | (defun epa-mail--find-usable-key (keys usage) | 56 | (defun epa-mail--find-usable-key (keys usage) |
| 54 | "Find a usable key from KEYS for USAGE." | 57 | "Find a usable key from KEYS for USAGE." |
| 55 | (catch 'found | 58 | (catch 'found |
| @@ -63,6 +66,71 @@ | |||
| 63 | (setq pointer (cdr pointer)))) | 66 | (setq pointer (cdr pointer)))) |
| 64 | (setq keys (cdr keys))))) | 67 | (setq keys (cdr keys))))) |
| 65 | 68 | ||
| 69 | (defvar epa-mail-group-alist nil | ||
| 70 | "Alist of GnuPG mail groups (`group' commands in `.gnupg/gpg.conf'). | ||
| 71 | Each element has the form (GROUPNAME ADDRESSES...). | ||
| 72 | t means the list is not yet read in.") | ||
| 73 | |||
| 74 | (defvar epa-mail-group-modtime nil | ||
| 75 | "The modification time of `~/.gnupg/gpg.conf' file when last examined.") | ||
| 76 | |||
| 77 | (defvar epa-mail-gnupg-conf-file "~/.gnupg/gpg.conf" | ||
| 78 | "File name of GnuPG configuration file that specifies recipient groups.") | ||
| 79 | |||
| 80 | (defun epa-mail-parse-groups () | ||
| 81 | "Parse `~/.gnupg/gpg.conf' and set `epa-mail-group-alist' from it." | ||
| 82 | (let (aliases) | ||
| 83 | (with-temp-buffer | ||
| 84 | (insert-file-contents-literally epa-mail-gnupg-conf-file) | ||
| 85 | |||
| 86 | (while (re-search-forward "^[ \t]*group[ \t]*" nil t) | ||
| 87 | (if (looking-at "\\([^= \t]+\\)[ \t]*=[ \t]*\\([^ \t\n]+\\)") | ||
| 88 | (push (cons (match-string-no-properties 1) | ||
| 89 | (split-string (match-string-no-properties 2))) | ||
| 90 | aliases)))) | ||
| 91 | (setq epa-mail-group-alist aliases))) | ||
| 92 | |||
| 93 | (defun epa-mail-sync-groups () | ||
| 94 | "Update GnuPG groups from file if necessary." | ||
| 95 | (if (file-exists-p epa-mail-gnupg-conf-file) | ||
| 96 | (let ((modtime (nth 5 (file-attributes epa-mail-gnupg-conf-file)))) | ||
| 97 | (if (not (equal epa-mail-group-modtime modtime)) | ||
| 98 | (progn | ||
| 99 | (setq epa-mail-group-modtime modtime) | ||
| 100 | (epa-mail-parse-groups)))) | ||
| 101 | (setq epa-mail-group-alist nil))) | ||
| 102 | |||
| 103 | (defun epa-mail-expand-recipient-1 (recipient) | ||
| 104 | "Expand RECIPIENT once thru `epa-mail-group-alist'. | ||
| 105 | Returns the list of names it stands for, or nil if it isn't a group." | ||
| 106 | ;; Load the alias list if not loaded before. | ||
| 107 | (let (alist-elt) | ||
| 108 | (setq alist-elt (assoc recipient epa-mail-group-alist)) | ||
| 109 | (cdr alist-elt))) | ||
| 110 | |||
| 111 | (defun epa-mail-expand-recipients-2 (recipients) | ||
| 112 | "Expand list RECIPIENTS once thru `epa-mail-group-alist'. | ||
| 113 | Returns the list of names they stand for." | ||
| 114 | ;; Load the alias list if not loaded before. | ||
| 115 | (let (output) | ||
| 116 | (dolist (r recipients) | ||
| 117 | (let ((expanded (epa-mail-expand-recipient-1 r))) | ||
| 118 | (if expanded | ||
| 119 | (dolist (xr expanded) | ||
| 120 | (unless (member xr output) | ||
| 121 | (push xr output))) | ||
| 122 | (unless (member r output) | ||
| 123 | (push r output))))) | ||
| 124 | (nreverse output))) | ||
| 125 | |||
| 126 | (defun epa-mail-expand-recipients (recipients) | ||
| 127 | "Expand RECIPIENTS thru `epa-mail-group-alist' until it stops changing." | ||
| 128 | (epa-mail-sync-groups) | ||
| 129 | (while (not (equal recipients | ||
| 130 | (setq recipients | ||
| 131 | (epa-mail-expand-recipients-2 recipients))))) | ||
| 132 | recipients) | ||
| 133 | |||
| 66 | ;;;###autoload | 134 | ;;;###autoload |
| 67 | (defun epa-mail-decrypt () | 135 | (defun epa-mail-decrypt () |
| 68 | "Decrypt OpenPGP armors in the current buffer. | 136 | "Decrypt OpenPGP armors in the current buffer. |
| @@ -140,6 +208,13 @@ Don't use this command in Lisp programs!" | |||
| 140 | (setq recipients (delete "" | 208 | (setq recipients (delete "" |
| 141 | (split-string recipients | 209 | (split-string recipients |
| 142 | "[ \t\n]*,[ \t\n]*")))) | 210 | "[ \t\n]*,[ \t\n]*")))) |
| 211 | |||
| 212 | ;; Process all the recipients thru the list of GnuPG groups. | ||
| 213 | ;; Expand GnuPG group names to what they stand for. | ||
| 214 | ;; The code below, and elsewhere, that checks that names have keys | ||
| 215 | ;; does not know about these group names. | ||
| 216 | (setq recipients (epa-mail-expand-recipients recipients)) | ||
| 217 | |||
| 143 | (goto-char (point-min)) | 218 | (goto-char (point-min)) |
| 144 | (if (search-forward mail-header-separator nil t) | 219 | (if (search-forward mail-header-separator nil t) |
| 145 | (forward-line)) | 220 | (forward-line)) |
diff --git a/lisp/epa.el b/lisp/epa.el index e2fafc753d7..f0ec1ece0d1 100644 --- a/lisp/epa.el +++ b/lisp/epa.el | |||
| @@ -803,10 +803,15 @@ If no one is selected, symmetric encryption will be performed. "))) | |||
| 803 | (file-name-nondirectory cipher)))) | 803 | (file-name-nondirectory cipher)))) |
| 804 | 804 | ||
| 805 | ;;;###autoload | 805 | ;;;###autoload |
| 806 | (defun epa-decrypt-region (start end) | 806 | (defun epa-decrypt-region (start end &optional make-buffer-function) |
| 807 | "Decrypt the current region between START and END. | 807 | "Decrypt the current region between START and END. |
| 808 | 808 | ||
| 809 | Don't use this command in Lisp programs! | 809 | If MAKE-BUFFER-FUNCTION is non-nil, call it to prepare an output buffer. |
| 810 | It should return that buffer. If it copies the input, it should | ||
| 811 | delete the text now being decrypted. It should leave point at the | ||
| 812 | proper place to insert the plaintext. | ||
| 813 | |||
| 814 | Be careful about using this command in Lisp programs! | ||
| 810 | Since this function operates on regions, it does some tricks such | 815 | Since this function operates on regions, it does some tricks such |
| 811 | as coding-system detection and unibyte/multibyte conversion. If | 816 | as coding-system detection and unibyte/multibyte conversion. If |
| 812 | you are sure how the data in the region should be treated, you | 817 | you are sure how the data in the region should be treated, you |
| @@ -838,16 +843,19 @@ For example: | |||
| 838 | (or coding-system-for-read | 843 | (or coding-system-for-read |
| 839 | (get-text-property start 'epa-coding-system-used) | 844 | (get-text-property start 'epa-coding-system-used) |
| 840 | 'undecided))) | 845 | 'undecided))) |
| 841 | (if (y-or-n-p "Replace the original text? ") | 846 | (if make-buffer-function |
| 842 | (let ((inhibit-read-only t) | 847 | (with-current-buffer (funcall make-buffer-function) |
| 843 | buffer-read-only) | 848 | (let ((inhibit-read-only t)) |
| 844 | (delete-region start end) | 849 | (insert plain))) |
| 845 | (goto-char start) | 850 | (if (y-or-n-p "Replace the original text? ") |
| 846 | (insert plain)) | 851 | (let ((inhibit-read-only t)) |
| 847 | (with-output-to-temp-buffer "*Temp*" | 852 | (delete-region start end) |
| 848 | (set-buffer standard-output) | 853 | (goto-char start) |
| 849 | (insert plain) | 854 | (insert plain)) |
| 850 | (epa-info-mode))) | 855 | (with-output-to-temp-buffer "*Temp*" |
| 856 | (set-buffer standard-output) | ||
| 857 | (insert plain) | ||
| 858 | (epa-info-mode)))) | ||
| 851 | (if (epg-context-result-for context 'verify) | 859 | (if (epg-context-result-for context 'verify) |
| 852 | (epa-display-info (epg-verify-result-to-string | 860 | (epa-display-info (epg-verify-result-to-string |
| 853 | (epg-context-result-for context 'verify))))))) | 861 | (epg-context-result-for context 'verify))))))) |
| @@ -856,12 +864,13 @@ For example: | |||
| 856 | (if (featurep 'xemacs) | 864 | (if (featurep 'xemacs) |
| 857 | (if (fboundp 'find-coding-system) | 865 | (if (fboundp 'find-coding-system) |
| 858 | (find-coding-system mime-charset)) | 866 | (find-coding-system mime-charset)) |
| 867 | ;; Find the first coding system which corresponds to MIME-CHARSET. | ||
| 859 | (let ((pointer (coding-system-list))) | 868 | (let ((pointer (coding-system-list))) |
| 860 | (while (and pointer | 869 | (while (and pointer |
| 861 | (eq (coding-system-get (car pointer) 'mime-charset) | 870 | (not (eq (coding-system-get (car pointer) 'mime-charset) |
| 862 | mime-charset)) | 871 | mime-charset))) |
| 863 | (setq pointer (cdr pointer))) | 872 | (setq pointer (cdr pointer))) |
| 864 | pointer))) | 873 | (car pointer)))) |
| 865 | 874 | ||
| 866 | ;;;###autoload | 875 | ;;;###autoload |
| 867 | (defun epa-decrypt-armor-in-region (start end) | 876 | (defun epa-decrypt-armor-in-region (start end) |
| @@ -880,7 +889,7 @@ See the reason described in the `epa-decrypt-region' documentation." | |||
| 880 | armor-end (re-search-forward "^-----END PGP MESSAGE-----$" | 889 | armor-end (re-search-forward "^-----END PGP MESSAGE-----$" |
| 881 | nil t)) | 890 | nil t)) |
| 882 | (unless armor-end | 891 | (unless armor-end |
| 883 | (error "No armor tail")) | 892 | (error "Encryption armor beginning has no matching end")) |
| 884 | (goto-char armor-start) | 893 | (goto-char armor-start) |
| 885 | (let ((coding-system-for-read | 894 | (let ((coding-system-for-read |
| 886 | (or coding-system-for-read | 895 | (or coding-system-for-read |
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index c43ec9e5611..9b4bbf91823 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el | |||
| @@ -4249,7 +4249,7 @@ TEXT and INDENT are not used." | |||
| 4249 | ;; rmail-output expands non-absolute filenames against rmail-default-file. | 4249 | ;; rmail-output expands non-absolute filenames against rmail-default-file. |
| 4250 | ;; What is the point of that, anyway? | 4250 | ;; What is the point of that, anyway? |
| 4251 | (rmail-output (expand-file-name token)))) | 4251 | (rmail-output (expand-file-name token)))) |
| 4252 | 4252 | ||
| 4253 | ;; Functions for setting, getting and encoding the POP password. | 4253 | ;; Functions for setting, getting and encoding the POP password. |
| 4254 | ;; The password is encoded to prevent it from being easily accessible | 4254 | ;; The password is encoded to prevent it from being easily accessible |
| 4255 | ;; to "prying eyes." Obviously, this encoding isn't "real security," | 4255 | ;; to "prying eyes." Obviously, this encoding isn't "real security," |
| @@ -4300,6 +4300,110 @@ encoded string (and the same mask) will decode the string." | |||
| 4300 | (setq i (1+ i))) | 4300 | (setq i (1+ i))) |
| 4301 | (concat string-vector))) | 4301 | (concat string-vector))) |
| 4302 | 4302 | ||
| 4303 | (defun rmail-epa-decrypt () | ||
| 4304 | "Decrypt OpenPGP armors in current message." | ||
| 4305 | (interactive) | ||
| 4306 | |||
| 4307 | ;; Save the current buffer here for cleanliness, in case we | ||
| 4308 | ;; change it in one of the calls to `epa-decrypt-region'. | ||
| 4309 | |||
| 4310 | (save-excursion | ||
| 4311 | (let (new-buffer not-first-armor) | ||
| 4312 | (goto-char (point-min)) | ||
| 4313 | |||
| 4314 | ;; In case the encrypted data is inside a mime attachment, | ||
| 4315 | ;; show it. This is a kludge; to be clean, it should not | ||
| 4316 | ;; modify the buffer, but I don't see how to do that. | ||
| 4317 | (when (search-forward "octet-stream" nil t) | ||
| 4318 | (beginning-of-line) | ||
| 4319 | (forward-button 1) | ||
| 4320 | (if (looking-at "Show") | ||
| 4321 | (rmail-mime-toggle-hidden))) | ||
| 4322 | |||
| 4323 | ;; Now find all armored messages in the buffer | ||
| 4324 | ;; and decrypt them one by one. | ||
| 4325 | (goto-char (point-min)) | ||
| 4326 | (while (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t) | ||
| 4327 | (let (armor-start armor-end | ||
| 4328 | (coding-system-for-read coding-system-for-read)) | ||
| 4329 | (setq armor-start (match-beginning 0) | ||
| 4330 | armor-end (re-search-forward "^-----END PGP MESSAGE-----$" | ||
| 4331 | nil t)) | ||
| 4332 | (unless armor-end | ||
| 4333 | (error "Encryption armor beginning has no matching end")) | ||
| 4334 | (goto-char armor-start) | ||
| 4335 | |||
| 4336 | ;; Because epa--find-coding-system-for-mime-charset not autoloaded. | ||
| 4337 | (require 'epa) | ||
| 4338 | |||
| 4339 | ;; Use the charset specified in the armor. | ||
| 4340 | (unless coding-system-for-read | ||
| 4341 | (if (re-search-forward "^Charset: \\(.*\\)" armor-end t) | ||
| 4342 | (setq coding-system-for-read | ||
| 4343 | (epa--find-coding-system-for-mime-charset | ||
| 4344 | (intern (downcase (match-string 1))))))) | ||
| 4345 | |||
| 4346 | ;; Advance over this armor. | ||
| 4347 | (goto-char armor-end) | ||
| 4348 | |||
| 4349 | ;; Decrypt it, maybe in place, maybe making new buffer. | ||
| 4350 | (epa-decrypt-region | ||
| 4351 | armor-start armor-end | ||
| 4352 | ;; Call back this function to prepare the output. | ||
| 4353 | (lambda () | ||
| 4354 | (if (or not-first-armor | ||
| 4355 | (y-or-n-p "Replace the original message? ")) | ||
| 4356 | ;; User wants to decrypt in place, | ||
| 4357 | ;; or this isn't the first armor. | ||
| 4358 | ;; We only ask the question for the first armor. | ||
| 4359 | (let ((inhibit-read-only t)) | ||
| 4360 | (delete-region armor-start armor-end) | ||
| 4361 | (goto-char armor-start) | ||
| 4362 | (current-buffer)) | ||
| 4363 | ;; User says not to replace the original text. | ||
| 4364 | (or new-buffer | ||
| 4365 | (let ((from-buffer | ||
| 4366 | (if (rmail-buffers-swapped-p) | ||
| 4367 | rmail-view-buffer rmail-buffer)) | ||
| 4368 | (from-pruned (rmail-msg-is-pruned)) | ||
| 4369 | (beg (rmail-msgbeg rmail-current-message)) | ||
| 4370 | (end (rmail-msgend rmail-current-message))) | ||
| 4371 | (with-current-buffer (generate-new-buffer "*Decrypt*") | ||
| 4372 | (setq buffer-read-only nil) | ||
| 4373 | (insert-buffer-substring from-buffer beg end) | ||
| 4374 | (rmail-mode) | ||
| 4375 | ;; This should be pruned if the original message was. | ||
| 4376 | (unless from-pruned (rmail-toggle-header)) | ||
| 4377 | (goto-char (point-min)) | ||
| 4378 | |||
| 4379 | ;; Find the first armor in the text we just copied. | ||
| 4380 | ;; What we copied may not be identical | ||
| 4381 | ;; to the initial text. | ||
| 4382 | (re-search-forward "-----BEGIN PGP MESSAGE-----$") | ||
| 4383 | (setq armor-start (match-beginning 0)) | ||
| 4384 | (re-search-forward "^-----END PGP MESSAGE-----$") | ||
| 4385 | (setq armor-end (point)) | ||
| 4386 | ;; Delete it and put point there. | ||
| 4387 | (let ((inhibit-read-only t)) | ||
| 4388 | (delete-region armor-start armor-end)) | ||
| 4389 | (goto-char armor-start) | ||
| 4390 | (setq new-buffer (current-buffer)) | ||
| 4391 | ;; Return; epa-decrypt-region will insert plaintext. | ||
| 4392 | )))))) | ||
| 4393 | |||
| 4394 | (setq not-first-armor t) | ||
| 4395 | |||
| 4396 | ;; If we copied the buffer, switch to the copy | ||
| 4397 | ;; for the rest of this loop. | ||
| 4398 | ;; Point is the only buffer pointer that is live here, | ||
| 4399 | ;; and it was properly set in NEW-BUFFER by `epa-decrypt-region' | ||
| 4400 | ;; when it inserted the decrypted epa | ||
| 4401 | (if new-buffer (set-buffer new-buffer)))) | ||
| 4402 | |||
| 4403 | ;; If we decrypted into a new buffer, show it. | ||
| 4404 | (if new-buffer | ||
| 4405 | (display-buffer new-buffer))))) | ||
| 4406 | |||
| 4303 | ;;;; Desktop support | 4407 | ;;;; Desktop support |
| 4304 | 4408 | ||
| 4305 | (defun rmail-restore-desktop-buffer (desktop-buffer-file-name | 4409 | (defun rmail-restore-desktop-buffer (desktop-buffer-file-name |