process password protected pdf files

This commit is contained in:
Alex Turchyn
2024-01-14 23:22:41 +02:00
committed by Pete Matsyburka
parent a573545ead
commit e864e8a47f
9 changed files with 143 additions and 14 deletions
+29
View File
@@ -0,0 +1,29 @@
# frozen_string_literal: true
module PdfUtils
module_function
def encrypted?(data, password: nil)
HexaPDF::Document.new(io: StringIO.new(data), decryption_opts: { password: })
false
rescue HexaPDF::EncryptionError
true
end
def decrypt(data, password)
encrypted_doc = HexaPDF::Document.new(io: StringIO.new(data), decryption_opts: { password: })
decrypted_doc = HexaPDF::Document.new
encrypted_doc.pages.each do |page|
decrypted_doc.pages << decrypted_doc.import(page)
end
decrypted_io = StringIO.new
decrypted_doc.write(decrypted_io, validate: false)
decrypted_io.tap(&:rewind).read
end
end
+22
View File
@@ -5,6 +5,7 @@ module Templates
PDF_CONTENT_TYPE = 'application/pdf'
ANNOTATIONS_SIZE_LIMIT = 6.megabytes
InvalidFileType = Class.new(StandardError)
PdfEncrypted = Class.new(StandardError)
module_function
@@ -19,6 +20,15 @@ module Templates
document = template.documents.create!(blob:)
if blob.content_type == PDF_CONTENT_TYPE && blob.metadata['pdf'].nil?
data = maybe_decrypt_pdf_or_raise(document_data, params)
if data != document_data
blob = ActiveStorage::Blob.create_and_upload!(
io: StringIO.new(new_data), filename: blob.filename
)
document_data = data
end
annotations =
document_data.size > ANNOTATIONS_SIZE_LIMIT ? [] : Templates::BuildAnnotations.call(document_data)
@@ -41,6 +51,8 @@ module Templates
data = file.read
if file.content_type == PDF_CONTENT_TYPE
data = maybe_decrypt_pdf_or_raise(data, params)
annotations = data.size > ANNOTATIONS_SIZE_LIMIT ? [] : Templates::BuildAnnotations.call(data)
metadata = { 'identified' => true, 'analyzed' => true,
'sha256' => Base64.urlsafe_encode64(Digest::SHA256.digest(data)),
@@ -56,6 +68,16 @@ module Templates
end
end
def maybe_decrypt_pdf_or_raise(data, params)
if data.size < ANNOTATIONS_SIZE_LIMIT && PdfUtils.encrypted?(data)
PdfUtils.decrypt(data, params[:password])
else
data
end
rescue HexaPDF::EncryptionError
raise PdfEncrypted
end
def handle_file_types(_document_data, blob)
raise InvalidFileType, blob.content_type
end