X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=elmo%2Felmo-pop3.el;h=19db3b0ca86b1ceaf2bdda8c4475f7bcff72b398;hb=0a4f27eec0a2e5035d6bb853a62dd7631ea8cb2a;hp=e210fd5100ee9dbcf395c7d4f4248bfa799297b9;hpb=9ef19f77adfa042aefebdf54f58ba272e4fee489;p=elisp%2Fwanderlust.git diff --git a/elmo/elmo-pop3.el b/elmo/elmo-pop3.el index e210fd5..19db3b0 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) @@ -56,7 +56,11 @@ If server doesn't accept asynchronous commands, this variable should be set as non-nil.") -(defvar elmo-pop3-exists-exactly t) +(defcustom elmo-pop3-exists-exactly nil + "If non-nil, POP3 folder existence is checked everytime before the session." + :type 'boolean + :group 'elmo) + (defvar sasl-mechanism-alist) (defvar elmo-pop3-total-size nil) @@ -66,15 +70,15 @@ set as non-nil.") "Non-nil forces POP3 folder as debug mode. Debug information is inserted in the buffer \"*POP3 DEBUG*\"") -(defvar elmo-pop3-debug-inhibit-logging nil) - ;;; Debug (defsubst elmo-pop3-debug (message &rest args) (if elmo-pop3-debug - (with-current-buffer (get-buffer-create "*POP3 DEBUG*") - (goto-char (point-max)) - (if elmo-pop3-debug-inhibit-logging - (insert "NO LOGGING\n") + (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 @@ -112,7 +116,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") elmo-pop3-default-use-uidl (string= (car parse) "uidl"))) (unless (elmo-net-folder-server-internal folder) - (elmo-net-folder-set-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 @@ -149,33 +153,50 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (when (memq (process-status (elmo-network-session-process-internal session)) '(open run)) - (let ((buffer (process-buffer - (elmo-network-session-process-internal session)))) - (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) - (error "POP error: QUIT failed")))) + (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) + (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 (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)))) - (elmo-network-get-session 'elmo-pop3-session "POP3" folder if-exists))) - -(defun elmo-pop3-send-command (process command &optional no-erase) + (prog1 + (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)) + ;; For saving existency. + (unless (file-exists-p (elmo-folder-msgdb-path folder)) + (elmo-make-directory (elmo-folder-msgdb-path folder)))))) + +(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" command) + (elmo-pop3-debug "SEND: %s\n" (if no-log "" command)) (process-send-string process command) (process-send-string process "\r\n"))) @@ -190,7 +211,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (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 @@ -211,7 +232,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (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) @@ -220,38 +241,44 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") return-value))) (defun elmo-pop3-process-filter (process output) - (save-excursion - (set-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)))))) + (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 .*\\(<[^\>]+>\\)" @@ -267,14 +294,17 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") 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 @@ -311,10 +341,9 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (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)) - (elmo-pop3-debug-inhibit-logging t) (auth (elmo-network-session-auth-internal session)) (auth (mapcar '(lambda (mechanism) (upcase (symbol-name mechanism))) (if (listp auth) auth (list auth)))) @@ -355,7 +384,8 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (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)) @@ -375,7 +405,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (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 @@ -383,7 +413,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (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)) @@ -420,7 +450,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") 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 @@ -434,7 +464,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (expand-file-name (elmo-net-folder-server-internal folder) (expand-file-name "pop" - elmo-msgdb-dir))))) + elmo-msgdb-directory))))) (luna-define-method elmo-folder-exists-p ((folder elmo-pop3-folder)) (if (and elmo-pop3-exists-exactly @@ -447,7 +477,11 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (setq session (elmo-pop3-get-session folder)) (if session (elmo-network-close-session session))))) - t)) + (or (file-directory-p (elmo-folder-msgdb-path folder)) + ;; First time. + (when (elmo-folder-plugged-p folder) + (let ((elmo-pop3-exists-exactly t)) + (elmo-folder-exists-p folder)))))) (defun elmo-pop3-parse-uidl-response (string) (let ((buffer (current-buffer)) @@ -474,7 +508,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (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) @@ -565,7 +599,7 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (elmo-pop3-list-by-uidl-subr folder) (elmo-pop3-list-by-list folder))) -(luna-define-method elmo-folder-list-messages-internal +(luna-define-method elmo-folder-list-messages-plugged ((folder elmo-pop3-folder) &optional nohide) (elmo-pop3-folder-list-messages folder)) @@ -599,11 +633,11 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (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))) @@ -655,42 +689,34 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (copy-to-buffer tobuffer (point-min) (point-max))))) (luna-define-method elmo-folder-msgdb-create ((folder elmo-pop3-folder) - numlist new-mark - already-mark seen-mark - important-mark seen-list) + numlist flag-table) (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 + folder process numlist - new-mark already-mark - seen-mark seen-list + flag-table (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 - (sort overview - (lambda (ent1 ent2) - (< (elmo-pop3-uidl-to-number - (cdr (assq (elmo-msgdb-overview-entity-get-number ent1) - loc-alist))) - (elmo-pop3-uidl-to-number - (cdr (assq (elmo-msgdb-overview-entity-get-number ent2) - loc-alist)))))) - overview)) - (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-pop3-folder-location-alist-internal folder))) - (message "Sorting...done") - (list overview (nth 1 msgdb)(nth 2 msgdb)(nth 3 msgdb)))) + (let ((location-alist (elmo-pop3-folder-location-alist-internal folder))) + (when location-alist + (elmo-msgdb-sort-entities + msgdb + (lambda (ent1 ent2 loc-alist) + (< (elmo-pop3-uidl-to-number + (cdr (assq (elmo-message-entity-number ent1) + loc-alist))) + (elmo-pop3-uidl-to-number + (cdr (assq (elmo-message-entity-number ent2) + loc-alist))))) + location-alist)) + msgdb)) (defun elmo-pop3-uidl-to-number (uidl) (string-to-number (elmo-get-hash-val uidl @@ -704,11 +730,9 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (elmo-get-hash-val (format "#%d" number) elmo-pop3-size-hash)) -(defun elmo-pop3-msgdb-create-by-header (process numlist - new-mark already-mark - seen-mark - seen-list - loc-alist) +(defun elmo-pop3-msgdb-create-by-header (folder process numlist + flag-table + loc-alist) (let ((tmp-buffer (get-buffer-create " *ELMO Overview TMP*"))) (with-current-buffer (process-buffer process) (if loc-alist ; use uidl. @@ -723,23 +747,24 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") tmp-buffer process numlist) (prog1 (elmo-pop3-msgdb-create-message + folder tmp-buffer process (length numlist) numlist - new-mark already-mark seen-mark seen-list loc-alist) + flag-table loc-alist) (kill-buffer tmp-buffer))))) -(defun elmo-pop3-msgdb-create-message (buffer +(defun elmo-pop3-msgdb-create-message (folder + buffer process num - numlist new-mark already-mark - seen-mark - seen-list + numlist + flag-table loc-alist) (save-excursion - (let (beg overview number-alist mark-alist - entity i number message-id gmark seen size) + (let ((new-msgdb (elmo-make-msgdb)) + beg entity i number message-id flags) (set-buffer buffer) (elmo-set-buffer-multibyte default-enable-multibyte-characters) (goto-char (point-min)) @@ -753,55 +778,35 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (save-restriction (narrow-to-region beg (point)) (setq entity - (elmo-msgdb-create-overview-from-buffer - (car numlist))) + (elmo-msgdb-create-message-entity-from-buffer + new-msgdb (car numlist))) (setq numlist (cdr numlist)) (when entity - (setq overview - (elmo-msgdb-append-element - overview entity)) (with-current-buffer (process-buffer process) - (elmo-msgdb-overview-entity-set-size + (elmo-message-entity-set-field entity + 'size (string-to-number (elmo-pop3-number-to-size - (elmo-msgdb-overview-entity-get-number entity)))) + (elmo-message-entity-number entity)))) (if (setq number (car (rassoc (elmo-pop3-number-to-uidl - (elmo-msgdb-overview-entity-get-number entity)) + (elmo-message-entity-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))) - (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-file-cache-status - (elmo-file-cache-get message-id)) - (if seen - nil - already-mark) - (if seen - (if elmo-pop3-use-cache - seen-mark) - new-mark)))) - (setq mark-alist - (elmo-msgdb-mark-append - mark-alist - (elmo-msgdb-overview-entity-get-number entity) - gmark)))))) + (elmo-message-entity-set-number entity number))) + (setq message-id (elmo-message-entity-field entity 'message-id) + flags (elmo-flag-table-get flag-table message-id)) + (elmo-global-flags-set flags folder number message-id) + (elmo-msgdb-append-entity new-msgdb entity flags)))) (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)))) + new-msgdb))) (defun elmo-pop3-read-body (process outbuf) (with-current-buffer (process-buffer process) @@ -809,12 +814,13 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") 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)))))) + (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) @@ -861,12 +867,13 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (when (null (setq response (elmo-pop3-read-response process t))) (error "Fetching message failed")) - (setq response (elmo-pop3-read-body process outbuf))) + (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 "" 100) ; remove progress bar. - (message "Retrieving...done.")) + '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) @@ -889,13 +896,13 @@ Debug information is inserted in the buffer \"*POP3 DEBUG*\"") (error "Deleting message failed"))) (error "Deleting message failed"))))) -(luna-define-method elmo-folder-delete-messages ((folder elmo-pop3-folder) - msgs) +(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 folder)))) - (mapcar '(lambda (msg) (elmo-pop3-delete-msg - process msg loc-alist)) + (mapcar '(lambda (msg) (elmo-pop3-delete-msg process msg loc-alist)) msgs))) (luna-define-method elmo-message-use-cache-p ((folder elmo-pop3-folder) number)