Files
davideisinger.com/bin/dither/dither.rb
David Eisinger c41e908ed5
All checks were successful
Deploy / deploy (push) Successful in 1m33s
Fix cache key error
2026-04-09 00:26:36 -04:00

100 lines
2.2 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"
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