From ba465d382d0b222fdd7b62a6c736c37ade08b8ba Mon Sep 17 00:00:00 2001 From: yamaoka Date: Mon, 13 Nov 2000 22:53:12 +0000 Subject: [PATCH] Synch with Gnus. --- lisp/ChangeLog | 131 +++++++++++++++++++++++++++++++++++++++++++++++- lisp/gnus-art.el | 93 +++++++++++++++++++++++++++++++++-- lisp/gnus-cite.el | 13 ++--- lisp/gnus-msg.el | 16 +++++- lisp/gnus-sum.el | 8 +-- lisp/message.el | 15 +++--- lisp/mm-decode.el | 11 +++-- lisp/mm-extern.el | 5 +- lisp/mm-uu.el | 17 ++++--- lisp/mml-smime.el | 17 ++++++- lisp/mml2015.el | 61 +++++++++++++++++++---- lisp/rfc2231.el | 5 +- lisp/smime.el | 24 +++++++-- texi/ChangeLog | 18 +++++++ texi/emacs-mime.texi | 26 ++++++++++ texi/gnus-ja.texi | 4 -- texi/gnus.texi | 4 -- texi/message-ja.texi | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ texi/message.texi | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ todo | 4 ++ 20 files changed, 679 insertions(+), 61 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 950c44b..4d896fc 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,9 +1,138 @@ +2000-11-13 16:09:09 ShengHuo ZHU + + * mml2015.el (mml2015-mailcrypt-decrypt): Handle quit. + (mml2015-mailcrypt-clear-decrypt): Ditto. + (mml2015-mailcrypt-verify): Ditto. + (mml2015-mailcrypt-clear-verify): Ditto. + (mml2015-gpg-verify): Ditto. + +2000-11-13 15:29:58 ShengHuo ZHU + + * smime.el (smime-openssl-program): Test the existence of openssl. + * mml-smime.el: Require mm-decode. + (mml-smime-verify-test): New function. + * mm-decode.el (mm-verify-function-alist): Use it. + +2000-11-13 09:50:29 ShengHuo ZHU + + * gnus-sum.el (gnus-summary-repair-multipart): Fix Mime-Version + anyway. + +2000-11-13 Simon Josefsson + + * mm-uu.el (mm-uu-pgp-signed-extract): Explain why clear + verification doesn't work. + +2000-11-12 23:36:45 ShengHuo ZHU + + * gnus-msg.el (gnus-inews-mark-gcc-as-read): New variable. + (gnus-inews-do-gcc): Use it. + +2000-11-12 21:35:04 ShengHuo ZHU + + * rfc2231.el (rfc2231-encode-string): Insert semi-colon and + leading space. + * mm-extern.el (mm-inline-external-body): Report error when no + access-type. + +2000-11-12 19:48:30 ShengHuo ZHU + + * gnus-sum.el (gnus-select-newsgroup): Change the error message. + +2000-11-12 11:53:18 ShengHuo ZHU + + * gnus-art.el (gnus-mime-button-menu): Use select-window. + +2000-11-12 09:47:54 ShengHuo ZHU + + * gnus-art.el (gnus-mime-display-part): Display multipart/related + as multipart/mixed. + +2000-11-12 David Edmondson + + * message.el (message-cite-prefix-regexp): moved from gnus-cite.el + and replace `.' with `\w' to allow for different syntax tables + (from Vladimir Volovich). + * message.el (message-newline-and-reformat): use + `message-cite-prefix-regexp'. + * gnus-cite.el (gnus-supercite-regexp): use + `message-cite-prefix-regexp'. + * gnus-cite.el (gnus-cite-parse): use + `message-cite-prefix-regexp'. + +2000-11-12 08:52:46 ShengHuo ZHU + + * mml2015.el (mml2015-mailcrypt-verify): Replace armors with + PGP SIGNATURE. Escape leading "-"'s. + (mml2015-mailcrypt-sign): Replace armors with PGP MESSAGE. + +2000-11-11 15:55:35 ShengHuo ZHU + + * mm-uu.el (mm-uu-type-alist): Stricter shar regexp. + +2000-11-11 Simon Josefsson + + * mml2015.el (mml2015-gpg-verify): Set "OK" security status. + + * smime.el (smime-details-buffer): New variable. + (smime-sign-region): + (smime-encrypt-region): + (smime-verify-region): + (smime-decrypt-region): Copy OpenSSL output to the buffer. + + * mml-smime.el (mml-smime-verify): Support security info. + +2000-11-10 17:11:22 ShengHuo ZHU + + * mm-decode.el (mm-verify-option): Set default to nil. + (mm-decrypt-option): Ditto. + * gnus-art.el (article-verify-x-pgp-sig): New function. + +2000-11-10 09:01:25 ShengHuo ZHU + + * gnus-art.el (gnus-mime-display-alternative): Show button if no + preferred part. + 2000-11-07 Kai Gro,A_(Bjohann * gnus-sum.el (gnus-move-split-methods): Say that `gnus-split-methods' uses file names, whereas this uses group names. (Report from Nevin Kapur) +2000-11-10 01:23:20 ShengHuo ZHU + + * mm-partial.el (mm-inline-partial): Insert MIME-Version. + +2000-11-09 17:02:50 ShengHuo ZHU + + * nnheader.el (nnheader-directory-files-is-safe): New variable. + (nnheader-directory-articles): Use it. + (nnheader-article-to-file-alist): Ditto. + +2000-11-09 16:20:37 ShengHuo ZHU + + * rfc2047.el (rfc2047-pad-base64): New function. + (rfc2047-decode): Use it. + +2000-11-09 08:53:04 ShengHuo ZHU + + * gnus-srvr.el (gnus-browse-foreign-server): Bind the original + select method. + +2000-11-08 19:58:58 ShengHuo ZHU + + * mml2015.el (mml2015-gpg-decrypt-1): + (mml2015-gpg-verify): buffer-string has no argument in Emacs. + +2000-11-08 16:37:02 ShengHuo ZHU + + * gnus-cache.el (gnus-cache-generate-nov-databases): Reopen cache. + +2000-11-08 08:38:30 ShengHuo ZHU + + * pop3.el (pop3-munge-message-separator): A message may have an + empty body. + 2000-11-07 18:02:26 ShengHuo ZHU * mm-uu.el (mm-uu-type-alist): Don't test pgp stuff. @@ -152,8 +281,6 @@ 2000-09-29 David Edmondson - One-line patch. - * message.el (message-newline-and-reformat): Typo. 2000-11-04 10:11:05 ShengHuo ZHU diff --git a/lisp/gnus-art.el b/lisp/gnus-art.el index acf82c9..031ec4a 100644 --- a/lisp/gnus-art.el +++ b/lisp/gnus-art.el @@ -1013,6 +1013,14 @@ See the manual for details." :group 'gnus-article-treat :type gnus-article-treat-custom) +(defcustom gnus-treat-x-pgp-sig 'head + "Verify X-PGP-Sig. +Valid values are nil, t, `head', `last', an integer or a predicate. +See the manual for details." + :group 'gnus-article-treat + :group 'mime-security + :type gnus-article-treat-custom) + (defvar gnus-article-encrypt-protocol-alist '(("PGP" . mml2015-self-encrypt))) @@ -1034,6 +1042,7 @@ It is a string, such as \"PGP\". If nil, ask user." (defvar gnus-treatment-function-alist '((gnus-treat-decode-article-as-default-mime-charset gnus-article-decode-article-as-default-mime-charset) + (gnus-treat-x-pgp-sig gnus-article-verify-x-pgp-sig) (gnus-treat-strip-banner gnus-article-strip-banner) (gnus-treat-strip-headers-in-body gnus-article-strip-headers-in-body) (gnus-treat-buttonize gnus-article-add-buttons) @@ -2747,6 +2756,76 @@ If variable `gnus-use-long-file-name' is non-nil, it is (expand-file-name "news" (gnus-newsgroup-directory-form newsgroup))) gnus-article-save-directory))) +(defun article-verify-x-pgp-sig () + "Verify X-PGP-Sig." + (interactive) + (let ((sig (with-current-buffer gnus-original-article-buffer + (gnus-fetch-field "X-PGP-Sig"))) + items info headers) + (when (and sig (mm-uu-pgp-signed-test)) + (with-temp-buffer + (insert-buffer gnus-original-article-buffer) + (setq items (split-string sig)) + (message-narrow-to-head) + (let ((inhibit-point-motion-hooks t) + (case-fold-search t)) + ;; Don't verify multiple headers. + (setq headers (mapconcat (lambda (header) + (concat header ": " + (mail-fetch-field header) "\n")) + (split-string (nth 1 items) ",") ""))) + (delete-region (point-min) (point-max)) + (insert "-----BEGIN PGP SIGNED MESSAGE-----\n\n") + (insert "X-Signed-Headers: " (nth 1 items) "\n") + (insert headers) + (widen) + (forward-line) + (while (not (eobp)) + (if (looking-at "^-") + (insert "- ")) + (forward-line)) + (insert "\n-----BEGIN PGP SIGNATURE-----\n") + (insert "Version: " (car items) "\n\n") + (insert (mapconcat 'identity (cddr items) "\n")) + (insert "\n-----END PGP SIGNATURE-----\n") + (let ((mm-security-handle (list (format "multipart/signed")))) + (mml2015-clean-buffer) + (let ((coding-system-for-write (or gnus-newsgroup-charset + 'iso-8859-1))) + (funcall (mml2015-clear-verify-function))) + (setq info + (or (mm-handle-multipart-ctl-parameter + mm-security-handle 'gnus-details) + (mm-handle-multipart-ctl-parameter + mm-security-handle 'gnus-info))))) + (when info + (let (buffer-read-only bface eface) + (save-restriction + (message-narrow-to-head) + (goto-char (point-max)) + (forward-line -1) + (setq bface (get-text-property (gnus-point-at-bol) 'face) + eface (get-text-property (1- (gnus-point-at-eol)) 'face)) + (message-remove-header "X-Gnus-PGP-Verify") + (if (re-search-forward "^X-PGP-Sig:" nil t) + (forward-line) + (goto-char (point-max))) + (narrow-to-region (point) (point)) + (insert "X-Gnus-PGP-Verify: " info "\n") + (goto-char (point-min)) + (forward-line) + (while (not (eobp)) + (if (not (looking-at "^[ \t]")) + (insert " ")) + (forward-line)) + ;; Do highlighting. + (goto-char (point-min)) + (when (looking-at "\\([^:]+\\): *") + (put-text-property (match-beginning 1) (1+ (match-end 1)) + 'face bface) + (put-text-property (match-end 0) (point-max) + 'face eface)))))))) + (eval-and-compile (mapcar (lambda (func) @@ -2767,6 +2846,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is (call-interactively ',afunc) (apply ',afunc args)))))))) '(article-hide-headers + article-verify-x-pgp-sig article-hide-boring-headers article-toggle-headers article-treat-overstrike @@ -3331,9 +3411,9 @@ value of the variable `gnus-show-mime' is non-nil." (defun gnus-mime-button-menu (event) "Construct a context-sensitive menu of MIME commands." (interactive "e") - (save-excursion + (save-window-excursion (let ((pos (event-start event))) - (set-buffer (window-buffer (posn-window pos))) + (select-window (posn-window pos)) (goto-char (posn-point pos)) (gnus-article-check-buffer) (let ((response (x-popup-menu @@ -3855,8 +3935,11 @@ In no internal viewer is available, use an external viewer." (not gnus-mime-display-multipart-as-mixed)) ;;;!!!We should find the start part, but we just default ;;;!!!to the first part. - (gnus-mime-display-part (cadr handle))) - ;; Other multiparts are handled like multipart/mixed. + ;;(gnus-mime-display-part (cadr handle)) + ;;;!!! Most multipart/related is an HTML message plus images. + ;;;!!! Unfortunately we are unable to let W3 display those + ;;;!!! included images, so we just display it as a mixed multipart. + (gnus-mime-display-mixed (cdr handle))) ((equal (car handle) "multipart/signed") (or (memq 'signed gnus-article-wash-types) (push 'signed gnus-article-wash-types)) @@ -3867,6 +3950,7 @@ In no internal viewer is available, use an external viewer." (push 'encrypted gnus-article-wash-types)) (gnus-insert-mime-security-button handle) (gnus-mime-display-mixed (cdr handle))) + ;; Other multiparts are handled like multipart/mixed. (t (gnus-mime-display-mixed (cdr handle))))) @@ -3978,6 +4062,7 @@ In no internal viewer is available, use an external viewer." (unless (setq not-pref (cadr (member preferred ihandles))) (setq not-pref (car ihandles))) (when (or ibegend + (not preferred) (not (gnus-unbuttonized-mime-type-p "multipart/alternative"))) (gnus-add-text-properties diff --git a/lisp/gnus-cite.el b/lisp/gnus-cite.el index a2dbe97..925acb3 100644 --- a/lisp/gnus-cite.el +++ b/lisp/gnus-cite.el @@ -26,6 +26,7 @@ (require 'gnus) (require 'gnus-art) (require 'gnus-range) +(require 'message) ; for message-cite-prefix-regexp (eval-when-compile (require 'static)) @@ -76,19 +77,13 @@ Set it to nil to parse all articles." :type '(choice (const :tag "all" nil) integer)) -(defcustom gnus-cite-prefix-regexp - "^[]>»|:}+ ]*[]>»|:}+]\\(.*>»\\)?\\|^.*>" - "*Regexp matching the longest possible citation prefix on a line." - :group 'gnus-cite - :type 'regexp) - (defcustom gnus-cite-max-prefix 20 "Maximum possible length for a citation prefix." :group 'gnus-cite :type 'integer) (defcustom gnus-supercite-regexp - (concat "^\\(" gnus-cite-prefix-regexp "\\)? *" + (concat "^\\(" message-cite-prefix-regexp "\\)? *" ">>>>> +\"\\([^\"\n]+\\)\" +==") "*Regexp matching normal Supercite attribution lines. The first grouping must match prefixes added by other packages." @@ -308,7 +303,7 @@ Attribution lines are highlighted with the same face as the corresponding citation merged with `gnus-cite-attribution-face'. Text is considered cited if at least `gnus-cite-minimum-match-count' -lines matches `gnus-cite-prefix-regexp' with the same prefix. +lines matches `message-cite-prefix-regexp' with the same prefix. Lines matching `gnus-cite-attribution-suffix' and perhaps `gnus-cite-attribution-prefix' are considered attribution lines." @@ -681,7 +676,7 @@ See also the documentation for `gnus-article-highlight-citation'." ;; Ignore very long prefixes. (when (> end (+ (point) gnus-cite-max-prefix)) (setq end (+ (point) gnus-cite-max-prefix))) - (while (re-search-forward gnus-cite-prefix-regexp (1- end) t) + (while (re-search-forward message-cite-prefix-regexp (1- end) t) ;; Each prefix. (setq end (match-end 0) prefix (buffer-substring begin end)) diff --git a/lisp/gnus-msg.el b/lisp/gnus-msg.el index 0f4b95f..7ab899a 100644 --- a/lisp/gnus-msg.el +++ b/lisp/gnus-msg.el @@ -106,6 +106,9 @@ the second with the current group name.") (defvar gnus-posting-styles nil "*Alist of styles to use when posting.") +(defvar gnus-inews-mark-gcc-as-read nil + "If non-nil, automatically mark Gcc articles as read.") + (defcustom gnus-group-posting-charset-alist '(("^\\(no\\|fr\\|dk\\)\\.[^,]*\\(,[ \t\n]*\\(no\\|fr\\|dk\\)\\.[^,]*\\)*$" iso-8859-1 (iso-8859-1)) ("^\\(fido7\\|relcom\\)\\.[^,]*\\(,[ \t\n]*\\(fido7\\|relcom\\)\\.[^,]*\\)*$" koi8-r (koi8-r)) @@ -1158,7 +1161,7 @@ this is a reply." (let ((gcc (or gcc (mail-fetch-field "gcc" nil t))) (coding-system-for-write 'raw-text) (output-coding-system 'raw-text) - groups group method) + groups group method group-art) (when gcc (message-remove-header "gcc") (widen) @@ -1179,10 +1182,19 @@ this is a reply." (concat "^" (regexp-quote mail-header-separator) "$") nil t) (replace-match "" t t )) - (unless (gnus-request-accept-article group method t t) + (unless (setq group-art + (gnus-request-accept-article group method t t)) (gnus-message 1 "Couldn't store article in group %s: %s" group (gnus-status-message method)) (sit-for 2)) + (when (and group-art gnus-inews-mark-gcc-as-read) + (let ((active (gnus-active group))) + (when active + (if (< (cdr active) (cdr group-art)) + (gnus-set-active group (cons (car active) + (cdr group-art)))) + (gnus-group-make-articles-read group + (list (cdr group-art)))))) (kill-buffer (current-buffer)))))))))) (defun gnus-inews-insert-gcc () diff --git a/lisp/gnus-sum.el b/lisp/gnus-sum.el index 7d0f16a..7e36abb 100644 --- a/lisp/gnus-sum.el +++ b/lisp/gnus-sum.el @@ -1590,6 +1590,7 @@ increase the score of each group you read." "v" gnus-summary-verbose-headers "m" gnus-summary-toggle-mime "H" gnus-article-strip-headers-in-body + "p" gnus-article-verify-x-pgp-sig "d" gnus-article-treat-dumbquotes "s" gnus-smiley-display) @@ -1760,6 +1761,7 @@ increase the score of each group you read." ["Verbose header" gnus-summary-verbose-headers t] ["Toggle header" gnus-summary-toggle-header t] ["Toggle smileys" gnus-smiley-display t] + ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t] ["HZ" gnus-article-decode-HZ t]) ("Output" ["Save in default format" gnus-summary-save-article t] @@ -4197,7 +4199,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." (progn ; Or we bug out. (when (equal major-mode 'gnus-summary-mode) (kill-buffer (current-buffer))) - (error "Couldn't request group %s: %s" + (error "Couldn't activate group %s: %s" group (gnus-status-message group)))) (unless (gnus-request-group group t) @@ -9986,17 +9988,17 @@ treated as multipart/mixed." (interactive (list (gnus-summary-article-number))) (gnus-with-article article (message-narrow-to-head) + (message-remove-header "Mime-Version") (goto-char (point-max)) + (insert "Mime-Version: 1.0\n") (widen) (when (search-forward "\n--" nil t) (let ((separator (buffer-substring (point) (gnus-point-at-eol)))) (message-narrow-to-head) - (message-remove-header "Mime-Version") (message-remove-header "Content-Type") (goto-char (point-max)) (insert (format "Content-Type: multipart/mixed; boundary=\"%s\"\n" separator)) - (insert "Mime-Version: 1.0\n") (widen)))) (let (gnus-mark-article-hook) (gnus-summary-select-article t t nil article))) diff --git a/lisp/message.el b/lisp/message.el index 2669b15..842f32c 100644 --- a/lisp/message.el +++ b/lisp/message.el @@ -436,6 +436,12 @@ The provided functions are: :group 'message-insertion :type 'regexp) +(defcustom message-cite-prefix-regexp + "^[]>»|:}+ ]*[]>»|:}+]\\(\\w*>»\\)?\\|^\\w*>" + "*Regexp matching the longest possible citation prefix on a line." + :group 'message-insertion + :type 'regexp) + (defcustom message-cancel-message "I am canceling my own article.\n" "Message to be inserted in the cancel message." :group 'message-interface @@ -2120,21 +2126,18 @@ With the prefix argument FORCE, insert the header anyway." (defun message-newline-and-reformat () "Insert four newlines, and then reformat if inside quoted text." (interactive) - (let ((prefix "[]>»|:}+ \t]*") - (supercite-thing "[-._a-zA-Z0-9]*[>]+[ \t]*") - quoted point) + (let (quoted point) (unless (bolp) (save-excursion (beginning-of-line) - (when (looking-at (concat prefix "\\|" - supercite-thing)) + (when (looking-at message-cite-prefix-regexp) (setq quoted (match-string 0)))) (insert "\n")) (setq point (point)) (insert "\n\n\n") (delete-region (point) (re-search-forward "[ \t]*")) (when quoted - (insert quoted)) + (insert quoted " ")) (fill-paragraph nil) (goto-char point) (forward-line 1))) diff --git a/lisp/mm-decode.el b/lisp/mm-decode.el index d2f9257..4020aa9 100644 --- a/lisp/mm-decode.el +++ b/lisp/mm-decode.el @@ -239,13 +239,16 @@ to: (autoload 'mml2015-verify "mml2015") (autoload 'mml2015-verify-test "mml2015") (autoload 'mml-smime-verify "mml-smime") +(autoload 'mml-smime-verify-test "mml-smime") (defvar mm-verify-function-alist '(("application/pgp-signature" mml2015-verify "PGP" mml2015-verify-test) - ("application/pkcs7-signature" mml-smime-verify "S/MIME" nil) - ("application/x-pkcs7-signature" mml-smime-verify "S/MIME" nil))) + ("application/pkcs7-signature" mml-smime-verify "S/MIME" + mml-smime-verify-test) + ("application/x-pkcs7-signature" mml-smime-verify "S/MIME" + mml-smime-verify-test))) -(defcustom mm-verify-option 'known +(defcustom mm-verify-option nil "Option of verifying signed parts. `never', not verify; `always', always verify; `known', only verify known protocols. Otherwise, ask user." @@ -261,7 +264,7 @@ to: (defvar mm-decrypt-function-alist '(("application/pgp-encrypted" mml2015-decrypt "PGP" mml2015-decrypt-test))) -(defcustom mm-decrypt-option 'known +(defcustom mm-decrypt-option nil "Option of decrypting signed parts. `never', not decrypt; `always', always decrypt; `known', only decrypt known protocols. Otherwise, ask user." diff --git a/lisp/mm-extern.el b/lisp/mm-extern.el index f2b20f9..e9c07fb 100644 --- a/lisp/mm-extern.el +++ b/lisp/mm-extern.el @@ -116,7 +116,10 @@ the entire message. If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing." (let* ((access-type (cdr (assq 'access-type (cdr (mm-handle-type handle))))) - (func (cdr (assq (intern (downcase access-type)) + (func (cdr (assq (intern + (downcase + (or access-type + (error "Couldn't find access type.")))) mm-extern-function-alist))) gnus-displaying-mime buf handles) diff --git a/lisp/mm-uu.el b/lisp/mm-uu.el index 9e9c37f..b1b6102 100644 --- a/lisp/mm-uu.el +++ b/lisp/mm-uu.el @@ -85,7 +85,7 @@ This can be either \"inline\" or \"attachment\".") mm-uu-binhex-filename) (shar "^#! */bin/sh" - "^exit 0\\|^$" + "^exit 0$" mm-uu-shar-extract) (forward ;;; Thanks to Edward J. Sabol and @@ -262,11 +262,16 @@ To disable dissecting shar codes, for instance, add (mm-set-handle-multipart-parameter mm-security-handle 'protocol "application/pgp-signature") (with-current-buffer buf - (when (mm-uu-pgp-signed-test) - (mml2015-clean-buffer) - (let ((coding-system-for-write (or gnus-newsgroup-charset - 'iso-8859-1))) - (funcall (mml2015-clear-verify-function)))) + (if (mm-uu-pgp-signed-test) + (progn + (mml2015-clean-buffer) + (let ((coding-system-for-write (or gnus-newsgroup-charset + 'iso-8859-1))) + (funcall (mml2015-clear-verify-function)))) + (when (and mml2015-use (null (mml2015-clear-verify-function))) + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-details + (format "Clear verification not supported by `%s'.\n" mml2015-use)))) (goto-char (point-min)) (if (search-forward "\n\n" nil t) (delete-region (point-min) (point))) diff --git a/lisp/mml-smime.el b/lisp/mml-smime.el index 427c538..62e27d6 100644 --- a/lisp/mml-smime.el +++ b/lisp/mml-smime.el @@ -28,6 +28,7 @@ ;;; Code: (require 'smime) +(require 'mm-decode) (defun mml-smime-verify (handle ctl) (with-current-buffer (mm-handle-multipart-original-buffer ctl) @@ -40,9 +41,23 @@ (mm-handle-multipart-ctl-parameter ctl 'micalg))) (insert (format "boundary=\"%s\"\n\n" (mm-handle-multipart-ctl-parameter ctl 'boundary))) - (smime-verify-buffer) + (when (get-buffer smime-details-buffer) + (kill-buffer smime-details-buffer)) + (if (smime-verify-buffer) + (progn + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-info "OK") + (kill-buffer smime-details-buffer)) + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-info "Failed") + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-details (with-current-buffer smime-details-buffer + (buffer-string)))) handle)) +(defun mml-smime-verify-test (handle ctl) + smime-openssl-program) + (provide 'mml-smime) ;;; mml-smime.el ends here diff --git a/lisp/mml2015.el b/lisp/mml2015.el index a571748..154677f 100644 --- a/lisp/mml2015.el +++ b/lisp/mml2015.el @@ -93,6 +93,10 @@ (error (mm-set-handle-multipart-parameter mm-security-handle 'gnus-details (cadr err)) + nil) + (quit + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-details "Quit.") nil))) (unless (car result) (mm-set-handle-multipart-parameter @@ -114,6 +118,10 @@ (error (mm-set-handle-multipart-parameter mm-security-handle 'gnus-details (cadr err)) + nil) + (quit + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-details "Quit.") nil))) (if (car result) (mm-set-handle-multipart-parameter @@ -143,19 +151,36 @@ (or (mml2015-fix-micalg (mail-content-type-get ctl 'micalg)) "SHA1"))) - (insert part "\n") - (goto-char (point-max)) + (save-restriction + (narrow-to-region (point) (point)) + (insert part "\n") + (goto-char (point-min)) + (while (not (eobp)) + (if (looking-at "^-") + (insert "- ")) + (forward-line))) (unless (setq part (mm-find-part-by-type (cdr handle) "application/pgp-signature" nil t)) (mm-set-handle-multipart-parameter mm-security-handle 'gnus-info "Corrupted") (throw 'error handle)) - (mm-insert-part part) + (save-restriction + (narrow-to-region (point) (point)) + (mm-insert-part part) + (goto-char (point-min)) + (if (re-search-forward "^-----\\([^-]+\\)-----$" nil t) + (replace-match "BEGIN PGP SIGNATURE" t t nil 1)) + (if (re-search-forward "^-----\\([^-]+\\)-----$" nil t) + (replace-match "END PGP SIGNATURE" t t nil 1))) (unless (condition-case err (funcall mml2015-verify-function) (error (mm-set-handle-multipart-parameter mm-security-handle 'gnus-details (cadr err)) + nil) + (quit + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-details "Quit.") nil)) (mm-set-handle-multipart-parameter mm-security-handle 'gnus-info "Failed") @@ -170,6 +195,10 @@ (error (mm-set-handle-multipart-parameter mm-security-handle 'gnus-details (cadr err)) + nil) + (quit + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-details "Quit.") nil)) (mm-set-handle-multipart-parameter mm-security-handle 'gnus-info "OK") @@ -181,11 +210,9 @@ nil nil nil nil) (let ((boundary (funcall mml-boundary-function (incf mml-multipart-number))) - (scheme-alist (funcall (or mc-default-scheme - (cdr (car mc-schemes))))) hash) (goto-char (point-min)) - (unless (re-search-forward (cdr (assq 'signed-begin-line scheme-alist))) + (unless (re-search-forward "^-----BEGIN PGP SIGNED MESSAGE-----\r?$" nil t) (error "Cannot find signed begin line." )) (goto-char (match-beginning 0)) (forward-line 1) @@ -202,11 +229,14 @@ (downcase hash))) (insert (format "\n--%s\n" boundary)) (goto-char (point-max)) - (unless (re-search-backward (cdr (assq 'signed-end-line scheme-alist))) + (unless (re-search-backward "^-----END PGP \\(SIGNATURE\\)-----\r?$" nil t) (error "Cannot find signature part." )) + (replace-match "MESSAGE" t t nil 1) (goto-char (match-beginning 0)) - (unless (re-search-backward "^-+BEGIN" nil t) + (unless (re-search-backward "^-----BEGIN PGP \\(SIGNATURE\\)-----\r?$" + nil t) (error "Cannot find signature part." )) + (replace-match "MESSAGE" t t nil 1) (goto-char (match-beginning 0)) (insert (format "--%s\n" boundary)) (insert "Content-Type: application/pgp-signature\n\n") @@ -311,14 +341,25 @@ mm-security-handle 'gnus-info "Corrupted") (throw 'error handle)) (mm-insert-part part) - (unless (gpg-verify message signature mml2015-result-buffer) + (unless (condition-case err + (gpg-verify message signature mml2015-result-buffer) + (error + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-details (cadr err)) + nil) + (quit + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-details "Quit.") + nil)) (mm-set-handle-multipart-parameter mm-security-handle 'gnus-details (with-current-buffer mml2015-result-buffer (buffer-string))) (mm-set-handle-multipart-parameter mm-security-handle 'gnus-info "Failed") - (throw 'error handle)))) + (throw 'error handle))) + (mm-set-handle-multipart-parameter + mm-security-handle 'gnus-info "OK")) handle))) (defun mml2015-gpg-sign (cont) diff --git a/lisp/rfc2231.el b/lisp/rfc2231.el index 65367eb..d8d381b 100644 --- a/lisp/rfc2231.el +++ b/lisp/rfc2231.el @@ -186,7 +186,7 @@ These look like \"us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A\"." (goto-char (point-min)) (while (not (eobp)) (when (> (current-column) 60) - (insert "\n") + (insert ";\n") (setq broken t)) (if (or (not (memq (following-char) ascii)) (memq (following-char) control) @@ -203,7 +203,8 @@ These look like \"us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A\"." (if (not broken) (insert param "*=") (while (not (eobp)) - (insert param "*" (format "%d" (incf num)) "*=") + (insert (if (>= num 0) " " "\n ") + param "*" (format "%d" (incf num)) "*=") (forward-line 1)))) (spacep (goto-char (point-min)) diff --git a/lisp/smime.el b/lisp/smime.el index 0d3bbe9..530ed8d 100644 --- a/lisp/smime.el +++ b/lisp/smime.el @@ -26,9 +26,9 @@ ;; This library perform S/MIME operations from within Emacs. ;; ;; Functions for fetching certificates from public repositories are -;; NOT provided (yet). +;; provided, currently only from DNS. LDAP support (via EUDC) is planned. ;; -;; It uses OpenSSL (tested with version 0.9.5a) for signing, +;; It uses OpenSSL (tested with version 0.9.5a and 0.9.6) for signing, ;; encryption and decryption. ;; ;; Some general knowledge of S/MIME, X.509, PKCS#12, PEM etc is @@ -140,7 +140,11 @@ manually." :type 'directory :group 'smime) -(defcustom smime-openssl-program "openssl" +(defcustom smime-openssl-program + (and (condition-case () + (eq 0 (call-process "openssl" nil nil nil "version")) + (error nil)) + "openssl") "Name of OpenSSL binary." :type 'string :group 'smime) @@ -152,6 +156,8 @@ If nil, use system defaults." string) :group 'dig) +(defvar smime-details-buffer "*S/MIME OpenSSL output*") + ;; OpenSSL wrappers. (defun smime-call-openssl-region (b e buf &rest args) @@ -179,6 +185,9 @@ private key and certificate." (when (looking-at "^MIME-Version: 1.0$") (delete-region (point) (progn (forward-line 1) (point)))) t) + (with-current-buffer (get-buffer-create smime-details-buffer) + (goto-char (point-max)) + (insert-buffer buffer)) (kill-buffer buffer)))) (defun smime-encrypt-region (b e certfiles) @@ -195,6 +204,9 @@ is expected to contain of a PEM encoded certificate." (when (looking-at "^MIME-Version: 1.0$") (delete-region (point) (progn (forward-line 1) (point)))) t) + (with-current-buffer (get-buffer-create smime-details-buffer) + (goto-char (point-max)) + (insert-buffer buffer)) (kill-buffer buffer)))) ;; Sign+encrypt buffer @@ -240,6 +252,9 @@ nil." (message "S/MIME message verified succesfully.") (message "S/MIME message NOT verified successfully.") nil) + (with-current-buffer (get-buffer-create smime-details-buffer) + (goto-char (point-max)) + (insert-buffer buffer)) (kill-buffer buffer)))) (defun smime-decrypt-region (b e keyfile) @@ -249,6 +264,9 @@ nil." "-recip" keyfile) ) + (with-current-buffer (get-buffer-create smime-details-buffer) + (goto-char (point-max)) + (insert-buffer buffer)) (kill-buffer buffer))) ;; Verify+Decrypt buffer diff --git a/texi/ChangeLog b/texi/ChangeLog index 95727db..f94f32a 100644 --- a/texi/ChangeLog +++ b/texi/ChangeLog @@ -1,3 +1,21 @@ +2000-11-12 Florian Weimer + + * message.texi (Security): Fixed typo, change "PGP" to "OpenPGP". + +2000-11-12 David Edmondson + + * gnus.texi: remove `gnus-cite-prefix-regexp'. + + * message.texi (Insertion): move `gnus-cite-prefix-regexp' from + gnus.texi to here and rename to `message-cite-prefix-regexp'. + +2000-11-11 Simon Josefsson + + * message.texi (Security): Add. + + * emacs-mime.texi (MML Definition): Add sign, encrypt, keyfile and + certfile. + 2000-11-07 Kai Gro,A_(Bjohann * gnus.texi (Mail Group Commands): `gnus-move-split-methods' uses diff --git a/texi/emacs-mime.texi b/texi/emacs-mime.texi index c8a2f46..a0c96b4 100644 --- a/texi/emacs-mime.texi +++ b/texi/emacs-mime.texi @@ -1067,6 +1067,14 @@ RFC822 date when the part was read (@code{Content-Disposition}). @item size The size (in octets) of the part (@code{Content-Disposition}). +@item sign +What technology to sign this MML part with (@code{smime} or +@code{pgpmime}) + +@item encrypt +What technology to encrypt this MML part with (@code{smime} or +@code{pgpmime}) + @end table Parameters for @samp{application/octet-stream}: @@ -1098,6 +1106,24 @@ Valid values are @samp{read} and @samp{read-write} @end table +Parameters for @samp{sign=smime}: + +@table @samp + +@item keyfile +File containing key and certificate for signer. + +@end table + +Parameters for @samp{encrypt=smime}: + +@table @samp + +@item certfile +File containing certificate for recipient. + +@end table + @node Advanced MML Example @section Advanced MML Example diff --git a/texi/gnus-ja.texi b/texi/gnus-ja.texi index 505ad94..1d91685 100644 --- a/texi/gnus-ja.texi +++ b/texi/gnus-ja.texi @@ -6870,10 +6870,6 @@ Gnus $B$O%U%!%$%k$r1\Mw$9$k$N$r7hDj$9$k$N$K(B@dfn{$B5,B'JQ?t(B}$B$rMQ$$$^$9 $B5-;v$NBg$-$5$,$3$NJQ?t(B ($B%G%#%U%)%k%H$G$O(B 25000) $B$h$jBg$-$$5-;v$O!"0zMQ%O(B $B%$%i%$%H$O9T$o$l$^$;$s!#(B -@item gnus-cite-prefix-regexp -@vindex gnus-cite-prefix-regexp -$B$"$k9T$,$r;H$&$+!#(B @@ -466,6 +467,10 @@ u} (@code{undo}) $B$,;HMQ2DG=$G!"Bg>fIW$G$"$k$H8@$&;v$r3P$($F$*$$$F2<$5$$!#(B $B$+$l$^$9!#=i4|CM$O(B @samp{.} $B$G!"$3$l$OA4$F$N%X%C%@!<$,$O$=$NA0$K(B @samp{-- } $B$N(B3$BJ8;z$@$1$N9T$,$"$k$Y$ @c language (@pxref{Composing, , Composing, emacs-mime, The Emacs MIME @c Manual}). +@c @node Security +@c @section Security +@c @cindex Security +@c @cindex S/MIME +@c @cindex PGP/MIME +@c @cindex sign +@c @cindex encrypt + +@c Using the MML language, Message is able to create digitally signed and +@c digitally encrypted messages. Message (or rather MML) currently support +@c PGP/MIME and S/MIME. Instructing MML to perform security operations on +@c a MIME part is done using the @code{M-m s} key map for signing and the +@c @code{M-m c} key map for encryption, as follows. + +@c @table @kbd + +@c @item M-m s s +@c @kindex M-m s s +@c @findex mml-secure-sign-smime + +@c Digitally sign current MIME part using S/MIME. + +@c @item M-m s p +@c @kindex M-m s p +@c @findex mml-secure-sign-pgp + +@c Digitally sign current MIME part using PGP/MIME. + +@c @item M-m c s +@c @kindex M-m c s +@c @findex mml-secure-encrypt-smime + +@c Digitally encrypt current MIME part using S/MIME. + +@c @item M-m c p +@c @kindex M-m c p +@c @findex mml-secure-encrypt-pgpmime + +@c Digitally encrypt current MIME part using PGP/MIME. + +@c @end table + +@c These commands do not immediately sign or encrypt the message, they +@c merely insert proper MML tags to instruct the MML engine to perform that +@c operation when the message is actually sent. They may perform other +@c operations too, such as locating and retrieving a S/MIME certificate of +@c the person you wish to send encrypted mail to. + +@c Since signing and especially encryption often is used when sensitive +@c information is sent, you may want to have some way to ensure that your +@c mail is actually signed or encrypted. After invoking the above +@c sign/encrypt commands, it is possible to preview the raw article by +@c using @code{C-u M-m P} (@code{mml-preview}). Then you can verify that +@c your long rant about what your ex-significant other or whomever actually +@c did with that funny looking person at that strange party the other +@c night, actually will be sent encrypted. + +@c @emph{Note!} Neither PGP/MIME nor S/MIME encrypt/signs RFC822 headers. +@c They only operate on the MIME object. Keep this in mind before sending +@c mail with a sensitive Subject line. + +@c Actually using the security commands above is not very difficult. At +@c least not compared with making sure all involved programs talk with each +@c other properly. Thus, we now describe what external libraries or +@c programs are required to make things work, and some small general hints. + +@c @subsection Using S/MIME + +@c @emph{Note!} This section assume you have a basic familiarity with +@c modern cryptography, S/MIME, various PKCS standards, OpenSSL and so on. + +@c The S/MIME support in Message (and MML) require OpenSSL. OpenSSL +@c perform the actual S/MIME sign/encrypt operations. OpenSSL can be found +@c at @code{http://www.openssl.org/}. OpenSSL 0.9.5a and later should +@c work. However, version 0.9.5a insert a spurious CR character into MIME +@c separators so you may wish to avoid it if you would like to avoid being +@c regarded as someone who send strange mail. (Although by sending S/MIME +@c messages you've probably already lost that contest.) + +@c To be able to send encrypted mail, a personal certificate is not +@c required. Message (MML) need a certificate for the person to whom you +@c wish to communicate with though. You're asked for this when you type +@c @code{M-m c s}. Currently there are two ways to retrieve this +@c certificate, from a local file or from DNS. If you chose a local file, +@c it need to contain a X.509 certificate in PEM format. If you chose DNS, +@c you're asked for the domain name where the certificate is stored, the +@c default is a good guess. To my belief, Message (MML) is the first mail +@c agent in the world to support retrieving S/MIME certificates from DNS, +@c so you're not likely to find very many certificates out there. At least +@c there should be one, stored at the domain @code{simon.josefsson.org}. +@c LDAP is a more popular method of distributing certificates, support for +@c it is planned. (Meanwhile, you can use @code{ldapsearch} from the +@c command line to retrieve a certificate into a file and use it.) + +@c As for signing messages, OpenSSL can't perform signing operations +@c without some kind of configuration. Especially, you need to tell it +@c where your private key and your certificate is stored. MML uses an +@c Emacs interface to OpenSSL, aptly named @code{smime.el}, and it contain +@c a @code{custom} group used for this configuration. So, try @code{M-x +@c customize-group RET smime RET} and look around. + +@c Currently there is no support for talking to a CA (or RA) to create your +@c own certificate. None is planned either. You need to do this manually +@c with OpenSSL or using some other program. I used Netscape and got a +@c free S/MIME certificate from one of the big CA's on the net. Netscape +@c is able to export your private key and certificate in PKCS #12 format. +@c Use OpenSSL to convert this into a plain X.509 certificate in PEM format +@c as follows. + +@c @example +@c $ openssl pkcs12 -in ns.p12 -clcerts -nodes > key+cert.pem +@c @end example + +@c The @code{key+cert.pem} file should be pointed to from the +@c @code{smime-keys} variable. You should now be able to send signed mail. + +@c @emph{Note!} Your private key is store unencrypted in the file, so take +@c care in handling it. + +@c @subsection Using PGP/MIME + +@c PGP/MIME require an external OpenPGP implementation, such as GNU Privacy +@c Guard (@code{http://www.gnupg.org/}. It also require a Emacs interface +@c to it, such as Mailcrypt (available from +@c @code{http://www.nb.net/~lbudney/linux/software/mailcrypt.html}) or +@c Florian Weimer's @code{gpg.el}. + +@c Creating your own OpenPGP key is described in detail in the +@c documentation of your OpenPGP implementation, so we refer to it. @node Various Commands @section $B$$$m$$$m$JL?Na(B diff --git a/texi/message.texi b/texi/message.texi index fb42b8b..178b867 100644 --- a/texi/message.texi +++ b/texi/message.texi @@ -324,6 +324,7 @@ will be removed before popping up the buffer. The default is * Movement:: Moving around in message buffers. * Insertion:: Inserting things into message buffers. * MIME:: @sc{mime} considerations. +* Security:: Signing and encrypting messages. * Various Commands:: Various things. * Sending:: Actually sending the message. * Mail Aliases:: How to use mail aliases. @@ -466,6 +467,10 @@ All headers that match this regexp will be removed from yanked messages. The default is @samp{.}, which means that all headers will be removed. +@item message-cite-prefix-regexp +@vindex message-cite-prefix-regexp +Regexp matching the longest possible citation prefix on a line. + @item message-citation-line-function @vindex message-citation-line-function Function called to insert the citation line. The default is @@ -575,6 +580,135 @@ You can also create arbitrarily complex multiparts using the MML language (@pxref{Composing, , Composing, emacs-mime, The Emacs MIME Manual}). +@node Security +@section Security +@cindex Security +@cindex S/MIME +@cindex PGP/MIME +@cindex sign +@cindex encrypt + +Using the MML language, Message is able to create digitally signed and +digitally encrypted messages. Message (or rather MML) currently support +PGP/MIME and S/MIME. Instructing MML to perform security operations on +a MIME part is done using the @code{M-m s} key map for signing and the +@code{M-m c} key map for encryption, as follows. + +@table @kbd + +@item M-m s s +@kindex M-m s s +@findex mml-secure-sign-smime + +Digitally sign current MIME part using S/MIME. + +@item M-m s p +@kindex M-m s p +@findex mml-secure-sign-pgp + +Digitally sign current MIME part using PGP/MIME. + +@item M-m c s +@kindex M-m c s +@findex mml-secure-encrypt-smime + +Digitally encrypt current MIME part using S/MIME. + +@item M-m c p +@kindex M-m c p +@findex mml-secure-encrypt-pgpmime + +Digitally encrypt current MIME part using PGP/MIME. + +@end table + +These commands do not immediately sign or encrypt the message, they +merely insert proper MML tags to instruct the MML engine to perform that +operation when the message is actually sent. They may perform other +operations too, such as locating and retrieving a S/MIME certificate of +the person you wish to send encrypted mail to. + +Since signing and especially encryption often is used when sensitive +information is sent, you may want to have some way to ensure that your +mail is actually signed or encrypted. After invoking the above +sign/encrypt commands, it is possible to preview the raw article by +using @code{C-u M-m P} (@code{mml-preview}). Then you can verify that +your long rant about what your ex-significant other or whomever actually +did with that funny looking person at that strange party the other +night, actually will be sent encrypted. + +@emph{Note!} Neither PGP/MIME nor S/MIME encrypt/signs RFC822 headers. +They only operate on the MIME object. Keep this in mind before sending +mail with a sensitive Subject line. + +Actually using the security commands above is not very difficult. At +least not compared with making sure all involved programs talk with each +other properly. Thus, we now describe what external libraries or +programs are required to make things work, and some small general hints. + +@subsection Using S/MIME + +@emph{Note!} This section assume you have a basic familiarity with +modern cryptography, S/MIME, various PKCS standards, OpenSSL and so on. + +The S/MIME support in Message (and MML) require OpenSSL. OpenSSL +perform the actual S/MIME sign/encrypt operations. OpenSSL can be found +at @code{http://www.openssl.org/}. OpenSSL 0.9.5a and later should +work. However, version 0.9.5a insert a spurious CR character into MIME +separators so you may wish to avoid it if you would like to avoid being +regarded as someone who send strange mail. (Although by sending S/MIME +messages you've probably already lost that contest.) + +To be able to send encrypted mail, a personal certificate is not +required. Message (MML) need a certificate for the person to whom you +wish to communicate with though. You're asked for this when you type +@code{M-m c s}. Currently there are two ways to retrieve this +certificate, from a local file or from DNS. If you chose a local file, +it need to contain a X.509 certificate in PEM format. If you chose DNS, +you're asked for the domain name where the certificate is stored, the +default is a good guess. To my belief, Message (MML) is the first mail +agent in the world to support retrieving S/MIME certificates from DNS, +so you're not likely to find very many certificates out there. At least +there should be one, stored at the domain @code{simon.josefsson.org}. +LDAP is a more popular method of distributing certificates, support for +it is planned. (Meanwhile, you can use @code{ldapsearch} from the +command line to retrieve a certificate into a file and use it.) + +As for signing messages, OpenSSL can't perform signing operations +without some kind of configuration. Especially, you need to tell it +where your private key and your certificate is stored. MML uses an +Emacs interface to OpenSSL, aptly named @code{smime.el}, and it contain +a @code{custom} group used for this configuration. So, try @code{M-x +customize-group RET smime RET} and look around. + +Currently there is no support for talking to a CA (or RA) to create your +own certificate. None is planned either. You need to do this manually +with OpenSSL or using some other program. I used Netscape and got a +free S/MIME certificate from one of the big CA's on the net. Netscape +is able to export your private key and certificate in PKCS #12 format. +Use OpenSSL to convert this into a plain X.509 certificate in PEM format +as follows. + +@example +$ openssl pkcs12 -in ns.p12 -clcerts -nodes > key+cert.pem +@end example + +The @code{key+cert.pem} file should be pointed to from the +@code{smime-keys} variable. You should now be able to send signed mail. + +@emph{Note!} Your private key is store unencrypted in the file, so take +care in handling it. + +@subsection Using PGP/MIME + +PGP/MIME require an external OpenPGP implementation, such as GNU Privacy +Guard (@code{http://www.gnupg.org/}. It also require a Emacs interface +to it, such as Mailcrypt (available from +@code{http://www.nb.net/~lbudney/linux/software/mailcrypt.html}) or +Florian Weimer's @code{gpg.el}. + +Creating your own OpenPGP key is described in detail in the +documentation of your OpenPGP implementation, so we refer to it. @node Various Commands @section Various Commands diff --git a/todo b/todo index f3243de..3aded8c 100644 --- a/todo +++ b/todo @@ -1,6 +1,8 @@ ;; Also know as the "wish list". Some are done. For the others, no ;; promise when to be implemented. +* Emphasis delimiters show when `W W c'. + * Parsing of the common list confirmation requests so that Gnus can prepare the response with a single command. Including LISTSERV periodic ping messages and the like. @@ -679,6 +681,8 @@ exceeding lisp nesting on huge groups. * a way to tick/mark as read Gcc'd articles. + [done, (setq gnus-inews-mark-gcc-as-read t)] + * a way to say that all groups within a specific topic comes from a particular server? Hm. -- 1.7.10.4