💾 Archived View for gemini.conman.org › extensions › GLV-1 › handlers › torture.lua captured on 2023-09-28 at 19:24:37.
⬅️ Previous capture (2022-06-04)
-=-=-=-=-=-=-
-- ************************************************************************ -- -- CGI interface. -- Copyright 2019 by Sean Conner. All Rights Reserved. -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- -- Comments, questions and criticisms can be sent to: sean@conman.org -- -- ************************************************************************ -- luacheck: globals handler -- luacheck: ignore 611 local syslog = require "org.conman.syslog" local fsys = require "org.conman.fsys" local abnf = require "org.conman.parsers.abnf" local uurl = require "GLV-1.url-util" local lpeg = require "lpeg" local io = require "io" local string = require "string" local tonumber = tonumber _ENV = {} -- ************************************************************************ local parse_headers do local Cf = lpeg.Cf local Cg = lpeg.Cg local Cp = lpeg.Cp local Cs = lpeg.Cs local Ct = lpeg.Ct local C = lpeg.C local P = lpeg.P local R = lpeg.R local S = lpeg.S local H do local text = R("AZ","az") / function(c) return P(c:lower()) + P(c:upper()) end + P(1) / function(c) return P(c) end H = function(s) local pattern = Cf(text^1,function(acc,pat) return acc * pat end) return pattern:match(s) / s end end local LWSP = (abnf.WSP + abnf.CRLF * abnf.WSP) local text = LWSP^1 / " " + abnf.VCHAR local separator = S'()<>@,;:\\"/[]?={}\t ' local token = (abnf.VCHAR - separator)^1 local number = R"09"^1 / tonumber local title = H"Title" * P":" * LWSP * Cs(text^1) * abnf.CRLF local status = H"Status" * P":" * LWSP * number * abnf.CRLF local content_type = H"Content-Type" * P":" * LWSP * Cs(text^1) * abnf.CRLF local location = H"Location" * P":" * LWSP * Cs(text^1) * abnf.CRLF local reason = H"Error" * P":" * LWSP * Cs(text^1) * abnf.CRLF local generic = C(token) * P":" * LWSP * C(text^0) * abnf.CRLF local headers = title + status + content_type + location + reason + generic parse_headers = Cf(Ct"" * Cg(headers)^1,function(acc,name,value) acc[name] = value return acc end) * abnf.CRLF * Cp() end -- ************************************************************************ function handler(conf,_,loc,pathinfo,ios) local function write_status(headers,textfield) ios:write(string.format("%d %s\r\n",headers['Status'],headers[textfield])) end if pathinfo == "" then loc.path = loc.path .. "/" ios:write("31 ",uurl.toa(loc),"\r\n") return 31 end if not pathinfo:match "^/" then ios:write("51\r\n") return 51 end pathinfo = pathinfo:sub(2,-1) if pathinfo == "" then pathinfo = "0000" end local fname = conf.directory .. "/" .. pathinfo local file,err = io.open(fname,"r") if not file then syslog('error',"%s = %s",fname,err) ios:write("40\r\n") return 40 end local headers = "" for line in file:lines() do headers = headers .. line .. "\n" if line == "" then break end end if not headers then syslog('error',"bad headers") ios:write("40\r\n") return 40 end headers = parse_headers:match(headers) if not headers then syslog('error',"cannot parse headers") ios:write("40\r\n") return 40 end if headers['Status'] == 39 then write_status(headers,'Location') elseif headers['Status'] == 49 then write_status(headers,'Error') elseif headers['Status'] == 58 then write_status(headers,'Error') else write_status(headers,'Content-Type') repeat local data = file:read(1024) if data then ios:write(data) end until not data if pathinfo == "0000" then ios:write("\r\nList of tests\r\n\r\n") for filename in fsys.gexpand(conf.directory .. "/[0-9][0-9][0-9][0-9]") do local f = io.open(filename,"r") local hdr = "" for line in f:lines() do hdr = hdr .. line .. "\n" if line == "" then break end end hdr = parse_headers:match(hdr) f:close() local name = fsys.basename(filename) ios:write( string.format("=> %s %s %s\r\n", name, name, hdr['Title'] )) end end file:close() end return headers['Status'] end -- ************************************************************************ return _ENV