Fix my last change.
[gnus] / lisp / mailcap.el
index 3450905..aaa29fa 100644 (file)
@@ -286,11 +286,42 @@ not.")
        (write-region (point-min) (point-max) file))
     (kill-buffer (current-buffer))))
 
+(defvar mailcap-maybe-eval-warning
+  "*** WARNING ***
+
+This MIME part contains untrusted and possibly harmful content.  
+If you evaluate the Emacs Lisp code contained in it, a lot of nasty
+things can happen.  Please examine the code very carefully before you
+instruct Emacs to evaluate it.  You can browse the buffer containing
+the code using \\[scroll-other-window].
+
+If you are unsure what to do, please answer \"no\"."
+  "Text of warning message displayed by `mailcap-maybe-eval'.
+Make sure that this text consists only of few text lines.  Otherwise,
+Gnus might fail to display all of it.")
+  
 (defun mailcap-maybe-eval ()
   "Maybe evaluate a buffer of emacs lisp code."
-  (if (yes-or-no-p "This is emacs-lisp code, evaluate it? ")
-      (eval-buffer (current-buffer))
-    (emacs-lisp-mode)))
+  (let ((lisp-buffer (current-buffer)))
+    (goto-char (point-min))
+    (when
+       (save-window-excursion
+         (delete-other-windows)
+         (let ((buffer (get-buffer-create (generate-new-buffer-name
+                                           "*Warning*"))))
+           (unwind-protect
+               (with-current-buffer buffer
+                 (insert (substitute-command-keys 
+                          mailcap-maybe-eval-warning))
+                 (goto-char (point-min))
+                 (display-buffer buffer)
+                 (yes-or-no-p "This is potentially dangerous emacs-lisp code, evaluate it? "))
+             (kill-buffer buffer))))
+      (eval-buffer (current-buffer)))
+    (when (buffer-live-p lisp-buffer)
+      (with-current-buffer lisp-buffer
+       (emacs-lisp-mode)))))
+
 
 ;;;
 ;;; The mailcap parser
@@ -798,39 +829,46 @@ this type is returned."
     (".jpeg"     . "image/jpeg"))
   "An assoc list of file extensions and corresponding MIME content-types.")
 
-(defun mailcap-parse-mimetypes (&optional path)
+(defvar mailcap-mimetypes-parsed-p nil)
+
+(defun mailcap-parse-mimetypes (&optional path force)
   "Parse out all the mimetypes specified in a unix-style path string PATH.
 Components of PATH are separated by the `path-separator' character
 appropriate for this system.  If PATH is omitted, use the value of
-environment variable MIMETYPES if set; otherwise use a default path."
-  (cond
-   (path nil)
-   ((getenv "MIMETYPES") (setq path (getenv "MIMETYPES")))
-   ((memq system-type '(ms-dos ms-windows windows-nt))
-    (setq path '("~/mime.typ" "~/etc/mime.typ")))
-   (t (setq path
-           ;; mime.types seems to be the normal name, definitely so
-           ;; on current GNUish systems.  The search order follows
-           ;; that for mailcap.
-           '("~/.mime.types"
-             "/etc/mime.types"
-             "/usr/etc/mime.types"
-             "/usr/local/etc/mime.types"
-             "/usr/local/www/conf/mime.types"
-             "~/.mime-types"
-             "/etc/mime-types"
-             "/usr/etc/mime-types"
-             "/usr/local/etc/mime-types"
-             "/usr/local/www/conf/mime-types"))))
-  (let ((fnames (reverse (if (stringp path)
-                            (parse-colon-path path)
-                          path)))
-       fname)
-    (while fnames
-      (setq fname (car fnames))
-      (if (and (file-readable-p fname))
-         (mailcap-parse-mimetype-file fname))
-      (setq fnames (cdr fnames)))))
+environment variable MIMETYPES if set; otherwise use a default path.
+If FORCE, re-parse even if already parsed."
+  (interactive (list nil t))
+  (when (or (not mailcap-mimetypes-parsed-p)
+           force)
+    (cond
+     (path nil)
+     ((getenv "MIMETYPES") (setq path (getenv "MIMETYPES")))
+     ((memq system-type '(ms-dos ms-windows windows-nt))
+      (setq path '("~/mime.typ" "~/etc/mime.typ")))
+     (t (setq path
+             ;; mime.types seems to be the normal name, definitely so
+             ;; on current GNUish systems.  The search order follows
+             ;; that for mailcap.
+             '("~/.mime.types"
+               "/etc/mime.types"
+               "/usr/etc/mime.types"
+               "/usr/local/etc/mime.types"
+               "/usr/local/www/conf/mime.types"
+               "~/.mime-types"
+               "/etc/mime-types"
+               "/usr/etc/mime-types"
+               "/usr/local/etc/mime-types"
+               "/usr/local/www/conf/mime-types"))))
+    (let ((fnames (reverse (if (stringp path)
+                              (parse-colon-path path)
+                            path)))
+         fname)
+      (while fnames
+       (setq fname (car fnames))
+       (if (and (file-readable-p fname))
+           (mailcap-parse-mimetype-file fname))
+       (setq fnames (cdr fnames))))
+    (setq mailcap-mimetypes-parsed-p t)))
 
 (defun mailcap-parse-mimetype-file (fname)
   ;; Parse out a mime-types file
@@ -850,7 +888,7 @@ environment variable MIMETYPES if set; otherwise use a default path."
       (while (not (eobp))
        (skip-chars-forward " \t\n")
        (setq save-pos (point))
-       (skip-chars-forward "^ \t")
+       (skip-chars-forward "^ \t\n")
        (downcase-region save-pos (point))
        (setq type (buffer-substring save-pos (point)))
        (while (not (eolp))
@@ -869,6 +907,7 @@ environment variable MIMETYPES if set; otherwise use a default path."
 
 (defun mailcap-extension-to-mime (extn)
   "Return the MIME content type of the file extensions EXTN."
+  (mailcap-parse-mimetypes)
   (if (and (stringp extn)
           (not (eq (string-to-char extn) ?.)))
       (setq extn (concat "." extn)))
@@ -897,7 +936,24 @@ The path of COMMAND will be returned iff COMMAND is a command."
 
 (defun mailcap-mime-types ()
   "Return a list of MIME media types."
-  (mm-delete-duplicates (mapcar 'cdr mailcap-mime-extensions)))
+  (mailcap-parse-mimetypes)
+  (mm-delete-duplicates
+   (nconc
+    (mapcar 'cdr mailcap-mime-extensions)
+    (apply
+     'nconc
+     (mapcar
+      (lambda (l)
+       (delq nil
+             (mapcar
+              (lambda (m)
+                (let ((type (cdr (assq 'type (cdr m)))))
+                  (if (equal (cadr (split-string type "/"))
+                             "*")
+                      nil
+                    type)))
+              (cdr l))))
+      mailcap-mime-data)))))
 
 (provide 'mailcap)