(mime-content-type-subtype): Fix DOC.
[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 ;;; @@ for encoded-word
72 ;;;
73
74 (defgroup mime-header nil
75   "Header representation, specially encoded-word"
76   :group 'mime)
77
78 ;;; @@@ decoding
79 ;;;
80
81 (defcustom mime-field-decoding-max-size 1000
82   "*Max size to decode header field."
83   :group 'mime-header
84   :type '(choice (integer :tag "Limit (bytes)")
85                  (const :tag "Don't limit" nil)))
86
87 ;;; @@@ encoding
88 ;;;
89
90 (defcustom mime-field-encoding-method-alist
91   '(("X-Nsubject" . iso-2022-jp-2)
92     ("Newsgroups" . nil)
93     ("Message-ID" . nil)
94     (t            . mime)
95     )
96   "*Alist to specify field encoding method.
97 Its key is field-name, value is encoding method.
98
99 If method is `mime', this field will be encoded into MIME format.
100
101 If method is a MIME-charset, this field will be encoded as the charset
102 when it must be convert into network-code.
103
104 If method is `default-mime-charset', this field will be encoded as
105 variable `default-mime-charset' when it must be convert into
106 network-code.
107
108 If method is nil, this field will not be encoded."
109   :group 'mime-header
110   :type '(repeat (cons (choice :tag "Field"
111                                (string :tag "Name")
112                                (const :tag "Default" t))
113                        (choice :tag "Method"
114                                (const :tag "MIME conversion" mime)
115                                (symbol :tag "non-MIME conversion")
116                                (const :tag "no-conversion" nil)))))
117
118
119 ;;; @ required functions
120 ;;;
121
122 (defsubst regexp-* (regexp)
123   (concat regexp "*"))
124
125 (defsubst regexp-or (&rest args)
126   (concat "\\(" (mapconcat (function identity) args "\\|") "\\)"))
127
128 (or (fboundp 'char-int)
129     (defalias 'char-int 'identity))
130
131
132 ;;; @ about STD 11
133 ;;;
134
135 (eval-and-compile
136   (defconst std11-quoted-pair-regexp "\\\\.")
137   (defconst std11-non-qtext-char-list '(?\" ?\\ ?\r ?\n))
138   (defconst std11-qtext-regexp
139     (eval-when-compile
140       (concat "[^" std11-non-qtext-char-list "]"))))
141 (defconst std11-quoted-string-regexp
142   (eval-when-compile
143     (concat "\""
144             (regexp-*
145              (regexp-or std11-qtext-regexp std11-quoted-pair-regexp))
146             "\"")))
147
148
149 ;;; @ about MIME
150 ;;;
151
152 (eval-and-compile
153   (defconst mime-tspecial-char-list
154     '(?\] ?\[ ?\( ?\) ?< ?> ?@ ?, ?\; ?: ?\\ ?\" ?/ ?? ?=)))
155 (defconst mime-token-regexp
156   (eval-when-compile
157     (concat "[^" mime-tspecial-char-list "\000-\040]+")))
158 (defconst mime-charset-regexp mime-token-regexp)
159
160 (defconst mime-media-type/subtype-regexp
161   (concat mime-token-regexp "/" mime-token-regexp))
162
163
164 ;;; @@ base64 / B
165 ;;;
166
167 (defconst base64-token-regexp "[A-Za-z0-9+/]")
168 (defconst base64-token-padding-regexp "[A-Za-z0-9+/=]")
169
170 (defconst B-encoded-text-regexp
171   (concat "\\(\\("
172           base64-token-regexp
173           base64-token-regexp
174           base64-token-regexp
175           base64-token-regexp
176           "\\)*"
177           base64-token-regexp
178           base64-token-regexp
179           base64-token-padding-regexp
180           base64-token-padding-regexp
181           "\\)"))
182
183 ;; (defconst eword-B-encoding-and-encoded-text-regexp
184 ;;   (concat "\\(B\\)\\?" eword-B-encoded-text-regexp))
185
186
187 ;;; @@ Quoted-Printable / Q
188 ;;;
189
190 (defconst quoted-printable-hex-chars "0123456789ABCDEF")
191
192 (defconst quoted-printable-octet-regexp
193   (concat "=[" quoted-printable-hex-chars
194           "][" quoted-printable-hex-chars "]"))
195
196 (defconst Q-encoded-text-regexp
197   (concat "\\([^=?]\\|" quoted-printable-octet-regexp "\\)+"))
198
199 ;; (defconst eword-Q-encoding-and-encoded-text-regexp
200 ;;   (concat "\\(Q\\)\\?" eword-Q-encoded-text-regexp))
201
202
203 ;;; @ Content-Type
204 ;;;
205
206 (defsubst make-mime-content-type (type subtype &optional parameters)
207   (list* (cons 'type type)
208          (cons 'subtype subtype)
209          (nreverse parameters))
210   )
211
212 (defsubst mime-content-type-primary-type (content-type)
213   "Return primary-type of CONTENT-TYPE."
214   (cdr (car content-type)))
215
216 (defsubst mime-content-type-subtype (content-type)
217   "Return subtype of CONTENT-TYPE."
218   (cdr (cadr content-type)))
219
220 (defsubst mime-content-type-parameters (content-type)
221   "Return parameters of CONTENT-TYPE."
222   (cddr content-type))
223
224 (defsubst mime-content-type-parameter (content-type parameter)
225   "Return PARAMETER value of CONTENT-TYPE."
226   (cdr (assoc parameter (mime-content-type-parameters content-type))))
227
228
229 (defsubst mime-type/subtype-string (type &optional subtype)
230   "Return type/subtype string from TYPE and SUBTYPE."
231   (if type
232       (if subtype
233           (format "%s/%s" type subtype)
234         (format "%s" type))))
235
236
237 ;;; @ Content-Disposition
238 ;;;
239
240 (defsubst mime-content-disposition-type (content-disposition)
241   "Return disposition-type of CONTENT-DISPOSITION."
242   (cdr (car content-disposition)))
243
244 (defsubst mime-content-disposition-parameters (content-disposition)
245   "Return disposition-parameters of CONTENT-DISPOSITION."
246   (cdr content-disposition))
247
248 (defsubst mime-content-disposition-parameter (content-disposition parameter)
249   "Return PARAMETER value of CONTENT-DISPOSITION."
250   (cdr (assoc parameter (cdr content-disposition))))
251
252 (defsubst mime-content-disposition-filename (content-disposition)
253   "Return filename of CONTENT-DISPOSITION."
254   (mime-content-disposition-parameter content-disposition "filename"))
255
256
257 ;;; @ message structure
258 ;;;
259
260 (defvar mime-message-structure nil
261   "Information about structure of message.
262 Please use reference function `mime-entity-SLOT' to get value of SLOT.
263
264 Following is a list of slots of the structure:
265
266 node-id                 node-id (list of integers)
267 content-type            content-type (content-type)
268 content-disposition     content-disposition (content-disposition)
269 encoding                Content-Transfer-Encoding (string or nil)
270 children                entities included in this entity (list of entity)
271
272 If an entity includes other entities in its body, such as multipart or
273 message/rfc822, `mime-entity' structures of them are included in
274 `children', so the `mime-entity' structure become a tree.")
275
276 (make-variable-buffer-local 'mime-message-structure)
277
278 (make-obsolete-variable 'mime-message-structure "should not use it.")
279
280
281 ;;; @ for mel-backend
282 ;;;
283
284 (defvar mel-service-list nil)
285
286 (defmacro mel-define-service (name &optional args &rest rest)
287   "Define NAME as a service for Content-Transfer-Encodings.
288 If ARGS is specified, NAME is defined as a generic function for the
289 service."
290   `(progn
291      (add-to-list 'mel-service-list ',name)
292      (defvar ,(intern (format "%s-obarray" name)) (make-vector 7 0))
293      ,@(if args
294            `((defun ,name ,args
295                ,@rest
296                (funcall (mel-find-function ',name ,(car (last args)))
297                         ,@(luna-arglist-to-arguments (butlast args)))
298                )))
299      ))
300
301 (put 'mel-define-service 'lisp-indent-function 'defun)
302
303
304 (defvar mel-encoding-module-alist nil)
305
306 (defsubst mel-find-function-from-obarray (ob-array encoding)
307   (let* ((f (intern-soft encoding ob-array)))
308     (or f
309         (let ((rest (cdr (assoc encoding mel-encoding-module-alist))))
310           (while (and rest
311                       (progn
312                         (require (car rest))
313                         (null (setq f (intern-soft encoding ob-array)))
314                         ))
315             (setq rest (cdr rest))
316             )
317           f))))
318
319 (defsubst mel-copy-method (service src-backend dst-backend)
320   (let* ((oa (symbol-value (intern (format "%s-obarray" service))))
321          (f (mel-find-function-from-obarray oa src-backend))
322          sym)
323     (when f
324       (setq sym (intern dst-backend oa))
325       (or (fboundp sym)
326           (fset sym (symbol-function f))
327           ))))
328        
329 (defsubst mel-copy-backend (src-backend dst-backend)
330   (let ((services mel-service-list))
331     (while services
332       (mel-copy-method (car services) src-backend dst-backend)
333       (setq services (cdr services)))))
334
335 (defmacro mel-define-backend (type &optional parents)
336   "Define TYPE as a mel-backend.
337 If PARENTS is specified, TYPE inherits PARENTS.
338 Each parent must be backend name (string)."
339   (cons 'progn
340         (mapcar (lambda (parent)
341                   `(mel-copy-backend ,parent ,type)
342                   )
343                 parents)))
344
345 (defmacro mel-define-method (name args &rest body)
346   "Define NAME as a method function of (nth 1 (car (last ARGS))) backend.
347 ARGS is like an argument list of lambda, but (car (last ARGS)) must be
348 specialized parameter.  (car (car (last ARGS))) is name of variable
349 and (nth 1 (car (last ARGS))) is name of backend (encoding)."
350   (let* ((specializer (car (last args)))
351          (class (nth 1 specializer)))
352     `(progn
353        (mel-define-service ,name)
354        (fset (intern ,class ,(intern (format "%s-obarray" name)))
355              (lambda ,(butlast args)
356                ,@body)))))
357
358 (put 'mel-define-method 'lisp-indent-function 'defun)
359
360 (defmacro mel-define-method-function (spec function)
361   "Set SPEC's function definition to FUNCTION.
362 First element of SPEC is service.
363 Rest of ARGS is like an argument list of lambda, but (car (last ARGS))
364 must be specialized parameter.  (car (car (last ARGS))) is name of
365 variable and (nth 1 (car (last ARGS))) is name of backend (encoding)."
366   (let* ((name (car spec))
367          (args (cdr spec))
368          (specializer (car (last args)))
369          (class (nth 1 specializer)))
370     `(let (sym)
371        (mel-define-service ,name)
372        (setq sym (intern ,class ,(intern (format "%s-obarray" name))))
373        (or (fboundp sym)
374            (fset sym (symbol-function ,function))))))
375
376 (defmacro mel-define-function (function spec)
377   (let* ((name (car spec))
378          (args (cdr spec))
379          (specializer (car (last args)))
380          (class (nth 1 specializer)))
381     `(progn
382        (define-function ,function
383          (intern ,class ,(intern (format "%s-obarray" name))))
384        )))
385
386 (defvar base64-dl-module
387   (if (and (fboundp 'base64-encode-string)
388            (subrp (symbol-function 'base64-encode-string)))
389       nil
390     (if (fboundp 'dynamic-link)
391         (let ((path (expand-file-name "base64.so" exec-directory)))
392           (and (file-exists-p path)
393                path)
394           ))))
395
396
397 ;;; @ end
398 ;;;
399
400 (provide 'mime-def)
401
402 ;;; mime-def.el ends here