summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-03-03 20:13:30 +0000
committerEdward Thomson <ethomson@edwardthomson.com>2018-03-19 16:08:01 -0700
commit60e7848e1e3cb3a1a3e4f3aa08d353bab90d47c0 (patch)
treed8b331a26b520c11fcaed83a86b6872399bd8c7b
parent6f57790657c447051986ec95b3ba474134d71386 (diff)
downloadlibgit2-60e7848e1e3cb3a1a3e4f3aa08d353bab90d47c0.tar.gz
gitno_extract_url_parts: use `git_buf`s
Now that we can decode percent-encoded strings as part of `git_buf`s, use that decoder in `gitno_extract_url_parts`.
-rw-r--r--src/netops.c115
1 files changed, 73 insertions, 42 deletions
diff --git a/src/netops.c b/src/netops.c
index 0622622de..26cb6079d 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -225,64 +225,95 @@ char* gitno_unescape(char *str)
}
int gitno_extract_url_parts(
- char **host,
- char **port,
- char **path,
- char **username,
- char **password,
- const char *url,
- const char *default_port)
+ char **host_out,
+ char **port_out,
+ char **path_out,
+ char **username_out,
+ char **password_out,
+ const char *url,
+ const char *default_port)
{
struct http_parser_url u = {0};
- const char *_host, *_port, *_path, *_userinfo;
+ bool has_host, has_port, has_path, has_userinfo;
+ git_buf host = GIT_BUF_INIT,
+ port = GIT_BUF_INIT,
+ path = GIT_BUF_INIT,
+ username = GIT_BUF_INIT,
+ password = GIT_BUF_INIT;
+ int error = 0;
if (http_parser_parse_url(url, strlen(url), false, &u)) {
giterr_set(GITERR_NET, "malformed URL '%s'", url);
- return GIT_EINVALIDSPEC;
+ error = GIT_EINVALIDSPEC;
+ goto done;
}
- _host = url+u.field_data[UF_HOST].off;
- _port = url+u.field_data[UF_PORT].off;
- _path = url+u.field_data[UF_PATH].off;
- _userinfo = url+u.field_data[UF_USERINFO].off;
+ has_host = !!(u.field_set & (1 << UF_HOST));
+ has_port = !!(u.field_set & (1 << UF_PORT));
+ has_path = !!(u.field_set & (1 << UF_PATH));
+ has_userinfo = !!(u.field_set & (1 << UF_USERINFO));
- if (u.field_set & (1 << UF_HOST)) {
- *host = git__substrdup(_host, u.field_data[UF_HOST].len);
- GITERR_CHECK_ALLOC(*host);
+ if (has_host) {
+ const char *url_host = url + u.field_data[UF_HOST].off;
+ size_t url_host_len = u.field_data[UF_HOST].len;
+ git_buf_put(&host, url_host, url_host_len);
}
- if (u.field_set & (1 << UF_PORT))
- *port = git__substrdup(_port, u.field_data[UF_PORT].len);
- else
- *port = git__strdup(default_port);
- GITERR_CHECK_ALLOC(*port);
+ if (has_port) {
+ const char *url_port = url + u.field_data[UF_PORT].off;
+ size_t url_port_len = u.field_data[UF_PORT].len;
+ git_buf_put(&port, url_port, url_port_len);
+ } else {
+ git_buf_puts(&port, default_port);
+ }
- if (path) {
- if (u.field_set & (1 << UF_PATH)) {
- *path = git__substrdup(_path, u.field_data[UF_PATH].len);
- GITERR_CHECK_ALLOC(*path);
- } else {
- git__free(*port);
- *port = NULL;
- git__free(*host);
- *host = NULL;
- giterr_set(GITERR_NET, "invalid url, missing path");
- return GIT_EINVALIDSPEC;
- }
+ if (has_path && path_out) {
+ const char *url_path = url + u.field_data[UF_PATH].off;
+ size_t url_path_len = u.field_data[UF_PATH].len;
+ git_buf_decode_percent(&path, url_path, url_path_len);
+ } else if (path_out) {
+ giterr_set(GITERR_NET, "invalid url, missing path");
+ error = GIT_EINVALIDSPEC;
+ goto done;
}
- if (u.field_set & (1 << UF_USERINFO)) {
- const char *colon = memchr(_userinfo, ':', u.field_data[UF_USERINFO].len);
+ if (has_userinfo) {
+ const char *url_userinfo = url + u.field_data[UF_USERINFO].off;
+ size_t url_userinfo_len = u.field_data[UF_USERINFO].len;
+ const char *colon = memchr(url_userinfo, ':', url_userinfo_len);
+
if (colon) {
- *username = gitno_unescape(git__substrdup(_userinfo, colon - _userinfo));
- *password = gitno_unescape(git__substrdup(colon+1, u.field_data[UF_USERINFO].len - (colon+1-_userinfo)));
- GITERR_CHECK_ALLOC(*password);
+ const char *url_username = url_userinfo;
+ size_t url_username_len = colon - url_userinfo;
+ const char *url_password = colon + 1;
+ size_t url_password_len = url_userinfo_len - (url_username_len + 1);
+
+ git_buf_decode_percent(&username, url_username, url_username_len);
+ git_buf_decode_percent(&password, url_password, url_password_len);
} else {
- *username = git__substrdup(_userinfo, u.field_data[UF_USERINFO].len);
+ git_buf_decode_percent(&username, url_userinfo, url_userinfo_len);
}
- GITERR_CHECK_ALLOC(*username);
-
}
- return 0;
+ if (git_buf_oom(&host) ||
+ git_buf_oom(&port) ||
+ git_buf_oom(&path) ||
+ git_buf_oom(&username) ||
+ git_buf_oom(&password))
+ return -1;
+
+ *host_out = git_buf_detach(&host);
+ *port_out = git_buf_detach(&port);
+ if (path_out)
+ *path_out = git_buf_detach(&path);
+ *username_out = git_buf_detach(&username);
+ *password_out = git_buf_detach(&password);
+
+done:
+ git_buf_free(&host);
+ git_buf_free(&port);
+ git_buf_free(&path);
+ git_buf_free(&username);
+ git_buf_free(&password);
+ return error;
}