Last active
October 8, 2026 00:23
-
-
Save fsubal/d5e1aebbed3717afc66bb27431c2bf86 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class PdfgateClient | |
| class Error < StandardError | |
| attr_reader :code | |
| def initialize(code, message) | |
| super("PdfgateClient Error (#{code}): #{message}") | |
| @code = code | |
| end | |
| end | |
| Issue = Data.define(:severity, :code, :message) do | |
| def deny? | |
| severity == "deny" | |
| end | |
| def warn? | |
| severity == "warn" | |
| end | |
| end | |
| EXECUTABLE_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..', 'bin', 'pdfgate')) | |
| POLICY_FILE_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..', 'policy', 'default.json')) | |
| def initialize(pdf_file_path, policy_file_path: POLICY_FILE_PATH, timeout: 20.seconds) | |
| @pdf_file_path = pdf_file_path | |
| @policy_file_path = policy_file_path if File.exist?(policy_file_path) | |
| @timeout = timeout | |
| end | |
| def validate! | |
| case result | |
| in [{ ok: true, issues: }, 0] | |
| issues.map { |issue| Issue.new(**issue) } | |
| in [{ ok: false, issues: }, 1] | |
| issues.map { |issue| Issue.new(**issue) } | |
| in [{ error: { code:, message: } }, 2] | |
| raise Error.new(code, message) | |
| else | |
| error = Error.new("parse-failure", "Failed to parse the output of the pdfgate command.") | |
| Sentry.capture_exception(error, extra: { stdout: result[0], exitstatus: result[1] }) | |
| raise error | |
| end | |
| end | |
| private | |
| def result | |
| stdout, status = run_with_timeout | |
| [JSON.parse(stdout, symbolize_names: true), status&.exitstatus] | |
| rescue JSON::ParserError | |
| [nil, status&.exitstatus] | |
| end | |
| def pdfgate_arguments | |
| [EXECUTABLE_PATH, "validate", @pdf_file_path].tap do |args| | |
| args.push("--policy", @policy_file_path.to_s) if @policy_file_path | |
| end | |
| end | |
| def run_with_timeout | |
| Open3.popen2(*pdfgate_arguments) do |stdin, stdout, wait_thr| | |
| stdin.close | |
| reader = Thread.new { stdout.read } | |
| if wait_thr.join(@timeout) | |
| [reader.value, wait_thr.value] | |
| else | |
| begin | |
| Process.kill("KILL", wait_thr.pid) | |
| rescue Errno::ESRCH | |
| nil | |
| end | |
| wait_thr.join | |
| [nil, nil] | |
| end | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment