diff --git a/CHANGES b/CHANGES index 5271bd0cd..74175abae 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,10 @@ Changelog +Daniel (28 January 2007) +- David McCreedy fixed the Curl command line tool for HTTP on non-ASCII + platforms. + Daniel (25 January 2007) - Added the --libcurl [file] option to curl. Append this option to any ordinary curl command line, and you will get a libcurl-using source code diff --git a/TODO-RELEASE b/TODO-RELEASE index acda7fdf8..80f499a07 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -1,16 +1,4 @@ To get fixed in 7.16.1 (planned release: January 2007) ====================== -69 - Jeff Pohlmeyer's curl_multi_socket crashing case. Recipe and instructions - here: http://curl.haxx.se/mail/lib-2007-01/0022.html - -78 - HTTP Pipelining, NULL content - http://curl.haxx.se/bug/view.cgi?id=1631566 - -80 - Steffen Rumler's Race Condition in Curl_proxyCONNECT: - http://curl.haxx.se/mail/lib-2007-01/0045.html - -81 - Kumar Swamy Bhatt's problem in ftp/ssl "LIST" operation: - http://curl.haxx.se/mail/lib-2007-01/0103.html - 82 - diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS index 2ccabb82f..90faf77fd 100644 --- a/docs/KNOWN_BUGS +++ b/docs/KNOWN_BUGS @@ -3,6 +3,18 @@ join in and help us correct one or more of these! Also be sure to check the changelog of the current development status, as one or more of these problems may have been fixed since this was written! +41. Jeff Pohlmeyer's curl_multi_socket crashing case. Recipe and instructions + here: http://curl.haxx.se/mail/lib-2007-01/0022.html + +40. HTTP Pipelining, NULL content + http://curl.haxx.se/bug/view.cgi?id=1631566 + +39. Steffen Rumler's Race Condition in Curl_proxyCONNECT: + http://curl.haxx.se/mail/lib-2007-01/0045.html + +38. Kumar Swamy Bhatt's problem in ftp/ssl "LIST" operation: + http://curl.haxx.se/mail/lib-2007-01/0103.html + 37. Having more than one connection to the same host when doing NTLM authentication (with performs multiple "passes" and authenticates a connection rather than a HTTP request), and particularly when using the diff --git a/src/main.c b/src/main.c index d43228b6a..e35050025 100644 --- a/src/main.c +++ b/src/main.c @@ -203,9 +203,112 @@ typedef enum { #define struct_stat struct stat #endif -#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) +#ifdef CURL_DOES_CONVERSIONS +#ifdef HAVE_ICONV iconv_t inbound_cd = (iconv_t)-1; -#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ +iconv_t outbound_cd = (iconv_t)-1; + +/* + * convert_to_network() is an internal function to convert + * from the host encoding to ASCII on non-ASCII platforms. + */ +static CURLcode +convert_to_network(char *buffer, size_t length) +{ + CURLcode rc; + + /* translate from the host encoding to the network encoding */ + char *input_ptr, *output_ptr; + size_t in_bytes, out_bytes; + + /* open an iconv conversion descriptor if necessary */ + if(outbound_cd == (iconv_t)-1) { + outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, + CURL_ICONV_CODESET_OF_HOST); + if(outbound_cd == (iconv_t)-1) { + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(outbound_cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if ((rc == -1) || (in_bytes != 0)) { + return CURLE_CONV_FAILED; + } + + return CURLE_OK; +} + +/* + * convert_from_network() is an internal function + * for performing ASCII conversions on non-ASCII platforms. + */ +static CURLcode +convert_from_network(char *buffer, size_t length) +{ + CURLcode rc; + + /* translate from the network encoding to the host encoding */ + char *input_ptr, *output_ptr; + size_t in_bytes, out_bytes; + + /* open an iconv conversion descriptor if necessary */ + if(inbound_cd == (iconv_t)-1) { + inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, + CURL_ICONV_CODESET_OF_NETWORK); + if(inbound_cd == (iconv_t)-1) { + return CURLE_CONV_FAILED; + } + } + /* call iconv */ + input_ptr = output_ptr = buffer; + in_bytes = out_bytes = length; + rc = iconv(inbound_cd, &input_ptr, &in_bytes, + &output_ptr, &out_bytes); + if ((rc == -1) || (in_bytes != 0)) { + return CURLE_CONV_FAILED; + } + + return CURLE_OK; +} +#endif /* HAVE_ICONV */ + +static +char convert_char(curl_infotype infotype, char this_char) +{ +/* determine how this specific character should be displayed */ + switch(infotype) { + case CURLINFO_DATA_IN: + case CURLINFO_DATA_OUT: + case CURLINFO_SSL_DATA_IN: + case CURLINFO_SSL_DATA_OUT: + /* data, treat as ASCII */ + if ((this_char >= 0x20) && (this_char < 0x7f)) { + /* printable ASCII hex value: convert to host encoding */ + convert_from_network(&this_char, 1); + } + else { + /* non-printable ASCII, use a replacement character */ + return UNPRINTABLE_CHAR; + } + /* fall through to default */ + default: + /* treat as host encoding */ + if (ISPRINT(this_char) + && (this_char != '\t') + && (this_char != '\r') + && (this_char != '\n')) { + /* printable characters excluding tabs and line end characters */ + return this_char; + } + break; + } + /* non-printable, use a replacement character */ + return UNPRINTABLE_CHAR; +} +#endif /* CURL_DOES_CONVERSIONS */ #ifdef WIN32 /* @@ -434,9 +537,10 @@ static void main_free(void) curl_global_cleanup(); #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) /* close iconv conversion descriptor */ - if (inbound_cd != (iconv_t)-1) { - iconv_close(inbound_cd); - } + if(inbound_cd != (iconv_t)-1) + iconv_close(inbound_cd); + if(outbound_cd != (iconv_t)-1) + iconv_close(outbound_cd); #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ } @@ -1088,6 +1192,9 @@ static int formparse(struct Configurable *config, } } else { +#ifdef CURL_DOES_CONVERSIONS + convert_to_network(contp, strlen(contp)); +#endif info[i].option = CURLFORM_COPYCONTENTS; info[i].value = contp; i++; @@ -1909,6 +2016,12 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ else { GetStr(&postdata, nextarg); } + +#ifdef CURL_DOES_CONVERSIONS + if(subletter != 'b') { /* NOT forced binary, convert to ASCII */ + convert_to_network(postdata, strlen(postdata)); + } +#endif if(config->postfields) { /* we already have a string, we append this one @@ -1918,7 +2031,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ config->postfields=malloc(newlen); if(!config->postfields) return PARAM_NO_MEM; - snprintf(config->postfields, newlen, "%s&%s", oldpost, postdata); + /* use ASCII value 0x26 for '&' to accommodate non-ASCII platforms */ + snprintf(config->postfields, newlen, "%s\x26%s", oldpost, postdata); free(oldpost); free(postdata); } @@ -2832,74 +2946,6 @@ void progressbarinit(struct ProgressData *bar, bar->out = config->errors; } -#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) -/* - * convert_from_network() is an internal function - * for performing ASCII conversions on non-ASCII platforms. - */ -CURLcode -convert_from_network(char *buffer, size_t length) -{ - CURLcode rc; - - /* translate from the network encoding to the host encoding */ - char *input_ptr, *output_ptr; - size_t in_bytes, out_bytes; - - /* open an iconv conversion descriptor if necessary */ - if(inbound_cd == (iconv_t)-1) { - inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, - CURL_ICONV_CODESET_OF_NETWORK); - if(inbound_cd == (iconv_t)-1) { - return CURLE_CONV_FAILED; - } - } - /* call iconv */ - input_ptr = output_ptr = buffer; - in_bytes = out_bytes = length; - rc = iconv(inbound_cd, &input_ptr, &in_bytes, - &output_ptr, &out_bytes); - if ((rc == -1) || (in_bytes != 0)) { - return CURLE_CONV_FAILED; - } - - return CURLE_OK; -} - -static -char convert_char(curl_infotype infotype, char this_char) -{ -/* determine how this specific character should be displayed */ - switch(infotype) { - case CURLINFO_DATA_IN: - case CURLINFO_DATA_OUT: - case CURLINFO_SSL_DATA_IN: - case CURLINFO_SSL_DATA_OUT: - /* data, treat as ASCII */ - if ((this_char >= 0x20) && (this_char < 0x7f)) { - /* printable ASCII hex value: convert to host encoding */ - convert_from_network(&this_char, 1); - } - else { - /* non-printable ASCII, use a replacement character */ - return UNPRINTABLE_CHAR; - } - /* fall through to default */ - default: - /* treat as host encoding */ - if (ISPRINT(this_char) - && (this_char != '\t') - && (this_char != '\r') - && (this_char != '\n')) { - /* printable characters excluding tabs and line end characters */ - return this_char; - } - break; - } - /* non-printable, use a replacement character */ - return UNPRINTABLE_CHAR; -} -#endif /* CURL_DOES_CONVERSIONS */ static void dump(char *timebuf, const char *text, @@ -2937,14 +2983,20 @@ void dump(char *timebuf, const char *text, i+=(c+2-width); break; } -#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) +#ifdef CURL_DOES_CONVERSIONS + /* repeat the 0D0A check above but use the host encoding for CRLF */ + if ((tracetype == TRACE_ASCII) && + (i+c+1 < size) && ptr[i+c]=='\r' && ptr[i+c+1]=='\n') { + i+=(c+2-width); + break; + } /* convert to host encoding and print this character */ fprintf(stream, "%c", convert_char(infotype, ptr[i+c])); #else (void)infotype; fprintf(stream, "%c", (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:UNPRINTABLE_CHAR); -#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ +#endif /* CURL_DOES_CONVERSIONS */ /* check again for 0D0A, to avoid an extra \n if it's at width */ if ((tracetype == TRACE_ASCII) && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) { @@ -3066,6 +3118,27 @@ int my_trace(CURL *handle, curl_infotype type, return 0; } +#ifdef CURL_DOES_CONVERSIONS + /* Special processing is needed for CURLINFO_HEADER_OUT blocks + * if they contain both headers and data (separated by CRLFCRLF). + * We dump the header text and then switch type to CURLINFO_DATA_OUT. + */ + if((type == CURLINFO_HEADER_OUT) && (size > 4)) { + int i; + for(i = 0; i < size - 4; i++) { + if(memcmp(&data[i], "\r\n\r\n", 4) == 0) { + /* dump everthing through the CRLFCRLF as a sent header */ + text = "=> Send header"; + dump(timebuf, text, output, data, i+4, config->tracetype, type); + data += i + 3; + size -= i + 4; + type = CURLINFO_DATA_OUT; + data += 1; + break; + } + } + } +#endif /* CURL_DOES_CONVERSIONS */ switch (type) { case CURLINFO_TEXT: