Synch to No Gnus 200512141312.
[elisp/gnus.git-] / lisp / nnimap.el
index 77240a7..1da27f1 100644 (file)
@@ -1,6 +1,7 @@
 ;;; nnimap.el --- imap backend for Gnus
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
-;;        Free Software Foundation, Inc.
+
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <jas@pdc.kth.se>
 ;;         Jim Radford <radford@robby.caltech.edu>
@@ -20,8 +21,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:
 
@@ -206,13 +207,13 @@ RFC2060 section 6.4.4."
   "Whether to download entire articles during splitting.
 This is generally not required, and will slow things down considerably.
 You may need it if you want to use an advanced splitting function that
-analyses the body before splitting the article.
+analyzes the body before splitting the article.
 If this variable is nil, bodies will not be downloaded; if this
 variable is the symbol `default' the default behaviour is
 used (which currently is nil, unless you use a statistical
 spam.el test); if this variable is another non-nil value bodies
 will be downloaded."
-  :version "21.4"
+  :version "22.1"
   :group 'nnimap
   :type '(choice (const :tag "Let system decide" deault)
                 boolean))
@@ -224,7 +225,7 @@ will be downloaded."
 This means that errors caught by nnimap when closing the mailbox will
 not prevent Gnus from updating the group status, which may be harmful.
 However, it increases speed."
-  :version "21.4"
+  :version "22.1"
   :type 'boolean
   :group 'nnimap)
 
@@ -233,7 +234,7 @@ However, it increases speed."
 This increases the speed of closing mailboxes (quiting group) but may
 decrease the speed of selecting another mailbox later.  Re-selecting
 the same mailbox will be faster though."
-  :version "21.4"
+  :version "22.1"
   :type 'boolean
   :group 'nnimap)
 
@@ -246,7 +247,7 @@ more carefully for new mail.
 
 In summary, the default is O((1-p)*k+p*n) and changing it to nil makes
 it O(n).  If p is small, then the default is probably faster."
-  :version "21.4"
+  :version "22.1"
   :type 'boolean
   :group 'nnimap)
 
@@ -317,6 +318,11 @@ every message in the group, thus making it quite slow.
 Unlike other backends, you do not need to take special care if you
 flip this variable.")
 
+(defvoo nnimap-search-uids-not-since-is-evil nil
+  "If non-nil, avoid \"UID SEARCH UID ... NOT SINCE\" queries when expiring.
+Instead, use \"UID SEARCH SINCE\" to prune the list of expirable
+articles within Gnus.  This seems to be faster on Courier in some cases.")
+
 (defvoo nnimap-expunge-on-close 'always ; 'ask, 'never
   "Whether to expunge a group when it is closed.
 When a IMAP group with articles marked for deletion is closed, this
@@ -447,7 +453,11 @@ 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, random debug spews are placed in *nnimap-debug* buffer.
+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."
   :group 'nnimap
   :type 'boolean)
 
@@ -707,6 +717,8 @@ If EXAMINE is non-nil the group is selected read-only."
                            (if (imap-capability 'IMAP4rev1)
                                (format "BODY.PEEK[HEADER.FIELDS %s])" headers)
                              (format "RFC822.HEADER.LINES %s)" headers)))))
+      (with-current-buffer nntp-server-buffer
+       (sort-numeric-fields 1 (point-min) (point-max)))
       (and (numberp nnmail-large-newsgroup)
           (> nnimap-length nnmail-large-newsgroup)
           (nnheader-message 6 "nnimap: Retrieving headers...done")))))
@@ -768,11 +780,13 @@ If EXAMINE is non-nil the group is selected read-only."
                (imap-capability 'IMAP4rev1 nnimap-server-buffer))
       (imap-close nnimap-server-buffer)
       (nnheader-report 'nnimap "Server %s is not IMAP4 compliant" server))
-    (let* ((list (netrc-parse nnimap-authinfo-file))
-          (port (if nnimap-server-port
-                    (int-to-string nnimap-server-port)
-                  "imap"))
-          (user (netrc-machine-user-or-password 
+    (let* ((list (progn (gnus-message 7 "Parsing authinfo file `%s'."
+                                     nnimap-authinfo-file)
+                       (netrc-parse nnimap-authinfo-file)))
+          (port (if nnimap-server-port
+                    (int-to-string nnimap-server-port)
+                  "imap"))
+          (user (netrc-machine-user-or-password
                  "login"
                  list
                  (list server
@@ -780,7 +794,7 @@ If EXAMINE is non-nil the group is selected read-only."
                            nnimap-address))
                  (list port)
                  (list "imap" "imaps")))
-          (passwd (netrc-machine-user-or-password 
+          (passwd (netrc-machine-user-or-password
                    "password"
                    list
                    (list server
@@ -789,9 +803,9 @@ If EXAMINE is non-nil the group is selected read-only."
                    (list port)
                    (list "imap" "imaps"))))
       (if (imap-authenticate user passwd nnimap-server-buffer)
-         (prog1
+         (prog2
              (setq nnimap-server-buffer-alist
-                   (nnimap-remove-server-from-buffer-alist 
+                   (nnimap-remove-server-from-buffer-alist
                     server
                     nnimap-server-buffer-alist))
              (push (list server nnimap-server-buffer)
@@ -823,7 +837,7 @@ If EXAMINE is non-nil the group is selected read-only."
     (or (and nnimap-server-buffer
             (imap-opened nnimap-server-buffer)
             (if (with-current-buffer nnimap-server-buffer
-                  (memq imap-state '(auth select examine)))
+                  (memq imap-state '(auth selected examine)))
                 t
               (imap-close nnimap-server-buffer)
               (nnimap-open-connection server)))
@@ -850,7 +864,7 @@ Return nil if the server couldn't be closed for some reason."
       (setq nnimap-server-buffer nil
            nnimap-current-server nil
            nnimap-server-buffer-alist
-           (nnimap-remove-server-from-buffer-alist 
+           (nnimap-remove-server-from-buffer-alist
             server
             nnimap-server-buffer-alist)))
     (nnoo-close-server 'nnimap server)))
@@ -1366,7 +1380,7 @@ function is generally only called when Gnus is shutting down."
                             (let (msgid)
                               (and (setq msgid
                                          (nnmail-fetch-field "message-id"))
-                                   (nnmail-cache-insert msgid 
+                                   (nnmail-cache-insert msgid
                                                         to-group
                                                         (nnmail-fetch-field "subject"))))))
                         ;; Add the group-art list to the history list.
@@ -1434,8 +1448,10 @@ function is generally only called when Gnus is shutting down."
        (list (- ms 1) (+ (expt 2 16) ls))
       (list ms ls))))
 
+(eval-when-compile (require 'parse-time))
 (defun nnimap-date-days-ago (daysago)
   "Return date, in format \"3-Aug-1998\", for DAYSAGO days ago."
+  (require 'parse-time)
   (let* ((time (nnimap-time-substract (current-time) (days-to-time daysago)))
         (date (format-time-string
                (format "%%d-%s-%%Y"
@@ -1483,6 +1499,21 @@ function is generally only called when Gnus is shutting down."
                             (gnus-compress-sequence oldarts)) "\\Deleted")
                       (setq articles (gnus-set-difference
                                       articles oldarts))))))
+               ((and nnimap-search-uids-not-since-is-evil (numberp days))
+                (let* ((all-new-articles
+                        (gnus-compress-sequence
+                         (imap-search (format "SINCE %s"
+                                              (nnimap-date-days-ago days)))))
+                       (oldartseq
+                        (gnus-range-difference artseq all-new-articles))
+                       (oldarts (gnus-uncompress-range oldartseq)))
+                  (when oldarts
+                    (nnimap-expiry-target oldarts group server)
+                    (when (imap-message-flags-add
+                           (imap-range-to-message-set oldartseq)
+                           "\\Deleted")
+                      (setq articles (gnus-set-difference
+                                      articles oldarts))))))
                ((numberp days)
                 (let ((oldarts (imap-search
                                 (format nnimap-expunge-search-string
@@ -1500,8 +1531,8 @@ function is generally only called when Gnus is shutting down."
   ;; return articles not deleted
   articles)
 
-(deffoo nnimap-request-move-article (article group server
-                                            accept-form &optional last)
+(deffoo nnimap-request-move-article (article group server accept-form 
+                                            &optional last move-is-internal)
   (when (nnimap-possibly-change-server server)
     (save-excursion
       (let ((buf (get-buffer-create " *nnimap move*"))
@@ -1509,7 +1540,13 @@ function is generally only called when Gnus is shutting down."
            (nnimap-current-move-group group)
            (nnimap-current-move-server nnimap-current-server)
            result)
-       (and (nnimap-request-article article group server)
+       (gnus-message 10 "nnimap-request-move-article: this is an %s move"
+                     (if move-is-internal
+                         "internal"
+                       "external"))
+       ;; request the article only when the move is NOT internal
+       (and (or move-is-internal
+                (nnimap-request-article article group server))
             (save-excursion
               (set-buffer buf)
               (buffer-disable-undo (current-buffer))