diff options
-rw-r--r-- | src/net.c | 7 | ||||
-rw-r--r-- | src/net.h | 7 | ||||
-rw-r--r-- | src/transports/httpclient.c | 40 | ||||
-rw-r--r-- | src/transports/winhttp.c | 42 | ||||
-rw-r--r-- | tests/network/urlparse.c | 413 |
5 files changed, 469 insertions, 40 deletions
@@ -335,7 +335,7 @@ bool git_net_url_valid(git_net_url *url) return (url->host && url->port && url->path); } -int git_net_url_is_default_port(git_net_url *url) +bool git_net_url_is_default_port(git_net_url *url) { const char *default_port; @@ -345,6 +345,11 @@ int git_net_url_is_default_port(git_net_url *url) return false; } +bool git_net_url_is_ipv6(git_net_url *url) +{ + return (strchr(url->host, ':') != NULL); +} + void git_net_url_swap(git_net_url *a, git_net_url *b) { git_net_url tmp = GIT_NET_URL_INIT; @@ -33,8 +33,11 @@ extern int git_net_url_joinpath( /** Ensures that a URL is minimally valid (contains a host, port and path) */ extern bool git_net_url_valid(git_net_url *url); -/** Returns nonzero if the URL is on the default port. */ -extern int git_net_url_is_default_port(git_net_url *url); +/** Returns true if the URL is on the default port. */ +extern bool git_net_url_is_default_port(git_net_url *url); + +/** Returns true if the host portion of the URL is an ipv6 address. */ +extern bool git_net_url_is_ipv6(git_net_url *url); /* Applies a redirect to the URL with a git-aware service suffix. */ extern int git_net_url_apply_redirect( diff --git a/src/transports/httpclient.c b/src/transports/httpclient.c index d9cbf1783..d3975746b 100644 --- a/src/transports/httpclient.c +++ b/src/transports/httpclient.c @@ -631,6 +631,26 @@ GIT_INLINE(int) apply_proxy_credentials( request->proxy_credentials); } +static int puts_host_and_port(git_buf *buf, git_net_url *url, bool force_port) +{ + bool ipv6 = git_net_url_is_ipv6(url); + + if (ipv6) + git_buf_putc(buf, '['); + + git_buf_puts(buf, url->host); + + if (ipv6) + git_buf_putc(buf, ']'); + + if (force_port || !git_net_url_is_default_port(url)) { + git_buf_putc(buf, ':'); + git_buf_puts(buf, url->port); + } + + return git_buf_oom(buf) ? -1 : 0; +} + static int generate_connect_request( git_http_client *client, git_http_request *request) @@ -641,14 +661,17 @@ static int generate_connect_request( git_buf_clear(&client->request_msg); buf = &client->request_msg; - git_buf_printf(buf, "CONNECT %s:%s HTTP/1.1\r\n", - client->server.url.host, client->server.url.port); + git_buf_puts(buf, "CONNECT "); + puts_host_and_port(buf, &client->server.url, true); + git_buf_puts(buf, " HTTP/1.1\r\n"); git_buf_puts(buf, "User-Agent: "); git_http__user_agent(buf); git_buf_puts(buf, "\r\n"); - git_buf_printf(buf, "Host: %s\r\n", client->proxy.url.host); + git_buf_puts(buf, "Host: "); + puts_host_and_port(buf, &client->proxy.url, false); + git_buf_puts(buf, "\r\n"); if ((error = apply_proxy_credentials(buf, client, request) < 0)) return -1; @@ -687,11 +710,8 @@ static int generate_request( git_http__user_agent(buf); git_buf_puts(buf, "\r\n"); - git_buf_printf(buf, "Host: %s", request->url->host); - - if (!git_net_url_is_default_port(request->url)) - git_buf_printf(buf, ":%s", request->url->port); - + git_buf_puts(buf, "Host: "); + puts_host_and_port(buf, request->url, false); git_buf_puts(buf, "\r\n"); if (request->accept) @@ -902,7 +922,7 @@ static int proxy_connect( int error; if (!client->proxy_connected || !client->keepalive) { - git_trace(GIT_TRACE_DEBUG, "Connecting to proxy %s:%s", + git_trace(GIT_TRACE_DEBUG, "Connecting to proxy %s port %s", client->proxy.url.host, client->proxy.url.port); if ((error = server_create_stream(&client->proxy)) < 0 || @@ -1023,7 +1043,7 @@ static int http_client_connect( goto on_error; } - git_trace(GIT_TRACE_DEBUG, "Connecting to remote %s:%s", + git_trace(GIT_TRACE_DEBUG, "Connecting to remote %s port %s", client->server.url.host, client->server.url.port); if ((error = server_connect(client)) < 0) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index c82c788ae..54aacdba3 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -451,8 +451,14 @@ static int winhttp_stream_connect(winhttp_stream *s) git_buf_puts(&processed_url, t->proxy.url.scheme); git_buf_PUTS(&processed_url, "://"); + if (git_net_url_is_ipv6(&t->proxy.url)) + git_buf_putc(&processed_url, '['); + git_buf_puts(&processed_url, t->proxy.url.host); + if (git_net_url_is_ipv6(&t->proxy.url)) + git_buf_putc(&processed_url, ']'); + if (!git_net_url_is_default_port(&t->proxy.url)) git_buf_printf(&processed_url, ":%s", t->proxy.url.port); @@ -736,10 +742,11 @@ static void CALLBACK winhttp_status( static int winhttp_connect( winhttp_subtransport *t) { - wchar_t *wide_host; + wchar_t *wide_host = NULL; int32_t port; - wchar_t *wide_ua; - git_buf ua = GIT_BUF_INIT; + wchar_t *wide_ua = NULL; + git_buf ipv6 = GIT_BUF_INIT, ua = GIT_BUF_INIT; + const char *host; int error = -1; int default_timeout = TIMEOUT_INFINITE; int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT; @@ -755,29 +762,33 @@ static int winhttp_connect( /* Prepare port */ if (git__strntol32(&port, t->server.url.port, strlen(t->server.url.port), NULL, 10) < 0) - return -1; + goto on_error; + + /* IPv6? Add braces around the host. */ + if (git_net_url_is_ipv6(&t->server.url)) { + if (git_buf_printf(&ipv6, "[%s]", t->server.url.host) < 0) + goto on_error; + + host = ipv6.ptr; + } else { + host = t->server.url.host; + } /* Prepare host */ - if (git__utf8_to_16_alloc(&wide_host, t->server.url.host) < 0) { + if (git__utf8_to_16_alloc(&wide_host, host) < 0) { git_error_set(GIT_ERROR_OS, "unable to convert host to wide characters"); - return -1; + goto on_error; } - if ((error = git_http__user_agent(&ua)) < 0) { - git__free(wide_host); - return error; - } + if (git_http__user_agent(&ua) < 0) + goto on_error; if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) { git_error_set(GIT_ERROR_OS, "unable to convert host to wide characters"); - git__free(wide_host); - git_buf_dispose(&ua); - return -1; + goto on_error; } - git_buf_dispose(&ua); - /* Establish session */ t->session = WinHttpOpen( wide_ua, @@ -836,6 +847,7 @@ on_error: if (error < 0) winhttp_close_connection(t); + git_buf_dispose(&ipv6); git__free(wide_host); git__free(wide_ua); diff --git a/tests/network/urlparse.c b/tests/network/urlparse.c index 15707885a..91c1a527c 100644 --- a/tests/network/urlparse.c +++ b/tests/network/urlparse.c @@ -13,7 +13,9 @@ void test_network_urlparse__cleanup(void) git_net_url_dispose(&conndata); } -void test_network_urlparse__trivial(void) +/* Hostname */ + +void test_network_urlparse__hostname_trivial(void) { cl_git_pass(git_net_url_parse(&conndata, "http://example.com/resource")); cl_assert_equal_s(conndata.scheme, "http"); @@ -25,7 +27,7 @@ void test_network_urlparse__trivial(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__root(void) +void test_network_urlparse__hostname_root(void) { cl_git_pass(git_net_url_parse(&conndata, "http://example.com/")); cl_assert_equal_s(conndata.scheme, "http"); @@ -37,7 +39,7 @@ void test_network_urlparse__root(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__implied_root(void) +void test_network_urlparse__hostname_implied_root(void) { cl_git_pass(git_net_url_parse(&conndata, "http://example.com")); cl_assert_equal_s(conndata.scheme, "http"); @@ -49,7 +51,7 @@ void test_network_urlparse__implied_root(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__implied_root_custom_port(void) +void test_network_urlparse__hostname_implied_root_custom_port(void) { cl_git_pass(git_net_url_parse(&conndata, "http://example.com:42")); cl_assert_equal_s(conndata.scheme, "http"); @@ -61,7 +63,7 @@ void test_network_urlparse__implied_root_custom_port(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } -void test_network_urlparse__implied_root_empty_port(void) +void test_network_urlparse__hostname_implied_root_empty_port(void) { cl_git_pass(git_net_url_parse(&conndata, "http://example.com:")); cl_assert_equal_s(conndata.scheme, "http"); @@ -73,7 +75,7 @@ void test_network_urlparse__implied_root_empty_port(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__encoded_password(void) +void test_network_urlparse__hostname_encoded_password(void) { cl_git_pass(git_net_url_parse(&conndata, "https://user:pass%2fis%40bad@hostname.com:1234/")); @@ -86,7 +88,7 @@ void test_network_urlparse__encoded_password(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } -void test_network_urlparse__user(void) +void test_network_urlparse__hostname_user(void) { cl_git_pass(git_net_url_parse(&conndata, "https://user@example.com/resource")); @@ -99,7 +101,7 @@ void test_network_urlparse__user(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__user_pass(void) +void test_network_urlparse__hostname_user_pass(void) { /* user:pass@hostname.tld/resource */ cl_git_pass(git_net_url_parse(&conndata, @@ -113,7 +115,7 @@ void test_network_urlparse__user_pass(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__port(void) +void test_network_urlparse__hostname_port(void) { /* hostname.tld:port/resource */ cl_git_pass(git_net_url_parse(&conndata, @@ -127,7 +129,7 @@ void test_network_urlparse__port(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } -void test_network_urlparse__empty_port(void) +void test_network_urlparse__hostname_empty_port(void) { cl_git_pass(git_net_url_parse(&conndata, "http://example.com:/resource")); cl_assert_equal_s(conndata.scheme, "http"); @@ -139,7 +141,7 @@ void test_network_urlparse__empty_port(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__user_port(void) +void test_network_urlparse__hostname_user_port(void) { /* user@hostname.tld:port/resource */ cl_git_pass(git_net_url_parse(&conndata, @@ -153,7 +155,7 @@ void test_network_urlparse__user_port(void) cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } -void test_network_urlparse__user_pass_port(void) +void test_network_urlparse__hostname_user_pass_port(void) { /* user:pass@hostname.tld:port/resource */ cl_git_pass(git_net_url_parse(&conndata, @@ -166,3 +168,390 @@ void test_network_urlparse__user_pass_port(void) cl_assert_equal_s(conndata.password, "pass"); cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } + +/* IPv4 addresses */ + +void test_network_urlparse__ipv4_trivial(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1/resource")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv4_root(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1/")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv4_implied_root(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv4_implied_root_custom_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:42")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "42"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv4_implied_root_empty_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv4_encoded_password(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass%2fis%40bad@192.168.1.1:1234/")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "1234"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass/is@bad"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv4_user(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user@192.168.1.1/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv4_user_pass(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass@192.168.1.1/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv4_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://192.168.1.1:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv4_empty_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:/resource")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv4_user_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user@192.168.1.1:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv4_user_pass_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass@192.168.1.1:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "192.168.1.1"); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +/* IPv6 addresses */ + +void test_network_urlparse__ipv6_trivial(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]/resource")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv6_root(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]/")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv6_implied_root(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv6_implied_root_custom_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:42")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "42"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv6_implied_root_empty_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv6_encoded_password(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001]:1234/")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "1234"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass/is@bad"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv6_user(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user@[fe80::dcad:beff:fe00:0001]/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv6_user_pass(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass@[fe80::dcad:beff:fe00:0001]/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv6_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://[fe80::dcad:beff:fe00:0001]:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv6_empty_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:/resource")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); +} + +void test_network_urlparse__ipv6_user_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user@[fe80::dcad:beff:fe00:0001]:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv6_user_pass_port(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass@[fe80::dcad:beff:fe00:0001]:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001"); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); +} + +void test_network_urlparse__ipv6_invalid_addresses(void) +{ + /* Opening bracket missing */ + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001]/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001]/")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001]")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001]:42")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001]:")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass%2fis%40bad@fe80::dcad:beff:fe00:0001]:1234/")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user@fe80::dcad:beff:fe00:0001]/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass@fe80::dcad:beff:fe00:0001]/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://fe80::dcad:beff:fe00:0001]:9191/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001]:/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user@fe80::dcad:beff:fe00:0001]:9191/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass@fe80::dcad:beff:fe00:0001]:9191/resource")); + + /* Closing bracket missing */ + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://[fe80::dcad:beff:fe00:0001/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://[fe80::dcad:beff:fe00:0001/")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://[fe80::dcad:beff:fe00:0001")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://[fe80::dcad:beff:fe00:0001:42")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://[fe80::dcad:beff:fe00:0001:")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001:1234/")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user@[fe80::dcad:beff:fe00:0001/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass@[fe80::dcad:beff:fe00:0001/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://[fe80::dcad:beff:fe00:0001:9191/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://[fe80::dcad:beff:fe00:0001:/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user@[fe80::dcad:beff:fe00:0001:9191/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass@[fe80::dcad:beff:fe00:0001:9191/resource")); + /* Both brackets missing */ + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001/")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001:42")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001:")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass%2fis%40bad@fe80::dcad:beff:fe00:0001:1234/")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user@fe80::dcad:beff:fe00:0001/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass@fe80::dcad:beff:fe00:0001/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://fe80::dcad:beff:fe00:0001:9191/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "http://fe80::dcad:beff:fe00:0001:/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user@fe80::dcad:beff:fe00:0001:9191/resource")); + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, + "https://user:pass@fe80::dcad:beff:fe00:0001:9191/resource")); + + /* Invalid chracter inside address */ + cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://[fe8o::dcad:beff:fe00:0001]/resource")); +} |