diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Restyle the sources and fix the audit's findings
Diffstat (limited to 'source/cmd.c')
-rw-r--r--source/cmd.c162
1 file changed, 85 insertions, 77 deletions
diff --git a/source/cmd.c b/source/cmd.c
index c17d8d9..456a937 100644
--- a/source/cmd.c
+++ b/source/cmd.c
@@ -1,15 +1,14 @@
-/* cmd.c: the cgit command dispatcher
- *
- * Copyright (C) 2006-2017 cgit Development Team <cgit@lists.zx2c4.com>
- *
- * Licensed under GNU General Public License v2
- * (see LICENSE.txt for full license text)
+/*
+ * One thunk per page, each pulling the parts of the request its renderer
+ * needs out of the global ctx, plus the table that maps a page name onto its
+ * thunk. Keeping the thunks here lets every renderer take ordinary arguments
+ * instead of reaching into the request state itself.
*/
+#include "cache.h"
#include "cgit.h"
#include "cmd.h"
-#include "cache.h"
-#include "ui-shared.h"
+#include "html.h"
#include "ui-atom.h"
#include "ui-blame.h"
#include "ui-blob.h"
@@ -21,50 +20,56 @@
#include "ui-plain.h"
#include "ui-refs.h"
#include "ui-repolist.h"
+#include "ui-shared.h"
#include "ui-snapshot.h"
#include "ui-stats.h"
#include "ui-summary.h"
#include "ui-tag.h"
#include "ui-tree.h"
-#define def_cmd(name, want_repo, want_vpath, is_clone) \
- {#name, name##_fn, want_repo, want_vpath, is_clone}
-static void HEAD_fn(void)
+static void head_fn(void)
{
cgit_clone_head();
}
-static void atom_fn(void)
+static void about_fn(void)
{
- cgit_print_atom(ctx.qry.head, ctx.qry.path, ctx.cfg.max_atom_items);
+ char *currenturl, *redirect;
+ size_t path_info_len;
+
+ if (!ctx.repo) {
+ cgit_print_site_readme();
+ return;
+ }
+
+ // The about page resolves relative links against its own URL, so it
+ // only works with a trailing slash.
+ path_info_len = ctx.env.path_info ? strlen(ctx.env.path_info) : 0;
+ if (!ctx.qry.path &&
+ (!ctx.qry.url || !*ctx.qry.url ||
+ ctx.qry.url[strlen(ctx.qry.url) - 1] != '/') &&
+ (!path_info_len || ctx.env.path_info[path_info_len - 1] != '/')) {
+ currenturl = cgit_currenturl();
+ redirect = cgit_fmtalloc("%s/", currenturl);
+ cgit_redirect(redirect, true);
+ free(currenturl);
+ free(redirect);
+ } else if (ctx.repo->readme.nr) {
+ cgit_print_repo_readme(ctx.qry.path);
+ } else if (ctx.repo->homepage) {
+ cgit_redirect(ctx.repo->homepage, false);
+ } else {
+ currenturl = cgit_currenturl();
+ redirect = cgit_fmtalloc("%s../", currenturl);
+ cgit_redirect(redirect, false);
+ free(currenturl);
+ free(redirect);
+ }
}
-static void about_fn(void)
+static void atom_fn(void)
{
- if (ctx.repo) {
- size_t path_info_len = ctx.env.path_info ? strlen(ctx.env.path_info) : 0;
- if (!ctx.qry.path &&
- (!ctx.qry.url || !*ctx.qry.url ||
- ctx.qry.url[strlen(ctx.qry.url) - 1] != '/') &&
- (!path_info_len || ctx.env.path_info[path_info_len - 1] != '/')) {
- char *currenturl = cgit_currenturl();
- char *redirect = cgit_fmtalloc("%s/", currenturl);
- cgit_redirect(redirect, true);
- free(currenturl);
- free(redirect);
- } else if (ctx.repo->readme.nr)
- cgit_print_repo_readme(ctx.qry.path);
- else if (ctx.repo->homepage)
- cgit_redirect(ctx.repo->homepage, false);
- else {
- char *currenturl = cgit_currenturl();
- char *redirect = cgit_fmtalloc("%s../", currenturl);
- cgit_redirect(redirect, false);
- free(currenturl);
- free(redirect);
- }
- } else
- cgit_print_site_readme();
+ cgit_print_atom(ctx.qry.head, ctx.qry.path, ctx.cfg.max_atom_items);
}
static void blame_fn(void)
@@ -90,11 +95,6 @@ static void diff_fn(void)
cgit_print_diff(ctx.qry.oid, ctx.qry.oid2, ctx.qry.path, 1, 0);
}
-static void rawdiff_fn(void)
-{
- cgit_print_diff(ctx.qry.oid, ctx.qry.oid2, ctx.qry.path, 1, 1);
-}
-
static void info_fn(void)
{
cgit_clone_info();
@@ -110,8 +110,8 @@ static void log_fn(void)
static void ls_cache_fn(void)
{
- /* The listing exposes the cache path and the URLs other visitors
- * requested, so it stays off unless an admin opts in. */
+ // The listing names the cache path and the URLs other visitors asked
+ // for, so it stays off until an administrator opts in.
if (!ctx.cfg.enable_cache_list) {
cgit_print_error_page(404, "Not found", "Not found");
return;
@@ -127,11 +127,6 @@ static void objects_fn(void)
cgit_clone_objects();
}
-static void repolist_fn(void)
-{
- cgit_print_repolist();
-}
-
static void patch_fn(void)
{
cgit_print_patch(ctx.qry.oid, ctx.qry.oid2, ctx.qry.path);
@@ -142,11 +137,21 @@ static void plain_fn(void)
cgit_print_plain();
}
+static void rawdiff_fn(void)
+{
+ cgit_print_diff(ctx.qry.oid, ctx.qry.oid2, ctx.qry.path, 1, 1);
+}
+
static void refs_fn(void)
{
cgit_print_refs();
}
+static void repolist_fn(void)
+{
+ cgit_print_repolist();
+}
+
static void snapshot_fn(void)
{
cgit_print_snapshot(ctx.qry.head, ctx.qry.oid, ctx.qry.path,
@@ -176,31 +181,34 @@ static void tree_fn(void)
cgit_print_tree(ctx.qry.oid, ctx.qry.path);
}
-struct cgit_cmd *cgit_get_cmd(void)
+// The name is what a request spells as p=, so these strings are part of the
+// URL space and cannot be renamed.
+static const struct cgit_cmd commands[] = {
+ { .name = "HEAD", .fn = head_fn, .want_repo = 1, .is_clone = 1 },
+ { .name = "about", .fn = about_fn },
+ { .name = "atom", .fn = atom_fn, .want_repo = 1 },
+ { .name = "blame", .fn = blame_fn, .want_repo = 1, .want_vpath = 1 },
+ { .name = "blob", .fn = blob_fn, .want_repo = 1 },
+ { .name = "commit", .fn = commit_fn, .want_repo = 1, .want_vpath = 1 },
+ { .name = "diff", .fn = diff_fn, .want_repo = 1, .want_vpath = 1 },
+ { .name = "info", .fn = info_fn, .want_repo = 1, .is_clone = 1 },
+ { .name = "log", .fn = log_fn, .want_repo = 1, .want_vpath = 1 },
+ { .name = "ls_cache", .fn = ls_cache_fn },
+ { .name = "objects", .fn = objects_fn, .want_repo = 1, .is_clone = 1 },
+ { .name = "patch", .fn = patch_fn, .want_repo = 1, .want_vpath = 1 },
+ { .name = "plain", .fn = plain_fn, .want_repo = 1 },
+ { .name = "rawdiff", .fn = rawdiff_fn, .want_repo = 1, .want_vpath = 1 },
+ { .name = "refs", .fn = refs_fn, .want_repo = 1 },
+ { .name = "repolist", .fn = repolist_fn },
+ { .name = "snapshot", .fn = snapshot_fn, .want_repo = 1 },
+ { .name = "stats", .fn = stats_fn, .want_repo = 1, .want_vpath = 1 },
+ { .name = "summary", .fn = summary_fn, .want_repo = 1 },
+ { .name = "tag", .fn = tag_fn, .want_repo = 1 },
+ { .name = "tree", .fn = tree_fn, .want_repo = 1, .want_vpath = 1 },
+};
+
+const struct cgit_cmd *cgit_get_cmd(void)
{
- static struct cgit_cmd cmds[] = {
- def_cmd(HEAD, 1, 0, 1),
- def_cmd(atom, 1, 0, 0),
- def_cmd(about, 0, 0, 0),
- def_cmd(blame, 1, 1, 0),
- def_cmd(blob, 1, 0, 0),
- def_cmd(commit, 1, 1, 0),
- def_cmd(diff, 1, 1, 0),
- def_cmd(info, 1, 0, 1),
- def_cmd(log, 1, 1, 0),
- def_cmd(ls_cache, 0, 0, 0),
- def_cmd(objects, 1, 0, 1),
- def_cmd(patch, 1, 1, 0),
- def_cmd(plain, 1, 0, 0),
- def_cmd(rawdiff, 1, 1, 0),
- def_cmd(refs, 1, 0, 0),
- def_cmd(repolist, 0, 0, 0),
- def_cmd(snapshot, 1, 0, 0),
- def_cmd(stats, 1, 1, 0),
- def_cmd(summary, 1, 0, 0),
- def_cmd(tag, 1, 0, 0),
- def_cmd(tree, 1, 1, 0),
- };
size_t i;
if (ctx.qry.page == NULL) {
@@ -210,8 +218,8 @@ struct cgit_cmd *cgit_get_cmd(void)
ctx.qry.page = "repolist";
}
- for (i = 0; i < ARRAY_SIZE(cmds); i++)
- if (!strcmp(ctx.qry.page, cmds[i].name))
- return &cmds[i];
+ for (i = 0; i < ARRAY_SIZE(commands); i++)
+ if (!strcmp(ctx.qry.page, commands[i].name))
+ return &commands[i];
return NULL;
}