X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=elmo%2Felmo-pop3.el;h=d594e9333f7a4daab2cc3b6ee62a2ac72b8a37cc;hb=158d76afcd9b25ea8369062dfc53984f2f1435fc;hp=55a1f5df1ae5df499f6830c6ccf546bfc6b85754;hpb=df6eabd626b3a4d8f31bed990dd4d94cf815ba77;p=elisp%2Fwanderlust.git diff --git a/elmo/elmo-pop3.el b/elmo/elmo-pop3.el index 55a1f5d..d594e93 100644 --- a/elmo/elmo-pop3.el +++ b/elmo/elmo-pop3.el @@ -1,4 +1,4 @@ -;;; elmo-pop3.el -- POP3 Interface for ELMO. +;;; elmo-pop3.el --- POP3 Interface for ELMO. ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi ;; Copyright (C) 1999,2000 Kenichi OKADA @@ -26,10 +26,10 @@ ;; ;;; Commentary: -;; +;; ;;; Code: -;; +;; (require 'elmo-msgdb) (require 'elmo-net) @@ -40,10 +40,92 @@ (eval-and-compile (autoload 'md5 "md5")) +(defcustom elmo-pop3-default-use-uidl t + "If non-nil, use UIDL on POP3." + :type 'boolean + :group 'elmo) + +(defvar elmo-pop3-use-uidl-internal t + "(Internal switch for using UIDL on POP3).") + +(defvar elmo-pop3-use-cache t + "Use cache in pop3 folder.") + +(defvar elmo-pop3-send-command-synchronously nil + "If non-nil, commands are send synchronously. +If server doesn't accept asynchronous commands, this variable should be +set as non-nil.") + (defvar elmo-pop3-exists-exactly t) (defvar sasl-mechanism-alist) -(luna-define-class elmo-pop3-session (elmo-network-session)) +(defvar elmo-pop3-total-size nil) + +;; For debugging. +(defvar elmo-pop3-debug nil + "Non-nil forces POP3 folder as debug mode. +Debug information is inserted in the buffer \"*POP3 DEBUG*\"") + +;;; Debug +(defsubst elmo-pop3-debug (message &rest args) + (if elmo-pop3-debug + (let ((biff (string-match "BIFF-" (buffer-name))) + pos) + (with-current-buffer (get-buffer-create (concat "*POP3 DEBUG*" + (if biff "BIFF"))) + (goto-char (point-max)) + (setq pos (point)) + (insert (apply 'format message args) "\n"))))) + +;;; ELMO POP3 folder +(eval-and-compile + (luna-define-class elmo-pop3-folder (elmo-net-folder) + (use-uidl location-alist)) + (luna-define-internal-accessors 'elmo-pop3-folder)) + +(luna-define-method elmo-folder-initialize :around ((folder + elmo-pop3-folder) + name) + (let ((elmo-network-stream-type-alist + (if elmo-pop3-stream-type-alist + (append elmo-pop3-stream-type-alist + elmo-network-stream-type-alist) + elmo-network-stream-type-alist)) + parse) + (setq name (luna-call-next-method)) + ;; user + (setq parse (elmo-parse-token name "/:")) + (elmo-net-folder-set-user-internal folder + (if (eq (length (car parse)) 0) + elmo-pop3-default-user + (car parse))) + ;; auth + (setq parse (elmo-parse-prefixed-element ?/ (cdr parse) ":")) + (elmo-net-folder-set-auth-internal folder + (if (eq (length (car parse)) 0) + elmo-pop3-default-authenticate-type + (intern (downcase (car parse))))) + ;; uidl + (setq parse (elmo-parse-prefixed-element ?: (cdr parse))) + (elmo-pop3-folder-set-use-uidl-internal folder + (if (eq (length (car parse)) 0) + elmo-pop3-default-use-uidl + (string= (car parse) "uidl"))) + (unless (elmo-net-folder-server-internal folder) + (elmo-net-folder-set-server-internal folder + elmo-pop3-default-server)) + (unless (elmo-net-folder-port-internal folder) + (elmo-net-folder-set-port-internal folder + elmo-pop3-default-port)) + (unless (elmo-net-folder-stream-type-internal folder) + (elmo-net-folder-set-stream-type-internal + folder + (elmo-get-network-stream-type + elmo-pop3-default-stream-type))) + folder)) + +;;; POP3 session +(luna-define-class elmo-pop3-session (elmo-network-session) ()) ;; buffer-local (defvar elmo-pop3-read-point nil) @@ -52,13 +134,15 @@ (defvar elmo-pop3-size-hash nil) ; number -> size (defvar elmo-pop3-uidl-done nil) (defvar elmo-pop3-list-done nil) +(defvar elmo-pop3-lock nil) (defvar elmo-pop3-local-variables '(elmo-pop3-read-point elmo-pop3-uidl-number-hash elmo-pop3-number-uidl-hash elmo-pop3-uidl-done elmo-pop3-size-hash - elmo-pop3-list-done)) + elmo-pop3-list-done + elmo-pop3-lock)) (luna-define-method elmo-network-close-session ((session elmo-pop3-session)) (when (elmo-network-session-process-internal session) @@ -67,34 +151,49 @@ '(open run)) (elmo-pop3-send-command (elmo-network-session-process-internal session) "quit") + ;; process is dead. (or (elmo-pop3-read-response - (elmo-network-session-process-internal session) t) + (elmo-network-session-process-internal session) + t) (error "POP error: QUIT failed"))) (kill-buffer (process-buffer (elmo-network-session-process-internal session))) (delete-process (elmo-network-session-process-internal session)))) -(defun elmo-pop3-get-session (spec &optional if-exists) - (elmo-network-get-session - 'elmo-pop3-session - "POP3" - (elmo-pop3-spec-hostname spec) - (elmo-pop3-spec-port spec) - (elmo-pop3-spec-username spec) - (elmo-pop3-spec-auth spec) - (elmo-pop3-spec-stream-type spec) - if-exists)) - -(defun elmo-pop3-send-command (process command &optional no-erase) +(defun elmo-pop3-get-session (folder &optional if-exists) + "Get POP3 session for FOLDER. +If IF-EXISTS is non-nil, don't get new session. +If IF-EXISTS is `any-exists', get BIFF session or normal session if exists." + (let ((elmo-pop3-use-uidl-internal (if elmo-inhibit-number-mapping + nil + (elmo-pop3-folder-use-uidl-internal + folder)))) + (if (eq if-exists 'any-exists) + (or (elmo-network-get-session 'elmo-pop3-session + "POP3" + folder if-exists) + (elmo-network-get-session 'elmo-pop3-session + "BIFF-POP3" + folder if-exists)) + (elmo-network-get-session 'elmo-pop3-session + (concat + (if (elmo-folder-biff-internal folder) + "BIFF-") + "POP3") + folder if-exists)))) + +(defun elmo-pop3-send-command (process command &optional no-erase no-log) (with-current-buffer (process-buffer process) (unless no-erase (erase-buffer)) (goto-char (point-min)) (setq elmo-pop3-read-point (point)) + (elmo-pop3-debug "SEND: %s\n" (if no-log "" command)) (process-send-string process command) (process-send-string process "\r\n"))) (defun elmo-pop3-read-response (process &optional not-command) + ;; buffer is in case for process is dead. (with-current-buffer (process-buffer process) (let ((case-fold-search nil) (response-string nil) @@ -104,7 +203,7 @@ (while response-continue (goto-char elmo-pop3-read-point) (while (not (re-search-forward "\r?\n" nil t)) - (accept-process-output process) + (accept-process-output process 1) (goto-char elmo-pop3-read-point)) (setq match-end (point)) (setq response-string @@ -125,7 +224,7 @@ (setq return-value nil)) (setq elmo-pop3-read-point match-end) (if not-command - (setq response-continue nil)) + (setq response-continue nil)) (setq return-value (if return-value (concat return-value "\n" response-string) @@ -134,29 +233,44 @@ return-value))) (defun elmo-pop3-process-filter (process output) - (save-excursion - (set-buffer (process-buffer process)) - (goto-char (point-max)) - (insert output) - (message "Retrieving...(%d bytes)." (buffer-size)))) + (when (buffer-live-p (process-buffer process)) + (with-current-buffer (process-buffer process) + (goto-char (point-max)) + (insert output) + (elmo-pop3-debug "RECEIVED: %s\n" output) + (if (and elmo-pop3-total-size + (> elmo-pop3-total-size + (min elmo-display-retrieval-progress-threshold 100))) + (elmo-display-progress + 'elmo-display-retrieval-progress + (format "Retrieving (%d/%d bytes)..." + (buffer-size) + elmo-pop3-total-size) + (/ (buffer-size) (/ elmo-pop3-total-size 100))))))) (defun elmo-pop3-auth-user (session) (let ((process (elmo-network-session-process-internal session))) ;; try USER/PASS (elmo-pop3-send-command process - (format "user %s" (elmo-network-session-user-internal session))) + (format "user %s" (elmo-network-session-user-internal session)) + nil 'no-log) (or (elmo-pop3-read-response process t) - (signal 'elmo-authenticate-error - '(elmo-pop-auth-user))) + (progn + (delete-process process) + (signal 'elmo-authenticate-error + '(elmo-pop-auth-user)))) (elmo-pop3-send-command process (format "pass %s" (elmo-get-passwd - (elmo-network-session-password-key session)))) + (elmo-network-session-password-key session))) + nil 'no-log) (or (elmo-pop3-read-response process t) - (signal 'elmo-authenticate-error - '(elmo-pop-auth-user))))) + (progn + (delete-process process) + (signal 'elmo-authenticate-error + '(elmo-pop-auth-user)))))) (defun elmo-pop3-auth-apop (session) (if (string-match "^\+OK .*\\(<[^\>]+>\\)" @@ -172,14 +286,17 @@ 1 (elmo-network-session-greeting-internal session)) (elmo-get-passwd - (elmo-network-session-password-key session)))))) + (elmo-network-session-password-key session))))) + nil 'no-log) (or (elmo-pop3-read-response (elmo-network-session-process-internal session) t) - (signal 'elmo-authenticate-error - '(elmo-pop3-auth-apop)))) + (progn + (delete-process (elmo-network-session-process-internal session)) + (signal 'elmo-authenticate-error + '(elmo-pop3-auth-apop))))) (signal 'elmo-open-error '(elmo-pop3-auth-apop)))) - + (luna-define-method elmo-network-initialize-session-buffer :after ((session elmo-pop3-session) buffer) (with-current-buffer buffer @@ -216,7 +333,7 @@ (luna-define-method elmo-network-authenticate-session ((session elmo-pop3-session)) - (with-current-buffer (process-buffer + (with-current-buffer (process-buffer (elmo-network-session-process-internal session)) (let* ((process (elmo-network-session-process-internal session)) (auth (elmo-network-session-auth-internal session)) @@ -240,7 +357,7 @@ mechanism (elmo-network-session-user-internal session) "pop" - (elmo-network-session-host-internal session))) + (elmo-network-session-server-internal session))) ;;; (if elmo-pop3-auth-user-realm ;;; (sasl-client-set-property client 'realm elmo-pop3-auth-user-realm)) (setq name (sasl-mechanism-name mechanism)) @@ -259,7 +376,8 @@ (concat " " (elmo-base64-encode-string - (sasl-step-data step) 'no-line-break))))) ;) + (sasl-step-data step) 'no-line-break)))) + nil 'no-log) (catch 'done (while t (unless (setq response (elmo-pop3-read-response process t)) @@ -279,7 +397,7 @@ (throw 'done nil))) (sasl-step-set-data step - (elmo-base64-decode-string + (elmo-base64-decode-string (cadr (split-string response " ")))) (setq step (sasl-next-step client step)) (elmo-pop3-send-command @@ -287,7 +405,7 @@ (if (sasl-step-data step) (elmo-base64-encode-string (sasl-step-data step) 'no-line-break) - ""))))))))) + "") nil 'no-log)))))))) (luna-define-method elmo-network-setup-session ((session elmo-pop3-session)) @@ -306,7 +424,7 @@ ;; POP server always returns a sequence of serial numbers. (setq count (elmo-pop3-parse-list-response response)) ;; UIDL - (when elmo-pop3-use-uidl + (when elmo-pop3-use-uidl-internal (setq elmo-pop3-uidl-number-hash (elmo-make-hash (* count 2))) (setq elmo-pop3-number-uidl-hash (elmo-make-hash (* count 2))) ;; UIDL @@ -319,37 +437,39 @@ (elmo-pop3-parse-uidl-response response))))) (defun elmo-pop3-read-contents (buffer process) - (save-excursion - (set-buffer buffer) + (with-current-buffer buffer (let ((case-fold-search nil) match-end) (goto-char elmo-pop3-read-point) (while (not (re-search-forward "^\\.\r\n" nil t)) - (accept-process-output process) + (accept-process-output process 1) (goto-char elmo-pop3-read-point)) (setq match-end (point)) (elmo-delete-cr (buffer-substring elmo-pop3-read-point (- match-end 3)))))) -;; dummy functions -(defun elmo-pop3-list-folders (spec &optional hierarchy) nil) -(defun elmo-pop3-append-msg (spec string) nil nil) -(defun elmo-pop3-folder-creatable-p (spec) nil) -(defun elmo-pop3-create-folder (spec) nil) +(luna-define-method elmo-folder-expand-msgdb-path ((folder elmo-pop3-folder)) + (convert-standard-filename + (expand-file-name + (elmo-safe-filename (elmo-net-folder-user-internal folder)) + (expand-file-name (elmo-net-folder-server-internal folder) + (expand-file-name + "pop" + elmo-msgdb-directory))))) -(defun elmo-pop3-folder-exists-p (spec) +(luna-define-method elmo-folder-exists-p ((folder elmo-pop3-folder)) (if (and elmo-pop3-exists-exactly - (elmo-pop3-plugged-p spec)) + (elmo-folder-plugged-p folder)) (save-excursion - (let (elmo-auto-change-plugged ; don't change plug status. - elmo-pop3-use-uidl ; No need to use uidl. + (let (elmo-auto-change-plugged ; don't change plug status. + (elmo-inhibit-number-mapping t) ; No need to use uidl. session) (prog1 - (setq session (elmo-pop3-get-session spec)) + (setq session (elmo-pop3-get-session folder)) (if session (elmo-network-close-session session))))) - t)) + (file-directory-p (elmo-folder-msgdb-path folder)))) (defun elmo-pop3-parse-uidl-response (string) (let ((buffer (current-buffer)) @@ -358,7 +478,7 @@ (let (number uid list) (insert string) (goto-char (point-min)) - (while (re-search-forward "^\\([0-9]+\\)[\t ]\\([^ \n]+\\)$" nil t) + (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 @@ -376,7 +496,7 @@ (with-temp-buffer (insert string) (goto-char (point-min)) - (while (re-search-forward "^\\([0-9]+\\)[\t ]\\([0-9]+\\)$" nil t) + (while (re-search-forward "^\\([0-9]+\\)[\t ]+\\([0-9]+\\)$" nil t) (setq alist (cons (cons (elmo-match-buffer 1) @@ -393,32 +513,63 @@ (setq elmo-pop3-list-done t)) count))) -(defun elmo-pop3-list-location (spec) +(defun elmo-pop3-list-location (folder) (with-current-buffer (process-buffer (elmo-network-session-process-internal - (elmo-pop3-get-session spec))) - (let (list) + (elmo-pop3-get-session folder))) + (let (locations) (if elmo-pop3-uidl-done (progn (mapatoms (lambda (atom) - (setq list (cons (symbol-name atom) list))) + (setq locations (cons (symbol-name atom) locations))) elmo-pop3-uidl-number-hash) - (nreverse list)) + (sort locations + (lambda (loc1 loc2) + (< (elmo-pop3-uidl-to-number loc1) + (elmo-pop3-uidl-to-number loc2))))) (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)))) +(defun elmo-pop3-list-folder-by-location (folder locations) + (let* ((location-alist (elmo-pop3-folder-location-alist-internal folder)) + (locations-in-db (mapcar 'cdr location-alist)) + result new-locs new-alist deleted-locs i) + (setq new-locs + (elmo-delete-if (function + (lambda (x) (member x locations-in-db))) + locations)) + (setq deleted-locs + (elmo-delete-if (function + (lambda (x) (member x locations))) + locations-in-db)) + (setq i (or (elmo-max-of-list (mapcar 'car location-alist)) 0)) + (mapcar + (function + (lambda (x) + (setq location-alist + (delq (rassoc x location-alist) location-alist)))) + deleted-locs) + (while new-locs + (setq i (1+ i)) + (setq new-alist (cons (cons i (car new-locs)) new-alist)) + (setq new-locs (cdr new-locs))) + (setq result (nconc location-alist new-alist)) + (setq result (sort result (lambda (x y) (< (car x)(car y))))) + (elmo-pop3-folder-set-location-alist-internal folder result) + (mapcar 'car result))) + +(defun elmo-pop3-list-by-uidl-subr (folder &optional nonsort) + (let ((flist (elmo-pop3-list-folder-by-location + folder + (elmo-pop3-list-location folder)))) (if nonsort (cons (elmo-max-of-list flist) (length flist)) (sort flist '<)))) -(defun elmo-pop3-list-by-list (spec) +(defun elmo-pop3-list-by-list (folder) (with-current-buffer (process-buffer (elmo-network-session-process-internal - (elmo-pop3-get-session spec))) + (elmo-pop3-get-session folder))) (let (list) (if elmo-pop3-list-done (progn @@ -430,25 +581,26 @@ (sort list '<)) (error "POP3: Error in list"))))) -(defun elmo-pop3-list-folder (spec &optional nohide) - (let ((killed (and elmo-use-killed-list - (elmo-msgdb-killed-list-load - (elmo-msgdb-expand-path spec)))) - numbers) - (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))) - (elmo-living-messages numbers killed))) - -(defun elmo-pop3-max-of-folder (spec) - (elmo-pop3-commit spec) - (if elmo-pop3-use-uidl - (elmo-pop3-list-by-uidl-subr spec 'nonsort) +(defsubst elmo-pop3-folder-list-messages (folder) + (if (and (not elmo-inhibit-number-mapping) + (elmo-pop3-folder-use-uidl-internal folder)) + (elmo-pop3-list-by-uidl-subr folder) + (elmo-pop3-list-by-list folder))) + +(luna-define-method elmo-folder-list-messages-plugged + ((folder elmo-pop3-folder) &optional nohide) + (elmo-pop3-folder-list-messages folder)) + +(luna-define-method elmo-folder-status ((folder elmo-pop3-folder)) + (elmo-folder-open-internal folder) + (elmo-folder-check folder) + (if (elmo-pop3-folder-use-uidl-internal folder) + (prog1 + (elmo-pop3-list-by-uidl-subr folder 'nonsort) + (elmo-folder-close-internal folder)) (let* ((process (elmo-network-session-process-internal - (elmo-pop3-get-session spec))) + (elmo-pop3-get-session folder))) (total 0) response) (with-current-buffer (process-buffer process) @@ -460,6 +612,7 @@ (setq total (string-to-int (substring response (match-beginning 1)(match-end 1 )))) + (elmo-folder-close-internal folder) (cons total total)))))) (defvar elmo-pop3-header-fetch-chop-length 200) @@ -468,15 +621,15 @@ (cond ((eq (following-char) ?+) (if (re-search-forward "\n\\.\r?\n" nil t) - t + t nil)) ((looking-at "-") (if (search-forward "\n" nil t) - t + t nil)) (t nil))) - + (defun elmo-pop3-retrieve-headers (buffer tobuffer process articles) (save-excursion (set-buffer buffer) @@ -523,7 +676,22 @@ (replace-match "\n")) (copy-to-buffer tobuffer (point-min) (point-max))))) -(defalias 'elmo-pop3-msgdb-create 'elmo-pop3-msgdb-create-as-numlist) +(luna-define-method elmo-folder-msgdb-create ((folder elmo-pop3-folder) + numlist new-mark + already-mark seen-mark + important-mark seen-list) + (let ((process (elmo-network-session-process-internal + (elmo-pop3-get-session folder)))) + (with-current-buffer (process-buffer process) + (elmo-pop3-sort-msgdb-by-original-number + folder + (elmo-pop3-msgdb-create-by-header + process + numlist + new-mark already-mark + seen-mark seen-list + (if (elmo-pop3-folder-use-uidl-internal folder) + (elmo-pop3-folder-location-alist-internal folder))))))) (defun elmo-pop3-sort-overview-by-original-number (overview loc-alist) (if loc-alist @@ -537,33 +705,14 @@ loc-alist)))))) overview)) -(defun elmo-pop3-sort-msgdb-by-original-number (msgdb) +(defun elmo-pop3-sort-msgdb-by-original-number (folder msgdb) (message "Sorting...") (let ((overview (elmo-msgdb-get-overview msgdb))) (setq overview (elmo-pop3-sort-overview-by-original-number overview - (elmo-msgdb-get-location msgdb))) + (elmo-pop3-folder-location-alist-internal folder))) (message "Sorting...done") - (list overview (nth 1 msgdb)(nth 2 msgdb)(nth 3 msgdb)(nth 4 msgdb)))) - -(defun elmo-pop3-msgdb-create-as-numlist (spec numlist new-mark - already-mark seen-mark - important-mark seen-list - &optional msgdb) - (when numlist - (let ((process (elmo-network-session-process-internal - (elmo-pop3-get-session spec))) - 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 spec))))) - (with-current-buffer (process-buffer process) - (elmo-pop3-sort-msgdb-by-original-number - (elmo-pop3-msgdb-create-by-header process numlist - new-mark already-mark - seen-mark seen-list - loc-alist)))))) + (list overview (nth 1 msgdb)(nth 2 msgdb)(nth 3 msgdb)))) (defun elmo-pop3-uidl-to-number (uidl) (string-to-number (elmo-get-hash-val uidl @@ -654,8 +803,8 @@ (setq message-id (car entity)) (setq seen (member message-id seen-list)) (if (setq gmark (or (elmo-msgdb-global-mark-get message-id) - (if (elmo-cache-exists-p - message-id) ; XXX + (if (elmo-file-cache-status + (elmo-file-cache-get message-id)) (if seen nil already-mark) @@ -674,7 +823,7 @@ (elmo-display-progress 'elmo-pop3-msgdb-create-message "Creating msgdb..." (/ (* i 100) num))))) - (list overview number-alist mark-alist loc-alist)))) + (list overview number-alist mark-alist)))) (defun elmo-pop3-read-body (process outbuf) (with-current-buffer (process-buffer process) @@ -682,34 +831,66 @@ end) (goto-char start) (while (not (re-search-forward "^\\.\r?\n" nil t)) - (accept-process-output process) + (accept-process-output process 1) (goto-char start)) (setq end (point)) (with-current-buffer outbuf (erase-buffer) - (insert-buffer-substring (process-buffer process) start (- end 3)) - (elmo-delete-cr-get-content-type))))) - -(defun elmo-pop3-read-msg (spec number outbuf &optional msgdb unread) - (let* ((loc-alist (if elmo-pop3-use-uidl - (if msgdb - (elmo-msgdb-get-location msgdb) - (elmo-msgdb-location-load - (elmo-msgdb-expand-path spec))))) + (insert-buffer-substring (process-buffer process) start (- end 3))) + t))) + +(luna-define-method elmo-folder-open-internal ((folder elmo-pop3-folder)) + (if (and (not elmo-inhibit-number-mapping) + (elmo-pop3-folder-use-uidl-internal folder)) + (elmo-pop3-folder-set-location-alist-internal + folder (elmo-msgdb-location-load (elmo-folder-msgdb-path folder))))) + +(luna-define-method elmo-folder-commit :after ((folder elmo-pop3-folder)) + (when (elmo-folder-persistent-p folder) + (elmo-msgdb-location-save (elmo-folder-msgdb-path folder) + (elmo-pop3-folder-location-alist-internal + folder)))) + +(luna-define-method elmo-folder-close-internal ((folder elmo-pop3-folder)) + (elmo-pop3-folder-set-location-alist-internal folder nil) + ;; Just close connection + (elmo-folder-check folder)) + +(luna-define-method elmo-message-fetch-plugged ((folder elmo-pop3-folder) + number strategy + &optional section + outbuf unseen) + (let* ((loc-alist (elmo-pop3-folder-location-alist-internal folder)) (process (elmo-network-session-process-internal - (elmo-pop3-get-session spec))) - response errmsg msg) + (elmo-pop3-get-session folder))) + size response errmsg msg) (with-current-buffer (process-buffer process) (if loc-alist (setq number (elmo-pop3-uidl-to-number (cdr (assq number loc-alist))))) + (setq size (string-to-number + (elmo-pop3-number-to-size number))) (when number (elmo-pop3-send-command process (format "retr %s" number)) - (when (null (setq response (elmo-pop3-read-response - process t))) - (error "Fetching message failed")) - (setq response (elmo-pop3-read-body process outbuf)) + (unless elmo-inhibit-display-retrieval-progress + (setq elmo-pop3-total-size size) + (elmo-display-progress + 'elmo-display-retrieval-progress + (format "Retrieving (0/%d bytes)..." elmo-pop3-total-size) + 0)) + (unwind-protect + (progn + (when (null (setq response (elmo-pop3-read-response + process t))) + (error "Fetching message failed")) + (setq response (elmo-pop3-read-body process outbuf))) + (setq elmo-pop3-total-size nil)) + (unless elmo-inhibit-display-retrieval-progress + (elmo-display-progress + 'elmo-display-retrieval-progress + "Retrieving..." 100) ; remove progress bar. + (message "Retrieving...done")) (set-buffer outbuf) (goto-char (point-min)) (while (re-search-forward "^\\." nil t) @@ -732,62 +913,33 @@ (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 spec))))) +(luna-define-method elmo-folder-delete-messages-plugged + ((folder elmo-pop3-folder) msgs) + (let ((loc-alist (elmo-pop3-folder-location-alist-internal folder)) (process (elmo-network-session-process-internal - (elmo-pop3-get-session spec)))) + (elmo-pop3-get-session folder)))) (mapcar '(lambda (msg) (elmo-pop3-delete-msg process msg loc-alist)) msgs))) -(defun elmo-pop3-search (spec condition &optional numlist) - (error "Searching in pop3 folder is not implemented yet")) - -(defun elmo-pop3-use-cache-p (spec number) +(luna-define-method elmo-message-use-cache-p ((folder elmo-pop3-folder) number) elmo-pop3-use-cache) -(defun elmo-pop3-local-file-p (spec number) - nil) - -(defun elmo-pop3-port-label (spec) - (concat "pop3" - (if (elmo-pop3-spec-stream-type spec) - (concat "!" (symbol-name - (elmo-network-stream-type-symbol - (elmo-pop3-spec-stream-type spec))))))) - -(defsubst elmo-pop3-portinfo (spec) - (list (elmo-pop3-spec-hostname spec) - (elmo-pop3-spec-port spec))) - -(defun elmo-pop3-plugged-p (spec) - (apply 'elmo-plugged-p - (append (elmo-pop3-portinfo spec) - (list nil (quote (elmo-pop3-port-label spec)))))) - -(defun elmo-pop3-set-plugged (spec plugged add) - (apply 'elmo-set-plugged plugged - (append (elmo-pop3-portinfo spec) - (list nil nil (quote (elmo-pop3-port-label spec)) add)))) - -(defalias 'elmo-pop3-sync-number-alist - 'elmo-generic-sync-number-alist) -(defalias 'elmo-pop3-list-folder-unread - 'elmo-generic-list-folder-unread) -(defalias 'elmo-pop3-list-folder-important - 'elmo-generic-list-folder-important) -(defalias 'elmo-pop3-folder-diff 'elmo-generic-folder-diff) - -(defun elmo-pop3-commit (spec) - (if (elmo-pop3-plugged-p spec) - (let ((session (elmo-pop3-get-session spec 'if-exists))) - (and session - (elmo-network-close-session session))))) - +(luna-define-method elmo-folder-persistent-p ((folder elmo-pop3-folder)) + (and (elmo-folder-persistent-internal folder) + (elmo-pop3-folder-use-uidl-internal folder))) + +(luna-define-method elmo-folder-clear :around ((folder elmo-pop3-folder) + &optional keep-killed) + (unless keep-killed + (elmo-pop3-folder-set-location-alist-internal folder nil)) + (luna-call-next-method)) + +(luna-define-method elmo-folder-check ((folder elmo-pop3-folder)) + (if (elmo-folder-plugged-p folder) + (let ((session (elmo-pop3-get-session folder 'if-exists))) + (when session + (elmo-network-close-session session))))) (require 'product) (product-provide (provide 'elmo-pop3) (require 'elmo-version))