Skip to content

Commit

Permalink
Fix indirect Fields on Interactive Form
Browse files Browse the repository at this point in the history
  • Loading branch information
tomascco committed Dec 1, 2023
1 parent 9cec203 commit 56142b7
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 1 deletion.
10 changes: 9 additions & 1 deletion lib/rubrik/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,15 @@ def add_signature_field
modified_objects << {id: first_page_reference, value: new_first_page}
end

(interactive_form[:Fields] ||= []) << signature_field_id
fields_entry = interactive_form[:Fields]
if fields_entry.is_a?(PDF::Reader::Reference)
new_fields_array = objects.fetch(fields_entry).dup
new_fields_array << signature_field_id

modified_objects << {id: fields_entry, value: new_fields_array}
else
(interactive_form[:Fields] ||= []) << signature_field_id
end

signature_value_id
end
Expand Down
22 changes: 22 additions & 0 deletions test/rubrik/document_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,5 +189,27 @@ def test_add_signature_field_with_indirect_annots
ensure
input&.close
end

def test_add_signature_field_with_indirect_fields
# Arrange
input = File.open(SupportPDF["indirect_fields"], "rb")
document = Document.new(input)
initial_number_of_objects = document.modified_objects.size

# Act
result = document.add_signature_field

# Assert
number_of_added_objects = document.modified_objects.size - initial_number_of_objects
assert_equal(4, number_of_added_objects)

assert_pattern do
document.modified_objects => [{id: PDF::Reader::Reference, value: {Fields: fields_ref}}, *]
document.modified_objects => [*, {id: ^fields_ref, value: [signature_field_ref]}]
document.modified_objects => [*, {id: ^signature_field_ref, value: {FT: :Sig}}, *]
end
ensure
input&.close
end
end
end
36 changes: 36 additions & 0 deletions test/rubrik/sign_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,41 @@ def test_document_with_inline_interactive_form
input_pdf&.close
expected_output&.close
end

def test_document_with_indirect_fields
# Arrange
input_pdf = File.open(SupportPDF["indirect_fields"], "rb")
output_pdf = StringIO.new
certificate_file = File.open("test/support/demo_cert.pem", "rb")

private_key = OpenSSL::PKey::RSA.new(certificate_file, "")
certificate_file.rewind
certificate = OpenSSL::X509::Certificate.new(certificate_file)

# Act
Sign.call(input_pdf, output_pdf, private_key:, certificate:)

# Assert
expected_output = File.open(SupportPDF["indirect_fields.expected"], "rb")

expected_output.readlines.zip(output_pdf.readlines).each do |(expected_line, actual_line)|
# We must erase the signature because it is timestampped
if actual_line&.match?("/Type /Sig")
actual_line.sub!(/<[a-f0-9]+>/, "")
expected_line.sub!(/<[a-f0-9]+>/, "")
# The signature field name is also random
elsif actual_line&.match?(/Signature-[a-f0-9]{4}/)
actual_line.sub!(/Signature-[a-f0-9]{4}/, "")
expected_line.sub!(/Signature-[a-f0-9]{4}/, "")
end

assert_equal(expected_line, actual_line)
end
ensure
certificate_file&.close
output_pdf&.close
input_pdf&.close
expected_output&.close
end
end
end
Binary file added test/support/indirect_fields.expected.pdf
Binary file not shown.
Binary file added test/support/indirect_fields.pdf
Binary file not shown.

0 comments on commit 56142b7

Please sign in to comment.