diff --git a/net/nmap/Makefile b/net/nmap/Makefile index d0db2c005..46c047981 100644 --- a/net/nmap/Makefile +++ b/net/nmap/Makefile @@ -13,31 +13,32 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nmap -PKG_VERSION:=7.70 -PKG_RELEASE:=2 +PKG_VERSION:=7.80 +PKG_RELEASE:=1 PKG_MAINTAINER:=Nuno Goncalves PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://nmap.org/dist/ -PKG_HASH:=847b068955f792f4cc247593aca6dc3dc4aae12976169873247488de147a6e18 -PKG_LICENSE:=GPL-2.0 +PKG_HASH:=fcfa5a0e42099e12e4bf7a68ebe6fde05553383a682e816a7ec9256ab4773faa +PKG_LICENSE:=GPL-2.0-only PKG_LICENSE_FILES:=COPYING PKG_CPE_ID:=cpe:/a:nmap:nmap +PKG_BUILD_PARALLEL:=1 PKG_INSTALL:=1 include $(INCLUDE_DIR)/package.mk +include ../../lang/python/python3-package.mk NMAP_DEPENDS:=+libpcap +libstdcpp +zlib +libpcre NCAT_DEPENDS:=+libpcap NPING_DEPENDS:=+libpcap +libpthread +libstdcpp -NDIFF_DEPENDS:=+python define Package/nmap/default SUBMENU:=NMAP Suite SECTION:=net CATEGORY:=Network - URL:=http://nmap.org/ + URL:=https://nmap.org/ endef define Package/nmap @@ -54,6 +55,13 @@ $(call Package/nmap/default) TITLE:=Nmap (with OpenSSL support) endef +define Package/nmap-full +$(call Package/nmap/default) + DEPENDS:=$(NMAP_DEPENDS) +libopenssl +liblua5.3 +libssh2 + VARIANT:=full + TITLE:=Nmap (with OpenSSL and scripting support) +endef + define Package/ncat $(call Package/nmap/default) DEPENDS:=$(NCAT_DEPENDS) @@ -68,6 +76,13 @@ $(call Package/nmap/default) TITLE:=Ncat (with OpenSSL support) endef +define Package/ncat-full +$(call Package/nmap/default) + DEPENDS:=$(NCAT_DEPENDS) +libopenssl +liblua5.3 + VARIANT:=full + TITLE:=Ncat (with OpenSSL and scripting support) +endef + define Package/nping $(call Package/nmap/default) DEPENDS:=$(NPING_DEPENDS) @@ -84,40 +99,73 @@ endef define Package/ndiff $(call Package/nmap/default) - DEPENDS:=$(NDIFF_DEPENDS) - VARIANT:=nossl + DEPENDS:=+python3-light +python3-xml + VARIANT:=python3 TITLE:=Utility to compare the results of Nmap scans endef CONFIGURE_ARGS += \ --with-libdnet=included \ - --with-libpcre="$(STAGING_DIR)/usr" \ + --with-liblinear=included \ --with-libpcap="$(STAGING_DIR)/usr" \ - --without-liblua \ + --with-libpcre="$(STAGING_DIR)/usr" \ + --with-libz="$(STAGING_DIR)/usr" \ + --with-ncat \ + --without-localdirs \ + --without-ndiff \ + --without-nmap-update \ + --without-subversion \ --without-zenmap + # --with-libnbase=included + # --with-libnsock=included + # --without-apr + +ifeq ($(BUILD_VARIANT),full) + CONFIGURE_ARGS += \ + --with-liblua="$(STAGING_DIR)/usr" \ + --with-libssh2="$(STAGING_DIR)/usr" \ + --with-openssl="$(STAGING_DIR)/usr" \ + --without-nping + +else ifeq ($(BUILD_VARIANT),ssl) + CONFIGURE_ARGS += \ + --with-nping \ + --with-openssl="$(STAGING_DIR)/usr" \ + --without-liblua \ + --without-libssh2 + +else # nossl + CONFIGURE_ARGS += \ + --with-nping \ + --without-liblua \ + --without-libssh2 \ + --without-openssl +endif CONFIGURE_VARS += \ - ac_cv_dnet_bsd_bpf=no \ - CXXFLAGS="$$$$CXXFLAGS -fno-builtin" + ac_cv_dnet_bsd_bpf=no -ifeq ($(BUILD_VARIANT),ssl) - CONFIGURE_ARGS += --with-openssl="$(STAGING_DIR)/usr" --without-libssh2 -else - CONFIGURE_ARGS += --without-openssl +PYTHON3_PKG_SETUP_DIR:=ndiff +PYTHON3_PKG_SETUP_ARGS:= + +ifeq ($(BUILD_VARIANT),python3) + Build/Configure:=: + Build/Install:=: endif define Package/nmap/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nmap $(1)/usr/bin/ $(INSTALL_DIR) $(1)/usr/share/nmap - $(CP) $(PKG_INSTALL_DIR)/usr/share/nmap/* $(1)/usr/share/nmap/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/nmap/nmap* $(1)/usr/share/nmap/ endef -define Package/nmap-ssl/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nmap $(1)/usr/bin/ - $(INSTALL_DIR) $(1)/usr/share/nmap - $(CP) $(PKG_INSTALL_DIR)/usr/share/nmap/* $(1)/usr/share/nmap/ +Package/nmap-ssl/install=$(Package/nmap/install) + +define Package/nmap-full/install + $(call Package/nmap/install,$(1)) + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/nmap/nse_main.lua $(1)/usr/share/nmap/ + $(CP) $(PKG_INSTALL_DIR)/usr/share/nmap/{nselib,scripts} $(1)/usr/share/nmap/ endef define Package/ncat/install @@ -126,31 +174,34 @@ define Package/ncat/install endef define Package/ncat-ssl/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ncat $(1)/usr/bin/ + $(call Package/ncat/install,$(1)) $(INSTALL_DIR) $(1)/usr/share/ncat - $(CP) $(PKG_INSTALL_DIR)/usr/share/ncat/ca-bundle.crt $(1)/usr/share/ncat/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ncat/ca-bundle.crt $(1)/usr/share/ncat/ endef -define Package/ndiff/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ndiff $(1)/usr/bin/ -endef +Package/ncat-full/install=$(Package/ncat-ssl/install) define Package/nping/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nping $(1)/usr/bin/ endef -define Package/nping-ssl/install +Package/nping-ssl/install=$(Package/nping/install) + +define Py3Package/ndiff/install $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nping $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ndiff $(1)/usr/bin/ endef $(eval $(call BuildPackage,nmap)) $(eval $(call BuildPackage,nmap-ssl)) +$(eval $(call BuildPackage,nmap-full)) $(eval $(call BuildPackage,ncat)) $(eval $(call BuildPackage,ncat-ssl)) +$(eval $(call BuildPackage,ncat-full)) $(eval $(call BuildPackage,nping)) $(eval $(call BuildPackage,nping-ssl)) + +$(eval $(call Py3Package,ndiff)) $(eval $(call BuildPackage,ndiff)) +$(eval $(call BuildPackage,ndiff-src)) diff --git a/net/nmap/patches/010-Avoid-using-namespace-std-causing-name-conflicts.patch b/net/nmap/patches/010-Avoid-using-namespace-std-causing-name-conflicts.patch new file mode 100644 index 000000000..400ea1a29 --- /dev/null +++ b/net/nmap/patches/010-Avoid-using-namespace-std-causing-name-conflicts.patch @@ -0,0 +1,135 @@ +From ea4e2d6657103a2c3d6f543a1a8619eb4d4472c8 Mon Sep 17 00:00:00 2001 +From: dmiller +Date: Mon, 30 Dec 2019 04:03:03 +0000 +Subject: [PATCH] Avoid 'using namespace std' causing name conflicts. Fixes + #1363, fixes #1867 + +--- + CHANGELOG | 4 ++++ + nping/EchoServer.cc | 2 +- + nping/EchoServer.h | 4 +--- + nping/NEPContext.h | 3 +-- + nping/NpingTargets.h | 4 +--- + nping/ProbeMode.h | 2 -- + nping/nping.cc | 1 - + nping/utils.h | 2 -- + 8 files changed, 8 insertions(+), 14 deletions(-) + +diff --git a/nping/EchoServer.cc b/nping/EchoServer.cc +index ccdcf9c2d0..a824340cd2 100644 +--- a/nping/EchoServer.cc ++++ b/nping/EchoServer.cc +@@ -199,7 +199,7 @@ NEPContext *EchoServer::getClientContext(nsock_iod iod){ + * the context could not be found. */ + int EchoServer::destroyClientContext(clientid_t clnt){ + bool deleted=false; +- vector::iterator it; ++ std::vector::iterator it; + /* Iterate through the context array and delete the one that belongs to clnt */ + for ( it=this->client_ctx.begin(); itclient_ctx.end(); it++){ + if(it->getIdentifier()==clnt){ +diff --git a/nping/EchoServer.h b/nping/EchoServer.h +index c3dece6341..c9fee6de9e 100644 +--- a/nping/EchoServer.h ++++ b/nping/EchoServer.h +@@ -136,15 +136,13 @@ + #include + #include "NEPContext.h" + +-using namespace std; +- + #define LISTEN_QUEUE_SIZE 10 + + class EchoServer { + + private: + /* Attributes */ +- vector client_ctx; ++ std::vector client_ctx; + clientid_t client_id_count; + + /* Methods */ +diff --git a/nping/NEPContext.h b/nping/NEPContext.h +index 5e470d7551..32b8be48d6 100644 +--- a/nping/NEPContext.h ++++ b/nping/NEPContext.h +@@ -135,7 +135,6 @@ + #include "nsock.h" + #include "EchoHeader.h" + #include +-using namespace std; + + /* SERVER STATE MACHINE */ + /* _ */ +@@ -204,7 +203,7 @@ class NEPContext { + u8 client_nonce[NONCE_LEN]; + bool server_nonce_set; + bool client_nonce_set; +- vector fspecs; ++ std::vector fspecs; + struct sockaddr_storage clnt_addr; + + u8 *generateKey(int key_type, size_t *final_len); +diff --git a/nping/NpingTargets.h b/nping/NpingTargets.h +index 61bb356f39..3a9a2145af 100644 +--- a/nping/NpingTargets.h ++++ b/nping/NpingTargets.h +@@ -137,8 +137,6 @@ + #include "NpingTarget.h" + #include + +-using namespace std; +- + #define MAX_NPING_HOSTNAME_LEN 512 /**< Max length for named hosts */ + + class NpingTargets { +@@ -176,7 +174,7 @@ class NpingTargets { + + /* TODO: Make private */ + NpingTarget *currenths; +- vector Targets; ++ std::vector Targets; + + }; /* End of class NpingTargets */ + +diff --git a/nping/ProbeMode.h b/nping/ProbeMode.h +index aa86939e02..313776d862 100644 +--- a/nping/ProbeMode.h ++++ b/nping/ProbeMode.h +@@ -135,11 +135,9 @@ + + #include "nping.h" + #include "nsock.h" +-#include + #include "NpingTarget.h" + #include "utils_net.h" + #include "utils.h" +-using namespace std; + + #define PKT_TYPE_TCP_CONNECT 1 + #define PKT_TYPE_UDP_NORMAL 2 +diff --git a/nping/nping.cc b/nping/nping.cc +index 9de151a7be..40df912a88 100644 +--- a/nping/nping.cc ++++ b/nping/nping.cc +@@ -150,7 +150,6 @@ + #include + #include + +-using namespace std; + NpingOps o; + EchoClient ec; + EchoServer es; +diff --git a/nping/utils.h b/nping/utils.h +index c3516cf29f..5de6b64b89 100644 +--- a/nping/utils.h ++++ b/nping/utils.h +@@ -143,8 +143,6 @@ + #endif + + #include "global_structures.h" +-#include +-using namespace std; + + /* Function prototypes */ + bool contains(const char *source, const char *substring); diff --git a/net/nmap/patches/010-cxx.patch b/net/nmap/patches/010-cxx.patch deleted file mode 100644 index 8007b60ed..000000000 --- a/net/nmap/patches/010-cxx.patch +++ /dev/null @@ -1,80 +0,0 @@ ---- a/nmap_error.cc -+++ b/nmap_error.cc -@@ -135,6 +135,7 @@ - #include "xml.h" - - #include -+#include - - extern NmapOps o; - ---- a/nping/EchoServer.cc -+++ b/nping/EchoServer.cc -@@ -131,6 +131,7 @@ - #include "EchoServer.h" - #include "EchoHeader.h" - #include "NEPContext.h" -+#include - #include - #include "nsock.h" - #include "output.h" -@@ -281,12 +282,12 @@ int EchoServer::nep_listen_socket(){ - server_addr6.sin6_len = sizeof(struct sockaddr_in6); - #endif - /* Bind to local address and the specified port */ -- if( bind(master_sd, (struct sockaddr *)&server_addr6, sizeof(server_addr6)) != 0 ){ -+ if( ::bind(master_sd, (struct sockaddr *)&server_addr6, sizeof(server_addr6)) != 0 ){ - nping_warning(QT_3, "Failed to bind to source address %s. Trying to bind to port %d...", IPtoa(server_addr6.sin6_addr), port); - /* If the bind failed for the supplied address, just try again with in6addr_any */ - if( o.spoofSource() ){ - server_addr6.sin6_addr = in6addr_any; -- if( bind(master_sd, (struct sockaddr *)&server_addr6, sizeof(server_addr6)) != 0 ){ -+ if( ::bind(master_sd, (struct sockaddr *)&server_addr6, sizeof(server_addr6)) != 0 ){ - nping_fatal(QT_3, "Could not bind to port %d (%s).", port, strerror(errno)); - }else{ - nping_print(VB_1, "Server bound to port %d", port); -@@ -319,12 +320,12 @@ int EchoServer::nep_listen_socket(){ - #endif - - /* Bind to local address and the specified port */ -- if( bind(master_sd, (struct sockaddr *)&server_addr4, sizeof(server_addr4)) != 0 ){ -+ if( ::bind(master_sd, (struct sockaddr *)&server_addr4, sizeof(server_addr4)) != 0 ){ - nping_warning(QT_3, "Failed to bind to source address %s. Trying to bind to port %d...", IPtoa(server_addr4.sin_addr), port); - /* If the bind failed for the supplied address, just try again with in6addr_any */ - if( o.spoofSource() ){ - server_addr4.sin_addr.s_addr=INADDR_ANY; -- if( bind(master_sd, (struct sockaddr *)&server_addr4, sizeof(server_addr4)) != 0 ){ -+ if( ::bind(master_sd, (struct sockaddr *)&server_addr4, sizeof(server_addr4)) != 0 ){ - nping_fatal(QT_3, "Could not bind to port %d (%s).", port, strerror(errno)); - }else{ - nping_print(VB_1, "Server bound to port %d", port); ---- a/osscan.cc -+++ b/osscan.cc -@@ -151,6 +151,7 @@ - #endif - - #include -+#include - #include - #include - ---- a/osscan2.cc -+++ b/osscan2.cc -@@ -145,6 +145,7 @@ - - #include "struct_ip.h" - -+#include - #include - #include - ---- a/service_scan.cc -+++ b/service_scan.cc -@@ -173,6 +173,7 @@ - #endif - - #include -+#include - #include - - extern NmapOps o; diff --git a/net/nmap/patches/020-Python3-port-of-ndiff.patch b/net/nmap/patches/020-Python3-port-of-ndiff.patch new file mode 100644 index 000000000..ccf09c6e1 --- /dev/null +++ b/net/nmap/patches/020-Python3-port-of-ndiff.patch @@ -0,0 +1,1715 @@ +From: Bryan Quigley +Date: Sat, 2 Nov 2019 21:06:44 -0700 +Subject: Python3 port of ndiff + +Ported all python scrips in ndiff/ except setup.py + +Some hints on cmp taken from #1484 + +Minor tweaks to Makefile to support python3, but unsure if +there is a better way to do that. + +Seperated .travis.yml commands for easier debugging where it breaks. + +This closes the easy half of #1176 + +Resolves: #1484 +--- + .travis.yml | 8 +- + Makefile.in | 6 +- + ndiff/ndiff.py | 495 +++++++++++++++++++++--------------------- + ndiff/ndifftest.py | 94 ++++---- + ndiff/scripts/ndiff | 14 +- + ndiff/setup.py | 34 +-- + ndiff/test-scans/anonymize.py | 18 +- + 7 files changed, 337 insertions(+), 332 deletions(-) + mode change 100644 => 100755 ndiff/setup.py + +diff --git a/.travis.yml b/.travis.yml +index 145ebc6..9bb50d6 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -4,7 +4,13 @@ compiler: + - clang + # Change this to your needs + sudo: false +-script: mkdir /tmp/n && ./configure $SSL_FLAG $LUA_FLAG --prefix=/tmp/n && make && make check && make install && /tmp/n/bin/nmap -A localhost ++script: ++ - "mkdir /tmp/n" ++ - "./configure $SSL_FLAG $LUA_FLAG --prefix=/tmp/n" ++ - "make" ++ - "make check" ++ - "make install" ++ - "/tmp/n/bin/nmap -A localhost" + + env: + - SSL_FLAG="--without-openssl" LUA_FLAG="--without-liblua" +diff --git a/Makefile.in b/Makefile.in +index 7ac5ae5..a0152f4 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -35,6 +35,7 @@ ZENMAPDIR = @ZENMAPDIR@ + NDIFFDIR = @NDIFFDIR@ + NPINGDIR = @NPINGDIR@ + PYTHON = @PYTHON@ ++PYTHON3 = /usr/bin/env python3 + DEFS = @DEFS@ -DNMAP_PLATFORM=\"$(NMAP_PLATFORM)\" -DNMAPDATADIR=\"$(nmapdatadir)\" + # With GCC, add extra security checks to source code. + # http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html +@@ -368,6 +369,7 @@ tests/check_dns: $(OBJS) + # this as the location of the interpreter whenever we're not doing a + # local installation. + DEFAULT_PYTHON_PATH = /usr/bin/env python ++DEFAULT_PYTHON3_PATH = /usr/bin/env python3 + + build-zenmap: $(ZENMAPDIR)/setup.py $(ZENMAPDIR)/zenmapCore/Version.py + # When DESTDIR is defined, assume we're building an executable +@@ -388,7 +390,7 @@ install-zenmap: $(ZENMAPDIR)/setup.py + ln -sf zenmap $(DESTDIR)$(bindir)/xnmap + + build-ndiff: +- cd $(NDIFFDIR) && $(PYTHON) setup.py build $(if $(DESTDIR),--executable "$(DEFAULT_PYTHON_PATH)") ++ cd $(NDIFFDIR) && $(PYTHON) setup.py build $(if $(DESTDIR),--executable "$(DEFAULT_PYTHON3_PATH)") + + build-nping: $(NPINGDIR)/Makefile build-nbase build-nsock build-netutil $(NPINGDIR)/nping.h @DNET_BUILD@ @PCAP_BUILD@ + @cd $(NPINGDIR) && $(MAKE) +@@ -458,7 +460,7 @@ check-ncat: + @cd $(NCATDIR) && $(MAKE) check + + check-ndiff: +- @cd $(NDIFFDIR) && $(PYTHON) ndifftest.py ++ @cd $(NDIFFDIR) && $(PYTHON3) ndifftest.py + + check-nsock: + @cd $(NSOCKDIR)/src && $(MAKE) check +diff --git a/ndiff/ndiff.py b/ndiff/ndiff.py +index 043273f..abbd1c5 100755 +--- a/ndiff/ndiff.py ++++ b/ndiff/ndiff.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + + # Ndiff + # +@@ -26,11 +26,11 @@ xml.__path__ = [x for x in xml.__path__ if "_xmlplus" not in x] + import xml.sax + import xml.sax.saxutils + import xml.dom.minidom +-from StringIO import StringIO ++from io import StringIO + + verbose = False + +-NDIFF_XML_VERSION = u"1" ++NDIFF_XML_VERSION = "1" + + + class OverrideEntityResolver(xml.sax.handler.EntityResolver): +@@ -78,35 +78,35 @@ class Scan(object): + def write_nmaprun_open(self, writer): + attrs = {} + if self.scanner is not None: +- attrs[u"scanner"] = self.scanner ++ attrs["scanner"] = self.scanner + if self.args is not None: +- attrs[u"args"] = self.args ++ attrs["args"] = self.args + if self.start_date is not None: +- attrs[u"start"] = "%d" % time.mktime(self.start_date.timetuple()) +- attrs[u"startstr"] = self.start_date.strftime( ++ attrs["start"] = "%d" % time.mktime(self.start_date.timetuple()) ++ attrs["startstr"] = self.start_date.strftime( + "%a %b %d %H:%M:%S %Y") + if self.version is not None: +- attrs[u"version"] = self.version +- writer.startElement(u"nmaprun", attrs) ++ attrs["version"] = self.version ++ writer.startElement("nmaprun", attrs) + + def write_nmaprun_close(self, writer): +- writer.endElement(u"nmaprun") ++ writer.endElement("nmaprun") + + def nmaprun_to_dom_fragment(self, document): + frag = document.createDocumentFragment() +- elem = document.createElement(u"nmaprun") ++ elem = document.createElement("nmaprun") + if self.scanner is not None: +- elem.setAttribute(u"scanner", self.scanner) ++ elem.setAttribute("scanner", self.scanner) + if self.args is not None: +- elem.setAttribute(u"args", self.args) ++ elem.setAttribute("args", self.args) + if self.start_date is not None: + elem.setAttribute( +- u"start", "%d" % time.mktime(self.start_date.timetuple())) ++ "start", "%d" % time.mktime(self.start_date.timetuple())) + elem.setAttribute( +- u"startstr", ++ "startstr", + self.start_date.strftime("%a %b %d %H:%M:%S %Y")) + if self.version is not None: +- elem.setAttribute(u"version", self.version) ++ elem.setAttribute("version", self.version) + frag.appendChild(elem) + return frag + +@@ -136,17 +136,17 @@ class Host(object): + + def format_name(self): + """Return a human-readable identifier for this host.""" +- address_s = u", ".join(a.s for a in sorted(self.addresses)) +- hostname_s = u", ".join(sorted(self.hostnames)) ++ address_s = ", ".join(a.s for a in sorted(self.addresses)) ++ hostname_s = ", ".join(sorted(self.hostnames)) + if len(hostname_s) > 0: + if len(address_s) > 0: +- return u"%s (%s)" % (hostname_s, address_s) ++ return "%s (%s)" % (hostname_s, address_s) + else: + return hostname_s + elif len(address_s) > 0: + return address_s + else: +- return u"" ++ return "" + + def add_port(self, port): + self.ports[port.spec] = port +@@ -163,46 +163,46 @@ class Host(object): + return state is None or state in self.extraports + + def extraports_string(self): +- list = [(count, state) for (state, count) in self.extraports.items()] ++ locallist = [(count, state) for (state, count) in list(self.extraports.items())] + # Reverse-sort by count. +- list.sort(reverse=True) +- return u", ".join( +- [u"%d %s ports" % (count, state) for (count, state) in list]) ++ locallist.sort(reverse=True) ++ return ", ".join( ++ ["%d %s ports" % (count, state) for (count, state) in locallist]) + + def state_to_dom_fragment(self, document): + frag = document.createDocumentFragment() + if self.state is not None: +- elem = document.createElement(u"status") +- elem.setAttribute(u"state", self.state) ++ elem = document.createElement("status") ++ elem.setAttribute("state", self.state) + frag.appendChild(elem) + return frag + + def hostname_to_dom_fragment(self, document, hostname): + frag = document.createDocumentFragment() +- elem = document.createElement(u"hostname") +- elem.setAttribute(u"name", hostname) ++ elem = document.createElement("hostname") ++ elem.setAttribute("name", hostname) + frag.appendChild(elem) + return frag + + def extraports_to_dom_fragment(self, document): + frag = document.createDocumentFragment() +- for state, count in self.extraports.items(): +- elem = document.createElement(u"extraports") +- elem.setAttribute(u"state", state) +- elem.setAttribute(u"count", unicode(count)) ++ for state, count in list(self.extraports.items()): ++ elem = document.createElement("extraports") ++ elem.setAttribute("state", state) ++ elem.setAttribute("count", str(count)) + frag.appendChild(elem) + return frag + + def os_to_dom_fragment(self, document, os): + frag = document.createDocumentFragment() +- elem = document.createElement(u"osmatch") +- elem.setAttribute(u"name", os) ++ elem = document.createElement("osmatch") ++ elem.setAttribute("name", os) + frag.appendChild(elem) + return frag + + def to_dom_fragment(self, document): + frag = document.createDocumentFragment() +- elem = document.createElement(u"host") ++ elem = document.createElement("host") + + if self.state is not None: + elem.appendChild(self.state_to_dom_fragment(document)) +@@ -211,13 +211,13 @@ class Host(object): + elem.appendChild(addr.to_dom_fragment(document)) + + if len(self.hostnames) > 0: +- hostnames_elem = document.createElement(u"hostnames") ++ hostnames_elem = document.createElement("hostnames") + for hostname in self.hostnames: + hostnames_elem.appendChild( + self.hostname_to_dom_fragment(document, hostname)) + elem.appendChild(hostnames_elem) + +- ports_elem = document.createElement(u"ports") ++ ports_elem = document.createElement("ports") + ports_elem.appendChild(self.extraports_to_dom_fragment(document)) + for port in sorted(self.ports.values()): + if not self.is_extraports(port.state): +@@ -226,13 +226,13 @@ class Host(object): + elem.appendChild(ports_elem) + + if len(self.os) > 0: +- os_elem = document.createElement(u"os") ++ os_elem = document.createElement("os") + for os in self.os: + os_elem.appendChild(self.os_to_dom_fragment(document, os)) + elem.appendChild(os_elem) + + if len(self.script_results) > 0: +- hostscript_elem = document.createElement(u"hostscript") ++ hostscript_elem = document.createElement("hostscript") + for sr in self.script_results: + hostscript_elem.appendChild(sr.to_dom_fragment(document)) + elem.appendChild(hostscript_elem) +@@ -246,7 +246,7 @@ class Address(object): + self.s = s + + def __eq__(self, other): +- return self.__cmp__(other) == 0 ++ return self.sort_key() == other.sort_key() + + def __ne__(self, other): + return not self.__eq__(other) +@@ -254,8 +254,8 @@ class Address(object): + def __hash__(self): + return hash(self.sort_key()) + +- def __cmp__(self, other): +- return cmp(self.sort_key(), other.sort_key()) ++ def __lt__(self, other): ++ return self.sort_key() < other.sort_key() + + def __str__(self): + return str(self.s) +@@ -264,21 +264,21 @@ class Address(object): + return self.s + + def new(type, s): +- if type == u"ipv4": ++ if type == "ipv4": + return IPv4Address(s) +- elif type == u"ipv6": ++ elif type == "ipv6": + return IPv6Address(s) +- elif type == u"mac": ++ elif type == "mac": + return MACAddress(s) + else: +- raise ValueError(u"Unknown address type %s." % type) ++ raise ValueError("Unknown address type %s." % type) + new = staticmethod(new) + + def to_dom_fragment(self, document): + frag = document.createDocumentFragment() +- elem = document.createElement(u"address") +- elem.setAttribute(u"addr", self.s) +- elem.setAttribute(u"addrtype", self.type) ++ elem = document.createElement("address") ++ elem.setAttribute("addr", self.s) ++ elem.setAttribute("addrtype", self.type) + frag.appendChild(elem) + return frag + +@@ -287,21 +287,21 @@ class Address(object): + + + class IPv4Address(Address): +- type = property(lambda self: u"ipv4") ++ type = property(lambda self: "ipv4") + + def sort_key(self): + return (0, self.s) + + + class IPv6Address(Address): +- type = property(lambda self: u"ipv6") ++ type = property(lambda self: "ipv6") + + def sort_key(self): + return (1, self.s) + + + class MACAddress(Address): +- type = property(lambda self: u"mac") ++ type = property(lambda self: "mac") + + def sort_key(self): + return (2, self.s) +@@ -320,28 +320,25 @@ class Port(object): + + def state_string(self): + if self.state is None: +- return u"unknown" ++ return "unknown" + else: +- return unicode(self.state) ++ return str(self.state) + + def spec_string(self): +- return u"%d/%s" % self.spec ++ return "%d/%s" % self.spec + +- def __cmp__(self, other): +- d = cmp(self.spec, other.spec) +- if d != 0: +- return d +- return cmp((self.spec, self.service, self.script_results), +- (other.spec, other.service, other.script_results)) ++ def __lt__(self, other): ++ return (self.spec, self.service, self.script_results) < ( ++ other.spec, other.service, other.script_results) + + def to_dom_fragment(self, document): + frag = document.createDocumentFragment() +- elem = document.createElement(u"port") +- elem.setAttribute(u"portid", unicode(self.spec[0])) +- elem.setAttribute(u"protocol", self.spec[1]) ++ elem = document.createElement("port") ++ elem.setAttribute("portid", str(self.spec[0])) ++ elem.setAttribute("protocol", self.spec[1]) + if self.state is not None: +- state_elem = document.createElement(u"state") +- state_elem.setAttribute(u"state", self.state) ++ state_elem = document.createElement("state") ++ state_elem.setAttribute("state", self.state) + elem.appendChild(state_elem) + elem.appendChild(self.service.to_dom_fragment(document)) + for sr in self.script_results: +@@ -385,7 +382,7 @@ class Service(object): + if len(parts) == 0: + return None + else: +- return u"/".join(parts) ++ return "/".join(parts) + + def version_string(self): + """Get a string like in the VERSION column of Nmap output.""" +@@ -395,17 +392,17 @@ class Service(object): + if self.version is not None: + parts.append(self.version) + if self.extrainfo is not None: +- parts.append(u"(%s)" % self.extrainfo) ++ parts.append("(%s)" % self.extrainfo) + + if len(parts) == 0: + return None + else: +- return u" ".join(parts) ++ return " ".join(parts) + + def to_dom_fragment(self, document): + frag = document.createDocumentFragment() +- elem = document.createElement(u"service") +- for attr in (u"name", u"product", u"version", u"extrainfo", u"tunnel"): ++ elem = document.createElement("service") ++ for attr in ("name", "product", "version", "extrainfo", "tunnel"): + v = getattr(self, attr) + if v is None: + continue +@@ -435,53 +432,53 @@ class ScriptResult(object): + result = [] + lines = self.output.splitlines() + if len(lines) > 0: +- lines[0] = self.id + u": " + lines[0] ++ lines[0] = self.id + ": " + lines[0] + for line in lines[:-1]: +- result.append(u"| " + line) ++ result.append("| " + line) + if len(lines) > 0: +- result.append(u"|_ " + lines[-1]) ++ result.append("|_ " + lines[-1]) + return result + + def to_dom_fragment(self, document): + frag = document.createDocumentFragment() +- elem = document.createElement(u"script") +- elem.setAttribute(u"id", self.id) +- elem.setAttribute(u"output", self.output) ++ elem = document.createElement("script") ++ elem.setAttribute("id", self.id) ++ elem.setAttribute("output", self.output) + frag.appendChild(elem) + return frag + + + def format_banner(scan): + """Format a startup banner more or less like Nmap does.""" +- scanner = u"Nmap" +- if scan.scanner is not None and scan.scanner != u"nmap": ++ scanner = "Nmap" ++ if scan.scanner is not None and scan.scanner != "nmap": + scanner = scan.scanner + parts = [scanner] + if scan.version is not None: + parts.append(scan.version) +- parts.append(u"scan") ++ parts.append("scan") + if scan.start_date is not None: +- parts.append(u"initiated %s" % scan.start_date.strftime( ++ parts.append("initiated %s" % scan.start_date.strftime( + "%a %b %d %H:%M:%S %Y")) + if scan.args is not None: +- parts.append(u"as: %s" % scan.args) +- return u" ".join(parts) ++ parts.append("as: %s" % scan.args) ++ return " ".join(parts) + + + def print_script_result_diffs_text(title, script_results_a, script_results_b, + script_result_diffs, f=sys.stdout): +- table = Table(u"*") ++ table = Table("*") + for sr_diff in script_result_diffs: + sr_diff.append_to_port_table(table) + if len(table) > 0: +- print >> f ++ print(file=f) + if len(script_results_b) == 0: +- print >> f, u"-%s:" % title ++ print("-%s:" % title, file=f) + elif len(script_results_a) == 0: +- print >> f, u"+%s:" % title ++ print("+%s:" % title, file=f) + else: +- print >> f, u" %s:" % title +- print >> f, table ++ print(" %s:" % title, file=f) ++ print(table, file=f) + + + def script_result_diffs_to_dom_fragment(elem, script_results_a, +@@ -489,13 +486,13 @@ def script_result_diffs_to_dom_fragment(elem, script_results_a, + if len(script_results_a) == 0 and len(script_results_b) == 0: + return document.createDocumentFragment() + elif len(script_results_b) == 0: +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + for sr in script_results_a: + elem.appendChild(sr.to_dom_fragment(document)) + a_elem.appendChild(elem) + return a_elem + elif len(script_results_a) == 0: +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + for sr in script_results_b: + elem.appendChild(sr.to_dom_fragment(document)) + b_elem.appendChild(elem) +@@ -581,10 +578,10 @@ class ScanDiffText(ScanDiff): + banner_a = format_banner(self.scan_a) + banner_b = format_banner(self.scan_b) + if banner_a != banner_b: +- print >> self.f, u"-%s" % banner_a +- print >> self.f, u"+%s" % banner_b ++ print("-%s" % banner_a, file=self.f) ++ print("+%s" % banner_b, file=self.f) + elif verbose: +- print >> self.f, u" %s" % banner_a ++ print(" %s" % banner_a, file=self.f) + + def output_pre_scripts(self, pre_script_result_diffs): + print_script_result_diffs_text("Pre-scan script results", +@@ -597,7 +594,7 @@ class ScanDiffText(ScanDiff): + post_script_result_diffs, self.f) + + def output_host_diff(self, h_diff): +- print >> self.f ++ print(file=self.f) + h_diff.print_text(self.f) + + def output_ending(self): +@@ -622,8 +619,8 @@ class ScanDiffXML(ScanDiff): + + def output_beginning(self): + self.writer.startDocument() +- self.writer.startElement(u"nmapdiff", {u"version": NDIFF_XML_VERSION}) +- self.writer.startElement(u"scandiff", {}) ++ self.writer.startElement("nmapdiff", {"version": NDIFF_XML_VERSION}) ++ self.writer.startElement("scandiff", {}) + + if self.nmaprun_differs(): + self.writer.frag_a( +@@ -636,7 +633,7 @@ class ScanDiffXML(ScanDiff): + + def output_pre_scripts(self, pre_script_result_diffs): + if len(pre_script_result_diffs) > 0 or verbose: +- prescript_elem = self.document.createElement(u"prescript") ++ prescript_elem = self.document.createElement("prescript") + frag = script_result_diffs_to_dom_fragment( + prescript_elem, self.scan_a.pre_script_results, + self.scan_b.pre_script_results, pre_script_result_diffs, +@@ -646,7 +643,7 @@ class ScanDiffXML(ScanDiff): + + def output_post_scripts(self, post_script_result_diffs): + if len(post_script_result_diffs) > 0 or verbose: +- postscript_elem = self.document.createElement(u"postscript") ++ postscript_elem = self.document.createElement("postscript") + frag = script_result_diffs_to_dom_fragment( + postscript_elem, self.scan_a.post_script_results, + self.scan_b.post_script_results, post_script_result_diffs, +@@ -660,8 +657,8 @@ class ScanDiffXML(ScanDiff): + frag.unlink() + + def output_ending(self): +- self.writer.endElement(u"scandiff") +- self.writer.endElement(u"nmapdiff") ++ self.writer.endElement("scandiff") ++ self.writer.endElement("nmapdiff") + self.writer.endDocument() + + +@@ -719,9 +716,9 @@ class HostDiff(object): + self.cost += os_cost + + extraports_a = tuple((count, state) +- for (state, count) in self.host_a.extraports.items()) ++ for (state, count) in list(self.host_a.extraports.items())) + extraports_b = tuple((count, state) +- for (state, count) in self.host_b.extraports.items()) ++ for (state, count) in list(self.host_b.extraports.items())) + if extraports_a != extraports_b: + self.extraports_changed = True + self.cost += 1 +@@ -747,69 +744,69 @@ class HostDiff(object): + # Names and addresses. + if self.id_changed: + if host_a.state is not None: +- print >> f, u"-%s:" % host_a.format_name() ++ print("-%s:" % host_a.format_name(), file=f) + if self.host_b.state is not None: +- print >> f, u"+%s:" % host_b.format_name() ++ print("+%s:" % host_b.format_name(), file=f) + else: +- print >> f, u" %s:" % host_a.format_name() ++ print(" %s:" % host_a.format_name(), file=f) + + # State. + if self.state_changed: + if host_a.state is not None: +- print >> f, u"-Host is %s." % host_a.state ++ print("-Host is %s." % host_a.state, file=f) + if host_b.state is not None: +- print >> f, u"+Host is %s." % host_b.state ++ print("+Host is %s." % host_b.state, file=f) + elif verbose: +- print >> f, u" Host is %s." % host_b.state ++ print(" Host is %s." % host_b.state, file=f) + + # Extraports. + if self.extraports_changed: + if len(host_a.extraports) > 0: +- print >> f, u"-Not shown: %s" % host_a.extraports_string() ++ print("-Not shown: %s" % host_a.extraports_string(), file=f) + if len(host_b.extraports) > 0: +- print >> f, u"+Not shown: %s" % host_b.extraports_string() ++ print("+Not shown: %s" % host_b.extraports_string(), file=f) + elif verbose: + if len(host_a.extraports) > 0: +- print >> f, u" Not shown: %s" % host_a.extraports_string() ++ print(" Not shown: %s" % host_a.extraports_string(), file=f) + + # Port table. +- port_table = Table(u"** * * *") ++ port_table = Table("** * * *") + if host_a.state is None: +- mark = u"+" ++ mark = "+" + elif host_b.state is None: +- mark = u"-" ++ mark = "-" + else: +- mark = u" " +- port_table.append((mark, u"PORT", u"STATE", u"SERVICE", u"VERSION")) ++ mark = " " ++ port_table.append((mark, "PORT", "STATE", "SERVICE", "VERSION")) + + for port in self.ports: + port_diff = self.port_diffs[port] + port_diff.append_to_port_table(port_table, host_a, host_b) + + if len(port_table) > 1: +- print >> f, port_table ++ print(port_table, file=f) + + # OS changes. + if self.os_changed or verbose: + if len(host_a.os) > 0: + if len(host_b.os) > 0: +- print >> f, u" OS details:" ++ print(" OS details:", file=f) + else: +- print >> f, u"-OS details:" ++ print("-OS details:", file=f) + elif len(host_b.os) > 0: +- print >> f, u"+OS details:" ++ print("+OS details:", file=f) + # os_diffs is a list of 5-tuples returned by + # difflib.SequenceMatcher. + for op, i1, i2, j1, j2 in self.os_diffs: + if op == "replace" or op == "delete": + for i in range(i1, i2): +- print >> f, "- %s" % host_a.os[i] ++ print("- %s" % host_a.os[i], file=f) + if op == "replace" or op == "insert": + for i in range(j1, j2): +- print >> f, "+ %s" % host_b.os[i] ++ print("+ %s" % host_b.os[i], file=f) + if op == "equal": + for i in range(i1, i2): +- print >> f, " %s" % host_a.os[i] ++ print(" %s" % host_a.os[i], file=f) + + print_script_result_diffs_text("Host script results", + host_a.script_results, host_b.script_results, +@@ -820,32 +817,32 @@ class HostDiff(object): + host_b = self.host_b + + frag = document.createDocumentFragment() +- hostdiff_elem = document.createElement(u"hostdiff") ++ hostdiff_elem = document.createElement("hostdiff") + frag.appendChild(hostdiff_elem) + + if host_a.state is None or host_b.state is None: + # The host is missing in one scan. Output the whole thing. + if host_a.state is not None: +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + a_elem.appendChild(host_a.to_dom_fragment(document)) + hostdiff_elem.appendChild(a_elem) + elif host_b.state is not None: +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + b_elem.appendChild(host_b.to_dom_fragment(document)) + hostdiff_elem.appendChild(b_elem) + return frag + +- host_elem = document.createElement(u"host") ++ host_elem = document.createElement("host") + + # State. + if host_a.state == host_b.state: + if verbose: + host_elem.appendChild(host_a.state_to_dom_fragment(document)) + else: +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + a_elem.appendChild(host_a.state_to_dom_fragment(document)) + host_elem.appendChild(a_elem) +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + b_elem.appendChild(host_b.state_to_dom_fragment(document)) + host_elem.appendChild(b_elem) + +@@ -854,31 +851,31 @@ class HostDiff(object): + addrset_b = set(host_b.addresses) + for addr in sorted(addrset_a.intersection(addrset_b)): + host_elem.appendChild(addr.to_dom_fragment(document)) +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + for addr in sorted(addrset_a - addrset_b): + a_elem.appendChild(addr.to_dom_fragment(document)) + if a_elem.hasChildNodes(): + host_elem.appendChild(a_elem) +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + for addr in sorted(addrset_b - addrset_a): + b_elem.appendChild(addr.to_dom_fragment(document)) + if b_elem.hasChildNodes(): + host_elem.appendChild(b_elem) + + # Host names. +- hostnames_elem = document.createElement(u"hostnames") ++ hostnames_elem = document.createElement("hostnames") + hostnameset_a = set(host_a.hostnames) + hostnameset_b = set(host_b.hostnames) + for hostname in sorted(hostnameset_a.intersection(hostnameset_b)): + hostnames_elem.appendChild( + host_a.hostname_to_dom_fragment(document, hostname)) +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + for hostname in sorted(hostnameset_a - hostnameset_b): + a_elem.appendChild( + host_a.hostname_to_dom_fragment(document, hostname)) + if a_elem.hasChildNodes(): + hostnames_elem.appendChild(a_elem) +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + for hostname in sorted(hostnameset_b - hostnameset_a): + b_elem.appendChild( + host_b.hostname_to_dom_fragment(document, hostname)) +@@ -887,15 +884,15 @@ class HostDiff(object): + if hostnames_elem.hasChildNodes(): + host_elem.appendChild(hostnames_elem) + +- ports_elem = document.createElement(u"ports") ++ ports_elem = document.createElement("ports") + # Extraports. + if host_a.extraports == host_b.extraports: + ports_elem.appendChild(host_a.extraports_to_dom_fragment(document)) + else: +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + a_elem.appendChild(host_a.extraports_to_dom_fragment(document)) + ports_elem.appendChild(a_elem) +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + b_elem.appendChild(host_b.extraports_to_dom_fragment(document)) + ports_elem.appendChild(b_elem) + # Port list. +@@ -911,18 +908,18 @@ class HostDiff(object): + + # OS changes. + if self.os_changed or verbose: +- os_elem = document.createElement(u"os") ++ os_elem = document.createElement("os") + # os_diffs is a list of 5-tuples returned by + # difflib.SequenceMatcher. + for op, i1, i2, j1, j2 in self.os_diffs: + if op == "replace" or op == "delete": +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + for i in range(i1, i2): + a_elem.appendChild(host_a.os_to_dom_fragment( + document, host_a.os[i])) + os_elem.appendChild(a_elem) + if op == "replace" or op == "insert": +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + for i in range(j1, j2): + b_elem.appendChild(host_b.os_to_dom_fragment( + document, host_b.os[i])) +@@ -936,7 +933,7 @@ class HostDiff(object): + + # Host script changes. + if len(self.script_result_diffs) > 0 or verbose: +- hostscript_elem = document.createElement(u"hostscript") ++ hostscript_elem = document.createElement("hostscript") + host_elem.appendChild(script_result_diffs_to_dom_fragment( + hostscript_elem, host_a.script_results, + host_b.script_results, self.script_result_diffs, +@@ -989,38 +986,38 @@ class PortDiff(object): + self.port_b.service.version_string()] + if a_columns == b_columns: + if verbose or self.script_result_diffs > 0: +- table.append([u" "] + a_columns) ++ table.append([" "] + a_columns) + else: + if not host_a.is_extraports(self.port_a.state): +- table.append([u"-"] + a_columns) ++ table.append(["-"] + a_columns) + if not host_b.is_extraports(self.port_b.state): +- table.append([u"+"] + b_columns) ++ table.append(["+"] + b_columns) + + for sr_diff in self.script_result_diffs: + sr_diff.append_to_port_table(table) + + def to_dom_fragment(self, document): + frag = document.createDocumentFragment() +- portdiff_elem = document.createElement(u"portdiff") ++ portdiff_elem = document.createElement("portdiff") + frag.appendChild(portdiff_elem) + if (self.port_a.spec == self.port_b.spec and + self.port_a.state == self.port_b.state): +- port_elem = document.createElement(u"port") +- port_elem.setAttribute(u"portid", unicode(self.port_a.spec[0])) +- port_elem.setAttribute(u"protocol", self.port_a.spec[1]) ++ port_elem = document.createElement("port") ++ port_elem.setAttribute("portid", str(self.port_a.spec[0])) ++ port_elem.setAttribute("protocol", self.port_a.spec[1]) + if self.port_a.state is not None: +- state_elem = document.createElement(u"state") +- state_elem.setAttribute(u"state", self.port_a.state) ++ state_elem = document.createElement("state") ++ state_elem.setAttribute("state", self.port_a.state) + port_elem.appendChild(state_elem) + if self.port_a.service == self.port_b.service: + port_elem.appendChild( + self.port_a.service.to_dom_fragment(document)) + else: +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + a_elem.appendChild( + self.port_a.service.to_dom_fragment(document)) + port_elem.appendChild(a_elem) +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + b_elem.appendChild( + self.port_b.service.to_dom_fragment(document)) + port_elem.appendChild(b_elem) +@@ -1028,10 +1025,10 @@ class PortDiff(object): + port_elem.appendChild(sr_diff.to_dom_fragment(document)) + portdiff_elem.appendChild(port_elem) + else: +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + a_elem.appendChild(self.port_a.to_dom_fragment(document)) + portdiff_elem.appendChild(a_elem) +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + b_elem.appendChild(self.port_b.to_dom_fragment(document)) + portdiff_elem.appendChild(b_elem) + +@@ -1086,13 +1083,13 @@ class ScriptResultDiff(object): + for op, i1, i2, j1, j2 in diffs.get_opcodes(): + if op == "replace" or op == "delete": + for k in range(i1, i2): +- table.append_raw(u"-" + a_lines[k]) ++ table.append_raw("-" + a_lines[k]) + if op == "replace" or op == "insert": + for k in range(j1, j2): +- table.append_raw(u"+" + b_lines[k]) ++ table.append_raw("+" + b_lines[k]) + if op == "equal": + for k in range(i1, i2): +- table.append_raw(u" " + a_lines[k]) ++ table.append_raw(" " + a_lines[k]) + + def to_dom_fragment(self, document): + frag = document.createDocumentFragment() +@@ -1102,11 +1099,11 @@ class ScriptResultDiff(object): + frag.appendChild(self.sr_a.to_dom_fragment(document)) + else: + if self.sr_a is not None: +- a_elem = document.createElement(u"a") ++ a_elem = document.createElement("a") + a_elem.appendChild(self.sr_a.to_dom_fragment(document)) + frag.appendChild(a_elem) + if self.sr_b is not None: +- b_elem = document.createElement(u"b") ++ b_elem = document.createElement("b") + b_elem.appendChild(self.sr_b.to_dom_fragment(document)) + frag.appendChild(b_elem) + return frag +@@ -1120,7 +1117,7 @@ class Table(object): + copied to the output.""" + self.widths = [] + self.rows = [] +- self.prefix = u"" ++ self.prefix = "" + self.padding = [] + j = 0 + while j < len(template) and template[j] != "*": +@@ -1145,7 +1142,7 @@ class Table(object): + + for i in range(len(row)): + if row[i] is None: +- s = u"" ++ s = "" + else: + s = str(row[i]) + if i == len(self.widths): +@@ -1167,7 +1164,7 @@ class Table(object): + for row in self.rows: + parts = [self.prefix] + i = 0 +- if isinstance(row, basestring): ++ if isinstance(row, str): + # A raw string. + lines.append(row) + else: +@@ -1176,13 +1173,13 @@ class Table(object): + if i < len(self.padding): + parts.append(self.padding[i]) + i += 1 +- lines.append(u"".join(parts).rstrip()) +- return u"\n".join(lines) ++ lines.append("".join(parts).rstrip()) ++ return "\n".join(lines) + + + def warn(str): + """Print a warning to stderr.""" +- print >> sys.stderr, str ++ print(str, file=sys.stderr) + + + class NmapContentHandler(xml.sax.handler.ContentHandler): +@@ -1200,22 +1197,22 @@ class NmapContentHandler(xml.sax.handler.ContentHandler): + self.current_port = None + + self._start_elem_handlers = { +- u"nmaprun": self._start_nmaprun, +- u"host": self._start_host, +- u"status": self._start_status, +- u"address": self._start_address, +- u"hostname": self._start_hostname, +- u"extraports": self._start_extraports, +- u"port": self._start_port, +- u"state": self._start_state, +- u"service": self._start_service, +- u"script": self._start_script, +- u"osmatch": self._start_osmatch, +- u"finished": self._start_finished, ++ "nmaprun": self._start_nmaprun, ++ "host": self._start_host, ++ "status": self._start_status, ++ "address": self._start_address, ++ "hostname": self._start_hostname, ++ "extraports": self._start_extraports, ++ "port": self._start_port, ++ "state": self._start_state, ++ "service": self._start_service, ++ "script": self._start_script, ++ "osmatch": self._start_osmatch, ++ "finished": self._start_finished, + } + self._end_elem_handlers = { +- u'host': self._end_host, +- u'port': self._end_port, ++ 'host': self._end_host, ++ 'port': self._end_port, + } + + def parent_element(self): +@@ -1245,68 +1242,68 @@ class NmapContentHandler(xml.sax.handler.ContentHandler): + def _start_nmaprun(self, name, attrs): + assert self.parent_element() is None + if "start" in attrs: +- start_timestamp = int(attrs.get(u"start")) ++ start_timestamp = int(attrs.get("start")) + self.scan.start_date = datetime.datetime.fromtimestamp( + start_timestamp) +- self.scan.scanner = attrs.get(u"scanner") +- self.scan.args = attrs.get(u"args") +- self.scan.version = attrs.get(u"version") ++ self.scan.scanner = attrs.get("scanner") ++ self.scan.args = attrs.get("args") ++ self.scan.version = attrs.get("version") + + def _start_host(self, name, attrs): +- assert self.parent_element() == u"nmaprun" ++ assert self.parent_element() == "nmaprun" + self.current_host = Host() + self.scan.hosts.append(self.current_host) + + def _start_status(self, name, attrs): +- assert self.parent_element() == u"host" ++ assert self.parent_element() == "host" + assert self.current_host is not None +- state = attrs.get(u"state") ++ state = attrs.get("state") + if state is None: + warn(u'%s element of host %s is missing the "state" attribute; ' +- 'assuming \unknown\.' % ( ++ r'assuming \unknown\.' % ( + name, self.current_host.format_name())) + return + self.current_host.state = state + + def _start_address(self, name, attrs): +- assert self.parent_element() == u"host" ++ assert self.parent_element() == "host" + assert self.current_host is not None +- addr = attrs.get(u"addr") ++ addr = attrs.get("addr") + if addr is None: +- warn(u'%s element of host %s is missing the "addr" ' ++ warn('%s element of host %s is missing the "addr" ' + 'attribute; skipping.' % ( + name, self.current_host.format_name())) + return +- addrtype = attrs.get(u"addrtype", u"ipv4") ++ addrtype = attrs.get("addrtype", "ipv4") + self.current_host.add_address(Address.new(addrtype, addr)) + + def _start_hostname(self, name, attrs): +- assert self.parent_element() == u"hostnames" ++ assert self.parent_element() == "hostnames" + assert self.current_host is not None +- hostname = attrs.get(u"name") ++ hostname = attrs.get("name") + if hostname is None: +- warn(u'%s element of host %s is missing the "name" ' ++ warn('%s element of host %s is missing the "name" ' + 'attribute; skipping.' % ( + name, self.current_host.format_name())) + return + self.current_host.add_hostname(hostname) + + def _start_extraports(self, name, attrs): +- assert self.parent_element() == u"ports" ++ assert self.parent_element() == "ports" + assert self.current_host is not None +- state = attrs.get(u"state") ++ state = attrs.get("state") + if state is None: +- warn(u'%s element of host %s is missing the "state" ' ++ warn('%s element of host %s is missing the "state" ' + 'attribute; assuming "unknown".' % ( + name, self.current_host.format_name())) + state = None + if state in self.current_host.extraports: +- warn(u'Duplicate extraports state "%s" in host %s.' % ( ++ warn('Duplicate extraports state "%s" in host %s.' % ( + state, self.current_host.format_name())) + +- count = attrs.get(u"count") ++ count = attrs.get("count") + if count is None: +- warn(u'%s element of host %s is missing the "count" ' ++ warn('%s element of host %s is missing the "count" ' + 'attribute; assuming 0.' % ( + name, self.current_host.format_name())) + count = 0 +@@ -1314,99 +1311,99 @@ class NmapContentHandler(xml.sax.handler.ContentHandler): + try: + count = int(count) + except ValueError: +- warn(u"Can't convert extraports count \"%s\" " ++ warn("Can't convert extraports count \"%s\" " + "to an integer in host %s; assuming 0." % ( +- attrs[u"count"], self.current_host.format_name())) ++ attrs["count"], self.current_host.format_name())) + count = 0 + self.current_host.extraports[state] = count + + def _start_port(self, name, attrs): +- assert self.parent_element() == u"ports" ++ assert self.parent_element() == "ports" + assert self.current_host is not None +- portid_str = attrs.get(u"portid") ++ portid_str = attrs.get("portid") + if portid_str is None: +- warn(u'%s element of host %s missing the "portid" ' ++ warn('%s element of host %s missing the "portid" ' + 'attribute; skipping.' % ( + name, self.current_host.format_name())) + return + try: + portid = int(portid_str) + except ValueError: +- warn(u"Can't convert portid \"%s\" to an integer " ++ warn("Can't convert portid \"%s\" to an integer " + "in host %s; skipping port." % ( + portid_str, self.current_host.format_name())) + return +- protocol = attrs.get(u"protocol") ++ protocol = attrs.get("protocol") + if protocol is None: +- warn(u'%s element of host %s missing the "protocol" ' ++ warn('%s element of host %s missing the "protocol" ' + 'attribute; skipping.' % ( + name, self.current_host.format_name())) + return + self.current_port = Port((portid, protocol)) + + def _start_state(self, name, attrs): +- assert self.parent_element() == u"port" ++ assert self.parent_element() == "port" + assert self.current_host is not None + if self.current_port is None: + return + if "state" not in attrs: +- warn(u'%s element of port %s is missing the "state" ' ++ warn('%s element of port %s is missing the "state" ' + 'attribute; assuming "unknown".' % ( + name, self.current_port.spec_string())) + return +- self.current_port.state = attrs[u"state"] ++ self.current_port.state = attrs["state"] + self.current_host.add_port(self.current_port) + + def _start_service(self, name, attrs): +- assert self.parent_element() == u"port" ++ assert self.parent_element() == "port" + assert self.current_host is not None + if self.current_port is None: + return +- self.current_port.service.name = attrs.get(u"name") +- self.current_port.service.product = attrs.get(u"product") +- self.current_port.service.version = attrs.get(u"version") +- self.current_port.service.extrainfo = attrs.get(u"extrainfo") +- self.current_port.service.tunnel = attrs.get(u"tunnel") ++ self.current_port.service.name = attrs.get("name") ++ self.current_port.service.product = attrs.get("product") ++ self.current_port.service.version = attrs.get("version") ++ self.current_port.service.extrainfo = attrs.get("extrainfo") ++ self.current_port.service.tunnel = attrs.get("tunnel") + + def _start_script(self, name, attrs): + result = ScriptResult() +- result.id = attrs.get(u"id") ++ result.id = attrs.get("id") + if result.id is None: +- warn(u'%s element missing the "id" attribute; skipping.' % name) ++ warn('%s element missing the "id" attribute; skipping.' % name) + return + +- result.output = attrs.get(u"output") ++ result.output = attrs.get("output") + if result.output is None: +- warn(u'%s element missing the "output" attribute; skipping.' ++ warn('%s element missing the "output" attribute; skipping.' + % name) + return +- if self.parent_element() == u"prescript": ++ if self.parent_element() == "prescript": + self.scan.pre_script_results.append(result) +- elif self.parent_element() == u"postscript": ++ elif self.parent_element() == "postscript": + self.scan.post_script_results.append(result) +- elif self.parent_element() == u"hostscript": ++ elif self.parent_element() == "hostscript": + self.current_host.script_results.append(result) +- elif self.parent_element() == u"port": ++ elif self.parent_element() == "port": + self.current_port.script_results.append(result) + else: +- warn(u"%s element not inside prescript, postscript, hostscript, " ++ warn("%s element not inside prescript, postscript, hostscript, " + "or port element; ignoring." % name) + return + + def _start_osmatch(self, name, attrs): +- assert self.parent_element() == u"os" ++ assert self.parent_element() == "os" + assert self.current_host is not None + if "name" not in attrs: +- warn(u'%s element of host %s is missing the "name" ' ++ warn('%s element of host %s is missing the "name" ' + 'attribute; skipping.' % ( + name, self.current_host.format_name())) + return +- self.current_host.os.append(attrs[u"name"]) ++ self.current_host.os.append(attrs["name"]) + + def _start_finished(self, name, attrs): +- assert self.parent_element() == u"runstats" ++ assert self.parent_element() == "runstats" + if "time" in attrs: +- end_timestamp = int(attrs.get(u"time")) ++ end_timestamp = int(attrs.get("time")) + self.scan.end_date = datetime.datetime.fromtimestamp(end_timestamp) + + def _end_host(self, name): +@@ -1425,23 +1422,23 @@ class XMLWriter (xml.sax.saxutils.XMLGenerator): + + def frag(self, frag): + for node in frag.childNodes: +- node.writexml(self.f, newl=u"\n") ++ node.writexml(self.f, newl="\n") + + def frag_a(self, frag): +- self.startElement(u"a", {}) ++ self.startElement("a", {}) + for node in frag.childNodes: +- node.writexml(self.f, newl=u"\n") +- self.endElement(u"a") ++ node.writexml(self.f, newl="\n") ++ self.endElement("a") + + def frag_b(self, frag): +- self.startElement(u"b", {}) ++ self.startElement("b", {}) + for node in frag.childNodes: +- node.writexml(self.f, newl=u"\n") +- self.endElement(u"b") ++ node.writexml(self.f, newl="\n") ++ self.endElement("b") + + + def usage(): +- print u"""\ ++ print("""\ + Usage: %s [option] FILE1 FILE2 + Compare two Nmap XML files and display a list of their differences. + Differences include host state changes, port state changes, and changes to +@@ -1451,7 +1448,7 @@ service and OS detection. + -v, --verbose also show hosts and ports that haven't changed. + --text display output in text format (default) + --xml display output in XML format\ +-""" % sys.argv[0] ++""" % sys.argv[0]) + + EXIT_EQUAL = 0 + EXIT_DIFFERENT = 1 +@@ -1459,8 +1456,8 @@ EXIT_ERROR = 2 + + + def usage_error(msg): +- print >> sys.stderr, u"%s: %s" % (sys.argv[0], msg) +- print >> sys.stderr, u"Try '%s -h' for help." % sys.argv[0] ++ print("%s: %s" % (sys.argv[0], msg), file=sys.stderr) ++ print("Try '%s -h' for help." % sys.argv[0], file=sys.stderr) + sys.exit(EXIT_ERROR) + + +@@ -1471,7 +1468,7 @@ def main(): + try: + opts, input_filenames = getopt.gnu_getopt( + sys.argv[1:], "hv", ["help", "text", "verbose", "xml"]) +- except getopt.GetoptError, e: ++ except getopt.GetoptError as e: + usage_error(e.msg) + for o, a in opts: + if o == "-h" or o == "--help": +@@ -1481,15 +1478,15 @@ def main(): + verbose = True + elif o == "--text": + if output_format is not None and output_format != "text": +- usage_error(u"contradictory output format options.") ++ usage_error("contradictory output format options.") + output_format = "text" + elif o == "--xml": + if output_format is not None and output_format != "xml": +- usage_error(u"contradictory output format options.") ++ usage_error("contradictory output format options.") + output_format = "xml" + + if len(input_filenames) != 2: +- usage_error(u"need exactly two input filenames.") ++ usage_error("need exactly two input filenames.") + + if output_format is None: + output_format = "text" +@@ -1502,8 +1499,8 @@ def main(): + scan_a.load_from_file(filename_a) + scan_b = Scan() + scan_b.load_from_file(filename_b) +- except IOError, e: +- print >> sys.stderr, u"Can't open file: %s" % str(e) ++ except IOError as e: ++ print("Can't open file: %s" % str(e), file=sys.stderr) + sys.exit(EXIT_ERROR) + + if output_format == "text": +diff --git a/ndiff/ndifftest.py b/ndiff/ndifftest.py +index 2fa4ae0..27fc525 100755 +--- a/ndiff/ndifftest.py ++++ b/ndiff/ndifftest.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + + # Unit tests for Ndiff. + +@@ -22,7 +22,7 @@ for x in dir(ndiff): + sys.dont_write_bytecode = dont_write_bytecode + del dont_write_bytecode + +-import StringIO ++import io + + + class scan_test(unittest.TestCase): +@@ -52,7 +52,7 @@ class scan_test(unittest.TestCase): + scan.load_from_file("test-scans/single.xml") + host = scan.hosts[0] + self.assertEqual(len(host.ports), 5) +- self.assertEqual(host.extraports.items(), [("filtered", 95)]) ++ self.assertEqual(list(host.extraports.items()), [("filtered", 95)]) + + def test_extraports_multi(self): + """Test that the correct number of known ports is returned when there +@@ -68,9 +68,9 @@ class scan_test(unittest.TestCase): + """Test that nmaprun information is recorded.""" + scan = Scan() + scan.load_from_file("test-scans/empty.xml") +- self.assertEqual(scan.scanner, u"nmap") +- self.assertEqual(scan.version, u"4.90RC2") +- self.assertEqual(scan.args, u"nmap -oX empty.xml -p 1-100") ++ self.assertEqual(scan.scanner, "nmap") ++ self.assertEqual(scan.version, "4.90RC2") ++ self.assertEqual(scan.args, "nmap -oX empty.xml -p 1-100") + + def test_addresses(self): + """Test that addresses are recorded.""" +@@ -84,7 +84,7 @@ class scan_test(unittest.TestCase): + scan = Scan() + scan.load_from_file("test-scans/simple.xml") + host = scan.hosts[0] +- self.assertEqual(host.hostnames, [u"scanme.nmap.org"]) ++ self.assertEqual(host.hostnames, ["scanme.nmap.org"]) + + def test_os(self): + """Test that OS information is recorded.""" +@@ -99,7 +99,7 @@ class scan_test(unittest.TestCase): + scan.load_from_file("test-scans/complex.xml") + host = scan.hosts[0] + self.assertTrue(len(host.script_results) > 0) +- self.assertTrue(len(host.ports[(22, u"tcp")].script_results) > 0) ++ self.assertTrue(len(host.ports[(22, "tcp")].script_results) > 0) + + # This test is commented out because Nmap XML doesn't store any information + # about down hosts, not even the fact that they are down. Recovering the list +@@ -128,16 +128,16 @@ class host_test(unittest.TestCase): + + def test_format_name(self): + h = Host() +- self.assertTrue(isinstance(h.format_name(), basestring)) +- h.add_address(IPv4Address(u"127.0.0.1")) +- self.assertTrue(u"127.0.0.1" in h.format_name()) ++ self.assertTrue(isinstance(h.format_name(), str)) ++ h.add_address(IPv4Address("127.0.0.1")) ++ self.assertTrue("127.0.0.1" in h.format_name()) + h.add_address(IPv6Address("::1")) +- self.assertTrue(u"127.0.0.1" in h.format_name()) +- self.assertTrue(u"::1" in h.format_name()) +- h.add_hostname(u"localhost") +- self.assertTrue(u"127.0.0.1" in h.format_name()) +- self.assertTrue(u"::1" in h.format_name()) +- self.assertTrue(u"localhost" in h.format_name()) ++ self.assertTrue("127.0.0.1" in h.format_name()) ++ self.assertTrue("::1" in h.format_name()) ++ h.add_hostname("localhost") ++ self.assertTrue("127.0.0.1" in h.format_name()) ++ self.assertTrue("::1" in h.format_name()) ++ self.assertTrue("localhost" in h.format_name()) + + def test_empty_get_port(self): + h = Host() +@@ -197,8 +197,8 @@ class host_test(unittest.TestCase): + h = s.hosts[0] + self.assertEqual(len(h.ports), 5) + self.assertEqual(len(h.extraports), 1) +- self.assertEqual(h.extraports.keys()[0], u"filtered") +- self.assertEqual(h.extraports.values()[0], 95) ++ self.assertEqual(list(h.extraports.keys())[0], "filtered") ++ self.assertEqual(list(h.extraports.values())[0], 95) + self.assertEqual(h.state, "up") + + +@@ -241,13 +241,13 @@ class port_test(unittest.TestCase): + """Test the Port class.""" + def test_spec_string(self): + p = Port((10, "tcp")) +- self.assertEqual(p.spec_string(), u"10/tcp") ++ self.assertEqual(p.spec_string(), "10/tcp") + p = Port((100, "ip")) +- self.assertEqual(p.spec_string(), u"100/ip") ++ self.assertEqual(p.spec_string(), "100/ip") + + def test_state_string(self): + p = Port((10, "tcp")) +- self.assertEqual(p.state_string(), u"unknown") ++ self.assertEqual(p.state_string(), "unknown") + + + class service_test(unittest.TestCase): +@@ -255,47 +255,47 @@ class service_test(unittest.TestCase): + def test_compare(self): + """Test that services with the same contents compare equal.""" + a = Service() +- a.name = u"ftp" +- a.product = u"FooBar FTP" +- a.version = u"1.1.1" +- a.tunnel = u"ssl" ++ a.name = "ftp" ++ a.product = "FooBar FTP" ++ a.version = "1.1.1" ++ a.tunnel = "ssl" + self.assertEqual(a, a) + b = Service() +- b.name = u"ftp" +- b.product = u"FooBar FTP" +- b.version = u"1.1.1" +- b.tunnel = u"ssl" ++ b.name = "ftp" ++ b.product = "FooBar FTP" ++ b.version = "1.1.1" ++ b.tunnel = "ssl" + self.assertEqual(a, b) +- b.name = u"http" ++ b.name = "http" + self.assertNotEqual(a, b) + c = Service() + self.assertNotEqual(a, c) + + def test_tunnel(self): + serv = Service() +- serv.name = u"http" +- serv.tunnel = u"ssl" +- self.assertEqual(serv.name_string(), u"ssl/http") ++ serv.name = "http" ++ serv.tunnel = "ssl" ++ self.assertEqual(serv.name_string(), "ssl/http") + + def test_version_string(self): + serv = Service() +- serv.product = u"FooBar" ++ serv.product = "FooBar" + self.assertTrue(len(serv.version_string()) > 0) + serv = Service() +- serv.version = u"1.2.3" ++ serv.version = "1.2.3" + self.assertTrue(len(serv.version_string()) > 0) + serv = Service() +- serv.extrainfo = u"misconfigured" ++ serv.extrainfo = "misconfigured" + self.assertTrue(len(serv.version_string()) > 0) + serv = Service() +- serv.product = u"FooBar" +- serv.version = u"1.2.3" ++ serv.product = "FooBar" ++ serv.version = "1.2.3" + # Must match Nmap output. + self.assertEqual(serv.version_string(), +- u"%s %s" % (serv.product, serv.version)) +- serv.extrainfo = u"misconfigured" ++ "%s %s" % (serv.product, serv.version)) ++ serv.extrainfo = "misconfigured" + self.assertEqual(serv.version_string(), +- u"%s %s (%s)" % (serv.product, serv.version, serv.extrainfo)) ++ "%s %s (%s)" % (serv.product, serv.version, serv.extrainfo)) + + + class ScanDiffSub(ScanDiff): +@@ -703,7 +703,7 @@ class scan_diff_xml_test(unittest.TestCase): + a.load_from_file("test-scans/empty.xml") + b = Scan() + b.load_from_file("test-scans/simple.xml") +- f = StringIO.StringIO() ++ f = io.StringIO() + self.scan_diff = ScanDiffXML(a, b, f) + self.scan_diff.output() + self.xml = f.getvalue() +@@ -712,8 +712,8 @@ class scan_diff_xml_test(unittest.TestCase): + def test_well_formed(self): + try: + document = xml.dom.minidom.parseString(self.xml) +- except Exception, e: +- self.fail(u"Parsing XML diff output caused the exception: %s" ++ except Exception as e: ++ self.fail("Parsing XML diff output caused the exception: %s" + % str(e)) + + +@@ -739,8 +739,8 @@ def host_apply_diff(host, diff): + host.os = diff.host_b.os[:] + + if diff.extraports_changed: +- for state in host.extraports.keys(): +- for port in host.ports.values(): ++ for state in list(host.extraports.keys()): ++ for port in list(host.ports.values()): + if port.state == state: + del host.ports[port.spec] + host.extraports = diff.host_b.extraports.copy() +diff --git a/ndiff/scripts/ndiff b/ndiff/scripts/ndiff +index 8517c07..4671e73 100755 +--- a/ndiff/scripts/ndiff ++++ b/ndiff/scripts/ndiff +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + + # Ndiff + # +@@ -67,15 +67,15 @@ if INSTALL_LIB is not None and is_secure_dir(INSTALL_LIB): + + try: + import ndiff +-except ImportError, e: +- print >> sys.stderr, """\ ++except ImportError as e: ++ print("""\ + Could not import the ndiff module: %s. +-I checked in these directories:""" % repr(e.message) ++I checked in these directories:""" % repr(e), file=sys.stderr) + for dir in sys.path: +- print >> sys.stderr, " %s" % dir +- print >> sys.stderr, """\ ++ print(" %s" % dir, file=sys.stderr) ++ print("""\ + If you installed Ndiff in another directory, you may have to add the +-modules directory to the PYTHONPATH environment variable.""" ++modules directory to the PYTHONPATH environment variable.""", file=sys.stderr) + sys.exit(1) + + import ndiff +diff --git a/ndiff/setup.py b/ndiff/setup.py +old mode 100644 +new mode 100755 +index b5e254c..c49bcf3 +--- a/ndiff/setup.py ++++ b/ndiff/setup.py +@@ -94,7 +94,7 @@ class checked_install(distutils.command.install.install): + self.saved_prefix = sys.prefix + try: + distutils.command.install.install.finalize_options(self) +- except distutils.errors.DistutilsPlatformError, e: ++ except distutils.errors.DistutilsPlatformError as e: + raise distutils.errors.DistutilsPlatformError(str(e) + """ + Installing your distribution's python-dev package may solve this problem.""") + +@@ -155,13 +155,13 @@ Installing your distribution's python-dev package may solve this problem.""") + #!/usr/bin/env python + import errno, os, os.path, sys + +-print 'Uninstall %(name)s' ++print('Uninstall %(name)s') + + answer = raw_input('Are you sure that you want to uninstall ' + '%(name)s (yes/no) ') + + if answer != 'yes' and answer != 'y': +- print 'Not uninstalling.' ++ print('Not uninstalling.') + sys.exit(0) + + """ % {'name': APP_NAME} +@@ -177,8 +177,8 @@ if answer != 'yes' and answer != 'y': + # This should never happen (everything gets installed + # inside the root), but if it does, be safe and don't + # delete anything. +- uninstaller += ("print '%s was not installed inside " +- "the root %s; skipping.'\n" % (output, self.root)) ++ uninstaller += ("print('%s was not installed inside " ++ "the root %s; skipping.')\n" % (output, self.root)) + continue + output = path_strip_prefix(output, self.root) + assert os.path.isabs(output) +@@ -202,24 +202,24 @@ for path in INSTALLED_FILES: + dirs.append(path) + # Delete the files. + for file in files: +- print "Removing '%s'." % file ++ print("Removing '%s'." % file) + try: + os.remove(file) +- except OSError, e: +- print >> sys.stderr, ' Error: %s.' % str(e) ++ except OSError as e: ++ print(' Error: %s.' % str(e), file=sys.stderr) + # Delete the directories. First reverse-sort the normalized paths by + # length so that child directories are deleted before their parents. + dirs = [os.path.normpath(dir) for dir in dirs] + dirs.sort(key = len, reverse = True) + for dir in dirs: + try: +- print "Removing the directory '%s'." % dir ++ print("Removing the directory '%s'." % dir) + os.rmdir(dir) +- except OSError, e: ++ except OSError as e: + if e.errno == errno.ENOTEMPTY: +- print "Directory '%s' not empty; not removing." % dir ++ print("Directory '%s' not empty; not removing." % dir) + else: +- print >> sys.stderr, str(e) ++ print(str(e), file=sys.stderr) + """ + + uninstaller_file = open(uninstaller_filename, 'w') +@@ -227,7 +227,7 @@ for dir in dirs: + uninstaller_file.close() + + # Set exec bit for uninstaller +- mode = ((os.stat(uninstaller_filename)[ST_MODE]) | 0555) & 07777 ++ mode = ((os.stat(uninstaller_filename)[ST_MODE]) | 0o555) & 0o7777 + os.chmod(uninstaller_filename, mode) + + def write_installed_files(self): +@@ -242,7 +242,7 @@ for dir in dirs: + try: + for output in self.get_installed_files(): + assert "\n" not in output +- print >> f, output ++ print(output, file=f) + finally: + f.close() + +@@ -266,7 +266,7 @@ class my_uninstall(distutils.cmd.Command): + # Read the list of installed files. + try: + f = open(INSTALLED_FILES_NAME, "r") +- except IOError, e: ++ except IOError as e: + if e.errno == errno.ENOENT: + log.error("Couldn't open the installation record '%s'. " + "Have you installed yet?" % INSTALLED_FILES_NAME) +@@ -289,7 +289,7 @@ class my_uninstall(distutils.cmd.Command): + try: + if not self.dry_run: + os.remove(file) +- except OSError, e: ++ except OSError as e: + log.error(str(e)) + # Delete the directories. First reverse-sort the normalized paths by + # length so that child directories are deleted before their parents. +@@ -300,7 +300,7 @@ class my_uninstall(distutils.cmd.Command): + log.info("Removing the directory '%s'." % dir) + if not self.dry_run: + os.rmdir(dir) +- except OSError, e: ++ except OSError as e: + if e.errno == errno.ENOTEMPTY: + log.info("Directory '%s' not empty; not removing." % dir) + else: +diff --git a/ndiff/test-scans/anonymize.py b/ndiff/test-scans/anonymize.py +index 9ba612a..fd251fe 100755 +--- a/ndiff/test-scans/anonymize.py ++++ b/ndiff/test-scans/anonymize.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + + # Anonymize an Nmap XML file, replacing host name and IP addresses with random + # anonymous ones. Anonymized names will be consistent between runs of the +@@ -20,20 +20,20 @@ r = random.Random() + + + def hash(s): +- digest = hashlib.sha512(s).hexdigest() ++ digest = hashlib.sha512(s.encode()).hexdigest() + return int(digest, 16) + + + def anonymize_mac_address(addr): + r.seed(hash(addr)) + nums = (0, 0, 0) + tuple(r.randrange(256) for i in range(3)) +- return u":".join(u"%02X" % x for x in nums) ++ return ":".join("%02X" % x for x in nums) + + + def anonymize_ipv4_address(addr): + r.seed(hash(addr)) + nums = (10,) + tuple(r.randrange(256) for i in range(3)) +- return u".".join(unicode(x) for x in nums) ++ return ".".join(str(x) for x in nums) + + + def anonymize_ipv6_address(addr): +@@ -41,7 +41,7 @@ def anonymize_ipv6_address(addr): + # RFC 4193. + nums = (0xFD00 + r.randrange(256),) + nums = nums + tuple(r.randrange(65536) for i in range(7)) +- return u":".join("%04X" % x for x in nums) ++ return ":".join("%04X" % x for x in nums) + + # Maps to memoize address and host name conversions. + hostname_map = {} +@@ -54,11 +54,11 @@ def anonymize_hostname(name): + LETTERS = "acbdefghijklmnopqrstuvwxyz" + r.seed(hash(name)) + length = r.randrange(5, 10) +- prefix = u"".join(r.sample(LETTERS, length)) ++ prefix = "".join(r.sample(LETTERS, length)) + num = r.randrange(1000) +- hostname_map[name] = u"%s-%d.example.com" % (prefix, num) ++ hostname_map[name] = "%s-%d.example.com" % (prefix, num) + if VERBOSE: +- print >> sys.stderr, "Replace %s with %s" % (name, hostname_map[name]) ++ print("Replace %s with %s" % (name, hostname_map[name]), file=sys.stderr) + return hostname_map[name] + + mac_re = re.compile(r'\b([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\b') +@@ -78,7 +78,7 @@ def anonymize_address(addr): + else: + assert False + if VERBOSE: +- print >> sys.stderr, "Replace %s with %s" % (addr, address_map[addr]) ++ print("Replace %s with %s" % (addr, address_map[addr]), file=sys.stderr) + return address_map[addr] + +