summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2005-08-25 19:06:47 +0000
committerStef Walter <stef@memberwebs.com>2005-08-25 19:06:47 +0000
commita861a0200b526ec48a0eebc9abaededa04b72318 (patch)
treea023a6b182febf07b87f552c4056240ac6ee754c
parent9d2890bf108060d61081c2dc34962bd55978decc (diff)
Support embedded nulls in email data.
-rw-r--r--common/compat.c71
-rw-r--r--common/compat.h8
-rw-r--r--common/smtppass.c18
3 files changed, 93 insertions, 4 deletions
diff --git a/common/compat.c b/common/compat.c
index 23a73d0..1f1736b 100644
--- a/common/compat.c
+++ b/common/compat.c
@@ -254,6 +254,77 @@ int daemon(int nochdir, int noclose)
#endif
+#ifndef HAVE_GETLINE
+
+ssize_t getline(char** lineptr, size_t* n, FILE* stream)
+{
+ return getdelim(lineptr, n, '\n', stream);
+}
+
+#endif
+
+#ifndef HAVE_GETDELIM
+
+ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* stream)
+{
+ size_t written = 0;
+ int allocated, ch;
+ char* p;
+
+ if(!n || !lineptr || !stream)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Track whether we allocated this or not */
+ allocated = !(*lineptr);
+
+ for(;;)
+ {
+ if(!*lineptr)
+ *n = 0;
+
+ /* Reallocate if we need more space */
+ if(written == *n - 1)
+ {
+ *n = *n ? 256 : *n * 2;
+ if(!(p = (char*)realloc(*lineptr, *n)))
+ {
+ if(allocated && *lineptr)
+ free(*lineptr);
+ errno = ENOMEM;
+ return -1;
+ }
+ *lineptr = p;
+ }
+
+ while(written < *n - 1)
+ {
+ ch = fgetc(stream);
+
+ if(ferror(stream))
+ {
+ if(allocated && *lineptr)
+ free(*lineptr);
+ return -1;
+ }
+
+ if(ch != EOF)
+ (*lineptr)[written++] = ch;
+
+ /* Done, null terminate, return */
+ if(ch == EOF || ch == delim)
+ {
+ (*lineptr)[written] = 0;
+ return written ? written : -1;
+ }
+ }
+ }
+}
+
+#endif
+
#ifndef HAVE_ERR_H
#include <stdlib.h>
diff --git a/common/compat.h b/common/compat.h
index b772f63..addf815 100644
--- a/common/compat.h
+++ b/common/compat.h
@@ -91,6 +91,14 @@ int setenv(const char* name, const char* value, int overwrite);
int daemon(int nochdir, int noclose);
#endif
+#ifndef HAVE_GETLINE
+ssize_t getline(char** lineptr, size_t* n, FILE* stream);
+#endif
+
+#ifndef HAVE_GETDELIM
+ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* stream);
+#endif
+
#ifdef HAVE_ERR_H
#include <err.h>
#else
diff --git a/common/smtppass.c b/common/smtppass.c
index 0ea9ca5..e94f95e 100644
--- a/common/smtppass.c
+++ b/common/smtppass.c
@@ -38,6 +38,8 @@
* Olivier Beyssac <ob@r14.freenix.org>
*/
+#define _GNU_SOURCE
+
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -1478,15 +1480,21 @@ int sp_done_data(spctx_t* ctx)
FILE* file = 0;
int had_header = 0;
int ret = 0;
- char line[SP_LINE_LENGTH];
+ char *line;
char header[MAX_HEADER_LENGTH];
- size_t header_len;
+ size_t header_len, line_len;
+ ssize_t rc;
ASSERT(ctx->cachename[0]); /* Must still be around */
ASSERT(!ctx->cachefile); /* File must be closed */
memset(header, 0, sizeof(header));
+ /* Alloc line buffer */
+ line_len = SP_LINE_LENGTH;
+ if((line = (char *)malloc(line_len)) == NULL)
+ RETURN(-1);
+
/* Open the file */
file = fopen(ctx->cachename, "r");
if(file == NULL)
@@ -1528,7 +1536,7 @@ int sp_done_data(spctx_t* ctx)
}
/* Transfer actual file data */
- while(fgets(line, SP_LINE_LENGTH, file) != NULL)
+ while((rc = getline(&line, &line_len, file)) != -1)
{
/*
* If the line is <CRLF>.<CRLF> we need to change it so that
@@ -1555,7 +1563,7 @@ int sp_done_data(spctx_t* ctx)
}
}
- if(spio_write_data_raw(ctx, &(ctx->server), line, strlen(line)) == -1)
+ if(spio_write_data_raw(ctx, &(ctx->server), line, rc) == -1)
RETURN(-1);
}
@@ -1580,6 +1588,8 @@ int sp_done_data(spctx_t* ctx)
cleanup:
+ if(line)
+ free(line);
if(file)
fclose(file); /* read-only so no error check */