(char-int): New alias.
[elisp/flim.git] / mime-def.el
1 ;;; mime-def.el --- definition module about MIME -*- coding: iso-8859-4; -*-
2
3 ;; Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
4
5 ;; Author: MORIOKA Tomohiko <tomo@m17n.org>
6 ;; Keywords: definition, MIME, multimedia, mail, news
7
8 ;; This file is part of FLIM (Faithful Library about Internet Message).
9
10 ;; This program is free software; you can redistribute it and/or
11 ;; modify it under the terms of the GNU General Public License as
12 ;; published by the Free Software Foundation; either version 2, or (at
13 ;; your option) any later version.
14
15 ;; This program is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ;; General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Code:
26
27 (require 'custom)
28 (require 'mcharset)
29 (require 'alist)
30
31 (eval-when-compile
32   (require 'cl)   ; list*
33   (require 'luna) ; luna-arglist-to-arguments
34   )
35
36 (eval-and-compile
37   (defconst mime-library-product ["FLIM" (1 14 0) "Ninokuchi"]
38     "Product name, version number and code name of MIME-library package."))
39
40 (defmacro mime-product-name (product)
41   `(aref ,product 0))
42
43 (defmacro mime-product-version (product)
44   `(aref ,product 1))
45
46 (defmacro mime-product-code-name (product)
47   `(aref ,product 2))
48
49 (defconst mime-library-version
50   (eval-when-compile
51     (concat (mime-product-name mime-library-product) " "
52             (mapconcat #'number-to-string
53                        (mime-product-version mime-library-product) ".")
54             " - \"" (mime-product-code-name mime-library-product) "\"")))
55
56
57 ;;; @ variables
58 ;;;
59
60 (defgroup mime '((default-mime-charset custom-variable))
61   "Emacs MIME Interfaces"
62   :group 'news
63   :group 'mail)
64
65 (defcustom mime-uuencode-encoding-name-list '("x-uue" "x-uuencode")
66   "*List of encoding names for uuencode format."
67   :group 'mime
68   :type '(repeat string))
69
70
71 ;;; @ required functions
72 ;;;
73
74 (defsubst regexp-* (regexp)
75   (concat regexp "*"))
76
77 (defsubst regexp-or (&rest args)
78   (concat "\\(" (mapconcat (function identity) args "\\|") "\\)"))
79
80 (eval-when-compile (require 'static))
81
82 (static-if (and (featurep 'xemacs)
83                 (not (featurep 'utf-2000)))
84     (progn
85       (require 'pces)
86       (defalias 'binary-insert-file-contents 'insert-file-contents-as-binary)
87       (defalias 'binary-write-region 'write-region-as-binary))
88   (defalias 'binary-insert-file-contents 'insert-file-contents-literally)
89   (defun binary-write-region (start end filename
90                                     &optional append visit lockname)
91     "Like `write-region', q.v., but don't encode."
92     (let ((coding-system-for-write 'binary)
93           jka-compr-compression-info-list jam-zcat-filename-list)
94       (write-region start end filename append visit lockname)))
95   )
96
97 (or (fboundp 'char-int)
98     (defalias 'char-int 'identity))
99
100
101 ;;; @ about STD 11
102 ;;;
103
104 (eval-and-compile
105   (defconst std11-quoted-pair-regexp "\\\\.")
106   (defconst std11-non-qtext-char-list '(?\" ?\\ ?\r ?\n))
107   (defconst std11-qtext-regexp
108     (eval-when-compile
109       (concat "[^" std11-non-qtext-char-list "]"))))
110 (defconst std11-quoted-string-regexp
111   (eval-when-compile
112     (concat "\""
113             (regexp-*
114              (regexp-or std11-qtext-regexp std11-quoted-pair-regexp))
115             "\"")))
116
117
118 ;;; @ about MIME
119 ;;;
120
121 (eval-and-compile
122   (defconst mime-tspecial-char-list
123     '(?\] ?\[ ?\( ?\) ?< ?> ?@ ?, ?\; ?: ?\\ ?\" ?/ ?? ?=)))
124 (defconst mime-token-regexp
125   (eval-when-compile
126     (concat "[^" mime-tspecial-char-list "\000-\040]+")))
127 (defconst mime-charset-regexp mime-token-regexp)
128
129 (defconst mime-media-type/subtype-regexp
130   (concat mime-token-regexp "/" mime-token-regexp))
131
132
133 ;;; @@ base64 / B
134 ;;;
135
136 (defconst base64-token-regexp "[A-Za-z0-9+/]")
137 (defconst base64-token-padding-regexp "[A-Za-z0-9+/=]")
138
139 (defconst B-encoded-text-regexp
140   (concat "\\(\\("
141           base64-token-regexp
142           base64-token-regexp
143           base64-token-regexp
144           base64-token-regexp
145           "\\)*"
146           base64-token-regexp
147           base64-token-regexp
148           base64-token-padding-regexp
149           base64-token-padding-regexp
150           "\\)"))
151
152 ;; (defconst eword-B-encoding-and-encoded-text-regexp
153 ;;   (concat "\\(B\\)\\?" eword-B-encoded-text-regexp))
154
155
156 ;;; @@ Quoted-Printable / Q
157 ;;;
158
159 (defconst quoted-printable-hex-chars "0123456789ABCDEF")
160
161 (defconst quoted-printable-octet-regexp
162   (concat "=[" quoted-printable-hex-chars
163           "][" quoted-printable-hex-chars "]"))
164
165 (defconst Q-encoded-text-regexp
166   (concat "\\([^=?]\\|" quoted-printable-octet-regexp "\\)+"))
167
168 ;; (defconst eword-Q-encoding-and-encoded-text-regexp
169 ;;   (concat "\\(Q\\)\\?" eword-Q-encoded-text-regexp))
170
171
172 ;;; @ Content-Type
173 ;;;
174
175 (defsubst make-mime-content-type (type subtype &optional parameters)
176   (list* (cons 'type type)
177          (cons 'subtype subtype)
178          (nreverse parameters))
179   )
180
181 (defsubst mime-content-type-primary-type (content-type)
182   "Return primary-type of CONTENT-TYPE."
183   (cdr (car content-type)))
184
185 (defsubst mime-content-type-subtype (content-type)
186   "Return primary-type of CONTENT-TYPE."
187   (cdr (cadr content-type)))
188
189 (defsubst mime-content-type-parameters (content-type)
190   "Return primary-type of CONTENT-TYPE."
191   (cddr content-type))
192
193 (defsubst mime-content-type-parameter (content-type parameter)
194   "Return PARAMETER value of CONTENT-TYPE."
195   (cdr (assoc parameter (mime-content-type-parameters content-type))))
196
197
198 (defsubst mime-type/subtype-string (type &optional subtype)
199   "Return type/subtype string from TYPE and SUBTYPE."
200   (if type
201       (if subtype
202           (format "%s/%s" type subtype)
203         (format "%s" type))))
204
205
206 ;;; @ Content-Disposition
207 ;;;
208
209 (defsubst mime-content-disposition-type (content-disposition)
210   "Return disposition-type of CONTENT-DISPOSITION."
211   (cdr (car content-disposition)))
212
213 (defsubst mime-content-disposition-parameters (content-disposition)
214   "Return disposition-parameters of CONTENT-DISPOSITION."
215   (cdr content-disposition))
216
217 (defsubst mime-content-disposition-parameter (content-disposition parameter)
218   "Return PARAMETER value of CONTENT-DISPOSITION."
219   (cdr (assoc parameter (cdr content-disposition))))
220
221 (defsubst mime-content-disposition-filename (content-disposition)
222   "Return filename of CONTENT-DISPOSITION."
223   (mime-content-disposition-parameter content-disposition "filename"))
224
225
226 ;;; @ message structure
227 ;;;
228
229 (defvar mime-message-structure nil
230   "Information about structure of message.
231 Please use reference function `mime-entity-SLOT' to get value of SLOT.
232
233 Following is a list of slots of the structure:
234
235 node-id                 node-id (list of integers)
236 content-type            content-type (content-type)
237 content-disposition     content-disposition (content-disposition)
238 encoding                Content-Transfer-Encoding (string or nil)
239 children                entities included in this entity (list of entity)
240
241 If an entity includes other entities in its body, such as multipart or
242 message/rfc822, `mime-entity' structures of them are included in
243 `children', so the `mime-entity' structure become a tree.")
244
245 (make-variable-buffer-local 'mime-message-structure)
246
247 (make-obsolete-variable 'mime-message-structure "should not use it.")
248
249
250 ;;; @ for mel-backend
251 ;;;
252
253 (defvar mel-service-list nil)
254
255 (defmacro mel-define-service (name &optional args &rest rest)
256   "Define NAME as a service for Content-Transfer-Encodings.
257 If ARGS is specified, NAME is defined as a generic function for the
258 service."
259   `(progn
260      (add-to-list 'mel-service-list ',name)
261      (defvar ,(intern (format "%s-obarray" name)) (make-vector 7 0))
262      ,@(if args
263            `((defun ,name ,args
264                ,@rest
265                (funcall (mel-find-function ',name ,(car (last args)))
266                         ,@(luna-arglist-to-arguments (butlast args)))
267                )))
268      ))
269
270 (put 'mel-define-service 'lisp-indent-function 'defun)
271
272
273 (defvar mel-encoding-module-alist nil)
274
275 (defsubst mel-find-function-from-obarray (ob-array encoding)
276   (let* ((f (intern-soft encoding ob-array)))
277     (or f
278         (let ((rest (cdr (assoc encoding mel-encoding-module-alist))))
279           (while (and rest
280                       (progn
281                         (require (car rest))
282                         (null (setq f (intern-soft encoding ob-array)))
283                         ))
284             (setq rest (cdr rest))
285             )
286           f))))
287
288 (defsubst mel-copy-method (service src-backend dst-backend)
289   (let* ((oa (symbol-value (intern (format "%s-obarray" service))))
290          (f (mel-find-function-from-obarray oa src-backend))
291          sym)
292     (when f
293       (setq sym (intern dst-backend oa))
294       (or (fboundp sym)
295           (fset sym (symbol-function f))
296           ))))
297        
298 (defsubst mel-copy-backend (src-backend dst-backend)
299   (let ((services mel-service-list))
300     (while services
301       (mel-copy-method (car services) src-backend dst-backend)
302       (setq services (cdr services)))))
303
304 (defmacro mel-define-backend (type &optional parents)
305   "Define TYPE as a mel-backend.
306 If PARENTS is specified, TYPE inherits PARENTS.
307 Each parent must be backend name (string)."
308   (cons 'progn
309         (mapcar (lambda (parent)
310                   `(mel-copy-backend ,parent ,type)
311                   )
312                 parents)))
313
314 (defmacro mel-define-method (name args &rest body)
315   "Define NAME as a method function of (nth 1 (car (last ARGS))) backend.
316 ARGS is like an argument list of lambda, but (car (last ARGS)) must be
317 specialized parameter.  (car (car (last ARGS))) is name of variable
318 and (nth 1 (car (last ARGS))) is name of backend (encoding)."
319   (let* ((specializer (car (last args)))
320          (class (nth 1 specializer)))
321     `(progn
322        (mel-define-service ,name)
323        (fset (intern ,class ,(intern (format "%s-obarray" name)))
324              (lambda ,(butlast args)
325                ,@body)))))
326
327 (put 'mel-define-method 'lisp-indent-function 'defun)
328
329 (defmacro mel-define-method-function (spec function)
330   "Set SPEC's function definition to FUNCTION.
331 First element of SPEC is service.
332 Rest of ARGS is like an argument list of lambda, but (car (last ARGS))
333 must be specialized parameter.  (car (car (last ARGS))) is name of
334 variable and (nth 1 (car (last ARGS))) is name of backend (encoding)."
335   (let* ((name (car spec))
336          (args (cdr spec))
337          (specializer (car (last args)))
338          (class (nth 1 specializer)))
339     `(let (sym)
340        (mel-define-service ,name)
341        (setq sym (intern ,class ,(intern (format "%s-obarray" name))))
342        (or (fboundp sym)
343            (fset sym (symbol-function ,function))))))
344
345 (defmacro mel-define-function (function spec)
346   (let* ((name (car spec))
347          (args (cdr spec))
348          (specializer (car (last args)))
349          (class (nth 1 specializer)))
350     `(progn
351        (define-function ,function
352          (intern ,class ,(intern (format "%s-obarray" name))))
353        )))
354
355 (defvar base64-dl-module
356   (if (and (fboundp 'base64-encode-string)
357            (subrp (symbol-function 'base64-encode-string)))
358       nil
359     (if (fboundp 'dynamic-link)
360         (let ((path (expand-file-name "base64.so" exec-directory)))
361           (and (file-exists-p path)
362                path)
363           ))))
364
365
366 ;;; @ end
367 ;;;
368
369 (provide 'mime-def)
370
371 ;;; mime-def.el ends here