commit 8d02314fcaebb323c9ca3b102f8a085d66ea4633 from: Omar Polo date: Wed Sep 07 09:25:51 2022 UTC gotwebd: percent-encode generated URLs This adds a new helper function `gotweb_link' that outputs an HTML link with the parameter correctly escaped. ok stsp@ commit - 6e64c55881ec2855a3d5583227c02e4958db0ba9 commit + 8d02314fcaebb323c9ca3b102f8a085d66ea4633 blob - e77b8424231bf88c153a32dd90a19292c41dc39d blob + 04e9e72ece31adeacc0aef6f6fb7cffbaace078a --- gotwebd/fcgi.c +++ gotwebd/fcgi.c @@ -288,16 +288,12 @@ fcgi_timeout(int fd, short events, void *arg) } int -fcgi_printf(struct request *c, const char *fmt, ...) +fcgi_vprintf(struct request *c, const char *fmt, va_list ap) { - va_list ap; char *str; int r; - va_start(ap, fmt); r = vasprintf(&str, fmt, ap); - va_end(ap); - if (r == -1) { log_warn("%s: asprintf", __func__); return -1; @@ -309,6 +305,19 @@ fcgi_printf(struct request *c, const char *fmt, ...) } int +fcgi_printf(struct request *c, const char *fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = fcgi_vprintf(c, fmt, ap); + va_end(ap); + + return r; +} + +int fcgi_gen_binary_response(struct request *c, const uint8_t *data, int len) { int r; blob - 04dc980392274b236587daf89d34a45c992b64c1 blob + 5211e085ce0097066a9ec6cb94c843ffc952f29f --- gotwebd/got_operations.c +++ gotwebd/got_operations.c @@ -810,7 +810,7 @@ got_output_repo_tree(struct request *c) struct got_reflist_head refs; struct got_tree_object *tree = NULL; struct repo_dir *repo_dir = t->repo_dir; - const char *name, *index_page_str, *folder; + const char *name, *folder; char *escaped_name = NULL, *path = NULL; int nentries, i, r; @@ -849,7 +849,6 @@ got_output_repo_tree(struct request *c) nentries = got_object_tree_get_nentries(tree); - index_page_str = qs->index_page_str ? qs->index_page_str : ""; folder = qs->folder ? qs->folder : ""; for (i = 0; i < nentries; i++) { @@ -877,42 +876,76 @@ got_output_repo_tree(struct request *c) goto done; if (S_ISDIR(mode)) { - r = fcgi_printf(c, - "
\n" - "
" - "%s%s" - "
\n" /* .tree_line */ - "
 
\n" - "
\n", /* .tree_wrapper */ - index_page_str, qs->path, rc->commit_id, - folder, name, escaped_name, modestr); + struct gotweb_url url = { + .index_page = -1, + .page = -1, + .action = TREE, + .commit = rc->commit_id, + .path = qs->path, + /* `folder' is filled later */ + }; + char *path = NULL; + + if (fcgi_printf(c,"
\n" + "
") == -1) + goto done; + + if (asprintf(&path, "%s/%s", folder, name) == -1) { + error = got_error_from_errno("asprintf"); + goto done; + } + url.folder = path; + r = gotweb_link(c, &url, "%s%s", escaped_name, + modestr); + free(path); if (r == -1) goto done; + + if (fcgi_printf(c, "
\n" /* .tree_line */ + "
 
\n" + "
\n") == -1) + goto done; } else { - r = fcgi_printf(c, - "
\n" - "
" - "%s%s" - "
\n" /* .tree_line */ - "
" - "commits\n" - " | \n" - "blame\n" - "
\n" /* .tree_line_blank */ - "
\n", /* .tree_wrapper */ - index_page_str, qs->path, rc->commit_id, - folder, name, escaped_name, modestr, - index_page_str, qs->path, rc->commit_id, - folder, name, - index_page_str, qs->path, rc->commit_id, - folder, name); + struct gotweb_url url = { + .index_page = -1, + .page = -1, + .path = qs->path, + .commit = rc->commit_id, + .folder = folder, + .file = name, + }; + + if (fcgi_printf(c, "
\n" + "
") == -1) + goto done; + + url.action = BLOB; + r = gotweb_link(c, &url, "%s%s", escaped_name, + modestr); if (r == -1) goto done; + + if (fcgi_printf(c, "
\n" /* .tree_line */ + "
") == -1) + goto done; + + url.action = COMMITS; + r = gotweb_link(c, &url, "commits"); + if (r == -1) + goto done; + + if (fcgi_printf(c, " | ") == -1) + goto done; + + url.action = BLAME; + r = gotweb_link(c, &url, "blame"); + if (r == -1) + goto done; + + if (fcgi_printf(c, + "
\n" /* .tree_line_blank */ + "
\n") == -1) /* .tree_wrapper */ + goto done; } free(escaped_name); escaped_name = NULL; @@ -1069,9 +1102,7 @@ got_gotweb_blame_cb(void *arg, int nlines, int lineno, struct blame_line *bline; struct request *c = a->c; struct transport *t = c->t; - struct querystring *qs = t->qs; struct repo_dir *repo_dir = t->repo_dir; - const char *index_page_str; char *line = NULL, *eline = NULL; size_t linesize = 0; off_t offset; @@ -1121,8 +1152,6 @@ got_gotweb_blame_cb(void *arg, int nlines, int lineno, goto done; } - index_page_str = qs->index_page_str ? qs->index_page_str : ""; - while (a->lineno_cur <= a->nlines && bline->annotated) { char *smallerthan, *at, *nl, *committer; size_t len; @@ -1152,19 +1181,28 @@ got_gotweb_blame_cb(void *arg, int nlines, int lineno, if (err) goto done; - r = fcgi_printf(c, "
" + if (fcgi_printf(c, "
" "
%.*d
" - "
" - "" - "%.8s" + "
", + a->nlines_prec, a->lineno_cur) == -1) + goto done; + + r = gotweb_link(c, &(struct gotweb_url){ + .action = DIFF, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + .commit = bline->id_str, + }, "%.8s", bline->id_str); + if (r == -1) + goto done; + + r = fcgi_printf(c, "
" "
%s
" "
%s
" "
%s
" "
", /* .blame_wrapper */ - a->nlines_prec, a->lineno_cur, - index_page_str, repo_dir->name, bline->id_str, - bline->id_str, bline->datebuf, committer, eline); blob - 045fe4910629bd84e416a1c27e13e918b0403be7 blob + aafa0224a0f81173ac396f4607674dc80127339a --- gotwebd/gotweb.c +++ gotwebd/gotweb.c @@ -694,6 +694,7 @@ gotweb_render_content_type_file(struct request *c, con static const struct got_error * gotweb_render_header(struct request *c) { + const struct got_error *err = NULL; struct server *srv = c->srv; struct querystring *qs = c->t->qs; int r; @@ -743,10 +744,21 @@ gotweb_render_header(struct request *c) if (qs != NULL) { if (qs->path != NULL) { - r = fcgi_printf(c, " / " - "" - "%s", - qs->index_page, qs->path, qs->path); + char *epath; + + if (fcgi_printf(c, " / ") == -1) + goto done; + + err = gotweb_escape_html(&epath, qs->path); + if (err) + return err; + r = gotweb_link(c, &(struct gotweb_url){ + .action = SUMMARY, + .index_page = -1, + .page = -1, + .path = qs->path, + }, "%s", epath); + free(epath); if (r == -1) goto done; } @@ -826,8 +838,7 @@ gotweb_render_navs(struct request *c) struct transport *t = c->t; struct querystring *qs = t->qs; struct server *srv = c->srv; - char *nhref = NULL, *phref = NULL; - int r, disp = 0; + int r; r = fcgi_printf(c, "
\n\n" /* #nav_prev */ "\n"); /* #nav_next */ fcgi_printf(c, "
\n"); /* #np_wrapper */ done: @@ -977,8 +982,6 @@ done: t->next_id = NULL; free(t->prev_id); t->prev_id = NULL; - free(phref); - free(nhref); return error; } @@ -992,14 +995,11 @@ gotweb_render_index(struct request *c) struct repo_dir *repo_dir = NULL; DIR *d; struct dirent **sd_dent = NULL; - const char *index_page_str; char *c_path = NULL; struct stat st; unsigned int d_cnt, d_i, d_disp = 0; int r; - index_page_str = qs->index_page_str ? qs->index_page_str : ""; - d = opendir(srv->repos_path); if (d == NULL) { error = got_error_from_errno2("opendir", srv->repos_path); @@ -1091,17 +1091,22 @@ render: d_disp++; t->prev_disp++; - r = fcgi_printf(c, "
\n" - "
" - "" - " %s " - "" - "
", /* .index_project */ - index_page_str, repo_dir->name, - repo_dir->name); + if (fcgi_printf(c, "
\n" + "
") == -1) + goto done; + + r = gotweb_link(c, &(struct gotweb_url){ + .action = SUMMARY, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + }, "%s", repo_dir->name); if (r == -1) goto done; + if (fcgi_printf(c, "
") == -1) /* .index_project */ + goto done; + if (srv->show_repo_description) { r = fcgi_printf(c, "
\n" @@ -1124,32 +1129,71 @@ render: goto done; } - r = fcgi_printf(c, "\n", /* .index_wrapper */ - index_page_str, repo_dir->name, - index_page_str, repo_dir->name, - index_page_str, repo_dir->name, - index_page_str, repo_dir->name, - index_page_str, repo_dir->name); + "
\n" /* .navs_wrapper */ + "
\n"); /* .index_wrapper */ if (r == -1) goto done; @@ -1243,13 +1287,10 @@ gotweb_render_briefs(struct request *c) struct transport *t = c->t; struct querystring *qs = t->qs; struct repo_dir *repo_dir = t->repo_dir; - const char *index_page_str; char *smallerthan, *newline; char *age = NULL, *author = NULL, *msg = NULL; int r; - index_page_str = qs->index_page_str ? qs->index_page_str : ""; - r = fcgi_printf(c, "
\n" "
Commit Briefs
\n" "
\n" /* #briefs_title_wrapper */ @@ -1287,16 +1328,22 @@ gotweb_render_briefs(struct request *c) r = fcgi_printf(c, "
%s
\n" "
%s
\n" - "
" - "%s", - age, - author, - index_page_str, repo_dir->name, rc->commit_id, qs->headref, - msg); + "
", + age, author); if (r == -1) goto done; + r = gotweb_link(c, &(struct gotweb_url){ + .action = DIFF, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + .commit = rc->commit_id, + .headref = qs->headref, + }, "%s", msg); + if (r == -1) + goto done; + if (rc->refs_str) { char *refs; @@ -1313,20 +1360,40 @@ gotweb_render_briefs(struct request *c) goto done; r = fcgi_printf(c, "\n" /* .navs_wrapper */ - "
\n", - index_page_str, repo_dir->name, rc->commit_id, qs->headref, - index_page_str, repo_dir->name, rc->commit_id, qs->headref); + "\n" /* .navs */ + "
\n" /* .navs_wrapper */ + "
\n") == -1) + goto done; + free(age); age = NULL; free(author); @@ -1355,14 +1422,10 @@ gotweb_render_commits(struct request *c) struct repo_commit *rc = NULL; struct server *srv = c->srv; struct transport *t = c->t; - struct querystring *qs = t->qs; struct repo_dir *repo_dir = t->repo_dir; - const char *index_page_str; char *age = NULL, *author = NULL, *msg = NULL; int r; - index_page_str = qs->index_page_str ? qs->index_page_str : ""; - r = fcgi_printf(c, "
\n" "
Commits
\n" "
\n" /* .commits_title_wrapper */ @@ -1404,21 +1467,38 @@ gotweb_render_commits(struct request *c) if (r == -1) goto done; - r = fcgi_printf(c, "\n" /* .navs_wrapper */ - "
\n", - index_page_str, repo_dir->name, rc->commit_id, - index_page_str, repo_dir->name, rc->commit_id); + if (fcgi_printf(c, "\n" /* .navs_wrapper */ + "
\n") == -1) + goto done; + free(age); age = NULL; free(author); @@ -1449,12 +1529,10 @@ gotweb_render_branches(struct request *c) struct transport *t = c->t; struct querystring *qs = t->qs; struct got_repository *repo = t->repo; - const char *index_page_str; + char *escaped_refname = NULL; char *age = NULL; int r; - index_page_str = qs->index_page_str ? qs->index_page_str : ""; - TAILQ_INIT(&refs); error = got_ref_list(&refs, repo, "refs/heads", @@ -1471,7 +1549,6 @@ gotweb_render_branches(struct request *c) TAILQ_FOREACH(re, &refs, entry) { const char *refname = NULL; - char *escaped_refname = NULL; if (got_ref_is_symbolic(re->ref)) continue; @@ -1498,41 +1575,77 @@ gotweb_render_branches(struct request *c) r = fcgi_printf(c, "
\n" "
%s
\n" "
 
\n" - "
" - "" - "%s" - "
\n" /* .branch */ + "
", age); + if (r == -1) + goto done; + + r = gotweb_link(c, &(struct gotweb_url){ + .action = SUMMARY, + .index_page = -1, + .page = -1, + .path = qs->path, + .headref = refname, + }, "%s", escaped_refname); + if (r == -1) + goto done; + + if (fcgi_printf(c, "
\n" /* .branch */ "\n" /* .navs_wrapper */ + "\n" /* .navs */ + "
\n" /* .navs_wrapper */ "
\n" - "
\n", /* .branches_wrapper */ - age ? age : "", - index_page_str, qs->path, refname, - escaped_refname, - index_page_str, qs->path, refname, - index_page_str, qs->path, refname, - index_page_str, qs->path, refname); - free(escaped_refname); + "
\n"); /* .branches_wrapper */ if (r == -1) goto done; free(age); age = NULL; - + free(escaped_refname); + escaped_refname = NULL; } fcgi_printf(c, "
\n"); /* #branches_content */ done: free(age); + free(escaped_refname); got_ref_list_free(&refs); return error; } @@ -1813,12 +1926,9 @@ gotweb_render_tags(struct request *c) struct transport *t = c->t; struct querystring *qs = t->qs; struct repo_dir *repo_dir = t->repo_dir; - const char *index_page_str; char *age = NULL, *tagname = NULL, *msg = NULL, *newline; int r, commit_found = 0; - index_page_str = qs->index_page_str ? qs->index_page_str : ""; - if (qs->action == BRIEFS) { qs->action = TAGS; error = got_get_repo_tags(c, D_MAXSLCOMMDISP); @@ -1868,32 +1978,66 @@ gotweb_render_tags(struct request *c) goto done; } - r = fcgi_printf(c, "
%s
\n" + if (fcgi_printf(c, "
%s
\n" "
%s
\n" - "
" - "" - "%s" - "
\n" /* .tag_log */ + "
", age, tagname) == -1) + goto done; + + r = gotweb_link(c, &(struct gotweb_url){ + .action = TAG, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + .commit = rt->commit_id, + }, "%s", msg ? msg : ""); + if (r == -1) + goto done; + + if (fcgi_printf(c, "
\n" /* .tag_log */ "