X-Git-Url: http://git.chise.org/gitweb/?p=elisp%2Fflim.git;a=blobdiff_plain;f=mime-def.el;h=9ee7781a1b555b1845872059433889722a88e474;hp=b8f4513a4f4ea9f35ebe5947ae126181585c6d08;hb=HEAD;hpb=b9214bcff9e185920d53dec4437f9d00350eb96c diff --git a/mime-def.el b/mime-def.el index b8f4513..9ee7781 100644 --- a/mime-def.el +++ b/mime-def.el @@ -1,8 +1,10 @@ -;;; mime-def.el --- definition module about MIME +;;; mime-def.el --- definition module about MIME -*- coding: iso-8859-4; -*- -;; Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc. +;; Copyright (C) 1995,96,97,98,99,2000,2001,2002,2003,2004,2005,2006 +;; Free Software Foundation, Inc. -;; Author: MORIOKA Tomohiko +;; Author: MORIOKA Tomohiko +;; Shuhei KOBAYASHI ;; Keywords: definition, MIME, multimedia, mail, news ;; This file is part of FLIM (Faithful Library about Internet Message). @@ -19,69 +21,108 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. ;;; Code: -(defconst mime-library-version-string "FLIM 1.8.1 - \"Kutsukawa\"") +(require 'custom) +(require 'mcharset) +(require 'alist) +(eval-when-compile (require 'luna)) ; luna-arglist-to-arguments -;;; @ variables -;;; +(eval-and-compile + (defconst mime-library-product ["FLIM" (1 14 9) "Gojò"] + "Product name, version number and code name of MIME-library package.")) -(require 'custom) +(defmacro mime-product-name (product) + `(aref ,product 0)) + +(defmacro mime-product-version (product) + `(aref ,product 1)) + +(defmacro mime-product-code-name (product) + `(aref ,product 2)) + +(defconst mime-library-version + (eval-when-compile + (concat (mime-product-name mime-library-product) " " + (mapconcat #'number-to-string + (mime-product-version mime-library-product) ".") + " - \"" (mime-product-code-name mime-library-product) "\""))) -(eval-when-compile (require 'cl)) -(defgroup mime nil +;;; @ variables +;;; + +(defgroup mime '((default-mime-charset custom-variable)) "Emacs MIME Interfaces" :group 'news :group 'mail) -(custom-handle-keyword 'default-mime-charset :group 'mime - 'custom-variable) - -(defcustom mime-temp-directory (or (getenv "MIME_TMP_DIR") - (getenv "TM_TMP_DIR") - (getenv "TMPDIR") - (getenv "TMP") - (getenv "TEMP") - "/tmp/") - "*Directory for temporary files." - :group 'mime - :type 'directory) - (defcustom mime-uuencode-encoding-name-list '("x-uue" "x-uuencode") "*List of encoding names for uuencode format." :group 'mime :type '(repeat string)) -;;; @ required functions +;;; @@ for encoded-word +;;; + +(defgroup mime-header nil + "Header representation, specially encoded-word" + :group 'mime) + +;;; @@@ decoding +;;; + +(defcustom mime-field-decoding-max-size 1000 + "*Max size to decode header field." + :group 'mime-header + :type '(choice (integer :tag "Limit (bytes)") + (const :tag "Don't limit" nil))) + +(defcustom mime-header-accept-quoted-encoded-words nil + "*Accept encoded-words in quoted-strings." + :group 'mime-header + :type 'boolean) + + +;;; @@@ encoding ;;; -(unless (fboundp 'butlast) - (defun butlast (x &optional n) - "Returns a copy of LIST with the last N elements removed." - (if (and n (<= n 0)) x - (nbutlast (copy-sequence x) n))) - - (defun nbutlast (x &optional n) - "Modifies LIST to remove the last N elements." - (let ((m (length x))) - (or n (setq n 1)) - (and (< n m) - (progn - (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil)) - x)))) - ) - -(defsubst eliminate-top-spaces (string) - "Eliminate top sequence of space or tab in STRING." - (if (string-match "^[ \t]+" string) - (substring string (match-end 0)) - string)) +(defcustom mime-field-encoding-method-alist + '(("X-Nsubject" . iso-2022-jp-2) + ("Newsgroups" . nil) + ("Message-ID" . nil) + (t . mime) + ) + "*Alist to specify field encoding method. +Its key is field-name, value is encoding method. + +If method is `mime', this field will be encoded into MIME format. + +If method is a MIME-charset, this field will be encoded as the charset +when it must be convert into network-code. + +If method is `default-mime-charset', this field will be encoded as +variable `default-mime-charset' when it must be convert into +network-code. + +If method is nil, this field will not be encoded." + :group 'mime-header + :type '(repeat (cons (choice :tag "Field" + (string :tag "Name") + (const :tag "Default" t)) + (choice :tag "Method" + (const :tag "MIME conversion" mime) + (symbol :tag "non-MIME conversion") + (const :tag "no-conversion" nil))))) + + +;;; @ required functions +;;; (defsubst regexp-* (regexp) (concat regexp "*")) @@ -89,33 +130,58 @@ (defsubst regexp-or (&rest args) (concat "\\(" (mapconcat (function identity) args "\\|") "\\)")) +(or (fboundp 'char-int) + (defalias 'char-int 'identity)) + -;;; @ about STD 11 +;;; @ MIME constants ;;; -(defconst std11-quoted-pair-regexp "\\\\.") -(defconst std11-non-qtext-char-list '(?\" ?\\ ?\r ?\n)) -(defconst std11-qtext-regexp - (concat "[^" (char-list-to-string std11-non-qtext-char-list) "]")) -(defconst std11-quoted-string-regexp - (concat "\"" - (regexp-* - (regexp-or std11-qtext-regexp std11-quoted-pair-regexp)) - "\"")) +(defconst mime-tspecial-char-list + '(?\] ?\[ ?\( ?\) ?< ?> ?@ ?, ?\; ?: ?\\ ?\" ?/ ?? ?=)) +(defconst mime-token-regexp + (concat "[^" mime-tspecial-char-list "\000-\040]+")) +(defconst mime-attribute-char-regexp + (concat "[^" mime-tspecial-char-list "\000-\040" + "*'%" ; introduced in RFC 2231. + "]")) +(defconst mime-charset-regexp + (concat "[^" mime-tspecial-char-list "\000-\040" + "*'%" ; should not include "%"? + "]+")) -;;; @ about MIME +;; More precisely, length of "[A-Za-z]+" is limited to at most 8. +;; (defconst mime-language-regexp "[A-Za-z]+\\(-[A-Za-z]+\\)*") +(defconst mime-language-regexp "[-A-Za-z]+") + +(defconst mime-encoding-regexp mime-token-regexp) + + +;;; @@ base64 / B ;;; -(defconst mime-tspecials "][()<>@,\;:\\\"/?=") -(defconst mime-token-regexp (concat "[^" mime-tspecials "\000-\040]+")) -(defconst mime-charset-regexp mime-token-regexp) +(defconst base64-token-regexp "[A-Za-z0-9+/]") +(defconst base64-token-padding-regexp "[A-Za-z0-9+/=]") -(defconst mime-media-type/subtype-regexp - (concat mime-token-regexp "/" mime-token-regexp)) +(defconst B-encoded-text-regexp + (concat "\\(\\(" + base64-token-regexp + base64-token-regexp + base64-token-regexp + base64-token-regexp + "\\)*" + base64-token-regexp + base64-token-regexp + base64-token-padding-regexp + base64-token-padding-regexp + "\\)")) +;; (defconst eword-B-encoding-and-encoded-text-regexp +;; (concat "\\(B\\)\\?" eword-B-encoded-text-regexp)) -;;; @@ Quoted-Printable + +;;; @@ Quoted-Printable / Q ;;; (defconst quoted-printable-hex-chars "0123456789ABCDEF") @@ -124,31 +190,36 @@ (concat "=[" quoted-printable-hex-chars "][" quoted-printable-hex-chars "]")) +(defconst Q-encoded-text-regexp + (concat "\\([^=?]\\|" quoted-printable-octet-regexp "\\)+")) + +;; (defconst eword-Q-encoding-and-encoded-text-regexp +;; (concat "\\(Q\\)\\?" eword-Q-encoded-text-regexp)) + ;;; @ Content-Type ;;; (defsubst make-mime-content-type (type subtype &optional parameters) - (list* (cons 'type type) - (cons 'subtype subtype) - (nreverse parameters)) - ) + (cons (cons 'type type) + (cons (cons 'subtype subtype) + parameters))) (defsubst mime-content-type-primary-type (content-type) "Return primary-type of CONTENT-TYPE." (cdr (car content-type))) (defsubst mime-content-type-subtype (content-type) - "Return primary-type of CONTENT-TYPE." - (cdr (cadr content-type))) + "Return subtype of CONTENT-TYPE." + (cdr (car (cdr content-type)))) (defsubst mime-content-type-parameters (content-type) - "Return primary-type of CONTENT-TYPE." - (cddr content-type)) + "Return parameters of CONTENT-TYPE." + (cdr (cdr content-type))) (defsubst mime-content-type-parameter (content-type parameter) "Return PARAMETER value of CONTENT-TYPE." - (cdr (assoc parameter (mime-content-type-parameters content-type)))) + (cdr (assoc parameter (cdr (cdr content-type))))) (defsubst mime-type/subtype-string (type &optional subtype) @@ -162,6 +233,10 @@ ;;; @ Content-Disposition ;;; +(defsubst make-mime-content-disposition (type &optional parameters) + (cons (cons 'type type) + parameters)) + (defsubst mime-content-disposition-type (content-disposition) "Return disposition-type of CONTENT-DISPOSITION." (cdr (car content-disposition))) @@ -179,55 +254,6 @@ (mime-content-disposition-parameter content-disposition "filename")) -;;; @ MIME entity -;;; - -(defsubst make-mime-entity-internal (representation-type - location - &optional content-type children - node-id - buffer - header-start header-end - body-start body-end) - (vector representation-type location - content-type children nil nil node-id - buffer header-start header-end body-start body-end - nil nil)) - -(defsubst mime-entity-representation-type-internal (entity) (aref entity 0)) -(defsubst mime-entity-location-internal (entity) (aref entity 1)) - -(defsubst mime-entity-content-type-internal (entity) (aref entity 2)) -(defsubst mime-entity-children-internal (entity) (aref entity 3)) -(defsubst mime-entity-content-disposition-internal (entity) (aref entity 4)) -(defsubst mime-entity-encoding-internal (entity) (aref entity 5)) -(defsubst mime-entity-node-id-internal (entity) (aref entity 6)) - -(defsubst mime-entity-buffer-internal (entity) (aref entity 7)) -(defsubst mime-entity-header-start-internal (entity) (aref entity 8)) -(defsubst mime-entity-header-end-internal (entity) (aref entity 9)) -(defsubst mime-entity-body-start-internal (entity) (aref entity 10)) -(defsubst mime-entity-body-end-internal (entity) (aref entity 11)) - -(defsubst mime-entity-original-header-internal (entity) (aref entity 12)) -(defsubst mime-entity-parsed-header-internal (entity) (aref entity 13)) - -(defsubst mime-entity-set-representation-type-internal (entity type) - (aset entity 0 type)) -(defsubst mime-entity-set-content-type-internal (entity type) - (aset entity 2 type)) -(defsubst mime-entity-set-children-internal (entity children) - (aset entity 3 children)) -(defsubst mime-entity-set-content-disposition-internal (entity disposition) - (aset entity 4 disposition)) -(defsubst mime-entity-set-encoding-internal (entity encoding) - (aset entity 5 encoding)) -(defsubst mime-entity-set-original-header-internal (entity header) - (aset entity 12 header)) -(defsubst mime-entity-set-parsed-header-internal (entity header) - (aset entity 13 header)) - - ;;; @ message structure ;;; @@ -237,12 +263,7 @@ Please use reference function `mime-entity-SLOT' to get value of SLOT. Following is a list of slots of the structure: -buffer buffer includes this entity (buffer). node-id node-id (list of integers) -header-start minimum point of header in raw-buffer -header-end maximum point of header in raw-buffer -body-start minimum point of body in raw-buffer -body-end maximum point of body in raw-buffer content-type content-type (content-type) content-disposition content-disposition (content-disposition) encoding Content-Transfer-Encoding (string or nil) @@ -254,6 +275,124 @@ message/rfc822, `mime-entity' structures of them are included in (make-variable-buffer-local 'mime-message-structure) +(make-obsolete-variable 'mime-message-structure "should not use it.") + + +;;; @ for mel-backend +;;; + +(defvar mel-service-list nil) + +(defmacro mel-define-service (name &optional args &rest rest) + "Define NAME as a service for Content-Transfer-Encodings. +If ARGS is specified, NAME is defined as a generic function for the +service." + `(progn + (add-to-list 'mel-service-list ',name) + (defvar ,(intern (format "%s-obarray" name)) (make-vector 7 0)) + ,@(if args + `((defun ,name ,args + ,@rest + (funcall (mel-find-function ',name ,(car (last args))) + ,@(luna-arglist-to-arguments (butlast args))) + ))) + )) + +(put 'mel-define-service 'lisp-indent-function 'defun) + + +(defvar mel-encoding-module-alist nil) + +(defsubst mel-find-function-from-obarray (ob-array encoding) + (let* ((f (intern-soft encoding ob-array))) + (or f + (let ((rest (cdr (assoc encoding mel-encoding-module-alist)))) + (while (and rest + (progn + (require (car rest)) + (null (setq f (intern-soft encoding ob-array))) + )) + (setq rest (cdr rest)) + ) + f)))) + +(defsubst mel-copy-method (service src-backend dst-backend) + (let* ((oa (symbol-value (intern (format "%s-obarray" service)))) + (f (mel-find-function-from-obarray oa src-backend)) + sym) + (when f + (setq sym (intern dst-backend oa)) + (or (fboundp sym) + (fset sym (symbol-function f)) + )))) + +(defsubst mel-copy-backend (src-backend dst-backend) + (let ((services mel-service-list)) + (while services + (mel-copy-method (car services) src-backend dst-backend) + (setq services (cdr services))))) + +(defmacro mel-define-backend (type &optional parents) + "Define TYPE as a mel-backend. +If PARENTS is specified, TYPE inherits PARENTS. +Each parent must be backend name (string)." + (cons 'progn + (mapcar (lambda (parent) + `(mel-copy-backend ,parent ,type) + ) + parents))) + +(defmacro mel-define-method (name args &rest body) + "Define NAME as a method function of (nth 1 (car (last ARGS))) backend. +ARGS is like an argument list of lambda, but (car (last ARGS)) must be +specialized parameter. (car (car (last ARGS))) is name of variable +and (nth 1 (car (last ARGS))) is name of backend (encoding)." + (let* ((specializer (car (last args))) + (class (nth 1 specializer))) + `(progn + (mel-define-service ,name) + (fset (intern ,class ,(intern (format "%s-obarray" name))) + (lambda ,(butlast args) + ,@body))))) + +(put 'mel-define-method 'lisp-indent-function 'defun) + +(defmacro mel-define-method-function (spec function) + "Set SPEC's function definition to FUNCTION. +First element of SPEC is service. +Rest of ARGS is like an argument list of lambda, but (car (last ARGS)) +must be specialized parameter. (car (car (last ARGS))) is name of +variable and (nth 1 (car (last ARGS))) is name of backend (encoding)." + (let* ((name (car spec)) + (args (cdr spec)) + (specializer (car (last args))) + (class (nth 1 specializer))) + `(let (sym) + (mel-define-service ,name) + (setq sym (intern ,class ,(intern (format "%s-obarray" name)))) + (or (fboundp sym) + (fset sym (symbol-function ,function)))))) + +(defmacro mel-define-function (function spec) + (let* ((name (car spec)) + (args (cdr spec)) + (specializer (car (last args))) + (class (nth 1 specializer))) + `(progn + (define-function ,function + (intern ,class ,(intern (format "%s-obarray" name)))) + ))) + +(defvar base64-dl-module + (if (and (fboundp 'base64-encode-string) + (subrp (symbol-function 'base64-encode-string))) + nil + (if (fboundp 'dynamic-link) + (let ((path (expand-file-name "base64.so" exec-directory))) + (and (file-exists-p path) + path) + )))) + ;;; @ end ;;;