update cvs development method.
[elisp/flim.git] / mime-parse.el
index a61ec05..0072ad0 100644 (file)
@@ -3,6 +3,7 @@
 ;; Copyright (C) 1994,1995,1996,1997,1998,1999 Free Software Foundation, Inc.
 
 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;         Keiichi Suzuki <keiichi@nanap.org>
 ;; Keywords: parse, MIME, multimedia, mail, news
 
 ;; This file is part of SEMI (Spadework for Emacs MIME Interfaces).
 
 ;;; Code:
 
-(require 'std11)
 (require 'mime-def)
+(require 'std11)
 
-(eval-when-compile (require 'cl))
+(autoload 'mime-entity-body-buffer "mime")
+(autoload 'mime-entity-body-start-point "mime")
+(autoload 'mime-entity-body-end-point "mime")
 
 
 ;;; @ lexical analyzer
@@ -71,37 +74,96 @@ be the result."
 ;;; @ field parser
 ;;;
 
-(defconst mime/content-parameter-value-regexp
-  (concat "\\("
-         std11-quoted-string-regexp
-         "\\|[^; \t\n]*\\)"))
-
-(defconst mime::parameter-regexp
-  (concat "^[ \t]*\;[ \t]*\\(" mime-token-regexp "\\)"
-         "[ \t]*=[ \t]*\\(" mime/content-parameter-value-regexp "\\)"))
-
-(defun mime-parse-parameter (str)
-  (if (string-match mime::parameter-regexp str)
-      (let ((e (match-end 2)))
-       (cons
-        (cons (downcase (substring str (match-beginning 1) (match-end 1)))
-              (std11-strip-quoted-string
-               (substring str (match-beginning 2) e))
-              )
-        (substring str e)
-        ))))
-
+(defun mime-parse-parameters-skip-to-next-token (lrl)
+  (while (and lrl
+             (memq (caar lrl) '(comment spaces)))
+    (setq lrl (cdr lrl))
+    )
+  (if (eq (caar lrl) 'error)
+      nil
+    lrl))
+
+(defun mime-parse-parameters (str)
+  (let* ((lrl (std11-lexical-analyze str mime-lexical-analyzer))
+        (token (car lrl))
+        rest name val)
+    (while (and token
+               (eq (car token) 'tpecials)
+               (string= (cdr token) ";")
+               )
+      (if (and (setq lrl (mime-parse-parameters-skip-to-next-token
+                         (cdr lrl)
+                         ))
+              (setq name (cdar lrl))
+              (setq lrl (mime-parse-parameters-skip-to-next-token
+                         (cdr lrl)
+                         ))
+              (string= (cdar lrl) "=")
+              (setq lrl (mime-parse-parameters-skip-to-next-token
+                         (cdr lrl)
+                         ))
+              (setq val (if (eq (caar lrl) 'quoted-string)
+                            (std11-strip-quoted-pair (cdar lrl))
+                          (cdar lrl)
+                          )))
+         (setq lrl (mime-parse-parameters-skip-to-next-token (cdr lrl))
+               token (car lrl)
+               rest (cons val rest)
+               rest (cons name rest)
+               )
+       (setq token nil)))
+    (mime-parse-parameters-from-list rest)))
+
+(defun mime-parse-parameters-from-list (list)
+  (let (rest name val)
+    (while list
+      (let ((name (car list))
+           (val (cadr list)))
+       (setq list (cddr list))
+       (when (string-match "^\\([^*]+\\)\\(\\*\\([0-9]+\\)\\)?\\(\\*\\)?"
+                           name)
+         (let ((number (if (match-beginning 3)
+                           (string-to-int (substring name
+                                                     (match-beginning 3)
+                                                     (match-end 3)))
+                         0))
+               (encoded (if (match-beginning 4) t nil))
+               (parm (progn
+                       (setq name (downcase (substring name
+                                                       (match-beginning 1)
+                                                       (match-end 1))))
+                       (or (assoc name rest)
+                           (car (setq rest
+                                      (cons (make-mime-parameter name)
+                                            rest)))))))
+           (when (and (eq number 0)
+                      encoded
+                      (string-match "^\\([^']*\\)'\\([^']*\\)'\\(.*\\)" val))
+             (when (< (match-beginning 1) (match-end 1))
+               (mime-parameter-set-charset
+                parm
+                (intern (downcase (substring val
+                                             (match-beginning 1)
+                                             (match-end 1)
+                                             )))))
+             (when (< (match-beginning 2) (match-end 2))
+               (mime-parameter-set-language
+                parm
+                (intern (downcase (substring val
+                                             (match-beginning 2)
+                                             (match-end 2)
+                                             )))))
+             (setq val (substring val (match-beginning 3)))
+             )
+           (mime-parameter-append-raw-value parm number encoded val)))))
+      rest))
 
 ;;; @ Content-Type
 ;;;
 
 ;;;###autoload
 (defun mime-parse-Content-Type (string)
-  "Parse STRING as field-body of Content-Type field.
-Return value is
-    (PRIMARY-TYPE SUBTYPE (NAME1 . VALUE1)(NAME2 . VALUE2) ...)
-or nil.  PRIMARY-TYPE and SUBTYPE are symbol and NAME_n and VALUE_n
-are string."
+  "Parse STRING as field-body of Content-Type field."
   (setq string (std11-unfold-string string))
   (if (string-match `,(concat "^\\(" mime-token-regexp
                              "\\)/\\(" mime-token-regexp "\\)") string)
@@ -111,19 +173,14 @@ are string."
                       (substring string (match-beginning 2) (match-end 2))))
             ret dest)
        (setq string (substring string (match-end 0)))
-       (while (setq ret (mime-parse-parameter string))
-         (setq dest (cons (car ret) dest)
-               string (cdr ret))
-         )
        (make-mime-content-type (intern type)(intern subtype)
-                               (nreverse dest))
-       )))
+                               (nreverse (mime-parse-parameters string))
+                               ))))
 
 ;;;###autoload
 (defun mime-read-Content-Type ()
   "Read field-body of Content-Type field from current-buffer,
-and return parsed it.  Format of return value is as same as
-`mime-parse-Content-Type'."
+and return parsed it."
   (let ((str (std11-field-body "Content-Type")))
     (if str
        (mime-parse-Content-Type str)
@@ -147,12 +204,8 @@ and return parsed it.  Format of return value is as same as
             (type (downcase (substring string 0 e)))
             ret dest)
        (setq string (substring string e))
-       (while (setq ret (mime-parse-parameter string))
-         (setq dest (cons (car ret) dest)
-               string (cdr ret))
-         )
        (cons (cons 'type (intern type))
-             (nreverse dest))
+             (nreverse (mime-parse-parameters string)))
        )))
 
 ;;;###autoload
@@ -277,8 +330,8 @@ If is is not found, return DEFAULT-ENCODING."
    entity
    (with-current-buffer (mime-entity-body-buffer entity)
      (save-restriction
-       (narrow-to-region (mime-buffer-entity-body-start-internal entity)
-                        (mime-buffer-entity-body-end-internal entity))
+       (narrow-to-region (mime-entity-body-start-point entity)
+                        (mime-entity-body-end-point entity))
        (list (mime-parse-message
              (mime-entity-representation-type-internal entity) nil
              entity (cons 0 (mime-entity-node-id-internal entity))))
@@ -330,7 +383,8 @@ If buffer is omitted, it parses current-buffer."
   (save-excursion
     (if buffer (set-buffer buffer))
     (setq mime-message-structure
-         (mime-parse-message (or representation-type 'buffer) nil))
+         (mime-parse-message (or representation-type
+                                 'mime-buffer-entity) nil))
     ))