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.
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,79 +1,75 @@
1
1
  =begin
2
2
 
3
- = File
4
- xrefs.rb
5
-
6
- = Info
7
- This file is part of PDF Walker, a graphical PDF file browser
8
- Copyright (C) 2010 Guillaume Delugré <guillaume AT security-labs DOT org>
9
- All right reserved.
10
-
11
- PDF Walker is free software: you can redistribute it and/or modify
12
- it under the terms of the GNU 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
- PDF Walker 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 General Public License for more details.
20
-
21
- You should have received a copy of the GNU General Public License
22
- along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
3
+ This file is part of PDF Walker, a graphical PDF file browser
4
+ Copyright (C) 2016 Guillaume Delugré.
23
5
 
24
- =end
6
+ PDF Walker is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU 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
+ PDF Walker 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 General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
25
18
 
26
- require 'origami'
27
- include Origami
19
+ =end
28
20
 
29
21
  module PDFWalker
30
22
 
31
- class Walker < Window
32
-
33
- def show_xrefs(target)
34
- XrefsDialog.new(self, target)
23
+ class Walker < Window
24
+ def show_xrefs(target)
25
+ XrefsDialog.new(self, target)
26
+ end
35
27
  end
36
28
 
37
- end
29
+ class XrefsDialog < Dialog
30
+ OBJCOL = 0
31
+ REFCOL = 1
32
+ NAMECOL = 2
38
33
 
39
- class XrefsDialog < Dialog
40
-
41
- OBJCOL = 0
42
- TEXTCOL = 1
34
+ def initialize(parent, target)
35
+ super("Xrefs to #{target.reference}", parent, Dialog::MODAL, [Stock::CLOSE, Dialog::RESPONSE_NONE])
36
+ @parent = parent
43
37
 
44
- def initialize(parent, target)
45
-
46
- super("Xrefs to #{target.reference}", parent, Dialog::MODAL, [Stock::CLOSE, Dialog::RESPONSE_NONE])
47
- @parent = parent
38
+ @list = ListStore.new(Object, String, String)
39
+ @view = TreeView.new(@list)
48
40
 
49
- @list = ListStore.new(Object, String)
50
- @view = TreeView.new(@list)
41
+ column = Gtk::TreeViewColumn.new("Origin", Gtk::CellRendererText.new, text: REFCOL)
42
+ @view.append_column(column)
51
43
 
52
- column = Gtk::TreeViewColumn.new("Objects", Gtk::CellRendererText.new, :text => TEXTCOL)
53
- @view.append_column(column)
44
+ column = Gtk::TreeViewColumn.new("Objects", Gtk::CellRendererText.new, text: NAMECOL)
45
+ @view.append_column(column)
54
46
 
55
- target.xrefs.each { |obj|
56
- str = obj.class.to_s
57
- iter = @list.append
58
- @list.set_value(iter, OBJCOL, obj)
59
- @list.set_value(iter, TEXTCOL, str)
60
- }
47
+ target.xrefs.each { |obj|
48
+ str = obj.type.to_s
49
+ iter = @list.append
50
+ @list.set_value(iter, OBJCOL, obj)
61
51
 
62
- @view.signal_connect("row_activated") { |tree, path, column|
63
- if @view.selection.selected
64
- from = @list.get_value(@view.selection.selected, OBJCOL)
65
- @parent.treeview.goto(from)
66
- end
67
- }
52
+ obj = obj.parent until obj.indirect?
53
+ @list.set_value(iter, REFCOL, obj.reference.to_s)
68
54
 
69
- scroll = ScrolledWindow.new.set_policy(POLICY_NEVER, POLICY_AUTOMATIC)
70
- scroll.add(@view)
71
- vbox.add(scroll)
55
+ @list.set_value(iter, NAMECOL, str)
56
+ }
72
57
 
73
- signal_connect('response') { destroy }
74
- show_all
75
- end
76
-
77
- end
58
+ @view.signal_connect("row_activated") { |tree, path, _column|
59
+ if @view.selection.selected
60
+ from = @list.get_value(@view.selection.selected, OBJCOL)
61
+ @parent.treeview.goto(from)
62
+ end
63
+ }
64
+
65
+ scroll = ScrolledWindow.new.set_policy(POLICY_NEVER, POLICY_AUTOMATIC)
66
+ scroll.add(@view)
67
+ vbox.add(scroll)
68
+
69
+ set_default_size(200, 200)
78
70
 
71
+ signal_connect('response') { destroy }
72
+ show_all
73
+ end
74
+ end
79
75
  end
@@ -1,91 +1,87 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  =begin
4
4
 
5
- = Author:
6
- Guillaume Delugré <guillaume/at/security-labs.org>
5
+ = Info
6
+ Enforces a document to be rendered as PDF/A.
7
+ This will disable multimedia features and JavaScript execution in Adobe Reader.
7
8
 
8
- = Info:
9
- Enforces a document to be rendered as PDF/A.
10
- This will disable multimedia features and JavaScript execution in Adobe Reader.
9
+ = License
10
+ Copyright (C) 2016 Guillaume Delugré.
11
11
 
12
- = License:
13
- Origami is free software: you can redistribute it and/or modify
14
- it under the terms of the GNU Lesser General Public License as published by
15
- the Free Software Foundation, either version 3 of the License, or
16
- (at your option) any later version.
12
+ Origami is free software: you can redistribute it and/or modify
13
+ it under the terms of the GNU Lesser General Public License as published by
14
+ the Free Software Foundation, either version 3 of the License, or
15
+ (at your option) any later version.
17
16
 
18
- Origami is distributed in the hope that it will be useful,
19
- but WITHOUT ANY WARRANTY; without even the implied warranty of
20
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
- GNU Lesser General Public License for more details.
17
+ Origami is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ GNU Lesser General Public License for more details.
22
21
 
23
- You should have received a copy of the GNU Lesser General Public License
24
- along with Origami. If not, see <http://www.gnu.org/licenses/>.
22
+ You should have received a copy of the GNU Lesser General Public License
23
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
25
24
 
26
25
  =end
27
26
 
28
27
  begin
29
- require 'origami'
28
+ require 'origami'
30
29
  rescue LoadError
31
- ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib"
32
- $: << ORIGAMIDIR
33
- require 'origami'
30
+ $: << File.join(__dir__, '../lib')
31
+ require 'origami'
34
32
  end
35
33
  include Origami
36
34
 
37
35
  require 'optparse'
38
36
 
39
37
  class OptParser
40
- BANNER = <<USAGE
38
+ BANNER = <<USAGE
41
39
  Usage: #{$0} [<PDF-file>] [-o <output-file>]
42
- Enforces a document to be rendered as PDF/A.
40
+ Enforces a document to be rendered as PDF/A.
43
41
  This will disable multimedia features and JavaScript execution in Adobe Reader.
44
- Bug reports or feature requests at: http://origami-pdf.googlecode.com/
42
+ Bug reports or feature requests at: http://github.com/gdelugre/origami
45
43
 
46
44
  Options:
47
45
  USAGE
48
46
 
49
- def self.parser(options)
50
- OptionParser.new do |opts|
51
- opts.banner = BANNER
47
+ def self.parser(options)
48
+ OptionParser.new do |opts|
49
+ opts.banner = BANNER
52
50
 
53
- opts.on("-o", "--output FILE", "Output PDF file (stdout by default)") do |o|
54
- options[:output] = o
55
- end
51
+ opts.on("-o", "--output FILE", "Output PDF file (stdout by default)") do |o|
52
+ options[:output] = o
53
+ end
56
54
 
57
- opts.on_tail("-h", "--help", "Show this message") do
58
- puts opts
59
- exit
60
- end
55
+ opts.on_tail("-h", "--help", "Show this message") do
56
+ puts opts
57
+ exit
58
+ end
59
+ end
61
60
  end
62
- end
63
61
 
64
- def self.parse(args)
65
- options =
66
- {
67
- :output => STDOUT,
68
- }
62
+ def self.parse(args)
63
+ options =
64
+ {
65
+ output: STDOUT,
66
+ }
69
67
 
70
- self.parser(options).parse!(args)
68
+ self.parser(options).parse!(args)
71
69
 
72
- options
73
- end
70
+ options
71
+ end
74
72
  end
75
73
 
76
74
  begin
77
- @options = OptParser.parse(ARGV)
78
-
79
- target = (ARGV.empty?) ? STDIN : ARGV.shift
80
- params =
81
- {
82
- :verbosity => Parser::VERBOSE_QUIET,
83
- }
84
-
85
- PDF.read(target, params).save(@options[:output], :intent => 'PDF/A', :noindent => true)
86
- rescue SystemExit
87
- rescue Exception => e
88
- STDERR.puts "#{e.class}: #{e.message}"
89
- exit 1
90
- end
75
+ @options = OptParser.parse(ARGV)
91
76
 
77
+ target = (ARGV.empty?) ? STDIN : ARGV.shift
78
+ params =
79
+ {
80
+ verbosity: Parser::VERBOSE_QUIET,
81
+ }
82
+
83
+ PDF.read(target, params).save(@options[:output], intent: 'PDF/A', noindent: true)
84
+
85
+ rescue
86
+ abort"#{$!.class}: #{$!.message}"
87
+ end
@@ -2,37 +2,37 @@
2
2
 
3
3
  =begin
4
4
 
5
- = Info
6
- Convert a PDF document to an Origami script.
7
- Experimental.
5
+ = Info
6
+ Convert a PDF document to an Origami script.
7
+ Experimental.
8
8
 
9
9
  = License:
10
- Origami is free software: you can redistribute it and/or modify
11
- it under the terms of the GNU Lesser General Public License as published by
12
- the Free Software Foundation, either version 3 of the License, or
13
- (at your option) any later version.
10
+ Copyright (C) 2016 Guillaume Delugré.
14
11
 
15
- Origami is distributed in the hope that it will be useful,
16
- but WITHOUT ANY WARRANTY; without even the implied warranty of
17
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
- GNU Lesser General Public License for more details.
12
+ Origami is free software: you can redistribute it and/or modify
13
+ it under the terms of the GNU Lesser General Public License as published by
14
+ the Free Software Foundation, either version 3 of the License, or
15
+ (at your option) any later version.
19
16
 
20
- You should have received a copy of the GNU Lesser General Public License
21
- along with Origami. If not, see <http://www.gnu.org/licenses/>.
17
+ Origami is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ GNU Lesser General Public License for more details.
22
21
 
23
- = Author
24
- Guillaume Delugré
22
+ You should have received a copy of the GNU Lesser General Public License
23
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
25
24
 
26
25
  =end
27
26
 
28
27
  require 'optparse'
29
28
  require 'fileutils'
29
+ require 'colorize'
30
+
30
31
  begin
31
- ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib"
32
- require 'origami'
32
+ require 'origami'
33
33
  rescue LoadError
34
- $: << ORIGAMIDIR
35
- require 'origami'
34
+ $: << File.join(__dir__, '../lib')
35
+ require 'origami'
36
36
  end
37
37
  include Origami
38
38
 
@@ -42,252 +42,247 @@ include Origami
42
42
  @current_idx = nil
43
43
 
44
44
  class OptParser
45
- def self.parse(args)
46
- options = {}
47
- options[:verbose] =
48
- options[:xstreams] = false
45
+ def self.parse(args)
46
+ options = {}
47
+ options[:verbose] =
48
+ options[:xstreams] = false
49
49
 
50
- opts = OptionParser.new do |opts|
51
- opts.banner = <<BANNER
50
+ opts = OptionParser.new do |opts|
51
+ opts.banner = <<BANNER
52
52
  Usage: #{$0} [-v] [-x] <PDF-file>
53
53
  Convert a PDF document to an Origami script (experimental).
54
54
 
55
55
  Options:
56
56
  BANNER
57
-
58
- opts.on("-v", "--verbose", "Verbose mode") do
59
- options[:verbose] = true
60
- end
61
-
62
- opts.on("-x", "--extract-streams", "Extract PDF streams to separate files") do
63
- options[:xstreams] = true
64
- end
65
-
66
- opts.on_tail("-h", "--help", "Show this message") do
67
- puts opts
68
- exit
69
- end
70
- end
71
- opts.parse!(args)
72
57
 
73
- options
74
- end
58
+ opts.on("-v", "--verbose", "Verbose mode") do
59
+ options[:verbose] = true
60
+ end
61
+
62
+ opts.on("-x", "--extract-streams", "Extract PDF streams to separate files") do
63
+ options[:xstreams] = true
64
+ end
65
+
66
+ opts.on_tail("-h", "--help", "Show this message") do
67
+ puts opts
68
+ exit
69
+ end
70
+ end
71
+
72
+ opts.parse!(args)
73
+
74
+ options
75
+ end
75
76
  end
76
77
 
77
78
  @options = OptParser.parse(ARGV)
78
79
 
79
80
  if ARGV.empty?
80
- STDERR.puts "Error: No filename was specified. #{$0} --help for details."
81
- exit 1
81
+ abort "Error: No filename was specified. #{$0} --help for details."
82
82
  else
83
83
  TARGET = ARGV.shift
84
84
  end
85
85
 
86
86
  Origami::OPTIONS[:enable_type_guessing] = Origami::OPTIONS[:enable_type_propagation] = true
87
-
87
+
88
88
  TARGET_DIR = File.basename(TARGET, '.pdf')
89
- TARGET_FILE = "#{TARGET_DIR}/#{TARGET_DIR}.rb"
89
+ TARGET_FILE = File.join(TARGET_DIR, "#{TARGET_DIR}.rb")
90
90
  STREAM_DIR = "streams"
91
91
 
92
92
  def objectToRuby(obj, inclevel = 0, internalname = nil, do_convert = false)
93
- code = ""
94
-
95
- code <<
96
- case obj
97
- when Origami::Null
98
- "Null.new"
99
- when Origami::Boolean, Origami::Number
100
- obj.value.to_s
101
- when Origami::String
102
- "'#{obj.value.gsub("'","\\\\'")}'"
103
- when Origami::Dictionary
104
- customclass = nil
105
- if obj.class != Origami::Dictionary
106
- p = (obj.class == Origami::Encoding) ? 0 : 1
107
- customclass = obj.class.to_s.split('::')[p..-1].join('::') # strip Origami prefix if there is no collision
108
- end
109
- dictionaryToRuby(obj, inclevel, internalname, customclass)
110
- when Origami::Array
111
- arrayToRuby(obj, inclevel, internalname)
112
- when Origami::Stream
113
- streamToRuby(obj, internalname)
114
- when Origami::Name
115
- nameToRuby(obj)
116
- when Origami::Reference
117
- referenceToRuby(obj, internalname)
118
- else
119
- raise RuntimeError, "Unknown object type: #{obj.class}"
120
- end
93
+ code = ""
94
+
95
+ code <<
96
+ case obj
97
+ when Origami::Null
98
+ "Null.new"
99
+ when Origami::Boolean, Origami::Number
100
+ obj.value.to_s
101
+ when Origami::String
102
+ obj.inspect
103
+ when Origami::Dictionary
104
+ customclass = nil
105
+ if obj.class != Origami::Dictionary
106
+ p = (obj.class == Origami::Encoding) ? 0 : 1
107
+ customclass = obj.class.to_s.split('::')[p..-1].join('::') # strip Origami prefix if there is no collision
108
+ end
109
+ dictionaryToRuby(obj, inclevel, internalname, customclass)
110
+ when Origami::Array
111
+ arrayToRuby(obj, inclevel, internalname)
112
+ when Origami::Stream
113
+ streamToRuby(obj, internalname) unless obj.is_a?(ObjectStream) or obj.is_a?(XRefStream)
114
+ when Origami::Name
115
+ nameToRuby(obj)
116
+ when Origami::Reference
117
+ referenceToRuby(obj, internalname)
118
+ else
119
+ raise RuntimeError, "Unknown object type: #{obj.class}"
120
+ end
121
121
 
122
- case obj
122
+ case obj
123
123
  when Origami::String, Origami::Dictionary, Origami::Array, Origami::Name
124
- code << ".to_o" if do_convert
125
- end
124
+ code << ".to_o" if do_convert
125
+ end
126
126
 
127
- code
127
+ code
128
128
  end
129
129
 
130
130
  def referenceToRuby(ref, internalname)
131
- varname = @var_hash[ref]
131
+ varname = @var_hash[ref]
132
132
 
133
- if varname.nil?
134
- "nil"
135
- elsif @obj_route[0..@current_idx].include?(varname)
136
- @code_hash[varname] ||= {}
137
- @code_hash[varname][:afterDecl] ||= []
138
- @code_hash[varname][:afterDecl] << "#{internalname} = #{varname}"#.to_o.set_indirect(true)"
139
-
140
- "nil"
141
- else
142
- @obj_route.push(varname) unless @obj_route.include?(varname)
143
- varname
144
- end
133
+ if varname.nil?
134
+ "nil"
135
+ elsif @obj_route[0..@current_idx].include?(varname)
136
+ @code_hash[varname] ||= {}
137
+ @code_hash[varname][:afterDecl] ||= []
138
+ @code_hash[varname][:afterDecl] << "#{internalname} = #{varname}"#.to_o.set_indirect(true)"
139
+
140
+ "nil"
141
+ else
142
+ @obj_route.push(varname) unless @obj_route.include?(varname)
143
+ varname
144
+ end
145
145
  end
146
146
 
147
147
  def nameToRuby(name)
148
- code = ':'
149
- valid = (name.value.to_s =~ /[+.:-]/).nil?
148
+ code = ':'
149
+ valid = (name.value.to_s =~ /[+.:-]/).nil?
150
150
 
151
- code << '"' unless valid
152
- code << name.value.to_s
153
- code << '"' unless valid
151
+ code << '"' unless valid
152
+ code << name.value.to_s
153
+ code << '"' unless valid
154
154
 
155
- code
155
+ code
156
156
  end
157
157
 
158
158
  def arrayToRuby(arr, inclevel, internalname)
159
- i = 0
160
- code = "\n" + " " * inclevel + "["
161
- arr.each do |obj|
162
- subintname = "#{internalname}[#{i}]"
163
-
164
- code << "#{objectToRuby(obj, inclevel + 1, subintname)}"
165
- code << ", " unless i == arr.length - 1
166
- i = i + 1
167
- end
168
- code << "]"
169
-
170
- code
159
+ i = 0
160
+ code = "\n" + " " * inclevel + "["
161
+ arr.each do |obj|
162
+ subintname = "#{internalname}[#{i}]"
163
+
164
+ code << "#{objectToRuby(obj, inclevel + 1, subintname)}"
165
+ code << ", " unless i == arr.length - 1
166
+ i = i + 1
167
+ end
168
+ code << "]"
169
+
170
+ code
171
171
  end
172
172
 
173
173
  def dictionaryToRuby(dict, inclevel, internalname, customtype = nil)
174
- i = 0
175
- code = "\n" + " " * inclevel
176
-
177
- if customtype
178
- code << "#{customtype}.new(#{dictionaryToHashMap(dict, inclevel, internalname)}"
179
- code << " " * inclevel + ")"
180
- else
181
- code << "{\n"
182
- dict.each_pair do |key, val|
183
- rubyname = nameToRuby(key)
184
- subintname = "#{internalname}[#{rubyname}]"
185
-
186
- if val.is_a?(Origami::Reference) and @var_hash[val] and @var_hash[val][0,3] == "obj"
187
- oldname = @var_hash[val]
188
- newname = (key.value.to_s.downcase + "_" + @var_hash[val][4..-1]).gsub('.','_')
174
+ i = 0
175
+ code = "\n" + " " * inclevel
189
176
 
190
- if not @obj_route.include?(oldname)
191
- @var_hash[val] = newname
192
- @code_hash[newname] = @code_hash[oldname]
193
- @code_hash.delete(oldname)
177
+ if customtype
178
+ code << "#{customtype}.new(#{dictionaryToHashMap(dict, inclevel, internalname)}"
179
+ code << " " * inclevel + ")"
180
+ else
181
+ code << "{\n"
182
+ dict.each_pair do |key, val|
183
+ rubyname = nameToRuby(key)
184
+ subintname = "#{internalname}[#{rubyname}]"
185
+
186
+ if val.is_a?(Origami::Reference) and @var_hash[val] and @var_hash[val][0,3] == "obj"
187
+ oldname = @var_hash[val]
188
+ newname = (key.value.to_s.downcase.gsub(/[^[[:alnum:]]]/,'_') + "_" + @var_hash[val][4..-1]).gsub('.','_')
189
+
190
+ if not @obj_route.include?(oldname)
191
+ @var_hash[val] = newname
192
+ @code_hash[newname] = @code_hash[oldname]
193
+ @code_hash.delete(oldname)
194
+ end
195
+ end
196
+
197
+ code << " " * (inclevel + 1) +
198
+ "#{rubyname} => #{objectToRuby(val, inclevel + 2, subintname)}"
199
+ code << ", " unless i == dict.length - 1
200
+
201
+ i = i + 1
202
+ code << "\n"
194
203
  end
195
- end
196
-
197
- code << " " * (inclevel + 1) +
198
- "#{rubyname} => #{objectToRuby(val, inclevel + 2, subintname)}"
199
- code << ", " unless i == dict.length - 1
200
-
201
- i = i + 1
202
- code << "\n"
204
+
205
+ code << " " * inclevel + "}"
203
206
  end
204
- code << " " * inclevel + "}"
205
- end
206
207
 
207
- code
208
+ code
208
209
  end
209
210
 
210
211
  def dictionaryToHashMap(dict, inclevel, internalname)
211
- i = 0
212
- code = "\n"
213
- dict.each_pair do |key, val|
214
- rubyname = nameToRuby(key)
215
- subintname = "#{internalname}[#{rubyname}]"
216
-
217
- if val.is_a?(Origami::Reference) and @var_hash[val] and @var_hash[val][0,3] == "obj"
218
- oldname = @var_hash[val]
219
- newname = (key.value.to_s.downcase + "_" + @var_hash[val][4..-1]).gsub('.','_')
220
-
221
- if not @obj_route.include?(oldname)
222
- @var_hash[val] = newname
223
- @code_hash[newname] = @code_hash[oldname]
224
- @code_hash.delete(oldname)
225
- end
226
- end
212
+ i = 0
213
+ code = "\n"
214
+ dict.each_pair do |key, val|
215
+ rubyname = nameToRuby(key)
216
+ subintname = "#{internalname}[#{rubyname}]"
217
+
218
+ if val.is_a?(Origami::Reference) and @var_hash[val] and @var_hash[val][0,3] == "obj"
219
+ oldname = @var_hash[val]
220
+ newname = (key.value.to_s.downcase + "_" + @var_hash[val][4..-1]).gsub('.','_')
221
+
222
+ if not @obj_route.include?(oldname)
223
+ @var_hash[val] = newname
224
+ @code_hash[newname] = @code_hash[oldname]
225
+ @code_hash.delete(oldname)
226
+ end
227
+ end
227
228
 
228
- code << " " * (inclevel + 1) +
229
- "#{rubyname} => #{objectToRuby(val, inclevel + 2, subintname)}"
230
- code << ", " unless i == dict.length - 1
231
- i = i + 1
232
- code << "\n"
233
- end
229
+ code << " " * (inclevel + 1) +
230
+ "#{rubyname} => #{objectToRuby(val, inclevel + 2, subintname)}"
231
+ code << ", " unless i == dict.length - 1
232
+ i = i + 1
233
+ code << "\n"
234
+ end
234
235
 
235
- code
236
+ code
236
237
  end
237
238
 
238
239
  def streamToRuby(stm, internalname)
239
- dict = stm.dictionary.dup.delete_if{|k,v| k == :Length or k == :Filter}
240
-
241
- code = "Stream.new("
242
-
243
- if @options[:xstreams]
244
- stmdir = "#{TARGET_DIR}/#{STREAM_DIR}"
245
- Dir::mkdir(stmdir) unless File.directory? stmdir
246
- stmfile = "#{stmdir}/stm_#{stm.reference.refno}.data"
247
- File.open(stmfile, "w") do |stmfd|
248
- stmfd.write stm.data
240
+ dict = stm.dictionary.dup.delete_if{|k,v| k == :Length}
241
+
242
+ code = "Stream.new("
243
+
244
+ if @options[:xstreams]
245
+ stmdir = File.join(TARGET_DIR, STREAM_DIR)
246
+ Dir::mkdir(stmdir) unless File.directory? stmdir
247
+ stmfile = File.join(stmdir, "stm_#{stm.reference.refno}.data")
248
+ File.binwrite(stmfile, stm.data)
249
+
250
+ code << "File.binread('#{stmfile}')"
251
+ else
252
+ code << stm.data.inspect << ".b"
249
253
  end
250
254
 
251
- code << "File.read('#{STREAM_DIR}/stm_#{stm.reference.refno}.data')"
252
- else
253
- code << stm.data.inspect
254
- end
255
-
256
- code << ", #{dictionaryToHashMap(dict, 1, internalname)}" unless dict.empty?
257
- code << ")"
258
- if stm.dictionary.has_key? :Filter
259
- code << ".setFilter(#{objectToRuby(stm.Filter, 1, internalname)})"
260
- end
261
-
262
- code
255
+ code << ", #{dictionaryToHashMap(dict, 1, internalname)}" unless dict.empty?
256
+ code << ")"
257
+
258
+ code
263
259
  end
264
260
 
265
- Console.colorprint "[*] ", Console::Colors::RED
266
- puts "Loading document '#{TARGET}'"
267
- verbosity = @options[:verbose] ? Parser::VERBOSE_INSANE : Parser::VERBOSE_QUIET
268
- target = PDF.read(TARGET, :verbosity => verbosity)
269
- Console.colorprint "[*] ", Console::Colors::RED
270
- puts "Document successfully loaded into Origami"
261
+ puts "[*] ".red + "Loading document '#{TARGET}'"
262
+
263
+ verbosity = @options[:verbose] ? Parser::VERBOSE_TRACE : Parser::VERBOSE_QUIET
264
+ target = PDF.read(TARGET, verbosity: verbosity)
265
+ puts "[*] ".red + "Document successfully loaded into Origami"
271
266
 
272
267
  Dir::mkdir(TARGET_DIR) unless File.directory? TARGET_DIR
273
268
  fd = File.open(TARGET_FILE, 'w', 0700)
274
269
 
275
270
  DOCREF = "pdf"
276
- ORIGAMI_PATH = ORIGAMIDIR[0,1] == '/' ?
277
- ORIGAMIDIR :
278
- "../#{ORIGAMIDIR}"
279
271
 
280
272
  fd.puts <<RUBY
281
273
  #!/usr/bin/env ruby
282
274
 
283
275
  begin
284
- require 'origami'
276
+ require 'origami'
285
277
  rescue LoadError
286
- ORIGAMIDIR = "#{ORIGAMI_PATH}"
287
- $: << ORIGAMIDIR
288
- require 'origami'
278
+ $: << "#{File.join(__dir__, '../lib')}"
279
+ require 'origami'
289
280
  end
290
281
  include Origami
282
+ using Origami::TypeConversion
283
+
284
+ # Disable automatic type casting.
285
+ Origami::OPTIONS[:enable_type_guessing] = false
291
286
 
292
287
  OUTPUT = "\#{File.basename(__FILE__, '.rb')}.pdf"
293
288
 
@@ -298,50 +293,42 @@ OUTPUT = "\#{File.basename(__FILE__, '.rb')}.pdf"
298
293
 
299
294
  RUBY
300
295
 
301
- Console.colorprint "[*] ", Console::Colors::RED
302
- puts "Retrieving all indirect objects..."
303
- roots = target.root_objects
304
- roots.each do |obj|
305
- varname = "obj_" + obj.no.to_s
306
- @var_hash[obj.reference] = varname
296
+ puts "[*] ".red + "Retrieving all indirect objects..."
297
+ target.each_object(compressed: true) do |obj|
298
+ varname = "obj_" + obj.no.to_s
299
+ @var_hash[obj.reference] = varname
307
300
  end
308
301
 
309
- Console.colorprint "[*] ", Console::Colors::RED
310
- puts "Retrieving the document Catalog..."
302
+ puts "[*] ".red + "Retrieving the document Catalog..."
311
303
  catalog = target.Catalog
312
304
 
313
305
  @var_hash[catalog.reference] = "#{DOCREF}.Catalog"
314
306
  @obj_route.push "#{DOCREF}.Catalog"
315
307
 
316
- Console.colorprint "[*] ", Console::Colors::RED
317
- puts "Processing the object hierarchy..."
308
+ puts "[*] ".red + "Processing the object hierarchy..."
318
309
  @current_idx = 0
319
310
  while @current_idx != @obj_route.size
320
- varname = @obj_route[@current_idx]
321
- if RUBY_VERSION < '1.9'
322
- obj = target[@var_hash.index(varname)]
323
- else
311
+ varname = @obj_route[@current_idx]
324
312
  obj = target[@var_hash.key(varname)]
325
- end
326
-
327
- @code_hash[varname] ||= {}
328
- @code_hash[varname][:body] = objectToRuby(obj, 0, varname, true)
329
313
 
330
- @current_idx = @current_idx + 1
314
+ @code_hash[varname] ||= {}
315
+ @code_hash[varname][:body] = objectToRuby(obj, 0, varname, true)
316
+
317
+ @current_idx = @current_idx + 1
331
318
  end
332
319
 
333
320
  @obj_route.reverse.each do |varname|
334
- fd.puts "#{varname} = #{@code_hash[varname][:body]}"
335
- if @code_hash[varname][:afterDecl]
336
- @code_hash[varname][:afterDecl].each do |decl|
337
- fd.puts decl
321
+ fd.puts "#{varname} = #{@code_hash[varname][:body]}"
322
+ if @code_hash[varname][:afterDecl]
323
+ @code_hash[varname][:afterDecl].each do |decl|
324
+ fd.puts decl
325
+ end
338
326
  end
339
- end
340
- fd.puts
327
+ fd.puts
341
328
  end
342
329
 
343
330
  @obj_route.each do |varname|
344
- fd.puts "#{DOCREF}.insert(#{varname})" unless varname == "#{DOCREF}.Catalog"
331
+ fd.puts "#{DOCREF}.insert(#{varname})" unless varname == "#{DOCREF}.Catalog"
345
332
  end
346
333
  fd.puts
347
334
 
@@ -350,11 +337,8 @@ fd.puts <<RUBY
350
337
  # Saves the document.
351
338
  #
352
339
  #{DOCREF}.save(OUTPUT)
353
-
354
340
  RUBY
355
341
 
356
- Console.colorprint "[*] ", Console::Colors::RED
357
- puts "Successfully generated script '#{TARGET_FILE}'"
358
- fd.close
359
- exit
342
+ puts "[*] ".red + "Successfully generated script '#{TARGET_FILE}'"
360
343
 
344
+ fd.close