Mercurial > emacs
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 |