diff options
author | Torsten Bögershausen <tboegi@web.de> | 2015-02-21 16:52:48 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-02-22 12:02:59 -0800 |
commit | 86ceb337ec340c7db9b060b90bfab05a08b8251b (patch) | |
tree | 8a4292cda1a9d9d5b185792d32441a47d25b2501 /connect.c | |
parent | fdf96a20acf96a6ac538df8113b2aafd6ed71d50 (diff) | |
download | git-86ceb337ec340c7db9b060b90bfab05a08b8251b.tar.gz |
connect.c: allow ssh://user@[2001:db8::1]/repo.git
The ssh:// syntax was added in 2386d658 (Add first cut at "git
protocol" connect logic., 2005-07-13), it accepted
ssh://user@2001:db8::1/repo.git, which is now legacy.
Over the years the parser was improved to support [] and port numbers,
but the combination of ssh://user@[2001:db8::1]:222/repo.git did
never work.
The only only way to use a user name, a literall IPV6 address and a port
number was ssh://[user@2001:db8::1]:222/repo.git
(Thanks to Christian Taube <lists@hcf.yourweb.de> for reporting this long
standing issue)
New users would use ssh://user@[2001:db8::1]:222/repo.git,
so change the parser to handle it correctly.
Support the old legacy URLs as well, to be backwards compatible,
and avoid regressions for users which upgrade an existing installation
to a later Git version.
Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'connect.c')
-rw-r--r-- | connect.c | 63 |
1 files changed, 38 insertions, 25 deletions
@@ -274,28 +274,44 @@ static enum protocol get_protocol(const char *name) die("I don't handle protocol '%s'", name); } +static char *host_end(char **hoststart, int removebrackets) +{ + char *host = *hoststart; + char *end; + char *start = strstr(host, "@["); + if (start) + start++; /* Jump over '@' */ + else + start = host; + if (start[0] == '[') { + end = strchr(start + 1, ']'); + if (end) { + if (removebrackets) { + *end = 0; + memmove(start, start + 1, end - start); + end++; + } + } else + end = host; + } else + end = host; + return end; +} + #define STR_(s) # s #define STR(s) STR_(s) static void get_host_and_port(char **host, const char **port) { char *colon, *end; - - if (*host[0] == '[') { - end = strchr(*host + 1, ']'); - if (end) { - *end = 0; - end++; - (*host)++; - } else - end = *host; - } else - end = *host; + end = host_end(host, 1); colon = strchr(end, ':'); - if (colon) { - *colon = 0; - *port = colon + 1; + long portnr = strtol(colon + 1, &end, 10); + if (end != colon + 1 && *end == '\0' && 0 <= portnr && portnr < 65536) { + *colon = 0; + *port = colon + 1; + } } } @@ -547,13 +563,16 @@ static struct child_process *git_proxy_connect(int fd[2], char *host) return proxy; } -static const char *get_port_numeric(const char *p) +static char *get_port(char *host) { char *end; + char *p = strchr(host, ':'); + if (p) { long port = strtol(p + 1, &end, 10); if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) { - return p; + *p = '\0'; + return p+1; } } @@ -595,14 +614,7 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host, * Don't do destructive transforms as protocol code does * '[]' unwrapping in get_host_and_port() */ - if (host[0] == '[') { - end = strchr(host + 1, ']'); - if (end) { - end++; - } else - end = host; - } else - end = host; + end = host_end(&host, 0); if (protocol == PROTO_LOCAL) path = end; @@ -705,7 +717,8 @@ struct child_process *git_connect(int fd[2], const char *url, char *ssh_host = hostandport; const char *port = NULL; get_host_and_port(&ssh_host, &port); - port = get_port_numeric(port); + if (!port) + port = get_port(ssh_host); if (!ssh) ssh = "ssh"; |