diff options
author | Daniel Stenberg <daniel@haxx.se> | 2007-01-27 23:02:17 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2007-01-27 23:02:17 +0000 |
commit | fbc4407583528059923f48c5887d743e243326c3 (patch) | |
tree | 87528e1df90546657e2ad45aab623f52d9e04f44 /src | |
parent | a79e5d79250c6f431d8623748700b69d52683924 (diff) |
- David McCreedy fixed the Curl command line tool for HTTP on non-ASCII
platforms.
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 225 |
1 files changed, 149 insertions, 76 deletions
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: |