Commit 60e7848e by Edward Thomson

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`.
parent 6f577906
...@@ -225,64 +225,95 @@ char* gitno_unescape(char *str) ...@@ -225,64 +225,95 @@ char* gitno_unescape(char *str)
} }
int gitno_extract_url_parts( int gitno_extract_url_parts(
char **host, char **host_out,
char **port, char **port_out,
char **path, char **path_out,
char **username, char **username_out,
char **password, char **password_out,
const char *url, const char *url,
const char *default_port) const char *default_port)
{ {
struct http_parser_url u = {0}; 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)) { if (http_parser_parse_url(url, strlen(url), false, &u)) {
giterr_set(GITERR_NET, "malformed URL '%s'", url); giterr_set(GITERR_NET, "malformed URL '%s'", url);
return GIT_EINVALIDSPEC; error = GIT_EINVALIDSPEC;
goto done;
} }
_host = url+u.field_data[UF_HOST].off; has_host = !!(u.field_set & (1 << UF_HOST));
_port = url+u.field_data[UF_PORT].off; has_port = !!(u.field_set & (1 << UF_PORT));
_path = url+u.field_data[UF_PATH].off; has_path = !!(u.field_set & (1 << UF_PATH));
_userinfo = url+u.field_data[UF_USERINFO].off; has_userinfo = !!(u.field_set & (1 << UF_USERINFO));
if (u.field_set & (1 << UF_HOST)) { if (has_host) {
*host = git__substrdup(_host, u.field_data[UF_HOST].len); const char *url_host = url + u.field_data[UF_HOST].off;
GITERR_CHECK_ALLOC(*host); 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)) if (has_port) {
*port = git__substrdup(_port, u.field_data[UF_PORT].len); const char *url_port = url + u.field_data[UF_PORT].off;
else size_t url_port_len = u.field_data[UF_PORT].len;
*port = git__strdup(default_port); git_buf_put(&port, url_port, url_port_len);
GITERR_CHECK_ALLOC(*port); } else {
git_buf_puts(&port, default_port);
}
if (path) { if (has_path && path_out) {
if (u.field_set & (1 << UF_PATH)) { const char *url_path = url + u.field_data[UF_PATH].off;
*path = git__substrdup(_path, u.field_data[UF_PATH].len); size_t url_path_len = u.field_data[UF_PATH].len;
GITERR_CHECK_ALLOC(*path); git_buf_decode_percent(&path, url_path, url_path_len);
} else { } else if (path_out) {
git__free(*port); giterr_set(GITERR_NET, "invalid url, missing path");
*port = NULL; error = GIT_EINVALIDSPEC;
git__free(*host); goto done;
*host = NULL;
giterr_set(GITERR_NET, "invalid url, missing path");
return GIT_EINVALIDSPEC;
}
} }
if (u.field_set & (1 << UF_USERINFO)) { if (has_userinfo) {
const char *colon = memchr(_userinfo, ':', u.field_data[UF_USERINFO].len); 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) { if (colon) {
*username = gitno_unescape(git__substrdup(_userinfo, colon - _userinfo)); const char *url_username = url_userinfo;
*password = gitno_unescape(git__substrdup(colon+1, u.field_data[UF_USERINFO].len - (colon+1-_userinfo))); size_t url_username_len = colon - url_userinfo;
GITERR_CHECK_ALLOC(*password); 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 { } 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;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment