hexapdf 0.45.0 → 0.46.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +87 -47
- data/examples/019-acro_form.rb +5 -0
- data/lib/hexapdf/cli/inspect.rb +5 -0
- data/lib/hexapdf/composer.rb +1 -1
- data/lib/hexapdf/configuration.rb +8 -0
- data/lib/hexapdf/digital_signature/cms_handler.rb +31 -3
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +9 -1
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +5 -1
- data/lib/hexapdf/document/layout.rb +48 -27
- data/lib/hexapdf/document.rb +24 -2
- data/lib/hexapdf/importer.rb +15 -5
- data/lib/hexapdf/layout/box.rb +25 -28
- data/lib/hexapdf/layout/frame.rb +1 -1
- data/lib/hexapdf/layout/inline_box.rb +17 -23
- data/lib/hexapdf/layout/list_box.rb +24 -29
- data/lib/hexapdf/layout/page_style.rb +23 -16
- data/lib/hexapdf/layout/style.rb +2 -2
- data/lib/hexapdf/layout/text_box.rb +2 -6
- data/lib/hexapdf/parser.rb +5 -1
- data/lib/hexapdf/revisions.rb +1 -1
- data/lib/hexapdf/stream.rb +3 -3
- data/lib/hexapdf/tokenizer.rb +3 -2
- data/lib/hexapdf/type/acro_form/button_field.rb +2 -0
- data/lib/hexapdf/type/acro_form/choice_field.rb +2 -0
- data/lib/hexapdf/type/acro_form/field.rb +8 -0
- data/lib/hexapdf/type/acro_form/form.rb +2 -1
- data/lib/hexapdf/type/acro_form/text_field.rb +2 -0
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/digital_signature/common.rb +66 -84
- data/test/hexapdf/digital_signature/signing/test_default_handler.rb +7 -0
- data/test/hexapdf/digital_signature/signing/test_signed_data_creator.rb +9 -0
- data/test/hexapdf/digital_signature/test_cms_handler.rb +41 -1
- data/test/hexapdf/digital_signature/test_handler.rb +2 -1
- data/test/hexapdf/document/test_layout.rb +28 -5
- data/test/hexapdf/layout/test_box.rb +12 -5
- data/test/hexapdf/layout/test_frame.rb +12 -2
- data/test/hexapdf/layout/test_inline_box.rb +17 -28
- data/test/hexapdf/layout/test_list_box.rb +5 -5
- data/test/hexapdf/layout/test_page_style.rb +7 -2
- data/test/hexapdf/layout/test_text_box.rb +3 -9
- data/test/hexapdf/layout/test_text_layouter.rb +0 -3
- data/test/hexapdf/test_document.rb +27 -0
- data/test/hexapdf/test_importer.rb +17 -0
- data/test/hexapdf/test_revisions.rb +54 -41
- data/test/hexapdf/type/acro_form/test_form.rb +9 -0
- 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: f9c1a35d4ad93b48faa1f728bcddc91778da584c8d673e2f15557bd22050a438
|
4
|
+
data.tar.gz: 2ef8ca70891723643080a402f0808882f66f01a816c422477cc03fad34774859
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87c109bd8a6711b4df27a40c689a025d816075d6c68c21a1cc22924b5ae827cd44d98e45bff8f43c85403dd82d6a6e54b66c99bfe135298cba33292e9511a1fc
|
7
|
+
data.tar.gz: e0529e3e244be8366e722ea29ab06a8b922f18698526c79a28d5d11f02da5ee103cba71ecbc6882fefe3de27f02d38f8ce8b505fefbb45839069c74aefaed9ae
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,43 @@
|
|
1
|
+
## 0.46.0 - 2024-08-11
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* [HexaPDF::DigitalSignature::CMSHandler#embedded_tsa_signature] to return the
|
6
|
+
embedded timestamp authority signature if any
|
7
|
+
* [HexaPDF::DigitalSignature::Signing::DefaultHandler#signing_time] for setting
|
8
|
+
a custom signing time
|
9
|
+
* [HexaPDF::Document#duplicate] for making an in-memory copy of a PDF document
|
10
|
+
* Configuration option 'font.default' for setting the default font for the
|
11
|
+
document layout engine
|
12
|
+
|
13
|
+
### Changed
|
14
|
+
|
15
|
+
* [HexaPDF::Document::Layout::CellArgumentCollector#[]=] to allow stepped ranges
|
16
|
+
* [HexaPDF::Document::Layout::ChildrenCollector] to also return the box when
|
17
|
+
creating and adding one to the list
|
18
|
+
* [HexaPDF::Layout::InlineBox] to allow usage without predefined width
|
19
|
+
* [HexaPDF::DigitalSignature::CMSHandler#verify] to recognize non-repudiation
|
20
|
+
signatures
|
21
|
+
* [HexaPDF::DigitalSignature::CMSHandler#signing_time] to use time from an
|
22
|
+
embedded timestamp authority signature if possible
|
23
|
+
* [HexaPDF::Layout::Box#fit] to return success for boxes with content
|
24
|
+
width/height of zero
|
25
|
+
* [HexaPDF::Importer::copy] to optionally allow copying the catalog and page
|
26
|
+
tree nodes
|
27
|
+
|
28
|
+
### Fixed
|
29
|
+
|
30
|
+
* Setting of correct x-position in fit result for boxes with flow positioning
|
31
|
+
* [HexaPDF::Layout::ListBox#fit] to respect the set height
|
32
|
+
* CLI command `hexapdf inspect` to work in case of missing Unicde mappings
|
33
|
+
* [HexaPDF::Type::AcroForm::Form#delete_field] to correctly work for fields with
|
34
|
+
an embedded widget
|
35
|
+
* Parsing of "linearized" PDF files where the first cross-reference section
|
36
|
+
isn't actually used
|
37
|
+
* [HexaPDF::Layout::PageStyle#create_page] to return new frame objects on each
|
38
|
+
invocation
|
39
|
+
|
40
|
+
|
1
41
|
## 0.45.0 - 2024-06-18
|
2
42
|
|
3
43
|
### Added
|
@@ -375,8 +415,8 @@
|
|
375
415
|
|
376
416
|
### Fixed
|
377
417
|
|
378
|
-
* [HexaPDF::Document::Pages#add_labelling_range] to add a correct entry for
|
379
|
-
|
418
|
+
* [HexaPDF::Document::Pages#add_labelling_range] to add a correct entry for the
|
419
|
+
default range starting at page 1
|
380
420
|
* [HexaPDF::Type::Page#flatten_annotations] to correctly handle scaled
|
381
421
|
appearances
|
382
422
|
* Using an unknown style name in [HexaPDF:Document::Layout] method by providing
|
@@ -387,6 +427,8 @@
|
|
387
427
|
than the item content height
|
388
428
|
* [HexaPDF::Dictionary] setting default values on wrong classes in certain
|
389
429
|
situations
|
430
|
+
* [HexaPDF::Importer#import] to correctly import stream objects backed by a
|
431
|
+
[HexaPDF::FiberDoubleForString]
|
390
432
|
|
391
433
|
|
392
434
|
## 0.33.0 - 2023-08-02
|
@@ -439,8 +481,8 @@
|
|
439
481
|
* [HexaPDF::Content::Canvas#text] to set the leading only when multiple lines
|
440
482
|
are drawn
|
441
483
|
* [HexaPDF::Layout::TextBox#split] to use float comparison
|
442
|
-
* Validation of standard encryption dictionary to auto-correct invalid /U and
|
443
|
-
|
484
|
+
* Validation of standard encryption dictionary to auto-correct invalid /U and /O
|
485
|
+
fields in case they are padded with zeros
|
444
486
|
* [HexaPDF::Document#wrap] handling of sub-type mapping in case of missing type
|
445
487
|
* [HexaPDF::Type::AcroForm::AppearanceGenerator] to also take a text field
|
446
488
|
widget's width into account when auto-sizing
|
@@ -761,8 +803,8 @@
|
|
761
803
|
* Support for the document outline
|
762
804
|
* [HexaPDF::Layout::Style#line_height] for setting a custom line height
|
763
805
|
independent of the font size
|
764
|
-
* [HexaPDF::Document::Destinations#use_or_create] as unified interface for
|
765
|
-
|
806
|
+
* [HexaPDF::Document::Destinations#use_or_create] as unified interface for using
|
807
|
+
or creating destinations
|
766
808
|
* [HexaPDF::Document::Destinations::Destination#valid?] and class method for
|
767
809
|
checking whether a destination array is valid
|
768
810
|
|
@@ -771,8 +813,8 @@
|
|
771
813
|
* Calculation of text related [HexaPDF::Layout::Style] values for Type3 fonts
|
772
814
|
* [HexaPDF::Encryption::SecurityHandler#encrypt_string] to either return a
|
773
815
|
dupped or encrypted string
|
774
|
-
* [HexaPDF::Layout::TextLayouter#fit] to avoid infinite loop when encountering
|
775
|
-
|
816
|
+
* [HexaPDF::Layout::TextLayouter#fit] to avoid infinite loop when encountering a
|
817
|
+
non-zero width breakpoint penalty
|
776
818
|
* [HexaPDF::Type::ObjectStream] to parse the initial stream data right after
|
777
819
|
initialization to avoid access errors
|
778
820
|
* [HexaPDF::Revisions::from_io] to merge a completely empty revision with just a
|
@@ -854,8 +896,7 @@
|
|
854
896
|
fragment if there would not be enough height left anyway
|
855
897
|
* [HexaPDF::Layout::WidthFromPolygon] to work correctly in case of very small
|
856
898
|
floating point errors
|
857
|
-
* HexaPDF::Layout::TextFragment#inspect to work in case of interspersed
|
858
|
-
numbers
|
899
|
+
* HexaPDF::Layout::TextFragment#inspect to work in case of interspersed numbers
|
859
900
|
* [HexaPDF::Layout::TextBox#split] to work for position :flow when box is wider
|
860
901
|
than the initial available width
|
861
902
|
* [HexaPDF::Layout::Frame#fit] to create minimally sized mask rectangles
|
@@ -1137,8 +1178,8 @@
|
|
1137
1178
|
dictionary are indirect objects
|
1138
1179
|
* [HexaPDF::Content::GraphicObject::EndpointArc] to correctly determine the
|
1139
1180
|
start and end points
|
1140
|
-
* HexaPDF::Dictionary#perform_validation to correctly handle objects that
|
1141
|
-
|
1181
|
+
* HexaPDF::Dictionary#perform_validation to correctly handle objects that should
|
1182
|
+
not be indirect objects
|
1142
1183
|
|
1143
1184
|
|
1144
1185
|
## 0.17.3 - 2021-10-31
|
@@ -1260,8 +1301,8 @@
|
|
1260
1301
|
|
1261
1302
|
### Fixed
|
1262
1303
|
|
1263
|
-
* [HexaPDF::Type::Annotation#appearance] to handle cases where there is
|
1264
|
-
|
1304
|
+
* [HexaPDF::Type::Annotation#appearance] to handle cases where there is no valid
|
1305
|
+
appearance stream
|
1265
1306
|
|
1266
1307
|
|
1267
1308
|
## 0.15.3 - 2021-05-01
|
@@ -1316,8 +1357,8 @@
|
|
1316
1357
|
empty background color arrays
|
1317
1358
|
* [HexaPDF::Type::AcroForm::Field#delete_widget] to update the wrapper object
|
1318
1359
|
stored in the document in case the widget is embedded
|
1319
|
-
* Processing of invalid PDF files containing a space,CR,LF combination after
|
1320
|
-
|
1360
|
+
* Processing of invalid PDF files containing a space,CR,LF combination after the
|
1361
|
+
'stream' keyword
|
1321
1362
|
* Cross-reference stream reconstruction with respect to detection of linearized
|
1322
1363
|
files
|
1323
1364
|
* Detection of existing appearances for AcroForm push button fields when
|
@@ -1412,8 +1453,8 @@
|
|
1412
1453
|
|
1413
1454
|
* [HexaPDF::Utils::ObjectHash#oids] to be public instead of private
|
1414
1455
|
* Cross-reference table parsing to handle invalidly numbered main sections
|
1415
|
-
* [HexaPDF::Document#cache] and [HexaPDF::Object#cache] to allow updating
|
1416
|
-
|
1456
|
+
* [HexaPDF::Document#cache] and [HexaPDF::Object#cache] to allow updating values
|
1457
|
+
for existing keys
|
1417
1458
|
* Appearance creation methods of AcroForm objects to allow forcing the creation
|
1418
1459
|
of new appearances
|
1419
1460
|
* [HexaPDF::Type::AcroForm::AppearanceGenerator#create_text_appearances] to
|
@@ -1451,8 +1492,8 @@
|
|
1451
1492
|
new 'parser.try_xref_reconstruction' option
|
1452
1493
|
* Two new `hexapdf inspect` commands for showing page objects and page content
|
1453
1494
|
streams by page number
|
1454
|
-
* Flag `--check` to the CLI command `hexapdf info` for checking a file for
|
1455
|
-
|
1495
|
+
* Flag `--check` to the CLI command `hexapdf info` for checking a file for parse
|
1496
|
+
and validation errors
|
1456
1497
|
* [HexaPDF::Type::AcroForm::Field#embedded_widget?] for checking if a widget is
|
1457
1498
|
embedded in the field object
|
1458
1499
|
* [HexaPDF::Type::AcroForm::Field#delete_widget] for deleting a widget
|
@@ -1509,8 +1550,8 @@
|
|
1509
1550
|
|
1510
1551
|
### Added
|
1511
1552
|
|
1512
|
-
* [HexaPDF::Font::Encoding::Base#code] for retrieving the code for a given
|
1513
|
-
|
1553
|
+
* [HexaPDF::Font::Encoding::Base#code] for retrieving the code for a given glyph
|
1554
|
+
name
|
1514
1555
|
|
1515
1556
|
### Fixed
|
1516
1557
|
|
@@ -1526,11 +1567,11 @@
|
|
1526
1567
|
[HexaPDF::Type::AcroForm::Field]
|
1527
1568
|
* [HexaPDF::Type::AcroForm::TextField] and
|
1528
1569
|
[HexaPDF::Type::AcroForm::VariableTextField] for basic text field support
|
1529
|
-
* [HexaPDF::Type::AcroForm::ButtonField] for push button, radio button and
|
1530
|
-
|
1570
|
+
* [HexaPDF::Type::AcroForm::ButtonField] for push button, radio button and check
|
1571
|
+
box support
|
1531
1572
|
* [HexaPDF::Type::AcroForm::ChoiceField] for combo box and list box support
|
1532
|
-
* [HexaPDF::Type::AcroForm::AppearanceGenerator] as central class for
|
1533
|
-
|
1573
|
+
* [HexaPDF::Type::AcroForm::AppearanceGenerator] as central class for generating
|
1574
|
+
appearance streams for form fields
|
1534
1575
|
* Various convenience methods for [HexaPDF::Type::AcroForm::Form]
|
1535
1576
|
* Various convenience methods for [HexaPDF::Type::AcroForm::Field]
|
1536
1577
|
* Various convenience methods for [HexaPDF::Type::Annotations::Widget]
|
@@ -1549,8 +1590,8 @@
|
|
1549
1590
|
* [HexaPDF::Type::Annotation::Border] class
|
1550
1591
|
* [HexaPDF::Content::ColorSpace::device_color_from_specification] for easily
|
1551
1592
|
getting a device color object
|
1552
|
-
* [HexaPDF::Content::ColorSpace::prenormalized_device_color] for getting a
|
1553
|
-
color object without normalizing values
|
1593
|
+
* [HexaPDF::Content::ColorSpace::prenormalized_device_color] for getting a
|
1594
|
+
device color object without normalizing values
|
1554
1595
|
* [HexaPDF::Type::Annotation#appearance] for returning the associated appearance
|
1555
1596
|
dictionary
|
1556
1597
|
* [HexaPDF::Type::Annotation#appearance?] for checking whether an appearance for
|
@@ -1669,8 +1710,8 @@
|
|
1669
1710
|
|
1670
1711
|
### Fixed
|
1671
1712
|
|
1672
|
-
* Conversion of [HexaPDF::Rectangle] type when the original is not a plain
|
1673
|
-
|
1713
|
+
* Conversion of [HexaPDF::Rectangle] type when the original is not a plain Array
|
1714
|
+
but a [HexaPDF::PDFArray]
|
1674
1715
|
|
1675
1716
|
|
1676
1717
|
## 0.11.1 - 2019-11-19
|
@@ -1831,12 +1872,12 @@
|
|
1831
1872
|
|
1832
1873
|
### Added
|
1833
1874
|
|
1834
|
-
* [HexaPDF::Layout::Frame] for box positioning and easier text layouting
|
1835
|
-
|
1875
|
+
* [HexaPDF::Layout::Frame] for box positioning and easier text layouting inside
|
1876
|
+
an arbitrary polygon
|
1836
1877
|
* [HexaPDF::Layout::TextBox] for displaying text in a rectangular and for
|
1837
1878
|
flowing text inside a frame
|
1838
|
-
* [HexaPDF::Layout::WidthFromPolygon] for getting a width specification from
|
1839
|
-
|
1879
|
+
* [HexaPDF::Layout::WidthFromPolygon] for getting a width specification from a
|
1880
|
+
polygon for use with the text layouting engine
|
1840
1881
|
* [HexaPDF::Type::Image#width] and [HexaPDF::Type::Image#height] convenience
|
1841
1882
|
methods
|
1842
1883
|
* [HexaPDF::Type::FontType3] for Type 3 font support
|
@@ -1888,12 +1929,12 @@
|
|
1888
1929
|
character in a text fragment is \r
|
1889
1930
|
* [HexaPDF::Layout::TextLayouter] to work if an optional break point (think
|
1890
1931
|
soft-hyphen) is followed by whitespace
|
1891
|
-
* [HexaPDF::Font::TrueType::Builder] to correctly order the entries in the
|
1892
|
-
|
1932
|
+
* [HexaPDF::Font::TrueType::Builder] to correctly order the entries in the table
|
1933
|
+
directory
|
1893
1934
|
* [HexaPDF::Font::TrueType::Builder] to pad the table data to achieve the
|
1894
1935
|
correct alignment
|
1895
|
-
* [HexaPDF::Filter::FlateDecode] by removing the Zlib pools since they were
|
1896
|
-
|
1936
|
+
* [HexaPDF::Filter::FlateDecode] by removing the Zlib pools since they were not
|
1937
|
+
thread safe
|
1897
1938
|
* All color space classes to accept the color space definition as argument to
|
1898
1939
|
`::new`
|
1899
1940
|
|
@@ -1925,9 +1966,8 @@
|
|
1925
1966
|
* Cross-reference subsection parsing can handle missing whitespace
|
1926
1967
|
* Renamed HexaPDF::Layout::LineFragment to [HexaPDF::Layout::Line]
|
1927
1968
|
* Renamed HexaPDF::Layout::TextBox to [HexaPDF::Layout::TextLayouter]
|
1928
|
-
* [HexaPDF::Layout::TextFragment::new] and
|
1929
|
-
|
1930
|
-
style options
|
1969
|
+
* [HexaPDF::Layout::TextFragment::new] and [HexaPDF::Layout::TextLayouter::new]
|
1970
|
+
to either take a Style object or style options
|
1931
1971
|
* [HexaPDF::Layout::TextLayouter#fit] method signature
|
1932
1972
|
* [HexaPDF::Layout::InlineBox] to wrap a generic box
|
1933
1973
|
* HexaPDF::Document::Fonts#load to [HexaPDF::Document::Fonts#add] for
|
@@ -1989,8 +2029,8 @@
|
|
1989
2029
|
|
1990
2030
|
* Handling of invalid glyphs is done using the special
|
1991
2031
|
[HexaPDF::Font::InvalidGlyph] class
|
1992
|
-
* Configuration option 'font.on_missing_glyph'; returns an invalid glyph
|
1993
|
-
|
2032
|
+
* Configuration option 'font.on_missing_glyph'; returns an invalid glyph instead
|
2033
|
+
of raising an error
|
1994
2034
|
* Bounding box of TrueType glyphs without contours is set to `[0, 0, 0, 0]`
|
1995
2035
|
* Ligature pairs for AFM fonts are stored like kerning pairs
|
1996
2036
|
* Use TrueType configuration option 'font.true_type.unknown_format' in all
|
@@ -2007,8 +2047,8 @@
|
|
2007
2047
|
|
2008
2048
|
* [HexaPDF::Task::Dereference] to work correctly when encountering invalid
|
2009
2049
|
references
|
2010
|
-
* [HexaPDF::Tokenizer] and HexaPDF::Content::Tokenizer to parse a solitary
|
2011
|
-
|
2050
|
+
* [HexaPDF::Tokenizer] and HexaPDF::Content::Tokenizer to parse a solitary plus
|
2051
|
+
sign
|
2012
2052
|
* Usage of Strings instead of Symbols for AFM font kerning and ligature pairs
|
2013
2053
|
* Processing the contents of form XObjects in case they don't have a resources
|
2014
2054
|
dictionary
|
@@ -2031,8 +2071,8 @@
|
|
2031
2071
|
* CLI option `--verbose` for more verbose output; also changed the default
|
2032
2072
|
verbosity level to only display warnings and not informational messages
|
2033
2073
|
* CLI option `--quiet` for suppressing additional and diagnostic output
|
2034
|
-
* CLI option `--strict` for enabling strict parsing and validation; also
|
2035
|
-
|
2074
|
+
* CLI option `--strict` for enabling strict parsing and validation; also changed
|
2075
|
+
the default from strict to non-strict parsing/validation
|
2036
2076
|
* CLI optimization option `--optimize-fonts` for optimizing embedded fonts
|
2037
2077
|
* Method `#word_spacing_applicable?` to font types
|
2038
2078
|
* Support for marked-content points and sequences in [HexaPDF::Content::Canvas]
|
data/examples/019-acro_form.rb
CHANGED
@@ -6,6 +6,11 @@
|
|
6
6
|
# This example show-cases how to create the various form field types and their
|
7
7
|
# possible standard appearances.
|
8
8
|
#
|
9
|
+
# The [HexaPDF::Type::AcroForm::Form] and [HexaPDF::Type::AcroForm::Field]
|
10
|
+
# classes provide a plethora of convenience methods for working with forms, like
|
11
|
+
# for creating fields and their widgets, getting field properties like the full
|
12
|
+
# hierarchical field name or for setting the field value.
|
13
|
+
#
|
9
14
|
# Usage:
|
10
15
|
# : `ruby acro_form.rb`
|
11
16
|
#
|
data/lib/hexapdf/cli/inspect.rb
CHANGED
@@ -117,6 +117,11 @@ module HexaPDF
|
|
117
117
|
|
118
118
|
def execute(file, *commands) #:nodoc:
|
119
119
|
with_document(file, password: @password) do |doc|
|
120
|
+
doc.config['font.on_missing_unicode_mapping'] = lambda do |code, font|
|
121
|
+
$stderr.puts("No Unicode mapping for code point #{code} in font #{font[:BaseFont]}, " \
|
122
|
+
"using the Unicode replacement character")
|
123
|
+
"\u{FFFD}"
|
124
|
+
end
|
120
125
|
@doc = doc
|
121
126
|
if commands.empty?
|
122
127
|
begin
|
data/lib/hexapdf/composer.rb
CHANGED
@@ -450,7 +450,7 @@ module HexaPDF
|
|
450
450
|
(box = draw_box; break) unless box
|
451
451
|
elsif !@frame.find_next_region
|
452
452
|
unless drawn_on_page
|
453
|
-
raise HexaPDF::Error, "Box
|
453
|
+
raise HexaPDF::Error, "Box didn't fit multiple times, even on empty page"
|
454
454
|
end
|
455
455
|
new_page
|
456
456
|
drawn_on_page = false
|
@@ -277,6 +277,13 @@ module HexaPDF
|
|
277
277
|
#
|
278
278
|
# See PDF2.0 s7.4.1, ADB sH.3 3.3
|
279
279
|
#
|
280
|
+
# font.default::
|
281
|
+
# This font is used by the layout engine when no font is specified but one is needed.
|
282
|
+
#
|
283
|
+
# This is used, for example, for the font set on styles that don't have a font set.
|
284
|
+
#
|
285
|
+
# The default value is 'Times'.
|
286
|
+
#
|
280
287
|
# font.fallback::
|
281
288
|
# An array of fallback font names to be used when replacing invalid glyphs.
|
282
289
|
#
|
@@ -518,6 +525,7 @@ module HexaPDF
|
|
518
525
|
Crypt: 'HexaPDF::Filter::Crypt',
|
519
526
|
Encryption: 'HexaPDF::Filter::Encryption',
|
520
527
|
},
|
528
|
+
'font.default' => 'Times',
|
521
529
|
'font.fallback' => ['ZapfDingbats', 'Symbol'],
|
522
530
|
'font.map' => {},
|
523
531
|
'font.on_invalid_glyph' => method(:font_on_invalid_glyph),
|
@@ -59,7 +59,11 @@ module HexaPDF
|
|
59
59
|
|
60
60
|
# Returns the time of signing.
|
61
61
|
def signing_time
|
62
|
-
|
62
|
+
if embedded_tsa_signature
|
63
|
+
embedded_tsa_signature.signers.first.signed_time
|
64
|
+
else
|
65
|
+
signer_info.signed_time rescue super
|
66
|
+
end
|
63
67
|
end
|
64
68
|
|
65
69
|
# Returns the certificate chain.
|
@@ -78,6 +82,23 @@ module HexaPDF
|
|
78
82
|
@pkcs7.signers.first
|
79
83
|
end
|
80
84
|
|
85
|
+
# Returns the OpenSSL::PKCS7 object for the embedded TSA signature if there is one or +nil+
|
86
|
+
# otherwise.
|
87
|
+
def embedded_tsa_signature
|
88
|
+
return @embedded_tsa_signature if defined?(@embedded_tsa_signature)
|
89
|
+
|
90
|
+
@embedded_tsa_signature = nil
|
91
|
+
p7 = OpenSSL::ASN1.decode(signature_dict.contents.sub(/\x00*\z/, ''))
|
92
|
+
signed_data = p7.value[1].value[0]
|
93
|
+
signer_info = signed_data.value[-1].value[0] # first (and only) signer info
|
94
|
+
return unless signer_info.value[-1].tag == 1 # check for unsigned attributes
|
95
|
+
timestamp_token = signer_info.value[-1].value.find do |unsigned_attr|
|
96
|
+
unsigned_attr.value[0].value == "id-smime-aa-timeStampToken"
|
97
|
+
end
|
98
|
+
return unless timestamp_token
|
99
|
+
@embedded_tsa_signature = OpenSSL::PKCS7.new(timestamp_token.value[1].value[0])
|
100
|
+
end
|
101
|
+
|
81
102
|
# Verifies the signature using the provided OpenSSL::X509::Store object.
|
82
103
|
def verify(store, allow_self_signed: false)
|
83
104
|
result = super
|
@@ -101,9 +122,16 @@ module HexaPDF
|
|
101
122
|
return result
|
102
123
|
end
|
103
124
|
|
125
|
+
if embedded_tsa_signature
|
126
|
+
result.log(:info, 'Signing time comes from timestamp authority')
|
127
|
+
end
|
128
|
+
|
104
129
|
key_usage = signer_certificate.extensions.find {|ext| ext.oid == 'keyUsage' }
|
105
|
-
|
106
|
-
|
130
|
+
key_usage = key_usage&.value&.split(', ')
|
131
|
+
if key_usage&.include?("Non Repudiation") && !key_usage.include?("Digital Signature")
|
132
|
+
result.log(:info, 'Certificate used for non-repudiation')
|
133
|
+
elsif !key_usage || !key_usage.include?("Digital Signature")
|
134
|
+
result.log(:error, "Certificate key usage is missing 'Digital Signature' or 'Non Repudiation'")
|
107
135
|
end
|
108
136
|
|
109
137
|
if signature_dict.signature_type == 'ETSI.RFC3161'
|
@@ -211,6 +211,13 @@ module HexaPDF
|
|
211
211
|
# The contact information. If used, will be set on the signature dictionary.
|
212
212
|
attr_accessor :contact_info
|
213
213
|
|
214
|
+
# The custom signing time.
|
215
|
+
#
|
216
|
+
# The signing time is usually the time when signing actually happens. This is also what
|
217
|
+
# HexaPDF uses. If it is known that signing happened at a different point in time, that time
|
218
|
+
# can be provided using this accessor.
|
219
|
+
attr_accessor :signing_time
|
220
|
+
|
214
221
|
# The size of the serialized signature that should be reserved.
|
215
222
|
#
|
216
223
|
# If this attribute is not set, an empty string will be signed using #sign to determine the
|
@@ -277,7 +284,7 @@ module HexaPDF
|
|
277
284
|
def finalize_objects(_signature_field, signature)
|
278
285
|
signature[:Filter] = :'Adobe.PPKLite'
|
279
286
|
signature[:SubFilter] = (signature_type == :pades ? :'ETSI.CAdES.detached' : :'adbe.pkcs7.detached')
|
280
|
-
signature[:M] = Time.now
|
287
|
+
signature[:M] = self.signing_time ||= Time.now
|
281
288
|
signature[:Reason] = reason if reason
|
282
289
|
signature[:Location] = location if location
|
283
290
|
signature[:ContactInfo] = contact_info if contact_info
|
@@ -312,6 +319,7 @@ module HexaPDF
|
|
312
319
|
type: signature_type,
|
313
320
|
certificate: certificate, key: key,
|
314
321
|
digest_algorithm: digest_algorithm,
|
322
|
+
signing_time: signing_time,
|
315
323
|
timestamp_handler: timestamp_handler,
|
316
324
|
certificates: certificate_chain, &external_signing).to_der
|
317
325
|
else
|
@@ -84,6 +84,9 @@ module HexaPDF
|
|
84
84
|
# Allowed values: sha256, sha384, sha512.
|
85
85
|
attr_accessor :digest_algorithm
|
86
86
|
|
87
|
+
# The signing time to use instead of Time.now.
|
88
|
+
attr_accessor :signing_time
|
89
|
+
|
87
90
|
# The timestamp handler instance that should be used for timestamping.
|
88
91
|
attr_accessor :timestamp_handler
|
89
92
|
|
@@ -119,9 +122,10 @@ module HexaPDF
|
|
119
122
|
|
120
123
|
# Creates the set of signed attributes for the signer information structure.
|
121
124
|
def create_signed_attrs(data, signing_time: true)
|
125
|
+
signing_time = (self.signing_time || Time.now).utc if signing_time
|
122
126
|
set(
|
123
127
|
attribute('content-type', oid('id-data')),
|
124
|
-
(attribute('id-signingTime', utc_time(
|
128
|
+
(attribute('id-signingTime', utc_time(signing_time)) if signing_time),
|
125
129
|
attribute(
|
126
130
|
'message-digest',
|
127
131
|
binary(OpenSSL::Digest.digest(@digest_algorithm, data))
|
@@ -77,9 +77,9 @@ module HexaPDF
|
|
77
77
|
#
|
78
78
|
# One style property, Layout::Style#font, is handled specially:
|
79
79
|
#
|
80
|
-
# * If no font is set on a style, the font
|
81
|
-
#
|
82
|
-
# valid default value).
|
80
|
+
# * If no font is set on a style, the default font specified via the configuration option
|
81
|
+
# 'font.default' is automatically set because otherwise there would be problems with text
|
82
|
+
# drawing operations (font is the only style property that has no valid default value).
|
83
83
|
#
|
84
84
|
# * Standard style objects only allow font wrapper objects to be set via the Layout::Style#font
|
85
85
|
# method. This class makes usage easier by allowing strings or an array [name, options_hash]
|
@@ -151,7 +151,9 @@ module HexaPDF
|
|
151
151
|
# :nodoc:
|
152
152
|
def method_missing(name, *args, **kwargs, &block)
|
153
153
|
if @layout.box_creation_method?(name)
|
154
|
-
|
154
|
+
box = @layout.send(name, *args, **kwargs, &block)
|
155
|
+
@children << box
|
156
|
+
box
|
155
157
|
else
|
156
158
|
super
|
157
159
|
end
|
@@ -354,6 +356,7 @@ module HexaPDF
|
|
354
356
|
width: width, height: height, properties: properties,
|
355
357
|
style: box_style)
|
356
358
|
end
|
359
|
+
alias text text_box
|
357
360
|
|
358
361
|
# Creates a HexaPDF::Layout::TextBox like #text_box but allows parts of the text to be
|
359
362
|
# formatted differently.
|
@@ -456,6 +459,7 @@ module HexaPDF
|
|
456
459
|
box_class_for_name(:text).new(items: data, width: width, height: height,
|
457
460
|
properties: properties, style: box_style)
|
458
461
|
end
|
462
|
+
alias formatted_text formatted_text_box
|
459
463
|
|
460
464
|
# Creates a HexaPDF::Layout::ImageBox for the given image.
|
461
465
|
#
|
@@ -477,6 +481,7 @@ module HexaPDF
|
|
477
481
|
box_class_for_name(:image).new(image: image, width: width, height: height,
|
478
482
|
properties: properties, style: style)
|
479
483
|
end
|
484
|
+
alias image image_box
|
480
485
|
|
481
486
|
# This helper class is used by Layout#table_box to allow specifying the keyword arguments used
|
482
487
|
# when converting cell data to box instances.
|
@@ -495,8 +500,25 @@ module HexaPDF
|
|
495
500
|
@number_of_columns = number_of_columns
|
496
501
|
end
|
497
502
|
|
498
|
-
# Stores the
|
499
|
-
#
|
503
|
+
# Stores the hash +args+ containing styling properties for the cells specified via the given
|
504
|
+
# 0-based rows and columns.
|
505
|
+
#
|
506
|
+
# Rows and columns can either be single numbers, ranges of numbers or stepped ranges (i.e.
|
507
|
+
# Enumerator::ArithmeticSequence instances).
|
508
|
+
#
|
509
|
+
# Examples:
|
510
|
+
#
|
511
|
+
# # Gray background for all cells
|
512
|
+
# args[] = {cell: {background_color: "gray"}}
|
513
|
+
#
|
514
|
+
# # Cell at (2, 3) gets a bigger font size
|
515
|
+
# args[2, 3] = {font_size: 50}
|
516
|
+
#
|
517
|
+
# # First column of every row has bold font
|
518
|
+
# args[0..-1, 0] = {font: 'Helvetica bold'}
|
519
|
+
#
|
520
|
+
# # Every second row has a blue background
|
521
|
+
# args[(0..-1).step(2)] = {cell: {background_color: "blue"}}
|
500
522
|
def []=(rows = 0..-1, cols = 0..-1, args)
|
501
523
|
rows = adjust_range(rows.kind_of?(Integer) ? rows..rows : rows, @number_of_rows)
|
502
524
|
cols = adjust_range(cols.kind_of?(Integer) ? cols..cols : cols, @number_of_columns)
|
@@ -509,7 +531,7 @@ module HexaPDF
|
|
509
531
|
# is merged.
|
510
532
|
def retrieve_arguments_for(row, col)
|
511
533
|
@argument_infos.each_with_object({}) do |arg_info, result|
|
512
|
-
next unless arg_info.rows.
|
534
|
+
next unless arg_info.rows.include?(row) && arg_info.cols.include?(col)
|
513
535
|
if arg_info.args[:cell]
|
514
536
|
arg_info.args[:cell] = (result[:cell] || {}).merge(arg_info.args[:cell])
|
515
537
|
end
|
@@ -522,7 +544,8 @@ module HexaPDF
|
|
522
544
|
# Adjusts the +range+ so that both the begin and the end of the range are zero or positive
|
523
545
|
# integers smaller than +max+.
|
524
546
|
def adjust_range(range, max)
|
525
|
-
(range.begin % max)..(range.end % max)
|
547
|
+
r = (range.begin % max)..(range.end % max)
|
548
|
+
range.kind_of?(Range) ? r : r.step(range.step)
|
526
549
|
end
|
527
550
|
|
528
551
|
end
|
@@ -540,7 +563,8 @@ module HexaPDF
|
|
540
563
|
# Additional arguments for the #text_box invocations can be specified using the optional block
|
541
564
|
# that yields a CellArgumentCollector instance. This allows customization of the text boxes.
|
542
565
|
# By specifying the special key +:cell+ it is also possible to assign style properties to the
|
543
|
-
# cells themselves.
|
566
|
+
# cells themselves, irrespective of the type of content of the cells. See
|
567
|
+
# CellArgumentCollector#[]= for details.
|
544
568
|
#
|
545
569
|
# See HexaPDF::Layout::TableBox::new for details on +column_widths+, +header+, +footer+, and
|
546
570
|
# +cell_style+.
|
@@ -586,6 +610,7 @@ module HexaPDF
|
|
586
610
|
footer: footer, cell_style: cell_style, width: width,
|
587
611
|
height: height, properties: properties, style: style)
|
588
612
|
end
|
613
|
+
alias table table_box
|
589
614
|
|
590
615
|
LOREM_IPSUM = [ # :nodoc:
|
591
616
|
"Lorem ipsum dolor sit amet, con\u{00AD}sectetur adipis\u{00AD}cing elit, sed " \
|
@@ -605,22 +630,13 @@ module HexaPDF
|
|
605
630
|
def lorem_ipsum_box(sentences: 4, count: 1, **text_box_properties)
|
606
631
|
text_box(([LOREM_IPSUM[0, sentences].join(" ")] * count).join("\n\n"), **text_box_properties)
|
607
632
|
end
|
633
|
+
alias lorem_ipsum lorem_ipsum_box
|
608
634
|
|
609
|
-
|
610
|
-
|
611
|
-
# Allows creating boxes using more convenient method names:
|
612
|
-
#
|
613
|
-
# * #text for #text_box
|
614
|
-
# * #formatted_text for #formatted_text_box
|
615
|
-
# * #image for #image_box
|
616
|
-
# * #lorem_ipsum for #lorem_ipsum_box
|
617
|
-
# * The name of a pre-defined box class like #column will invoke #box appropriately. Same if
|
618
|
-
# used with a '_box' suffix.
|
635
|
+
# Allows creating boxes using more convenient method names: The name of a pre-defined box
|
636
|
+
# class like #column will invoke #box appropriately. Same if used with a '_box' suffix.
|
619
637
|
def method_missing(name, *args, **kwargs, &block)
|
620
638
|
name_without_box = name.to_s.sub(/_box$/, '').intern
|
621
|
-
if
|
622
|
-
send("#{name}_box", *args, **kwargs, &block)
|
623
|
-
elsif @document.config['layout.boxes.map'].key?(name_without_box)
|
639
|
+
if @document.config['layout.boxes.map'].key?(name_without_box)
|
624
640
|
box(name_without_box, *args, **kwargs, &block)
|
625
641
|
else
|
626
642
|
super
|
@@ -632,6 +648,8 @@ module HexaPDF
|
|
632
648
|
box_creation_method?(name) || super
|
633
649
|
end
|
634
650
|
|
651
|
+
BOX_METHOD_NAMES = [:text, :formatted_text, :image, :table, :lorem_ipsum] #:nodoc:
|
652
|
+
|
635
653
|
# :nodoc:
|
636
654
|
def box_creation_method?(name)
|
637
655
|
name = name.to_s.sub(/_box$/, '').intern
|
@@ -648,8 +666,8 @@ module HexaPDF
|
|
648
666
|
end
|
649
667
|
end
|
650
668
|
|
651
|
-
# Retrieves the appropriate HexaPDF::Layout::Style object based on the +style+ and
|
652
|
-
# arguments.
|
669
|
+
# Retrieves the appropriate HexaPDF::Layout::Style object based on the +style+ and
|
670
|
+
# +properties+ arguments.
|
653
671
|
#
|
654
672
|
# The +style+ argument specifies the style to retrieve. It can either be a registered style
|
655
673
|
# name (see #style), a hash with style properties or +nil+. In the latter case the registered
|
@@ -658,15 +676,18 @@ module HexaPDF
|
|
658
676
|
# If the +properties+ hash is not empty, the retrieved style is duplicated and the properties
|
659
677
|
# hash is applied to it.
|
660
678
|
#
|
661
|
-
# Finally, a default font (the one from the :base style or otherwise
|
662
|
-
# necessary to ensure that the style object
|
679
|
+
# Finally, a default font (the one from the :base style or otherwise the one set using the
|
680
|
+
# configuration option 'font.default') is set if necessary to ensure that the style object
|
681
|
+
# works in all cases.
|
663
682
|
def retrieve_style(style, properties = nil)
|
664
683
|
if style.kind_of?(Symbol) && !@styles.key?(style)
|
665
684
|
raise HexaPDF::Error, "Style #{style} not defined"
|
666
685
|
end
|
667
686
|
style = HexaPDF::Layout::Style.create(@styles[style] || style || @styles[:base])
|
668
687
|
style = style.dup.update(**properties) unless properties.nil? || properties.empty?
|
669
|
-
|
688
|
+
unless style.font?
|
689
|
+
style.font(@styles[:base].font? && @styles[:base].font || @document.config['font.default'])
|
690
|
+
end
|
670
691
|
unless style.font.respond_to?(:pdf_object)
|
671
692
|
name, options = *style.font
|
672
693
|
style.font(@document.fonts.add(name, **(options || {})))
|