skeksis/lib/skeksis.rb
2023-09-27 18:22:58 +00:00

151 lines
3.6 KiB
Ruby
Executable File

# frozen_string_literal: true
require "yaml"
require "tree"
require_relative "skeksis/version"
require_relative "skeksis/parser"
require_relative "skeksis/htmlize"
module Skeksis
#class Error < StandardError; end
Header = <<~HTML
<!DOCTYPE html>
<html lang="en">
<head>
<title>Gembridge</title>
<style>
h1,h2,h3,h4,h5,h6 {
color: #2e3440;
}
a {
color: #434c5e;
}
a:visited {
color: #4c566a;
}
</style>
</head>
<body>
<h1>Directory Listing</h1>
HTML
Footer = <<~HTML
</body>
</html>
HTML
class GemBridge
def initialize
config = YAML.load(File.read("config.yml"))
@gemini_uri = config['skeksis_config']['gemini_uri']
@serve_dir = config['skeksis_config']['serve_dir']
@allowlist = Tree::TreeNode.new("ROOT", false)
build_allowlist(@allowlist, @serve_dir)
puts @allowlist.to_h
end
def build_allowlist(tree, path)
Dir.each_child(path) do |child|
full_path = Pathname.new(path).join(child)
if child == ".serve_ok"
tree.content = true
end
serve_ok = false
if Dir.exist?(full_path)
Dir.each_child(full_path) do |subchild|
if subchild == ".serve_ok"
serve_ok = true
end
end
child_node = Tree::TreeNode.new(child, serve_ok)
tree << child_node
end
end
end
def query(path, env)
query_path = Pathname.new(path).each_filename.to_a
# Just do a directory listing if we're serving the root path
if path == "/"
return create_dir_listing(@serve_dir, env, check_subdirs=true)
end
# Otherwise check if user's site has opted in to bridging
is_allowed = @allowlist.children.any? {|child| child.name == query_path[0] and child.content == true }
unless is_allowed
return [Header, "Error.", Footer]
end
# End allowlist checking
# Chomps the first / and builds path
full_path = Pathname.new(@serve_dir) + path[1..-1]
puts full_path.to_s
if Dir.exist?(full_path)
index_file = full_path + "index.gmi"
if File.exist?(index_file)
data = File.open(index_file, 'r').readlines
[htmlize(data, env)]
else
create_dir_listing(full_path, env)
end
elsif File.exist?(full_path)
file = File.open(full_path, 'r')
data = file.readlines
[htmlize(data, env)]
else # path is invalid
return nil
end
end
def htmlize(data, env)
Skeksis::Parser.parse(data, strip_blanks=true).htmlize(env, @gemini_uri)
end
private
def load_style
"<script type=\"text/css\">" +
File.open("style/nord.css", 'r').readlines.join("\n") +
"</script>"
end
def create_dir_listing(path, env, check_subdirs=false)
#http = URI.parse(env['REQUEST_URI'])
puts env
unless Dir.each_child(path).include?('.directory-listing-ok')
return nil
end
listing = Dir.each_child(path).map do |i|
if i == ".directory-listing-ok" or i == ".serve_ok"
next
end
child_path = Pathname.new(path).join(i)
puts child_path
if check_subdirs and Dir.exist?(child_path) and not Dir.each_child(child_path).include?('.serve_ok')
next
end
uri_path = Pathname.new(env['PATH_INFO']).join(i)
puts "uri_path: #{uri_path.to_s}"
uri = URI::HTTP.build(host: env['HTTP_HOST'], port: env['SERVER_PORT'], path: uri_path.to_s)
"<a href=\"#{uri.to_s}\">#{i}</a><br>"
end.join("\n")
puts listing
[Header + listing + Footer]
end
end
end