Download raw body.
gotwebd: some html fixes
On Fri, Aug 19, 2022 at 07:30:59PM +0200, Omar Polo wrote: > as all the tragic stories goes, it all started with a simple goal of > making the W3C validator happy and endend up in pain and (html) > escaping. > > The w3c validator complained about three things: > > - invalid target=_sotd in a link > - unexpected `alt' attribute on some links > - missing lang on the html tag. > > the last one is questionable: we don't really know in what language > the commits will be (especially when they don't need to be in the same > language!) but still i think that since the whole UI is in english > there's not much harm in setting lang=en. > > Then, I saw a few places where we forgot to escape some strings and > re-cheked all the fcgi_printf calls. > > So, I'd like to propose diff below. it's actually two commit > together, I'm bundling them here because it's easier. It fixes the > issue reported by the w3c validator and escapes all the potential > unsafe strings I've found. > > There's still a bit that's missing and it's properly URL-escape links, > which is different from the html escaping, but i'd like to address > that in a follow up commit. gotwebd needs to learn how to > percent-decode querystrings too. > > I have this diff on my instance, now I can render 'funny' trees with > files like '<script>' :) > > https://git.omarpolo.com/?index_page=0&path=testing.git&action=tree&commit=78397ac198dbef68c371cef13a4fb986ff93fe34&headref=HEAD > > (note that the first two links don't work because of the escaping) > > thoughts/ok? Ok, although I'm not sold on the lang=en. > > diff refs/remotes/got/main refs/heads/main > commit - 01498c42e0fc9fb6355312a236656cf2f36cebc0 > commit + 0e9860257eadd668942affe9f2846a6e09603e3b > blob - 35735937cc54916d0fa7248397a0a66248c0c510 > blob + 18dca123b78589b4efb8482bc4caa54e1aae7176 > --- gotwebd/got_operations.c > +++ gotwebd/got_operations.c > @@ -830,7 +830,7 @@ got_output_repo_tree(struct request *c) > struct got_tree_object *tree = NULL; > struct repo_dir *repo_dir = t->repo_dir; > const char *name, *index_page_str, *folder; > - char *id_str = NULL; > + char *id_str = NULL, *escaped_name; > char *path = NULL, *in_repo_path = NULL, *modestr = NULL; > int nentries, i, r; > > @@ -920,8 +920,12 @@ got_output_repo_tree(struct request *c) > } > } > > + name = got_tree_entry_get_name(te); > + error = gotweb_escape_html(&escaped_name, name); > + if (error) > + goto done; > + > if (S_ISDIR(mode)) { > - name = got_tree_entry_get_name(te); > r = fcgi_printf(c, > "<div class='tree_wrapper'>\n" > "<div class='tree_line'>" > @@ -932,11 +936,10 @@ got_output_repo_tree(struct request *c) > "<div class='tree_line_blank'> </div>\n" > "</div>\n", /* .tree_wrapper */ > index_page_str, qs->path, rc->commit_id, > - folder, name, name, modestr); > + folder, name, escaped_name, modestr); > if (r == -1) > goto done; > } else { > - name = got_tree_entry_get_name(te); > r = fcgi_printf(c, > "<div class='tree_wrapper'>\n" > "<div class='tree_line'>" > @@ -952,7 +955,7 @@ got_output_repo_tree(struct request *c) > "</div>\n" /* .tree_line_blank */ > "</div>\n", /* .tree_wrapper */ > index_page_str, qs->path, rc->commit_id, > - folder, name, name, modestr, > + folder, name, escaped_name, modestr, > index_page_str, qs->path, rc->commit_id, > folder, name, > index_page_str, qs->path, rc->commit_id, > blob - 9358e442cb79338b33110402f61e9bd695a9690d > blob + 4dfa5656c52bd7eff6cdc8b2196476bb8e664581 > --- gotwebd/gotweb.c > +++ gotwebd/gotweb.c > @@ -655,7 +655,7 @@ gotweb_render_header(struct request *c) > strlcpy(droot, "/", sizeof(droot)); > > r = fcgi_printf(c, "<!doctype html>\n" > - "<html>\n" > + "<html lang=\"en\">\n" > "<head>\n" > "<title>%s</title>\n" > "<meta charset='utf-8' />\n" > @@ -676,14 +676,14 @@ gotweb_render_header(struct request *c) > "<div id='gw_body'>\n" > "<div id='header'>\n" > "<div id='got_link'>" > - "<a href='%s' target='_sotd'>" > + "<a href='%s' target='_blank'>" > "<img src='%s%s' alt='logo' id='logo' />" > "</a>\n" > "</div>\n" /* #got_link */ > "</div>\n" /* #header */ > "<div id='site_path'>\n" > "<div id='site_link'>\n" > - "<a href='/%s?index_page=%d' alt='sitelink'>%s</a>", > + "<a href='/%s?index_page=%d'>%s</a>", > srv->site_name, > droot, srv->custom_css, > srv->logo_url, > @@ -695,8 +695,8 @@ gotweb_render_header(struct request *c) > if (qs != NULL) { > if (qs->path != NULL) { > r = fcgi_printf(c, " / " > - "<a href='/%s?index_page=%d&path=%s&action=summary'" > - " alt='summlink'>%s</a>", > + "<a href='/%s?index_page=%d&path=%s&action=summary'>" > + "%s</a>", > c->document_root, qs->index_page, qs->path, > qs->path); > if (r == -1) > @@ -1136,7 +1136,7 @@ gotweb_render_blame(struct request *c) > const struct got_error *error = NULL; > struct transport *t = c->t; > struct repo_commit *rc = NULL; > - char *age = NULL; > + char *age = NULL, *msg = NULL; > int r; > > error = got_get_repo_commits(c, 1); > @@ -1148,6 +1148,9 @@ gotweb_render_blame(struct request *c) > error = gotweb_get_time_str(&age, rc->committer_time, TM_LONG); > if (error) > goto done; > + error = gotweb_escape_html(&msg, rc->commit_msg); > + if (error) > + goto done; > > r = fcgi_printf(c, "<div id='blame_title_wrapper'>\n" > "<div id='blame_title'>Blame</div>\n" > @@ -1164,7 +1167,7 @@ gotweb_render_blame(struct request *c) > "<div class='dotted_line'></div>\n" > "<div id='blame'>\n", > age ? age : "", > - rc->commit_msg); > + msg); > if (r == -1) > goto done; > > @@ -1175,6 +1178,7 @@ gotweb_render_blame(struct request *c) > fcgi_printf(c, "</div>\n" /* #blame */ > "</div>\n"); /* #blame_content */ > done: > + free(msg); > return error; > } > > @@ -1189,7 +1193,7 @@ gotweb_render_briefs(struct request *c) > struct repo_dir *repo_dir = t->repo_dir; > const char *index_page_str; > char *smallerthan, *newline; > - char *age = NULL; > + char *age = NULL, *author = NULL, *msg = NULL; > int r; > > index_page_str = qs->index_page_str ? qs->index_page_str : ""; > @@ -1222,22 +1226,34 @@ gotweb_render_briefs(struct request *c) > if (newline) > *newline = '\0'; > > + error = gotweb_escape_html(&author, rc->author); > + if (error) > + goto done; > + error = gotweb_escape_html(&msg, rc->commit_msg); > + if (error) > + goto done; > + > r = fcgi_printf(c, "<div class='briefs_age'>%s</div>\n" > "<div class='briefs_author'>%s</div>\n" > "<div class='briefs_log'>" > "<a href='?index_page=%s&path=%s&action=diff&commit=%s" > "&headref=%s'>%s</a>", > age ? age : "", > - rc->author, > + author, > index_page_str, repo_dir->name, rc->commit_id, qs->headref, > - rc->commit_msg); > + msg); > if (r == -1) > goto done; > > if (rc->refs_str) { > + char *refs; > + > + error = gotweb_escape_html(&refs, rc->refs_str); > + if (error) > + goto done; > r = fcgi_printf(c, > - " <span class='refs_str'>(%s)</span>", > - rc->refs_str); > + " <span class='refs_str'>(%s)</span>", refs); > + free(refs); > if (r == -1) > goto done; > } > @@ -1261,6 +1277,10 @@ gotweb_render_briefs(struct request *c) > > free(age); > age = NULL; > + free(author); > + author = NULL; > + free(msg); > + msg = NULL; > } > > if (t->next_id || t->prev_id) { > @@ -1271,6 +1291,8 @@ gotweb_render_briefs(struct request *c) > fcgi_printf(c, "</div>\n"); /* #briefs_content */ > done: > free(age); > + free(author); > + free(msg); > return error; > } > > @@ -1284,7 +1306,7 @@ gotweb_render_commits(struct request *c) > struct querystring *qs = t->qs; > struct repo_dir *repo_dir = t->repo_dir; > const char *index_page_str; > - char *age = NULL, *author = NULL; > + char *age = NULL, *author = NULL, *msg = NULL; > int r; > > index_page_str = qs->index_page_str ? qs->index_page_str : ""; > @@ -1307,6 +1329,9 @@ gotweb_render_commits(struct request *c) > error = gotweb_escape_html(&author, rc->author); > if (error) > goto done; > + error = gotweb_escape_html(&msg, rc->commit_msg); > + if (error) > + goto done; > > r = fcgi_printf(c, "<div class='commits_header_wrapper'>\n" > "<div class='commits_header'>\n" > @@ -1321,9 +1346,9 @@ gotweb_render_commits(struct request *c) > "<div class='dotted_line'></div>\n" > "<div class='commit'>\n%s</div>\n", > rc->commit_id, > - author ? author : "", > + author, > age ? age : "", > - rc->commit_msg); > + msg); > if (r == -1) > goto done; > > @@ -1344,6 +1369,8 @@ gotweb_render_commits(struct request *c) > age = NULL; > free(author); > author = NULL; > + free(msg); > + msg = NULL; > } > > if (t->next_id || t->prev_id) { > @@ -1354,6 +1381,8 @@ gotweb_render_commits(struct request *c) > fcgi_printf(c, "</div>\n"); /* .commits_content */ > done: > free(age); > + free(author); > + free(msg); > return error; > } > > @@ -1387,12 +1416,13 @@ gotweb_render_branches(struct request *c) > goto done; > > TAILQ_FOREACH(re, &refs, entry) { > - char *refname = NULL; > + const char *refname = NULL; > + char *escaped_refname = NULL; > > if (got_ref_is_symbolic(re->ref)) > continue; > > - refname = strdup(got_ref_get_name(re->ref)); > + refname = got_ref_get_name(re->ref); > if (refname == NULL) { > error = got_error_from_errno("strdup"); > goto done; > @@ -1407,6 +1437,9 @@ gotweb_render_branches(struct request *c) > > if (strncmp(refname, "refs/heads/", 11) == 0) > refname += 11; > + error = gotweb_escape_html(&escaped_refname, refname); > + if (error) > + goto done; > > r = fcgi_printf(c, "<div class='branches_wrapper'>\n" > "<div class='branches_age'>%s</div>\n" > @@ -1431,10 +1464,11 @@ gotweb_render_branches(struct request *c) > "</div>\n", /* .branches_wrapper */ > age ? age : "", > index_page_str, qs->path, refname, > - refname, > + escaped_refname, > index_page_str, qs->path, refname, > index_page_str, qs->path, refname, > index_page_str, qs->path, refname); > + free(escaped_refname); > if (r == -1) > goto done; > > @@ -1453,7 +1487,7 @@ gotweb_render_tree(struct request *c) > const struct got_error *error = NULL; > struct transport *t = c->t; > struct repo_commit *rc = NULL; > - char *age = NULL; > + char *age = NULL, *msg = NULL; > int r; > > error = got_get_repo_commits(c, 1); > @@ -1466,6 +1500,10 @@ gotweb_render_tree(struct request *c) > if (error) > goto done; > > + error = gotweb_escape_html(&msg, rc->commit_msg); > + if (error) > + goto done; > + > r = fcgi_printf(c, "<div id='tree_title_wrapper'>\n" > "<div id='tree_title'>Tree</div>\n" > "</div>\n" /* #tree_title_wrapper */ > @@ -1484,7 +1522,7 @@ gotweb_render_tree(struct request *c) > "<div id='tree'>\n", > rc->tree_id, > age ? age : "", > - rc->commit_msg); > + msg); > if (r == -1) > goto done; > > @@ -1495,6 +1533,7 @@ gotweb_render_tree(struct request *c) > fcgi_printf(c, "</div>\n"); /* #tree */ > fcgi_printf(c, "</div>\n"); /* #tree_content */ > done: > + free(msg); > return error; > } > > @@ -1504,7 +1543,7 @@ gotweb_render_diff(struct request *c) > const struct got_error *error = NULL; > struct transport *t = c->t; > struct repo_commit *rc = NULL; > - char *age = NULL, *author = NULL; > + char *age = NULL, *author = NULL, *msg = NULL; > int r; > > error = got_get_repo_commits(c, 1); > @@ -1519,6 +1558,9 @@ gotweb_render_diff(struct request *c) > error = gotweb_escape_html(&author, rc->author); > if (error) > goto done; > + error = gotweb_escape_html(&msg, rc->commit_msg); > + if (error) > + goto done; > > r = fcgi_printf(c, "<div id='diff_title_wrapper'>\n" > "<div id='diff_title'>Commit Diff</div>\n" > @@ -1545,9 +1587,9 @@ gotweb_render_diff(struct request *c) > rc->parent_id, rc->commit_id, > rc->commit_id, > rc->tree_id, > - author ? author : "", > + author, > age ? age : "", > - rc->commit_msg); > + msg); > if (r == -1) > goto done; > > @@ -1560,6 +1602,7 @@ gotweb_render_diff(struct request *c) > done: > free(age); > free(author); > + free(msg); > return error; > } > > @@ -1578,7 +1621,7 @@ gotweb_render_summary(struct request *c) > r = fcgi_printf(c, > "<div id='description_title'>Description:</div>\n" > "<div id='description'>%s</div>\n", > - t->repo_dir->description); > + t->repo_dir->description ? t->repo_dir->description : ""); > if (r == -1) > goto done; > } > @@ -1587,7 +1630,7 @@ gotweb_render_summary(struct request *c) > r = fcgi_printf(c, > "<div id='repo_owner_title'>Owner:</div>\n" > "<div id='repo_owner'>%s</div>\n", > - t->repo_dir->owner); > + t->repo_dir->owner ? t->repo_dir->owner : ""); > if (r == -1) > goto done; > } > @@ -1639,7 +1682,7 @@ gotweb_render_tag(struct request *c) > const struct got_error *error = NULL; > struct repo_tag *rt = NULL; > struct transport *t = c->t; > - char *age = NULL, *author = NULL; > + char *tagname = NULL, *age = NULL, *author = NULL, *msg = NULL; > > error = got_get_repo_tags(c, 1); > if (error) > @@ -1659,9 +1702,15 @@ gotweb_render_tag(struct request *c) > error = gotweb_escape_html(&author, rt->tagger); > if (error) > goto done; > + error = gotweb_escape_html(&msg, rt->commit_msg); > + if (error) > + goto done; > > if (strncmp(rt->tag_name, "refs/", 5) == 0) > rt->tag_name += 5; > + error = gotweb_escape_html(&tagname, rt->tag_name); > + if (error) > + goto done; > > fcgi_printf(c, "<div id='tags_title_wrapper'>\n" > "<div id='tags_title'>Tag</div>\n" > @@ -1683,15 +1732,16 @@ gotweb_render_tag(struct request *c) > "<div id='tag_commit'>\n%s</div>" > "</div>", /* tag_header_wrapper */ > rt->commit_id, > - rt->tag_name, > - author ? author : "", > + tagname, > + author, > age ? age : "", > - rt->commit_msg, > + msg, > rt->tag_commit); > > done: > free(age); > free(author); > + free(msg); > return error; > } > > @@ -1705,8 +1755,7 @@ gotweb_render_tags(struct request *c) > struct querystring *qs = t->qs; > struct repo_dir *repo_dir = t->repo_dir; > const char *index_page_str; > - char *newline; > - char *age = NULL; > + char *age = NULL, *tagname = NULL, *msg = NULL, *newline; > int r, commit_found = 0; > > index_page_str = qs->index_page_str ? qs->index_page_str : ""; > @@ -1746,11 +1795,17 @@ gotweb_render_tags(struct request *c) > > if (strncmp(rt->tag_name, "refs/tags/", 10) == 0) > rt->tag_name += 10; > + error = gotweb_escape_html(&tagname, rt->tag_name); > + if (error) > + goto done; > > if (rt->tag_commit != NULL) { > newline = strchr(rt->tag_commit, '\n'); > if (newline) > *newline = '\0'; > + error = gotweb_escape_html(&msg, rt->tag_commit); > + if (error) > + goto done; > } > > r = fcgi_printf(c, "<div class='tag_age'>%s</div>\n" > @@ -1773,9 +1828,9 @@ gotweb_render_tags(struct request *c) > "</div>\n" /* .navs_wrapper */ > "<div class='dotted_line'></div>\n", > age ? age : "", > - rt->tag_name, > + tagname, > index_page_str, repo_dir->name, rt->commit_id, > - rt->tag_commit ? rt->tag_commit : "", > + msg ? msg : "", > index_page_str, repo_dir->name, rt->commit_id, > index_page_str, repo_dir->name, rt->commit_id, > index_page_str, repo_dir->name, rt->commit_id); > @@ -1784,6 +1839,10 @@ gotweb_render_tags(struct request *c) > > free(age); > age = NULL; > + free(tagname); > + tagname = NULL; > + free(msg); > + msg = NULL; > } > if (t->next_id || t->prev_id) { > error = gotweb_render_navs(c); > @@ -1793,6 +1852,8 @@ gotweb_render_tags(struct request *c) > fcgi_printf(c, "</div>\n"); /* #tags_content */ > done: > free(age); > + free(tagname); > + free(msg); > return error; > } > > > > -- Tracey Emery
gotwebd: some html fixes