Skip to content

Commit 60e7848

Browse files
committed
gitno_extract_url_parts: use git_bufs
Now that we can decode percent-encoded strings as part of `git_buf`s, use that decoder in `gitno_extract_url_parts`.
1 parent 6f57790 commit 60e7848

File tree

1 file changed

+73
-42
lines changed

1 file changed

+73
-42
lines changed

src/netops.c

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -225,64 +225,95 @@ char* gitno_unescape(char *str)
225225
}
226226

227227
int gitno_extract_url_parts(
228-
char **host,
229-
char **port,
230-
char **path,
231-
char **username,
232-
char **password,
233-
const char *url,
234-
const char *default_port)
228+
char **host_out,
229+
char **port_out,
230+
char **path_out,
231+
char **username_out,
232+
char **password_out,
233+
const char *url,
234+
const char *default_port)
235235
{
236236
struct http_parser_url u = {0};
237-
const char *_host, *_port, *_path, *_userinfo;
237+
bool has_host, has_port, has_path, has_userinfo;
238+
git_buf host = GIT_BUF_INIT,
239+
port = GIT_BUF_INIT,
240+
path = GIT_BUF_INIT,
241+
username = GIT_BUF_INIT,
242+
password = GIT_BUF_INIT;
243+
int error = 0;
238244

239245
if (http_parser_parse_url(url, strlen(url), false, &u)) {
240246
giterr_set(GITERR_NET, "malformed URL '%s'", url);
241-
return GIT_EINVALIDSPEC;
247+
error = GIT_EINVALIDSPEC;
248+
goto done;
242249
}
243250

244-
_host = url+u.field_data[UF_HOST].off;
245-
_port = url+u.field_data[UF_PORT].off;
246-
_path = url+u.field_data[UF_PATH].off;
247-
_userinfo = url+u.field_data[UF_USERINFO].off;
251+
has_host = !!(u.field_set & (1 << UF_HOST));
252+
has_port = !!(u.field_set & (1 << UF_PORT));
253+
has_path = !!(u.field_set & (1 << UF_PATH));
254+
has_userinfo = !!(u.field_set & (1 << UF_USERINFO));
248255

249-
if (u.field_set & (1 << UF_HOST)) {
250-
*host = git__substrdup(_host, u.field_data[UF_HOST].len);
251-
GITERR_CHECK_ALLOC(*host);
256+
if (has_host) {
257+
const char *url_host = url + u.field_data[UF_HOST].off;
258+
size_t url_host_len = u.field_data[UF_HOST].len;
259+
git_buf_put(&host, url_host, url_host_len);
252260
}
253261

254-
if (u.field_set & (1 << UF_PORT))
255-
*port = git__substrdup(_port, u.field_data[UF_PORT].len);
256-
else
257-
*port = git__strdup(default_port);
258-
GITERR_CHECK_ALLOC(*port);
262+
if (has_port) {
263+
const char *url_port = url + u.field_data[UF_PORT].off;
264+
size_t url_port_len = u.field_data[UF_PORT].len;
265+
git_buf_put(&port, url_port, url_port_len);
266+
} else {
267+
git_buf_puts(&port, default_port);
268+
}
259269

260-
if (path) {
261-
if (u.field_set & (1 << UF_PATH)) {
262-
*path = git__substrdup(_path, u.field_data[UF_PATH].len);
263-
GITERR_CHECK_ALLOC(*path);
264-
} else {
265-
git__free(*port);
266-
*port = NULL;
267-
git__free(*host);
268-
*host = NULL;
269-
giterr_set(GITERR_NET, "invalid url, missing path");
270-
return GIT_EINVALIDSPEC;
271-
}
270+
if (has_path && path_out) {
271+
const char *url_path = url + u.field_data[UF_PATH].off;
272+
size_t url_path_len = u.field_data[UF_PATH].len;
273+
git_buf_decode_percent(&path, url_path, url_path_len);
274+
} else if (path_out) {
275+
giterr_set(GITERR_NET, "invalid url, missing path");
276+
error = GIT_EINVALIDSPEC;
277+
goto done;
272278
}
273279

274-
if (u.field_set & (1 << UF_USERINFO)) {
275-
const char *colon = memchr(_userinfo, ':', u.field_data[UF_USERINFO].len);
280+
if (has_userinfo) {
281+
const char *url_userinfo = url + u.field_data[UF_USERINFO].off;
282+
size_t url_userinfo_len = u.field_data[UF_USERINFO].len;
283+
const char *colon = memchr(url_userinfo, ':', url_userinfo_len);
284+
276285
if (colon) {
277-
*username = gitno_unescape(git__substrdup(_userinfo, colon - _userinfo));
278-
*password = gitno_unescape(git__substrdup(colon+1, u.field_data[UF_USERINFO].len - (colon+1-_userinfo)));
279-
GITERR_CHECK_ALLOC(*password);
286+
const char *url_username = url_userinfo;
287+
size_t url_username_len = colon - url_userinfo;
288+
const char *url_password = colon + 1;
289+
size_t url_password_len = url_userinfo_len - (url_username_len + 1);
290+
291+
git_buf_decode_percent(&username, url_username, url_username_len);
292+
git_buf_decode_percent(&password, url_password, url_password_len);
280293
} else {
281-
*username = git__substrdup(_userinfo, u.field_data[UF_USERINFO].len);
294+
git_buf_decode_percent(&username, url_userinfo, url_userinfo_len);
282295
}
283-
GITERR_CHECK_ALLOC(*username);
284-
285296
}
286297

287-
return 0;
298+
if (git_buf_oom(&host) ||
299+
git_buf_oom(&port) ||
300+
git_buf_oom(&path) ||
301+
git_buf_oom(&username) ||
302+
git_buf_oom(&password))
303+
return -1;
304+
305+
*host_out = git_buf_detach(&host);
306+
*port_out = git_buf_detach(&port);
307+
if (path_out)
308+
*path_out = git_buf_detach(&path);
309+
*username_out = git_buf_detach(&username);
310+
*password_out = git_buf_detach(&password);
311+
312+
done:
313+
git_buf_free(&host);
314+
git_buf_free(&port);
315+
git_buf_free(&path);
316+
git_buf_free(&username);
317+
git_buf_free(&password);
318+
return error;
288319
}

0 commit comments

Comments
 (0)