Merge flim-1_10_4.
[elisp/flim.git] / eword-decode.el
index 32fd1d4..02e1c9a 100644 (file)
   "Encoded-word decoding"
   :group 'mime)
 
+(defcustom eword-max-size-to-decode 1000
+  "*Max size to decode header field."
+  :group 'eword-decode
+  :type '(choice (integer :tag "Limit (bytes)")
+                (const :tag "Don't limit" nil)))
+
 
 ;;; @ MIME encoded-word definition
 ;;;
 
-(defconst eword-encoded-text-regexp "[!->@-~]+")
+(eval-and-compile
+  (defconst eword-encoded-text-regexp "[!->@-~]+")
+  )
 (defconst eword-encoded-word-regexp
-  (concat (regexp-quote "=?")
-         "\\("
-         mime-charset-regexp
-         "\\)"
-         (regexp-quote "?")
-         "\\(B\\|Q\\)"
-         (regexp-quote "?")
-         "\\("
-         eword-encoded-text-regexp
-         "\\)"
-         (regexp-quote "?=")))
-
-
-;;; @@ Base64
-;;;
-
-(defconst base64-token-regexp "[A-Za-z0-9+/]")
-(defconst base64-token-padding-regexp "[A-Za-z0-9+/=]")
-
-(defconst eword-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
-;;;
-
-(defconst eword-Q-encoded-text-regexp
-  (concat "\\([^=?]\\|" quoted-printable-octet-regexp "\\)+"))
-;; (defconst eword-Q-encoding-and-encoded-text-regexp
-;;   (concat "\\(Q\\)\\?" eword-Q-encoded-text-regexp))
+  (eval-when-compile
+    (concat (regexp-quote "=?")
+           "\\("
+           mime-charset-regexp
+           "\\)"
+           (regexp-quote "?")
+           "\\(B\\|Q\\)"
+           (regexp-quote "?")
+           "\\("
+           eword-encoded-text-regexp
+           "\\)"
+           (regexp-quote "?="))))
 
 
 ;;; @ for string
@@ -130,6 +107,117 @@ such as a version of Net$cape)."
     (concat dest string)
     ))
 
+(defun eword-decode-and-fold-structured-field
+  (string start-column &optional max-column must-unfold)
+  "Decode and fold (fill) STRING as structured field body.
+It decodes non us-ascii characters in FULL-NAME encoded as
+encoded-words or invalid \"raw\" string.  \"Raw\" non us-ascii
+characters are regarded as variable `default-mime-charset'.
+
+If an encoded-word is broken or your emacs implementation can not
+decode the charset included in it, it is not decoded.
+
+If MAX-COLUMN is omitted, `fill-column' is used.
+
+If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
+if there are in decoded encoded-words (generated by bad manner MUA
+such as a version of Net$cape)."
+  (if (and eword-max-size-to-decode
+          (> (length string) eword-max-size-to-decode))
+      string
+    (or max-column
+       (setq max-column fill-column))
+    (let ((c start-column)
+         (tokens (eword-lexical-analyze string must-unfold))
+         (result "")
+         token)
+      (while (and (setq token (car tokens))
+                 (setq tokens (cdr tokens)))
+       (let* ((type (car token)))
+         (if (eq type 'spaces)
+             (let* ((next-token (car tokens))
+                    (next-str (eword-decode-token next-token))
+                    (next-len (string-width next-str))
+                    (next-c (+ c next-len 1)))
+               (if (< next-c max-column)
+                   (setq result (concat result " " next-str)
+                         c next-c)
+                 (setq result (concat result "\n " next-str)
+                       c (1+ next-len)))
+               (setq tokens (cdr tokens))
+               )
+           (let* ((str (eword-decode-token token)))
+             (setq result (concat result str)
+                   c (+ c (string-width str)))
+             ))))
+      (if token
+         (concat result (eword-decode-token token))
+       result))))
+
+(defun eword-decode-and-unfold-structured-field (string)
+  "Decode and unfold STRING as structured field body.
+It decodes non us-ascii characters in FULL-NAME encoded as
+encoded-words or invalid \"raw\" string.  \"Raw\" non us-ascii
+characters are regarded as variable `default-mime-charset'.
+
+If an encoded-word is broken or your emacs implementation can not
+decode the charset included in it, it is not decoded."
+  (let ((tokens (eword-lexical-analyze string 'must-unfold))
+       (result ""))
+    (while tokens
+      (let* ((token (car tokens))
+            (type (car token)))
+       (setq tokens (cdr tokens))
+       (setq result
+             (if (eq type 'spaces)
+                 (concat result " ")
+               (concat result (eword-decode-token token))
+               ))))
+    result))
+
+(defun eword-decode-structured-field-body (string &optional must-unfold
+                                                 start-column max-column)
+  "Decode non us-ascii characters in STRING as structured field body.
+STRING is unfolded before decoding.
+
+It decodes non us-ascii characters in FULL-NAME encoded as
+encoded-words or invalid \"raw\" string.  \"Raw\" non us-ascii
+characters are regarded as variable `default-mime-charset'.
+
+If an encoded-word is broken or your emacs implementation can not
+decode the charset included in it, it is not decoded.
+
+If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
+if there are in decoded encoded-words (generated by bad manner MUA
+such as a version of Net$cape)."
+  (if start-column
+      ;; fold with max-column
+      (eword-decode-and-fold-structured-field
+       string start-column max-column must-unfold)
+    ;; Don't fold
+    (mapconcat (function eword-decode-token)
+              (eword-lexical-analyze string must-unfold)
+              "")
+    ))
+
+(defun eword-decode-unstructured-field-body (string &optional must-unfold)
+  "Decode non us-ascii characters in STRING as unstructured field body.
+STRING is unfolded before decoding.
+
+It decodes non us-ascii characters in FULL-NAME encoded as
+encoded-words or invalid \"raw\" string.  \"Raw\" non us-ascii
+characters are regarded as variable `default-mime-charset'.
+
+If an encoded-word is broken or your emacs implementation can not
+decode the charset included in it, it is not decoded.
+
+If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
+if there are in decoded encoded-words (generated by bad manner MUA
+such as a version of Net$cape)."
+  (eword-decode-string
+   (decode-mime-charset-string string default-mime-charset)
+   must-unfold))
+
 
 ;;; @ for region
 ;;;
@@ -180,6 +268,7 @@ Each field name must be symbol."
 (defcustom eword-decode-structured-field-list
   '(Reply-To Resent-Reply-To From Resent-From Sender Resent-Sender
             To Resent-To Cc Resent-Cc Bcc Resent-Bcc Dcc
+            Mail-Followup-To
             Mime-Version Content-Type Content-Transfer-Encoding
             Content-Disposition User-Agent)
   "*List of field-names to decode as structured field.
@@ -317,22 +406,7 @@ if there are in decoded encoded-text (generated by bad manner MUA such
 as a version of Net$cape)."
   (let ((cs (mime-charset-to-coding-system charset)))
     (if cs
-       (let ((dest
-               (cond
-                ((string-equal "B" encoding)
-                 (if (and (string-match eword-B-encoded-text-regexp string)
-                          (string-equal string (match-string 0 string)))
-                     (base64-decode-string string)
-                   (error "Invalid encoded-text %s" string)))
-                ((string-equal "Q" encoding)
-                 (if (and (string-match eword-Q-encoded-text-regexp string)
-                          (string-equal string (match-string 0 string)))
-                     (q-encoding-decode-string string)
-                   (error "Invalid encoded-text %s" string)))
-                (t
-                 (error "Invalid encoding %s" encoding)
-                 )))
-              )
+       (let ((dest (encoded-text-decode-string string encoding)))
          (when dest
            (setq dest (decode-mime-charset-string dest charset))
            (if must-unfold
@@ -485,114 +559,6 @@ characters encoded as encoded-words or invalid \"raw\" format.
           (concat "(" (std11-wrap-as-quoted-pairs value '(?( ?))) ")"))
          (t value))))
 
-(defun eword-decode-and-fold-structured-field
-  (string start-column &optional max-column must-unfold)
-  "Decode and fold (fill) STRING as structured field body.
-It decodes non us-ascii characters in FULL-NAME encoded as
-encoded-words or invalid \"raw\" string.  \"Raw\" non us-ascii
-characters are regarded as variable `default-mime-charset'.
-
-If an encoded-word is broken or your emacs implementation can not
-decode the charset included in it, it is not decoded.
-
-If MAX-COLUMN is omitted, `fill-column' is used.
-
-If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
-if there are in decoded encoded-words (generated by bad manner MUA
-such as a version of Net$cape)."
-  (or max-column
-      (setq max-column fill-column))
-  (let ((c start-column)
-       (tokens (eword-lexical-analyze string must-unfold))
-       (result "")
-       token)
-    (while (and (setq token (car tokens))
-               (setq tokens (cdr tokens)))
-      (let* ((type (car token)))
-       (if (eq type 'spaces)
-           (let* ((next-token (car tokens))
-                  (next-str (eword-decode-token next-token))
-                  (next-len (string-width next-str))
-                  (next-c (+ c next-len 1)))
-             (if (< next-c max-column)
-                 (setq result (concat result " " next-str)
-                       c next-c)
-               (setq result (concat result "\n " next-str)
-                     c (1+ next-len)))
-             (setq tokens (cdr tokens))
-             )
-         (let* ((str (eword-decode-token token)))
-           (setq result (concat result str)
-                 c (+ c (string-width str)))
-           ))))
-    (if token
-       (concat result (eword-decode-token token))
-      result)))
-
-(defun eword-decode-and-unfold-structured-field (string)
-  "Decode and unfold STRING as structured field body.
-It decodes non us-ascii characters in FULL-NAME encoded as
-encoded-words or invalid \"raw\" string.  \"Raw\" non us-ascii
-characters are regarded as variable `default-mime-charset'.
-
-If an encoded-word is broken or your emacs implementation can not
-decode the charset included in it, it is not decoded."
-  (let ((tokens (eword-lexical-analyze string 'must-unfold))
-       (result ""))
-    (while tokens
-      (let* ((token (car tokens))
-            (type (car token)))
-       (setq tokens (cdr tokens))
-       (setq result
-             (if (eq type 'spaces)
-                 (concat result " ")
-               (concat result (eword-decode-token token))
-               ))))
-    result))
-
-(defun eword-decode-structured-field-body (string &optional must-unfold
-                                                 start-column max-column)
-  "Decode non us-ascii characters in STRING as structured field body.
-STRING is unfolded before decoding.
-
-It decodes non us-ascii characters in FULL-NAME encoded as
-encoded-words or invalid \"raw\" string.  \"Raw\" non us-ascii
-characters are regarded as variable `default-mime-charset'.
-
-If an encoded-word is broken or your emacs implementation can not
-decode the charset included in it, it is not decoded.
-
-If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
-if there are in decoded encoded-words (generated by bad manner MUA
-such as a version of Net$cape)."
-  (if start-column
-      ;; fold with max-column
-      (eword-decode-and-fold-structured-field
-       string start-column max-column must-unfold)
-    ;; Don't fold
-    (mapconcat (function eword-decode-token)
-              (eword-lexical-analyze string must-unfold)
-              "")
-    ))
-
-(defun eword-decode-unstructured-field-body (string &optional must-unfold)
-  "Decode non us-ascii characters in STRING as unstructured field body.
-STRING is unfolded before decoding.
-
-It decodes non us-ascii characters in FULL-NAME encoded as
-encoded-words or invalid \"raw\" string.  \"Raw\" non us-ascii
-characters are regarded as variable `default-mime-charset'.
-
-If an encoded-word is broken or your emacs implementation can not
-decode the charset included in it, it is not decoded.
-
-If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
-if there are in decoded encoded-words (generated by bad manner MUA
-such as a version of Net$cape)."
-  (eword-decode-string
-   (decode-mime-charset-string string default-mime-charset)
-   must-unfold))
-
 (defun eword-extract-address-components (string)
   "Extract full name and canonical address from STRING.
 Returns a list of the form (FULL-NAME CANONICAL-ADDRESS).