From a861a0200b526ec48a0eebc9abaededa04b72318 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Thu, 25 Aug 2005 19:06:47 +0000 Subject: Support embedded nulls in email data. --- common/compat.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/compat.h | 8 +++++++ common/smtppass.c | 18 ++++++++++---- 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 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 #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 */ +#define _GNU_SOURCE + #include #include #include @@ -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 . 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 */ -- cgit v1.2.3