]> git.proxmox.com Git - libgit2.git/blobdiff - src/transports/http.c
New upstream version 1.4.3+dfsg.1
[libgit2.git] / src / transports / http.c
index 914335aba57e929b920051a943aea432dc4a25e0..7db5582cab4b3d0e34af3d8eabab4400b8d247ca 100644 (file)
@@ -9,13 +9,10 @@
 
 #ifndef GIT_WINHTTP
 
-#include "git2.h"
 #include "http_parser.h"
-#include "buffer.h"
 #include "net.h"
 #include "netops.h"
 #include "remote.h"
-#include "git2/sys/credential.h"
 #include "smart.h"
 #include "auth.h"
 #include "http.h"
@@ -25,6 +22,7 @@
 #include "streams/tls.h"
 #include "streams/socket.h"
 #include "httpclient.h"
+#include "git2/sys/credential.h"
 
 bool git_http__expect_continue = false;
 
@@ -40,7 +38,8 @@ typedef struct {
        const char *url;
        const char *request_type;
        const char *response_type;
-       unsigned chunked : 1;
+       unsigned int initial : 1,
+                    chunked : 1;
 } http_service;
 
 typedef struct {
@@ -72,24 +71,28 @@ static const http_service upload_pack_ls_service = {
        GIT_HTTP_METHOD_GET, "/info/refs?service=git-upload-pack",
        NULL,
        "application/x-git-upload-pack-advertisement",
+       1,
        0
 };
 static const http_service upload_pack_service = {
        GIT_HTTP_METHOD_POST, "/git-upload-pack",
        "application/x-git-upload-pack-request",
        "application/x-git-upload-pack-result",
+       0,
        0
 };
 static const http_service receive_pack_ls_service = {
        GIT_HTTP_METHOD_GET, "/info/refs?service=git-receive-pack",
        NULL,
        "application/x-git-receive-pack-advertisement",
+       1,
        0
 };
 static const http_service receive_pack_service = {
        GIT_HTTP_METHOD_POST, "/git-receive-pack",
        "application/x-git-receive-pack-request",
        "application/x-git-receive-pack-result",
+       0,
        1
 };
 
@@ -176,6 +179,7 @@ GIT_INLINE(int) handle_remote_auth(
        git_http_response *response)
 {
        http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
+       git_remote_connect_options *connect_opts = &transport->owner->connect_opts;
 
        if (response->server_auth_credtypes == 0) {
                git_error_set(GIT_ERROR_HTTP, "server requires authentication that we do not support");
@@ -189,8 +193,8 @@ GIT_INLINE(int) handle_remote_auth(
                transport->owner->url,
                response->server_auth_schemetypes,
                response->server_auth_credtypes,
-               transport->owner->cred_acquire_cb,
-               transport->owner->cred_acquire_payload);
+               connect_opts->callbacks.credentials,
+               connect_opts->callbacks.payload);
 }
 
 GIT_INLINE(int) handle_proxy_auth(
@@ -198,6 +202,7 @@ GIT_INLINE(int) handle_proxy_auth(
        git_http_response *response)
 {
        http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
+       git_remote_connect_options *connect_opts = &transport->owner->connect_opts;
 
        if (response->proxy_auth_credtypes == 0) {
                git_error_set(GIT_ERROR_HTTP, "proxy requires authentication that we do not support");
@@ -208,13 +213,26 @@ GIT_INLINE(int) handle_proxy_auth(
        return handle_auth(
                &transport->proxy,
                SERVER_TYPE_PROXY,
-               transport->owner->proxy.url,
+               connect_opts->proxy_opts.url,
                response->server_auth_schemetypes,
                response->proxy_auth_credtypes,
-               transport->owner->proxy.credentials,
-               transport->owner->proxy.payload);
+               connect_opts->proxy_opts.credentials,
+               connect_opts->proxy_opts.payload);
 }
 
+static bool allow_redirect(http_stream *stream)
+{
+       http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
+
+       switch (transport->owner->connect_opts.follow_redirects) {
+       case GIT_REMOTE_REDIRECT_INITIAL:
+               return (stream->service->initial == 1);
+       case GIT_REMOTE_REDIRECT_ALL:
+               return true;
+       default:
+               return false;
+       }
+}
 
 static int handle_response(
        bool *complete,
@@ -233,7 +251,7 @@ static int handle_response(
                        return -1;
                }
 
-               if (git_net_url_apply_redirect(&transport->server.url, response->location, stream->service->url) < 0) {
+               if (git_net_url_apply_redirect(&transport->server.url, response->location, allow_redirect(stream), stream->service->url) < 0) {
                        return -1;
                }
 
@@ -288,6 +306,7 @@ static int lookup_proxy(
        bool *out_use,
        http_subtransport *transport)
 {
+       git_remote_connect_options *connect_opts = &transport->owner->connect_opts;
        const char *proxy;
        git_remote *remote;
        char *config = NULL;
@@ -296,9 +315,9 @@ static int lookup_proxy(
        *out_use = false;
        git_net_url_dispose(&transport->proxy.url);
 
-       switch (transport->owner->proxy.type) {
+       switch (connect_opts->proxy_opts.type) {
        case GIT_PROXY_SPECIFIED:
-               proxy = transport->owner->proxy.url;
+               proxy = connect_opts->proxy_opts.url;
                break;
 
        case GIT_PROXY_AUTO:
@@ -347,7 +366,7 @@ static int generate_request(
        request->credentials = transport->server.cred;
        request->proxy = use_proxy ? &transport->proxy.url : NULL;
        request->proxy_credentials = transport->proxy.cred;
-       request->custom_headers = &transport->owner->custom_headers;
+       request->custom_headers = &transport->owner->connect_opts.custom_headers;
 
        if (stream->service->method == GIT_HTTP_METHOD_POST) {
                request->chunked = stream->service->chunked;
@@ -635,6 +654,7 @@ static int http_action(
        git_smart_service_t action)
 {
        http_subtransport *transport = GIT_CONTAINER_OF(t, http_subtransport, parent);
+       git_remote_connect_options *connect_opts = &transport->owner->connect_opts;
        http_stream *stream;
        const http_service *service;
        int error;
@@ -666,10 +686,10 @@ static int http_action(
        if (!transport->http_client) {
                git_http_client_options opts = {0};
 
-               opts.server_certificate_check_cb = transport->owner->certificate_check_cb;
-               opts.server_certificate_check_payload = transport->owner->message_cb_payload;
-               opts.proxy_certificate_check_cb = transport->owner->proxy.certificate_check;
-               opts.proxy_certificate_check_payload = transport->owner->proxy.payload;
+               opts.server_certificate_check_cb = connect_opts->callbacks.certificate_check;
+               opts.server_certificate_check_payload = connect_opts->callbacks.payload;
+               opts.proxy_certificate_check_cb = connect_opts->proxy_opts.certificate_check;
+               opts.proxy_certificate_check_payload = connect_opts->proxy_opts.payload;
 
                if (git_http_client_new(&transport->http_client, &opts) < 0)
                        return -1;