Mercurial > emacs
comparison lisp/gnus/mm-view.el @ 88155:d7ddb3e565de
sync with trunk
author | Henrik Enberg <henrik.enberg@telia.com> |
---|---|
date | Mon, 16 Jan 2006 00:03:54 +0000 |
parents | 0d8b17d428b5 |
children |
comparison
equal
deleted
inserted
replaced
88154:8ce476d3ba36 | 88155:d7ddb3e565de |
---|---|
1 ;;; mm-view.el --- functions for viewing MIME objects | 1 ;;; mm-view.el --- functions for viewing MIME objects |
2 ;; Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. | 2 |
3 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, | |
4 ;; 2005 Free Software Foundation, Inc. | |
3 | 5 |
4 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> | 6 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> |
5 ;; This file is part of GNU Emacs. | 7 ;; This file is part of GNU Emacs. |
6 | 8 |
7 ;; GNU Emacs is free software; you can redistribute it and/or modify | 9 ;; GNU Emacs is free software; you can redistribute it and/or modify |
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 ;; GNU General Public License for more details. | 17 ;; GNU General Public License for more details. |
16 | 18 |
17 ;; You should have received a copy of the GNU General Public License | 19 ;; You should have received a copy of the GNU General Public License |
18 ;; along with GNU Emacs; see the file COPYING. If not, write to the | 20 ;; along with GNU Emacs; see the file COPYING. If not, write to the |
19 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 21 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 ;; Boston, MA 02111-1307, USA. | 22 ;; Boston, MA 02110-1301, USA. |
21 | 23 |
22 ;;; Commentary: | 24 ;;; Commentary: |
23 | 25 |
24 ;;; Code: | 26 ;;; Code: |
25 | 27 |
32 (eval-and-compile | 34 (eval-and-compile |
33 (autoload 'gnus-article-prepare-display "gnus-art") | 35 (autoload 'gnus-article-prepare-display "gnus-art") |
34 (autoload 'vcard-parse-string "vcard") | 36 (autoload 'vcard-parse-string "vcard") |
35 (autoload 'vcard-format-string "vcard") | 37 (autoload 'vcard-format-string "vcard") |
36 (autoload 'fill-flowed "flow-fill") | 38 (autoload 'fill-flowed "flow-fill") |
39 (autoload 'html2text "html2text") | |
37 (unless (fboundp 'diff-mode) | 40 (unless (fboundp 'diff-mode) |
38 (autoload 'diff-mode "diff-mode" "" t nil))) | 41 (autoload 'diff-mode "diff-mode" "" t nil))) |
42 | |
43 (defvar gnus-article-mime-handles) | |
44 (defvar gnus-newsgroup-charset) | |
45 (defvar smime-keys) | |
46 (defvar w3m-cid-retrieve-function-alist) | |
47 (defvar w3m-current-buffer) | |
48 (defvar w3m-display-inline-images) | |
49 (defvar w3m-minor-mode-map) | |
50 | |
51 (defvar mm-text-html-renderer-alist | |
52 '((w3 . mm-inline-text-html-render-with-w3) | |
53 (w3m . mm-inline-text-html-render-with-w3m) | |
54 (w3m-standalone mm-inline-render-with-stdin nil | |
55 "w3m" "-dump" "-T" "text/html") | |
56 (links mm-inline-render-with-file | |
57 mm-links-remove-leading-blank | |
58 "links" "-dump" file) | |
59 (lynx mm-inline-render-with-stdin nil | |
60 "lynx" "-dump" "-force_html" "-stdin" "-nolist") | |
61 (html2text mm-inline-render-with-function html2text)) | |
62 "The attributes of renderer types for text/html.") | |
63 | |
64 (defvar mm-text-html-washer-alist | |
65 '((w3 . gnus-article-wash-html-with-w3) | |
66 (w3m . gnus-article-wash-html-with-w3m) | |
67 (w3m-standalone mm-inline-wash-with-stdin nil | |
68 "w3m" "-dump" "-T" "text/html") | |
69 (links mm-inline-wash-with-file | |
70 mm-links-remove-leading-blank | |
71 "links" "-dump" file) | |
72 (lynx mm-inline-wash-with-stdin nil | |
73 "lynx" "-dump" "-force_html" "-stdin" "-nolist") | |
74 (html2text html2text)) | |
75 "The attributes of washer types for text/html.") | |
76 | |
77 ;;; Internal variables. | |
39 | 78 |
40 ;;; | 79 ;;; |
41 ;;; Functions for displaying various formats inline | 80 ;;; Functions for displaying various formats inline |
42 ;;; | 81 ;;; |
82 | |
43 (defun mm-inline-image-emacs (handle) | 83 (defun mm-inline-image-emacs (handle) |
44 (let ((b (point-marker)) | 84 (let ((b (point-marker)) |
45 buffer-read-only) | 85 buffer-read-only) |
46 (insert "\n") | |
47 (put-image (mm-get-image handle) b) | 86 (put-image (mm-get-image handle) b) |
87 (insert "\n\n") | |
48 (mm-handle-set-undisplayer | 88 (mm-handle-set-undisplayer |
49 handle | 89 handle |
50 `(lambda () (remove-images ,b (1+ ,b)))))) | 90 `(lambda () |
91 (let ((b ,b) | |
92 buffer-read-only) | |
93 (remove-images b b) | |
94 (delete-region b (+ b 2))))))) | |
51 | 95 |
52 (defun mm-inline-image-xemacs (handle) | 96 (defun mm-inline-image-xemacs (handle) |
53 (insert "\n") | 97 (insert "\n\n") |
54 (forward-char -1) | 98 (forward-char -2) |
55 (let ((b (point)) | 99 (let ((annot (make-annotation (mm-get-image handle) nil 'text)) |
56 (annot (make-annotation (mm-get-image handle) nil 'text)) | |
57 buffer-read-only) | 100 buffer-read-only) |
58 (mm-handle-set-undisplayer | 101 (mm-handle-set-undisplayer |
59 handle | 102 handle |
60 `(lambda () | 103 `(lambda () |
61 (let (buffer-read-only) | 104 (let ((b ,(point-marker)) |
105 buffer-read-only) | |
62 (delete-annotation ,annot) | 106 (delete-annotation ,annot) |
63 (delete-region ,(set-marker (make-marker) b) | 107 (delete-region (- b 2) b)))) |
64 ,(set-marker (make-marker) (point)))))) | |
65 (set-extent-property annot 'mm t) | 108 (set-extent-property annot 'mm t) |
66 (set-extent-property annot 'duplicable t))) | 109 (set-extent-property annot 'duplicable t))) |
67 | 110 |
68 (eval-and-compile | 111 (eval-and-compile |
69 (if (featurep 'xemacs) | 112 (if (featurep 'xemacs) |
78 (require 'url) | 121 (require 'url) |
79 (require 'w3-vars) | 122 (require 'w3-vars) |
80 (require 'url-vars) | 123 (require 'url-vars) |
81 (setq mm-w3-setup t))) | 124 (setq mm-w3-setup t))) |
82 | 125 |
126 (defun mm-inline-text-html-render-with-w3 (handle) | |
127 (mm-setup-w3) | |
128 (let ((text (mm-get-part handle)) | |
129 (b (point)) | |
130 (url-standalone-mode t) | |
131 (url-gateway-unplugged t) | |
132 (w3-honor-stylesheets nil) | |
133 (url-current-object | |
134 (url-generic-parse-url (format "cid:%s" (mm-handle-id handle)))) | |
135 (width (window-width)) | |
136 (charset (mail-content-type-get | |
137 (mm-handle-type handle) 'charset))) | |
138 (save-excursion | |
139 (insert text) | |
140 (save-restriction | |
141 (narrow-to-region b (point)) | |
142 (goto-char (point-min)) | |
143 (if (or (and (boundp 'w3-meta-content-type-charset-regexp) | |
144 (re-search-forward | |
145 w3-meta-content-type-charset-regexp nil t)) | |
146 (and (boundp 'w3-meta-charset-content-type-regexp) | |
147 (re-search-forward | |
148 w3-meta-charset-content-type-regexp nil t))) | |
149 (setq charset | |
150 (or (let ((bsubstr (buffer-substring-no-properties | |
151 (match-beginning 2) | |
152 (match-end 2)))) | |
153 (if (fboundp 'w3-coding-system-for-mime-charset) | |
154 (w3-coding-system-for-mime-charset bsubstr) | |
155 (mm-charset-to-coding-system bsubstr))) | |
156 charset))) | |
157 (delete-region (point-min) (point-max)) | |
158 (insert (mm-decode-string text charset)) | |
159 (save-window-excursion | |
160 (save-restriction | |
161 (let ((w3-strict-width width) | |
162 ;; Don't let w3 set the global version of | |
163 ;; this variable. | |
164 (fill-column fill-column)) | |
165 (if (or debug-on-error debug-on-quit) | |
166 (w3-region (point-min) (point-max)) | |
167 (condition-case () | |
168 (w3-region (point-min) (point-max)) | |
169 (error | |
170 (delete-region (point-min) (point-max)) | |
171 (let ((b (point)) | |
172 (charset (mail-content-type-get | |
173 (mm-handle-type handle) 'charset))) | |
174 (if (or (eq charset 'gnus-decoded) | |
175 (eq mail-parse-charset 'gnus-decoded)) | |
176 (save-restriction | |
177 (narrow-to-region (point) (point)) | |
178 (mm-insert-part handle) | |
179 (goto-char (point-max))) | |
180 (insert (mm-decode-string (mm-get-part handle) | |
181 charset)))) | |
182 (message | |
183 "Error while rendering html; showing as text/plain"))))))) | |
184 (mm-handle-set-undisplayer | |
185 handle | |
186 `(lambda () | |
187 (let (buffer-read-only) | |
188 (if (functionp 'remove-specifier) | |
189 (mapcar (lambda (prop) | |
190 (remove-specifier | |
191 (face-property 'default prop) | |
192 (current-buffer))) | |
193 '(background background-pixmap foreground))) | |
194 (delete-region ,(point-min-marker) | |
195 ,(point-max-marker))))))))) | |
196 | |
197 (defvar mm-w3m-setup nil | |
198 "Whether gnus-article-mode has been setup to use emacs-w3m.") | |
199 | |
200 (defun mm-setup-w3m () | |
201 "Setup gnus-article-mode to use emacs-w3m." | |
202 (unless mm-w3m-setup | |
203 (require 'w3m) | |
204 (unless (assq 'gnus-article-mode w3m-cid-retrieve-function-alist) | |
205 (push (cons 'gnus-article-mode 'mm-w3m-cid-retrieve) | |
206 w3m-cid-retrieve-function-alist)) | |
207 (setq mm-w3m-setup t)) | |
208 (setq w3m-display-inline-images mm-inline-text-html-with-images)) | |
209 | |
210 (defun mm-w3m-cid-retrieve-1 (url handle) | |
211 (dolist (elem handle) | |
212 (when (listp elem) | |
213 (if (equal url (mm-handle-id elem)) | |
214 (progn | |
215 (mm-insert-part elem) | |
216 (throw 'found-handle (mm-handle-media-type elem)))) | |
217 (if (equal "multipart" (mm-handle-media-supertype elem)) | |
218 (mm-w3m-cid-retrieve-1 url elem))))) | |
219 | |
220 (defun mm-w3m-cid-retrieve (url &rest args) | |
221 "Insert a content pointed by URL if it has the cid: scheme." | |
222 (when (string-match "\\`cid:" url) | |
223 (catch 'found-handle | |
224 (mm-w3m-cid-retrieve-1 (concat "<" (substring url (match-end 0)) ">") | |
225 (with-current-buffer w3m-current-buffer | |
226 gnus-article-mime-handles))))) | |
227 | |
228 (defun mm-inline-text-html-render-with-w3m (handle) | |
229 "Render a text/html part using emacs-w3m." | |
230 (mm-setup-w3m) | |
231 (let ((text (mm-get-part handle)) | |
232 (b (point)) | |
233 (charset (mail-content-type-get (mm-handle-type handle) 'charset))) | |
234 (save-excursion | |
235 (insert (if charset (mm-decode-string text charset) text)) | |
236 (save-restriction | |
237 (narrow-to-region b (point)) | |
238 (unless charset | |
239 (goto-char (point-min)) | |
240 (when (setq charset (w3m-detect-meta-charset)) | |
241 (delete-region (point-min) (point-max)) | |
242 (insert (mm-decode-string text charset)))) | |
243 (let ((w3m-safe-url-regexp mm-w3m-safe-url-regexp) | |
244 w3m-force-redisplay) | |
245 (w3m-region (point-min) (point-max) nil charset)) | |
246 (when (and mm-inline-text-html-with-w3m-keymap | |
247 (boundp 'w3m-minor-mode-map) | |
248 w3m-minor-mode-map) | |
249 (add-text-properties | |
250 (point-min) (point-max) | |
251 (list 'keymap w3m-minor-mode-map | |
252 ;; Put the mark meaning this part was rendered by emacs-w3m. | |
253 'mm-inline-text-html-with-w3m t))) | |
254 (mm-handle-set-undisplayer | |
255 handle | |
256 `(lambda () | |
257 (let (buffer-read-only) | |
258 (if (functionp 'remove-specifier) | |
259 (mapcar (lambda (prop) | |
260 (remove-specifier | |
261 (face-property 'default prop) | |
262 (current-buffer))) | |
263 '(background background-pixmap foreground))) | |
264 (delete-region ,(point-min-marker) | |
265 ,(point-max-marker))))))))) | |
266 | |
267 (defun mm-links-remove-leading-blank () | |
268 ;; Delete the annoying three spaces preceding each line of links | |
269 ;; output. | |
270 (goto-char (point-min)) | |
271 (while (re-search-forward "^ " nil t) | |
272 (delete-region (match-beginning 0) (match-end 0)))) | |
273 | |
274 (defun mm-inline-wash-with-file (post-func cmd &rest args) | |
275 (let ((file (mm-make-temp-file | |
276 (expand-file-name "mm" mm-tmp-directory)))) | |
277 (let ((coding-system-for-write 'binary)) | |
278 (write-region (point-min) (point-max) file nil 'silent)) | |
279 (delete-region (point-min) (point-max)) | |
280 (unwind-protect | |
281 (apply 'call-process cmd nil t nil (mapcar 'eval args)) | |
282 (delete-file file)) | |
283 (and post-func (funcall post-func)))) | |
284 | |
285 (defun mm-inline-wash-with-stdin (post-func cmd &rest args) | |
286 (let ((coding-system-for-write 'binary)) | |
287 (apply 'call-process-region (point-min) (point-max) | |
288 cmd t t nil args)) | |
289 (and post-func (funcall post-func))) | |
290 | |
291 (defun mm-inline-render-with-file (handle post-func cmd &rest args) | |
292 (let ((source (mm-get-part handle))) | |
293 (mm-insert-inline | |
294 handle | |
295 (mm-with-unibyte-buffer | |
296 (insert source) | |
297 (apply 'mm-inline-wash-with-file post-func cmd args) | |
298 (buffer-string))))) | |
299 | |
300 (defun mm-inline-render-with-stdin (handle post-func cmd &rest args) | |
301 (let ((source (mm-get-part handle))) | |
302 (mm-insert-inline | |
303 handle | |
304 (mm-with-unibyte-buffer | |
305 (insert source) | |
306 (apply 'mm-inline-wash-with-stdin post-func cmd args) | |
307 (buffer-string))))) | |
308 | |
309 (defun mm-inline-render-with-function (handle func &rest args) | |
310 (let ((source (mm-get-part handle)) | |
311 (charset (mail-content-type-get (mm-handle-type handle) 'charset))) | |
312 (mm-insert-inline | |
313 handle | |
314 (mm-with-multibyte-buffer | |
315 (insert (if charset | |
316 (mm-decode-string source charset) | |
317 source)) | |
318 (apply func args) | |
319 (buffer-string))))) | |
320 | |
321 (defun mm-inline-text-html (handle) | |
322 (let* ((func (or mm-inline-text-html-renderer mm-text-html-renderer)) | |
323 (entry (assq func mm-text-html-renderer-alist)) | |
324 buffer-read-only) | |
325 (if entry | |
326 (setq func (cdr entry))) | |
327 (cond | |
328 ((functionp func) | |
329 (funcall func handle)) | |
330 (t | |
331 (apply (car func) handle (cdr func)))))) | |
332 | |
333 (defun mm-inline-text-vcard (handle) | |
334 (let (buffer-read-only) | |
335 (mm-insert-inline | |
336 handle | |
337 (concat "\n-- \n" | |
338 (ignore-errors | |
339 (if (fboundp 'vcard-pretty-print) | |
340 (vcard-pretty-print (mm-get-part handle)) | |
341 (vcard-format-string | |
342 (vcard-parse-string (mm-get-part handle) | |
343 'vcard-standard-filter)))))))) | |
344 | |
83 (defun mm-inline-text (handle) | 345 (defun mm-inline-text (handle) |
84 (let ((type (mm-handle-media-subtype handle)) | 346 (let ((b (point)) |
85 text buffer-read-only) | 347 (type (mm-handle-media-subtype handle)) |
86 (cond | 348 (charset (mail-content-type-get |
87 ((equal type "html") | 349 (mm-handle-type handle) 'charset)) |
88 (mm-setup-w3) | 350 buffer-read-only) |
89 (setq text (mm-get-part handle)) | 351 (if (or (eq charset 'gnus-decoded) |
90 (let ((b (point)) | 352 ;; This is probably not entirely correct, but |
91 (url-standalone-mode t) | 353 ;; makes rfc822 parts with embedded multiparts work. |
92 (url-gateway-unplugged t) | 354 (eq mail-parse-charset 'gnus-decoded)) |
93 (url-current-object | 355 (save-restriction |
94 (url-generic-parse-url (format "cid:%s" (mm-handle-id handle)))) | 356 (narrow-to-region (point) (point)) |
95 (width (window-width)) | 357 (mm-insert-part handle) |
96 (charset (mail-content-type-get | 358 (goto-char (point-max))) |
97 (mm-handle-type handle) 'charset))) | 359 (insert (mm-decode-string (mm-get-part handle) charset))) |
98 (save-excursion | 360 (when (and (equal type "plain") |
99 (insert text) | 361 (equal (cdr (assoc 'format (mm-handle-type handle))) |
100 (save-restriction | 362 "flowed")) |
101 (narrow-to-region b (point)) | 363 (save-restriction |
102 (goto-char (point-min)) | 364 (narrow-to-region b (point)) |
103 (if (or (and (boundp 'w3-meta-content-type-charset-regexp) | 365 (goto-char b) |
104 (re-search-forward | 366 (fill-flowed) |
105 w3-meta-content-type-charset-regexp nil t)) | 367 (goto-char (point-max)))) |
106 (and (boundp 'w3-meta-charset-content-type-regexp) | 368 (save-restriction |
107 (re-search-forward | 369 (narrow-to-region b (point)) |
108 w3-meta-charset-content-type-regexp nil t))) | 370 (when (or (equal type "enriched") |
109 (setq charset | 371 (equal type "richtext")) |
110 (or (let ((bsubstr (buffer-substring-no-properties | 372 (set-text-properties (point-min) (point-max) nil) |
111 (match-beginning 2) | 373 (ignore-errors |
112 (match-end 2)))) | 374 (enriched-decode (point-min) (point-max)))) |
113 (if (fboundp 'w3-coding-system-for-mime-charset) | 375 (mm-handle-set-undisplayer |
114 (w3-coding-system-for-mime-charset bsubstr) | |
115 (mm-charset-to-coding-system bsubstr))) | |
116 charset))) | |
117 (delete-region (point-min) (point-max)) | |
118 (insert (mm-decode-string text charset)) | |
119 (save-window-excursion | |
120 (save-restriction | |
121 (let ((w3-strict-width width) | |
122 ;; Don't let w3 set the global version of | |
123 ;; this variable. | |
124 (fill-column fill-column)) | |
125 (condition-case var | |
126 (w3-region (point-min) (point-max)) | |
127 (error | |
128 (delete-region (point-min) (point-max)) | |
129 (let ((b (point)) | |
130 (charset (mail-content-type-get | |
131 (mm-handle-type handle) 'charset))) | |
132 (if (or (eq charset 'gnus-decoded) | |
133 (eq mail-parse-charset 'gnus-decoded)) | |
134 (save-restriction | |
135 (narrow-to-region (point) (point)) | |
136 (mm-insert-part handle) | |
137 (goto-char (point-max))) | |
138 (insert (mm-decode-string (mm-get-part handle) | |
139 charset)))) | |
140 (message | |
141 "Error while rendering html; showing as text/plain")))))) | |
142 (mm-handle-set-undisplayer | |
143 handle | |
144 `(lambda () | |
145 (let (buffer-read-only) | |
146 (if (functionp 'remove-specifier) | |
147 (mapcar (lambda (prop) | |
148 (remove-specifier | |
149 (face-property 'default prop) | |
150 (current-buffer))) | |
151 '(background background-pixmap foreground))) | |
152 (delete-region ,(point-min-marker) | |
153 ,(point-max-marker))))))))) | |
154 ((equal type "x-vcard") | |
155 (mm-insert-inline | |
156 handle | 376 handle |
157 (concat "\n-- \n" | 377 `(lambda () |
158 (ignore-errors | 378 (let (buffer-read-only) |
159 (if (fboundp 'vcard-pretty-print) | 379 (delete-region ,(point-min-marker) |
160 (vcard-pretty-print (mm-get-part handle)) | 380 ,(point-max-marker)))))))) |
161 (vcard-format-string | |
162 (vcard-parse-string (mm-get-part handle) | |
163 'vcard-standard-filter))))))) | |
164 (t | |
165 (let ((b (point)) | |
166 (charset (mail-content-type-get | |
167 (mm-handle-type handle) 'charset))) | |
168 (if (or (eq charset 'gnus-decoded) | |
169 ;; This is probably not entirely correct, but | |
170 ;; makes rfc822 parts with embedded multiparts work. | |
171 (eq mail-parse-charset 'gnus-decoded)) | |
172 (save-restriction | |
173 (narrow-to-region (point) (point)) | |
174 (mm-insert-part handle) | |
175 (goto-char (point-max))) | |
176 (insert (mm-decode-string (mm-get-part handle) charset))) | |
177 (when (and (equal type "plain") | |
178 (equal (cdr (assoc 'format (mm-handle-type handle))) | |
179 "flowed")) | |
180 (save-restriction | |
181 (narrow-to-region b (point)) | |
182 (goto-char b) | |
183 (fill-flowed) | |
184 (goto-char (point-max)))) | |
185 (save-restriction | |
186 (narrow-to-region b (point)) | |
187 (set-text-properties (point-min) (point-max) nil) | |
188 (when (or (equal type "enriched") | |
189 (equal type "richtext")) | |
190 (enriched-decode (point-min) (point-max))) | |
191 (mm-handle-set-undisplayer | |
192 handle | |
193 `(lambda () | |
194 (let (buffer-read-only) | |
195 (delete-region ,(point-min-marker) | |
196 ,(point-max-marker))))))))))) | |
197 | 381 |
198 (defun mm-insert-inline (handle text) | 382 (defun mm-insert-inline (handle text) |
199 "Insert TEXT inline from HANDLE." | 383 "Insert TEXT inline from HANDLE." |
200 (let ((b (point))) | 384 (let ((b (point))) |
201 (insert text) | 385 (insert text) |
213 (message "Not implemented")) | 397 (message "Not implemented")) |
214 | 398 |
215 (defun mm-w3-prepare-buffer () | 399 (defun mm-w3-prepare-buffer () |
216 (require 'w3) | 400 (require 'w3) |
217 (let ((url-standalone-mode t) | 401 (let ((url-standalone-mode t) |
218 (url-gateway-unplugged t)) | 402 (url-gateway-unplugged t) |
403 (w3-honor-stylesheets nil)) | |
219 (w3-prepare-buffer))) | 404 (w3-prepare-buffer))) |
220 | 405 |
221 (defun mm-view-message () | 406 (defun mm-view-message () |
222 (mm-enable-multibyte) | 407 (mm-enable-multibyte) |
223 (let (handles) | 408 (let (handles) |
226 (run-hooks 'gnus-article-decode-hook) | 411 (run-hooks 'gnus-article-decode-hook) |
227 (gnus-article-prepare-display) | 412 (gnus-article-prepare-display) |
228 (setq handles gnus-article-mime-handles)) | 413 (setq handles gnus-article-mime-handles)) |
229 (when handles | 414 (when handles |
230 (setq gnus-article-mime-handles | 415 (setq gnus-article-mime-handles |
231 (nconc gnus-article-mime-handles | 416 (mm-merge-handles gnus-article-mime-handles handles)))) |
232 (if (listp (car handles)) | |
233 handles (list handles)))))) | |
234 (fundamental-mode) | 417 (fundamental-mode) |
235 (goto-char (point-min))) | 418 (goto-char (point-min))) |
236 | 419 |
237 (defun mm-inline-message (handle) | 420 (defun mm-inline-message (handle) |
238 (let ((b (point)) | 421 (let ((b (point)) |
252 (let (gnus-article-mime-handles | 435 (let (gnus-article-mime-handles |
253 ;; disable prepare hook | 436 ;; disable prepare hook |
254 gnus-article-prepare-hook | 437 gnus-article-prepare-hook |
255 (gnus-newsgroup-charset | 438 (gnus-newsgroup-charset |
256 (or charset gnus-newsgroup-charset))) | 439 (or charset gnus-newsgroup-charset))) |
257 (run-hooks 'gnus-article-decode-hook) | 440 (let ((gnus-original-article-buffer (mm-handle-buffer handle))) |
441 (run-hooks 'gnus-article-decode-hook)) | |
258 (gnus-article-prepare-display) | 442 (gnus-article-prepare-display) |
259 (setq handles gnus-article-mime-handles)) | 443 (setq handles gnus-article-mime-handles)) |
260 (goto-char (point-min)) | 444 (goto-char (point-min)) |
261 (unless bolp | 445 (unless bolp |
262 (insert "\n")) | 446 (insert "\n")) |
264 (unless (bolp) | 448 (unless (bolp) |
265 (insert "\n")) | 449 (insert "\n")) |
266 (insert "----------\n\n") | 450 (insert "----------\n\n") |
267 (when handles | 451 (when handles |
268 (setq gnus-article-mime-handles | 452 (setq gnus-article-mime-handles |
269 (nconc gnus-article-mime-handles | 453 (mm-merge-handles gnus-article-mime-handles handles))) |
270 (if (listp (car handles)) | |
271 handles (list handles))))) | |
272 (mm-handle-set-undisplayer | 454 (mm-handle-set-undisplayer |
273 handle | 455 handle |
274 `(lambda () | 456 `(lambda () |
275 (let (buffer-read-only) | 457 (let (buffer-read-only) |
276 (if (fboundp 'remove-specifier) | 458 (if (fboundp 'remove-specifier) |
281 '(background background-pixmap foreground))) | 463 '(background background-pixmap foreground))) |
282 (delete-region ,(point-min-marker) ,(point-max-marker))))))))) | 464 (delete-region ,(point-min-marker) ,(point-max-marker))))))))) |
283 | 465 |
284 (defun mm-display-inline-fontify (handle mode) | 466 (defun mm-display-inline-fontify (handle mode) |
285 (let (text) | 467 (let (text) |
286 (with-temp-buffer | 468 ;; XEmacs @#$@ version of font-lock refuses to fully turn itself |
287 (mm-insert-part handle) | 469 ;; on for buffers whose name begins with " ". That's why we use |
288 (funcall mode) | 470 ;; save-current-buffer/get-buffer-create rather than |
289 (font-lock-fontify-buffer) | 471 ;; with-temp-buffer. |
290 (when (fboundp 'extent-list) | 472 (save-current-buffer |
291 (map-extents (lambda (ext ignored) | 473 (set-buffer (generate-new-buffer "*fontification*")) |
292 (set-extent-property ext 'duplicable t) | 474 (unwind-protect |
293 nil) | 475 (progn |
294 nil nil nil nil nil 'text-prop)) | 476 (buffer-disable-undo) |
295 (setq text (buffer-string))) | 477 (mm-insert-part handle) |
478 (require 'font-lock) | |
479 (let ((font-lock-maximum-size nil) | |
480 ;; Disable support modes, e.g., jit-lock, lazy-lock, etc. | |
481 (font-lock-mode-hook nil) | |
482 (font-lock-support-mode nil) | |
483 ;; I find font-lock a bit too verbose. | |
484 (font-lock-verbose nil)) | |
485 (funcall mode) | |
486 ;; The mode function might have already turned on font-lock. | |
487 (unless (symbol-value 'font-lock-mode) | |
488 (font-lock-fontify-buffer))) | |
489 ;; By default, XEmacs font-lock uses non-duplicable text | |
490 ;; properties. This code forces all the text properties | |
491 ;; to be copied along with the text. | |
492 (when (fboundp 'extent-list) | |
493 (map-extents (lambda (ext ignored) | |
494 (set-extent-property ext 'duplicable t) | |
495 nil) | |
496 nil nil nil nil nil 'text-prop)) | |
497 (setq text (buffer-string))) | |
498 (kill-buffer (current-buffer)))) | |
296 (mm-insert-inline handle text))) | 499 (mm-insert-inline handle text))) |
500 | |
501 ;; Shouldn't these functions check whether the user even wants to use | |
502 ;; font-lock? At least under XEmacs, this fontification is pretty | |
503 ;; much unconditional. Also, it would be nice to change for the size | |
504 ;; of the fontified region. | |
297 | 505 |
298 (defun mm-display-patch-inline (handle) | 506 (defun mm-display-patch-inline (handle) |
299 (mm-display-inline-fontify handle 'diff-mode)) | 507 (mm-display-inline-fontify handle 'diff-mode)) |
300 | 508 |
301 (defun mm-display-elisp-inline (handle) | 509 (defun mm-display-elisp-inline (handle) |
302 (mm-display-inline-fontify handle 'emacs-lisp-mode)) | 510 (mm-display-inline-fontify handle 'emacs-lisp-mode)) |
303 | 511 |
512 ;; id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) | |
513 ;; us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 } | |
514 (defvar mm-pkcs7-signed-magic | |
515 (mm-string-as-unibyte | |
516 (apply 'concat | |
517 (mapcar 'char-to-string | |
518 (list ?\x30 ?\x5c ?\x28 ?\x80 ?\x5c ?\x7c ?\x81 ?\x2e ?\x5c | |
519 ?\x7c ?\x82 ?\x2e ?\x2e ?\x5c ?\x7c ?\x83 ?\x2e ?\x2e | |
520 ?\x2e ?\x5c ?\x29 ?\x06 ?\x09 ?\x5c ?\x2a ?\x86 ?\x48 | |
521 ?\x86 ?\xf7 ?\x0d ?\x01 ?\x07 ?\x02))))) | |
522 | |
523 ;; id-envelopedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) | |
524 ;; us(840) rsadsi(113549) pkcs(1) pkcs7(7) 3 } | |
525 (defvar mm-pkcs7-enveloped-magic | |
526 (mm-string-as-unibyte | |
527 (apply 'concat | |
528 (mapcar 'char-to-string | |
529 (list ?\x30 ?\x5c ?\x28 ?\x80 ?\x5c ?\x7c ?\x81 ?\x2e ?\x5c | |
530 ?\x7c ?\x82 ?\x2e ?\x2e ?\x5c ?\x7c ?\x83 ?\x2e ?\x2e | |
531 ?\x2e ?\x5c ?\x29 ?\x06 ?\x09 ?\x5c ?\x2a ?\x86 ?\x48 | |
532 ?\x86 ?\xf7 ?\x0d ?\x01 ?\x07 ?\x03))))) | |
533 | |
534 (defun mm-view-pkcs7-get-type (handle) | |
535 (mm-with-unibyte-buffer | |
536 (mm-insert-part handle) | |
537 (cond ((looking-at mm-pkcs7-enveloped-magic) | |
538 'enveloped) | |
539 ((looking-at mm-pkcs7-signed-magic) | |
540 'signed) | |
541 (t | |
542 (error "Could not identify PKCS#7 type"))))) | |
543 | |
544 (defun mm-view-pkcs7 (handle) | |
545 (case (mm-view-pkcs7-get-type handle) | |
546 (enveloped (mm-view-pkcs7-decrypt handle)) | |
547 (signed (mm-view-pkcs7-verify handle)) | |
548 (otherwise (error "Unknown or unimplemented PKCS#7 type")))) | |
549 | |
550 (defun mm-view-pkcs7-verify (handle) | |
551 ;; A bogus implementation of PKCS#7. FIXME:: | |
552 (mm-insert-part handle) | |
553 (goto-char (point-min)) | |
554 (if (search-forward "Content-Type: " nil t) | |
555 (delete-region (point-min) (match-beginning 0))) | |
556 (goto-char (point-max)) | |
557 (if (re-search-backward "--\r?\n?" nil t) | |
558 (delete-region (match-end 0) (point-max))) | |
559 (goto-char (point-min)) | |
560 (while (search-forward "\r\n" nil t) | |
561 (replace-match "\n")) | |
562 (message "Verify signed PKCS#7 message is unimplemented.") | |
563 (sit-for 1) | |
564 t) | |
565 | |
566 (autoload 'gnus-completing-read-maybe-default "gnus-util" nil nil 'macro) | |
567 | |
568 (defun mm-view-pkcs7-decrypt (handle) | |
569 (insert-buffer-substring (mm-handle-buffer handle)) | |
570 (goto-char (point-min)) | |
571 (insert "MIME-Version: 1.0\n") | |
572 (mm-insert-headers "application/pkcs7-mime" "base64" "smime.p7m") | |
573 (smime-decrypt-region | |
574 (point-min) (point-max) | |
575 (if (= (length smime-keys) 1) | |
576 (cadar smime-keys) | |
577 (smime-get-key-by-email | |
578 (gnus-completing-read-maybe-default | |
579 (concat "Decipher using key" | |
580 (if smime-keys | |
581 (concat " (default " (caar smime-keys) "): ") | |
582 ": ")) | |
583 smime-keys nil nil nil nil (car-safe (car-safe smime-keys)))))) | |
584 (goto-char (point-min)) | |
585 (while (search-forward "\r\n" nil t) | |
586 (replace-match "\n")) | |
587 (goto-char (point-min))) | |
588 | |
304 (provide 'mm-view) | 589 (provide 'mm-view) |
305 | 590 |
591 ;;; arch-tag: b60e749a-d05c-47f2-bccd-bdaa59327cb2 | |
306 ;;; mm-view.el ends here | 592 ;;; mm-view.el ends here |