origami 1.0.2

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 (108) hide show
  1. data/COPYING.LESSER +165 -0
  2. data/README +77 -0
  3. data/VERSION +1 -0
  4. data/bin/config/pdfcop.conf.yml +237 -0
  5. data/bin/gui/about.rb +46 -0
  6. data/bin/gui/config.rb +132 -0
  7. data/bin/gui/file.rb +385 -0
  8. data/bin/gui/hexdump.rb +74 -0
  9. data/bin/gui/hexview.rb +91 -0
  10. data/bin/gui/imgview.rb +72 -0
  11. data/bin/gui/menu.rb +392 -0
  12. data/bin/gui/properties.rb +132 -0
  13. data/bin/gui/signing.rb +635 -0
  14. data/bin/gui/textview.rb +107 -0
  15. data/bin/gui/treeview.rb +409 -0
  16. data/bin/gui/walker.rb +282 -0
  17. data/bin/gui/xrefs.rb +79 -0
  18. data/bin/pdf2graph +121 -0
  19. data/bin/pdf2ruby +353 -0
  20. data/bin/pdfcocoon +104 -0
  21. data/bin/pdfcop +455 -0
  22. data/bin/pdfdecompress +104 -0
  23. data/bin/pdfdecrypt +95 -0
  24. data/bin/pdfencrypt +112 -0
  25. data/bin/pdfextract +221 -0
  26. data/bin/pdfmetadata +123 -0
  27. data/bin/pdfsh +13 -0
  28. data/bin/pdfwalker +7 -0
  29. data/bin/shell/.irbrc +104 -0
  30. data/bin/shell/console.rb +136 -0
  31. data/bin/shell/hexdump.rb +83 -0
  32. data/origami.rb +36 -0
  33. data/origami/3d.rb +239 -0
  34. data/origami/acroform.rb +321 -0
  35. data/origami/actions.rb +299 -0
  36. data/origami/adobe/fdf.rb +259 -0
  37. data/origami/adobe/ppklite.rb +489 -0
  38. data/origami/annotations.rb +775 -0
  39. data/origami/array.rb +187 -0
  40. data/origami/boolean.rb +101 -0
  41. data/origami/catalog.rb +486 -0
  42. data/origami/destinations.rb +213 -0
  43. data/origami/dictionary.rb +188 -0
  44. data/origami/docmdp.rb +96 -0
  45. data/origami/encryption.rb +1293 -0
  46. data/origami/export.rb +283 -0
  47. data/origami/file.rb +222 -0
  48. data/origami/filters.rb +250 -0
  49. data/origami/filters/ascii.rb +189 -0
  50. data/origami/filters/ccitt.rb +515 -0
  51. data/origami/filters/crypt.rb +47 -0
  52. data/origami/filters/dct.rb +61 -0
  53. data/origami/filters/flate.rb +112 -0
  54. data/origami/filters/jbig2.rb +63 -0
  55. data/origami/filters/jpx.rb +53 -0
  56. data/origami/filters/lzw.rb +195 -0
  57. data/origami/filters/predictors.rb +276 -0
  58. data/origami/filters/runlength.rb +117 -0
  59. data/origami/font.rb +209 -0
  60. data/origami/functions.rb +93 -0
  61. data/origami/graphics.rb +33 -0
  62. data/origami/graphics/colors.rb +191 -0
  63. data/origami/graphics/instruction.rb +126 -0
  64. data/origami/graphics/path.rb +154 -0
  65. data/origami/graphics/patterns.rb +180 -0
  66. data/origami/graphics/state.rb +164 -0
  67. data/origami/graphics/text.rb +224 -0
  68. data/origami/graphics/xobject.rb +493 -0
  69. data/origami/header.rb +90 -0
  70. data/origami/linearization.rb +318 -0
  71. data/origami/metadata.rb +114 -0
  72. data/origami/name.rb +170 -0
  73. data/origami/null.rb +75 -0
  74. data/origami/numeric.rb +188 -0
  75. data/origami/obfuscation.rb +233 -0
  76. data/origami/object.rb +527 -0
  77. data/origami/outline.rb +59 -0
  78. data/origami/page.rb +559 -0
  79. data/origami/parser.rb +268 -0
  80. data/origami/parsers/fdf.rb +45 -0
  81. data/origami/parsers/pdf.rb +27 -0
  82. data/origami/parsers/pdf/linear.rb +113 -0
  83. data/origami/parsers/ppklite.rb +86 -0
  84. data/origami/pdf.rb +1144 -0
  85. data/origami/reference.rb +113 -0
  86. data/origami/signature.rb +474 -0
  87. data/origami/stream.rb +575 -0
  88. data/origami/string.rb +416 -0
  89. data/origami/trailer.rb +173 -0
  90. data/origami/webcapture.rb +87 -0
  91. data/origami/xfa.rb +3027 -0
  92. data/origami/xreftable.rb +447 -0
  93. data/templates/patterns.rb +66 -0
  94. data/templates/widgets.rb +173 -0
  95. data/templates/xdp.rb +92 -0
  96. data/tests/dataset/test.dummycrt +28 -0
  97. data/tests/dataset/test.dummykey +27 -0
  98. data/tests/tc_actions.rb +32 -0
  99. data/tests/tc_annotations.rb +85 -0
  100. data/tests/tc_pages.rb +37 -0
  101. data/tests/tc_pdfattach.rb +24 -0
  102. data/tests/tc_pdfencrypt.rb +110 -0
  103. data/tests/tc_pdfnew.rb +32 -0
  104. data/tests/tc_pdfparse.rb +98 -0
  105. data/tests/tc_pdfsig.rb +37 -0
  106. data/tests/tc_streams.rb +129 -0
  107. data/tests/ts_pdf.rb +45 -0
  108. metadata +193 -0
@@ -0,0 +1,282 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+
5
+ = File
6
+ walker.rb
7
+
8
+ = Info
9
+ This file is part of Origami, PDF manipulation framework for Ruby
10
+ Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.org>
11
+ All right reserved.
12
+
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.
17
+
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.
22
+
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/>.
25
+
26
+ =end
27
+
28
+ begin
29
+ require 'gtk2'
30
+ rescue LoadError
31
+ abort('Error: you need to install ruby-gtk2 to run this application')
32
+ end
33
+ include Gtk
34
+
35
+ begin
36
+ require 'origami'
37
+ rescue LoadError
38
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../.."
39
+ $: << ORIGAMIDIR
40
+ require 'origami'
41
+ end
42
+
43
+ require 'gui/menu'
44
+ require 'gui/about'
45
+ require 'gui/file'
46
+ require 'gui/hexview'
47
+ require 'gui/treeview'
48
+ require 'gui/textview'
49
+ require 'gui/imgview'
50
+ require 'gui/config'
51
+ require 'gui/properties'
52
+ require 'gui/xrefs'
53
+ require 'gui/signing'
54
+
55
+ module PDFWalker #:nodoc:all
56
+
57
+ class Walker < Window
58
+
59
+ attr_reader :treeview, :hexview, :objectview
60
+ attr_reader :explorer_history
61
+ attr_reader :config
62
+ attr_reader :filename
63
+
64
+ def self.start
65
+ Gtk.init
66
+ Walker.new
67
+ Gtk.main
68
+ end
69
+
70
+ def initialize
71
+ super("PDF Walker")
72
+
73
+ @config = Walker::Config.new
74
+
75
+ @last_search_result = []
76
+ @last_search =
77
+ {
78
+ :expr => "",
79
+ :regexp => false,
80
+ :type => :body
81
+ }
82
+
83
+ @explorer_history = Array.new
84
+
85
+ signal_connect('destroy') {
86
+ @config.save
87
+ Gtk.main_quit
88
+ }
89
+
90
+ add_events(Gdk::Event::KEY_RELEASE_MASK)
91
+ signal_connect('key_release_event') { |w, event|
92
+
93
+ if event.keyval == Gdk::Keyval::GDK_F1 then about
94
+ elsif event.keyval == Gdk::Keyval::GDK_Escape && @opened && ! @explorer_history.empty?
95
+ @treeview.goto(@explorer_history.pop)
96
+ end
97
+
98
+ }
99
+
100
+ create_menus
101
+ create_treeview
102
+ create_hexview
103
+ create_objectview
104
+ create_panels
105
+ create_statusbar
106
+
107
+ @vbox = VBox.new
108
+ @vbox.pack_start(@menu, false, false)
109
+ @vbox.pack_start(@hpaned)
110
+ @vbox.pack_end(@statusbar, false, false)
111
+
112
+ add @vbox
113
+
114
+ set_default_size(self.screen.width * 0.5, self.screen.height * 0.5)
115
+ #maximize
116
+ show_all
117
+
118
+ open
119
+ end
120
+
121
+ def error(msg)
122
+
123
+ dialog = Gtk::MessageDialog.new(self,
124
+ Gtk::Dialog::DESTROY_WITH_PARENT,
125
+ Gtk::MessageDialog::ERROR,
126
+ Gtk::MessageDialog::BUTTONS_CLOSE,
127
+ msg)
128
+ dialog.run
129
+ dialog.destroy
130
+
131
+ end
132
+
133
+ def reload
134
+ @treeview.load(@opened) if @opened
135
+ end
136
+
137
+ def search
138
+ dialog = Gtk::Dialog.new("Search...",
139
+ self,
140
+ Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
141
+ [Gtk::Stock::FIND, Gtk::Dialog::RESPONSE_OK],
142
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL]
143
+ )
144
+
145
+ entry = Gtk::Entry.new
146
+ entry.signal_connect('activate') { dialog.response(Gtk::Dialog::RESPONSE_OK) }
147
+ entry.text = @last_search[:expr]
148
+
149
+ button_bydata = Gtk::RadioButton.new("In object body")
150
+ button_byname = Gtk::RadioButton.new(button_bydata, "In object name")
151
+ button_regexp = Gtk::CheckButton.new("Regular expression")
152
+
153
+ button_bydata.set_active(true) if @last_search[:type] == :body
154
+ button_byname.set_active(true) if @last_search[:type] == :name
155
+ button_regexp.set_active(@last_search[:regexp])
156
+
157
+ hbox = HBox.new
158
+ hbox.pack_start Gtk::Label.new("Search for expression ")
159
+ hbox.pack_start entry
160
+
161
+ dialog.vbox.pack_start(hbox)
162
+ dialog.vbox.pack_start(button_bydata)
163
+ dialog.vbox.pack_start(button_byname)
164
+ dialog.vbox.pack_end(button_regexp)
165
+
166
+ dialog.signal_connect('response') do |dlg, response|
167
+ if response == Gtk::Dialog::RESPONSE_OK
168
+ search =
169
+ {
170
+ :expr => entry.text,
171
+ :regexp => button_regexp.active?,
172
+ :type => button_byname.active? ? :name : :body
173
+ }
174
+
175
+ if search == @last_search
176
+ @last_search_result.push @last_search_result.shift
177
+ results = @last_search_result
178
+ else
179
+ expr = search[:regexp] ? Regexp.new(search[:expr]) : search[:expr]
180
+
181
+ results =
182
+ if search[:type] == :body
183
+ @opened.grep(expr)
184
+ else
185
+ @opened.ls(expr)
186
+ end
187
+ @last_search = search
188
+ end
189
+
190
+ if results.empty?
191
+ error("No result found.")
192
+ else
193
+ if results != @last_search_result
194
+ @last_search_result.each do |obj| @treeview.highlight(obj, nil) end
195
+ results.each do |obj| @treeview.highlight(obj, "lightpink") end
196
+
197
+ @last_search_result = results
198
+ end
199
+
200
+ @treeview.goto(results.first)
201
+ end
202
+ else
203
+ dialog.destroy
204
+ end
205
+ end
206
+
207
+ dialog.show_all
208
+ end
209
+
210
+ def goto_catalog
211
+ @treeview.goto(@opened.Catalog.reference)
212
+ end
213
+
214
+ def goto_object
215
+ dialog = Gtk::Dialog.new("Jump to object...",
216
+ self,
217
+ Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
218
+ [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK],
219
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL]
220
+ )
221
+
222
+ entry = Gtk::Entry.new
223
+ entry.signal_connect('activate') { dialog.response(Gtk::Dialog::RESPONSE_OK) }
224
+
225
+ dialog.vbox.pack_start Gtk::Label.new("Object number: ")
226
+ dialog.vbox.pack_start entry
227
+ dialog.show_all
228
+
229
+ no = 0
230
+ dialog.run do |response|
231
+ if response == Gtk::Dialog::RESPONSE_OK
232
+ no = entry.text.to_i
233
+ end
234
+
235
+ dialog.destroy
236
+ end
237
+
238
+ if no > 0
239
+ obj = @opened[no]
240
+
241
+ if obj.nil?
242
+ error("Object #{no} not found.")
243
+ else
244
+ @treeview.goto(obj)
245
+ end
246
+ end
247
+ end
248
+
249
+ private
250
+
251
+ def create_panels
252
+
253
+ @hpaned = HPaned.new
254
+
255
+ @treepanel = ScrolledWindow.new.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
256
+ @treepanel.add @treeview
257
+
258
+ @vpaned = VPaned.new
259
+ @vpaned.pack1(@objectview, true, false)
260
+ @vpaned.pack2(@hexview, true, false)
261
+
262
+ @hpaned.pack1(@treepanel, true, false)
263
+ @hpaned.pack2(@vpaned, true, false)
264
+
265
+ end
266
+
267
+ def create_statusbar
268
+
269
+ @statusbar = Statusbar.new
270
+
271
+ @main_context = @statusbar.get_context_id 'Main'
272
+ @statusbar.push(@main_context, 'No file selected')
273
+
274
+ end
275
+
276
+ end
277
+
278
+ end
279
+
280
+ if __FILE__ == $0
281
+ PDFWalker::Walker.start
282
+ end
@@ -0,0 +1,79 @@
1
+ =begin
2
+
3
+ = File
4
+ xrefs.rb
5
+
6
+ = Info
7
+ This file is part of Origami, PDF manipulation framework for Ruby
8
+ Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.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/>.
23
+
24
+ =end
25
+
26
+ require 'origami'
27
+ include Origami
28
+
29
+ module PDFWalker
30
+
31
+ class Walker < Window
32
+
33
+ def show_xrefs(target)
34
+ XrefsDialog.new(self, target)
35
+ end
36
+
37
+ end
38
+
39
+ class XrefsDialog < Dialog
40
+
41
+ OBJCOL = 0
42
+ TEXTCOL = 1
43
+
44
+ def initialize(parent, target)
45
+
46
+ super("Xrefs to #{target.reference}", parent, Dialog::MODAL, [Stock::CLOSE, Dialog::RESPONSE_NONE])
47
+ @parent = parent
48
+
49
+ @list = ListStore.new(Object, String)
50
+ @view = TreeView.new(@list)
51
+
52
+ column = Gtk::TreeViewColumn.new("Objects", Gtk::CellRendererText.new, :text => TEXTCOL)
53
+ @view.append_column(column)
54
+
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
+ }
61
+
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
+ }
68
+
69
+ scroll = ScrolledWindow.new.set_policy(POLICY_NEVER, POLICY_AUTOMATIC)
70
+ scroll.add(@view)
71
+ vbox.add(scroll)
72
+
73
+ signal_connect('response') { destroy }
74
+ show_all
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+
5
+ = Author:
6
+ Guillaume Delugré <guillaume/at/security-labs.org>
7
+
8
+ = Info:
9
+ Generates a Graphviz DOT or GraphML file out of a PDF document.
10
+
11
+ = License:
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.
16
+
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.
21
+
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/>.
24
+
25
+ =end
26
+
27
+ begin
28
+ require 'origami'
29
+ rescue LoadError
30
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/.."
31
+ $: << ORIGAMIDIR
32
+ require 'origami'
33
+ end
34
+ include Origami
35
+
36
+ require 'optparse'
37
+
38
+ class OptParser
39
+ BANNER = <<USAGE
40
+ Usage: #{$0} <PDF-file> [-f <format>] [-o <output-file>]
41
+ Generates a Graphviz DOT file out of a PDF document.
42
+ Bug reports or feature requests at: http://origami-pdf.googlecode.com/
43
+
44
+ Options:
45
+ USAGE
46
+
47
+ def self.parser(options)
48
+ OptionParser.new do |opts|
49
+ opts.banner = BANNER
50
+
51
+ opts.on("-o", "--output FILE", "Output PDF file") do |o|
52
+ options[:output] = o
53
+ end
54
+
55
+ opts.on("-f", "--format FORMAT", "File format for the generated graph, dot or graphml (Default: dot).") do |f|
56
+ options[:format] = f
57
+ end
58
+
59
+ opts.on_tail("-h", "--help", "Show this message") do
60
+ puts opts
61
+ exit
62
+ end
63
+ end
64
+ end
65
+
66
+ def self.parse(args)
67
+ options =
68
+ {
69
+ :format => 'DOT'
70
+ }
71
+
72
+ self.parser(options).parse!(args)
73
+
74
+ options
75
+ end
76
+ end
77
+
78
+ begin
79
+ @options = OptParser.parse(ARGV)
80
+
81
+ if ARGV.empty?
82
+ STDERR.puts "Error: No filename was specified. #{$0} --help for details."
83
+ exit 1
84
+ else
85
+ target = ARGV.shift
86
+ end
87
+
88
+ unless ['DOT', 'GRAPHML'].include? @options[:format].upcase
89
+ STDERR.puts "Error: Invalid format `#{format}'. #{0} --help for details."
90
+ end
91
+
92
+ if @options[:outfile].nil?
93
+ @options[:outfile] = File.basename(target, '.pdf') +
94
+ case @options[:format].upcase
95
+ when 'DOT' then
96
+ '.dot'
97
+ when 'GRAPHML' then
98
+ '.graphml'
99
+ end
100
+ end
101
+
102
+ params =
103
+ {
104
+ :verbosity => Parser::VERBOSE_QUIET,
105
+ }
106
+
107
+ pdf = PDF.read(target, params)
108
+ case @options[:format].upcase
109
+ when 'DOT' then
110
+ pdf.export_to_graph(@options[:outfile])
111
+
112
+ when 'GRAPHML' then
113
+ pdf.export_to_graphml(@options[:outfile])
114
+ end
115
+
116
+ rescue SystemExit
117
+ rescue Exception => e
118
+ STDERR.puts "#{e.class}: #{e.message}"
119
+ exit 1
120
+ end
121
+