origami 1.2.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/README.md +112 -0
  4. data/bin/config/pdfcop.conf.yml +232 -233
  5. data/bin/gui/about.rb +27 -37
  6. data/bin/gui/config.rb +108 -117
  7. data/bin/gui/file.rb +416 -365
  8. data/bin/gui/gtkhex.rb +1138 -1153
  9. data/bin/gui/hexview.rb +55 -57
  10. data/bin/gui/imgview.rb +48 -51
  11. data/bin/gui/menu.rb +388 -386
  12. data/bin/gui/properties.rb +114 -130
  13. data/bin/gui/signing.rb +571 -617
  14. data/bin/gui/textview.rb +77 -95
  15. data/bin/gui/treeview.rb +382 -387
  16. data/bin/gui/walker.rb +227 -232
  17. data/bin/gui/xrefs.rb +56 -60
  18. data/bin/pdf2pdfa +53 -57
  19. data/bin/pdf2ruby +212 -228
  20. data/bin/pdfcop +338 -348
  21. data/bin/pdfdecompress +58 -65
  22. data/bin/pdfdecrypt +56 -60
  23. data/bin/pdfencrypt +75 -80
  24. data/bin/pdfexplode +185 -182
  25. data/bin/pdfextract +201 -218
  26. data/bin/pdfmetadata +83 -82
  27. data/bin/pdfsh +4 -5
  28. data/bin/pdfwalker +1 -2
  29. data/bin/shell/.irbrc +45 -82
  30. data/bin/shell/console.rb +105 -130
  31. data/bin/shell/hexdump.rb +40 -64
  32. data/examples/README.md +34 -0
  33. data/examples/attachments/attachment.rb +38 -0
  34. data/examples/attachments/nested_document.rb +51 -0
  35. data/examples/encryption/encryption.rb +28 -0
  36. data/{samples/actions/triggerevents/trigger.rb → examples/events/events.rb} +13 -16
  37. data/examples/flash/flash.rb +37 -0
  38. data/{samples → examples}/flash/helloworld.swf +0 -0
  39. data/examples/forms/javascript.rb +54 -0
  40. data/examples/forms/xfa.rb +115 -0
  41. data/examples/javascript/hello_world.rb +22 -0
  42. data/examples/javascript/js_emulation.rb +54 -0
  43. data/examples/loop/goto.rb +32 -0
  44. data/examples/loop/named.rb +33 -0
  45. data/examples/signature/signature.rb +65 -0
  46. data/examples/uri/javascript.rb +56 -0
  47. data/examples/uri/open-uri.rb +21 -0
  48. data/examples/uri/submitform.rb +47 -0
  49. data/lib/origami.rb +29 -42
  50. data/lib/origami/3d.rb +350 -225
  51. data/lib/origami/acroform.rb +262 -288
  52. data/lib/origami/actions.rb +268 -288
  53. data/lib/origami/annotations.rb +697 -722
  54. data/lib/origami/array.rb +258 -184
  55. data/lib/origami/boolean.rb +74 -84
  56. data/lib/origami/catalog.rb +397 -434
  57. data/lib/origami/collections.rb +144 -0
  58. data/lib/origami/destinations.rb +233 -194
  59. data/lib/origami/dictionary.rb +253 -232
  60. data/lib/origami/encryption.rb +1274 -1243
  61. data/lib/origami/export.rb +232 -268
  62. data/lib/origami/extensions/fdf.rb +307 -220
  63. data/lib/origami/extensions/ppklite.rb +368 -435
  64. data/lib/origami/filespec.rb +197 -0
  65. data/lib/origami/filters.rb +301 -295
  66. data/lib/origami/filters/ascii.rb +177 -180
  67. data/lib/origami/filters/ccitt.rb +528 -535
  68. data/lib/origami/filters/crypt.rb +26 -35
  69. data/lib/origami/filters/dct.rb +46 -52
  70. data/lib/origami/filters/flate.rb +95 -94
  71. data/lib/origami/filters/jbig2.rb +49 -55
  72. data/lib/origami/filters/jpx.rb +38 -44
  73. data/lib/origami/filters/lzw.rb +189 -183
  74. data/lib/origami/filters/predictors.rb +221 -235
  75. data/lib/origami/filters/runlength.rb +103 -104
  76. data/lib/origami/font.rb +173 -186
  77. data/lib/origami/functions.rb +67 -81
  78. data/lib/origami/graphics.rb +25 -21
  79. data/lib/origami/graphics/colors.rb +178 -187
  80. data/lib/origami/graphics/instruction.rb +79 -85
  81. data/lib/origami/graphics/path.rb +142 -148
  82. data/lib/origami/graphics/patterns.rb +160 -167
  83. data/lib/origami/graphics/render.rb +43 -50
  84. data/lib/origami/graphics/state.rb +138 -153
  85. data/lib/origami/graphics/text.rb +188 -205
  86. data/lib/origami/graphics/xobject.rb +819 -815
  87. data/lib/origami/header.rb +63 -78
  88. data/lib/origami/javascript.rb +596 -597
  89. data/lib/origami/linearization.rb +285 -290
  90. data/lib/origami/metadata.rb +139 -148
  91. data/lib/origami/name.rb +112 -148
  92. data/lib/origami/null.rb +53 -62
  93. data/lib/origami/numeric.rb +162 -175
  94. data/lib/origami/obfuscation.rb +186 -174
  95. data/lib/origami/object.rb +593 -573
  96. data/lib/origami/outline.rb +42 -47
  97. data/lib/origami/outputintents.rb +73 -82
  98. data/lib/origami/page.rb +703 -592
  99. data/lib/origami/parser.rb +238 -290
  100. data/lib/origami/parsers/fdf.rb +41 -33
  101. data/lib/origami/parsers/pdf.rb +75 -95
  102. data/lib/origami/parsers/pdf/lazy.rb +137 -0
  103. data/lib/origami/parsers/pdf/linear.rb +64 -66
  104. data/lib/origami/parsers/ppklite.rb +34 -70
  105. data/lib/origami/pdf.rb +1030 -1005
  106. data/lib/origami/reference.rb +102 -102
  107. data/lib/origami/signature.rb +591 -609
  108. data/lib/origami/stream.rb +668 -551
  109. data/lib/origami/string.rb +397 -373
  110. data/lib/origami/template/patterns.rb +56 -0
  111. data/lib/origami/template/widgets.rb +151 -0
  112. data/lib/origami/trailer.rb +144 -158
  113. data/lib/origami/tree.rb +62 -0
  114. data/lib/origami/version.rb +23 -0
  115. data/lib/origami/webcapture.rb +88 -79
  116. data/lib/origami/xfa.rb +2863 -2882
  117. data/lib/origami/xreftable.rb +472 -384
  118. data/test/dataset/calc.pdf +85 -0
  119. data/test/dataset/crypto.pdf +82 -0
  120. data/test/dataset/empty.pdf +49 -0
  121. data/test/test_actions.rb +27 -0
  122. data/test/test_annotations.rb +90 -0
  123. data/test/test_pages.rb +31 -0
  124. data/test/test_pdf.rb +16 -0
  125. data/test/test_pdf_attachment.rb +34 -0
  126. data/test/test_pdf_create.rb +24 -0
  127. data/test/test_pdf_encrypt.rb +95 -0
  128. data/test/test_pdf_parse.rb +96 -0
  129. data/test/test_pdf_sign.rb +58 -0
  130. data/test/test_streams.rb +182 -0
  131. data/test/test_xrefs.rb +67 -0
  132. metadata +88 -58
  133. data/README +0 -67
  134. data/bin/pdf2graph +0 -121
  135. data/bin/pdfcocoon +0 -104
  136. data/lib/origami/file.rb +0 -233
  137. data/samples/README.txt +0 -45
  138. data/samples/actions/launch/calc.rb +0 -87
  139. data/samples/actions/launch/winparams.rb +0 -22
  140. data/samples/actions/loop/loopgoto.rb +0 -24
  141. data/samples/actions/loop/loopnamed.rb +0 -21
  142. data/samples/actions/named/named.rb +0 -31
  143. data/samples/actions/samba/smbrelay.rb +0 -26
  144. data/samples/actions/webbug/submitform.js +0 -26
  145. data/samples/actions/webbug/webbug-browser.rb +0 -68
  146. data/samples/actions/webbug/webbug-js.rb +0 -67
  147. data/samples/actions/webbug/webbug-reader.rb +0 -90
  148. data/samples/attachments/attach.rb +0 -40
  149. data/samples/attachments/attached.txt +0 -1
  150. data/samples/crypto/crypto.rb +0 -28
  151. data/samples/digsig/signed.rb +0 -46
  152. data/samples/exploits/cve-2008-2992-utilprintf.rb +0 -87
  153. data/samples/exploits/cve-2009-0927-geticon.rb +0 -65
  154. data/samples/exploits/exploit_customdictopen.rb +0 -55
  155. data/samples/exploits/getannots.rb +0 -69
  156. data/samples/flash/flash.rb +0 -31
  157. data/samples/javascript/attached.txt +0 -1
  158. data/samples/javascript/js.rb +0 -52
  159. data/templates/patterns.rb +0 -66
  160. data/templates/widgets.rb +0 -173
  161. data/templates/xdp.rb +0 -92
  162. data/test/ts_pdf.rb +0 -50
@@ -1,328 +1,276 @@
1
1
  =begin
2
2
 
3
- = File
4
- parser.rb
5
-
6
- = Info
7
- This file is part of Origami, PDF manipulation framework for Ruby
8
- Copyright (C) 2010 Guillaume Delugré <guillaume AT security-labs DOT 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/>.
3
+ This file is part of Origami, PDF manipulation framework for Ruby
4
+ Copyright (C) 2016 Guillaume Delugré.
5
+
6
+ Origami is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ Origami is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
18
 
24
19
  =end
25
20
 
21
+ require 'colorize'
26
22
  require 'strscan'
27
23
 
28
24
  module Origami
29
25
 
30
- module Console
31
-
32
- if RUBY_PLATFORM =~ /win32/ or RUBY_PLATFORM =~ /mingw32/
33
- require "Win32API"
34
-
35
- getStdHandle = Win32API.new("kernel32", "GetStdHandle", 'L', 'L')
36
- @@getConsoleScreenBufferInfo = Win32API.new("kernel32", "GetConsoleScreenBufferInfo", 'LP', 'L')
37
- @@setConsoleTextAttribute = Win32API.new("kernel32", "SetConsoleTextAttribute", 'LN', 'I')
38
- @@hOut = getStdHandle.call(-11)
39
- end
26
+ class Parser #:nodoc:
40
27
 
41
- module Colors #:nodoc;
42
- if RUBY_PLATFORM =~ /win32/ or RUBY_PLATFORM =~ /mingw32/
43
- BLACK = 0
44
- BLUE = 1
45
- GREEN = 2
46
- CYAN = 3
47
- RED = 4
48
- MAGENTA = 5
49
- YELLOW = 6
50
- GREY = 7
51
- WHITE = 8
52
- else
53
- GREY = '0;0'
54
- BLACK = '0;30'
55
- RED = '0;31'
56
- GREEN = '0;32'
57
- YELLOW = '0;33'
58
- BLUE = '0;34'
59
- MAGENTA = '0;35'
60
- CYAN = '0;36'
61
- WHITE = '0;37'
62
- BRIGHT_GREY = '1;30'
63
- BRIGHT_RED = '1;31'
64
- BRIGHT_GREEN = '1;32'
65
- BRIGHT_YELLOW = '1;33'
66
- BRIGHT_BLUE = '1;34'
67
- BRIGHT_MAGENTA = '1;35'
68
- BRIGHT_CYAN = '1;36'
69
- BRIGHT_WHITE = '1;37'
70
- end
71
- end
28
+ class ParsingError < Error #:nodoc:
29
+ end
72
30
 
73
- def self.set_fg_color(color, bright = false, fd = STDOUT) #:nodoc:
74
- if RUBY_PLATFORM =~ /win32/ or RUBY_PLATFORM =~ /mingw32/
75
- screen_info = "\x00" * 30
76
- current =
77
- if @@getConsoleScreenBufferInfo.call(@@hOut, screen_info) == 1
78
- screen_info[8,2].unpack('v')[0]
79
- else
80
- Colors::GREY
81
- end
82
- color |= Colors::WHITE if bright
83
- @@setConsoleTextAttribute.call(@@hOut, color)
84
- yield
85
- @@setConsoleTextAttribute.call(@@hOut, current)
86
- else
87
- col, nocol = [color, Colors::GREY].map! { |key| "\033[#{key}m" }
88
- fd << col
89
- yield
90
- fd << nocol
91
- end
92
- end
31
+ #
32
+ # Do not output debug information.
33
+ #
34
+ VERBOSE_QUIET = 0
35
+
36
+ #
37
+ # Output some useful information.
38
+ #
39
+ VERBOSE_INFO = 1
40
+
41
+ #
42
+ # Output debug information.
43
+ #
44
+ VERBOSE_DEBUG = 2
45
+
46
+ #
47
+ # Output every objects read
48
+ #
49
+ VERBOSE_TRACE = 3
50
+
51
+ attr_accessor :options
52
+
53
+ def initialize(options = {}) #:nodoc:
54
+ # Type information for indirect objects.
55
+ @deferred_casts = {}
56
+
57
+ #Default options values
58
+ @options =
59
+ {
60
+ verbosity: VERBOSE_INFO, # Verbose level.
61
+ ignore_errors: true, # Try to keep on parsing when errors occur.
62
+ callback: Proc.new {}, # Callback procedure whenever a structure is read.
63
+ logger: STDERR, # Where to output parser messages.
64
+ colorize_log: true # Colorize parser output?
65
+ }
66
+
67
+ @options.update(options)
68
+ @logger = @options[:logger]
69
+ @data = nil
70
+
71
+ ::String.disable_colorization(false) if @options[:colorize_log]
72
+ end
93
73
 
94
- unless RUBY_PLATFORM =~ /win32/ or RUBY_PLATFORM =~ /mingw32/
95
- def self.colorize(text, color, bright = false)
96
- col, nocol = [color, Colors::GREY].map! { |key| "\033[#{key}m" }
97
- "#{col}#{text}#{nocol}"
98
- end
99
- end
74
+ def pos
75
+ raise RuntimeError, "Cannot get position, parser has no loaded data." if @data.nil?
100
76
 
101
- def self.colorprint(text, color, bright = false, fd = STDOUT) #:nodoc:
102
- set_fg_color(color, bright, fd) {
103
- fd << text
104
- }
105
- end
77
+ @data.pos
78
+ end
106
79
 
107
- end
108
-
109
- class Parser #:nodoc:
80
+ def pos=(offset)
81
+ raise RuntimeError, "Cannot set position, parser has no loaded data." if @data.nil?
110
82
 
111
- class ParsingError < Exception #:nodoc:
112
- end
113
-
114
- #
115
- # Do not output debug information.
116
- #
117
- VERBOSE_QUIET = 0
118
-
119
- #
120
- # Output some useful information.
121
- #
122
- VERBOSE_INFO = 1
123
-
124
- #
125
- # Output debug information.
126
- #
127
- VERBOSE_DEBUG = 2
128
-
129
- #
130
- # Output every objects read
131
- #
132
- VERBOSE_INSANE = 3
133
-
134
- attr_accessor :options
135
-
136
- def initialize(options = {}) #:nodoc:
137
-
138
- # Type information for indirect objects.
139
- @deferred_casts = {}
140
-
141
- #Default options values
142
- @options =
143
- {
144
- :verbosity => VERBOSE_INFO, # Verbose level.
145
- :ignore_errors => true, # Try to keep on parsing when errors occur.
146
- :callback => Proc.new {}, # Callback procedure whenever a structure is read.
147
- :logger => STDERR, # Where to output parser messages.
148
- :colorize_log => true # Colorize parser output?
149
- }
150
-
151
- @options.update(options)
152
- end
83
+ @data.pos = offset
84
+ end
153
85
 
154
- def parse(stream)
155
- data =
156
- if stream.respond_to? :read
157
- if ''.respond_to? :force_encoding
158
- StringScanner.new(stream.read.force_encoding('binary')) # 1.9 compat
159
- else
160
- StringScanner.new(stream.read)
86
+ def parse(stream)
87
+ data =
88
+ if stream.respond_to? :read
89
+ StringScanner.new(stream.read.force_encoding('binary'))
90
+ elsif stream.is_a? ::String
91
+ @filename = stream
92
+ StringScanner.new(File.binread(@filename))
93
+ elsif stream.is_a? StringScanner
94
+ stream
95
+ else
96
+ raise TypeError
97
+ end
98
+
99
+ @data = data
100
+ @data.pos = 0
161
101
  end
162
- elsif stream.is_a? ::String
163
- @filename = stream
164
- if ''.respond_to? :force_encoding
165
- StringScanner.new(File.open(stream, "r", :encoding => 'binary').binmode.read)
166
- else
167
- StringScanner.new(File.open(stream, "r").binmode.read)
102
+
103
+ def parse_object(pos = @data.pos) #:nodoc:
104
+ @data.pos = pos
105
+
106
+ begin
107
+ obj = Object.parse(@data, self)
108
+ return if obj.nil?
109
+
110
+ if Origami::OPTIONS[:enable_type_propagation] and @deferred_casts.key?(obj.reference)
111
+ types = @deferred_casts[obj.reference]
112
+ types = [ types ] unless types.is_a?(::Array)
113
+
114
+ # Promote object if a compatible type is found.
115
+ if cast_type = types.find{|type| type < obj.class}
116
+ obj = obj.cast_to(cast_type, self)
117
+ end
118
+ end
119
+
120
+ trace "Read #{obj.type} object#{
121
+ if obj.class != obj.native_type
122
+ " (" + obj.native_type.to_s.split('::').last + ")"
123
+ end
124
+ }, #{obj.reference}"
125
+
126
+ @options[:callback].call(obj)
127
+ obj
128
+
129
+ rescue UnterminatedObjectError
130
+ error $!.message
131
+ obj = $!.obj
132
+
133
+ Object.skip_until_next_obj(@data)
134
+ @options[:callback].call(obj)
135
+ obj
136
+
137
+ rescue
138
+ error "Breaking on: #{(@data.peek(10) + "...").inspect} at offset 0x#{@data.pos.to_s(16)}"
139
+ error "Last exception: [#{$!.class}] #{$!.message}"
140
+ if not @options[:ignore_errors]
141
+ error "Manually fix the file or set :ignore_errors parameter."
142
+ raise
143
+ end
144
+
145
+ debug 'Skipping this indirect object.'
146
+ raise if not Object.skip_until_next_obj(@data)
147
+
148
+ retry
149
+ end
168
150
  end
169
- elsif stream.is_a? StringScanner
170
- stream
171
- else
172
- raise TypeError
173
- end
174
-
175
- @logger = @options[:logger]
176
- @data = data
177
- @data.pos = 0
178
- end
179
151
 
180
- def parse_object(pos = @data.pos) #:nodoc:
181
- @data.pos = pos
182
-
183
- begin
184
- obj = Object.parse(@data, self)
185
- return if obj.nil?
186
-
187
- trace "Read #{obj.type} object#{
188
- if obj.class != obj.native_type
189
- " (" + obj.native_type.to_s.split('::').last + ")"
190
- end
191
- }, #{obj.reference}"
192
-
193
- @options[:callback].call(obj)
194
- obj
195
-
196
- rescue UnterminatedObjectError => e
197
- error e.message
198
- obj = e.obj
199
-
200
- Object.skip_until_next_obj(@data)
201
- @options[:callback].call(obj)
202
- obj
203
-
204
- rescue Exception => e
205
- error "Breaking on: #{(@data.peek(10) + "...").inspect} at offset 0x#{@data.pos.to_s(16)}"
206
- error "Last exception: [#{e.class}] #{e.message}"
207
- if not @options[:ignore_errors]
208
- error "Manually fix the file or set :ignore_errors parameter."
209
- raise
152
+ def parse_xreftable(pos = @data.pos) #:nodoc:
153
+ @data.pos = pos
154
+
155
+ begin
156
+ info "...Parsing xref table..."
157
+ xreftable = XRef::Section.parse(@data)
158
+ @options[:callback].call(xreftable)
159
+
160
+ xreftable
161
+
162
+ rescue
163
+ debug "Exception caught while parsing xref table : " + $!.message
164
+ warn "Unable to parse xref table! Xrefs might be stored into an XRef stream."
165
+
166
+ @data.pos -= 'trailer'.length unless @data.skip_until(/trailer/).nil?
167
+
168
+ nil
169
+ end
210
170
  end
211
171
 
212
- debug 'Skipping this indirect object.'
213
- raise if not Object.skip_until_next_obj(@data)
214
-
215
- retry
216
- end
217
- end
218
-
219
- def parse_xreftable(pos = @data.pos) #:nodoc:
220
- @data.pos = pos
172
+ def parse_trailer(pos = @data.pos) #:nodoc:
173
+ @data.pos = pos
221
174
 
222
- begin
223
- info "...Parsing xref table..."
224
- xreftable = XRef::Section.parse(@data)
225
- @options[:callback].call(xreftable)
175
+ begin
176
+ info "...Parsing trailer..."
177
+ trailer = Trailer.parse(@data, self)
226
178
 
227
- xreftable
228
- rescue Exception => e
229
- debug "Exception caught while parsing xref table : " + e.message
230
- warn "Unable to parse xref table! Xrefs might be stored into an XRef stream."
179
+ @options[:callback].call(trailer)
180
+ trailer
231
181
 
232
- @data.pos -= 'trailer'.length unless @data.skip_until(/trailer/).nil?
182
+ rescue
183
+ debug "Exception caught while parsing trailer : " + $!.message
184
+ warn "Unable to parse trailer!"
233
185
 
234
- nil
235
- end
236
- end
237
-
238
- def parse_trailer(pos = @data.pos) #:nodoc:
239
- @data.pos = pos
240
-
241
- begin
242
- info "...Parsing trailer..."
243
- trailer = Trailer.parse(@data, self)
244
-
245
- @options[:callback].call(trailer)
246
- trailer
247
-
248
- rescue Exception => e
249
- debug "Exception caught while parsing trailer : " + e.message
250
- warn "Unable to parse trailer!"
251
-
252
- abort("Manually fix the file or set :ignore_errors parameter.") if not @options[:ignore_errors]
253
-
254
- raise
255
- end
256
- end
186
+ raise
187
+ end
188
+ end
257
189
 
258
- def defer_type_cast(reference, type) #:nodoc:
259
- @deferred_casts[reference] = type
260
- end
190
+ def defer_type_cast(reference, type) #:nodoc:
191
+ @deferred_casts[reference] = type
192
+ end
261
193
 
262
- def target_filename
263
- @filename
264
- end
194
+ def target_filename
195
+ @filename
196
+ end
265
197
 
266
- def target_filesize
267
- @data.string.size if @data
268
- end
198
+ def target_filesize
199
+ @data.string.size if @data
200
+ end
269
201
 
270
- def target_data
271
- @data.string.dup if @data
272
- end
202
+ def target_data
203
+ @data.string.dup if @data
204
+ end
273
205
 
274
- private
275
-
276
- def error(str = "") #:nodoc:
277
- if @options[:colorize_log]
278
- Console.colorprint("[error] #{str}\n", Console::Colors::RED, false, @logger)
279
- else
280
- @logger.puts "[error] #{str}"
281
- end
282
- end
206
+ private
283
207
 
284
- def warn(str = "") #:nodoc:
285
- if @options[:verbosity] >= VERBOSE_INFO
286
- if @options[:colorize_log]
287
- Console.colorprint("[info ] Warning: #{str}\n", Console::Colors::YELLOW, false, @logger)
288
- else
289
- @logger.puts "[info ] #{str}"
208
+ def error(str = "") #:nodoc:
209
+ if @options[:colorize_log]
210
+ @logger.puts "[error] #{str}".red
211
+ else
212
+ @logger.puts "[error] #{str}"
213
+ end
290
214
  end
291
- end
292
- end
293
215
 
294
- def info(str = "") #:nodoc:
295
- if @options[:verbosity] >= VERBOSE_INFO
296
- if @options[:colorize_log]
297
- Console.colorprint("[info ] ", Console::Colors::GREEN, false, @logger)
298
- @logger.puts str
299
- else
300
- @logger.puts "[info ] #{str}"
216
+ def warn(str = "") #:nodoc:
217
+ return unless @options[:verbosity] >= VERBOSE_INFO
218
+
219
+ if @options[:colorize_log]
220
+ @logger.puts "[info ] Warning: #{str}".yellow
221
+ else
222
+ @logger.puts "[info ] Warning: #{str}"
223
+ end
301
224
  end
302
- end
303
- end
304
-
305
- def debug(str = "") #:nodoc:
306
- if @options[:verbosity] >= VERBOSE_DEBUG
307
- if @options[:colorize_log]
308
- Console.colorprint("[debug] ", Console::Colors::MAGENTA, false, @logger)
309
- @logger.puts str
310
- else
311
- @logger.puts "[debug] #{str}"
225
+
226
+ def info(str = "") #:nodoc:
227
+ return unless @options[:verbosity] >= VERBOSE_INFO
228
+
229
+ if @options[:colorize_log]
230
+ @logger.print "[info ] ".green
231
+ @logger.puts str
232
+ else
233
+ @logger.puts "[info ] #{str}"
234
+ end
312
235
  end
313
- end
314
- end
315
-
316
- def trace(str = "") #:nodoc:
317
- if @options[:verbosity] >= VERBOSE_INSANE
318
- if @options[:colorize_log]
319
- Console.colorprint("[trace] ", Console::Colors::CYAN, false, @logger)
320
- @logger.puts str
321
- else
322
- @logger.puts "[trace] #{str}"
236
+
237
+ def debug(str = "") #:nodoc:
238
+ return unless @options[:verbosity] >= VERBOSE_DEBUG
239
+
240
+ if @options[:colorize_log]
241
+ @logger.print "[debug] ".magenta
242
+ @logger.puts str
243
+ else
244
+ @logger.puts "[debug] #{str}"
245
+ end
246
+ end
247
+
248
+ def trace(str = "") #:nodoc:
249
+ return unless @options[:verbosity] >= VERBOSE_TRACE
250
+
251
+ if @options[:colorize_log]
252
+ @logger.print "[trace] ".cyan
253
+ @logger.puts str
254
+ else
255
+ @logger.puts "[trace] #{str}"
256
+ end
257
+ end
258
+
259
+ def propagate_types(document)
260
+ info "...Propagating types..."
261
+
262
+ current_state = nil
263
+ until current_state == @deferred_casts
264
+ current_state = @deferred_casts.clone
265
+
266
+ current_state.each_pair do |ref, type|
267
+ type = [ type ] unless type.is_a?(::Array)
268
+ type.each do |hint|
269
+ break if document.cast_object(ref, hint, self)
270
+ end
271
+ end
272
+ end
323
273
  end
324
- end
325
274
  end
326
- end
327
- end
328
275
 
276
+ end