diff options
author | Stef Walter <stef@memberwebs.com> | 2005-08-25 19:06:47 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2005-08-25 19:06:47 +0000 |
commit | a861a0200b526ec48a0eebc9abaededa04b72318 (patch) | |
tree | a023a6b182febf07b87f552c4056240ac6ee754c /common | |
parent | 9d2890bf108060d61081c2dc34962bd55978decc (diff) |
Support embedded nulls in email data.
Diffstat (limited to 'common')
-rw-r--r-- | common/compat.c | 71 | ||||
-rw-r--r-- | common/compat.h | 8 | ||||
-rw-r--r-- | 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 <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 */ |