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,489 @@
1
+ =begin
2
+
3
+ = File
4
+ adobe/ppklite.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/object'
27
+ require 'origami/name'
28
+ require 'origami/dictionary'
29
+ require 'origami/reference'
30
+ require 'origami/boolean'
31
+ require 'origami/numeric'
32
+ require 'origami/string'
33
+ require 'origami/array'
34
+ require 'origami/trailer'
35
+ require 'origami/xreftable'
36
+
37
+ require 'openssl'
38
+
39
+ module Origami
40
+
41
+ module Adobe
42
+
43
+ #
44
+ # Class representing an Adobe Reader certificate store.
45
+ #
46
+ class PPKLite
47
+
48
+ #
49
+ # Class representing a certificate store header.
50
+ #
51
+ class Header
52
+
53
+ MAGIC = /\A%PPKLITE-(\d)\.(\d)/
54
+
55
+ attr_accessor :majorversion, :minorversion
56
+
57
+ #
58
+ # Creates a file header, with the given major and minor versions.
59
+ # _majorversion_:: Major version.
60
+ # _minorversion_:: Minor version.
61
+ #
62
+ def initialize(majorversion = 2, minorversion = 1)
63
+ @majorversion, @minorversion = majorversion, minorversion
64
+ end
65
+
66
+ def self.parse(stream) #:nodoc:
67
+
68
+ if not stream.scan(MAGIC).nil?
69
+ maj = stream[1].to_i
70
+ min = stream[2].to_i
71
+ else
72
+ raise InvalidHeader, "Invalid header format"
73
+ end
74
+
75
+ PPKLite::Header.new(maj,min)
76
+ end
77
+
78
+ #
79
+ # Outputs self into PDF code.
80
+ #
81
+ def to_s
82
+ "%PPKLITE-#{@majorversion}.#{@minorversion}" + EOL
83
+ end
84
+
85
+ def to_sym #:nodoc:
86
+ "#{@majorversion}.#{@minorversion}".to_sym
87
+ end
88
+
89
+ def to_f #:nodoc:
90
+ to_sym.to_s.to_f
91
+ end
92
+
93
+ end
94
+
95
+ class Revision #:nodoc;
96
+ attr_accessor :pdf
97
+ attr_accessor :body, :xreftable, :trailer
98
+
99
+ def initialize(adbk)
100
+ @pdf = adbk
101
+ @body = {}
102
+ @xreftable = nil
103
+ @trailer = nil
104
+ end
105
+
106
+ def trailer=(trl)
107
+ trl.pdf = @pdf
108
+ @trailer = trl
109
+ end
110
+ end
111
+
112
+ attr_accessor :header, :revisions
113
+
114
+ def initialize #:nodoc:
115
+ @header = PPKLite::Header.new
116
+ @revisions = [ Revision.new(self) ]
117
+ @revisions.first.trailer = Trailer.new
118
+ end
119
+
120
+ def objects
121
+ def append_subobj(root, objset)
122
+ if objset.find{ |o| o.object_id == root.object_id }.nil?
123
+ objset << root
124
+ if root.is_a?(Array) or root.is_a?(Dictionary)
125
+ root.each { |subobj| append_subobj(subobj, objset) unless subobj.is_a?(Reference) }
126
+ end
127
+ end
128
+ end
129
+
130
+ objset = []
131
+ @revisions.first.body.values.each do |object|
132
+ unless object.is_a?(Reference)
133
+ append_subobj(object, objset)
134
+ end
135
+ end
136
+
137
+ objset
138
+ end
139
+
140
+ def <<(object)
141
+
142
+ object.set_indirect(true)
143
+
144
+ if object.no.zero?
145
+ maxno = 1
146
+ while get_object(maxno) do maxno = maxno.succ end
147
+
148
+ object.generation = 0
149
+ object.no = maxno
150
+ end
151
+
152
+ @revisions.first.body[object.reference] = object
153
+
154
+ object.reference
155
+ end
156
+
157
+ def Catalog
158
+ get_object(@trailer.Root)
159
+ end
160
+
161
+ def save(filename)
162
+
163
+ bin = ""
164
+ bin << @header.to_s
165
+
166
+ lastno, brange = 0, 0
167
+
168
+ xrefs = [ XRef.new(0, XRef::LASTFREE, XRef::FREE) ]
169
+ xrefsection = XRef::Section.new
170
+
171
+ @revisions.first.body.values.sort.each { |obj|
172
+ if (obj.no - lastno).abs > 1
173
+ xrefsection << XRef::Subsection.new(brange, xrefs)
174
+ brange = obj.no
175
+ xrefs.clear
176
+ end
177
+
178
+ xrefs << XRef.new(bin.size, obj.generation, XRef::USED)
179
+ lastno = obj.no
180
+
181
+ bin << obj.to_s
182
+ }
183
+
184
+ xrefsection << XRef::Subsection.new(brange, xrefs)
185
+
186
+ @xreftable = xrefsection
187
+ @trailer ||= Trailer.new
188
+ @trailer.Size = rev.body.size + 1
189
+ @trailer.startxref = bin.size
190
+
191
+ bin << @xreftable.to_s
192
+ bin << @trailer.to_s
193
+
194
+ fd = File.open(filename, "w").binmode
195
+ fd << bin
196
+ fd.close
197
+
198
+ show_entries
199
+ end
200
+ alias saveas save
201
+
202
+ #
203
+ # Prints registered users in the address book
204
+ #
205
+ def show_users
206
+
207
+ puts "----------"
208
+ puts "Users list"
209
+ puts "----------"
210
+
211
+ @revisions.first.body.values.each { |obj| if obj.is_a?(User) then obj.show; puts end }
212
+
213
+ nil
214
+ end
215
+
216
+ #
217
+ # Prints registered certificates in the addressbook
218
+ #
219
+ def show_certs
220
+ puts "-----------------"
221
+ puts "Certificates list"
222
+ puts "-----------------"
223
+
224
+ @revisions.first.body.values.each { |obj| if obj.is_a?(Certificate) then obj.show; puts end }
225
+
226
+ nil
227
+ end
228
+
229
+ #
230
+ # Prints certificate with the specified id
231
+ #
232
+ def show_cert(id)
233
+ @revisions.first.body.values.find_all { |obj| obj.is_a?(Certificate) and obj.ID == id }.each do |cert|
234
+ cert.show
235
+ puts
236
+ end
237
+
238
+ nil
239
+ end
240
+
241
+ #
242
+ # Returns a Certificate dictionary corresponding to the specified id
243
+ #
244
+ def get_cert(id)
245
+ @revisions.first.body.values.find { |obj| obj.is_a?(Certificate) and obj.ID == id }
246
+ end
247
+
248
+ def show_user(id)
249
+ users = @revisions.first.body.values.find_all { |obj| obj.is_a?(User) and obj.ID == id }.each do |user|
250
+ user.show
251
+ puts
252
+ end
253
+
254
+ nil
255
+ end
256
+
257
+ #
258
+ # Prints users and certificates registered in the address book
259
+ #
260
+ def show_entries
261
+ show_users
262
+ show_certs
263
+
264
+ puts "End of address book."
265
+ end
266
+
267
+ #
268
+ # Add a certificate into the address book
269
+ #
270
+ def add_certificate(certfile, attributes, viewable = false, editable = false)
271
+
272
+ cert = Certificate.new
273
+ cert.Cert = OpenSSL::X509::Certificate.new(certfile).to_der
274
+ cert.ID = self.Catalog.PPK.AddressBook.NextID
275
+ self.Catalog.PPK.AddressBook.NextID += 1
276
+ cert.Trust = attributes
277
+ cert.Viewable = viewable
278
+ cert.Editable = editable
279
+
280
+ self.Catalog.PPK.AddressBook.Entries.push(self << cert)
281
+
282
+ show_certs
283
+ end
284
+
285
+ alias to_s show_entries
286
+ alias to_str show_entries
287
+
288
+ class Catalog < Dictionary
289
+
290
+ include StandardObject
291
+
292
+ field :Type, :Type => Name, :Default => :Catalog, :Required => true
293
+ field :PPK, :Type => Dictionary, :Required => true
294
+
295
+ def initialize(hash = {}) #:nodoc:
296
+ super(hash)
297
+ end
298
+
299
+ end
300
+
301
+ class PPK < Dictionary
302
+
303
+ include StandardObject
304
+
305
+ field :Type, :Type => Name, :Default => :PPK, :Required => true
306
+ field :User, :Type => Dictionary, :Required => true
307
+ field :AddressBook, :Type => Dictionary, :Required => true
308
+ field :V, :Type => Integer, :Default => 0x10001, :Required => true
309
+
310
+ def initialize(hash = {}) #:nodoc:
311
+ super(hash)
312
+ end
313
+
314
+ end
315
+
316
+ class UserList < Dictionary
317
+
318
+ include StandardObject
319
+
320
+ field :Type, :Type => Name, :Default => :User, :Required => true
321
+
322
+ def initialize(hash = {})
323
+ super(hash)
324
+ end
325
+
326
+ end
327
+
328
+ class AddressList < Dictionary
329
+
330
+ include StandardObject
331
+
332
+ field :Type, :Type => Name, :Default => :AddressBook, :Required => true
333
+ field :NextID, :Type => Integer
334
+ field :Entries, :Type => Array, :Default => [], :Required => true
335
+
336
+ def initialize(hash = {}) #:nodoc:
337
+ super(hash)
338
+ end
339
+
340
+ end
341
+
342
+ module Descriptor
343
+
344
+ CERTIFICATE = 1
345
+ USER = 2
346
+
347
+ def self.included(receiver) #:nodoc:
348
+ receiver.field :ID, :Type => Integer, :Required => true
349
+ receiver.field :ABEType, :Type => Integer, :Default => Descriptor::CERTIFICATE, :Required => true
350
+ end
351
+
352
+ def initialize(hash = {}) #:nodoc:
353
+ super(hash)
354
+ end
355
+
356
+ end
357
+
358
+ class User < Dictionary
359
+
360
+ include StandardObject
361
+ include Descriptor
362
+
363
+ field :ABEType, :Type => Integer, :Default => Descriptor::USER, :Required => true
364
+ field :Name, :Type => String, :Required => true
365
+ field :Encrypt, :Type => Integer
366
+ field :Certs, :Type => Array, :Default => [], :Required => true
367
+
368
+ def show
369
+ puts "ID: #{self.ID}"
370
+ puts "Name: #{self.Name}"
371
+ puts "Certificates: " + self.Certs.join(", ")
372
+ end
373
+
374
+ end
375
+
376
+ class Certificate < Dictionary
377
+
378
+ include StandardObject
379
+ include Descriptor
380
+
381
+ module Flags
382
+
383
+ CAN_CERTIFY = 1 << 1
384
+ ALLOW_DYNAMIC_CONTENT = 1 << 2
385
+ UNKNOWN_1 = 1 << 3
386
+ ALLOW_HIGH_PRIV_JS = 1 << 4
387
+ UNKNOWN_2 = 1 << 5
388
+ IS_ROOT_CA = 1 << 6
389
+
390
+ #~ FULL_TRUST = 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6
391
+ FULL_TRUST = 8190
392
+ end
393
+
394
+ field :ABEType, :Type => Integer, :Default => Descriptor::CERTIFICATE, :Required => true
395
+ field :Usage, :Type => Integer, :Default => 1, :Required => true
396
+ field :Viewable, :Type => Boolean, :Default => true
397
+ field :Editable, :Type => Boolean, :Default => true
398
+ field :Cert, :Type => String, :Required => true
399
+ field :Trust, :Type => Integer, :Default => Flags::UNKNOWN_2, :Required => true
400
+
401
+ def show
402
+ puts "ID: #{self.ID}"
403
+ puts "Viewable: #{self.Viewable}"
404
+ puts "Editable: #{self.Editable}"
405
+ puts "Trust attributes: #{self.Trust}"
406
+ end
407
+
408
+ end
409
+
410
+ def get_object(no, generation = 0) #:nodoc:
411
+
412
+ case no
413
+ when Reference
414
+ target = no
415
+ when ::Integer
416
+ target = Reference.new(no, generation)
417
+ when Origami::Object
418
+ return no
419
+ end
420
+
421
+ @revisions.first.body[target]
422
+ end
423
+
424
+ private
425
+
426
+ def rebuildxrefs #:nodoc:
427
+
428
+ startxref = @header.to_s.size
429
+
430
+ @revisions.first.body.values.each { |object|
431
+ startxref += object.to_s.size
432
+ }
433
+
434
+ @xreftable = buildxrefs(@revisions.first.body)
435
+
436
+ @trailer ||= Trailer.new
437
+ @trailer.Size = @revisions.first.body.size + 1
438
+ @trailer.startxref = startxref
439
+
440
+ self
441
+ end
442
+
443
+ def buildxrefs(objects) #:nodoc:
444
+
445
+ lastno = 0
446
+ brange = 0
447
+
448
+ xrefs = [ XRef.new(0, XRef::LASTFREE, XRef::FREE) ]
449
+
450
+ xrefsection = XRef::Section.new
451
+ objects.sort.each { |object|
452
+ if (object.no - lastno).abs > 1
453
+ xrefsection << XRef::Subsection.new(brange, xrefs)
454
+ brange = object.no
455
+ xrefs.clear
456
+ end
457
+
458
+ xrefs << XRef.new(get_object_offset(object.no, object.generation), object.generation, XRef::USED)
459
+
460
+ lastno = object.no
461
+ }
462
+
463
+ xrefsection << XRef::Subsection.new(brange, xrefs)
464
+
465
+ xrefsection
466
+ end
467
+
468
+ def get_object_offset(no,generation) #:nodoc:
469
+
470
+ bodyoffset = @header.to_s.size
471
+
472
+ objectoffset = bodyoffset
473
+
474
+ @revisions.first.body.values.each { |object|
475
+ if object.no == no and object.generation == generation then return objectoffset
476
+ else
477
+ objectoffset += object.to_s.size
478
+ end
479
+ }
480
+
481
+ nil
482
+ end
483
+
484
+ end
485
+
486
+ end
487
+
488
+ end
489
+