commit e7e5fa49fc2e589a02ba9a9412a7b8e2377ead68 from: Omar Polo via: Thomas Adam date: Fri Dec 30 14:58:02 2022 UTC gotwebd: start using the template system ok tracey@ commit - 6509b1818d1d3c5ab05781cef4007360f127a9a2 commit + e7e5fa49fc2e589a02ba9a9412a7b8e2377ead68 blob - 782bdf6c59161b2cb856b76e7c3f1b31b47d80aa blob + 610ff43a6109e8d62b91ec6d4af4515623412ce8 --- gotwebd/fcgi.c +++ gotwebd/fcgi.c @@ -38,6 +38,7 @@ #include "proc.h" #include "gotwebd.h" +#include "tmpl.h" size_t fcgi_parse_record(uint8_t *, size_t, struct request *); void fcgi_parse_begin_request(uint8_t *, uint16_t, struct request *, @@ -290,6 +291,21 @@ fcgi_timeout(int fd, short events, void *arg) } int +fcgi_puts(struct template *tp, const char *str) +{ + if (str == NULL) + return 0; + return fcgi_gen_binary_response(tp->tp_arg, str, strlen(str)); +} + +int +fcgi_putc(struct template *tp, int ch) +{ + uint8_t c = ch; + return fcgi_gen_binary_response(tp->tp_arg, &c, 1); +} + +int fcgi_vprintf(struct request *c, const char *fmt, va_list ap) { char *str; @@ -485,6 +501,7 @@ fcgi_cleanup_request(struct request *c) event_del(&c->ev); close(c->fd); + template_free(c->tp); gotweb_free_transport(c->t); free(c); } blob - ca8ba4229658d797a7c36e18298eb24eaa3af3a1 blob + 6c6d29dcbaef64cd1c831a6101da9fa2515c06cf --- gotwebd/gotweb.c +++ gotwebd/gotweb.c @@ -50,13 +50,6 @@ #include "proc.h" #include "gotwebd.h" -#include "got_compat.h" - -enum gotweb_ref_tm { - TM_DIFF, - TM_LONG, -}; - static const struct querystring_keys querystring_keys[] = { { "action", ACTION }, { "commit", COMMIT }, @@ -87,8 +80,6 @@ static const struct got_error *gotweb_parse_querystrin char *); static const struct got_error *gotweb_assign_querystring(struct querystring **, char *, char *); -static const struct got_error *gotweb_render_header(struct request *); -static const struct got_error *gotweb_render_footer(struct request *); static const struct got_error *gotweb_render_index(struct request *); static const struct got_error *gotweb_init_repo_dir(struct repo_dir **, const char *); @@ -98,9 +89,7 @@ static const struct got_error *gotweb_get_repo_descrip struct server *, const char *, int); static const struct got_error *gotweb_get_clone_url(char **, struct server *, const char *, int); -static const struct got_error *gotweb_render_navs(struct request *); static const struct got_error *gotweb_render_blame(struct request *); -static const struct got_error *gotweb_render_briefs(struct request *); static const struct got_error *gotweb_render_commits(struct request *); static const struct got_error *gotweb_render_diff(struct request *); static const struct got_error *gotweb_render_summary(struct request *); @@ -109,6 +98,8 @@ static const struct got_error *gotweb_render_tags(stru static const struct got_error *gotweb_render_tree(struct request *); static const struct got_error *gotweb_render_branches(struct request *); +const struct got_error *gotweb_render_navs(struct request *); + static void gotweb_free_querystring(struct querystring *); static void gotweb_free_repo_dir(struct repo_dir *); @@ -196,11 +187,8 @@ render: } html = 1; - error = gotweb_render_header(c); - if (error) { - log_warnx("%s: %s", __func__, error->msg); + if (gotweb_render_header(c->tp) == -1) goto err; - } if (error2) { error = error2; @@ -216,11 +204,8 @@ render: } break; case BRIEFS: - error = gotweb_render_briefs(c); - if (error) { - log_warnx("%s: %s", __func__, error->msg); + if (gotweb_render_briefs(c->tp) == -1) goto err; - } break; case COMMITS: error = gotweb_render_commits(c); @@ -297,7 +282,7 @@ err: return; done: if (html && srv != NULL) - gotweb_render_footer(c); + gotweb_render_footer(c->tp); } struct server * @@ -690,148 +675,10 @@ gotweb_render_content_type_file(struct request *c, con fcgi_printf(c, "Content-type: %s\r\n" "Content-disposition: attachment; filename=%s\r\n\r\n", type, file); - return NULL; -} - -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; - - r = fcgi_printf(c, "\n" - "\n" - "\n" - "%s\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "
\n" - "\n" /* #header */ - "
\n" - "\n" /* #site_path */ - "
\n" /* #site_link */ - "
\n"); - -done: return NULL; } -static const struct got_error * -gotweb_render_footer(struct request *c) -{ - const struct got_error *error = NULL; - struct server *srv = c->srv; - const char *siteowner = " "; - char *escaped_owner = NULL; - - if (srv->show_site_owner) { - error = gotweb_escape_html(&escaped_owner, srv->site_owner); - if (error) - return error; - siteowner = escaped_owner; - } - - fcgi_printf(c, "
\n" - "
%s
\n" - "
\n" /* #site_owner_wrapper */ - "
\n" /* #content */ - "
\n" /* #gw_body */ - "\n\n", siteowner); - - free(escaped_owner); - return NULL; -} - -static const struct got_error * +const struct got_error * gotweb_render_navs(struct request *c) { const struct got_error *error = NULL; @@ -997,7 +844,7 @@ gotweb_render_index(struct request *c) struct dirent **sd_dent = NULL; unsigned int d_cnt, d_i, d_disp = 0; unsigned int d_skipped = 0; - int r, type; + int type; d = opendir(srv->repos_path); if (d == NULL) { @@ -1012,26 +859,9 @@ gotweb_render_index(struct request *c) goto done; } - r = fcgi_printf(c, "
\n" - "
Project
\n"); - if (r == -1) + if (gotweb_render_repo_table_hdr(c->tp) == -1) goto done; - if (srv->show_repo_description) - if (fcgi_printf(c, "
" - "Description
\n") == -1) - goto done; - if (srv->show_repo_owner) - if (fcgi_printf(c, "
" - "Owner
\n") == -1) - goto done; - if (srv->show_repo_age) - if (fcgi_printf(c, "
" - "Last Change
\n") == -1) - goto done; - if (fcgi_printf(c, "
\n") == -1) /* #index_header */ - goto done; - for (d_i = 0; d_i < d_cnt; d_i++) { if (srv->max_repos > 0 && t->prev_disp == srv->max_repos) break; @@ -1075,112 +905,9 @@ gotweb_render_index(struct request *c) d_disp++; t->prev_disp++; - 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" - "%s
\n", repo_dir->description); - if (r == -1) - goto done; - } - - if (srv->show_repo_owner) { - r = fcgi_printf(c, "
" - "%s
\n", repo_dir->owner); - if (r == -1) - goto done; - } - - if (srv->show_repo_age) { - r = fcgi_printf(c, "
" - "%s
\n", repo_dir->age); - if (r == -1) - goto done; - } - - if (fcgi_printf(c, "\n" /* .navs_wrapper */ - "
\n"); /* .index_wrapper */ - if (r == -1) - goto done; - gotweb_free_repo_dir(repo_dir); repo_dir = NULL; t->next_disp++; @@ -1258,145 +985,8 @@ gotweb_render_blame(struct request *c) fcgi_printf(c, "\n" /* #blame */ "\n"); /* #blame_content */ -done: - free(age); - free(msg); - return error; -} - -static const struct got_error * -gotweb_render_briefs(struct request *c) -{ - const struct got_error *error = NULL; - 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; - char *smallerthan, *newline; - char *age = NULL, *author = NULL, *msg = NULL; - int r; - - r = fcgi_printf(c, "
\n" - "
Commit Briefs
\n" - "
\n" /* #briefs_title_wrapper */ - "
\n"); - if (r == -1) - goto done; - - if (qs->action == SUMMARY) { - qs->action = BRIEFS; - error = got_get_repo_commits(c, D_MAXSLCOMMDISP); - } else - error = got_get_repo_commits(c, srv->max_commits_display); - if (error) - goto done; - - TAILQ_FOREACH(rc, &t->repo_commits, entry) { - error = gotweb_get_time_str(&age, rc->committer_time, TM_DIFF); - if (error) - goto done; - - smallerthan = strchr(rc->author, '<'); - if (smallerthan) - *smallerthan = '\0'; - - newline = strchr(rc->commit_msg, '\n'); - 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, "
%s
\n" - "
%s
\n" - "
", - 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; - - error = gotweb_escape_html(&refs, rc->refs_str); - if (error) - goto done; - r = fcgi_printf(c, - " (%s)", refs); - free(refs); - if (r == -1) - goto done; - } - if (fcgi_printf(c, "
\n") == -1) /* .briefs_log */ - goto done; - - r = fcgi_printf(c, "\n" /* .navs_wrapper */ - "
\n") == -1) - goto done; - - free(age); - age = NULL; - free(author); - author = NULL; - free(msg); - msg = NULL; - } - - if (t->next_id || t->prev_id) { - error = gotweb_render_navs(c); - if (error) - goto done; - } - fcgi_printf(c, "
\n"); /* #briefs_content */ done: free(age); - free(author); free(msg); return error; } @@ -1812,11 +1402,8 @@ gotweb_render_summary(struct request *c) if (r == -1) goto done; - error = gotweb_render_briefs(c); - if (error) { - log_warnx("%s: %s", __func__, error->msg); + if (gotweb_render_briefs(c->tp) == -1) goto done; - } error = gotweb_render_tags(c); if (error) { @@ -2178,8 +1765,8 @@ gotweb_urlencode(const char *str) return escaped; } -static inline const char * -action_name(int action) +const char * +gotweb_action_name(int action) { switch (action) { case BLAME: @@ -2209,14 +1796,14 @@ action_name(int action) } } -static int -gotweb_print_url(struct request *c, struct gotweb_url *url) +int +gotweb_render_url(struct request *c, struct gotweb_url *url) { const char *sep = "?", *action; char *tmp; int r; - action = action_name(url->action); + action = gotweb_action_name(url->action); if (action != NULL) { if (fcgi_printf(c, "?action=%s", action) == -1) return -1; @@ -2310,7 +1897,7 @@ gotweb_link(struct request *c, struct gotweb_url *url, if (fcgi_printf(c, "") == -1) blob - 14426b3f4ad9787e7876dc233211e8fb8875cab6 blob + 64fce7c6d8ee3f57305034f0c0434cff991a82bd --- gotwebd/gotwebd.h +++ gotwebd/gotwebd.h @@ -202,10 +202,12 @@ enum socket_priv_fds { PRIV_FDS__MAX, }; +struct template; struct request { struct socket *sock; struct server *srv; struct transport *t; + struct template *tp; struct event ev; struct event tmo; @@ -415,6 +417,11 @@ enum query_actions { ACTIONS__MAX, }; +enum gotweb_ref_tm { + TM_DIFF, + TM_LONG, +}; + extern struct gotwebd *gotwebd_env; /* sockets.c */ @@ -432,6 +439,8 @@ const struct got_error const struct got_error *gotweb_get_time_str(char **, time_t, int); const struct got_error *gotweb_init_transport(struct transport **); const struct got_error *gotweb_escape_html(char **, const char *); +const char *gotweb_action_name(int); +int gotweb_render_url(struct request *, struct gotweb_url *); int gotweb_link(struct request *, struct gotweb_url *, const char *, ...) __attribute__((__format__(printf, 3, 4))) __attribute__((__nonnull__(3))); @@ -440,6 +449,13 @@ void gotweb_free_repo_tag(struct repo_tag *); void gotweb_process_request(struct request *); void gotweb_free_transport(struct transport *); +/* pages.tmpl */ +int gotweb_render_header(struct template *); +int gotweb_render_footer(struct template *); +int gotweb_render_repo_table_hdr(struct template *); +int gotweb_render_repo_fragment(struct template *, struct repo_dir *); +int gotweb_render_briefs(struct template *); + /* parse.y */ int parse_config(const char *, struct gotwebd *); int cmdline_symset(char *); @@ -450,6 +466,8 @@ void fcgi_timeout(int, short, void *); void fcgi_cleanup_request(struct request *); void fcgi_create_end_record(struct request *); void dump_fcgi_record(const char *, struct fcgi_record_header *); +int fcgi_puts(struct template *, const char *); +int fcgi_putc(struct template *, int); int fcgi_vprintf(struct request *, const char *, va_list); int fcgi_printf(struct request *, const char *, ...) __attribute__((__format__(printf, 2, 3))) blob - /dev/null blob + 0d49898e174e9bfad77b158729eb04ab949bd736 (mode 644) --- /dev/null +++ gotwebd/pages.tmpl @@ -0,0 +1,302 @@ +{! +/* + * Copyright (c) 2022 Omar Polo + * Copyright (c) 2016, 2019, 2020-2022 Tracey Emery + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "proc.h" + +#include "gotwebd.h" +#include "tmpl.h" + +const struct got_error *gotweb_render_navs(struct request *); + +static int +gotweb_render_age(struct template *tp, time_t time, int ref_tm) +{ + const struct got_error *err; + char *age; + int r; + + err = gotweb_get_time_str(&age, time, ref_tm); + if (err) + return 0; + r = tp->tp_puts(tp, age); + free(age); + return r; +} + +!} + +{{ define gotweb_render_header(struct template *tp) }} +{! + struct request *c = tp->tp_arg; + struct server *srv = c->srv; + struct querystring *qs = c->t->qs; + struct gotweb_url u_path; + const char *prfx = c->script_name; + const char *css = srv->custom_css; + + memset(&u_path, 0, sizeof(u_path)); + u_path.index_page = -1; + u_path.page = -1; + u_path.action = SUMMARY; +!} + + + + + {{ srv->site_name }} + + + + + + + + + + + +
+ +
+ +
+
+{{ end }} + +{{ define gotweb_render_footer(struct template *tp) }} +{! + struct request *c = tp->tp_arg; + struct server *srv = c->srv; +!} +
+
+ {{ if srv->show_site_owner }} + {{ srv->site_owner }} + {{ end }} +
+
+
+
+ + +{{ end }} + +{{ define gotweb_render_repo_table_hdr(struct template *tp) }} +{! + struct request *c = tp->tp_arg; + struct server *srv = c->srv; +!} +
+
+ Project +
+ {{ if srv->show_repo_description }} +
+ Description +
+ {{ end }} + {{ if srv->show_repo_owner }} +
+ Owner +
+ {{ end }} + {{ if srv->show_repo_age }} +
+ Last Change +
+ {{ end }} +
+{{ end }} + +{{ define gotweb_render_repo_fragment(struct template *tp, struct repo_dir *repo_dir) }} +{! + struct request *c = tp->tp_arg; + struct server *srv = c->srv; + struct gotweb_url summary = { + .action = SUMMARY, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + }, briefs = { + .action = BRIEFS, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + }, commits = { + .action = COMMITS, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + }, tags = { + .action = TAGS, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + }, tree = { + .action = TREE, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + }; +!} +
+ + {{ if srv->show_repo_description }} +
+ {{ repo_dir->description }} +
+ {{ end }} + {{ if srv->show_repo_owner }} +
+ {{ repo_dir->owner }} +
+ {{ end }} + {{ if srv->show_repo_age }} +
+ {{ repo_dir->age }} +
+ {{ end }} + +
+{{ end }} + +{{ define gotweb_render_briefs(struct template *tp) }} +{! + const struct got_error *error; + struct request *c = tp->tp_arg; + struct server *srv = c->srv; + struct transport *t = c->t; + struct querystring *qs = c->t->qs; + struct repo_commit *rc; + struct repo_dir *repo_dir = t->repo_dir; + struct gotweb_url diff_url, tree_url; + char *tmp; + + diff_url = (struct gotweb_url){ + .action = DIFF, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + .headref = qs->headref, + }; + tree_url = (struct gotweb_url){ + .action = TREE, + .index_page = -1, + .page = -1, + .path = repo_dir->name, + .headref = qs->headref, + }; + + if (qs->action == SUMMARY) { + qs->action = BRIEFS; + error = got_get_repo_commits(c, D_MAXSLCOMMDISP); + } else + error = got_get_repo_commits(c, srv->max_commits_display); + if (error) + return -1; +!} +
+
Commit Briefs
+
+
+ {{ tailq-foreach rc &t->repo_commits entry }} + {! + diff_url.commit = rc->commit_id; + tree_url.commit = rc->commit_id; + + tmp = strchr(rc->author, '<'); + if (tmp) + *tmp = '\0'; + + tmp = strchr(rc->commit_msg, '\n'); + if (tmp) + *tmp = '\0'; + !} +
+ {{ render gotweb_render_age(tp, rc->committer_time, TM_DIFF) }} +
+
+ {{ rc->author }} +
+
+ + {{ rc->commit_msg }} + + {{ if rc->refs_str }} + {{ " " }} ({{ rc->refs_str }}) + {{ end }} + +
+ +
+ {{ end }} + {{ if t->next_id || t->prev_id }} + {! gotweb_render_navs(c); !} + {{ end }} +
+{{ end }} blob - 014dfabbd7f22b69786fa4f0ac1aea670254e685 blob + 900136782434063aea4382874f2a1330db7656b6 --- gotwebd/sockets.c +++ gotwebd/sockets.c @@ -53,6 +53,7 @@ #include "proc.h" #include "gotwebd.h" +#include "tmpl.h" #include "got_compat.h" @@ -623,9 +624,18 @@ sockets_socket_accept(int fd, short event, void *arg) c = calloc(1, sizeof(struct request)); if (c == NULL) { + log_warn("%s", __func__); + close(s); + cgi_inflight--; + return; + } + + c->tp = template(c, fcgi_puts, fcgi_putc); + if (c->tp == NULL) { log_warn("%s", __func__); close(s); cgi_inflight--; + free(c); return; }