2023-07-29 20:04:45 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2023-08-05 01:49:40 +00:00
|
|
|
require "yaml"
|
2023-08-29 20:18:52 +00:00
|
|
|
require "tree"
|
2023-08-05 01:49:40 +00:00
|
|
|
|
2023-07-29 20:04:45 +00:00
|
|
|
require_relative "skeksis/version"
|
2023-08-02 02:53:54 +00:00
|
|
|
require_relative "skeksis/parser"
|
2023-08-03 17:42:28 +00:00
|
|
|
require_relative "skeksis/htmlize"
|
2023-07-29 20:04:45 +00:00
|
|
|
|
|
|
|
module Skeksis
|
2023-08-05 01:49:40 +00:00
|
|
|
#class Error < StandardError; end
|
2023-08-07 18:04:55 +00:00
|
|
|
Header = <<~HTML
|
2023-08-15 18:35:52 +00:00
|
|
|
<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
2023-08-07 18:04:55 +00:00
|
|
|
<head>
|
|
|
|
<title>Gembridge</title>
|
2023-08-15 18:35:52 +00:00
|
|
|
<style>
|
|
|
|
h1,h2,h3,h4,h5,h6 {
|
|
|
|
color: #2e3440;
|
|
|
|
}
|
|
|
|
a {
|
|
|
|
color: #434c5e;
|
|
|
|
}
|
|
|
|
a:visited {
|
|
|
|
color: #4c566a;
|
|
|
|
}
|
|
|
|
</style>
|
2023-08-07 18:04:55 +00:00
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Directory Listing</h1>
|
|
|
|
HTML
|
|
|
|
|
|
|
|
Footer = <<~HTML
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
HTML
|
2023-08-05 01:49:40 +00:00
|
|
|
|
|
|
|
class GemBridge
|
|
|
|
def initialize
|
2023-08-08 01:02:09 +00:00
|
|
|
config = YAML.load(File.read("config.yml"))
|
|
|
|
@gemini_uri = config['skeksis_config']['gemini_uri']
|
|
|
|
@serve_dir = config['skeksis_config']['serve_dir']
|
2023-08-29 20:18:52 +00:00
|
|
|
@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
|
2023-08-05 01:49:40 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def query(path, env)
|
2023-08-29 20:18:52 +00:00
|
|
|
query_path = Pathname.new(path).each_filename.to_a
|
|
|
|
|
2023-09-26 21:46:47 +00:00
|
|
|
# Just do a directory listing if we're serving the root path
|
|
|
|
if path == "/"
|
|
|
|
return create_dir_listing(@serve_dir, env)
|
2023-08-29 20:18:52 +00:00
|
|
|
end
|
|
|
|
|
2023-09-26 21:46:47 +00:00
|
|
|
# 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
|
|
|
|
|
2023-08-08 01:02:09 +00:00
|
|
|
# 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')
|
2023-08-05 01:49:40 +00:00
|
|
|
data = file.readlines
|
|
|
|
[htmlize(data, env)]
|
|
|
|
else # path is invalid
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
end
|
2023-08-03 17:42:28 +00:00
|
|
|
|
2023-08-05 01:49:40 +00:00
|
|
|
def htmlize(data, env)
|
|
|
|
Skeksis::Parser.parse(data, strip_blanks=true).htmlize(env['REQUEST_URI'], @gemini_uri)
|
|
|
|
end
|
2023-08-07 18:04:55 +00:00
|
|
|
|
|
|
|
private
|
|
|
|
|
2023-08-15 18:35:52 +00:00
|
|
|
def load_style
|
|
|
|
"<script type=\"text/css\">" +
|
|
|
|
File.open("style/nord.css", 'r').readlines.join("\n") +
|
|
|
|
"</script>"
|
|
|
|
end
|
|
|
|
|
2023-08-07 18:04:55 +00:00
|
|
|
def create_dir_listing(path, env)
|
|
|
|
http = URI.parse(env['REQUEST_URI'])
|
2023-08-15 18:35:52 +00:00
|
|
|
|
|
|
|
unless Dir.each_child(path).include?('.directory-listing-ok')
|
|
|
|
return nil
|
|
|
|
end
|
2023-08-07 18:04:55 +00:00
|
|
|
|
|
|
|
listing = Dir.each_child(path).map do |i|
|
2023-08-29 20:18:52 +00:00
|
|
|
if i == ".directory-listing-ok" or i == ".serve_ok"
|
|
|
|
next
|
|
|
|
end
|
|
|
|
|
|
|
|
child_path = Pathname.new(path).join(i)
|
|
|
|
puts child_path
|
|
|
|
|
|
|
|
if Dir.exist?(child_path) and not Dir.each_child(child_path).include?('.serve_ok')
|
2023-08-15 18:35:52 +00:00
|
|
|
next
|
|
|
|
end
|
|
|
|
|
2023-08-29 20:18:52 +00:00
|
|
|
uri_path = Pathname.new(env['PATH_INFO']).join(i)
|
|
|
|
uri = URI::HTTP.build(host: http.host, port: http.port, path: uri_path.to_s)
|
2023-08-15 18:35:52 +00:00
|
|
|
"<a href=\"#{uri.to_s}\">#{i}</a><br>"
|
2023-08-07 18:04:55 +00:00
|
|
|
end.join("\n")
|
|
|
|
[Header + listing + Footer]
|
|
|
|
end
|
2023-08-03 17:42:28 +00:00
|
|
|
end
|
2023-07-29 20:04:45 +00:00
|
|
|
end
|