From c7212838b5e411e90afd35bb5acf3c412991975f Mon Sep 17 00:00:00 2001 From: teranisi Date: Tue, 18 Jul 2000 02:43:25 +0000 Subject: [PATCH] * 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. --- elmo/ChangeLog | 48 ++++++ elmo/elmo-msgdb.el | 7 + elmo/elmo-pipe.el | 9 +- elmo/elmo-pop3.el | 486 ++++++++++++++++++++++++++++++++++------------------ 4 files changed, 376 insertions(+), 174 deletions(-) diff --git a/elmo/ChangeLog b/elmo/ChangeLog index fe51df4..7bb14a8 100644 --- a/elmo/ChangeLog +++ b/elmo/ChangeLog @@ -1,3 +1,51 @@ +2000-07-18 Yuuichi Teranishi + + * 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 * elmo-vars.el (elmo-use-killed-list): New variable diff --git a/elmo/elmo-msgdb.el b/elmo/elmo-msgdb.el index 5ee920e..3b378a4 100644 --- a/elmo/elmo-msgdb.el +++ b/elmo/elmo-msgdb.el @@ -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))) diff --git a/elmo/elmo-pipe.el b/elmo/elmo-pipe.el index 8e5eff6..e07e45c 100644 --- a/elmo/elmo-pipe.el +++ b/elmo/elmo-pipe.el @@ -66,10 +66,12 @@ (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))))) diff --git a/elmo/elmo-pop3.el b/elmo/elmo-pop3.el index 82185c3..cd2d074 100644 --- a/elmo/elmo-pop3.el +++ b/elmo/elmo-pop3.el @@ -54,18 +54,39 @@ (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) @@ -82,74 +103,91 @@ (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) @@ -179,8 +217,7 @@ (setq return-value (if return-value (concat return-value "\n" response-string) - response-string - ))) + response-string))) (if (looking-at "\\-.*$") (progn (setq response-continue nil) @@ -326,7 +363,7 @@ 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 @@ -371,48 +408,93 @@ (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) @@ -421,22 +503,24 @@ 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) @@ -463,12 +547,10 @@ (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 @@ -494,54 +576,80 @@ (/ (* 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)) @@ -562,10 +670,24 @@ (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) @@ -582,15 +704,14 @@ (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 @@ -606,42 +727,62 @@ (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")) @@ -676,7 +817,10 @@ '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) -- 1.7.10.4