origami 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/README +1 -1
  2. data/bin/gui/hexview.rb +1 -1
  3. data/bin/gui/menu.rb +4 -4
  4. data/bin/gui/textview.rb +6 -4
  5. data/bin/gui/treeview.rb +4 -4
  6. data/bin/gui/walker.rb +1 -1
  7. data/bin/pdf2graph +1 -1
  8. data/bin/pdf2pdfa +1 -1
  9. data/bin/pdf2ruby +1 -1
  10. data/bin/pdfcocoon +1 -1
  11. data/bin/pdfcop +1 -1
  12. data/bin/pdfdecompress +1 -1
  13. data/bin/pdfdecrypt +1 -1
  14. data/bin/pdfencrypt +1 -1
  15. data/bin/pdfextract +75 -14
  16. data/bin/pdfmetadata +1 -1
  17. data/bin/shell/.irbrc +1 -1
  18. data/{origami.rb → lib/origami.rb} +3 -3
  19. data/{origami → lib/origami}/3d.rb +0 -0
  20. data/{origami → lib/origami}/acroform.rb +2 -2
  21. data/{origami → lib/origami}/actions.rb +0 -0
  22. data/{origami → lib/origami}/annotations.rb +0 -0
  23. data/{origami → lib/origami}/array.rb +0 -0
  24. data/{origami → lib/origami}/boolean.rb +0 -0
  25. data/{origami → lib/origami}/catalog.rb +0 -0
  26. data/{origami → lib/origami}/destinations.rb +0 -0
  27. data/{origami → lib/origami}/dictionary.rb +0 -0
  28. data/{origami → lib/origami}/docmdp.rb +0 -0
  29. data/{origami → lib/origami}/encryption.rb +9 -7
  30. data/{origami → lib/origami}/export.rb +0 -0
  31. data/lib/origami/extensions/fdf.rb +257 -0
  32. data/{origami/adobe → lib/origami/extensions}/ppklite.rb +3 -1
  33. data/{origami → lib/origami}/file.rb +0 -0
  34. data/{origami → lib/origami}/filters.rb +0 -0
  35. data/{origami → lib/origami}/filters/ascii.rb +0 -0
  36. data/{origami → lib/origami}/filters/ccitt.rb +0 -1
  37. data/{origami → lib/origami}/filters/crypt.rb +0 -0
  38. data/{origami → lib/origami}/filters/dct.rb +0 -0
  39. data/{origami → lib/origami}/filters/flate.rb +0 -0
  40. data/{origami → lib/origami}/filters/jbig2.rb +0 -0
  41. data/{origami → lib/origami}/filters/jpx.rb +0 -0
  42. data/{origami → lib/origami}/filters/lzw.rb +0 -0
  43. data/{origami → lib/origami}/filters/predictors.rb +0 -0
  44. data/{origami → lib/origami}/filters/runlength.rb +0 -0
  45. data/{origami → lib/origami}/font.rb +0 -0
  46. data/{origami → lib/origami}/functions.rb +0 -0
  47. data/{origami → lib/origami}/graphics.rb +0 -0
  48. data/{origami → lib/origami}/graphics/colors.rb +45 -23
  49. data/{origami → lib/origami}/graphics/instruction.rb +0 -0
  50. data/{origami → lib/origami}/graphics/path.rb +0 -0
  51. data/{origami → lib/origami}/graphics/patterns.rb +0 -0
  52. data/{origami → lib/origami}/graphics/render.rb +0 -0
  53. data/{origami → lib/origami}/graphics/state.rb +2 -2
  54. data/{origami → lib/origami}/graphics/text.rb +0 -0
  55. data/{origami → lib/origami}/graphics/xobject.rb +219 -0
  56. data/{origami → lib/origami}/header.rb +0 -0
  57. data/{origami → lib/origami}/javascript.rb +0 -0
  58. data/{origami → lib/origami}/linearization.rb +0 -0
  59. data/{origami → lib/origami}/metadata.rb +0 -0
  60. data/{origami → lib/origami}/name.rb +0 -0
  61. data/{origami → lib/origami}/null.rb +0 -0
  62. data/{origami → lib/origami}/numeric.rb +0 -0
  63. data/{origami → lib/origami}/obfuscation.rb +0 -0
  64. data/{origami → lib/origami}/object.rb +7 -2
  65. data/{origami → lib/origami}/outline.rb +0 -0
  66. data/{origami → lib/origami}/outputintents.rb +0 -0
  67. data/{origami → lib/origami}/page.rb +0 -0
  68. data/{origami → lib/origami}/parser.rb +76 -51
  69. data/{origami → lib/origami}/parsers/fdf.rb +9 -6
  70. data/{origami/parsers/pdf/linear.rb → lib/origami/parsers/pdf.rb} +31 -39
  71. data/lib/origami/parsers/pdf/linear.rb +84 -0
  72. data/lib/origami/parsers/ppklite.rb +93 -0
  73. data/{origami → lib/origami}/pdf.rb +6 -3
  74. data/{origami → lib/origami}/reference.rb +0 -0
  75. data/{origami → lib/origami}/signature.rb +170 -19
  76. data/{origami → lib/origami}/stream.rb +9 -0
  77. data/{origami → lib/origami}/string.rb +0 -0
  78. data/{origami → lib/origami}/trailer.rb +0 -0
  79. data/{origami → lib/origami}/webcapture.rb +0 -0
  80. data/{origami → lib/origami}/xfa.rb +0 -0
  81. data/{origami → lib/origami}/xreftable.rb +3 -7
  82. data/samples/README.txt +45 -0
  83. data/samples/actions/launch/calc.rb +87 -0
  84. data/samples/actions/launch/winparams.rb +22 -0
  85. data/samples/actions/loop/loopgoto.rb +24 -0
  86. data/samples/actions/loop/loopnamed.rb +21 -0
  87. data/samples/actions/named/named.rb +31 -0
  88. data/samples/actions/samba/smbrelay.rb +26 -0
  89. data/samples/actions/triggerevents/trigger.rb +75 -0
  90. data/samples/actions/webbug/submitform.js +26 -0
  91. data/samples/actions/webbug/webbug-browser.rb +68 -0
  92. data/samples/actions/webbug/webbug-js.rb +67 -0
  93. data/samples/actions/webbug/webbug-reader.rb +90 -0
  94. data/samples/attachments/attach.rb +40 -0
  95. data/samples/attachments/attached.txt +1 -0
  96. data/samples/crypto/crypto.rb +28 -0
  97. data/samples/digsig/signed.rb +46 -0
  98. data/samples/exploits/cve-2008-2992-utilprintf.rb +87 -0
  99. data/samples/exploits/cve-2009-0927-geticon.rb +65 -0
  100. data/samples/exploits/exploit_customdictopen.rb +55 -0
  101. data/samples/exploits/getannots.rb +69 -0
  102. data/samples/flash/flash.rb +31 -0
  103. data/samples/flash/helloworld.swf +0 -0
  104. data/samples/javascript/attached.txt +1 -0
  105. data/samples/javascript/js.rb +52 -0
  106. data/{tests → test}/ts_pdf.rb +1 -1
  107. metadata +109 -95
  108. data/origami/adobe/fdf.rb +0 -259
  109. data/origami/parsers/pdf.rb +0 -27
  110. data/origami/parsers/ppklite.rb +0 -86
  111. data/tests/dataset/test.dummycrt +0 -28
  112. data/tests/dataset/test.dummykey +0 -27
  113. data/tests/tc_actions.rb +0 -32
  114. data/tests/tc_annotations.rb +0 -85
  115. data/tests/tc_pages.rb +0 -37
  116. data/tests/tc_pdfattach.rb +0 -24
  117. data/tests/tc_pdfencrypt.rb +0 -110
  118. data/tests/tc_pdfnew.rb +0 -32
  119. data/tests/tc_pdfparse.rb +0 -98
  120. data/tests/tc_pdfsig.rb +0 -37
  121. data/tests/tc_streams.rb +0 -129
File without changes
File without changes
File without changes
File without changes
@@ -69,9 +69,9 @@ module Origami
69
69
  @line_join = LineJoinStyle::MITER_JOIN
70
70
  @miter_limit = 10.0
71
71
  @dash_pattern = DashPattern.new([], 0)
72
- @rendering_intent = RenderingIntent::RELATIVE_COLORIMETRIC
72
+ @rendering_intent = Color::Intent::RELATIVE
73
73
  @stroke_adjustment = false
74
- @blend_mode = BlendMode::NORMAL
74
+ @blend_mode = Color::BlendMode::NORMAL
75
75
  @soft_mask = :None
76
76
  @alpha_constant = 1.0
77
77
  @alpha_source = false
File without changes
@@ -492,6 +492,225 @@ module Origami
492
492
  field :Measure, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3
493
493
  field :PtData, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3
494
494
 
495
+ #
496
+ # Converts an ImageXObject stream into an image file data.
497
+ # Output format depends on the stream encoding:
498
+ # * JPEG for DCTDecode
499
+ # * JPEG2000 for JPXDecode
500
+ # * JBIG2 for JBIG2Decode
501
+ # * PNG for everything else
502
+ #
503
+ # Returns an array of the form [ _format_, _data_ ]
504
+ #
505
+ def to_image_file
506
+ encoding = self.Filter
507
+ encoding = encoding[0] if encoding.is_a? ::Array
508
+
509
+ case (encoding && encoding.value)
510
+ when :DCTDecode then [ 'jpg', self.data ]
511
+ when :JBIG2Decode then [ 'jbig2', self.data ]
512
+ when :JPXDecode then [ 'jp2', self.data ]
513
+
514
+ else
515
+ raise InvalidColorError, "No colorspace specified" unless self.ColorSpace
516
+
517
+ case cs = self.ColorSpace.value
518
+ when Color::Space::DEVICE_GRAY
519
+ colortype = 0
520
+ components = 1
521
+ when Color::Space::DEVICE_RGB
522
+ colortype = 2
523
+ components = 3
524
+ when ::Array
525
+ cstype = cs[0].is_a?(Reference) ? cs[0].solve : cs[0]
526
+ case cstype.value
527
+ when :Indexed
528
+ colortype = 3
529
+ components = 3
530
+ csbase = cs[1].is_a?(Reference) ? cs[1].solve : cs[1]
531
+ lookup = cs[3].is_a?(Reference) ? cs[3].solve : cs[3]
532
+
533
+ when :ICCBased
534
+ iccprofile = cs[1].is_a?(Reference) ? cs[1].solve : cs[1]
535
+ raise InvalidColorError,
536
+ "Invalid ICC Profile parameter" unless iccprofile.is_a?(Stream)
537
+
538
+ case iccprofile.N
539
+ when 1
540
+ colortype = 0
541
+ components = 1
542
+ when 3
543
+ colortype = 2
544
+ components = 3
545
+ else
546
+ raise InvalidColorError,
547
+ "Invalid number of components in ICC profile: #{iccprofile.N}"
548
+ end
549
+ else
550
+ raise InvalidColorError, "Unsupported color space: #{self.ColorSpace}"
551
+ end
552
+ else
553
+ raise InvalidColorError, "Unsupported color space: #{self.ColorSpace}"
554
+ end
555
+
556
+ bpc = self.BitsPerComponent || 8
557
+ w,h = self.Width, self.Height
558
+ pixels = self.data
559
+
560
+ hdr = [137, 80, 78, 71, 13, 10, 26, 10].pack('C*')
561
+ chunks = []
562
+
563
+ chunks <<
564
+ [
565
+ 'IHDR',
566
+ [
567
+ w, h,
568
+ bpc, colortype, 0, 0, 0
569
+ ].pack("N2C5")
570
+ ]
571
+
572
+
573
+ if self.Intents
574
+ intents =
575
+ case self.Intents.value
576
+ when Intents::PERCEPTUAL then 0
577
+ when Intents::RELATIVE then 1
578
+ when Intents::SATURATION then 2
579
+ when Intents::ABSOLUTE then 3
580
+ else
581
+ 3
582
+ end
583
+
584
+ chunks <<
585
+ [
586
+ 'sRGB',
587
+ [ intents ].pack('C')
588
+ ]
589
+
590
+ chunks << [ 'gAMA', [ 45455 ].pack("N") ]
591
+ chunks <<
592
+ [
593
+ 'cHRM',
594
+ [
595
+ 31270,
596
+ 32900,
597
+ 64000,
598
+ 33000,
599
+ 30000,
600
+ 60000,
601
+ 15000,
602
+ 6000
603
+ ].pack("N8")
604
+ ]
605
+ end
606
+
607
+ if colortype == 3
608
+ lookup =
609
+ case lookup
610
+ when Stream then lookup.data
611
+ when String then lookup.value
612
+ else
613
+ raise InvalidColorError, "Invalid indexed palette table"
614
+ end
615
+
616
+ raise InvalidColorError, "Invalid base color space" unless csbase
617
+ palette = ""
618
+
619
+ case csbase.value
620
+ when Color::Space::DEVICE_GRAY
621
+ lookup.each_byte do |g|
622
+ palette << Color.gray_to_rgb(g).pack("C3")
623
+ end
624
+ when Color::Space::DEVICE_RGB
625
+ palette << lookup[0, (lookup.size / 3) * 3]
626
+ when Color::Space::DEVICE_CMYK
627
+ (lookup.size / 4).times do |i|
628
+ cmyk = lookup[i * 4, 4].unpack("C4").map!{|c| c.to_f / 255}
629
+ palette << Color.cmyk_to_rgb(*cmyk).map!{|c| (c * 255).to_i}.pack("C3")
630
+ end
631
+ when ::Array
632
+ case csbase[0].solve.value
633
+ when :ICCBased
634
+ iccprofile = csbase[1].solve
635
+ raise InvalidColorError,
636
+ "Invalid ICC Profile parameter" unless iccprofile.is_a?(Stream)
637
+
638
+ case iccprofile.N
639
+ when 1
640
+ lookup.each_byte do |g|
641
+ palette << Color.gray_to_rgb(g).pack("C3")
642
+ end
643
+ when 3
644
+ palette << lookup[0, (lookup.size / 3) * 3]
645
+ else
646
+ raise InvalidColorError,
647
+ "Invalid number of components in ICC profile: #{iccprofile.N}"
648
+ end
649
+ else
650
+ raise InvalidColorError, "Unsupported color space: #{csbase}"
651
+ end
652
+ else
653
+ raise InvalidColorError, "Unsupported color space: #{csbase}"
654
+ end
655
+
656
+ if iccprofile
657
+ chunks <<
658
+ [
659
+ 'iCCP',
660
+ 'ICC Profile' + "\x00\x00" + Zlib::Deflate.deflate(iccprofile.data, Zlib::BEST_COMPRESSION)
661
+ ]
662
+ end
663
+
664
+ chunks <<
665
+ [
666
+ 'PLTE',
667
+ palette
668
+ ]
669
+
670
+ bpr = w
671
+ else
672
+
673
+ if iccprofile
674
+ chunks <<
675
+ [
676
+ 'iCCP',
677
+ 'ICC Profile' + "\x00\x00" + Zlib::Deflate.deflate(iccprofile.data, Zlib::BEST_COMPRESSION)
678
+ ]
679
+ end
680
+
681
+ bpr = (bpc >> 3) * components * w
682
+ end
683
+
684
+ require 'zlib'
685
+
686
+ nrows = pixels.size / bpr
687
+ nrows.times do |irow|
688
+ pixels.insert(irow * bpr + irow, "\x00")
689
+ end
690
+
691
+ chunks <<
692
+ [
693
+ 'IDAT',
694
+ Zlib::Deflate.deflate(pixels, Zlib::BEST_COMPRESSION)
695
+ ]
696
+
697
+ if self.Metadata.is_a?(Stream)
698
+ chunks <<
699
+ [
700
+ 'tEXt',
701
+ "XML:com.adobe.xmp" + "\x00" + self.Metadata.data
702
+ ]
703
+ end
704
+
705
+ chunks << [ 'IEND', '' ]
706
+
707
+ [ 'png',
708
+ hdr + chunks.map!{ |chk|
709
+ [ chk[1].size, chk[0], chk[1], Zlib.crc32(chk[0] + chk[1]) ].pack("NA4A*N")
710
+ }.join
711
+ ]
712
+ end
713
+ end
495
714
  end
496
715
 
497
716
  class ReferenceDictionary < Dictionary
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -234,6 +234,12 @@ module Origami
234
234
  end
235
235
  end
236
236
 
237
+ WHITESPACES = "([ \\f\\t\\r\\n\\0]|%[^\\n]*\\n)*" #:nodoc:
238
+ WHITECHARS_NORET = "[ \\f\\t\\0]*" #:nodoc:
239
+ EOL = "\r\n" #:nodoc:
240
+ WHITECHARS = "[ \\f\\t\\r\\n\\0]*" #:nodoc:
241
+ REGEXP_WHITESPACES = Regexp.new(WHITESPACES) #:nodoc:
242
+
237
243
  #
238
244
  # Parent module representing a PDF Object.
239
245
  # PDF specification declares a set of primitive object types :
@@ -248,9 +254,8 @@ module Origami
248
254
  # * Stream
249
255
  #
250
256
  module Object
251
-
257
+
252
258
  TOKENS = %w{ obj endobj } #:nodoc:
253
-
254
259
  @@regexp_obj = Regexp.new(WHITESPACES + "(\\d+)" + WHITESPACES + "(\\d+)" + WHITESPACES + TOKENS.first + WHITESPACES)
255
260
  @@regexp_endobj = Regexp.new(WHITESPACES + TOKENS.last + WHITESPACES)
256
261
 
File without changes
File without changes
File without changes
@@ -94,15 +94,7 @@ module Origami
94
94
  end
95
95
 
96
96
  end
97
-
98
- EOL = "\r\n" #:nodoc:
99
- DEFINED_TOKENS = "[<\\[(%\\/)\\]>]" #:nodoc:
100
- WHITESPACES = "([ \\f\\t\\r\\n\\0]|%[^\\n]*\\n)*" #:nodoc:
101
- WHITECHARS = "[ \\f\\t\\r\\n\\0]*" #:nodoc:
102
- WHITECHARS_NORET = "[ \\f\\t\\0]*" #:nodoc:
103
97
 
104
- REGEXP_WHITESPACES = Regexp.new(WHITESPACES) #:nodoc:
105
-
106
98
  class Parser #:nodoc:
107
99
 
108
100
  class ParsingError < Exception #:nodoc:
@@ -138,9 +130,8 @@ module Origami
138
130
  :verbosity => VERBOSE_INFO, # Verbose level.
139
131
  :ignore_errors => true, # Try to keep on parsing when errors occur.
140
132
  :callback => Proc.new {}, # Callback procedure whenever a structure is read.
141
- :password => '', # Default password being tried when opening a protected document.
142
- :prompt_password => Proc.new { print "Password: "; gets.chomp }, # Callback procedure to prompt password when document is encrypted.
143
- :force => false # Force PDF header detection
133
+ :logger => STDERR, # Where to output parser messages.
134
+ :colorize_log => true # Colorize parser output?
144
135
  }
145
136
 
146
137
  @options.update(options)
@@ -167,75 +158,78 @@ module Origami
167
158
  raise TypeError
168
159
  end
169
160
 
161
+ @logger = @options[:logger]
170
162
  @data = data
171
163
  @data.pos = 0
172
164
  end
173
-
174
- def parse_objects(file) #:nodoc:
165
+
166
+ def parse_object(pos = @data.pos) #:nodoc:
167
+ @data.pos = pos
168
+
175
169
  begin
176
- loop do
177
- obj = Object.parse(@data)
178
- return if obj.nil?
179
-
180
- trace "Read #{obj.type} object#{if obj.type != obj.real_type then " (" + obj.real_type.to_s.split('::').last + ")" end}, #{obj.reference}"
181
-
182
- file << obj
183
-
184
- @options[:callback].call(obj)
185
- end
170
+ obj = Object.parse(@data)
171
+ return if obj.nil?
186
172
 
173
+ trace "Read #{obj.type} object#{
174
+ if obj.type != obj.real_type
175
+ " (" + obj.real_type.to_s.split('::').last + ")"
176
+ end
177
+ }, #{obj.reference}"
178
+
179
+ @options[:callback].call(obj)
180
+ obj
181
+
187
182
  rescue UnterminatedObjectError => e
188
183
  error e.message
189
- file << e.obj
190
-
191
- @options[:callback].call(e.obj)
184
+ obj = e.obj
192
185
 
193
186
  Object.skip_until_next_obj(@data)
194
- retry
187
+ @options[:callback].call(obj)
188
+ obj
195
189
 
196
190
  rescue Exception => e
197
191
  error "Breaking on: #{(@data.peek(10) + "...").inspect} at offset 0x#{@data.pos.to_s(16)}"
198
192
  error "Last exception: [#{e.class}] #{e.message}"
199
- debug "-> Stopped reading body : #{file.revisions.last.body.size} indirect objects have been parsed" if file.is_a?(PDF)
200
- abort("Manually fix the file or set :ignore_errors parameter.") if not @options[:ignore_errors]
193
+ if not @options[:ignore_errors]
194
+ error "Manually fix the file or set :ignore_errors parameter."
195
+ raise
196
+ end
201
197
 
202
198
  debug 'Skipping this indirect object.'
203
- raise(e) if not Object.skip_until_next_obj(@data)
199
+ raise if not Object.skip_until_next_obj(@data)
204
200
 
205
201
  retry
206
202
  end
207
203
  end
208
204
 
209
- def parse_xreftable(file) #:nodoc:
205
+ def parse_xreftable(pos = @data.pos) #:nodoc:
206
+ @data.pos = pos
207
+
210
208
  begin
211
209
  info "...Parsing xref table..."
212
- file.revisions.last.xreftable = XRef::Section.parse(@data)
213
- @options[:callback].call(file.revisions.last.xreftable)
210
+ xreftable = XRef::Section.parse(@data)
211
+ @options[:callback].call(xreftable)
212
+
213
+ xreftable
214
214
  rescue Exception => e
215
215
  debug "Exception caught while parsing xref table : " + e.message
216
216
  warn "Unable to parse xref table! Xrefs might be stored into an XRef stream."
217
217
 
218
218
  @data.pos -= 'trailer'.length unless @data.skip_until(/trailer/).nil?
219
+
220
+ nil
219
221
  end
220
222
  end
221
223
 
222
- def parse_trailer(file) #:nodoc:
224
+ def parse_trailer(pos = @data.pos) #:nodoc:
225
+ @data.pos = pos
226
+
223
227
  begin
224
228
  info "...Parsing trailer..."
225
229
  trailer = Trailer.parse(@data)
226
230
 
227
- if file.is_a?(PDF)
228
- xrefstm = file.get_object_by_offset(trailer.startxref) ||
229
- (file.get_object_by_offset(trailer.XRefStm) if trailer.has_field? :XRefStm)
230
- end
231
-
232
- if not xrefstm.nil?
233
- debug "Found a XRefStream for this revision at #{xrefstm.reference}"
234
- file.revisions.last.xrefstm = xrefstm
235
- end
236
-
237
- file.revisions.last.trailer = trailer
238
- @options[:callback].call(file.revisions.last.trailer)
231
+ @options[:callback].call(trailer)
232
+ trailer
239
233
 
240
234
  rescue Exception => e
241
235
  debug "Exception caught while parsing trailer : " + e.message
@@ -262,23 +256,54 @@ module Origami
262
256
  private
263
257
 
264
258
  def error(str = "") #:nodoc:
265
- Console.colorprint("[error] #{str}\n", Console::Colors::RED, false, STDERR)
259
+ if @options[:colorize_log]
260
+ Console.colorprint("[error] #{str}\n", Console::Colors::RED, false, @logger)
261
+ else
262
+ @logger.puts "[error] #{str}"
263
+ end
266
264
  end
267
265
 
268
266
  def warn(str = "") #:nodoc:
269
- Console.colorprint("[info ] Warning: #{str}\n", Console::Colors::YELLOW, false, STDERR) if @options[:verbosity] >= VERBOSE_INFO
267
+ if @options[:verbosity] >= VERBOSE_INFO
268
+ if @options[:colorize_log]
269
+ Console.colorprint("[info ] Warning: #{str}\n", Console::Colors::YELLOW, false, @logger)
270
+ else
271
+ @logger.puts "[info ] #{str}"
272
+ end
273
+ end
270
274
  end
271
275
 
272
276
  def info(str = "") #:nodoc:
273
- (Console.colorprint("[info ] ", Console::Colors::GREEN, false, STDERR); STDERR << "#{str}\n") if @options[:verbosity] >= VERBOSE_INFO
277
+ if @options[:verbosity] >= VERBOSE_INFO
278
+ if @options[:colorize_log]
279
+ Console.colorprint("[info ] ", Console::Colors::GREEN, false, @logger)
280
+ @logger.puts str
281
+ else
282
+ @logger.puts "[info ] #{str}"
283
+ end
284
+ end
274
285
  end
275
286
 
276
287
  def debug(str = "") #:nodoc:
277
- (Console.colorprint("[debug] ", Console::Colors::MAGENTA, false, STDERR); STDERR << "#{str}\n") if @options[:verbosity] >= VERBOSE_DEBUG
288
+ if @options[:verbosity] >= VERBOSE_DEBUG
289
+ if @options[:colorize_log]
290
+ Console.colorprint("[debug] ", Console::Colors::MAGENTA, false, @logger)
291
+ @logger.puts str
292
+ else
293
+ @logger.puts "[debug] #{str}"
294
+ end
295
+ end
278
296
  end
279
297
 
280
298
  def trace(str = "") #:nodoc:
281
- (Console.colorprint("[trace] ", Console::Colors::CYAN, false, STDERR); STDERR << "#{str}\n") if @options[:verbosity] >= VERBOSE_INSANE
299
+ if @options[:verbosity] >= VERBOSE_INSANE
300
+ if @options[:colorize_log]
301
+ Console.colorprint("[trace] ", Console::Colors::CYAN, false, @logger)
302
+ @logger.puts str
303
+ else
304
+ @logger.puts "[trace] #{str}"
305
+ end
306
+ end
282
307
  end
283
308
  end
284
309
  end