origami 1.2.7 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -0
- data/README.md +112 -0
- data/bin/config/pdfcop.conf.yml +232 -233
- data/bin/gui/about.rb +27 -37
- data/bin/gui/config.rb +108 -117
- data/bin/gui/file.rb +416 -365
- data/bin/gui/gtkhex.rb +1138 -1153
- data/bin/gui/hexview.rb +55 -57
- data/bin/gui/imgview.rb +48 -51
- data/bin/gui/menu.rb +388 -386
- data/bin/gui/properties.rb +114 -130
- data/bin/gui/signing.rb +571 -617
- data/bin/gui/textview.rb +77 -95
- data/bin/gui/treeview.rb +382 -387
- data/bin/gui/walker.rb +227 -232
- data/bin/gui/xrefs.rb +56 -60
- data/bin/pdf2pdfa +53 -57
- data/bin/pdf2ruby +212 -228
- data/bin/pdfcop +338 -348
- data/bin/pdfdecompress +58 -65
- data/bin/pdfdecrypt +56 -60
- data/bin/pdfencrypt +75 -80
- data/bin/pdfexplode +185 -182
- data/bin/pdfextract +201 -218
- data/bin/pdfmetadata +83 -82
- data/bin/pdfsh +4 -5
- data/bin/pdfwalker +1 -2
- data/bin/shell/.irbrc +45 -82
- data/bin/shell/console.rb +105 -130
- data/bin/shell/hexdump.rb +40 -64
- data/examples/README.md +34 -0
- data/examples/attachments/attachment.rb +38 -0
- data/examples/attachments/nested_document.rb +51 -0
- data/examples/encryption/encryption.rb +28 -0
- data/{samples/actions/triggerevents/trigger.rb → examples/events/events.rb} +13 -16
- data/examples/flash/flash.rb +37 -0
- data/{samples → examples}/flash/helloworld.swf +0 -0
- data/examples/forms/javascript.rb +54 -0
- data/examples/forms/xfa.rb +115 -0
- data/examples/javascript/hello_world.rb +22 -0
- data/examples/javascript/js_emulation.rb +54 -0
- data/examples/loop/goto.rb +32 -0
- data/examples/loop/named.rb +33 -0
- data/examples/signature/signature.rb +65 -0
- data/examples/uri/javascript.rb +56 -0
- data/examples/uri/open-uri.rb +21 -0
- data/examples/uri/submitform.rb +47 -0
- data/lib/origami.rb +29 -42
- data/lib/origami/3d.rb +350 -225
- data/lib/origami/acroform.rb +262 -288
- data/lib/origami/actions.rb +268 -288
- data/lib/origami/annotations.rb +697 -722
- data/lib/origami/array.rb +258 -184
- data/lib/origami/boolean.rb +74 -84
- data/lib/origami/catalog.rb +397 -434
- data/lib/origami/collections.rb +144 -0
- data/lib/origami/destinations.rb +233 -194
- data/lib/origami/dictionary.rb +253 -232
- data/lib/origami/encryption.rb +1274 -1243
- data/lib/origami/export.rb +232 -268
- data/lib/origami/extensions/fdf.rb +307 -220
- data/lib/origami/extensions/ppklite.rb +368 -435
- data/lib/origami/filespec.rb +197 -0
- data/lib/origami/filters.rb +301 -295
- data/lib/origami/filters/ascii.rb +177 -180
- data/lib/origami/filters/ccitt.rb +528 -535
- data/lib/origami/filters/crypt.rb +26 -35
- data/lib/origami/filters/dct.rb +46 -52
- data/lib/origami/filters/flate.rb +95 -94
- data/lib/origami/filters/jbig2.rb +49 -55
- data/lib/origami/filters/jpx.rb +38 -44
- data/lib/origami/filters/lzw.rb +189 -183
- data/lib/origami/filters/predictors.rb +221 -235
- data/lib/origami/filters/runlength.rb +103 -104
- data/lib/origami/font.rb +173 -186
- data/lib/origami/functions.rb +67 -81
- data/lib/origami/graphics.rb +25 -21
- data/lib/origami/graphics/colors.rb +178 -187
- data/lib/origami/graphics/instruction.rb +79 -85
- data/lib/origami/graphics/path.rb +142 -148
- data/lib/origami/graphics/patterns.rb +160 -167
- data/lib/origami/graphics/render.rb +43 -50
- data/lib/origami/graphics/state.rb +138 -153
- data/lib/origami/graphics/text.rb +188 -205
- data/lib/origami/graphics/xobject.rb +819 -815
- data/lib/origami/header.rb +63 -78
- data/lib/origami/javascript.rb +596 -597
- data/lib/origami/linearization.rb +285 -290
- data/lib/origami/metadata.rb +139 -148
- data/lib/origami/name.rb +112 -148
- data/lib/origami/null.rb +53 -62
- data/lib/origami/numeric.rb +162 -175
- data/lib/origami/obfuscation.rb +186 -174
- data/lib/origami/object.rb +593 -573
- data/lib/origami/outline.rb +42 -47
- data/lib/origami/outputintents.rb +73 -82
- data/lib/origami/page.rb +703 -592
- data/lib/origami/parser.rb +238 -290
- data/lib/origami/parsers/fdf.rb +41 -33
- data/lib/origami/parsers/pdf.rb +75 -95
- data/lib/origami/parsers/pdf/lazy.rb +137 -0
- data/lib/origami/parsers/pdf/linear.rb +64 -66
- data/lib/origami/parsers/ppklite.rb +34 -70
- data/lib/origami/pdf.rb +1030 -1005
- data/lib/origami/reference.rb +102 -102
- data/lib/origami/signature.rb +591 -609
- data/lib/origami/stream.rb +668 -551
- data/lib/origami/string.rb +397 -373
- data/lib/origami/template/patterns.rb +56 -0
- data/lib/origami/template/widgets.rb +151 -0
- data/lib/origami/trailer.rb +144 -158
- data/lib/origami/tree.rb +62 -0
- data/lib/origami/version.rb +23 -0
- data/lib/origami/webcapture.rb +88 -79
- data/lib/origami/xfa.rb +2863 -2882
- data/lib/origami/xreftable.rb +472 -384
- data/test/dataset/calc.pdf +85 -0
- data/test/dataset/crypto.pdf +82 -0
- data/test/dataset/empty.pdf +49 -0
- data/test/test_actions.rb +27 -0
- data/test/test_annotations.rb +90 -0
- data/test/test_pages.rb +31 -0
- data/test/test_pdf.rb +16 -0
- data/test/test_pdf_attachment.rb +34 -0
- data/test/test_pdf_create.rb +24 -0
- data/test/test_pdf_encrypt.rb +95 -0
- data/test/test_pdf_parse.rb +96 -0
- data/test/test_pdf_sign.rb +58 -0
- data/test/test_streams.rb +182 -0
- data/test/test_xrefs.rb +67 -0
- metadata +88 -58
- data/README +0 -67
- data/bin/pdf2graph +0 -121
- data/bin/pdfcocoon +0 -104
- data/lib/origami/file.rb +0 -233
- data/samples/README.txt +0 -45
- data/samples/actions/launch/calc.rb +0 -87
- data/samples/actions/launch/winparams.rb +0 -22
- data/samples/actions/loop/loopgoto.rb +0 -24
- data/samples/actions/loop/loopnamed.rb +0 -21
- data/samples/actions/named/named.rb +0 -31
- data/samples/actions/samba/smbrelay.rb +0 -26
- data/samples/actions/webbug/submitform.js +0 -26
- data/samples/actions/webbug/webbug-browser.rb +0 -68
- data/samples/actions/webbug/webbug-js.rb +0 -67
- data/samples/actions/webbug/webbug-reader.rb +0 -90
- data/samples/attachments/attach.rb +0 -40
- data/samples/attachments/attached.txt +0 -1
- data/samples/crypto/crypto.rb +0 -28
- data/samples/digsig/signed.rb +0 -46
- data/samples/exploits/cve-2008-2992-utilprintf.rb +0 -87
- data/samples/exploits/cve-2009-0927-geticon.rb +0 -65
- data/samples/exploits/exploit_customdictopen.rb +0 -55
- data/samples/exploits/getannots.rb +0 -69
- data/samples/flash/flash.rb +0 -31
- data/samples/javascript/attached.txt +0 -1
- data/samples/javascript/js.rb +0 -52
- data/templates/patterns.rb +0 -66
- data/templates/widgets.rb +0 -173
- data/templates/xdp.rb +0 -92
- data/test/ts_pdf.rb +0 -50
data/lib/origami/header.rb
CHANGED
|
@@ -1,90 +1,75 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
|
31
|
-
|
|
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
|
-
|
|
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
|
data/lib/origami/javascript.rb
CHANGED
|
@@ -1,694 +1,693 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
module JavaScript
|
|
36
|
+
class PDF
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
module JavaScript
|
|
39
|
+
module Platforms
|
|
40
|
+
WINDOWS = "WIN"
|
|
41
|
+
UNIX = "UNIX"
|
|
42
|
+
MAC = "MAC"
|
|
43
|
+
end
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
module Viewers
|
|
46
|
+
ADOBE_READER = "Reader"
|
|
47
|
+
end
|
|
54
48
|
|
|
55
|
-
|
|
56
|
-
def initialize; super("Missing required argument.") end
|
|
57
|
-
end
|
|
49
|
+
class Error < Origami::Error; end
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
class MissingArgError < Error
|
|
52
|
+
def initialize; super("Missing required argument.") end
|
|
53
|
+
end
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
55
|
+
class TypeError < Error
|
|
56
|
+
def initialize; super("Incorrect argument type.") end
|
|
57
|
+
end
|
|
66
58
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
class InvalidArgsError < Error
|
|
60
|
+
def initialize; super("Incorrect arguments.") end
|
|
61
|
+
end
|
|
70
62
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
63
|
+
class NotAllowedError < Error
|
|
64
|
+
def initialize; super("Security settings prevent access to this property or method.") end
|
|
65
|
+
end
|
|
74
66
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
class HelpError < Error
|
|
68
|
+
def initialize; super("Help") end
|
|
69
|
+
end
|
|
78
70
|
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
127
|
-
|
|
101
|
+
class AcrobatObject
|
|
102
|
+
def initialize(engine)
|
|
103
|
+
@engine = engine
|
|
104
|
+
end
|
|
128
105
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
168
|
+
def to_s
|
|
169
|
+
"[object #{self.class.to_s.split('::').last}]"
|
|
170
|
+
end
|
|
171
|
+
alias inspect to_s
|
|
172
|
+
end
|
|
167
173
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
-
|
|
181
|
-
|
|
186
|
+
class TimeOut < AcroTimer
|
|
187
|
+
def initialize(engine, timeout, code)
|
|
188
|
+
super(engine, timeout, code, false)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
182
191
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
+
class ReadStream < AcrobatObject
|
|
199
|
+
def initialize(engine, data)
|
|
200
|
+
super(engine)
|
|
198
201
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
super(engine, timeout, code, true)
|
|
202
|
-
end
|
|
203
|
-
end
|
|
202
|
+
@data = data
|
|
203
|
+
end
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
210
|
-
end
|
|
210
|
+
class Acrohelp < AcrobatObject; end
|
|
211
211
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
end
|
|
216
|
-
end
|
|
212
|
+
class Global < AcrobatObject
|
|
213
|
+
def initialize(engine)
|
|
214
|
+
super(engine)
|
|
217
215
|
|
|
218
|
-
|
|
216
|
+
@vars = {}
|
|
217
|
+
end
|
|
219
218
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
225
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
231
|
+
acro_method 'setPersistent',
|
|
232
|
+
Arg[name: 'cVariable', required: true],
|
|
233
|
+
Arg[name: 'bPersist', required: true] do |cVariable, bPersist|
|
|
238
234
|
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
249
|
+
class Doc < AcrobatObject
|
|
250
|
+
attr_reader :info
|
|
251
|
+
attr_accessor :disclosed
|
|
252
|
+
attr_reader :hidden
|
|
298
253
|
|
|
299
|
-
|
|
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
|
-
|
|
308
|
-
|
|
256
|
+
class Info < AcrobatObject
|
|
257
|
+
def initialize(engine, doc)
|
|
258
|
+
super(engine)
|
|
309
259
|
|
|
310
|
-
|
|
311
|
-
|
|
260
|
+
@doc = doc
|
|
261
|
+
end
|
|
312
262
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
-
|
|
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
|
-
|
|
351
|
-
|
|
352
|
-
else raise TypeError
|
|
353
|
-
end
|
|
354
|
-
end
|
|
290
|
+
def numFields
|
|
291
|
+
fields = @pdf.fields
|
|
355
292
|
|
|
356
|
-
|
|
357
|
-
|
|
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
|
-
|
|
364
|
-
else raise TypeError
|
|
365
|
-
end
|
|
296
|
+
def numPages; @pdf.pages.size end
|
|
366
297
|
|
|
367
|
-
|
|
368
|
-
|
|
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
|
-
|
|
371
|
-
|
|
372
|
-
field = @pdf.get_field(cName)
|
|
306
|
+
def metadata
|
|
307
|
+
meta = @pdf.Catalog.Metadata
|
|
373
308
|
|
|
374
|
-
|
|
375
|
-
|
|
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
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
388
|
-
fields = @pdf.fields
|
|
404
|
+
class App < AcrobatObject
|
|
389
405
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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
|
-
|
|
395
|
-
attr_reader :platform, :viewerVariation, :viewerVersion
|
|
411
|
+
def activeDocs; [] end
|
|
396
412
|
|
|
397
|
-
|
|
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
|
-
|
|
415
|
+
acro_method 'setInterval',
|
|
416
|
+
Arg[name: 'cExpr', required: true],
|
|
417
|
+
Arg[name: 'nMilliseconds', type: Numeric, required: true] do |cExpr, nMilliseconds|
|
|
403
418
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
nil
|
|
424
|
-
end
|
|
427
|
+
cExpr = cExpr.is_a?(::String) ? cExpr : ''
|
|
428
|
+
TimeOut.new(@engine, nMilliseconds, cExpr)
|
|
429
|
+
end
|
|
425
430
|
|
|
426
|
-
|
|
427
|
-
|
|
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
|
-
|
|
433
|
-
|
|
434
|
-
|
|
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
|
-
|
|
442
|
-
|
|
443
|
-
raise MissingArgError unless args.length > 0
|
|
438
|
+
acro_method 'clearTimeOut',
|
|
439
|
+
Arg[name: 'oInterval', type: TimeOut, required: true] do |oInterval|
|
|
444
440
|
|
|
445
|
-
|
|
446
|
-
|
|
441
|
+
oInterval.instance_variable_get(:@thr).terminate
|
|
442
|
+
nil
|
|
443
|
+
end
|
|
447
444
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
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
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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
|
-
|
|
459
|
-
|
|
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
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
-
|
|
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
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
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
|
-
|
|
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
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
601
|
+
@hooks[name] = [previous, callback]
|
|
602
|
+
else
|
|
603
|
+
raise JavaScript::EngineError, "#{name} is not a function"
|
|
604
|
+
end
|
|
605
|
+
end
|
|
524
606
|
|
|
525
|
-
|
|
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
|
-
|
|
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
|
-
|
|
530
|
-
|
|
531
|
-
@description, @MIMEType = description, mimeType
|
|
532
|
-
end
|
|
533
|
-
end
|
|
631
|
+
members
|
|
632
|
+
end
|
|
534
633
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
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
|
-
|
|
584
|
-
|
|
585
|
-
|
|
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
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
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
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
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
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
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
|
-
#
|
|
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
|
-
|