origami 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+