origami 1.0.2
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.
- data/COPYING.LESSER +165 -0
- data/README +77 -0
- data/VERSION +1 -0
- data/bin/config/pdfcop.conf.yml +237 -0
- data/bin/gui/about.rb +46 -0
- data/bin/gui/config.rb +132 -0
- data/bin/gui/file.rb +385 -0
- data/bin/gui/hexdump.rb +74 -0
- data/bin/gui/hexview.rb +91 -0
- data/bin/gui/imgview.rb +72 -0
- data/bin/gui/menu.rb +392 -0
- data/bin/gui/properties.rb +132 -0
- data/bin/gui/signing.rb +635 -0
- data/bin/gui/textview.rb +107 -0
- data/bin/gui/treeview.rb +409 -0
- data/bin/gui/walker.rb +282 -0
- data/bin/gui/xrefs.rb +79 -0
- data/bin/pdf2graph +121 -0
- data/bin/pdf2ruby +353 -0
- data/bin/pdfcocoon +104 -0
- data/bin/pdfcop +455 -0
- data/bin/pdfdecompress +104 -0
- data/bin/pdfdecrypt +95 -0
- data/bin/pdfencrypt +112 -0
- data/bin/pdfextract +221 -0
- data/bin/pdfmetadata +123 -0
- data/bin/pdfsh +13 -0
- data/bin/pdfwalker +7 -0
- data/bin/shell/.irbrc +104 -0
- data/bin/shell/console.rb +136 -0
- data/bin/shell/hexdump.rb +83 -0
- data/origami.rb +36 -0
- data/origami/3d.rb +239 -0
- data/origami/acroform.rb +321 -0
- data/origami/actions.rb +299 -0
- data/origami/adobe/fdf.rb +259 -0
- data/origami/adobe/ppklite.rb +489 -0
- data/origami/annotations.rb +775 -0
- data/origami/array.rb +187 -0
- data/origami/boolean.rb +101 -0
- data/origami/catalog.rb +486 -0
- data/origami/destinations.rb +213 -0
- data/origami/dictionary.rb +188 -0
- data/origami/docmdp.rb +96 -0
- data/origami/encryption.rb +1293 -0
- data/origami/export.rb +283 -0
- data/origami/file.rb +222 -0
- data/origami/filters.rb +250 -0
- data/origami/filters/ascii.rb +189 -0
- data/origami/filters/ccitt.rb +515 -0
- data/origami/filters/crypt.rb +47 -0
- data/origami/filters/dct.rb +61 -0
- data/origami/filters/flate.rb +112 -0
- data/origami/filters/jbig2.rb +63 -0
- data/origami/filters/jpx.rb +53 -0
- data/origami/filters/lzw.rb +195 -0
- data/origami/filters/predictors.rb +276 -0
- data/origami/filters/runlength.rb +117 -0
- data/origami/font.rb +209 -0
- data/origami/functions.rb +93 -0
- data/origami/graphics.rb +33 -0
- data/origami/graphics/colors.rb +191 -0
- data/origami/graphics/instruction.rb +126 -0
- data/origami/graphics/path.rb +154 -0
- data/origami/graphics/patterns.rb +180 -0
- data/origami/graphics/state.rb +164 -0
- data/origami/graphics/text.rb +224 -0
- data/origami/graphics/xobject.rb +493 -0
- data/origami/header.rb +90 -0
- data/origami/linearization.rb +318 -0
- data/origami/metadata.rb +114 -0
- data/origami/name.rb +170 -0
- data/origami/null.rb +75 -0
- data/origami/numeric.rb +188 -0
- data/origami/obfuscation.rb +233 -0
- data/origami/object.rb +527 -0
- data/origami/outline.rb +59 -0
- data/origami/page.rb +559 -0
- data/origami/parser.rb +268 -0
- data/origami/parsers/fdf.rb +45 -0
- data/origami/parsers/pdf.rb +27 -0
- data/origami/parsers/pdf/linear.rb +113 -0
- data/origami/parsers/ppklite.rb +86 -0
- data/origami/pdf.rb +1144 -0
- data/origami/reference.rb +113 -0
- data/origami/signature.rb +474 -0
- data/origami/stream.rb +575 -0
- data/origami/string.rb +416 -0
- data/origami/trailer.rb +173 -0
- data/origami/webcapture.rb +87 -0
- data/origami/xfa.rb +3027 -0
- data/origami/xreftable.rb +447 -0
- data/templates/patterns.rb +66 -0
- data/templates/widgets.rb +173 -0
- data/templates/xdp.rb +92 -0
- data/tests/dataset/test.dummycrt +28 -0
- data/tests/dataset/test.dummykey +27 -0
- data/tests/tc_actions.rb +32 -0
- data/tests/tc_annotations.rb +85 -0
- data/tests/tc_pages.rb +37 -0
- data/tests/tc_pdfattach.rb +24 -0
- data/tests/tc_pdfencrypt.rb +110 -0
- data/tests/tc_pdfnew.rb +32 -0
- data/tests/tc_pdfparse.rb +98 -0
- data/tests/tc_pdfsig.rb +37 -0
- data/tests/tc_streams.rb +129 -0
- data/tests/ts_pdf.rb +45 -0
- metadata +193 -0
@@ -0,0 +1,113 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
reference.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
Origami is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
Origami is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
=end
|
21
|
+
|
22
|
+
module Origami
|
23
|
+
|
24
|
+
class InvalidReferenceError < Exception #:nodoc:
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Class representing a Reference Object.
|
29
|
+
# Reference are like symbolic links pointing to a particular object into the file.
|
30
|
+
#
|
31
|
+
class Reference
|
32
|
+
|
33
|
+
include Origami::Object
|
34
|
+
|
35
|
+
TOKENS = [ "(\\d+)" + WHITESPACES + "(\\d+)" + WHITESPACES + "R" ] #:nodoc:
|
36
|
+
REGEXP_TOKEN = Regexp.new(TOKENS.first, Regexp::MULTILINE)
|
37
|
+
@@regexp = Regexp.new(WHITESPACES + TOKENS.first + WHITESPACES)
|
38
|
+
|
39
|
+
attr_accessor :refno, :refgen
|
40
|
+
|
41
|
+
def initialize(refno, refgen)
|
42
|
+
@refno, @refgen = refno, refgen
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.parse(stream) #:nodoc:
|
46
|
+
|
47
|
+
offset = stream.pos
|
48
|
+
|
49
|
+
if stream.scan(@@regexp).nil?
|
50
|
+
raise InvalidReferenceError, "Bad reference to indirect objet format"
|
51
|
+
end
|
52
|
+
|
53
|
+
refno = stream[2].to_i
|
54
|
+
refgen = stream[4].to_i
|
55
|
+
|
56
|
+
ref = Reference.new(refno,refgen)
|
57
|
+
ref.file_offset = offset
|
58
|
+
|
59
|
+
ref
|
60
|
+
end
|
61
|
+
|
62
|
+
def solve
|
63
|
+
|
64
|
+
pdfdoc = self.pdf
|
65
|
+
|
66
|
+
if pdfdoc.nil?
|
67
|
+
raise InvalidReferenceError, "Not attached to any PDF"
|
68
|
+
end
|
69
|
+
|
70
|
+
target = pdfdoc.get_object(self)
|
71
|
+
|
72
|
+
if target.nil?
|
73
|
+
raise InvalidReferenceError, "Cannot resolve reference : #{self.to_s}"
|
74
|
+
end
|
75
|
+
|
76
|
+
target
|
77
|
+
end
|
78
|
+
|
79
|
+
def eql?(ref) #:nodoc
|
80
|
+
ref.is_a?(Reference) and ref.refno == @refno and ref.refgen == @refgen
|
81
|
+
end
|
82
|
+
|
83
|
+
def hash #:nodoc:
|
84
|
+
self.to_a.hash
|
85
|
+
end
|
86
|
+
|
87
|
+
def <=>(ref) #:nodoc
|
88
|
+
self.to_a <=> ref.to_a
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Returns a Ruby array with the object number and the generation this reference is pointing to.
|
93
|
+
#
|
94
|
+
def to_a
|
95
|
+
[@refno, @refgen]
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_s #:nodoc:
|
99
|
+
super("#{@refno} #{@refgen} R")
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Returns self.
|
104
|
+
#
|
105
|
+
def value
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
def real_type ; Reference end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,474 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
signature.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
Origami is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
Origami is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
=end
|
21
|
+
|
22
|
+
module Origami
|
23
|
+
|
24
|
+
class PDF
|
25
|
+
|
26
|
+
#
|
27
|
+
# Sign the document with the given key and x509 certificate.
|
28
|
+
# _certificate_:: The X509 certificate containing the public key.
|
29
|
+
# _key_:: The private key associated with the certificate.
|
30
|
+
# _ca_:: Optional CA certificates used to sign the user certificate.
|
31
|
+
#
|
32
|
+
def sign(certificate, key, ca = [], annotation = nil, location = nil, contact = nil, reason = nil)
|
33
|
+
|
34
|
+
unless Origami::OPTIONS[:use_openssl]
|
35
|
+
fail "OpenSSL is not present or has been disabled."
|
36
|
+
end
|
37
|
+
|
38
|
+
unless certificate.is_a?(OpenSSL::X509::Certificate)
|
39
|
+
raise TypeError, "A OpenSSL::X509::Certificate object must be passed."
|
40
|
+
end
|
41
|
+
|
42
|
+
unless key.is_a?(OpenSSL::PKey::RSA)
|
43
|
+
raise TypeError, "A OpenSSL::PKey::RSA object must be passed."
|
44
|
+
end
|
45
|
+
|
46
|
+
unless ca.is_a?(::Array)
|
47
|
+
raise TypeError, "Expected an Array of CA certificate."
|
48
|
+
end
|
49
|
+
|
50
|
+
unless annotation.nil? or annotation.is_a?(Annotation::Widget::Signature)
|
51
|
+
raise TypeError, "Expected a Annotation::Widget::Signature object."
|
52
|
+
end
|
53
|
+
|
54
|
+
def signfield_size(certificate, key, ca = []) #;nodoc:
|
55
|
+
datatest = "abcdefghijklmnopqrstuvwxyz"
|
56
|
+
OpenSSL::PKCS7.sign(certificate, key, datatest, ca, OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der.size + 128
|
57
|
+
end
|
58
|
+
|
59
|
+
digsig = Signature::DigitalSignature.new.set_indirect(true)
|
60
|
+
|
61
|
+
if annotation.nil?
|
62
|
+
annotation = Annotation::Widget::Signature.new
|
63
|
+
annotation.Rect = Rectangle[:llx => 0.0, :lly => 0.0, :urx => 0.0, :ury => 0.0]
|
64
|
+
end
|
65
|
+
|
66
|
+
annotation.V = digsig ;
|
67
|
+
add_fields(annotation)
|
68
|
+
self.Catalog.AcroForm.SigFlags = InteractiveForm::SigFlags::SIGNATURESEXIST | InteractiveForm::SigFlags::APPENDONLY
|
69
|
+
|
70
|
+
digsig.Type = :Sig #:nodoc:
|
71
|
+
digsig.Contents = HexaString.new("\x00" * signfield_size(certificate, key, ca)) #:nodoc:
|
72
|
+
digsig.Filter = Name.new("Adobe.PPKMS") #:nodoc:
|
73
|
+
digsig.SubFilter = Name.new("adbe.pkcs7.detached") #:nodoc:
|
74
|
+
digsig.ByteRange = [0, 0, 0, 0] #:nodoc:
|
75
|
+
|
76
|
+
digsig.Location = HexaString.new(location) if location
|
77
|
+
digsig.ContactInfo = HexaString.new(contact) if contact
|
78
|
+
digsig.Reason = HexaString.new(reason) if reason
|
79
|
+
|
80
|
+
#
|
81
|
+
# Flattening the PDF to get file view.
|
82
|
+
#
|
83
|
+
self.compile
|
84
|
+
|
85
|
+
#
|
86
|
+
# Creating an empty Xref table to compute signature byte range.
|
87
|
+
#
|
88
|
+
rebuild_dummy_xrefs
|
89
|
+
|
90
|
+
sigoffset = get_object_offset(digsig.no, digsig.generation) + digsig.sigOffset
|
91
|
+
|
92
|
+
digsig.ByteRange[0] = 0
|
93
|
+
digsig.ByteRange[1] = sigoffset
|
94
|
+
digsig.ByteRange[2] = sigoffset + digsig.Contents.size
|
95
|
+
|
96
|
+
digsig.ByteRange[3] = filesize - digsig.ByteRange[2] until digsig.ByteRange[3] == filesize - digsig.ByteRange[2]
|
97
|
+
|
98
|
+
# From that point the file size remains constant
|
99
|
+
|
100
|
+
#
|
101
|
+
# Correct Xrefs variations caused by ByteRange modifications.
|
102
|
+
#
|
103
|
+
rebuildxrefs
|
104
|
+
|
105
|
+
filedata = self.to_bin
|
106
|
+
signable_data = filedata[digsig.ByteRange[0],digsig.ByteRange[1]] + filedata[digsig.ByteRange[2],digsig.ByteRange[3]]
|
107
|
+
|
108
|
+
signature = OpenSSL::PKCS7.sign(certificate, key, signable_data, ca, OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der
|
109
|
+
digsig.Contents[0, signature.size] = signature
|
110
|
+
|
111
|
+
#
|
112
|
+
# No more modification are allowed after signing.
|
113
|
+
#
|
114
|
+
self.freeze
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Returns whether the document contains a digital signature.
|
119
|
+
#
|
120
|
+
def is_signed?
|
121
|
+
not self.Catalog.AcroForm.nil? and
|
122
|
+
self.Catalog.AcroForm.has_key?(:SigFlags) and
|
123
|
+
(self.Catalog.AcroForm[:SigFlags].solve & InteractiveForm::SigFlags::SIGNATURESEXIST != 0)
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# Enable the document Usage Rights.
|
128
|
+
# _rights_:: list of rights defined in UsageRights::Rights
|
129
|
+
#
|
130
|
+
def enable_usage_rights(cert, pkey, *rights)
|
131
|
+
|
132
|
+
def signfield_size(certificate, key, ca = []) #:nodoc:
|
133
|
+
datatest = "abcdefghijklmnopqrstuvwxyz"
|
134
|
+
OpenSSL::PKCS7.sign(certificate, key, datatest, ca, OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der.size + 128
|
135
|
+
end
|
136
|
+
|
137
|
+
unless Origami::OPTIONS[:use_openssl]
|
138
|
+
fail "OpenSSL is not present or has been disabled."
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# Load key pair
|
143
|
+
#
|
144
|
+
key = pkey.is_a?(OpenSSL::PKey::RSA) ? pkey : OpenSSL::PKey::RSA.new(pkey)
|
145
|
+
certificate = cert.is_a?(OpenSSL::X509::Certificate) ? cert : OpenSSL::X509::Certificate.new(cert)
|
146
|
+
|
147
|
+
#
|
148
|
+
# Forge digital signature dictionary
|
149
|
+
#
|
150
|
+
digsig = Signature::DigitalSignature.new.set_indirect(true)
|
151
|
+
|
152
|
+
self.Catalog.AcroForm ||= InteractiveForm.new
|
153
|
+
#self.Catalog.AcroForm.SigFlags = InteractiveForm::SigFlags::APPENDONLY
|
154
|
+
|
155
|
+
digsig.Type = :Sig #:nodoc:
|
156
|
+
digsig.Contents = HexaString.new("\x00" * signfield_size(certificate, key, [])) #:nodoc:
|
157
|
+
digsig.Filter = Name.new("Adobe.PPKLite") #:nodoc:
|
158
|
+
digsig.Name = "ARE Acrobat Product v8.0 P23 0002337" #:nodoc:
|
159
|
+
digsig.SubFilter = Name.new("adbe.pkcs7.detached") #:nodoc:
|
160
|
+
digsig.ByteRange = [0, 0, 0, 0] #:nodoc:
|
161
|
+
|
162
|
+
sigref = Signature::Reference.new #:nodoc:
|
163
|
+
sigref.Type = :SigRef #:nodoc:
|
164
|
+
sigref.TransformMethod = :UR3 #:nodoc:
|
165
|
+
sigref.Data = self.Catalog
|
166
|
+
|
167
|
+
sigref.TransformParams = UsageRights::TransformParams.new
|
168
|
+
sigref.TransformParams.P = true #:nodoc:
|
169
|
+
sigref.TransformParams.Type = :TransformParams #:nodoc:
|
170
|
+
sigref.TransformParams.V = UsageRights::TransformParams::VERSION
|
171
|
+
|
172
|
+
rights.each do |right|
|
173
|
+
sigref.TransformParams[right.first] ||= []
|
174
|
+
sigref.TransformParams[right.first].concat(right[1..-1])
|
175
|
+
end
|
176
|
+
|
177
|
+
digsig.Reference = [ sigref ]
|
178
|
+
|
179
|
+
self.Catalog.Perms ||= Perms.new
|
180
|
+
self.Catalog.Perms.UR3 = digsig
|
181
|
+
|
182
|
+
#
|
183
|
+
# Flattening the PDF to get file view.
|
184
|
+
#
|
185
|
+
self.compile
|
186
|
+
|
187
|
+
#
|
188
|
+
# Creating an empty Xref table to compute signature byte range.
|
189
|
+
#
|
190
|
+
rebuild_dummy_xrefs
|
191
|
+
|
192
|
+
sigoffset = get_object_offset(digsig.no, digsig.generation) + digsig.sigOffset
|
193
|
+
|
194
|
+
digsig.ByteRange[0] = 0
|
195
|
+
digsig.ByteRange[1] = sigoffset
|
196
|
+
digsig.ByteRange[2] = sigoffset + digsig.Contents.size
|
197
|
+
|
198
|
+
digsig.ByteRange[3] = filesize - digsig.ByteRange[2] until digsig.ByteRange[3] == filesize - digsig.ByteRange[2]
|
199
|
+
|
200
|
+
# From that point the file size remains constant
|
201
|
+
|
202
|
+
#
|
203
|
+
# Correct Xrefs variations caused by ByteRange modifications.
|
204
|
+
#
|
205
|
+
rebuildxrefs
|
206
|
+
|
207
|
+
filedata = self.to_bin
|
208
|
+
signable_data = filedata[digsig.ByteRange[0],digsig.ByteRange[1]] + filedata[digsig.ByteRange[2],digsig.ByteRange[3]]
|
209
|
+
|
210
|
+
signature = OpenSSL::PKCS7.sign(certificate, key, signable_data, [], OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der
|
211
|
+
digsig.Contents[0, signature.size] = signature
|
212
|
+
|
213
|
+
#
|
214
|
+
# No more modification are allowed after signing.
|
215
|
+
#
|
216
|
+
self.freeze
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
def has_usage_rights?
|
221
|
+
not self.Catalog.Perms.nil? and (not self.Catalog.Perms.has_key?(:UR3) or not self.Catalog.Perms.has_key?(:UR))
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
class Perms < Dictionary
|
227
|
+
|
228
|
+
include StandardObject
|
229
|
+
|
230
|
+
field :DocMDP, :Type => Dictionary
|
231
|
+
field :UR, :Type => Dictionary
|
232
|
+
field :UR3, :Type => Dictionary, :Version => "1.6"
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
module Signature
|
237
|
+
|
238
|
+
#
|
239
|
+
# Class representing a digital signature.
|
240
|
+
#
|
241
|
+
class DigitalSignature < Dictionary
|
242
|
+
|
243
|
+
include StandardObject
|
244
|
+
|
245
|
+
field :Type, :Type => Name, :Default => :Sig
|
246
|
+
field :Filter, :Type => Name, :Default => "Adobe.PPKMS".to_sym, :Required => true
|
247
|
+
field :SubFilter, :Type => Name
|
248
|
+
field :Contents, :Type => String, :Required => true
|
249
|
+
field :Cert, :Type => [ Array, String ]
|
250
|
+
field :ByteRange, :Type => Array
|
251
|
+
field :Reference, :Type => Array, :Version => "1.5"
|
252
|
+
field :Changes, :Type => Array
|
253
|
+
field :Name, :Type => String
|
254
|
+
field :M, :Type => String
|
255
|
+
field :Location, :Type => String
|
256
|
+
field :Reason, :Type => String
|
257
|
+
field :ContactInfo, :Type => String
|
258
|
+
field :R, :Type => Integer
|
259
|
+
field :V, :Type => Integer, :Default => 0, :Version => "1.5"
|
260
|
+
field :Prop_Build, :Type => Dictionary, :Version => "1.5"
|
261
|
+
field :Prop_AuthTime, :Type => Integer, :Version => "1.5"
|
262
|
+
field :Prop_AuthType, :Type => Name, :Version => "1.5"
|
263
|
+
|
264
|
+
def pre_build #:nodoc:
|
265
|
+
self.M = Origami::Date.now
|
266
|
+
self.Prop_Build ||= BuildProperties.new.pre_build
|
267
|
+
|
268
|
+
super
|
269
|
+
end
|
270
|
+
|
271
|
+
def to_s(dummy_param = nil) #:nodoc:
|
272
|
+
indent = 1
|
273
|
+
pairs = self.to_a
|
274
|
+
content = TOKENS.first + EOL
|
275
|
+
|
276
|
+
pairs.sort_by{ |k| k.to_s }.reverse.each do |pair|
|
277
|
+
key, value = pair[0].to_o, pair[1].to_o
|
278
|
+
|
279
|
+
content << "\t" * indent + key.to_s + " " + (value.is_a?(Dictionary) ? value.to_s(indent + 1) : value.to_s) + EOL
|
280
|
+
end
|
281
|
+
|
282
|
+
content << "\t" * (indent - 1) + TOKENS.last
|
283
|
+
|
284
|
+
output(content)
|
285
|
+
end
|
286
|
+
|
287
|
+
def sigOffset #:nodoc:
|
288
|
+
base = 1
|
289
|
+
pairs = self.to_a
|
290
|
+
content = "#{no} #{generation} obj" + EOL + TOKENS.first + EOL
|
291
|
+
|
292
|
+
pairs.sort_by{ |k| k.to_s }.reverse.each do |pair|
|
293
|
+
key, value = pair[0].to_o, pair[1].to_o
|
294
|
+
|
295
|
+
if key == :Contents
|
296
|
+
content << "\t" * base + key.to_s + " "
|
297
|
+
|
298
|
+
return content.size
|
299
|
+
else
|
300
|
+
content << "\t" * base + key.to_s + " " + (value.is_a?(Dictionary) ? value.to_s(base+1) : value.to_s) + EOL
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
nil
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
#
|
310
|
+
# Class representing a signature which can be embedded in DigitalSignature dictionary.
|
311
|
+
# It must be a direct object.
|
312
|
+
#
|
313
|
+
class Reference < Dictionary
|
314
|
+
|
315
|
+
include StandardObject
|
316
|
+
|
317
|
+
field :Type, :Type => Name, :Default => :SigRef
|
318
|
+
field :TransformMethod, :Type => Name, :Default => :DocMDP, :Required => true
|
319
|
+
field :TransformParams, :Type => Dictionary
|
320
|
+
field :Data, :Type => Object
|
321
|
+
field :DigestMethod, :Type => Name, :Default => :MD5
|
322
|
+
field :DigestValue, :Type => String
|
323
|
+
field :DigestLocation, :Type => Array
|
324
|
+
|
325
|
+
def initialize(hash = {})
|
326
|
+
set_indirect(false)
|
327
|
+
|
328
|
+
super(hash)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
class BuildProperties < Dictionary
|
333
|
+
|
334
|
+
include StandardObject
|
335
|
+
|
336
|
+
field :Filter, :Type => Dictionary, :Version => "1.5"
|
337
|
+
field :PubSec, :Type => Dictionary, :Version => "1.5"
|
338
|
+
field :App, :Type => Dictionary, :Version => "1.5"
|
339
|
+
field :SigQ, :Type => Dictionary, :Version => "1.7"
|
340
|
+
|
341
|
+
def initialize(hash = {})
|
342
|
+
set_indirect(false)
|
343
|
+
|
344
|
+
super(hash)
|
345
|
+
end
|
346
|
+
|
347
|
+
def pre_build #:nodoc:
|
348
|
+
|
349
|
+
self.Filter ||= BuildData.new
|
350
|
+
self.Filter.Name ||= Name.new("Adobe.PPKMS")
|
351
|
+
self.Filter.R ||= 0x2001D
|
352
|
+
self.Filter.Date ||= Time.now.to_s
|
353
|
+
|
354
|
+
self.SigQ ||= SigQData.new
|
355
|
+
self.SigQ.Preview ||= false
|
356
|
+
self.SigQ.R ||= 0x2001D
|
357
|
+
|
358
|
+
self.PubSec ||= BuildData.new
|
359
|
+
self.PubSec.NonEFontNoWarn ||= false
|
360
|
+
self.PubSec.Date ||= Time.now.to_s
|
361
|
+
self.PubSec.R ||= 0x2001D
|
362
|
+
|
363
|
+
self.App ||= AppData.new
|
364
|
+
self.App.TrustedMode ||= false
|
365
|
+
self.App.OS ||= [ :Win ]
|
366
|
+
self.App.R ||= 0x70000
|
367
|
+
self.App.Name ||= Name.new("Exchange-Pro")
|
368
|
+
|
369
|
+
super
|
370
|
+
end
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
class BuildData < Dictionary
|
375
|
+
|
376
|
+
include StandardObject
|
377
|
+
|
378
|
+
field :Name, :Type => Name, :Version => "1.5"
|
379
|
+
field :Date, :Type => String, :Version => "1.5"
|
380
|
+
field :R, :Type => Number, :Version => "1.5"
|
381
|
+
field :PreRelease, :Type => Boolean, :Default => false, :Version => "1.5"
|
382
|
+
field :OS, :Type => Array, :Version => "1.5"
|
383
|
+
field :NonEFontNoWarn, :Type => Boolean, :Version => "1.5"
|
384
|
+
field :TrustedMode, :Type => Boolean, :Version => "1.5"
|
385
|
+
field :V, :Type => Number, :Version => "1.5"
|
386
|
+
|
387
|
+
def initialize(hash = {})
|
388
|
+
set_indirect(false)
|
389
|
+
|
390
|
+
super(hash)
|
391
|
+
end
|
392
|
+
|
393
|
+
end
|
394
|
+
|
395
|
+
class AppData < BuildData
|
396
|
+
field :REx, :Type => String, :Version => "1.6"
|
397
|
+
end
|
398
|
+
|
399
|
+
class SigQData < BuildData
|
400
|
+
field :Preview, :Type => Boolean, :Default => false, :Version => "1.7"
|
401
|
+
end
|
402
|
+
|
403
|
+
end
|
404
|
+
|
405
|
+
module UsageRights
|
406
|
+
|
407
|
+
module Rights
|
408
|
+
|
409
|
+
DOCUMENT_FULLSAVE = [:Document, :FullSave]
|
410
|
+
DOCUMENT_ALL = DOCUMENT_FULLSAVE
|
411
|
+
|
412
|
+
ANNOTS_CREATE = [:Annots, :Create]
|
413
|
+
ANNOTS_DELETE = [:Annots, :Delete]
|
414
|
+
ANNOTS_MODIFY = [:Annots, :Modify]
|
415
|
+
ANNOTS_COPY = [:Annots, :Copy]
|
416
|
+
ANNOTS_IMPORT = [:Annots, :Import]
|
417
|
+
ANNOTS_EXPORT = [:Annots, :Export]
|
418
|
+
ANNOTS_ONLINE = [:Annots, :Online]
|
419
|
+
ANNOTS_SUMMARYVIEW = [:Annots, :SummaryView]
|
420
|
+
ANNOTS_ALL = [ :Annots, :Create, :Modify, :Copy, :Import, :Export, :Online, :SummaryView ]
|
421
|
+
|
422
|
+
FORM_FILLIN = [:Form, :FillIn]
|
423
|
+
FORM_IMPORT = [:Form, :Import]
|
424
|
+
FORM_EXPORT = [:Form, :Export]
|
425
|
+
FORM_SUBMITSTANDALONE = [:Form, :SubmitStandAlone]
|
426
|
+
FORM_SPAWNTEMPLATE = [:Form, :SpawnTemplate]
|
427
|
+
FORM_BARCODEPLAINTEXT = [:Form, :BarcodePlaintext]
|
428
|
+
FORM_ONLINE = [:Form, :Online]
|
429
|
+
FORM_ALL = [:Form, :FillIn, :Import, :Export, :SubmitStandAlone, :SpawnTemplate, :BarcodePlaintext, :Online]
|
430
|
+
|
431
|
+
FORMEX_BARCODEPLAINTEXT = [:FormEx, :BarcodePlaintext]
|
432
|
+
FORMEX_ALL = FORMEX_BARCODEPLAINTEXT
|
433
|
+
|
434
|
+
SIGNATURE_MODIFY = [:Signature, :Modify]
|
435
|
+
SIGNATURE_ALL = SIGNATURE_MODIFY
|
436
|
+
|
437
|
+
EF_CREATE = [:EF, :Create]
|
438
|
+
EF_DELETE = [:EF, :Delete]
|
439
|
+
EF_MODIFY = [:EF, :Modify]
|
440
|
+
EF_IMPORT = [:EF, :Import]
|
441
|
+
EF_ALL = [:EF, :Create, :Delete, :Modify, :Import]
|
442
|
+
|
443
|
+
ALL = [ DOCUMENT_ALL, ANNOTS_ALL, FORM_ALL, SIGNATURE_ALL, EF_ALL ]
|
444
|
+
|
445
|
+
end
|
446
|
+
|
447
|
+
class TransformParams < Dictionary
|
448
|
+
|
449
|
+
include StandardObject
|
450
|
+
|
451
|
+
VERSION = Name.new("2.2")
|
452
|
+
|
453
|
+
field :Type, :Type => Name, :Default => :TransformParams
|
454
|
+
field :Document, :Type => Array
|
455
|
+
field :Msg, :Type => String
|
456
|
+
field :V, :Type => Name, :Default => VERSION
|
457
|
+
field :Annots, :Type => Array
|
458
|
+
field :Form, :Type => Array
|
459
|
+
field :FormEx, :Type => Array
|
460
|
+
field :Signature, :Type => Array
|
461
|
+
field :EF, :Type => Array, :Version => "1.6"
|
462
|
+
field :P, :Type => Boolean, :Default => false, :Version => "1.6"
|
463
|
+
|
464
|
+
def initialize(hash = {})
|
465
|
+
set_indirect(false)
|
466
|
+
|
467
|
+
super(hash)
|
468
|
+
end
|
469
|
+
|
470
|
+
end
|
471
|
+
|
472
|
+
end
|
473
|
+
|
474
|
+
end
|