# HG changeset patch # User Karl Heuer # Date 881217896 0 # Node ID 7e1538a4570279dd643f555c395ee6d37ada4b32 # Parent 01d602ca5dcf66d9fdb092320d1e2c8cb6f2fe46 Allow messages retrieved from the POP server to contain embedded nulls. diff -r 01d602ca5dcf -r 7e1538a45702 lib-src/movemail.c --- a/lib-src/movemail.c Thu Dec 04 06:14:04 1997 +0000 +++ b/lib-src/movemail.c Thu Dec 04 06:44:56 1997 +0000 @@ -795,12 +795,12 @@ return (NOTOK); } - while (! (ret = pop_retrieve_next (server, &line))) + while ((ret = pop_retrieve_next (server, &line)) >= 0) { if (! line) break; - if (mbx_write (line, arg) != OK) + if (mbx_write (line, ret, arg) != OK) { strcpy (Errmsg, strerror (errno)); pop_close (server); @@ -826,8 +826,9 @@ && (a[4] == ' ')) int -mbx_write (line, mbf) +mbx_write (line, len, mbf) char *line; + int len; FILE *mbf; { #ifdef MOVEMAIL_QUOTE_POP_FROM_LINES @@ -844,7 +845,7 @@ line++; len--; } - if (fputs (line, mbf) == EOF) + if (fwrite (line, 1, len, mbf) != len) return (NOTOK); if (fputc (0x0a, mbf) == EOF) return (NOTOK); diff -r 01d602ca5dcf -r 7e1538a45702 lib-src/pop.c --- a/lib-src/pop.c Thu Dec 04 06:14:04 1997 +0000 +++ b/lib-src/pop.c Thu Dec 04 06:44:56 1997 +0000 @@ -130,16 +130,24 @@ #endif #endif -static int socket_connection (/* char *, int */); -static char *getline (/* popserver */); -static int sendline (/* popserver, char * */); -static int fullwrite (/* int, char *, int */); -static int getok (/* popserver */); +#ifndef _P +# ifdef __STDC__ +# define _P(a) a +# else +# define _P(a) () +# endif /* __STDC__ */ +#endif /* ! __P */ + +static int socket_connection _P((char *, int)); +static int getline _P((popserver, char **)); +static int sendline _P((popserver, char *)); +static int fullwrite _P((int, char *, int)); +static int getok _P((popserver)); #if 0 -static int gettermination (/* popserver */); +static int gettermination _P((popserver)); #endif -static void pop_trash (/* popserver */); -static char *find_crlf (/* char * */); +static void pop_trash _P((popserver)); +static char *find_crlf _P((char *, int)); #define ERROR_MAX 80 /* a pretty arbitrary size */ #define POP_PORT 110 @@ -373,7 +381,7 @@ return (-1); } - if (sendline (server, "STAT") || (! (fromserver = getline (server)))) + if (sendline (server, "STAT") || (getline (server, &fromserver) < 0)) return (-1); if (strncmp (fromserver, "+OK ", 4)) @@ -469,7 +477,7 @@ free ((char *) *sizes); return (-1); } - if (! (fromserver = getline (server))) + if (getline (server, &fromserver) < 0) { free ((char *) *IDs); free ((char *) *sizes); @@ -514,7 +522,7 @@ } for (i = 0; i < how_many; i++) { - if (pop_multi_next (server, &fromserver)) + if (pop_multi_next (server, &fromserver) <= 0) { free ((char *) *IDs); free ((char *) *sizes); @@ -533,7 +541,7 @@ } (*sizes)[i] = atoi (fromserver); } - if (pop_multi_next (server, &fromserver)) + if (pop_multi_next (server, &fromserver) < 0) { free ((char *) *IDs); free ((char *) *sizes); @@ -563,17 +571,21 @@ * markfrom * If true, then mark the string "From " at the beginning * of lines with '>'. + * msg_buf Output parameter to which a buffer containing the + * message is assigned. * - * Return value: A string pointing to the message, if successful, or - * null with pop_error set if not. + * Return value: The number of bytes in msg_buf, which may contain + * embedded nulls, not including its final null, or -1 on error + * with pop_error set. * * Side effects: May kill connection on error. */ -char * -pop_retrieve (server, message, markfrom) +int +pop_retrieve (server, message, markfrom, msg_buf) popserver server; int message; int markfrom; + char **msg_buf; { int *IDs, *sizes, bufsize, fromcount = 0, cp = 0; char *ptr, *fromserver; @@ -582,15 +594,15 @@ if (server->in_multi) { strcpy (pop_error, "In multi-line query in pop_retrieve"); - return (0); + return (-1); } if (pop_list (server, message, &IDs, &sizes)) - return (0); + return (-1); if (pop_retrieve_first (server, message, &fromserver)) { - return (0); + return (-1); } /* @@ -608,17 +620,16 @@ { strcpy (pop_error, "Out of memory in pop_retrieve"); pop_retrieve_flush (server); - return (0); + return (-1); } - while (! (ret = pop_retrieve_next (server, &fromserver))) + while ((ret = pop_retrieve_next (server, &fromserver)) >= 0) { - int linesize; - if (! fromserver) { ptr[cp] = '\0'; - return (ptr); + *msg_buf = ptr; + return (cp); } if (markfrom && fromserver[0] == 'F' && fromserver[1] == 'r' && fromserver[2] == 'o' && fromserver[3] == 'm' && @@ -632,23 +643,19 @@ { strcpy (pop_error, "Out of memory in pop_retrieve"); pop_retrieve_flush (server); - return (0); + return (-1); } fromcount = 0; } ptr[cp++] = '>'; } - linesize = strlen (fromserver); - bcopy (fromserver, &ptr[cp], linesize); - cp += linesize; + bcopy (fromserver, &ptr[cp], ret); + cp += ret; ptr[cp++] = '\n'; } - if (ret) - { - free (ptr); - return (0); - } + free (ptr); + return (-1); } int @@ -661,6 +668,14 @@ return (pop_multi_first (server, pop_error, response)); } +/* + Returns a negative number on error, 0 to indicate that the data has + all been read (i.e., the server has returned a "." termination + line), or a positive number indicating the number of bytes in the + returned buffer (which is null-terminated and may contain embedded + nulls, but the returned bytecount doesn't include the final null). + */ + int pop_retrieve_next (server, line) popserver server; @@ -686,6 +701,14 @@ return (pop_multi_first (server, pop_error, response)); } +/* + Returns a negative number on error, 0 to indicate that the data has + all been read (i.e., the server has returned a "." termination + line), or a positive number indicating the number of bytes in the + returned buffer (which is null-terminated and may contain embedded + nulls, but the returned bytecount doesn't include the final null). + */ + int pop_top_next (server, line) popserver server; @@ -714,7 +737,7 @@ return (-1); } - if (sendline (server, command) || (! (*response = getline (server)))) + if (sendline (server, command) || (getline (server, response) < 0)) { return (-1); } @@ -738,12 +761,22 @@ } } +/* + Read the next line of data from SERVER and place a pointer to it + into LINE. Return -1 on error, 0 if there are no more lines to read + (i.e., the server has returned a line containing only "."), or a + positive number indicating the number of bytes in the LINE buffer + (not including the final null). The data in that buffer may contain + embedded nulls, but does not contain the final CRLF. When returning + 0, LINE is set to null. */ + int pop_multi_next (server, line) popserver server; char **line; { char *fromserver; + int ret; if (! server->in_multi) { @@ -751,8 +784,7 @@ return (-1); } - fromserver = getline (server); - if (! fromserver) + if ((ret = getline (server, &fromserver)) < 0) { return (-1); } @@ -768,13 +800,13 @@ else { *line = fromserver + 1; - return (0); + return (ret - 1); } } else { *line = fromserver; - return (0); + return (ret); } } @@ -783,21 +815,20 @@ popserver server; { char *line; + int ret; if (! server->in_multi) { return (0); } - while (! pop_multi_next (server, &line)) + while ((ret = pop_multi_next (server, &line))) { - if (! line) - { - return (0); - } + if (ret < 0) + return (-1); } - return (-1); + return (0); } /* Function: pop_delete @@ -888,7 +919,7 @@ if (sendline (server, "LAST")) return (-1); - if (! (fromserver = getline (server))) + if (getline (server, &fromserver) < 0) return (-1); if (! strncmp (fromserver, "-ERR", 4)) @@ -1234,16 +1265,22 @@ * Arguments: * server The server from which to get the line of text. * - * Returns: A non-null pointer if successful, or a null pointer on any - * error, with an error message copied into pop_error. + * Returns: The number of characters in the line, which is returned in + * LINE, not including the final null. A return value of 0 + * indicates a blank line. A negative return value indicates an + * error (in which case the contents of LINE are undefined. In + * case of error, an error message is copied into pop_error. * * Notes: The line returned is overwritten with each call to getline. * * Side effects: Closes the connection on error. + * + * THE RETURNED LINE MAY CONTAIN EMBEDDED NULLS! */ -static char * -getline (server) +static int +getline (server, line) popserver server; + char **line; { #define GETLINE_ERROR "Error reading from server: " @@ -1252,7 +1289,8 @@ if (server->data) { - char *cp = find_crlf (server->buffer + server->buffer_index); + char *cp = find_crlf (server->buffer + server->buffer_index, + server->data); if (cp) { int found; @@ -1266,8 +1304,11 @@ server->buffer_index += data_used; if (pop_debug) + /* Embedded nulls will truncate this output prematurely, + but that's OK because it's just for debugging anyway. */ fprintf (stderr, "<<< %s\n", server->buffer + found); - return (server->buffer + found); + *line = server->buffer + found; + return (data_used - 2); } else { @@ -1302,7 +1343,7 @@ { strcpy (pop_error, "Out of memory in getline"); pop_trash (server); - return (0); + return (-1); } } ret = RECV (server->file, server->buffer + server->data, @@ -1313,13 +1354,13 @@ strncat (pop_error, strerror (errno), ERROR_MAX - sizeof (GETLINE_ERROR)); pop_trash (server); - return (0); + return (-1); } else if (ret == 0) { strcpy (pop_error, "Unexpected EOF from server in getline"); pop_trash (server); - return (0); + return (-1); } else { @@ -1327,7 +1368,8 @@ server->data += ret; server->buffer[server->data] = '\0'; - cp = find_crlf (server->buffer + search_offset); + cp = find_crlf (server->buffer + search_offset, + server->data - search_offset); if (cp) { int data_used = (cp + 2) - server->buffer; @@ -1337,7 +1379,8 @@ if (pop_debug) fprintf (stderr, "<<< %s\n", server->buffer); - return (server->buffer); + *line = server->buffer; + return (data_used - 2); } /* As above, the "- 1" here is to account for the fact that we may have read a CR without its accompanying LF. */ @@ -1442,7 +1485,7 @@ { char *fromline; - if (! (fromline = getline (server))) + if (getline (server, &fromline) < 0) { return (-1); } @@ -1481,8 +1524,7 @@ { char *fromserver; - fromserver = getline (server); - if (! fromserver) + if (getline (server, &fromserver) < 0) return (-1); if (strcmp (fromserver, ".")) @@ -1555,18 +1597,18 @@ #endif } -/* Return a pointer to the first CRLF in IN_STRING, - or 0 if it does not contain one. */ +/* Return a pointer to the first CRLF in IN_STRING, which can contain + embedded nulls and has LEN characters in it not including the final + null, or 0 if it does not contain one. */ static char * -find_crlf (in_string) +find_crlf (in_string, len) char *in_string; + int len; { - while (1) + while (len--) { - if (! *in_string) - return (0); - else if (*in_string == '\r') + if (*in_string == '\r') { if (*++in_string == '\n') return (in_string - 1); @@ -1574,7 +1616,7 @@ else in_string++; } - /* NOTREACHED */ + return (0); } #endif /* MAIL_USE_POP */ diff -r 01d602ca5dcf -r 7e1538a45702 lib-src/pop.h --- a/lib-src/pop.h Thu Dec 04 06:14:04 1997 +0000 +++ b/lib-src/pop.h Thu Dec 04 06:44:56 1997 +0000 @@ -59,7 +59,8 @@ extern int pop_stat _ARGS((popserver server, int *count, int *size)); extern int pop_list _ARGS((popserver server, int message, int **IDs, int **size)); -extern char *pop_retrieve _ARGS((popserver server, int message, int markfrom)); +extern int pop_retrieve _ARGS((popserver server, int message, int markfrom, + char **)); extern int pop_retrieve_first _ARGS((popserver server, int message, char **response)); extern int pop_retrieve_next _ARGS((popserver server, char **line));