49 lines
1.1 KiB
Crystal
49 lines
1.1 KiB
Crystal
require "uri"
|
|
|
|
# Processes a Gemini request
|
|
class Gemini::Request
|
|
getter server : Server
|
|
getter connection : IO
|
|
getter uri : URI
|
|
getter path : Path
|
|
getter host : Path
|
|
|
|
def initialize(@server, @connection, uri : String)
|
|
@uri = URI.parse uri
|
|
|
|
if @uri.host.nil? || @uri.host.try(&.blank?)
|
|
raise Error.new("Host can't be empty")
|
|
end
|
|
|
|
@host = @server.pwd / Path[@uri.host || "doesnt_exist"]
|
|
@path = process_path
|
|
end
|
|
|
|
# Validates the request by raising exceptions
|
|
def validate!
|
|
unless host_exist?
|
|
raise Error.new("Missing host directory #{@uri.host} at #{Dir.current}, you may need to create and populate it")
|
|
end
|
|
|
|
if malicious_path?
|
|
raise Error.new("#{path} is outside served directory #{@host}")
|
|
end
|
|
end
|
|
|
|
def host_exist? : Bool
|
|
File.directory? @host
|
|
end
|
|
|
|
# Path must be inside served directory
|
|
def malicious_path? : Bool
|
|
!path.to_s.starts_with?(@host.to_s)
|
|
end
|
|
|
|
private def process_path : Path
|
|
path = (@host / Path[@uri.path]).normalize
|
|
path = path / Path["index.gmi"] if File.directory? path
|
|
|
|
path
|
|
end
|
|
end
|