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