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,447 @@
1
+ =begin
2
+
3
+ = File
4
+ xreftable.rb
5
+
6
+ = Info
7
+ Origami is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Origami is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+
22
+ module Origami
23
+
24
+ class PDF
25
+
26
+ #
27
+ # Tries to strip any xrefs information off the document.
28
+ #
29
+ def remove_xrefs
30
+ def delete_xrefstm(xrefstm)
31
+ prev = xrefstm.Prev
32
+ delete_object(xrefstm.reference)
33
+
34
+ if prev.is_a?(Integer) and (prev_stm = get_object_by_offset(prev)).is_a?(XRefStream)
35
+ delete_xrefstm(prev_stm)
36
+ end
37
+ end
38
+
39
+ @revisions.reverse_each do |rev|
40
+ if rev.has_xrefstm?
41
+ delete_xrefstm(rev.xrefstm)
42
+ end
43
+
44
+ if rev.trailer.has_dictionary? and rev.trailer.XRefStm.is_a?(Integer)
45
+ xrefstm = get_object_by_offset(rev.trailer.XRefStm)
46
+
47
+ delete_xrefstm(xrefstm) if xrefstm.is_a?(XRefStream)
48
+ end
49
+
50
+ rev.xrefstm = rev.xreftable = nil
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ class InvalidXRefError < Exception #:nodoc:
57
+ end
58
+
59
+ #
60
+ # Class representing a Cross-reference information.
61
+ #
62
+ class XRef
63
+
64
+ FREE = "f"
65
+ USED = "n"
66
+ FIRSTFREE = 65535
67
+
68
+ @@regexp = /(\d{10}) (\d{5}) (n|f)(\r| )\n/
69
+
70
+ attr_accessor :offset, :generation, :state
71
+
72
+ #
73
+ # Creates a new XRef.
74
+ # _offset_:: The file _offset_ of the referenced Object.
75
+ # _generation_:: The generation number of the referenced Object.
76
+ # _state_:: The state of the referenced Object (FREE or USED).
77
+ #
78
+ def initialize(offset, generation, state)
79
+
80
+ @offset, @generation, @state = offset, generation, state
81
+
82
+ end
83
+
84
+ def self.parse(stream) #:nodoc:
85
+
86
+ if stream.scan(@@regexp).nil?
87
+ raise InvalidXRefError, "Invalid XRef format"
88
+ end
89
+
90
+ offset = stream[1].to_i
91
+ generation = stream[2].to_i
92
+ state = stream[3]
93
+
94
+ XRef.new(offset, generation, state)
95
+ end
96
+
97
+ #
98
+ # Outputs self into PDF code.
99
+ #
100
+ def to_s
101
+ off = ("0" * (10 - @offset.to_s.length)) + @offset.to_s
102
+ gen = ("0" * (5 - @generation.to_s.length)) + @generation.to_s
103
+
104
+ "#{off} #{gen} #{@state}" + EOL
105
+ end
106
+
107
+ def to_xrefstm_data(type_w, field1_w, field2_w)
108
+ type_w <<= 3
109
+ field1_w <<= 3
110
+ field2_w <<= 3
111
+
112
+ type = ((@state == FREE) ? "\000" : "\001").unpack("B#{type_w}")[0]
113
+
114
+ offset = @offset.to_s(2)
115
+ offset = '0' * (field1_w - offset.size) + offset
116
+ generation = @generation.to_s(2)
117
+
118
+ generation = '0' * (field2_w - generation.size) + generation
119
+
120
+ [ type , offset, generation ].pack("B#{type_w}B#{field1_w}B#{field2_w}")
121
+ end
122
+
123
+ class InvalidXRefSubsectionError < Exception #:nodoc:
124
+ end
125
+
126
+ #
127
+ # Class representing a cross-reference subsection.
128
+ # A subsection contains a continute set of XRef.
129
+ #
130
+ class Subsection
131
+
132
+ @@regexp = Regexp.new("(\\d+) (\\d+)" + WHITESPACES + "(\\r?\\n|\\r\\n?)")
133
+
134
+ attr_reader :range
135
+
136
+ #
137
+ # Creates a new XRef subsection.
138
+ # _start_:: The number of the first object referenced in the subsection.
139
+ # _entries_:: An array of XRef.
140
+ #
141
+ def initialize(start, entries = [])
142
+
143
+ @entries = entries.dup
144
+ @range = Range.new(start, start + entries.size - 1)
145
+
146
+ end
147
+
148
+ def self.parse(stream) #:nodoc:
149
+
150
+ if stream.scan(@@regexp).nil?
151
+ raise InvalidXRefSubsectionError, "Bad subsection format"
152
+ end
153
+
154
+ start = stream[1].to_i
155
+ size = stream[2].to_i
156
+
157
+ xrefs = []
158
+ size.times {
159
+ xrefs << XRef.parse(stream)
160
+ }
161
+
162
+ XRef::Subsection.new(start, xrefs)
163
+ end
164
+
165
+ #
166
+ # Returns whether this subsection contains information about a particular object.
167
+ # _no_:: The Object number.
168
+ #
169
+ def has_object?(no)
170
+ @range.include?(no)
171
+ end
172
+
173
+ #
174
+ # Returns XRef associated with a given object.
175
+ # _no_:: The Object number.
176
+ #
177
+ def [](no)
178
+ @entries[no - @range.begin]
179
+ end
180
+
181
+ #
182
+ # Processes each XRef in the subsection.
183
+ #
184
+ def each(&b)
185
+ @entries.each(&b)
186
+ end
187
+
188
+ #
189
+ # Outputs self into PDF code.
190
+ #
191
+ def to_s
192
+ section = "#{@range.begin} #{@range.end - @range.begin + 1}" + EOL
193
+ @entries.each { |xref|
194
+ section << xref.to_s
195
+ }
196
+
197
+ section
198
+ end
199
+
200
+ end
201
+
202
+ class InvalidXRefSectionError < Exception #:nodoc:
203
+ end
204
+
205
+ #
206
+ # Class representing a Cross-reference table.
207
+ # A section contains a set of XRefSubsection.
208
+ #
209
+ class Section
210
+
211
+ @@regexp_open = Regexp.new(WHITESPACES + "xref" + WHITESPACES + "(\\r?\\n|\\r\\n?)")
212
+ @@regexp_sub = Regexp.new("(\\d+) (\\d+)" + WHITESPACES + "(\\r?\\n|\\r\\n?)")
213
+
214
+ #
215
+ # Creates a new XRef section.
216
+ # _subsections_:: An array of XRefSubsection.
217
+ #
218
+ def initialize(subsections = [])
219
+ @subsections = subsections
220
+ end
221
+
222
+ def self.parse(stream) #:nodoc:
223
+
224
+ if stream.skip(@@regexp_open).nil?
225
+ raise InvalidXRefSectionError, "No xref token found"
226
+ end
227
+
228
+ subsections = []
229
+ while stream.match?(@@regexp_sub) do
230
+ subsections << XRef::Subsection.parse(stream)
231
+ end
232
+
233
+ XRef::Section.new(subsections)
234
+ end
235
+
236
+ #
237
+ # Appends a new subsection.
238
+ # _subsection_:: A XRefSubsection.
239
+ #
240
+ def <<(subsection)
241
+ @subsections << subsection
242
+ end
243
+
244
+ #
245
+ # Returns a XRef associated with a given object.
246
+ # _no_:: The Object number.
247
+ #
248
+ def [](no)
249
+ @subsections.each { |s|
250
+ return s[no] if s.has_object?(no)
251
+ }
252
+ nil
253
+ end
254
+
255
+ alias :find :[]
256
+
257
+ #
258
+ # Processes each XRefSubsection.
259
+ #
260
+ def each(&b)
261
+ @subsections.each(&b)
262
+ end
263
+
264
+ #
265
+ # Outputs self into PDF code.
266
+ #
267
+ def to_s
268
+ "xref" << EOL << @subsections.join
269
+ end
270
+
271
+ end
272
+
273
+ end
274
+
275
+ #
276
+ # An xref poiting to an Object embedded in an ObjectStream.
277
+ #
278
+ class XRefToCompressedObj
279
+
280
+ attr_accessor :objstmno, :index
281
+
282
+ def initialize(objstmno, index)
283
+ @objstmno = objstmno
284
+ @index = index
285
+ end
286
+
287
+ def to_xrefstm_data(type_w, field1_w, field2_w)
288
+
289
+ type_w <<= 3
290
+ field1_w <<= 3
291
+ field2_w <<= 3
292
+
293
+ type = "\002".unpack("B#{type_w}")[0]
294
+ objstmno = @objstmno.to_s(2)
295
+ objstmno = '0' * (field1_w - objstmno.size) + objstmno
296
+ index = @index.to_s(2)
297
+ index = '0' * (field2_w - index.size) + index
298
+
299
+ [ type , objstmno, index ].pack("B#{type_w}B#{field1_w}B#{field2_w}")
300
+ end
301
+
302
+ end
303
+
304
+ class InvalidXRefStreamObjectError < InvalidStreamObjectError ; end
305
+
306
+ #
307
+ # Class representing a XRef Stream.
308
+ #
309
+ class XRefStream < Stream
310
+
311
+ XREF_FREE = 0
312
+ XREF_USED = 1
313
+ XREF_COMPRESSED = 2
314
+
315
+ include Enumerable
316
+ include StandardObject
317
+
318
+ attr_reader :xrefs
319
+
320
+ #
321
+ # Xref fields
322
+ #
323
+ field :Type, :Type => Name, :Default => :XRef, :Required => true, :Version => "1.5"
324
+ field :Size, :Type => Integer, :Required => true
325
+ field :Index, :Type => Array
326
+ field :Prev, :Type => Integer
327
+ field :W, :Type => Array, :Required => true
328
+
329
+ #
330
+ # Trailer fields
331
+ #
332
+ field :Root, :Type => Dictionary, :Required => true
333
+ field :Encrypt, :Type => Dictionary
334
+ field :Info, :Type => Dictionary
335
+ field :ID, :Type => Array
336
+
337
+ def initialize(data = "", dictionary = {})
338
+ super(data, dictionary)
339
+
340
+ @xrefs = nil
341
+ end
342
+
343
+ def pre_build #:nodoc:
344
+ load! if @xrefs.nil?
345
+
346
+ self.W = [ 1, 2, 2 ] unless has_field?(:W)
347
+ self.Size = @xrefs.length + 1
348
+
349
+ save!
350
+
351
+ super
352
+ end
353
+
354
+ #
355
+ # Adds an XRef to this Stream.
356
+ #
357
+ def <<(xref)
358
+ load! if @xrefs.nil?
359
+
360
+ @xrefs << xref
361
+ end
362
+
363
+ #
364
+ # Iterates over each XRef present in the stream.
365
+ #
366
+ def each(&b)
367
+ load! if @xrefs.nil?
368
+
369
+ @xrefs.each(&b)
370
+ end
371
+
372
+ #
373
+ # Returns an XRef matching this object number.
374
+ #
375
+ def find(no)
376
+ load! if @xrefs.nil?
377
+
378
+ ranges = self.Index || [ 0, @xrefs.length ]
379
+
380
+ index = 0
381
+ (ranges.size / 2).times do |i|
382
+ brange = ranges[i*2].to_i
383
+ size = ranges[i*2+1].to_i
384
+ return @xrefs[index + no - brange] if Range.new(brange, brange + size - 1) === no
385
+
386
+ index += size
387
+ end
388
+
389
+ nil
390
+ end
391
+
392
+ def clear
393
+ @rawdata, @data = nil, ''
394
+ @xrefs = []
395
+ self.Index = []
396
+ end
397
+
398
+ private
399
+
400
+ def load! #:nodoc:
401
+ if @xrefs.nil? and has_field?(:W)
402
+ widths = self.W
403
+
404
+ if not widths.is_a?(Array) or widths.length != 3 or widths.any?{|width| not width.is_a?(Integer) }
405
+ raise InvalidXRefStreamObjectError, "W field must be an array of 3 integers"
406
+ end
407
+
408
+ decode!
409
+
410
+ type_w = self.W[0]
411
+ field1_w = self.W[1]
412
+ field2_w = self.W[2]
413
+
414
+ entrymask = "B#{type_w << 3}B#{field1_w << 3}B#{field2_w << 3}"
415
+ size = @data.size / (type_w + field1_w + field2_w)
416
+
417
+ entries = @data.unpack(entrymask * size).map!{|field| field.to_i(2) }
418
+
419
+ @xrefs = []
420
+ size.times do |i|
421
+ type,field1,field2 = entries[i*3],entries[i*3+1],entries[i*3+2]
422
+ case type
423
+ when XREF_FREE
424
+ @xrefs << XRef.new(field1, field2, XRef::FREE)
425
+ when XREF_USED
426
+ @xrefs << XRef.new(field1, field2, XRef::USED)
427
+ when XREF_COMPRESSED
428
+ @xrefs << XRefToCompressedObj.new(field1, field2)
429
+ end
430
+ end
431
+ else
432
+ @xrefs = []
433
+ end
434
+ end
435
+
436
+ def save! #:nodoc:
437
+ @data = ""
438
+
439
+ type_w, field1_w, field2_w = self.W
440
+ @xrefs.each do |xref| @data << xref.to_xrefstm_data(type_w, field1_w, field2_w) end
441
+
442
+ encode!
443
+ end
444
+
445
+ end
446
+
447
+ end
@@ -0,0 +1,66 @@
1
+ =begin
2
+
3
+ = File
4
+ patterns.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 Origami
27
+
28
+ module Template
29
+
30
+ class AxialGradient < Graphics::Pattern::Shading::Axial
31
+
32
+ def initialize(from, to, color0, color1, coeff = 1)
33
+ super()
34
+
35
+ set_indirect(true)
36
+
37
+ x, y = from
38
+ tx, ty = to
39
+
40
+ c0 = Graphics::Color.to_a(color0)
41
+ c1 = Graphics::Color.to_a(color1)
42
+
43
+ space =
44
+ case c0.size
45
+ when 1 then Graphics::Color::Space::DEVICE_GRAY
46
+ when 3 then Graphics::Color::Space::DEVICE_RGB
47
+ when 4 then Graphics::Color::Space::DEVICE_CMYK
48
+ end
49
+
50
+ f = Function::Exponential.new
51
+ f.Domain = [ 0.0, 1.0 ]
52
+ f.N = coeff
53
+ f.C0, f.C1 = c0, c1
54
+
55
+ self.ColorSpace = space
56
+ self.Coords = [ x, y, tx, ty ]
57
+ self.Function = f
58
+ self.Extend = [ true, true ]
59
+
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ end