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 +4 -4
- data/lib/pdfrb/document/encryption.rb +205 -0
- data/lib/pdfrb/document.rb +3 -0
- data/lib/pdfrb/encryption/standard_security_handler.rb +5 -1
- data/lib/pdfrb/model/type/bead.rb +56 -0
- data/lib/pdfrb/model/type/thread.rb +48 -0
- data/lib/pdfrb/model/type/trap_region.rb +25 -0
- data/lib/pdfrb/model/type/web_capture_command.rb +47 -0
- data/lib/pdfrb/model/type/web_capture_command_settings.rb +24 -0
- data/lib/pdfrb/model/type/web_capture_image_set.rb +50 -0
- data/lib/pdfrb/model/type/web_capture_page_set.rb +76 -0
- data/lib/pdfrb/model/type.rb +14 -0
- data/lib/pdfrb/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c59e3261ad38e5013f1adae6c5a5f48197ddfdc6226acd96e7fe09e6d7d9b3a5
|
|
4
|
+
data.tar.gz: f39fadf09d0a6b8ad2a401111c12384ac3a2fab66f7bbf8c40dc55cc174f1775
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/pdfrb/document.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
data/lib/pdfrb/model/type.rb
CHANGED
|
@@ -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
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.
|
|
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-
|
|
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
|