origami 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -12,12 +12,13 @@ DESCRIPTION
12
12
 
13
13
  VERSION
14
14
 
15
- 1.1
15
+ 1.2
16
16
 
17
17
  OPTIONAL DEPENDENCIES
18
18
 
19
19
  - Ruby-GTK2 (only for GUI), http://ruby-gnome2.sourceforge.jp/
20
20
  - Ruby with OpenSSL support
21
+ - TheRubyRacer gem (only for JavaScript support)
21
22
 
22
23
  INSTALL
23
24
 
@@ -166,7 +166,17 @@ module Origami
166
166
  end
167
167
 
168
168
  def [](key)
169
- super(key.to_o)
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)
@@ -97,7 +97,7 @@ module Origami
97
97
  result = ""
98
98
  until stream[i].ord == EOD do
99
99
 
100
- length = stream[i]
100
+ length = stream[i].ord
101
101
  if length < EOD
102
102
  result << stream[i + 1, length + 1]
103
103
  i = i + length + 2
@@ -25,305 +25,686 @@
25
25
 
26
26
  module Origami
27
27
 
28
- class PDF
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
- module JavaScript
43
+ module JavaScript
31
44
 
32
- module Platforms
33
- WINDOWS = "WIN"
34
- UNIX = "UNIX"
35
- MAC = "MAC"
36
- end
45
+ module Platforms
46
+ WINDOWS = "WIN"
47
+ UNIX = "UNIX"
48
+ MAC = "MAC"
49
+ end
37
50
 
38
- module Viewers
39
- ADOBE_READER = "Reader"
40
- end
51
+ module Viewers
52
+ ADOBE_READER = "Reader"
53
+ end
41
54
 
42
- class AcrobatObject
43
- #def to_s
44
- # "[object #{self.class.to_s.split('::').last}]"
45
- #end
46
- end
55
+ class MissingArgError < Exception
56
+ def initialize; super("Missing required argument.") end
57
+ end
47
58
 
48
- class Doc < AcrobatObject
49
- attr_reader :info
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
- def initialize(pdf)
68
- @pdf = pdf
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
- def numFields
75
- fields = @pdf.fields
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
- def numPages; @pdf.pages.size end
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
- def title; @info.title end
86
- def author; @info.author end
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
- def metadata
94
- meta = @pdf.Catalog.Metadata
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
- (meta.data if meta.is_a?(Stream)).to_s
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
- def filesize; @pdf.original_filesize end
100
- def path; @pdf.original_filename end
101
- def documentFileName; File.basename(self.path) end
102
- def URL; "file://#{self.path}" end
103
- def baseURL; '' end
104
-
105
- def dataObjects
106
- data_objs = []
107
- @pdf.ls_names(Names::Root::EMBEDDEDFILES).each do |name, file_desc|
108
- if file_desc
109
- ef = file_desc[:EF].solve
110
- if ef
111
- f = ef[:F].solve
112
- data_objs.push Data.new(name, f.data.size) if f.is_a?(Stream)
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
- data_objs
119
- end
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
- def getDataObject(cName)
122
- file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
166
+ raise NotAllowedError
123
167
 
124
- if file_desc
125
- ef = file_desc[:EF].solve
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
- def getDataObjectContents(cName, bAllowAuth = false)
134
- file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
180
+ class AcroTimer < AcrobatObject
181
+ def initialize(engine, timeout, code, repeat)
135
182
 
136
- if file_desc
137
- ef = file_desc[:EF].solve
138
- if ef
139
- f = ef[:F].solve
140
- ReadStream.new(f.data) if f.is_a?(Stream)
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
- def getField(cName)
146
- field = @pdf.get_field(cName)
193
+ class TimeOut < AcroTimer
194
+ def initialize(engine, timeout, code)
195
+ super(engine, timeout, code, false)
196
+ end
197
+ end
147
198
 
148
- Field.new(field) if field
199
+ class Interval < AcroTimer
200
+ def initialize(engine, timeout, code)
201
+ super(engine, timeout, code, true)
202
+ end
149
203
  end
150
204
 
151
- def getNthFieldName(nIndex)
152
- fields = @pdf.fields
205
+ class ReadStream < AcrobatObject
206
+ def initialize(engine, data)
207
+ super(engine)
153
208
 
154
- (Field.new(fields[nIndex]).name if fields and fields[nIndex]).to_s
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
- class App < AcrobatObject
159
- attr_reader :platform, :viewerVariation, :viewerVersion
218
+ class Acrohelp < AcrobatObject; end
160
219
 
161
- def initialize(platform, viewerVariation, viewerVersion)
162
- @platform = platform
163
- @viewerVariation, @viewerVersion = viewerVariation, viewerVersion
164
- end
220
+ class Global < AcrobatObject
221
+ def initialize(engine)
222
+ super(engine)
165
223
 
166
- def response(params)
167
- puts params.class
168
- gets
169
- end
170
- end
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
- class Console < AcrobatObject
173
- def initialize(output = STDOUT)
174
- @output = output
175
- end
235
+ def [](name)
236
+ @vars[name][:value] if @vars.include?(name)
237
+ end
176
238
 
177
- def println(msg)
178
- @output.puts msg
179
- end
180
- end
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
- class Util < AcrobatObject
183
- def streamFromString(cString, cCharset = 'utf-8')
184
- ReadStream.new(cString.to_s)
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
- def stringFromStream(oStream, cCharset = 'utf-8')
188
- if oStream.is_a?(ReadStream)
189
- oStream.instance_variable_get(:@data).dup
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
- class Field < AcrobatObject
195
- def initialize(field)
196
- @field = field
197
- end
276
+ def initialize(engine, pdf)
277
+ super(engine)
198
278
 
199
- def doc; Doc.new(@field.pdf) end
200
- def name
201
- (@field[:T].solve.value if @field.has_key?(:T)).to_s
202
- end
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
- def value
205
- @field[:V].solve.value if @field.has_key?(:V)
206
- end
336
+ acro_method 'closeDoc'
207
337
 
208
- def valueAsString
209
- self.value.to_s
210
- end
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
- def type
213
- (if @field.has_key?(:FT)
214
- case @field[:FT].solve.value
215
- when PDF::Field::Type::BUTTON
216
- if @fields.has_key?(:Ff)
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
- when PDF::Field::Type::TEXT then 'text'
228
- when PDF::Field::Type::SIGNATURE then 'signature'
229
- when PDF::Field::Type::CHOICE
230
- if @field.has_key?(:Ff)
231
- if (@field[:Ff].solve.value & Origami::Annotation::Widget::Choice::Flags::COMBO).zero?
232
- 'listbox'
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
- 'combobox'
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
- end
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
- class Data < AcrobatObject
244
- attr_reader :name, :path, :size
245
- attr_reader :creationDate, :modDate
246
- attr_reader :description, :MIMEType
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
- def initialize(name, size, path = nil, creationDate = nil, modDate = nil, description = nil, mimeType = nil)
249
- @name, @path, @size = name, path, size
250
- @creationDate, @modDate = creationDate, modDate
251
- @description, @MIMEType = description, mimeType
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
- class ReadStream < AcrobatObject
256
- def initialize(data)
257
- @data = data
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
- def read(n)
261
- @data.slice!(0, n)
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
- begin
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, params = {})
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
- }.update(params)
280
-
281
- doc = JavaScript::Doc.new(pdf)
282
- app = JavaScript::App.new(options[:platform], options[:viewerVariation], options[:viewerVersion])
283
- util = JavaScript::Util.new
284
- console = JavaScript::Console.new
285
-
286
- @context = V8::Context.new(:with => doc)
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
- rescue LoadError
298
- end
299
- end
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
- if defined?(PDF::JavaScript::Engine)
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
- def eval_as_js(options = {})
304
- runtime = options[:runtime] || PDF::JavaScript::Engine.new(self.pdf, options)
305
- runtime.exec(self.value)
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
- def eval_as_js(options = {})
311
- runtime = options[:runtime] || PDF::JavaScript::Engine.new(self.pdf, options)
312
- runtime.exec(self.data)
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
- get_js_engine.exec(code)
696
+ js_engine.exec(code)
319
697
  end
320
698
 
321
- private
322
-
323
- def get_js_engine(options = {})
324
- @js_engine ||= PDF::JavaScript::Engine.new(self, options)
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
+
@@ -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.1.2"
61
- REVISION = "$Revision: rev 122/, 2011/09/26 12:12:39 darko $" #:nodoc:
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: 23
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 1
9
8
  - 2
10
- version: 1.1.2
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-26 00:00:00 +02:00
18
+ date: 2011-09-29 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies: []
21
21