* elmo-pop3.el (elmo-pop3-use-uidl): New variable.
authorteranisi <teranisi>
Tue, 18 Jul 2000 02:43:25 +0000 (02:43 +0000)
committerteranisi <teranisi>
Tue, 18 Jul 2000 02:43:25 +0000 (02:43 +0000)
(elmo-pop3-number-uidl-hash): New buffer-local variable.
(elmo-pop3-uidl-number-hash): Ditto.
(elmo-pop3-size-hash): Ditto.
(elmo-pop3-uidl-done): Ditto.
(elmo-pop3-list-done): Ditto.
(elmo-pop3-connection-get-process): New defmacro.
(elmo-pop3-connection-get-buffer): Ditto.
(elmo-pop3-close-connection): Delete buffer and process.
(elmo-pop3-flush-connection): Don't delete buffer and process.
(elmo-pop3-get-connection): Added optional argument `if-exists'.
Setup UIDL and size hash.
(elmo-pop3-send-command-no-erase): Deleted
(elmo-pop3-send-command): Added optional argument `no-erase'.
(elmo-pop3-parse-uidl-response): New function.
(elmo-pop3-parse-list-response): Set size hash.
(elmo-pop3-list-location): New function.
(elmo-pop3-list-by-uidl-subr): Ditto.
(elmo-pop3-list-by-list): Ditto.
(elmo-pop3-list-folder): Call `elmo-pop3-commit'.
Call `elmo-pop3-list-by-uidl-subr' or `elmo-pop3-list-by-list'.
(elmo-pop3-max-of-folder): Call `elmo-pop3-commit'.
Call `elmo-pop3-list-by-uidl-subr' if `elmo-pop3-use-uidl' is non-nil.
(elmo-pop3-msgdb-create-as-numlist): Added optional argument `msgdb'.
Use uidl.
(elmo-pop3-uidl-to-number): New function.
(elmo-pop3-number-to-uidl): Ditto.
(elmo-pop3-number-to-size): Ditto.
(elmo-pop3-msgdb-create-by-header): Added argument `loc-alist'.
Set number by use of uidl.
(elmo-pop3-msgdb-create-message): Likewise.
Set size, loc-alist in msgdb.
(elmo-pop3-read-msg): Set number by use of uidl.
Added optional argument `msgdb'.
(elmo-pop3-delete-msg): Ditto.
(elmo-pop3-delete-msgs): Added optional argument `msgdb'.
(elmo-pop3-commit): Close connection.

* elmo-pipe.el (elmo-pipe-max-of-folder):
Bind `elmo-pop3-use-uidl' as nil.
(elmo-pipe-drain): Ditto.
Call `elmo-commit'.

* elmo-msgdb.el (elmo-msgdb-delete-msgs): Delete location too.
(elmo-msgdb-overview-entity-set-size): New defsubst.

elmo/ChangeLog
elmo/elmo-msgdb.el
elmo/elmo-pipe.el
elmo/elmo-pop3.el

index fe51df4..7bb14a8 100644 (file)
@@ -1,3 +1,51 @@
+2000-07-18  Yuuichi Teranishi  <teranisi@gohome.org>
+
+       * elmo-pop3.el (elmo-pop3-use-uidl): New variable.
+       (elmo-pop3-number-uidl-hash): New buffer-local variable.
+       (elmo-pop3-uidl-number-hash): Ditto.
+       (elmo-pop3-size-hash): Ditto.
+       (elmo-pop3-uidl-done): Ditto.
+       (elmo-pop3-list-done): Ditto.
+       (elmo-pop3-connection-get-process): New defmacro.
+       (elmo-pop3-connection-get-buffer): Ditto.
+       (elmo-pop3-close-connection): Delete buffer and process.
+       (elmo-pop3-flush-connection): Don't delete buffer and process.
+       (elmo-pop3-get-connection): Added optional argument `if-exists'.
+       Setup UIDL and size hash.
+       (elmo-pop3-send-command-no-erase): Deleted
+       (elmo-pop3-send-command): Added optional argument `no-erase'.
+       (elmo-pop3-parse-uidl-response): New function.
+       (elmo-pop3-parse-list-response): Set size hash.
+       (elmo-pop3-list-location): New function.
+       (elmo-pop3-list-by-uidl-subr): Ditto.
+       (elmo-pop3-list-by-list): Ditto.
+       (elmo-pop3-list-folder): Call `elmo-pop3-commit'.
+       Call `elmo-pop3-list-by-uidl-subr' or `elmo-pop3-list-by-list'.
+       (elmo-pop3-max-of-folder): Call `elmo-pop3-commit'.
+       Call `elmo-pop3-list-by-uidl-subr' if `elmo-pop3-use-uidl' is non-nil.
+       (elmo-pop3-msgdb-create-as-numlist): Added optional argument `msgdb'.
+       Use uidl.
+       (elmo-pop3-uidl-to-number): New function.
+       (elmo-pop3-number-to-uidl): Ditto.
+       (elmo-pop3-number-to-size): Ditto.
+       (elmo-pop3-msgdb-create-by-header): Added argument `loc-alist'.
+       Set number by use of uidl.
+       (elmo-pop3-msgdb-create-message): Likewise.
+       Set size, loc-alist in msgdb.
+       (elmo-pop3-read-msg): Set number by use of uidl.
+       Added optional argument `msgdb'.
+       (elmo-pop3-delete-msg): Ditto.
+       (elmo-pop3-delete-msgs): Added optional argument `msgdb'.
+       (elmo-pop3-commit): Close connection.
+
+       * elmo-pipe.el (elmo-pipe-max-of-folder):
+       Bind `elmo-pop3-use-uidl' as nil.
+       (elmo-pipe-drain): Ditto.
+       Call `elmo-commit'.
+
+       * elmo-msgdb.el (elmo-msgdb-delete-msgs): Delete location too.
+       (elmo-msgdb-overview-entity-set-size): New defsubst.
+
 2000-07-17  Yuuichi Teranishi  <teranisi@gohome.org>
 
        * elmo-vars.el (elmo-use-killed-list): New variable
index 5ee920e..3b378a4 100644 (file)
@@ -419,6 +419,8 @@ content of MSGDB is changed."
                             (elmo-msgdb-number-load dir)))
           (mark-alist (or (caddr msgdb)
                           (elmo-msgdb-mark-load dir)))
+          (loc-alist (or (elmo-msgdb-get-location msgdb)
+                         (elmo-msgdb-location-load dir)))
           (hashtb (or (elmo-msgdb-get-overviewht msgdb)
                       (elmo-msgdb-make-overview-hashtb overview)))
           (newmsgdb (list overview number-alist mark-alist (nth 3 msgdb) hashtb))
@@ -441,6 +443,7 @@ content of MSGDB is changed."
        (setq number-alist
              (delq (assq (car msg-list) number-alist) number-alist))
        (setq mark-alist (delq (assq (car msg-list) mark-alist) mark-alist))
+       (setq loc-alist (delq (assq (car msg-list) loc-alist) loc-alist))
        (setq msg-list (cdr msg-list)))
       (setcar msgdb overview)
       (setcar (cdr msgdb) number-alist)
@@ -510,6 +513,10 @@ content of MSGDB is changed."
 (defsubst elmo-msgdb-overview-entity-get-size (entity)
   (and entity (aref (cdr entity) 7)))
 
+(defsubst elmo-msgdb-overview-entity-set-size (entity size)
+  (and entity (aset (cdr entity) 7 size))
+  entity)
+
 (defsubst elmo-msgdb-overview-entity-get-id (entity)
   (and entity (car entity)))
 
index 8e5eff6..e07e45c 100644 (file)
   (let ((msgdb (elmo-msgdb-load src))
        elmo-nntp-use-cache 
        elmo-imap4-use-cache
-       elmo-pop3-use-cache) ; Inhibit caching while moving messages.
+       elmo-pop3-use-cache ; Inhibit caching while moving messages.
+       elmo-pop3-use-uidl) ; No need to use UIDL
     (message "Checking %s..." src)
     (elmo-move-msgs src (elmo-list-folder src) dst msgdb)
     (elmo-msgdb-save src msgdb)
+    (elmo-commit src)
     (run-hooks 'elmo-pipe-drained-hook)))
 
 (defun elmo-pipe-list-folder (spec)
@@ -94,8 +96,9 @@
   (elmo-list-folder-important (elmo-pipe-spec-dst spec) overview))
 
 (defun elmo-pipe-max-of-folder (spec)
-  (let ((src-length (length (elmo-list-folder (elmo-pipe-spec-src spec))))
-       (dst-list (elmo-list-folder (elmo-pipe-spec-dst spec))))
+  (let* (elmo-pop3-use-uidl
+        (src-length (length (elmo-list-folder (elmo-pipe-spec-src spec))))
+        (dst-list (elmo-list-folder (elmo-pipe-spec-dst spec))))
     (cons (+ src-length (elmo-max-of-list dst-list))
          (+ src-length (length dst-list)))))
 
index 82185c3..cd2d074 100644 (file)
       (require 'sasl))
   (error))
 
+(defvar elmo-pop3-use-uidl t
+  "*If non-nil, use UIDL.")
+
 (defvar elmo-pop3-exists-exactly t)
 (defvar elmo-pop3-read-point nil)
 (defvar elmo-pop3-connection-cache nil
   "Cache of pop3 connection.")
 
+;; buffer-local
+(defvar elmo-pop3-number-uidl-hash nil) ; number -> uidl
+(defvar elmo-pop3-uidl-number-hash nil) ; uidl -> number
+(defvar elmo-pop3-size-hash nil) ; number -> size
+(defvar elmo-pop3-uidl-done nil)
+(defvar elmo-pop3-list-done nil)
+
+(defmacro elmo-pop3-connection-get-process (connection)
+  (` (nth 1 (, connection))))
+
+(defmacro elmo-pop3-connection-get-buffer (connection)
+  (` (nth 0 (, connection))))
+
 (defun elmo-pop3-close-connection (connection &optional process buffer)
-  (save-excursion
-    (let* ((buffer  (or buffer (nth 0 connection)))
-          (process (or process (nth 1 connection))))
-      (elmo-pop3-send-command buffer process "quit")
-      (when (null (elmo-pop3-read-response buffer process t))
-       (error "POP error: QUIT failed")))))
+  (and (or connection process)
+       (save-excursion
+        (let ((buffer  (or buffer
+                           (elmo-pop3-connection-get-buffer connection)))
+              (process (or process 
+                           (elmo-pop3-connection-get-process connection))))
+          (elmo-pop3-send-command buffer process "quit")
+          (when (null (elmo-pop3-read-response buffer process t))
+            (error "POP error: QUIT failed"))
+          (if buffer (kill-buffer buffer))
+          (if process (delete-process process))))))
 
 (defun elmo-pop3-flush-connection ()
   (interactive)
          (condition-case ()
              (elmo-pop3-close-connection nil process buffer)
            (error)))
-      (if buffer (kill-buffer buffer))
-      ;;(setq process (car (cdr (cdr (car cache)))))
-      (if process (delete-process process))
       (setq cache (cdr cache)))
     (setq elmo-pop3-connection-cache nil)))
 
-(defun elmo-pop3-get-connection (spec)
+(defun elmo-pop3-get-connection (spec &optional if-exists)
   (let* ((user   (elmo-pop3-spec-username spec))
         (server (elmo-pop3-spec-hostname spec))
         (port   (elmo-pop3-spec-port spec))
         (auth   (elmo-pop3-spec-auth spec))
         (ssl    (elmo-pop3-spec-ssl spec))
         (user-at-host (format "%s@%s" user server))
-        ret-val result buffer process errmsg proc-stat
+        connection result buffer process errmsg proc-stat response
         user-at-host-on-port)
     (if (not (elmo-plugged-p server port))
        (error "Unplugged"))
     (setq user-at-host-on-port 
          (concat user-at-host ":" (int-to-string port)
                  (if (eq ssl 'starttls) "!!" (if ssl "!"))))
-    (setq ret-val (assoc user-at-host-on-port elmo-pop3-connection-cache))
-    (if (and ret-val 
+    (setq connection (assoc user-at-host-on-port elmo-pop3-connection-cache))
+    (if (and connection 
             (or (eq (setq proc-stat 
-                          (process-status (cadr (cdr ret-val)))) 
+                          (process-status (cadr (cdr connection)))) 
                     'closed)
                 (eq proc-stat 'exit)))
        ;; connection is closed...
        (progn
-         (kill-buffer (car (cdr ret-val)))
+         (kill-buffer (car (cdr connection)))
          (setq elmo-pop3-connection-cache 
-               (delete ret-val elmo-pop3-connection-cache))
-         (setq ret-val nil)
-         ))
-    (if ret-val
-       (cdr ret-val)
-      (setq result
-           (elmo-pop3-open-connection 
-            server user port auth
-            (elmo-get-passwd user-at-host) ssl))
-      (if (null result)
-         (error "Connection failed"))
-      (setq buffer (car result))
-      (setq process (cdr result))
-      (when (and process (null buffer))
-       (elmo-remove-passwd user-at-host)
-       (delete-process process)
-       (error "Login failed")
-       )
-      (setq elmo-pop3-connection-cache 
-           (append elmo-pop3-connection-cache 
-                   (list 
-                    (cons user-at-host-on-port
-                          (setq ret-val (list buffer process))))))
-      ret-val)))
-
-(defun elmo-pop3-send-command (buffer process command)
-  (save-excursion
-    (set-buffer buffer)
-    (erase-buffer)
-    (goto-char (point-min))
-    (setq elmo-pop3-read-point (point))
-    (process-send-string process command)
-    (process-send-string process "\r\n")))
-
-(defun elmo-pop3-send-command-no-erase (buffer process command)
-  (save-excursion
-    (set-buffer buffer)
-    ;(erase-buffer)
+               (delete connection elmo-pop3-connection-cache))
+         (setq connection nil)))
+    (if connection
+       (cdr connection)
+      (unless if-exists
+       (setq result
+             (elmo-pop3-open-connection 
+              server user port auth
+              (elmo-get-passwd user-at-host) ssl))
+       (if (null result)
+           (error "Connection failed"))
+       (setq buffer (car result))
+       (setq process (cdr result))
+       (when (and process (null buffer))
+         (elmo-remove-passwd user-at-host)
+         (delete-process process)
+         (error "Login failed"))
+       (setq elmo-pop3-connection-cache 
+             (append elmo-pop3-connection-cache 
+                     (list 
+                      (cons user-at-host-on-port
+                            (setq connection (list buffer process))))))
+       ;; initialization of list
+       (with-current-buffer buffer
+         (make-variable-buffer-local 'elmo-pop3-uidl-number-hash)
+         (make-variable-buffer-local 'elmo-pop3-number-uidl-hash)
+         (make-variable-buffer-local 'elmo-pop3-uidl-done)
+         (make-variable-buffer-local 'elmo-pop3-size-hash)
+         (make-variable-buffer-local 'elmo-pop3-list-done)
+         (setq elmo-pop3-size-hash (make-vector 31 0))
+         ;; To get obarray of uidl and size
+         ;; List
+         (elmo-pop3-send-command buffer process "list")
+         (if (null (elmo-pop3-read-response buffer process))
+             (error "POP List folder failed"))
+         (if (null (setq response
+                         (elmo-pop3-read-contents buffer process)))
+             (error "POP List folder failed"))
+         ;; POP server always returns a sequence of serial numbers.
+         (elmo-pop3-parse-list-response response)
+         ;; UIDL
+         (when elmo-pop3-use-uidl
+           (setq elmo-pop3-uidl-number-hash (make-vector 31 0))
+           (setq elmo-pop3-number-uidl-hash (make-vector 31 0))
+           ;; UIDL
+           (elmo-pop3-send-command buffer process "uidl")
+           (unless (elmo-pop3-read-response buffer process)
+             (error "UIDL failed."))
+           (unless (setq response (elmo-pop3-read-contents buffer process))
+             (error "UIDL failed."))
+           (elmo-pop3-parse-uidl-response response)
+           elmo-pop3-uidl-done))
+       connection))))
+
+(defun elmo-pop3-send-command (buffer process command &optional no-erase)
+  (with-current-buffer buffer
+    (unless no-erase
+      (erase-buffer))
     (goto-char (point-min))
     (setq elmo-pop3-read-point (point))
     (process-send-string process command)
              (setq return-value 
                    (if return-value 
                        (concat return-value "\n" response-string)
-                     response-string
-                     )))
+                     response-string)))
          (if (looking-at "\\-.*$")
              (progn 
                (setq response-continue nil)
                             salted-pass))
                      (throw 'done nil))
                  (elmo-pop3-send-command
-                  process-buffer process "") ))
+                  process-buffer process "")))
               (t
                ;; try USER/PASS
                (elmo-pop3-send-command  process-buffer process 
          (condition-case nil
              (prog1
                  (elmo-pop3-get-connection spec)
-               (elmo-pop3-flush-connection))
+               (elmo-pop3-close-connection
+                (elmo-pop3-get-connection spec 'if-exists)))
            (error nil))))
     t))
 
-(defun elmo-pop3-parse-list-response (string)
-  (save-excursion
-    (let ((tmp-buffer (get-buffer-create " *ELMO PARSE TMP*"))
-         ret-val)
-      (set-buffer tmp-buffer)
-      (let ((case-fold-search t))
-       (erase-buffer)
+(defun elmo-pop3-parse-uidl-response (string)
+  (let ((buffer (current-buffer))
+       number list size)
+    (with-temp-buffer
+      (let (number uid list)
        (insert string)
        (goto-char (point-min))
-       (while (re-search-forward "^\\([0-9]*\\)[\t ].*$" nil t)
-         (setq ret-val
-               (cons
-                (string-to-int
-                 (elmo-match-buffer 1))
-                ret-val)))
-       (kill-buffer tmp-buffer)
-       (nreverse ret-val)))))
+       (while (re-search-forward "^\\([0-9]+\\)[\t ]\\([^ \n]+\\)$" nil t)
+         (setq number  (elmo-match-buffer 1))
+         (setq uid (elmo-match-buffer 2))
+         (with-current-buffer buffer
+           (elmo-set-hash-val uid number elmo-pop3-uidl-number-hash)
+           (elmo-set-hash-val (concat "#" number) uid
+                              elmo-pop3-number-uidl-hash))
+         (setq list (cons uid list)))
+       (with-current-buffer buffer (setq elmo-pop3-uidl-done t))
+       (nreverse list)))))
+
+(defun elmo-pop3-parse-list-response (string)
+  (let ((buffer (current-buffer))
+       number list size)
+    (with-temp-buffer
+      (insert string)
+      (goto-char (point-min))
+      (while (re-search-forward "^\\([0-9]+\\)[\t ]\\([0-9]+\\)$" nil t)
+       (setq list
+             (cons
+              (string-to-int (setq number (elmo-match-buffer 1)))
+              list))
+       (setq size (elmo-match-buffer 2))
+       (with-current-buffer buffer
+         (elmo-set-hash-val (concat "#" number)
+                            size
+                            elmo-pop3-size-hash)))
+      (with-current-buffer buffer (setq elmo-pop3-list-done t))
+      (nreverse list))))
+
+(defun elmo-pop3-list-location (spec)
+  (with-current-buffer (elmo-pop3-connection-get-buffer
+                       (elmo-pop3-get-connection spec))
+    (let (list)
+      (if elmo-pop3-uidl-done
+         (progn
+           (mapatoms
+            (lambda (atom)
+              (setq list (cons (symbol-name atom) list)))
+            elmo-pop3-uidl-number-hash)
+           (nreverse list))
+       (error "POP3: Error in UIDL")))))
+
+(defun elmo-pop3-list-by-uidl-subr (spec &optional nonsort)
+  (let ((flist (elmo-list-folder-by-location
+               spec
+               (elmo-pop3-list-location spec))))
+    (if nonsort
+       (cons (elmo-max-of-list flist) (length flist))
+      (sort flist '<))))
+
+(defun elmo-pop3-list-by-list (spec)
+  (with-current-buffer (elmo-pop3-connection-get-buffer
+                       (elmo-pop3-get-connection spec))
+    (let (list)
+      (if elmo-pop3-list-done
+         (progn
+           (mapatoms (lambda (atom)
+                       (setq list (cons (string-to-int
+                                         (substring (symbol-name atom) 1))
+                                        list)))
+                     elmo-pop3-size-hash)
+           (sort list '<))
+       (error "POP3: Error in list")))))
 
 (defun elmo-pop3-list-folder (spec)
   (let ((killed (and elmo-use-killed-list
                     (elmo-msgdb-killed-list-load
                      (elmo-msgdb-expand-path nil spec))))
        numbers)
-    (setq numbers
-         (save-excursion
-           (elmo-pop3-flush-connection)
-           (let* ((connection (elmo-pop3-get-connection spec))
-                  (buffer  (nth 0 connection))
-                  (process (nth 1 connection))
-                  response errmsg ret-val)
-             (elmo-pop3-send-command buffer process "list")
-             (if (null (elmo-pop3-read-response buffer process))
-                 (error "POP List folder failed"))
-             (if (null (setq response
-                             (elmo-pop3-read-contents buffer process)))
-                 (error "POP List folder failed"))
-             ;; POP server always returns a sequence of serial numbers.
-             (elmo-pop3-parse-list-response response))))
+    (elmo-pop3-commit spec)
+    (setq numbers (if elmo-pop3-use-uidl
+                     (progn
+                       (elmo-pop3-list-by-uidl-subr spec))
+                   (elmo-pop3-list-by-list spec)))
     (if killed
        (delq nil
              (mapcar (lambda (number)
       numbers)))
 
 (defun elmo-pop3-max-of-folder (spec)
-  (save-excursion
-    (elmo-pop3-flush-connection)
+  (elmo-pop3-commit spec)
+  (if elmo-pop3-use-uidl
+      (elmo-pop3-list-by-uidl-subr spec 'nonsort)
     (let* ((connection (elmo-pop3-get-connection spec))
           (buffer  (nth 0 connection))
           (process (nth 1 connection))
           (total 0)
           response)
-      (elmo-pop3-send-command buffer process "STAT")
-      (setq response (elmo-pop3-read-response buffer process))
-      ;; response: "^\+OK 2 7570$"
-      (if (not (string-match "^\+OK[ \t]*\\([0-9]*\\)" response))
-         (error "POP STAT command failed")
-       (setq total
-             (string-to-int
-              (substring response (match-beginning 1)(match-end 1 ))))
-       (cons total total)))))
+      (with-current-buffer buffer
+       (elmo-pop3-send-command buffer process "STAT")
+       (setq response (elmo-pop3-read-response buffer process))
+       ;; response: "^\+OK 2 7570$"
+       (if (not (string-match "^\+OK[ \t]*\\([0-9]*\\)" response))
+           (error "POP STAT command failed")
+         (setq total
+               (string-to-int
+                (substring response (match-beginning 1)(match-end 1 ))))
+         (cons total total))))))
 
 (defvar elmo-pop3-header-fetch-chop-length 200)
 
          (last-point (point-min)))
       ;; Send HEAD commands.
       (while articles
-       (elmo-pop3-send-command-no-erase
-        buffer
-        process
-        (format "top %s 0" (car articles))
-        )
-       ; (accept-process-output process 1)
+       (elmo-pop3-send-command buffer process (format
+                                               "top %s 0" (car articles))
+                               'no-erase)
+       ;; (accept-process-output process 1)
        (setq articles (cdr articles))
        (setq count (1+ count))
        ;; Every 200 requests we have to read the stream in
                   (/ (* received 100) number))))
            (accept-process-output process 1)
            ;(accept-process-output process)
-           (discard-input)
-           )))
+           (discard-input))))
       ;; Remove all "\r"'s.
       (goto-char (point-min))
       (while (search-forward "\r\n" nil t)
        (replace-match "\n"))
-      (copy-to-buffer tobuffer (point-min) (point-max))
-      ;(elmo-pop3-close-connection nil process buffer) ; close connection
-      )))
+      (copy-to-buffer tobuffer (point-min) (point-max)))))
 
 (defalias 'elmo-pop3-msgdb-create 'elmo-pop3-msgdb-create-as-numlist)
+
 (defun elmo-pop3-msgdb-create-as-numlist (spec numlist new-mark
                                               already-mark seen-mark
-                                              important-mark seen-list)
+                                              important-mark seen-list
+                                              &optional msgdb)
   (when numlist
     (let* ((connection (elmo-pop3-get-connection spec))
-          (buffer (nth 0 connection))
-          (process (nth 1 connection))
-          response errmsg ret-val)
+          (buffer (elmo-pop3-connection-get-buffer connection))
+          (process (elmo-pop3-connection-get-process connection))
+          loc-alist)
+      (if elmo-pop3-use-uidl
+         (setq loc-alist (if msgdb (elmo-msgdb-get-location msgdb)
+                           (elmo-msgdb-location-load
+                            (elmo-msgdb-expand-path nil spec)))))
       (elmo-pop3-msgdb-create-by-header buffer process numlist
                                        new-mark already-mark 
-                                       seen-mark seen-list))))
+                                       seen-mark seen-list
+                                       loc-alist))))
+
+(defun elmo-pop3-uidl-to-number (uidl)
+  (string-to-number (elmo-get-hash-val uidl
+                                      elmo-pop3-uidl-number-hash)))
+
+(defun elmo-pop3-number-to-uidl (number)
+  (elmo-get-hash-val (format "#%d" number)
+                    elmo-pop3-number-uidl-hash))
+
+(defun elmo-pop3-number-to-size (number)
+  (elmo-get-hash-val (format "#%d" number)
+                    elmo-pop3-size-hash))
 
 (defun elmo-pop3-msgdb-create-by-header (buffer process numlist
                                                new-mark already-mark 
                                                seen-mark
-                                               seen-list)
-  (let ((tmp-buffer (get-buffer-create " *ELMO Overview TMP*"))
-       ret-val)
-    (elmo-pop3-retrieve-headers
-     buffer tmp-buffer process numlist)
-    (setq ret-val
+                                               seen-list
+                                               loc-alist)
+  (let ((tmp-buffer (get-buffer-create " *ELMO Overview TMP*")))
+    (with-current-buffer buffer
+      (if loc-alist ; use uidl.
+         (setq numlist
+               (delq 
+                nil
+                (mapcar 
+                 (lambda (number)
+                   (elmo-pop3-uidl-to-number (cdr (assq number loc-alist))))
+                 numlist))))
+      (elmo-pop3-retrieve-headers buffer tmp-buffer process numlist)
+      (prog1
          (elmo-pop3-msgdb-create-message
           tmp-buffer 
+          process
           (length numlist)
           numlist
-          new-mark already-mark seen-mark seen-list))
-    (kill-buffer tmp-buffer)
-    ret-val))
+          new-mark already-mark seen-mark seen-list loc-alist)
+       (kill-buffer tmp-buffer)))))
 
 (defun elmo-pop3-msgdb-create-message (buffer 
-                                      num numlist new-mark already-mark 
+                                      process
+                                      num
+                                      numlist new-mark already-mark 
                                       seen-mark
-                                      seen-list)
+                                      seen-list
+                                      loc-alist)
   (save-excursion
-    (let (beg
-         overview number-alist mark-alist
-         entity i number message-id gmark seen)
+    (let (beg overview number-alist mark-alist
+             entity i number message-id gmark seen size)
       (set-buffer buffer)
       (elmo-set-buffer-multibyte default-enable-multibyte-characters)
       (goto-char (point-min))
              (setq overview 
                    (elmo-msgdb-append-element
                     overview entity))
+             (with-current-buffer (process-buffer process)
+               (elmo-msgdb-overview-entity-set-size
+                entity
+                (string-to-number
+                 (elmo-pop3-number-to-size
+                  (elmo-msgdb-overview-entity-get-number entity))))
+               (if (setq number
+                         (car
+                          (rassoc
+                           (elmo-pop3-number-to-uidl
+                            (elmo-msgdb-overview-entity-get-number entity))
+                           loc-alist)))
+                   (elmo-msgdb-overview-entity-set-number entity number)))
              (setq number-alist
-                   (elmo-msgdb-number-add number-alist
-                                          (elmo-msgdb-overview-entity-get-number entity)
-                                          (car entity)))
+                   (elmo-msgdb-number-add
+                    number-alist
+                    (elmo-msgdb-overview-entity-get-number entity)
+                    (car entity)))
              (setq message-id (car entity))
              (setq seen (member message-id seen-list))
              (if (setq gmark (or (elmo-msgdb-global-mark-get message-id)
                        (elmo-msgdb-mark-append 
                         mark-alist
                         (elmo-msgdb-overview-entity-get-number entity)
-                        gmark)))
-             )))
+                        gmark))))))
        (when (> num elmo-display-progress-threshold)
          (setq i (1+ i))
          (if (or (zerop (% i 5)) (= i num))
              (elmo-display-progress
               'elmo-pop3-msgdb-create-message "Creating msgdb..."
               (/ (* i 100) num)))))
-      (list overview number-alist mark-alist))))
+      (list overview number-alist mark-alist loc-alist))))
 
 (defun elmo-pop3-read-body (buffer process outbuf)
   (with-current-buffer buffer
        (insert-buffer-substring buffer start (- end 3))
        (elmo-delete-cr-get-content-type)))))
 
-(defun elmo-pop3-read-msg (spec number outbuf)
-  (save-excursion
-    (let* ((connection (elmo-pop3-get-connection spec))
-          (buffer  (car connection))
-          (process (cadr connection))
-          (cwf     (caddr connection))  
-          response errmsg msg)
-      (elmo-pop3-send-command buffer process 
-                             (format "retr %s" number))
-      (when (null (setq response (elmo-pop3-read-response
-                                 buffer process t)))
-       (error "Fetching message failed"))
-      (setq response (elmo-pop3-read-body buffer process outbuf))
-      (set-buffer outbuf)
-      (goto-char (point-min))
-      (while (re-search-forward "^\\." nil t)
-       (replace-match "")
-       (forward-line))
-      response)))
-
-(defun elmo-pop3-delete-msg (buffer process number)
-  (let (response errmsg msg)
-    (elmo-pop3-send-command buffer process 
-                           (format "dele %s" number))
-    (when (null (setq response (elmo-pop3-read-response
-                               buffer process t)))
-      (error "Deleting message failed"))))
-
-(defun elmo-pop3-delete-msgs (spec msgs)
-  (save-excursion
-    (let* ((connection (elmo-pop3-get-connection spec))
-          (buffer  (car connection))
-          (process (cadr connection)))
-      (mapcar '(lambda (msg) (elmo-pop3-delete-msg 
-                             buffer process msg))
-             msgs))))
+(defun elmo-pop3-read-msg (spec number outbuf &optional msgdb)
+  (let* ((loc-alist (if elmo-pop3-use-uidl
+                       (if msgdb
+                           (elmo-msgdb-get-location msgdb)
+                         (elmo-msgdb-location-load
+                          (elmo-msgdb-expand-path nil spec)))))
+        (connection (elmo-pop3-get-connection spec))
+        (buffer  (elmo-pop3-connection-get-buffer connection))
+        (process (elmo-pop3-connection-get-process connection))
+        response errmsg msg)
+    (with-current-buffer buffer
+      (if loc-alist
+         (setq number (elmo-pop3-uidl-to-number
+                       (cdr (assq number loc-alist)))))
+      (when number
+       (elmo-pop3-send-command buffer process 
+                               (format "retr %s" number))
+       (when (null (setq response (elmo-pop3-read-response
+                                   buffer process t)))
+         (error "Fetching message failed"))
+       (setq response (elmo-pop3-read-body buffer process outbuf))
+       (set-buffer outbuf)
+       (goto-char (point-min))
+       (while (re-search-forward "^\\." nil t)
+         (replace-match "")
+         (forward-line))
+       response))))
+
+(defun elmo-pop3-delete-msg (buffer process number loc-alist)
+  (with-current-buffer buffer
+    (let (response errmsg msg)
+      (if loc-alist
+         (setq number (elmo-pop3-uidl-to-number
+                       (cdr (assq number loc-alist)))))
+      (if number
+         (progn
+           (elmo-pop3-send-command buffer process 
+                                   (format "dele %s" number))
+           (when (null (setq response (elmo-pop3-read-response
+                                       buffer process t)))
+             (error "Deleting message failed")))
+       (error "Deleting message failed")))))
+       
+
+(defun elmo-pop3-delete-msgs (spec msgs &optional msgdb)
+  (let* ((loc-alist (if elmo-pop3-use-uidl
+                       (if msgdb
+                           (elmo-msgdb-get-location msgdb)
+                         (elmo-msgdb-location-load
+                          (elmo-msgdb-expand-path nil spec)))))
+        (connection (elmo-pop3-get-connection spec))
+        (buffer  (elmo-pop3-connection-get-buffer connection))
+        (process (elmo-pop3-connection-get-process connection)))
+    (mapcar '(lambda (msg) (elmo-pop3-delete-msg 
+                           buffer process msg loc-alist))
+           msgs)))
 
 (defun elmo-pop3-search (spec condition &optional numlist)
   (error "Searching in pop3 folder is not implemented yet"))
   'elmo-generic-list-folder-unread)
 (defalias 'elmo-pop3-list-folder-important
   'elmo-generic-list-folder-important)
-(defalias 'elmo-pop3-commit 'elmo-generic-commit)
+
+(defun elmo-pop3-commit (spec)
+  (elmo-pop3-close-connection
+   (elmo-pop3-get-connection spec 'if-exists)))
 
 (provide 'elmo-pop3)