#!/usr/bin/ruby require 'socket' require 'fileutils' require './database.rb' ANSI_GREEN = "\e[32m" ANSI_BLUE = "\e[34m" ANSI_CLEAR = "\e[0m" APPNAME = "#{ANSI_GREEN}APOCRYPHA#{ANSI_CLEAR}" HTTP_GET = "GET" HTTP_POST = "POST" HTTP_QUERY = "QUERY" HTTP_NIL = "NIL" ROOT = ARGV[0] PORT = ARGV[1] db = Database.new('db.rb') def message(msg) puts "#{APPNAME}: #{msg}" end def error(msg) puts "#{APPNAME}: #{msg}" exit 1 end #just to make the rest of the code look prettier class String def as_root return "#{ROOT}/#{self}" end def tag(tag) return "<#{tag}>#{self}" end def tag_href(tag, href) return "<#{tag} href=#{href}>#{self}" end def tag_attrs(tag, attrs) #this is kinda yucky return "<#{tag} #{attrs.keys[0]}=\"#{attrs.values[0]}\">#{self}" end end def tmpl_not_found(data) "404 File not found: #{data}" end def http_ok(data) return "HTTP/1.1 200 OK\r\n\r\n #{data.join}" if data.class == Array return "HTTP/1.1 200 OK\r\n\r\n #{data}" if data.class == String message("could not :(") end def http_png(data) return "HTTP/1.1 200 OK\r\nContent-Length: #{data.length}\r\nConnection: close\r\nContent-Type: image/png\r\n\r\n#{data}" puts data.bytes #message("could not :(") end def http_not_found(uri) return "HTTP/1.1 404 Not Found\r\n\r\n #{tmpl_not_found(uri)}" end def despace(dir) Dir.children(dir).each { |s| FileUtils.mv("#{s.as_root}", "#{s.delete(' ').as_root}") unless s == s.delete(' ') } end def init_database(db) #get all files and check if theyre already in the database keys = db.get(:key) files = Dir.children(ROOT).filter {|x| x.end_with? ".pdf"} not_files = files - keys threads = [] mtx = Mutex.new #if not make a thumbnail and add it not_files.each do |file| threads << Thread.new { make_thumbnail "#{ROOT}/#{file}" mtx.synchronize { db.append(file, "#{File.basename(file, ".pdf")}.png") } } end threads.each { |t| t.join } until threads.map {|t| t.alive?}.include? false end unless threads.empty? end #generate html to send on requesting "/" def gen_html(db) keys = db.get(:key) hrefs = db.get(:value) key = 0 value = 1 content = keys.zip(hrefs).map { |x| img_tag = "" img_tag = img_tag.tag_href("a", x[key]) img_tag = img_tag.tag_attrs("div", {:class => "grid-item"}) } content = content.join content = content.tag_attrs("div", {:class => "grid-container"}) stylesheet = File.read("#{ROOT}/style.css") stylesheet = stylesheet.tag("style") head = stylesheet.tag("head") body = content.tag("pre").tag("body") html = (head + body).tag("html") html = "" + html end HANDLERS = {"/" => lambda { |cli| cli.puts http_ok gen_html(db)}} DEFAULT = lambda { |cli, uri| unless File.exist? "#{uri.as_root}" message("could not open file: #{uri}") cli.write http_not_found uri return end cli.write http_ok File.read(uri.as_root) } IMAGE_HANDLER = lambda { |cli, uri| unless File.exist? "#{uri.as_root}" message("could not open file: #{uri}") cli.write http_not_found uri return end cli.write http_png File.read(uri.as_root) } def make_thumbnail(file) `convert -thumbnail "140x200" -background white -alpha remove -crop 178x178+0+0 "#{file}"[0] "#{ROOT}/#{File.basename(file, ".pdf")}.png"` end def get_file(cli, uri) if HANDLERS[uri] HANDLERS[uri].call(cli) elsif uri.end_with? ".png" IMAGE_HANDLER.call(cli, uri.split("/")[1]) #never wants the ico? else DEFAULT.call(cli, uri.split("/")[1]) end end def put_file(cli, uri, data) "handle it" end class Request attr_reader :method attr_reader :data attr_reader :uri attr_reader :version attr_reader :headers def parse_request(str) if @data[0].nil? @method = HTTP_NIL return end @method = @data[0].split(" ")[0] @uri = @data[0].split(" ")[1] @version = @data[0].split(" ")[2] @headers = @data.map.drop(1) { |header| {header.split(": ")[0] => header.split(": ")[1]} } end def initialize(cli) @data = [cli.gets] parse_request(@data) end end error("specify root folder") if ROOT.nil? error("specify port") if PORT.nil? message("starting server on port: #{PORT}") despace(ROOT) init_database(db) TCPServer.open("127.0.0.1", PORT) { |srv| mutex = Mutex.new loop do #Thread.start(srv.accept) { |cli| cli = srv.accept mutex.synchronize do h = Request.new(cli) case h.method when HTTP_GET cli.write get_file(cli, h.uri) when HTTP_POST message("unknown method: #{h.method}") when HTTP_QUERY cli.write Dir.children(ROOT).join("\n") when HTTP_NIL break else message("unknown method: #{h.method}") end cli.close end #} end }