diff options
context:
space:
mode:
-rw-r--r--assets/cgit.js18
-rw-r--r--source/ui-diff.c6
-rw-r--r--source/ui-shared.c2
-rw-r--r--source/ui-stats.c4
-rw-r--r--tests/t0200-security.sh10
5 files changed, 34 insertions, 6 deletions
diff --git a/assets/cgit.js b/assets/cgit.js
index 2164c1a..4e0ac70 100644
--- a/assets/cgit.js
+++ b/assets/cgit.js
@@ -73,6 +73,24 @@ document.addEventListener("DOMContentLoaded", function() {
})();
+/* Selects marked data-autosubmit reload the page with the new setting.
+ * Wired here instead of inline onchange handlers, which a strict
+ * Content-Security-Policy blocks. Without scripting the forms keep
+ * their noscript reload button. */
+
+(function () {
+
+document.addEventListener("DOMContentLoaded", function () {
+ var i, els = document.querySelectorAll("select[data-autosubmit]");
+
+ for (i = 0; i < els.length; i++)
+ els[i].addEventListener("change", function () {
+ this.form.submit();
+ });
+}, false);
+
+})();
+
/* Colour theme toggle: cycles auto -> light -> dark and remembers the
* choice. "auto" leaves the page following the system preference via CSS. */
diff --git a/source/ui-diff.c b/source/ui-diff.c
index c2f4717..baaa1f8 100644
--- a/source/ui-diff.c
+++ b/source/ui-diff.c
@@ -353,7 +353,7 @@ void cgit_print_diff_ctrls(void)
html("<tr>");
html("<td class='label'>context:</td>");
html("<td class='ctrl'>");
- html("<select name='context' onchange='this.form.submit();'>");
+ html("<select name='context' data-autosubmit='1'>");
curr = ctx.qry.context;
if (!curr)
curr = 3;
@@ -366,7 +366,7 @@ void cgit_print_diff_ctrls(void)
html("</tr><tr>");
html("<td class='label'>space:</td>");
html("<td class='ctrl'>");
- html("<select name='ignorews' onchange='this.form.submit();'>");
+ html("<select name='ignorews' data-autosubmit='1'>");
html_intoption(0, "include", ctx.qry.ignorews);
html_intoption(1, "ignore", ctx.qry.ignorews);
html("</select>");
@@ -374,7 +374,7 @@ void cgit_print_diff_ctrls(void)
html("</tr><tr>");
html("<td class='label'>mode:</td>");
html("<td class='ctrl'>");
- html("<select name='dt' onchange='this.form.submit();'>");
+ html("<select name='dt' data-autosubmit='1'>");
curr = ctx.qry.has_difftype ? ctx.qry.difftype : ctx.cfg.difftype;
html_intoption(0, "unified", curr);
html_intoption(1, "ssdiff", curr);
diff --git a/source/ui-shared.c b/source/ui-shared.c
index c7a91e2..df7ad1f 100644
--- a/source/ui-shared.c
+++ b/source/ui-shared.c
@@ -1064,7 +1064,7 @@ static void print_header(void)
if (ctx.repo && ctx.env.authenticated) {
html("<form class='branch-switch' method='get'>\n");
cgit_add_hidden_formfields(0, 1, ctx.qry.page);
- html("<select name='h' aria-label='Branch' onchange='this.form.submit();'>\n");
+ html("<select name='h' aria-label='Branch' data-autosubmit='1'>\n");
refs_for_each_branch_ref(get_main_ref_store(the_repository),
print_branch_option, ctx.qry.head);
if (ctx.repo->enable_remote_branches)
diff --git a/source/ui-stats.c b/source/ui-stats.c
index d33441b..cabbc3c 100644
--- a/source/ui-stats.c
+++ b/source/ui-stats.c
@@ -405,14 +405,14 @@ void cgit_show_stats(void)
html("<table><tr><td colspan='2'/></tr>");
if (ctx.repo->max_stats > 1) {
html("<tr><td class='label'>Period:</td>");
- html("<td class='ctrl'><select name='period' onchange='this.form.submit();'>");
+ html("<td class='ctrl'><select name='period' data-autosubmit='1'>");
for (i = 0; i < ctx.repo->max_stats; i++)
html_option(fmt("%c", periods[i].code),
periods[i].name, fmt("%c", period->code));
html("</select></td></tr>");
}
html("<tr><td class='label'>Authors:</td>");
- html("<td class='ctrl'><select name='ofs' onchange='this.form.submit();'>");
+ html("<td class='ctrl'><select name='ofs' data-autosubmit='1'>");
html_intoption(10, "10", top);
html_intoption(25, "25", top);
html_intoption(50, "50", top);
diff --git a/tests/t0200-security.sh b/tests/t0200-security.sh
index 221b56b..afce715 100644
--- a/tests/t0200-security.sh
+++ b/tests/t0200-security.sh
@@ -100,6 +100,16 @@ test_expect_success 'non-markdown readme without a filter is escaped' '
! grep "<script>alert(2)</script>" tmp
'
+# --- Auto-submitting selects carry no inline handlers ------------------------
+# A Content-Security-Policy without unsafe-inline blocks inline onchange
+# handlers, so the forms mark their selects and cgit.js wires them up.
+test_expect_success 'diff option selects use the autosubmit marker' '
+ sha=$(git -C repos/foo rev-parse HEAD) &&
+ cgit_query "url=foo/commit&id=$sha" >tmp &&
+ grep "data-autosubmit" tmp &&
+ ! grep "onchange" tmp
+'
+
# --- Fork feature: directories are grouped before files in the tree ---------
test_expect_success 'tree groups directories before files' '
secq "url=sec/tree/" >tmp &&