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