summaryrefslogtreecommitdiff
path: root/src/netops.c
diff options
context:
space:
mode:
authorBen Straub <bs@github.com>2013-09-25 20:41:56 -0700
committerBen Straub <bs@github.com>2013-09-25 20:41:56 -0700
commit8988688c479c6e511432187c7e7e746aefb23c08 (patch)
tree1d86d7baa31181681e8a401f855e6eafa1d77e6c /src/netops.c
parentac316e743878908df762cc0ea07a71cbee5c5802 (diff)
downloadlibgit2-8988688c479c6e511432187c7e7e746aefb23c08.tar.gz
Migrate redirect URL handling to common utility
Diffstat (limited to 'src/netops.c')
-rw-r--r--src/netops.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/netops.c b/src/netops.c
index c1e74546f..bda064cfb 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -573,6 +573,81 @@ int gitno_select_in(gitno_buffer *buf, long int sec, long int usec)
return select((int)buf->socket->socket + 1, &fds, NULL, NULL, &tv);
}
+static const char *prefix_http = "http://";
+static const char *prefix_https = "https://";
+
+int gitno_connection_data_from_url(
+ gitno_connection_data *data,
+ const char *url,
+ const char *service_suffix,
+ const char *original_host,
+ bool original_use_ssl)
+{
+ int error = 0;
+ const char *default_port = NULL;
+
+ /* service_suffix is optional */
+ assert(data && url);
+
+ if (!git__prefixcmp(url, prefix_http)) {
+ url = url + strlen(prefix_http);
+ default_port = "80";
+
+ if (data->use_ssl) {
+ giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP is not allowed");
+ return -1;
+ }
+ }
+
+ if (!git__prefixcmp(url, prefix_https)) {
+ url += strlen(prefix_https);
+ default_port = "443";
+ data->use_ssl = true;
+ }
+
+ if (!default_port) {
+ giterr_set(GITERR_NET, "Unrecognized URL prefix");
+ return -1;
+ }
+
+ error = gitno_extract_url_parts(
+ &data->host, &data->port, &data->user, &data->pass,
+ url, default_port);
+
+ if (!error) {
+ const char *path = strchr(url, '/');
+ size_t pathlen = strlen(path);
+ size_t suffixlen = service_suffix ? strlen(service_suffix) : 0;
+
+ if (suffixlen &&
+ !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen))
+ data->path = git__strndup(path, pathlen - suffixlen);
+ else
+ data->path = git__strdup(path);
+
+ /* Check for errors in the resulting data */
+ if (original_use_ssl && !data->use_ssl) {
+ giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP not allowed");
+ error = -1;
+ }
+ if (original_host && url[0] != '/' && strcmp(original_host, data->host)) {
+ giterr_set(GITERR_NET, "Cross host redirect not allowed");
+ error = -1;
+ }
+ }
+
+ return error;
+}
+
+void gitno_connection_data_free_ptrs(gitno_connection_data *d)
+{
+ git__free(d->host); d->host = NULL;
+ git__free(d->port); d->port = NULL;
+ git__free(d->path); d->path = NULL;
+ git__free(d->user); d->user = NULL;
+ git__free(d->pass); d->pass = NULL;
+}
+
int gitno_extract_url_parts(
char **host,
char **port,