# -*- coding: binary -*-
require 'rexml/document'
require 'rex/ui'

module Rex
module Parser


class IP360XMLStreamParser

	attr_accessor :on_found_host

	def initialize(&block)
		reset_state
		on_found_host = block if block
	end

	def reset_state
		@host = {'hname' => nil, 'hid' => nil, 'addr' => nil, 'mac' => nil, 'os' => nil,
			'vulns' => ['vuln' => {'vulnid' => nil, 'port' => nil, 'proto' => nil} ],
			'apps' => ['app' => {'appid' => nil, 'svcid' => nil, 'port' => nil, 'proto' => nil } ],
		}
		@state = :generic_state
	end

	def tag_start(name, attributes)
		case name
		when "host"
			@host['hid'] = attributes['persistent_id']
		when "ip"
			@state = :is_ip
		when "dnsName"
			@state = :is_fqdn
		when "macAddress"
			@state = :is_mac
		when "os"
			@host['os'] = attributes['id']
		when "vulnerability"
			@x = Hash.new
			@x['vulnid'] = attributes['id']
		when "port"
			@state = :is_port
		when "protocol"
			@state = :is_proto
		when "application"
			@y = Hash.new
			@y['appid'] = attributes['application_id']
			@y['svcid'] = attributes['svcid']
			@y['port'] = attributes['port']
			@y['proto'] = attributes['protocol']
			@host['apps'].push @y
		end
	end

	def text(str)
		case @state
		when :is_fqdn
			@host['hname'] = str
		when :is_ip
			@host['addr'] = str
		when :is_mac
			@host['mac'] = str
		when :is_port
			@x['port'] = str
		when :is_proto
			@x['proto'] = str
		end
	end

	def tag_end(name)
		case name
		when "host"
			on_found_host.call(@host) if on_found_host
			reset_state
		when "vulnerability"
			@host['vulns'].push @x
		end
		@state = :generic_state
	end

	def cdata(d)
		#do nothing
	end

	# We don't need these methods, but they're necessary to keep REXML happy
	#
	def xmldecl(version, encoding, standalone) # :nodoc:
	end
	def comment(str) # :nodoc:
	end
	def instruction(name, instruction) # :nodoc:
	end
	def attlist # :nodoc:
	end
end

end
end
