mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 14:11:29 +00:00
Apply PEP 8 style guidance to zenmap
Using the pep8 tool (https://pypi.python.org/pypi/pep8), fixed the following style issues: Count Issue 11 E201 whitespace after '[' 8 E203 whitespace before ',' 41 E211 whitespace before '(' 11 E221 multiple spaces before operator 61 E225 missing whitespace around operator 237 E231 missing whitespace after ':' 91 E251 no spaces around keyword / parameter equals 19 E261 at least two spaces before inline comment 41 E301 expected 1 blank line, found 0 200 E302 expected 2 blank lines, found 1 356 E303 too many blank lines (2) 563 E501 line too long (106 characters) 39 E701 multiple statements on one line (colon) 13 E702 multiple statements on one line (semicolon) 4 W291 trailing whitespace 2 W293 blank line contains whitespace 8 W391 blank line at end of file 21 W601 .has_key() is deprecated, use 'in' 2 W602 deprecated form of raising exception The remaining issues are long lines due to very deep data structures. I chose not to alter them, as it would involve backslash-continuation where whitespace is not permitted: ./zenmapGUI/ScanInterface.py:323:80: E501 line too long (90 characters) ./zenmapGUI/ScanInterface.py:456:80: E501 line too long (84 characters) ./zenmapGUI/ScanInterface.py:464:80: E501 line too long (84 characters) ./zenmapGUI/ScanInterface.py:472:80: E501 line too long (122 characters) ./zenmapGUI/ScanInterface.py:479:80: E501 line too long (122 characters) ./zenmapGUI/ScanInterface.py:920:80: E501 line too long (94 characters) ./zenmapGUI/ScanInterface.py:923:80: E501 line too long (93 characters) ./zenmapGUI/MainWindow.py:575:80: E501 line too long (99 characters) ./zenmapGUI/MainWindow.py:906:80: E501 line too long (99 characters)
This commit is contained in:
@@ -128,9 +128,11 @@ import zenmapCore.NmapParser
|
||||
from zenmapGUI.SearchGUI import SearchParser
|
||||
from SearchResult import HostSearch
|
||||
|
||||
|
||||
class NetworkInventory(object):
|
||||
"""This class acts as a container for aggregated scans. It is also
|
||||
responsible for opening/saving the aggregation from/to persistent storage."""
|
||||
responsible for opening/saving the aggregation from/to persistent
|
||||
storage."""
|
||||
def __init__(self, filename=None):
|
||||
# A list of all scans that make up this inventory
|
||||
self.scans = []
|
||||
@@ -162,8 +164,8 @@ class NetworkInventory(object):
|
||||
# Add this host to the hosts dictionary, mapped by IP address
|
||||
self.hosts[addr] = host.make_clone()
|
||||
else:
|
||||
# This host is already present in the host list, so we need to update its
|
||||
# info with the info held in the current host object
|
||||
# This host is already present in the host list, so we need to
|
||||
# update its info with the info held in the current host object
|
||||
old_host = self.hosts[addr]
|
||||
# We need to find old_host's scan date
|
||||
old_date = localtime(0)
|
||||
@@ -171,7 +173,8 @@ class NetworkInventory(object):
|
||||
if old_host in old_scan.get_hosts():
|
||||
old_date = old_scan.get_date()
|
||||
new_date = scan.get_date()
|
||||
self._update_host_info(old_host, host, old_date, new_date, scan)
|
||||
self._update_host_info(
|
||||
old_host, host, old_date, new_date, scan)
|
||||
|
||||
self.scans.append(scan)
|
||||
|
||||
@@ -179,7 +182,8 @@ class NetworkInventory(object):
|
||||
basename = os.path.basename(filename)
|
||||
|
||||
if basename in self.filenames.values():
|
||||
# We need to generate a new filename, since this basename already exists
|
||||
# We need to generate a new filename, since this basename
|
||||
# already exists
|
||||
base = basename
|
||||
ext = "xml"
|
||||
try:
|
||||
@@ -195,7 +199,8 @@ class NetworkInventory(object):
|
||||
self.filenames[scan] = basename
|
||||
|
||||
def remove_scan(self, scan):
|
||||
"""Removes a scan and any host information it contained from the inventory."""
|
||||
"""Removes a scan and any host information it contained from the
|
||||
inventory."""
|
||||
# Note: If a scan is passed in that isn't in the inventory then this
|
||||
# method will throw a ValueError Exception and will not finish
|
||||
# Remove the scan from our scan list
|
||||
@@ -214,12 +219,13 @@ class NetworkInventory(object):
|
||||
if scan in self.filenames:
|
||||
del self.filenames[scan]
|
||||
|
||||
# For each scan in the remembered list, append it to the scan list and update
|
||||
# the host list accordingly
|
||||
# For each scan in the remembered list, append it to the scan list and
|
||||
# update the host list accordingly
|
||||
for scan in scans:
|
||||
self.add_scan(scan)
|
||||
|
||||
def _update_host_info(self, old_host, new_host, old_date, new_date, new_scan):
|
||||
def _update_host_info(self, old_host, new_host,
|
||||
old_date, new_date, new_scan):
|
||||
"""This function is called when a host needs to be added to the hosts
|
||||
dictionary, but another HostInfo object for that host already exists
|
||||
in the dictionary (from a previous scan). In that case, we need to
|
||||
@@ -232,19 +238,21 @@ class NetworkInventory(object):
|
||||
for new_port in new_host.ports:
|
||||
# Check if new_port is already present in old_host's ports
|
||||
for old_port in old_host.ports:
|
||||
if old_port["portid"] == new_port["portid"] and old_port["protocol"] == new_port["protocol"]:
|
||||
if (old_port["portid"] == new_port["portid"] and
|
||||
old_port["protocol"] == new_port["protocol"]):
|
||||
old_list.remove(old_port)
|
||||
# We update old_host's port information to reflect the latest known port state
|
||||
# We update old_host's port information to reflect the
|
||||
# latest known port state
|
||||
if old_date < new_date:
|
||||
index = old_host.ports.index(old_port)
|
||||
old_host.ports[index] = new_port
|
||||
# Finished processing this new_port, we jump to the next one
|
||||
# Finished processing this new_port, we jump to the next
|
||||
break
|
||||
else:
|
||||
# This new_port isn't present in old_host, so we simply append it to
|
||||
# old_host's port info
|
||||
# This new_port isn't present in old_host, so we simply append
|
||||
# it to old_host's port info
|
||||
old_host.ports.append(new_port)
|
||||
|
||||
|
||||
ports = new_scan.get_port_protocol_dict()
|
||||
|
||||
#remove ports which are no longer up
|
||||
@@ -269,7 +277,8 @@ class NetworkInventory(object):
|
||||
if old_host.comment == "":
|
||||
old_host.comment = new_host.comment
|
||||
elif new_host.comment != "":
|
||||
old_host.comment = "%s\n\n%s" % (old_host.comment, new_host.comment)
|
||||
old_host.comment = "%s\n\n%s" % (
|
||||
old_host.comment, new_host.comment)
|
||||
|
||||
# Hostnames
|
||||
# Replace old_host's hostname with new_host's if old_host has no
|
||||
@@ -279,21 +288,29 @@ class NetworkInventory(object):
|
||||
old_host.hostnames = new_host.hostnames
|
||||
|
||||
# MAC address
|
||||
# If there was no MAC address set in old_host, set it to whatever is in new_host.mac.
|
||||
# Do the same if both hosts have a MAC address set, but new_host's address is newer.
|
||||
if old_host.mac is None or \
|
||||
(old_host.mac is not None and new_host.mac is not None and old_date < new_date):
|
||||
# If there was no MAC address set in old_host, set it to whatever is in
|
||||
# new_host.mac. Do the same if both hosts have a MAC address set, but
|
||||
# new_host's address is newer.
|
||||
if (old_host.mac is None or
|
||||
(old_host.mac is not None and
|
||||
new_host.mac is not None and
|
||||
old_date < new_date)
|
||||
):
|
||||
old_host.mac = new_host.mac
|
||||
|
||||
# OS detection fields
|
||||
# Replace old_host's OS detection fields with new_host's if old_host has no
|
||||
# OS detection info or new_host's info is newer.
|
||||
if len(new_host.osmatches) > 0 and (len(old_host.osmatches) == 0 or old_date < new_date):
|
||||
# Replace old_host's OS detection fields with new_host's if old_host
|
||||
# has no OS detection info or new_host's info is newer.
|
||||
if (len(new_host.osmatches) > 0 and
|
||||
(len(old_host.osmatches) == 0 or old_date < new_date)
|
||||
):
|
||||
old_host.osmatches = new_host.osmatches
|
||||
old_host.ports_used = new_host.ports_used
|
||||
|
||||
# Traceroute information
|
||||
if len(new_host.trace) > 0 and (len(old_host.trace) == 0 or old_date < new_date):
|
||||
if (len(new_host.trace) > 0 and
|
||||
(len(old_host.trace) == 0 or old_date < new_date)
|
||||
):
|
||||
old_host.trace = new_host.trace
|
||||
|
||||
def get_scans(self):
|
||||
@@ -317,7 +334,8 @@ class NetworkInventory(object):
|
||||
self.add_scan(parsed, path)
|
||||
|
||||
def open_from_dir(self, path):
|
||||
"""Loads all scans from the given directory into the network inventory."""
|
||||
"""Loads all scans from the given directory into the network
|
||||
inventory."""
|
||||
from zenmapCore.NmapParser import NmapParser
|
||||
|
||||
for filename in os.listdir(path):
|
||||
@@ -328,7 +346,7 @@ class NetworkInventory(object):
|
||||
parsed.parse_file(fullpath)
|
||||
self.add_scan(parsed, filename=fullpath)
|
||||
|
||||
def save_to_file(self, path, index, format = "xml"):
|
||||
def save_to_file(self, path, index, format="xml"):
|
||||
"""Saves the scan with the given list index into a file with a given
|
||||
path. With format = "xml", saves Nmap XML; otherwise saves plain text
|
||||
output."""
|
||||
@@ -341,21 +359,24 @@ class NetworkInventory(object):
|
||||
f.close()
|
||||
|
||||
def _generate_filenames(self, path):
|
||||
"""Generates filenames for all scans that don't already have a filename."""
|
||||
# The directory must not contain filenames other than those in the self.filenames dictionary
|
||||
"""Generates filenames for all scans that don't already have a
|
||||
filename."""
|
||||
# The directory must not contain filenames other than those in the
|
||||
# self.filenames dictionary
|
||||
for filename in os.listdir(path):
|
||||
if os.path.basename(filename) not in self.filenames.values():
|
||||
raise Exception("The destination directory contains a file (%s) that's not a part "
|
||||
"of the current inventory. The inventory will not be saved." %
|
||||
os.path.basename(filename))
|
||||
raise Exception("The destination directory contains a file"
|
||||
"(%s) that's not a part of the current inventory."
|
||||
"The inventory will not be saved." %
|
||||
os.path.basename(filename))
|
||||
|
||||
for scan in self.scans:
|
||||
if scan in self.filenames:
|
||||
# This scan already has a filename
|
||||
continue
|
||||
|
||||
date = "%04d%02d%02d%02d%02d" % (scan.date[0], scan.date[1], scan.date[2],
|
||||
scan.date[3], scan.date[4])
|
||||
date = "%04d%02d%02d%02d%02d" % (scan.date[0], scan.date[1],
|
||||
scan.date[2], scan.date[3], scan.date[4])
|
||||
filename = scan.get_scan_name()
|
||||
|
||||
# Prepend the date
|
||||
@@ -367,20 +388,22 @@ class NetworkInventory(object):
|
||||
filename = filename.replace(char, "_")
|
||||
|
||||
# Filename length check
|
||||
# (http://en.wikipedia.org/wiki/Filename#Comparison_of_file_name_limitations)
|
||||
# https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
|
||||
if len(filename) > 250:
|
||||
filename = filename[:250]
|
||||
|
||||
# TODO: Filename security checks?
|
||||
|
||||
# Try to open the file in append mode. If file.tell() returns a greater-than-zero
|
||||
# value, this means that the file already exists and has some data in it, so we
|
||||
# choose another filename until we successfully open a zero-length file.
|
||||
# Try to open the file in append mode. If file.tell() returns a
|
||||
# greater-than-zero value, this means that the file already exists
|
||||
# and has some data in it, so we choose another filename until we
|
||||
# successfully open a zero-length file.
|
||||
filename_full = filename + ".xml"
|
||||
counter = 2
|
||||
while filename_full in self.filenames.values():
|
||||
# There's already a scan with this filename, so we generate a new name by appending
|
||||
# the counter value before the file extension.
|
||||
# There's already a scan with this filename, so we generate a
|
||||
# new name by appending the counter value before the file
|
||||
# extension.
|
||||
filename_full = "%s %s.xml" % (filename, str(counter))
|
||||
counter += 1
|
||||
|
||||
@@ -413,12 +436,13 @@ class NetworkInventory(object):
|
||||
f = StringIO()
|
||||
parsed.write_xml(f)
|
||||
|
||||
scan = Scans(scan_name = parsed.scan_name,
|
||||
nmap_xml_output = f.getvalue(),
|
||||
date = time())
|
||||
scan = Scans(scan_name=parsed.scan_name,
|
||||
nmap_xml_output=f.getvalue(),
|
||||
date=time())
|
||||
|
||||
|
||||
class FilteredNetworkInventory(NetworkInventory):
|
||||
def __init__(self, filename = None):
|
||||
def __init__(self, filename=None):
|
||||
NetworkInventory.__init__(self, filename)
|
||||
|
||||
# A dictionary listing host filtering criteria
|
||||
@@ -459,18 +483,24 @@ class FilteredNetworkInventory(NetworkInventory):
|
||||
return self.filtered_hosts
|
||||
else:
|
||||
return NetworkInventory.get_hosts(self)
|
||||
|
||||
def get_hosts_up(self):
|
||||
if len(self.search_dict) > 0:
|
||||
return filter(lambda h: h.get_state() == 'up', self.filtered_hosts)
|
||||
return filter(lambda h: h.get_state() == 'up',
|
||||
self.filtered_hosts)
|
||||
else:
|
||||
return NetworkInventory.get_hosts_up(self)
|
||||
|
||||
def get_hosts_down(self):
|
||||
if len(self.search_dict) > 0:
|
||||
return filter(lambda h: h.get_state() == 'down', self.filtered_hosts)
|
||||
return filter(lambda h: h.get_state() == 'down',
|
||||
self.filtered_hosts)
|
||||
else:
|
||||
return NetworkInventory.get_hosts_down(self)
|
||||
|
||||
def get_total_host_count(self):
|
||||
return len(self.hosts)
|
||||
|
||||
def _match_all_args(self, host, operator, args):
|
||||
"""A helper function that calls the matching function for the given
|
||||
operator and each of its arguments."""
|
||||
@@ -479,48 +509,63 @@ class FilteredNetworkInventory(NetworkInventory):
|
||||
if arg != "" and arg[0] == "!":
|
||||
arg = arg[1:]
|
||||
positive = False
|
||||
if positive != self.__getattribute__("match_%s" % operator)(host, arg):
|
||||
if positive != self.__getattribute__(
|
||||
"match_%s" % operator)(host, arg):
|
||||
# No match for this operator
|
||||
return False
|
||||
else:
|
||||
# if the operator is not supported, pretend its true
|
||||
# All arguments for this operator produced a match
|
||||
return True
|
||||
|
||||
def get_host_count(self):
|
||||
return len(self.network_inventory.hosts)
|
||||
|
||||
def match_keyword(self, host, keyword):
|
||||
return self.match_os(host, keyword) or\
|
||||
self.match_target(host, keyword) or\
|
||||
self.match_service(host, keyword)
|
||||
|
||||
def match_target(self, host, name):
|
||||
return HostSearch.match_target(host, name)
|
||||
|
||||
def match_in_route(self, host, hop):
|
||||
hops = host.get_trace().get('hops', [])
|
||||
return hop in hops
|
||||
|
||||
def match_hostname(self, host, hostname):
|
||||
return HostSearch.match_hostname(host, hostname)
|
||||
|
||||
def match_service(self, host, service):
|
||||
return HostSearch.match_service(host, service)
|
||||
|
||||
def match_os(self, host, os):
|
||||
return HostSearch.match_os(host, os)
|
||||
|
||||
def match_open(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "open")
|
||||
|
||||
def match_closed(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "closed")
|
||||
|
||||
def match_filtered(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "filtered")
|
||||
|
||||
def match_unfiltered(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "unfiltered")
|
||||
|
||||
def match_open_filtered(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "open|filtered")
|
||||
|
||||
def match_closed_filtered(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "closed|filtered")
|
||||
|
||||
def apply_filter(self, filter_text):
|
||||
self.filter_text = filter_text.lower()
|
||||
self.search_parser.update(self.filter_text)
|
||||
@@ -537,10 +582,11 @@ class FilteredNetworkInventory(NetworkInventory):
|
||||
# host satisfies all conditions
|
||||
self.filtered_hosts.append(host)
|
||||
|
||||
|
||||
class NetworkInventoryTest(unittest.TestCase):
|
||||
def test_no_external_modification(self):
|
||||
"""Test that HostInfo objects passed into the inventory are not modified
|
||||
during aggregation."""
|
||||
"""Test that HostInfo objects passed into the inventory are not
|
||||
modified during aggregation."""
|
||||
scan_1 = zenmapCore.NmapParser.ParserBasics()
|
||||
host_a = zenmapCore.NmapParser.HostInfo()
|
||||
host_a.hostnames = ["a"]
|
||||
@@ -564,28 +610,30 @@ class NetworkInventoryTest(unittest.TestCase):
|
||||
self.assertEqual(scan_1.nmap["hosts"], [host_a])
|
||||
self.assertEqual(scan_2.nmap["hosts"], [host_b])
|
||||
self.assertEqual(inv.get_hosts_up()[0].hostnames, ["b"])
|
||||
|
||||
def test_cancel_and_remove_scan(self):
|
||||
"""Test that canceling and removing a scan does not blow away the inventory hosts"""
|
||||
added_ips = ['10.0.0.1','10.0.0.2']
|
||||
"""Test that canceling and removing a scan does not blow away the
|
||||
inventory hosts"""
|
||||
added_ips = ['10.0.0.1', '10.0.0.2']
|
||||
removed_ips = ['10.0.0.3']
|
||||
scan_1 = zenmapCore.NmapParser.ParserBasics()
|
||||
host_a = zenmapCore.NmapParser.HostInfo()
|
||||
host_a.hostnames = ["a"]
|
||||
host_a.set_ip({'addr':added_ips[0]})
|
||||
host_a.set_ip({'addr': added_ips[0]})
|
||||
scan_1.start = "1000000000"
|
||||
scan_1.nmap["hosts"] = [host_a]
|
||||
|
||||
scan_2 = zenmapCore.NmapParser.ParserBasics()
|
||||
host_b = zenmapCore.NmapParser.HostInfo()
|
||||
host_b.hostnames = ["b"]
|
||||
host_b.set_ip({'addr':added_ips[1]})
|
||||
host_b.set_ip({'addr': added_ips[1]})
|
||||
scan_2.start = "1000000001"
|
||||
scan_2.nmap["hosts"] = [host_b]
|
||||
|
||||
scan_3 = zenmapCore.NmapParser.ParserBasics()
|
||||
host_c = zenmapCore.NmapParser.HostInfo()
|
||||
host_c.hostnames = ["b"]
|
||||
host_c.set_ip({'addr':removed_ips[0]})
|
||||
host_c.set_ip({'addr': removed_ips[0]})
|
||||
scan_3.start = "1000000001"
|
||||
scan_3.nmap["hosts"] = [host_c]
|
||||
|
||||
@@ -600,6 +648,7 @@ class NetworkInventoryTest(unittest.TestCase):
|
||||
self.assertEqual(host_a.hostnames, ["a"])
|
||||
self.assertEqual(host_b.hostnames, ["b"])
|
||||
|
||||
|
||||
class FilteredNetworkInventoryTest(unittest.TestCase):
|
||||
def test_filter(self):
|
||||
"""Test that the filter still works after moving code to the """
|
||||
@@ -613,6 +662,7 @@ class FilteredNetworkInventoryTest(unittest.TestCase):
|
||||
inv.apply_filter(filter_text)
|
||||
assert(len(inv.get_hosts()) == 2)
|
||||
|
||||
|
||||
class PortChangeTest(unittest.TestCase):
|
||||
def test_port(self):
|
||||
"""Verify that the port status (open/filtered/closed) is diplayed """ \
|
||||
@@ -632,17 +682,17 @@ class PortChangeTest(unittest.TestCase):
|
||||
assert(len(inv.get_hosts()[0].ports) == 0)
|
||||
|
||||
# Additional test case for when the two scans have port scan ranges
|
||||
# which do not overlap. Example nmap -F -sU versus
|
||||
# nmap -F scanme.nmap.org
|
||||
# which do not overlap. Example nmap -F -sU versus
|
||||
# nmap -F scanme.nmap.org
|
||||
inv = NetworkInventory()
|
||||
scan4 = NmapParser()
|
||||
scan4.parse_file("test/xml_test16.xml")
|
||||
inv.add_scan(scan4)
|
||||
assert(len(inv.get_hosts()[0].ports)==3)
|
||||
assert(len(inv.get_hosts()[0].ports) == 3)
|
||||
scan5 = NmapParser()
|
||||
scan5.parse_file("test/xml_test17.xml")
|
||||
inv.add_scan(scan5)
|
||||
assert(len(inv.get_hosts()[0].ports)==7)
|
||||
assert(len(inv.get_hosts()[0].ports) == 7)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user