diff options
Diffstat (limited to 'socket.c')
-rw-r--r-- | socket.c | 41 |
1 files changed, 41 insertions, 0 deletions
@@ -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; } |