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,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
+