=begin
                  Arachni
  Copyright (c) 2010-2011 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>

  This is free software; you can copy and distribute and modify
  this program under the term of the GPL v2.0 License
  (See LICENSE file for details)

=end

module Arachni
module UI
module Web

    #
    # Lame hack to make XMLRPC output appear stream-ish to Sinatra
    # in order to send it back to the browser.
    #
    class OutputStream

        #
        #
        # @param    [Arachni::RPC::XML::Client::Instance]   instance
        # @param    [Integer]   lines   number of lines to output between refreshes
        #
        def initialize( instance, lines, &block )

            @lines    = lines
            @instance = instance
            @buffer  = []

            @icon_whitelist = {}
            [ 'status', 'ok', 'error', 'info' ].each {
                |icon|
                @icon_whitelist[icon] = "<img src='/icons/#{icon}.png' />"
            }

        end

        #
        # @param    [Array<Hash>]   output
        #
        def <<( output )
            @buffer << output.reverse
            @buffer.flatten!
        end

        def data
            data = ''
            each {
                |line|
                data << line
            }

            data
        end

        #
        # Sinatra (or Rack, not sure) expects the output to respond to "each" so we oblige.
        #
        def each

            self << @instance.service.output

            @@last_output ||= ''
            cnt = 0

            if @buffer.empty?
                yield @@last_output
            else
                @@last_output = ''
            end

            while( ( out = @buffer.pop ) && ( ( cnt += 1 ) < @lines ) )

                type = out.keys[0]
                msg  = out.values[0]

                next if out.values[0].empty?

                icon = @icon_whitelist[type] || ''
                str = icon + CGI.escapeHTML( " #{out.values[0]}" ) + "<br/>"
                @@last_output << str
                yield str

            end

            self << @instance.service.output
        end

    end
end
end
end