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,107 @@
1
+ =begin
2
+
3
+ = File
4
+ textview.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 'kconv'
27
+ require 'gui/hexdump'
28
+
29
+ module PDFWalker
30
+
31
+ class Walker < Window
32
+
33
+ private
34
+
35
+ def create_objectview
36
+
37
+ @objectview = ObjectView.new(self)
38
+
39
+ end
40
+
41
+ class ObjectView < Notebook
42
+
43
+ attr_reader :parent
44
+ attr_reader :pdfpanel, :valuepanel
45
+
46
+ def initialize(parent)
47
+
48
+ @parent = parent
49
+
50
+ super()
51
+
52
+ @pdfbuffer = TextBuffer.new
53
+ @pdfview = TextView.new(@pdfbuffer).set_editable(false).set_cursor_visible(false).set_left_margin(5)
54
+
55
+ @pdfpanel = ScrolledWindow.new.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
56
+ @pdfpanel.add_with_viewport @pdfview
57
+ append_page(@pdfpanel, Label.new("PDF Code"))
58
+
59
+ @pdfbuffer.create_tag("Object", { :weight => Pango::WEIGHT_BOLD, :foreground => "darkblue", :family => "Courier", :scale => Pango::AttrScale::LARGE })
60
+
61
+ end
62
+
63
+ def load(object)
64
+
65
+ begin
66
+
67
+ self.clear
68
+
69
+ pdftag = "Object"
70
+
71
+ if object.is_a?(Stream)
72
+ stm = "#{object.no} #{object.generation} obj\n"
73
+ stm << object.dictionary.to_s
74
+
75
+ if object.rawdata.is_binary_data?
76
+ stm << "stream\n[Binary data]\nendstream"
77
+ else
78
+ stm << "stream\n#{object.rawdata}endstream"
79
+ end
80
+
81
+ @pdfbuffer.set_text(stm)
82
+
83
+ elsif (not object.is_a?(::Array) or object.is_a?(Array)) and
84
+ not object.is_a?(PDF) and not object.is_a?(Adobe::PPKLite) and
85
+ not object.is_a?(PDF::Revision) and not object.is_a?(Adobe::PPKLite::Revision) and
86
+ not object.is_a?(XRefToCompressedObj)
87
+
88
+ @pdfbuffer.set_text(object.to_s)
89
+ end
90
+
91
+ @pdfbuffer.apply_tag(pdftag, @pdfbuffer.start_iter, @pdfbuffer.end_iter)
92
+
93
+ rescue Exception => e
94
+ @parent.error("An error occured while loading this object.\n#{e} (#{e.class})")
95
+ end
96
+
97
+ end
98
+
99
+ def clear
100
+ @pdfbuffer.set_text("")
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,409 @@
1
+ =begin
2
+
3
+ = File
4
+ treeview.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
+ module PDFWalker
27
+
28
+ class Walker < Window
29
+
30
+ private
31
+
32
+ def create_treeview
33
+
34
+ @treeview = PDFTree.new(self).set_headers_visible(false)
35
+
36
+ colcontent = Gtk::TreeViewColumn.new("Names",
37
+ Gtk::CellRendererText.new.set_foreground_set(true).set_background_set(true),
38
+ :text => PDFTree::TEXTCOL,
39
+ :weight => PDFTree::WEIGHTCOL,
40
+ :style => PDFTree::STYLECOL,
41
+ :foreground => PDFTree::FGCOL,
42
+ :background => PDFTree::BGCOL
43
+ )
44
+
45
+ @treeview.append_column(colcontent)
46
+
47
+ end
48
+
49
+ end
50
+
51
+ class PDFTree < TreeView
52
+
53
+ include Popable
54
+
55
+ OBJCOL = 0
56
+ TEXTCOL = 1
57
+ WEIGHTCOL = 2
58
+ STYLECOL = 3
59
+ FGCOL = 4
60
+ BGCOL = 5
61
+
62
+ @@appearance = Hash.new({ :Color => "black", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_NORMAL })
63
+
64
+ attr_reader :parent
65
+
66
+ def initialize(parent)
67
+
68
+ @parent = parent
69
+
70
+ reset_appearance
71
+
72
+ @treestore = TreeStore.new(Object::Object, String, Pango::FontDescription::Weight, Pango::FontDescription::Style, String, String)
73
+ super(@treestore)
74
+
75
+ signal_connect('cursor-changed') {
76
+ iter = selection.selected
77
+ if iter
78
+ obj = @treestore.get_value(iter, OBJCOL)
79
+
80
+ if obj.is_a?(Stream) and iter.n_children == 1
81
+
82
+ # Processing with an XRef or Object Stream
83
+ if obj.is_a?(ObjectStream)
84
+ obj.each { |embeddedobj|
85
+ load_object(iter, embeddedobj)
86
+ }
87
+
88
+ elsif obj.is_a?(XRefStream)
89
+ obj.each { |xref|
90
+ load_xrefstm(iter, xref)
91
+ }
92
+ end
93
+ end
94
+
95
+ parent.hexview.load(obj)
96
+ parent.objectview.load(obj)
97
+ end
98
+ }
99
+
100
+ signal_connect('row-activated') { |tree, path, column|
101
+ if selection.selected
102
+ obj = @treestore.get_value(selection.selected, OBJCOL)
103
+
104
+ if row_expanded?(path)
105
+ collapse_row(path)
106
+ else
107
+ expand_row(path, false)
108
+ end
109
+
110
+ goto(obj.solve) if obj.is_a?(Origami::Reference)
111
+ end
112
+ }
113
+
114
+ add_events(Gdk::Event::BUTTON_PRESS_MASK)
115
+ signal_connect('button_press_event') { |widget, event|
116
+ if event.button == 3 && parent.opened
117
+ path = get_path(event.x,event.y).first
118
+ set_cursor(path, nil, false)
119
+
120
+ obj = @treestore.get_value(@treestore.get_iter(path), OBJCOL)
121
+ popup_menu(obj, event, path)
122
+ end
123
+ }
124
+
125
+ end
126
+
127
+ def clear
128
+ @treestore.clear
129
+ end
130
+
131
+ def goto(obj)
132
+
133
+ if obj.is_a?(TreePath)
134
+ set_cursor(obj, nil, false)
135
+ else
136
+ if obj.is_a?(Name) and obj.parent.is_a?(Dictionary) and obj.parent.has_key?(obj)
137
+ obj = obj.parent[obj]
138
+ elsif obj.is_a?(Reference)
139
+ obj = obj.solve
140
+ end
141
+
142
+ @treestore.each { |model, path, iter|
143
+ current_obj = @treestore.get_value(iter, OBJCOL)
144
+
145
+ if current_obj.is_a?(ObjectStream) and obj.parent.equal?(current_obj)
146
+ current_obj.each { |embeddedobj|
147
+ load_object(iter, embeddedobj)
148
+ }
149
+ next
150
+ end
151
+
152
+ if obj.equal?(current_obj)
153
+ expand_to_path(path) unless row_expanded?(path)
154
+
155
+ if cursor.first then @parent.explorer_history << cursor.first end
156
+ set_cursor(path, nil, false)
157
+
158
+ return
159
+ end
160
+ }
161
+
162
+ @parent.error("Object not found : #{obj}")
163
+ end
164
+
165
+ end
166
+
167
+ def highlight(obj, color)
168
+ if obj.is_a?(Name) and obj.parent.is_a?(Dictionary) and obj.parent.has_key?(obj)
169
+ obj = obj.parent[obj]
170
+ end
171
+
172
+ @treestore.each { |model, path, iter|
173
+ current_obj = @treestore.get_value(iter, OBJCOL)
174
+
175
+ if obj.equal?(current_obj)
176
+ @treestore.set_value(iter, BGCOL, color)
177
+ expand_to_path(path) unless row_expanded?(path)
178
+ return
179
+ end
180
+ }
181
+
182
+ @parent.error("Object not found : #{obj}")
183
+ end
184
+
185
+ def load(pdf)
186
+
187
+ if pdf
188
+ self.clear
189
+
190
+ begin
191
+ #
192
+ # Create root entry
193
+ #
194
+ root = @treestore.append(nil)
195
+ @treestore.set_value(root, OBJCOL, pdf)
196
+
197
+ set_node(root, :Filename, @parent.filename)
198
+
199
+ #
200
+ # Create header entry
201
+ #
202
+ header = @treestore.append(root)
203
+ @treestore.set_value(header, OBJCOL, pdf.header)
204
+
205
+ set_node(header, :Header, "Header (version #{pdf.header.majorversion}.#{pdf.header.minorversion})")
206
+
207
+ no = 1
208
+ pdf.revisions.each { |revision|
209
+
210
+ load_revision(root, no, revision)
211
+ no = no + 1
212
+
213
+ }
214
+
215
+ set_model(@treestore)
216
+
217
+ ensure
218
+ expand(@treestore.iter_first, 3)
219
+ set_cursor(@treestore.iter_first.path, nil, false)
220
+ end
221
+ end
222
+
223
+ end
224
+
225
+ private
226
+
227
+ def expand(row, depth)
228
+
229
+ if row and depth != 0
230
+
231
+ loop do
232
+ expand_row(row.path, false)
233
+ expand(row.first_child, depth - 1)
234
+
235
+ break if not row.next!
236
+ end
237
+
238
+ end
239
+
240
+ end
241
+
242
+ def load_revision(root, no, revision)
243
+
244
+ revroot = @treestore.append(root)
245
+ @treestore.set_value(revroot, OBJCOL, revision)
246
+
247
+ set_node(revroot, :Revision, "Revision #{no}")
248
+
249
+ load_body(revroot, revision.body.values)
250
+
251
+ load_xrefs(revroot, revision.xreftable)
252
+
253
+ load_trailer(revroot, revision.trailer)
254
+
255
+ end
256
+
257
+ def load_body(rev, body)
258
+
259
+ bodyroot = @treestore.append(rev)
260
+ @treestore.set_value(bodyroot, OBJCOL, body)
261
+
262
+ set_node(bodyroot, :Body, "Body")
263
+
264
+ body.sort_by{|obj| obj.file_offset}.each { |object|
265
+ begin
266
+ load_object(bodyroot, object)
267
+ rescue Exception => e
268
+ msg = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
269
+
270
+ #@parent.error(msg)
271
+ next
272
+ end
273
+ }
274
+
275
+ end
276
+
277
+ def load_object(container, object, name = nil)
278
+
279
+ obj = @treestore.append(container)
280
+ @treestore.set_value(obj, OBJCOL, object)
281
+
282
+ type = object.real_type.to_s.split('::').last.to_sym
283
+
284
+ if name.nil?
285
+ name =
286
+ case object
287
+ when Origami::String
288
+ '"' + object.value + '"'
289
+ when Origami::Number, Name
290
+ object.value.to_s
291
+ else
292
+ object.type.to_s
293
+ end
294
+ end
295
+
296
+ set_node(obj, type, name)
297
+
298
+ if object.is_a? Origami::Array
299
+ object.each { |subobject|
300
+ load_object(obj, subobject)
301
+ }
302
+ elsif object.is_a? Origami::Dictionary
303
+ object.each_key { |subkey|
304
+ load_object(obj, object[subkey.value], subkey.value.to_s)
305
+ }
306
+ elsif object.is_a? Origami::Stream
307
+ load_object(obj, object.dictionary, "Stream Dictionary")
308
+ end
309
+
310
+ end
311
+
312
+ def load_xrefstm(stm, embxref)
313
+
314
+ xref = @treestore.append(stm)
315
+ @treestore.set_value(xref, OBJCOL, embxref)
316
+
317
+ if embxref.is_a?(XRef)
318
+ set_node(xref, :XRef, embxref.to_s.chomp)
319
+ else
320
+ set_node(xref, :XRef, "xref to ObjectStream #{embxref.objstmno}, object index #{embxref.index}")
321
+ end
322
+
323
+ end
324
+
325
+ def load_xrefs(rev, table)
326
+
327
+ if table
328
+
329
+ section = @treestore.append(rev)
330
+ @treestore.set_value(section, OBJCOL, table)
331
+
332
+ set_node(section, :XRefSection, "XRef section")
333
+
334
+ table.each { |subtable|
335
+
336
+ subsection = @treestore.append(section)
337
+ @treestore.set_value(subsection, OBJCOL, subtable)
338
+
339
+ set_node(subsection, :XRefSubSection, "#{subtable.range.begin} #{subtable.range.end - subtable.range.begin + 1}")
340
+
341
+ subtable.each { |entry|
342
+
343
+ xref = @treestore.append(subsection)
344
+ @treestore.set_value(xref, OBJCOL, entry)
345
+
346
+ set_node(xref, :XRef, entry.to_s.chomp)
347
+
348
+ }
349
+
350
+ }
351
+
352
+ end
353
+
354
+ end
355
+
356
+ def load_trailer(rev, trailer)
357
+
358
+ trailerroot = @treestore.append(rev)
359
+ @treestore.set_value(trailerroot, OBJCOL, trailer)
360
+
361
+ set_node(trailerroot, :Trailer, "Trailer")
362
+
363
+ unless trailer.dictionary.nil?
364
+ load_object(trailerroot, trailer.dictionary)
365
+ end
366
+
367
+ end
368
+
369
+ def reset_appearance
370
+
371
+ @@appearance[:Filename] = {:Color => "black", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
372
+ @@appearance[:Header] = {:Color => "darkgreen", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
373
+ @@appearance[:Revision] = {:Color => "blue", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
374
+ @@appearance[:Body] = {:Color => "purple", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
375
+ @@appearance[:XRefSection] = {:Color => "purple", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
376
+ @@appearance[:XRefSubSection] = {:Color => "brown", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
377
+ @@appearance[:XRef] = {:Color => "gray20", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
378
+ @@appearance[:Trailer] = {:Color => "purple", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
379
+ @@appearance[:StartXref] = {:Color => "black", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
380
+ @@appearance[:String] = {:Color => "red", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_ITALIC}
381
+ @@appearance[:Name] = {:Color => "gray", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_ITALIC}
382
+ @@appearance[:Number] = {:Color => "orange", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_NORMAL}
383
+ @@appearance[:Dictionary] = {:Color => "brown", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
384
+ @@appearance[:Stream] = {:Color => "darkcyan", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
385
+ @@appearance[:StreamData] = {:Color => "darkcyan", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_OBLIQUE}
386
+ @@appearance[:Array] = {:Color => "darkgreen", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL}
387
+ @@appearance[:Reference] = {:Color => "black", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_OBLIQUE}
388
+ @@appearance[:Boolean] = {:Color => "deeppink", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_NORMAL}
389
+
390
+ end
391
+
392
+ def get_object_appearance(type)
393
+ @@appearance[type]
394
+ end
395
+
396
+ def set_node(node, type, text)
397
+
398
+ @treestore.set_value(node, TEXTCOL, text)
399
+
400
+ app = get_object_appearance(type)
401
+ @treestore.set_value(node, WEIGHTCOL, app[:Weight])
402
+ @treestore.set_value(node, STYLECOL, app[:Style])
403
+ @treestore.set_value(node, FGCOL, app[:Color])
404
+
405
+ end
406
+
407
+ end
408
+
409
+ end