#include "config.h"
#include <stdio.h>
#include <string.h>
+#include <ctype.h> /* isspace() */
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif /* HAVE_MEMORY_H */
for (remaining = fetchlen; remaining > 0 || protocol->delimited; remaining -= linelen)
{
char *line;
+ int overlong = FALSE;
line = xmalloc(sizeof(buf));
linelen = 0;
linelen += n;
msgblk.msglen += n;
+ /*
+ * Try to gracefully handle the case, where the length of a
+ * line exceeds MSGBUFSIZE.
+ */
+ if ( n && buf[n-1] != '\n' ) {
+ unsigned int llen = strlen(line);
+ overlong = TRUE;
+ line = realloc(line, llen + n + 1);
+ strcpy(line + llen, buf);
+ ch = ' '; /* So the next iteration starts */
+ continue;
+ }
+
/* lines may not be properly CRLF terminated; fix this for qmail */
if (ctl->forcecr)
{
}
}
- /*
- * Decode MIME encoded headers. We MUST do this before
- * looking at the Content-Type / Content-Transfer-Encoding
- * headers (RFC 2046).
- */
- if (ctl->mimedecode)
- UnMimeHeader(buf);
-
- line = (char *) realloc(line, strlen(line) + strlen(buf) +1);
+ /*
+ * Decode MIME encoded headers. We MUST do this before
+ * looking at the Content-Type / Content-Transfer-Encoding
+ * headers (RFC 2046).
+ */
+ if ( ctl->mimedecode && overlong ) {
+ /*
+ * If we received an overlong line, we have to decode the
+ * whole line at once.
+ */
+ line = (char *) realloc(line, strlen(line) + strlen(buf) +1);
+ strcat(line, buf);
+ UnMimeHeader(line);
+ }
+ else {
+ if ( ctl->mimedecode )
+ UnMimeHeader(buf);
- strcat(line, buf);
+ line = (char *) realloc(line, strlen(line) + strlen(buf) +1);
+ strcat(line, buf);
+ }
/* check for end of headers */
if (EMPTYLINE(line))
*/
if (protocol->delimited && line[0] == '.' && EMPTYLINE(line+1))
{
- free(line);
has_nuls = (linelen != strlen(line));
+ free(line);
goto process_headers;
}
line,
strlen(ctl->server.envelope)))
{
- if (skipcount++ != ctl->server.envskip)
+ if (skipcount++ < ctl->server.envskip)
continue;
env_offs = (line - msgblk.headers);
}
}
else if (!received_for && !strncasecmp("Received:", line, 9))
{
- if (skipcount++ != ctl->server.envskip)
+ if (skipcount++ < ctl->server.envskip)
continue;
received_for = parse_received(ctl, line);
}
{
/* utter any per-message Received information we need here */
if (ctl->server.trueaddr) {
- sprintf(buf, "Received: from %s [%u.%u.%u.%u]\r\n",
+#ifdef HAVE_SNPRINTF
+ snprintf(buf, sizeof(buf),
+#else
+ sprintf(buf,
+#endif /* HAVE_SNPRINTF */
+ "Received: from %s [%u.%u.%u.%u]\r\n",
ctl->server.truename,
(unsigned char)ctl->server.trueaddr[0],
(unsigned char)ctl->server.trueaddr[1],
(unsigned char)ctl->server.trueaddr[2],
(unsigned char)ctl->server.trueaddr[3]);
} else {
- sprintf(buf, "Received: from %s\r\n", ctl->server.truename);
+#ifdef HAVE_SNPRINTF
+ snprintf(buf, sizeof(buf),
+#else
+ sprintf(buf,
+#endif /* HAVE_SNPRINTF */
+ "Received: from %s\r\n", ctl->server.truename);
}
n = stuffline(ctl, buf);
if (n != -1)
* This header is technically invalid under RFC822.
* POP3, IMAP, etc. are not legal mail-parameter values.
*/
- sprintf(buf, "\tby %s with %s (fetchmail-%s)",
+#ifdef HAVE_SNPRINTF
+ snprintf(buf, sizeof(buf),
+#else
+ sprintf(buf,
+#endif /* HAVE_SNPRINTF */
+ "\tby %s with %s (fetchmail-%s",
fetchmailhost,
protocol->name,
VERSION);
ctl->server.pollname,
ctl->remotename);
}
- strcat(buf, "\r\n");
+#ifdef HAVE_SNPRINTF
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), ")\r\n");
+#else
+ strcat(buf, ")\r\n");
+#endif /* HAVE_SNPRINTF */
n = stuffline(ctl, buf);
if (n != -1)
{
buf[0] = '\t';
if (good_addresses == 0)
{
- sprintf(buf+1,
+#ifdef HAVE_SNPRINTF
+ snprintf(buf+1, sizeof(buf)-1,
+#else
+ sprintf(buf+1,
+#endif /* HAVE_SNPRINTF */
"for %s@%s (by default); ",
user, ctl->destaddr);
}
if (idp->val.status.mark == XMIT_ACCEPT)
break; /* only report first address */
if (strchr(idp->id, '@'))
- sprintf(buf+1, "for %s", idp->id);
+#ifdef HAVE_SNPRINTF
+ snprintf(buf+1, sizeof(buf)-1,
+#else
+ sprintf(buf+1,
+#endif /* HAVE_SNPRINTF */
+ "for %s", idp->id);
else
/*
* This could be a bit misleading, as destaddr is
* the forwarding host rather than the actual
* destination. Most of the time they coincide.
*/
- sprintf(buf+1, "for %s@%s", idp->id, ctl->destaddr);
+#ifdef HAVE_SNPRINTF
+ snprintf(buf+1, sizeof(buf)-1,
+#else
+ sprintf(buf+1,
+#endif /* HAVE_SNPRINTF */
+ "for %s@%s", idp->id, ctl->destaddr);
sprintf(buf+strlen(buf), " (%s); ",
MULTIDROP(ctl) ? "multi-drop" : "single-drop");
}
else
buf[1] = '\0';
+#ifdef HAVE_SNPRINTF
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s\r\n",
+ rfc822timestamp());
+#else
strcat(buf, rfc822timestamp());
strcat(buf, "\r\n");
+#endif /* HAVE_SNPRINTF */
n = stuffline(ctl, buf);
}
}
#endif
va_end(ap);
+#ifdef HAVE_SNPRINTF
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "\r\n");
+#else
strcat(buf, "\r\n");
+#endif /* HAVE_SNPRINTF */
SockWrite(sock, buf, strlen(buf));
if (outlevel >= O_MONITOR)
#endif
va_end(ap);
+#ifdef HAVE_SNPRINTF
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "\r\n");
+#else
strcat(buf, "\r\n");
+#endif /* HAVE_SNPRINTF */
SockWrite(sock, buf, strlen(buf));
if (outlevel >= O_MONITOR)