Regenerate ldefs-boot.el
[bpt/emacs.git] / lisp / gnus / mm-view.el
CommitLineData
715a2ca2 1;;; mm-view.el --- functions for viewing MIME objects
e84b4b86 2
ba318903 3;; Copyright (C) 1998-2014 Free Software Foundation, Inc.
c113de23
GM
4
5;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
6;; This file is part of GNU Emacs.
7
5e809f55 8;; GNU Emacs is free software: you can redistribute it and/or modify
c113de23 9;; it under the terms of the GNU General Public License as published by
5e809f55
GM
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
c113de23
GM
12
13;; GNU Emacs is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
5e809f55 15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c113de23
GM
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
5e809f55 19;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
c113de23
GM
20
21;;; Commentary:
22
23;;; Code:
f0b7f5a8
KY
24
25;; For Emacs <22.2 and XEmacs.
49ad38a1
GM
26(eval-and-compile
27 (unless (fboundp 'declare-function) (defmacro declare-function (&rest r))))
c113de23
GM
28(eval-when-compile (require 'cl))
29(require 'mail-parse)
30(require 'mailcap)
31(require 'mm-bodies)
32(require 'mm-decode)
01c52d31 33(require 'smime)
bb7f5cbc 34(require 'mml-smime)
c113de23 35
229b59da 36(autoload 'gnus-completing-read "gnus-util")
a41c2e6d 37(autoload 'gnus-window-inside-pixel-edges "gnus-ems")
8abf1b22
GM
38(autoload 'gnus-article-prepare-display "gnus-art")
39(autoload 'vcard-parse-string "vcard")
40(autoload 'vcard-format-string "vcard")
41(autoload 'fill-flowed "flow-fill")
42(autoload 'html2text "html2text" nil t)
c113de23 43
dd3eac76
JB
44(defvar gnus-article-mime-handles)
45(defvar gnus-newsgroup-charset)
46(defvar smime-keys)
47(defvar w3m-cid-retrieve-function-alist)
48(defvar w3m-current-buffer)
49(defvar w3m-display-inline-images)
50(defvar w3m-minor-mode-map)
51
23f87bed 52(defvar mm-text-html-renderer-alist
2526f423
G
53 '((shr . mm-shr)
54 (w3 . mm-inline-text-html-render-with-w3)
23f87bed 55 (w3m . mm-inline-text-html-render-with-w3m)
73043f7d 56 (w3m-standalone . mm-inline-text-html-render-with-w3m-standalone)
2526f423 57 (gnus-w3m . gnus-article-html)
23f87bed
MB
58 (links mm-inline-render-with-file
59 mm-links-remove-leading-blank
60 "links" "-dump" file)
2526f423
G
61 (lynx mm-inline-render-with-stdin nil
62 "lynx" "-dump" "-force_html" "-stdin" "-nolist")
63 (html2text mm-inline-render-with-function html2text))
23f87bed
MB
64 "The attributes of renderer types for text/html.")
65
5f4264e5 66(defcustom mm-fill-flowed t
01c52d31 67 "If non-nil a format=flowed article will be displayed flowed."
5f4264e5
MB
68 :type 'boolean
69 :version "22.1"
70 :group 'mime-display)
71
a41c2e6d
G
72(defcustom mm-inline-large-images-proportion 0.9
73 "Maximum proportion of large image resized when
74`mm-inline-large-images' is set to resize."
75 :type 'float
76 :version "24.1"
77 :group 'mime-display)
78
23f87bed
MB
79;;; Internal variables.
80
c113de23
GM
81;;;
82;;; Functions for displaying various formats inline
83;;;
23f87bed 84
c36dea19
GM
85(autoload 'gnus-rescale-image "gnus-util")
86
c113de23
GM
87(defun mm-inline-image-emacs (handle)
88 (let ((b (point-marker))
3d2440b4 89 (inhibit-read-only t))
a41c2e6d
G
90 (put-image
91 (let ((image (mm-get-image handle)))
92 (if (eq mm-inline-large-images 'resize)
540e44db
LMI
93 (gnus-rescale-image
94 image
95 (let ((edges (gnus-window-inside-pixel-edges
96 (get-buffer-window (current-buffer)))))
97 (cons (truncate (* mm-inline-large-images-proportion
98 (- (nth 2 edges) (nth 0 edges))))
99 (truncate (* mm-inline-large-images-proportion
100 (- (nth 3 edges) (nth 1 edges)))))))
a41c2e6d
G
101 image))
102 b)
23f87bed 103 (insert "\n\n")
c113de23
GM
104 (mm-handle-set-undisplayer
105 handle
23f87bed
MB
106 `(lambda ()
107 (let ((b ,b)
3d2440b4 108 (inhibit-read-only t))
23f87bed
MB
109 (remove-images b b)
110 (delete-region b (+ b 2)))))))
c113de23
GM
111
112(defun mm-inline-image-xemacs (handle)
9efa445f
DN
113 (when (featurep 'xemacs)
114 (insert "\n\n")
115 (forward-char -2)
116 (let ((annot (make-annotation (mm-get-image handle) nil 'text))
3d2440b4 117 (inhibit-read-only t))
9efa445f
DN
118 (mm-handle-set-undisplayer
119 handle
120 `(lambda ()
121 (let ((b ,(point-marker))
3d2440b4 122 (inhibit-read-only t))
9efa445f
DN
123 (delete-annotation ,annot)
124 (delete-region (- b 2) b))))
125 (set-extent-property annot 'mm t)
126 (set-extent-property annot 'duplicable t))))
c113de23
GM
127
128(eval-and-compile
722a8409 129 (if (featurep 'xemacs)
c113de23
GM
130 (defalias 'mm-inline-image 'mm-inline-image-xemacs)
131 (defalias 'mm-inline-image 'mm-inline-image-emacs)))
132
49ad38a1
GM
133;; External.
134(declare-function w3-do-setup "ext:w3" ())
135(declare-function w3-region "ext:w3-display" (st nd))
136(declare-function w3-prepare-buffer "ext:w3-display" (&rest args))
137
c113de23
GM
138(defvar mm-w3-setup nil)
139(defun mm-setup-w3 ()
140 (unless mm-w3-setup
141 (require 'w3)
142 (w3-do-setup)
143 (require 'url)
144 (require 'w3-vars)
145 (require 'url-vars)
146 (setq mm-w3-setup t)))
147
23f87bed
MB
148(defun mm-inline-text-html-render-with-w3 (handle)
149 (mm-setup-w3)
150 (let ((text (mm-get-part handle))
151 (b (point))
152 (url-standalone-mode t)
153 (url-gateway-unplugged t)
154 (w3-honor-stylesheets nil)
155 (url-current-object
156 (url-generic-parse-url (format "cid:%s" (mm-handle-id handle))))
157 (width (window-width))
158 (charset (mail-content-type-get
159 (mm-handle-type handle) 'charset)))
160 (save-excursion
01c52d31 161 (insert (if charset (mm-decode-string text charset) text))
23f87bed
MB
162 (save-restriction
163 (narrow-to-region b (point))
01c52d31
MB
164 (unless charset
165 (goto-char (point-min))
166 (when (or (and (boundp 'w3-meta-content-type-charset-regexp)
167 (re-search-forward
168 w3-meta-content-type-charset-regexp nil t))
169 (and (boundp 'w3-meta-charset-content-type-regexp)
170 (re-search-forward
171 w3-meta-charset-content-type-regexp nil t)))
23f87bed 172 (setq charset
01c52d31
MB
173 (let ((bsubstr (buffer-substring-no-properties
174 (match-beginning 2)
175 (match-end 2))))
176 (if (fboundp 'w3-coding-system-for-mime-charset)
177 (w3-coding-system-for-mime-charset bsubstr)
07178229 178 (mm-charset-to-coding-system bsubstr nil t))))
01c52d31
MB
179 (delete-region (point-min) (point-max))
180 (insert (mm-decode-string text charset))))
23f87bed 181 (save-window-excursion
c113de23 182 (save-restriction
23f87bed
MB
183 (let ((w3-strict-width width)
184 ;; Don't let w3 set the global version of
185 ;; this variable.
186 (fill-column fill-column))
187 (if (or debug-on-error debug-on-quit)
188 (w3-region (point-min) (point-max))
189 (condition-case ()
190 (w3-region (point-min) (point-max))
191 (error
192 (delete-region (point-min) (point-max))
193 (let ((b (point))
194 (charset (mail-content-type-get
195 (mm-handle-type handle) 'charset)))
196 (if (or (eq charset 'gnus-decoded)
197 (eq mail-parse-charset 'gnus-decoded))
198 (save-restriction
199 (narrow-to-region (point) (point))
200 (mm-insert-part handle)
201 (goto-char (point-max)))
202 (insert (mm-decode-string (mm-get-part handle)
203 charset))))
204 (message
205 "Error while rendering html; showing as text/plain")))))))
206 (mm-handle-set-undisplayer
207 handle
208 `(lambda ()
3d2440b4 209 (let ((inhibit-read-only t))
01c52d31 210 ,@(if (functionp 'remove-specifier)
3d2440b4
SM
211 '((dolist (prop '(background background-pixmap foreground))
212 (remove-specifier
213 (face-property 'default prop)
214 (current-buffer)))))
23f87bed
MB
215 (delete-region ,(point-min-marker)
216 ,(point-max-marker)))))))))
217
218(defvar mm-w3m-setup nil
219 "Whether gnus-article-mode has been setup to use emacs-w3m.")
220
49ad38a1
GM
221;; External.
222(declare-function w3m-detect-meta-charset "ext:w3m" ())
223(declare-function w3m-region "ext:w3m" (start end &optional url charset))
224
23f87bed
MB
225(defun mm-setup-w3m ()
226 "Setup gnus-article-mode to use emacs-w3m."
227 (unless mm-w3m-setup
228 (require 'w3m)
229 (unless (assq 'gnus-article-mode w3m-cid-retrieve-function-alist)
230 (push (cons 'gnus-article-mode 'mm-w3m-cid-retrieve)
231 w3m-cid-retrieve-function-alist))
232 (setq mm-w3m-setup t))
233 (setq w3m-display-inline-images mm-inline-text-html-with-images))
234
235(defun mm-w3m-cid-retrieve-1 (url handle)
54506618 236 (dolist (elem handle)
fe62aacc
MB
237 (when (consp elem)
238 (when (equal url (mm-handle-id elem))
239 (mm-insert-part elem)
240 (throw 'found-handle (mm-handle-media-type elem)))
241 (when (and (stringp (car elem))
242 (equal "multipart" (mm-handle-media-supertype elem)))
243 (mm-w3m-cid-retrieve-1 url elem)))))
23f87bed
MB
244
245(defun mm-w3m-cid-retrieve (url &rest args)
246 "Insert a content pointed by URL if it has the cid: scheme."
247 (when (string-match "\\`cid:" url)
fe62aacc
MB
248 (or (catch 'found-handle
249 (mm-w3m-cid-retrieve-1
250 (setq url (concat "<" (substring url (match-end 0)) ">"))
251 (with-current-buffer w3m-current-buffer
252 gnus-article-mime-handles)))
253 (prog1
254 nil
255 (message "Failed to find \"Content-ID: %s\"" url)))))
23f87bed
MB
256
257(defun mm-inline-text-html-render-with-w3m (handle)
258 "Render a text/html part using emacs-w3m."
259 (mm-setup-w3m)
260 (let ((text (mm-get-part handle))
261 (b (point))
6b554e88
MB
262 (charset (or (mail-content-type-get (mm-handle-type handle) 'charset)
263 mail-parse-charset)))
23f87bed
MB
264 (save-excursion
265 (insert (if charset (mm-decode-string text charset) text))
266 (save-restriction
267 (narrow-to-region b (point))
268 (unless charset
269 (goto-char (point-min))
270 (when (setq charset (w3m-detect-meta-charset))
c113de23 271 (delete-region (point-min) (point-max))
23f87bed
MB
272 (insert (mm-decode-string text charset))))
273 (let ((w3m-safe-url-regexp mm-w3m-safe-url-regexp)
274 w3m-force-redisplay)
275 (w3m-region (point-min) (point-max) nil charset))
1250af7b
KY
276 ;; Put the mark meaning this part was rendered by emacs-w3m.
277 (put-text-property (point-min) (point-max)
278 'mm-inline-text-html-with-w3m t)
23f87bed
MB
279 (when (and mm-inline-text-html-with-w3m-keymap
280 (boundp 'w3m-minor-mode-map)
281 w3m-minor-mode-map)
886367d8
KY
282 (if (and (boundp 'w3m-link-map)
283 w3m-link-map)
1250af7b
KY
284 (let* ((start (point-min))
285 (end (point-max))
286 (on (get-text-property start 'w3m-href-anchor))
287 (map (copy-keymap w3m-link-map))
288 next)
886367d8 289 (set-keymap-parent map w3m-minor-mode-map)
1250af7b
KY
290 (while (< start end)
291 (if on
292 (progn
293 (setq next (or (text-property-any start end
294 'w3m-href-anchor nil)
295 end))
296 (put-text-property start next 'keymap map))
297 (setq next (or (text-property-not-all start end
298 'w3m-href-anchor nil)
299 end))
300 (put-text-property start next 'keymap w3m-minor-mode-map))
301 (setq start next
302 on (not on))))
303 (put-text-property (point-min) (point-max)
304 'keymap w3m-minor-mode-map)))
58090a8d
MB
305 (mm-handle-set-undisplayer
306 handle
307 `(lambda ()
01c52d31 308 (let ((inhibit-read-only t))
58090a8d
MB
309 (delete-region ,(point-min-marker)
310 ,(point-max-marker)))))))))
23f87bed 311
7347faa8
MB
312(defvar mm-w3m-standalone-supports-m17n-p (if (featurep 'mule) 'undecided)
313 "*T means the w3m command supports the m17n feature.")
314
315(defun mm-w3m-standalone-supports-m17n-p ()
316 "Say whether the w3m command supports the m17n feature."
317 (cond ((eq mm-w3m-standalone-supports-m17n-p t) t)
318 ((eq mm-w3m-standalone-supports-m17n-p nil) nil)
319 ((not (featurep 'mule)) (setq mm-w3m-standalone-supports-m17n-p nil))
320 ((condition-case nil
321 (let ((coding-system-for-write 'iso-2022-jp)
322 (coding-system-for-read 'iso-2022-jp)
323 (str (mm-decode-coding-string "\
8f7abae3 324\e$B#D#o#e#s!!#w#3#m!!#s#u#p#p#o#r#t!!#m#1#7#n!)\e(B" 'iso-2022-jp)))
7347faa8
MB
325 (mm-with-multibyte-buffer
326 (insert str)
327 (call-process-region
328 (point-min) (point-max) "w3m" t t nil "-dump"
329 "-T" "text/html" "-I" "iso-2022-jp" "-O" "iso-2022-jp")
330 (goto-char (point-min))
331 (search-forward str nil t)))
332 (error nil))
333 (setq mm-w3m-standalone-supports-m17n-p t))
334 (t
335 ;;(message "You had better upgrade your w3m command")
336 (setq mm-w3m-standalone-supports-m17n-p nil))))
337
73043f7d
MB
338(defun mm-inline-text-html-render-with-w3m-standalone (handle)
339 "Render a text/html part using w3m."
7347faa8
MB
340 (if (mm-w3m-standalone-supports-m17n-p)
341 (let ((source (mm-get-part handle))
6b554e88
MB
342 (charset (or (mail-content-type-get (mm-handle-type handle)
343 'charset)
344 (symbol-name mail-parse-charset)))
7347faa8 345 cs)
07178229
KY
346 (if (and charset
347 (setq cs (mm-charset-to-coding-system charset nil t))
348 (not (eq cs 'ascii)))
349 (setq charset (format "%s" (mm-coding-system-to-mime-charset cs)))
7347faa8
MB
350 ;; The default.
351 (setq charset "iso-8859-1"
352 cs 'iso-8859-1))
353 (mm-insert-inline
354 handle
355 (mm-with-unibyte-buffer
356 (insert source)
357 (mm-enable-multibyte)
358 (let ((coding-system-for-write 'binary)
359 (coding-system-for-read cs))
360 (call-process-region
361 (point-min) (point-max)
362 "w3m" t t nil "-dump" "-T" "text/html"
363 "-I" charset "-O" charset))
364 (buffer-string))))
365 (mm-inline-render-with-stdin handle nil "w3m" "-dump" "-T" "text/html")))
73043f7d 366
23f87bed
MB
367(defun mm-links-remove-leading-blank ()
368 ;; Delete the annoying three spaces preceding each line of links
369 ;; output.
370 (goto-char (point-min))
371 (while (re-search-forward "^ " nil t)
372 (delete-region (match-beginning 0) (match-end 0))))
373
374(defun mm-inline-wash-with-file (post-func cmd &rest args)
375 (let ((file (mm-make-temp-file
376 (expand-file-name "mm" mm-tmp-directory))))
377 (let ((coding-system-for-write 'binary))
378 (write-region (point-min) (point-max) file nil 'silent))
379 (delete-region (point-min) (point-max))
380 (unwind-protect
381 (apply 'call-process cmd nil t nil (mapcar 'eval args))
382 (delete-file file))
383 (and post-func (funcall post-func))))
384
385(defun mm-inline-wash-with-stdin (post-func cmd &rest args)
386 (let ((coding-system-for-write 'binary))
387 (apply 'call-process-region (point-min) (point-max)
388 cmd t t nil args))
389 (and post-func (funcall post-func)))
390
391(defun mm-inline-render-with-file (handle post-func cmd &rest args)
392 (let ((source (mm-get-part handle)))
393 (mm-insert-inline
394 handle
395 (mm-with-unibyte-buffer
396 (insert source)
397 (apply 'mm-inline-wash-with-file post-func cmd args)
398 (buffer-string)))))
399
400(defun mm-inline-render-with-stdin (handle post-func cmd &rest args)
401 (let ((source (mm-get-part handle)))
402 (mm-insert-inline
403 handle
404 (mm-with-unibyte-buffer
405 (insert source)
406 (apply 'mm-inline-wash-with-stdin post-func cmd args)
407 (buffer-string)))))
408
409(defun mm-inline-render-with-function (handle func &rest args)
410 (let ((source (mm-get-part handle))
6b554e88
MB
411 (charset (or (mail-content-type-get (mm-handle-type handle) 'charset)
412 mail-parse-charset)))
23f87bed
MB
413 (mm-insert-inline
414 handle
415 (mm-with-multibyte-buffer
416 (insert (if charset
417 (mm-decode-string source charset)
418 source))
419 (apply func args)
420 (buffer-string)))))
421
422(defun mm-inline-text-html (handle)
6ed7a66a
G
423 (if (stringp (car handle))
424 (mapcar 'mm-inline-text-html (cdr handle))
425 (let* ((func mm-text-html-renderer)
426 (entry (assq func mm-text-html-renderer-alist))
427 (inhibit-read-only t))
428 (if entry
429 (setq func (cdr entry)))
430 (cond
431 ((functionp func)
432 (funcall func handle))
433 (t
434 (apply (car func) handle (cdr func)))))))
23f87bed
MB
435
436(defun mm-inline-text-vcard (handle)
3d2440b4 437 (let ((inhibit-read-only t))
23f87bed
MB
438 (mm-insert-inline
439 handle
440 (concat "\n-- \n"
441 (ignore-errors
442 (if (fboundp 'vcard-pretty-print)
443 (vcard-pretty-print (mm-get-part handle))
444 (vcard-format-string
445 (vcard-parse-string (mm-get-part handle)
446 'vcard-standard-filter))))))))
447
448(defun mm-inline-text (handle)
449 (let ((b (point))
450 (type (mm-handle-media-subtype handle))
451 (charset (mail-content-type-get
452 (mm-handle-type handle) 'charset))
3d2440b4 453 (inhibit-read-only t))
23f87bed
MB
454 (if (or (eq charset 'gnus-decoded)
455 ;; This is probably not entirely correct, but
456 ;; makes rfc822 parts with embedded multiparts work.
457 (eq mail-parse-charset 'gnus-decoded))
c113de23 458 (save-restriction
23f87bed
MB
459 (narrow-to-region (point) (point))
460 (mm-insert-part handle)
461 (goto-char (point-max)))
247c22e1 462 (mm-display-inline-fontify handle))
5f4264e5
MB
463 (when (and mm-fill-flowed
464 (equal type "plain")
23f87bed
MB
465 (equal (cdr (assoc 'format (mm-handle-type handle)))
466 "flowed"))
467 (save-restriction
468 (narrow-to-region b (point))
469 (goto-char b)
01c52d31
MB
470 (fill-flowed nil (equal (cdr (assoc 'delsp (mm-handle-type handle)))
471 "yes"))
23f87bed
MB
472 (goto-char (point-max))))
473 (save-restriction
474 (narrow-to-region b (point))
3d2440b4
SM
475 (when (member type '("enriched" "richtext"))
476 (set-text-properties (point-min) (point-max) nil)
23f87bed
MB
477 (ignore-errors
478 (enriched-decode (point-min) (point-max))))
479 (mm-handle-set-undisplayer
480 handle
481 `(lambda ()
3d2440b4 482 (let ((inhibit-read-only t))
23f87bed
MB
483 (delete-region ,(point-min-marker)
484 ,(point-max-marker))))))))
c113de23
GM
485
486(defun mm-insert-inline (handle text)
487 "Insert TEXT inline from HANDLE."
23f87bed 488 (let ((b (point)))
c113de23 489 (insert text)
01c52d31
MB
490 (unless (bolp)
491 (insert "\n"))
c113de23
GM
492 (mm-handle-set-undisplayer
493 handle
494 `(lambda ()
3d2440b4
SM
495 (let ((inhibit-read-only t))
496 (delete-region ,(copy-marker b)
497 ,(copy-marker (point))))))))
c113de23
GM
498
499(defun mm-inline-audio (handle)
500 (message "Not implemented"))
501
c113de23
GM
502(defun mm-w3-prepare-buffer ()
503 (require 'w3)
6833e8ba 504 (let ((url-standalone-mode t)
23f87bed
MB
505 (url-gateway-unplugged t)
506 (w3-honor-stylesheets nil))
c113de23
GM
507 (w3-prepare-buffer)))
508
509(defun mm-view-message ()
510 (mm-enable-multibyte)
511 (let (handles)
512 (let (gnus-article-mime-handles)
513 ;; Double decode problem may happen. See mm-inline-message.
514 (run-hooks 'gnus-article-decode-hook)
515 (gnus-article-prepare-display)
516 (setq handles gnus-article-mime-handles))
517 (when handles
518 (setq gnus-article-mime-handles
23f87bed 519 (mm-merge-handles gnus-article-mime-handles handles))))
c113de23
GM
520 (fundamental-mode)
521 (goto-char (point-min)))
522
523(defun mm-inline-message (handle)
524 (let ((b (point))
4e728580 525 (bolp (bolp))
c113de23
GM
526 (charset (mail-content-type-get
527 (mm-handle-type handle) 'charset))
528 gnus-displaying-mime handles)
529 (when (and charset
530 (stringp charset))
531 (setq charset (intern (downcase charset)))
532 (when (eq charset 'us-ascii)
533 (setq charset nil)))
534 (save-excursion
535 (save-restriction
536 (narrow-to-region b b)
537 (mm-insert-part handle)
538 (let (gnus-article-mime-handles
4e728580
SZ
539 ;; disable prepare hook
540 gnus-article-prepare-hook
c113de23 541 (gnus-newsgroup-charset
34128042
MB
542 (unless (eq charset 'gnus-decoded) ;; mm-uu might set it.
543 (or charset gnus-newsgroup-charset))))
23f87bed
MB
544 (let ((gnus-original-article-buffer (mm-handle-buffer handle)))
545 (run-hooks 'gnus-article-decode-hook))
c113de23
GM
546 (gnus-article-prepare-display)
547 (setq handles gnus-article-mime-handles))
4e728580
SZ
548 (goto-char (point-min))
549 (unless bolp
550 (insert "\n"))
c113de23
GM
551 (goto-char (point-max))
552 (unless (bolp)
553 (insert "\n"))
554 (insert "----------\n\n")
555 (when handles
556 (setq gnus-article-mime-handles
23f87bed 557 (mm-merge-handles gnus-article-mime-handles handles)))
c113de23
GM
558 (mm-handle-set-undisplayer
559 handle
560 `(lambda ()
3d2440b4 561 (let ((inhibit-read-only t))
722a8409 562 (if (fboundp 'remove-specifier)
c113de23 563 ;; This is only valid on XEmacs.
3d2440b4
SM
564 (dolist (prop '(background background-pixmap foreground))
565 (remove-specifier
566 (face-property 'default prop) (current-buffer))))
c113de23
GM
567 (delete-region ,(point-min-marker) ,(point-max-marker)))))))))
568
252f26e9
LMI
569;; Shut up byte-compiler.
570(defvar font-lock-mode-hook)
247c22e1
JD
571(defun mm-display-inline-fontify (handle &optional mode)
572 "Insert HANDLE inline fontifying with MODE.
573If MODE is not set, try to find mode automatically."
01c52d31
MB
574 (let ((charset (mail-content-type-get (mm-handle-type handle) 'charset))
575 text coding-system)
576 (unless (eq charset 'gnus-decoded)
577 (mm-with-unibyte-buffer
578 (mm-insert-part handle)
579 (mm-decompress-buffer
247c22e1 580 (mm-handle-filename handle)
01c52d31
MB
581 t t)
582 (unless charset
583 (setq coding-system (mm-find-buffer-file-coding-system)))
584 (setq text (buffer-string))))
23f87bed
MB
585 ;; XEmacs @#$@ version of font-lock refuses to fully turn itself
586 ;; on for buffers whose name begins with " ". That's why we use
01c52d31
MB
587 ;; `with-current-buffer'/`generate-new-buffer' rather than
588 ;; `with-temp-buffer'.
589 (with-current-buffer (generate-new-buffer "*fontification*")
590 (buffer-disable-undo)
591 (mm-enable-multibyte)
592 (insert (cond ((eq charset 'gnus-decoded)
593 (with-current-buffer (mm-handle-buffer handle)
594 (buffer-string)))
595 (coding-system
596 (mm-decode-coding-string text coding-system))
597 (charset
598 (mm-decode-string text charset))
599 (t
600 text)))
601 (require 'font-lock)
252f26e9 602 ;; I find font-lock a bit too verbose.
576950c6
LI
603 (let ((font-lock-verbose nil)
604 (font-lock-support-mode nil))
252f26e9 605 ;; Disable support modes, e.g., jit-lock, lazy-lock, etc.
29a8b279 606 ;; Note: XEmacs people use `font-lock-mode-hook' to run those modes.
252f26e9 607 (set (make-local-variable 'font-lock-mode-hook) nil)
247c22e1 608 (setq buffer-file-name (mm-handle-filename handle))
b62f8267 609 (set (make-local-variable 'enable-local-variables) nil)
252f26e9
LMI
610 (with-demoted-errors
611 (if mode
612 (funcall mode)
613 (let ((auto-mode-alist
614 (delq (rassq 'doc-view-mode-maybe auto-mode-alist)
615 (copy-sequence auto-mode-alist))))
616 (set-auto-mode)))
617 ;; The mode function might have already turned on font-lock.
618 ;; Do not fontify if the guess mode is fundamental.
619 (unless (or (symbol-value 'font-lock-mode)
620 (eq major-mode 'fundamental-mode))
621 (font-lock-fontify-buffer))))
01c52d31
MB
622 ;; By default, XEmacs font-lock uses non-duplicable text
623 ;; properties. This code forces all the text properties
624 ;; to be copied along with the text.
9efa445f 625 (when (featurep 'xemacs)
01c52d31
MB
626 (map-extents (lambda (ext ignored)
627 (set-extent-property ext 'duplicable t)
628 nil)
629 nil nil nil nil nil 'text-prop))
630 (setq text (buffer-string))
247c22e1
JD
631 ;; Set buffer unmodified to avoid confirmation when killing the
632 ;; buffer.
633 (set-buffer-modified-p nil)
01c52d31 634 (kill-buffer (current-buffer)))
c113de23
GM
635 (mm-insert-inline handle text)))
636
23f87bed
MB
637;; Shouldn't these functions check whether the user even wants to use
638;; font-lock? At least under XEmacs, this fontification is pretty
639;; much unconditional. Also, it would be nice to change for the size
640;; of the fontified region.
641
ce9401f3
DL
642(defun mm-display-patch-inline (handle)
643 (mm-display-inline-fontify handle 'diff-mode))
644
645(defun mm-display-elisp-inline (handle)
646 (mm-display-inline-fontify handle 'emacs-lisp-mode))
647
01c52d31
MB
648(defun mm-display-dns-inline (handle)
649 (mm-display-inline-fontify handle 'dns-mode))
650
6e3165fb
JD
651(defun mm-display-org-inline (handle)
652 "Show an Org mode text from HANDLE inline."
653 (mm-display-inline-fontify handle 'org-mode))
654
655(defun mm-display-shell-script-inline (handle)
008cad90 656 "Show a shell script from HANDLE inline."
6e3165fb
JD
657 (mm-display-inline-fontify handle 'shell-script-mode))
658
008cad90
G
659(defun mm-display-javascript-inline (handle)
660 "Show JavsScript code from HANDLE inline."
661 (mm-display-inline-fontify handle 'javascript-mode))
662
23f87bed
MB
663;; id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
664;; us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
665(defvar mm-pkcs7-signed-magic
d058863a
RH
666 (concat
667 "0"
668 "\\(\\(\x80\\)"
669 "\\|\\(\x81\\(.\\|\n\\)\\{1\\}\\)"
670 "\\|\\(\x82\\(.\\|\n\\)\\{2\\}\\)"
671 "\\|\\(\x83\\(.\\|\n\\)\\{3\\}\\)"
672 "\\)"
673 "\x06\x09\\*\x86H\x86\xf7\x0d\x01\x07\x02"))
23f87bed
MB
674
675;; id-envelopedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
676;; us(840) rsadsi(113549) pkcs(1) pkcs7(7) 3 }
677(defvar mm-pkcs7-enveloped-magic
d058863a
RH
678 (concat
679 "0"
680 "\\(\\(\x80\\)"
681 "\\|\\(\x81\\(.\\|\n\\)\\{1\\}\\)"
682 "\\|\\(\x82\\(.\\|\n\\)\\{2\\}\\)"
683 "\\|\\(\x83\\(.\\|\n\\)\\{3\\}\\)"
684 "\\)"
685 "\x06\x09\\*\x86H\x86\xf7\x0d\x01\x07\x03"))
23f87bed
MB
686
687(defun mm-view-pkcs7-get-type (handle)
688 (mm-with-unibyte-buffer
689 (mm-insert-part handle)
690 (cond ((looking-at mm-pkcs7-enveloped-magic)
691 'enveloped)
692 ((looking-at mm-pkcs7-signed-magic)
693 'signed)
694 (t
695 (error "Could not identify PKCS#7 type")))))
696
b0feab7d 697(defun mm-view-pkcs7 (handle &optional from)
23f87bed 698 (case (mm-view-pkcs7-get-type handle)
b0feab7d 699 (enveloped (mm-view-pkcs7-decrypt handle from))
23f87bed
MB
700 (signed (mm-view-pkcs7-verify handle))
701 (otherwise (error "Unknown or unimplemented PKCS#7 type"))))
702
703(defun mm-view-pkcs7-verify (handle)
01c52d31
MB
704 (let ((verified nil))
705 (with-temp-buffer
706 (insert "MIME-Version: 1.0\n")
707 (mm-insert-headers "application/pkcs7-mime" "base64" "smime.p7m")
708 (insert-buffer-substring (mm-handle-buffer handle))
709 (setq verified (smime-verify-region (point-min) (point-max))))
710 (goto-char (point-min))
711 (mm-insert-part handle)
712 (if (search-forward "Content-Type: " nil t)
713 (delete-region (point-min) (match-beginning 0)))
714 (goto-char (point-max))
715 (if (re-search-backward "--\r?\n?" nil t)
716 (delete-region (match-end 0) (point-max)))
717 (unless verified
718 (insert-buffer-substring smime-details-buffer)))
23f87bed
MB
719 (goto-char (point-min))
720 (while (search-forward "\r\n" nil t)
721 (replace-match "\n"))
23f87bed
MB
722 t)
723
b0feab7d 724(defun mm-view-pkcs7-decrypt (handle &optional from)
23f87bed
MB
725 (insert-buffer-substring (mm-handle-buffer handle))
726 (goto-char (point-min))
bb7f5cbc
G
727 (if (eq mml-smime-use 'epg)
728 ;; Use EPG/gpgsm
729 (let ((part (base64-decode-string (buffer-string))))
730 (erase-buffer)
731 (insert (epg-decrypt-string (epg-make-context 'CMS) part)))
732 ;; Use openssl
733 (insert "MIME-Version: 1.0\n")
734 (mm-insert-headers "application/pkcs7-mime" "base64" "smime.p7m")
735 (smime-decrypt-region
736 (point-min) (point-max)
737 (if (= (length smime-keys) 1)
738 (cadar smime-keys)
739 (smime-get-key-by-email
740 (gnus-completing-read
741 "Decipher using key"
742 smime-keys nil nil nil (car-safe (car-safe smime-keys)))))
743 from))
23f87bed
MB
744 (goto-char (point-min))
745 (while (search-forward "\r\n" nil t)
746 (replace-match "\n"))
747 (goto-char (point-min)))
748
c113de23
GM
749(provide 'mm-view)
750
715a2ca2 751;;; mm-view.el ends here