Synch with Oort Gnus.
[elisp/gnus.git-] / lisp / pop3.el
index b8bc546..78038c3 100644 (file)
@@ -1,14 +1,15 @@
 ;;; pop3.el --- Post Office Protocol (RFC 1460) interface
 
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Richard L. Pieri <ratinox@peorth.gweep.net>
 ;;      Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
-;; Maintainer: FSF
+;;      Katsumi Yamaoka <yamaoka@jpl.org>
+;; Maintainer: Volunteers
 ;; Keywords: mail
 
-;; This file is part of GNU Emacs.
+;; This file is part of T-gnus.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 
 ;; This program was inspired by Kyle E. Jones's vm-pop program.
 
+;; You have to set the variable `pop3-connection-type' to `ssl' or
+;; `tls' expressly, if you would like to use this module with Gnus
+;; (not T-gnus) for those connection types.  For examples:
+;;
+;;(setq mail-sources '((pop :server "POPSERVER" :port 995 :connection ssl
+;;                          :authentication apop)))
+;;(setq pop3-connection-type 'ssl)
+
 ;;; Code:
 
 (eval-when-compile (require 'cl))
-(eval-when-compile (require 'static))
+
+;; as-binary-process, open-network-stream-as-binary, write-region-as-binary
+(require 'pces)
+;; exec-installed-p
+(require 'path-util)
 
 (require 'mail-utils)
 
@@ -87,7 +100,6 @@ Nil means no, t means yes, not-nil-or-t means yet to be determined.")
 (defvar pop3-debug nil)
 
 (eval-and-compile
-  (autoload 'open-ssl-stream "ssl")
   (autoload 'starttls-open-stream "starttls")
   (autoload 'starttls-negotiate "starttls"))
 
@@ -179,7 +191,7 @@ Nil means no, t means yes, not-nil-or-t means yet to be determined.")
          ((equal 'pass pop3-authentication-scheme)
           (pop3-user process pop3-maildrop)
           (pop3-pass process))
-         (t (error "Invalid POP3 authentication scheme.")))
+         (t (error "Invalid POP3 authentication scheme")))
     (setq message-count (car (pop3-stat process)))
     (pop3-quit process)
     message-count))
@@ -211,22 +223,23 @@ Argument PORT specifies connecting port."
       process)))
 
 (defun pop3-open-ssl-stream-1 (name buffer host service extra-arg)
-  (require 'path-util)
+  (require 'ssl)
   (let* ((ssl-program-name
          pop3-ssl-program-name)
         (ssl-program-arguments
-         `(,@pop3-ssl-program-arguments ,extra-arg
+         `(,@pop3-ssl-program-arguments
+           ,extra-arg
            "-connect" ,(format "%s:%d" host service)))
-         (process (open-ssl-stream name buffer host service)))
+        (process (open-ssl-stream name buffer host service)))
     (when process
       (with-current-buffer buffer
        (goto-char (point-min))
        (while (and (memq (process-status process) '(open run))
-                    (goto-char (point-max))
-                    (forward-line -1)
-                    (not (looking-at "+OK")))
-          (accept-process-output process 1)
-          (sit-for 1))
+                   (goto-char (point-max))
+                   (forward-line -1)
+                   (not (looking-at "+OK")))
+         (accept-process-output process 1)
+         (sit-for 1))
        (delete-region (point-min) (point)))
       (and process (memq (process-status process) '(open run))
           process))))
@@ -235,16 +248,9 @@ Argument PORT specifies connecting port."
   "Open a SSL connection for a service to a host.
 Returns a subprocess-object to represent the connection.
 Args are NAME BUFFER HOST SERVICE."
-  (cond ((eq system-type 'windows-nt)
-        (let (selective-display
-              (coding-system-for-write 'binary)
-              (coding-system-for-read 'raw-text-dos))
-          (or (pop3-open-ssl-stream-1 name buffer host service "-ssl3")
-              (pop3-open-ssl-stream-1 name buffer host service "-ssl2"))))
-       (t
-        (as-binary-process
-          (or (pop3-open-ssl-stream-1 name buffer host service "-ssl3")
-              (pop3-open-ssl-stream-1 name buffer host service "-ssl2"))))))
+  (as-binary-process
+   (or (pop3-open-ssl-stream-1 name buffer host service "-ssl3")
+       (pop3-open-ssl-stream-1 name buffer host service "-ssl2"))))
 
 (defun pop3-open-tls-stream (name buffer host service)
   "Open a TLSv1 connection for a service to a host.
@@ -266,15 +272,15 @@ Args are NAME BUFFER HOST SERVICE."
     (insert output)))
 
 (defun pop3-send-command (process command)
-    (set-buffer (process-buffer process))
-    (goto-char (point-max))
-;;    (if (= (aref command 0) ?P)
-;;     (insert "PASS <omitted>\r\n")
-;;      (insert command "\r\n"))
-    (setq pop3-read-point (point))
-    (goto-char (point-max))
-    (process-send-string process (concat command "\r\n"))
-    )
+  (set-buffer (process-buffer process))
+  (goto-char (point-max))
+;;  (if (= (aref command 0) ?P)
+;;      (insert "PASS <omitted>\r\n")
+;;    (insert command "\r\n"))
+  (setq pop3-read-point (point))
+  (goto-char (point-max))
+  (process-send-string process (concat command "\r\n"))
+  )
 
 (defun pop3-read-response (process &optional return)
   "Read the response from the server PROCESS.
@@ -358,18 +364,23 @@ If NOW, use that time instead."
                   (looking-at "\001\001\001\001\n") ; MMDF
                   (looking-at "BABYL OPTIONS:") ; Babyl
                   ))
-         (let ((from (mail-strip-quoted-names (mail-fetch-field "From")))
-               (date (split-string (or (mail-fetch-field "Date")
-                                       (pop3-make-date))
-                                   " "))
-               (From_))
+         (let* ((from (mail-strip-quoted-names (mail-fetch-field "From")))
+                (tdate (mail-fetch-field "Date"))
+                (date (split-string (or (and tdate
+                                             (not (string= "" tdate))
+                                             tdate)
+                                        (pop3-make-date))
+                                    " "))
+                (From_))
            ;; sample date formats I have seen
            ;; Date: Tue, 9 Jul 1996 09:04:21 -0400 (EDT)
            ;; Date: 08 Jul 1996 23:22:24 -0400
            ;; should be
            ;; Tue Jul 9 09:04:21 1996
            (setq date
-                 (cond ((string-match "[A-Z]" (nth 0 date))
+                 (cond ((not date)
+                        "Tue Jan 1 00:00:0 1900")
+                       ((string-match "[A-Z]" (nth 0 date))
                         (format "%s %s %s %s %s"
                                 (nth 0 date) (nth 2 date) (nth 1 date)
                                 (nth 4 date) (nth 3 date)))
@@ -492,7 +503,7 @@ If NOW, use that time instead."
   (pop3-send-command process (format "USER %s" user))
   (let ((response (pop3-read-response process t)))
     (if (not (and response (string-match "+OK" response)))
-       (error (format "USER %s not valid." user)))))
+       (error (format "USER %s not valid" user)))))
 
 (defun pop3-pass (process)
   "Send authentication information to the server."
@@ -501,28 +512,46 @@ If NOW, use that time instead."
     (if (not (and response (string-match "+OK" response)))
        (pop3-quit process))))
 
-(static-unless (and (fboundp 'md5) (subrp (symbol-function 'md5)))
-  (eval-and-compile
-    (require 'path-util)
-    (if (module-installed-p 'md5)
-       (progn
-         (autoload 'md5 "md5")
-         (fset 'pop3-md5 'md5))
-
-      (defvar pop3-md5-program "md5"
-       "*Program to encode its input in MD5.")
-
-      (defun pop3-md5 (string)
-       (with-temp-buffer
-         (insert string)
-         (call-process-region (point-min) (point-max)
-                              (or shell-file-name "/bin/sh")
-                              t (current-buffer) nil
-                              "-c" pop3-md5-program)
-         ;; The meaningful output is the first 32 characters.
-         ;; Don't return the newline that follows them!
-         (buffer-substring (point-min) (+ (point-min) 32))))
-      )))
+;; When this file is being compiled in the Gnus (not T-gnus) source
+;; tree, `md5' might have been defined in w3/md5.el, ./lpath.el or one
+;; of some other libraries and `md5' will accept only 3 arguments.  We
+;; will deceive the byte-compiler not to say warnings.
+(eval-and-compile
+  (if (fboundp 'eval-when)
+      ;; `eval-when' might not be provided when loading .el file.
+      (eval-when 'compile
+       (let ((def (assq 'md5 byte-compile-function-environment)))
+         (if def
+             (setcdr def '(lambda (object &optional start end
+                                          coding-system noerror)))
+           (setq byte-compile-function-environment
+                 (cons '(md5 . (lambda (object &optional start end
+                                               coding-system noerror)))
+                       byte-compile-function-environment)))))))
+
+;; Note that `pop3-md5' should never encode a given string to use for
+;; the apop authentication.
+(eval-and-compile
+  (if (fboundp 'md5)
+      (if (condition-case nil
+             (md5 "\
+Check whether the 4th argument CODING-SYSTEM is allowed"
+                  nil nil 'binary)
+           (error nil))
+         ;; Emacs 21 or XEmacs 21
+         ;; (md5 OBJECT &optional START END CODING-SYSTEM NOERROR)
+         (defun pop3-md5 (string)
+           (md5 string nil nil 'binary))
+       ;; The reason why the program reaches here:
+       ;; 1. XEmacs 20 is running and the built-in `md5' doesn't
+       ;;    allow the 4th argument.
+       ;; 2. `md5' has been defined by one of some lisp libraries.
+       ;; 3. This file is being compiled in the Gnus source tree,
+       ;;    and `md5' has been defined in lpath.el.
+       (defalias 'pop3-md5 'md5))
+    ;; The lisp function will be provided by FLIM or other libraries.
+    (autoload 'md5 "md5")
+    (defalias 'pop3-md5 'md5)))
 
 (defun pop3-apop (process user)
   "Send alternate authentication information to the server."
@@ -531,10 +560,7 @@ If NOW, use that time instead."
        (setq pass
              (pop3-read-passwd (format "Password for %s: " pop3-maildrop))))
     (if pass
-       (let ((hash (static-if (and (fboundp 'md5)
-                                   (subrp (symbol-function 'md5)))
-                       (md5 (concat pop3-timestamp pass))
-                     (pop3-md5 (concat pop3-timestamp pass)))))
+       (let ((hash (pop3-md5 (concat pop3-timestamp pass))))
          (pop3-send-command process (format "APOP %s %s" user hash))
          (let ((response (pop3-read-response process t)))
            (if (not (and response (string-match "+OK" response)))
@@ -620,7 +646,7 @@ where
   (if msgno
       (pop3-send-command process (format "UIDL %d" msgno))
     (pop3-send-command process "UIDL"))
-  
+
   (if (null (pop3-read-response process t))
       nil ;; UIDL is not supported on this server
     (let (pairs uidl)