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