prawn 1.1.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.yardopts +1 -0
- data/GPLv2 +20 -21
- data/Gemfile +3 -9
- data/Rakefile +9 -40
- data/lib/prawn/document/bounding_box.rb +54 -40
- data/lib/prawn/document/column_box.rb +8 -10
- data/lib/prawn/document/internals.rb +39 -146
- data/lib/prawn/document/span.rb +23 -17
- data/lib/prawn/document.rb +217 -182
- data/lib/prawn/encoding.rb +69 -101
- data/lib/prawn/errors.rb +47 -43
- data/lib/prawn/font.rb +124 -104
- data/lib/prawn/font_metric_cache.rb +23 -21
- data/lib/prawn/fonts/afm.rb +292 -0
- data/lib/prawn/{font → fonts}/dfont.rb +5 -12
- data/lib/prawn/fonts/otf.rb +11 -0
- data/lib/prawn/fonts/ttc.rb +36 -0
- data/lib/prawn/{font → fonts}/ttf.rb +140 -88
- data/lib/prawn/graphics/blend_mode.rb +65 -0
- data/lib/prawn/graphics/cap_style.rb +5 -5
- data/lib/prawn/graphics/color.rb +46 -44
- data/lib/prawn/graphics/dash.rb +27 -11
- data/lib/prawn/graphics/join_style.rb +11 -6
- data/lib/prawn/graphics/patterns.rb +220 -78
- data/lib/prawn/graphics/transformation.rb +20 -12
- data/lib/prawn/graphics/transparency.rb +20 -18
- data/lib/prawn/graphics.rb +153 -115
- data/lib/prawn/grid.rb +93 -50
- data/lib/prawn/image_handler.rb +4 -4
- data/lib/prawn/images/image.rb +3 -2
- data/lib/prawn/images/jpg.rb +31 -24
- data/lib/prawn/images/png.rb +101 -68
- data/lib/prawn/images.rb +64 -56
- data/lib/prawn/measurement_extensions.rb +10 -9
- data/lib/prawn/measurements.rb +20 -23
- data/lib/prawn/outline.rb +96 -75
- data/lib/prawn/repeater.rb +16 -16
- data/lib/prawn/security/arcfour.rb +2 -2
- data/lib/prawn/security.rb +100 -85
- data/lib/prawn/soft_mask.rb +37 -38
- data/lib/prawn/stamp.rb +28 -13
- data/lib/prawn/text/box.rb +24 -29
- data/lib/prawn/text/formatted/arranger.rb +108 -63
- data/lib/prawn/text/formatted/box.rb +187 -124
- data/lib/prawn/text/formatted/fragment.rb +24 -20
- data/lib/prawn/text/formatted/line_wrap.rb +133 -73
- data/lib/prawn/text/formatted/parser.rb +147 -127
- data/lib/prawn/text/formatted/wrap.rb +48 -35
- data/lib/prawn/text/formatted.rb +5 -5
- data/lib/prawn/text.rb +103 -68
- data/lib/prawn/transformation_stack.rb +44 -0
- data/lib/prawn/utilities.rb +10 -22
- data/lib/prawn/version.rb +5 -0
- data/lib/prawn/view.rb +101 -0
- data/lib/prawn.rb +39 -54
- data/manual/basic_concepts/adding_pages.rb +6 -7
- data/manual/basic_concepts/basic_concepts.rb +34 -25
- data/manual/basic_concepts/creation.rb +10 -11
- data/manual/basic_concepts/cursor.rb +4 -5
- data/manual/basic_concepts/measurement.rb +8 -9
- data/manual/basic_concepts/origin.rb +5 -6
- data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
- data/manual/basic_concepts/view.rb +48 -0
- data/manual/bounding_box/bounding_box.rb +30 -28
- data/manual/bounding_box/bounds.rb +12 -13
- data/manual/bounding_box/canvas.rb +7 -8
- data/manual/bounding_box/creation.rb +6 -7
- data/manual/bounding_box/indentation.rb +14 -15
- data/manual/bounding_box/nesting.rb +25 -18
- data/manual/bounding_box/russian_boxes.rb +18 -18
- data/manual/bounding_box/stretchy.rb +12 -14
- data/manual/contents.rb +28 -22
- data/manual/cover.rb +33 -32
- data/manual/document_and_page_options/background.rb +15 -13
- data/manual/document_and_page_options/document_and_page_options.rb +24 -22
- data/manual/document_and_page_options/metadata.rb +20 -18
- data/manual/document_and_page_options/page_margins.rb +18 -20
- data/manual/document_and_page_options/page_size.rb +13 -13
- data/manual/document_and_page_options/print_scaling.rb +18 -15
- data/manual/example_helper.rb +5 -4
- data/manual/graphics/blend_mode.rb +52 -0
- data/manual/graphics/circle_and_ellipse.rb +4 -5
- data/manual/graphics/color.rb +7 -9
- data/manual/graphics/common_lines.rb +7 -8
- data/manual/graphics/fill_and_stroke.rb +5 -6
- data/manual/graphics/fill_rules.rb +12 -11
- data/manual/graphics/gradients.rb +27 -21
- data/manual/graphics/graphics.rb +46 -40
- data/manual/graphics/helper.rb +19 -9
- data/manual/graphics/line_width.rb +8 -7
- data/manual/graphics/lines_and_curves.rb +8 -9
- data/manual/graphics/polygon.rb +6 -8
- data/manual/graphics/rectangle.rb +4 -5
- data/manual/graphics/rotate.rb +6 -9
- data/manual/graphics/scale.rb +14 -13
- data/manual/graphics/soft_masks.rb +4 -6
- data/manual/graphics/stroke_cap.rb +7 -8
- data/manual/graphics/stroke_dash.rb +15 -16
- data/manual/graphics/stroke_join.rb +6 -7
- data/manual/graphics/translate.rb +10 -10
- data/manual/graphics/transparency.rb +7 -9
- data/manual/how_to_read_this_manual.rb +8 -9
- data/manual/images/absolute_position.rb +6 -7
- data/manual/images/fit.rb +7 -8
- data/manual/images/horizontal.rb +10 -11
- data/manual/images/images.rb +28 -27
- data/manual/images/plain_image.rb +5 -6
- data/manual/images/scale.rb +9 -10
- data/manual/images/vertical.rb +16 -14
- data/manual/images/width_and_height.rb +10 -11
- data/manual/layout/boxes.rb +10 -11
- data/manual/layout/content.rb +9 -10
- data/manual/layout/layout.rb +17 -18
- data/manual/layout/simple_grid.rb +6 -7
- data/manual/outline/add_subsection_to.rb +20 -21
- data/manual/outline/insert_section_after.rb +15 -16
- data/manual/outline/outline.rb +22 -21
- data/manual/outline/sections_and_pages.rb +17 -18
- data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
- data/manual/repeatable_content/page_numbering.rb +17 -16
- data/manual/repeatable_content/repeatable_content.rb +27 -23
- data/manual/repeatable_content/repeater.rb +15 -16
- data/manual/repeatable_content/stamp.rb +14 -15
- data/manual/security/encryption.rb +8 -11
- data/manual/security/permissions.rb +20 -15
- data/manual/security/security.rb +18 -18
- data/manual/table.rb +16 -0
- data/manual/text/alignment.rb +16 -17
- data/manual/text/color.rb +12 -12
- data/manual/text/column_box.rb +9 -11
- data/manual/text/fallback_fonts.rb +25 -21
- data/manual/text/font.rb +11 -12
- data/manual/text/font_size.rb +13 -14
- data/manual/text/font_style.rb +10 -8
- data/manual/text/formatted_callbacks.rb +33 -23
- data/manual/text/formatted_text.rb +36 -25
- data/manual/text/free_flowing_text.rb +22 -23
- data/manual/text/inline.rb +18 -19
- data/manual/text/kerning_and_character_spacing.rb +14 -15
- data/manual/text/leading.rb +7 -8
- data/manual/text/line_wrapping.rb +37 -18
- data/manual/text/paragraph_indentation.rb +15 -10
- data/manual/text/positioned_text.rb +16 -17
- data/manual/text/registering_families.rb +27 -24
- data/manual/text/rendering_and_color.rb +9 -10
- data/manual/text/right_to_left_text.rb +30 -19
- data/manual/text/rotation.rb +33 -24
- data/manual/text/single_usage.rb +8 -9
- data/manual/text/text.rb +56 -54
- data/manual/text/text_box_excess.rb +20 -17
- data/manual/text/text_box_extensions.rb +18 -15
- data/manual/text/text_box_overflow.rb +24 -17
- data/manual/text/utf8.rb +12 -13
- data/manual/text/win_ansi_charset.rb +28 -25
- data/prawn.gemspec +45 -50
- data/spec/extensions/encoding_helpers.rb +3 -3
- data/spec/prawn/document/bounding_box_spec.rb +550 -0
- data/spec/prawn/document/column_box_spec.rb +75 -0
- data/spec/prawn/document/security_spec.rb +176 -0
- data/spec/prawn/document_annotations_spec.rb +76 -0
- data/spec/prawn/document_destinations_spec.rb +15 -0
- data/spec/prawn/document_grid_spec.rb +99 -0
- data/spec/prawn/document_reference_spec.rb +27 -0
- data/spec/prawn/document_span_spec.rb +44 -0
- data/spec/prawn/document_spec.rb +805 -0
- data/spec/prawn/font_metric_cache_spec.rb +54 -0
- data/spec/prawn/font_spec.rb +544 -0
- data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
- data/spec/prawn/graphics/transparency_spec.rb +81 -0
- data/spec/prawn/graphics_spec.rb +872 -0
- data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
- data/spec/prawn/image_handler_spec.rb +53 -0
- data/spec/prawn/images/jpg_spec.rb +20 -0
- data/spec/prawn/images/png_spec.rb +283 -0
- data/spec/prawn/images_spec.rb +229 -0
- data/spec/prawn/measurements_extensions_spec.rb +24 -0
- data/spec/prawn/outline_spec.rb +512 -0
- data/spec/prawn/repeater_spec.rb +166 -0
- data/spec/prawn/soft_mask_spec.rb +74 -0
- data/spec/prawn/stamp_spec.rb +173 -0
- data/spec/prawn/text/box_spec.rb +1110 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
- data/spec/prawn/text/formatted/box_spec.rb +849 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
- data/spec/prawn/text/formatted/parser_spec.rb +697 -0
- data/spec/prawn/text_draw_text_spec.rb +150 -0
- data/spec/prawn/text_rendering_mode_spec.rb +48 -0
- data/spec/prawn/text_spacing_spec.rb +95 -0
- data/spec/prawn/text_spec.rb +603 -0
- data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
- data/spec/prawn/transformation_stack_spec.rb +66 -0
- data/spec/prawn/view_spec.rb +63 -0
- data/spec/prawn_manual_spec.rb +35 -0
- data/spec/spec_helper.rb +19 -25
- data.tar.gz.sig +0 -0
- metadata +113 -276
- metadata.gz.sig +0 -0
- data/data/encodings/win_ansi.txt +0 -29
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.color +0 -0
- data/data/images/16bit.png +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.color +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/dice_interlaced.png +0 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/license.md +0 -8
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.color +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/prawn.png +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/tru256.bmp +0 -0
- data/data/images/web-links.dat +0 -1
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/form.pdf +1 -819
- data/data/pdfs/hexagon.pdf +0 -61
- data/data/pdfs/indirect_reference.pdf +0 -86
- data/data/pdfs/multipage_template.pdf +0 -127
- data/data/pdfs/nested_pages.pdf +0 -118
- data/data/pdfs/page_without_mediabox.pdf +0 -193
- data/data/pdfs/resources_as_indirect_object.pdf +0 -83
- data/data/pdfs/two_hexagons.pdf +0 -90
- data/data/pdfs/version_1_6.pdf +0 -61
- data/data/shift_jis_text.txt +0 -1
- data/lib/prawn/document/graphics_state.rb +0 -73
- data/lib/prawn/font/afm.rb +0 -247
- data/lib/prawn/table/cell/image.rb +0 -69
- data/lib/prawn/table/cell/in_table.rb +0 -33
- data/lib/prawn/table/cell/span_dummy.rb +0 -93
- data/lib/prawn/table/cell/subtable.rb +0 -66
- data/lib/prawn/table/cell/text.rb +0 -154
- data/lib/prawn/table/cell.rb +0 -772
- data/lib/prawn/table/cells.rb +0 -255
- data/lib/prawn/table/column_width_calculator.rb +0 -182
- data/lib/prawn/table.rb +0 -644
- data/manual/table/basic_block.rb +0 -53
- data/manual/table/before_rendering_page.rb +0 -26
- data/manual/table/cell_border_lines.rb +0 -24
- data/manual/table/cell_borders_and_bg.rb +0 -31
- data/manual/table/cell_dimensions.rb +0 -30
- data/manual/table/cell_text.rb +0 -38
- data/manual/table/column_widths.rb +0 -30
- data/manual/table/content_and_subtables.rb +0 -39
- data/manual/table/creation.rb +0 -27
- data/manual/table/filtering.rb +0 -36
- data/manual/table/flow_and_header.rb +0 -17
- data/manual/table/image_cells.rb +0 -33
- data/manual/table/position.rb +0 -29
- data/manual/table/row_colors.rb +0 -20
- data/manual/table/span.rb +0 -30
- data/manual/table/style.rb +0 -22
- data/manual/table/table.rb +0 -52
- data/manual/table/width.rb +0 -27
- data/spec/acceptance/png.rb +0 -25
- data/spec/annotations_spec.rb +0 -74
- data/spec/bounding_box_spec.rb +0 -510
- data/spec/cell_spec.rb +0 -629
- data/spec/column_box_spec.rb +0 -65
- data/spec/destinations_spec.rb +0 -15
- data/spec/document_spec.rb +0 -730
- data/spec/extensions/mocha.rb +0 -46
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/font_spec.rb +0 -449
- data/spec/formatted_text_arranger_spec.rb +0 -421
- data/spec/formatted_text_box_spec.rb +0 -639
- data/spec/formatted_text_fragment_spec.rb +0 -298
- data/spec/graphics_spec.rb +0 -669
- data/spec/grid_spec.rb +0 -96
- data/spec/image_handler_spec.rb +0 -54
- data/spec/images_spec.rb +0 -153
- data/spec/inline_formatted_text_parser_spec.rb +0 -564
- data/spec/jpg_spec.rb +0 -25
- data/spec/line_wrap_spec.rb +0 -344
- data/spec/measurement_units_spec.rb +0 -25
- data/spec/outline_spec.rb +0 -430
- data/spec/png_spec.rb +0 -237
- data/spec/reference_spec.rb +0 -25
- data/spec/repeater_spec.rb +0 -160
- data/spec/security_spec.rb +0 -158
- data/spec/soft_mask_spec.rb +0 -79
- data/spec/span_spec.rb +0 -44
- data/spec/stamp_spec.rb +0 -160
- data/spec/stroke_styles_spec.rb +0 -211
- data/spec/table/span_dummy_spec.rb +0 -17
- data/spec/table_spec.rb +0 -1527
- data/spec/text_at_spec.rb +0 -115
- data/spec/text_box_spec.rb +0 -1034
- data/spec/text_rendering_mode_spec.rb +0 -45
- data/spec/text_spacing_spec.rb +0 -93
- data/spec/text_spec.rb +0 -437
- data/spec/text_with_inline_formatting_spec.rb +0 -35
- data/spec/transparency_spec.rb +0 -91
data/lib/prawn/security.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# encryption.rb : Implements encrypted PDF and access permissions.
|
4
4
|
#
|
5
5
|
# Copyright August 2008, Brad Ediger. All Rights Reserved.
|
@@ -8,17 +8,13 @@
|
|
8
8
|
|
9
9
|
require 'digest/md5'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
require 'prawn/security/arcfour'
|
11
|
+
require_relative 'security/arcfour'
|
14
12
|
|
15
13
|
module Prawn
|
16
14
|
class Document
|
17
|
-
|
18
15
|
# Implements PDF encryption (password protection and permissions) as
|
19
16
|
# specified in the PDF Reference, version 1.3, section 3.5 "Encryption".
|
20
17
|
module Security
|
21
|
-
|
22
18
|
# @group Experimental API
|
23
19
|
|
24
20
|
# Encrypts the document, to protect confidential data or control
|
@@ -89,15 +85,15 @@ module Prawn
|
|
89
85
|
# not a limitation of Prawn, but is rather a built-in limitation of the
|
90
86
|
# PDF format.
|
91
87
|
#
|
92
|
-
def encrypt_document(options={})
|
93
|
-
Prawn.verify_options [
|
88
|
+
def encrypt_document(options = {})
|
89
|
+
Prawn.verify_options %i[user_password owner_password permissions],
|
94
90
|
options
|
95
|
-
@user_password = options.delete(:user_password) ||
|
91
|
+
@user_password = options.delete(:user_password) || ''
|
96
92
|
|
97
93
|
@owner_password = options.delete(:owner_password) || @user_password
|
98
94
|
if @owner_password == :random
|
99
95
|
# Generate a completely ridiculous password
|
100
|
-
@owner_password = (1..32).map{ rand(256) }.pack(
|
96
|
+
@owner_password = (1..32).map { rand(256) }.pack('c*')
|
101
97
|
end
|
102
98
|
|
103
99
|
self.permissions = options.delete(:permissions) || {}
|
@@ -113,8 +109,8 @@ module Prawn
|
|
113
109
|
# See Algorithm 3.1.
|
114
110
|
def self.encrypt_string(str, key, id, gen)
|
115
111
|
# Convert ID and Gen number into little-endian truncated byte strings
|
116
|
-
id = [id].pack('V')[0,3]
|
117
|
-
gen = [gen].pack('V')[0,2]
|
112
|
+
id = [id].pack('V')[0, 3]
|
113
|
+
gen = [gen].pack('V')[0, 2]
|
118
114
|
extended_key = "#{key}#{id}#{gen}"
|
119
115
|
|
120
116
|
# Compute the RC4 key from the extended key and perform the encryption
|
@@ -126,32 +122,41 @@ module Prawn
|
|
126
122
|
|
127
123
|
# Provides the values for the trailer encryption dictionary.
|
128
124
|
def encryption_dictionary
|
129
|
-
{
|
130
|
-
:
|
131
|
-
:
|
132
|
-
:
|
133
|
-
:
|
134
|
-
:
|
125
|
+
{
|
126
|
+
Filter: :Standard, # default PDF security handler
|
127
|
+
V: 1, # "Algorithm 3.1", PDF reference 1.3
|
128
|
+
R: 2, # Revision 2 of the algorithm
|
129
|
+
O: PDF::Core::ByteString.new(owner_password_hash),
|
130
|
+
U: PDF::Core::ByteString.new(user_password_hash),
|
131
|
+
P: permissions_value
|
132
|
+
}
|
135
133
|
end
|
136
134
|
|
137
135
|
# Flags in the permissions word, numbered as LSB = 1
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
136
|
+
PERMISSIONS_BITS = {
|
137
|
+
print_document: 3,
|
138
|
+
modify_contents: 4,
|
139
|
+
copy_contents: 5,
|
140
|
+
modify_annotations: 6
|
141
|
+
}.freeze
|
142
|
+
private_constant :PERMISSIONS_BITS
|
143
|
+
|
144
|
+
FULL_PERMISSIONS = 0b1111_1111_1111_1111_1111_1111_1111_1111
|
145
|
+
private_constant :FULL_PERMISSIONS
|
146
|
+
|
147
|
+
def permissions=(perms = {})
|
148
|
+
@permissions ||= FULL_PERMISSIONS
|
147
149
|
perms.each do |key, value|
|
148
|
-
unless
|
149
|
-
raise
|
150
|
-
|
150
|
+
unless PERMISSIONS_BITS[key]
|
151
|
+
raise(
|
152
|
+
ArgumentError,
|
153
|
+
"Unknown permission :#{key}. Valid options: " +
|
154
|
+
PERMISSIONS_BITS.keys.map(&:inspect).join(', ')
|
155
|
+
)
|
151
156
|
end
|
152
157
|
|
153
158
|
# 0-based bit number, from LSB
|
154
|
-
bit_position =
|
159
|
+
bit_position = PERMISSIONS_BITS[key] - 1
|
155
160
|
|
156
161
|
if value # set bit
|
157
162
|
@permissions |= (1 << bit_position)
|
@@ -162,44 +167,44 @@ module Prawn
|
|
162
167
|
end
|
163
168
|
|
164
169
|
def permissions_value
|
165
|
-
@permissions ||
|
170
|
+
@permissions || FULL_PERMISSIONS
|
166
171
|
end
|
167
172
|
|
168
|
-
|
169
|
-
|
170
|
-
|
173
|
+
PASSWORD_PADDING =
|
174
|
+
'28BF4E5E4E758A4164004E56FFFA01082E2E00B6D0683E802F0CA9FE6453697A'
|
175
|
+
.scan(/../).map { |x| x.to_i(16) }.pack('c*')
|
171
176
|
|
172
177
|
# Pads or truncates a password to 32 bytes as per Alg 3.2.
|
173
178
|
def pad_password(password)
|
174
179
|
password = password[0, 32]
|
175
|
-
password +
|
180
|
+
password + PASSWORD_PADDING[0, 32 - password.length]
|
176
181
|
end
|
177
182
|
|
178
183
|
def user_encryption_key
|
179
|
-
@user_encryption_key ||=
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
184
|
+
@user_encryption_key ||=
|
185
|
+
begin
|
186
|
+
md5 = Digest::MD5.new
|
187
|
+
md5 << pad_password(@user_password)
|
188
|
+
md5 << owner_password_hash
|
189
|
+
md5 << [permissions_value].pack('V')
|
190
|
+
md5.digest[0, 5]
|
191
|
+
end
|
186
192
|
end
|
187
193
|
|
188
194
|
# The O (owner) value in the encryption dictionary. Algorithm 3.3.
|
189
195
|
def owner_password_hash
|
190
|
-
@owner_password_hash ||=
|
191
|
-
|
192
|
-
|
193
|
-
|
196
|
+
@owner_password_hash ||=
|
197
|
+
begin
|
198
|
+
key = Digest::MD5.digest(pad_password(@owner_password))[0, 5]
|
199
|
+
Arcfour.new(key).encrypt(pad_password(@user_password))
|
200
|
+
end
|
194
201
|
end
|
195
202
|
|
196
203
|
# The U (user) value in the encryption dictionary. Algorithm 3.4.
|
197
204
|
def user_password_hash
|
198
|
-
Arcfour.new(user_encryption_key).encrypt(
|
205
|
+
Arcfour.new(user_encryption_key).encrypt(PASSWORD_PADDING)
|
199
206
|
end
|
200
|
-
|
201
207
|
end
|
202
|
-
|
203
208
|
end
|
204
209
|
end
|
205
210
|
|
@@ -208,56 +213,65 @@ module PDF
|
|
208
213
|
module Core
|
209
214
|
module_function
|
210
215
|
|
211
|
-
# Like
|
216
|
+
# Like pdf_object, but returns an encrypted result if required.
|
212
217
|
# For direct objects, requires the object identifier and generation number
|
213
218
|
# from the indirect object referencing obj.
|
214
219
|
#
|
215
220
|
# @private
|
216
|
-
def
|
221
|
+
def encrypted_pdf_object(obj, key, id, gen, in_content_stream = false)
|
217
222
|
case obj
|
218
223
|
when Array
|
219
|
-
|
220
|
-
|
221
|
-
|
224
|
+
array_content = obj.map do |e|
|
225
|
+
encrypted_pdf_object(e, key, id, gen, in_content_stream)
|
226
|
+
end.join(' ')
|
227
|
+
"[#{array_content}]"
|
222
228
|
when LiteralString
|
223
|
-
obj =
|
229
|
+
obj =
|
230
|
+
ByteString.new(
|
231
|
+
Prawn::Document::Security.encrypt_string(obj, key, id, gen)
|
232
|
+
).gsub(/[\\\n()]/) { |m| "\\#{m}" }
|
224
233
|
"(#{obj})"
|
225
234
|
when Time
|
226
|
-
obj = obj.strftime(
|
227
|
-
obj =
|
235
|
+
obj = "#{obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop}'00'"
|
236
|
+
obj =
|
237
|
+
ByteString.new(
|
238
|
+
Prawn::Document::Security.encrypt_string(obj, key, id, gen)
|
239
|
+
).gsub(/[\\\n()]/) { |m| "\\#{m}" }
|
228
240
|
"(#{obj})"
|
229
241
|
when String
|
230
|
-
|
242
|
+
pdf_object(
|
231
243
|
ByteString.new(
|
232
|
-
Prawn::Document::Security.encrypt_string(obj, key, id, gen)
|
233
|
-
|
244
|
+
Prawn::Document::Security.encrypt_string(obj, key, id, gen)
|
245
|
+
),
|
246
|
+
in_content_stream
|
247
|
+
)
|
234
248
|
when ::Hash
|
235
|
-
|
236
|
-
|
237
|
-
unless String === k || Symbol === k
|
249
|
+
hash_content = obj.map do |k, v|
|
250
|
+
unless k.is_a?(String) || k.is_a?(Symbol)
|
238
251
|
raise PDF::Core::Errors::FailedObjectConversion,
|
239
|
-
|
252
|
+
'A PDF Dictionary must be keyed by names'
|
240
253
|
end
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
output << ">>"
|
254
|
+
"#{pdf_object(k.to_sym, in_content_stream)} #{encrypted_pdf_object(v, key, id, gen, in_content_stream)}\n"
|
255
|
+
end.join('')
|
256
|
+
"<< #{hash_content}>>"
|
245
257
|
when NameTree::Value
|
246
|
-
|
247
|
-
EncryptedPdfObject(obj.value, key, id, gen, in_content_stream)
|
258
|
+
"#{pdf_object(obj.name)} #{encrypted_pdf_object(obj.value, key, id, gen, in_content_stream)}"
|
248
259
|
when PDF::Core::OutlineRoot, PDF::Core::OutlineItem
|
249
|
-
|
250
|
-
else # delegate back to
|
251
|
-
|
260
|
+
encrypted_pdf_object(obj.to_hash, key, id, gen, in_content_stream)
|
261
|
+
else # delegate back to pdf_object
|
262
|
+
pdf_object(obj, in_content_stream)
|
252
263
|
end
|
253
264
|
end
|
254
265
|
|
255
|
-
|
256
266
|
# @private
|
257
267
|
class Stream
|
258
268
|
def encrypted_object(key, id, gen)
|
259
269
|
if filtered_stream
|
260
|
-
"stream\n#{
|
270
|
+
"stream\n#{
|
271
|
+
Prawn::Document::Security.encrypt_string(
|
272
|
+
filtered_stream, key, id, gen
|
273
|
+
)
|
274
|
+
}\nendstream\n"
|
261
275
|
else
|
262
276
|
''
|
263
277
|
end
|
@@ -266,23 +280,24 @@ module PDF
|
|
266
280
|
|
267
281
|
# @private
|
268
282
|
class Reference
|
269
|
-
|
270
283
|
# Returns the object definition for the object this references, keyed from
|
271
284
|
# +key+.
|
272
285
|
def encrypted_object(key)
|
273
|
-
@on_encode
|
286
|
+
@on_encode&.call(self)
|
274
287
|
|
275
|
-
output = "#{@identifier} #{gen} obj\n"
|
276
|
-
|
277
|
-
output <<
|
278
|
-
|
288
|
+
output = +"#{@identifier} #{gen} obj\n"
|
289
|
+
if @stream.empty?
|
290
|
+
output <<
|
291
|
+
PDF::Core.encrypted_pdf_object(data, key, @identifier, gen) << "\n"
|
279
292
|
else
|
280
|
-
output << PDF::Core
|
293
|
+
output << PDF::Core.encrypted_pdf_object(
|
294
|
+
data.merge(@stream.data), key, @identifier, gen
|
295
|
+
) << "\n" <<
|
296
|
+
@stream.encrypted_object(key, @identifier, gen)
|
281
297
|
end
|
282
298
|
|
283
299
|
output << "endobj\n"
|
284
300
|
end
|
285
|
-
|
286
301
|
end
|
287
302
|
end
|
288
303
|
end
|
data/lib/prawn/soft_mask.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# soft_mask.rb : Implements soft-masking
|
4
4
|
#
|
5
5
|
# Copyright September 2012, Alexander Mankuta. All Rights Reserved.
|
@@ -8,7 +8,6 @@
|
|
8
8
|
#
|
9
9
|
|
10
10
|
module Prawn
|
11
|
-
|
12
11
|
# The Prawn::SoftMask module is used to create arbitrary transparency in
|
13
12
|
# document. Using a soft mask allows creating more visually rich documents.
|
14
13
|
#
|
@@ -29,59 +28,59 @@ module Prawn
|
|
29
28
|
# @group Stable API
|
30
29
|
|
31
30
|
def soft_mask(&block)
|
32
|
-
min_version(1.4)
|
31
|
+
renderer.min_version(1.4)
|
33
32
|
|
34
|
-
group_attrs = ref!(
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
39
|
-
:
|
40
|
-
|
33
|
+
group_attrs = ref!(
|
34
|
+
Type: :Group,
|
35
|
+
S: :Transparency,
|
36
|
+
CS: :DeviceRGB,
|
37
|
+
I: false,
|
38
|
+
K: false
|
39
|
+
)
|
41
40
|
|
42
|
-
group = ref!(
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
|
41
|
+
group = ref!(
|
42
|
+
Type: :XObject,
|
43
|
+
Subtype: :Form,
|
44
|
+
BBox: state.page.dimensions,
|
45
|
+
Group: group_attrs
|
46
|
+
)
|
48
47
|
|
49
48
|
state.page.stamp_stream(group, &block)
|
50
49
|
|
51
|
-
mask = ref!(
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
|
50
|
+
mask = ref!(
|
51
|
+
Type: :Mask,
|
52
|
+
S: :Luminosity,
|
53
|
+
G: group
|
54
|
+
)
|
56
55
|
|
57
|
-
g_state = ref!(
|
58
|
-
:
|
59
|
-
:
|
56
|
+
g_state = ref!(
|
57
|
+
Type: :ExtGState,
|
58
|
+
SMask: mask,
|
60
59
|
|
61
|
-
:
|
62
|
-
:
|
63
|
-
:
|
64
|
-
:
|
65
|
-
:
|
66
|
-
:
|
67
|
-
|
60
|
+
AIS: false,
|
61
|
+
BM: :Normal,
|
62
|
+
OP: false,
|
63
|
+
op: false,
|
64
|
+
OPM: 1,
|
65
|
+
SA: true
|
66
|
+
)
|
68
67
|
|
69
68
|
registry_key = {
|
70
|
-
:
|
71
|
-
:
|
72
|
-
:
|
69
|
+
bbox: state.page.dimensions,
|
70
|
+
mask: [group.stream.filters.normalized, group.stream.filtered_stream],
|
71
|
+
page: state.page_count
|
73
72
|
}.hash
|
74
73
|
|
75
74
|
if soft_mask_registry[registry_key]
|
76
|
-
add_content "/#{soft_mask_registry[registry_key]} gs"
|
75
|
+
renderer.add_content "/#{soft_mask_registry[registry_key]} gs"
|
77
76
|
else
|
78
77
|
masks = page.resources[:ExtGState] ||= {}
|
79
|
-
id = masks.empty? ? 'GS1' : masks.keys.
|
78
|
+
id = masks.empty? ? 'GS1' : masks.keys.max.succ
|
80
79
|
masks[id] = g_state
|
81
80
|
|
82
81
|
soft_mask_registry[registry_key] = id
|
83
82
|
|
84
|
-
add_content "/#{id} gs"
|
83
|
+
renderer.add_content "/#{id} gs"
|
85
84
|
end
|
86
85
|
end
|
87
86
|
|
data/lib/prawn/stamp.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# stamp.rb : Implements a repeatable stamp
|
4
4
|
#
|
5
5
|
# Copyright October 2009, Daniel Nelson. All Rights Reserved.
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
#
|
9
|
-
|
10
9
|
module Prawn
|
11
|
-
|
12
10
|
# The Prawn::Stamp module is used to create content that will be
|
13
11
|
# included multiple times in a document. Using a stamp has three
|
14
12
|
# advantages over creating content anew each time it is placed on
|
@@ -27,7 +25,6 @@ module Prawn
|
|
27
25
|
# pdf.stamp("my_stamp")
|
28
26
|
#
|
29
27
|
module Stamp
|
30
|
-
|
31
28
|
# @group Stable API
|
32
29
|
|
33
30
|
# Renders the stamp named <tt>name</tt> to the page
|
@@ -44,7 +41,8 @@ module Prawn
|
|
44
41
|
#
|
45
42
|
def stamp(name)
|
46
43
|
dictionary_name, dictionary = stamp_dictionary(name)
|
47
|
-
add_content "/#{dictionary_name} Do"
|
44
|
+
renderer.add_content "/#{dictionary_name} Do"
|
45
|
+
update_annotation_references dictionary.data[:Annots]
|
48
46
|
state.page.xobjects.merge!(dictionary_name => dictionary)
|
49
47
|
end
|
50
48
|
|
@@ -109,21 +107,39 @@ module Prawn
|
|
109
107
|
def create_stamp_dictionary(name)
|
110
108
|
raise Prawn::Errors::InvalidName if name.empty?
|
111
109
|
raise Prawn::Errors::NameTaken unless stamp_dictionary_registry[name].nil?
|
110
|
+
|
112
111
|
# BBox origin is the lower left margin of the page, so we need
|
113
112
|
# it to be the full dimension of the page, or else things that
|
114
113
|
# should appear near the top or right margin are invisible
|
115
|
-
dictionary = ref!(
|
116
|
-
|
117
|
-
|
118
|
-
|
114
|
+
dictionary = ref!(
|
115
|
+
Type: :XObject,
|
116
|
+
Subtype: :Form,
|
117
|
+
BBox: [
|
118
|
+
0, 0,
|
119
|
+
state.page.dimensions[2], state.page.dimensions[3]
|
120
|
+
]
|
121
|
+
)
|
119
122
|
|
120
123
|
dictionary_name = "Stamp#{next_stamp_dictionary_id}"
|
121
124
|
|
122
|
-
stamp_dictionary_registry[name] = {
|
123
|
-
|
125
|
+
stamp_dictionary_registry[name] = {
|
126
|
+
stamp_dictionary_name: dictionary_name,
|
127
|
+
stamp_dictionary: dictionary
|
128
|
+
}
|
124
129
|
dictionary
|
125
130
|
end
|
126
131
|
|
132
|
+
# Referencing annotations from a stamp XObject doesn't result
|
133
|
+
# in a working link. Instead, the references must be appended
|
134
|
+
# to the /Annot dictionary of the object that contains the
|
135
|
+
# call to the stamp object.
|
136
|
+
def update_annotation_references(annots)
|
137
|
+
if annots&.any?
|
138
|
+
state.page.dictionary.data[:Annots] ||= []
|
139
|
+
state.page.dictionary.data[:Annots] |= annots
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
127
143
|
def freeze_stamp_graphics
|
128
144
|
update_colors
|
129
145
|
write_line_width
|
@@ -131,6 +147,5 @@ module Prawn
|
|
131
147
|
write_stroke_join_style
|
132
148
|
write_stroke_dash
|
133
149
|
end
|
134
|
-
|
135
150
|
end
|
136
151
|
end
|
data/lib/prawn/text/box.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# text/rectangle.rb : Implements text boxes
|
4
4
|
#
|
@@ -7,7 +7,7 @@
|
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
#
|
9
9
|
|
10
|
-
require_relative
|
10
|
+
require_relative 'formatted/box'
|
11
11
|
|
12
12
|
module Prawn
|
13
13
|
module Text
|
@@ -40,6 +40,8 @@ module Prawn
|
|
40
40
|
# <tt>:character_spacing</tt>:: <tt>number</tt>. The amount of space to add
|
41
41
|
# to or remove from the default character
|
42
42
|
# spacing. [0]
|
43
|
+
# <tt>:disable_wrap_by_char</tt>:: <tt>boolean</tt> Whether
|
44
|
+
# or not to prevent mid-word breaks when text does not fit in box. [false]
|
43
45
|
# <tt>:mode</tt>:: <tt>symbol</tt>. The text rendering mode. See
|
44
46
|
# documentation for Prawn::Document#text_rendering_mode
|
45
47
|
# for a list of valid options. [:fill]
|
@@ -50,7 +52,8 @@ module Prawn
|
|
50
52
|
# <tt>[x, y]</tt>. The upper left corner of the box
|
51
53
|
# [@document.bounds.left, @document.bounds.top]
|
52
54
|
# <tt>:width</tt>::
|
53
|
-
# <tt>number</tt>. The width of the box
|
55
|
+
# <tt>number</tt>. The width of the box
|
56
|
+
# [@document.bounds.right - @at[0]]
|
54
57
|
# <tt>:height</tt>::
|
55
58
|
# <tt>number</tt>. The height of the box [default_height()]
|
56
59
|
# <tt>:direction</tt>::
|
@@ -58,7 +61,7 @@ module Prawn
|
|
58
61
|
# or right-to-left) [value of document.text_direction]
|
59
62
|
# <tt>:fallback_fonts</tt>::
|
60
63
|
# An array of font names. Each name must be the name of an AFM font or
|
61
|
-
# the name that was used to register a family of
|
64
|
+
# the name that was used to register a family of external fonts (see
|
62
65
|
# Prawn::Document#font_families). If present, then each glyph will be
|
63
66
|
# rendered using the first font that includes the glyph, starting with
|
64
67
|
# the current font and then moving through :fallback_fonts from
|
@@ -70,7 +73,6 @@ module Prawn
|
|
70
73
|
# <tt>:valign</tt>::
|
71
74
|
# <tt>:top</tt>, <tt>:center</tt>, or <tt>:bottom</tt>. Vertical
|
72
75
|
# alignment within the bounding box [:top]
|
73
|
-
#
|
74
76
|
# <tt>:rotate</tt>::
|
75
77
|
# <tt>number</tt>. The angle to rotate the text
|
76
78
|
# <tt>:rotate_around</tt>::
|
@@ -81,9 +83,8 @@ module Prawn
|
|
81
83
|
# <tt>number</tt>. Additional space between lines [value of
|
82
84
|
# document.default_leading]
|
83
85
|
# <tt>:single_line</tt>::
|
84
|
-
# <tt>boolean</tt>. If true, then only the first line will be drawn
|
85
|
-
#
|
86
|
-
# <tt>boolean</tt> [false]
|
86
|
+
# <tt>boolean</tt>. If true, then only the first line will be drawn
|
87
|
+
# [false]
|
87
88
|
# <tt>:overflow</tt>::
|
88
89
|
# <tt>:truncate</tt>, <tt>:shrink_to_fit</tt>, or <tt>:expand</tt>
|
89
90
|
# This controls the behavior when the amount of text
|
@@ -97,27 +98,24 @@ module Prawn
|
|
97
98
|
#
|
98
99
|
# Returns any text that did not print under the current settings.
|
99
100
|
#
|
100
|
-
# NOTE: if an AFM font is used, then the returned text is encoded in
|
101
|
-
# WinAnsi. Subsequent calls to text_box that pass this returned text back
|
102
|
-
# into text box must include a :skip_encoding => true option. This is
|
103
|
-
# unnecessary when using TTF fonts because those operate on UTF-8 encoding.
|
104
|
-
#
|
105
101
|
# == Exceptions
|
106
102
|
#
|
107
|
-
# Raises <tt>Prawn::
|
103
|
+
# Raises <tt>Prawn::Errors::CannotFit</tt> if not wide enough to print
|
108
104
|
# any text
|
109
105
|
#
|
110
|
-
def text_box(string, options={})
|
106
|
+
def text_box(string, options = {})
|
111
107
|
options = options.dup
|
112
108
|
options[:document] = self
|
113
109
|
|
114
|
-
box =
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
110
|
+
box =
|
111
|
+
if options[:inline_format]
|
112
|
+
p = options.delete(:inline_format)
|
113
|
+
p = [] unless p.is_a?(Array)
|
114
|
+
array = text_formatter.format(string, *p)
|
115
|
+
Text::Formatted::Box.new(array, options)
|
116
|
+
else
|
117
|
+
Text::Box.new(string, options)
|
118
|
+
end
|
121
119
|
|
122
120
|
box.render
|
123
121
|
end
|
@@ -131,17 +129,14 @@ module Prawn
|
|
131
129
|
# consumed by the printed text
|
132
130
|
#
|
133
131
|
class Box < Prawn::Text::Formatted::Box
|
134
|
-
|
135
|
-
|
136
|
-
super([{ :text => string }], options)
|
132
|
+
def initialize(string, options = {})
|
133
|
+
super([{ text: string }], options)
|
137
134
|
end
|
138
135
|
|
139
|
-
def render(flags={})
|
136
|
+
def render(flags = {})
|
140
137
|
leftover = super(flags)
|
141
|
-
leftover.
|
138
|
+
leftover.map { |hash| hash[:text] }.join
|
142
139
|
end
|
143
|
-
|
144
140
|
end
|
145
|
-
|
146
141
|
end
|
147
142
|
end
|