hexapdf 0.28.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +59 -10
- data/examples/024-digital-signatures.rb +23 -0
- data/lib/hexapdf/configuration.rb +12 -12
- data/lib/hexapdf/dictionary_fields.rb +13 -4
- data/lib/hexapdf/digital_signature/cms_handler.rb +137 -0
- data/lib/hexapdf/digital_signature/handler.rb +138 -0
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +96 -0
- data/lib/hexapdf/{type → digital_signature}/signature.rb +3 -8
- data/lib/hexapdf/digital_signature/signatures.rb +210 -0
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +317 -0
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +308 -0
- data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +148 -0
- data/lib/hexapdf/digital_signature/signing.rb +101 -0
- data/lib/hexapdf/{type/signature → digital_signature}/verification_result.rb +37 -41
- data/lib/hexapdf/digital_signature.rb +56 -0
- data/lib/hexapdf/document/pages.rb +35 -18
- data/lib/hexapdf/document.rb +21 -14
- data/lib/hexapdf/encryption/standard_security_handler.rb +4 -3
- data/lib/hexapdf/type/font_simple.rb +14 -2
- data/lib/hexapdf/type.rb +0 -1
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/{type/signature → digital_signature}/common.rb +31 -3
- data/test/hexapdf/digital_signature/signing/test_default_handler.rb +162 -0
- data/test/hexapdf/digital_signature/signing/test_signed_data_creator.rb +225 -0
- data/test/hexapdf/digital_signature/signing/test_timestamp_handler.rb +88 -0
- data/test/hexapdf/{type/signature/test_adbe_pkcs7_detached.rb → digital_signature/test_cms_handler.rb} +7 -7
- data/test/hexapdf/{type/signature → digital_signature}/test_handler.rb +4 -4
- data/test/hexapdf/{type/signature/test_adbe_x509_rsa_sha1.rb → digital_signature/test_pkcs1_handler.rb} +3 -3
- data/test/hexapdf/{type → digital_signature}/test_signature.rb +7 -7
- data/test/hexapdf/digital_signature/test_signatures.rb +137 -0
- data/test/hexapdf/digital_signature/test_signing.rb +53 -0
- data/test/hexapdf/{type/signature → digital_signature}/test_verification_result.rb +7 -7
- data/test/hexapdf/document/test_pages.rb +25 -0
- data/test/hexapdf/encryption/test_standard_security_handler.rb +2 -2
- data/test/hexapdf/test_dictionary_fields.rb +9 -3
- data/test/hexapdf/test_document.rb +1 -1
- data/test/hexapdf/test_writer.rb +6 -6
- data/test/hexapdf/type/test_font_simple.rb +18 -6
- metadata +25 -15
- data/lib/hexapdf/document/signatures.rb +0 -546
- data/lib/hexapdf/type/signature/adbe_pkcs7_detached.rb +0 -135
- data/lib/hexapdf/type/signature/adbe_x509_rsa_sha1.rb +0 -95
- data/lib/hexapdf/type/signature/handler.rb +0 -140
- data/test/hexapdf/document/test_signatures.rb +0 -352
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
require 'test_helper'
|
|
4
|
-
require 'hexapdf/
|
|
4
|
+
require 'hexapdf/digital_signature'
|
|
5
5
|
|
|
6
|
-
describe HexaPDF::
|
|
6
|
+
describe HexaPDF::DigitalSignature::VerificationResult do
|
|
7
7
|
describe "Message" do
|
|
8
8
|
it "accepts a type and a content argument on creation" do
|
|
9
|
-
m = HexaPDF::
|
|
9
|
+
m = HexaPDF::DigitalSignature::VerificationResult::Message.new(:type, 'content')
|
|
10
10
|
assert_equal(:type, m.type)
|
|
11
11
|
assert_equal('content', m.content)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it "allows sorting by type" do
|
|
15
|
-
info = HexaPDF::
|
|
16
|
-
warning = HexaPDF::
|
|
17
|
-
error = HexaPDF::
|
|
15
|
+
info = HexaPDF::DigitalSignature::VerificationResult::Message.new(:info, 'c')
|
|
16
|
+
warning = HexaPDF::DigitalSignature::VerificationResult::Message.new(:warning, 'c')
|
|
17
|
+
error = HexaPDF::DigitalSignature::VerificationResult::Message.new(:error, 'c')
|
|
18
18
|
assert_equal([error, warning, info], [info, error, warning].sort)
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
before do
|
|
23
|
-
@result = HexaPDF::
|
|
23
|
+
@result = HexaPDF::DigitalSignature::VerificationResult.new
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
it "can add new messages" do
|
|
@@ -14,6 +14,31 @@ describe HexaPDF::Document::Pages do
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
describe "create" do
|
|
18
|
+
it "uses the defaults from the configuration for missing arguments" do
|
|
19
|
+
page = @doc.pages.create
|
|
20
|
+
assert_equal([0, 0, 595, 842], page.box(:media).value)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "allows specifying a reference to a predefined page size" do
|
|
24
|
+
page = @doc.pages.create(media_box: :A3)
|
|
25
|
+
assert_equal([0, 0, 842, 1191], page.box(:media).value)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "allows specifying the orientation for a predefined page size" do
|
|
29
|
+
page = @doc.pages.create(media_box: :A4, orientation: :landscape)
|
|
30
|
+
assert_equal([0, 0, 842, 595], page.box(:media).value)
|
|
31
|
+
|
|
32
|
+
page = @doc.pages.create(orientation: :landscape)
|
|
33
|
+
assert_equal([0, 0, 842, 595], page.box(:media).value)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "allows using a media box array" do
|
|
37
|
+
page = @doc.pages.create(media_box: [0, 0, 12, 24], orientation: :landscape)
|
|
38
|
+
assert_equal([0, 0, 12, 24], page.box(:media).value)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
17
42
|
describe "add" do
|
|
18
43
|
it "adds a new empty page when no page is given" do
|
|
19
44
|
page = @doc.pages.add
|
|
@@ -213,14 +213,14 @@ describe HexaPDF::Encryption::StandardSecurityHandler do
|
|
|
213
213
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
|
214
214
|
@handler.set_up_decryption({Filter: :NonStandard, V: 2})
|
|
215
215
|
end
|
|
216
|
-
assert_match(/Invalid \/Filter/i, exp.message)
|
|
216
|
+
assert_match(/Invalid \/Filter value NonStandard/i, exp.message)
|
|
217
217
|
end
|
|
218
218
|
|
|
219
219
|
it "fails if the /R value is incorrect" do
|
|
220
220
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
|
221
221
|
@handler.set_up_decryption({Filter: :Standard, V: 2, R: 5})
|
|
222
222
|
end
|
|
223
|
-
assert_match(/Invalid \/R/i, exp.message)
|
|
223
|
+
assert_match(/Invalid \/R value 5/i, exp.message)
|
|
224
224
|
end
|
|
225
225
|
|
|
226
226
|
it "fails if the supplied password is invalid" do
|
|
@@ -175,7 +175,6 @@ describe HexaPDF::DictionaryFields do
|
|
|
175
175
|
|
|
176
176
|
it "allows conversion to a Time object from a binary string" do
|
|
177
177
|
refute(@field.convert('test'.b, self))
|
|
178
|
-
refute(@field.convert('D:01211016165909+00\'64'.b, self))
|
|
179
178
|
|
|
180
179
|
[
|
|
181
180
|
["D:1998", [1998, 01, 01, 00, 00, 00, "-00:00"]],
|
|
@@ -189,8 +188,15 @@ describe HexaPDF::DictionaryFields do
|
|
|
189
188
|
["D:19981223-08'00'", [1998, 12, 23, 00, 00, 00, "-08:00"]],
|
|
190
189
|
["D:199812-08'00'", [1998, 12, 01, 00, 00, 00, "-08:00"]],
|
|
191
190
|
["D:1998-08'00'", [1998, 01, 01, 00, 00, 00, "-08:00"]],
|
|
192
|
-
["D:19981223195210-08", [1998, 12, 23, 19, 52, 10, "-08:00"]], #
|
|
193
|
-
["D:19981223195210-08'00", [1998, 12, 23, 19, 52, 10, "-08:00"]], #
|
|
191
|
+
["D:19981223195210-08", [1998, 12, 23, 19, 52, 10, "-08:00"]], # missing '
|
|
192
|
+
["D:19981223195210-08'00", [1998, 12, 23, 19, 52, 10, "-08:00"]], # missing '
|
|
193
|
+
["D:19981223195210-54'00", [1998, 12, 23, 19, 52, 10, "-23:59:59"]], # TZ hour too large
|
|
194
|
+
["D:19981223195210+10'65", [1998, 12, 23, 19, 52, 10, "+11:05"]], # TZ min too large
|
|
195
|
+
["D:19982423195210-08'00'", [1998, 12, 23, 19, 52, 10, "-08:00"]], # months too large
|
|
196
|
+
["D:19981273195210-08'00'", [1998, 12, 31, 19, 52, 10, "-08:00"]], # day too large
|
|
197
|
+
["D:19981223275210-08'00'", [1998, 12, 23, 23, 52, 10, "-08:00"]], # hour too large
|
|
198
|
+
["D:19981223197710-08'00'", [1998, 12, 23, 19, 59, 10, "-08:00"]], # minute too large
|
|
199
|
+
["D:19981223195280-08'00'", [1998, 12, 23, 19, 52, 59, "-08:00"]], # seconds too large
|
|
194
200
|
].each do |str, data|
|
|
195
201
|
obj = @field.convert(str, self)
|
|
196
202
|
assert_equal(Time.new(*data), obj, "date str used: #{str}")
|
|
@@ -504,7 +504,7 @@ describe HexaPDF::Document do
|
|
|
504
504
|
|
|
505
505
|
it "allows to conveniently sign a document" do
|
|
506
506
|
mock = Minitest::Mock.new
|
|
507
|
-
mock.expect(:
|
|
507
|
+
mock.expect(:signing_handler, :handler, name: :handler, opt: :key)
|
|
508
508
|
mock.expect(:add, :added, [:io, :handler], signature: :sig, write_options: :write_options)
|
|
509
509
|
@doc.instance_variable_set(:@signatures, mock)
|
|
510
510
|
result = @doc.sign(:io, handler: :handler, write_options: :write_options, signature: :sig, opt: :key)
|
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.
|
|
43
|
+
<</Producer(HexaPDF version 0.30.0)>>
|
|
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.
|
|
75
|
+
<</Producer(HexaPDF version 0.30.0)>>
|
|
76
76
|
endobj
|
|
77
77
|
2 0 obj
|
|
78
78
|
<</Length 10>>stream
|
|
@@ -164,9 +164,9 @@ describe HexaPDF::Writer do
|
|
|
164
164
|
|
|
165
165
|
document = HexaPDF::Document.new(io: io)
|
|
166
166
|
assert_equal(3, document.revisions.count)
|
|
167
|
-
assert_equal(1, document.revisions.all[0].object(
|
|
168
|
-
assert_equal(2, document.revisions.all[1].object(
|
|
169
|
-
assert_equal(3, document.revisions.all[2].object(
|
|
167
|
+
assert_equal(1, document.revisions.all[0].object(3)[:Kids].length)
|
|
168
|
+
assert_equal(2, document.revisions.all[1].object(3)[:Kids].length)
|
|
169
|
+
assert_equal(3, document.revisions.all[2].object(3)[:Kids].length)
|
|
170
170
|
end
|
|
171
171
|
|
|
172
172
|
it "creates an xref stream if no xref stream is in a revision but object streams are" do
|
|
@@ -214,7 +214,7 @@ describe HexaPDF::Writer do
|
|
|
214
214
|
<</Type/Page/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<<>>>>
|
|
215
215
|
endobj
|
|
216
216
|
5 0 obj
|
|
217
|
-
<</Producer(HexaPDF version 0.
|
|
217
|
+
<</Producer(HexaPDF version 0.30.0)>>
|
|
218
218
|
endobj
|
|
219
219
|
4 0 obj
|
|
220
220
|
<</Root 1 0 R/Info 5 0 R/Size 6/Type/XRef/W[1 1 2]/Index[0 6]/Filter/FlateDecode/DecodeParms<</Columns 4/Predictor 12>>/Length 33>>stream
|
|
@@ -15,7 +15,7 @@ describe HexaPDF::Type::FontSimple do
|
|
|
15
15
|
EOF
|
|
16
16
|
font_descriptor = @doc.add({Type: :FontDescriptor, FontName: :Embedded, Flags: 0b100,
|
|
17
17
|
FontBBox: [0, 1, 2, 3], ItalicAngle: 0, Ascent: 900,
|
|
18
|
-
Descent: -100, CapHeight: 800, StemV: 20})
|
|
18
|
+
MissingWidth: 500, Descent: -100, CapHeight: 800, StemV: 20})
|
|
19
19
|
@font = @doc.add({Type: :Font, Encoding: :WinAnsiEncoding,
|
|
20
20
|
BaseFont: :Embedded, FontDescriptor: font_descriptor, ToUnicode: cmap,
|
|
21
21
|
FirstChar: 32, LastChar: 34, Widths: [600, 0, 700]},
|
|
@@ -130,9 +130,7 @@ describe HexaPDF::Type::FontSimple do
|
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
it "returns the /MissingWidth of a /FontDescriptor if available and the width was not found" do
|
|
133
|
-
assert_equal(
|
|
134
|
-
@font[:FontDescriptor][:MissingWidth] = 99
|
|
135
|
-
assert_equal(99, @font.width(0))
|
|
133
|
+
assert_equal(500, @font.width(0))
|
|
136
134
|
end
|
|
137
135
|
|
|
138
136
|
it "returns 0 for a missing code point when FontDescriptor is not available" do
|
|
@@ -169,8 +167,22 @@ describe HexaPDF::Type::FontSimple do
|
|
|
169
167
|
end
|
|
170
168
|
|
|
171
169
|
it "validates the lengths of the /Widths field" do
|
|
172
|
-
@font[:Widths] = [65]
|
|
173
|
-
|
|
170
|
+
@font[:Widths] = [65, 65]
|
|
171
|
+
assert(@font.validate)
|
|
172
|
+
assert_equal([65, 65, 65], @font[:Widths])
|
|
173
|
+
|
|
174
|
+
@font[:Widths] = [65, 70]
|
|
175
|
+
assert(@font.validate)
|
|
176
|
+
assert_equal([65, 70, 500], @font[:Widths])
|
|
177
|
+
|
|
178
|
+
@font[:Widths] = [65, 70]
|
|
179
|
+
@font.delete(:FontDescriptor)
|
|
180
|
+
assert(@font.validate)
|
|
181
|
+
assert_equal([65, 70, 0], @font[:Widths])
|
|
182
|
+
|
|
183
|
+
@font[:Widths] = [65, 65, 70, 90, 100]
|
|
184
|
+
assert(@font.validate)
|
|
185
|
+
assert_equal([65, 65, 70], @font[:Widths])
|
|
174
186
|
end
|
|
175
187
|
end
|
|
176
188
|
end
|
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.
|
|
4
|
+
version: 0.30.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Thomas Leitner
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-02-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: cmdparse
|
|
@@ -291,6 +291,7 @@ files:
|
|
|
291
291
|
- examples/021-list_box.rb
|
|
292
292
|
- examples/022-outline.rb
|
|
293
293
|
- examples/023-images.rb
|
|
294
|
+
- examples/024-digital-signatures.rb
|
|
294
295
|
- examples/emoji-smile.png
|
|
295
296
|
- examples/emoji-wink.png
|
|
296
297
|
- examples/machupicchu.jpg
|
|
@@ -328,6 +329,17 @@ files:
|
|
|
328
329
|
- lib/hexapdf/data_dir.rb
|
|
329
330
|
- lib/hexapdf/dictionary.rb
|
|
330
331
|
- lib/hexapdf/dictionary_fields.rb
|
|
332
|
+
- lib/hexapdf/digital_signature.rb
|
|
333
|
+
- lib/hexapdf/digital_signature/cms_handler.rb
|
|
334
|
+
- lib/hexapdf/digital_signature/handler.rb
|
|
335
|
+
- lib/hexapdf/digital_signature/pkcs1_handler.rb
|
|
336
|
+
- lib/hexapdf/digital_signature/signature.rb
|
|
337
|
+
- lib/hexapdf/digital_signature/signatures.rb
|
|
338
|
+
- lib/hexapdf/digital_signature/signing.rb
|
|
339
|
+
- lib/hexapdf/digital_signature/signing/default_handler.rb
|
|
340
|
+
- lib/hexapdf/digital_signature/signing/signed_data_creator.rb
|
|
341
|
+
- lib/hexapdf/digital_signature/signing/timestamp_handler.rb
|
|
342
|
+
- lib/hexapdf/digital_signature/verification_result.rb
|
|
331
343
|
- lib/hexapdf/document.rb
|
|
332
344
|
- lib/hexapdf/document/destinations.rb
|
|
333
345
|
- lib/hexapdf/document/files.rb
|
|
@@ -335,7 +347,6 @@ files:
|
|
|
335
347
|
- lib/hexapdf/document/images.rb
|
|
336
348
|
- lib/hexapdf/document/layout.rb
|
|
337
349
|
- lib/hexapdf/document/pages.rb
|
|
338
|
-
- lib/hexapdf/document/signatures.rb
|
|
339
350
|
- lib/hexapdf/encryption.rb
|
|
340
351
|
- lib/hexapdf/encryption/aes.rb
|
|
341
352
|
- lib/hexapdf/encryption/arc4.rb
|
|
@@ -486,11 +497,6 @@ files:
|
|
|
486
497
|
- lib/hexapdf/type/page_label.rb
|
|
487
498
|
- lib/hexapdf/type/page_tree_node.rb
|
|
488
499
|
- lib/hexapdf/type/resources.rb
|
|
489
|
-
- lib/hexapdf/type/signature.rb
|
|
490
|
-
- lib/hexapdf/type/signature/adbe_pkcs7_detached.rb
|
|
491
|
-
- lib/hexapdf/type/signature/adbe_x509_rsa_sha1.rb
|
|
492
|
-
- lib/hexapdf/type/signature/handler.rb
|
|
493
|
-
- lib/hexapdf/type/signature/verification_result.rb
|
|
494
500
|
- lib/hexapdf/type/trailer.rb
|
|
495
501
|
- lib/hexapdf/type/viewer_preferences.rb
|
|
496
502
|
- lib/hexapdf/type/xref_stream.rb
|
|
@@ -587,13 +593,23 @@ files:
|
|
|
587
593
|
- test/hexapdf/content/test_parser.rb
|
|
588
594
|
- test/hexapdf/content/test_processor.rb
|
|
589
595
|
- test/hexapdf/content/test_transformation_matrix.rb
|
|
596
|
+
- test/hexapdf/digital_signature/common.rb
|
|
597
|
+
- test/hexapdf/digital_signature/signing/test_default_handler.rb
|
|
598
|
+
- test/hexapdf/digital_signature/signing/test_signed_data_creator.rb
|
|
599
|
+
- test/hexapdf/digital_signature/signing/test_timestamp_handler.rb
|
|
600
|
+
- test/hexapdf/digital_signature/test_cms_handler.rb
|
|
601
|
+
- test/hexapdf/digital_signature/test_handler.rb
|
|
602
|
+
- test/hexapdf/digital_signature/test_pkcs1_handler.rb
|
|
603
|
+
- test/hexapdf/digital_signature/test_signature.rb
|
|
604
|
+
- test/hexapdf/digital_signature/test_signatures.rb
|
|
605
|
+
- test/hexapdf/digital_signature/test_signing.rb
|
|
606
|
+
- test/hexapdf/digital_signature/test_verification_result.rb
|
|
590
607
|
- test/hexapdf/document/test_destinations.rb
|
|
591
608
|
- test/hexapdf/document/test_files.rb
|
|
592
609
|
- test/hexapdf/document/test_fonts.rb
|
|
593
610
|
- test/hexapdf/document/test_images.rb
|
|
594
611
|
- test/hexapdf/document/test_layout.rb
|
|
595
612
|
- test/hexapdf/document/test_pages.rb
|
|
596
|
-
- test/hexapdf/document/test_signatures.rb
|
|
597
613
|
- test/hexapdf/encryption/common.rb
|
|
598
614
|
- test/hexapdf/encryption/test_aes.rb
|
|
599
615
|
- test/hexapdf/encryption/test_arc4.rb
|
|
@@ -705,11 +721,6 @@ files:
|
|
|
705
721
|
- test/hexapdf/type/annotations/test_markup_annotation.rb
|
|
706
722
|
- test/hexapdf/type/annotations/test_text.rb
|
|
707
723
|
- test/hexapdf/type/annotations/test_widget.rb
|
|
708
|
-
- test/hexapdf/type/signature/common.rb
|
|
709
|
-
- test/hexapdf/type/signature/test_adbe_pkcs7_detached.rb
|
|
710
|
-
- test/hexapdf/type/signature/test_adbe_x509_rsa_sha1.rb
|
|
711
|
-
- test/hexapdf/type/signature/test_handler.rb
|
|
712
|
-
- test/hexapdf/type/signature/test_verification_result.rb
|
|
713
724
|
- test/hexapdf/type/test_annotation.rb
|
|
714
725
|
- test/hexapdf/type/test_catalog.rb
|
|
715
726
|
- test/hexapdf/type/test_cid_font.rb
|
|
@@ -732,7 +743,6 @@ files:
|
|
|
732
743
|
- test/hexapdf/type/test_page_label.rb
|
|
733
744
|
- test/hexapdf/type/test_page_tree_node.rb
|
|
734
745
|
- test/hexapdf/type/test_resources.rb
|
|
735
|
-
- test/hexapdf/type/test_signature.rb
|
|
736
746
|
- test/hexapdf/type/test_trailer.rb
|
|
737
747
|
- test/hexapdf/type/test_xref_stream.rb
|
|
738
748
|
- test/hexapdf/utils/test_bit_field.rb
|