* elmo-imap4.el (elmo-folder-open): Fix.
[elisp/wanderlust.git] / elmo / elmo-imap4.el
index 8d14bf7..8c8221f 100644 (file)
@@ -66,7 +66,7 @@
 ;;  ranges so that the command line is within that length, it should
 ;;  split the request into multiple commands. The client should use
 ;;  literals instead of long quoted strings, in order to keep the command
-;;  length down. 
+;;  length down.
 ;;  For its part, a server should allow for a command line of at least
 ;;  8000 octets. This provides plenty of leeway for accepting reasonable
 ;;  length commands from clients. The server should send a BAD response
   "Use cache in imap4 folder.")
 
 (defvar elmo-imap4-extra-namespace-alist
-  '(("^{.*/nntp}.*$" . ".")) ; Default is for UW's remote nntp mailbox...
-  "Extra namespace alist.  A list of cons cell like: (REGEXP . DELIMITER).")
+  '(("^\\({.*/nntp}\\).*$" . ".")) ; Default is for UW's remote nntp mailbox...
+  "Extra namespace alist. 
+A list of cons cell like: (REGEXP . DELIMITER).
+REGEXP should have a grouping for namespace prefix.")
 ;;
 ;;; internal variables
 ;;
@@ -251,9 +253,9 @@ Debug information is inserted in the buffer \"*IMAP4 DEBUG*\"")
 ;   "Send COMMAND to the SESSION and wait for response.
 ; Returns RESPONSE (parsed lisp object) of IMAP session."
 ;   (elmo-imap4-read-response session
-;                          (elmo-imap4-send-command
-;                           session
-;                           command)))
+;                          (elmo-imap4-send-command
+;                           session
+;                           command)))
 
 (defun elmo-imap4-send-command-wait (session command)
   "Send COMMAND to the SESSION.
@@ -1580,11 +1582,11 @@ Return nil if no complete line has arrived."
                            (if (eq (length prefix) 0)
                                (progn (setq default-delim delim) nil)
                              (cons
-                              (concat "^"
+                              (concat "^\\("
                                       (if (string= (downcase prefix) "inbox")
                                           "[Ii][Nn][Bb][Oo][Xx]"
                                         (regexp-quote prefix))
-                                      ".*$")
+                                      "\\).*$")
                               delim)))
                          (elmo-imap4-nth i ns))))))
     (if default-delim
@@ -1890,13 +1892,21 @@ Return nil if no complete line has arrived."
                   (with-current-buffer (elmo-network-session-buffer session)
                     elmo-imap4-server-namespace)))
                 elmo-imap4-default-hierarchy-delimiter))
+        ;; Append delimiter when root with namespace.
+        (root (if (and (match-end 1)
+                       (string= (substring root (match-end 1))
+                                ""))
+                  (concat root delim)
+                root))
         result append-serv type)
     (setq result (elmo-imap4-response-get-selectable-mailbox-list
                  (elmo-imap4-send-command-wait
                   session
                   (list "list " (elmo-imap4-mailbox root) " *"))))
-    (unless (string= (elmo-net-folder-user-internal folder)
-                    elmo-imap4-default-user)
+    (when (or (not (string= (elmo-net-folder-user-internal folder)
+                           elmo-imap4-default-user))
+             (not (eq (elmo-net-folder-auth-internal folder)
+                      (or elmo-imap4-default-authenticate-type 'clear))))
       (setq append-serv (concat ":" (elmo-net-folder-user-internal folder))))
     (unless (eq (elmo-net-folder-auth-internal folder)
                (or elmo-imap4-default-authenticate-type 'clear))
@@ -1920,6 +1930,7 @@ Return nil if no complete line has arrived."
                                     type)))))
     (if one-level
        (let ((re-delim (regexp-quote delim))
+             (case-fold-search nil)
              folder ret has-child-p)
          ;; Append delimiter
          (when (and root
@@ -1970,6 +1981,9 @@ Return nil if no complete line has arrived."
        (elmo-imap4-folder-mailbox-internal folder)
        'force 'notify-bye))))
 
+(luna-define-method elmo-folder-creatable-p ((folder elmo-imap4-folder))
+  t)
+
 (luna-define-method elmo-folder-writable-p ((folder elmo-imap4-folder))
   t)
 
@@ -2001,7 +2015,9 @@ Return nil if no complete line has arrived."
            (elmo-imap4-folder-mailbox-internal folder))
           " "
           (elmo-imap4-mailbox
-           (elmo-imap4-folder-mailbox-internal new-folder))))))
+           (elmo-imap4-folder-mailbox-internal new-folder))))
+    (elmo-imap4-session-set-current-mailbox-internal
+     session (elmo-imap4-folder-mailbox-internal new-folder))))
 
 (defun elmo-imap4-copy-messages (src-folder dst-folder numbers)
   (let ((session (elmo-imap4-get-session src-folder))
@@ -2072,7 +2088,8 @@ If optional argument REMOVE is non-nil, remove FLAG."
 
 (defun elmo-imap4-search-internal-primitive (folder session filter from-msgs)
   (let ((search-key (elmo-filter-key filter))
-       (imap-search-keys '("bcc" "body" "cc" "from" "subject" "to"))
+       (imap-search-keys '("bcc" "body" "cc" "from" "subject" "to"
+                           "larger" "smaller"))
        (total 0)
        (length (length from-msgs))
        charset set-list end results)
@@ -2205,14 +2222,16 @@ If optional argument REMOVE is non-nil, remove FLAG."
                            folder session (nth 2 condition) from-msgs)))
            result (sort result '<))))))
 
-(luna-define-method elmo-folder-search ((folder elmo-imap4-folder)
-                                       condition &optional numbers)
-  (save-excursion
-    (let ((session (elmo-imap4-get-session folder)))
-      (elmo-imap4-session-select-mailbox
-       session
-       (elmo-imap4-folder-mailbox-internal folder))
-      (elmo-imap4-search-internal folder session condition numbers))))
+(luna-define-method elmo-folder-search :around ((folder elmo-imap4-folder)
+                                               condition &optional numbers)
+  (if (elmo-folder-plugged-p folder)
+      (save-excursion
+       (let ((session (elmo-imap4-get-session folder)))
+         (elmo-imap4-session-select-mailbox
+          session
+          (elmo-imap4-folder-mailbox-internal folder))
+         (elmo-imap4-search-internal folder session condition numbers)))
+    (luna-call-next-method)))
 
 (luna-define-method elmo-folder-msgdb-create-plugged
   ((folder elmo-imap4-folder) numbers &rest args)
@@ -2305,8 +2324,7 @@ If optional argument REMOVE is non-nil, remove FLAG."
 
 (defsubst elmo-imap4-folder-diff-plugged (folder)
   (let ((session (elmo-imap4-get-session folder))
-       messages
-       response killed)
+       messages new unread response killed)
 ;;; (elmo-imap4-commit spec)
     (with-current-buffer (elmo-network-session-buffer session)
       (setq elmo-imap4-status-callback nil)
@@ -2326,9 +2344,10 @@ If optional argument REMOVE is non-nil, remove FLAG."
        (setq messages (- messages
                          (elmo-msgdb-killed-list-length
                           killed))))
-    (list (elmo-imap4-response-value response 'recent)
-         (elmo-imap4-response-value response 'unseen)
-         messages)))
+    (setq new (elmo-imap4-response-value response 'recent)
+         unread (elmo-imap4-response-value response 'unseen))
+    (if (< unread new) (setq new unread))
+    (list new unread messages)))
 
 (luna-define-method elmo-folder-diff-plugged ((folder elmo-imap4-folder))
   (elmo-imap4-folder-diff-plugged folder))
@@ -2344,7 +2363,7 @@ If optional argument REMOVE is non-nil, remove FLAG."
 (luna-define-method elmo-folder-open :around ((folder elmo-imap4-folder)
                                              &optional load-msgdb)
   (if (elmo-folder-plugged-p folder)
-      (let (session mailbox msgdb response tag)
+      (let (session mailbox msgdb result response tag)
        (condition-case err
            (progn
              (setq session (elmo-imap4-get-session folder)
@@ -2353,12 +2372,32 @@ If optional argument REMOVE is non-nil, remove FLAG."
                                                 (list "select "
                                                       (elmo-imap4-mailbox
                                                        mailbox))))
+             (message "Selecting %s..."
+                      (elmo-folder-name-internal folder))
              (if load-msgdb
-                 (setq msgdb (elmo-msgdb-load folder)))
+                 (setq msgdb (elmo-msgdb-load folder 'silent)))
              (elmo-folder-set-killed-list-internal
               folder
               (elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder)))
-             (setq response (elmo-imap4-read-response session tag)))
+             (if (setq result (elmo-imap4-response-ok-p
+                               (setq response
+                                     (elmo-imap4-read-response session tag))))
+                 (progn
+                   (elmo-imap4-session-set-current-mailbox-internal
+                    session mailbox)
+                   (elmo-imap4-session-set-read-only-internal
+                    session
+                    (nth 1 (assq 'read-only (assq 'ok response)))))
+               (elmo-imap4-session-set-current-mailbox-internal session nil)
+               (if (elmo-imap4-response-bye-p response)
+                   (elmo-imap4-process-bye session)
+                 (error (or
+                         (elmo-imap4-response-error-text response)
+                         (format "Select %s failed" mailbox)))))
+             (message "Selecting %s...done"
+                      (elmo-folder-name-internal folder))
+             (elmo-folder-set-msgdb-internal
+              folder msgdb))
          (quit
           (if response
               (elmo-imap4-session-set-current-mailbox-internal
@@ -2372,11 +2411,7 @@ If optional argument REMOVE is non-nil, remove FLAG."
                session mailbox)
             (and session
                  (elmo-imap4-session-set-current-mailbox-internal
-                  session nil)))))
-       (if load-msgdb
-           (elmo-folder-set-msgdb-internal
-            folder
-            (or msgdb (elmo-msgdb-load folder)))))
+                  session nil))))))
     (luna-call-next-method)))
 
 ;; elmo-folder-open-internal: do nothing.
@@ -2428,7 +2463,7 @@ If optional argument REMOVE is non-nil, remove FLAG."
                                      (elmo-file-cache-path
                                       cache-file)))))))
 
-(luna-define-method elmo-folder-create ((folder elmo-imap4-folder))
+(luna-define-method elmo-folder-create-plugged ((folder elmo-imap4-folder))
   (elmo-imap4-send-command-wait
    (elmo-imap4-get-session folder)
    (list "create "
@@ -2523,14 +2558,15 @@ If optional argument REMOVE is non-nil, remove FLAG."
       (setq elmo-imap4-display-literal-progress nil))
     (unless elmo-inhibit-display-retrieval-progress
       (elmo-display-progress 'elmo-imap4-display-literal-progress
-                            "" 100)  ; remove progress bar.
+                            "Retrieving..." 100)  ; remove progress bar.
       (message "Retrieving...done."))
     (if (setq response (elmo-imap4-response-bodydetail-text
                        (elmo-imap4-response-value-all
                         response 'fetch)))
        (with-current-buffer outbuf
          (erase-buffer)
-         (insert response)))))
+         (insert response)
+         t))))
 
 (luna-define-method elmo-message-fetch-plugged ((folder elmo-imap4-folder)
                                                number strategy