102 lines
2.3 KiB
Ruby
102 lines
2.3 KiB
Ruby
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"
|
|
stat = File.stat(source_path)
|
|
cache_key = Digest::SHA256.hexdigest([
|
|
path,
|
|
stat.size,
|
|
stat.mtime.to_f,
|
|
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
|