]> Pileus Git - ~andy/fetchmail/blobdiff - pop3.c
Ready to ship.
[~andy/fetchmail] / pop3.c
diff --git a/pop3.c b/pop3.c
index cbe6ac0f0373edb7462c6e901a6db81cf55085eb..bf91bc9206c7dcbb1867b89202f993e06847ef6f 100644 (file)
--- a/pop3.c
+++ b/pop3.c
@@ -8,6 +8,7 @@
 
 #include  <stdio.h>
 #include  <string.h>
+#include  <ctype.h>
 #if defined(HAVE_UNISTD_H)
 #include <unistd.h>
 #endif
 #endif
  
 #include  "fetchmail.h"
+#include  "socket.h"
 
-#define PROTOCOL_ERROR {fputs("fetchmail: protocol error\n", stderr); return(PS_ERROR);}
+#define PROTOCOL_ERROR {error(0, 0, "protocol error"); return(PS_ERROR);}
+
+extern char *strstr(); /* needed on sysV68 R3V7.1. */
 
 static int last;
 
-int pop3_ok (sockfp, argbuf)
+int pop3_ok (FILE *sockfp, char *argbuf)
 /* parse command response */
-FILE *sockfp;
-char *argbuf;
 {
-  int ok;
-  char buf [POPBUFSIZE+1];
-  char *bufp;
-
-  if (fgets(buf, sizeof(buf), sockfp) != (char *)NULL) {
-    if (outlevel == O_VERBOSE)
-      fprintf(stderr,"%s",buf);
-
-    bufp = buf;
-    if (*bufp == '+' || *bufp == '-')
-      bufp++;
-    else
-      return(PS_PROTOCOL);
-
-    while (isalpha(*bufp))
-      bufp++;
-    *(bufp++) = '\0';
-
-    if (strcmp(buf,"+OK") == 0)
-      ok = 0;
-    else if (strcmp(buf,"-ERR") == 0)
-      ok = PS_ERROR;
-    else
-      ok = PS_PROTOCOL;
+    int ok;
+    char buf [POPBUFSIZE+1];
+    char *bufp;
 
-    if (argbuf != NULL)
-      strcpy(argbuf,bufp);
-  }
-  else 
-    ok = PS_SOCKET;
+    if ((ok = gen_recv(sockfp, buf, sizeof(buf))) == 0)
+    {
+       bufp = buf;
+       if (*bufp == '+' || *bufp == '-')
+           bufp++;
+       else
+           return(PS_PROTOCOL);
+
+       while (isalpha(*bufp))
+           bufp++;
+       *(bufp++) = '\0';
+
+       if (strcmp(buf,"+OK") == 0)
+           ok = 0;
+       else if (strcmp(buf,"-ERR") == 0)
+           ok = PS_ERROR;
+       else
+           ok = PS_PROTOCOL;
+
+       if (argbuf != NULL)
+           strcpy(argbuf,bufp);
+    }
 
-  return(ok);
+    return(ok);
 }
 
-int pop3_getauth(sockfp, ctl, greeting)
+int pop3_getauth(FILE *sockfp, struct query *ctl, char *greeting)
 /* apply for connection authorization */
-FILE *sockfp;
-struct query *ctl;
-char *greeting;
 {
     /* build MD5 digest from greeting timestamp + password */
-    if (ctl->protocol == P_APOP) 
+    if (ctl->server.protocol == P_APOP) 
     {
        char *start,*end;
        char *msg;
@@ -76,21 +71,22 @@ char *greeting;
        for (start = greeting;  *start != 0 && *start != '<';  start++)
            continue;
        if (*start == 0) {
-           fprintf(stderr,"Required APOP timestamp not found in greeting\n");
+           error(0, 0, "Required APOP timestamp not found in greeting");
            return(PS_AUTHFAIL);
        }
 
        /* find end of timestamp */
        for (end = start;  *end != 0  && *end != '>';  end++)
            continue;
-       if (*end == 0 || (end - start - 1) == 1) {
-           fprintf(stderr,"Timestamp syntax error in greeting\n");
+       if (*end == 0 || end == start + 1) {
+           error(0, 0, "Timestamp syntax error in greeting");
            return(PS_AUTHFAIL);
        }
+       else
+           *++end = '\0';
 
        /* copy timestamp and password into digestion buffer */
-       msg = (char *)xmalloc((end-start-1) + strlen(ctl->password) + 1);
-       *(++end) = 0;
+       msg = (char *)xmalloc((end-start+1) + strlen(ctl->password) + 1);
        strcpy(msg,start);
        strcat(msg,ctl->password);
 
@@ -98,9 +94,9 @@ char *greeting;
        free(msg);
     }
 
-    switch (ctl->protocol) {
+    switch (ctl->server.protocol) {
     case P_POP3:
-       if ((gen_transact(sockfp,"USER %s", ctl->remotename)) != 0)
+       if ((gen_transact(sockfp, "USER %s", ctl->remotename)) != 0)
            PROTOCOL_ERROR
 
        if ((gen_transact(sockfp, "PASS %s", ctl->password)) != 0)
@@ -113,19 +109,24 @@ char *greeting;
            PROTOCOL_ERROR
        break;
 
+    case P_RPOP:
+       if ((gen_transact(sockfp,"USER %s", ctl->remotename)) != 0)
+           PROTOCOL_ERROR
+
+       if ((gen_transact(sockfp, "RPOP %s", ctl->password)) != 0)
+           PROTOCOL_ERROR
+       break;
+
     default:
-       fprintf(stderr,"Undefined protocol request in POP3_auth\n");
+       error(0, 0, "Undefined protocol request in POP3_auth");
     }
 
     /* we're approved */
     return(0);
 }
 
-static int pop3_getrange(sockfp, ctl, countp, newp)
+static int pop3_getrange(FILE *sockfp, struct query *ctl, int*countp, int*newp)
 /* get range of messages to be fetched */
-FILE *sockfp;
-struct query *ctl;
-int *countp, *newp;
 {
     int ok;
     char buf [POPBUFSIZE+1];
@@ -170,19 +171,18 @@ int *countp, *newp;
                int     num;
 
                *newp = 0;
-               while (fgets(buf, sizeof(buf), sockfp) != (char *)NULL)
+               while ((ok = gen_recv(sockfp, buf, sizeof(buf))) == 0)
                {
-                   if (outlevel == O_VERBOSE)
-                       fprintf(stderr,"%s\n",buf);
                    if (buf[0] == '.')
                        break;
                    else if (sscanf(buf, "%d %s", &num, id) == 2)
                    {
-                       save_uid(&ctl->newsaved, num, id);
-                       if (!uid_in_list(&ctl->oldsaved, id))
+                       save_str(&ctl->newsaved, num, id);
+
+                       /* note: ID comparison is caseblind */
+                       if (!str_in_list(&ctl->oldsaved, id))
                            (*newp)++;
                    }
-                   fseek(sockfp, 0L, SEEK_CUR);
                }
            }
        }
@@ -191,11 +191,8 @@ int *countp, *newp;
     return(0);
 }
 
-static int pop3_getsizes(sockfp, count, sizes)
+static int pop3_getsizes(FILE *sockfp, int count, int *sizes)
 /* capture the sizes of all messages */
-FILE   *sockfp;
-int    count;
-int    *sizes;
 {
     int        ok;
 
@@ -205,12 +202,10 @@ int       *sizes;
     {
        char buf [POPBUFSIZE+1];
 
-       while (fgets(buf, sizeof(buf), sockfp) != (char *)NULL)
+       while ((ok = gen_recv(sockfp, buf, sizeof(buf))) == 0)
        {
            int num, size;
 
-           if (outlevel == O_VERBOSE)
-               fprintf(stderr,"%s\n",buf);
            if (buf[0] == '.')
                break;
            else if (sscanf(buf, "%d %d", &num, &size) == 2)
@@ -218,30 +213,24 @@ int       *sizes;
            else
                sizes[num - 1] = -1;
        }
-       fseek(sockfp, 0L, SEEK_CUR);
 
-       return(0);
+       return(ok);
     }
 }
 
-static int pop3_is_old(sockfp, ctl, num)
+static int pop3_is_old(FILE *sockfp, struct query *ctl, int num)
 /* is the given message old? */
-FILE *sockfp;
-struct query *ctl;
-int num;
 {
     if (!ctl->oldsaved)
        return (num <= last);
     else
-        return (uid_in_list(&ctl->oldsaved,
-                           uid_find (&ctl->newsaved, num)));
+       /* note: ID comparison is caseblind */
+        return (str_in_list(&ctl->oldsaved,
+                           str_find (&ctl->newsaved, num)));
 }
 
-static int pop3_fetch(sockfp, number, lenp)
+static int pop3_fetch(FILE *sockfp, struct query *ctl, int number, int *lenp)
 /* request nth message */
-FILE *sockfp;
-int number;
-int *lenp; 
 {
     int ok;
     char buf [POPBUFSIZE+1], *cp;
@@ -254,18 +243,15 @@ int *lenp;
        *lenp = 0;
     else
     {
-       while (isdigit(*--cp))
+       while (--cp >= buf && isdigit(*cp))
            continue;
        *lenp = atoi(++cp);
     }
     return(0);
 }
 
-static int pop3_delete(sockfp, ctl, number)
+static int pop3_delete(FILE *sockfp, struct query *ctl, int number)
 /* delete a given message */
-FILE *sockfp;
-struct query *ctl;
-int number;
 {
     return(gen_transact(sockfp, "DELE %d", number));
 }
@@ -284,18 +270,17 @@ const static struct method pop3 =
     pop3_fetch,                /* request given message */
     NULL,              /* no message trailer */
     pop3_delete,       /* how to delete a message */
-    NULL,              /* no POP3 expunge command */
     "QUIT",            /* the POP3 exit command */
 };
 
-int doPOP3 (ctl)
+int doPOP3 (struct query *ctl)
 /* retrieve messages using POP3 */
-struct query *ctl;
 {
-    if (ctl->mailbox[0]) {
+    if (ctl->mailbox) {
        fprintf(stderr,"Option --remote is not supported with POP3\n");
        return(PS_SYNTAX);
     }
+    peek_capable = FALSE;
     return(do_protocol(ctl, &pop3));
 }