[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

nnimap 0.3.27 released



Bugfixes and some code re-design.

My folder collection just went over 75MB so expiring is the next thing
to do. :-)

Get it from http://vic20.dzp.se/gnus-imap/nnimap.tar.gz.

/s

1998-08-23 18:51:23  Simon Josefsson  <jas@pdc.kth.se>

	* nnimap 0.3.27 released.

1998-08-23 17:57:20  Simon Josefsson  <jas@pdc.kth.se>

	* nnimap.el (nnimap-possibly-change-group): Unselect folder on
	uidvalidity change.

	* nnimap.el (nnimap-request-article-part): Argument peek renamed
	to add-peek.

	* nnimap.el (nnimap-request-list-mapper): Spaces are already
	ignored. Use 1-.

	* nnimap.el (nnimap-request-update-info): Can't update active
	info.
	
	* nnimap.el (nnimap-request-group):
	(nnimap-retrieve-headers):
	(nnimap-open-server):
	(nnimap-close-group):
	(nnimap-request-list-mapper):
	(nnimap-request-article-part):
	(nnimap-request-list):
	(nnimap-request-update-info):
	(nnimap-split-articles):
	(nnimap-possibly-change-group): Update to use new imap.el
	functions.

	* imap.el (imap-message-reset): New function.
	(imap-capability-get): Set if nil, set to IMAP2 if server didn't
	get it.
	(imap-folder-map): New function.
	(imap-open-server): Initialize imap-data-folder.
	(imap-authenticate-cram-md5): Don't send CAPABILITY.

1998-08-23 17:28:38  Simon Josefsson  <jas@pdc.kth.se>

	* nnimap.el (gnus-group-edit-nnimap-acl): Use
	destructive-plist-to-alist.

1998-08-23 17:28:33  Simon Josefsson  <jas@pdc.kth.se>

	* nnimap.el (nnimap-pattern-to-list-arguments): New function
	(nnimap-request-list): Use it.

	* imap.el (imap-select-folder):
	(imap-unselect-folder): 
	(imap-expunge-close-folder): New functions.
	(imap-open-server): Set imap-data-folder.

1998-08-23 15:08:58  Simon Josefsson  <jas@pdc.kth.se>

	* imap.el (imap-search):
	* nnimap.el (nnimap-search): Move to imap.el.

Index: nnimap/ChangeLog
diff -c nnimap/ChangeLog:1.56 nnimap/ChangeLog:1.58
*** nnimap/ChangeLog:1.56	Sun Aug 23 05:42:29 1998
--- nnimap/ChangeLog	Sun Aug 23 09:53:05 1998
***************
*** 1,3 ****
--- 1,60 ----
+ 1998-08-23 18:51:23  Simon Josefsson  <jas@pdc.kth.se>
+ 
+ 	* nnimap 0.3.27 released.
+ 
+ 1998-08-23 17:57:20  Simon Josefsson  <jas@pdc.kth.se>
+ 
+ 	* nnimap.el (nnimap-possibly-change-group): Unselect folder on
+ 	uidvalidity change.
+ 
+ 	* nnimap.el (nnimap-request-article-part): Argument peek renamed
+ 	to add-peek.
+ 
+ 	* nnimap.el (nnimap-request-list-mapper): Spaces are already
+ 	ignored. Use 1-.
+ 
+ 	* nnimap.el (nnimap-request-update-info): Can't update active
+ 	info.
+ 	
+ 	* nnimap.el (nnimap-request-group):
+ 	(nnimap-retrieve-headers):
+ 	(nnimap-open-server):
+ 	(nnimap-close-group):
+ 	(nnimap-request-list-mapper):
+ 	(nnimap-request-article-part):
+ 	(nnimap-request-list):
+ 	(nnimap-request-update-info):
+ 	(nnimap-split-articles):
+ 	(nnimap-possibly-change-group): Update to use new imap.el
+ 	functions.
+ 
+ 	* imap.el (imap-message-reset): New function.
+ 	(imap-capability-get): Set if nil, set to IMAP2 if server didn't
+ 	get it.
+ 	(imap-folder-map): New function.
+ 	(imap-open-server): Initialize imap-data-folder.
+ 	(imap-authenticate-cram-md5): Don't send CAPABILITY.
+ 
+ 1998-08-23 17:28:38  Simon Josefsson  <jas@pdc.kth.se>
+ 
+ 	* nnimap.el (gnus-group-edit-nnimap-acl): Use
+ 	destructive-plist-to-alist.
+ 
+ 1998-08-23 17:28:33  Simon Josefsson  <jas@pdc.kth.se>
+ 
+ 	* nnimap.el (nnimap-pattern-to-list-arguments): New function
+ 	(nnimap-request-list): Use it.
+ 
+ 	* imap.el (imap-select-folder):
+ 	(imap-unselect-folder): 
+ 	(imap-expunge-close-folder): New functions.
+ 	(imap-open-server): Set imap-data-folder.
+ 
+ 1998-08-23 15:08:58  Simon Josefsson  <jas@pdc.kth.se>
+ 
+ 	* imap.el (imap-search):
+ 	* nnimap.el (nnimap-search): Move to imap.el.
+ 
  1998-08-23 14:40:47  Simon Josefsson  <jas@pdc.kth.se>
  
  	* nnimap 0.3.26 released.
Index: nnimap/imap.el
diff -c nnimap/imap.el:1.27 nnimap/imap.el:1.28
*** nnimap/imap.el:1.27	Fri Aug 21 14:04:20 1998
--- nnimap/imap.el	Sun Aug 23 09:29:08 1998
***************
*** 27,35 ****
  ;;; the current group.  All the parameter variables become local
  ;;; to the IMAP process buffer.
  
  ;;; Todo:
! ;;;   On expunge, remove messages from message-data. Note it doesn't
! ;;;     return UIDs.  Ouch.
  
  (eval-when-compile (require 'cl))
  
--- 27,46 ----
  ;;; the current group.  All the parameter variables become local
  ;;; to the IMAP process buffer.
  
+ ;;; RFC1730 (IMAP4): done
+ ;;; RFC1731 (Authentication mecanisms): currently only support for KERBEROS_V4
+ ;;; RFC2060 (IMAP4rev1): done
+ ;;; RFC???? (UNSELECT ext): done
+ ;;; RFC2195 (CRAM-MD5 auth): done
+ ;;; RFC2086 (ACL ext): done
+ ;;; RFC2359 (UIDPLUS ext): done
+ 
  ;;; Todo:
! ;;; 
! ;;; o On expunge, remove messages from message-data. Note it doesn't
! ;;;   return UIDs.  Ouch.
! ;;; o Rename "folder" to "mailbox".
! ;;; 
  
  (eval-when-compile (require 'cl))
  
***************
*** 193,199 ****
          '(imap-open-server
            imap-close-server
            imap-server-opened
! 	  imap-select-mailbox
            imap-send-command
            imap-send-command-wait
            imap-send-commands-wait
--- 204,212 ----
          '(imap-open-server
            imap-close-server
            imap-server-opened
! 	  imap-select-folder
! 	  imap-unselect-folder
! 	  imap-expunge-close-folder
            imap-send-command
            imap-send-command-wait
            imap-send-commands-wait
***************
*** 208,217 ****
--- 221,232 ----
  	  imap-authenticate
  	  imap-authenticate-login
  	  imap-authenticate-cram-md5
+ 	  imap-search
            imap-message-set
            imap-message-get
            imap-message-map
            imap-message-plist
+ 	  imap-message-reset
            imap-cb-response
            imap-cb-bye
            imap-cb-numbered
***************
*** 332,338 ****
    (require 'md5)
    (with-current-buffer (or buffer (current-buffer))
      (and (imap-authinfo-get server)
- 	 (or (imap-capability-get) (imap-send-command-wait "CAPABILITY"))
  	 (memq 'AUTH=CRAM-MD5 (imap-capability-get))
  	 (imap-ok-p 
  	  (imap-send-command-wait
--- 347,352 ----
***************
*** 368,377 ****
        (setq imap-tag-char (int-char (+ (char-int ?A) 
  				       (% imap-connection-number 26))))
        (setq imap-connection-number (1+ imap-connection-number))
! ; I really don't get this.  Is it needed.  If it is, does it really save
! ;   all that much time and/or effort.
! ;      (setq imap-data-folder
! ;            (make-vector imap-convenient-group-prime 0))
        (current-buffer))))
  
  ;; If there is a need for sending commands without a callback, then
--- 382,388 ----
        (setq imap-tag-char (int-char (+ (char-int ?A) 
  				       (% imap-connection-number 26))))
        (setq imap-connection-number (1+ imap-connection-number))
!       (setq imap-data-folder (make-vector imap-convenient-group-prime 0))
        (current-buffer))))
  
  ;; If there is a need for sending commands without a callback, then
***************
*** 472,481 ****
--- 483,533 ----
      (setq imap-last-status nil)
      t))
  
+ (defun imap-search (predicate &optional buffer)
+   (with-current-buffer (or buffer (current-buffer))
+     (imap-folder-set 'search nil)
+     (when (imap-ok-p (imap-send-command-wait (concat "UID SEARCH " predicate)))
+       (imap-folder-get 'search))))
+ 
+ (defun imap-select-folder (folder &optional buffer examine)
+   (with-current-buffer (or buffer (current-buffer))
+     ;; xxx: check SELECT/EXAMINE status!  This is BAD.
+     (unless (string= folder imap-current-folder)   
+       (setq imap-current-folder folder)
+       (if (imap-ok-p (imap-send-command-wait
+ 		      (concat (if examine "EXAMINE" "SELECT") " " folder)))
+ 	  (setq imap-message-data (make-vector imap-convenient-folder-prime 0))
+ 	;; Failed SELECT unselects the current group
+ 	(setq imap-current-folder nil
+ 	      imap-message-data nil)))
+     imap-current-folder))
+ 
+ (defun imap-unselect-folder (group &optional buffer)
+   "Close current folder in BUFFER, without expunging articles."
+   (with-current-buffer (or buffer (current-buffer))
+     (when (or (and (memq 'UNSELECT (imap-capability-get))
+ 		   (imap-ok-p (imap-send-command-wait "UNSELECT")))
+ 	      (and (imap-ok-p 
+ 		    (imap-send-command-wait (concat "EXAMINE " group)))
+ 		   (imap-ok-p (nnimap-send-command-wait "CLOSE"))))
+       (setq imap-current-folder nil
+ 	    imap-message-data nil))))
+ 
+ (defun imap-expunge-close-folder (&optional buffer)
+   "Expunge articles and close current folder in BUFFER."
+   (with-current-buffer (or buffer (current-buffer))
+     (when (imap-ok-p (imap-send-command-wait "CLOSE"))
+       (setq imap-current-folder nil
+ 	    imap-message-data nil))))
+ 
  ;;; Variable setters and getters
  
  (defun imap-capability-get (&optional buffer)
+   "Return a list of identifiers which the server support."
    (with-current-buffer (or buffer (current-buffer))
+     (unless imap-data-capability
+       (unless (imap-send-command-wait "CAPABILITY")
+ 	(setq imap-data-capbility '(IMAP2))))
      imap-data-capability))
  
  (defun imap-folder-plist (&optional folder buffer)
***************
*** 498,503 ****
--- 550,563 ----
      (get (intern (or folder
                       imap-current-folder) imap-data-folder) prop)))
  
+ (defun imap-folder-map (func &optional buffer)
+   "Call (func FOLDER) for each folder in `imap-data-folder'."
+   (with-current-buffer (or buffer (current-buffer))
+     (mapatoms 
+      (lambda (s)
+        (funcall func (symbol-name s)))
+      imap-data-folder)))
+ 
  ;;; Internal functions
  
  (defun imap-read-passwd (prompt &rest args)
***************
*** 822,829 ****
  
  (defun imap-message-get (id prop &optional buffer)
    "Get PROP for message ID in BUFFER."
    (with-current-buffer (or buffer (current-buffer)) 
!     (get (intern (imap-message-to-string id) imap-message-data) prop)))
  
  ; Fetches MUST include (UID) otherwise we can't store the results.
  ; NUM is always the logical message number not the UID.  We ignore it.
--- 882,893 ----
  
  (defun imap-message-get (id prop &optional buffer)
    "Get PROP for message ID in BUFFER."
+   (with-current-buffer (or buffer (current-buffer))  
+    (get (intern (imap-message-to-string id) imap-message-data) prop)))
+ 
+ (defun imap-message-reset (&optional buffer)
    (with-current-buffer (or buffer (current-buffer)) 
!     (setq imap-message-data (make-vector imap-convenient-folder-prime 0))))
  
  ; Fetches MUST include (UID) otherwise we can't store the results.
  ; NUM is always the logical message number not the UID.  We ignore it.
Index: nnimap/nnimap.el
diff -c nnimap/nnimap.el:1.50 nnimap/nnimap.el:1.51
*** nnimap/nnimap.el:1.50	Sun Aug 23 05:34:26 1998
--- nnimap/nnimap.el	Sun Aug 23 09:29:41 1998
***************
*** 45,57 ****
  ;;; Yep, I just checked.  It is fixed in at least 5.6.27.  It was
  ;;; still broken in 5.5.
  
- ;;; RFC1730 (IMAP4): done
- ;;; RFC1731 (Authentication mecanisms): currently only support for KERBEROS_V4
- ;;; RFC2060 (IMAP4rev1): done
- ;;; RFC2086 (ACL's): done
- ;;; RFC2195 (CRAM-MD5): done
- ;;; RFC2359 (UIDPLUS ext): done
- 
  ;;; Todo (roughly in order of priority):
  
  ;;;   o Convert the manual to texi.
--- 45,50 ----
***************
*** 109,117 ****
  
  (nnoo-declare nnimap) ; we derive from no one
  
! (defconst nnimap-version "nnimap 0.3.26")
  
! ;; External variables.
  
  (defvoo nnimap-list-pattern "*" 
  "*PATTERN or list of PATTERNS use to limit available groups.  
--- 102,110 ----
  
  (nnoo-declare nnimap) ; we derive from no one
  
! (defconst nnimap-version "nnimap 0.3.27")
  
! ;; Various server variables.
  
  (defvoo nnimap-list-pattern "*" 
  "*PATTERN or list of PATTERNS use to limit available groups.  
***************
*** 165,170 ****
--- 158,171 ----
  port-extended address in your authinfo file, and don't use this
  variable at all.")
  
+ (defvoo nnimap-imap-defs nil
+   "*Definitions of variables to set up in the IMAP buffer.")
+ 
+ (defvoo nnimap-group-list-speed 'slow ; 'fast, 'medium
+   "*If fast, do not show number of articles in the group list.
+ If medium, guess number of articles by using the UIDNEXT attribute.
+ If slow, fetch the UID of lowest/highest article.")
+ 
  ;; Splitting variables
  
  (defvar nnimap-split-crosspost t
***************
*** 203,216 ****
  the argument.  It should return a non-nil value if it thinks that the
  mail belongs in that group.")
  
- (defvoo nnimap-imap-defs nil
-   "*Definitions of variables to set up in the IMAP buffer.")
- 
- (defvoo nnimap-group-list-speed 'slow ; 'fast, 'medium
-   "*If fast, do not show number of articles in the group list.
- If medium, guess number of articles by using the UIDNEXT attribute.
- If slow, fetch the UID of lowest/highest article.")
- 
  ;; Authorization / Privacy variables
  
  ;; todo:
--- 204,209 ----
***************
*** 310,316 ****
            nnimap-server-opened
            nnimap-status-message
  	  nnimap-update-alist-soft
- 	  nnimap-search
  	  nnimap-range-to-string
            nnimap-request-expire-articles
            nnimap-request-move-article
--- 303,308 ----
***************
*** 353,386 ****
        (when (numberp fetch-old) 
          (setcar uncompressed (- (car uncompressed) fetch-old)))
        (setq compressed (gnus-compress-sequence uncompressed t))
-       ;; Should we clear `imap-data-folder' ???
        (with-current-buffer nnimap-server-buffer
!         (when 
!             ;; Should we clear `imap-message-data' before this???  If
!             ;; we don't need to cache the headers then I think we
!             ;; should.
!             (nnimap-ok-p (nnimap-send-command-wait
!                           (concat "UID FETCH "
!                                   (if (and fetch-old (not (numberp fetch-old)))
!                                       "1:*"
!                                     (nnimap-range-to-string compressed))
!                                   " (UID RFC822.HEADER RFC822.SIZE BODY)")))
!           (mapc (lambda (num)
!                   (let* ((header (imap-message-get num 'RFC822.HEADER))
! 			 (size   (imap-message-get num 'RFC822.SIZE))
! 			 (body   (imap-message-get num 'BODY))
! 			 (lines  (nnimap-body-lines body)))
!                     (with-current-buffer nntp-server-buffer
!                       (if (not header)
!                           (insert "423 Bad article number.\n")
!                         (insert (format "221 %d Article retrieved.\n" num))
! 			(insert (format "Chars: %d\n" size))
! 			(insert (format "Lines: %d\n" lines))
!                         (insert header)
!                         (delete-char -1)
!                         (insert ".\n")))))
!                 uncompressed)
!           'headers)))))
  
  (defun nnimap-authenticate (server &optional buffer)
    (with-current-buffer (or buffer (current-buffer))
--- 345,378 ----
        (when (numberp fetch-old) 
          (setcar uncompressed (- (car uncompressed) fetch-old)))
        (setq compressed (gnus-compress-sequence uncompressed t))
        (with-current-buffer nnimap-server-buffer
! 	;; Reset message info, this makes sure we return 423 on
! 	;; articles that were removed by another client while we
! 	;; had the mailbox SELECTed. This isn't really necessery (the user
! 	;; will find out when he selects the article anyway).
! 	;(imap-message-reset)
! 	(nnimap-ok-p (nnimap-send-command-wait
! 		      (concat "UID FETCH "
! 			      (if (and fetch-old (not (numberp fetch-old)))
! 				  "1:*"
! 				(nnimap-range-to-string compressed))
! 			      " (UID RFC822.HEADER RFC822.SIZE BODY)")))
! 	(mapc (lambda (num)
! 		(let* ((header (imap-message-get num 'RFC822.HEADER))
! 		       (size   (imap-message-get num 'RFC822.SIZE))
! 		       (body   (imap-message-get num 'BODY))
! 		       (lines  (nnimap-body-lines body)))
! 		  (with-current-buffer nntp-server-buffer
! 		    (if (not header)
! 			(insert "423 Bad article number.\n")
! 		      (insert (format "221 %d Article retrieved.\n" num))
! 		      (insert (format "Chars: %d\n" size))
! 		      (insert (format "Lines: %d\n" lines))
! 		      (insert header)
! 		      (delete-char -1)
! 		      (insert ".\n")))))
! 	      uncompressed)
! 	'headers))))
  
  (defun nnimap-authenticate (server &optional buffer)
    (with-current-buffer (or buffer (current-buffer))
***************
*** 407,413 ****
  	(sleep-for 2)
  	(setq ok (imap-authenticate server buffer)))
        ok)))
!       
  (deffoo nnimap-open-server (server &optional defs)
    (or (and (nnimap-server-opened server)
  	   (nnoo-change-server 'nnimap server defs)
--- 399,407 ----
  	(sleep-for 2)
  	(setq ok (imap-authenticate server buffer)))
        ok)))
! 
! ;; todo:
! ;;   only condition-case on imap-open-stream??
  (deffoo nnimap-open-server (server &optional defs)
    (or (and (nnimap-server-opened server)
  	   (nnoo-change-server 'nnimap server defs)
***************
*** 437,450 ****
  					nnimap-server-buffer 
  					nnimap-imap-defs)
  		  ;; we only support imap4.*
! 		  (unless (and (nnimap-ok-p (nnimap-send-command-wait 
! 					     "CAPABILITY" nnimap-server-buffer))
! 			       (or (memq 'IMAP4 (imap-capability-get
! 						 nnimap-server-buffer))
! 				   (memq 'IMAP4rev1 (imap-capability-get
! 						     nnimap-server-buffer))
! 				   (memq 'IMAP4REV1 (imap-capability-get
! 						     nnimap-server-buffer))))
  		    (imap-close-server nnimap-server-buffer)
  		    (nnheader-report 
  		     'nnimap 
--- 431,442 ----
  					nnimap-server-buffer 
  					nnimap-imap-defs)
  		  ;; we only support imap4.*
! 		  (unless (or (memq 'IMAP4 (imap-capability-get
! 					    nnimap-server-buffer))
! 			      (memq 'IMAP4rev1 (imap-capability-get
! 						nnimap-server-buffer))
! 			      (memq 'IMAP4REV1 (imap-capability-get
! 						nnimap-server-buffer)))
  		    (imap-close-server nnimap-server-buffer)
  		    (nnheader-report 
  		     'nnimap 
***************
*** 513,525 ****
    (nnimap-request-article-part 'RFC822.TEXT article group server to-buffer t))
  
  (defun nnimap-request-article-part (part article &optional 
! 					 group server to-buffer peek)
    (when (nnimap-possibly-change-group group server)
      (with-current-buffer nnimap-server-buffer
        (when (stringp article)
          ;; Find the article number by Message-Id
!         (let ((articles (nnimap-search 
! 			 (format "HEADER Message-Id %d" article))))
            (when (cdr articles)
              (message 
               "IMAP Warning: Message Id search yielded more than one article %s"
--- 505,516 ----
    (nnimap-request-article-part 'RFC822.TEXT article group server to-buffer t))
  
  (defun nnimap-request-article-part (part article &optional 
! 					 group server to-buffer add-peek)
    (when (nnimap-possibly-change-group group server)
      (with-current-buffer nnimap-server-buffer
        (when (stringp article)
          ;; Find the article number by Message-Id
!         (let ((articles (imap-search (format "HEADER Message-Id %d" article))))
            (when (cdr articles)
              (message 
               "IMAP Warning: Message Id search yielded more than one article %s"
***************
*** 528,542 ****
        (when article
          ;; Find the article by number
          (nnimap-send-command-wait (format "UID FETCH %d (%s%s)" article part
! 					  (if peek ".PEEK" "")))
          (let ((text (imap-message-get article part)))
            (with-current-buffer (or to-buffer nntp-server-buffer)
              (erase-buffer)
              (if (not text)
!                 (nnheader-report 
! 		 'nnimap 
! 		 (format "Article %s does not exist." article))
!               (insert text) 
  	      t)))))))
  
  ;;; Select GROUP and unless FAST return 211 EXISTS LOWEST HIGHEST GROUP
--- 519,532 ----
        (when article
          ;; Find the article by number
          (nnimap-send-command-wait (format "UID FETCH %d (%s%s)" article part
! 					  (if add-peek ".PEEK" "")))
          (let ((text (imap-message-get article part)))
            (with-current-buffer (or to-buffer nntp-server-buffer)
              (erase-buffer)
              (if (not text)
!                 (nnheader-report 'nnimap 
! 				 (format "Article %s does not exist." article))
!               (insert text)
  	      t)))))))
  
  ;;; Select GROUP and unless FAST return 211 EXISTS LOWEST HIGHEST GROUP
***************
*** 567,574 ****
  ;	  (erase-buffer)
  ;	  t)
        (with-current-buffer nnimap-server-buffer
! 	(let ((imap-message-data (make-vector 2 0))
! 	      (exists (imap-folder-get 'EXISTS))
  	      articles)
  	  (if (eq 0 exists)
  	      (setq articles '(0))
--- 557,567 ----
  ;	  (erase-buffer)
  ;	  t)
        (with-current-buffer nnimap-server-buffer
! 	;; clear message data, we won't necesserily have to do this if
! 	;; it weren't for buggy CCmail (we can't know how many tagged
! 	;; responses were returned otherwise).
! 	(imap-message-reset)
! 	(let ((exists (imap-folder-get 'EXISTS))
  	      articles)
  	  (if (eq 0 exists)
  	      (setq articles '(0))
***************
*** 624,629 ****
--- 617,623 ----
  
  ;;; We need to optimize for no changes i.e. doing Q.  We should
  ;;; not touch the server.
+ ;;; When someone Qs out of a group we could EXAMINE first???
  (deffoo nnimap-close-group (group &optional server)
    (when (nnimap-possibly-change-group group server)
      (setq server (or server (nnoo-current-server 'nnimap)))
***************
*** 656,670 ****
                                    (nnimap-range-to-string val)
                                    " +FLAGS.SILENT (" (cdr mark-flag) ")"))))))
               nnimap-mark-to-flag-alist)))
-       ;; When someone Qs out of a group we could EXAMINE first???
        ;; Close her up.  We don't necessarily have to do this.
!       (when (or (and (memq 'UNSELECT (imap-capability-get))
! 		     (nnimap-ok-p (nnimap-send-command-wait "UNSELECT")))
! 		(and (nnimap-ok-p 
! 		      (nnimap-send-command-wait (concat "EXAMINE " group)))
! 		     (nnimap-ok-p (nnimap-send-command-wait "CLOSE"))))
!         (setq imap-current-folder nil
!               imap-message-data nil)
  	t))))
  
  ;;; Returns: GROUP HIGHEST LOWEST [ynmxj=]
--- 650,657 ----
                                    (nnimap-range-to-string val)
                                    " +FLAGS.SILENT (" (cdr mark-flag) ")"))))))
               nnimap-mark-to-flag-alist)))
        ;; Close her up.  We don't necessarily have to do this.
!       (when (imap-unselect-folder group)
  	t))))
  
  ;;; Returns: GROUP HIGHEST LOWEST [ynmxj=]
***************
*** 676,691 ****
        (gnus-message 7 "Generating active list for nnimap group %s" group)
        (cond 
         ((eq nnimap-group-list-speed 'slow)
! 	(when (nnimap-possibly-change-group group nil)
! 	  (let ((imap-message-data (make-vector 2 0))
! 		(exists (imap-folder-get 'EXISTS))
  		articles)
  	    (if (eq 0 exists)
  		(with-current-buffer nntp-server-buffer
  		  (insert (format "%s 0 1 y\n" group)))
! 	      (when (nnimap-ok-p (nnimap-send-command-wait
! 				  "FETCH 1,* (UID)"))
! 		(imap-message-map (lambda (uid Uid) 
  				    (push uid articles)) 'UID)
  		;; start of bug workaround code
  		;; Lotus CCmail is broken, returns:
--- 663,678 ----
        (gnus-message 7 "Generating active list for nnimap group %s" group)
        (cond 
         ((eq nnimap-group-list-speed 'slow)
! 	(when (imap-select-folder group)
! 	  (let ((exists (imap-folder-get 'EXISTS))
  		articles)
  	    (if (eq 0 exists)
  		(with-current-buffer nntp-server-buffer
  		  (insert (format "%s 0 1 y\n" group)))
! 	      ;; if it weren't for buggy CCmail we needn't reset
! 	      (imap-message-reset)
! 	      (when (nnimap-ok-p (nnimap-send-command-wait "FETCH 1,* (UID)"))
! 		(imap-message-map (lambda (uid Uid)
  				    (push uid articles)) 'UID)
  		;; start of bug workaround code
  		;; Lotus CCmail is broken, returns:
***************
*** 694,701 ****
  		;; C13 OK Completed
  		;; we fetch * in addition
  		(when (< 2 (length articles))
! 		  (when (nnimap-ok-p (nnimap-send-command-wait 
! 				      "FETCH * (UID"))
  		    (imap-message-map (lambda (uid Uid)
  					(push uid articles)) 'UID)))
  		;; end of bug workaround code
--- 681,687 ----
  		;; C13 OK Completed
  		;; we fetch * in addition
  		(when (< 2 (length articles))
! 		  (when (nnimap-ok-p (nnimap-send-command-wait "FETCH * (UID"))
  		    (imap-message-map (lambda (uid Uid)
  					(push uid articles)) 'UID)))
  		;; end of bug workaround code
***************
*** 706,718 ****
  				    (apply 'min articles)))
  		    t)))))))
         ((eq nnimap-group-list-speed 'medium)
- 	;; Need to quote group if it has spaces!!!???
  	(when (nnimap-ok-p (nnimap-send-command-wait
  			    (concat "STATUS " group 
  				    " (UIDNEXT)")))
! 	  (setq high (imap-folder-get 'UIDNEXT group))
  	  (with-current-buffer nntp-server-buffer
! 	    (insert (format "%s %d 1 y\n" group (- high 1)))
  	    t)))
         ((eq nnimap-group-list-speed 'fast)
  	(with-current-buffer nntp-server-buffer
--- 692,703 ----
  				    (apply 'min articles)))
  		    t)))))))
         ((eq nnimap-group-list-speed 'medium)
  	(when (nnimap-ok-p (nnimap-send-command-wait
  			    (concat "STATUS " group 
  				    " (UIDNEXT)")))
! 	  (setq high (1- (imap-folder-get 'UIDNEXT group)))
  	  (with-current-buffer nntp-server-buffer
! 	    (insert (format "%s %d 1 y\n" group high))
  	    t)))
         ((eq nnimap-group-list-speed 'fast)
  	(with-current-buffer nntp-server-buffer
***************
*** 722,755 ****
  	(error "Unknown nnimap-group-list-speed: %s"
  	       nnimap-group-list-speed))))))
  
  ;;; Returns: GROUP HIGHEST LOWEST [ynmxj=]
  (deffoo nnimap-request-list (&optional server)
    (when (nnimap-possibly-change-server server)
      (with-current-buffer nntp-server-buffer (erase-buffer))
      (with-current-buffer nnimap-server-buffer
!       (setq imap-data-folder (make-vector imap-convenient-group-prime 0)
! 	    imap-current-folder nil)
!       (message "ok")
!       (let* ((patterns (mapcar (lambda (p) (if (consp p)
! 					       p 
! 					     (cons "\"\"" p)))
! 			       (if (and (listp nnimap-list-pattern)
! 					(listp (cdr nnimap-list-pattern)))
! 				   nnimap-list-pattern
! 				 (list nnimap-list-pattern))))
  	     pattern)
  	(while (setq pattern (pop patterns))
  	  (nnimap-ok-p (nnimap-send-command-wait
                          (concat nnimap-list-method " "
                                  (car pattern) " "
!                                 (cdr pattern)))))
!         (gnus-message 5 "Generating active list for %s" server)
! 	(let ((nnimap-group-list-speed 'fast))
! 	  (mapatoms (lambda (sym) (nnimap-request-list-mapper 
! 				   (symbol-name sym)))
! 		    imap-data-folder)))
!     (setq nnimap-group-alist (nnmail-get-active))
!     t)))
    
  
  ;;; IMAP doesn't support posting, but this must be defined
--- 707,738 ----
  	(error "Unknown nnimap-group-list-speed: %s"
  	       nnimap-group-list-speed))))))
  
+ (defun nnimap-pattern-to-list-arguments (pattern)
+   (mapcar (lambda (p) (if (consp p)
+ 			  p 
+ 			(cons "\"\"" p)))
+ 	  (if (and (listp pattern)
+ 		   (listp (cdr pattern)))
+ 	      pattern
+ 	    (list pattern))))
+ 
  ;;; Returns: GROUP HIGHEST LOWEST [ynmxj=]
  (deffoo nnimap-request-list (&optional server)
    (when (nnimap-possibly-change-server server)
      (with-current-buffer nntp-server-buffer (erase-buffer))
      (with-current-buffer nnimap-server-buffer
!       (let* ((patterns (nnimap-pattern-to-list-arguments nnimap-list-pattern))
  	     pattern)
+ 	(gnus-message 5 "Generating active list for %s" server)
  	(while (setq pattern (pop patterns))
  	  (nnimap-ok-p (nnimap-send-command-wait
                          (concat nnimap-list-method " "
                                  (car pattern) " "
!                                 (cdr pattern))))))
!       (let ((nnimap-group-list-speed 'fast))
! 	(imap-folder-map 'nnimap-request-list-mapper))
!       (setq nnimap-group-alist (nnmail-get-active))
!       t)))
    
  
  ;;; IMAP doesn't support posting, but this must be defined
***************
*** 796,807 ****
        (and (string-match "gnus-" (cdr mark-string))
             (member "\\*" (imap-folder-get 'permanentflags group)))))
    
- ;;; I really think this should update the active-info too???
  (deffoo nnimap-request-update-info (group info &optional server silly)
    (when silly
      (when (nnimap-possibly-change-group group server) ;; SELECT
        (with-current-buffer nnimap-server-buffer
! 	(gnus-message 5 "Updating active info for mailbox %s" group)
  	
  	;; extend info to have parameters (otherwise when we set them, 
  	;; they don't get set)
--- 779,789 ----
        (and (string-match "gnus-" (cdr mark-string))
             (member "\\*" (imap-folder-get 'permanentflags group)))))
    
  (deffoo nnimap-request-update-info (group info &optional server silly)
    (when silly
      (when (nnimap-possibly-change-group group server) ;; SELECT
        (with-current-buffer nnimap-server-buffer
! 	(gnus-message 5 "Updating info for mailbox %s" group)
  	
  	;; extend info to have parameters (otherwise when we set them, 
  	;; they don't get set)
***************
*** 817,827 ****
  		;; oldseen could contain articles marked unread by other
  		;; imap clients!  we correct this
  		(oldseentmp (gnus-uncompress-range (gnus-info-read info)))
! 		(unseen (nnimap-search "UNSEEN"))
  		(oldseen (gnus-set-difference oldseentmp unseen))
  		;; oldseen might lack articles marked as read by other
  		;; imap clients! we correct this
! 		(newseen (nnimap-search "SEEN"))
  		;; ok, read articles are in oldseen+newseen (xxx lots of dupes)
  		(seen (append oldseen newseen))
  		;; sort to have gnus-compress-sequence remove dupes
--- 799,809 ----
  		;; oldseen could contain articles marked unread by other
  		;; imap clients!  we correct this
  		(oldseentmp (gnus-uncompress-range (gnus-info-read info)))
! 		(unseen (imap-search "UNSEEN"))
  		(oldseen (gnus-set-difference oldseentmp unseen))
  		;; oldseen might lack articles marked as read by other
  		;; imap clients! we correct this
! 		(newseen (imap-search "SEEN"))
  		;; ok, read articles are in oldseen+newseen (xxx lots of dupes)
  		(seen (append oldseen newseen))
  		;; sort to have gnus-compress-sequence remove dupes
***************
*** 838,844 ****
  		info 
  		(nnimap-update-alist-soft (car mark-search) 
  					  (gnus-compress-sequence 
! 					   (nnimap-search (cdr mark-search)))
  					  (gnus-info-marks info)))))
  	 nnimap-mark-to-predicate-alist))
        info)))
--- 820,826 ----
  		info 
  		(nnimap-update-alist-soft (car mark-search) 
  					  (gnus-compress-sequence 
! 					   (imap-search (cdr mark-search)))
  					  (gnus-info-marks info)))))
  	 nnimap-mark-to-predicate-alist))
        info)))
***************
*** 935,941 ****
  		    (nnimap-possibly-change-group inbox)) ;; SELECT
  	  ;; find split rule for this server / inbox
  	  (when (setq rule (nnimap-split-find-rule server inbox))
! 	    (let (article (unseens (nnimap-search "UNSEEN")))
  	      ;; iterate over articles
  	      (while (setq article (pop unseens))
  		(when (nnimap-request-head article)
--- 917,923 ----
  		    (nnimap-possibly-change-group inbox)) ;; SELECT
  	  ;; find split rule for this server / inbox
  	  (when (setq rule (nnimap-split-find-rule server inbox))
! 	    (let (article (unseens (imap-search "UNSEEN")))
  	      ;; iterate over articles
  	      (while (setq article (pop unseens))
  		(when (nnimap-request-head article)
***************
*** 951,964 ****
  		      ;; move to first matching box, if any
  		      (nnimap-split-move-article article inbox 
  						 (car groups))))))))
! 	      (when (nnimap-possibly-change-group inbox) ;; just in case
! 		;; todo: only remove splitted articles
! 		;; use UID EXPUNGE, unfortunely not in the standard :-(
! 		(nnimap-send-command-wait "EXPUNGE") ;; to get tagged data
! 		(when (nnimap-send-command-wait "CLOSE")
! 		  (setq imap-current-folder nil
! 			imap-message-data nil))))))
!     t))
  
  ;; nnimap-request-scan doesn't need to do anything. the delivery agent
  ;; program is responsible for putting new message in the imap folders.
--- 933,944 ----
  		      ;; move to first matching box, if any
  		      (nnimap-split-move-article article inbox 
  						 (car groups))))))))
! 	  (when (imap-select-folder inbox) ;; just in case
! 	    ;; todo: only remove splitted articles
! 	    ;; use UID EXPUNGE, unfortunely not in the standard :-(
! 	    (nnimap-send-command-wait "EXPUNGE") ;; debug: to get tagged data
! 	    (imap-expunge-close-folder)))
! 	t))))
  
  ;; nnimap-request-scan doesn't need to do anything. the delivery agent
  ;; program is responsible for putting new message in the imap folders.
***************
*** 1011,1017 ****
    (when force
      (when (nnimap-possibly-change-group group server)
        (with-current-buffer nnimap-server-buffer
! ;;;        (setq deleted (nnimap-search "DELETED"))
  ;;;        (nnimap-ok-p (nnimap-send-command-wait "EXPUNGE"))
  ;;;        (setq articles (gnus-sorted-complement articles deleted)))))
          (when (nnimap-ok-p (nnimap-send-command-wait 
--- 991,997 ----
    (when force
      (when (nnimap-possibly-change-group group server)
        (with-current-buffer nnimap-server-buffer
! ;;;        (setq deleted (imap-search "DELETED"))
  ;;;        (nnimap-ok-p (nnimap-send-command-wait "EXPUNGE"))
  ;;;        (setq articles (gnus-sorted-complement articles deleted)))))
          (when (nnimap-ok-p (nnimap-send-command-wait 
***************
*** 1130,1141 ****
  	(nnheader-report 'nnimap (cdr status)))
      (nnheader-report 'nnimap (format "IMAP Command Timed Out"))))
  
- (defun nnimap-search (predicate)
-   (imap-folder-set 'search nil)
-   (when (nnimap-ok-p (nnimap-send-command-wait 
- 		      (concat "UID SEARCH " predicate)))
-     (imap-folder-get 'search)))
- 
  (defun nnimap-possibly-change-server (server)
    "Change to server SERVER if needed (open it if it's closed). If SERVER is
  nil, change to current server."
--- 1110,1115 ----
***************
*** 1143,1182 ****
         (nnimap-open-server server)))
  
  (defun nnimap-possibly-change-group (group &optional server)
    (when (nnimap-possibly-change-server server)
-     (setq server (or server (nnoo-current-server 'nnimap)))
      (with-current-buffer nnimap-server-buffer
        (when group
! 	(unless (string= group imap-current-folder)
! 	  (setq imap-message-data (make-vector 199 0)) ; itty bitty obarray???
! 	  ;; Folder must be set during SELECT
! 	  (setq imap-current-folder group)
!           (let ((groupname (gnus-group-normally-qualified
!                             'nnimap server group)))
!             (if (not (nnimap-ok-p (nnimap-send-command-wait
!                                    (concat (if (gnus-ephemeral-group-p
!                                                 groupname)
!                                                "EXAMINE"
!                                              "SELECT")
!                                            " " group))))
!                 ;; Failed SELECT unselects the current group
!                 (setq imap-current-folder nil)
!               ;; check/set UIDVALIDITY
!               (let ((new-uid (imap-folder-get 'uidvalidity))
!                     (old-uid (gnus-group-get-parameter groupname 
! 						       'uidvalidity))
! 		    (info (gnus-get-info groupname)))
!                 (if (not old-uid)
! 		    (gnus-group-add-parameter groupname (cons 'uidvalidity 
! 							      new-uid))
! 		  (when (not (equal old-uid new-uid))
! 		    (if (and (not (gnus-info-marks info))
! 			     (not (gnus-info-read info)))
! 			(gnus-group-set-parameter groupname 'uidvalidity 
! 						  new-uid)
!                       (message "UIDVALIDITY clash. Old value `%s', new `%s'"
!                                old-uid new-uid)
!                       (setq imap-current-folder nil)))))))))
        imap-current-folder)))
  
  ;;; Other functions
--- 1117,1145 ----
         (nnimap-open-server server)))
  
  (defun nnimap-possibly-change-group (group &optional server)
+   (setq server (or server (nnoo-current-server 'nnimap)))
    (when (nnimap-possibly-change-server server)
      (with-current-buffer nnimap-server-buffer
        (when group
! 	(let ((groupname (gnus-group-normally-qualified 
! 			  'nnimap server group)))
! 	  (when (imap-select-folder group nil
! 				    (gnus-ephemeral-group-p groupname))
! 	    ;; check/set UIDVALIDITY
! 	    (let ((new-uid (imap-folder-get 'uidvalidity))
! 		  (old-uid (gnus-group-get-parameter groupname 'uidvalidity))
! 		  (info (gnus-get-info groupname)))
! 	      (if (not old-uid)
! 		  (gnus-group-add-parameter groupname (cons 'uidvalidity 
! 							    new-uid))
! 		(when (not (equal old-uid new-uid))
! 		  (if (and (not (gnus-info-marks info))
! 			   (not (gnus-info-read info)))
! 		      (gnus-group-set-parameter groupname 'uidvalidity 
! 						new-uid)
! 		    (message "UIDVALIDITY clash. Old value `%s', new `%s'"
! 			     old-uid new-uid)
! 		    (imap-unselect-folder group))))))))
        imap-current-folder)))
  
  ;;; Other functions
***************
*** 1198,1213 ****
        (gnus-edit-form (with-current-buffer nnimap-server-buffer
  			(imap-folder-set 'acl nil mailbox)
  			(nnimap-send-command-wait (format "GETACL %s" mailbox))
! 			(let ((raw (imap-folder-get 'acl mailbox))
! 			      user access)
! 			  (while (setq access (pop raw))
! 			    (if user
! 				(prog1
! 				    (push (cons (symbol-name user)
! 						(symbol-name access)) acl)
! 				  (setq user nil))
! 			      (setq user access))))
! 			acl)
  		      (format "Editing the access control list for `%s'.
  
     An access control list is a list of (identifier . rights) elements.
--- 1161,1168 ----
        (gnus-edit-form (with-current-buffer nnimap-server-buffer
  			(imap-folder-set 'acl nil mailbox)
  			(nnimap-send-command-wait (format "GETACL %s" mailbox))
! 			(setq acl (destructive-plist-to-alist 
! 				   (imap-folder-get 'acl mailbox))))
  		      (format "Editing the access control list for `%s'.
  
     An access control list is a list of (identifier . rights) elements.