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`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
diff --git a/src/netops.c b/src/netops.c
index 0622622..26cb607 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;
}