(article-transform-date): Fix infinite recursion.
[gnus] / lisp / nnimap.el
index d316015..005f60b 100644 (file)
@@ -1,6 +1,6 @@
 ;;; nnimap.el --- IMAP interface for Gnus
 
-;; Copyright (C) 20102011 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2011 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;         Simon Josefsson <simon@josefsson.org>
@@ -124,7 +124,7 @@ textual parts.")
 
 (defstruct nnimap
   group process commands capabilities select-result newlinep server
-  last-command-time greeting examined)
+  last-command-time greeting examined stream-type)
 
 (defvar nnimap-object nil)
 
@@ -350,7 +350,7 @@ textual parts.")
            login-result credentials)
       (when nnimap-server-port
        (setq ports (append ports (list nnimap-server-port))))
-      (destructuring-bind (stream greeting capabilities)
+      (destructuring-bind (stream greeting capabilities stream-type)
          (open-protocol-stream
           "*nnimap*" (current-buffer) nnimap-address (car (last ports))
           :type nnimap-stream
@@ -362,6 +362,7 @@ textual parts.")
             (when (gnus-string-match-p "STARTTLS" capabilities)
               "1 STARTTLS\r\n")))
        (setf (nnimap-process nnimap-object) stream)
+       (setf (nnimap-stream-type nnimap-object) stream-type)
        (if (not stream)
            (progn
              (nnheader-report 'nnimap "Unable to contact %s:%s via %s"
@@ -411,15 +412,12 @@ textual parts.")
 
 (defun nnimap-login (user password)
   (cond
-   ((not (nnimap-capability "LOGINDISABLED"))
+   ;; Prefer plain LOGIN if it's enabled (since it requires fewer
+   ;; round trips than CRAM-MD5, and it's less likely to be buggy),
+   ;; and we're using an encrypted connection.
+   ((and (not (nnimap-capability "LOGINDISABLED"))
+        (eq (nnimap-stream-type nnimap-object) 'tls))
     (nnimap-command "LOGIN %S %S" user password))
-   ((nnimap-capability "AUTH=PLAIN")
-    (nnimap-command
-     "AUTHENTICATE PLAIN %s"
-     (base64-encode-string
-      (format "\000%s\000%s"
-             (nnimap-quote-specials user)
-             (nnimap-quote-specials password)))))
    ((nnimap-capability "AUTH=CRAM-MD5")
     (erase-buffer)
     (let ((sequence (nnimap-send-command "AUTHENTICATE CRAM-MD5"))
@@ -432,7 +430,16 @@ textual parts.")
                 (rfc2104-hash 'md5 64 16 password
                               (base64-decode-string challenge))))
        "\r\n"))
-      (nnimap-wait-for-response sequence)))))
+      (nnimap-wait-for-response sequence)))
+   ((not (nnimap-capability "LOGINDISABLED"))
+    (nnimap-command "LOGIN %S %S" user password))
+   ((nnimap-capability "AUTH=PLAIN")
+    (nnimap-command
+     "AUTHENTICATE PLAIN %s"
+     (base64-encode-string
+      (format "\000%s\000%s"
+             (nnimap-quote-specials user)
+             (nnimap-quote-specials password)))))))
 
 (defun nnimap-quote-specials (string)
   (with-temp-buffer
@@ -512,15 +519,17 @@ textual parts.")
     (with-current-buffer (nnimap-buffer)
       (when (stringp article)
        (setq article (nnimap-find-article-by-message-id group article)))
-      (nnimap-get-whole-article
-       article (format "UID FETCH %%d %s"
-                      (nnimap-header-parameters)))
-      (let ((buffer (current-buffer)))
-       (with-current-buffer (or to-buffer nntp-server-buffer)
-         (erase-buffer)
-         (insert-buffer-substring buffer)
-         (nnheader-ms-strip-cr)
-         (cons group article))))))
+      (if (null article)
+         nil
+       (nnimap-get-whole-article
+        article (format "UID FETCH %%d %s"
+                        (nnimap-header-parameters)))
+       (let ((buffer (current-buffer)))
+         (with-current-buffer (or to-buffer nntp-server-buffer)
+           (erase-buffer)
+           (insert-buffer-substring buffer)
+           (nnheader-ms-strip-cr)
+           (cons group article)))))))
 
 (defun nnimap-get-whole-article (article &optional command)
   (let ((result
@@ -582,7 +591,7 @@ textual parts.")
     ;; Collect all the body parts.
     (while (looking-at ".*BODY\\[\\([.0-9]+\\)\\]")
       (setq id (match-string 1)
-           bytes (nnimap-get-length))
+           bytes (or (nnimap-get-length) 0))
       (beginning-of-line)
       (delete-region (point) (progn (forward-line 1) (point)))
       (push (list id (buffer-substring (point) (+ (point) bytes)))
@@ -1580,17 +1589,14 @@ textual parts.")
          (goto-char (point-max))
          (while (and (setq openp (memq (process-status process)
                                        '(open run)))
-                     (not (re-search-backward
-                           (format "^%d .*\n" sequence)
-                           (if nnimap-streaming
-                               (max (point-min)
-                                    (min
-                                     (- (point) 500)
-                                     (save-excursion
-                                       (forward-line -3)
-                                       (point))))
-                             (point-min))
-                           t)))
+                     (progn
+                       ;; Skip past any "*" lines that the server has
+                       ;; output.
+                       (while (and (not (bobp))
+                                   (progn
+                                     (forward-line -1)
+                                     (looking-at "\\*"))))
+                       (not (looking-at (format "%d " sequence)))))
            (when messagep
              (nnheader-message 7 "nnimap read %dk" (/ (buffer-size) 1000)))
            (nnheader-accept-process-output process)