diff options
-rw-r--r-- | http.c | 38 | ||||
-rw-r--r-- | remote-curl.c | 2 | ||||
-rwxr-xr-x | t/lib-httpd/error.sh | 8 | ||||
-rwxr-xr-x | t/t5550-http-fetch-dumb.sh | 5 |
4 files changed, 48 insertions, 5 deletions
@@ -906,6 +906,35 @@ static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf) return ret; } +/* + * Extract a normalized version of the content type, with any + * spaces suppressed, all letters lowercased, and no trailing ";" + * or parameters. + * + * Note that we will silently remove even invalid whitespace. For + * example, "text / plain" is specifically forbidden by RFC 2616, + * but "text/plain" is the only reasonable output, and this keeps + * our code simple. + * + * Example: + * "TEXT/PLAIN; charset=utf-8" -> "text/plain" + * "text / plain" -> "text/plain" + */ +static void extract_content_type(struct strbuf *raw, struct strbuf *type) +{ + const char *p; + + strbuf_reset(type); + strbuf_grow(type, raw->len); + for (p = raw->buf; *p; p++) { + if (isspace(*p)) + continue; + if (*p == ';') + break; + strbuf_addch(type, tolower(*p)); + } +} + /* http_request() targets */ #define HTTP_REQUEST_STRBUF 0 #define HTTP_REQUEST_FILE 1 @@ -957,9 +986,12 @@ static int http_request(const char *url, ret = run_one_slot(slot, &results); - if (options && options->content_type) - curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE, - options->content_type); + if (options && options->content_type) { + struct strbuf raw = STRBUF_INIT; + curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE, &raw); + extract_content_type(&raw, options->content_type); + strbuf_release(&raw); + } if (options && options->effective_url) curlinfo_strbuf(slot->curl, CURLINFO_EFFECTIVE_URL, diff --git a/remote-curl.c b/remote-curl.c index 52c2d96ce6..a5ab977306 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -205,7 +205,7 @@ static int show_http_message(struct strbuf *type, struct strbuf *msg) * TODO should handle "; charset=XXX", and re-encode into * logoutputencoding */ - if (strcasecmp(type->buf, "text/plain")) + if (strcmp(type->buf, "text/plain")) return -1; strbuf_trim(msg); diff --git a/t/lib-httpd/error.sh b/t/lib-httpd/error.sh index 786f2816bb..23cec97cc3 100755 --- a/t/lib-httpd/error.sh +++ b/t/lib-httpd/error.sh @@ -3,6 +3,7 @@ printf "Status: 500 Intentional Breakage\n" printf "Content-Type: " +charset=iso-8859-1 case "$PATH_INFO" in *html*) printf "text/html" @@ -10,8 +11,13 @@ case "$PATH_INFO" in *text*) printf "text/plain" ;; +*charset*) + printf "text/plain; charset=utf-8" + charset=utf-8 + ;; esac printf "\n" printf "\n" -printf "this is the error message\n" +printf "this is the error message\n" | +iconv -f us-ascii -t $charset diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 13defd3886..b35b2610e3 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -181,5 +181,10 @@ test_expect_success 'git client does not show html errors' ' ! grep "this is the error message" stderr ' +test_expect_success 'git client shows text/plain with a charset' ' + test_must_fail git clone "$HTTPD_URL/error/charset" 2>stderr && + grep "this is the error message" stderr +' + stop_httpd test_done |