#!/usr/bin/env luajit local function escape(s) return s:gsub("<", "<"):gsub("<", "<") end local function urldecode(s) if s == nil then return nil end return s:gsub("+", " "):gsub("%%20", " ") end local function urlencode(s) if s == nil then return nil end return s:gsub(" ", "%%20") end local function parse_query(q) if q == nil then return {} end local data = {} for pair in string.gmatch(q, "([^&]+)") do local flag = string.match(pair, "^([^=]+)$") if flag ~= nil then data[flag] = "1" else local key, value = string.match(pair, "^([^=]+)=([^=]*)$") if key ~= nil and value ~= nil then data[key] = urldecode(value) end end end return data end local path = os.getenv("PATH_INFO") local method = os.getenv("REQUEST_METHOD") local query = parse_query(os.getenv("QUERY_STRING")) local stylesheet = [[ /* body { background-color: #161616; } h1, h2, h3, h4, h5, h6, p, label, a { color: #e2e2e2; } */ .amount-presets form { display: inline-block; width: 60px } .amount-pos { color: green; } .amount-neg { color: red; } nav h2 { display: inline-block } .notif { padding: 0.5em; margin: 0.5em; background-color: #ddd; } .notif p { margin: 5px; } form.box { border: 2px solid grey; padding: 0.5em; margin: 0.5em; display: inline-block; } form h3 { margin: 5px; } ]] local script = [[ ]] local function respond(status, title, body) print(string.format("Status: %d", status)) print("Content-Type: text/html") print("") print(string.format([[
Error: %s
", escape(message))) end) end local function redirect(path) print("Status: 307") print(string.format("Location: %s", path)) print() end local function form_data() return parse_query(io.read()) end local function read_log() local log = io.open("log", "r") if log == nil then return function() return nil end end local lines = log:lines("l") return function() local l = lines() if l == "" or l == nil then return nil end local time, username, amount, comment = string.match(l, "(%d+),([%w_ -]+),(-?%d+),([%w_ -]*)") return tonumber(time), username, tonumber(amount), comment end end local function read_products() local log = io.open("products", "r") if log == nil then return function() return nil end end local lines = log:lines("l") return function() local l = lines() if l == "" or l == nil then return nil end local barcode, amount, name = string.match(l, "([%w_-]+),(-?%d+),([%w_ -]*)") return barcode, tonumber(amount), name end end local function balances() local users = {} for _, username, amount, _ in read_log() do users[username] = (users[username] or 0) + amount end return users end local function r_user() if path == nil then return respond_error("no path") end local username = urldecode(path:sub(2)) if username == nil or username:match("^([%w_ -]+)$") == nil then return respond_error("username invalid") end local notif = nil if method == "POST" then local data = form_data() local amount = nil local comment = "" if data.barcode then for p_barcode, p_amount, p_name in read_products() do if p_barcode == data.barcode then amount = p_amount comment = p_name end end else amount = tonumber(data.amount) comment = data.comment or "" end if amount == nil then return respond_error("amount invalid") end if comment:match("^[%w_ -]*$") == nil then return respond_error("comment invalid") end local log = io.open("log", "a+") if log == nil then return respond_error("failed to open log") end local time = os.time() log:write(string.format("%d,%s,%d,%s\n", time, username, amount, comment)) log:flush() log:close() notif = string.format( "Transaction successful: %.02f€ (%s)
This user account does not exist yet. It will only be created after the first transaction.
Current balance: %.02f€
", balance >= 0 and "pos" or "neg", balance / 100)) print([[ ]]) print("Time | Username | Amount | Comment |
---|---|---|---|
%d | %s | %.02f€ | %s |