hexapdf 0.45.0 → 0.47.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +120 -47
  3. data/examples/019-acro_form.rb +5 -0
  4. data/lib/hexapdf/cli/inspect.rb +5 -0
  5. data/lib/hexapdf/composer.rb +1 -1
  6. data/lib/hexapdf/configuration.rb +19 -0
  7. data/lib/hexapdf/digital_signature/cms_handler.rb +31 -3
  8. data/lib/hexapdf/digital_signature/signing/default_handler.rb +9 -1
  9. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +5 -1
  10. data/lib/hexapdf/document/layout.rb +48 -27
  11. data/lib/hexapdf/document.rb +24 -2
  12. data/lib/hexapdf/encryption/standard_security_handler.rb +32 -26
  13. data/lib/hexapdf/importer.rb +15 -5
  14. data/lib/hexapdf/layout/box.rb +25 -28
  15. data/lib/hexapdf/layout/frame.rb +1 -1
  16. data/lib/hexapdf/layout/inline_box.rb +17 -23
  17. data/lib/hexapdf/layout/list_box.rb +24 -29
  18. data/lib/hexapdf/layout/page_style.rb +23 -16
  19. data/lib/hexapdf/layout/style.rb +2 -2
  20. data/lib/hexapdf/layout/table_box.rb +57 -10
  21. data/lib/hexapdf/layout/text_box.rb +2 -6
  22. data/lib/hexapdf/parser.rb +5 -1
  23. data/lib/hexapdf/revisions.rb +1 -1
  24. data/lib/hexapdf/stream.rb +3 -3
  25. data/lib/hexapdf/task/optimize.rb +4 -4
  26. data/lib/hexapdf/tokenizer.rb +3 -2
  27. data/lib/hexapdf/type/acro_form/appearance_generator.rb +8 -4
  28. data/lib/hexapdf/type/acro_form/button_field.rb +2 -0
  29. data/lib/hexapdf/type/acro_form/choice_field.rb +2 -0
  30. data/lib/hexapdf/type/acro_form/field.rb +8 -0
  31. data/lib/hexapdf/type/acro_form/form.rb +10 -6
  32. data/lib/hexapdf/type/acro_form/signature_field.rb +2 -1
  33. data/lib/hexapdf/type/acro_form/text_field.rb +2 -0
  34. data/lib/hexapdf/type/acro_form/variable_text_field.rb +11 -3
  35. data/lib/hexapdf/type/annotations/widget.rb +4 -2
  36. data/lib/hexapdf/version.rb +1 -1
  37. data/lib/hexapdf/writer.rb +1 -0
  38. data/test/data/standard-security-handler/bothpwd-aes-256bit-V5-R5.pdf +43 -0
  39. data/test/data/standard-security-handler/nopwd-aes-256bit-V5-R5.pdf +44 -0
  40. data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5-R5.pdf +43 -0
  41. data/test/data/standard-security-handler/userpwd-aes-256bit-V5-R5.pdf +0 -0
  42. data/test/hexapdf/digital_signature/common.rb +66 -84
  43. data/test/hexapdf/digital_signature/signing/test_default_handler.rb +7 -0
  44. data/test/hexapdf/digital_signature/signing/test_signed_data_creator.rb +9 -0
  45. data/test/hexapdf/digital_signature/test_cms_handler.rb +41 -1
  46. data/test/hexapdf/digital_signature/test_handler.rb +2 -1
  47. data/test/hexapdf/digital_signature/test_signatures.rb +4 -4
  48. data/test/hexapdf/document/test_layout.rb +28 -5
  49. data/test/hexapdf/encryption/test_standard_security_handler.rb +5 -2
  50. data/test/hexapdf/layout/test_box.rb +12 -5
  51. data/test/hexapdf/layout/test_frame.rb +12 -2
  52. data/test/hexapdf/layout/test_inline_box.rb +17 -28
  53. data/test/hexapdf/layout/test_list_box.rb +5 -5
  54. data/test/hexapdf/layout/test_page_style.rb +7 -2
  55. data/test/hexapdf/layout/test_table_box.rb +52 -0
  56. data/test/hexapdf/layout/test_text_box.rb +3 -9
  57. data/test/hexapdf/layout/test_text_layouter.rb +0 -3
  58. data/test/hexapdf/task/test_optimize.rb +2 -0
  59. data/test/hexapdf/test_document.rb +30 -3
  60. data/test/hexapdf/test_importer.rb +24 -0
  61. data/test/hexapdf/test_revisions.rb +54 -41
  62. data/test/hexapdf/test_writer.rb +11 -2
  63. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +22 -5
  64. data/test/hexapdf/type/acro_form/test_form.rb +9 -5
  65. data/test/hexapdf/type/acro_form/test_signature_field.rb +3 -1
  66. data/test/hexapdf/type/acro_form/test_variable_text_field.rb +14 -1
  67. data/test/hexapdf/type/annotations/test_widget.rb +4 -0
  68. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd31e769d2a906198da2a4194085cb2a884fa3879442b75add168d7f81d67d8b
4
- data.tar.gz: 43c2b4ba4df2f997d470835995f2581aa306c639c63ddc892e648d94605f3b22
3
+ metadata.gz: 15f4c7590b5f2ce321519ac0b4871971c12073a9d4b0df36ab2f2e3c156f09ab
4
+ data.tar.gz: 76dac6196e06e80fd88dade3f831b7744c2b763f004d3c389d3efebcace3be82
5
5
  SHA512:
6
- metadata.gz: f17a303dba8104974564a213c72c0f0862c520964a3255b575544489ccb5a17a468d093d3970817903c4eb798e888592410db18447d3264d535f3a01a4a94c82
7
- data.tar.gz: d5727e2f2bfb5ed827ac92eecc8cd9e0ba73044150ba07d03623dccde43dc29db1cddc2fbce24bfd63268522e7965519e188271c2bc9c00162b1a660fc468b74
6
+ metadata.gz: 8ea19ed17370cad1a1fa48a7e0cb85c16e3ff62b344d2a9a90c42d2ac98d5ce5f75c356facf6bb8276822db460e2d9f912f523783c82b3539200e33f9de9f383
7
+ data.tar.gz: bdf2d93feade9f0654366bbf89711b670cbd03ee88b81f197f756c2032305f9ee7b9265973f31c5a4e18e7afd3e4f9dfd08b46a0483502b896774494294c111a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,76 @@
1
+ ## 0.47.0 - 2024-09-07
2
+
3
+ ### Added
4
+
5
+ * Configuration option 'acro_form.fallback_default_appearance' to allow setting
6
+ a standard default appearance string for a variable text field if none is
7
+ found
8
+ * Support for decrypting files with the proprietary algorithm /R 5
9
+
10
+ ### Changed
11
+
12
+ * [HexaPDF::Task::Optimize] to not remove optional /Type entries containing
13
+ default values
14
+ * Validation of [HexaPDF::Type::AcroForm::Form] to not add a /DA entry
15
+
16
+ ### Fixed
17
+
18
+ * [HexaPDF::Layout::TableBox] to correctly calculcate and distribute row
19
+ heights when row spans are involved
20
+ * [HexaPDF::Type::AcroForm::AppearanceGenerator] to work for files where check
21
+ boxes don't define the name of the on state
22
+ * [HexaPDF::Importer#import] to handle null values in all cases
23
+ * [HexaPDF::Type::AcroForm::VariableTextField] to handle parsing of invalid PDFs
24
+ with symbolic appearance strings
25
+ * [HexaPDF::Type::Annotations::Widget#marker_style] to handle invalid /DA values
26
+ with missing font size or color information
27
+ * [HexaPDF::Type::AcroForm::SignatureField#field_value] to always return a
28
+ correctly wrapped object
29
+ * [HexaPDF::Writer] to remove /Type entry from trailer
30
+ * [HexaPDF::Type::AcroForm::AppearanceGenerator#create_text_appearances] to
31
+ handle invalid appearance streams that are not correct Form XObjects
32
+
33
+
34
+ ## 0.46.0 - 2024-08-11
35
+
36
+ ### Added
37
+
38
+ * [HexaPDF::DigitalSignature::CMSHandler#embedded_tsa_signature] to return the
39
+ embedded timestamp authority signature if any
40
+ * [HexaPDF::DigitalSignature::Signing::DefaultHandler#signing_time] for setting
41
+ a custom signing time
42
+ * [HexaPDF::Document#duplicate] for making an in-memory copy of a PDF document
43
+ * Configuration option 'font.default' for setting the default font for the
44
+ document layout engine
45
+
46
+ ### Changed
47
+
48
+ * [HexaPDF::Document::Layout::CellArgumentCollector#[]=] to allow stepped ranges
49
+ * [HexaPDF::Document::Layout::ChildrenCollector] to also return the box when
50
+ creating and adding one to the list
51
+ * [HexaPDF::Layout::InlineBox] to allow usage without predefined width
52
+ * [HexaPDF::DigitalSignature::CMSHandler#verify] to recognize non-repudiation
53
+ signatures
54
+ * [HexaPDF::DigitalSignature::CMSHandler#signing_time] to use time from an
55
+ embedded timestamp authority signature if possible
56
+ * [HexaPDF::Layout::Box#fit] to return success for boxes with content
57
+ width/height of zero
58
+ * [HexaPDF::Importer::copy] to optionally allow copying the catalog and page
59
+ tree nodes
60
+
61
+ ### Fixed
62
+
63
+ * Setting of correct x-position in fit result for boxes with flow positioning
64
+ * [HexaPDF::Layout::ListBox#fit] to respect the set height
65
+ * CLI command `hexapdf inspect` to work in case of missing Unicde mappings
66
+ * [HexaPDF::Type::AcroForm::Form#delete_field] to correctly work for fields with
67
+ an embedded widget
68
+ * Parsing of "linearized" PDF files where the first cross-reference section
69
+ isn't actually used
70
+ * [HexaPDF::Layout::PageStyle#create_page] to return new frame objects on each
71
+ invocation
72
+
73
+
1
74
  ## 0.45.0 - 2024-06-18
2
75
 
3
76
  ### Added
@@ -375,8 +448,8 @@
375
448
 
376
449
  ### Fixed
377
450
 
378
- * [HexaPDF::Document::Pages#add_labelling_range] to add a correct entry for
379
- the default range starting at page 1
451
+ * [HexaPDF::Document::Pages#add_labelling_range] to add a correct entry for the
452
+ default range starting at page 1
380
453
  * [HexaPDF::Type::Page#flatten_annotations] to correctly handle scaled
381
454
  appearances
382
455
  * Using an unknown style name in [HexaPDF:Document::Layout] method by providing
@@ -387,6 +460,8 @@
387
460
  than the item content height
388
461
  * [HexaPDF::Dictionary] setting default values on wrong classes in certain
389
462
  situations
463
+ * [HexaPDF::Importer#import] to correctly import stream objects backed by a
464
+ [HexaPDF::FiberDoubleForString]
390
465
 
391
466
 
392
467
  ## 0.33.0 - 2023-08-02
@@ -439,8 +514,8 @@
439
514
  * [HexaPDF::Content::Canvas#text] to set the leading only when multiple lines
440
515
  are drawn
441
516
  * [HexaPDF::Layout::TextBox#split] to use float comparison
442
- * Validation of standard encryption dictionary to auto-correct invalid /U and
443
- /O fields in case they are padded with zeros
517
+ * Validation of standard encryption dictionary to auto-correct invalid /U and /O
518
+ fields in case they are padded with zeros
444
519
  * [HexaPDF::Document#wrap] handling of sub-type mapping in case of missing type
445
520
  * [HexaPDF::Type::AcroForm::AppearanceGenerator] to also take a text field
446
521
  widget's width into account when auto-sizing
@@ -761,8 +836,8 @@
761
836
  * Support for the document outline
762
837
  * [HexaPDF::Layout::Style#line_height] for setting a custom line height
763
838
  independent of the font size
764
- * [HexaPDF::Document::Destinations#use_or_create] as unified interface for
765
- using or creating destinations
839
+ * [HexaPDF::Document::Destinations#use_or_create] as unified interface for using
840
+ or creating destinations
766
841
  * [HexaPDF::Document::Destinations::Destination#valid?] and class method for
767
842
  checking whether a destination array is valid
768
843
 
@@ -771,8 +846,8 @@
771
846
  * Calculation of text related [HexaPDF::Layout::Style] values for Type3 fonts
772
847
  * [HexaPDF::Encryption::SecurityHandler#encrypt_string] to either return a
773
848
  dupped or encrypted string
774
- * [HexaPDF::Layout::TextLayouter#fit] to avoid infinite loop when encountering
775
- a non-zero width breakpoint penalty
849
+ * [HexaPDF::Layout::TextLayouter#fit] to avoid infinite loop when encountering a
850
+ non-zero width breakpoint penalty
776
851
  * [HexaPDF::Type::ObjectStream] to parse the initial stream data right after
777
852
  initialization to avoid access errors
778
853
  * [HexaPDF::Revisions::from_io] to merge a completely empty revision with just a
@@ -854,8 +929,7 @@
854
929
  fragment if there would not be enough height left anyway
855
930
  * [HexaPDF::Layout::WidthFromPolygon] to work correctly in case of very small
856
931
  floating point errors
857
- * HexaPDF::Layout::TextFragment#inspect to work in case of interspersed
858
- numbers
932
+ * HexaPDF::Layout::TextFragment#inspect to work in case of interspersed numbers
859
933
  * [HexaPDF::Layout::TextBox#split] to work for position :flow when box is wider
860
934
  than the initial available width
861
935
  * [HexaPDF::Layout::Frame#fit] to create minimally sized mask rectangles
@@ -1137,8 +1211,8 @@
1137
1211
  dictionary are indirect objects
1138
1212
  * [HexaPDF::Content::GraphicObject::EndpointArc] to correctly determine the
1139
1213
  start and end points
1140
- * HexaPDF::Dictionary#perform_validation to correctly handle objects that
1141
- should not be indirect objects
1214
+ * HexaPDF::Dictionary#perform_validation to correctly handle objects that should
1215
+ not be indirect objects
1142
1216
 
1143
1217
 
1144
1218
  ## 0.17.3 - 2021-10-31
@@ -1260,8 +1334,8 @@
1260
1334
 
1261
1335
  ### Fixed
1262
1336
 
1263
- * [HexaPDF::Type::Annotation#appearance] to handle cases where there is
1264
- no valid appearance stream
1337
+ * [HexaPDF::Type::Annotation#appearance] to handle cases where there is no valid
1338
+ appearance stream
1265
1339
 
1266
1340
 
1267
1341
  ## 0.15.3 - 2021-05-01
@@ -1316,8 +1390,8 @@
1316
1390
  empty background color arrays
1317
1391
  * [HexaPDF::Type::AcroForm::Field#delete_widget] to update the wrapper object
1318
1392
  stored in the document in case the widget is embedded
1319
- * Processing of invalid PDF files containing a space,CR,LF combination after
1320
- the 'stream' keyword
1393
+ * Processing of invalid PDF files containing a space,CR,LF combination after the
1394
+ 'stream' keyword
1321
1395
  * Cross-reference stream reconstruction with respect to detection of linearized
1322
1396
  files
1323
1397
  * Detection of existing appearances for AcroForm push button fields when
@@ -1412,8 +1486,8 @@
1412
1486
 
1413
1487
  * [HexaPDF::Utils::ObjectHash#oids] to be public instead of private
1414
1488
  * Cross-reference table parsing to handle invalidly numbered main sections
1415
- * [HexaPDF::Document#cache] and [HexaPDF::Object#cache] to allow updating
1416
- values for existing keys
1489
+ * [HexaPDF::Document#cache] and [HexaPDF::Object#cache] to allow updating values
1490
+ for existing keys
1417
1491
  * Appearance creation methods of AcroForm objects to allow forcing the creation
1418
1492
  of new appearances
1419
1493
  * [HexaPDF::Type::AcroForm::AppearanceGenerator#create_text_appearances] to
@@ -1451,8 +1525,8 @@
1451
1525
  new 'parser.try_xref_reconstruction' option
1452
1526
  * Two new `hexapdf inspect` commands for showing page objects and page content
1453
1527
  streams by page number
1454
- * Flag `--check` to the CLI command `hexapdf info` for checking a file for
1455
- parse and validation errors
1528
+ * Flag `--check` to the CLI command `hexapdf info` for checking a file for parse
1529
+ and validation errors
1456
1530
  * [HexaPDF::Type::AcroForm::Field#embedded_widget?] for checking if a widget is
1457
1531
  embedded in the field object
1458
1532
  * [HexaPDF::Type::AcroForm::Field#delete_widget] for deleting a widget
@@ -1509,8 +1583,8 @@
1509
1583
 
1510
1584
  ### Added
1511
1585
 
1512
- * [HexaPDF::Font::Encoding::Base#code] for retrieving the code for a given
1513
- glyph name
1586
+ * [HexaPDF::Font::Encoding::Base#code] for retrieving the code for a given glyph
1587
+ name
1514
1588
 
1515
1589
  ### Fixed
1516
1590
 
@@ -1526,11 +1600,11 @@
1526
1600
  [HexaPDF::Type::AcroForm::Field]
1527
1601
  * [HexaPDF::Type::AcroForm::TextField] and
1528
1602
  [HexaPDF::Type::AcroForm::VariableTextField] for basic text field support
1529
- * [HexaPDF::Type::AcroForm::ButtonField] for push button, radio button and
1530
- check box support
1603
+ * [HexaPDF::Type::AcroForm::ButtonField] for push button, radio button and check
1604
+ box support
1531
1605
  * [HexaPDF::Type::AcroForm::ChoiceField] for combo box and list box support
1532
- * [HexaPDF::Type::AcroForm::AppearanceGenerator] as central class for
1533
- generating appearance streams for form fields
1606
+ * [HexaPDF::Type::AcroForm::AppearanceGenerator] as central class for generating
1607
+ appearance streams for form fields
1534
1608
  * Various convenience methods for [HexaPDF::Type::AcroForm::Form]
1535
1609
  * Various convenience methods for [HexaPDF::Type::AcroForm::Field]
1536
1610
  * Various convenience methods for [HexaPDF::Type::Annotations::Widget]
@@ -1549,8 +1623,8 @@
1549
1623
  * [HexaPDF::Type::Annotation::Border] class
1550
1624
  * [HexaPDF::Content::ColorSpace::device_color_from_specification] for easily
1551
1625
  getting a device color object
1552
- * [HexaPDF::Content::ColorSpace::prenormalized_device_color] for getting a device
1553
- color object without normalizing values
1626
+ * [HexaPDF::Content::ColorSpace::prenormalized_device_color] for getting a
1627
+ device color object without normalizing values
1554
1628
  * [HexaPDF::Type::Annotation#appearance] for returning the associated appearance
1555
1629
  dictionary
1556
1630
  * [HexaPDF::Type::Annotation#appearance?] for checking whether an appearance for
@@ -1669,8 +1743,8 @@
1669
1743
 
1670
1744
  ### Fixed
1671
1745
 
1672
- * Conversion of [HexaPDF::Rectangle] type when the original is not a plain
1673
- Array but a [HexaPDF::PDFArray]
1746
+ * Conversion of [HexaPDF::Rectangle] type when the original is not a plain Array
1747
+ but a [HexaPDF::PDFArray]
1674
1748
 
1675
1749
 
1676
1750
  ## 0.11.1 - 2019-11-19
@@ -1831,12 +1905,12 @@
1831
1905
 
1832
1906
  ### Added
1833
1907
 
1834
- * [HexaPDF::Layout::Frame] for box positioning and easier text layouting
1835
- inside an arbitrary polygon
1908
+ * [HexaPDF::Layout::Frame] for box positioning and easier text layouting inside
1909
+ an arbitrary polygon
1836
1910
  * [HexaPDF::Layout::TextBox] for displaying text in a rectangular and for
1837
1911
  flowing text inside a frame
1838
- * [HexaPDF::Layout::WidthFromPolygon] for getting a width specification from
1839
- a polygon for use with the text layouting engine
1912
+ * [HexaPDF::Layout::WidthFromPolygon] for getting a width specification from a
1913
+ polygon for use with the text layouting engine
1840
1914
  * [HexaPDF::Type::Image#width] and [HexaPDF::Type::Image#height] convenience
1841
1915
  methods
1842
1916
  * [HexaPDF::Type::FontType3] for Type 3 font support
@@ -1888,12 +1962,12 @@
1888
1962
  character in a text fragment is \r
1889
1963
  * [HexaPDF::Layout::TextLayouter] to work if an optional break point (think
1890
1964
  soft-hyphen) is followed by whitespace
1891
- * [HexaPDF::Font::TrueType::Builder] to correctly order the entries in the
1892
- table directory
1965
+ * [HexaPDF::Font::TrueType::Builder] to correctly order the entries in the table
1966
+ directory
1893
1967
  * [HexaPDF::Font::TrueType::Builder] to pad the table data to achieve the
1894
1968
  correct alignment
1895
- * [HexaPDF::Filter::FlateDecode] by removing the Zlib pools since they were
1896
- not thread safe
1969
+ * [HexaPDF::Filter::FlateDecode] by removing the Zlib pools since they were not
1970
+ thread safe
1897
1971
  * All color space classes to accept the color space definition as argument to
1898
1972
  `::new`
1899
1973
 
@@ -1925,9 +1999,8 @@
1925
1999
  * Cross-reference subsection parsing can handle missing whitespace
1926
2000
  * Renamed HexaPDF::Layout::LineFragment to [HexaPDF::Layout::Line]
1927
2001
  * Renamed HexaPDF::Layout::TextBox to [HexaPDF::Layout::TextLayouter]
1928
- * [HexaPDF::Layout::TextFragment::new] and
1929
- [HexaPDF::Layout::TextLayouter::new] to either take a Style object or
1930
- style options
2002
+ * [HexaPDF::Layout::TextFragment::new] and [HexaPDF::Layout::TextLayouter::new]
2003
+ to either take a Style object or style options
1931
2004
  * [HexaPDF::Layout::TextLayouter#fit] method signature
1932
2005
  * [HexaPDF::Layout::InlineBox] to wrap a generic box
1933
2006
  * HexaPDF::Document::Fonts#load to [HexaPDF::Document::Fonts#add] for
@@ -1989,8 +2062,8 @@
1989
2062
 
1990
2063
  * Handling of invalid glyphs is done using the special
1991
2064
  [HexaPDF::Font::InvalidGlyph] class
1992
- * Configuration option 'font.on_missing_glyph'; returns an invalid glyph
1993
- instead of raising an error
2065
+ * Configuration option 'font.on_missing_glyph'; returns an invalid glyph instead
2066
+ of raising an error
1994
2067
  * Bounding box of TrueType glyphs without contours is set to `[0, 0, 0, 0]`
1995
2068
  * Ligature pairs for AFM fonts are stored like kerning pairs
1996
2069
  * Use TrueType configuration option 'font.true_type.unknown_format' in all
@@ -2007,8 +2080,8 @@
2007
2080
 
2008
2081
  * [HexaPDF::Task::Dereference] to work correctly when encountering invalid
2009
2082
  references
2010
- * [HexaPDF::Tokenizer] and HexaPDF::Content::Tokenizer to parse a solitary
2011
- plus sign
2083
+ * [HexaPDF::Tokenizer] and HexaPDF::Content::Tokenizer to parse a solitary plus
2084
+ sign
2012
2085
  * Usage of Strings instead of Symbols for AFM font kerning and ligature pairs
2013
2086
  * Processing the contents of form XObjects in case they don't have a resources
2014
2087
  dictionary
@@ -2031,8 +2104,8 @@
2031
2104
  * CLI option `--verbose` for more verbose output; also changed the default
2032
2105
  verbosity level to only display warnings and not informational messages
2033
2106
  * CLI option `--quiet` for suppressing additional and diagnostic output
2034
- * CLI option `--strict` for enabling strict parsing and validation; also
2035
- changed the default from strict to non-strict parsing/validation
2107
+ * CLI option `--strict` for enabling strict parsing and validation; also changed
2108
+ the default from strict to non-strict parsing/validation
2036
2109
  * CLI optimization option `--optimize-fonts` for optimizing embedded fonts
2037
2110
  * Method `#word_spacing_applicable?` to font types
2038
2111
  * Support for marked-content points and sequences in [HexaPDF::Content::Canvas]
@@ -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
  #
@@ -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
@@ -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 doesn't fit on empty page"
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
@@ -182,6 +182,16 @@ module HexaPDF
182
182
  # acro_form.default_font_size::
183
183
  # A number specifying the default font size of AcroForm text fields which should be auto-sized.
184
184
  #
185
+ # acro_form.fallback_default_appearance::
186
+ # A hash containging arguments for
187
+ # HexaPDF::Type::AcroForm::VariableTextField#set_defaut_appearance_string which is used as
188
+ # fallback for fields without a default appearance.
189
+ #
190
+ # If this value is set to +nil+, an error is raised in case a variable text field cannot
191
+ # resolve a default appearance string.
192
+ #
193
+ # The default is the empty hash meaning the defaults from the method are used.
194
+ #
185
195
  # acro_form.fallback_font::
186
196
  # The font that should be used when a variable text field references a font that cannot be used.
187
197
  #
@@ -277,6 +287,13 @@ module HexaPDF
277
287
  #
278
288
  # See PDF2.0 s7.4.1, ADB sH.3 3.3
279
289
  #
290
+ # font.default::
291
+ # This font is used by the layout engine when no font is specified but one is needed.
292
+ #
293
+ # This is used, for example, for the font set on styles that don't have a font set.
294
+ #
295
+ # The default value is 'Times'.
296
+ #
280
297
  # font.fallback::
281
298
  # An array of fallback font names to be used when replacing invalid glyphs.
282
299
  #
@@ -478,6 +495,7 @@ module HexaPDF
478
495
  Configuration.new('acro_form.appearance_generator' => 'HexaPDF::Type::AcroForm::AppearanceGenerator',
479
496
  'acro_form.create_appearances' => true,
480
497
  'acro_form.default_font_size' => 10,
498
+ 'acro_form.fallback_default_appearance' => {},
481
499
  'acro_form.fallback_font' => 'Helvetica',
482
500
  'acro_form.on_invalid_value' => proc do |field, value|
483
501
  raise HexaPDF::Error, "Invalid value #{value.inspect} for " \
@@ -518,6 +536,7 @@ module HexaPDF
518
536
  Crypt: 'HexaPDF::Filter::Crypt',
519
537
  Encryption: 'HexaPDF::Filter::Encryption',
520
538
  },
539
+ 'font.default' => 'Times',
521
540
  'font.fallback' => ['ZapfDingbats', 'Symbol'],
522
541
  'font.map' => {},
523
542
  '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
- signer_info.signed_time rescue super
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
- unless key_usage && key_usage.value.split(', ').include?("Digital Signature")
106
- result.log(:error, "Certificate key usage is missing 'Digital Signature'")
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(Time.now.utc)) if signing_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))