pdfrb 0.7.14 → 0.7.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29668fa0363922e98c020c762e0de36fc221ed3667407d70ab68b02bc40bf90e
4
- data.tar.gz: 10e2c7a8f2f9dd8e43b464cab777ef54e921004ae8a59b89c3c29dfd3c0823db
3
+ metadata.gz: c59e3261ad38e5013f1adae6c5a5f48197ddfdc6226acd96e7fe09e6d7d9b3a5
4
+ data.tar.gz: f39fadf09d0a6b8ad2a401111c12384ac3a2fab66f7bbf8c40dc55cc174f1775
5
5
  SHA512:
6
- metadata.gz: 5b2e9643a1eb44228dccaf6882139060297ebb0bfec23ba33f5e10303d4c477dd562a94b98bc0027ed049f99aac94bf56eae0cf19160cd37ed78825e32422d41
7
- data.tar.gz: c43041d9ca87df1184b44897a4f5456e3b252e1a3cd604d67d2b6d6d8a1e0c4d4327c6ee01a449f1f16f7b8527098f1b73b7f0132b8aa148393f484617d161e8
6
+ metadata.gz: 8cc9ef29aa8e9be785306010db555dc7bdac6ddd45c6de13107bb0cf194b5c28091d13b61a321252edc39ec41500b82eb478b338aae88480eae6c51e7861416b
7
+ data.tar.gz: 14ed721ff08a6a3fc8a6ce8cd3ced4aa09edec502c870d008aef7a9f7374cddcedf8ab4472e3d48773773e4b8530b059ed73fd42ec1ba5988af7ae2cc98cece6
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/md5"
4
+ require "securerandom"
5
+
6
+ module Pdfrb
7
+ class Document
8
+ # Encryption facade. Exposes a clean API for encrypting a
9
+ # document (builds the /Encrypt dict, wires the security handler
10
+ # into the writer config) and for checking encryption status.
11
+ #
12
+ # Usage:
13
+ # doc.encryption.encrypt!(
14
+ # user_password: "reader",
15
+ # owner_password: "owner",
16
+ # bits: 128,
17
+ # permissions: %i[print copy]
18
+ # )
19
+ # doc.write("encrypted.pdf")
20
+ class Encryption
21
+ PERMISSION_FLAGS = {
22
+ print: 1 << 2,
23
+ modify: 1 << 3,
24
+ copy: 1 << 4,
25
+ annotate: 1 << 5,
26
+ fill: 1 << 8,
27
+ extract: 1 << 9,
28
+ assemble: 1 << 10,
29
+ print_hq: 1 << 11,
30
+ }.freeze
31
+
32
+ attr_reader :document
33
+
34
+ def initialize(document)
35
+ @document = document
36
+ end
37
+
38
+ # Encrypt this document with a user + owner password.
39
+ #
40
+ # @param user_password [String] the password readers need to open.
41
+ # @param owner_password [String] the password that grants full
42
+ # permissions (defaults to user_password).
43
+ # @param bits [Integer] key length: 40, 128 (AES-128), or
44
+ # 256 (AES-256 R6).
45
+ # @param permissions [Array<Symbol>] granted permissions from
46
+ # PERMISSION_FLAGS keys; any not listed are denied.
47
+ # @return [Pdfrb::Model::Cos::Dictionary] the /Encrypt dict.
48
+ def encrypt!(user_password:, owner_password: nil, bits: 128,
49
+ permissions: PERMISSION_FLAGS.keys)
50
+ case bits
51
+ when 256 then encrypt_v5(user_password, owner_password || user_password, permissions)
52
+ when 128 then encrypt_rc4(user_password, owner_password || user_password,
53
+ permissions, v: 4, r: 4, length: 128)
54
+ when 40 then encrypt_rc4(user_password, owner_password || user_password,
55
+ permissions, v: 2, r: 3, length: 40)
56
+ else
57
+ raise Pdfrb::EncryptionError,
58
+ "unsupported key length: #{bits} (use 40, 128, or 256)"
59
+ end
60
+ end
61
+
62
+ # Whether the document has an /Encrypt dict in the trailer.
63
+ def encrypted?
64
+ trailer = document.trailer
65
+ !trailer.nil? && !trailer[:Encrypt].nil?
66
+ end
67
+
68
+ # Remove /Encrypt from the trailer (decrypt use case). Returns
69
+ # self for chaining; use encrypted? to check the result.
70
+ def decrypt!
71
+ trailer = document.trailer
72
+ if trailer && trailer[:Encrypt]
73
+ if trailer.is_a?(Pdfrb::Model::Cos::Dictionary)
74
+ trailer.value.delete(:Encrypt)
75
+ else
76
+ trailer.delete(:Encrypt)
77
+ end
78
+ document.config["encryption.handler"] = nil
79
+ document.config["encryption.password"] = nil
80
+ end
81
+ self
82
+ end
83
+
84
+ # Compute the /P integer: all bits set minus the denied ones.
85
+ def self.permission_bits(granted)
86
+ base = -1
87
+ PERMISSION_FLAGS.each do |name, bit|
88
+ base &= ~bit unless granted.include?(name)
89
+ end
90
+ base
91
+ end
92
+
93
+ private
94
+
95
+ def ensure_id!
96
+ id0 = Digest::MD5.hexdigest(Time.now.to_s + rand.to_s)[0, 16]
97
+ trailer = document.trailer
98
+ if trailer.is_a?(Pdfrb::Model::Cos::Dictionary)
99
+ trailer.value[:ID] = [id0.b, id0.b]
100
+ else
101
+ trailer[:ID] = [id0.b, id0.b]
102
+ end
103
+ id0.b
104
+ end
105
+
106
+ # RC4-based encryption for V2/V4 (40-bit or 128-bit).
107
+ def encrypt_rc4(user_pw, owner_pw, permissions, v:, r:, length:)
108
+ p_bits = self.class.permission_bits(permissions)
109
+ id0 = ensure_id!
110
+
111
+ o_entry = compute_o_entry(user_pw, owner_pw, r, length)
112
+ key = Pdfrb::Encryption::PasswordVerification.derive_key_rc4(
113
+ password: user_pw, o_entry: o_entry.b, p_flags: p_bits,
114
+ id0: id0, revision: r, key_length_bits: length,
115
+ encrypt_metadata: true
116
+ )
117
+ u_entry =
118
+ if r == 2
119
+ Pdfrb::Encryption::PasswordVerification.build_u_r2(key)
120
+ else
121
+ Pdfrb::Encryption::PasswordVerification.build_u_r3plus(
122
+ file_key: key, id0: id0, revision: r
123
+ )
124
+ end
125
+
126
+ register({ Filter: :Standard, V: v, R: r, Length: length,
127
+ P: p_bits, O: o_entry, U: u_entry },
128
+ user_password: user_pw)
129
+ end
130
+
131
+ # AES-256 R6 encryption for V5.
132
+ def encrypt_v5(user_pw, owner_pw, permissions)
133
+ p_bits = self.class.permission_bits(permissions)
134
+ id0 = ensure_id!
135
+
136
+ handler = Pdfrb::Encryption::StandardSecurityHandler.for_v5(
137
+ user_password: user_pw, owner_password: owner_pw,
138
+ permissions: p_bits, id: id0
139
+ )
140
+ dict = handler.encrypt_dict
141
+ register({ Filter: :Standard, V: dict[:V], R: dict[:R],
142
+ Length: dict[:Length], P: p_bits,
143
+ O: dict[:O], U: dict[:U], UE: dict[:UE],
144
+ OE: dict[:OE], Perms: dict[:Perms] },
145
+ user_password: user_pw,
146
+ prebuilt_handler: handler)
147
+ end
148
+
149
+ # Compute the /O entry per Algorithm 3 (owner password hash).
150
+ def compute_o_entry(user_pw, owner_pw, revision, length_bits)
151
+ require "digest/md5"
152
+ pv = Pdfrb::Encryption::PasswordVerification
153
+ padded = pv.pad_password(owner_pw)
154
+ digest = Digest::MD5.digest(padded)
155
+ if revision >= 3
156
+ 50.times do
157
+ digest = if length_bits >= 128
158
+ Digest::MD5.digest(digest[0, length_bits / 8])
159
+ else
160
+ Digest::MD5.digest(digest[0, 5])
161
+ end
162
+ end
163
+ end
164
+ rc4 = Pdfrb::Encryption::RC4Impl.new(digest[0, length_bits / 8])
165
+ o = rc4.process(pv.pad_password(user_pw))
166
+ if revision >= 3
167
+ 19.downto(1) do |i|
168
+ key = digest[0, length_bits / 8].bytes.map { |b| b ^ i }.pack("C*")
169
+ o = Pdfrb::Encryption::RC4Impl.new(key).process(o)
170
+ end
171
+ end
172
+ o
173
+ end
174
+
175
+ # Register the encrypt dict in the trailer + wire the handler.
176
+ def register(encrypt_hash, user_password:, prebuilt_handler: nil)
177
+ dict = document.add(encrypt_hash,
178
+ type: Pdfrb::Model::Type::EncryptionStandard)
179
+ ref = Pdfrb::Model::Reference.new(dict.oid, dict.gen)
180
+ trailer = document.trailer
181
+ if trailer.is_a?(Pdfrb::Model::Cos::Dictionary)
182
+ trailer.value[:Encrypt] = ref
183
+ else
184
+ trailer[:Encrypt] = ref
185
+ end
186
+
187
+ handler = prebuilt_handler || begin
188
+ h = Pdfrb::Encryption::StandardSecurityHandler.new(
189
+ { Encrypt: encrypt_hash,
190
+ ID: if trailer.is_a?(Pdfrb::Model::Cos::Dictionary)
191
+ trailer.value[:ID]
192
+ else
193
+ trailer[:ID]
194
+ end }
195
+ )
196
+ h.verify_user_password?(user_password)
197
+ h
198
+ end
199
+ document.config["encryption.handler"] = handler
200
+ document.config["encryption.password"] = user_password
201
+ dict
202
+ end
203
+ end
204
+ end
205
+ end
@@ -31,6 +31,7 @@ module Pdfrb
31
31
  autoload :Info, "pdfrb/document/info"
32
32
  autoload :PageLabels, "pdfrb/document/page_labels"
33
33
  autoload :Stamps, "pdfrb/document/stamps"
34
+ autoload :Encryption, "pdfrb/document/encryption"
34
35
 
35
36
  def initialize(io: nil, config: {})
36
37
  Pdfrb::Model::Type.eager_load!
@@ -163,6 +164,8 @@ module Pdfrb
163
164
 
164
165
  def stamps; @stamps ||= Document::Stamps.new(self); end
165
166
 
167
+ def encryption; @encryption ||= Document::Encryption.new(self); end
168
+
166
169
  def info; @info ||= Document::Info.new(self); end
167
170
 
168
171
  def display; @display ||= Document::Display.new(self); end
@@ -219,7 +219,11 @@ module Pdfrb
219
219
  hash = md5.digest
220
220
 
221
221
  rc4 = RC4Impl.new(key)
222
- 20.times { |i| hash = rc4.process(hash, key ^ i) }
222
+ 19.downto(1) do |i|
223
+ xored_key = key.bytes.map { |b| b ^ i }.pack("C*")
224
+ rc4 = RC4Impl.new(xored_key)
225
+ hash = rc4.process(hash)
226
+ end
223
227
 
224
228
  hash[0, 16]
225
229
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Bead (ISO 32000-2 §12.4.3, PDF 1.1+). A single rectangular
7
+ # portion of a page that is part of a Thread (article). Beads
8
+ # form a doubly-linked list via /N (next) and /V (previous).
9
+ class Bead < Pdfrb::Model::Cos::Dictionary
10
+ arlington_object "Bead"
11
+
12
+ # /Type — optional, fixed "Bead".
13
+ def type
14
+ value[:Type]&.to_sym
15
+ end
16
+
17
+ # /T — optional indirect Thread this bead belongs to.
18
+ def thread(document = nil)
19
+ ref = value[:T]
20
+ return nil unless ref && document
21
+
22
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
23
+ end
24
+
25
+ # /N — required indirect next Bead.
26
+ def next_bead(document = nil)
27
+ ref = value[:N]
28
+ return nil unless ref && document
29
+
30
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
31
+ end
32
+
33
+ # /V — required indirect previous Bead.
34
+ def previous_bead(document = nil)
35
+ ref = value[:V]
36
+ return nil unless ref && document
37
+
38
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
39
+ end
40
+
41
+ # /P — required indirect Page the bead sits on.
42
+ def page(document = nil)
43
+ ref = value[:P]
44
+ return nil unless ref && document
45
+
46
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
47
+ end
48
+
49
+ # /R — required rectangle on the page.
50
+ def rect
51
+ value[:R]
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Thread (ISO 32000-2 §12.4.2, PDF 1.1+). Represents an
7
+ # article — a sequence of text blocks that flows across pages
8
+ # (e.g. a newspaper column that continues on a later page).
9
+ # Threads are listed in the Catalog's /Threads array.
10
+ class Thread < Pdfrb::Model::Cos::Dictionary
11
+ arlington_object "Thread"
12
+
13
+ # /Type — optional, fixed "Thread".
14
+ def type
15
+ value[:Type]&.to_sym
16
+ end
17
+
18
+ # /F — required indirect reference to the first Bead in
19
+ # the thread.
20
+ def first_bead(document = nil)
21
+ ref = value[:F]
22
+ return nil unless ref && document
23
+
24
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
25
+ end
26
+
27
+ # /I — optional DocInfo dict with article metadata.
28
+ def info(document = nil)
29
+ ref = value[:I]
30
+ return nil unless ref && document
31
+
32
+ resolved = ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
33
+ return nil unless resolved
34
+
35
+ Pdfrb::Model::Type::Info.new(resolved.value) if resolved.value.is_a?(::Hash)
36
+ end
37
+
38
+ # /Metadata — optional indirect stream (PDF 2.0).
39
+ def metadata(document = nil)
40
+ ref = value[:Metadata]
41
+ return nil unless ref && document
42
+
43
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # TrapRegion (Adobe TechNote 5620 §5.34, PDF 1.3, deprecated
7
+ # PDF 2.0). A trapping (prepress) region on a page. Referenced
8
+ # from /Annots as /Subtype /Traps or from separation profiles.
9
+ class TrapRegion < Pdfrb::Model::Cos::Dictionary
10
+ arlington_object "TrapRegion"
11
+
12
+ # /TP — required name: trapping parameters version.
13
+ def trap_parameters
14
+ value[:TP]
15
+ end
16
+
17
+ # /TZ — optional array-of-arrays of numbers defining trap
18
+ # zones.
19
+ def trap_zones
20
+ value[:TZ]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # WebCaptureCommand (ISO 32000-1 §14.10.4, PDF 1.3, deprecated
7
+ # PDF 2.0). Describes a URL retrieval for the Web Capture
8
+ # (spider) system: what to fetch, how to fetch it, and what
9
+ # form data to post.
10
+ class WebCaptureCommand < Pdfrb::Model::Cos::Dictionary
11
+ arlington_object "WebCaptureCommand"
12
+
13
+ # /URL — required ASCII string to retrieve.
14
+ def url
15
+ value[:URL]
16
+ end
17
+
18
+ # /L — optional integer, delay before retrieval in seconds
19
+ # (default 1). Must be >= 1.
20
+ def delay_seconds
21
+ value[:L] || 1
22
+ end
23
+
24
+ # /F — optional bitmask of flags.
25
+ def flags
26
+ value[:F] || 0
27
+ end
28
+
29
+ # /CT — optional content type of posted data (RFC 2045).
30
+ def content_type
31
+ value[:CT] || "application/x-www-form-urlencoded"
32
+ end
33
+
34
+ # /S — optional WebCaptureCommandSettings dict.
35
+ def settings(document = nil)
36
+ ref = value[:S]
37
+ return nil unless ref && document
38
+
39
+ resolved = ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
40
+ return nil unless resolved
41
+
42
+ Pdfrb::Model::Type::WebCaptureCommandSettings.new(resolved.value)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # WebCaptureCommandSettings (ISO 32000-1 §14.10.4, PDF 1.3,
7
+ # deprecated PDF 2.0). Browser-like settings (get/post data,
8
+ # cookies) for a WebCaptureCommand.
9
+ class WebCaptureCommandSettings < Pdfrb::Model::Cos::Dictionary
10
+ arlington_object "WebCaptureCommandSettings"
11
+
12
+ # /G — optional GET parameters dictionary.
13
+ def get_params
14
+ value[:G]
15
+ end
16
+
17
+ # /C — optional cookie parameters dictionary.
18
+ def cookie_params
19
+ value[:C]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # WebCaptureImageSet (ISO 32000-1 §14.10.3, PDF 1.3, deprecated
7
+ # PDF 2.0). A spider content set holding captured images. The
8
+ # /O array lists image XObjects; /R gives the crawl depth for
9
+ # each image.
10
+ class WebCaptureImageSet < Pdfrb::Model::Cos::Stream
11
+ arlington_object "WebCaptureImageSet"
12
+
13
+ # /Type — optional, fixed "SpiderContentSet".
14
+ def type
15
+ value[:Type]&.to_sym
16
+ end
17
+
18
+ # /S — required, fixed "SIS" (Spider Image Set).
19
+ def set_type
20
+ value[:S]&.to_sym
21
+ end
22
+
23
+ # /ID — required unique identifier.
24
+ def set_id
25
+ value[:ID]
26
+ end
27
+
28
+ # /O — required array of indirect references to images.
29
+ def images(document = nil)
30
+ refs = value[:O]
31
+ return [] unless refs && document
32
+
33
+ arr = refs.is_a?(Pdfrb::Model::PdfArray) ? refs.value : refs
34
+ arr = [arr] unless arr.is_a?(::Array)
35
+ arr.filter_map { |r| r.is_a?(Pdfrb::Model::Reference) ? document.object(r) : r }
36
+ end
37
+
38
+ # /CT — optional content type (RFC 2045).
39
+ def content_type
40
+ value[:CT]
41
+ end
42
+
43
+ # /TS — optional date of capture.
44
+ def timestamp
45
+ value[:TS]
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # WebCapturePageSet (ISO 32000-1 §14.10.3, PDF 1.3, deprecated
7
+ # PDF 2.0). A spider content set holding captured pages. The
8
+ # /O array lists page objects converted from HTML.
9
+ class WebCapturePageSet < Pdfrb::Model::Cos::Stream
10
+ arlington_object "WebCapturePageSet"
11
+
12
+ # /Type — optional, fixed "SpiderContentSet".
13
+ def type
14
+ value[:Type]&.to_sym
15
+ end
16
+
17
+ # /S — required, fixed "SPS" (Spider Page Set).
18
+ def set_type
19
+ value[:S]&.to_sym
20
+ end
21
+
22
+ # /ID — required unique identifier.
23
+ def set_id
24
+ value[:ID]
25
+ end
26
+
27
+ # /O — required array of indirect references to pages.
28
+ def pages(document = nil)
29
+ refs = value[:O]
30
+ return [] unless refs && document
31
+
32
+ arr = refs.is_a?(Pdfrb::Model::PdfArray) ? refs.value : refs
33
+ arr = [arr] unless arr.is_a?(::Array)
34
+ arr.filter_map { |r| r.is_a?(Pdfrb::Model::Reference) ? document.object(r) : r }
35
+ end
36
+
37
+ # /CT — optional content type.
38
+ def content_type
39
+ value[:CT]
40
+ end
41
+
42
+ # /TS — optional date of capture.
43
+ def timestamp
44
+ value[:TS]
45
+ end
46
+ end
47
+
48
+ # WebCaptureInfo (ISO 32000-1 §14.10.2, PDF 1.3, deprecated
49
+ # PDF 2.0). Root dictionary for the Web Capture system, listed
50
+ # in the Catalog's /SpiderInfo key.
51
+ class WebCaptureInfo < Pdfrb::Model::Cos::Dictionary
52
+ arlington_object "WebCaptureInfo"
53
+
54
+ # /V — required version number (fixed 1).
55
+ def version
56
+ value[:V]
57
+ end
58
+
59
+ # /C — optional array of WebCaptureCommands.
60
+ def commands(document = nil)
61
+ refs = value[:C]
62
+ return [] unless refs && document
63
+
64
+ arr = refs.is_a?(Pdfrb::Model::PdfArray) ? refs.value : refs
65
+ arr = [arr] unless arr.is_a?(::Array)
66
+ arr.filter_map do |r|
67
+ resolved = r.is_a?(Pdfrb::Model::Reference) ? document.object(r) : r
68
+ next nil unless resolved && resolved.value.is_a?(::Hash)
69
+
70
+ Pdfrb::Model::Type::WebCaptureCommand.new(resolved.value)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -371,6 +371,20 @@ module Pdfrb
371
371
 
372
372
  # User property (s14.7.5).
373
373
  autoload :UserProperty, "pdfrb/model/type/user_property"
374
+
375
+ # Threads/articles (s12.4).
376
+ autoload :Thread, "pdfrb/model/type/thread"
377
+ autoload :Bead, "pdfrb/model/type/bead"
378
+
379
+ # Web Capture / spider (s14.10, PDF 1.3, deprecated 2.0).
380
+ autoload :WebCaptureInfo, "pdfrb/model/type/web_capture_page_set"
381
+ autoload :WebCaptureCommand, "pdfrb/model/type/web_capture_command"
382
+ autoload :WebCaptureCommandSettings, "pdfrb/model/type/web_capture_command_settings"
383
+ autoload :WebCaptureImageSet, "pdfrb/model/type/web_capture_image_set"
384
+ autoload :WebCapturePageSet, "pdfrb/model/type/web_capture_page_set"
385
+
386
+ # Trapping (Adobe TechNote 5620).
387
+ autoload :TrapRegion, "pdfrb/model/type/trap_region"
374
388
  end
375
389
  end
376
390
  end
data/lib/pdfrb/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pdfrb
4
- VERSION = "0.7.14"
4
+ VERSION = "0.7.16"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdfrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.14
4
+ version: 0.7.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-08-14 00:00:00.000000000 Z
11
+ date: 2026-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -817,6 +817,7 @@ files:
817
817
  - lib/pdfrb/document/colors.rb
818
818
  - lib/pdfrb/document/destinations.rb
819
819
  - lib/pdfrb/document/display.rb
820
+ - lib/pdfrb/document/encryption.rb
820
821
  - lib/pdfrb/document/files.rb
821
822
  - lib/pdfrb/document/fonts.rb
822
823
  - lib/pdfrb/document/form.rb
@@ -979,6 +980,7 @@ files:
979
980
  - lib/pdfrb/model/type/appearance_characteristics.rb
980
981
  - lib/pdfrb/model/type/appearance_generator.rb
981
982
  - lib/pdfrb/model/type/appearance_trap_net.rb
983
+ - lib/pdfrb/model/type/bead.rb
982
984
  - lib/pdfrb/model/type/border_effect.rb
983
985
  - lib/pdfrb/model/type/border_styling.rb
984
986
  - lib/pdfrb/model/type/box_color_info.rb
@@ -1132,6 +1134,7 @@ files:
1132
1134
  - lib/pdfrb/model/type/text_appearance.rb
1133
1135
  - lib/pdfrb/model/type/text_field.rb
1134
1136
  - lib/pdfrb/model/type/text_markup_annotation.rb
1137
+ - lib/pdfrb/model/type/thread.rb
1135
1138
  - lib/pdfrb/model/type/three_d_activation.rb
1136
1139
  - lib/pdfrb/model/type/three_d_animation_style.rb
1137
1140
  - lib/pdfrb/model/type/three_d_background.rb
@@ -1153,6 +1156,7 @@ files:
1153
1156
  - lib/pdfrb/model/type/timespan.rb
1154
1157
  - lib/pdfrb/model/type/to_unicode_cmap_stream.rb
1155
1158
  - lib/pdfrb/model/type/transition.rb
1159
+ - lib/pdfrb/model/type/trap_region.rb
1156
1160
  - lib/pdfrb/model/type/underline_annotation.rb
1157
1161
  - lib/pdfrb/model/type/ur_transform_parameters.rb
1158
1162
  - lib/pdfrb/model/type/uri_dict.rb
@@ -1163,6 +1167,10 @@ files:
1163
1167
  - lib/pdfrb/model/type/viewport.rb
1164
1168
  - lib/pdfrb/model/type/vri.rb
1165
1169
  - lib/pdfrb/model/type/watermark_annotation.rb
1170
+ - lib/pdfrb/model/type/web_capture_command.rb
1171
+ - lib/pdfrb/model/type/web_capture_command_settings.rb
1172
+ - lib/pdfrb/model/type/web_capture_image_set.rb
1173
+ - lib/pdfrb/model/type/web_capture_page_set.rb
1166
1174
  - lib/pdfrb/model/type/widget_annotation.rb
1167
1175
  - lib/pdfrb/model/type/widget_appearance.rb
1168
1176
  - lib/pdfrb/model/type/xobject_form.rb