origami 1.1.2 → 1.2.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.
- data/README +2 -1
- data/origami/dictionary.rb +11 -1
- data/origami/filters/runlength.rb +1 -1
- data/origami/javascript.rb +584 -203
- data/origami/pdf.rb +4 -2
- metadata +4 -4
data/README
CHANGED
data/origami/dictionary.rb
CHANGED
@@ -166,7 +166,17 @@ module Origami
|
|
166
166
|
end
|
167
167
|
|
168
168
|
def [](key)
|
169
|
-
|
169
|
+
#if key.is_a?(::Array) and key.size == 1
|
170
|
+
# follow = true
|
171
|
+
# key = key.first
|
172
|
+
#end
|
173
|
+
|
174
|
+
val = super(key.to_o)
|
175
|
+
#if follow and val.is_a?(Reference)
|
176
|
+
# val.solve
|
177
|
+
#else
|
178
|
+
# val
|
179
|
+
#end
|
170
180
|
end
|
171
181
|
|
172
182
|
def has_key?(key)
|
data/origami/javascript.rb
CHANGED
@@ -25,305 +25,686 @@
|
|
25
25
|
|
26
26
|
module Origami
|
27
27
|
|
28
|
-
|
28
|
+
begin
|
29
|
+
require 'v8'
|
30
|
+
|
31
|
+
class V8::Object
|
32
|
+
#def inspect
|
33
|
+
# case self
|
34
|
+
# when V8::Array,V8::Function then super
|
35
|
+
# else
|
36
|
+
# "{#{self.to_a.map{|k,v| "#{k}:#{v.inspect}"}.join(', ')}}"
|
37
|
+
# end
|
38
|
+
#end
|
39
|
+
end
|
40
|
+
|
41
|
+
class PDF
|
29
42
|
|
30
|
-
|
43
|
+
module JavaScript
|
31
44
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
45
|
+
module Platforms
|
46
|
+
WINDOWS = "WIN"
|
47
|
+
UNIX = "UNIX"
|
48
|
+
MAC = "MAC"
|
49
|
+
end
|
37
50
|
|
38
|
-
|
39
|
-
|
40
|
-
|
51
|
+
module Viewers
|
52
|
+
ADOBE_READER = "Reader"
|
53
|
+
end
|
41
54
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
#end
|
46
|
-
end
|
55
|
+
class MissingArgError < Exception
|
56
|
+
def initialize; super("Missing required argument.") end
|
57
|
+
end
|
47
58
|
|
48
|
-
|
49
|
-
|
50
|
-
attr_accessor :disclosed
|
51
|
-
attr_reader :hidden
|
52
|
-
|
53
|
-
class Info < AcrobatObject
|
54
|
-
def initialize(doc)
|
55
|
-
@doc = doc
|
56
|
-
end
|
57
|
-
|
58
|
-
def title; @doc.title.to_s end
|
59
|
-
def author; @doc.author.to_s end
|
60
|
-
def subject; @doc.subject.to_s end
|
61
|
-
def keywords; @doc.keywords.to_s end
|
62
|
-
def creator; @doc.creator.to_s end
|
63
|
-
def creationDate; @doc.creation_date.to_s end
|
64
|
-
def modDate; @doc.mod_date.to_s end
|
59
|
+
class TypeError < Exception
|
60
|
+
def initialize; super("Incorrect argument type.") end
|
65
61
|
end
|
66
62
|
|
67
|
-
|
68
|
-
|
69
|
-
@disclosed = false
|
70
|
-
@hidden = false
|
71
|
-
@info = Info.new(pdf)
|
63
|
+
class InvalidArgsError < Exception
|
64
|
+
def initialize; super("Incorrect arguments.") end
|
72
65
|
end
|
73
66
|
|
74
|
-
|
75
|
-
|
76
|
-
if fields.nil?
|
77
|
-
0
|
78
|
-
else
|
79
|
-
fields.size
|
80
|
-
end
|
67
|
+
class NotAllowedError < Exception
|
68
|
+
def initialize; super("Security settings prevent access to this property or method.") end
|
81
69
|
end
|
82
70
|
|
83
|
-
|
71
|
+
class HelpError < Exception
|
72
|
+
def initialize; super("Help") end
|
73
|
+
end
|
74
|
+
|
75
|
+
class GeneralError < Exception
|
76
|
+
def initialize; super("Operation failed.") end
|
77
|
+
end
|
84
78
|
|
85
|
-
|
86
|
-
|
87
|
-
def subject; @info.subject end
|
88
|
-
def keywords; @info.keywords end
|
89
|
-
def creator; @info.creator end
|
90
|
-
def creationDate; @info.creationDate end
|
91
|
-
def modDate; @info.modDate end
|
79
|
+
class Arg
|
80
|
+
attr_reader :name, :type, :required, :default
|
92
81
|
|
93
|
-
|
94
|
-
|
82
|
+
def initialize(declare = {})
|
83
|
+
@name = declare[:name]
|
84
|
+
@type = declare[:type]
|
85
|
+
@required = declare[:required]
|
86
|
+
@default = declare[:default]
|
87
|
+
end
|
95
88
|
|
96
|
-
(
|
89
|
+
def self.[](declare = {})
|
90
|
+
self.new(declare)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.inspect(obj)
|
94
|
+
case obj
|
95
|
+
when V8::Function then "function #{obj.name}"
|
96
|
+
when V8::Array then obj.to_a.inspect
|
97
|
+
when V8::Object
|
98
|
+
"{#{obj.to_a.map{|k,v| "#{k}:#{Arg.inspect(v)}"}.join(', ')}}"
|
99
|
+
else
|
100
|
+
obj.inspect
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
97
104
|
end
|
98
105
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
106
|
+
class AcrobatObject
|
107
|
+
def initialize(engine)
|
108
|
+
@engine = engine
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.check_method_args(args, def_args)
|
112
|
+
if args.first.is_a?(V8::Object)
|
113
|
+
args = args.first
|
114
|
+
members = args.entries.map{|k,v| k}
|
115
|
+
argv = []
|
116
|
+
def_args.each do |def_arg|
|
117
|
+
raise MissingArgError if def_arg.required and not members.include?(def_arg.name)
|
118
|
+
|
119
|
+
if members.include?(def_arg.name)
|
120
|
+
arg = args[def_arg.name]
|
121
|
+
raise TypeError if def_arg.type and not arg.is_a?(def_arg.type)
|
122
|
+
else
|
123
|
+
arg = def_arg.default
|
124
|
+
end
|
125
|
+
|
126
|
+
argv.push(arg)
|
127
|
+
end
|
128
|
+
|
129
|
+
args = argv
|
130
|
+
else
|
131
|
+
i = 0
|
132
|
+
def_args.each do |def_arg|
|
133
|
+
raise MissingArgError if def_arg.required and i >= args.length
|
134
|
+
raise TypeError if def_arg.type and not args[i].is_a?(def_arg.type)
|
135
|
+
|
136
|
+
args.push(def_arg.default) if i >= args.length
|
137
|
+
|
138
|
+
i = i + 1
|
113
139
|
end
|
114
140
|
end
|
115
141
|
|
142
|
+
args
|
116
143
|
end
|
117
|
-
|
118
|
-
|
119
|
-
|
144
|
+
|
145
|
+
def self.acro_method(name, *def_args, &b)
|
146
|
+
define_method(name) do |*args|
|
147
|
+
if @engine.options[:log_method_calls]
|
148
|
+
@engine.options[:console].puts(
|
149
|
+
"LOG: #{self.class}.#{name}(#{args.map{|arg| Arg.inspect(arg)}.join(',')})"
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
args = AcrobatObject.check_method_args(args, def_args)
|
154
|
+
self.instance_exec(*args, &b) if b
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.acro_method_protected(name, *def_args, &b)
|
159
|
+
define_method(name) do |*args|
|
160
|
+
if @engine.options[:log_method_calls]
|
161
|
+
@engine.options[:console].puts(
|
162
|
+
"LOG: #{self.class}.#{name}(#{args.map{|arg| arg.inspect}.join(',')})"
|
163
|
+
)
|
164
|
+
end
|
120
165
|
|
121
|
-
|
122
|
-
file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
|
166
|
+
raise NotAllowedError
|
123
167
|
|
124
|
-
|
125
|
-
|
126
|
-
if ef
|
127
|
-
f = ef[:F].solve
|
128
|
-
Data.new(cName, f.data.size) if f.is_a?(Stream)
|
168
|
+
args = AcrobatObject.check_method_args(args, def_args)
|
169
|
+
self.instance_exec(*args, &b) if b
|
129
170
|
end
|
130
171
|
end
|
172
|
+
|
173
|
+
def to_s
|
174
|
+
"[object #{self.class.to_s.split('::').last}]"
|
175
|
+
end
|
176
|
+
alias inspect to_s
|
177
|
+
|
131
178
|
end
|
132
179
|
|
133
|
-
|
134
|
-
|
180
|
+
class AcroTimer < AcrobatObject
|
181
|
+
def initialize(engine, timeout, code, repeat)
|
135
182
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
183
|
+
@thr = Thread.start(engine, timeout, code, repeat) do
|
184
|
+
loop do
|
185
|
+
sleep(timeout / 1000.0)
|
186
|
+
engine.exec(code)
|
187
|
+
break if not repeat
|
188
|
+
end
|
141
189
|
end
|
142
190
|
end
|
143
191
|
end
|
144
192
|
|
145
|
-
|
146
|
-
|
193
|
+
class TimeOut < AcroTimer
|
194
|
+
def initialize(engine, timeout, code)
|
195
|
+
super(engine, timeout, code, false)
|
196
|
+
end
|
197
|
+
end
|
147
198
|
|
148
|
-
|
199
|
+
class Interval < AcroTimer
|
200
|
+
def initialize(engine, timeout, code)
|
201
|
+
super(engine, timeout, code, true)
|
202
|
+
end
|
149
203
|
end
|
150
204
|
|
151
|
-
|
152
|
-
|
205
|
+
class ReadStream < AcrobatObject
|
206
|
+
def initialize(engine, data)
|
207
|
+
super(engine)
|
153
208
|
|
154
|
-
|
209
|
+
@data = data
|
210
|
+
end
|
211
|
+
|
212
|
+
acro_method 'read',
|
213
|
+
Arg[:name => 'nBytes', :type => Numeric, :required => true] do |nBytes|
|
214
|
+
@data.slice!(0, nBytes)
|
215
|
+
end
|
155
216
|
end
|
156
|
-
end
|
157
217
|
|
158
|
-
|
159
|
-
attr_reader :platform, :viewerVariation, :viewerVersion
|
218
|
+
class Acrohelp < AcrobatObject; end
|
160
219
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
end
|
220
|
+
class Global < AcrobatObject
|
221
|
+
def initialize(engine)
|
222
|
+
super(engine)
|
165
223
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
224
|
+
@vars = {}
|
225
|
+
end
|
226
|
+
|
227
|
+
def []=(name, value)
|
228
|
+
@vars[name] ||= {:callbacks => []}
|
229
|
+
@vars[name][:value] = value
|
230
|
+
@vars[name][:callbacks].each do |callback|
|
231
|
+
callback.call(value)
|
232
|
+
end
|
233
|
+
end
|
171
234
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
end
|
235
|
+
def [](name)
|
236
|
+
@vars[name][:value] if @vars.include?(name)
|
237
|
+
end
|
176
238
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
239
|
+
acro_method 'setPersistent',
|
240
|
+
Arg[:name => 'cVariable', :required => true],
|
241
|
+
Arg[:name => 'bPersist', :required => true] do |cVariable, bPersist|
|
242
|
+
raise GeneralError unless @vars.include?(cVariable)
|
243
|
+
end
|
181
244
|
|
182
|
-
|
183
|
-
|
184
|
-
|
245
|
+
acro_method 'subscribe',
|
246
|
+
Arg[:name => 'cVariable', :required => true],
|
247
|
+
Arg[:name => 'fCallback', :type => V8::Function, :required => true] do |cVariable, fCallback|
|
248
|
+
if @vars.include?(cVariable)
|
249
|
+
@vars[cVariable][:callbacks].push(fCallback)
|
250
|
+
fCallback.call(@vars[cVariable][:value])
|
251
|
+
end
|
252
|
+
end
|
185
253
|
end
|
186
254
|
|
187
|
-
|
188
|
-
|
189
|
-
|
255
|
+
class Doc < AcrobatObject
|
256
|
+
attr_reader :info
|
257
|
+
attr_accessor :disclosed
|
258
|
+
attr_reader :hidden
|
259
|
+
|
260
|
+
class Info < AcrobatObject
|
261
|
+
def initialize(engine, doc)
|
262
|
+
super(engine)
|
263
|
+
|
264
|
+
@doc = doc
|
265
|
+
end
|
266
|
+
|
267
|
+
def title; @doc.title.to_s end
|
268
|
+
def author; @doc.author.to_s end
|
269
|
+
def subject; @doc.subject.to_s end
|
270
|
+
def keywords; @doc.keywords.to_s end
|
271
|
+
def creator; @doc.creator.to_s end
|
272
|
+
def creationDate; @doc.creation_date.to_s end
|
273
|
+
def modDate; @doc.mod_date.to_s end
|
190
274
|
end
|
191
|
-
end
|
192
|
-
end
|
193
275
|
|
194
|
-
|
195
|
-
|
196
|
-
@field = field
|
197
|
-
end
|
276
|
+
def initialize(engine, pdf)
|
277
|
+
super(engine)
|
198
278
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
279
|
+
@pdf = pdf
|
280
|
+
@disclosed = false
|
281
|
+
@hidden = false
|
282
|
+
@info = Info.new(@engine, pdf)
|
283
|
+
end
|
284
|
+
|
285
|
+
### PROPERTIES ###
|
286
|
+
|
287
|
+
def numFields
|
288
|
+
fields = @pdf.fields
|
289
|
+
if fields.nil?
|
290
|
+
0
|
291
|
+
else
|
292
|
+
fields.size
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def numPages; @pdf.pages.size end
|
297
|
+
|
298
|
+
def title; @info.title end
|
299
|
+
def author; @info.author end
|
300
|
+
def subject; @info.subject end
|
301
|
+
def keywords; @info.keywords end
|
302
|
+
def creator; @info.creator end
|
303
|
+
def creationDate; @info.creationDate end
|
304
|
+
def modDate; @info.modDate end
|
305
|
+
|
306
|
+
def metadata
|
307
|
+
meta = @pdf.Catalog.Metadata
|
308
|
+
|
309
|
+
(meta.data if meta.is_a?(Stream)).to_s
|
310
|
+
end
|
311
|
+
|
312
|
+
def filesize; @pdf.original_filesize end
|
313
|
+
def path; @pdf.original_filename.to_s end
|
314
|
+
def documentFileName; File.basename(self.path) end
|
315
|
+
def URL; "file://#{self.path}" end
|
316
|
+
def baseURL; '' end
|
317
|
+
|
318
|
+
def dataObjects
|
319
|
+
data_objs = []
|
320
|
+
@pdf.ls_names(Names::Root::EMBEDDEDFILES).each do |name, file_desc|
|
321
|
+
if file_desc
|
322
|
+
ef = file_desc[:EF].solve
|
323
|
+
if ef
|
324
|
+
f = ef[:F].solve
|
325
|
+
data_objs.push Data.new(@engine, name, f.data.size) if f.is_a?(Stream)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
data_objs
|
332
|
+
end
|
333
|
+
|
334
|
+
### METHODS ###
|
203
335
|
|
204
|
-
|
205
|
-
@field[:V].solve.value if @field.has_key?(:V)
|
206
|
-
end
|
336
|
+
acro_method 'closeDoc'
|
207
337
|
|
208
|
-
|
209
|
-
|
210
|
-
|
338
|
+
acro_method 'getDataObject',
|
339
|
+
Arg[:name => 'cName', :type => ::String, :required => true] do |cName|
|
340
|
+
file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
|
211
341
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
flags = @fields[:Ff].solve.value
|
218
|
-
|
219
|
-
if (flags & Origami::Annotation::Widget::Button::Flags::PUSHBUTTON) != 0
|
220
|
-
'button'
|
221
|
-
elsif (flags & Origami::Annotation::Widget::Button::Flags::RADIO) != 0
|
222
|
-
'radiobox'
|
223
|
-
else
|
224
|
-
'checkbox'
|
225
|
-
end
|
342
|
+
if file_desc
|
343
|
+
ef = file_desc[:EF].solve
|
344
|
+
if ef
|
345
|
+
f = ef[:F].solve
|
346
|
+
else raise TypeError
|
226
347
|
end
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
348
|
+
else raise TypeError
|
349
|
+
end
|
350
|
+
|
351
|
+
Data.new(@engine, cName, f.data.size) if f.is_a?(Stream)
|
352
|
+
end
|
353
|
+
|
354
|
+
acro_method 'getDataObjectContents',
|
355
|
+
Arg[:name => 'cName', :type => ::String, :required => true],
|
356
|
+
Arg[:name => 'bAllowAuth', :default => false] do |cName, bAllowAuth|
|
357
|
+
file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
|
358
|
+
|
359
|
+
if file_desc
|
360
|
+
ef = file_desc[:EF].solve
|
361
|
+
if ef
|
362
|
+
f = ef[:F].solve
|
363
|
+
else raise TypeError
|
364
|
+
end
|
365
|
+
else raise TypeError
|
366
|
+
end
|
367
|
+
|
368
|
+
ReadStream.new(@engine, f.data) if f.is_a?(Stream)
|
369
|
+
end
|
370
|
+
|
371
|
+
acro_method 'exportDataObject',
|
372
|
+
Arg[:name => 'cName', :type => ::String, :required => true],
|
373
|
+
Arg[:name => 'cDIPath' ],
|
374
|
+
Arg[:name => 'bAllowAuth'],
|
375
|
+
Arg[:name => 'nLaunch'] do |cName, cDIPath, bAllowAuth, nLaunch|
|
376
|
+
file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
|
377
|
+
|
378
|
+
if file_desc
|
379
|
+
ef = file_desc[:EF].solve
|
380
|
+
if ef
|
381
|
+
f = ef[:F].solve
|
382
|
+
else raise TypeError
|
383
|
+
end
|
384
|
+
else raise TypeError
|
385
|
+
end
|
386
|
+
|
387
|
+
raise TypeError if f.nil?
|
388
|
+
end
|
389
|
+
|
390
|
+
acro_method 'getField',
|
391
|
+
Arg[:name => 'cName', :type => ::Object, :required => true] do |cName|
|
392
|
+
field = @pdf.get_field(cName)
|
393
|
+
|
394
|
+
Field.new(@engine, field) if field
|
395
|
+
end
|
396
|
+
|
397
|
+
acro_method 'getNthFieldName',
|
398
|
+
Arg[:name => 'nIndex', :type => ::Object, :required => true] do |nIndex|
|
399
|
+
nIndex =
|
400
|
+
case nIndex
|
401
|
+
when false then 0
|
402
|
+
when true then 1
|
233
403
|
else
|
234
|
-
|
235
|
-
end
|
404
|
+
@engine.parseInt.call(nIndex)
|
236
405
|
end
|
406
|
+
|
407
|
+
raise TypeError if (nIndex.is_a?(Float) and nIndex.nan?) or nIndex < 0
|
408
|
+
fields = @pdf.fields
|
409
|
+
|
410
|
+
(Field.new(@engine, fields[nIndex]).name if fields and fields[nIndex]).to_s
|
237
411
|
end
|
238
|
-
end).to_s
|
239
412
|
end
|
240
413
|
|
241
|
-
|
414
|
+
class App < AcrobatObject
|
415
|
+
attr_reader :platform, :viewerVariation, :viewerVersion
|
416
|
+
|
417
|
+
def platform; @engine.options[:platform] end
|
418
|
+
def viewerType; @engine.options[:viewerType] end
|
419
|
+
def viewerVariation; @engine.options[:viewerVariation] end
|
420
|
+
def viewerVersion; @engine.options[:viewerVersion] end
|
421
|
+
|
422
|
+
def activeDocs; [] end
|
423
|
+
|
424
|
+
### METHODS ###
|
425
|
+
|
426
|
+
acro_method 'setInterval',
|
427
|
+
Arg[:name => 'cExpr', :required => true],
|
428
|
+
Arg[:name => 'nMilliseconds', :type => Numeric, :required => true] do |cExpr, nMilliseconds|
|
429
|
+
cExpr = cExpr.is_a?(::String) ? cExpr : ''
|
430
|
+
Interval.new(@engine, nMilliseconds, cExpr)
|
431
|
+
end
|
242
432
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
433
|
+
acro_method 'setTimeOut',
|
434
|
+
Arg[:name => 'cExpr', :required => true],
|
435
|
+
Arg[:name => 'nMilliseconds', :type => Numeric, :required => true] do |cExpr, nMilliseconds|
|
436
|
+
cExpr = cExpr.is_a?(::String) ? cExpr : ''
|
437
|
+
TimeOut.new(@engine, nMilliseconds, cExpr)
|
438
|
+
end
|
439
|
+
|
440
|
+
acro_method 'clearInterval',
|
441
|
+
Arg[:name => 'oInterval', :type => Interval, :required => true] do |oInterval|
|
442
|
+
oInterval.instance_variable_get(:@thr).terminate
|
443
|
+
nil
|
444
|
+
end
|
445
|
+
|
446
|
+
acro_method 'clearTimeOut',
|
447
|
+
Arg[:name => 'oInterval', :type => TimeOut, :required => true] do |oInterval|
|
448
|
+
oInterval.instance_variable_get(:@thr).terminate
|
449
|
+
nil
|
450
|
+
end
|
247
451
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
452
|
+
acro_method_protected 'addMenuItem'
|
453
|
+
acro_method_protected 'addSubMenu'
|
454
|
+
acro_method 'addToolButton'
|
455
|
+
acro_method_protected 'beginPriv'
|
456
|
+
acro_method 'beep'
|
457
|
+
acro_method_protected 'browseForDoc'
|
458
|
+
acro_method_protected 'endPriv'
|
252
459
|
end
|
253
|
-
end
|
254
460
|
|
255
|
-
|
256
|
-
|
257
|
-
|
461
|
+
class Console < AcrobatObject
|
462
|
+
def println(*args)
|
463
|
+
raise MissingArgError unless args.length > 0
|
464
|
+
|
465
|
+
@engine.options[:console].puts(args.first.to_s)
|
466
|
+
end
|
467
|
+
|
468
|
+
acro_method 'show'
|
469
|
+
acro_method 'clear'
|
470
|
+
acro_method 'hide'
|
258
471
|
end
|
259
472
|
|
260
|
-
|
261
|
-
|
473
|
+
class Util < AcrobatObject
|
474
|
+
acro_method 'streamFromString',
|
475
|
+
Arg[:name => 'cString', :type => ::Object, :required => true],
|
476
|
+
Arg[:name => 'cCharset', :type => ::Object, :default => 'utf-8'] do |cString, cCharset|
|
477
|
+
|
478
|
+
ReadStream.new(@engine, cString.to_s)
|
479
|
+
end
|
480
|
+
|
481
|
+
acro_method 'stringFromStream',
|
482
|
+
Arg[:name => 'oStream', :type => ReadStream, :required => true],
|
483
|
+
Arg[:name => 'cCharset', :type => ::Object, :default => 'utf-8'] do |oStream, cCharset|
|
484
|
+
|
485
|
+
oStream.instance_variable_get(:@data).dup
|
486
|
+
end
|
262
487
|
end
|
488
|
+
|
489
|
+
class Field < AcrobatObject
|
490
|
+
def initialize(engine, field)
|
491
|
+
super(engine)
|
492
|
+
|
493
|
+
@field = field
|
494
|
+
end
|
495
|
+
|
496
|
+
def doc; Doc.new(@field.pdf) end
|
497
|
+
def name
|
498
|
+
(@field[:T].solve.value if @field.has_key?(:T)).to_s
|
499
|
+
end
|
500
|
+
|
501
|
+
def value
|
502
|
+
@field[:V].solve.value if @field.has_key?(:V)
|
503
|
+
end
|
504
|
+
|
505
|
+
def valueAsString
|
506
|
+
self.value.to_s
|
507
|
+
end
|
508
|
+
|
509
|
+
def type
|
510
|
+
(if @field.has_key?(:FT)
|
511
|
+
case @field[:FT].solve.value
|
512
|
+
when PDF::Field::Type::BUTTON
|
513
|
+
if @fields.has_key?(:Ff)
|
514
|
+
flags = @fields[:Ff].solve.value
|
515
|
+
|
516
|
+
if (flags & Origami::Annotation::Widget::Button::Flags::PUSHBUTTON) != 0
|
517
|
+
'button'
|
518
|
+
elsif (flags & Origami::Annotation::Widget::Button::Flags::RADIO) != 0
|
519
|
+
'radiobox'
|
520
|
+
else
|
521
|
+
'checkbox'
|
522
|
+
end
|
523
|
+
end
|
524
|
+
when PDF::Field::Type::TEXT then 'text'
|
525
|
+
when PDF::Field::Type::SIGNATURE then 'signature'
|
526
|
+
when PDF::Field::Type::CHOICE
|
527
|
+
if @field.has_key?(:Ff)
|
528
|
+
if (@field[:Ff].solve.value & Origami::Annotation::Widget::Choice::Flags::COMBO).zero?
|
529
|
+
'listbox'
|
530
|
+
else
|
531
|
+
'combobox'
|
532
|
+
end
|
533
|
+
end
|
534
|
+
end
|
535
|
+
end).to_s
|
536
|
+
end
|
537
|
+
|
538
|
+
end
|
539
|
+
|
540
|
+
class Data < AcrobatObject
|
541
|
+
attr_reader :name, :path, :size
|
542
|
+
attr_reader :creationDate, :modDate
|
543
|
+
attr_reader :description, :MIMEType
|
544
|
+
|
545
|
+
def initialize(engine, name, size, path = nil, creationDate = nil, modDate = nil, description = nil, mimeType = nil)
|
546
|
+
|
547
|
+
super(engine)
|
548
|
+
|
549
|
+
@name, @path, @size = name, path, size
|
550
|
+
@creationDate, @modDate = creationDate, modDate
|
551
|
+
@description, @MIMEType = description, mimeType
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
263
555
|
end
|
264
|
-
end
|
265
556
|
|
266
|
-
|
267
|
-
require 'v8'
|
557
|
+
class JavaScript::EngineError < Exception; end
|
268
558
|
|
269
559
|
class JavaScript::Engine
|
270
560
|
|
561
|
+
attr_reader :global
|
271
562
|
attr_reader :context
|
563
|
+
attr_reader :options
|
564
|
+
attr_reader :parseInt
|
272
565
|
|
273
|
-
def initialize(pdf
|
274
|
-
options =
|
566
|
+
def initialize(pdf)
|
567
|
+
@options =
|
275
568
|
{
|
276
569
|
:viewerVersion => JavaScript::Platforms::WINDOWS,
|
570
|
+
:viewerType => JavaScript::Viewers::ADOBE_READER,
|
277
571
|
:viewerVariation => JavaScript::Viewers::ADOBE_READER,
|
278
|
-
:platform => 9
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
572
|
+
:platform => 9,
|
573
|
+
:console => STDOUT,
|
574
|
+
:log_method_calls => false
|
575
|
+
}
|
576
|
+
|
577
|
+
@global = JavaScript::Doc.new(self, pdf)
|
578
|
+
app = JavaScript::App.new(self)
|
579
|
+
acrohelp = JavaScript::Acrohelp.new(self)
|
580
|
+
global = JavaScript::Global.new(self)
|
581
|
+
console = JavaScript::Console.new(self)
|
582
|
+
util = JavaScript::Util.new(self)
|
583
|
+
|
584
|
+
@context = V8::Context.new(:with => @global)
|
287
585
|
@context['app'] = app
|
586
|
+
@context['acrohelp'] = acrohelp
|
288
587
|
@context['console'] = console
|
588
|
+
@context['global'] = global
|
289
589
|
@context['util'] = util
|
590
|
+
|
591
|
+
@parseInt = @context['parseInt']
|
592
|
+
@hooks = {}
|
290
593
|
end
|
291
594
|
|
595
|
+
#
|
596
|
+
# Evaluates a JavaScript code in the current context.
|
597
|
+
#
|
292
598
|
def exec(script)
|
293
599
|
@context.eval(script)
|
294
600
|
end
|
295
|
-
end
|
296
601
|
|
297
|
-
|
298
|
-
|
299
|
-
|
602
|
+
#
|
603
|
+
# Set a hook on a JavaScript method.
|
604
|
+
#
|
605
|
+
def hook(name, &callback)
|
606
|
+
ns = name.split('.')
|
607
|
+
previous = @context
|
608
|
+
|
609
|
+
ns.each do |n|
|
610
|
+
raise JavaScript::EngineError, "#{name} does not exist" if previous.nil?
|
611
|
+
previous = previous[n]
|
612
|
+
end
|
613
|
+
|
614
|
+
case previous
|
615
|
+
when V8::Function, UnboundMethod, nil then
|
616
|
+
@context[name] = lambda do |*args|
|
617
|
+
callback[previous, *args]
|
618
|
+
end
|
619
|
+
|
620
|
+
@hooks[name] = [previous, callback]
|
621
|
+
else
|
622
|
+
raise JavaScript::EngineError, "#{name} is not a function"
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
#
|
627
|
+
# Removes an existing hook on a JavaScript method.
|
628
|
+
#
|
629
|
+
def unhook(name)
|
630
|
+
if @hooks.has_key?(name)
|
631
|
+
@context[name] = @hooks[name][0]
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
#
|
636
|
+
# Returns an Hash of all defined members in specified object name.
|
637
|
+
#
|
638
|
+
def members(obj)
|
639
|
+
members = {}
|
640
|
+
list = @context.eval <<-JS
|
641
|
+
(function(base){
|
642
|
+
var members = [];
|
643
|
+
for (var i in base) members.push([i, base[i]]);
|
644
|
+
return members;
|
645
|
+
})(#{obj})
|
646
|
+
JS
|
647
|
+
|
648
|
+
list.each do |var|
|
649
|
+
members[var[0]] = var[1]
|
650
|
+
end
|
651
|
+
|
652
|
+
members
|
653
|
+
end
|
654
|
+
|
655
|
+
#
|
656
|
+
# Returns all members in the global scope.
|
657
|
+
#
|
658
|
+
def scope
|
659
|
+
members('this')
|
660
|
+
end
|
300
661
|
|
301
|
-
|
662
|
+
#
|
663
|
+
# Binds the V8 remote debugging agent on the specified TCP _port_.
|
664
|
+
#
|
665
|
+
def enable_debugger(port)
|
666
|
+
V8::C::Debug.EnableAgent("Origami", port)
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
end
|
671
|
+
|
302
672
|
module String
|
303
|
-
|
304
|
-
|
305
|
-
|
673
|
+
#
|
674
|
+
# Evaluates the current String as JavaScript.
|
675
|
+
#
|
676
|
+
def eval_js
|
677
|
+
self.pdf.eval_js(self.value)
|
306
678
|
end
|
307
679
|
end
|
308
680
|
|
309
681
|
class Stream
|
310
|
-
|
311
|
-
|
312
|
-
|
682
|
+
#
|
683
|
+
# Evaluates the current Stream as JavaScript.
|
684
|
+
#
|
685
|
+
def eval_js
|
686
|
+
self.pdf.eval_js(self.data)
|
313
687
|
end
|
314
688
|
end
|
315
689
|
|
316
690
|
class PDF
|
691
|
+
|
692
|
+
#
|
693
|
+
# Executes a JavaScript script in the current document context.
|
694
|
+
#
|
317
695
|
def eval_js(code)
|
318
|
-
|
696
|
+
js_engine.exec(code)
|
319
697
|
end
|
320
698
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
699
|
+
#
|
700
|
+
# Returns the JavaScript engine (if JavaScript support is present).
|
701
|
+
#
|
702
|
+
def js_engine
|
703
|
+
@js_engine ||= PDF::JavaScript::Engine.new(self)
|
325
704
|
end
|
326
705
|
end
|
706
|
+
|
707
|
+
rescue LoadError
|
327
708
|
end
|
328
|
-
|
329
709
|
end
|
710
|
+
|
data/origami/pdf.rb
CHANGED
@@ -54,11 +54,12 @@ require 'origami/encryption'
|
|
54
54
|
require 'origami/linearization'
|
55
55
|
require 'origami/obfuscation'
|
56
56
|
require 'origami/xfa'
|
57
|
+
require 'origami/javascript'
|
57
58
|
|
58
59
|
module Origami
|
59
60
|
|
60
|
-
VERSION = "1.
|
61
|
-
REVISION = "$Revision: rev
|
61
|
+
VERSION = "1.2.0"
|
62
|
+
REVISION = "$Revision: rev 125/, 2011/09/29 15:18:36 darko $" #:nodoc:
|
62
63
|
|
63
64
|
#
|
64
65
|
# Global options for Origami.
|
@@ -179,6 +180,7 @@ module Origami
|
|
179
180
|
# Reads and parses a PDF file from disk.
|
180
181
|
#
|
181
182
|
def read(filename, options = {:verbosity => Parser::VERBOSE_INSANE})
|
183
|
+
filename = File.expand_path(filename) if filename.is_a?(::String)
|
182
184
|
PDF::LinearParser.new(options).parse(filename)
|
183
185
|
end
|
184
186
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: origami
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
- 1
|
9
8
|
- 2
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 1.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Guillaume Delugr\xC3\xA9"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-09-
|
18
|
+
date: 2011-09-29 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|