From 95152aec685c4d11de6cb25802303e4872d51b3e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 26 Apr 2006 07:40:37 +0000 Subject: David McCreedy brought line end conversions when doing FTP ASCII transfers. They are done on non-windows systems and translate CRLF to LF. --- lib/sendf.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 15 deletions(-) (limited to 'lib/sendf.c') diff --git a/lib/sendf.c b/lib/sendf.c index dda70c42b..a9cb58363 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -139,6 +139,89 @@ void curl_slist_free_all(struct curl_slist *list) } while (next); } +#ifdef CURL_DO_LINEEND_CONV +/* + * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF + * (\n), with special processing for CRLF sequences that are split between two + * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new + * size of the data is returned. + */ +static size_t convert_lineends(struct SessionHandle *data, + char *startPtr, size_t size) +{ + char *inPtr, *outPtr; + + /* sanity check */ + if ((startPtr == NULL) || (size < 1)) { + return(size); + } + + if (data->state.prev_block_had_trailing_cr == TRUE) { + /* The previous block of incoming data + had a trailing CR, which was turned into a LF. */ + if (*startPtr == '\n') { + /* This block of incoming data starts with the + previous block's LF so get rid of it */ + memcpy(startPtr, startPtr+1, size-1); + size--; + /* and it wasn't a bare CR but a CRLF conversion instead */ + data->state.crlf_conversions++; + } + data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */ + } + + /* find 1st CR, if any */ + inPtr = outPtr = memchr(startPtr, '\r', size); + if (inPtr) { + /* at least one CR, now look for CRLF */ + while (inPtr < (startPtr+size-1)) { + /* note that it's size-1, so we'll never look past the last byte */ + if (memcmp(inPtr, "\r\n", 2) == 0) { + /* CRLF found, bump past the CR and copy the NL */ + inPtr++; + *outPtr = *inPtr; + /* keep track of how many CRLFs we converted */ + data->state.crlf_conversions++; + } + else { + if (*inPtr == '\r') { + /* lone CR, move LF instead */ + *outPtr = '\n'; + } + else { + /* not a CRLF nor a CR, just copy whatever it is */ + *outPtr = *inPtr; + } + } + outPtr++; + inPtr++; + } /* end of while loop */ + + if (inPtr < startPtr+size) { + /* handle last byte */ + if (*inPtr == '\r') { + /* deal with a CR at the end of the buffer */ + *outPtr = '\n'; /* copy a NL instead */ + /* note that a CRLF might be split across two blocks */ + data->state.prev_block_had_trailing_cr = TRUE; + } + else { + /* copy last byte */ + *outPtr = *inPtr; + } + outPtr++; + inPtr++; + } + if (outPtr < startPtr+size) { + /* tidy up by null terminating the now shorter data */ + *outPtr = '\0'; + } + return(outPtr - startPtr); + } + return(size); +} +#endif /* CURL_DO_LINEEND_CONV */ + /* Curl_infof() is for info message along the way */ void Curl_infof(struct SessionHandle *data, const char *fmt, ...) @@ -294,36 +377,36 @@ CURLcode Curl_client_write(struct SessionHandle *data, if(0 == len) len = strlen(ptr); -#ifdef CURL_DOES_CONVERSIONS if(type & CLIENTWRITE_BODY) { if(data->ftp_in_ascii_mode) { +#ifdef CURL_DOES_CONVERSIONS /* convert from the network encoding */ size_t rc; rc = Curl_convert_from_network(data, ptr, len); /* Curl_convert_from_network calls failf if unsuccessful */ - if(rc != CURLE_OK) { - return(rc); - } + if(rc != CURLE_OK) + return rc; +#endif /* CURL_DOES_CONVERSIONS */ + +#ifdef CURL_DO_LINEEND_CONV + /* convert end-of-line markers */ + len = convert_lineends(data, ptr, len); +#endif /* CURL_DO_LINEEND_CONV */ } + /* If the previous block of data ended with CR and this block of data is + just a NL, then the length might be zero */ if (len) { wrote = data->set.fwrite(ptr, 1, len, data->set.out); - } else { - wrote = len; } - if(wrote != len) { - failf (data, "Failed writing body"); - return CURLE_WRITE_ERROR; + else { + wrote = len; } - } -#else - if(type & CLIENTWRITE_BODY) { - wrote = data->set.fwrite(ptr, 1, len, data->set.out); + if(wrote != len) { failf (data, "Failed writing body"); return CURLE_WRITE_ERROR; } } -#endif /* CURL_DOES_CONVERSIONS */ if((type & CLIENTWRITE_HEADER) && (data->set.fwrite_header || data->set.writeheader) ) { -- cgit v1.2.3