hexapdf 0.32.2 → 0.33.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.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -1
  3. data/README.md +9 -0
  4. data/examples/002-graphics.rb +15 -17
  5. data/examples/003-arcs.rb +9 -9
  6. data/examples/009-text_layouter_alignment.rb +1 -1
  7. data/examples/010-text_layouter_inline_boxes.rb +2 -2
  8. data/examples/011-text_layouter_line_wrapping.rb +1 -1
  9. data/examples/012-text_layouter_styling.rb +7 -7
  10. data/examples/013-text_layouter_shapes.rb +1 -1
  11. data/examples/014-text_in_polygon.rb +1 -1
  12. data/examples/015-boxes.rb +8 -7
  13. data/examples/016-frame_automatic_box_placement.rb +2 -2
  14. data/examples/017-frame_text_flow.rb +2 -1
  15. data/examples/018-composer.rb +1 -1
  16. data/examples/020-column_box.rb +2 -1
  17. data/examples/025-table_box.rb +46 -0
  18. data/lib/hexapdf/cli/command.rb +5 -2
  19. data/lib/hexapdf/cli/form.rb +5 -5
  20. data/lib/hexapdf/cli/inspect.rb +3 -3
  21. data/lib/hexapdf/composer.rb +104 -52
  22. data/lib/hexapdf/configuration.rb +44 -39
  23. data/lib/hexapdf/content/canvas.rb +393 -267
  24. data/lib/hexapdf/content/color_space.rb +72 -25
  25. data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
  26. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
  27. data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
  28. data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
  29. data/lib/hexapdf/content/graphic_object.rb +6 -7
  30. data/lib/hexapdf/content/graphics_state.rb +54 -45
  31. data/lib/hexapdf/content/operator.rb +52 -54
  32. data/lib/hexapdf/content/parser.rb +2 -2
  33. data/lib/hexapdf/content/processor.rb +15 -15
  34. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  35. data/lib/hexapdf/content.rb +5 -0
  36. data/lib/hexapdf/dictionary.rb +6 -5
  37. data/lib/hexapdf/dictionary_fields.rb +42 -14
  38. data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
  39. data/lib/hexapdf/digital_signature/handler.rb +1 -1
  40. data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
  41. data/lib/hexapdf/digital_signature/signature.rb +6 -6
  42. data/lib/hexapdf/digital_signature/signatures.rb +13 -12
  43. data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
  44. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
  45. data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
  46. data/lib/hexapdf/digital_signature/signing.rb +4 -0
  47. data/lib/hexapdf/digital_signature/verification_result.rb +2 -2
  48. data/lib/hexapdf/digital_signature.rb +7 -2
  49. data/lib/hexapdf/document/destinations.rb +12 -11
  50. data/lib/hexapdf/document/files.rb +1 -1
  51. data/lib/hexapdf/document/fonts.rb +1 -1
  52. data/lib/hexapdf/document/layout.rb +167 -39
  53. data/lib/hexapdf/document/pages.rb +3 -2
  54. data/lib/hexapdf/document.rb +89 -55
  55. data/lib/hexapdf/encryption/aes.rb +5 -5
  56. data/lib/hexapdf/encryption/arc4.rb +1 -1
  57. data/lib/hexapdf/encryption/fast_aes.rb +2 -2
  58. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  59. data/lib/hexapdf/encryption/identity.rb +1 -1
  60. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  61. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  62. data/lib/hexapdf/encryption/security_handler.rb +31 -24
  63. data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
  64. data/lib/hexapdf/encryption.rb +7 -2
  65. data/lib/hexapdf/error.rb +18 -0
  66. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  67. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  68. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  69. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  70. data/lib/hexapdf/filter/pass_through.rb +1 -1
  71. data/lib/hexapdf/filter/predictor.rb +1 -1
  72. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  73. data/lib/hexapdf/filter.rb +55 -6
  74. data/lib/hexapdf/font/cmap/parser.rb +2 -2
  75. data/lib/hexapdf/font/cmap.rb +1 -1
  76. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  77. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  78. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
  79. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  80. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  81. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
  82. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  83. data/lib/hexapdf/font/invalid_glyph.rb +3 -0
  84. data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
  85. data/lib/hexapdf/font/type1_wrapper.rb +19 -4
  86. data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
  87. data/lib/hexapdf/font_loader/from_file.rb +5 -5
  88. data/lib/hexapdf/font_loader/standard14.rb +3 -3
  89. data/lib/hexapdf/font_loader.rb +3 -0
  90. data/lib/hexapdf/image_loader/jpeg.rb +2 -2
  91. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  92. data/lib/hexapdf/image_loader/png.rb +2 -2
  93. data/lib/hexapdf/image_loader.rb +1 -1
  94. data/lib/hexapdf/importer.rb +13 -0
  95. data/lib/hexapdf/layout/box.rb +9 -2
  96. data/lib/hexapdf/layout/box_fitter.rb +2 -2
  97. data/lib/hexapdf/layout/column_box.rb +18 -4
  98. data/lib/hexapdf/layout/frame.rb +30 -12
  99. data/lib/hexapdf/layout/image_box.rb +5 -0
  100. data/lib/hexapdf/layout/inline_box.rb +1 -0
  101. data/lib/hexapdf/layout/list_box.rb +17 -1
  102. data/lib/hexapdf/layout/page_style.rb +4 -4
  103. data/lib/hexapdf/layout/style.rb +18 -3
  104. data/lib/hexapdf/layout/table_box.rb +682 -0
  105. data/lib/hexapdf/layout/text_box.rb +5 -3
  106. data/lib/hexapdf/layout/text_fragment.rb +1 -1
  107. data/lib/hexapdf/layout/text_layouter.rb +12 -4
  108. data/lib/hexapdf/layout.rb +1 -0
  109. data/lib/hexapdf/name_tree_node.rb +1 -1
  110. data/lib/hexapdf/number_tree_node.rb +1 -1
  111. data/lib/hexapdf/object.rb +18 -7
  112. data/lib/hexapdf/parser.rb +7 -7
  113. data/lib/hexapdf/pdf_array.rb +1 -1
  114. data/lib/hexapdf/rectangle.rb +1 -1
  115. data/lib/hexapdf/reference.rb +1 -1
  116. data/lib/hexapdf/revision.rb +1 -1
  117. data/lib/hexapdf/revisions.rb +3 -3
  118. data/lib/hexapdf/serializer.rb +15 -15
  119. data/lib/hexapdf/stream.rb +4 -2
  120. data/lib/hexapdf/tokenizer.rb +14 -14
  121. data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
  122. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  123. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  124. data/lib/hexapdf/type/acro_form/field.rb +2 -2
  125. data/lib/hexapdf/type/acro_form/form.rb +1 -1
  126. data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
  127. data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
  128. data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
  129. data/lib/hexapdf/type/acro_form.rb +1 -1
  130. data/lib/hexapdf/type/action.rb +1 -1
  131. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  132. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  133. data/lib/hexapdf/type/actions/launch.rb +1 -1
  134. data/lib/hexapdf/type/actions/uri.rb +1 -1
  135. data/lib/hexapdf/type/actions.rb +1 -1
  136. data/lib/hexapdf/type/annotation.rb +3 -3
  137. data/lib/hexapdf/type/annotations/link.rb +1 -1
  138. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  139. data/lib/hexapdf/type/annotations/text.rb +1 -1
  140. data/lib/hexapdf/type/annotations/widget.rb +2 -2
  141. data/lib/hexapdf/type/annotations.rb +1 -1
  142. data/lib/hexapdf/type/catalog.rb +1 -1
  143. data/lib/hexapdf/type/cid_font.rb +3 -3
  144. data/lib/hexapdf/type/embedded_file.rb +1 -1
  145. data/lib/hexapdf/type/file_specification.rb +2 -2
  146. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  147. data/lib/hexapdf/type/font_simple.rb +2 -2
  148. data/lib/hexapdf/type/font_type0.rb +3 -3
  149. data/lib/hexapdf/type/font_type3.rb +1 -1
  150. data/lib/hexapdf/type/form.rb +1 -1
  151. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  152. data/lib/hexapdf/type/icon_fit.rb +1 -1
  153. data/lib/hexapdf/type/image.rb +1 -1
  154. data/lib/hexapdf/type/info.rb +1 -1
  155. data/lib/hexapdf/type/mark_information.rb +1 -1
  156. data/lib/hexapdf/type/names.rb +2 -2
  157. data/lib/hexapdf/type/object_stream.rb +2 -1
  158. data/lib/hexapdf/type/outline.rb +1 -1
  159. data/lib/hexapdf/type/outline_item.rb +1 -1
  160. data/lib/hexapdf/type/page.rb +19 -10
  161. data/lib/hexapdf/type/page_label.rb +1 -1
  162. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  163. data/lib/hexapdf/type/resources.rb +1 -1
  164. data/lib/hexapdf/type/trailer.rb +2 -2
  165. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  166. data/lib/hexapdf/type/xref_stream.rb +2 -2
  167. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  168. data/lib/hexapdf/version.rb +1 -1
  169. data/lib/hexapdf/writer.rb +4 -4
  170. data/lib/hexapdf/xref_section.rb +2 -2
  171. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
  172. data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
  173. data/test/hexapdf/content/test_canvas.rb +0 -1
  174. data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
  175. data/test/hexapdf/document/test_files.rb +2 -2
  176. data/test/hexapdf/document/test_layout.rb +98 -0
  177. data/test/hexapdf/encryption/test_security_handler.rb +12 -11
  178. data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
  179. data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
  180. data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
  181. data/test/hexapdf/layout/test_box.rb +1 -1
  182. data/test/hexapdf/layout/test_column_box.rb +65 -21
  183. data/test/hexapdf/layout/test_frame.rb +14 -14
  184. data/test/hexapdf/layout/test_image_box.rb +4 -0
  185. data/test/hexapdf/layout/test_inline_box.rb +5 -0
  186. data/test/hexapdf/layout/test_list_box.rb +40 -6
  187. data/test/hexapdf/layout/test_page_style.rb +3 -2
  188. data/test/hexapdf/layout/test_style.rb +50 -0
  189. data/test/hexapdf/layout/test_table_box.rb +722 -0
  190. data/test/hexapdf/layout/test_text_box.rb +18 -0
  191. data/test/hexapdf/layout/test_text_layouter.rb +4 -0
  192. data/test/hexapdf/test_dictionary_fields.rb +4 -1
  193. data/test/hexapdf/test_document.rb +1 -0
  194. data/test/hexapdf/test_filter.rb +8 -0
  195. data/test/hexapdf/test_importer.rb +9 -0
  196. data/test/hexapdf/test_object.rb +16 -5
  197. data/test/hexapdf/test_stream.rb +7 -0
  198. data/test/hexapdf/test_writer.rb +3 -3
  199. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
  200. data/test/hexapdf/type/acro_form/test_form.rb +4 -3
  201. data/test/hexapdf/type/test_page.rb +18 -4
  202. metadata +17 -8
@@ -50,7 +50,12 @@ module HexaPDF
50
50
  # field object is automatically assigned a stateless converter object that knows if data read
51
51
  # from a PDF file potentially needs to be converted into a standard format before use.
52
52
  #
53
- # The methods that need to be implemented by such stateless converter objects are:
53
+ # The available converter objects can be retrieved or modified via the Field.converters method.
54
+ #
55
+ #
56
+ # == Converter Objects
57
+ #
58
+ # The methods that need to be implemented by a stateless converter objects are the following:
54
59
  #
55
60
  # usable_for?(type)::
56
61
  # Should return +true+ if the converter is usable for the given type.
@@ -63,19 +68,28 @@ module HexaPDF
63
68
  # Should return the +converted+ data if conversion is possible and +nil+ otherwise. The +type+
64
69
  # argument is the result of the Field#type method call and +document+ is the HexaPDF::Document
65
70
  # for which the data should be converted.
71
+ #
72
+ # Since a converter usually doesn't need to store any data, it can be implemented as a module
73
+ # using class methods. This is how it is done for the built-in converter objects.
66
74
  module DictionaryFields
67
75
 
68
76
  # This constant should *always* be used for boolean fields.
77
+ #
78
+ # See: PDF2.0 s7.3.2
69
79
  Boolean = [TrueClass, FalseClass].freeze
70
80
 
71
81
  # PDFByteString is used for defining fields with strings in binary encoding.
82
+ #
83
+ # See: PDF2.0 s7.9.2.4
72
84
  PDFByteString = Class.new { private_class_method :new }
73
85
 
74
86
  # PDFDate is used for defining fields which store a date object as a string.
87
+ #
88
+ # See: PDF2.0 s7.9.4
75
89
  PDFDate = Class.new { private_class_method :new }
76
90
 
77
- # A dictionary field contains information about one field of a structured PDF object and this
78
- # information comes directly from the PDF specification.
91
+ # A field contains information about one field of a structured PDF object and this information
92
+ # comes directly from the PDF specification.
79
93
  #
80
94
  # By incorporating this field information into HexaPDF it is possible to do many things
81
95
  # automatically, like checking for the correct minimum PDF version to use or converting a date
@@ -91,9 +105,9 @@ module HexaPDF
91
105
 
92
106
  # Returns the converter for the given +type+ specification.
93
107
  #
94
- # The converter list is checked for a suitable converter from the front to the back. So if
95
- # two converters could potentially be used for the same type, the one that appears earlier
96
- # is used.
108
+ # The converter list from #converters is checked for a suitable converter from the front to
109
+ # the back. So if two converters could potentially be used for the same type, the one that
110
+ # appears earlier is used.
97
111
  def self.converter_for(type)
98
112
  @converters.find {|converter| converter.usable_for?(type) }
99
113
  end
@@ -148,8 +162,7 @@ module HexaPDF
148
162
  !@default.nil?
149
163
  end
150
164
 
151
- # Returns a duplicated default value, automatically taking unduplicatable classes into
152
- # account.
165
+ # Returns a duplicated default value.
153
166
  def default
154
167
  @default.dup
155
168
  end
@@ -171,8 +184,10 @@ module HexaPDF
171
184
 
172
185
  end
173
186
 
174
- # Converter module for fields of type Dictionary and its subclasses. The first class in the
175
- # type array of the field is used for the conversion.
187
+ # Converter module for fields of type Dictionary and its subclasses.
188
+ #
189
+ # The first class in the type array of the field is used for the conversion. Symbol names for
190
+ # classes may also be used since they are automatically resolved.
176
191
  module DictionaryConverter
177
192
 
178
193
  # This converter is used when either a Symbol is provided as +type+ (for lazy loading) or
@@ -199,6 +214,8 @@ module HexaPDF
199
214
  end
200
215
 
201
216
  # Converter module for fields of type PDFArray.
217
+ #
218
+ # This converter ensures that arrays are wrapped by the PDFArray class for more convenient use.
202
219
  module ArrayConverter
203
220
 
204
221
  # This converter is usable if the +type+ is PDFArray.
@@ -220,6 +237,8 @@ module HexaPDF
220
237
  end
221
238
 
222
239
  # Converter module for string fields to automatically convert a string into UTF-8 encoding.
240
+ #
241
+ # See: PDF2.0 s7.9.2
223
242
  module StringConverter
224
243
 
225
244
  # This converter is usable if the +type+ is the String class.
@@ -231,8 +250,8 @@ module HexaPDF
231
250
  def self.additional_types
232
251
  end
233
252
 
234
- # Converts the string into UTF-8 encoding, assuming it is a binary string. Otherwise +nil+ is
235
- # returned.
253
+ # Converts the string into UTF-8 encoding, assuming it is a binary string (i.e. one not yet
254
+ # converted). Otherwise returns +nil+.
236
255
  def self.convert(str, _type, document)
237
256
  return unless str.kind_of?(String) && str.encoding == Encoding::BINARY
238
257
 
@@ -252,6 +271,8 @@ module HexaPDF
252
271
 
253
272
  # Converter module for binary string fields to automatically convert a string into binary
254
273
  # encoding.
274
+ #
275
+ # See: PDF2.0 s7.9.2.4
255
276
  module PDFByteStringConverter
256
277
 
257
278
  # This converter is usable if the +type+ is PDFByteString.
@@ -279,7 +300,7 @@ module HexaPDF
279
300
  # date format. When converting from a date string to a Time object, this is taken into
280
301
  # account.
281
302
  #
282
- # See: PDF1.7 s7.9.4, ADB1.7 3.8.3
303
+ # See: PDF2.0 s7.9.4, ADB1.7 3.8.3
283
304
  module DateConverter
284
305
 
285
306
  # This converter is usable if the +type+ is PDFDate.
@@ -297,6 +318,8 @@ module HexaPDF
297
318
 
298
319
  # Checks if the given object is a string and converts into a Time object if possible.
299
320
  # Otherwise returns +nil+.
321
+ #
322
+ # This method takes some forms of mangled date strings into account that were found in the wild.
300
323
  def self.convert(str, _type, _document)
301
324
  return unless str.kind_of?(String) && (m = str.match(DATE_RE))
302
325
 
@@ -318,6 +341,8 @@ module HexaPDF
318
341
 
319
342
  # Converter module for file specification fields. A file specification in string format is
320
343
  # converted to the corresponding file specification dictionary.
344
+ #
345
+ # See: PDF2.0 s7.11, HexaPDF::Type::FileSpecification
321
346
  module FileSpecificationConverter
322
347
 
323
348
  # This converter is only used for the :Filespec type.
@@ -343,6 +368,8 @@ module HexaPDF
343
368
  end
344
369
 
345
370
  # Converter module for fields of type Rectangle.
371
+ #
372
+ # See: PDF2.0 s7.9.5
346
373
  module RectangleConverter
347
374
 
348
375
  # This converter is usable if the +type+ is Rectangle.
@@ -355,7 +382,8 @@ module HexaPDF
355
382
  Array
356
383
  end
357
384
 
358
- # Wraps a given array in the Rectangle class. Otherwise returns +nil+.
385
+ # Wraps a given array using the Rectangle class or as a Null value if the array is invalid.
386
+ # Otherwise returns +nil+.
359
387
  def self.convert(data, _type, document)
360
388
  return unless data.kind_of?(Array) || data.kind_of?(HexaPDF::PDFArray)
361
389
  data.empty? ? document.wrap(nil) : document.wrap(data, type: Rectangle)
@@ -41,9 +41,9 @@ module HexaPDF
41
41
  module DigitalSignature
42
42
 
43
43
  # The signature handler for PKCS#7 a.k.a. CMS signatures. Those include, for example, the
44
- # adbe.pkcs7.detached sub-filter.
44
+ # adbe.pkcs7.detached and ETSI.CAdES.detached sub-filters.
45
45
  #
46
- # See: PDF1.7/2.0 s12.8.3.3
46
+ # See: PDF2.0 s12.8.3.3
47
47
  class CMSHandler < Handler
48
48
 
49
49
  # Creates a new signature handler for the given signature dictionary.
@@ -41,7 +41,7 @@ module HexaPDF
41
41
 
42
42
  # The base signature handler providing common functionality.
43
43
  #
44
- # Specific signature handler need to override methods if necessary and implement the needed
44
+ # Specific signature handlers need to override methods if necessary and implement the needed
45
45
  # ones that don't have a default implementation.
46
46
  class Handler
47
47
 
@@ -43,10 +43,9 @@ module HexaPDF
43
43
  # The signature handler for PKCS#1 based sub-filters, the only being the adbe.x509.rsa_sha1
44
44
  # sub-filter.
45
45
  #
46
- # Since PKCS#1 signatures are deprecated with PDF 2.0, the handler only provides the
47
- # implementation for reading and verifying signatures.
46
+ # Note that PKCS#1 signatures are deprecated with PDF 2.0.
48
47
  #
49
- # See: PDF1.7/2.0 s12.8.3.2
48
+ # See: PDF2.0 s12.8.3.2
50
49
  class PKCS1Handler < Handler
51
50
 
52
51
  # Returns the certificate chain.
@@ -50,10 +50,10 @@ module HexaPDF
50
50
  # differ from use-case to use-case. Therefore HexaPDF provides as much diagnostic information as
51
51
  # possible so that the user can decide whether a signature is valid.
52
52
  #
53
- # By defining a custom signature handler one is able to also customize the signature
54
- # verification.
53
+ # By defining a custom signature handler based on BaseHandler or CMSHandler one is able to also
54
+ # customize the signature verification.
55
55
  #
56
- # See: PDF1.7/2.0 s12.8.1, HexaPDF::Type::AcroForm::SignatureField
56
+ # See: PDF2.0 s12.8.1, HexaPDF::Type::AcroForm::SignatureField
57
57
  class Signature < Dictionary
58
58
 
59
59
  # Represents a transform parameters dictionary.
@@ -61,7 +61,7 @@ module HexaPDF
61
61
  # The allowed fields depend on the transform method, so not all fields are available all the
62
62
  # time.
63
63
  #
64
- # See: PDF1.7 s12.8.2.2, s12.8.2.3, s12.8.2.4
64
+ # See: PDF2.0 s12.8.2.2, s12.8.2.3, s12.8.2.4
65
65
  class TransformParams < Dictionary
66
66
 
67
67
  define_type :TransformParams
@@ -117,7 +117,7 @@ module HexaPDF
117
117
 
118
118
  # Represents a signature reference dictionary.
119
119
  #
120
- # See: PDF1.7/2.0 s12.8.1, HexaPDF::DigitalSignature::Signature
120
+ # See: PDF2.0 s12.8.1, HexaPDF::DigitalSignature::Signature
121
121
  class SignatureReference < Dictionary
122
122
 
123
123
  define_type :SigRef
@@ -202,7 +202,7 @@ module HexaPDF
202
202
  self[:Contents]
203
203
  end
204
204
 
205
- # Returns the signed data as indicated by the /ByteRange entry as byte string.
205
+ # Returns the signed data as indicated by the /ByteRange entry as binary string.
206
206
  def signed_data
207
207
  unless document.revisions.parser
208
208
  raise HexaPDF::Error, "Can't load signed data without existing PDF file"
@@ -42,7 +42,7 @@ require 'hexapdf/error'
42
42
  module HexaPDF
43
43
  module DigitalSignature
44
44
 
45
- # This class provides methods for interacting with digital signatures of a PDF file. Use it
45
+ # This class provides methods for interacting with digital signatures of a PDF file. It is used
46
46
  # through HexaPDF::Document#signatures.
47
47
  class Signatures
48
48
 
@@ -56,7 +56,7 @@ module HexaPDF
56
56
  # Creates a signing handler with the given attributes and returns it.
57
57
  #
58
58
  # A signing handler name is mapped to a class via the 'signature.signing_handler'
59
- # configuration option. The default signing handler is DefaultHandler.
59
+ # configuration option. The default signing handler is Signing::DefaultHandler.
60
60
  def signing_handler(name: :default, **attributes)
61
61
  handler = @document.config.constantize('signature.signing_handler', name) do
62
62
  raise HexaPDF::Error, "No signing handler named '#{name}' is available"
@@ -90,19 +90,12 @@ module HexaPDF
90
90
  #
91
91
  # +handler+::
92
92
  # The signing handler that provides the necessary methods for signing and adjusting the
93
- # signature and signature field objects to one's liking, see #handler and DefaultHandler.
93
+ # signature and signature field objects to one's liking, see #signing_handler and
94
+ # Signing::DefaultHandler.
94
95
  #
95
96
  # +write_options+::
96
97
  # The key-value pairs of this hash will be passed on to the HexaPDF::Document#write
97
98
  # method. Note that +incremental+ will be automatically set to ensure proper behaviour.
98
- #
99
- # The used signature object will have the following default values set:
100
- #
101
- # /Filter:: /Adobe.PPKLite
102
- # /SubFilter:: /adbe.pkcs7.detached
103
- # /M:: The current time.
104
- #
105
- # These values can be overridden in the #finalize_objects method of the signature handler.
106
99
  def add(file_or_io, handler, signature: nil, write_options: {})
107
100
  if signature && signature.type != :Sig
108
101
  signature_field = signature
@@ -123,6 +116,14 @@ module HexaPDF
123
116
  signature_field.create_widget(@document.pages[0], Rect: [0, 0, 0, 0])
124
117
  end
125
118
 
119
+ # Work-around for Adobe Acrobat to recognize images (https://stackoverflow.com/a/73011571/8203541)
120
+ signature_field.each_widget do |widget|
121
+ next unless (resources = widget.appearance&.resources)
122
+ resources[:XObject]&.each do |_name, entry|
123
+ entry[:Resources] ||= {}
124
+ end
125
+ end
126
+
126
127
  # Prepare signature object
127
128
  handler.finalize_objects(signature_field, signature)
128
129
  signature[:ByteRange] = [0, 1_000_000_000_000, 1_000_000_000_000, 1_000_000_000_000]
@@ -178,7 +179,7 @@ module HexaPDF
178
179
  # signatures.each {|signature| block } -> signatures
179
180
  # signatures.each -> Enumerator
180
181
  #
181
- # Iterates over all signatures in the order they are found.
182
+ # Iterates over all signatures in the order they are found in the PDF.
182
183
  def each
183
184
  return to_enum(__method__) unless block_given?
184
185
 
@@ -158,12 +158,18 @@ module HexaPDF
158
158
  #
159
159
  # If the certificate is provided, HexaPDF creates the signature object. Otherwise the
160
160
  # #external_signing callable object has to create it.
161
+ #
162
+ # See the class documentation section "Signing Modes" on how #certificate, #key and
163
+ # #external_signing play together.
161
164
  attr_accessor :certificate
162
165
 
163
166
  # The private key for the #certificate.
164
167
  #
165
168
  # If the key is provided, HexaPDF does the signing. Otherwise the #external_signing callable
166
169
  # object has to sign the data.
170
+ #
171
+ # See the class documentation section "Signing Modes" on how #certificate, #key and
172
+ # #external_signing play together.
167
173
  attr_accessor :key
168
174
 
169
175
  # The certificate chain that should be embedded in the PDF; usually contains all
@@ -191,21 +197,24 @@ module HexaPDF
191
197
  # * If #certificate is set and #key is not, it is just used for signing. Here it needs to
192
198
  # accept the used digest algorithm and the already digested data as arguments and return
193
199
  # the signature.
200
+ #
201
+ # Also dee the class documentation section "Signing Modes" on how #certificate, #key and
202
+ # #external_signing play together.
194
203
  attr_accessor :external_signing
195
204
 
196
- # The reason for signing. If used, will be set on the signature object.
205
+ # The reason for signing. If used, will be set on the signature dictionary.
197
206
  attr_accessor :reason
198
207
 
199
- # The signing location. If used, will be set on the signature object.
208
+ # The signing location. If used, will be set on the signature dictionary.
200
209
  attr_accessor :location
201
210
 
202
- # The contact information. If used, will be set on the signature object.
211
+ # The contact information. If used, will be set on the signature dictionary.
203
212
  attr_accessor :contact_info
204
213
 
205
214
  # The size of the serialized signature that should be reserved.
206
215
  #
207
- # If this attribute has not been set, an empty string will be signed using #sign to
208
- # determine the signature size.
216
+ # If this attribute is not set, an empty string will be signed using #sign to determine the
217
+ # signature size.
209
218
  #
210
219
  # The size needs to be at least as big as the final signature, otherwise signing results in
211
220
  # an error.
@@ -55,7 +55,7 @@ module HexaPDF
55
55
  #
56
56
  # Additionally, only RSA signatures are currently supported!
57
57
  #
58
- # See: PDF1.7/2.0 s12.8.3.3, PDF2.0 s12.8.3.4, RFC5652, ETSI TS 102 778 Parts 1-4
58
+ # See: PDF2.0 s12.8.3.3, PDF2.0 s12.8.3.4, RFC5652, ETSI TS 102 778 Parts 1-4
59
59
  class SignedDataCreator
60
60
 
61
61
  # Creates a SignedDataCreator, sets the given attributes if they are not nil and then calls
@@ -88,8 +88,6 @@ module HexaPDF
88
88
  attr_accessor :timestamp_handler
89
89
 
90
90
  # Creates a new SignedData object.
91
- #
92
- # Use the attribute accessor methods to set the required attributes.
93
91
  def initialize
94
92
  @certificate = nil
95
93
  @key = nil
@@ -170,7 +168,7 @@ module HexaPDF
170
168
 
171
169
  # Digests the data and then signs it using the assigned key, or if the key is not available,
172
170
  # by yielding to the caller.
173
- def digest_and_sign_data(data)
171
+ def digest_and_sign_data(data) #:yields: digest_algorithm, hashed_data
174
172
  hash = OpenSSL::Digest.digest(@digest_algorithm, data)
175
173
  if @key
176
174
  @key.sign_raw(@digest_algorithm, hash)
@@ -75,19 +75,19 @@ module HexaPDF
75
75
  # The size of the serialized signature that should be reserved.
76
76
  #
77
77
  # If this attribute has not been set, an empty string will be signed using #sign to
78
- # determine the signature size which will contact the TSA server
78
+ # determine the signature size. Note thtat this will contact the TSA server!
79
79
  #
80
80
  # The size needs to be at least as big as the final signature, otherwise signing results in
81
81
  # an error.
82
82
  attr_writer :signature_size
83
83
 
84
- # The reason for timestamping. If used, will be set on the signature object.
84
+ # The reason for timestamping. If used, will be set on the signature dictionary.
85
85
  attr_accessor :reason
86
86
 
87
- # The timestamping location. If used, will be set on the signature object.
87
+ # The timestamping location. If used, will be set on the signature dictionary.
88
88
  attr_accessor :location
89
89
 
90
- # The contact information. If used, will be set on the signature object.
90
+ # The contact information. If used, will be set on the signature dictionary.
91
91
  attr_accessor :contact_info
92
92
 
93
93
  # Creates a new TimestampHandler with the given attributes.
@@ -41,6 +41,10 @@ module HexaPDF
41
41
 
42
42
  # This module contains everything related to the signing of a PDF document, i.e. signing
43
43
  # handlers and the actual code for signing.
44
+ #
45
+ # * The DefaultHandler is the standard signing handler and should be sufficient for most cases.
46
+ # * The TimestampHandler is used for timestamping purposes.
47
+ # * The SignedDataCreator provides the functionality to create custom CMS signed data objects.
44
48
  module Signing
45
49
 
46
50
  autoload(:DefaultHandler, 'hexapdf/digital_signature/signing/default_handler')
@@ -37,7 +37,7 @@
37
37
  module HexaPDF
38
38
  module DigitalSignature
39
39
 
40
- # Holds the result information when verifying a signature.
40
+ # Holds the result of verifying a signature.
41
41
  class VerificationResult
42
42
 
43
43
  # :nodoc:
@@ -47,7 +47,7 @@ module HexaPDF
47
47
  error: {info: -1, warning: -1, error: 0},
48
48
  }
49
49
 
50
- # This structure represents a single status message, containing the type (:info, :warning,
50
+ # This structure represents a single status message, containing the type (:info, :warning, or
51
51
  # :error) and the content of the message.
52
52
  Message = Struct.new(:type, :content) do
53
53
  def <=>(other)
@@ -39,9 +39,14 @@ module HexaPDF
39
39
  # PDF documents can be signed using digital signatures. Such a signature can be used to
40
40
  # authenticate the identity of the signer and the contents of the documents.
41
41
  #
42
- # This module contains all code related to digital signatures in PDF.
42
+ # This module contains all code related to digital signatures in PDF:
43
43
  #
44
- # See: PDF1.7/2.0 s12.8
44
+ # * Signatures provides the convenience interface accessible via Document#signatures.
45
+ # * Signature implements the PDF signature dictionary.
46
+ # * BaseHandler, CMSHandler and PKCS1Handler are used for verifying existing signatures.
47
+ # * The Signing module implements the functionality for creating digital signatures.
48
+ #
49
+ # See: PDF2.0 s12.8
45
50
  module DigitalSignature
46
51
 
47
52
  autoload(:Signatures, 'hexapdf/digital_signature/signatures')
@@ -49,7 +49,7 @@ module HexaPDF
49
49
  # may be named and later referenced through the name. This class allows to create destinations
50
50
  # with or without a name.
51
51
  #
52
- # See: PDF1.7 s12.3.2
52
+ # See: PDF2.0 s12.3.2
53
53
  class Destinations
54
54
 
55
55
  # Wraps an explicit destination array to allow easy access to query its properties.
@@ -127,8 +127,9 @@ module HexaPDF
127
127
  destination[2..-1].all? {|item| item.nil? || item.kind_of?(Numeric) }
128
128
  end
129
129
 
130
- # Creates a new Destination for the given +destination+ which may be an explicit destination
131
- # array or a dictionary with a /D entry (as allowed for a named destination).
130
+ # Creates a new Destination for the given +destination+ specification which may be an
131
+ # explicit destination array or a dictionary with a /D entry (as allowed for a named
132
+ # destination).
132
133
  def initialize(destination)
133
134
  @destination = if destination.kind_of?(HexaPDF::Dictionary) || destination.kind_of?(Hash)
134
135
  destination[:D]
@@ -235,15 +236,15 @@ module HexaPDF
235
236
  # destinations.use_or_create(type:, page, **options) -> destination
236
237
  #
237
238
  # Uses the given destination name/array or creates a destination array based on the given
238
- # +value+.
239
+ # arguments.
239
240
  #
240
241
  # This is the main utility method for other parts of HexaPDF for getting a valid destination
241
- # array based on various different types of the given +value+:
242
+ # array based on various different types of the given arguments:
242
243
  #
243
244
  # String::
244
245
  #
245
246
  # If a string is provided, it is assumed to be a named destination. If the named
246
- # destination exists, the value itself is returned. Otherwise an error is raised.
247
+ # destination exists, the destination itself is returned. Otherwise an error is raised.
247
248
  #
248
249
  # Array::
249
250
  #
@@ -438,7 +439,7 @@ module HexaPDF
438
439
  # :call-seq:
439
440
  # destinations.add(name, destination)
440
441
  #
441
- # Adds the given +destination+ under +name+ to the destinations name tree.
442
+ # Adds the given +destination+ under +name+ (a String) to the destinations name tree.
442
443
  #
443
444
  # If the name does already exist, an error is raised.
444
445
  def add(name, destination)
@@ -448,8 +449,8 @@ module HexaPDF
448
449
  # :call-seq:
449
450
  # destinations.delete(name) -> destination
450
451
  #
451
- # Deletes the given destination from the destinations name tree and returns it or +nil+ if no
452
- # destination was registered under that name.
452
+ # Deletes the destination specified via +name+ (a String) from the destinations name tree and
453
+ # returns it or +nil+ if no destination was registered under that name.
453
454
  def delete(name)
454
455
  destinations.delete_entry(name)
455
456
  end
@@ -487,8 +488,8 @@ module HexaPDF
487
488
  # :call-seq:
488
489
  # destinations[name] -> destination
489
490
  #
490
- # Returns the destination registered under the given +name+ or +nil+ if no destination was
491
- # registered under that name.
491
+ # Returns the destination registered under the given +name+ (a String) or +nil+ if no
492
+ # destination was registered under that name.
492
493
  def [](name)
493
494
  destinations.find_entry(name)
494
495
  end
@@ -96,7 +96,7 @@ module HexaPDF
96
96
  #
97
97
  # Iterates over indirect file specification dictionaries of the PDF.
98
98
  #
99
- # By default, only the file specifications in their standard locations, namely in the
99
+ # By default, only the file specifications in their standard locations, i.e. in the
100
100
  # EmbeddedFiles name tree and in the page annotations, are returned. If the +search+ option is
101
101
  # +true+, then all indirect objects are searched for file specification dictionaries which can
102
102
  # be much slower.
@@ -53,7 +53,7 @@ module HexaPDF
53
53
  # :call-seq:
54
54
  # fonts.add(name, **options) -> font
55
55
  #
56
- # Adds the font to the document and returns it (using the loaders specified with the
56
+ # Adds the font to the document and returns it (using the font loaders specified with the
57
57
  # configuration option 'font_loaders').
58
58
  #
59
59
  # If a font with the same parameters has been loaded before, the cached font object is used.