origami 1.2.7 → 2.0.0

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 (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