vendor/libgit2/src/net.c in rugged-1.1.1 vs vendor/libgit2/src/net.c in rugged-1.2.0

- old
+ new

@@ -12,11 +12,11 @@ #include "git2/errors.h" #include "posix.h" #include "buffer.h" #include "http_parser.h" -#include "global.h" +#include "runtime.h" #define DEFAULT_PORT_HTTP "80" #define DEFAULT_PORT_HTTPS "443" #define DEFAULT_PORT_GIT "9418" #define DEFAULT_PORT_SSH "22" @@ -33,10 +33,50 @@ return DEFAULT_PORT_SSH; return NULL; } +int git_net_url_dup(git_net_url *out, git_net_url *in) +{ + if (in->scheme) { + out->scheme = git__strdup(in->scheme); + GIT_ERROR_CHECK_ALLOC(out->scheme); + } + + if (in->host) { + out->host = git__strdup(in->host); + GIT_ERROR_CHECK_ALLOC(out->host); + } + + if (in->port) { + out->port = git__strdup(in->port); + GIT_ERROR_CHECK_ALLOC(out->port); + } + + if (in->path) { + out->path = git__strdup(in->path); + GIT_ERROR_CHECK_ALLOC(out->path); + } + + if (in->query) { + out->query = git__strdup(in->query); + GIT_ERROR_CHECK_ALLOC(out->query); + } + + if (in->username) { + out->username = git__strdup(in->username); + GIT_ERROR_CHECK_ALLOC(out->username); + } + + if (in->password) { + out->password = git__strdup(in->password); + GIT_ERROR_CHECK_ALLOC(out->password); + } + + return 0; +} + int git_net_url_parse(git_net_url *url, const char *given) { struct http_parser_url u = {0}; bool has_scheme, has_host, has_port, has_path, has_query, has_userinfo; git_buf scheme = GIT_BUF_INIT, @@ -279,11 +319,12 @@ const char *service_suffix) { git_net_url tmp = GIT_NET_URL_INIT; int error = 0; - assert(url && redirect_location); + GIT_ASSERT(url); + GIT_ASSERT(redirect_location); if (redirect_location[0] == '/') { git__free(url->path); if ((url->path = git__strdup(redirect_location)) == NULL) { @@ -332,20 +373,25 @@ 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; if ((default_port = default_port_for_scheme(url->scheme)) != NULL) return (strcmp(url->port, default_port) == 0); else 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; memcpy(&tmp, a, sizeof(git_net_url)); @@ -353,10 +399,14 @@ memcpy(b, &tmp, sizeof(git_net_url)); } int git_net_url_fmt(git_buf *buf, git_net_url *url) { + GIT_ASSERT_ARG(url); + GIT_ASSERT_ARG(url->scheme); + GIT_ASSERT_ARG(url->host); + git_buf_puts(buf, url->scheme); git_buf_puts(buf, "://"); if (url->username) { git_buf_puts(buf, url->username); @@ -394,9 +444,83 @@ git_buf_putc(buf, '?'); git_buf_puts(buf, url->query); } return git_buf_oom(buf) ? -1 : 0; +} + +static bool matches_pattern( + git_net_url *url, + const char *pattern, + size_t pattern_len) +{ + const char *domain, *port = NULL, *colon; + size_t host_len, domain_len, port_len = 0, wildcard = 0; + + GIT_UNUSED(url); + GIT_UNUSED(pattern); + + if (!pattern_len) + return false; + else if (pattern_len == 1 && pattern[0] == '*') + return true; + else if (pattern_len > 1 && pattern[0] == '*' && pattern[1] == '.') + wildcard = 2; + else if (pattern[0] == '.') + wildcard = 1; + + domain = pattern + wildcard; + domain_len = pattern_len - wildcard; + + if ((colon = memchr(domain, ':', domain_len)) != NULL) { + domain_len = colon - domain; + port = colon + 1; + port_len = pattern_len - wildcard - domain_len - 1; + } + + /* A pattern's port *must* match if it's specified */ + if (port_len && git__strlcmp(url->port, port, port_len) != 0) + return false; + + /* No wildcard? Host must match exactly. */ + if (!wildcard) + return !git__strlcmp(url->host, domain, domain_len); + + /* Wildcard: ensure there's (at least) a suffix match */ + if ((host_len = strlen(url->host)) < domain_len || + memcmp(url->host + (host_len - domain_len), domain, domain_len)) + return false; + + /* The pattern is *.domain and the host is simply domain */ + if (host_len == domain_len) + return true; + + /* The pattern is *.domain and the host is foo.domain */ + return (url->host[host_len - domain_len - 1] == '.'); +} + +bool git_net_url_matches_pattern(git_net_url *url, const char *pattern) +{ + return matches_pattern(url, pattern, strlen(pattern)); +} + +bool git_net_url_matches_pattern_list( + git_net_url *url, + const char *pattern_list) +{ + const char *pattern, *pattern_end, *sep; + + for (pattern = pattern_list; + pattern && *pattern; + pattern = sep ? sep + 1 : NULL) { + sep = strchr(pattern, ','); + pattern_end = sep ? sep : strchr(pattern, '\0'); + + if (matches_pattern(url, pattern, (pattern_end - pattern))) + return true; + } + + return false; } void git_net_url_dispose(git_net_url *url) { if (url->username)