require "sinatra" require "mini_magick" require "digest" require "fileutils" require "tempfile" MiniMagick.logger.level = Logger::DEBUG ROOT = ENV.fetch("ROOT") KEY = ENV.fetch("KEY") DITHER = ENV["DITHER"] != "0" FORMAT = "png" CACHE_DIR = ENV["DITHER_CACHE_DIR"] def cache_path_for(path, geometry) return unless CACHE_DIR source_path = "#{ROOT}/#{path}.enc" cache_key = Digest::SHA256.hexdigest([ path, Digest::SHA256.file(source_path).hexdigest, geometry, DITHER, FORMAT, 1 ].join("\0")) FileUtils.mkdir_p(CACHE_DIR) File.join(CACHE_DIR, "#{cache_key}.#{FORMAT}") end get "/*" do |path| halt 404, {"Content-Type" => "text/plain"}, "not found" unless File.exist?("#{ROOT}/#{path}.enc") content_type "image/#{FORMAT}" geometry = params["geo"] unless params["geo"] == "" geometry.gsub!(/\d+/) { |n| n.to_i * 2 } if geometry && !DITHER cached_path = cache_path_for(path, geometry) if cached_path && File.exist?(cached_path) return File.binread(cached_path) end decrypted = Tempfile.new(["dither", File.extname(path)]) decrypted.binmode decrypted.close begin openssl_ok = system( "openssl", "aes-256-cbc", "-d", "-in", "#{ROOT}/#{path}.enc", "-out", decrypted.path, "-pass", "file:#{KEY}", "-iter", "1000000" ) halt 500, {"Content-Type" => "text/plain"}, "decrypt failed" unless openssl_ok convert = MiniMagick::Tool::Convert.new convert.limit("memory", "128MiB") convert.limit("map", "256MiB") convert.limit("disk", "1GiB") convert << decrypted.path convert.background("white") convert.layers("flatten") convert.strip convert.auto_orient if geometry if geometry.match?(/^\d+x\d+$/) convert.resize "#{geometry}^" convert.gravity "center" convert.extent geometry else convert.resize geometry end end if DITHER convert.ordered_dither "o8x8" convert.monochrome end convert << "#{FORMAT.upcase}:-" output = convert.call if cached_path temp_cache_path = "#{cached_path}.tmp-#{Process.pid}" File.binwrite(temp_cache_path, output) FileUtils.mv(temp_cache_path, cached_path) end output ensure decrypted.unlink end end