Merge from emacs--devo--0
[gnus] / lisp / nnimap.el
index 8a9d5c7..96b8329 100644 (file)
@@ -1,9 +1,9 @@
 ;;; nnimap.el --- imap backend for Gnus
 
 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-;;   2007, 2008  Free Software Foundation, Inc.
+;;   2007, 2008, 2009  Free Software Foundation, Inc.
 
-;; Author: Simon Josefsson <jas@pdc.kth.se>
+;; Author: Simon Josefsson <simon@josefsson.org>
 ;;         Jim Radford <radford@robby.caltech.edu>
 ;; Keywords: mail
 
@@ -163,6 +163,8 @@ the inbox string is also a regexp.  The actual splitting rules are as
 before, either a function, or a list with group/regexp or
 group/function elements."
   :group 'nnimap
+  ;; FIXME: Doesn't allow `("my2server" ("INBOX" nnimap-split-fancy))'
+  ;; per example above.  -- fx
   :type '(choice :tag "Rule type"
                 (repeat :menu-tag "Single-server"
                         :tag "Single-server list"
@@ -424,8 +426,8 @@ restrict visible folders.")
 
 (defcustom nnimap-id nil
   "Plist with client identity to send to server upon login.
-Nil means no information is sent, symbol `no' to disable ID query
-alltogheter, or plist with identifier-value pairs to send to
+A nil value means no information is sent, symbol `no' to disable ID query
+altogether, or plist with identifier-value pairs to send to
 server.  RFC 2971 describes the list as follows:
 
    Any string may be sent as a field, but the following are defined to
@@ -460,11 +462,17 @@ An example plist would be '(\"name\" \"Gnus\" \"version\" gnus-version-number
                 (plist :key-type string :value-type string)))
 
 (defcustom nnimap-debug nil
-  "If non-nil, random debug spews are placed in *nnimap-debug* buffer.
+  "If non-nil, trace nnimap- functions into `nnimap-debug-buffer'.
+Uses `trace-function-background', so you can turn it off with,
+say, `untrace-all'.
+
 Note that username, passwords and other privacy sensitive
-information (such as e-mail) may be stored in the *nnimap-debug*
-buffer.  It is not written to disk, however.  Do not enable this
-variable unless you are comfortable with that."
+information (such as e-mail) may be stored in the buffer.
+It is not written to disk, however.  Do not enable this
+variable unless you are comfortable with that.
+
+This variable only takes effect when loading the `nnimap' library.
+See also `nnimap-log'."
   :group 'nnimap
   :type 'boolean)
 
@@ -555,8 +563,7 @@ If EXAMINE is non-nil the group is selected read-only."
              (imap-mailbox-select group examine))
       (let (minuid maxuid)
        (when (> (imap-mailbox-get 'exists) 0)
-         (imap-fetch (if imap-enable-exchange-bug-workaround "1,*:*" "1,*")
-                     "UID" nil 'nouidfetch)
+         (imap-fetch-safe '("1,*" . "1,*:*") "UID" nil 'nouidfetch)
          (imap-message-map (lambda (uid Uid)
                              (setq minuid (if minuid (min minuid uid) uid)
                                    maxuid (if maxuid (max maxuid uid) uid)))
@@ -608,12 +615,11 @@ If EXAMINE is non-nil the group is selected read-only."
       (with-current-buffer nnimap-server-buffer
        (setq uid imap-current-message
              mbx imap-current-mailbox
-             headers (nnimap-demule
-                      (if (imap-capability 'IMAP4rev1)
+             headers (if (imap-capability 'IMAP4rev1)
                           ;; xxx don't just use car? alist doesn't contain
                           ;; anything else now, but it might...
                           (nth 2 (car (imap-message-get uid 'BODYDETAIL)))
-                        (imap-message-get uid 'RFC822.HEADER)))
+                        (imap-message-get uid 'RFC822.HEADER))
              lines (imap-body-lines (imap-message-body imap-current-message))
              chars (imap-message-get imap-current-message 'RFC822.SIZE)))
       (nnheader-insert-nov
@@ -621,7 +627,8 @@ If EXAMINE is non-nil the group is selected read-only."
        ;; to make it more clear.
        (mm-with-unibyte-buffer
         (buffer-disable-undo)
-        (insert headers)
+        ;; headers can be nil if article is write-only
+        (when headers (insert headers))
         (let ((head (nnheader-parse-naked-head uid)))
           (mail-header-set-number head uid)
           (mail-header-set-chars head chars)
@@ -901,17 +908,17 @@ function is generally only called when Gnus is shutting down."
   (when (nnimap-possibly-change-server server)
     (nnoo-status-message 'nnimap server)))
 
-(defun nnimap-demule (string)
-  ;; BEWARE: we used to use string-as-multibyte here which is braindead
-  ;; because it will turn accidental emacs-mule-valid byte sequences
-  ;; into multibyte chars.  --Stef
-  ;; Reverted, braindead got 7.5 out of 10 on imdb, so it can't be
-  ;; that bad. --Simon
-  (funcall (if (and (fboundp 'string-as-multibyte)
-                   (subrp (symbol-function 'string-as-multibyte)))
-              'string-as-multibyte
-            'identity)
-          (or string "")))
+;; We used to use a string-as-multibyte here, but it is really incorrect.
+;; This function is used when we're about to insert a unibyte string
+;; into a potentially multibyte buffer.  The string is either an article
+;; header or body (or both?), undecoded.  When Emacs is asked to convert
+;; a unibyte string to multibyte, it may either use the equivalent of
+;; nothing (e.g. non-Mule XEmacs), string-make-unibyte (i.e. decode using
+;; locale), string-as-multibyte (decode using emacs-internal coding system)
+;; or string-to-multibyte (keep the data undecoded as a sequence of bytes).
+;; Only the last one preserves the data such that we can reliably later on
+;; decode the text using the mime info.
+(defalias 'nnimap-demule 'mm-string-to-multibyte)
 
 (defun nnimap-make-callback (article gnus-callback buffer)
   "Return a callback function."
@@ -951,9 +958,11 @@ function is generally only called when Gnus is shutting down."
              (erase-buffer)
              (let ((data (imap-fetch article part prop nil
                                      nnimap-server-buffer)))
-               (insert (nnimap-demule (if detail
-                                          (nth 2 (car data))
-                                        data))))
+               ;; data can be nil if article is write-only
+               (when data
+                 (insert (nnimap-demule (if detail
+                                            (nth 2 (car data))
+                                          data)))))
              (nnheader-ms-strip-cr)
              (gnus-message
               10 "nnimap: Fetching (part of) article %d from %s...done"