summaryrefslogtreecommitdiff
path: root/http.c
diff options
context:
space:
mode:
Diffstat (limited to 'http.c')
-rw-r--r--http.c106
1 files changed, 94 insertions, 12 deletions
diff --git a/http.c b/http.c
index 94e1afdee7..040f362a6a 100644
--- a/http.c
+++ b/http.c
@@ -1,3 +1,4 @@
+#include "git-compat-util.h"
#include "http.h"
#include "pack.h"
#include "sideband.h"
@@ -300,6 +301,9 @@ static CURL *get_curl_handle(void)
{
CURL *result = curl_easy_init();
+ if (!result)
+ die("curl_easy_init failed");
+
if (!curl_ssl_verify) {
curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0);
@@ -399,7 +403,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
git_config(urlmatch_config_entry, &config);
free(normalized_url);
- curl_global_init(CURL_GLOBAL_ALL);
+ if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
+ die("curl_global_init failed");
http_proactive_auth = proactive_auth;
@@ -417,10 +422,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
}
curlm = curl_multi_init();
- if (curlm == NULL) {
- fprintf(stderr, "Error creating curl multi handle.\n");
- exit(1);
- }
+ if (!curlm)
+ die("curl_multi_init failed");
#endif
if (getenv("GIT_SSL_NO_VERIFY"))
@@ -906,6 +909,83 @@ static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
return ret;
}
+/*
+ * Check for and extract a content-type parameter. "raw"
+ * should be positioned at the start of the potential
+ * parameter, with any whitespace already removed.
+ *
+ * "name" is the name of the parameter. The value is appended
+ * to "out".
+ */
+static int extract_param(const char *raw, const char *name,
+ struct strbuf *out)
+{
+ size_t len = strlen(name);
+
+ if (strncasecmp(raw, name, len))
+ return -1;
+ raw += len;
+
+ if (*raw != '=')
+ return -1;
+ raw++;
+
+ while (*raw && !isspace(*raw) && *raw != ';')
+ strbuf_addch(out, *raw++);
+ return 0;
+}
+
+/*
+ * 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.
+ *
+ * If the "charset" argument is not NULL, store the value of any
+ * charset parameter there.
+ *
+ * Example:
+ * "TEXT/PLAIN; charset=utf-8" -> "text/plain", "utf-8"
+ * "text / plain" -> "text/plain"
+ */
+static void extract_content_type(struct strbuf *raw, struct strbuf *type,
+ struct strbuf *charset)
+{
+ const char *p;
+
+ strbuf_reset(type);
+ strbuf_grow(type, raw->len);
+ for (p = raw->buf; *p; p++) {
+ if (isspace(*p))
+ continue;
+ if (*p == ';') {
+ p++;
+ break;
+ }
+ strbuf_addch(type, tolower(*p));
+ }
+
+ if (!charset)
+ return;
+
+ strbuf_reset(charset);
+ while (*p) {
+ while (isspace(*p) || *p == ';')
+ p++;
+ if (!extract_param(p, "charset", charset))
+ return;
+ while (*p && !isspace(*p))
+ p++;
+ }
+
+ if (!charset->len && starts_with(type->buf, "text/"))
+ strbuf_addstr(charset, "ISO-8859-1");
+}
+
/* http_request() targets */
#define HTTP_REQUEST_STRBUF 0
#define HTTP_REQUEST_FILE 1
@@ -957,9 +1037,13 @@ 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,
+ options->charset);
+ strbuf_release(&raw);
+ }
if (options && options->effective_url)
curlinfo_strbuf(slot->curl, CURLINFO_EFFECTIVE_URL,
@@ -1006,11 +1090,10 @@ static int update_url_from_redirect(struct strbuf *base,
if (!strcmp(asked, got->buf))
return 0;
- if (!starts_with(asked, base->buf))
+ if (!skip_prefix(asked, base->buf, &tail))
die("BUG: update_url_from_redirect: %s is not a superset of %s",
asked, base->buf);
- tail = asked + base->len;
tail_len = strlen(tail);
if (got->len < tail_len ||
@@ -1252,7 +1335,7 @@ int finish_http_pack_request(struct http_pack_request *preq)
struct packed_git **lst;
struct packed_git *p = preq->target;
char *tmp_idx;
- struct child_process ip;
+ struct child_process ip = CHILD_PROCESS_INIT;
const char *ip_argv[8];
close_pack_index(p);
@@ -1275,7 +1358,6 @@ int finish_http_pack_request(struct http_pack_request *preq)
ip_argv[3] = preq->tmpfile;
ip_argv[4] = NULL;
- memset(&ip, 0, sizeof(ip));
ip.argv = ip_argv;
ip.git_cmd = 1;
ip.no_stdin = 1;