for f in pop.[hc] ; do diff -c $f $f.WITH-APOP ; done
*** pop.c	Sun Mar 18 03:02:58 2007
--- pop.c.WITH-APOP	Thu Mar 15 14:41:46 2007
***************
*** 2,7 ****
--- 2,8 ----
     Copyright (C) 1991, 1993, 1996, 1997, 1999, 2001, 2002, 2003, 2004,
                   2005, 2006, 2007  Free Software Foundation, Inc.
     Written by Jonathan Kamens, jik@security.ov.com.
+    Thien-Thi Nguyen added APOP support.
  
  This file is part of GNU Emacs.
  
***************
*** 121,127 ****
  static int pop_getline __P((popserver, char **));
  static int sendline __P((popserver, char *));
  static int fullwrite __P((int, char *, int));
! static int getok __P((popserver));
  #if 0
  static int gettermination __P((popserver));
  #endif
--- 122,129 ----
  static int pop_getline __P((popserver, char **));
  static int sendline __P((popserver, char *));
  static int fullwrite __P((int, char *, int));
! static int actual_getok __P((popserver, int));
! #define getok(popserver)  actual_getok (popserver, 0)
  #if 0
  static int gettermination __P((popserver));
  #endif
***************
*** 294,302 ****
    server->buffer_size = GETLINE_MIN;
    server->in_multi = 0;
    server->trash_started = 0;
  
-   if (getok (server))
-     return (0);
  
    /*
     * I really shouldn't use the pop_error variable like this, but....
--- 296,356 ----
    server->buffer_size = GETLINE_MIN;
    server->in_multi = 0;
    server->trash_started = 0;
+   server->greeting_stamp = 0;
+ 
+   {
+     if (actual_getok (server, 1))
+       return (0);
+ 
+     /* Try APOP if the server seems to support it.  */
+     if (server->greeting_stamp)
+       {
+         int i;
+         unsigned char digest[16];
+         char *secret, *apop;
+ 
+         fprintf (stderr, "greeting: %s\n", server->greeting_stamp);
+ 
+         if (! (secret = malloc (strlen (server->greeting_stamp)
+                                 + strlen (password) + 1)))
+           {
+             strcpy (pop_error, "Out of memory in pop_open");
+             free (server->greeting_stamp);
+             return (0);
+           }
+         sprintf (secret, "%s%s", server->greeting_stamp, password);
+         free (server->greeting_stamp);
+         server->greeting_stamp = 0;
+ 
+         extern void *md5_buffer (const char *buffer, size_t len,
+                                  void *resblock);
+ 
+         md5_buffer (secret, strlen (secret), digest);
+         free (secret);
+ 
+         if (! (apop = malloc (5          /* "APOP " */
+                               + strlen (username)
+                               + 33      /* " DIGEST" */
+                               + 1)))
+           {
+             strcpy (pop_error, "Out of memory in pop_open");
+             free (server->greeting_stamp);
+             return (0);
+           }
+         sprintf (apop, "APOP %s ", username);
+         for (i = 0; i < 16; i++)
+           sprintf (apop + strlen (apop), "%02x", digest[i]);
+ 
+         {
+           int authp = (! sendline (server, apop) && ! getok (server));
+           free (apop);
+ 
+           if (authp)
+             return server;
+         }
+       }
+   }
  
  
    /*
     * I really shouldn't use the pop_error variable like this, but....
***************
*** 1066,1071 ****
--- 1120,1136 ----
  	}
      }
  #endif
+   {
+     char *env_pop_port = getenv ("POP_PORT");
+ 
+     if (env_pop_port)
+       {
+         if (pop_debug)
+           fprintf (stderr, "NOTE: POP port: %s\n", env_pop_port);
+         addr.sin_port = htons (atoi (env_pop_port));
+         found_port = 1;
+       }
+   }
    if (! found_port)
      {
        servent = getservbyname (service, "tcp");
***************
*** 1458,1489 ****
  }
  
  /*
!  * Procedure getok
   *
   * Purpose: Reads a line from the server.  If the return indicator is
   * 	positive, return with a zero exit status.  If not, return with
!  * 	a negative exit status.
   *
   * Arguments:
   * 	server	The server to read from.
   *
   * Returns: 0 for success, else for failure and puts error in pop_error.
   *
   * Side effects: On failure, may make the connection unusable.
   */
  static int
! getok (server)
       popserver server;
  {
    char *fromline;
  
!   if (pop_getline (server, &fromline) < 0)
      {
        return (-1);
      }
  
    if (! strncmp (fromline, "+OK", 3))
!     return (0);
    else if (! strncmp (fromline, "-ERR", 4))
      {
        strncpy (pop_error, fromline, ERROR_MAX);
--- 1523,1583 ----
  }
  
  /*
!  * Procedure actual_getok
   *
   * Purpose: Reads a line from the server.  If the return indicator is
   * 	positive, return with a zero exit status.  If not, return with
!  * 	a negative exit status.  Optionally, saves the greeting stamp.
   *
   * Arguments:
   * 	server	The server to read from.
+  * 	sgs_p	If 1, "save greeting stamp" (indicates APOP-support).
   *
   * Returns: 0 for success, else for failure and puts error in pop_error.
   *
   * Side effects: On failure, may make the connection unusable.
+  * 	Also, `server->greeting_stamp' may be modified.
   */
  static int
! actual_getok (server, sgs_p)
       popserver server;
+      int sgs_p;
  {
    char *fromline;
+   int len;
  
!   if ((len = pop_getline (server, &fromline)) < 0)
      {
        return (-1);
      }
  
    if (! strncmp (fromline, "+OK", 3))
!     {
!       if (sgs_p)
!         {
!           int i;
!           char *b = 0, *e = 0;          /* begin, end */
! 
!           for (i = 3; i < len; i++)
!             {
!               if (! b && '<' == fromline[i])
!                 b = fromline + i;
!               if (b && '>' == fromline[i])
!                 e = fromline + i + 1;
!             }
!           if (b && e)
!             {
!               server->greeting_stamp = malloc (1 + (e - b));
!               if (! server->greeting_stamp)
!                 {
!                   strcpy (pop_error, "Out of memory in getok");
!                   return (-1);
!                 }
!               strncpy (server->greeting_stamp, b, e - b);
!             }
!         }
!       return (0);
!     }
    else if (! strncmp (fromline, "-ERR", 4))
      {
        strncpy (pop_error, fromline, ERROR_MAX);
*** pop.h	Thu Mar 15 14:43:16 2007
--- pop.h.WITH-APOP	Thu Mar 15 14:42:40 2007
***************
*** 37,42 ****
--- 37,43 ----
    int buffer_size, buffer_index;
    int in_multi;
    int trash_started;
+   char *greeting_stamp;                 /* non-NULL => try APOP first */
  };
  
  typedef struct _popserver *popserver;

