Synch to No Gnus 200510111141.
[elisp/gnus.git-] / lisp / rfc2047.el
index 07818b8..6fa537f 100644 (file)
@@ -1,7 +1,7 @@
 ;;; rfc2047.el --- functions for encoding and decoding rfc2047 messages
 
-;; Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004
-;;        Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004,
+;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
@@ -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.
 
 ;;; Commentary:
 
@@ -35,6 +35,7 @@
 
 (require 'qp)
 (require 'mm-util)
+(require 'ietf-drums)
 ;; Fixme: Avoid this (used for mail-parse-charset) mm dependence on gnus.
 (require 'mail-prsvr)
 (require 'base64)
@@ -44,7 +45,7 @@
   '(("Newsgroups" . nil)
     ("Followup-To" . nil)
     ("Message-ID" . nil)
-    ("\\(Resent-\\)?\\(From\\|Cc\\|To\\|Bcc\\|Reply-To\\|Sender\
+    ("\\(Resent-\\)?\\(From\\|Cc\\|To\\|Bcc\\|\\(In-\\)?Reply-To\\|Sender\
 \\|Mail-Followup-To\\|Mail-Copies-To\\|Approved\\)" . address-mime)
     (t . mime))
   "*Header/encoding method alist.
@@ -369,8 +370,8 @@ Dynamically bind `rfc2047-encoding-type' to change that."
                  (forward-list)
                  ;; Encode text as an unstructured field.
                  (let ((rfc2047-encoding-type 'mime))
-                   (rfc2047-encode-region (1+ start) (1- (point)))
-                   (forward-char)))
+                   (rfc2047-encode-region (1+ start) (1- (point))))
+                 (skip-chars-forward ")"))
                 (t                 ; normal token/whitespace sequence
                  ;; Find the end.
                  ;; Skip one ASCII word, or encode continuous words
@@ -422,7 +423,9 @@ Dynamically bind `rfc2047-encoding-type' to change that."
                              ;; to be encoded so that MTAs may parse
                              ;; them safely.
                              (cond ((= end (point)))
-                                   ((looking-at encodable-regexp)
+                                   ((looking-at (concat "\\sw*\\("
+                                                        encodable-regexp
+                                                        "\\)"))
                                     (setq end nil))
                                    (t
                                     (goto-char (1- (match-end 0)))
@@ -442,12 +445,20 @@ Dynamically bind `rfc2047-encoding-type' to change that."
                  (goto-char start)
                  (if (re-search-forward encodable-regexp end 'move)
                      (progn
-                       (goto-char start)
-                       (unless (memq (char-before) '(nil ?\t ? ))
-                         ;; Separate encodable text and delimiter.
-                         (insert " ")
-                         (setq end (1+ end)))
-                       (rfc2047-encode (point) end)
+                       (unless (memq (char-before start) '(nil ?\t ? ))
+                         (if (progn
+                               (goto-char start)
+                               (skip-chars-backward "^ \t\n")
+                               (and (looking-at "\\Sw+")
+                                    (= (match-end 0) start)))
+                             ;; Also encode bogus delimiters.
+                             (setq start (point))
+                           ;; Separate encodable text and delimiter.
+                           (goto-char start)
+                           (insert " ")
+                           (setq start (1+ start)
+                                 end (1+ end))))
+                       (rfc2047-encode start end)
                        (setq last-encoded t))
                    (setq last-encoded nil)))))
            (error
@@ -607,7 +618,9 @@ Point moves to the end of the region."
             (insert eword)
             (set-marker b nil)
             (set-marker e nil)
-            (unless (looking-at "[ \t\n)]")
+            (unless (or (/= 0 (length tail))
+                        (eobp)
+                        (looking-at "[ \t\n)]"))
               (insert " "))))
          (t
           (goto-char e)))))
@@ -754,8 +767,7 @@ it, put the following line in your ~/.gnus.el file:
   (let* ((rfc2047-encoding-type 'mime)
         (rfc2047-encode-max-chars nil)
         (string (rfc2047-encode-string value)))
-    (if (string-match "[][()<>@,;:\\\"/?=]" ;; tspecials
-                     string)
+    (if (string-match (concat "[" ietf-drums-tspecials "]") string)
        (format "%s=%S" param string)
       (concat param "=" string))))
 
@@ -768,6 +780,9 @@ it, put the following line in your ~/.gnus.el file:
     "=\\?\\([^][\000-\040()<>@,\;:*\\\"/?.=]+\\)\\(?:\\*[^?]+\\)?\
 \\?\\(B\\|Q\\)\\?\\([!->@-~ ]*\\)\\?="))
 
+(defvar rfc2047-quote-decoded-words-containing-tspecials nil
+  "If non-nil, quote decoded words containing special characters.")
+
 ;; Fixme: This should decode in place, not cons intermediate strings.
 ;; Also check whether it needs to worry about delimiting fields like
 ;; encoding.
@@ -802,14 +817,66 @@ it, put the following line in your ~/.gnus.el file:
          (insert (rfc2047-parse-and-decode
                   (prog1
                       (match-string 0)
-                    (delete-region (match-beginning 0) (match-end 0)))))
-         ;; Remove newlines between decoded words, though such things
-         ;; essentially must not be there.
+                    (delete-region e (match-end 0)))))
+         (while (looking-at rfc2047-encoded-word-regexp)
+           (insert (rfc2047-parse-and-decode
+                    (prog1
+                        (match-string 0)
+                      (delete-region (point) (match-end 0))))))
          (save-restriction
            (narrow-to-region e (point))
            (goto-char e)
+           ;; Remove newlines between decoded words, though such
+           ;; things essentially must not be there.
            (while (re-search-forward "[\n\r]+" nil t)
              (replace-match " "))
+           ;; Quote decoded words if there are special characters
+           ;; which might violate RFC2822.
+           (when (and rfc2047-quote-decoded-words-containing-tspecials
+                      (let ((regexp (car (rassq
+                                          'address-mime
+                                          rfc2047-header-encoding-alist))))
+                        (when regexp
+                          (save-restriction
+                            (widen)
+                            (beginning-of-line)
+                            (while (and (memq (char-after) '(?  ?\t))
+                                        (zerop (forward-line -1))))
+                            (looking-at regexp)))))
+             (let (quoted)
+               (goto-char e)
+               (skip-chars-forward " \t")
+               (setq start (point))
+               (setq quoted (eq (char-after) ?\"))
+               (goto-char (point-max))
+               (skip-chars-backward " \t")
+               (if (setq quoted (and quoted
+                                     (> (point) (1+ start))
+                                     (eq (char-before) ?\")))
+                   (progn
+                     (backward-char)
+                     (setq start (1+ start)
+                           end (point-marker)))
+                 (setq end (point-marker)))
+               (goto-char start)
+               (while (search-forward "\"" end t)
+                 (when (prog2
+                           (backward-char)
+                           (zerop (% (skip-chars-backward "\\\\") 2))
+                         (goto-char (match-beginning 0)))
+                   (insert "\\"))
+                 (forward-char))
+               (when (and (not quoted)
+                          (progn
+                            (goto-char start)
+                            (re-search-forward
+                             (concat "[" ietf-drums-tspecials "]")
+                             end t)))
+                 (goto-char start)
+                 (insert "\"")
+                 (goto-char end)
+                 (insert "\""))
+               (set-marker end nil)))
            (goto-char (point-max)))
          (when (and (mm-multibyte-p)
                     mail-parse-charset