travis: run tests with GIT_TEST_SPLIT_INDEX
[gitweb.git] / http.c
diff --git a/http.c b/http.c
index d9d73a2e607573e88d35c112660293cde92ff1bd..713525f38ed3f254aed2b0dd65fece7972444072 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "http.h"
+#include "config.h"
 #include "pack.h"
 #include "sideband.h"
 #include "run-command.h"
@@ -10,6 +11,7 @@
 #include "pkt-line.h"
 #include "gettext.h"
 #include "transport.h"
+#include "packfile.h"
 
 static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
 #if LIBCURL_VERSION_NUM >= 0x070a08
@@ -19,7 +21,7 @@ long int git_curl_ipresolve;
 #endif
 int active_requests;
 int http_is_verbose;
-size_t http_post_buffer = 16 * LARGE_PACKET_MAX;
+ssize_t http_post_buffer = 16 * LARGE_PACKET_MAX;
 
 #if LIBCURL_VERSION_NUM >= 0x070a06
 #define LIBCURL_CAN_HANDLE_AUTH_ANY
@@ -90,7 +92,7 @@ static struct {
         * here, too
         */
 };
-#if LIBCURL_VERSION_NUM >= 0x071600
+#ifdef CURLGSSAPI_DELEGATION_FLAG
 static const char *curl_deleg;
 static struct {
        const char *name;
@@ -271,10 +273,10 @@ static int http_options(const char *var, const char *value, void *cb)
        if (!strcmp("http.sslversion", var))
                return git_config_string(&ssl_version, var, value);
        if (!strcmp("http.sslcert", var))
-               return git_config_string(&ssl_cert, var, value);
+               return git_config_pathname(&ssl_cert, var, value);
 #if LIBCURL_VERSION_NUM >= 0x070903
        if (!strcmp("http.sslkey", var))
-               return git_config_string(&ssl_key, var, value);
+               return git_config_pathname(&ssl_key, var, value);
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070908
        if (!strcmp("http.sslcapath", var))
@@ -331,7 +333,9 @@ static int http_options(const char *var, const char *value, void *cb)
        }
 
        if (!strcmp("http.postbuffer", var)) {
-               http_post_buffer = git_config_int(var, value);
+               http_post_buffer = git_config_ssize_t(var, value);
+               if (http_post_buffer < 0)
+                       warning(_("negative value for http.postbuffer; defaulting to %d"), LARGE_PACKET_MAX);
                if (http_post_buffer < LARGE_PACKET_MAX)
                        http_post_buffer = LARGE_PACKET_MAX;
                return 0;
@@ -349,7 +353,7 @@ static int http_options(const char *var, const char *value, void *cb)
        }
 
        if (!strcmp("http.delegation", var)) {
-#if LIBCURL_VERSION_NUM >= 0x071600
+#ifdef CURLGSSAPI_DELEGATION_FLAG
                return git_config_string(&curl_deleg, var, value);
 #else
                warning(_("Delegation control is not supported with cURL < 7.22.0"));
@@ -634,9 +638,7 @@ static int curl_trace(CURL *handle, curl_infotype type, char *data, size_t size,
        switch (type) {
        case CURLINFO_TEXT:
                trace_printf_key(&trace_curl, "== Info: %s", data);
-       default:                /* we ignore unknown types by default */
-               return 0;
-
+               break;
        case CURLINFO_HEADER_OUT:
                text = "=> Send header";
                curl_dump_header(text, (unsigned char *)data, size, DO_FILTER);
@@ -661,6 +663,9 @@ static int curl_trace(CURL *handle, curl_infotype type, char *data, size_t size,
                text = "<= Recv SSL data";
                curl_dump_data(text, (unsigned char *)data, size);
                break;
+
+       default:                /* we ignore unknown types by default */
+               return 0;
        }
        return 0;
 }
@@ -674,11 +679,27 @@ void setup_curl_trace(CURL *handle)
        curl_easy_setopt(handle, CURLOPT_DEBUGDATA, NULL);
 }
 
+#ifdef CURLPROTO_HTTP
+static long get_curl_allowed_protocols(int from_user)
+{
+       long allowed_protocols = 0;
+
+       if (is_transport_allowed("http", from_user))
+               allowed_protocols |= CURLPROTO_HTTP;
+       if (is_transport_allowed("https", from_user))
+               allowed_protocols |= CURLPROTO_HTTPS;
+       if (is_transport_allowed("ftp", from_user))
+               allowed_protocols |= CURLPROTO_FTP;
+       if (is_transport_allowed("ftps", from_user))
+               allowed_protocols |= CURLPROTO_FTPS;
+
+       return allowed_protocols;
+}
+#endif
 
 static CURL *get_curl_handle(void)
 {
        CURL *result = curl_easy_init();
-       long allowed_protocols = 0;
 
        if (!result)
                die("curl_easy_init failed");
@@ -700,7 +721,7 @@ static CURL *get_curl_handle(void)
        curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
 #endif
 
-#if LIBCURL_VERSION_NUM >= 0x071600
+#ifdef CURLGSSAPI_DELEGATION_FLAG
        if (curl_deleg) {
                int i;
                for (i = 0; i < ARRAY_SIZE(curl_deleg_levels); i++) {
@@ -773,21 +794,14 @@ static CURL *get_curl_handle(void)
 #elif LIBCURL_VERSION_NUM >= 0x071101
        curl_easy_setopt(result, CURLOPT_POST301, 1);
 #endif
-#if LIBCURL_VERSION_NUM >= 0x071304
-       if (is_transport_allowed("http"))
-               allowed_protocols |= CURLPROTO_HTTP;
-       if (is_transport_allowed("https"))
-               allowed_protocols |= CURLPROTO_HTTPS;
-       if (is_transport_allowed("ftp"))
-               allowed_protocols |= CURLPROTO_FTP;
-       if (is_transport_allowed("ftps"))
-               allowed_protocols |= CURLPROTO_FTPS;
-       curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols);
-       curl_easy_setopt(result, CURLOPT_PROTOCOLS, allowed_protocols);
+#ifdef CURLPROTO_HTTP
+       curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS,
+                        get_curl_allowed_protocols(0));
+       curl_easy_setopt(result, CURLOPT_PROTOCOLS,
+                        get_curl_allowed_protocols(-1));
 #else
-       if (transport_restrict_protocols())
-               warning("protocol restrictions not applied to curl redirects because\n"
-                       "your curl version is too old (>= 7.19.4)");
+       warning("protocol restrictions not applied to curl redirects because\n"
+               "your curl version is too old (>= 7.19.4)");
 #endif
        if (getenv("GIT_CURL_VERBOSE"))
                curl_easy_setopt(result, CURLOPT_VERBOSE, 1L);
@@ -829,8 +843,14 @@ static CURL *get_curl_handle(void)
                }
        }
 
-       if (curl_http_proxy) {
-               curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
+       if (curl_http_proxy && curl_http_proxy[0] == '\0') {
+               /*
+                * Handle case with the empty http.proxy value here to keep
+                * common code clean.
+                * NB: empty option disables proxying at all.
+                */
+               curl_easy_setopt(result, CURLOPT_PROXY, "");
+       } else if (curl_http_proxy) {
 #if LIBCURL_VERSION_NUM >= 0x071800
                if (starts_with(curl_http_proxy, "socks5h"))
                        curl_easy_setopt(result,
@@ -854,6 +874,9 @@ static CURL *get_curl_handle(void)
                        strbuf_release(&url);
                }
 
+               if (!proxy_auth.host)
+                       die("Invalid proxy URL '%s'", curl_http_proxy);
+
                curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host);
 #if LIBCURL_VERSION_NUM >= 0x071304
                var_override(&curl_no_proxy, getenv("NO_PROXY"));
@@ -1008,8 +1031,7 @@ void http_cleanup(void)
 
        if (proxy_auth.password) {
                memset(proxy_auth.password, 0, strlen(proxy_auth.password));
-               free(proxy_auth.password);
-               proxy_auth.password = NULL;
+               FREE_AND_NULL(proxy_auth.password);
        }
 
        free((void *)curl_proxyuserpwd);
@@ -1020,13 +1042,11 @@ void http_cleanup(void)
 
        if (cert_auth.password != NULL) {
                memset(cert_auth.password, 0, strlen(cert_auth.password));
-               free(cert_auth.password);
-               cert_auth.password = NULL;
+               FREE_AND_NULL(cert_auth.password);
        }
        ssl_cert_password_required = 0;
 
-       free(cached_accept_language);
-       cached_accept_language = NULL;
+       FREE_AND_NULL(cached_accept_language);
 }
 
 struct active_request_slot *get_active_slot(void)
@@ -1359,9 +1379,9 @@ static int handle_curl_result(struct slot_results *results)
                 * FAILONERROR it is lost, so we can give only the numeric
                 * status code.
                 */
-               snprintf(curl_errorstr, sizeof(curl_errorstr),
-                        "The requested URL returned error: %ld",
-                        results->http_code);
+               xsnprintf(curl_errorstr, sizeof(curl_errorstr),
+                         "The requested URL returned error: %ld",
+                         results->http_code);
        }
 
        if (results->curl_result == CURLE_OK) {
@@ -1403,8 +1423,8 @@ int run_one_slot(struct active_request_slot *slot,
 {
        slot->results = results;
        if (!start_active_slot(slot)) {
-               snprintf(curl_errorstr, sizeof(curl_errorstr),
-                        "failed to start HTTP request");
+               xsnprintf(curl_errorstr, sizeof(curl_errorstr),
+                         "failed to start HTTP request");
                return HTTP_START_FAILED;
        }
 
@@ -1762,6 +1782,9 @@ static int http_request_reauth(const char *url,
 {
        int ret = http_request(url, result, target, options);
 
+       if (ret != HTTP_OK && ret != HTTP_REAUTH)
+               return ret;
+
        if (options && options->effective_url && options->base_url) {
                if (update_url_from_redirect(options->base_url,
                                             url, options->effective_url)) {
@@ -1875,8 +1898,7 @@ static char *fetch_pack_index(unsigned char *sha1, const char *base_url)
 
        if (http_get_file(url, tmp, NULL) != HTTP_OK) {
                error("Unable to get pack index %s", url);
-               free(tmp);
-               tmp = NULL;
+               FREE_AND_NULL(tmp);
        }
 
        free(url);
@@ -2307,8 +2329,7 @@ void release_http_object_request(struct http_object_request *freq)
                freq->localfile = -1;
        }
        if (freq->url != NULL) {
-               free(freq->url);
-               freq->url = NULL;
+               FREE_AND_NULL(freq->url);
        }
        if (freq->slot != NULL) {
                freq->slot->callback_func = NULL;