aboutsummaryrefslogtreecommitdiffstats
path: root/socket.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2003-07-17 15:19:56 +0000
committerEric S. Raymond <esr@thyrsus.com>2003-07-17 15:19:56 +0000
commit736db44524864225b719eda2262cd4b2a940304b (patch)
tree45135b7d62c42e497b90b06bb7d4c09e29997ee7 /socket.c
parent7d1fc7b9e3f5fba4c1f0d09f841a08ca94dd5e8f (diff)
downloadfetchmail-736db44524864225b719eda2262cd4b2a940304b.tar.gz
fetchmail-736db44524864225b719eda2262cd4b2a940304b.tar.bz2
fetchmail-736db44524864225b719eda2262cd4b2a940304b.zip
Yet another round of fixes.
svn path=/trunk/; revision=3819
Diffstat (limited to 'socket.c')
-rw-r--r--socket.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/socket.c b/socket.c
index 47f074dd..5f295a04 100644
--- a/socket.c
+++ b/socket.c
@@ -540,6 +540,7 @@ int SockRead(int sock, char *buf, int len)
{
char *newline, *bp = buf;
int n;
+ int maxavailable = 0;
#ifdef SSL_ENABLE
SSL *ssl;
#endif
@@ -579,6 +580,7 @@ int SockRead(int sock, char *buf, int len)
(void)SSL_get_error(ssl, n);
return(-1);
}
+ maxavailable = n;
if( 0 == n ) {
/* SSL_peek says no data... Does he mean no data
or did the connection blow up? If we got an error
@@ -622,6 +624,7 @@ int SockRead(int sock, char *buf, int len)
if ((n = fm_peek(sock, bp, len)) <= 0)
#endif
return (-1);
+ maxavailable = n;
if ((newline = memchr(bp, '\n', n)) != NULL)
n = newline - bp + 1;
#ifndef __BEOS__
@@ -634,6 +637,44 @@ int SockRead(int sock, char *buf, int len)
} while
(!newline && len);
*bp = '\0';
+ /* OK, very weird hack coming up here:
+ * When POP and IMAP servers send us a message, they're supposed to
+ * terminate the message with a line containing only a dot. To protect
+ * against lines in the real message that might contain only a dot,
+ * they're supposed to preface any line that starts with a dot with
+ * an additional dot, which will be removed on the client side. That
+ * process, called byte-stuffing (and unstuffing) is really not the
+ * concern of this low-level routine, ordinarily, but there are some
+ * POP servers (and maybe IMAP servers too, who knows) that fail to
+ * do the byte-stuffing, and this routine is the best place to try to
+ * identify and fix that fault.
+ *
+ * Since the DOT line is supposed to come only at the end of a
+ * message, the implication is that right after we see it, the server
+ * is supposed to go back to waiting for the next command. There
+ * isn't supposed to be any more data to read after we see the dot.
+ * THEREFORE, if we see more data to be read after something that
+ * looks like the dot line, then probably the server is failing to
+ * do byte-stuffing. In that case, we'll byte-pack it for them so
+ * that the higher-level routines see things as hunky-dorey.
+ * This is not a perfect test or fix by any means (it has an
+ * obvious race condition, for one thing), but it should at least
+ * reduce the nastiness that ensues when people don't know how
+ * to write POP servers.
+ */
+ if ((maxavailable > (bp-buf)) &&
+ ((((bp-buf) == 3) &&
+ (buf[0] == '.') &&
+ (buf[1] == '\r') &&
+ (buf[2] == '\n')) ||
+ (((bp-buf) == 2) &&
+ (buf[0] == '.') &&
+ (buf[1] == '\n')))) {
+
+ memmove(buf+1, buf, (bp-buf)+1);
+ buf[0] = '.';
+ bp++;
+ }
return bp - buf;
}