summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--http.c38
-rw-r--r--remote-curl.c2
-rwxr-xr-xt/lib-httpd/error.sh8
-rwxr-xr-xt/t5550-http-fetch-dumb.sh5
4 files changed, 48 insertions, 5 deletions
diff --git a/http.c b/http.c
index 94e1afdee7..6bfd0934b3 100644
--- a/http.c
+++ b/http.c
@@ -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