diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2018-03-03 20:13:30 +0000 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2018-03-19 16:08:01 -0700 |
commit | 60e7848e1e3cb3a1a3e4f3aa08d353bab90d47c0 (patch) | |
tree | d8b331a26b520c11fcaed83a86b6872399bd8c7b | |
parent | 6f57790657c447051986ec95b3ba474134d71386 (diff) | |
download | libgit2-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.c | 115 |
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; } |