💾 Archived View for gemini.conman.org › extensions › GLV-1 › handlers › gRFC.lua captured on 2021-12-03 at 14:04:38.
⬅️ Previous capture (2020-10-31)
-=-=-=-=-=-=-
-- ************************************************************************ -- -- 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 init fini handler -- luacheck: ignore 611 -- RFC-3875 -- ************************************************************************ local abnf = require "org.conman.parsers.abnf" local strftime = require "org.conman.parsers.strftime" local fsys = require "org.conman.fsys" local lpeg = require "lpeg" local io = require "io" local os = require "os" local string = require "string" local table = require "table" _ENV = {} -- ************************************************************************ local parse_headers, parse_body do local Cf = lpeg.Cf local Cg = lpeg.Cg 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 subject = H"Subject" * P":" * LWSP * Cs(text^1) * abnf.CRLF local from = H"From" * P":" * LWSP * Cs(text^1) * abnf.CRLF local date = H"Date" * P":" * LWSP * strftime:match("%a, %e %b %Y") * abnf.CRLF local content_type = H"Content-Type" * P":" * LWSP * Cs(text^1) * abnf.CRLF local status = H"Status" * P":" * LWSP * Cs(text^1) * abnf.CRLF local generic = C(token) * P":" * LWSP * C(text^0) * abnf.CRLF local headers = subject + from + date + status + content_type + generic parse_headers = Cf(Ct"" * Cg(headers)^1,function(acc,name,value) acc[name] = value return acc end) * abnf.CRLF local line = C(R("\9\9"," ~")^0) * abnf.CRLF parse_body = Ct(line^1) end -- ************************************************************************ function handler(conf,_,_,match,ios) if match[1] == "" then ios:write( "20 text/gemini\r\n", "Gemini Request For Comments\r\n", "---------------------------\r\n", "\r\n" ) for file in fsys.gexpand(conf.directory .. "/[0-9][0-9][0-9][0-9]") do local f = io.open(file,"r") local headers = parse_headers:match(f:read("*a")) f:close() local name = fsys.basename(file) local when = os.date("%Y-%m-%d",os.time(headers['Date'])) ios:write(string.format([[=> %s %s %s %-8s %s]], name, name, when, headers['Status'], headers['Subject'] ),"\r\n") end ios:write( "\r\n", "---------------------------\r\n", "GLV-1.12556\r\n" ) return 20 else local f = io.open(conf.directory .. "/" .. match[1],"r") if not f then ios:write("51\r\n") return 51 end local d = f:read("*a") local headers = parse_headers:match(d) local reply = parse_body:match(d) f:close() ios:write( "20 ",headers['Content-Type'],"\r\n", table.concat(reply,"\r\n"), "\r\n" ) return 20 end end -- ************************************************************************ return _ENV