#!/usr/bin/python
''':'
exec python -u "$0" ${1+"$@"}
' '''

import sys
import re

Ports = {21:'FTP(21)',	22:'SSH(22)',	23:'TELNET(23)',		25:'SMTP(25)',
	53:'DNS(53)', 	79:'Finger(79)',	80:'HTTP(80)',		139:'NetBIOS(139)',
	443:'HTTPS(443)',	445:'SMB(445)'}

def usage():
  print "Usage: %s <file>" % sys.argv[0]
  sys.exit(1)

# Main starts here
if (len(sys.argv)<>2):
  usage()

try:
  f = open(sys.argv[1])

except:
  print "Could not open file %s" % sys.argv[1]
  usage()

def parse(f):
  f = f.read()
  # ports is a list of all ports in the scan
  ports = set()
  # a list of text blocks, each block contains information about 1 host
  hosts = f.split('\n\n')
  if len(hosts) > 1:
    hosts = hosts[:-1]
  # final will be a list of dictionaries, each dictionary is a host
  final = []
  log = ''
  for host in hosts:
    try:
      # output will hold the information about a host before adding it to final
      output = {}
      try:
        info = re.findall(r'Nmap scan report for (.*)',host)[0].split()
      except:
        continue
      if len(info) > 1:
        # Hostname exists
        output['IP'] = re.findall(r'\((.*)\)',info[1])[0]
        output['HOSTNAME'] = info[0]
      else:
        # no Hostname
        output['IP'] = info[0]
        output['HOSTNAME'] = ''
      os = re.findall(' OS: (.*)',host)
      if os == []:
        os = re.findall('OS details: (.*)',host)
      if os == []:
        output['OS'] = ''
      else:
        output['OS'] = os[0].replace(","," ")
      # PORTS is a dictionary of all the ports that had some kind of respond on the host
      output['PORTS'] = {}
      for line in host.splitlines():
        if re.findall('[0-9]{1,5}\/[tcud]{2}p',line) != []:
          port_vars = line.split()
          #find out the port state
          state = port_vars[1]
          #parse port details only if state is open
          if state == 'open':
            port = re.findall('([0-9]{1,5})\/[tcud]{2}p',port_vars[0])[0]
            ports.add(port)
            port_dict = {}
            #find out what flags existed in the command
            sections = re.findall('(PORT.*)',host)[0].split()
            for i in range(1,len(sections)-1):
              port_dict[sections[i]] = port_vars[i]
            # parse version
            if len(port_vars) > i+1:
              port_dict[sections[-1]] = ' '.join(port_vars[i+1:])
            output['PORTS'][port] = port_dict
      if output['PORTS'] == {}:
        output['ALIVE'] = '0'
      else:
        output['ALIVE'] = '1'
      final.append(output)
    except:
      log += str(info) + '\r\n'
  ports = list(ports)
  ports.sort()
  return final, ports, log

def parse_to_excel(final, ports):
  txt = [','.join(['IP','Hostname','ALIVE?','OS']+ports)]
  for host in final:
    row = ','.join([host['IP'],host['HOSTNAME'],host['ALIVE'],host['OS'],''])
    ind = 0
    host_ports = host['PORTS'].keys()
    host_ports.sort()
    for port in host_ports:
      row += ','*(ports.index(port)-ind)
      info = host['PORTS'][port].keys()
      info.sort()
      for data in info:
        # don't add the state info, because it's always open
        if data != 'STATE':
          row += host['PORTS'][port][data]+';'
      ind = ports.index(port)
    txt.append(row)
  txt = '\n'.join(txt)
  return txt
  
final,ports,log = parse(f)
if log:
  file(sys.argv[1]+'.log').write(log)
print parse_to_excel(final,ports)














