(gnus-mime-delete-part): Specify gnus-decoded as charset to deleted part.
[gnus] / lisp / nnimap.el
index 45f7946..d4f5fb2 100644 (file)
@@ -1,28 +1,26 @@
 ;;; nnimap.el --- imap backend for Gnus
 
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+;;   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
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;; 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., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -73,6 +71,8 @@
 
 (eval-when-compile (require 'cl))
 
+(autoload 'auth-source-user-or-password "auth-source")
+
 (nnoo-declare nnimap)
 
 (defconst nnimap-version "nnimap 1.0")
@@ -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)
@@ -798,22 +805,30 @@ If EXAMINE is non-nil the group is selected read-only."
           (port (if nnimap-server-port
                     (int-to-string nnimap-server-port)
                   "imap"))
-          (user (netrc-machine-user-or-password
-                 "login"
-                 list
-                 (list server
-                       (or nnimap-server-address
-                           nnimap-address))
-                 (list port)
-                 (list "imap" "imaps" "143" "993")))
-          (passwd (netrc-machine-user-or-password
-                   "password"
-                   list
-                   (list server
-                         (or nnimap-server-address
-                             nnimap-address))
-                   (list port)
-                   (list "imap" "imaps" "143" "993"))))
+          (auth-info 
+           (auth-source-user-or-password '("login" "password") server port))
+          (auth-user (nth 0 auth-info))
+          (auth-passwd (nth 1 auth-info))
+          (user (or
+                 auth-user ; this is preferred to netrc-*
+                 (netrc-machine-user-or-password
+                  "login"
+                  list
+                  (list server
+                        (or nnimap-server-address
+                            nnimap-address))
+                  (list port)
+                  (list "imap" "imaps" "143" "993"))))
+          (passwd (or
+                   auth-passwd ; this is preferred to netrc-*
+                   (netrc-machine-user-or-password
+                    "password"
+                    list
+                    (list server
+                          (or nnimap-server-address
+                              nnimap-address))
+                    (list port)
+                    (list "imap" "imaps" "143" "993")))))
       (if (imap-authenticate user passwd nnimap-server-buffer)
          (prog2
              (setq nnimap-server-buffer-alist
@@ -897,17 +912,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."
@@ -947,9 +962,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"
@@ -1604,6 +1621,8 @@ function is generally only called when Gnus is shutting down."
 
 (deffoo nnimap-request-delete-group (group force &optional server)
   (when (nnimap-possibly-change-server server)
+    (when (string= group (imap-current-mailbox nnimap-server-buffer))
+      (imap-mailbox-unselect nnimap-server-buffer))
     (with-current-buffer nnimap-server-buffer
       (if force
          (or (null (imap-mailbox-status group 'uidvalidity))