Revision: miles@gnu.org--gnu-2005/gnus--devo--0--patch-182
[gnus] / lisp / mm-extern.el
1 ;;; mm-extern.el --- showing message/external-body
2
3 ;; Copyright (C) 2000, 2001, 2002, 2003, 2004,
4 ;;   2005 Free Software Foundation, Inc.
5
6 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
7 ;; Keywords: message external-body
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published
13 ;; by the Free Software Foundation; either version 2, or (at your
14 ;; option) any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 ;; General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Commentary:
27
28 ;;; Code:
29
30 (eval-when-compile (require 'cl))
31
32 (require 'mm-util)
33 (require 'mm-decode)
34 (require 'mm-url)
35
36 (defvar mm-extern-function-alist
37   '((local-file . mm-extern-local-file)
38     (url . mm-extern-url)
39     (anon-ftp . mm-extern-anon-ftp)
40     (ftp . mm-extern-ftp)
41 ;;;     (tftp . mm-extern-tftp)
42     (mail-server . mm-extern-mail-server)
43 ;;;     (afs . mm-extern-afs))
44     ))
45
46 (defvar mm-extern-anonymous "anonymous")
47
48 (defun mm-extern-local-file (handle)
49   (erase-buffer)
50   (let ((name (cdr (assq 'name (cdr (mm-handle-type handle)))))
51         (coding-system-for-read mm-binary-coding-system))
52     (unless name
53       (error "The filename is not specified"))
54     (mm-disable-multibyte)
55     (if (file-exists-p name)
56         (mm-insert-file-contents name nil nil nil nil t)
57       (error "File %s is gone" name))))
58
59 (defun mm-extern-url (handle)
60   (erase-buffer)
61   (let ((url (cdr (assq 'url (cdr (mm-handle-type handle)))))
62         (name buffer-file-name)
63         (coding-system-for-read mm-binary-coding-system))
64     (unless url
65       (error "URL is not specified"))
66     (mm-with-unibyte-current-buffer
67       (mm-url-insert-file-contents url))
68     (mm-disable-multibyte)
69     (setq buffer-file-name name)))
70
71 (defun mm-extern-anon-ftp (handle)
72   (erase-buffer)
73   (let* ((params (cdr (mm-handle-type handle)))
74          (name (cdr (assq 'name params)))
75          (site (cdr (assq 'site params)))
76          (directory (cdr (assq 'directory params)))
77          (mode (cdr (assq 'mode params)))
78          (path (concat "/" (or mm-extern-anonymous
79                                (read-string (format "ID for %s: " site)))
80                        "@" site ":" directory "/" name))
81          (coding-system-for-read mm-binary-coding-system))
82     (unless name
83       (error "The filename is not specified"))
84     (mm-disable-multibyte)
85     (mm-insert-file-contents path nil nil nil nil t)))
86
87 (defun mm-extern-ftp (handle)
88   (let (mm-extern-anonymous)
89     (mm-extern-anon-ftp handle)))
90
91 (defun mm-extern-mail-server (handle)
92   (require 'message)
93   (let* ((params (cdr (mm-handle-type handle)))
94          (server (cdr (assq 'server params)))
95          (subject (or (cdr (assq 'subject params)) "none"))
96          (buf (current-buffer))
97          info)
98     (if (y-or-n-p (format "Send a request message to %s?" server))
99         (save-window-excursion
100           (message-mail server subject)
101           (message-goto-body)
102           (delete-region (point) (point-max))
103           (insert-buffer-substring buf)
104           (message "Requesting external body...")
105           (message-send-and-exit)
106           (setq info "Request is sent.")
107           (message info))
108       (setq info "Request is not sent."))
109     (goto-char (point-min))
110     (insert "[" info "]\n\n")))
111
112 ;;;###autoload
113 (defun mm-inline-external-body (handle &optional no-display)
114   "Show the external-body part of HANDLE.
115 This function replaces the buffer of HANDLE with a buffer contains
116 the entire message.
117 If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing."
118   (let* ((access-type (cdr (assq 'access-type
119                                  (cdr (mm-handle-type handle)))))
120          (func (cdr (assq (intern
121                            (downcase
122                             (or access-type
123                                 (error "Couldn't find access type"))))
124                           mm-extern-function-alist)))
125          gnus-displaying-mime buf
126          handles)
127     (unless (mm-handle-cache handle)
128       (unless func
129         (error "Access type (%s) is not supported" access-type))
130       (with-temp-buffer
131         (mm-insert-part handle)
132         (goto-char (point-max))
133         (insert "\n\n")
134         (setq handles (mm-dissect-buffer t)))
135       (unless (bufferp (car handles))
136         (mm-destroy-parts handles)
137         (error "Multipart external body is not supported"))
138       (save-excursion ;; single part
139         (set-buffer (setq buf (mm-handle-buffer handles)))
140         (let (good)
141           (unwind-protect
142               (progn
143                 (funcall func handle)
144                 (setq good t))
145             (unless good
146               (mm-destroy-parts handles))))
147         (mm-handle-set-cache handle handles))
148       (setq gnus-article-mime-handles
149             (mm-merge-handles gnus-article-mime-handles handles)))
150     (unless no-display
151       (save-excursion
152         (save-restriction
153           (narrow-to-region (point) (point))
154           (gnus-display-mime (mm-handle-cache handle))
155           (mm-handle-set-undisplayer
156            handle
157            `(lambda ()
158               (let (buffer-read-only)
159                 (condition-case nil
160                     ;; This is only valid on XEmacs.
161                     (mapcar (lambda (prop)
162                             (remove-specifier
163                              (face-property 'default prop) (current-buffer)))
164                             '(background background-pixmap foreground))
165                   (error nil))
166                 (delete-region ,(point-min-marker) ,(point-max-marker))))))))))
167
168 (provide 'mm-extern)
169
170 ;;; arch-tag: 9653808e-14d9-4172-86e6-adceaa05378e
171 ;;; mm-extern.el ends here