Require `custom' instead of `pcustom'.
[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 'poe)
28 (require 'poem)
29 (require 'custom)
30 (require 'mcharset)
31 (require 'alist)
32
33 (eval-when-compile
34   (require 'cl)   ; list*
35   (require 'luna) ; luna-arglist-to-arguments
36   )
37
38 (eval-and-compile
39   (defconst mime-library-product ["FLIM" (1 14 0) "Ninokuchi"]
40     "Product name, version number and code name of MIME-library package."))
41
42 (defmacro mime-product-name (product)
43   `(aref ,product 0))
44
45 (defmacro mime-product-version (product)
46   `(aref ,product 1))
47
48 (defmacro mime-product-code-name (product)
49   `(aref ,product 2))
50
51 (defconst mime-library-version
52   (eval-when-compile
53     (concat (mime-product-name mime-library-product) " "
54             (mapconcat #'number-to-string
55                        (mime-product-version mime-library-product) ".")
56             " - \"" (mime-product-code-name mime-library-product) "\"")))
57
58
59 ;;; @ variables
60 ;;;
61
62 (defgroup mime '((default-mime-charset custom-variable))
63   "Emacs MIME Interfaces"
64   :group 'news
65   :group 'mail)
66
67 (defcustom mime-uuencode-encoding-name-list '("x-uue" "x-uuencode")
68   "*List of encoding names for uuencode format."
69   :group 'mime
70   :type '(repeat string))
71
72
73 ;;; @ required functions
74 ;;;
75
76 (defsubst regexp-* (regexp)
77   (concat regexp "*"))
78
79 (defsubst regexp-or (&rest args)
80   (concat "\\(" (mapconcat (function identity) args "\\|") "\\)"))
81
82
83 ;;; @ about STD 11
84 ;;;
85
86 (eval-and-compile
87   (defconst std11-quoted-pair-regexp "\\\\.")
88   (defconst std11-non-qtext-char-list '(?\" ?\\ ?\r ?\n))
89   (defconst std11-qtext-regexp
90     (eval-when-compile
91       (concat "[^" std11-non-qtext-char-list "]"))))
92 (defconst std11-quoted-string-regexp
93   (eval-when-compile
94     (concat "\""
95             (regexp-*
96              (regexp-or std11-qtext-regexp std11-quoted-pair-regexp))
97             "\"")))
98
99
100 ;;; @ about MIME
101 ;;;
102
103 (eval-and-compile
104   (defconst mime-tspecial-char-list
105     '(?\] ?\[ ?\( ?\) ?< ?> ?@ ?, ?\; ?: ?\\ ?\" ?/ ?? ?=)))
106 (defconst mime-token-regexp
107   (eval-when-compile
108     (concat "[^" mime-tspecial-char-list "\000-\040]+")))
109 (defconst mime-charset-regexp mime-token-regexp)
110
111 (defconst mime-media-type/subtype-regexp
112   (concat mime-token-regexp "/" mime-token-regexp))
113
114
115 ;;; @@ base64 / B
116 ;;;
117
118 (defconst base64-token-regexp "[A-Za-z0-9+/]")
119 (defconst base64-token-padding-regexp "[A-Za-z0-9+/=]")
120
121 (defconst B-encoded-text-regexp
122   (concat "\\(\\("
123           base64-token-regexp
124           base64-token-regexp
125           base64-token-regexp
126           base64-token-regexp
127           "\\)*"
128           base64-token-regexp
129           base64-token-regexp
130           base64-token-padding-regexp
131           base64-token-padding-regexp
132           "\\)"))
133
134 ;; (defconst eword-B-encoding-and-encoded-text-regexp
135 ;;   (concat "\\(B\\)\\?" eword-B-encoded-text-regexp))
136
137
138 ;;; @@ Quoted-Printable / Q
139 ;;;
140
141 (defconst quoted-printable-hex-chars "0123456789ABCDEF")
142
143 (defconst quoted-printable-octet-regexp
144   (concat "=[" quoted-printable-hex-chars
145           "][" quoted-printable-hex-chars "]"))
146
147 (defconst Q-encoded-text-regexp
148   (concat "\\([^=?]\\|" quoted-printable-octet-regexp "\\)+"))
149
150 ;; (defconst eword-Q-encoding-and-encoded-text-regexp
151 ;;   (concat "\\(Q\\)\\?" eword-Q-encoded-text-regexp))
152
153
154 ;;; @ Content-Type
155 ;;;
156
157 (defsubst make-mime-content-type (type subtype &optional parameters)
158   (list* (cons 'type type)
159          (cons 'subtype subtype)
160          (nreverse parameters))
161   )
162
163 (defsubst mime-content-type-primary-type (content-type)
164   "Return primary-type of CONTENT-TYPE."
165   (cdr (car content-type)))
166
167 (defsubst mime-content-type-subtype (content-type)
168   "Return primary-type of CONTENT-TYPE."
169   (cdr (cadr content-type)))
170
171 (defsubst mime-content-type-parameters (content-type)
172   "Return primary-type of CONTENT-TYPE."
173   (cddr content-type))
174
175 (defsubst mime-content-type-parameter (content-type parameter)
176   "Return PARAMETER value of CONTENT-TYPE."
177   (cdr (assoc parameter (mime-content-type-parameters content-type))))
178
179
180 (defsubst mime-type/subtype-string (type &optional subtype)
181   "Return type/subtype string from TYPE and SUBTYPE."
182   (if type
183       (if subtype
184           (format "%s/%s" type subtype)
185         (format "%s" type))))
186
187
188 ;;; @ Content-Disposition
189 ;;;
190
191 (defsubst mime-content-disposition-type (content-disposition)
192   "Return disposition-type of CONTENT-DISPOSITION."
193   (cdr (car content-disposition)))
194
195 (defsubst mime-content-disposition-parameters (content-disposition)
196   "Return disposition-parameters of CONTENT-DISPOSITION."
197   (cdr content-disposition))
198
199 (defsubst mime-content-disposition-parameter (content-disposition parameter)
200   "Return PARAMETER value of CONTENT-DISPOSITION."
201   (cdr (assoc parameter (cdr content-disposition))))
202
203 (defsubst mime-content-disposition-filename (content-disposition)
204   "Return filename of CONTENT-DISPOSITION."
205   (mime-content-disposition-parameter content-disposition "filename"))
206
207
208 ;;; @ message structure
209 ;;;
210
211 (defvar mime-message-structure nil
212   "Information about structure of message.
213 Please use reference function `mime-entity-SLOT' to get value of SLOT.
214
215 Following is a list of slots of the structure:
216
217 node-id                 node-id (list of integers)
218 content-type            content-type (content-type)
219 content-disposition     content-disposition (content-disposition)
220 encoding                Content-Transfer-Encoding (string or nil)
221 children                entities included in this entity (list of entity)
222
223 If an entity includes other entities in its body, such as multipart or
224 message/rfc822, `mime-entity' structures of them are included in
225 `children', so the `mime-entity' structure become a tree.")
226
227 (make-variable-buffer-local 'mime-message-structure)
228
229 (make-obsolete-variable 'mime-message-structure "should not use it.")
230
231
232 ;;; @ for mel-backend
233 ;;;
234
235 (defvar mel-service-list nil)
236
237 (defmacro mel-define-service (name &optional args &rest rest)
238   "Define NAME as a service for Content-Transfer-Encodings.
239 If ARGS is specified, NAME is defined as a generic function for the
240 service."
241   `(progn
242      (add-to-list 'mel-service-list ',name)
243      (defvar ,(intern (format "%s-obarray" name)) (make-vector 7 0))
244      ,@(if args
245            `((defun ,name ,args
246                ,@rest
247                (funcall (mel-find-function ',name ,(car (last args)))
248                         ,@(luna-arglist-to-arguments (butlast args)))
249                )))
250      ))
251
252 (put 'mel-define-service 'lisp-indent-function 'defun)
253
254
255 (defvar mel-encoding-module-alist nil)
256
257 (defsubst mel-find-function-from-obarray (ob-array encoding)
258   (let* ((f (intern-soft encoding ob-array)))
259     (or f
260         (let ((rest (cdr (assoc encoding mel-encoding-module-alist))))
261           (while (and rest
262                       (progn
263                         (require (car rest))
264                         (null (setq f (intern-soft encoding ob-array)))
265                         ))
266             (setq rest (cdr rest))
267             )
268           f))))
269
270 (defsubst mel-copy-method (service src-backend dst-backend)
271   (let* ((oa (symbol-value (intern (format "%s-obarray" service))))
272          (f (mel-find-function-from-obarray oa src-backend))
273          sym)
274     (when f
275       (setq sym (intern dst-backend oa))
276       (or (fboundp sym)
277           (fset sym (symbol-function f))
278           ))))
279        
280 (defsubst mel-copy-backend (src-backend dst-backend)
281   (let ((services mel-service-list))
282     (while services
283       (mel-copy-method (car services) src-backend dst-backend)
284       (setq services (cdr services)))))
285
286 (defmacro mel-define-backend (type &optional parents)
287   "Define TYPE as a mel-backend.
288 If PARENTS is specified, TYPE inherits PARENTS.
289 Each parent must be backend name (string)."
290   (cons 'progn
291         (mapcar (lambda (parent)
292                   `(mel-copy-backend ,parent ,type)
293                   )
294                 parents)))
295
296 (defmacro mel-define-method (name args &rest body)
297   "Define NAME as a method function of (nth 1 (car (last ARGS))) backend.
298 ARGS is like an argument list of lambda, but (car (last ARGS)) must be
299 specialized parameter.  (car (car (last ARGS))) is name of variable
300 and (nth 1 (car (last ARGS))) is name of backend (encoding)."
301   (let* ((specializer (car (last args)))
302          (class (nth 1 specializer)))
303     `(progn
304        (mel-define-service ,name)
305        (fset (intern ,class ,(intern (format "%s-obarray" name)))
306              (lambda ,(butlast args)
307                ,@body)))))
308
309 (put 'mel-define-method 'lisp-indent-function 'defun)
310
311 (defmacro mel-define-method-function (spec function)
312   "Set SPEC's function definition to FUNCTION.
313 First element of SPEC is service.
314 Rest of ARGS is like an argument list of lambda, but (car (last ARGS))
315 must be specialized parameter.  (car (car (last ARGS))) is name of
316 variable and (nth 1 (car (last ARGS))) is name of backend (encoding)."
317   (let* ((name (car spec))
318          (args (cdr spec))
319          (specializer (car (last args)))
320          (class (nth 1 specializer)))
321     `(let (sym)
322        (mel-define-service ,name)
323        (setq sym (intern ,class ,(intern (format "%s-obarray" name))))
324        (or (fboundp sym)
325            (fset sym (symbol-function ,function))))))
326
327 (defmacro mel-define-function (function spec)
328   (let* ((name (car spec))
329          (args (cdr spec))
330          (specializer (car (last args)))
331          (class (nth 1 specializer)))
332     `(progn
333        (define-function ,function
334          (intern ,class ,(intern (format "%s-obarray" name))))
335        )))
336
337 (defvar base64-dl-module
338   (if (and (fboundp 'base64-encode-string)
339            (subrp (symbol-function 'base64-encode-string)))
340       nil
341     (if (fboundp 'dynamic-link)
342         (let ((path (expand-file-name "base64.so" exec-directory)))
343           (and (file-exists-p path)
344                path)
345           ))))
346
347
348 ;;; @ end
349 ;;;
350
351 (provide 'mime-def)
352
353 ;;; mime-def.el ends here