186 lines
5.1 KiB
Lua
186 lines
5.1 KiB
Lua
local Lyre = require"lyre"
|
|
local Mime = require"mimetypes"
|
|
|
|
local BigGlobe = require"bigglobe"
|
|
|
|
local DB = require"db"
|
|
local Escapes = require"html"
|
|
local LFS = require"lfs"
|
|
|
|
local SMTPAuth = require"smtpauth"
|
|
|
|
-- Add template inclusions to Lyre
|
|
local function compiel(fn, sub)
|
|
local f = io.open(fn, "rb")
|
|
local buf = {}
|
|
|
|
for l in f:lines() do
|
|
local includie = l:match("^{#%s*(.*)$")
|
|
if includie then
|
|
table.insert(buf, compiel(includie, true))
|
|
else
|
|
table.insert(buf, l)
|
|
end
|
|
end
|
|
|
|
f:close()
|
|
|
|
return sub and table.concat(buf, "\n") or Lyre.compile(table.concat(buf, "\n"), fn)
|
|
end
|
|
|
|
local Static = {}
|
|
local Templates = {
|
|
["/"] = compiel("index.html.l"),
|
|
["/search"] = compiel("search.html.l"),
|
|
["/obji"] = compiel("obj.html.l"),
|
|
["/obje"] = compiel("obje.html.l"),
|
|
["/login"] = compiel("login.html.l"),
|
|
["/admin"] = compiel("admin.html.l"),
|
|
["/user"] = compiel("user.html.l"),
|
|
["/invite"] = compiel("invite.html.l"),
|
|
["/reportuser"] = compiel("reportuser.html.l"),
|
|
["/reg"] = compiel("reg.html.l"),
|
|
["/reports"] = compiel("reports.html.l"),
|
|
["404"] = compiel("404.html.l"),
|
|
}
|
|
|
|
local handler = function(req, res)
|
|
local verified = req:cookie"sesh" and DB.userverify(Escapes.urlunescape(req:cookie"sesh"))
|
|
|
|
if verified and verified.privs == DB.USER_PRIVS_BANNED then
|
|
verified = nil
|
|
end
|
|
|
|
if req:path() == "/autocomp" then
|
|
res:contentType("text/plain;charset=UTF-8")
|
|
res:write(DB.autocomplete(Escapes.urlunescape(req.querystring.q), req.querystring.a ~= nil))
|
|
elseif req:path():match"^/addobj/?$" then
|
|
if verified then
|
|
local oid = DB.regnewobj(verified.id, verified.privs >= DB.USER_PRIVS_APPROVED, false)
|
|
if oid then
|
|
res:addHeader("Location", "/obje/" .. DB.objhideid(oid))
|
|
res:statusCode(303)
|
|
end
|
|
else
|
|
res:statusCode(403)
|
|
end
|
|
res:write""
|
|
elseif req:path():match"^/verif/?$" then
|
|
res:addHeader("Set-Cookie", "sesh=" .. (req.querystring.q or "") .. "; SameSite=Lax; Secure; HttpOnly")
|
|
res:addHeader("Location", "/")
|
|
res:statusCode(303)
|
|
res:write""
|
|
elseif req:path():match"^/apprq/?$" then
|
|
if verified and verified.privs >= DB.USER_PRIVS_MOD then
|
|
-- Has decided on something already?
|
|
if req.querystring.csrf and DB.csrfverify(verified.id, Escapes.urlunescape(req.querystring.csrf)) then
|
|
local oid = DB.objshowid(Escapes.urlunescape(req.querystring.oid))
|
|
|
|
if req.querystring.deliamsure and DB.getuserbyid(DB.getobj(oid).owner).privs < verified.privs then
|
|
if req.querystring.banuser then
|
|
DB.banuser(DB.getobj(oid).owner)
|
|
end
|
|
|
|
DB.delobj(oid, req.querystring.delfiles ~= nil)
|
|
elseif req.querystring.approveiamsure then
|
|
if req.querystring.approveuser then
|
|
DB.approveuser(DB.getobj(oid).owner)
|
|
end
|
|
|
|
DB.approveobj(oid)
|
|
end
|
|
end
|
|
|
|
local oid = DB.nexttoapproveobj()
|
|
res:addHeader("Location", oid and ("/obji/" .. DB.objhideid(oid)) or "/")
|
|
res:statusCode(303)
|
|
else
|
|
res:statusCode(403)
|
|
end
|
|
res:write""
|
|
elseif req:path():match"^/static/" or req:path():match"^/objd/" or req:path() == "/favicon.ico" then
|
|
local p = req:path()
|
|
|
|
res:contentType(Mime.guess(p:sub(2):lower()) or "text/plain")
|
|
|
|
-- Force download
|
|
if p:match"^/objd/" then
|
|
res:addHeader("Content-Disposition", "attachment;filename=\"" .. p:match"^/objd/[^/]+/(.*)$" .. "\"")
|
|
end
|
|
|
|
res:addHeader("Cache-Control", "max-age=604800")
|
|
|
|
if req:method() == "HEAD" then
|
|
res:write""
|
|
return
|
|
end
|
|
|
|
local phys = DB.urltophysical(p)
|
|
|
|
if not BigGlobe.cfg.sendfile:match"^%s*$" then
|
|
res:addHeader(BigGlobe.cfg.sendfile, BigGlobe.cfg.sendfileprefix .. "/" .. phys)
|
|
res:write""
|
|
else
|
|
local f = io.open(phys, "rb")
|
|
if f then
|
|
local sz = f:seek("end")
|
|
if req:headers()["range"] then
|
|
local starto, endo = req:headers()["range"]:match("^bytes%=(%d+)%-(%d*)$")
|
|
starto = tonumber(starto)
|
|
endo = tonumber(endo)
|
|
if not endo then
|
|
endo = sz - 1
|
|
elseif endo >= sz then
|
|
res:statusCode(416)
|
|
res:write""
|
|
return
|
|
end
|
|
if starto and endo and starto <= endo then
|
|
res:statusCode(206)
|
|
res:addHeader("Accept-Ranges", "bytes")
|
|
res:addHeader("Content-Length", endo - starto + 1)
|
|
res:addHeader("Content-Range", "bytes " .. starto .. "-" .. endo .. "/" .. sz)
|
|
|
|
f:seek("set", starto)
|
|
res:write(f:read(endo - starto + 1))
|
|
end
|
|
else
|
|
f:seek("set")
|
|
res:write(f:read"*a")
|
|
end
|
|
f:close()
|
|
else
|
|
res:statusCode(404)
|
|
res:write""
|
|
end
|
|
end
|
|
else
|
|
local tmpl = Templates[req:path():sub(1, req:path():sub(2):find("/") or -1)]
|
|
if not tmpl then
|
|
res:statusCode(404)
|
|
tmpl = Templates["404"]
|
|
end
|
|
|
|
res:statusCode(200)
|
|
|
|
local env = {BigGlobe = BigGlobe, SMTPAuth = SMTPAuth, DB = DB, Escapes = Escapes, LFS = LFS, request = req, response = res, print = print, verified = verified}
|
|
|
|
local succ, val
|
|
if _ENV then
|
|
succ, val = xpcall(Lyre.render, debug.traceback, tmpl, env)
|
|
else
|
|
succ, val = pcall(Lyre.render, tmpl, env)
|
|
end
|
|
|
|
if succ then
|
|
res:write(val)
|
|
else
|
|
print("Error!")
|
|
print(val)
|
|
res:statusCode(500)
|
|
res:write"Internal server error. Try not doing that."
|
|
end
|
|
end
|
|
end
|
|
|
|
return handler |