comparison lisp/gnus/mailcap.el @ 33821:61905a6a0029

Doc fixes. (mailcap-mime-data): Various adjustments. (mailcap): New group. (mailcap-download-directory): Customize. (mailcap-generate-unique-filename, mailcap-binary-suffixes) (mailcap-temporary-directory): Deleted (unused). (mailcap-unescape-mime-test): Simplify slightly. (mailcap-viewer-passes-test): Use functionp. (mailcap-command-p): Aliased to executable-find.
author Dave Love <fx@gnu.org>
date Thu, 23 Nov 2000 17:04:51 +0000
parents e06db3b8e558
children 8b1375dbcbc6
comparison
equal deleted inserted replaced
33820:962073a4240a 33821:61905a6a0029
1 ;;; mailcap.el --- Functions for displaying MIME parts 1 ;;; mailcap.el --- MIME media types configuration
2 ;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. 2 ;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3 3
4 ;; Author: William M. Perry <wmperry@aventail.com> 4 ;; Author: William M. Perry <wmperry@aventail.com>
5 ;; Lars Magne Ingebrigtsen <larsi@gnus.org> 5 ;; Lars Magne Ingebrigtsen <larsi@gnus.org>
6 ;; Keywords: news, mail 6 ;; Keywords: news, mail, multimedia
7 7
8 ;; This file is part of GNU Emacs. 8 ;; This file is part of GNU Emacs.
9 9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify 10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by 11 ;; it under the terms of the GNU General Public License as published by
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA. 23 ;; Boston, MA 02111-1307, USA.
24 24
25 ;;; Commentary: 25 ;;; Commentary:
26 26
27 ;; Provides configuration of MIME media types from directly from Lisp
28 ;; and via the usual mailcap mechanism (RFC 1524). Deals with
29 ;; mime.types similarly.
30
27 ;;; Code: 31 ;;; Code:
28 32
29 (eval-when-compile (require 'cl)) 33 (eval-when-compile (require 'cl))
30 (require 'mail-parse) 34 (require 'mail-parse)
31 (require 'mm-util) 35 (require 'mm-util)
36
37 (defgroup mailcap nil
38 "Definition of viewers for MIME types."
39 :version "21.1"
40 :group 'mime)
32 41
33 (defvar mailcap-parse-args-syntax-table 42 (defvar mailcap-parse-args-syntax-table
34 (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table))) 43 (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
35 (modify-syntax-entry ?' "\"" table) 44 (modify-syntax-entry ?' "\"" table)
36 (modify-syntax-entry ?` "\"" table) 45 (modify-syntax-entry ?` "\"" table)
37 (modify-syntax-entry ?{ "(" table) 46 (modify-syntax-entry ?{ "(" table)
38 (modify-syntax-entry ?} ")" table) 47 (modify-syntax-entry ?} ")" table)
39 table) 48 table)
40 "A syntax table for parsing sgml attributes.") 49 "A syntax table for parsing sgml attributes.")
41 50
51 ;; Postpone using defcustom for this as it's so big and we essentially
52 ;; have to have two copies of the data around then. Perhaps just
53 ;; customize the Lisp viewers and rely on the normal configuration
54 ;; files for the rest? -- fx
42 (defvar mailcap-mime-data 55 (defvar mailcap-mime-data
43 '(("application" 56 '(("application"
44 ("x-x509-ca-cert" 57 ("x-x509-ca-cert"
45 (viewer . ssl-view-site-cert) 58 (viewer . ssl-view-site-cert)
46 (test . (fboundp 'ssl-view-site-cert)) 59 (test . (fboundp 'ssl-view-site-cert))
51 (type . "application/x-x509-user-cert")) 64 (type . "application/x-x509-user-cert"))
52 ("octet-stream" 65 ("octet-stream"
53 (viewer . mailcap-save-binary-file) 66 (viewer . mailcap-save-binary-file)
54 (non-viewer . t) 67 (non-viewer . t)
55 (type . "application/octet-stream")) 68 (type . "application/octet-stream"))
56 ("dvi" 69 ;;; XEmacs says `ns' device-type not implemented.
57 (viewer . "open %s") 70 ;; ("dvi"
58 (type . "application/dvi") 71 ;; (viewer . "open %s")
59 (test . (eq (mm-device-type) 'ns))) 72 ;; (type . "application/dvi")
73 ;; (test . (eq (mm-device-type) 'ns)))
60 ("dvi" 74 ("dvi"
61 (viewer . "xdvi %s") 75 (viewer . "xdvi %s")
62 (test . (eq (mm-device-type) 'x)) 76 (test . (eq (mm-device-type) 'x))
63 ("needsx11") 77 ("needsx11")
64 (type . "application/dvi")) 78 (type . "application/dvi"))
96 ("zip" 110 ("zip"
97 (viewer . mailcap-save-binary-file) 111 (viewer . mailcap-save-binary-file)
98 (non-viewer . t) 112 (non-viewer . t)
99 (type . "application/zip") 113 (type . "application/zip")
100 ("copiousoutput")) 114 ("copiousoutput"))
115 ;; Prefer free viewers.
116 ("pdf"
117 (viewer . "gv %s")
118 (type . "application/pdf")
119 (test . window-system))
120 ("pdf"
121 (viewer . "xpdf %s")
122 (type . "application/pdf")
123 (test . (eq (mm-device-type) 'x)))
101 ("pdf" 124 ("pdf"
102 (viewer . "acroread %s") 125 (viewer . "acroread %s")
103 (type . "application/pdf")) 126 (type . "application/pdf"))
127 ;;; XEmacs says `ns' device-type not implemented.
128 ;; ("postscript"
129 ;; (viewer . "open %s")
130 ;; (type . "application/postscript")
131 ;; (test . (eq (mm-device-type) 'ns)))
104 ("postscript" 132 ("postscript"
105 (viewer . "open %s") 133 (viewer . "gv -safer %s")
106 (type . "application/postscript") 134 (type . "application/postscript")
107 (test . (eq (mm-device-type) 'ns))) 135 (test . window-system)
136 ("needsx11"))
108 ("postscript" 137 ("postscript"
109 (viewer . "ghostview -dSAFER %s") 138 (viewer . "ghostview -dSAFER %s")
110 (type . "application/postscript") 139 (type . "application/postscript")
111 (test . (eq (mm-device-type) 'x)) 140 (test . (eq (mm-device-type) 'x))
112 ("needsx11")) 141 ("needsx11"))
136 (viewer . w3-mode) 165 (viewer . w3-mode)
137 (test . (fboundp 'w3-mode)) 166 (test . (fboundp 'w3-mode))
138 (type . "message/rfc822")) 167 (type . "message/rfc822"))
139 ("rfc-*822" 168 ("rfc-*822"
140 (viewer . view-mode) 169 (viewer . view-mode)
141 (test . (fboundp 'view-mode))
142 (type . "message/rfc822"))
143 ("rfc-*822"
144 (viewer . fundamental-mode)
145 (type . "message/rfc822"))) 170 (type . "message/rfc822")))
146 ("image" 171 ("image"
147 ("x-xwd" 172 ("x-xwd"
148 (viewer . "xwud -in %s") 173 (viewer . "xwud -in %s")
149 (type . "image/x-xwd") 174 (type . "image/x-xwd")
160 (viewer . "xwud -in %s") 185 (viewer . "xwud -in %s")
161 (type . "image/x-xwd") 186 (type . "image/x-xwd")
162 ("compose" . "xwd -frame > %s") 187 ("compose" . "xwd -frame > %s")
163 (test . (eq (mm-device-type) 'x)) 188 (test . (eq (mm-device-type) 'x))
164 ("needsx11")) 189 ("needsx11"))
165 (".*" 190 ;;; XEmacs says `ns' device-type not implemented.
166 (viewer . "aopen %s") 191 ;; (".*"
167 (type . "image/*") 192 ;; (viewer . "aopen %s")
168 (test . (eq (mm-device-type) 'ns))) 193 ;; (type . "image/*")
194 ;; (test . (eq (mm-device-type) 'ns)))
169 (".*" 195 (".*"
170 (viewer . "display %s") 196 (viewer . "display %s")
171 (type . "image/*") 197 (type . "image/*")
172 (test . (eq (mm-device-type) 'x)) 198 (test . (eq (mm-device-type) 'x))
173 ("needsx11")) 199 ("needsx11"))
223 (\"postscript\" . <info>)) 249 (\"postscript\" . <info>))
224 (\"text\" 250 (\"text\"
225 (\"plain\" . <info>))) 251 (\"plain\" . <info>)))
226 252
227 Where <info> is another assoc list of the various information 253 Where <info> is another assoc list of the various information
228 related to the mailcap RFC. This is keyed on the lowercase 254 related to the mailcap RFC 1524. This is keyed on the lowercase
229 attribute name (viewer, test, etc). This looks like: 255 attribute name (viewer, test, etc). This looks like:
230 ((viewer . viewerinfo) 256 ((viewer . VIEWERINFO)
231 (test . testinfo) 257 (test . TESTINFO)
232 (xxxx . \"string\")) 258 (xxxx . \"STRING\")
233 259 FLAG)
234 Where viewerinfo specifies how the content-type is viewed. Can be 260
261 Where VIEWERINFO specifies how the content-type is viewed. Can be
235 a string, in which case it is run through a shell, with 262 a string, in which case it is run through a shell, with
236 appropriate parameters, or a symbol, in which case the symbol is 263 appropriate parameters, or a symbol, in which case the symbol is
237 funcall'd, with the buffer as an argument. 264 `funcall'ed, with the buffer as an argument.
238 265
239 testinfo is a list of strings, or nil. If nil, it means the 266 TESTINFO is a test for the viewer's applicability, or nil. If nil, it
240 viewer specified is always valid. If it is a list of strings, 267 means the viewer is always valid. If it is a Lisp function, it is
241 these are used to determine whether a viewer passes the 'test' or 268 called with a list of items from any extra fields from the
242 not.") 269 Content-Type header as argument to return a boolean value for the
243 270 validity. Otherwise, if it is a non-function Lisp symbol or list
244 (defvar mailcap-download-directory nil 271 whose car is a symbol, it is `eval'led to yield the validity. If it
245 "*Where downloaded files should go by default.") 272 is a string or list of strings, it represents a shell command to run
246 273 to return a true or false shell value for the validity.")
247 (defvar mailcap-temporary-directory 274
248 (cond ((fboundp 'temp-directory) (temp-directory)) 275 (defcustom mailcap-download-directory nil
249 ((boundp 'temporary-file-directory) temporary-file-directory) 276 "*Where downloaded files should go by default."
250 ("/tmp/")) 277 :type 'directory
251 "*Where temporary files go.") 278 :group 'mailcap)
252 279
253 ;;; 280 ;;;
254 ;;; Utility functions 281 ;;; Utility functions
255 ;;; 282 ;;;
256
257 (defun mailcap-generate-unique-filename (&optional fmt)
258 "Generate a unique filename in mailcap-temporary-directory."
259 (if (not fmt)
260 (let ((base (format "mailcap-tmp.%d" (user-real-uid)))
261 (fname "")
262 (x 0))
263 (setq fname (format "%s%d" base x))
264 (while (file-exists-p
265 (expand-file-name fname mailcap-temporary-directory))
266 (setq x (1+ x)
267 fname (concat base (int-to-string x))))
268 (expand-file-name fname mailcap-temporary-directory))
269 (let ((base (concat "mm" (int-to-string (user-real-uid))))
270 (fname "")
271 (x 0))
272 (setq fname (format fmt (concat base (int-to-string x))))
273 (while (file-exists-p
274 (expand-file-name fname mailcap-temporary-directory))
275 (setq x (1+ x)
276 fname (format fmt (concat base (int-to-string x)))))
277 (expand-file-name fname mailcap-temporary-directory))))
278 283
279 (defun mailcap-save-binary-file () 284 (defun mailcap-save-binary-file ()
280 (goto-char (point-min)) 285 (goto-char (point-min))
281 (unwind-protect 286 (unwind-protect
282 (let ((file (read-file-name 287 (let ((file (read-file-name
287 (kill-buffer (current-buffer)))) 292 (kill-buffer (current-buffer))))
288 293
289 (defvar mailcap-maybe-eval-warning 294 (defvar mailcap-maybe-eval-warning
290 "*** WARNING *** 295 "*** WARNING ***
291 296
292 This MIME part contains untrusted and possibly harmful content. 297 This MIME part contains untrusted and possibly harmful content.
293 If you evaluate the Emacs Lisp code contained in it, a lot of nasty 298 If you evaluate the Emacs Lisp code contained in it, a lot of nasty
294 things can happen. Please examine the code very carefully before you 299 things can happen. Please examine the code very carefully before you
295 instruct Emacs to evaluate it. You can browse the buffer containing 300 instruct Emacs to evaluate it. You can browse the buffer containing
296 the code using \\[scroll-other-window]. 301 the code using \\[scroll-other-window].
297 302
299 "Text of warning message displayed by `mailcap-maybe-eval'. 304 "Text of warning message displayed by `mailcap-maybe-eval'.
300 Make sure that this text consists only of few text lines. Otherwise, 305 Make sure that this text consists only of few text lines. Otherwise,
301 Gnus might fail to display all of it.") 306 Gnus might fail to display all of it.")
302 307
303 (defun mailcap-maybe-eval () 308 (defun mailcap-maybe-eval ()
304 "Maybe evaluate a buffer of emacs lisp code." 309 "Maybe evaluate a buffer of Emacs Lisp code."
305 (let ((lisp-buffer (current-buffer))) 310 (let ((lisp-buffer (current-buffer)))
306 (goto-char (point-min)) 311 (goto-char (point-min))
307 (when 312 (when
308 (save-window-excursion 313 (save-window-excursion
309 (delete-other-windows) 314 (delete-other-windows)
310 (let ((buffer (get-buffer-create (generate-new-buffer-name 315 (let ((buffer (get-buffer-create (generate-new-buffer-name
311 "*Warning*")))) 316 "*Warning*"))))
312 (unwind-protect 317 (unwind-protect
313 (with-current-buffer buffer 318 (with-current-buffer buffer
314 (insert (substitute-command-keys 319 (insert (substitute-command-keys
315 mailcap-maybe-eval-warning)) 320 mailcap-maybe-eval-warning))
316 (goto-char (point-min)) 321 (goto-char (point-min))
317 (display-buffer buffer) 322 (display-buffer buffer)
318 (yes-or-no-p "This is potentially dangerous emacs-lisp code, evaluate it? ")) 323 (yes-or-no-p "This is potentially dangerous emacs-lisp code, evaluate it? "))
319 (kill-buffer buffer)))) 324 (kill-buffer buffer))))
367 (mailcap-parse-mailcap fname)) 372 (mailcap-parse-mailcap fname))
368 (setq fnames (cdr fnames)))) 373 (setq fnames (cdr fnames))))
369 (setq mailcap-parsed-p t))) 374 (setq mailcap-parsed-p t)))
370 375
371 (defun mailcap-parse-mailcap (fname) 376 (defun mailcap-parse-mailcap (fname)
372 ;; Parse out the mailcap file specified by FNAME 377 "Parse out the mailcap file specified by FNAME."
373 (let (major ; The major mime type (image/audio/etc) 378 (let (major ; The major mime type (image/audio/etc)
374 minor ; The minor mime type (gif, basic, etc) 379 minor ; The minor mime type (gif, basic, etc)
375 save-pos ; Misc saved positions used in parsing 380 save-pos ; Misc saved positions used in parsing
376 viewer ; How to view this mime type 381 viewer ; How to view this mime type
377 info ; Misc info about this mime type 382 info ; Misc info about this mime type
407 ((= (point) save-pos) ".*") 412 ((= (point) save-pos) ".*")
408 (t (regexp-quote (buffer-substring save-pos (point))))))) 413 (t (regexp-quote (buffer-substring save-pos (point)))))))
409 (skip-chars-forward " \t") 414 (skip-chars-forward " \t")
410 ;;; Got the major/minor chunks, now for the viewers/etc 415 ;;; Got the major/minor chunks, now for the viewers/etc
411 ;;; The first item _must_ be a viewer, according to the 416 ;;; The first item _must_ be a viewer, according to the
412 ;;; RFC for mailcap files (#1343) 417 ;;; RFC for mailcap files (#1524)
413 (setq viewer "") 418 (setq viewer "")
414 (when (eq (char-after) ?\;) 419 (when (eq (char-after) ?\;)
415 (forward-char) 420 (forward-char)
416 (skip-chars-forward " \t") 421 (skip-chars-forward " \t")
417 (setq save-pos (point)) 422 (setq save-pos (point))
418 (skip-chars-forward "^;\n") 423 (skip-chars-forward "^;\n")
419 ;; skip \; 424 ;; skip \;
430 (goto-char (point-max)) 435 (goto-char (point-max))
431 (widen)))) 436 (widen))))
432 (setq viewer (buffer-substring save-pos (point))))) 437 (setq viewer (buffer-substring save-pos (point)))))
433 (setq save-pos (point)) 438 (setq save-pos (point))
434 (end-of-line) 439 (end-of-line)
435 (unless (equal viewer "") 440 (unless (equal viewer "")
436 (setq info (nconc (list (cons 'viewer viewer) 441 (setq info (nconc (list (cons 'viewer viewer)
437 (cons 'type (concat major "/" 442 (cons 'type (concat major "/"
438 (if (string= minor ".*") 443 (if (string= minor ".*")
439 "*" minor)))) 444 "*" minor))))
440 (mailcap-parse-mailcap-extras save-pos (point)))) 445 (mailcap-parse-mailcap-extras save-pos (point))))
441 (mailcap-mailcap-entry-passes-test info) 446 (mailcap-mailcap-entry-passes-test info)
442 (mailcap-add-mailcap-entry major minor info)) 447 (mailcap-add-mailcap-entry major minor info))
443 (beginning-of-line))))) 448 (beginning-of-line)))))
444 449
445 (defun mailcap-parse-mailcap-extras (st nd) 450 (defun mailcap-parse-mailcap-extras (st nd)
446 ;; Grab all the extra stuff from a mailcap entry 451 "Grab all the extra stuff from a mailcap entry."
447 (let ( 452 (let (
448 name ; From name= 453 name ; From name=
449 value ; its value 454 value ; its value
450 results ; Assoc list of results 455 results ; Assoc list of results
451 name-pos ; Start of XXXX= position 456 name-pos ; Start of XXXX= position
486 (setq results (cons (cons name value) results)) 491 (setq results (cons (cons name value) results))
487 (skip-chars-forward " \";\n\t")) 492 (skip-chars-forward " \";\n\t"))
488 results))) 493 results)))
489 494
490 (defun mailcap-mailcap-entry-passes-test (info) 495 (defun mailcap-mailcap-entry-passes-test (info)
491 ;; Return t iff a mailcap entry passes its test clause or no test 496 "Return non-nil iff mailcap entry INFO passes its test clause.
492 ;; clause is present. 497 Also return non-nil if no test clause is present."
493 (let (status ; Call-process-regions return value 498 (let ((test (assq 'test info)) ; The test clause
494 (test (assq 'test info)) ; The test clause 499 status)
495 )
496 (setq status (and test (split-string (cdr test) " "))) 500 (setq status (and test (split-string (cdr test) " ")))
497 (if (and (or (assoc "needsterm" info) 501 (if (and (or (assoc "needsterm" info)
498 (assoc "needsterminal" info) 502 (assoc "needsterminal" info)
499 (assoc "needsx11" info)) 503 (assoc "needsx11" info))
500 (not (getenv "DISPLAY"))) 504 (not (getenv "DISPLAY")))
517 ;;; 521 ;;;
518 ;;; The action routines. 522 ;;; The action routines.
519 ;;; 523 ;;;
520 524
521 (defun mailcap-possible-viewers (major minor) 525 (defun mailcap-possible-viewers (major minor)
522 ;; Return a list of possible viewers from MAJOR for minor type MINOR 526 "Return a list of possible viewers from MAJOR for minor type MINOR."
523 (let ((exact '()) 527 (let ((exact '())
524 (wildcard '())) 528 (wildcard '()))
525 (while major 529 (while major
526 (cond 530 (cond
527 ((equal (car (car major)) minor) 531 ((equal (car (car major)) minor)
552 (delete-char 1) 556 (delete-char 1)
553 (skip-chars-forward "%.")) 557 (skip-chars-forward "%."))
554 (setq save-pos (point)) 558 (setq save-pos (point))
555 (skip-chars-forward "%") 559 (skip-chars-forward "%")
556 (setq save-chr (char-after (point))) 560 (setq save-chr (char-after (point)))
561 ;; Escapes:
562 ;; %s: name of a file for the body data
563 ;; %t: content-type
564 ;; %{<parameter name}: value of parameter in mailcap entry
565 ;; %n: number of sub-parts for multipart content-type
566 ;; %F: a set of content-type/filename pairs for multiparts
557 (cond 567 (cond
558 ((null save-chr) nil) 568 ((null save-chr) nil)
559 ((= save-chr ?t) 569 ((= save-chr ?t)
560 (delete-region save-pos (progn (forward-char 1) (point))) 570 (delete-region save-pos (progn (forward-char 1) (point)))
561 (insert (or (cdr (assq 'type type-info)) "\"\""))) 571 (insert (or (cdr (assq 'type type-info)) "\"\"")))
562 ((= save-chr ?M) 572 ((memq save-chr '(?M ?n ?F))
563 (delete-region save-pos (progn (forward-char 1) (point)))
564 (insert "\"\""))
565 ((= save-chr ?n)
566 (delete-region save-pos (progn (forward-char 1) (point)))
567 (insert "\"\""))
568 ((= save-chr ?F)
569 (delete-region save-pos (progn (forward-char 1) (point))) 573 (delete-region save-pos (progn (forward-char 1) (point)))
570 (insert "\"\"")) 574 (insert "\"\""))
571 ((= save-chr ?{) 575 ((= save-chr ?{)
572 (forward-char 1) 576 (forward-char 1)
573 (skip-chars-forward "^}") 577 (skip-chars-forward "^}")
575 (setq subst (buffer-substring (+ 2 save-pos) (point))) 579 (setq subst (buffer-substring (+ 2 save-pos) (point)))
576 (delete-region save-pos (1+ (point))) 580 (delete-region save-pos (1+ (point)))
577 (insert (or (cdr (assoc subst type-info)) "\"\""))) 581 (insert (or (cdr (assoc subst type-info)) "\"\"")))
578 (t nil)))) 582 (t nil))))
579 (buffer-string))) 583 (buffer-string)))
580 (t (error "Bad value to mailcap-unescape-mime-test. %s" test))))) 584 (t (error "Bad value to mailcap-unescape-mime-test: %s" test)))))
581 585
582 (defvar mailcap-viewer-test-cache nil) 586 (defvar mailcap-viewer-test-cache nil)
583 587
584 (defun mailcap-viewer-passes-test (viewer-info type-info) 588 (defun mailcap-viewer-passes-test (viewer-info type-info)
585 ;; Return non-nil iff the viewer specified by VIEWER-INFO passes its 589 "Return non-nil iff viewer specified by VIEWER-INFO passes its test clause.
586 ;; test clause (if any). 590 Also retun non-nil if it has no test clause. TYPE-INFO is an argument
591 to supply to the test."
587 (let* ((test-info (assq 'test viewer-info)) 592 (let* ((test-info (assq 'test viewer-info))
588 (test (cdr test-info)) 593 (test (cdr test-info))
589 (otest test) 594 (otest test)
590 (viewer (cdr (assoc 'viewer viewer-info))) 595 (viewer (cdr (assoc 'viewer viewer-info)))
591 (default-directory (expand-file-name "~/")) 596 (default-directory (expand-file-name "~/"))
596 result 601 result
597 (cond 602 (cond
598 ((not test-info) t) ; No test clause 603 ((not test-info) t) ; No test clause
599 ((not test) nil) ; Already failed test 604 ((not test) nil) ; Already failed test
600 ((eq test t) t) ; Already passed test 605 ((eq test t) t) ; Already passed test
601 ((and (symbolp test) ; Lisp function as test 606 ((functionp test) ; Lisp function as test
602 (fboundp test))
603 (funcall test type-info)) 607 (funcall test type-info))
604 ((and (symbolp test) ; Lisp variable as test 608 ((and (symbolp test) ; Lisp variable as test
605 (boundp test)) 609 (boundp test))
606 (symbol-value test)) 610 (symbol-value test))
607 ((and (listp test) ; List to be eval'd 611 ((and (listp test) ; List to be eval'd
652 ;;; 656 ;;;
653 ;;; The main whabbo 657 ;;; The main whabbo
654 ;;; 658 ;;;
655 659
656 (defun mailcap-viewer-lessp (x y) 660 (defun mailcap-viewer-lessp (x y)
657 ;; Return t iff viewer X is more desirable than viewer Y 661 "Return t iff viewer X is more desirable than viewer Y."
658 (let ((x-wild (string-match "[*?]" (or (cdr-safe (assq 'type x)) ""))) 662 (let ((x-wild (string-match "[*?]" (or (cdr-safe (assq 'type x)) "")))
659 (y-wild (string-match "[*?]" (or (cdr-safe (assq 'type y)) ""))) 663 (y-wild (string-match "[*?]" (or (cdr-safe (assq 'type y)) "")))
660 (x-lisp (not (stringp (or (cdr-safe (assq 'viewer x)) "")))) 664 (x-lisp (not (stringp (or (cdr-safe (assq 'viewer x)) ""))))
661 (y-lisp (not (stringp (or (cdr-safe (assq 'viewer y)) ""))))) 665 (y-lisp (not (stringp (or (cdr-safe (assq 'viewer y)) "")))))
662 (cond 666 (cond
733 ;;; 737 ;;;
734 ;;; Experimental MIME-types parsing 738 ;;; Experimental MIME-types parsing
735 ;;; 739 ;;;
736 740
737 (defvar mailcap-mime-extensions 741 (defvar mailcap-mime-extensions
738 '(("" . "text/plain") 742 '(("" . "text/plain")
739 (".abs" . "audio/x-mpeg") 743 (".abs" . "audio/x-mpeg")
740 (".aif" . "audio/aiff") 744 (".aif" . "audio/aiff")
741 (".aifc" . "audio/aiff") 745 (".aifc" . "audio/aiff")
742 (".aiff" . "audio/aiff") 746 (".aiff" . "audio/aiff")
743 (".ano" . "application/x-annotator") 747 (".ano" . "application/x-annotator")
744 (".au" . "audio/ulaw") 748 (".au" . "audio/ulaw")
745 (".avi" . "video/x-msvideo") 749 (".avi" . "video/x-msvideo")
746 (".bcpio" . "application/x-bcpio") 750 (".bcpio" . "application/x-bcpio")
747 (".bin" . "application/octet-stream") 751 (".bin" . "application/octet-stream")
748 (".cdf" . "application/x-netcdr") 752 (".cdf" . "application/x-netcdr")
749 (".cpio" . "application/x-cpio") 753 (".cpio" . "application/x-cpio")
750 (".csh" . "application/x-csh") 754 (".csh" . "application/x-csh")
751 (".css" . "text/css") 755 (".css" . "text/css")
752 (".dvi" . "application/x-dvi") 756 (".dvi" . "application/x-dvi")
753 (".diff" . "text/x-patch") 757 (".diff" . "text/x-patch")
754 (".el" . "application/emacs-lisp") 758 (".el" . "application/emacs-lisp")
755 (".eps" . "application/postscript") 759 (".eps" . "application/postscript")
756 (".etx" . "text/x-setext") 760 (".etx" . "text/x-setext")
757 (".exe" . "application/octet-stream") 761 (".exe" . "application/octet-stream")
758 (".fax" . "image/x-fax") 762 (".fax" . "image/x-fax")
759 (".gif" . "image/gif") 763 (".gif" . "image/gif")
760 (".hdf" . "application/x-hdf") 764 (".hdf" . "application/x-hdf")
761 (".hqx" . "application/mac-binhex40") 765 (".hqx" . "application/mac-binhex40")
762 (".htm" . "text/html") 766 (".htm" . "text/html")
763 (".html" . "text/html") 767 (".html" . "text/html")
764 (".icon" . "image/x-icon") 768 (".icon" . "image/x-icon")
765 (".ief" . "image/ief") 769 (".ief" . "image/ief")
766 (".jpg" . "image/jpeg") 770 (".jpg" . "image/jpeg")
767 (".macp" . "image/x-macpaint") 771 (".macp" . "image/x-macpaint")
768 (".man" . "application/x-troff-man") 772 (".man" . "application/x-troff-man")
769 (".me" . "application/x-troff-me") 773 (".me" . "application/x-troff-me")
770 (".mif" . "application/mif") 774 (".mif" . "application/mif")
771 (".mov" . "video/quicktime") 775 (".mov" . "video/quicktime")
772 (".movie" . "video/x-sgi-movie") 776 (".movie" . "video/x-sgi-movie")
773 (".mp2" . "audio/x-mpeg") 777 (".mp2" . "audio/x-mpeg")
774 (".mp3" . "audio/x-mpeg") 778 (".mp3" . "audio/x-mpeg")
775 (".mp2a" . "audio/x-mpeg2") 779 (".mp2a" . "audio/x-mpeg2")
776 (".mpa" . "audio/x-mpeg") 780 (".mpa" . "audio/x-mpeg")
777 (".mpa2" . "audio/x-mpeg2") 781 (".mpa2" . "audio/x-mpeg2")
778 (".mpe" . "video/mpeg") 782 (".mpe" . "video/mpeg")
779 (".mpeg" . "video/mpeg") 783 (".mpeg" . "video/mpeg")
780 (".mpega" . "audio/x-mpeg") 784 (".mpega" . "audio/x-mpeg")
781 (".mpegv" . "video/mpeg") 785 (".mpegv" . "video/mpeg")
782 (".mpg" . "video/mpeg") 786 (".mpg" . "video/mpeg")
783 (".mpv" . "video/mpeg") 787 (".mpv" . "video/mpeg")
784 (".ms" . "application/x-troff-ms") 788 (".ms" . "application/x-troff-ms")
785 (".nc" . "application/x-netcdf") 789 (".nc" . "application/x-netcdf")
786 (".nc" . "application/x-netcdf") 790 (".nc" . "application/x-netcdf")
787 (".oda" . "application/oda") 791 (".oda" . "application/oda")
788 (".patch" . "text/x-patch") 792 (".patch" . "text/x-patch")
789 (".pbm" . "image/x-portable-bitmap") 793 (".pbm" . "image/x-portable-bitmap")
790 (".pdf" . "application/pdf") 794 (".pdf" . "application/pdf")
791 (".pgm" . "image/portable-graymap") 795 (".pgm" . "image/portable-graymap")
792 (".pict" . "image/pict") 796 (".pict" . "image/pict")
793 (".png" . "image/png") 797 (".png" . "image/png")
794 (".pnm" . "image/x-portable-anymap") 798 (".pnm" . "image/x-portable-anymap")
795 (".ppm" . "image/portable-pixmap") 799 (".ppm" . "image/portable-pixmap")
796 (".ps" . "application/postscript") 800 (".ps" . "application/postscript")
797 (".qt" . "video/quicktime") 801 (".qt" . "video/quicktime")
798 (".ras" . "image/x-raster") 802 (".ras" . "image/x-raster")
799 (".rgb" . "image/x-rgb") 803 (".rgb" . "image/x-rgb")
800 (".rtf" . "application/rtf") 804 (".rtf" . "application/rtf")
801 (".rtx" . "text/richtext") 805 (".rtx" . "text/richtext")
802 (".sh" . "application/x-sh") 806 (".sh" . "application/x-sh")
803 (".sit" . "application/x-stuffit") 807 (".sit" . "application/x-stuffit")
804 (".snd" . "audio/basic") 808 (".snd" . "audio/basic")
805 (".src" . "application/x-wais-source") 809 (".src" . "application/x-wais-source")
806 (".tar" . "archive/tar") 810 (".tar" . "archive/tar")
807 (".tcl" . "application/x-tcl") 811 (".tcl" . "application/x-tcl")
808 (".tcl" . "application/x-tcl") 812 (".tex" . "application/x-tex")
809 (".tex" . "application/x-tex") 813 (".texi" . "application/texinfo")
810 (".texi" . "application/texinfo") 814 (".tga" . "image/x-targa")
811 (".tga" . "image/x-targa") 815 (".tif" . "image/tiff")
812 (".tif" . "image/tiff") 816 (".tiff" . "image/tiff")
813 (".tiff" . "image/tiff") 817 (".tr" . "application/x-troff")
814 (".tr" . "application/x-troff") 818 (".troff" . "application/x-troff")
815 (".troff" . "application/x-troff") 819 (".tsv" . "text/tab-separated-values")
816 (".tsv" . "text/tab-separated-values") 820 (".txt" . "text/plain")
817 (".txt" . "text/plain") 821 (".vbs" . "video/mpeg")
818 (".vbs" . "video/mpeg") 822 (".vox" . "audio/basic")
819 (".vox" . "audio/basic") 823 (".vrml" . "x-world/x-vrml")
820 (".vrml" . "x-world/x-vrml") 824 (".wav" . "audio/x-wav")
821 (".wav" . "audio/x-wav") 825 (".wrl" . "x-world/x-vrml")
822 (".wrl" . "x-world/x-vrml") 826 (".xbm" . "image/xbm")
823 (".xbm" . "image/xbm") 827 (".xpm" . "image/xpm")
824 (".xpm" . "image/xpm") 828 (".xwd" . "image/windowdump")
825 (".xwd" . "image/windowdump") 829 (".zip" . "application/zip")
826 (".zip" . "application/zip") 830 (".ai" . "application/postscript")
827 (".ai" . "application/postscript") 831 (".jpe" . "image/jpeg")
828 (".jpe" . "image/jpeg") 832 (".jpeg" . "image/jpeg"))
829 (".jpeg" . "image/jpeg")) 833 "An alist of file extensions and corresponding MIME content-types.
830 "An assoc list of file extensions and corresponding MIME content-types.") 834 This exists for you to customize the information in Lisp. It is
835 merged with values from mailcap files by `mailcap-parse-mimetypes'.")
831 836
832 (defvar mailcap-mimetypes-parsed-p nil) 837 (defvar mailcap-mimetypes-parsed-p nil)
833 838
834 (defun mailcap-parse-mimetypes (&optional path force) 839 (defun mailcap-parse-mimetypes (&optional path force)
835 "Parse out all the mimetypes specified in a unix-style path string PATH. 840 "Parse out all the mimetypes specified in a Unix-style path string PATH.
836 Components of PATH are separated by the `path-separator' character 841 Components of PATH are separated by the `path-separator' character
837 appropriate for this system. If PATH is omitted, use the value of 842 appropriate for this system. If PATH is omitted, use the value of
838 environment variable MIMETYPES if set; otherwise use a default path. 843 environment variable MIMETYPES if set; otherwise use a default path.
839 If FORCE, re-parse even if already parsed." 844 If FORCE, re-parse even if already parsed."
840 (interactive (list nil t)) 845 (interactive (list nil t))
869 (mailcap-parse-mimetype-file fname)) 874 (mailcap-parse-mimetype-file fname))
870 (setq fnames (cdr fnames)))) 875 (setq fnames (cdr fnames))))
871 (setq mailcap-mimetypes-parsed-p t))) 876 (setq mailcap-mimetypes-parsed-p t)))
872 877
873 (defun mailcap-parse-mimetype-file (fname) 878 (defun mailcap-parse-mimetype-file (fname)
874 ;; Parse out a mime-types file 879 "Parse out a mime-types file FNAME."
875 (let (type ; The MIME type for this line 880 (let (type ; The MIME type for this line
876 extns ; The extensions for this line 881 extns ; The extensions for this line
877 save-pos ; Misc. saved buffer positions 882 save-pos ; Misc. saved buffer positions
878 ) 883 )
879 (with-temp-buffer 884 (with-temp-buffer
911 (if (and (stringp extn) 916 (if (and (stringp extn)
912 (not (eq (string-to-char extn) ?.))) 917 (not (eq (string-to-char extn) ?.)))
913 (setq extn (concat "." extn))) 918 (setq extn (concat "." extn)))
914 (cdr (assoc (downcase extn) mailcap-mime-extensions))) 919 (cdr (assoc (downcase extn) mailcap-mime-extensions)))
915 920
916 (defvar mailcap-binary-suffixes 921 ;; Unused?
917 (if (memq system-type '(ms-dos windows-nt)) 922 (defalias 'mailcap-command-p 'executable-find)
918 '(".exe" ".com" ".bat" ".cmd" ".btm" "")
919 '("")))
920
921 (defun mailcap-command-p (command)
922 "Say whether COMMAND is in the exec path.
923 The path of COMMAND will be returned iff COMMAND is a command."
924 (let ((path (if (file-name-absolute-p command) '(nil) exec-path))
925 file dir)
926 (catch 'found
927 (while (setq dir (pop path))
928 (let ((suffixes mailcap-binary-suffixes))
929 (while suffixes
930 (when (and (file-executable-p
931 (setq file (expand-file-name
932 (concat command (pop suffixes))
933 dir)))
934 (not (file-directory-p file)))
935 (throw 'found file))))))))
936 923
937 (defun mailcap-mime-types () 924 (defun mailcap-mime-types ()
938 "Return a list of MIME media types." 925 "Return a list of MIME media types."
939 (mailcap-parse-mimetypes) 926 (mailcap-parse-mimetypes)
940 (mm-delete-duplicates 927 (mm-delete-duplicates