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,170 @@
1
+ =begin
2
+
3
+ = File
4
+ name.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
+ if RUBY_VERSION < '1.9'
27
+ class EmptySymbol
28
+ def ==(sym)
29
+ sym.is_a?(EmptySymbol)
30
+ end
31
+
32
+ def id2name
33
+ ""
34
+ end
35
+ alias to_s id2name
36
+
37
+ def to_sym
38
+ self
39
+ end
40
+
41
+ def to_o
42
+ Name.new("")
43
+ end
44
+
45
+ def inspect
46
+ ":"
47
+ end
48
+ end
49
+ end
50
+
51
+ module Origami
52
+
53
+ REGULARCHARS = "([^ \\t\\r\\n\\0\\[\\]<>()%\\/]|#[a-fA-F0-9][a-fA-F0-9])*" #:nodoc:
54
+
55
+ class InvalidNameObjectError < InvalidObjectError #:nodoc:
56
+ end
57
+
58
+ #
59
+ # Class representing a Name Object.
60
+ # Name objects are strings which identify some PDF file inner structures.
61
+ #
62
+ class Name #< DelegateClass(Symbol)
63
+
64
+ include Origami::Object
65
+
66
+ TOKENS = %w{ / } #:nodoc:
67
+
68
+ @@regexp = Regexp.new(WHITESPACES + TOKENS.first + "(" + REGULARCHARS + ")" + WHITESPACES) #:nodoc
69
+
70
+ #
71
+ # Creates a new Name.
72
+ # _name_:: A symbol representing the new Name value.
73
+ #
74
+ def initialize(name = "")
75
+ unless name.is_a?(Symbol) or name.is_a?(::String)
76
+ raise TypeError, "Expected type Symbol or String, received #{name.class}."
77
+ end
78
+
79
+ @value = name.to_s
80
+
81
+ super()
82
+ end
83
+
84
+ if RUBY_VERSION < '1.9'
85
+ def value
86
+ ( @value.empty? ) ? EmptySymbol.new : @value.to_sym
87
+ end
88
+ else
89
+ def value
90
+ @value.to_sym
91
+ end
92
+ end
93
+
94
+ def ==(object) #:nodoc:
95
+ @value.to_sym == object
96
+ end
97
+
98
+ def eql?(object) #:nodoc:
99
+ object.is_a?(Name) and self.to_s == object.to_s
100
+ end
101
+
102
+ def hash #:nodoc:
103
+ @value.hash
104
+ end
105
+
106
+ def to_s #:nodoc:
107
+ super(TOKENS.first + Name.expand(@value))
108
+ end
109
+
110
+ def self.parse(stream) #:nodoc:
111
+
112
+ offset = stream.pos
113
+
114
+ name =
115
+ if stream.scan(@@regexp).nil?
116
+ raise InvalidNameObjectError, "Bad name format"
117
+ else
118
+ value = stream[2]
119
+
120
+ Name.new(value.include?('#') ? contract(value) : value)
121
+ end
122
+
123
+ name.file_offset = offset
124
+
125
+ name
126
+ end
127
+
128
+ def self.contract(name) #:nodoc:
129
+
130
+ i = 0
131
+ while i < name.length
132
+
133
+ if name[i,1] == "#"
134
+ digits = name[i+1, 2]
135
+
136
+ unless /^[A-Za-z0-9]{2}$/ === digits
137
+ raise InvalidNameObjectError, "Irregular use of # token"
138
+ end
139
+
140
+ char = digits.hex.chr
141
+
142
+ if char == "\0"
143
+ raise InvalidNameObjectError, "Null byte forbidden inside name definition"
144
+ end
145
+
146
+ name[i, 3] = char
147
+ end
148
+
149
+ i = i + 1
150
+ end
151
+
152
+ name
153
+ end
154
+
155
+ def self.expand(name) #:nodoc:
156
+
157
+ forbiddenchars = /[ #\t\r\n\0\[\]<>()%\/]/
158
+
159
+ name.gsub!(forbiddenchars) do |c|
160
+ "#" + c[0].ord.to_s(16).rjust(2,"0")
161
+ end
162
+
163
+ name
164
+ end
165
+
166
+ def real_type ; Name end
167
+
168
+ end
169
+
170
+ end
@@ -0,0 +1,75 @@
1
+ =begin
2
+
3
+ = File
4
+ null.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
+ class InvalidNullObjectError < InvalidObjectError #:nodoc:
29
+ end
30
+
31
+ #
32
+ # Class representing Null Object.
33
+ #
34
+ class Null
35
+
36
+ include Origami::Object
37
+
38
+ TOKENS = %w{ null } #:nodoc:
39
+
40
+ @@regexp = Regexp.new(WHITESPACES + TOKENS.first)
41
+
42
+ def initialize
43
+ super
44
+ end
45
+
46
+ def self.parse(stream) #:nodoc:
47
+
48
+ offset = stream.pos
49
+
50
+ if stream.skip(@@regexp).nil?
51
+ raise InvalidNullObjectError
52
+ end
53
+
54
+ null = Null.new
55
+ null.file_offset = offset
56
+
57
+ null
58
+ end
59
+
60
+ #
61
+ # Returns *nil*.
62
+ #
63
+ def value
64
+ nil
65
+ end
66
+
67
+ def to_s #:nodoc:
68
+ super(TOKENS.first)
69
+ end
70
+
71
+ def real_type ; Null end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,188 @@
1
+ =begin
2
+
3
+ = File
4
+ numeric.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
+ require 'delegate'
23
+
24
+ module Origami
25
+
26
+ class InvalidIntegerObjectError < InvalidObjectError #:nodoc:
27
+ end
28
+
29
+ #
30
+ # Class representing a PDF number (Integer, or Real).
31
+ #
32
+ module Number
33
+ include Origami::Object
34
+
35
+ def ~
36
+ self.class.new(~self.to_i)
37
+ end
38
+
39
+ def |(val)
40
+ self.class.new(self.to_i | val)
41
+ end
42
+
43
+ def &(val)
44
+ self.class.new(self.to_i & val)
45
+ end
46
+
47
+ def ^(val)
48
+ self.class.new(self.to_i ^ val)
49
+ end
50
+
51
+ def <<(val)
52
+ self.class.new(self.to_i << val)
53
+ end
54
+
55
+ def >>(val)
56
+ self.class.new(self.to_i >> val)
57
+ end
58
+
59
+ def +(val)
60
+ self.class.new(self.to_i + val)
61
+ end
62
+
63
+ def -(val)
64
+ self.class.new(self.to_i - val)
65
+ end
66
+
67
+ def -@
68
+ self.class.new(-self.to_i)
69
+ end
70
+
71
+ def *(val)
72
+ self.class.new(self.to_i * val)
73
+ end
74
+
75
+ def /(val)
76
+ self.class.new(self.to_i / val)
77
+ end
78
+
79
+ def abs
80
+ self.class.new(self.to_i.abs)
81
+ end
82
+
83
+ def **(val)
84
+ self.class.new(self.to_i ** val)
85
+ end
86
+
87
+ def to_s
88
+ super(value.to_s)
89
+ end
90
+
91
+ def real_type ; Number end
92
+ end
93
+
94
+ #
95
+ # Class representing an Integer Object.
96
+ #
97
+ class Integer < DelegateClass(Bignum)
98
+
99
+ include Number
100
+
101
+ TOKENS = [ "(\\+|-)?[\\d]+[^.]?" ] #:nodoc:
102
+
103
+ REGEXP_TOKEN = Regexp.new(TOKENS.first)
104
+
105
+ @@regexp = Regexp.new(WHITESPACES + "((\\+|-)?[\\d]+)")
106
+
107
+ #
108
+ # Creates a new Integer from a Ruby Fixnum / Bignum.
109
+ # _i_:: The Integer value.
110
+ #
111
+ def initialize(i = 0)
112
+
113
+ unless i.is_a?(::Integer)
114
+ raise TypeError, "Expected type Fixnum or Bignum, received #{i.class}."
115
+ end
116
+
117
+ super(i)
118
+ end
119
+
120
+ def self.parse(stream) #:nodoc:
121
+
122
+ offset = stream.pos
123
+
124
+ if not stream.scan(@@regexp)
125
+ raise InvalidIntegerObjectError, "Invalid integer format"
126
+ end
127
+
128
+ value = stream[2].to_i
129
+ int = Integer.new(value)
130
+ int.file_offset = offset
131
+
132
+ int
133
+ end
134
+
135
+ alias value to_i
136
+
137
+ end
138
+
139
+ class InvalidRealObjectError < InvalidObjectError #:nodoc:
140
+ end
141
+
142
+ #
143
+ # Class representing a Real number Object.
144
+ # PDF real numbers are arbitrary precision numbers, depending on architectures.
145
+ #
146
+ class Real < DelegateClass(Float)
147
+
148
+ include Number
149
+
150
+ TOKENS = [ "(\\+|-)?([\\d]*\\.[\\d]+|[\\d]+\\.[\\d]*)([eE](\\+|-)?[\\d]+)?" ] #:nodoc:
151
+
152
+ REGEXP_TOKEN = Regexp.new(TOKENS.first)
153
+
154
+ @@regexp = Regexp.new(WHITESPACES + "(" + TOKENS.first + ")")
155
+
156
+ #
157
+ # Creates a new Real from a Ruby Float.
158
+ # _f_:: The new Real value.
159
+ #
160
+ def initialize(f = 0)
161
+
162
+ unless f.is_a?(Float)
163
+ raise TypeError, "Expected type Float, received #{f.class}."
164
+ end
165
+
166
+ super(f)
167
+ end
168
+
169
+ def self.parse(stream) #:nodoc:
170
+
171
+ offset = stream.pos
172
+
173
+ if not stream.scan(@@regexp)
174
+ raise InvalidRealObjectError, "Invalid real number format"
175
+ end
176
+
177
+ value = stream[2].to_f
178
+ real = Real.new(value)
179
+ real.file_offset = offset
180
+
181
+ real
182
+ end
183
+
184
+ alias value to_f
185
+
186
+ end
187
+
188
+ end
@@ -0,0 +1,233 @@
1
+ module Origami
2
+
3
+ module Obfuscator
4
+
5
+ WHITECHARS = [ " ", "\t", "\r", "\n", "\0" ]
6
+ OBJECTS = [ Array, Boolean, Dictionary, Integer, Name, Null, Stream, String, Real, Reference ]
7
+ MAX_INT = 0xFFFFFFFF
8
+ PRINTABLE = ("!".."9").to_a + (':'..'Z').to_a + ('['..'z').to_a + ('{'..'~').to_a
9
+ FILTERS = [ :FlateDecode, :RunLengthDecode, :LZWDecode, :ASCIIHexDecode, :ASCII85Decode ]
10
+
11
+ def self.junk_spaces(max_size = 3)
12
+ length = rand(max_size) + 1
13
+
14
+ ::Array.new(length) { WHITECHARS[rand(WHITECHARS.size)] }.join
15
+ end
16
+
17
+ def self.junk_comment(max_size = 15)
18
+ length = rand(max_size) + 1
19
+
20
+ junk_comment = ::Array.new(length) {
21
+ byte = rand(256).chr until (not byte.nil? and byte != "\n" and byte != "\r"); byte
22
+ }.join
23
+
24
+ "%#{junk_comment}#{EOL}"
25
+ end
26
+
27
+ def self.junk_object(type = nil)
28
+
29
+ if type.nil?
30
+ type = OBJECTS[rand(OBJECTS.size)]
31
+ end
32
+
33
+ unless type.include?(Origami::Object)
34
+ raise TypeError, "Not a valid object type"
35
+ end
36
+
37
+ Obfuscator.send("junk_#{type.to_s.split('::').last.downcase}")
38
+ end
39
+
40
+ def self.junk_array(max_size = 5)
41
+ length = rand(max_size) + 1
42
+
43
+ ::Array.new(length) {
44
+ obj = Obfuscator.junk_object until (not obj.nil? and not obj.is_a?(Stream)) ; obj
45
+ }.to_o
46
+ end
47
+
48
+ def self.junk_boolean
49
+ Boolean.new(rand(2).zero?)
50
+ end
51
+
52
+ def self.junk_dictionary(max_size = 5)
53
+ length = rand(max_size) + 1
54
+
55
+ hash = Hash.new
56
+ length.times do
57
+ obj = Obfuscator.junk_object
58
+ hash[Obfuscator.junk_name] = obj unless obj.is_a?(Stream)
59
+ end
60
+
61
+ hash.to_o
62
+ end
63
+
64
+ def self.junk_integer(max = MAX_INT)
65
+ Integer.new(rand(max + 1))
66
+ end
67
+
68
+ def self.junk_name(max_size = 8)
69
+ length = rand(max_size) + 1
70
+
71
+ Name.new(::Array.new(length) { PRINTABLE[rand(PRINTABLE.size)] }.join)
72
+ end
73
+
74
+ def self.junk_null
75
+ Null.new
76
+ end
77
+
78
+ def self.junk_stream(max_data_size = 200)
79
+
80
+ chainlen = rand(2) + 1
81
+ chain = ::Array.new(chainlen) { FILTERS[rand(FILTERS.size)] }
82
+
83
+ length = rand(max_data_size) + 1
84
+ junk_data = ::Array.new(length) { rand(256).chr }.join
85
+
86
+ stm = Stream.new
87
+ stm.dictionary = Obfuscator.junk_dictionary(5)
88
+ stm.setFilter(chain)
89
+ stm.data = junk_data
90
+
91
+ stm
92
+ end
93
+
94
+ def self.junk_string(max_size = 10)
95
+ length = rand(max_size) + 1
96
+
97
+ strtype = (rand(2).zero?) ? ByteString : HexaString
98
+
99
+ strtype.new(::Array.new(length) { PRINTABLE[rand(PRINTABLE.size)] }.join)
100
+ end
101
+
102
+ def self.junk_real
103
+ Real.new(rand * rand(MAX_INT + 1))
104
+ end
105
+
106
+ def self.junk_reference(max_no = 300, max_gen = 1)
107
+ no = rand(max_no) + 1
108
+ gen = rand(max_gen)
109
+
110
+ Reference.new(no, gen)
111
+ end
112
+
113
+ end
114
+
115
+ class Dictionary
116
+
117
+ def to_obfuscated_str
118
+ content = TOKENS.first + Obfuscator.junk_spaces
119
+ self.each_pair { |key, value|
120
+ content << Obfuscator.junk_spaces +
121
+ key.to_obfuscated_str + Obfuscator.junk_spaces +
122
+ value.to_obfuscated_str + Obfuscator.junk_spaces
123
+ }
124
+
125
+ content << TOKENS.last
126
+ super(content)
127
+ end
128
+
129
+ end
130
+
131
+ module Object
132
+ alias :to_obfuscated_str :to_s
133
+ end
134
+
135
+ class Array
136
+ def to_obfuscated_str
137
+ content = TOKENS.first + Obfuscator.junk_spaces
138
+ self.each { |entry|
139
+ content << entry.to_o.to_obfuscated_str + Obfuscator.junk_spaces
140
+ }
141
+
142
+ content << TOKENS.last
143
+
144
+ super(content)
145
+ end
146
+ end
147
+
148
+ class Null
149
+ alias :to_obfuscated_str :to_s
150
+ end
151
+
152
+ class Boolean
153
+ alias :to_obfuscated_str :to_s
154
+ end
155
+
156
+ class Integer
157
+ alias :to_obfuscated_str :to_s
158
+ end
159
+
160
+ class Real
161
+ alias :to_obfuscated_str :to_s
162
+ end
163
+
164
+ class Reference
165
+ def to_obfuscated_str
166
+ refstr = refno.to_s + Obfuscator.junk_spaces + refgen.to_s + Obfuscator.junk_spaces + "R"
167
+
168
+ super(refstr)
169
+ end
170
+ end
171
+
172
+ class ByteString
173
+ def to_obfuscated_str
174
+ to_s
175
+ end
176
+ end
177
+
178
+ class HexaString
179
+ def to_obfuscated_str
180
+ to_s
181
+ end
182
+ end
183
+
184
+ class Name
185
+ def to_obfuscated_str(prop = 2)
186
+ name = @value.dup
187
+
188
+ forbiddenchars = [ " ","#","\t","\r","\n","\0","[","]","<",">","(",")","%","/","\\" ]
189
+
190
+ name.gsub!(/./) do |c|
191
+ if rand(prop) == 0 or forbiddenchars.include?(c)
192
+ hexchar = c[0].to_s(base=16)
193
+ hexchar = "0" + hexchar if hexchar.length < 2
194
+
195
+ '#' + hexchar
196
+ else
197
+ c
198
+ end
199
+ end
200
+
201
+ super(TOKENS.first + name)
202
+ end
203
+ end
204
+
205
+ class Stream
206
+ def to_obfuscated_str
207
+ content = ""
208
+
209
+ content << @dictionary.to_obfuscated_str
210
+ content << "stream" + EOL
211
+ content << self.rawdata
212
+ content << EOL << TOKENS.last
213
+
214
+ super(content)
215
+ end
216
+ end
217
+
218
+ class Trailer
219
+
220
+ def to_obfuscated_str
221
+ content = ""
222
+ if self.has_dictionary?
223
+ content << TOKENS.first << EOL << @dictionary.to_obfuscated_str << EOL
224
+ end
225
+
226
+ content << XREF_TOKEN << EOL << @startxref.to_s << EOL << TOKENS.last << EOL
227
+
228
+ content
229
+ end
230
+
231
+ end
232
+
233
+ end