aboutsummaryrefslogtreecommitdiff
path: root/filters
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
Diffstat (limited to 'filters')
-rwxr-xr-xfilters/about-formatting.sh27
-rwxr-xr-xfilters/ci-jenkins.sh58
-rwxr-xr-xfilters/commit-links.sh28
-rw-r--r--filters/email-gravatar.lua35
-rwxr-xr-xfilters/email-gravatar.py39
-rw-r--r--filters/email-libravatar.lua36
-rw-r--r--filters/file-authentication.lua359
-rw-r--r--filters/gentoo-ldap-authentication.lua360
-rwxr-xr-xfilters/html-converters/man2html4
-rwxr-xr-xfilters/html-converters/md2html342
-rwxr-xr-xfilters/html-converters/rst2html2
-rwxr-xr-xfilters/html-converters/txt2html4
-rw-r--r--filters/owner-example.lua17
-rw-r--r--filters/simple-authentication.lua314
-rwxr-xr-xfilters/syntax-highlighting.py94
-rwxr-xr-xfilters/syntax-highlighting.sh127
16 files changed, 0 insertions, 1846 deletions
diff --git a/filters/about-formatting.sh b/filters/about-formatting.sh
deleted file mode 100755
index 85daf9c..0000000
--- a/filters/about-formatting.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-# This may be used with the about-filter or repo.about-filter setting in cgitrc.
-# It passes formatting of about pages to differing programs, depending on the usage.
-
-# Markdown support requires python and markdown-python.
-# RestructuredText support requires python and docutils.
-# Man page support requires groff.
-
-# The following environment variables can be used to retrieve the configuration
-# of the repository for which this script is called:
-# CGIT_REPO_URL ( = repo.url setting )
-# CGIT_REPO_NAME ( = repo.name setting )
-# CGIT_REPO_PATH ( = repo.path setting )
-# CGIT_REPO_OWNER ( = repo.owner setting )
-# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
-# CGIT_REPO_SECTION ( = section setting )
-# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
-
-cd "$(dirname $0)/html-converters/"
-case "$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')" in
- *.markdown|*.mdown|*.md|*.mkd) exec ./md2html; ;;
- *.rst) exec ./rst2html; ;;
- *.[1-9]) exec ./man2html; ;;
- *.htm|*.html) exec cat; ;;
- *.txt|*) exec ./txt2html; ;;
-esac
diff --git a/filters/ci-jenkins.sh b/filters/ci-jenkins.sh
deleted file mode 100755
index 842af21..0000000
--- a/filters/ci-jenkins.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/sh
-# This script may be used with the ci-filter or repo.ci-filter setting in
-# cgitrc to hide the "ci" tab for refs which have no pipeline on a Jenkins
-# instance.
-#
-# Arguments:
-# $1 the name of the branch or tag being viewed
-# $2 "branch" or "tag"
-# $3 the ci url which the "ci" tab would redirect to
-#
-# Exit with a zero status to show the tab, non-zero to hide it. This script
-# must not write anything to standard output, as that would end up in the
-# middle of the page cgit is rendering.
-#
-# The filter is consulted while rendering every repository page, so the
-# verdict is cached on disk to keep Jenkins from being hammered, and the
-# probe is given a short timeout so that an unreachable Jenkins degrades
-# into a missing tab rather than a hanging web server.
-#
-# Set CI_NETRC to a netrc(5) file if the Jenkins instance requires
-# authentication; without it a private job answers 403 and the tab is
-# hidden even though the pipeline exists.
-
-CI_CACHE_DIR="${CI_CACHE_DIR:-/var/cache/cgit/ci-filter}"
-CI_CACHE_TTL_MINUTES="${CI_CACHE_TTL_MINUTES:-5}"
-CI_TIMEOUT="${CI_TIMEOUT:-2}"
-
-url="$3"
-test -n "$url" || exit 1
-
-# Jenkins job pages are often not readable anonymously, so query the REST
-# API rather than the page the tab points at.
-probe="$url/api/json?tree=name"
-
-key="$(printf '%s' "$url" | cksum | tr -cd '0-9')"
-cache="$CI_CACHE_DIR/$key"
-
-mkdir -p "$CI_CACHE_DIR" 2>/dev/null
-
-if test -f "$cache" &&
- test -z "$(find "$cache" -mmin "+$CI_CACHE_TTL_MINUTES" 2>/dev/null)"
-then
- exit "$(cat "$cache")"
-fi
-
-status=0
-curl --silent --fail --head --output /dev/null \
- --max-time "$CI_TIMEOUT" \
- ${CI_NETRC:+--netrc-file "$CI_NETRC"} \
- "$probe" >/dev/null 2>&1 || status=1
-
-if test -d "$CI_CACHE_DIR"
-then
- printf '%s\n' "$status" >"$cache.$$" 2>/dev/null &&
- mv "$cache.$$" "$cache" 2>/dev/null
-fi
-
-exit "$status"
diff --git a/filters/commit-links.sh b/filters/commit-links.sh
deleted file mode 100755
index 796ac30..0000000
--- a/filters/commit-links.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-# This script can be used to generate links in commit messages.
-#
-# To use this script, refer to this file with either the commit-filter or the
-# repo.commit-filter options in cgitrc.
-#
-# The following environment variables can be used to retrieve the configuration
-# of the repository for which this script is called:
-# CGIT_REPO_URL ( = repo.url setting )
-# CGIT_REPO_NAME ( = repo.name setting )
-# CGIT_REPO_PATH ( = repo.path setting )
-# CGIT_REPO_OWNER ( = repo.owner setting )
-# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
-# CGIT_REPO_SECTION ( = section setting )
-# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
-#
-
-regex=''
-
-# This expression generates links to commits referenced by their SHA1.
-regex=$regex'
-s|\b([0-9a-fA-F]{7,64})\b|<a href="./?id=\1">\1</a>|g'
-
-# This expression generates links to a fictional bugtracker.
-regex=$regex'
-s|#([0-9]+)\b|<a href="http://bugs.example.com/?bug=\1">#\1</a>|g'
-
-sed -re "$regex"
diff --git a/filters/email-gravatar.lua b/filters/email-gravatar.lua
deleted file mode 100644
index c39b490..0000000
--- a/filters/email-gravatar.lua
+++ /dev/null
@@ -1,35 +0,0 @@
--- This script may be used with the email-filter or repo.email-filter settings in cgitrc.
--- It adds gravatar icons to author names. It is designed to be used with the lua:
--- prefix in filters. It is much faster than the corresponding python script.
---
--- Requirements:
--- luaossl
--- <http://25thandclement.com/~william/projects/luaossl.html>
---
-
-local digest = require("openssl.digest")
-
-function md5_hex(input)
- local b = digest.new("md5"):final(input)
- local x = ""
- for i = 1, #b do
- x = x .. string.format("%.2x", string.byte(b, i))
- end
- return x
-end
-
-function filter_open(email, page)
- buffer = ""
- md5 = md5_hex(email:sub(2, -2):lower())
-end
-
-function filter_close()
- html("<img src='//www.gravatar.com/avatar/" .. md5 .. "?s=13&amp;d=retro' width='13' height='13' alt='Gravatar' /> " .. buffer)
- return 0
-end
-
-function filter_write(str)
- buffer = buffer .. str
-end
-
-
diff --git a/filters/email-gravatar.py b/filters/email-gravatar.py
deleted file mode 100755
index d70440e..0000000
--- a/filters/email-gravatar.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python3
-
-# Please prefer the email-gravatar.lua using lua: as a prefix over this script. This
-# script is very slow, in comparison.
-#
-# This script may be used with the email-filter or repo.email-filter settings in cgitrc.
-#
-# The following environment variables can be used to retrieve the configuration
-# of the repository for which this script is called:
-# CGIT_REPO_URL ( = repo.url setting )
-# CGIT_REPO_NAME ( = repo.name setting )
-# CGIT_REPO_PATH ( = repo.path setting )
-# CGIT_REPO_OWNER ( = repo.owner setting )
-# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
-# CGIT_REPO_SECTION ( = section setting )
-# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
-#
-# It receives an email address on argv[1] and text on stdin. It prints
-# to stdout that text prepended by a gravatar at 10pt.
-
-import sys
-import hashlib
-import codecs
-
-email = sys.argv[1].lower().strip()
-if email[0] == '<':
- email = email[1:]
-if email[-1] == '>':
- email = email[0:-1]
-
-page = sys.argv[2]
-
-sys.stdin = codecs.getreader("utf-8")(sys.stdin.detach())
-sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
-
-md5 = hashlib.md5(email.encode()).hexdigest()
-text = sys.stdin.read().strip()
-
-print("<img src='//www.gravatar.com/avatar/" + md5 + "?s=13&amp;d=retro' width='13' height='13' alt='Gravatar' /> " + text)
diff --git a/filters/email-libravatar.lua b/filters/email-libravatar.lua
deleted file mode 100644
index 7336baf..0000000
--- a/filters/email-libravatar.lua
+++ /dev/null
@@ -1,36 +0,0 @@
--- This script may be used with the email-filter or repo.email-filter settings in cgitrc.
--- It adds libravatar icons to author names. It is designed to be used with the lua:
--- prefix in filters.
---
--- Requirements:
--- luaossl
--- <http://25thandclement.com/~william/projects/luaossl.html>
---
-
-local digest = require("openssl.digest")
-
-function md5_hex(input)
- local b = digest.new("md5"):final(input)
- local x = ""
- for i = 1, #b do
- x = x .. string.format("%.2x", string.byte(b, i))
- end
- return x
-end
-
-function filter_open(email, page)
- buffer = ""
- md5 = md5_hex(email:sub(2, -2):lower())
-end
-
-function filter_close()
- baseurl = os.getenv("HTTPS") and "https://seccdn.libravatar.org/" or "http://cdn.libravatar.org/"
- html("<img src='" .. baseurl .. "avatar/" .. md5 .. "?s=13&amp;d=retro' width='13' height='13' alt='Libravatar' /> " .. buffer)
- return 0
-end
-
-function filter_write(str)
- buffer = buffer .. str
-end
-
-
diff --git a/filters/file-authentication.lua b/filters/file-authentication.lua
deleted file mode 100644
index 0248804..0000000
--- a/filters/file-authentication.lua
+++ /dev/null
@@ -1,359 +0,0 @@
--- This script may be used with the auth-filter.
---
--- Requirements:
--- luaossl
--- <http://25thandclement.com/~william/projects/luaossl.html>
--- luaposix
--- <https://github.com/luaposix/luaposix>
---
-local sysstat = require("posix.sys.stat")
-local unistd = require("posix.unistd")
-local rand = require("openssl.rand")
-local hmac = require("openssl.hmac")
-
--- This file should contain a series of lines in the form of:
--- username1:hash1
--- username2:hash2
--- username3:hash3
--- ...
--- Hashes can be generated using something like `mkpasswd -m sha-512 -R 300000`.
--- This file should not be world-readable.
-local users_filename = "/etc/cgit-auth/users"
-
--- This file should contain a series of lines in the form of:
--- groupname1:username1,username2,username3,...
--- ...
-local groups_filename = "/etc/cgit-auth/groups"
-
--- This file should contain a series of lines in the form of:
--- reponame1:groupname1,groupname2,groupname3,...
--- ...
-local repos_filename = "/etc/cgit-auth/repos"
-
--- Set this to a path this script can write to for storing a persistent
--- cookie secret, which should not be world-readable.
-local secret_filename = "/var/cache/cgit/auth-secret"
-
---
---
--- Authentication functions follow below. Swap these out if you want different authentication semantics.
---
---
-
--- Looks up a hash for a given user.
-function lookup_hash(user)
- local line
- for line in io.lines(users_filename) do
- local u, h = string.match(line, "(.-):(.+)")
- if u:lower() == user:lower() then
- return h
- end
- end
- return nil
-end
-
--- Looks up users for a given repo.
-function lookup_users(repo)
- local users = nil
- local groups = nil
- local line, group, user
- for line in io.lines(repos_filename) do
- local r, g = string.match(line, "(.-):(.+)")
- if r == repo then
- groups = { }
- for group in string.gmatch(g, "([^,]+)") do
- groups[group:lower()] = true
- end
- break
- end
- end
- if groups == nil then
- return nil
- end
- for line in io.lines(groups_filename) do
- local g, u = string.match(line, "(.-):(.+)")
- if groups[g:lower()] then
- if users == nil then
- users = { }
- end
- for user in string.gmatch(u, "([^,]+)") do
- users[user:lower()] = true
- end
- end
- end
- return users
-end
-
-
--- Sets HTTP cookie headers based on post and sets up redirection.
-function authenticate_post()
- local hash = lookup_hash(post["username"])
- local redirect = validate_value("redirect", post["redirect"])
-
- if redirect == nil then
- not_found()
- return 0
- end
-
- redirect_to(redirect)
-
- if hash == nil or hash ~= unistd.crypt(post["password"], hash) then
- set_cookie("cgitauth", "")
- else
- -- One week expiration time
- local username = secure_value("username", post["username"], os.time() + 604800)
- set_cookie("cgitauth", username)
- end
-
- html("\n")
- return 0
-end
-
-
--- Returns 1 if the cookie is valid and 0 if it is not.
-function authenticate_cookie()
- accepted_users = lookup_users(cgit["repo"])
- if accepted_users == nil then
- -- We return as valid if the repo is not protected.
- return 1
- end
-
- local username = validate_value("username", get_cookie(http["cookie"], "cgitauth"))
- if username == nil or not accepted_users[username:lower()] then
- return 0
- else
- return 1
- end
-end
-
--- Prints the html for the login form.
-function body()
- html("<h2>Authentication Required</h2>")
- html("<form method='post' action='")
- html_attr(cgit["login"])
- html("'>")
- html("<input type='hidden' name='redirect' value='")
- html_attr(secure_value("redirect", cgit["url"], 0))
- html("' />")
- html("<table>")
- html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autofocus /></td></tr>")
- html("<tr><td><label for='password'>Password:</label></td><td><input id='password' name='password' type='password' /></td></tr>")
- html("<tr><td colspan='2'><input value='Login' type='submit' /></td></tr>")
- html("</table></form>")
-
- return 0
-end
-
-
-
---
---
--- Wrapper around filter API, exposing the http table, the cgit table, and the post table to the above functions.
---
---
-
-local actions = {}
-actions["authenticate-post"] = authenticate_post
-actions["authenticate-cookie"] = authenticate_cookie
-actions["body"] = body
-
-function filter_open(...)
- action = actions[select(1, ...)]
-
- http = {}
- http["cookie"] = select(2, ...)
- http["method"] = select(3, ...)
- http["query"] = select(4, ...)
- http["referer"] = select(5, ...)
- http["path"] = select(6, ...)
- http["host"] = select(7, ...)
- http["https"] = select(8, ...)
-
- cgit = {}
- cgit["repo"] = select(9, ...)
- cgit["page"] = select(10, ...)
- cgit["url"] = select(11, ...)
- cgit["login"] = select(12, ...)
-
-end
-
-function filter_close()
- return action()
-end
-
-function filter_write(str)
- post = parse_qs(str)
-end
-
-
---
---
--- Utility functions based on keplerproject/wsapi.
---
---
-
-function url_decode(str)
- if not str then
- return ""
- end
- str = string.gsub(str, "+", " ")
- str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end)
- str = string.gsub(str, "\r\n", "\n")
- return str
-end
-
-function url_encode(str)
- if not str then
- return ""
- end
- str = string.gsub(str, "\n", "\r\n")
- str = string.gsub(str, "([^%w ])", function(c) return string.format("%%%02X", string.byte(c)) end)
- str = string.gsub(str, " ", "+")
- return str
-end
-
-function parse_qs(qs)
- local tab = {}
- for key, val in string.gmatch(qs, "([^&=]+)=([^&=]*)&?") do
- tab[url_decode(key)] = url_decode(val)
- end
- return tab
-end
-
-function get_cookie(cookies, name)
- cookies = string.gsub(";" .. cookies .. ";", "%s*;%s*", ";")
- return url_decode(string.match(cookies, ";" .. name .. "=(.-);"))
-end
-
-function tohex(b)
- local x = ""
- for i = 1, #b do
- x = x .. string.format("%.2x", string.byte(b, i))
- end
- return x
-end
-
---
---
--- Cookie construction and validation helpers.
---
---
-
-local secret = nil
-
--- Loads a secret from a file, creates a secret, or returns one from memory.
-function get_secret()
- if secret ~= nil then
- return secret
- end
- local secret_file = io.open(secret_filename, "r")
- if secret_file == nil then
- local old_umask = sysstat.umask(63)
- local temporary_filename = secret_filename .. ".tmp." .. tohex(rand.bytes(16))
- local temporary_file = io.open(temporary_filename, "w")
- if temporary_file == nil then
- os.exit(177)
- end
- temporary_file:write(tohex(rand.bytes(32)))
- temporary_file:close()
- unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
- unistd.unlink(temporary_filename)
- sysstat.umask(old_umask)
- secret_file = io.open(secret_filename, "r")
- end
- if secret_file == nil then
- os.exit(177)
- end
- secret = secret_file:read()
- secret_file:close()
- if secret:len() ~= 64 then
- os.exit(177)
- end
- return secret
-end
-
--- Returns value of cookie if cookie is valid. Otherwise returns nil.
-function validate_value(expected_field, cookie)
- local i = 0
- local value = ""
- local field = ""
- local expiration = 0
- local salt = ""
- local chmac = ""
-
- if cookie == nil or cookie:len() < 3 or cookie:sub(1, 1) == "|" then
- return nil
- end
-
- for component in string.gmatch(cookie, "[^|]+") do
- if i == 0 then
- field = component
- elseif i == 1 then
- value = component
- elseif i == 2 then
- expiration = tonumber(component)
- if expiration == nil then
- expiration = -1
- end
- elseif i == 3 then
- salt = component
- elseif i == 4 then
- chmac = component
- else
- break
- end
- i = i + 1
- end
-
- if chmac == nil or chmac:len() == 0 then
- return nil
- end
-
- -- Lua hashes strings, so these comparisons are time invariant.
- if chmac ~= tohex(hmac.new(get_secret(), "sha256"):final(field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt)) then
- return nil
- end
-
- if expiration == -1 or (expiration ~= 0 and expiration <= os.time()) then
- return nil
- end
-
- if url_decode(field) ~= expected_field then
- return nil
- end
-
- return url_decode(value)
-end
-
-function secure_value(field, value, expiration)
- if value == nil or value:len() <= 0 then
- return ""
- end
-
- local authstr = ""
- local salt = tohex(rand.bytes(16))
- value = url_encode(value)
- field = url_encode(field)
- authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
- authstr = authstr .. "|" .. tohex(hmac.new(get_secret(), "sha256"):final(authstr))
- return authstr
-end
-
-function set_cookie(cookie, value)
- html("Set-Cookie: " .. cookie .. "=" .. value .. "; HttpOnly")
- if http["https"] == "yes" or http["https"] == "on" or http["https"] == "1" then
- html("; secure")
- end
- html("\n")
-end
-
-function redirect_to(url)
- html("Status: 302 Redirect\n")
- html("Cache-Control: no-cache, no-store\n")
- html("Location: " .. url .. "\n")
-end
-
-function not_found()
- html("Status: 404 Not Found\n")
- html("Cache-Control: no-cache, no-store\n\n")
-end
diff --git a/filters/gentoo-ldap-authentication.lua b/filters/gentoo-ldap-authentication.lua
deleted file mode 100644
index 673c88d..0000000
--- a/filters/gentoo-ldap-authentication.lua
+++ /dev/null
@@ -1,360 +0,0 @@
--- This script may be used with the auth-filter. Be sure to configure it as you wish.
---
--- Requirements:
--- luaossl
--- <http://25thandclement.com/~william/projects/luaossl.html>
--- lualdap >= 1.2
--- <https://git.zx2c4.com/lualdap/about/>
--- luaposix
--- <https://github.com/luaposix/luaposix>
---
-local sysstat = require("posix.sys.stat")
-local unistd = require("posix.unistd")
-local lualdap = require("lualdap")
-local rand = require("openssl.rand")
-local hmac = require("openssl.hmac")
-
---
---
--- Configure these variables for your settings.
---
---
-
--- A list of password protected repositories, with which gentooAccess
--- group is allowed to access each one.
-local protected_repos = {
- glouglou = "infra",
- portage = "dev"
-}
-
--- Set this to a path this script can write to for storing a persistent
--- cookie secret, which should be guarded.
-local secret_filename = "/var/cache/cgit/auth-secret"
-
-
---
---
--- Authentication functions follow below. Swap these out if you want different authentication semantics.
---
---
-
--- Sets HTTP cookie headers based on post and sets up redirection.
-function authenticate_post()
- local redirect = validate_value("redirect", post["redirect"])
-
- if redirect == nil then
- not_found()
- return 0
- end
-
- redirect_to(redirect)
-
- local groups = gentoo_ldap_user_groups(post["username"], post["password"])
- if groups == nil then
- set_cookie("cgitauth", "")
- else
- -- One week expiration time
- set_cookie("cgitauth", secure_value("gentoogroups", table.concat(groups, ","), os.time() + 604800))
- end
-
- html("\n")
- return 0
-end
-
-
--- Returns 1 if the cookie is valid and 0 if it is not.
-function authenticate_cookie()
- local required_group = protected_repos[cgit["repo"]]
- if required_group == nil then
- -- We return as valid if the repo is not protected.
- return 1
- end
-
- local user_groups = validate_value("gentoogroups", get_cookie(http["cookie"], "cgitauth"))
- if user_groups == nil or user_groups == "" then
- return 0
- end
- for group in string.gmatch(user_groups, "[^,]+") do
- if group == required_group then
- return 1
- end
- end
- return 0
-end
-
--- Prints the html for the login form.
-function body()
- html("<h2>Gentoo LDAP Authentication Required</h2>")
- html("<form method='post' action='")
- html_attr(cgit["login"])
- html("'>")
- html("<input type='hidden' name='redirect' value='")
- html_attr(secure_value("redirect", cgit["url"], 0))
- html("' />")
- html("<table>")
- html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autofocus /></td></tr>")
- html("<tr><td><label for='password'>Password:</label></td><td><input id='password' name='password' type='password' /></td></tr>")
- html("<tr><td colspan='2'><input value='Login' type='submit' /></td></tr>")
- html("</table></form>")
-
- return 0
-end
-
---
---
--- Gentoo LDAP support.
---
---
-
-function gentoo_ldap_user_groups(username, password)
- -- Ensure the user is alphanumeric
- if username == nil or username:match("%W") then
- return nil
- end
-
- local who = "uid=" .. username .. ",ou=devs,dc=gentoo,dc=org"
-
- local ldap, err = lualdap.open_simple {
- uri = "ldap://ldap1.gentoo.org",
- who = who,
- password = password,
- starttls = true,
- certfile = "/var/www/uwsgi/cgit/gentoo-ldap/star.gentoo.org.crt",
- keyfile = "/var/www/uwsgi/cgit/gentoo-ldap/star.gentoo.org.key",
- cacertfile = "/var/www/uwsgi/cgit/gentoo-ldap/ca.pem"
- }
- if ldap == nil then
- return nil
- end
-
- local group_suffix = ".group"
- local group_suffix_len = group_suffix:len()
- local groups = {}
- for dn, attribs in ldap:search { base = who, scope = "subtree" } do
- local access = attribs["gentooAccess"]
- if dn == who and access ~= nil then
- for i, v in ipairs(access) do
- local vlen = v:len()
- if vlen > group_suffix_len and v:sub(-group_suffix_len) == group_suffix then
- table.insert(groups, v:sub(1, vlen - group_suffix_len))
- end
- end
- end
- end
-
- ldap:close()
-
- return groups
-end
-
---
---
--- Wrapper around filter API, exposing the http table, the cgit table, and the post table to the above functions.
---
---
-
-local actions = {}
-actions["authenticate-post"] = authenticate_post
-actions["authenticate-cookie"] = authenticate_cookie
-actions["body"] = body
-
-function filter_open(...)
- action = actions[select(1, ...)]
-
- http = {}
- http["cookie"] = select(2, ...)
- http["method"] = select(3, ...)
- http["query"] = select(4, ...)
- http["referer"] = select(5, ...)
- http["path"] = select(6, ...)
- http["host"] = select(7, ...)
- http["https"] = select(8, ...)
-
- cgit = {}
- cgit["repo"] = select(9, ...)
- cgit["page"] = select(10, ...)
- cgit["url"] = select(11, ...)
- cgit["login"] = select(12, ...)
-
-end
-
-function filter_close()
- return action()
-end
-
-function filter_write(str)
- post = parse_qs(str)
-end
-
-
---
---
--- Utility functions based on keplerproject/wsapi.
---
---
-
-function url_decode(str)
- if not str then
- return ""
- end
- str = string.gsub(str, "+", " ")
- str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end)
- str = string.gsub(str, "\r\n", "\n")
- return str
-end
-
-function url_encode(str)
- if not str then
- return ""
- end
- str = string.gsub(str, "\n", "\r\n")
- str = string.gsub(str, "([^%w ])", function(c) return string.format("%%%02X", string.byte(c)) end)
- str = string.gsub(str, " ", "+")
- return str
-end
-
-function parse_qs(qs)
- local tab = {}
- for key, val in string.gmatch(qs, "([^&=]+)=([^&=]*)&?") do
- tab[url_decode(key)] = url_decode(val)
- end
- return tab
-end
-
-function get_cookie(cookies, name)
- cookies = string.gsub(";" .. cookies .. ";", "%s*;%s*", ";")
- return string.match(cookies, ";" .. name .. "=(.-);")
-end
-
-function tohex(b)
- local x = ""
- for i = 1, #b do
- x = x .. string.format("%.2x", string.byte(b, i))
- end
- return x
-end
-
---
---
--- Cookie construction and validation helpers.
---
---
-
-local secret = nil
-
--- Loads a secret from a file, creates a secret, or returns one from memory.
-function get_secret()
- if secret ~= nil then
- return secret
- end
- local secret_file = io.open(secret_filename, "r")
- if secret_file == nil then
- local old_umask = sysstat.umask(63)
- local temporary_filename = secret_filename .. ".tmp." .. tohex(rand.bytes(16))
- local temporary_file = io.open(temporary_filename, "w")
- if temporary_file == nil then
- os.exit(177)
- end
- temporary_file:write(tohex(rand.bytes(32)))
- temporary_file:close()
- unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
- unistd.unlink(temporary_filename)
- sysstat.umask(old_umask)
- secret_file = io.open(secret_filename, "r")
- end
- if secret_file == nil then
- os.exit(177)
- end
- secret = secret_file:read()
- secret_file:close()
- if secret:len() ~= 64 then
- os.exit(177)
- end
- return secret
-end
-
--- Returns value of cookie if cookie is valid. Otherwise returns nil.
-function validate_value(expected_field, cookie)
- local i = 0
- local value = ""
- local field = ""
- local expiration = 0
- local salt = ""
- local chmac = ""
-
- if cookie == nil or cookie:len() < 3 or cookie:sub(1, 1) == "|" then
- return nil
- end
-
- for component in string.gmatch(cookie, "[^|]+") do
- if i == 0 then
- field = component
- elseif i == 1 then
- value = component
- elseif i == 2 then
- expiration = tonumber(component)
- if expiration == nil then
- expiration = -1
- end
- elseif i == 3 then
- salt = component
- elseif i == 4 then
- chmac = component
- else
- break
- end
- i = i + 1
- end
-
- if chmac == nil or chmac:len() == 0 then
- return nil
- end
-
- -- Lua hashes strings, so these comparisons are time invariant.
- if chmac ~= tohex(hmac.new(get_secret(), "sha256"):final(field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt)) then
- return nil
- end
-
- if expiration == -1 or (expiration ~= 0 and expiration <= os.time()) then
- return nil
- end
-
- if url_decode(field) ~= expected_field then
- return nil
- end
-
- return url_decode(value)
-end
-
-function secure_value(field, value, expiration)
- if value == nil or value:len() <= 0 then
- return ""
- end
-
- local authstr = ""
- local salt = tohex(rand.bytes(16))
- value = url_encode(value)
- field = url_encode(field)
- authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
- authstr = authstr .. "|" .. tohex(hmac.new(get_secret(), "sha256"):final(authstr))
- return authstr
-end
-
-function set_cookie(cookie, value)
- html("Set-Cookie: " .. cookie .. "=" .. value .. "; HttpOnly")
- if http["https"] == "yes" or http["https"] == "on" or http["https"] == "1" then
- html("; secure")
- end
- html("\n")
-end
-
-function redirect_to(url)
- html("Status: 302 Redirect\n")
- html("Cache-Control: no-cache, no-store\n")
- html("Location: " .. url .. "\n")
-end
-
-function not_found()
- html("Status: 404 Not Found\n")
- html("Cache-Control: no-cache, no-store\n\n")
-end
diff --git a/filters/html-converters/man2html b/filters/html-converters/man2html
deleted file mode 100755
index 0ef7884..0000000
--- a/filters/html-converters/man2html
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-echo "<div style=\"font-family: monospace\">"
-groff -mandoc -T html -P -r -P -l | egrep -v '(<html>|<head>|<meta|<title>|</title>|</head>|<body>|</body>|</html>|<!DOCTYPE|"http://www.w3.org)'
-echo "</div>"
diff --git a/filters/html-converters/md2html b/filters/html-converters/md2html
deleted file mode 100755
index 4f6ad37..0000000
--- a/filters/html-converters/md2html
+++ /dev/null
@@ -1,342 +0,0 @@
-#!/usr/bin/env python3
-import markdown
-import sys
-import io
-from markdown.extensions.toc import TocExtension
-
-# Pygments' token classes, mapped onto the --syn-* custom properties that
-# cgit.css defines. The fallbacks are the palette those properties default to,
-# so that the output stays readable under a stylesheet without them.
-SYNTAX_COLORS = (
- (('k', 'kc', 'kd', 'kn', 'kr'), '--syn-keyword', '#000',
- 'font-weight: bold'),
- (('kp',), '--syn-keyword', '#000', None),
- (('kt',), '--syn-type', '#010181', None),
- (('nc', 'nf', 'nn', 'ne'), '--syn-keyword-alt', '#0057ae', None),
- (('s', 'sa', 'sb', 'sc', 'dl', 'sd', 's2', 'sh', 'sx', 'sr', 's1', 'ss'),
- '--syn-string', '#bf0303', None),
- (('se',), '--syn-escape', '#f0f', None),
- (('si',), '--syn-interpolation', '#0057ae', None),
- (('c', 'ch', 'cm', 'c1', 'cs'), '--syn-comment', '#838183',
- 'font-style: italic'),
- (('cp', 'cpf'), '--syn-preproc', '#008200', None),
- (('m', 'mb', 'mf', 'mh', 'mi', 'mo', 'il'), '--syn-number', '#b07e00',
- None),
- (('o', 'ow', 'p'), '--syn-operator', '#000', None),
- (('err',), '--syn-error', '#bf0303', None),
- (('gd',), '--red', 'red', None),
- (('gi',), '--green', 'green', None),
- (('lineno', 'linenos'), '--syn-linenum', '#555', None),
-)
-
-
-def style_defs(prefix='.highlight'):
- rules = []
- for classes, prop, fallback, extra in SYNTAX_COLORS:
- selector = ', '.join('%s .%s' % (prefix, c) for c in classes)
- decls = 'color: var(%s, %s)' % (prop, fallback)
- if extra:
- decls += '; ' + extra
- rules.append('%s { %s }' % (selector, decls))
- rules.append('%s .hll { background-color: var(--syn-mark-bg, #ffb) }'
- % prefix)
- return '\n'.join(rules) + '\n'
-
-sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8')
-sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
-sys.stdout.write('''
-<style>
-.markdown-body {
- font-size: 14px;
- line-height: 1.6;
- overflow: hidden;
-}
-.markdown-body>*:first-child {
- margin-top: 0 !important;
-}
-.markdown-body>*:last-child {
- margin-bottom: 0 !important;
-}
-.markdown-body a.absent {
- color: var(--red-mid, #c00);
-}
-.markdown-body a.anchor {
- display: block;
- padding-left: 30px;
- margin-left: -30px;
- cursor: pointer;
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
-}
-.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 {
- margin: 20px 0 10px;
- padding: 0;
- font-weight: bold;
- -webkit-font-smoothing: antialiased;
- cursor: text;
- position: relative;
-}
-.markdown-body h1 .mini-icon-link, .markdown-body h2 .mini-icon-link, .markdown-body h3 .mini-icon-link, .markdown-body h4 .mini-icon-link, .markdown-body h5 .mini-icon-link, .markdown-body h6 .mini-icon-link {
- display: none;
- color: var(--fg-strong, #000);
-}
-.markdown-body h1:hover a.anchor, .markdown-body h2:hover a.anchor, .markdown-body h3:hover a.anchor, .markdown-body h4:hover a.anchor, .markdown-body h5:hover a.anchor, .markdown-body h6:hover a.anchor {
- text-decoration: none;
- line-height: 1;
- padding-left: 0;
- margin-left: -22px;
- top: 15%;
-}
-.markdown-body h1:hover a.anchor .mini-icon-link, .markdown-body h2:hover a.anchor .mini-icon-link, .markdown-body h3:hover a.anchor .mini-icon-link, .markdown-body h4:hover a.anchor .mini-icon-link, .markdown-body h5:hover a.anchor .mini-icon-link, .markdown-body h6:hover a.anchor .mini-icon-link {
- display: inline-block;
-}
-div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div#cgit .markdown-body h3 a.toclink, div#cgit .markdown-body h4 a.toclink, div#cgit .markdown-body h5 a.toclink, div#cgit .markdown-body h6 a.toclink {
- color: var(--fg-strong, #000);
-}
-.markdown-body h1 tt, .markdown-body h1 code, .markdown-body h2 tt, .markdown-body h2 code, .markdown-body h3 tt, .markdown-body h3 code, .markdown-body h4 tt, .markdown-body h4 code, .markdown-body h5 tt, .markdown-body h5 code, .markdown-body h6 tt, .markdown-body h6 code {
- font-size: inherit;
-}
-.markdown-body h1 {
- font-size: 28px;
- color: var(--fg-strong, #000);
-}
-.markdown-body h2 {
- font-size: 24px;
- border-bottom: 1px solid var(--border, #ccc);
- color: var(--fg-strong, #000);
-}
-.markdown-body h3 {
- font-size: 18px;
-}
-.markdown-body h4 {
- font-size: 16px;
-}
-.markdown-body h5 {
- font-size: 14px;
-}
-.markdown-body h6 {
- color: var(--fg-mute, #777);
- font-size: 14px;
-}
-.markdown-body p, .markdown-body blockquote, .markdown-body ul, .markdown-body ol, .markdown-body dl, .markdown-body table, .markdown-body pre {
- margin: 15px 0;
-}
-.markdown-body hr {
- border: 2px solid var(--border, #ccc);
-}
-.markdown-body>h2:first-child, .markdown-body>h1:first-child, .markdown-body>h1:first-child+h2, .markdown-body>h3:first-child, .markdown-body>h4:first-child, .markdown-body>h5:first-child, .markdown-body>h6:first-child {
- margin-top: 0;
- padding-top: 0;
-}
-.markdown-body a:first-child h1, .markdown-body a:first-child h2, .markdown-body a:first-child h3, .markdown-body a:first-child h4, .markdown-body a:first-child h5, .markdown-body a:first-child h6 {
- margin-top: 0;
- padding-top: 0;
-}
-.markdown-body h1+p, .markdown-body h2+p, .markdown-body h3+p, .markdown-body h4+p, .markdown-body h5+p, .markdown-body h6+p {
- margin-top: 0;
-}
-.markdown-body li p.first {
- display: inline-block;
-}
-.markdown-body ul, .markdown-body ol {
- padding-left: 30px;
-}
-.markdown-body ul.no-list, .markdown-body ol.no-list {
- list-style-type: none;
- padding: 0;
-}
-.markdown-body ul li>:first-child, .markdown-body ul li ul:first-of-type, .markdown-body ul li ol:first-of-type, .markdown-body ol li>:first-child, .markdown-body ol li ul:first-of-type, .markdown-body ol li ol:first-of-type {
- margin-top: 0px;
-}
-.markdown-body ul li p:last-of-type, .markdown-body ol li p:last-of-type {
- margin-bottom: 0;
-}
-.markdown-body ul ul, .markdown-body ul ol, .markdown-body ol ol, .markdown-body ol ul {
- margin-bottom: 0;
-}
-.markdown-body dl {
- padding: 0;
-}
-.markdown-body dl dt {
- font-size: 14px;
- font-weight: bold;
- font-style: italic;
- padding: 0;
- margin: 15px 0 5px;
-}
-.markdown-body dl dt:first-child {
- padding: 0;
-}
-.markdown-body dl dt>:first-child {
- margin-top: 0px;
-}
-.markdown-body dl dt>:last-child {
- margin-bottom: 0px;
-}
-.markdown-body dl dd {
- margin: 0 0 15px;
- padding: 0 15px;
-}
-.markdown-body dl dd>:first-child {
- margin-top: 0px;
-}
-.markdown-body dl dd>:last-child {
- margin-bottom: 0px;
-}
-.markdown-body blockquote {
- border-left: 4px solid var(--border, #ddd);
- padding: 0 15px;
- color: var(--fg-mute, #777);
-}
-.markdown-body blockquote>:first-child {
- margin-top: 0px;
-}
-.markdown-body blockquote>:last-child {
- margin-bottom: 0px;
-}
-.markdown-body table th {
- font-weight: bold;
-}
-.markdown-body table th, .markdown-body table td {
- border: 1px solid var(--border, #ccc);
- padding: 6px 13px;
-}
-.markdown-body table tr {
- border-top: 1px solid var(--border, #ccc);
- background-color: var(--bg, #fff);
-}
-.markdown-body table tr:nth-child(2n) {
- background-color: var(--bg-zebra, #f8f8f8);
-}
-.markdown-body img {
- max-width: 100%;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-.markdown-body span.frame {
- display: block;
- overflow: hidden;
-}
-.markdown-body span.frame>span {
- border: 1px solid var(--border, #ddd);
- display: block;
- float: left;
- overflow: hidden;
- margin: 13px 0 0;
- padding: 7px;
- width: auto;
-}
-.markdown-body span.frame span img {
- display: block;
- float: left;
-}
-.markdown-body span.frame span span {
- clear: both;
- color: var(--fg, #333);
- display: block;
- padding: 5px 0 0;
-}
-.markdown-body span.align-center {
- display: block;
- overflow: hidden;
- clear: both;
-}
-.markdown-body span.align-center>span {
- display: block;
- overflow: hidden;
- margin: 13px auto 0;
- text-align: center;
-}
-.markdown-body span.align-center span img {
- margin: 0 auto;
- text-align: center;
-}
-.markdown-body span.align-right {
- display: block;
- overflow: hidden;
- clear: both;
-}
-.markdown-body span.align-right>span {
- display: block;
- overflow: hidden;
- margin: 13px 0 0;
- text-align: right;
-}
-.markdown-body span.align-right span img {
- margin: 0;
- text-align: right;
-}
-.markdown-body span.float-left {
- display: block;
- margin-right: 13px;
- overflow: hidden;
- float: left;
-}
-.markdown-body span.float-left span {
- margin: 13px 0 0;
-}
-.markdown-body span.float-right {
- display: block;
- margin-left: 13px;
- overflow: hidden;
- float: right;
-}
-.markdown-body span.float-right>span {
- display: block;
- overflow: hidden;
- margin: 13px auto 0;
- text-align: right;
-}
-.markdown-body code, .markdown-body tt {
- margin: 0 2px;
- padding: 0px 5px;
- border: 1px solid var(--border, #eaeaea);
- background-color: var(--bg-zebra, #f8f8f8);
- border-radius: 3px;
-}
-.markdown-body code {
- white-space: nowrap;
-}
-.markdown-body pre>code {
- margin: 0;
- padding: 0;
- white-space: pre;
- border: none;
- background: transparent;
-}
-.markdown-body .highlight pre, .markdown-body pre {
- background-color: var(--bg-zebra, #f8f8f8);
- border: 1px solid var(--border, #ccc);
- font-size: 13px;
- line-height: 19px;
- overflow: auto;
- padding: 6px 10px;
- border-radius: 3px;
-}
-.markdown-body pre code, .markdown-body pre tt {
- margin: 0;
- padding: 0;
- background-color: transparent;
- border: none;
-}
-''')
-sys.stdout.write(style_defs('.highlight'))
-sys.stdout.write('''
-</style>
-''')
-sys.stdout.write("<div class='markdown-body'>")
-sys.stdout.flush()
-# Note: you may want to run this through bleach for sanitization
-markdown.markdownFromFile(
- output_format="html5",
- extensions=[
- "markdown.extensions.fenced_code",
- "markdown.extensions.codehilite",
- "markdown.extensions.tables",
- "markdown.extensions.sane_lists",
- TocExtension(anchorlink=True)],
- extension_configs={
- "markdown.extensions.codehilite":{"css_class":"highlight"}})
-sys.stdout.write("</div>")
diff --git a/filters/html-converters/rst2html b/filters/html-converters/rst2html
deleted file mode 100755
index 02d90f8..0000000
--- a/filters/html-converters/rst2html
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-exec rst2html.py --template <(echo -e "%(stylesheet)s\n%(body_pre_docinfo)s\n%(docinfo)s\n%(body)s")
diff --git a/filters/html-converters/txt2html b/filters/html-converters/txt2html
deleted file mode 100755
index 495eece..0000000
--- a/filters/html-converters/txt2html
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-echo "<pre>"
-sed "s|&|\\&amp;|g;s|'|\\&apos;|g;s|\"|\\&quot;|g;s|<|\\&lt;|g;s|>|\\&gt;|g"
-echo "</pre>"
diff --git a/filters/owner-example.lua b/filters/owner-example.lua
deleted file mode 100644
index 50fc25a..0000000
--- a/filters/owner-example.lua
+++ /dev/null
@@ -1,17 +0,0 @@
--- This script is an example of an owner-filter. It replaces the
--- usual query link with one to a fictional homepage. This script may
--- be used with the owner-filter or repo.owner-filter settings in
--- cgitrc with the `lua:` prefix.
-
-function filter_open()
- buffer = ""
-end
-
-function filter_close()
- html(string.format("<a href=\"%s\">%s</a>", "http://wiki.example.com/about/" .. buffer, buffer))
- return 0
-end
-
-function filter_write(str)
- buffer = buffer .. str
-end
diff --git a/filters/simple-authentication.lua b/filters/simple-authentication.lua
deleted file mode 100644
index 23d3457..0000000
--- a/filters/simple-authentication.lua
+++ /dev/null
@@ -1,314 +0,0 @@
--- This script may be used with the auth-filter. Be sure to configure it as you wish.
---
--- Requirements:
--- luaossl
--- <http://25thandclement.com/~william/projects/luaossl.html>
--- luaposix
--- <https://github.com/luaposix/luaposix>
---
-local sysstat = require("posix.sys.stat")
-local unistd = require("posix.unistd")
-local rand = require("openssl.rand")
-local hmac = require("openssl.hmac")
-
---
---
--- Configure these variables for your settings.
---
---
-
--- A list of password protected repositories along with the users who can access them.
-local protected_repos = {
- glouglou = { laurent = true, jason = true },
- qt = { jason = true, bob = true }
-}
-
--- A list of users and hashes, generated with `mkpasswd -m sha-512 -R 300000`.
-local users = {
- jason = "$6$rounds=300000$YYJct3n/o.ruYK$HhpSeuCuW1fJkpvMZOZzVizeLsBKcGA/aF2UPuV5v60JyH2MVSG6P511UMTj2F3H75.IT2HIlnvXzNb60FcZH1",
- laurent = "$6$rounds=300000$dP0KNHwYb3JKigT$pN/LG7rWxQ4HniFtx5wKyJXBJUKP7R01zTNZ0qSK/aivw8ywGAOdfYiIQFqFhZFtVGvr11/7an.nesvm8iJUi.",
- bob = "$6$rounds=300000$jCLCCt6LUpTz$PI1vvd1yaVYcCzqH8QAJFcJ60b6W/6sjcOsU7mAkNo7IE8FRGW1vkjF8I/T5jt/auv5ODLb1L4S2s.CAyZyUC"
-}
-
--- Set this to a path this script can write to for storing a persistent
--- cookie secret, which should be guarded.
-local secret_filename = "/var/cache/cgit/auth-secret"
-
---
---
--- Authentication functions follow below. Swap these out if you want different authentication semantics.
---
---
-
--- Sets HTTP cookie headers based on post and sets up redirection.
-function authenticate_post()
- local hash = users[post["username"]]
- local redirect = validate_value("redirect", post["redirect"])
-
- if redirect == nil then
- not_found()
- return 0
- end
-
- redirect_to(redirect)
-
- if hash == nil or hash ~= unistd.crypt(post["password"], hash) then
- set_cookie("cgitauth", "")
- else
- -- One week expiration time
- local username = secure_value("username", post["username"], os.time() + 604800)
- set_cookie("cgitauth", username)
- end
-
- html("\n")
- return 0
-end
-
-
--- Returns 1 if the cookie is valid and 0 if it is not.
-function authenticate_cookie()
- accepted_users = protected_repos[cgit["repo"]]
- if accepted_users == nil then
- -- We return as valid if the repo is not protected.
- return 1
- end
-
- local username = validate_value("username", get_cookie(http["cookie"], "cgitauth"))
- if username == nil or not accepted_users[username:lower()] then
- return 0
- else
- return 1
- end
-end
-
--- Prints the html for the login form.
-function body()
- html("<h2>Authentication Required</h2>")
- html("<form method='post' action='")
- html_attr(cgit["login"])
- html("'>")
- html("<input type='hidden' name='redirect' value='")
- html_attr(secure_value("redirect", cgit["url"], 0))
- html("' />")
- html("<table>")
- html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autofocus /></td></tr>")
- html("<tr><td><label for='password'>Password:</label></td><td><input id='password' name='password' type='password' /></td></tr>")
- html("<tr><td colspan='2'><input value='Login' type='submit' /></td></tr>")
- html("</table></form>")
-
- return 0
-end
-
-
-
---
---
--- Wrapper around filter API, exposing the http table, the cgit table, and the post table to the above functions.
---
---
-
-local actions = {}
-actions["authenticate-post"] = authenticate_post
-actions["authenticate-cookie"] = authenticate_cookie
-actions["body"] = body
-
-function filter_open(...)
- action = actions[select(1, ...)]
-
- http = {}
- http["cookie"] = select(2, ...)
- http["method"] = select(3, ...)
- http["query"] = select(4, ...)
- http["referer"] = select(5, ...)
- http["path"] = select(6, ...)
- http["host"] = select(7, ...)
- http["https"] = select(8, ...)
-
- cgit = {}
- cgit["repo"] = select(9, ...)
- cgit["page"] = select(10, ...)
- cgit["url"] = select(11, ...)
- cgit["login"] = select(12, ...)
-
-end
-
-function filter_close()
- return action()
-end
-
-function filter_write(str)
- post = parse_qs(str)
-end
-
-
---
---
--- Utility functions based on keplerproject/wsapi.
---
---
-
-function url_decode(str)
- if not str then
- return ""
- end
- str = string.gsub(str, "+", " ")
- str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end)
- str = string.gsub(str, "\r\n", "\n")
- return str
-end
-
-function url_encode(str)
- if not str then
- return ""
- end
- str = string.gsub(str, "\n", "\r\n")
- str = string.gsub(str, "([^%w ])", function(c) return string.format("%%%02X", string.byte(c)) end)
- str = string.gsub(str, " ", "+")
- return str
-end
-
-function parse_qs(qs)
- local tab = {}
- for key, val in string.gmatch(qs, "([^&=]+)=([^&=]*)&?") do
- tab[url_decode(key)] = url_decode(val)
- end
- return tab
-end
-
-function get_cookie(cookies, name)
- cookies = string.gsub(";" .. cookies .. ";", "%s*;%s*", ";")
- return url_decode(string.match(cookies, ";" .. name .. "=(.-);"))
-end
-
-function tohex(b)
- local x = ""
- for i = 1, #b do
- x = x .. string.format("%.2x", string.byte(b, i))
- end
- return x
-end
-
---
---
--- Cookie construction and validation helpers.
---
---
-
-local secret = nil
-
--- Loads a secret from a file, creates a secret, or returns one from memory.
-function get_secret()
- if secret ~= nil then
- return secret
- end
- local secret_file = io.open(secret_filename, "r")
- if secret_file == nil then
- local old_umask = sysstat.umask(63)
- local temporary_filename = secret_filename .. ".tmp." .. tohex(rand.bytes(16))
- local temporary_file = io.open(temporary_filename, "w")
- if temporary_file == nil then
- os.exit(177)
- end
- temporary_file:write(tohex(rand.bytes(32)))
- temporary_file:close()
- unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
- unistd.unlink(temporary_filename)
- sysstat.umask(old_umask)
- secret_file = io.open(secret_filename, "r")
- end
- if secret_file == nil then
- os.exit(177)
- end
- secret = secret_file:read()
- secret_file:close()
- if secret:len() ~= 64 then
- os.exit(177)
- end
- return secret
-end
-
--- Returns value of cookie if cookie is valid. Otherwise returns nil.
-function validate_value(expected_field, cookie)
- local i = 0
- local value = ""
- local field = ""
- local expiration = 0
- local salt = ""
- local chmac = ""
-
- if cookie == nil or cookie:len() < 3 or cookie:sub(1, 1) == "|" then
- return nil
- end
-
- for component in string.gmatch(cookie, "[^|]+") do
- if i == 0 then
- field = component
- elseif i == 1 then
- value = component
- elseif i == 2 then
- expiration = tonumber(component)
- if expiration == nil then
- expiration = -1
- end
- elseif i == 3 then
- salt = component
- elseif i == 4 then
- chmac = component
- else
- break
- end
- i = i + 1
- end
-
- if chmac == nil or chmac:len() == 0 then
- return nil
- end
-
- -- Lua hashes strings, so these comparisons are time invariant.
- if chmac ~= tohex(hmac.new(get_secret(), "sha256"):final(field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt)) then
- return nil
- end
-
- if expiration == -1 or (expiration ~= 0 and expiration <= os.time()) then
- return nil
- end
-
- if url_decode(field) ~= expected_field then
- return nil
- end
-
- return url_decode(value)
-end
-
-function secure_value(field, value, expiration)
- if value == nil or value:len() <= 0 then
- return ""
- end
-
- local authstr = ""
- local salt = tohex(rand.bytes(16))
- value = url_encode(value)
- field = url_encode(field)
- authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
- authstr = authstr .. "|" .. tohex(hmac.new(get_secret(), "sha256"):final(authstr))
- return authstr
-end
-
-function set_cookie(cookie, value)
- html("Set-Cookie: " .. cookie .. "=" .. value .. "; HttpOnly")
- if http["https"] == "yes" or http["https"] == "on" or http["https"] == "1" then
- html("; secure")
- end
- html("\n")
-end
-
-function redirect_to(url)
- html("Status: 302 Redirect\n")
- html("Cache-Control: no-cache, no-store\n")
- html("Location: " .. url .. "\n")
-end
-
-function not_found()
- html("Status: 404 Not Found\n")
- html("Cache-Control: no-cache, no-store\n\n")
-end
diff --git a/filters/syntax-highlighting.py b/filters/syntax-highlighting.py
deleted file mode 100755
index d757e2d..0000000
--- a/filters/syntax-highlighting.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python3
-
-# This script uses Pygments and Python3. You must have both installed
-# for this to work.
-#
-# http://pygments.org/
-# http://python.org/
-#
-# It may be used with the source-filter or repo.source-filter settings
-# in cgitrc.
-#
-# The following environment variables can be used to retrieve the
-# configuration of the repository for which this script is called:
-# CGIT_REPO_URL ( = repo.url setting )
-# CGIT_REPO_NAME ( = repo.name setting )
-# CGIT_REPO_PATH ( = repo.path setting )
-# CGIT_REPO_OWNER ( = repo.owner setting )
-# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
-# CGIT_REPO_SECTION ( = section setting )
-# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
-
-
-import sys
-import io
-from pygments import highlight
-from pygments.util import ClassNotFound
-from pygments.lexers import TextLexer
-from pygments.lexers import guess_lexer
-from pygments.lexers import guess_lexer_for_filename
-from pygments.formatters import HtmlFormatter
-
-
-# Pygments' token classes, mapped onto the --syn-* custom properties that
-# cgit.css defines. The fallbacks are the palette those properties default to,
-# so that the output stays readable under a stylesheet without them.
-SYNTAX_COLORS = (
- (('k', 'kc', 'kd', 'kn', 'kr'), '--syn-keyword', '#000',
- 'font-weight: bold'),
- (('kp',), '--syn-keyword', '#000', None),
- (('kt',), '--syn-type', '#010181', None),
- (('nc', 'nf', 'nn', 'ne'), '--syn-keyword-alt', '#0057ae', None),
- (('s', 'sa', 'sb', 'sc', 'dl', 'sd', 's2', 'sh', 'sx', 'sr', 's1', 'ss'),
- '--syn-string', '#bf0303', None),
- (('se',), '--syn-escape', '#f0f', None),
- (('si',), '--syn-interpolation', '#0057ae', None),
- (('c', 'ch', 'cm', 'c1', 'cs'), '--syn-comment', '#838183',
- 'font-style: italic'),
- (('cp', 'cpf'), '--syn-preproc', '#008200', None),
- (('m', 'mb', 'mf', 'mh', 'mi', 'mo', 'il'), '--syn-number', '#b07e00',
- None),
- (('o', 'ow', 'p'), '--syn-operator', '#000', None),
- (('err',), '--syn-error', '#bf0303', None),
- (('gd',), '--red', 'red', None),
- (('gi',), '--green', 'green', None),
- (('lineno', 'linenos'), '--syn-linenum', '#555', None),
-)
-
-
-def style_defs(prefix='.highlight'):
- rules = []
- for classes, prop, fallback, extra in SYNTAX_COLORS:
- selector = ', '.join('%s .%s' % (prefix, c) for c in classes)
- decls = 'color: var(%s, %s)' % (prop, fallback)
- if extra:
- decls += '; ' + extra
- rules.append('%s { %s }' % (selector, decls))
- rules.append('%s .hll { background-color: var(--syn-mark-bg, #ffb) }'
- % prefix)
- return '\n'.join(rules) + '\n'
-
-
-sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8', errors='replace')
-sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
-data = sys.stdin.read()
-filename = sys.argv[1]
-formatter = HtmlFormatter(nobackground=True)
-
-try:
- lexer = guess_lexer_for_filename(filename, data)
-except ClassNotFound:
- # check if there is any shebang
- if data[0:2] == '#!':
- lexer = guess_lexer(data)
- else:
- lexer = TextLexer()
-except TypeError:
- lexer = TextLexer()
-
-# highlight! :-)
-# printout the css definitions for pygments' token classes as well
-sys.stdout.write('<style>')
-sys.stdout.write(style_defs('.highlight'))
-sys.stdout.write('</style>')
-sys.stdout.write(highlight(data, lexer, formatter, outfile=None))
diff --git a/filters/syntax-highlighting.sh b/filters/syntax-highlighting.sh
deleted file mode 100755
index bb8d60c..0000000
--- a/filters/syntax-highlighting.sh
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/bin/sh
-# This script can be used to implement syntax highlighting in the cgit
-# tree-view by referring to this file with the source-filter or repo.source-
-# filter options in cgitrc.
-#
-# This script requires a shell supporting the ${var##pattern} syntax.
-# It is supported by at least dash and bash, however busybox environments
-# might have to use an external call to sed instead.
-#
-# Note: the highlight command (http://www.andre-simon.de/) uses css for syntax
-# highlighting. cgit.css defines these classes in terms of its --syn-* custom
-# properties, so nothing has to be added when using the default stylesheet.
-# The palette below, from highlight 3.13, is what those properties default to;
-# a custom stylesheet wanting the same colors can use it directly:
-#
-# Style definition file generated by highlight 2.4.8, http://www.andre-simon.de/
-#
-# table.blob .num { color:#2928ff; }
-# table.blob .esc { color:#ff00ff; }
-# table.blob .str { color:#ff0000; }
-# table.blob .dstr { color:#818100; }
-# table.blob .slc { color:#838183; font-style:italic; }
-# table.blob .com { color:#838183; font-style:italic; }
-# table.blob .dir { color:#008200; }
-# table.blob .sym { color:#000000; }
-# table.blob .kwa { color:#000000; font-weight:bold; }
-# table.blob .kwb { color:#830000; }
-# table.blob .kwc { color:#000000; font-weight:bold; }
-# table.blob .kwd { color:#010181; }
-#
-#
-# Style definition file generated by highlight 2.6.14, http://www.andre-simon.de/
-#
-# body.hl { background-color:#ffffff; }
-# pre.hl { color:#000000; background-color:#ffffff; font-size:10pt; font-family:'Courier New';}
-# .hl.num { color:#2928ff; }
-# .hl.esc { color:#ff00ff; }
-# .hl.str { color:#ff0000; }
-# .hl.dstr { color:#818100; }
-# .hl.slc { color:#838183; font-style:italic; }
-# .hl.com { color:#838183; font-style:italic; }
-# .hl.dir { color:#008200; }
-# .hl.sym { color:#000000; }
-# .hl.line { color:#555555; }
-# .hl.mark { background-color:#ffffbb;}
-# .hl.kwa { color:#000000; font-weight:bold; }
-# .hl.kwb { color:#830000; }
-# .hl.kwc { color:#000000; font-weight:bold; }
-# .hl.kwd { color:#010181; }
-#
-#
-# Style definition file generated by highlight 3.8, http://www.andre-simon.de/
-#
-# body.hl { background-color:#e0eaee; }
-# pre.hl { color:#000000; background-color:#e0eaee; font-size:10pt; font-family:'Courier New';}
-# .hl.num { color:#b07e00; }
-# .hl.esc { color:#ff00ff; }
-# .hl.str { color:#bf0303; }
-# .hl.pps { color:#818100; }
-# .hl.slc { color:#838183; font-style:italic; }
-# .hl.com { color:#838183; font-style:italic; }
-# .hl.ppc { color:#008200; }
-# .hl.opt { color:#000000; }
-# .hl.lin { color:#555555; }
-# .hl.kwa { color:#000000; font-weight:bold; }
-# .hl.kwb { color:#0057ae; }
-# .hl.kwc { color:#000000; font-weight:bold; }
-# .hl.kwd { color:#010181; }
-#
-#
-# Style definition file generated by highlight 3.13, http://www.andre-simon.de/
-#
-# body.hl { background-color:#e0eaee; }
-# pre.hl { color:#000000; background-color:#e0eaee; font-size:10pt; font-family:'Courier New',monospace;}
-# .hl.num { color:#b07e00; }
-# .hl.esc { color:#ff00ff; }
-# .hl.str { color:#bf0303; }
-# .hl.pps { color:#818100; }
-# .hl.slc { color:#838183; font-style:italic; }
-# .hl.com { color:#838183; font-style:italic; }
-# .hl.ppc { color:#008200; }
-# .hl.opt { color:#000000; }
-# .hl.ipl { color:#0057ae; }
-# .hl.lin { color:#555555; }
-# .hl.kwa { color:#000000; font-weight:bold; }
-# .hl.kwb { color:#0057ae; }
-# .hl.kwc { color:#000000; font-weight:bold; }
-# .hl.kwd { color:#010181; }
-#
-#
-# The following environment variables can be used to retrieve the configuration
-# of the repository for which this script is called:
-# CGIT_REPO_URL ( = repo.url setting )
-# CGIT_REPO_NAME ( = repo.name setting )
-# CGIT_REPO_PATH ( = repo.path setting )
-# CGIT_REPO_OWNER ( = repo.owner setting )
-# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
-# CGIT_REPO_SECTION ( = section setting )
-# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
-#
-
-# store filename and extension in local vars
-BASENAME="$1"
-EXTENSION="${BASENAME##*.}"
-
-[ "${BASENAME}" = "${EXTENSION}" ] && EXTENSION=txt
-[ -z "${EXTENSION}" ] && EXTENSION=txt
-
-# map Makefile and Makefile.* to .mk
-[ "${BASENAME%%.*}" = "Makefile" ] && EXTENSION=mk
-
-# highlight versions 2 and 3 have different commandline options. Specifically,
-# the -X option that is used for version 2 is replaced by the -O xhtml option
-# for version 3.
-#
-# Version 2 can be found (for example) on EPEL 5, while version 3 can be
-# found (for example) on EPEL 6.
-#
-# Note that -I (--include-style) is not used: the stylesheet it embeds in the
-# output would override the .hl rules in cgit.css and with them any theming
-# done through the --syn-* custom properties.
-#
-# This is for version 2
-exec highlight --force -f -X -S "$EXTENSION" 2>/dev/null
-
-# This is for version 3
-#exec highlight --force -f -O xhtml -S "$EXTENSION" 2>/dev/null