Update FSF's address in GPL notices.
[elisp/flim.git] / mime.el
diff --git a/mime.el b/mime.el
index f595961..562b9da 100644 (file)
--- a/mime.el
+++ b/mime.el
@@ -1,6 +1,6 @@
 ;;; mime.el --- MIME library module
 
-;; Copyright (C) 1998,1999,2000 Free Software Foundation, Inc.
+;; Copyright (C) 1998,1999,2000,2001,2003 Free Software Foundation, Inc.
 
 ;; Author: MORIOKA Tomohiko <tomo@m17n.org>
 ;; Keywords: MIME, multimedia, mail, news
@@ -19,8 +19,8 @@
 
 ;; 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:
 
@@ -65,6 +65,10 @@ current-buffer, and return it.")
 
 )
 
+(autoload 'mime-encode-field-body "eword-encode"
+  "Encode FIELD-BODY as FIELD-NAME, and return the result.")
+
+
 ;;; @ Entity Representation and Implementation
 ;;;
 
@@ -87,10 +91,12 @@ representation-type."
 ;;;
 
 (defun mime-entity-children (entity)
+  "Return list of entities included in the ENTITY."
   (or (mime-entity-children-internal entity)
       (luna-send entity 'mime-entity-children entity)))
 
 (defun mime-entity-node-id (entity)
+  "Return node-id of ENTITY."
   (mime-entity-node-id-internal entity))
 
 (defun mime-entity-number (entity)
@@ -138,10 +144,9 @@ If MESSAGE is specified, it is regarded as root entity."
 
 (defun mime-find-root-entity (entity)
   "Return root entity of ENTITY."
-  (let ((p (mime-entity-parent entity)))
-    (if (null p)
-       entity
-      (mime-entity-parent p))))
+  (while (not (mime-root-entity-p entity))
+    (setq entity (mime-entity-parent entity)))
+  entity)
 
 
 ;;; @ Header buffer (obsolete)
@@ -263,6 +268,7 @@ If MESSAGE is specified, it is regarded as root entity."
 ;; (make-obsolete 'mime-fetch-field 'mime-entity-fetch-field)
 
 (defun mime-entity-content-type (entity)
+  "Return content-type of ENTITY."
   (or (mime-entity-content-type-internal entity)
       (let ((ret (mime-entity-fetch-field entity "Content-Type")))
        (if ret
@@ -271,6 +277,7 @@ If MESSAGE is specified, it is regarded as root entity."
          ))))
 
 (defun mime-entity-content-disposition (entity)
+  "Return content-disposition of ENTITY."
   (or (mime-entity-content-disposition-internal entity)
       (let ((ret (mime-entity-fetch-field entity "Content-Disposition")))
        (if ret
@@ -279,6 +286,10 @@ If MESSAGE is specified, it is regarded as root entity."
          ))))
 
 (defun mime-entity-encoding (entity &optional default-encoding)
+  "Return content-transfer-encoding of ENTITY.
+If the ENTITY does not have Content-Transfer-Encoding field, this
+function returns DEFAULT-ENCODING.  If it is nil, \"7bit\" is used as
+default value."
   (or (mime-entity-encoding-internal entity)
       (let ((ret (mime-entity-fetch-field entity "Content-Transfer-Encoding")))
        (mime-entity-set-encoding-internal
@@ -321,7 +332,7 @@ If MESSAGE is specified, it is regarded as root entity."
                 (prog1
                     field-name
                   (setq field-name (symbol-name field-name)))
-              (intern (capitalize (capitalize field-name))))))
+              (intern (capitalize field-name)))))
     (cond ((eq sym 'Content-Type)
           (mime-entity-content-type entity)
           )
@@ -377,35 +388,195 @@ If MESSAGE is specified, it is regarded as root entity."
                (buffer-substring (match-beginning 0)(match-end 0))
              )))))
 
+;; unlimited patch by simm-emacs@fan.gr.jp
+;;   Mon, 10 Jan 2000 12:59:46 +0900
 (defun mime-entity-filename (entity)
   "Return filename of ENTITY."
-  (or (mime-entity-uu-filename entity)
-      (mime-content-disposition-filename
-       (mime-entity-content-disposition entity))
-      (cdr (let ((param (mime-content-type-parameters
-                        (mime-entity-content-type entity))))
-            (or (assoc "name" param)
-                (assoc "x-name" param))
-            ))))
+  (let ((filename
+        (or (mime-entity-uu-filename entity)
+            (mime-content-disposition-filename
+             (mime-entity-content-disposition entity))
+            (cdr (let ((param (mime-content-type-parameters
+                               (mime-entity-content-type entity))))
+                   (or (assoc "name" param)
+                       (assoc "x-name" param))))
+            "")))
+    (or (and mime-decode-unlimited
+            (string-match "\033" filename)
+            (decode-mime-charset-string filename 'iso-2022-jp 'CRLF))
+       (eword-decode-string filename))))
 
 
 (defsubst mime-entity-media-type (entity)
+  "Return primary media-type of ENTITY."
   (mime-content-type-primary-type (mime-entity-content-type entity)))
+
 (defsubst mime-entity-media-subtype (entity)
+  "Return media-subtype of ENTITY."
   (mime-content-type-subtype (mime-entity-content-type entity)))
+
 (defsubst mime-entity-parameters (entity)
+  "Return parameters of Content-Type of ENTITY."
   (mime-content-type-parameters (mime-entity-content-type entity)))
+
 (defsubst mime-entity-type/subtype (entity-info)
+  "Return type/subtype of Content-Type of ENTITY."
   (mime-type/subtype-string (mime-entity-media-type entity-info)
                            (mime-entity-media-subtype entity-info)))
 
 (defun mime-entity-set-content-type (entity content-type)
+  "Set ENTITY's content-type to CONTENT-TYPE."
   (mime-entity-set-content-type-internal entity content-type))
 
 (defun mime-entity-set-encoding (entity encoding)
+  "Set ENTITY's content-transfer-encoding to ENCODING."
   (mime-entity-set-encoding-internal entity encoding))
 
 
+;;; @ unlimited patch
+;;;
+
+;; unlimited patch by simm-emacs@fan.gr.jp (code derives from irchat-pj)
+;;   Tue, 01 Feb 2000 01:42:05 +0900
+(defun mime-detect-coding-system-region-unlimited (beg end)
+  "Detect coding system on region."
+  (let (ch esc prev flag)
+    (save-excursion
+      (catch 'detect
+       ;; check ISO-2022-JP / ascii
+       (catch 'quit
+         (goto-char beg)
+         (while (< (point) end)
+           (setq ch (following-char))
+           (and (<= 256 ch)
+                (throw 'detect nil)) ;;'noconv))
+           (and (<= 128 ch)
+                (throw 'quit t))
+           (and (= 27 ch)
+                (setq esc t))
+           (forward-char 1))
+         (throw 'detect (if esc 'iso-2022-jp nil))) ;;'noconv)))
+       ;; check EUC-JP / SHIFT-JIS
+       (if esc (throw 'detect 'iso-2022-jp))
+       (while (< (point) end)
+         (setq ch (following-char))
+         (or (and (= 27 ch)                        ;; ESC
+                  (throw 'detect 'iso-2022-jp))
+             (and (<= 128 ch) (<= ch 141)          ;; 0x80 <= ch <= 0x8d
+                  (throw 'detect 'shift_jis))
+             (and (<= 144 ch) (<= ch 159)          ;; 0x90 <= ch <= 0x9f
+                  (throw 'detect 'shift_jis))
+             (and (eq 'shift_jis prev) (<= ch 127) ;; second byte MSB == 0
+                  (throw 'detect 'shift_jis))
+             (and (eq 'euc-jp prev)
+                  (<= 161 ch) (<= ch 243)          ;; second byte of EUC Kana
+                  (setq prev nil
+                        flag 'euc-jp))
+             (and (eq nil prev)
+                  (or (= 164 ch) (= 165 ch))       ;; first byte of EUC kana
+                  (setq prev 'euc-jp))
+             (< ch 160)                            ;;         ch <= 0xa0
+             (and (eq 'euc-jp prev)
+                  (throw 'detect 'euc-jp))
+             (setq prev (if prev nil 'shift_jis)
+                   flag (if (eq 'euc-jp flag) 'euc-jp 'shift_jis)))
+         (forward-char 1))
+       flag))))
+       ;;(or flag 'noconv)))))
+
+;; unlimited patch by simm-emacs@fan.gr.jp
+;;   Tue, 01 Feb 2000 01:56:38 +0900
+(defun mime-detect-coding-system-string-unlimited (str)
+  "Detect coding system on string."
+  (save-excursion
+    (set-buffer (get-buffer-create " *Temporary unlimited*"))
+    (insert str)
+    (unwind-protect
+       (mime-detect-coding-system-region-unlimited (point-min) (point-max))
+      (kill-buffer nil))))
+
+;; unlimited patch by simm-emacs@fan.gr.jp
+;;   Tue, 01 Feb 2000 13:32:14 +0900
+(defsubst insert-unlimited (str)
+  "Insert with no-conversion.
+On GNU Emacs 20.*, (insert str) after (set-buffer-multibyte nil).
+Other environment, perform (insert str)."
+  (static-if (boundp 'nonascii-translation-table-unlimited)
+      (let ((nonascii-translation-table nonascii-translation-table-unlimited))
+       (insert str))
+    (insert str)))
+
+(defun decode-mime-charset-string-dist-unlimited (str charset &optional lbt)
+  "Detect coding system on string."
+  (if (not (eq 'auto-detect charset))
+      (decode-mime-charset-string str charset lbt)
+    (save-excursion
+      (set-buffer (get-buffer-create " *Temporary unlimited*"))
+      (unwind-protect
+         (let (code)
+           (insert-unlimited str)
+           (setq code (mime-detect-coding-system-region-unlimited (point-min) (point-max)))
+           (cond ((eq code 'euc-jp)
+                  (message "EUC-JP code detected, so convert this message."))
+                 ((eq code 'shift_jis)
+                  (message "SHIFT-JIS code detected, so convert this message.")))
+           (decode-mime-charset-region (point-min) (point-max)
+                                       (or code default-mime-charset)
+                                       lbt)
+           (buffer-substring (point-min) (point-max)))
+       (kill-buffer nil)))))
+
+(defun decode-mime-charset-string-unlimited (str charset &optional lbt)
+  "Detect coding system on string."
+  (cond ((eq 'auto-detect charset)
+        (save-excursion
+          (set-buffer (get-buffer-create " *Temporary unlimited*"))
+          (unwind-protect
+              (let (code)
+                (insert-unlimited str)
+                (setq code
+                      (mime-detect-coding-system-region-unlimited (point-min) (point-max)))
+                (cond ((eq code 'euc-jp)
+                       (message "EUC-JP code detected, so convert this message."))
+                      ((eq code 'shift_jis)
+                       (message "SHIFT-JIS code detected, so convert this message.")))
+                (decode-mime-charset-region (point-min) (point-max)
+                                            (or code default-mime-charset)
+                                            lbt)
+                (buffer-substring (point-min) (point-max)))
+            (kill-buffer nil))))
+       ((string= "us-ascii" charset)
+        (save-excursion
+          (set-buffer (get-buffer-create " *Temporary unlimited*"))
+          (unwind-protect
+              (let ((code 'us-ascii))
+                (insert-unlimited str)
+                (goto-char (point-min))
+                (while (not (eobp))
+                  (if (and (<= 32 (following-char)) (< (following-char) 128))
+                      (forward-char 1)
+                    (setq code nil)
+                    (goto-char (point-max))))
+                (cond ((eq code 'us-ascii)
+                       (decode-mime-charset-region (point-min) (point-max) nil lbt))
+                      (code
+                       (decode-mime-charset-region (point-min) (point-max) code lbt))
+                      (t
+                       (setq code
+                             (mime-detect-coding-system-region-unlimited
+                              (point-min) (point-max)))
+                       (when code
+                         (message "Declared US-ASCII but detected %s, so convert."
+                                  (if (eq code 'shift_jis) "SHIFT-JIS"
+                                    (upcase (prin1-to-string code))))
+                         (decode-mime-charset-region (point-min) (point-max)
+                                                     (or code default-mime-charset)
+                                                     lbt))))
+                (buffer-substring (point-min) (point-max)))
+            (kill-buffer nil))))
+       (t
+        (decode-mime-charset-string str charset lbt))))
+
 ;;; @ end
 ;;;