hexapdf 0.20.2 → 0.20.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/hexapdf/cli/form.rb +9 -1
- data/lib/hexapdf/encryption/security_handler.rb +5 -1
- data/lib/hexapdf/type/annotation.rb +1 -1
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/writer.rb +11 -3
- data/test/hexapdf/encryption/test_security_handler.rb +11 -3
- data/test/hexapdf/test_writer.rb +13 -2
- data/test/hexapdf/type/test_annotation.rb +7 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edc0879019c00378efa5e596e5a24db8d094e8baf682f434c052e62f6a84a563
|
4
|
+
data.tar.gz: 9eb7a38c31ae34d9bdf2d4006a01419b29d0c21faabd9b6b2ff31a3079c4617f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 259aa6bcd520b74bec173c91d92b660681d09f0543287783aacc216fbf633c754e3d05dbcd56e84bff3227551e074193bbcf9d2d79d9435dad33dff6d85f89bf
|
7
|
+
data.tar.gz: 91ba8e27297a9c0769b19531e219987b749e8d356911bd03f22e579dff66cb90788efe1db8a56eb10ee4405eca39469022bafe6aebf597be4faf2285a908d1d5
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 0.20.3 - 2022-01-24
|
2
|
+
|
3
|
+
### Changed
|
4
|
+
|
5
|
+
* Appearance of signature field values when using the `hexapdf form` command
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
|
9
|
+
* Writing of encrypted PDF files in incremental node in case the encryption was
|
10
|
+
changed
|
11
|
+
* [HexaPDF::Type::Annotation#appearance] to return correctly wrapped object in
|
12
|
+
case of Form XObjects missing required data
|
13
|
+
* Decrypting of files with multiple revisions
|
14
|
+
|
15
|
+
|
1
16
|
## 0.20.2 - 2022-01-17
|
2
17
|
|
3
18
|
### Fixed
|
data/lib/hexapdf/cli/form.rb
CHANGED
@@ -135,12 +135,20 @@ module HexaPDF
|
|
135
135
|
concrete_field_type = field.concrete_field_type
|
136
136
|
nice_field_type = concrete_field_type.to_s.split('_').map(&:capitalize).join(' ')
|
137
137
|
position = "(#{widget[:Rect].left}, #{widget[:Rect].bottom})"
|
138
|
+
field_value = if !field.field_value || concrete_field_type != :signature_field
|
139
|
+
field.field_value.inspect
|
140
|
+
else
|
141
|
+
sig = field.field_value
|
142
|
+
temp = "#{sig.signer_name} (#{sig.signing_time})"
|
143
|
+
temp << " (#{sig.signing_reason})" if sig.signing_reason
|
144
|
+
temp
|
145
|
+
end
|
138
146
|
|
139
147
|
puts " #{field_name}"
|
140
148
|
if command_parser.verbosity_info?
|
141
149
|
printf(" └─ %-22s | %-20s\n", nice_field_type, position)
|
142
150
|
end
|
143
|
-
puts " └─ #{
|
151
|
+
puts " └─ #{field_value}"
|
144
152
|
if command_parser.verbosity_info?
|
145
153
|
if field.field_type == :Ch
|
146
154
|
puts " └─ Options: #{field.option_items.map(&:inspect).join(', ')}"
|
@@ -249,6 +249,10 @@ module HexaPDF
|
|
249
249
|
@document = document
|
250
250
|
@encrypt_dict_hash = nil
|
251
251
|
@encryption_details = {}
|
252
|
+
|
253
|
+
@is_encrypt_dict = document.revisions.each.with_object({}) do |rev, hash|
|
254
|
+
hash[rev.trailer[:Encrypt]] = true
|
255
|
+
end
|
252
256
|
end
|
253
257
|
|
254
258
|
# Checks if the encryption key computed by this security handler is derived from the
|
@@ -262,7 +266,7 @@ module HexaPDF
|
|
262
266
|
#
|
263
267
|
# See: PDF1.7 s7.6.2
|
264
268
|
def decrypt(obj)
|
265
|
-
return obj if obj
|
269
|
+
return obj if @is_encrypt_dict[obj] || obj.type == :XRef
|
266
270
|
|
267
271
|
key = object_key(obj.oid, obj.gen, string_algorithm)
|
268
272
|
each_string_in_object(obj.value) do |str|
|
@@ -160,7 +160,7 @@ module HexaPDF
|
|
160
160
|
end
|
161
161
|
return unless entry.kind_of?(HexaPDF::Stream)
|
162
162
|
|
163
|
-
if entry.type == :XObject && entry[:Subtype] == :Form
|
163
|
+
if entry.type == :XObject && entry[:Subtype] == :Form && !entry.instance_of?(HexaPDF::Stream)
|
164
164
|
entry
|
165
165
|
elsif (entry[:Type].nil? || entry[:Type] == :XObject) &&
|
166
166
|
(entry[:Subtype].nil? || entry[:Subtype] == :Form) && entry[:BBox]
|
data/lib/hexapdf/version.rb
CHANGED
data/lib/hexapdf/writer.rb
CHANGED
@@ -90,12 +90,20 @@ module HexaPDF
|
|
90
90
|
#
|
91
91
|
# For this method to work the document must have been created from an existing file.
|
92
92
|
def write_incremental
|
93
|
-
@document.revisions.parser
|
94
|
-
|
93
|
+
parser = @document.revisions.parser
|
94
|
+
|
95
|
+
_, orig_trailer = parser.load_revision(parser.startxref_offset)
|
96
|
+
orig_trailer = @document.wrap(orig_trailer, type: :XXTrailer)
|
97
|
+
if @document.revisions.current.trailer[:Encrypt]&.value != orig_trailer[:Encrypt]&.value
|
98
|
+
raise HexaPDF::Error, "Used encryption cannot be modified when doing incremental writing"
|
99
|
+
end
|
100
|
+
|
101
|
+
parser.io.seek(0, IO::SEEK_SET)
|
102
|
+
IO.copy_stream(parser.io, @io)
|
95
103
|
@io << "\n"
|
96
104
|
|
97
105
|
@rev_size = @document.revisions.current.next_free_oid
|
98
|
-
@use_xref_streams =
|
106
|
+
@use_xref_streams = parser.contains_xref_streams?
|
99
107
|
|
100
108
|
revision = Revision.new(@document.revisions.current.trailer)
|
101
109
|
@document.revisions.each do |rev|
|
@@ -294,9 +294,17 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
294
294
|
assert_equal('string', obj.stream)
|
295
295
|
end
|
296
296
|
|
297
|
-
it "doesn't decrypt a document's Encrypt
|
298
|
-
@document
|
299
|
-
|
297
|
+
it "doesn't decrypt a document's Encrypt dictionaries" do
|
298
|
+
@document = HexaPDF::Document.new
|
299
|
+
@document.trailer[:Encrypt] = @document.add({Key: "Something"})
|
300
|
+
@document.revisions.add
|
301
|
+
@document.trailer[:Encrypt] = @document.add({Key: "Otherthing"})
|
302
|
+
@handler = TestHandler.new(@document)
|
303
|
+
|
304
|
+
assert_equal("Something",
|
305
|
+
@handler.decrypt(@document.revisions[0].trailer[:Encrypt])[:Key])
|
306
|
+
assert_equal("Otherthing",
|
307
|
+
@handler.decrypt(@document.revisions[1].trailer[:Encrypt])[:Key])
|
300
308
|
end
|
301
309
|
|
302
310
|
it "defers handling encryption to a Crypt filter is specified" do
|
data/test/hexapdf/test_writer.rb
CHANGED
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
|
|
40
40
|
219
|
41
41
|
%%EOF
|
42
42
|
3 0 obj
|
43
|
-
<</Producer(HexaPDF version 0.20.
|
43
|
+
<</Producer(HexaPDF version 0.20.3)>>
|
44
44
|
endobj
|
45
45
|
xref
|
46
46
|
3 1
|
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
|
|
72
72
|
141
|
73
73
|
%%EOF
|
74
74
|
6 0 obj
|
75
|
-
<</Producer(HexaPDF version 0.20.
|
75
|
+
<</Producer(HexaPDF version 0.20.3)>>
|
76
76
|
endobj
|
77
77
|
2 0 obj
|
78
78
|
<</Length 10>>stream
|
@@ -123,6 +123,17 @@ describe HexaPDF::Writer do
|
|
123
123
|
HexaPDF::Writer.write(doc, output_io, incremental: true)
|
124
124
|
refute_match(/^trailer/, output_io.string)
|
125
125
|
end
|
126
|
+
|
127
|
+
it "raises an error if the used encryption was changed" do
|
128
|
+
io = StringIO.new
|
129
|
+
doc = HexaPDF::Document.new
|
130
|
+
doc.encrypt
|
131
|
+
doc.write(io)
|
132
|
+
|
133
|
+
doc = HexaPDF::Document.new(io: io)
|
134
|
+
doc.encrypt(owner_password: 'test')
|
135
|
+
assert_raises(HexaPDF::Error) { doc.write('notused', incremental: true) }
|
136
|
+
end
|
126
137
|
end
|
127
138
|
|
128
139
|
it "creates an xref stream if no xref stream is in a revision but object streams are" do
|
@@ -77,7 +77,13 @@ describe HexaPDF::Type::Annotation do
|
|
77
77
|
stream[:BBox] = [1, 2, 3, 4]
|
78
78
|
appearance = @annot.appearance
|
79
79
|
assert_same(stream.data, appearance.data)
|
80
|
-
|
80
|
+
assert_kind_of(HexaPDF::Type::Form, appearance)
|
81
|
+
|
82
|
+
stream[:Type] = :XObject
|
83
|
+
stream[:Subtype] = :Form
|
84
|
+
appearance = @annot.appearance
|
85
|
+
assert_same(stream.data, appearance.data)
|
86
|
+
assert_kind_of(HexaPDF::Type::Form, appearance)
|
81
87
|
|
82
88
|
@annot[:AP][:N] = {X: {}}
|
83
89
|
assert_nil(@annot.appearance)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hexapdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.20.
|
4
|
+
version: 0.20.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Leitner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cmdparse
|