Synch to Oort Gnus 200303190702.
[elisp/gnus.git-] / lisp / mm-bodies.el
index 28d202e..e4c7894 100644 (file)
@@ -1,5 +1,7 @@
 ;;; mm-bodies.el --- Functions for decoding MIME things
-;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+
+;; Copyright (C) 1998, 1999, 2000, 2001
+;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
@@ -70,7 +72,7 @@ If no encoding was done, nil is returned."
            (if (re-search-forward "[^\x0-\x7f]" nil t)
                (or mail-parse-charset
                    (message-options-get 'mm-encody-body-charset)
-                   (message-options-set 
+                   (message-options-set
                     'mm-encody-body-charset
                     (mm-read-charset "Charset used in the article: ")))
              ;; The logic in `mml-generate-mime-1' confirms that it's OK
@@ -82,7 +84,8 @@ If no encoding was done, nil is returned."
            (mm-encode-coding-region (point-min) (point-max) charset)
            charset)
        (goto-char (point-min))
-       (let ((charsets (mm-find-mime-charset-region (point-min) (point-max)))
+       (let ((charsets (mm-find-mime-charset-region (point-min) (point-max)
+                                                    mm-hack-charsets))
              start)
          (cond
           ;; No encoding.
@@ -128,6 +131,8 @@ If no encoding was done, nil is returned."
 
 (defun mm-body-encoding (charset &optional encoding)
   "Do Content-Transfer-Encoding and return the encoding of the current buffer."
+  (when (stringp encoding)
+    (setq encoding (intern (downcase encoding))))
   (let ((bits (mm-body-7-or-8))
        (longp (mm-long-lines-p 1000)))
     (require 'message)
@@ -138,6 +143,7 @@ If no encoding was done, nil is returned."
       bits)
      ((and (not mm-use-ultra-safe-encoding)
           (not longp)
+          (not (eq '7bit (cdr (assq charset mm-body-charset-encoding-alist))))
           (or (eq t (cdr message-posting-charset))
               (memq charset (cdr message-posting-charset))
               (eq charset mail-parse-charset)))
@@ -180,11 +186,14 @@ If no encoding was done, nil is returned."
 ;;;
 
 (defun mm-decode-content-transfer-encoding (encoding &optional type)
+  "Decodes buffer encoded with ENCODING, returning success status.
+If TYPE is `text/plain' CRLF->LF translation may occur."
   (prog1
       (condition-case error
          (cond
           ((eq encoding 'quoted-printable)
-           (quoted-printable-decode-region (point-min) (point-max)))
+           (quoted-printable-decode-region (point-min) (point-max))
+           t)
           ((eq encoding 'base64)
            (base64-decode-region
             (point-min)
@@ -203,36 +212,44 @@ If no encoding was done, nil is returned."
               (point))))
           ((memq encoding '(7bit 8bit binary))
            ;; Do nothing.
-           )
+           t)
           ((null encoding)
            ;; Do nothing.
-           )
+           t)
           ((memq encoding '(x-uuencode x-uue))
            (require 'mm-uu)
-           (funcall mm-uu-decode-function (point-min) (point-max)))
+           (funcall mm-uu-decode-function (point-min) (point-max))
+           t)
           ((eq encoding 'x-binhex)
            (require 'mm-uu)
-           (funcall mm-uu-binhex-decode-function (point-min) (point-max)))
+           (funcall mm-uu-binhex-decode-function (point-min) (point-max))
+           t)
+          ((eq encoding 'x-yenc)
+           (require 'mm-uu)
+           (funcall mm-uu-yenc-decode-function (point-min) (point-max))
+           )
           ((functionp encoding)
-           (funcall encoding (point-min) (point-max)))
+           (funcall encoding (point-min) (point-max))
+           t)
           (t
            (message "Unknown encoding %s; defaulting to 8bit" encoding)))
        (error
         (message "Error while decoding: %s" error)
         nil))
     (when (and
-          (memq encoding '(base64 x-uuencode x-uue x-binhex))
+          (memq encoding '(base64 x-uuencode x-uue x-binhex x-yenc))
           (equal type "text/plain"))
       (goto-char (point-min))
       (while (search-forward "\r\n" nil t)
        (replace-match "\n" t t)))))
 
-(defun mm-decode-body (charset &optional encoding type)
+(defun mm-decode-body (charset &optional encoding type force)
   "Decode the current article that has been encoded with ENCODING.
-The characters in CHARSET should then be decoded."
+The characters in CHARSET should then be decoded.  If FORCE is non-nil
+use the supplied charset unconditionally."
   (if (stringp charset)
       (setq charset (intern (downcase charset))))
-  (if (or (not charset) 
+  (if (or (not charset)
          (eq 'gnus-all mail-parse-ignored-charsets)
          (memq 'gnus-all mail-parse-ignored-charsets)
          (memq charset mail-parse-ignored-charsets))
@@ -245,7 +262,7 @@ The characters in CHARSET should then be decoded."
        (if (and (not coding-system)
                 (listp mail-parse-ignored-charsets)
                 (memq 'gnus-unknown mail-parse-ignored-charsets))
-           (setq coding-system 
+           (setq coding-system
                  (mm-charset-to-coding-system mail-parse-charset)))
        (when (and charset coding-system
                   ;; buffer-file-coding-system
@@ -255,13 +272,33 @@ The characters in CHARSET should then be decoded."
                   (or (not (eq coding-system 'ascii))
                       (setq coding-system mail-parse-charset))
                   (not (eq coding-system 'gnus-decoded)))
-         (mm-decode-coding-region (point-min) (point-max) coding-system))))))
+         (if force
+             (mm-decode-coding-region (point-min) (point-max)
+                                             coding-system)
+           (mm-decode-coding-region-safely (point-min) (point-max)
+                                           coding-system)))))))
+
+(defun mm-decode-coding-region-safely (start end coding-system)
+  "Decode region between START and END with CODING-SYSTEM.
+If CODING-SYSTEM is not a valid coding system for the text, let Emacs
+decide which coding system to use."
+  (let* ((orig (buffer-substring start end))
+        charsets)
+    (save-restriction
+      (narrow-to-region start end)
+      (mm-decode-coding-region (point-min) (point-max) coding-system)
+      (setq charsets (find-charset-region (point-min) (point-max)))
+      (when (or (memq 'eight-bit-control charsets)
+               (memq 'eight-bit-graphic charsets))
+       (delete-region (point-min) (point-max))
+       (insert orig)
+       (mm-decode-coding-region (point-min) (point-max) 'undecided)))))
 
 (defun mm-decode-string (string charset)
   "Decode STRING with CHARSET."
   (when (stringp charset)
     (setq charset (intern (downcase charset))))
-  (when (or (not charset) 
+  (when (or (not charset)
            (eq 'gnus-all mail-parse-ignored-charsets)
            (memq 'gnus-all mail-parse-ignored-charsets)
            (memq charset mail-parse-ignored-charsets))
@@ -272,7 +309,7 @@ The characters in CHARSET should then be decoded."
        (if (and (not coding-system)
                (listp mail-parse-ignored-charsets)
                (memq 'gnus-unknown mail-parse-ignored-charsets))
-          (setq coding-system 
+          (setq coding-system
                 (mm-charset-to-coding-system mail-parse-charset)))
        (when (and charset coding-system
                  (mm-multibyte-p)
@@ -283,4 +320,4 @@ The characters in CHARSET should then be decoded."
 
 (provide 'mm-bodies)
 
-;; mm-bodies.el ends here
+;;; mm-bodies.el ends here