origamindee 3.0.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 +7 -0
- data/CHANGELOG.md +89 -0
- data/COPYING.LESSER +165 -0
- data/README.md +131 -0
- data/bin/config/pdfcop.conf.yml +236 -0
- data/bin/pdf2pdfa +87 -0
- data/bin/pdf2ruby +333 -0
- data/bin/pdfcop +476 -0
- data/bin/pdfdecompress +97 -0
- data/bin/pdfdecrypt +91 -0
- data/bin/pdfencrypt +113 -0
- data/bin/pdfexplode +223 -0
- data/bin/pdfextract +277 -0
- data/bin/pdfmetadata +143 -0
- data/bin/pdfsh +12 -0
- data/bin/shell/console.rb +128 -0
- data/bin/shell/hexdump.rb +59 -0
- data/bin/shell/irbrc +69 -0
- data/examples/README.md +34 -0
- data/examples/attachments/attachment.rb +38 -0
- data/examples/attachments/nested_document.rb +51 -0
- data/examples/encryption/encryption.rb +28 -0
- data/examples/events/events.rb +72 -0
- data/examples/flash/flash.rb +37 -0
- data/examples/flash/helloworld.swf +0 -0
- data/examples/forms/javascript.rb +54 -0
- data/examples/forms/xfa.rb +115 -0
- data/examples/javascript/hello_world.rb +22 -0
- data/examples/javascript/js_emulation.rb +54 -0
- data/examples/loop/goto.rb +32 -0
- data/examples/loop/named.rb +33 -0
- data/examples/signature/signature.rb +65 -0
- data/examples/uri/javascript.rb +56 -0
- data/examples/uri/open-uri.rb +21 -0
- data/examples/uri/submitform.rb +47 -0
- data/lib/origami/3d.rb +364 -0
- data/lib/origami/acroform.rb +321 -0
- data/lib/origami/actions.rb +318 -0
- data/lib/origami/annotations.rb +711 -0
- data/lib/origami/array.rb +242 -0
- data/lib/origami/boolean.rb +90 -0
- data/lib/origami/catalog.rb +418 -0
- data/lib/origami/collections.rb +144 -0
- data/lib/origami/compound.rb +161 -0
- data/lib/origami/destinations.rb +252 -0
- data/lib/origami/dictionary.rb +192 -0
- data/lib/origami/encryption.rb +1084 -0
- data/lib/origami/extensions/fdf.rb +347 -0
- data/lib/origami/extensions/ppklite.rb +422 -0
- data/lib/origami/filespec.rb +197 -0
- data/lib/origami/filters/ascii.rb +211 -0
- data/lib/origami/filters/ccitt/tables.rb +267 -0
- data/lib/origami/filters/ccitt.rb +357 -0
- data/lib/origami/filters/crypt.rb +38 -0
- data/lib/origami/filters/dct.rb +54 -0
- data/lib/origami/filters/flate.rb +69 -0
- data/lib/origami/filters/jbig2.rb +57 -0
- data/lib/origami/filters/jpx.rb +47 -0
- data/lib/origami/filters/lzw.rb +170 -0
- data/lib/origami/filters/predictors.rb +292 -0
- data/lib/origami/filters/runlength.rb +129 -0
- data/lib/origami/filters.rb +364 -0
- data/lib/origami/font.rb +196 -0
- data/lib/origami/functions.rb +79 -0
- data/lib/origami/graphics/colors.rb +230 -0
- data/lib/origami/graphics/instruction.rb +98 -0
- data/lib/origami/graphics/path.rb +182 -0
- data/lib/origami/graphics/patterns.rb +174 -0
- data/lib/origami/graphics/render.rb +62 -0
- data/lib/origami/graphics/state.rb +149 -0
- data/lib/origami/graphics/text.rb +225 -0
- data/lib/origami/graphics/xobject.rb +918 -0
- data/lib/origami/graphics.rb +38 -0
- data/lib/origami/header.rb +75 -0
- data/lib/origami/javascript.rb +713 -0
- data/lib/origami/linearization.rb +330 -0
- data/lib/origami/metadata.rb +172 -0
- data/lib/origami/name.rb +135 -0
- data/lib/origami/null.rb +65 -0
- data/lib/origami/numeric.rb +181 -0
- data/lib/origami/obfuscation.rb +245 -0
- data/lib/origami/object.rb +760 -0
- data/lib/origami/optionalcontent.rb +183 -0
- data/lib/origami/outline.rb +54 -0
- data/lib/origami/outputintents.rb +85 -0
- data/lib/origami/page.rb +722 -0
- data/lib/origami/parser.rb +269 -0
- data/lib/origami/parsers/fdf.rb +56 -0
- data/lib/origami/parsers/pdf/lazy.rb +176 -0
- data/lib/origami/parsers/pdf/linear.rb +122 -0
- data/lib/origami/parsers/pdf.rb +118 -0
- data/lib/origami/parsers/ppklite.rb +57 -0
- data/lib/origami/pdf.rb +1108 -0
- data/lib/origami/reference.rb +134 -0
- data/lib/origami/signature.rb +702 -0
- data/lib/origami/stream.rb +705 -0
- data/lib/origami/string.rb +444 -0
- data/lib/origami/template/patterns.rb +56 -0
- data/lib/origami/template/widgets.rb +151 -0
- data/lib/origami/trailer.rb +190 -0
- data/lib/origami/tree.rb +62 -0
- data/lib/origami/version.rb +23 -0
- data/lib/origami/webcapture.rb +100 -0
- data/lib/origami/xfa/config.rb +453 -0
- data/lib/origami/xfa/connectionset.rb +146 -0
- data/lib/origami/xfa/datasets.rb +49 -0
- data/lib/origami/xfa/localeset.rb +42 -0
- data/lib/origami/xfa/package.rb +59 -0
- data/lib/origami/xfa/pdf.rb +73 -0
- data/lib/origami/xfa/signature.rb +42 -0
- data/lib/origami/xfa/sourceset.rb +43 -0
- data/lib/origami/xfa/stylesheet.rb +44 -0
- data/lib/origami/xfa/template.rb +1691 -0
- data/lib/origami/xfa/xdc.rb +42 -0
- data/lib/origami/xfa/xfa.rb +146 -0
- data/lib/origami/xfa/xfdf.rb +43 -0
- data/lib/origami/xfa/xmpmeta.rb +43 -0
- data/lib/origami/xfa.rb +62 -0
- data/lib/origami/xreftable.rb +557 -0
- data/lib/origami.rb +47 -0
- data/test/dataset/calc.pdf +85 -0
- data/test/dataset/crypto.pdf +36 -0
- data/test/dataset/empty.pdf +49 -0
- data/test/test_actions.rb +27 -0
- data/test/test_annotations.rb +68 -0
- data/test/test_forms.rb +30 -0
- data/test/test_native_types.rb +83 -0
- data/test/test_object_tree.rb +33 -0
- data/test/test_pages.rb +60 -0
- data/test/test_pdf.rb +20 -0
- data/test/test_pdf_attachment.rb +34 -0
- data/test/test_pdf_create.rb +24 -0
- data/test/test_pdf_encrypt.rb +102 -0
- data/test/test_pdf_parse.rb +134 -0
- data/test/test_pdf_parse_lazy.rb +69 -0
- data/test/test_pdf_sign.rb +97 -0
- data/test/test_streams.rb +184 -0
- data/test/test_xrefs.rb +67 -0
- metadata +280 -0
@@ -0,0 +1,347 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
4
|
+
Copyright (C) 2016 Guillaume Delugré.
|
5
|
+
|
6
|
+
Origami is free software: you can redistribute it and/or modify
|
7
|
+
it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
9
|
+
(at your option) any later version.
|
10
|
+
|
11
|
+
Origami is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU Lesser General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU Lesser General Public License
|
17
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
=end
|
20
|
+
|
21
|
+
require 'origami/object'
|
22
|
+
require 'origami/name'
|
23
|
+
require 'origami/dictionary'
|
24
|
+
require 'origami/reference'
|
25
|
+
require 'origami/boolean'
|
26
|
+
require 'origami/numeric'
|
27
|
+
require 'origami/string'
|
28
|
+
require 'origami/array'
|
29
|
+
require 'origami/trailer'
|
30
|
+
require 'origami/xreftable'
|
31
|
+
|
32
|
+
require 'origami/parsers/fdf'
|
33
|
+
|
34
|
+
module Origami
|
35
|
+
|
36
|
+
#
|
37
|
+
# Class representing an AcroForm Forms Data Format file.
|
38
|
+
#
|
39
|
+
class FDF
|
40
|
+
|
41
|
+
def self.read(path, options = {})
|
42
|
+
path = File.expand_path(path) if path.is_a?(::String)
|
43
|
+
|
44
|
+
FDF::Parser.new(options).parse(path)
|
45
|
+
end
|
46
|
+
|
47
|
+
class Header
|
48
|
+
MAGIC = /%FDF-(?<major>\d)\.(?<minor>\d)/
|
49
|
+
|
50
|
+
attr_accessor :major_version, :minor_version
|
51
|
+
|
52
|
+
#
|
53
|
+
# Creates a file header, with the given major and minor versions.
|
54
|
+
# _major_version_:: Major version.
|
55
|
+
# _minor_version_:: Minor version.
|
56
|
+
#
|
57
|
+
def initialize(major_version = 1, minor_version = 2)
|
58
|
+
@major_version, @minor_version = major_version, minor_version
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.parse(stream) #:nodoc:
|
62
|
+
scanner = Parser.init_scanner(stream)
|
63
|
+
|
64
|
+
if not scanner.scan(MAGIC).nil?
|
65
|
+
maj = scanner['major'].to_i
|
66
|
+
min = scanner['minor'].to_i
|
67
|
+
else
|
68
|
+
raise InvalidHeader, "Invalid header format"
|
69
|
+
end
|
70
|
+
|
71
|
+
scanner.skip(REGEXP_WHITESPACES)
|
72
|
+
|
73
|
+
FDF::Header.new(maj, min)
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_s(eol: $/)
|
77
|
+
"%FDF-#{@major_version}.#{@minor_version}".b + eol
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_sym #:nodoc:
|
81
|
+
"#{@major_version}.#{@minor_version}".to_sym
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_f #:nodoc:
|
85
|
+
to_sym.to_s.to_f
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Revision #:nodoc;
|
90
|
+
attr_accessor :document
|
91
|
+
attr_accessor :body, :xreftable
|
92
|
+
attr_reader :trailer
|
93
|
+
|
94
|
+
def initialize(fdf)
|
95
|
+
@document = fdf
|
96
|
+
@body = {}
|
97
|
+
@xreftable = nil
|
98
|
+
@trailer = nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def trailer=(trl)
|
102
|
+
trl.document = @document
|
103
|
+
@trailer = trl
|
104
|
+
end
|
105
|
+
|
106
|
+
def each_object(&b)
|
107
|
+
@body.each_value(&b)
|
108
|
+
end
|
109
|
+
|
110
|
+
def objects
|
111
|
+
@body.values
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class JavaScript < Dictionary
|
116
|
+
include StandardObject
|
117
|
+
|
118
|
+
field :Before, :Type => [ String, Stream ]
|
119
|
+
field :After, :Type => [ String, Stream ]
|
120
|
+
field :AfterPermsReady, :Type => [ String, Stream ]
|
121
|
+
field :Doc, :Type => Array.of(Name, String)
|
122
|
+
end
|
123
|
+
|
124
|
+
class IconFit < Dictionary
|
125
|
+
include StandardObject
|
126
|
+
|
127
|
+
ALWAYS_SCALE = :A
|
128
|
+
SCALE_WHEN_BIGGER = :B
|
129
|
+
SCALE_WHEN_SMALLER = :S
|
130
|
+
NEVER_SCALE = :N
|
131
|
+
|
132
|
+
field :SW, :Type => Name
|
133
|
+
field :S, :Type => Name
|
134
|
+
field :A, :Type => Array.of(Number, length: 2)
|
135
|
+
field :FB, :Type => Boolean
|
136
|
+
end
|
137
|
+
|
138
|
+
class NamedPageReference < Dictionary
|
139
|
+
include StandardObject
|
140
|
+
|
141
|
+
field :Name, :Type => String, :Required => true
|
142
|
+
field :F, :Type => FileSpec
|
143
|
+
end
|
144
|
+
|
145
|
+
class Field < Dictionary
|
146
|
+
include StandardObject
|
147
|
+
|
148
|
+
field :Kids, :Type => Array.of(Field)
|
149
|
+
field :T, :Type => String, :Required => true
|
150
|
+
field :V, :Type => Dictionary
|
151
|
+
field :Ff, :Type => Integer
|
152
|
+
field :SetFf, :Type => Integer
|
153
|
+
field :ClrFf, :Type => Integer
|
154
|
+
field :F, :Type => Integer
|
155
|
+
field :SetF, :Type => Integer
|
156
|
+
field :ClrF, :Type => Integer
|
157
|
+
field :AP, :Type => Annotation::AppearanceDictionary
|
158
|
+
field :APRef, :Type => Dictionary
|
159
|
+
field :IF, :Type => IconFit
|
160
|
+
field :Opt, :Type => Array.of([String, Array.of(String, String)])
|
161
|
+
field :A, :Type => Action
|
162
|
+
field :AA, :Type => Annotation::AdditionalActions
|
163
|
+
field :RV, :Type => [ String, Stream ]
|
164
|
+
end
|
165
|
+
|
166
|
+
class Template < Dictionary
|
167
|
+
include StandardObject
|
168
|
+
|
169
|
+
field :TRef, :Type => NamedPageReference, :Required => true
|
170
|
+
field :Fields, :Type => Array.of(Field)
|
171
|
+
field :Rename, :Type => Boolean
|
172
|
+
end
|
173
|
+
|
174
|
+
class Page < Dictionary
|
175
|
+
include StandardObject
|
176
|
+
|
177
|
+
field :Templates, :Type => Array.of(Template), :Required => true
|
178
|
+
field :Info, :Type => Dictionary
|
179
|
+
end
|
180
|
+
|
181
|
+
class Annotation < Origami::Annotation
|
182
|
+
field :Page, :Type => Integer, :Required => true
|
183
|
+
end
|
184
|
+
|
185
|
+
class Dictionary < Origami::Dictionary
|
186
|
+
include StandardObject
|
187
|
+
|
188
|
+
field :F, :Type => FileSpec
|
189
|
+
field :ID, :Type => Array.of(String, length: 2)
|
190
|
+
field :Fields, :Type => Array.of(FDF::Field)
|
191
|
+
field :Status, :Type => String
|
192
|
+
field :Pages, :Type => Array.of(FDF::Page)
|
193
|
+
field :Encoding, :Type => Name
|
194
|
+
field :Annots, :Type => Array.of(FDF::Annotation)
|
195
|
+
field :Differences, :Type => Stream
|
196
|
+
field :Target, :Type => String
|
197
|
+
field :EmbeddedFDFs, :Type => Array.of(FileSpec)
|
198
|
+
field :JavaScript, :Type => JavaScript
|
199
|
+
end
|
200
|
+
|
201
|
+
class Catalog < Dictionary
|
202
|
+
include StandardObject
|
203
|
+
|
204
|
+
field :Version, :Type => Name
|
205
|
+
field :FDF, :Type => FDF::Dictionary, :Required => true
|
206
|
+
end
|
207
|
+
|
208
|
+
attr_accessor :header, :revisions
|
209
|
+
|
210
|
+
def initialize(parser = nil) #:nodoc:
|
211
|
+
@header = FDF::Header.new
|
212
|
+
@revisions = [ Revision.new(self) ]
|
213
|
+
@revisions.first.trailer = Trailer.new
|
214
|
+
@parser = parser
|
215
|
+
|
216
|
+
init if parser.nil?
|
217
|
+
end
|
218
|
+
|
219
|
+
def <<(object)
|
220
|
+
object.set_indirect(true)
|
221
|
+
object.set_document(self)
|
222
|
+
|
223
|
+
if object.no.zero?
|
224
|
+
maxno = 1
|
225
|
+
maxno = maxno.succ while get_object(maxno)
|
226
|
+
|
227
|
+
object.generation = 0
|
228
|
+
object.no = maxno
|
229
|
+
end
|
230
|
+
|
231
|
+
@revisions.first.body[object.reference] = object
|
232
|
+
|
233
|
+
object.reference
|
234
|
+
end
|
235
|
+
alias insert <<
|
236
|
+
|
237
|
+
def get_object(no, generation = 0) #:nodoc:
|
238
|
+
case no
|
239
|
+
when Reference
|
240
|
+
target = no
|
241
|
+
when ::Integer
|
242
|
+
target = Reference.new(no, generation)
|
243
|
+
when Origami::Object
|
244
|
+
return no
|
245
|
+
end
|
246
|
+
|
247
|
+
@revisions.first.body[target]
|
248
|
+
end
|
249
|
+
|
250
|
+
def indirect_objects
|
251
|
+
@revisions.inject([]) do |set, rev| set.concat(rev.objects) end
|
252
|
+
end
|
253
|
+
alias root_objects indirect_objects
|
254
|
+
|
255
|
+
def cast_object(reference, type) #:nodoc:
|
256
|
+
@revisions.each do |rev|
|
257
|
+
if rev.body.include?(reference) and type < rev.body[reference].class
|
258
|
+
rev.body[reference] = rev.body[reference].cast_to(type, @parser)
|
259
|
+
|
260
|
+
rev.body[reference]
|
261
|
+
else
|
262
|
+
nil
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def Catalog
|
268
|
+
get_object(@revisions.first.trailer.Root)
|
269
|
+
end
|
270
|
+
|
271
|
+
def save(path)
|
272
|
+
bin = "".b
|
273
|
+
bin << @header.to_s
|
274
|
+
|
275
|
+
lastno, brange = 0, 0
|
276
|
+
|
277
|
+
xrefs = [ XRef.new(0, XRef::FIRSTFREE, XRef::FREE) ]
|
278
|
+
xrefsection = XRef::Section.new
|
279
|
+
|
280
|
+
@revisions.first.body.values.sort.each { |obj|
|
281
|
+
if (obj.no - lastno).abs > 1
|
282
|
+
xrefsection << XRef::Subsection.new(brange, xrefs)
|
283
|
+
brange = obj.no
|
284
|
+
xrefs.clear
|
285
|
+
end
|
286
|
+
|
287
|
+
xrefs << XRef.new(bin.size, obj.generation, XRef::USED)
|
288
|
+
lastno = obj.no
|
289
|
+
|
290
|
+
obj.pre_build
|
291
|
+
|
292
|
+
bin << obj.to_s
|
293
|
+
|
294
|
+
obj.post_build
|
295
|
+
}
|
296
|
+
|
297
|
+
xrefsection << XRef::Subsection.new(brange, xrefs)
|
298
|
+
|
299
|
+
@xreftable = xrefsection
|
300
|
+
@trailer ||= Trailer.new
|
301
|
+
@trailer.Size = @revisions.first.body.size + 1
|
302
|
+
@trailer.startxref = bin.size
|
303
|
+
|
304
|
+
bin << @xreftable.to_s
|
305
|
+
bin << @trailer.to_s
|
306
|
+
|
307
|
+
if path.respond_to?(:write)
|
308
|
+
io = path
|
309
|
+
else
|
310
|
+
path = File.expand_path(path)
|
311
|
+
io = File.open(path, "wb", encoding: 'binary')
|
312
|
+
close = true
|
313
|
+
end
|
314
|
+
|
315
|
+
begin
|
316
|
+
io.write(bin)
|
317
|
+
ensure
|
318
|
+
io.close if close
|
319
|
+
end
|
320
|
+
|
321
|
+
self
|
322
|
+
end
|
323
|
+
|
324
|
+
private
|
325
|
+
|
326
|
+
def init
|
327
|
+
catalog = Catalog.new(:FDF => FDF::Dictionary.new)
|
328
|
+
|
329
|
+
@revisions.first.trailer.Root = self.insert(catalog)
|
330
|
+
end
|
331
|
+
|
332
|
+
def get_object_offset(no,generation) #:nodoc:
|
333
|
+
bodyoffset = @header.to_s.size
|
334
|
+
objectoffset = bodyoffset
|
335
|
+
|
336
|
+
@revisions.first.body.values.each { |object|
|
337
|
+
if object.no == no and object.generation == generation then return objectoffset
|
338
|
+
else
|
339
|
+
objectoffset += object.to_s.size
|
340
|
+
end
|
341
|
+
}
|
342
|
+
|
343
|
+
nil
|
344
|
+
end
|
345
|
+
|
346
|
+
end
|
347
|
+
end
|