origami 1.2.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/README.md +112 -0
  4. data/bin/config/pdfcop.conf.yml +232 -233
  5. data/bin/gui/about.rb +27 -37
  6. data/bin/gui/config.rb +108 -117
  7. data/bin/gui/file.rb +416 -365
  8. data/bin/gui/gtkhex.rb +1138 -1153
  9. data/bin/gui/hexview.rb +55 -57
  10. data/bin/gui/imgview.rb +48 -51
  11. data/bin/gui/menu.rb +388 -386
  12. data/bin/gui/properties.rb +114 -130
  13. data/bin/gui/signing.rb +571 -617
  14. data/bin/gui/textview.rb +77 -95
  15. data/bin/gui/treeview.rb +382 -387
  16. data/bin/gui/walker.rb +227 -232
  17. data/bin/gui/xrefs.rb +56 -60
  18. data/bin/pdf2pdfa +53 -57
  19. data/bin/pdf2ruby +212 -228
  20. data/bin/pdfcop +338 -348
  21. data/bin/pdfdecompress +58 -65
  22. data/bin/pdfdecrypt +56 -60
  23. data/bin/pdfencrypt +75 -80
  24. data/bin/pdfexplode +185 -182
  25. data/bin/pdfextract +201 -218
  26. data/bin/pdfmetadata +83 -82
  27. data/bin/pdfsh +4 -5
  28. data/bin/pdfwalker +1 -2
  29. data/bin/shell/.irbrc +45 -82
  30. data/bin/shell/console.rb +105 -130
  31. data/bin/shell/hexdump.rb +40 -64
  32. data/examples/README.md +34 -0
  33. data/examples/attachments/attachment.rb +38 -0
  34. data/examples/attachments/nested_document.rb +51 -0
  35. data/examples/encryption/encryption.rb +28 -0
  36. data/{samples/actions/triggerevents/trigger.rb → examples/events/events.rb} +13 -16
  37. data/examples/flash/flash.rb +37 -0
  38. data/{samples → examples}/flash/helloworld.swf +0 -0
  39. data/examples/forms/javascript.rb +54 -0
  40. data/examples/forms/xfa.rb +115 -0
  41. data/examples/javascript/hello_world.rb +22 -0
  42. data/examples/javascript/js_emulation.rb +54 -0
  43. data/examples/loop/goto.rb +32 -0
  44. data/examples/loop/named.rb +33 -0
  45. data/examples/signature/signature.rb +65 -0
  46. data/examples/uri/javascript.rb +56 -0
  47. data/examples/uri/open-uri.rb +21 -0
  48. data/examples/uri/submitform.rb +47 -0
  49. data/lib/origami.rb +29 -42
  50. data/lib/origami/3d.rb +350 -225
  51. data/lib/origami/acroform.rb +262 -288
  52. data/lib/origami/actions.rb +268 -288
  53. data/lib/origami/annotations.rb +697 -722
  54. data/lib/origami/array.rb +258 -184
  55. data/lib/origami/boolean.rb +74 -84
  56. data/lib/origami/catalog.rb +397 -434
  57. data/lib/origami/collections.rb +144 -0
  58. data/lib/origami/destinations.rb +233 -194
  59. data/lib/origami/dictionary.rb +253 -232
  60. data/lib/origami/encryption.rb +1274 -1243
  61. data/lib/origami/export.rb +232 -268
  62. data/lib/origami/extensions/fdf.rb +307 -220
  63. data/lib/origami/extensions/ppklite.rb +368 -435
  64. data/lib/origami/filespec.rb +197 -0
  65. data/lib/origami/filters.rb +301 -295
  66. data/lib/origami/filters/ascii.rb +177 -180
  67. data/lib/origami/filters/ccitt.rb +528 -535
  68. data/lib/origami/filters/crypt.rb +26 -35
  69. data/lib/origami/filters/dct.rb +46 -52
  70. data/lib/origami/filters/flate.rb +95 -94
  71. data/lib/origami/filters/jbig2.rb +49 -55
  72. data/lib/origami/filters/jpx.rb +38 -44
  73. data/lib/origami/filters/lzw.rb +189 -183
  74. data/lib/origami/filters/predictors.rb +221 -235
  75. data/lib/origami/filters/runlength.rb +103 -104
  76. data/lib/origami/font.rb +173 -186
  77. data/lib/origami/functions.rb +67 -81
  78. data/lib/origami/graphics.rb +25 -21
  79. data/lib/origami/graphics/colors.rb +178 -187
  80. data/lib/origami/graphics/instruction.rb +79 -85
  81. data/lib/origami/graphics/path.rb +142 -148
  82. data/lib/origami/graphics/patterns.rb +160 -167
  83. data/lib/origami/graphics/render.rb +43 -50
  84. data/lib/origami/graphics/state.rb +138 -153
  85. data/lib/origami/graphics/text.rb +188 -205
  86. data/lib/origami/graphics/xobject.rb +819 -815
  87. data/lib/origami/header.rb +63 -78
  88. data/lib/origami/javascript.rb +596 -597
  89. data/lib/origami/linearization.rb +285 -290
  90. data/lib/origami/metadata.rb +139 -148
  91. data/lib/origami/name.rb +112 -148
  92. data/lib/origami/null.rb +53 -62
  93. data/lib/origami/numeric.rb +162 -175
  94. data/lib/origami/obfuscation.rb +186 -174
  95. data/lib/origami/object.rb +593 -573
  96. data/lib/origami/outline.rb +42 -47
  97. data/lib/origami/outputintents.rb +73 -82
  98. data/lib/origami/page.rb +703 -592
  99. data/lib/origami/parser.rb +238 -290
  100. data/lib/origami/parsers/fdf.rb +41 -33
  101. data/lib/origami/parsers/pdf.rb +75 -95
  102. data/lib/origami/parsers/pdf/lazy.rb +137 -0
  103. data/lib/origami/parsers/pdf/linear.rb +64 -66
  104. data/lib/origami/parsers/ppklite.rb +34 -70
  105. data/lib/origami/pdf.rb +1030 -1005
  106. data/lib/origami/reference.rb +102 -102
  107. data/lib/origami/signature.rb +591 -609
  108. data/lib/origami/stream.rb +668 -551
  109. data/lib/origami/string.rb +397 -373
  110. data/lib/origami/template/patterns.rb +56 -0
  111. data/lib/origami/template/widgets.rb +151 -0
  112. data/lib/origami/trailer.rb +144 -158
  113. data/lib/origami/tree.rb +62 -0
  114. data/lib/origami/version.rb +23 -0
  115. data/lib/origami/webcapture.rb +88 -79
  116. data/lib/origami/xfa.rb +2863 -2882
  117. data/lib/origami/xreftable.rb +472 -384
  118. data/test/dataset/calc.pdf +85 -0
  119. data/test/dataset/crypto.pdf +82 -0
  120. data/test/dataset/empty.pdf +49 -0
  121. data/test/test_actions.rb +27 -0
  122. data/test/test_annotations.rb +90 -0
  123. data/test/test_pages.rb +31 -0
  124. data/test/test_pdf.rb +16 -0
  125. data/test/test_pdf_attachment.rb +34 -0
  126. data/test/test_pdf_create.rb +24 -0
  127. data/test/test_pdf_encrypt.rb +95 -0
  128. data/test/test_pdf_parse.rb +96 -0
  129. data/test/test_pdf_sign.rb +58 -0
  130. data/test/test_streams.rb +182 -0
  131. data/test/test_xrefs.rb +67 -0
  132. metadata +88 -58
  133. data/README +0 -67
  134. data/bin/pdf2graph +0 -121
  135. data/bin/pdfcocoon +0 -104
  136. data/lib/origami/file.rb +0 -233
  137. data/samples/README.txt +0 -45
  138. data/samples/actions/launch/calc.rb +0 -87
  139. data/samples/actions/launch/winparams.rb +0 -22
  140. data/samples/actions/loop/loopgoto.rb +0 -24
  141. data/samples/actions/loop/loopnamed.rb +0 -21
  142. data/samples/actions/named/named.rb +0 -31
  143. data/samples/actions/samba/smbrelay.rb +0 -26
  144. data/samples/actions/webbug/submitform.js +0 -26
  145. data/samples/actions/webbug/webbug-browser.rb +0 -68
  146. data/samples/actions/webbug/webbug-js.rb +0 -67
  147. data/samples/actions/webbug/webbug-reader.rb +0 -90
  148. data/samples/attachments/attach.rb +0 -40
  149. data/samples/attachments/attached.txt +0 -1
  150. data/samples/crypto/crypto.rb +0 -28
  151. data/samples/digsig/signed.rb +0 -46
  152. data/samples/exploits/cve-2008-2992-utilprintf.rb +0 -87
  153. data/samples/exploits/cve-2009-0927-geticon.rb +0 -65
  154. data/samples/exploits/exploit_customdictopen.rb +0 -55
  155. data/samples/exploits/getannots.rb +0 -69
  156. data/samples/flash/flash.rb +0 -31
  157. data/samples/javascript/attached.txt +0 -1
  158. data/samples/javascript/js.rb +0 -52
  159. data/templates/patterns.rb +0 -66
  160. data/templates/widgets.rb +0 -173
  161. data/templates/xdp.rb +0 -92
  162. data/test/ts_pdf.rb +0 -50
@@ -1,90 +1,75 @@
1
1
  =begin
2
2
 
3
- = File
4
- header.rb
5
-
6
- = Info
7
- This file is part of Origami, PDF manipulation framework for Ruby
8
- Copyright (C) 2010 Guillaume Delugré <guillaume AT security-labs DOT org>
9
- All right reserved.
10
-
11
- Origami is free software: you can redistribute it and/or modify
12
- it under the terms of the GNU Lesser General Public License as published by
13
- the Free Software Foundation, either version 3 of the License, or
14
- (at your option) any later version.
15
-
16
- Origami is distributed in the hope that it will be useful,
17
- but WITHOUT ANY WARRANTY; without even the implied warranty of
18
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
- GNU Lesser General Public License for more details.
20
-
21
- You should have received a copy of the GNU Lesser General Public License
22
- along with Origami. If not, see <http://www.gnu.org/licenses/>.
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/>.
23
18
 
24
19
  =end
25
20
 
26
21
  module Origami
27
-
28
- class PDF
29
22
 
30
- class InvalidHeaderError < Exception #:nodoc:
31
- end
23
+ class PDF
24
+
25
+ class InvalidHeaderError < Error #:nodoc:
26
+ end
27
+
28
+ #
29
+ # Class representing a PDF Header.
30
+ #
31
+ class Header
32
+ MAGIC = /%PDF-(?<major>\d+)\.(?<minor>\d+)/
33
+
34
+ attr_accessor :major_version, :minor_version
35
+
36
+ #
37
+ # Creates a file header, with the given major and minor versions.
38
+ # _major_version_:: Major PDF version, must be 1.
39
+ # _minor_version_:: Minor PDF version, must be between 0 and 7.
40
+ #
41
+ def initialize(major_version = 1, minor_version = 4)
42
+ @major_version, @minor_version = major_version, minor_version
43
+ end
44
+
45
+ def self.parse(stream) #:nodoc:
46
+ unless stream.scan(MAGIC).nil?
47
+ maj = stream['major'].to_i
48
+ min = stream['minor'].to_i
49
+ else
50
+ raise InvalidHeaderError, "Invalid header format : #{stream.peek(15).inspect}"
51
+ end
52
+
53
+ stream.skip(REGEXP_WHITESPACES)
54
+
55
+ PDF::Header.new(maj, min)
56
+ end
57
+
58
+ #
59
+ # Outputs self into PDF code.
60
+ #
61
+ def to_s
62
+ "%PDF-#{@major_version}.#{@minor_version}".b + EOL
63
+ end
64
+
65
+ def to_sym #:nodoc:
66
+ "#{@major_version}.#{@minor_version}".to_sym
67
+ end
32
68
 
33
- #
34
- # Class representing a PDF Header.
35
- #
36
- class Header
37
-
38
- MINVERSION = 0
39
- MAXVERSION = 7
40
-
41
- MAGIC = /%PDF-(\d+)\.(\d+)/
42
-
43
- attr_accessor :majorversion, :minorversion
44
-
45
- #
46
- # Creates a file header, with the given major and minor versions.
47
- # _majorversion_:: Major PDF version, must be 1.
48
- # _minorversion_:: Minor PDF version, must be between 0 and 7.
49
- #
50
- def initialize(majorversion = 1, minorversion = 4)
51
-
52
- #if majorversion.to_i != 1 || ! ((MINVERSION..MAXVERSION) === minorversion.to_i)
53
- # Console.colorprint("[info ] Warning: Invalid file version : #{majorversion}.#{minorversion}\n", Console::Colors::YELLOW, false, STDERR)
54
- #end
55
-
56
- @majorversion, @minorversion = majorversion, minorversion
57
- end
58
-
59
- def self.parse(stream) #:nodoc:
60
-
61
- if not stream.scan(MAGIC).nil?
62
- maj = stream[1].to_i
63
- min = stream[2].to_i
64
- else
65
- raise InvalidHeaderError, "Invalid header format : #{stream.peek(15).inspect}"
69
+ def to_f #:nodoc:
70
+ to_sym.to_s.to_f
71
+ end
66
72
  end
67
-
68
- PDF::Header.new(maj,min)
69
- end
70
-
71
- #
72
- # Outputs self into PDF code.
73
- #
74
- def to_s
75
- "%PDF-#{@majorversion}.#{@minorversion}" + EOL
76
- end
77
-
78
- def to_sym #:nodoc:
79
- "#{@majorversion}.#{@minorversion}".to_sym
80
- end
81
-
82
- def to_f #:nodoc:
83
- to_sym.to_s.to_f
84
- end
85
-
86
73
  end
87
74
 
88
- end
89
-
90
75
  end
@@ -1,694 +1,693 @@
1
1
  =begin
2
2
 
3
- = File
4
- javascript.rb
5
-
6
- = Info
7
- This file is part of Origami, PDF manipulation framework for Ruby
8
- Copyright (C) 2010 Guillaume Delugré <guillaume AT security-labs DOT org>
9
- All right reserved.
10
-
11
- Origami is free software: you can redistribute it and/or modify
12
- it under the terms of the GNU Lesser General Public License as published by
13
- the Free Software Foundation, either version 3 of the License, or
14
- (at your option) any later version.
15
-
16
- Origami is distributed in the hope that it will be useful,
17
- but WITHOUT ANY WARRANTY; without even the implied warranty of
18
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
- GNU Lesser General Public License for more details.
20
-
21
- You should have received a copy of the GNU Lesser General Public License
22
- along with Origami. If not, see <http://www.gnu.org/licenses/>.
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/>.
23
18
 
24
19
  =end
25
20
 
26
21
  module Origami
27
22
 
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
23
+ begin
24
+ require 'v8'
25
+
26
+ class V8::Object
27
+ #def inspect
28
+ # case self
29
+ # when V8::Array,V8::Function then super
30
+ # else
31
+ # "{#{self.to_a.map{|k,v| "#{k}:#{v.inspect}"}.join(', ')}}"
32
+ # end
33
+ #end
34
+ end
40
35
 
41
- class PDF
42
-
43
- module JavaScript
36
+ class PDF
44
37
 
45
- module Platforms
46
- WINDOWS = "WIN"
47
- UNIX = "UNIX"
48
- MAC = "MAC"
49
- end
38
+ module JavaScript
39
+ module Platforms
40
+ WINDOWS = "WIN"
41
+ UNIX = "UNIX"
42
+ MAC = "MAC"
43
+ end
50
44
 
51
- module Viewers
52
- ADOBE_READER = "Reader"
53
- end
45
+ module Viewers
46
+ ADOBE_READER = "Reader"
47
+ end
54
48
 
55
- class MissingArgError < Exception
56
- def initialize; super("Missing required argument.") end
57
- end
49
+ class Error < Origami::Error; end
58
50
 
59
- class TypeError < Exception
60
- def initialize; super("Incorrect argument type.") end
61
- end
51
+ class MissingArgError < Error
52
+ def initialize; super("Missing required argument.") end
53
+ end
62
54
 
63
- class InvalidArgsError < Exception
64
- def initialize; super("Incorrect arguments.") end
65
- end
55
+ class TypeError < Error
56
+ def initialize; super("Incorrect argument type.") end
57
+ end
66
58
 
67
- class NotAllowedError < Exception
68
- def initialize; super("Security settings prevent access to this property or method.") end
69
- end
59
+ class InvalidArgsError < Error
60
+ def initialize; super("Incorrect arguments.") end
61
+ end
70
62
 
71
- class HelpError < Exception
72
- def initialize; super("Help") end
73
- end
63
+ class NotAllowedError < Error
64
+ def initialize; super("Security settings prevent access to this property or method.") end
65
+ end
74
66
 
75
- class GeneralError < Exception
76
- def initialize; super("Operation failed.") end
77
- end
67
+ class HelpError < Error
68
+ def initialize; super("Help") end
69
+ end
78
70
 
79
- class Arg
80
- attr_reader :name, :type, :required, :default
81
-
82
- def initialize(declare = {})
83
- @name = declare[:name]
84
- @type = declare[:type]
85
- @required = declare[:required]
86
- @default = declare[:default]
87
- end
88
-
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
-
104
- end
71
+ class GeneralError < Error
72
+ def initialize; super("Operation failed.") end
73
+ end
105
74
 
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
75
+ class Arg
76
+ attr_reader :name, :type, :required, :default
77
+
78
+ def initialize(declare = {})
79
+ @name = declare[:name]
80
+ @type = declare[:type]
81
+ @required = declare[:required]
82
+ @default = declare[:default]
83
+ end
84
+
85
+ def self.[](declare = {})
86
+ self.new(declare)
87
+ end
88
+
89
+ def self.inspect(obj)
90
+ case obj
91
+ when V8::Function then "function #{obj.name}"
92
+ when V8::Array then obj.to_a.inspect
93
+ when V8::Object
94
+ "{#{obj.to_a.map{|k,v| "#{k}:#{Arg.inspect(v)}"}.join(', ')}}"
95
+ else
96
+ obj.inspect
97
+ end
98
+ end
124
99
  end
125
100
 
126
- argv.push(arg)
127
- end
101
+ class AcrobatObject
102
+ def initialize(engine)
103
+ @engine = engine
104
+ end
128
105
 
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)
106
+ def self.check_method_args(args, def_args)
107
+ if args.first.is_a?(V8::Object)
108
+ args = args.first
109
+ members = args.entries.map{|k,v| k}
110
+ argv = []
111
+ def_args.each do |def_arg|
112
+ raise MissingArgError if def_arg.required and not members.include?(def_arg.name)
113
+
114
+ if members.include?(def_arg.name)
115
+ arg = args[def_arg.name]
116
+ raise TypeError if def_arg.type and not arg.is_a?(def_arg.type)
117
+ else
118
+ arg = def_arg.default
119
+ end
120
+
121
+ argv.push(arg)
122
+ end
123
+
124
+ args = argv
125
+ else
126
+ i = 0
127
+ def_args.each do |def_arg|
128
+ raise MissingArgError if def_arg.required and i >= args.length
129
+ raise TypeError if def_arg.type and not args[i].is_a?(def_arg.type)
130
+
131
+ args.push(def_arg.default) if i >= args.length
132
+
133
+ i = i + 1
134
+ end
135
+ end
136
+
137
+ args
138
+ end
135
139
 
136
- args.push(def_arg.default) if i >= args.length
140
+ def self.acro_method(name, *def_args, &b)
141
+ define_method(name) do |*args|
142
+ if @engine.options[:log_method_calls]
143
+ @engine.options[:console].puts(
144
+ "LOG: #{self.class}.#{name}(#{args.map{|arg| Arg.inspect(arg)}.join(',')})"
145
+ )
146
+ end
147
+
148
+ args = AcrobatObject.check_method_args(args, def_args)
149
+ self.instance_exec(*args, &b) if b
150
+ end
151
+ end
137
152
 
138
- i = i + 1
139
- end
140
- end
153
+ def self.acro_method_protected(name, *def_args, &b)
154
+ define_method(name) do |*args|
155
+ if @engine.options[:log_method_calls]
156
+ @engine.options[:console].puts(
157
+ "LOG: #{self.class}.#{name}(#{args.map{|arg| arg.inspect}.join(',')})"
158
+ )
159
+ end
141
160
 
142
- args
143
- 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
161
+ raise NotAllowedError
157
162
 
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
163
+ args = AcrobatObject.check_method_args(args, def_args)
164
+ self.instance_exec(*args, &b) if b
165
+ end
166
+ end
165
167
 
166
- raise NotAllowedError
168
+ def to_s
169
+ "[object #{self.class.to_s.split('::').last}]"
170
+ end
171
+ alias inspect to_s
172
+ end
167
173
 
168
- args = AcrobatObject.check_method_args(args, def_args)
169
- self.instance_exec(*args, &b) if b
170
- end
171
- end
172
-
173
- def to_s
174
- "[object #{self.class.to_s.split('::').last}]"
175
- end
176
- alias inspect to_s
177
-
178
- end
174
+ class AcroTimer < AcrobatObject
175
+ def initialize(engine, timeout, code, repeat)
176
+ @thr = Thread.start(engine, timeout, code, repeat) do
177
+ loop do
178
+ sleep(timeout / 1000.0)
179
+ engine.exec(code)
180
+ break if not repeat
181
+ end
182
+ end
183
+ end
184
+ end
179
185
 
180
- class AcroTimer < AcrobatObject
181
- def initialize(engine, timeout, code, repeat)
186
+ class TimeOut < AcroTimer
187
+ def initialize(engine, timeout, code)
188
+ super(engine, timeout, code, false)
189
+ end
190
+ end
182
191
 
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
189
- end
190
- end
191
- end
192
+ class Interval < AcroTimer
193
+ def initialize(engine, timeout, code)
194
+ super(engine, timeout, code, true)
195
+ end
196
+ end
192
197
 
193
- class TimeOut < AcroTimer
194
- def initialize(engine, timeout, code)
195
- super(engine, timeout, code, false)
196
- end
197
- end
198
+ class ReadStream < AcrobatObject
199
+ def initialize(engine, data)
200
+ super(engine)
198
201
 
199
- class Interval < AcroTimer
200
- def initialize(engine, timeout, code)
201
- super(engine, timeout, code, true)
202
- end
203
- end
202
+ @data = data
203
+ end
204
204
 
205
- class ReadStream < AcrobatObject
206
- def initialize(engine, data)
207
- super(engine)
205
+ acro_method 'read', Arg[name: 'nBytes', type: Numeric, required: true] do |nBytes|
206
+ @data.slice!(0, nBytes).unpack("H*")[0]
207
+ end
208
+ end
208
209
 
209
- @data = data
210
- end
210
+ class Acrohelp < AcrobatObject; end
211
211
 
212
- acro_method 'read',
213
- Arg[:name => 'nBytes', :type => Numeric, :required => true] do |nBytes|
214
- @data.slice!(0, nBytes).unpack("H*")[0]
215
- end
216
- end
212
+ class Global < AcrobatObject
213
+ def initialize(engine)
214
+ super(engine)
217
215
 
218
- class Acrohelp < AcrobatObject; end
216
+ @vars = {}
217
+ end
219
218
 
220
- class Global < AcrobatObject
221
- def initialize(engine)
222
- super(engine)
219
+ def []=(name, value)
220
+ @vars[name] ||= {callbacks: []}
221
+ @vars[name][:value] = value
222
+ @vars[name][:callbacks].each do |callback|
223
+ callback.call(value)
224
+ end
225
+ end
223
226
 
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
227
+ def [](name)
228
+ @vars[name][:value] if @vars.include?(name)
229
+ end
234
230
 
235
- def [](name)
236
- @vars[name][:value] if @vars.include?(name)
237
- end
231
+ acro_method 'setPersistent',
232
+ Arg[name: 'cVariable', required: true],
233
+ Arg[name: 'bPersist', required: true] do |cVariable, bPersist|
238
234
 
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
235
+ raise GeneralError unless @vars.include?(cVariable)
236
+ end
244
237
 
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
253
- end
238
+ acro_method 'subscribe',
239
+ Arg[name: 'cVariable', required: true],
240
+ Arg[name: 'fCallback', type: V8::Function, require: true] do |cVariable, fCallback|
254
241
 
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
274
- end
275
-
276
- def initialize(*args)
277
- engine, pdf = args # XXX: Bypass therubyracer bug #238. Temporary.
278
- super(engine)
279
-
280
- @pdf = pdf
281
- @disclosed = false
282
- @hidden = false
283
- @info = Info.new(@engine, pdf)
284
- end
285
-
286
- ### PROPERTIES ###
287
-
288
- def numFields
289
- fields = @pdf.fields
290
- if fields.nil?
291
- 0
292
- else
293
- fields.size
294
- end
295
- end
242
+ if @vars.include?(cVariable)
243
+ @vars[cVariable][:callbacks].push(fCallback)
244
+ fCallback.call(@vars[cVariable][:value])
245
+ end
246
+ end
247
+ end
296
248
 
297
- def numPages; @pdf.pages.size end
249
+ class Doc < AcrobatObject
250
+ attr_reader :info
251
+ attr_accessor :disclosed
252
+ attr_reader :hidden
298
253
 
299
- def title; @info.title end
300
- def author; @info.author end
301
- def subject; @info.subject end
302
- def keywords; @info.keywords end
303
- def creator; @info.creator end
304
- def creationDate; @info.creationDate end
305
- def modDate; @info.modDate end
254
+ attr_reader :app, :acrohelp, :global, :console, :util
306
255
 
307
- def metadata
308
- meta = @pdf.Catalog.Metadata
256
+ class Info < AcrobatObject
257
+ def initialize(engine, doc)
258
+ super(engine)
309
259
 
310
- (meta.data if meta.is_a?(Stream)).to_s
311
- end
260
+ @doc = doc
261
+ end
312
262
 
313
- def filesize; @pdf.original_filesize end
314
- def path; @pdf.original_filename.to_s end
315
- def documentFileName; File.basename(self.path) end
316
- def URL; "file://#{self.path}" end
317
- def baseURL; '' end
263
+ def title; @doc.title.to_s end
264
+ def author; @doc.author.to_s end
265
+ def subject; @doc.subject.to_s end
266
+ def keywords; @doc.keywords.to_s end
267
+ def creator; @doc.creator.to_s end
268
+ def creationDate; @doc.creation_date.to_s end
269
+ def modDate; @doc.mod_date.to_s end
270
+ end
318
271
 
319
- def dataObjects
320
- data_objs = []
321
- @pdf.ls_names(Names::Root::EMBEDDEDFILES).each do |name, file_desc|
322
- if file_desc and file_desc.EF and (f = file_desc.EF.F)
323
- data_objs.push Data.new(@engine, name, f.data.size) if f.is_a?(Stream)
324
- end
272
+ def initialize(*args)
273
+ engine, pdf = args # XXX: Bypass therubyracer bug #238. Temporary.
274
+ super(engine)
325
275
 
326
- end
327
-
328
- data_objs
329
- end
330
-
331
- ### METHODS ###
332
-
333
- acro_method 'closeDoc'
334
-
335
- acro_method 'getDataObject',
336
- Arg[:name => 'cName', :type => ::String, :required => true] do |cName|
337
- file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
338
-
339
- if file_desc and file_desc.EF and (f = file_desc.EF.F)
340
- Data.new(@engine, cName, f.data.size) if f.is_a?(Stream)
341
- else raise TypeError
342
- end
343
- end
276
+ @pdf = pdf
277
+ @disclosed = false
278
+ @hidden = false
279
+ @info = Info.new(@engine, pdf)
280
+
281
+ @app = JavaScript::App.new(@engine)
282
+ @acrohelp = JavaScript::Acrohelp.new(@engine)
283
+ @global = JavaScript::Global.new(@engine)
284
+ @console = JavaScript::Console.new(@engine)
285
+ @util = JavaScript::Util.new(@engine)
286
+ end
344
287
 
345
- acro_method 'getDataObjectContents',
346
- Arg[:name => 'cName', :type => ::String, :required => true],
347
- Arg[:name => 'bAllowAuth', :default => false] do |cName, bAllowAuth|
348
- file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
288
+ ### PROPERTIES ###
349
289
 
350
- if file_desc and file_desc.EF and (f = file_desc.EF.F)
351
- ReadStream.new(@engine, f.data) if f.is_a?(Stream)
352
- else raise TypeError
353
- end
354
- end
290
+ def numFields
291
+ fields = @pdf.fields
355
292
 
356
- acro_method 'exportDataObject',
357
- Arg[:name => 'cName', :type => ::String, :required => true],
358
- Arg[:name => 'cDIPath' ],
359
- Arg[:name => 'bAllowAuth'],
360
- Arg[:name => 'nLaunch'] do |cName, cDIPath, bAllowAuth, nLaunch|
361
- file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName)
293
+ fields.size
294
+ end
362
295
 
363
- if file_desc and file_desc.EF and (f = file_desc.EF.F)
364
- else raise TypeError
365
- end
296
+ def numPages; @pdf.pages.size end
366
297
 
367
- raise TypeError if f.nil?
368
- end
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
369
305
 
370
- acro_method 'getField',
371
- Arg[:name => 'cName', :type => ::Object, :required => true] do |cName|
372
- field = @pdf.get_field(cName)
306
+ def metadata
307
+ meta = @pdf.Catalog.Metadata
373
308
 
374
- Field.new(@engine, field) if field
375
- end
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.each_attachment do |name, file_desc|
321
+ if file_desc and file_desc.EF and (f = file_desc.EF.F)
322
+ data_objs.push Data.new(@engine, name, f.data.size) if f.is_a?(Stream)
323
+ end
324
+ end
325
+
326
+ data_objs
327
+ end
328
+
329
+ ### METHODS ###
330
+
331
+ acro_method 'closeDoc'
332
+
333
+ acro_method 'getDataObject',
334
+ Arg[name: 'cName', type: ::String, required: true] do |cName|
335
+
336
+ file_desc = @pdf.resolve_name(Names::EMBEDDED_FILES, cName)
337
+
338
+ if file_desc and file_desc.EF and (f = file_desc.EF.F)
339
+ Data.new(@engine, cName, f.data.size) if f.is_a?(Stream)
340
+ else
341
+ raise TypeError
342
+ end
343
+ end
344
+
345
+ acro_method 'getDataObjectContents',
346
+ Arg[name: 'cName', type: ::String, required: true],
347
+ Arg[name: 'bAllowAuth', default: false] do |cName, bAllowAuth|
348
+
349
+ file_desc = @pdf.resolve_name(Names::EMBEDDED_FILES, cName)
350
+
351
+ if file_desc and file_desc.EF and (f = file_desc.EF.F)
352
+ ReadStream.new(@engine, f.data) if f.is_a?(Stream)
353
+ else
354
+ raise TypeError
355
+ end
356
+ end
357
+
358
+ acro_method 'exportDataObject',
359
+ Arg[name: 'cName', type: ::String, required: true],
360
+ Arg[name: 'cDIPath' ],
361
+ Arg[name: 'bAllowAuth'],
362
+ Arg[name: 'nLaunch'] do |cName, cDIPath, bAllowAuth, nLaunch|
363
+
364
+ file_desc = @pdf.resolve_name(Names::EMBEDDED_FILES, cName)
365
+
366
+ if file_desc and file_desc.EF and (f = file_desc.EF.F)
367
+ else
368
+ raise TypeError
369
+ end
370
+
371
+ raise TypeError if f.nil?
372
+ end
376
373
 
377
- acro_method 'getNthFieldName',
378
- Arg[:name => 'nIndex', :type => ::Object, :required => true] do |nIndex|
379
- nIndex =
380
- case nIndex
381
- when false then 0
382
- when true then 1
383
- else
384
- @engine.parseInt.call(nIndex)
374
+ acro_method 'getField',
375
+ Arg[name: 'cName', type: ::Object, required: true] do |cName|
376
+
377
+ field = @pdf.get_field(cName)
378
+
379
+ Field.new(@engine, field) if field
380
+ end
381
+
382
+ acro_method 'getNthFieldName',
383
+ Arg[name: 'nIndex', type: ::Object, required: true] do |nIndex|
384
+
385
+ nIndex =
386
+ case nIndex
387
+ when false then 0
388
+ when true then 1
389
+ else
390
+ @engine.parseInt.call(nIndex)
391
+ end
392
+
393
+ raise TypeError if (nIndex.is_a?(Float) and nIndex.nan?) or nIndex < 0
394
+ fields = @pdf.fields
395
+
396
+ if fields and nIndex <= fields.size - 1
397
+ Field.new(@engine, fields.take(nIndex + 1).last).name.to_s
398
+ else
399
+ ""
400
+ end
401
+ end
385
402
  end
386
403
 
387
- raise TypeError if (nIndex.is_a?(Float) and nIndex.nan?) or nIndex < 0
388
- fields = @pdf.fields
404
+ class App < AcrobatObject
389
405
 
390
- (Field.new(@engine, fields[nIndex]).name if fields and fields[nIndex]).to_s
391
- end
392
- end
406
+ def platform; @engine.options[:platform] end
407
+ def viewerType; @engine.options[:viewerType] end
408
+ def viewerVariation; @engine.options[:viewerVariation] end
409
+ def viewerVersion; @engine.options[:viewerVersion] end
393
410
 
394
- class App < AcrobatObject
395
- attr_reader :platform, :viewerVariation, :viewerVersion
411
+ def activeDocs; [] end
396
412
 
397
- def platform; @engine.options[:platform] end
398
- def viewerType; @engine.options[:viewerType] end
399
- def viewerVariation; @engine.options[:viewerVariation] end
400
- def viewerVersion; @engine.options[:viewerVersion] end
413
+ ### METHODS ###
401
414
 
402
- def activeDocs; [] end
415
+ acro_method 'setInterval',
416
+ Arg[name: 'cExpr', required: true],
417
+ Arg[name: 'nMilliseconds', type: Numeric, required: true] do |cExpr, nMilliseconds|
403
418
 
404
- ### METHODS ###
405
-
406
- acro_method 'setInterval',
407
- Arg[:name => 'cExpr', :required => true],
408
- Arg[:name => 'nMilliseconds', :type => Numeric, :required => true] do |cExpr, nMilliseconds|
409
- cExpr = cExpr.is_a?(::String) ? cExpr : ''
410
- Interval.new(@engine, nMilliseconds, cExpr)
411
- end
419
+ cExpr = cExpr.is_a?(::String) ? cExpr : ''
420
+ Interval.new(@engine, nMilliseconds, cExpr)
421
+ end
412
422
 
413
- acro_method 'setTimeOut',
414
- Arg[:name => 'cExpr', :required => true],
415
- Arg[:name => 'nMilliseconds', :type => Numeric, :required => true] do |cExpr, nMilliseconds|
416
- cExpr = cExpr.is_a?(::String) ? cExpr : ''
417
- TimeOut.new(@engine, nMilliseconds, cExpr)
418
- end
423
+ acro_method 'setTimeOut',
424
+ Arg[name: 'cExpr', required: true],
425
+ Arg[name: 'nMilliseconds', type: Numeric, required: true] do |cExpr, nMilliseconds|
419
426
 
420
- acro_method 'clearInterval',
421
- Arg[:name => 'oInterval', :type => Interval, :required => true] do |oInterval|
422
- oInterval.instance_variable_get(:@thr).terminate
423
- nil
424
- end
427
+ cExpr = cExpr.is_a?(::String) ? cExpr : ''
428
+ TimeOut.new(@engine, nMilliseconds, cExpr)
429
+ end
425
430
 
426
- acro_method 'clearTimeOut',
427
- Arg[:name => 'oInterval', :type => TimeOut, :required => true] do |oInterval|
428
- oInterval.instance_variable_get(:@thr).terminate
429
- nil
430
- end
431
+ acro_method 'clearInterval',
432
+ Arg[name: 'oInterval', type: Interval, required: true] do |oInterval|
431
433
 
432
- acro_method_protected 'addMenuItem'
433
- acro_method_protected 'addSubMenu'
434
- acro_method 'addToolButton'
435
- acro_method_protected 'beginPriv'
436
- acro_method 'beep'
437
- acro_method_protected 'browseForDoc'
438
- acro_method_protected 'endPriv'
439
- end
434
+ oInterval.instance_variable_get(:@thr).terminate
435
+ nil
436
+ end
440
437
 
441
- class Console < AcrobatObject
442
- def println(*args)
443
- raise MissingArgError unless args.length > 0
438
+ acro_method 'clearTimeOut',
439
+ Arg[name: 'oInterval', type: TimeOut, required: true] do |oInterval|
444
440
 
445
- @engine.options[:console].puts(args.first.to_s)
446
- end
441
+ oInterval.instance_variable_get(:@thr).terminate
442
+ nil
443
+ end
447
444
 
448
- acro_method 'show'
449
- acro_method 'clear'
450
- acro_method 'hide'
451
- end
445
+ acro_method_protected 'addMenuItem'
446
+ acro_method_protected 'addSubMenu'
447
+ acro_method 'addToolButton'
448
+ acro_method_protected 'beginPriv'
449
+ acro_method 'beep'
450
+ acro_method_protected 'browseForDoc'
451
+ acro_method_protected 'endPriv'
452
+ end
452
453
 
453
- class Util < AcrobatObject
454
- acro_method 'streamFromString',
455
- Arg[:name => 'cString', :type => ::Object, :required => true],
456
- Arg[:name => 'cCharset', :type => ::Object, :default => 'utf-8'] do |cString, cCharset|
454
+ class Console < AcrobatObject
455
+ def println(*args)
456
+ raise MissingArgError unless args.length > 0
457
+
458
+ @engine.options[:console].puts(args.first.to_s)
459
+ end
457
460
 
458
- ReadStream.new(@engine, cString.to_s)
459
- end
461
+ acro_method 'show'
462
+ acro_method 'clear'
463
+ acro_method 'hide'
464
+ end
465
+
466
+ class Util < AcrobatObject
467
+ acro_method 'streamFromString',
468
+ Arg[name: 'cString', type: ::Object, required: true],
469
+ Arg[name: 'cCharset', type: ::Object, default: 'utf-8'] do |cString, cCharset|
470
+
471
+ ReadStream.new(@engine, cString.to_s)
472
+ end
473
+
474
+ acro_method 'stringFromStream',
475
+ Arg[name: 'oStream', type: ReadStream, required: true],
476
+ Arg[name: 'cCharset', type: ::Object, default: 'utf-8'] do |oStream, cCharset|
477
+
478
+ oStream.instance_variable_get(:@data).dup
479
+ end
480
+ end
481
+
482
+ class Field < AcrobatObject
483
+ def initialize(engine, field)
484
+ super(engine)
460
485
 
461
- acro_method 'stringFromStream',
462
- Arg[:name => 'oStream', :type => ReadStream, :required => true],
463
- Arg[:name => 'cCharset', :type => ::Object, :default => 'utf-8'] do |oStream, cCharset|
486
+ @field = field
487
+ end
488
+
489
+ def doc; Doc.new(@field.document) end
490
+ def name
491
+ (@field.T.value if @field.has_key?(:T)).to_s
492
+ end
464
493
 
465
- oStream.instance_variable_get(:@data).dup
494
+ def value
495
+ @field.V.value if @field.has_key?(:V)
496
+ end
497
+
498
+ def valueAsString
499
+ self.value.to_s
500
+ end
501
+
502
+ def type
503
+ (if @field.has_key?(:FT)
504
+ case @field.FT.value
505
+ when PDF::Field::Type::BUTTON
506
+ if @fields.has_key?(:Ff)
507
+ flags = @field.Ff.value
508
+
509
+ if (flags & Origami::Annotation::Widget::Button::Flags::PUSHBUTTON) != 0
510
+ 'button'
511
+ elsif (flags & Origami::Annotation::Widget::Button::Flags::RADIO) != 0
512
+ 'radiobox'
513
+ else
514
+ 'checkbox'
515
+ end
516
+ end
517
+ when PDF::Field::Type::TEXT then 'text'
518
+ when PDF::Field::Type::SIGNATURE then 'signature'
519
+ when PDF::Field::Type::CHOICE
520
+ if @field.has_key?(:Ff)
521
+ if (@field.Ff.value & Origami::Annotation::Widget::Choice::Flags::COMBO).zero?
522
+ 'listbox'
523
+ else
524
+ 'combobox'
525
+ end
526
+ end
527
+ end
528
+ end).to_s
529
+ end
530
+ end
531
+
532
+ class Data < AcrobatObject
533
+ attr_reader :name, :path, :size
534
+ attr_reader :creationDate, :modDate
535
+ attr_reader :description, :MIMEType
536
+
537
+ def initialize(engine, name, size,
538
+ path: nil,
539
+ creationDate: nil, modDate: nil, description: nil, mimeType: nil)
540
+
541
+ super(engine)
542
+
543
+ @name, @path, @size = name, path, size
544
+ @creationDate, @modDate = creationDate, modDate
545
+ @description, @MIMEType = description, mimeType
546
+ end
547
+ end
466
548
  end
467
- end
468
549
 
469
- class Field < AcrobatObject
470
- def initialize(engine, field)
471
- super(engine)
472
-
473
- @field = field
474
- end
475
-
476
- def doc; Doc.new(@field.pdf) end
477
- def name
478
- (@field.T.value if @field.has_key?(:T)).to_s
479
- end
480
-
481
- def value
482
- @field.V.value if @field.has_key?(:V)
483
- end
484
-
485
- def valueAsString
486
- self.value.to_s
487
- end
488
-
489
- def type
490
- (if @field.has_key?(:FT)
491
- case @field.FT.value
492
- when PDF::Field::Type::BUTTON
493
- if @fields.has_key?(:Ff)
494
- flags = @field.Ff.value
495
-
496
- if (flags & Origami::Annotation::Widget::Button::Flags::PUSHBUTTON) != 0
497
- 'button'
498
- elsif (flags & Origami::Annotation::Widget::Button::Flags::RADIO) != 0
499
- 'radiobox'
500
- else
501
- 'checkbox'
502
- end
503
- end
504
- when PDF::Field::Type::TEXT then 'text'
505
- when PDF::Field::Type::SIGNATURE then 'signature'
506
- when PDF::Field::Type::CHOICE
507
- if @field.has_key?(:Ff)
508
- if (@field.Ff.value & Origami::Annotation::Widget::Choice::Flags::COMBO).zero?
509
- 'listbox'
510
- else
511
- 'combobox'
550
+ class JavaScript::EngineError < Origami::Error; end
551
+
552
+ class JavaScript::Engine
553
+ attr_reader :doc
554
+ attr_reader :context
555
+ attr_reader :options
556
+ attr_reader :parseInt
557
+
558
+ def initialize(pdf)
559
+ @options =
560
+ {
561
+ viewerVersion: 11.008,
562
+ viewerType: JavaScript::Viewers::ADOBE_READER,
563
+ viewerVariation: JavaScript::Viewers::ADOBE_READER,
564
+ platform: JavaScript::Platforms::WINDOWS,
565
+ console: STDOUT,
566
+ log_method_calls: false
567
+ }
568
+
569
+ @doc = JavaScript::Doc.new(self, pdf)
570
+ @context = V8::Context.new(with: @doc)
571
+
572
+ @parseInt = V8::Context.new['parseInt']
573
+ @hooks = {}
574
+ end
575
+
576
+ #
577
+ # Evaluates a JavaScript code in the current context.
578
+ #
579
+ def exec(script)
580
+ @context.eval(script)
581
+ end
582
+
583
+ #
584
+ # Set a hook on a JavaScript method.
585
+ #
586
+ def hook(name, &callback)
587
+ ns = name.split('.')
588
+ previous = @context
589
+
590
+ ns.each do |n|
591
+ raise JavaScript::EngineError, "#{name} does not exist" if previous.nil?
592
+ previous = previous[n]
512
593
  end
513
- end
514
- end
515
- end).to_s
516
- end
517
594
 
518
- end
595
+ case previous
596
+ when V8::Function, UnboundMethod, nil then
597
+ @context[name] = lambda do |*args|
598
+ callback[previous, *args]
599
+ end
519
600
 
520
- class Data < AcrobatObject
521
- attr_reader :name, :path, :size
522
- attr_reader :creationDate, :modDate
523
- attr_reader :description, :MIMEType
601
+ @hooks[name] = [previous, callback]
602
+ else
603
+ raise JavaScript::EngineError, "#{name} is not a function"
604
+ end
605
+ end
524
606
 
525
- def initialize(engine, name, size, path = nil, creationDate = nil, modDate = nil, description = nil, mimeType = nil)
607
+ #
608
+ # Removes an existing hook on a JavaScript method.
609
+ #
610
+ def unhook(name)
611
+ @context[name] = @hooks[name][0] if @hooks.has_key?(name)
612
+ end
526
613
 
527
- super(engine)
614
+ #
615
+ # Returns an Hash of all defined members in specified object name.
616
+ #
617
+ def members(obj)
618
+ members = {}
619
+ list = @context.eval <<-JS
620
+ (function(base) {
621
+ var members = [];
622
+ for (var i in base) members.push([i, base[i]]);
623
+ return members;
624
+ })(#{obj})
625
+ JS
626
+
627
+ list.each do |var|
628
+ members[var[0]] = var[1]
629
+ end
528
630
 
529
- @name, @path, @size = name, path, size
530
- @creationDate, @modDate = creationDate, modDate
531
- @description, @MIMEType = description, mimeType
532
- end
533
- end
631
+ members
632
+ end
534
633
 
535
- end
536
-
537
- class JavaScript::EngineError < Exception; end
538
-
539
- class JavaScript::Engine
540
-
541
- attr_reader :global
542
- attr_reader :context
543
- attr_reader :options
544
- attr_reader :parseInt
545
-
546
- def initialize(pdf)
547
- @options =
548
- {
549
- :viewerVersion => JavaScript::Platforms::WINDOWS,
550
- :viewerType => JavaScript::Viewers::ADOBE_READER,
551
- :viewerVariation => JavaScript::Viewers::ADOBE_READER,
552
- :platform => 9,
553
- :console => STDOUT,
554
- :log_method_calls => false
555
- }
556
-
557
- @global = JavaScript::Doc.new(self, pdf)
558
- app = JavaScript::App.new(self)
559
- acrohelp = JavaScript::Acrohelp.new(self)
560
- global = JavaScript::Global.new(self)
561
- console = JavaScript::Console.new(self)
562
- util = JavaScript::Util.new(self)
563
-
564
- @context = V8::Context.new(:with => @global)
565
- @context['app'] = app
566
- @context['acrohelp'] = acrohelp
567
- @context['console'] = console
568
- @context['global'] = global
569
- @context['util'] = util
570
-
571
- @parseInt = @context['parseInt']
572
- @hooks = {}
573
- end
634
+ #
635
+ # Returns all members in the global scope.
636
+ #
637
+ def scope
638
+ members('this')
639
+ end
574
640
 
575
- #
576
- # Evaluates a JavaScript code in the current context.
577
- #
578
- def exec(script)
579
- @context.eval(script)
580
- end
641
+ #
642
+ # Binds the V8 remote debugging agent on the specified TCP _port_.
643
+ #
644
+ def enable_debugger(port = 5858)
645
+ V8::C::Debug.EnableAgent("Origami", port)
646
+ end
581
647
 
582
- #
583
- # Set a hook on a JavaScript method.
584
- #
585
- def hook(name, &callback)
586
- ns = name.split('.')
587
- previous = @context
588
-
589
- ns.each do |n|
590
- raise JavaScript::EngineError, "#{name} does not exist" if previous.nil?
591
- previous = previous[n]
592
- end
593
-
594
- case previous
595
- when V8::Function, UnboundMethod, nil then
596
- @context[name] = lambda do |*args|
597
- callback[previous, *args]
598
- end
599
-
600
- @hooks[name] = [previous, callback]
601
- else
602
- raise JavaScript::EngineError, "#{name} is not a function"
603
- end
648
+ def debugger_break
649
+ exec 'debugger'
650
+ end
651
+ end
604
652
  end
605
653
 
606
- #
607
- # Removes an existing hook on a JavaScript method.
608
- #
609
- def unhook(name)
610
- if @hooks.has_key?(name)
611
- @context[name] = @hooks[name][0]
612
- end
654
+ module String
655
+ #
656
+ # Evaluates the current String as JavaScript.
657
+ #
658
+ def eval_js
659
+ self.document.eval_js(self.value)
660
+ end
613
661
  end
614
662
 
615
- #
616
- # Returns an Hash of all defined members in specified object name.
617
- #
618
- def members(obj)
619
- members = {}
620
- list = @context.eval <<-JS
621
- (function(base){
622
- var members = [];
623
- for (var i in base) members.push([i, base[i]]);
624
- return members;
625
- })(#{obj})
626
- JS
627
-
628
- list.each do |var|
629
- members[var[0]] = var[1]
630
- end
631
-
632
- members
663
+ class Stream
664
+ #
665
+ # Evaluates the current Stream as JavaScript.
666
+ #
667
+ def eval_js
668
+ self.document.eval_js(self.data)
669
+ end
633
670
  end
634
671
 
635
- #
636
- # Returns all members in the global scope.
637
- #
638
- def scope
639
- members('this')
672
+ class PDF
673
+ #
674
+ # Executes a JavaScript script in the current document context.
675
+ #
676
+ def eval_js(code)
677
+ js_engine.exec(code)
678
+ end
679
+
680
+ #
681
+ # Returns the JavaScript engine (if JavaScript support is present).
682
+ #
683
+ def js_engine
684
+ @js_engine ||= PDF::JavaScript::Engine.new(self)
685
+ end
640
686
  end
641
687
 
688
+ rescue LoadError
642
689
  #
643
- # Binds the V8 remote debugging agent on the specified TCP _port_.
690
+ # V8 unavailable.
644
691
  #
645
- def enable_debugger(port = 5858)
646
- V8::C::Debug.EnableAgent("Origami", port)
647
- end
648
-
649
- def debugger_break
650
- exec 'debugger'
651
- end
652
- end
653
-
654
- end
655
-
656
- module String
657
- #
658
- # Evaluates the current String as JavaScript.
659
- #
660
- def eval_js
661
- self.pdf.eval_js(self.value)
662
- end
663
692
  end
664
-
665
- class Stream
666
- #
667
- # Evaluates the current Stream as JavaScript.
668
- #
669
- def eval_js
670
- self.pdf.eval_js(self.data)
671
- end
672
- end
673
-
674
- class PDF
675
-
676
- #
677
- # Executes a JavaScript script in the current document context.
678
- #
679
- def eval_js(code)
680
- js_engine.exec(code)
681
- end
682
-
683
- #
684
- # Returns the JavaScript engine (if JavaScript support is present).
685
- #
686
- def js_engine
687
- @js_engine ||= PDF::JavaScript::Engine.new(self)
688
- end
689
- end
690
-
691
- rescue LoadError
692
- end
693
693
  end
694
-