]> asedeno.scripts.mit.edu Git - git.git/blobdiff - http.c
docs/checkout: clarify what "non-branch" means
[git.git] / http.c
diff --git a/http.c b/http.c
index d1ead6643df649707527409b0dc226f29dcffb7d..2e3d6493ef40e1b34fea8d166d760f0b1fcccafc 100644 (file)
--- a/http.c
+++ b/http.c
@@ -25,6 +25,7 @@ static long curl_low_speed_limit = -1;
 static long curl_low_speed_time = -1;
 static int curl_ftp_no_epsv;
 static const char *curl_http_proxy;
+static char *user_name, *user_pass;
 
 static struct curl_slist *pragma_header;
 
@@ -43,6 +44,25 @@ size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
        return size;
 }
 
+#ifndef NO_CURL_IOCTL
+curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
+{
+       struct buffer *buffer = clientp;
+
+       switch (cmd) {
+       case CURLIOCMD_NOP:
+               return CURLIOE_OK;
+
+       case CURLIOCMD_RESTARTREAD:
+               buffer->posn = 0;
+               return CURLIOE_OK;
+
+       default:
+               return CURLIOE_UNKNOWNCMD;
+       }
+}
+#endif
+
 size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
 {
        size_t size = eltsize * nmemb;
@@ -94,52 +114,33 @@ static void process_curl_messages(void)
 static int http_options(const char *var, const char *value, void *cb)
 {
        if (!strcmp("http.sslverify", var)) {
-               if (curl_ssl_verify == -1)
-                       curl_ssl_verify = git_config_bool(var, value);
-               return 0;
-       }
-
-       if (!strcmp("http.sslcert", var)) {
-               if (ssl_cert == NULL)
-                       return git_config_string(&ssl_cert, var, value);
+               curl_ssl_verify = git_config_bool(var, value);
                return 0;
        }
+       if (!strcmp("http.sslcert", var))
+               return git_config_string(&ssl_cert, var, value);
 #if LIBCURL_VERSION_NUM >= 0x070902
-       if (!strcmp("http.sslkey", var)) {
-               if (ssl_key == NULL)
-                       return git_config_string(&ssl_key, var, value);
-               return 0;
-       }
+       if (!strcmp("http.sslkey", var))
+               return git_config_string(&ssl_key, var, value);
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070908
-       if (!strcmp("http.sslcapath", var)) {
-               if (ssl_capath == NULL)
-                       return git_config_string(&ssl_capath, var, value);
-               return 0;
-       }
+       if (!strcmp("http.sslcapath", var))
+               return git_config_string(&ssl_capath, var, value);
 #endif
-       if (!strcmp("http.sslcainfo", var)) {
-               if (ssl_cainfo == NULL)
-                       return git_config_string(&ssl_cainfo, var, value);
-               return 0;
-       }
-
+       if (!strcmp("http.sslcainfo", var))
+               return git_config_string(&ssl_cainfo, var, value);
 #ifdef USE_CURL_MULTI
        if (!strcmp("http.maxrequests", var)) {
-               if (max_requests == -1)
-                       max_requests = git_config_int(var, value);
+               max_requests = git_config_int(var, value);
                return 0;
        }
 #endif
-
        if (!strcmp("http.lowspeedlimit", var)) {
-               if (curl_low_speed_limit == -1)
-                       curl_low_speed_limit = (long)git_config_int(var, value);
+               curl_low_speed_limit = (long)git_config_int(var, value);
                return 0;
        }
        if (!strcmp("http.lowspeedtime", var)) {
-               if (curl_low_speed_time == -1)
-                       curl_low_speed_time = (long)git_config_int(var, value);
+               curl_low_speed_time = (long)git_config_int(var, value);
                return 0;
        }
 
@@ -147,16 +148,25 @@ static int http_options(const char *var, const char *value, void *cb)
                curl_ftp_no_epsv = git_config_bool(var, value);
                return 0;
        }
-       if (!strcmp("http.proxy", var)) {
-               if (curl_http_proxy == NULL)
-                       return git_config_string(&curl_http_proxy, var, value);
-               return 0;
-       }
+       if (!strcmp("http.proxy", var))
+               return git_config_string(&curl_http_proxy, var, value);
 
        /* Fall back on the default ones */
        return git_default_config(var, value, cb);
 }
 
+static void init_curl_http_auth(CURL *result)
+{
+       if (user_name) {
+               struct strbuf up = STRBUF_INIT;
+               if (!user_pass)
+                       user_pass = xstrdup(getpass("Password: "));
+               strbuf_addf(&up, "%s:%s", user_name, user_pass);
+               curl_easy_setopt(result, CURLOPT_USERPWD,
+                                strbuf_detach(&up, NULL));
+       }
+}
+
 static CURL *get_curl_handle(void)
 {
        CURL *result = curl_easy_init();
@@ -175,6 +185,8 @@ static CURL *get_curl_handle(void)
        curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
 #endif
 
+       init_curl_http_auth(result);
+
        if (ssl_cert != NULL)
                curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
 #if LIBCURL_VERSION_NUM >= 0x070902
@@ -212,11 +224,60 @@ static CURL *get_curl_handle(void)
        return result;
 }
 
+static void http_auth_init(const char *url)
+{
+       char *at, *colon, *cp, *slash;
+       int len;
+
+       cp = strstr(url, "://");
+       if (!cp)
+               return;
+
+       /*
+        * Ok, the URL looks like "proto://something".  Which one?
+        * "proto://<user>:<pass>@<host>/...",
+        * "proto://<user>@<host>/...", or just
+        * "proto://<host>/..."?
+        */
+       cp += 3;
+       at = strchr(cp, '@');
+       colon = strchr(cp, ':');
+       slash = strchrnul(cp, '/');
+       if (!at || slash <= at)
+               return; /* No credentials */
+       if (!colon || at <= colon) {
+               /* Only username */
+               len = at - cp;
+               user_name = xmalloc(len + 1);
+               memcpy(user_name, cp, len);
+               user_name[len] = '\0';
+               user_pass = NULL;
+       } else {
+               len = colon - cp;
+               user_name = xmalloc(len + 1);
+               memcpy(user_name, cp, len);
+               user_name[len] = '\0';
+               len = at - (colon + 1);
+               user_pass = xmalloc(len + 1);
+               memcpy(user_pass, colon + 1, len);
+               user_pass[len] = '\0';
+       }
+}
+
+static void set_from_env(const char **var, const char *envname)
+{
+       const char *val = getenv(envname);
+       if (val)
+               *var = val;
+}
+
 void http_init(struct remote *remote)
 {
        char *low_speed_limit;
        char *low_speed_time;
 
+       git_config(http_options, NULL);
+
        curl_global_init(CURL_GLOBAL_ALL);
 
        if (remote && remote->http_proxy)
@@ -241,14 +302,14 @@ void http_init(struct remote *remote)
        if (getenv("GIT_SSL_NO_VERIFY"))
                curl_ssl_verify = 0;
 
-       ssl_cert = getenv("GIT_SSL_CERT");
+       set_from_env(&ssl_cert, "GIT_SSL_CERT");
 #if LIBCURL_VERSION_NUM >= 0x070902
-       ssl_key = getenv("GIT_SSL_KEY");
+       set_from_env(&ssl_key, "GIT_SSL_KEY");
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070908
-       ssl_capath = getenv("GIT_SSL_CAPATH");
+       set_from_env(&ssl_capath, "GIT_SSL_CAPATH");
 #endif
-       ssl_cainfo = getenv("GIT_SSL_CAINFO");
+       set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO");
 
        low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
        if (low_speed_limit != NULL)
@@ -257,8 +318,6 @@ void http_init(struct remote *remote)
        if (low_speed_time != NULL)
                curl_low_speed_time = strtol(low_speed_time, NULL, 10);
 
-       git_config(http_options, NULL);
-
        if (curl_ssl_verify == -1)
                curl_ssl_verify = 1;
 
@@ -270,6 +329,9 @@ void http_init(struct remote *remote)
        if (getenv("GIT_CURL_FTP_NO_EPSV"))
                curl_ftp_no_epsv = 1;
 
+       if (remote && remote->url && remote->url[0])
+               http_auth_init(remote->url[0]);
+
 #ifndef NO_CURL_EASY_DUPHANDLE
        curl_default = get_curl_handle();
 #endif