1 ;;; mmimap.el --- MIME entity module for IMAP4rev1 (RFC2060).
2 ;; **** This is EXPERIMENTAL *****
4 ;; Copyright (C) 2000 Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
7 ;; Keywords: IMAP, MIME, multimedia, mail, news
9 ;; This file is part of FLIM (Faithful Library about Internet Message).
11 ;; This program is free software; you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation; either version 2, or (at
14 ;; your option) any later version.
16 ;; This program 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.
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., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
38 (luna-define-class mime-imap-entity (mime-entity)
39 (size header-string body-string new))
40 (luna-define-internal-accessors 'mime-imap-entity))
42 ;;; @ MIME IMAP location
43 ;; It should contain server, mailbox and uid (sequence number).
45 (luna-define-class mime-imap-location () ()))
47 (luna-define-generic mime-imap-location-section-body (location section)
48 "Return a body string from LOCATION which corresponds to SECTION.
49 SECTION is a section string which is defined in RFC2060.")
51 (luna-define-generic mime-imap-location-bodystructure (location)
52 "Return a parsed bodystructure of LOCATION.
53 `NIL' should be converted to nil, `astring' should be converted to a string.")
58 (defun mmimap-entity-section (node-id)
59 "Return a section string from NODE-ID"
62 (number-to-string (1+ node-id)))
65 'mmimap-entity-section
69 (static-if (fboundp 'mime-decode-parameters)
70 (defalias 'mmimap-parse-parameters-from-list 'mime-decode-parameters)
71 (defun mmimap-parse-parameters-from-list (attrlist)
72 "Parse parameters from ATTRLIST."
75 (setq ret-val (append ret-val
76 (list (cons (downcase (car attrlist))
77 (car (cdr attrlist))))))
78 (setq attrlist (cdr (cdr attrlist))))
81 (defun mmimap-make-mime-entity (bodystructure class location node-id number
83 "Analyze parsed IMAP4 BODYSTRUCTURE response and make MIME entity.
84 CLASS, LOCATION, NODE-ID, PARENT are set to the returned entity."
86 ((listp (car bodystructure)) ; multipart
88 curp children content-type entity)
95 :node-id (if (eq number 0)
97 (nconc (list number) node-id))
99 (while (and (setq curp (car bodystructure))
104 (mmimap-make-mime-entity curp class
108 (nconc (list number) node-id))
112 (setq bodystructure (cdr bodystructure)))
113 (mime-entity-set-children-internal entity children)
114 (setq content-type (list (cons 'type 'multipart)))
115 (if (car bodystructure)
116 (setq content-type (nconc content-type
121 bodystructure))))))))
122 (setq content-type (append content-type
123 (mmimap-parse-parameters-from-list
124 (nth 1 bodystructure))))
125 (mime-entity-set-content-type-internal entity content-type)
128 (let (content-type entity)
130 (list (cons 'type (intern (downcase (car bodystructure))))))
131 (if (nth 1 bodystructure)
132 (setq content-type (append content-type
137 (nth 1 bodystructure))))))))
138 (if (nth 2 bodystructure)
139 (setq content-type (append content-type
140 (mmimap-parse-parameters-from-list
141 (nth 2 bodystructure)))))
142 (setq node-id (nconc (list number) node-id))
147 :size (nth 6 bodystructure)
148 :content-type content-type
152 (mime-entity-set-content-type-internal entity content-type)
153 (mime-entity-set-encoding-internal entity
154 (and (nth 5 bodystructure)
156 (nth 5 bodystructure))))
157 (if (and (nth 7 bodystructure)
158 (nth 8 bodystructure)) ; children.
159 (mime-entity-set-children-internal
161 (list (mmimap-make-mime-entity
162 (nth 8 bodystructure) class
167 (luna-define-method initialize-instance :after ((entity mime-imap-entity)
169 ;; To prevent infinite loop...
170 (if (mime-imap-entity-new-internal entity)
172 (mmimap-make-mime-entity
173 (mime-imap-location-bodystructure
174 (mime-entity-location-internal entity))
175 (luna-class-name entity)
176 (mime-entity-location-internal entity)
182 (luna-define-method mime-insert-entity ((entity mime-imap-entity))
183 (if (mime-root-entity-p entity)
185 (insert (mime-imap-entity-header-string entity))
186 (mime-insert-entity-body entity))
187 ;; Insert body if it is not a multipart.
188 (unless (eq (mime-content-type-primary-type
189 (mime-entity-content-type entity))
191 (mime-insert-entity-body entity))))
193 (luna-define-method mime-write-entity ((entity mime-imap-entity) filename)
195 (mime-insert-entity entity)
196 (write-region-as-raw-text-CRLF (point-min) (point-max) filename)))
201 (luna-define-method mime-entity-body ((entity mime-imap-entity))
202 (or (mime-imap-entity-body-string-internal entity)
203 (mime-imap-entity-set-body-string-internal
205 (mime-imap-location-section-body
206 (mime-entity-location-internal entity)
207 (mmimap-entity-section
208 (mime-entity-node-id-internal entity))))))
210 (luna-define-method mime-insert-entity-body ((entity mime-imap-entity))
211 (insert (mime-entity-body entity)))
213 (luna-define-method mime-write-entity-body ((entity mime-imap-entity)
216 (mime-insert-entity-body entity)
217 (write-region-as-binary (point-min) (point-max) filename)))
222 (luna-define-method mime-entity-content ((entity mime-imap-entity))
223 (let ((ret (mime-entity-body entity)))
225 (mime-decode-string ret (mime-entity-encoding entity))
226 (message "Cannot decode content.")
229 (luna-define-method mime-insert-entity-content ((entity mime-imap-entity))
230 (insert (mime-entity-content entity)))
232 (luna-define-method mime-write-entity-content ((entity mime-imap-entity)
235 (mime-insert-entity-body entity)
236 (mime-write-decoded-region (point-min) (point-max)
238 (or (mime-entity-encoding entity) "7bit"))))
243 (defun mime-imap-entity-header-string (entity)
244 (or (mime-imap-entity-header-string-internal entity)
245 (mime-imap-entity-set-header-string-internal
247 (mime-imap-location-section-body
248 (mime-entity-location-internal entity)
249 (if (if (eq (car (mime-entity-node-id-internal entity)) 0)
250 (cdr (mime-entity-node-id-internal entity))
251 (mime-entity-node-id-internal entity))
252 (concat (mmimap-entity-section
253 (if (eq (car (mime-entity-node-id-internal entity)) 0)
254 (cdr (mime-entity-node-id-internal entity))
255 (mime-entity-node-id-internal entity)))
259 (luna-define-method mime-entity-fetch-field :around
260 ((entity mime-imap-entity) field-name)
261 (if (mime-root-entity-p entity)
262 (or (luna-call-next-method)
264 (insert (mime-imap-entity-header-string entity))
265 (let ((ret (std11-fetch-field field-name)))
267 (or (symbolp field-name)
269 (intern (capitalize (capitalize field-name)))))
270 (mime-entity-set-original-header-internal
272 (put-alist field-name ret
273 (mime-entity-original-header-internal entity)))
276 (luna-define-method mime-insert-header ((entity mime-imap-entity)
277 &optional invisible-fields
279 (let ((the-buf (current-buffer))
282 (insert (mime-imap-entity-header-string entity))
283 (setq buf (current-buffer)
287 (mime-insert-header-from-buffer buf p-min p-max
288 invisible-fields visible-fields))))
295 ;;; mmimap.el ends here