(article-verify-x-pgp-sig): Autoload "mm-uu".
[elisp/gnus.git-] / lisp / gnus-art.el
index acf82c9..89fc99f 100644 (file)
@@ -1013,6 +1013,14 @@ See the manual for details."
   :group 'gnus-article-treat
   :type gnus-article-treat-custom)
 
+(defcustom gnus-treat-x-pgp-sig nil
+  "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,78 @@ 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)))
 
+(autoload 'mm-uu-pgp-signed-test "mm-uu")
+
+(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 +2848,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 +3413,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 +3937,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 +3952,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 +4064,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