Changed koth to moth. Added some documentation on setting up a web server

This commit is contained in:
Jack Miner 2016-02-16 09:25:45 -07:00
parent 98e0e5ef2c
commit 703a781252
8 changed files with 93 additions and 56 deletions

View File

@ -25,17 +25,55 @@ Please check out [the overview](doc/overview.md)
for details.
Dependencies
--------------------
If you're using Ubuntu 14.04 LTS, you should have everything you need except
[LUA](http://lua.org).
$ sudo apt-get install lua5.2 -y
You'll also have to figure out a way to serve up CGI. Here's one way to do it
on Ubuntu 14.04 LTS with [lighttpd](https://lighttpd.net) where the contest
is at `/opt/moth/mycontest` accessible by user group `moth`, and the web
server is run as user `www-data`:
First, make sure your web server can access the contest files:
$ sudo usermod -a -G moth www-data
Next, install lighttpd and backup the configuration:
$ sudo apt-get install lighttpd
$ cp /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.orig
Add an entry for your contest to your `/etc/hosts`:
127.0.0.1 mycontest
Add a virtual host entry to `/etc/lighttpd/lighttpd.conf`:
$HTTP["host"] == "mycontest" {
server.document-root = "/opt/moth/mycontest/www"
cgi.assign = ( ".cgi" => "/usr/bin/lua" )
}
Finally, restart your server:
$ sudo service lighttpd restart
* Stopping web server lighttpd [ OK ]
* Starting web server lighttpd [ OK ]
How to set it up
--------------------
It's made to be virtualized,
so you can run multiple contests at once if you want.
If you were to want to run it out of `/opt/koth`,
If you were to want to run it out of `/opt/moth`,
do the following:
$ mkdir -p /opt/koth/mycontest
$ ./install /opt/koth/mycontest
$ cp kothd /opt/koth
$ mkdir -p /opt/moth/mycontest
$ ./install /opt/moth/mycontest
$ cp mothd /opt/moth
Yay, you've got it set up.
@ -45,17 +83,16 @@ Installing Puzzle Categories
Puzzle categories are distributed in a different way than the server.
After setting up (see above), just run
$ /opt/koth/mycontest/bin/install-category /path/to/my/category
$ /opt/moth/mycontest/bin/install-category /path/to/my/category
Running It
-------------
Get your web server to serve up files from
`/opt/koth/mycontest/www`.
`/opt/moth/mycontest/www`.
Then run `/opt/koth/kothd`.
Then run `/opt/moth/mothd`.
Permissions

View File

@ -6,7 +6,7 @@ if [ -z "$newdir" ]; then
exit 1
fi
KOTH_BASE=$(cd $(dirname $0)/.. && pwd)
MOTH_BASE=$(cd $(dirname $0)/.. && pwd)
echo "Figuring out web user..."
for www in www-data http _; do
@ -33,5 +33,5 @@ if ! [ -f assigned.txt ]; then
fi
mkdir -p www
cp -r $KOTH_BASE/html/* www/
cp $KOTH_BASE/bin/*.cgi www/
cp -r $MOTH_BASE/html/* www/
cp $MOTH_BASE/bin/*.cgi www/

View File

@ -1,12 +1,12 @@
#! /bin/sh
cd ${1:-$(dirname $0)}
KOTH_BASE=$(pwd)
MOTH_BASE=$(pwd)
echo "Running koth instances in $KOTH_BASE"
echo "Running moth instances in $MOTH_BASE"
while true; do
for i in $KOTH_BASE/*/assigned.txt; do
for i in $MOTH_BASE/*/assigned.txt; do
dir=${i%/*}
$dir/bin/once
done

View File

@ -1,9 +1,9 @@
#! /usr/bin/env lua
local koth = {}
local moth = {}
-- cut -d$ANCHOR -f2- | grep -Fx "$NEEDLE"
function koth.anchored_search(haystack, needle, anchor)
function moth.anchored_search(haystack, needle, anchor)
local f, err = io.open(haystack)
if (not f) then
return false, err
@ -27,7 +27,7 @@ function koth.anchored_search(haystack, needle, anchor)
return false
end
function koth.page(title, body)
function moth.page(title, body)
if (os.getenv("REQUEST_METHOD")) then
print("Content-type: text/html")
print()
@ -52,7 +52,7 @@ end
--
-- We're going to rely on `bin/once` only processing files with the right number of lines.
--
function koth.award_points(team, category, points, comment)
function moth.award_points(team, category, points, comment)
team = team:gsub("[^0-9a-f]", "-")
if (team == "") then
team = "-"
@ -65,19 +65,19 @@ function koth.award_points(team, category, points, comment)
entry = entry .. " " .. comment
end
local f = io.open(koth.path("state/teams/" .. team))
local f = io.open(moth.path("state/teams/" .. team))
if (f) then
f:close()
else
return false, "No such team"
end
local ok = koth.anchored_search(koth.path("state/points.log"), entry, " ")
local ok = moth.anchored_search(moth.path("state/points.log"), entry, " ")
if (ok) then
return false, "Points already awarded"
end
local f = io.open(koth.path("state/points.new/" .. filename), "a")
local f = io.open(moth.path("state/points.new/" .. filename), "a")
if (not f) then
return false, "Unable to write to points file"
end
@ -91,19 +91,19 @@ end
-- Most web servers cd to the directory containing the CGI.
-- Not uhttpd.
koth.base = ""
function koth.path(p)
return koth.base .. p
moth.base = ""
function moth.path(p)
return moth.base .. p
end
-- Traverse up to find assigned.txt
for i = 0, 5 do
local f = io.open(koth.path("assigned.txt"))
local f = io.open(moth.path("assigned.txt"))
if (f) then
f:close()
break
end
koth.base = koth.base .. "../"
moth.base = moth.base .. "../"
end
return koth
return moth

View File

@ -3,7 +3,7 @@
package.path = "?.lua;cgi-bin/?.lua;www/cgi-bin/?.lua"
local cgi = require "cgi"
local koth = require "koth"
local moth = require "moth"
local team = cgi.fields['t'] or ""
local category = cgi.fields['c'] or ""
@ -15,20 +15,20 @@ category = category:gsub("[^A-Za-z0-9]", "-")
-- Check answer
local needle = points .. " " .. answer
local haystack = koth.path("packages/" .. category .. "/answers.txt")
local found, err = koth.anchored_search(haystack, needle)
local haystack = moth.path("packages/" .. category .. "/answers.txt")
local found, err = moth.anchored_search(haystack, needle)
if (not found) then
koth.page("Wrong answer", err)
moth.page("Wrong answer", err)
end
local ok, err = koth.award_points(team, category, points)
local ok, err = moth.award_points(team, category, points)
if (not ok) then
koth.page("Error awarding points",
moth.page("Error awarding points",
"<p>You got the right answer, but there was a problem trying to give you points:</p>" ..
"<p>" .. err .. "</p>")
end
koth.page("Points awarded",
moth.page("Points awarded",
"<p>" .. points .. " points for " .. team .. "!</p>" ..
"<p><a href=\"../puzzles.html\">Back to puzzles</a></p>")

View File

@ -2,18 +2,18 @@
package.path = "?.lua;cgi-bin/?.lua;www/cgi-bin/?.lua"
local koth = require "koth"
local moth = require "moth"
local max_by_cat = {}
local f = io.popen("ls " .. koth.path("packages"))
local f = io.popen("ls " .. moth.path("packages"))
for cat in f:lines() do
max_by_cat[cat] = 0
end
f:close()
for line in io.lines(koth.path("state/points.log")) do
for line in io.lines(moth.path("state/points.log")) do
local ts, team, cat, points, comment = line:match("^(%d+) (%w+) ([%w-]+) (%d+) ?(.*)")
points = tonumber(points) or 0
@ -29,7 +29,7 @@ for cat, biggest in pairs(max_by_cat) do
body = body .. "<dt>" .. cat .. "</dt>"
body = body .. "<dd>"
for line in io.lines(koth.path("packages/" .. cat .. "/map.txt")) do
for line in io.lines(moth.path("packages/" .. cat .. "/map.txt")) do
points, dirname = line:match("^(%d+) (.*)")
points = tonumber(points)
@ -54,4 +54,4 @@ body = body .. "</form>"
body = body .. "</fieldset>"
body = body .. "<p>Reloading this page periodically may yield updated puzzle lists.</p>"
koth.page("Open Puzzles", body)
moth.page("Open Puzzles", body)

View File

@ -4,7 +4,7 @@ package.path = "?.lua;cgi-bin/?.lua;www/cgi-bin/?.lua"
local cgi = require "cgi"
local koth = require "koth"
local moth = require "moth"
local team = cgi.fields["n"] or ""
local hash = cgi.fields["h"] or ""
@ -12,22 +12,22 @@ local hash = cgi.fields["h"] or ""
hash = hash:match("[0-9a-f]*")
if ((hash == "") or (team == "")) then
koth.page("Invalid Entry", "Oops! Are you sure you got that right?")
elseif (not koth.anchored_search(koth.path("assigned.txt"), hash)) then
koth.page("Invalid Hash", "Oops! I don't have a record of that hash. Did you maybe use capital letters accidentally?")
moth.page("Invalid Entry", "Oops! Are you sure you got that right?")
elseif (not moth.anchored_search(moth.path("assigned.txt"), hash)) then
moth.page("Invalid Hash", "Oops! I don't have a record of that hash. Did you maybe use capital letters accidentally?")
end
local f = io.open(koth.path("state/teams/" .. hash))
local f = io.open(moth.path("state/teams/" .. hash))
if (f) then
f:close()
koth.page("Already Exists", "Your team has already been named! Maybe somebody on your team beat you to it.")
moth.page("Already Exists", "Your team has already been named! Maybe somebody on your team beat you to it.")
end
local f, err = io.open(koth.path("state/teams/" .. hash), "w+")
local f, err = io.open(moth.path("state/teams/" .. hash), "w+")
if (not f) then
koth.page("Kersplode", err)
moth.page("Kersplode", err)
end
f:write(team)
f:close()
koth.page("Success", "Okay, your team has been named and you may begin using your hash!")
moth.page("Success", "Okay, your team has been named and you may begin using your hash!")

View File

@ -3,36 +3,36 @@
package.path = "?.lua;cgi-bin/?.lua;www/cgi-bin/?.lua"
local cgi = require "cgi"
local koth = require "koth"
local moth = require "moth"
local team = cgi.fields['t'] or ""
local token = cgi.fields['k'] or ""
-- Check answer
local needle = token
local haystack = koth.path("tokens.txt")
local found, err = koth.anchored_search(haystack, needle)
local haystack = moth.path("tokens.txt")
local found, err = moth.anchored_search(haystack, needle)
if (not found) then
koth.page("Unrecognized token", err)
moth.page("Unrecognized token", err)
end
local category, points = token:match("^(.*):(.*):")
if ((category == nil) or (points == nil)) then
koth.page("Unrecognized token", "Something doesn't look right about that token")
moth.page("Unrecognized token", "Something doesn't look right about that token")
end
points = tonumber(points)
-- Defang category name; prevent directory traversal
category = category:gsub("[^A-Za-z0-9]", "-")
local ok, err = koth.award_points(team, category, points, token)
local ok, err = moth.award_points(team, category, points, token)
if (not ok) then
koth.page("Error awarding points",
moth.page("Error awarding points",
"<p>You entered a valid token, but there was a problem trying to give you points:</p>" ..
"<p>" .. err .. "</p>")
end
koth.page("Points awarded",
moth.page("Points awarded",
"<p>" .. points .. " points for " .. team .. "!</p>" ..
"<p><a href=\"../puzzles.html\">Back to puzzles</a></p>")