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