* gnus-cite.el (gnus-message-highlight-citation): Move to gnus-msg.el.
[gnus] / lisp / mm-decode.el
index 8a38c30..ce3010f 100644 (file)
@@ -1,6 +1,7 @@
 ;;; mm-decode.el --- Functions for decoding MIME things
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002,
-;;        2003 Free Software Foundation, Inc.
+
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
@@ -18,8 +19,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
                   (require 'term))
 
 (eval-and-compile
-  (autoload 'executable-find "executable")
   (autoload 'mm-inline-partial "mm-partial")
   (autoload 'mm-inline-external-body "mm-extern")
+  (autoload 'mm-extern-cache-contents "mm-extern")
   (autoload 'mm-insert-inline "mm-view"))
 
+(defvar gnus-current-window-configuration)
+
 (add-hook 'gnus-exit-gnus-hook 'mm-destroy-postponed-undisplay-list)
 
 (defgroup mime-display ()
   "Display of MIME in mail and news articles."
-  :link '(custom-manual "(emacs-mime)Customization")
+  :link '(custom-manual "(emacs-mime)Display Customization")
   :version "21.1"
   :group 'mail
   :group 'news
@@ -49,7 +52,7 @@
 
 (defgroup mime-security ()
   "MIME security in mail and news articles."
-  :link '(custom-manual "(emacs-mime)Customization")
+  :link '(custom-manual "(emacs-mime)Display Customization")
   :group 'mail
   :group 'news
   :group 'multimedia)
 
 (defcustom mm-text-html-renderer
   (cond ((locate-library "w3") 'w3)
-       ((locate-library "w3m") 'w3m)
+       ((executable-find "w3m") (if (locate-library "w3m")
+                                    'w3m
+                                  'w3m-standalone))
        ((executable-find "links") 'links)
        ((executable-find "lynx") 'lynx)
        (t 'html2text))
   "Render of HTML contents.
 It is one of defined renderer types, or a rendering function.
 The defined renderer types are:
-`w3'   : using Emacs/W3;
-`w3m'  : using emacs-w3m;
-`links': using links;
-`lynx' : using lynx;
-`html2text' : using html2text;
-nil    : using external viewer."
+`w3'   : use Emacs/W3;
+`w3m'  : use emacs-w3m;
+`w3m-standalone': use w3m;
+`links': use links;
+`lynx' : use lynx;
+`html2text' : use html2text;
+nil    : use external viewer."
+  :version "22.1"
   :type '(choice (const w3)
                 (const w3m)
+                (const w3m-standalone)
                 (const links)
                 (const lynx)
                 (const html2text)
                 (const nil)
                 (function))
-  :version "21.3"
   :group 'mime-display)
 
 (defvar mm-inline-text-html-renderer nil
@@ -127,32 +134,50 @@ nil    : using external viewer."
 It is suggested to customize `mm-text-html-renderer' instead.")
 
 (defcustom mm-inline-text-html-with-images nil
-  "If non-nil, Gnus will allow retrieving images in the HTML contents
-with <img> tags.  It has no effect on Emacs/w3.  See also
-the documentation for the option `mm-w3m-safe-url-regexp'."
+  "If non-nil, Gnus will allow retrieving images in HTML contents with
+the <img> tags.  It has no effect on Emacs/w3.  See also the
+documentation for the `mm-w3m-safe-url-regexp' variable."
+  :version "22.1"
   :type 'boolean
   :group 'mime-display)
 
 (defcustom mm-w3m-safe-url-regexp "\\`cid:"
-  "Regexp that matches safe url names.
-Some HTML mails might have a trick of spammers using <img> tags.
-It is likely to be intended to verify whether you have read the
-mail.  You can prevent your personal informations from leaking by
-setting this to the regexp which matches the safe url names.  The
-value of the variable `w3m-safe-url-regexp' will be bound with
-this value.  You may set this value to nil if you consider all
-urls to be safe."
+  "Regexp matching URLs which are considered to be safe.
+Some HTML mails might contain a nasty trick used by spammers, using
+the <img> tag which is far more evil than the [Click Here!] button.
+It is most likely intended to check whether the ominous spam mail has
+reached your eyes or not, in which case the spammer knows for sure
+that your email address is valid.  It is done by embedding an
+identifier string into a URL that you might automatically retrieve
+when displaying the image.  The default value is \"\\\\`cid:\" which only
+matches parts embedded to the Multipart/Related type MIME contents and
+Gnus will never connect to the spammer's site arbitrarily.  You may
+set this variable to nil if you consider all urls to be safe."
+  :version "22.1"
   :type '(choice (regexp :tag "Regexp")
                 (const :tag "All URLs are safe" nil))
   :group 'mime-display)
 
 (defcustom mm-inline-text-html-with-w3m-keymap t
   "If non-nil, use emacs-w3m command keys in the article buffer."
+  :version "22.1"
   :type 'boolean
   :group 'mime-display)
 
+(defcustom mm-enable-external t
+  "Indicate whether external MIME handlers should be used.
+
+If t, all defined external MIME handlers are used.  If nil, files are saved by
+`mailcap-save-binary-file'.  If it is the symbol `ask', you are prompted
+before the external MIME handler is invoked."
+  :version "22.1"
+  :type '(choice (const :tag "Always" t)
+                (const :tag "Never" nil)
+                (const :tag "Ask" ask))
+  :group 'mime-display)
+
 (defcustom mm-inline-media-tests
-  '(("image/jpeg"
+  '(("image/p?jpeg"
      mm-inline-image
      (lambda (handle)
        (mm-valid-and-fit-image-p 'jpeg handle)))
@@ -197,9 +222,15 @@ urls to be safe."
     ("text/richtext" mm-inline-text identity)
     ("text/x-patch" mm-display-patch-inline
      (lambda (handle)
-       (locate-library "diff-mode")))
+       ;; If the diff-mode.el package is installed, the function is
+       ;; autoloaded.  Checking (locate-library "diff-mode") would be trying
+       ;; to cater to broken installations.  OTOH checking the function
+       ;; makes it possible to install another package which provides an
+       ;; alternative implementation of diff-mode.  --Stef
+       (fboundp 'diff-mode)))
     ("application/emacs-lisp" mm-display-elisp-inline identity)
     ("application/x-emacs-lisp" mm-display-elisp-inline identity)
+    ("text/dns" mm-display-dns-inline identity)
     ("text/html"
      mm-inline-text-html
      (lambda (handle)
@@ -238,7 +269,7 @@ urls to be safe."
     ;; Default to displaying as text
     (".*" mm-inline-text mm-readable-p))
   "Alist of media types/tests saying whether types can be displayed inline."
-  :type '(repeat (list (string :tag "MIME type")
+  :type '(repeat (list (regexp :tag "MIME type")
                       (function :tag "Display function")
                       (function :tag "Display test")))
   :group 'mime-display)
@@ -249,11 +280,13 @@ urls to be safe."
     "application/x-emacs-lisp"
     "application/pgp-signature" "application/x-pkcs7-signature"
     "application/pkcs7-signature" "application/x-pkcs7-mime"
-    "application/pkcs7-mime")
+    "application/pkcs7-mime"
+    ;; Mutt still uses this even though it has already been withdrawn.
+    "application/pgp")
   "List of media types that are to be displayed inline.
 See also `mm-inline-media-tests', which says how to display a media
 type inline."
-  :type '(repeat string)
+  :type '(repeat regexp)
   :group 'mime-display)
 
 (defcustom mm-keep-viewer-alive-types
@@ -261,19 +294,22 @@ type inline."
     "application/pdf" "application/x-dvi")
   "List of media types for which the external viewer will not be killed
 when selecting a different article."
-  :type '(repeat string)
+  :version "22.1"
+  :type '(repeat regexp)
   :group 'mime-display)
 
 (defcustom mm-automatic-display
-  '("text/plain" "text/enriched" "text/richtext" "text/html"
+  '("text/plain" "text/enriched" "text/richtext" "text/html" "text/x-verbatim"
     "text/x-vcard" "image/.*" "message/delivery-status" "multipart/.*"
-    "message/rfc822" "text/x-patch" "application/pgp-signature"
+    "message/rfc822" "text/x-patch" "text/dns" "application/pgp-signature"
     "application/emacs-lisp" "application/x-emacs-lisp"
     "application/x-pkcs7-signature"
     "application/pkcs7-signature" "application/x-pkcs7-mime"
-    "application/pkcs7-mime")
+    "application/pkcs7-mime"
+    ;; Mutt still uses this even though it has already been withdrawn.
+    "application/pgp\\'")
   "A list of MIME types to be displayed automatically."
-  :type '(repeat string)
+  :type '(repeat regexp)
   :group 'mime-display)
 
 (defcustom mm-attachment-override-types '("text/x-vcard"
@@ -282,17 +318,17 @@ when selecting a different article."
                                          "application/pkcs7-signature"
                                          "application/x-pkcs7-signature")
   "Types to have \"attachment\" ignored if they can be displayed inline."
-  :type '(repeat string)
+  :type '(repeat regexp)
   :group 'mime-display)
 
 (defcustom mm-inline-override-types nil
   "Types to be treated as attachments even if they can be displayed inline."
-  :type '(repeat string)
+  :type '(repeat regexp)
   :group 'mime-display)
 
 (defcustom mm-automatic-external-display nil
   "List of MIME type regexps that will be displayed externally automatically."
-  :type '(repeat string)
+  :type '(repeat regexp)
   :group 'mime-display)
 
 (defcustom mm-discouraged-alternatives nil
@@ -304,8 +340,13 @@ for instance, text/html parts are very unwanted, and text/richtext are
 somewhat unwanted, then the value of this variable should be set
 to:
 
- (\"text/html\" \"text/richtext\")"
-  :type '(repeat string)
+ (\"text/html\" \"text/richtext\")
+
+Adding \"image/.*\" might also be useful.  Spammers use it as the
+prefered part of multipart/alternative messages.  See also
+`gnus-buttonized-mime-types', to which adding \"multipart/alternative\"
+enables you to choose manually one of two types those mails include."
+  :type '(repeat regexp) ;; See `mm-preferred-alternative-precedence'.
   :group 'mime-display)
 
 (defcustom mm-tmp-directory
@@ -355,8 +396,15 @@ If not set, `default-directory' will be used."
   :type '(choice directory (const :tag "Default" nil))
   :group 'mime-display)
 
+(defcustom mm-attachment-file-modes 384
+  "Set the mode bits of saved attachments to this integer."
+  :version "22.1"
+  :type 'integer
+  :group 'mime-display)
+
 (defcustom mm-external-terminal-program "xterm"
   "The program to start an external terminal."
+  :version "22.1"
   :type 'string
   :group 'mime-display)
 
@@ -388,7 +436,12 @@ If not set, `default-directory' will be used."
 (defcustom mm-verify-option 'never
   "Option of verifying signed parts.
 `never', not verify; `always', always verify;
-`known', only verify known protocols.  Otherwise, ask user."
+`known', only verify known protocols.  Otherwise, ask user.
+
+When set to `always' or `known', you should add
+\"multipart/signed\" to `gnus-buttonized-mime-types' to see
+result of the verification."
+  :version "22.1"
   :type '(choice (item always)
                 (item never)
                 (item :tag "only known protocols" known)
@@ -407,6 +460,7 @@ If not set, `default-directory' will be used."
   "Option of decrypting encrypted parts.
 `never', not decrypt; `always', always decrypt;
 `known', only decrypt known protocols.  Otherwise, ask user."
+  :version "22.1"
   :type '(choice (item always)
                 (item never)
                 (item :tag "only known protocols" known)
@@ -416,21 +470,19 @@ If not set, `default-directory' will be used."
 (defvar mm-viewer-completion-map
   (let ((map (make-sparse-keymap 'mm-viewer-completion-map)))
     (set-keymap-parent map minibuffer-local-completion-map)
+    ;; Should we bind other key to minibuffer-complete-word?
+    (define-key map " " 'self-insert-command)
     map)
   "Keymap for input viewer with completion.")
 
-;; Should we bind other key to minibuffer-complete-word?
-(define-key mm-viewer-completion-map " " 'self-insert-command)
-
 (defvar mm-viewer-completion-map
   (let ((map (make-sparse-keymap 'mm-viewer-completion-map)))
     (set-keymap-parent map minibuffer-local-completion-map)
+    ;; Should we bind other key to minibuffer-complete-word?
+    (define-key map " " 'self-insert-command)
     map)
   "Keymap for input viewer with completion.")
 
-;; Should we bind other key to minibuffer-complete-word?
-(define-key mm-viewer-completion-map " " 'self-insert-command)
-
 ;;; The functions.
 
 (defun mm-alist-to-plist (alist)
@@ -477,75 +529,69 @@ Postpone undisplaying of viewers for types in
     (message "Destroying external MIME viewers")
     (mm-destroy-parts mm-postponed-undisplay-list)))
 
-(defun mm-dissect-buffer (&optional no-strict-mime loose-mime)
+(defun mm-dissect-buffer (&optional no-strict-mime loose-mime from)
   "Dissect the current buffer and return a list of MIME handles."
   (save-excursion
-    (let (ct ctl type subtype cte cd description id result from)
+    (let (ct ctl type subtype cte cd description id result)
       (save-restriction
        (mail-narrow-to-head)
        (when (or no-strict-mime
                  loose-mime
                  (mail-fetch-field "mime-version"))
          (setq ct (mail-fetch-field "content-type")
-               ctl (ignore-errors (mail-header-parse-content-type ct))
+               ctl (and ct (mail-header-parse-content-type ct))
                cte (mail-fetch-field "content-transfer-encoding")
                cd (mail-fetch-field "content-disposition")
                description (mail-fetch-field "content-description")
-               from (mail-fetch-field "from")
                id (mail-fetch-field "content-id"))
+         (unless from
+           (setq from (mail-fetch-field "from")))
          ;; FIXME: In some circumstances, this code is running within
          ;; an unibyte macro.  mail-extract-address-components
          ;; creates unibyte buffers. This `if', though not a perfect
          ;; solution, avoids most of them.
          (if from
              (setq from (cadr (mail-extract-address-components from))))))
-      (when cte
-       (setq cte (mail-header-strip cte)))
       (if (or (not ctl)
              (not (string-match "/" (car ctl))))
          (mm-dissect-singlepart
           (list mm-dissect-default-type)
-          (and cte (intern (downcase (mail-header-remove-whitespace
-                                      (mail-header-remove-comments
-                                       cte)))))
+          (and cte (intern (downcase (mail-header-strip cte))))
           no-strict-mime
-          (and cd (ignore-errors (mail-header-parse-content-disposition cd)))
+          (and cd (mail-header-parse-content-disposition cd))
           description)
        (setq type (split-string (car ctl) "/"))
        (setq subtype (cadr type)
-             type (pop type))
+             type (car type))
        (setq
         result
         (cond
          ((equal type "multipart")
           (let ((mm-dissect-default-type (if (equal subtype "digest")
                                              "message/rfc822"
-                                           "text/plain")))
+                                           "text/plain"))
+                (start (cdr (assq 'start (cdr ctl)))))
             (add-text-properties 0 (length (car ctl))
                                  (mm-alist-to-plist (cdr ctl)) (car ctl))
 
             ;; what really needs to be done here is a way to link a
             ;; MIME handle back to it's parent MIME handle (in a multilevel
             ;; MIME article).  That would probably require changing
-            ;; the mm-handle API so we simply store the multipart buffert
+            ;; the mm-handle API so we simply store the multipart buffer
             ;; name as a text property of the "multipart/whatever" string.
             (add-text-properties 0 (length (car ctl))
-                                 (list 'buffer (mm-copy-to-buffer))
+                                 (list 'buffer (mm-copy-to-buffer)
+                                       'from from
+                                       'start start)
                                  (car ctl))
-            (add-text-properties 0 (length (car ctl))
-            &nb