1
0
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:
dmiller
2014-01-08 19:50:22 +00:00
parent 9210a7f1fa
commit 5c662fffdc
100 changed files with 2287 additions and 1814 deletions

View File

@@ -119,4 +119,4 @@
# * * # * *
# ***************************************************************************/ # ***************************************************************************/
__all__ = ["bestwidgets", "core", "gui", "util"]; __all__ = ["bestwidgets", "core", "gui", "util"]

View File

@@ -122,7 +122,6 @@
import gtk import gtk
class BWBox(gtk.Box): class BWBox(gtk.Box):
""" """
""" """
@@ -131,38 +130,32 @@ class BWBox(gtk.Box):
""" """
self.pack_start(widget, True, True, padding) self.pack_start(widget, True, True, padding)
def bw_pack_start_expand_nofill(self, widget, padding=0): def bw_pack_start_expand_nofill(self, widget, padding=0):
""" """
""" """
self.pack_start(widget, True, False, padding) self.pack_start(widget, True, False, padding)
def bw_pack_start_noexpand_nofill(self, widget, padding=0): def bw_pack_start_noexpand_nofill(self, widget, padding=0):
""" """
""" """
self.pack_start(widget, False, False, padding) self.pack_start(widget, False, False, padding)
def bw_pack_end_expand_fill(self, widget, padding=0): def bw_pack_end_expand_fill(self, widget, padding=0):
""" """
""" """
self.pack_end(widget, True, True, padding) self.pack_end(widget, True, True, padding)
def bw_pack_end_expand_nofill(self, widget, padding=0): def bw_pack_end_expand_nofill(self, widget, padding=0):
""" """
""" """
self.pack_end(widget, True, False, padding) self.pack_end(widget, True, False, padding)
def bw_pack_end_noexpand_nofill(self, widget, padding=0): def bw_pack_end_noexpand_nofill(self, widget, padding=0):
""" """
""" """
self.pack_end(widget, False, False, padding) self.pack_end(widget, False, False, padding)
class BWHBox(gtk.HBox, BWBox): class BWHBox(gtk.HBox, BWBox):
""" """
""" """
@@ -172,7 +165,6 @@ class BWHBox(gtk.HBox, BWBox):
gtk.HBox.__init__(self, homogeneous, spacing) gtk.HBox.__init__(self, homogeneous, spacing)
class BWVBox(gtk.VBox, BWBox): class BWVBox(gtk.VBox, BWBox):
""" """
""" """
@@ -182,7 +174,6 @@ class BWVBox(gtk.VBox, BWBox):
gtk.VBox.__init__(self, homogeneous, spacing) gtk.VBox.__init__(self, homogeneous, spacing)
class BWStatusbar(gtk.Statusbar, BWBox): class BWStatusbar(gtk.Statusbar, BWBox):
""" """
""" """
@@ -192,7 +183,6 @@ class BWStatusbar(gtk.Statusbar, BWBox):
gtk.HBox.__init__(self, homogeneous, spacing) gtk.HBox.__init__(self, homogeneous, spacing)
class BWTable(gtk.Table, BWBox): class BWTable(gtk.Table, BWBox):
""" """
""" """
@@ -207,14 +197,12 @@ class BWTable(gtk.Table, BWBox):
self.__last_point = (0, 0) self.__last_point = (0, 0)
def bw_set_spacing(self, spacing): def bw_set_spacing(self, spacing):
""" """
""" """
self.set_row_spacings(spacing) self.set_row_spacings(spacing)
self.set_col_spacings(spacing) self.set_col_spacings(spacing)
def bw_resize(self, rows, columns): def bw_resize(self, rows, columns):
""" """
""" """
@@ -223,11 +211,10 @@ class BWTable(gtk.Table, BWBox):
self.resize(rows, columns) self.resize(rows, columns)
def bw_attach_next(self, def bw_attach_next(self,
child, child,
xoptions=gtk.EXPAND|gtk.FILL, xoptions=gtk.EXPAND | gtk.FILL,
yoptions=gtk.EXPAND|gtk.FILL, yoptions=gtk.EXPAND | gtk.FILL,
xpadding=0, xpadding=0,
ypadding=0): ypadding=0):
""" """
@@ -257,7 +244,6 @@ class BWTable(gtk.Table, BWBox):
self.__last_point = (row, column) self.__last_point = (row, column)
class BWScrolledWindow(gtk.ScrolledWindow): class BWScrolledWindow(gtk.ScrolledWindow):
""" """
""" """

View File

@@ -122,7 +122,6 @@
import gtk import gtk
class BWStockButton(gtk.Button): class BWStockButton(gtk.Button):
""" """
""" """
@@ -138,7 +137,6 @@ class BWStockButton(gtk.Button):
self.set_image(self.__image) self.set_image(self.__image)
class BWToggleStockButton(gtk.ToggleButton): class BWToggleStockButton(gtk.ToggleButton):
""" """
""" """

View File

@@ -123,7 +123,6 @@ import gtk
import gobject import gobject
class BWChangeableComboBoxEntry(gtk.ComboBoxEntry): class BWChangeableComboBoxEntry(gtk.ComboBoxEntry):
""" """
""" """
@@ -139,20 +138,17 @@ class BWChangeableComboBoxEntry(gtk.ComboBoxEntry):
self.__last_active = None self.__last_active = None
def __changed(self, widget): def __changed(self, widget):
""" """
""" """
if self.get_active() != -1: if self.get_active() != -1:
self.__last_active = self.get_active() self.__last_active = self.get_active()
def bw_get_lenght(self): def bw_get_lenght(self):
""" """
""" """
return len(self.__liststore) return len(self.__liststore)
def __entry_changed(self, widget): def __entry_changed(self, widget):
""" """
""" """
@@ -163,7 +159,6 @@ class BWChangeableComboBoxEntry(gtk.ComboBoxEntry):
iter = self.get_model().get_iter((self.__last_active,)) iter = self.get_model().get_iter((self.__last_active,))
self.__liststore.set_value(iter, 0, widget.get_text().strip()) self.__liststore.set_value(iter, 0, widget.get_text().strip())
def bw_get_active(self): def bw_get_active(self):
""" """
""" """
@@ -173,7 +168,6 @@ class BWChangeableComboBoxEntry(gtk.ComboBoxEntry):
return self.get_active() return self.get_active()
# testing widget # testing widget
if __name__ == "__main__": if __name__ == "__main__":
@@ -182,7 +176,6 @@ if __name__ == "__main__":
""" """
combo.append_text('New') combo.append_text('New')
window = gtk.Window() window = gtk.Window()
window.connect("destroy", lambda w: gtk.main_quit()) window.connect("destroy", lambda w: gtk.main_quit())

View File

@@ -139,13 +139,11 @@ class BWExpander(gtk.Expander):
self.add(self.__alignment) self.add(self.__alignment)
def bw_set_label_text(self, text): def bw_set_label_text(self, text):
""" """
""" """
self.__label.bw_set_text(text) self.__label.bw_set_text(text)
def bw_add(self, widget): def bw_add(self, widget):
""" """
""" """
@@ -154,7 +152,6 @@ class BWExpander(gtk.Expander):
self.__alignment.add(widget) self.__alignment.add(widget)
def bw_no_padding(self): def bw_no_padding(self):
""" """
""" """

View File

@@ -122,7 +122,6 @@
import gtk import gtk
class BWFrame(gtk.Frame): class BWFrame(gtk.Frame):
""" """
""" """
@@ -141,20 +140,17 @@ class BWFrame(gtk.Frame):
self.bw_set_label(label) self.bw_set_label(label)
def bw_set_label(self, label): def bw_set_label(self, label):
""" """
""" """
self.set_label("<b>" + label + "</b>") self.set_label("<b>" + label + "</b>")
self.get_label_widget().set_use_markup(True) self.get_label_widget().set_use_markup(True)
def bw_add(self, widget): def bw_add(self, widget):
""" """
""" """
self.__alignment.add(widget) self.__alignment.add(widget)
def bw_remove(self, widget): def bw_remove(self, widget):
""" """
""" """

View File

@@ -122,7 +122,6 @@
import gtk import gtk
class BWLabel(gtk.Label): class BWLabel(gtk.Label):
""" """
""" """
@@ -137,7 +136,6 @@ class BWLabel(gtk.Label):
self.set_line_wrap(True) self.set_line_wrap(True)
class BWSectionLabel(gtk.Label): class BWSectionLabel(gtk.Label):
""" """
""" """
@@ -151,7 +149,6 @@ class BWSectionLabel(gtk.Label):
self.set_alignment(0, 0.50) self.set_alignment(0, 0.50)
self.set_line_wrap(True) self.set_line_wrap(True)
def bw_set_text(self, text): def bw_set_text(self, text):
""" """
""" """

View File

@@ -135,7 +135,6 @@ class BWTextView(BWScrolledWindow):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -144,25 +143,21 @@ class BWTextView(BWScrolledWindow):
self.add_with_viewport(self.__textview) self.add_with_viewport(self.__textview)
def bw_set_auto_scroll(self, value): def bw_set_auto_scroll(self, value):
""" """
""" """
self.__auto_scroll = value self.__auto_scroll = value
def bw_set_editable(self, editable): def bw_set_editable(self, editable):
""" """
""" """
self.__textview.set_editable(False) self.__textview.set_editable(False)
def bw_modify_font(self, font): def bw_modify_font(self, font):
""" """
""" """
self.__textview.modify_font(font) self.__textview.modify_font(font)
def bw_set_text(self, text): def bw_set_text(self, text):
""" """
""" """
@@ -171,27 +166,23 @@ class BWTextView(BWScrolledWindow):
if self.__auto_scroll: if self.__auto_scroll:
self.bw_set_scroll_down() self.bw_set_scroll_down()
def bw_get_text(self): def bw_get_text(self):
""" """
""" """
return self.__textbuffer.get_text(self.__textbuffer.get_start_iter(), return self.__textbuffer.get_text(self.__textbuffer.get_start_iter(),
self.__textbuffer.get_end_iter()) self.__textbuffer.get_end_iter())
def bw_set_scroll_down(self): def bw_set_scroll_down(self):
""" """
""" """
self.get_vadjustment().set_value(self.get_vadjustment().upper) self.get_vadjustment().set_value(self.get_vadjustment().upper)
def bw_get_textbuffer(self): def bw_get_textbuffer(self):
""" """
""" """
return self.__textbuffer return self.__textbuffer
class BWTextEditor(BWScrolledWindow): class BWTextEditor(BWScrolledWindow):
""" """
""" """
@@ -205,7 +196,6 @@ class BWTextEditor(BWScrolledWindow):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -225,33 +215,28 @@ class BWTextEditor(BWScrolledWindow):
self.add_with_viewport(self.__hbox) self.add_with_viewport(self.__hbox)
def __expose(self, widget, event): def __expose(self, widget, event):
""" """
""" """
# code to fix a gtk issue that don't show text correctly # code to fix a gtk issue that don't show text correctly
self.__hbox.check_resize() self.__hbox.check_resize()
def bw_set_auto_scroll(self, value): def bw_set_auto_scroll(self, value):
""" """
""" """
self.__auto_scroll = value self.__auto_scroll = value
def bw_set_editable(self, editable): def bw_set_editable(self, editable):
""" """
""" """
self.__textview.set_editable(False) self.__textview.set_editable(False)
def bw_modify_font(self, font): def bw_modify_font(self, font):
""" """
""" """
self.__textview.modify_font(font) self.__textview.modify_font(font)
self.__lineview.modify_font(font) self.__lineview.modify_font(font)
def bw_set_text(self, text): def bw_set_text(self, text):
""" """
""" """
@@ -273,14 +258,12 @@ class BWTextEditor(BWScrolledWindow):
self.__textbuffer.set_text("") self.__textbuffer.set_text("")
self.__linebuffer.set_text("") self.__linebuffer.set_text("")
def bw_get_text(self): def bw_get_text(self):
""" """
""" """
return self.__textbuffer.get_text(self.__textbuffer.get_start_iter(), return self.__textbuffer.get_text(self.__textbuffer.get_start_iter(),
self.__textbuffer.get_end_iter()) self.__textbuffer.get_end_iter())
def bw_set_scroll_down(self): def bw_set_scroll_down(self):
""" """
""" """

View File

@@ -125,7 +125,6 @@ from radialnet.bestwidgets import gtk_version_minor
PRIMARY_TEXT_MARKUP = '<span weight="bold" size="larger">%s</span>' PRIMARY_TEXT_MARKUP = '<span weight="bold" size="larger">%s</span>'
class BWAlertDialog(gtk.MessageDialog): class BWAlertDialog(gtk.MessageDialog):
""" """
""" """
@@ -149,14 +148,12 @@ class BWAlertDialog(gtk.MessageDialog):
if gtk_version_minor > 4: if gtk_version_minor > 4:
self.format_secondary_text(secondary_text) self.format_secondary_text(secondary_text)
def __destroy(self, dialog, id): def __destroy(self, dialog, id):
""" """
""" """
self.destroy() self.destroy()
class BWWindow(gtk.Window): class BWWindow(gtk.Window):
""" """
""" """

View File

@@ -130,7 +130,6 @@ class ArgvHandle:
""" """
self.__argv = argv self.__argv = argv
def get_option(self, option): def get_option(self, option):
""" """
""" """
@@ -143,20 +142,17 @@ class ArgvHandle:
return None return None
def has_option(self, option): def has_option(self, option):
""" """
""" """
return option in self.__argv return option in self.__argv
def get_last_value(self): def get_last_value(self):
""" """
""" """
return self.__argv[-1] return self.__argv[-1]
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys

View File

@@ -141,31 +141,26 @@ class PolarCoordinate:
self.__t = t self.__t = t
"""Angle (theta) of polar coordinate in radians""" """Angle (theta) of polar coordinate in radians"""
def get_theta(self): def get_theta(self):
""" """
""" """
return math.degrees(self.__t) return math.degrees(self.__t)
def get_radius(self): def get_radius(self):
""" """
""" """
return self.__r return self.__r
def set_theta(self, t): def set_theta(self, t):
""" """
""" """
self.__t = math.radians(t) self.__t = math.radians(t)
def set_radius(self, r): def set_radius(self, r):
""" """
""" """
self.__r = r self.__r = r
def get_coordinate(self): def get_coordinate(self):
""" """
Set polar coordinate Set polar coordinate
@@ -174,7 +169,6 @@ class PolarCoordinate:
""" """
return (self.__r, math.degrees(self.__t)) return (self.__r, math.degrees(self.__t))
def set_coordinate(self, r, t): def set_coordinate(self, r, t):
""" """
Set polar coordinate Set polar coordinate
@@ -186,7 +180,6 @@ class PolarCoordinate:
self.__r = r self.__r = r
self.__t = math.radians(t) self.__t = math.radians(t)
def to_cartesian(self): def to_cartesian(self):
""" """
Convert polar in cartesian coordinate Convert polar in cartesian coordinate
@@ -199,12 +192,10 @@ class PolarCoordinate:
return (x, y) return (x, y)
class CartesianCoordinate: class CartesianCoordinate:
""" """
Class to implement a cartesian coordinate object Class to implement a cartesian coordinate object
""" """
def __init__(self, x=0, y=0): def __init__(self, x=0, y=0):
""" """
Constructor method of CartesianCoordinate class Constructor method of CartesianCoordinate class
@@ -218,7 +209,6 @@ class CartesianCoordinate:
self.__y = y self.__y = y
"""Y component of cartesian coordinate""" """Y component of cartesian coordinate"""
def get_coordinate(self): def get_coordinate(self):
""" """
Get cartesian coordinate Get cartesian coordinate
@@ -227,7 +217,6 @@ class CartesianCoordinate:
""" """
return (self.__x, self.__y) return (self.__x, self.__y)
def set_coordinate(self, x, y): def set_coordinate(self, x, y):
""" """
Set cartesian coordinate Set cartesian coordinate
@@ -239,25 +228,24 @@ class CartesianCoordinate:
self.__x = x self.__x = x
self.__y = y self.__y = y
def to_polar(self): def to_polar(self):
""" """
Convert cartesian in polar coordinate Convert cartesian in polar coordinate
@rtype: tuple @rtype: tuple
@return: polar coordinates (r, t) @return: polar coordinates (r, t)
""" """
r = math.sqrt(self.__x**2 + self.__y**2) r = math.sqrt(self.__x ** 2 + self.__y ** 2)
if self.__x > 0: if self.__x > 0:
if self.__y >= 0: if self.__y >= 0:
t = math.atan( self.__y / self.__x ) t = math.atan(self.__y / self.__x)
else: else:
t = math.atan( self.__y / self.__x ) + 2 * math.pi t = math.atan(self.__y / self.__x) + 2 * math.pi
elif self.__x < 0: elif self.__x < 0:
t = math.atan( self.__y / self.__x ) + math.pi t = math.atan(self.__y / self.__x) + math.pi
elif self.__x == 0: elif self.__x == 0:
@@ -273,12 +261,11 @@ class CartesianCoordinate:
return (r, t) return (r, t)
if __name__ == "__main__": if __name__ == "__main__":
# Testing application # Testing application
polar = PolarCoordinate(1, math.pi) polar = PolarCoordinate(1, math.pi)
cartesian = CartesianCoordinate(-1, 0) cartesian = CartesianCoordinate(-1, 0)
print polar.to_cartesian() print polar.to_cartesian()

View File

@@ -135,15 +135,12 @@ class Node(object):
self.__edges = [] self.__edges = []
"""List of edges to other nodes""" """List of edges to other nodes"""
def get_data(self): def get_data(self):
return self.__data return self.__data
def set_data(self, data): def set_data(self, data):
self.__data = data self.__data = data
def get_edge(self, dest): def get_edge(self, dest):
""" """
Return the edge connecting to dest, or None if none Return the edge connecting to dest, or None if none
@@ -153,19 +150,16 @@ class Node(object):
return edge return edge
return None return None
def get_edges(self): def get_edges(self):
""" """
Return the list of edges Return the list of edges
""" """
return self.__edges return self.__edges
def add_edge(self, edge): def add_edge(self, edge):
self.__edges.append(edge) self.__edges.append(edge)
class Edge: class Edge:
""" """
""" """
@@ -176,41 +170,34 @@ class Edge:
self.__nodes = nodes self.__nodes = nodes
self.__weights_mean = None self.__weights_mean = None
def get_nodes(self): def get_nodes(self):
""" """
""" """
return self.__nodes return self.__nodes
def get_weights(self): def get_weights(self):
""" """
""" """
return self.__weights return self.__weights
def set_weights(self, weights): def set_weights(self, weights):
""" """
""" """
self.__weights = weights self.__weights = weights
self.__weights_mean = sum(self.__weights) / len(self.__weights) self.__weights_mean = sum(self.__weights) / len(self.__weights)
def add_weight(self, weight): def add_weight(self, weight):
""" """
""" """
self.__weights.append(weight) self.__weights.append(weight)
self.__weights_mean = sum(self.__weights) / len(self.__weights) self.__weights_mean = sum(self.__weights) / len(self.__weights)
def get_weights_mean(self): def get_weights_mean(self):
""" """
""" """
return self.__weights_mean return self.__weights_mean
class Graph: class Graph:
""" """
Network Graph class Network Graph class
@@ -227,19 +214,16 @@ class Graph:
self.__max_edge_mean_value = None self.__max_edge_mean_value = None
self.__min_edge_mean_value = None self.__min_edge_mean_value = None
def set_nodes(self, nodes): def set_nodes(self, nodes):
""" """
""" """
self.__nodes = nodes self.__nodes = nodes
def get_nodes(self): def get_nodes(self):
""" """
""" """
return self.__nodes return self.__nodes
def get_number_of_nodes(self): def get_number_of_nodes(self):
""" """
Get the number of nodes in graph Get the number of nodes in graph
@@ -248,7 +232,6 @@ class Graph:
""" """
return len(self.__nodes) return len(self.__nodes)
def set_main_node(self, node): def set_main_node(self, node):
""" """
Set the main node Set the main node
@@ -257,7 +240,6 @@ class Graph:
""" """
self.__main_node = node self.__main_node = node
def get_main_node(self): def get_main_node(self):
""" """
Get the main node Get the main node
@@ -266,7 +248,6 @@ class Graph:
""" """
return self.__main_node return self.__main_node
def set_connection(self, a, b, weight=None): def set_connection(self, a, b, weight=None):
""" """
Set node connections Set node connections
@@ -287,12 +268,13 @@ class Graph:
edge.add_weight(weight) edge.add_weight(weight)
mean_weight = edge.get_weights_mean() mean_weight = edge.get_weights_mean()
if self.__min_edge_mean_value is None or mean_weight < self.__min_edge_mean_value: if (self.__min_edge_mean_value is None or
mean_weight < self.__min_edge_mean_value):
self.__min_edge_mean_value = mean_weight self.__min_edge_mean_value = mean_weight
if self.__max_edge_mean_value is None or mean_weight > self.__max_edge_mean_value: if (self.__max_edge_mean_value is None or
mean_weight > self.__max_edge_mean_value):
self.__max_edge_mean_value = mean_weight self.__max_edge_mean_value = mean_weight
def get_edges(self): def get_edges(self):
""" """
An iterator that yields all edges An iterator that yields all edges
@@ -302,7 +284,6 @@ class Graph:
if edge.get_nodes()[0] == node: if edge.get_nodes()[0] == node:
yield edge yield edge
def get_node_connections(self, node): def get_node_connections(self, node):
""" """
""" """
@@ -319,16 +300,12 @@ class Graph:
return connections return connections
def get_max_edge_mean_weight(self): def get_max_edge_mean_weight(self):
""" """
""" """
return self.__max_edge_mean_value return self.__max_edge_mean_value
def get_min_edge_mean_weight(self): def get_min_edge_mean_weight(self):
""" """
""" """
return self.__min_edge_mean_value return self.__min_edge_mean_value

View File

@@ -122,7 +122,7 @@
import os import os
INFO = {'name' : 'RadialNet', INFO = {'name': 'RadialNet',
'version': '0.44', 'version': '0.44',
'website': 'http://www.dca.ufrn.br/~joaomedeiros/radialnet/', 'website': 'http://www.dca.ufrn.br/~joaomedeiros/radialnet/',
'authors': ['João Paulo de Souza Medeiros'], 'authors': ['João Paulo de Souza Medeiros'],

View File

@@ -136,7 +136,6 @@ class Linear2DInterpolator:
self.__interpolated_points = [] self.__interpolated_points = []
"""Interpolated points vector""" """Interpolated points vector"""
def set_start_point(self, a, b): def set_start_point(self, a, b):
""" """
Set initial coordinate Set initial coordinate
@@ -148,7 +147,6 @@ class Linear2DInterpolator:
""" """
self.__start_point = (a, b) self.__start_point = (a, b)
def set_final_point(self, a, b): def set_final_point(self, a, b):
""" """
Set final coordinate Set final coordinate
@@ -159,7 +157,6 @@ class Linear2DInterpolator:
""" """
self.__final_point = (a, b) self.__final_point = (a, b)
def get_weighed_points(self, number_of_pass, pass_vector): def get_weighed_points(self, number_of_pass, pass_vector):
""" """
Return the vector of coordinates between the initial and final Return the vector of coordinates between the initial and final
@@ -188,7 +185,6 @@ class Linear2DInterpolator:
return self.__interpolated_points return self.__interpolated_points
def get_points(self, number_of_pass): def get_points(self, number_of_pass):
""" """
Return the vector of coordinates between the initial and final Return the vector of coordinates between the initial and final
@@ -213,7 +209,6 @@ class Linear2DInterpolator:
return self.__interpolated_points return self.__interpolated_points
if __name__ == "__main__": if __name__ == "__main__":
# Testing application # Testing application
@@ -224,4 +219,3 @@ if __name__ == "__main__":
i.set_final_point(1, 1) i.set_final_point(1, 1)
print len(i.get_points(10)), i.get_points(10) print len(i.get_points(10)), i.get_points(10)

View File

@@ -124,14 +124,12 @@ import xml.sax.saxutils
from xml.sax.xmlreader import AttributesImpl as Attributes from xml.sax.xmlreader import AttributesImpl as Attributes
def convert_to_utf8(text): def convert_to_utf8(text):
""" """
""" """
return text.encode('utf8', 'replace') return text.encode('utf8', 'replace')
class XMLNode: class XMLNode:
""" """
""" """
@@ -143,70 +141,59 @@ class XMLNode:
self.__attrs = dict() self.__attrs = dict()
self.__children = [] self.__children = []
def set_text(self, text): def set_text(self, text):
""" """
""" """
self.__text = text self.__text = text
def get_text(self): def get_text(self):
""" """
""" """
return self.__text return self.__text
def set_name(self, name): def set_name(self, name):
""" """
""" """
self.__name = name self.__name = name
def get_name(self): def get_name(self):
""" """
""" """
return self.__name return self.__name
def add_attr(self, key, value): def add_attr(self, key, value):
""" """
""" """
self.__attrs[key] = value self.__attrs[key] = value
def add_child(self, child): def add_child(self, child):
""" """
""" """
self.__children.append(child) self.__children.append(child)
def get_keys(self): def get_keys(self):
""" """
""" """
return self.__attrs.keys() return self.__attrs.keys()
def get_attr(self, attr): def get_attr(self, attr):
""" """
""" """
if self.__attrs.has_key(attr): if attr in self.__attrs:
return self.__attrs[attr] return self.__attrs[attr]
return None return None
def get_attrs(self): def get_attrs(self):
""" """
""" """
return self.__attrs return self.__attrs
def get_children(self): def get_children(self):
""" """
""" """
return self.__children return self.__children
def query_children(self, name, attr, value, first=False, deep=False): def query_children(self, name, attr, value, first=False, deep=False):
""" """
""" """
@@ -216,7 +203,7 @@ class XMLNode:
if child.get_name() == name: if child.get_name() == name:
if child.get_attrs().has_key(attr): if attr in child.get_attrs():
c_value = child.get_attr(attr) c_value = child.get_attr(attr)
@@ -243,7 +230,6 @@ class XMLNode:
return result return result
def search_children(self, name, first=False, deep=False): def search_children(self, name, first=False, deep=False):
""" """
""" """
@@ -276,7 +262,6 @@ class XMLNode:
return result return result
class XMLWriter(xml.sax.saxutils.XMLGenerator): class XMLWriter(xml.sax.saxutils.XMLGenerator):
""" """
""" """
@@ -287,13 +272,11 @@ class XMLWriter(xml.sax.saxutils.XMLGenerator):
self.__root = root self.__root = root
def set_root(self, root): def set_root(self, root):
""" """
""" """
self.__root = root self.__root = root
def write(self): def write(self):
""" """
""" """
@@ -301,7 +284,6 @@ class XMLWriter(xml.sax.saxutils.XMLGenerator):
self.write_xml_node([self.__root]) self.write_xml_node([self.__root])
self.endDocument() self.endDocument()
def write_xml_node(self, root): def write_xml_node(self, root):
""" """
""" """
@@ -317,7 +299,6 @@ class XMLWriter(xml.sax.saxutils.XMLGenerator):
self.endElement(child.get_name()) self.endElement(child.get_name())
class XMLReader(xml.sax.ContentHandler): class XMLReader(xml.sax.ContentHandler):
""" """
""" """
@@ -330,41 +311,35 @@ class XMLReader(xml.sax.ContentHandler):
self.__file = file self.__file = file
self.__root = None self.__root = None
self.__parser = xml.sax.make_parser(); self.__parser = xml.sax.make_parser()
self.__parser.setContentHandler(self); self.__parser.setContentHandler(self)
def set_file(self, file, root): def set_file(self, file, root):
""" """
""" """
self.__file = file self.__file = file
def get_file(self): def get_file(self):
""" """
""" """
return self.__file return self.__file
def get_root(self): def get_root(self):
""" """
""" """
return self.__root return self.__root
def parse(self): def parse(self):
""" """
""" """
if self.__file != None: if self.__file != None:
self.__parser.parse(self.__file) self.__parser.parse(self.__file)
def startDocument(self): def startDocument(self):
""" """
""" """
pass pass
def startElement(self, name, attrs): def startElement(self, name, attrs):
""" """
""" """
@@ -384,7 +359,6 @@ class XMLReader(xml.sax.ContentHandler):
self.__status.append(node) self.__status.append(node)
def endElement(self, name): def endElement(self, name):
""" """
""" """
@@ -393,20 +367,17 @@ class XMLReader(xml.sax.ContentHandler):
self.__text = "" self.__text = ""
self.__status.pop() self.__status.pop()
def endDocument(self): def endDocument(self):
""" """
""" """
pass pass
def characters(self, text): def characters(self, text):
""" """
""" """
self.__text += text self.__text += text
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys

View File

@@ -118,4 +118,3 @@
# * Nmap, and also available from https://svn.nmap.org/nmap/COPYING * # * Nmap, and also available from https://svn.nmap.org/nmap/COPYING *
# * * # * *
# ***************************************************************************/ # ***************************************************************************/

View File

@@ -135,7 +135,6 @@ from radialnet.bestwidgets.boxes import *
DIMENSION = (640, 480) DIMENSION = (640, 480)
class Application(BWMainWindow): class Application(BWMainWindow):
""" """
""" """
@@ -149,7 +148,6 @@ class Application(BWMainWindow):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -188,7 +186,6 @@ class Application(BWMainWindow):
self.__fisheye.hide() self.__fisheye.hide()
self.__toolbar.disable_controls() self.__toolbar.disable_controls()
def parse_nmap_xml_file(self, file): def parse_nmap_xml_file(self, file):
""" """
""" """
@@ -217,7 +214,6 @@ class Application(BWMainWindow):
return True return True
def start(self): def start(self):
""" """
""" """

View File

@@ -143,7 +143,6 @@ OPTIONS = ['address',
REFRESH_RATE = 500 REFRESH_RATE = 500
class ControlWidget(BWVBox): class ControlWidget(BWVBox):
""" """
""" """
@@ -157,7 +156,6 @@ class ControlWidget(BWVBox):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -179,6 +177,7 @@ def try_set_tooltip_text(widget, text):
# The set_tooltip_text method was introduced in PyGTK 2.12. # The set_tooltip_text method was introduced in PyGTK 2.12.
pass pass
class ControlAction(BWExpander): class ControlAction(BWExpander):
""" """
""" """
@@ -192,7 +191,6 @@ class ControlAction(BWExpander):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -253,7 +251,6 @@ class ControlAction(BWExpander):
self.__region_color.set_no_show_all(True) self.__region_color.set_no_show_all(True)
self.__region_color.hide() self.__region_color.hide()
def __change_pointer(self, widget, pointer): def __change_pointer(self, widget, pointer):
""" """
""" """
@@ -265,14 +262,12 @@ class ControlAction(BWExpander):
else: else:
self.__region_color.hide() self.__region_color.hide()
def __change_region(self, widget): def __change_region(self, widget):
""" """
""" """
self.radialnet.set_region_color(self.__region_color.get_active()) self.radialnet.set_region_color(self.__region_color.get_active())
class ControlVariableWidget(gtk.DrawingArea): class ControlVariableWidget(gtk.DrawingArea):
""" """
""" """
@@ -307,7 +302,6 @@ class ControlVariableWidget(gtk.DrawingArea):
gobject.timeout_add(REFRESH_RATE, self.verify_value) gobject.timeout_add(REFRESH_RATE, self.verify_value)
def verify_value(self): def verify_value(self):
""" """
""" """
@@ -318,7 +312,6 @@ class ControlVariableWidget(gtk.DrawingArea):
return True return True
def button_press(self, widget, event): def button_press(self, widget, event):
""" """
""" """
@@ -331,7 +324,6 @@ class ControlVariableWidget(gtk.DrawingArea):
self.__active_increment = True self.__active_increment = True
self.__increment_value() self.__increment_value()
def button_release(self, widget, event): def button_release(self, widget, event):
""" """
""" """
@@ -342,7 +334,6 @@ class ControlVariableWidget(gtk.DrawingArea):
self.queue_draw() self.queue_draw()
def motion_notify(self, widget, event): def motion_notify(self, widget, event):
""" """
Drawing callback Drawing callback
@@ -363,7 +354,6 @@ class ControlVariableWidget(gtk.DrawingArea):
self.queue_draw() self.queue_draw()
def expose(self, widget, event): def expose(self, widget, event):
""" """
Drawing callback Drawing callback
@@ -381,7 +371,6 @@ class ControlVariableWidget(gtk.DrawingArea):
return True return True
def __draw(self): def __draw(self):
""" """
""" """
@@ -394,7 +383,7 @@ class ControlVariableWidget(gtk.DrawingArea):
# draw line # draw line
self.context.set_line_width(1) self.context.set_line_width(1)
self.context.set_dash([1,2]) self.context.set_dash([1, 2])
self.context.move_to(self.__radius, self.context.move_to(self.__radius,
yc + self.__radius) yc + self.__radius)
self.context.line_to(2 * xc - 5, self.context.line_to(2 * xc - 5,
@@ -402,7 +391,7 @@ class ControlVariableWidget(gtk.DrawingArea):
self.context.stroke() self.context.stroke()
# draw text # draw text
self.context.set_dash([1,0]) self.context.set_dash([1, 0])
self.context.set_font_size(10) self.context.set_font_size(10)
width = self.context.text_extents(self.__variable_name)[2] width = self.context.text_extents(self.__variable_name)[2]
@@ -428,7 +417,6 @@ class ControlVariableWidget(gtk.DrawingArea):
self.context.set_source_rgb(0.0, 0.0, 0.0) self.context.set_source_rgb(0.0, 0.0, 0.0)
self.context.stroke() self.context.stroke()
def __button_is_clicked(self, pointer): def __button_is_clicked(self, pointer):
""" """
""" """
@@ -440,7 +428,6 @@ class ControlVariableWidget(gtk.DrawingArea):
return False return False
def __increment_value(self): def __increment_value(self):
""" """
""" """
@@ -453,20 +440,17 @@ class ControlVariableWidget(gtk.DrawingArea):
gobject.timeout_add(self.__increment_time, gobject.timeout_add(self.__increment_time,
self.__increment_value) self.__increment_value)
def set_value_function(self, value): def set_value_function(self, value):
""" """
""" """
self.__value = value self.__value = value
def set_update_function(self, update): def set_update_function(self, update):
""" """
""" """
self.__update = update self.__update = update
class ControlVariable(BWHBox): class ControlVariable(BWHBox):
""" """
""" """
@@ -485,7 +469,6 @@ class ControlVariable(BWHBox):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -516,14 +499,12 @@ class ControlVariable(BWHBox):
self.bw_pack_start_expand_fill(self.__control) self.bw_pack_start_expand_fill(self.__control)
self.bw_pack_start_noexpand_nofill(self.__right_button) self.bw_pack_start_noexpand_nofill(self.__right_button)
def __pressed(self, widget, increment): def __pressed(self, widget, increment):
""" """
""" """
self.__increment = True self.__increment = True
self.__increment_function(increment) self.__increment_function(increment)
def __increment_function(self, increment): def __increment_function(self, increment):
""" """
""" """
@@ -536,15 +517,12 @@ class ControlVariable(BWHBox):
self.__increment_function, self.__increment_function,
increment) increment)
def __released(self, widget): def __released(self, widget):
""" """
""" """
self.__increment = False self.__increment = False
class ControlFisheye(BWVBox): class ControlFisheye(BWVBox):
""" """
""" """
@@ -559,7 +537,6 @@ class ControlFisheye(BWVBox):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -606,7 +583,6 @@ class ControlFisheye(BWVBox):
gobject.timeout_add(REFRESH_RATE, self.__update_fisheye) gobject.timeout_add(REFRESH_RATE, self.__update_fisheye)
def __update_fisheye(self): def __update_fisheye(self):
""" """
""" """
@@ -648,7 +624,6 @@ class ControlFisheye(BWVBox):
return True return True
def active_fisheye(self): def active_fisheye(self):
""" """
""" """
@@ -656,13 +631,11 @@ class ControlFisheye(BWVBox):
self.__change_ring() self.__change_ring()
self.__change_interest() self.__change_interest()
def deactive_fisheye(self): def deactive_fisheye(self):
""" """
""" """
self.radialnet.set_fisheye(False) self.radialnet.set_fisheye(False)
def __change_ring(self, widget=None): def __change_ring(self, widget=None):
""" """
""" """
@@ -671,7 +644,6 @@ class ControlFisheye(BWVBox):
else: else:
self.__ring.set_value(self.radialnet.get_fisheye_ring()) self.__ring.set_value(self.radialnet.get_fisheye_ring())
def __change_interest(self, widget=None): def __change_interest(self, widget=None):
""" """
""" """
@@ -680,7 +652,6 @@ class ControlFisheye(BWVBox):
else: else:
self.__interest.set_value(self.radialnet.get_fisheye_interest()) self.__interest.set_value(self.radialnet.get_fisheye_interest())
def __change_spread(self, widget=None): def __change_spread(self, widget=None):
""" """
""" """
@@ -690,7 +661,6 @@ class ControlFisheye(BWVBox):
self.__spread.set_value(self.radialnet.get_fisheye_spread()) self.__spread.set_value(self.radialnet.get_fisheye_spread())
class ControlInterpolation(BWExpander): class ControlInterpolation(BWExpander):
""" """
""" """
@@ -703,14 +673,14 @@ class ControlInterpolation(BWExpander):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
self.__vbox = BWVBox() self.__vbox = BWVBox()
self.__cartesian_radio = gtk.RadioButton(None, _('Cartesian')) self.__cartesian_radio = gtk.RadioButton(None, _('Cartesian'))
self.__polar_radio = gtk.RadioButton(self.__cartesian_radio, _('Polar')) self.__polar_radio = gtk.RadioButton(
self.__cartesian_radio, _('Polar'))
self.__cartesian_radio.connect('toggled', self.__cartesian_radio.connect('toggled',
self.__change_system, self.__change_system,
INTERPOLATION_CARTESIAN) INTERPOLATION_CARTESIAN)
@@ -741,7 +711,6 @@ class ControlInterpolation(BWExpander):
gobject.timeout_add(REFRESH_RATE, self.__update_animation) gobject.timeout_add(REFRESH_RATE, self.__update_animation)
def __update_animation(self): def __update_animation(self):
""" """
""" """
@@ -755,7 +724,6 @@ class ControlInterpolation(BWExpander):
return True return True
def __change_system(self, widget, value): def __change_system(self, widget, value):
""" """
""" """
@@ -769,7 +737,6 @@ class ControlInterpolation(BWExpander):
else: else:
self.__polar_radio.set_active(True) self.__polar_radio.set_active(True)
def __change_frames(self, widget): def __change_frames(self, widget):
""" """
""" """
@@ -777,7 +744,6 @@ class ControlInterpolation(BWExpander):
self.__frames.set_value(self.radialnet.get_number_of_frames()) self.__frames.set_value(self.radialnet.get_number_of_frames())
class ControlLayout(BWExpander): class ControlLayout(BWExpander):
""" """
""" """
@@ -790,7 +756,6 @@ class ControlLayout(BWExpander):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -811,7 +776,6 @@ class ControlLayout(BWExpander):
self.__check_layout() self.__check_layout()
def __check_layout(self): def __check_layout(self):
""" """
""" """
@@ -823,14 +787,12 @@ class ControlLayout(BWExpander):
return True return True
def __force_update(self, widget): def __force_update(self, widget):
""" """
""" """
self.__fisheye_ring = self.radialnet.get_fisheye_ring() self.__fisheye_ring = self.radialnet.get_fisheye_ring()
self.radialnet.update_layout() self.radialnet.update_layout()
def __change_layout(self, widget): def __change_layout(self, widget):
""" """
""" """
@@ -841,7 +803,6 @@ class ControlLayout(BWExpander):
self.__check_layout() self.__check_layout()
class ControlRingGap(BWVBox): class ControlRingGap(BWVBox):
""" """
""" """
@@ -854,7 +815,6 @@ class ControlRingGap(BWVBox):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -878,7 +838,6 @@ class ControlRingGap(BWVBox):
self.bw_pack_start_noexpand_nofill(self.__radius) self.bw_pack_start_noexpand_nofill(self.__radius)
self.bw_pack_start_noexpand_nofill(self.__lower_hbox) self.bw_pack_start_noexpand_nofill(self.__lower_hbox)
def __change_lower(self, widget): def __change_lower(self, widget):
""" """
""" """
@@ -886,7 +845,6 @@ class ControlRingGap(BWVBox):
self.__adjustment.set_value(self.radialnet.get_min_ring_gap()) self.__adjustment.set_value(self.radialnet.get_min_ring_gap())
class ControlOptions(BWScrolledWindow): class ControlOptions(BWScrolledWindow):
""" """
""" """
@@ -902,7 +860,6 @@ class ControlOptions(BWScrolledWindow):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -943,23 +900,23 @@ class ControlOptions(BWScrolledWindow):
gobject.timeout_add(REFRESH_RATE, self.__update_options) gobject.timeout_add(REFRESH_RATE, self.__update_options)
def __update_options(self): def __update_options(self):
""" """
""" """
model = self.__liststore model = self.__liststore
model[OPTIONS.index('address')][0] = self.radialnet.get_show_address() model[OPTIONS.index('address')][0] = self.radialnet.get_show_address()
model[OPTIONS.index('hostname')][0] = self.radialnet.get_show_hostname() model[OPTIONS.index('hostname')][0] = \
self.radialnet.get_show_hostname()
model[OPTIONS.index('icon')][0] = self.radialnet.get_show_icon() model[OPTIONS.index('icon')][0] = self.radialnet.get_show_icon()
model[OPTIONS.index('latency')][0] = self.radialnet.get_show_latency() model[OPTIONS.index('latency')][0] = self.radialnet.get_show_latency()
model[OPTIONS.index('ring')][0] = self.radialnet.get_show_ring() model[OPTIONS.index('ring')][0] = self.radialnet.get_show_ring()
model[OPTIONS.index('region')][0] = self.radialnet.get_show_region() model[OPTIONS.index('region')][0] = self.radialnet.get_show_region()
model[OPTIONS.index('slow in/out')][0] = self.radialnet.get_slow_inout() model[OPTIONS.index('slow in/out')][0] = \
self.radialnet.get_slow_inout()
return True return True
def __change_option(self, cell, option, model): def __change_option(self, cell, option, model):
""" """
""" """
@@ -988,7 +945,6 @@ class ControlOptions(BWScrolledWindow):
self.radialnet.set_slow_inout(model[option][0]) self.radialnet.set_slow_inout(model[option][0])
class ControlView(BWExpander): class ControlView(BWExpander):
""" """
""" """
@@ -1002,7 +958,6 @@ class ControlView(BWExpander):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -1026,7 +981,6 @@ class ControlView(BWExpander):
self.bw_add(self.__vbox) self.bw_add(self.__vbox)
class ControlNavigation(gtk.DrawingArea): class ControlNavigation(gtk.DrawingArea):
""" """
""" """
@@ -1047,12 +1001,12 @@ class ControlNavigation(gtk.DrawingArea):
self.__move_position = (0, 0) self.__move_position = (0, 0)
self.__move_addition = [(-1, 0), self.__move_addition = [(-1, 0),
(-1,-1), (-1, -1),
( 0,-1), (0, -1),
( 1,-1), (1, -1),
( 1, 0), (1, 0),
( 1, 1), (1, 1),
( 0, 1), (0, 1),
(-1, 1)] (-1, 1)]
self.__move_factor = 1 self.__move_factor = 1
@@ -1086,7 +1040,6 @@ class ControlNavigation(gtk.DrawingArea):
self.__rotate_node.set_coordinate(40, self.radialnet.get_rotation()) self.__rotate_node.set_coordinate(40, self.radialnet.get_rotation())
def key_press(self, widget, event): def key_press(self, widget, event):
""" """
""" """
@@ -1096,7 +1049,6 @@ class ControlNavigation(gtk.DrawingArea):
return True return True
def key_release(self, widget, event): def key_release(self, widget, event):
""" """
""" """
@@ -1106,13 +1058,11 @@ class ControlNavigation(gtk.DrawingArea):
return True return True
def enter_notify(self, widget, event): def enter_notify(self, widget, event):
""" """
""" """
return False return False
def leave_notify(self, widget, event): def leave_notify(self, widget, event):
""" """
""" """
@@ -1120,7 +1070,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def button_press(self, widget, event): def button_press(self, widget, event):
""" """
Drawing callback Drawing callback
@@ -1159,7 +1108,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def button_release(self, widget, event): def button_release(self, widget, event):
""" """
Drawing callback Drawing callback
@@ -1181,7 +1129,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def motion_notify(self, widget, event): def motion_notify(self, widget, event):
""" """
Drawing callback Drawing callback
@@ -1213,7 +1160,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def expose(self, widget, event): def expose(self, widget, event):
""" """
Drawing callback Drawing callback
@@ -1231,7 +1177,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def __draw_rotate_control(self): def __draw_rotate_control(self):
""" """
""" """
@@ -1251,14 +1196,14 @@ class ControlNavigation(gtk.DrawingArea):
self.context.stroke() self.context.stroke()
# draw arc # draw arc
self.context.set_dash([1,2]) self.context.set_dash([1, 2])
self.context.arc(xc, yc, 40, 0, 2 * math.pi) self.context.arc(xc, yc, 40, 0, 2 * math.pi)
self.context.set_source_rgb(0.0, 0.0, 0.0) self.context.set_source_rgb(0.0, 0.0, 0.0)
self.context.set_line_width(1) self.context.set_line_width(1)
self.context.stroke() self.context.stroke()
# draw node # draw node
self.context.set_dash([1,0]) self.context.set_dash([1, 0])
self.context.arc(xc + x, yc - y, self.__rotate_radius, 0, 2 * math.pi) self.context.arc(xc + x, yc - y, self.__rotate_radius, 0, 2 * math.pi)
if self.__rotating == True: if self.__rotating == True:
@@ -1274,14 +1219,13 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def __draw_move_control(self): def __draw_move_control(self):
""" """
""" """
xc, yc = self.__center_of_widget xc, yc = self.__center_of_widget
pc = PolarCoordinate() pc = PolarCoordinate()
self.context.set_dash([1,1]) self.context.set_dash([1, 1])
self.context.arc(xc, yc, 23, 0, 2 * math.pi) self.context.arc(xc, yc, 23, 0, 2 * math.pi)
self.context.set_source_rgb(0.0, 0.0, 0.0) self.context.set_source_rgb(0.0, 0.0, 0.0)
self.context.set_line_width(1) self.context.set_line_width(1)
@@ -1292,13 +1236,14 @@ class ControlNavigation(gtk.DrawingArea):
pc.set_coordinate(23, 45 * i) pc.set_coordinate(23, 45 * i)
x, y = pc.to_cartesian() x, y = pc.to_cartesian()
self.context.set_dash([1,1]) self.context.set_dash([1, 1])
self.context.move_to(xc, yc) self.context.move_to(xc, yc)
self.context.line_to(xc + x, yc - y) self.context.line_to(xc + x, yc - y)
self.context.stroke() self.context.stroke()
self.context.set_dash([1,0]) self.context.set_dash([1, 0])
self.context.arc(xc + x, yc - y, self.__move_radius, 0, 2 * math.pi) self.context.arc(
xc + x, yc - y, self.__move_radius, 0, 2 * math.pi)
if i == self.__moving: if i == self.__moving:
self.context.set_source_rgb(0.0, 0.0, 0.0) self.context.set_source_rgb(0.0, 0.0, 0.0)
@@ -1322,7 +1267,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def __draw(self): def __draw(self):
""" """
Drawing method Drawing method
@@ -1338,7 +1282,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def __move_in_direction(self, direction): def __move_in_direction(self, direction):
""" """
""" """
@@ -1360,7 +1303,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def __rotate_is_clicked(self, pointer): def __rotate_is_clicked(self, pointer):
""" """
""" """
@@ -1375,7 +1317,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def __center_is_clicked(self, pointer): def __center_is_clicked(self, pointer):
""" """
""" """
@@ -1388,7 +1329,6 @@ class ControlNavigation(gtk.DrawingArea):
return False return False
def __move_is_clicked(self, pointer): def __move_is_clicked(self, pointer):
""" """
""" """
@@ -1409,5 +1349,3 @@ class ControlNavigation(gtk.DrawingArea):
return i return i
return None return None

View File

@@ -126,7 +126,6 @@ from radialnet.core.Info import INFO
from radialnet.gui.Image import Pixmaps from radialnet.gui.Image import Pixmaps
class AboutDialog(gtk.AboutDialog): class AboutDialog(gtk.AboutDialog):
""" """
""" """
@@ -146,7 +145,6 @@ class AboutDialog(gtk.AboutDialog):
self.connect('response', self.__destroy) self.connect('response', self.__destroy)
def __destroy(self, dialog, id): def __destroy(self, dialog, id):
""" """
""" """

View File

@@ -138,7 +138,6 @@ DIMENSION = (700, 400)
IP_RE = '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' IP_RE = '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
class HostsViewer(BWMainWindow): class HostsViewer(BWMainWindow):
""" """
""" """
@@ -155,7 +154,6 @@ class HostsViewer(BWMainWindow):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -170,8 +168,6 @@ class HostsViewer(BWMainWindow):
self.add(self.__panel) self.add(self.__panel)
def change_notebook(self, node): def change_notebook(self, node):
""" """
""" """
@@ -187,7 +183,6 @@ class HostsViewer(BWMainWindow):
self.__panel.add2(self.__view) self.__panel.add2(self.__view)
class HostsList(gtk.ScrolledWindow): class HostsList(gtk.ScrolledWindow):
""" """
""" """
@@ -203,7 +198,6 @@ class HostsList(gtk.ScrolledWindow):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -239,16 +233,16 @@ class HostsList(gtk.ScrolledWindow):
column = gtk.TreeViewColumn(HOSTS_HEADER[i], column = gtk.TreeViewColumn(HOSTS_HEADER[i],
self.__cell, self.__cell,
text = i) text=i)
self.__hosts_column.append(column) self.__hosts_column.append(column)
self.__hosts_column[i].set_reorderable(True) self.__hosts_column[i].set_reorderable(True)
self.__hosts_column[i].set_resizable(True) self.__hosts_column[i].set_resizable(True)
self.__hosts_column[i].set_attributes(self.__cell, self.__hosts_column[i].set_attributes(self.__cell,
text = i, text=i,
background = 3, background=3,
editable = 4) editable=4)
self.__hosts_treeview.append_column(self.__hosts_column[2]) self.__hosts_treeview.append_column(self.__hosts_column[2])
@@ -262,7 +256,6 @@ class HostsList(gtk.ScrolledWindow):
self.__hosts_treeview.set_cursor((0,)) self.__hosts_treeview.set_cursor((0,))
self.__cursor_callback(self.__hosts_treeview) self.__cursor_callback(self.__hosts_treeview)
def __cursor_callback(self, widget): def __cursor_callback(self, widget):
""" """
""" """
@@ -276,7 +269,6 @@ class HostsList(gtk.ScrolledWindow):
self.__parent.change_notebook(node) self.__parent.change_notebook(node)
def __host_sort(self, treemodel, iter1, iter2): def __host_sort(self, treemodel, iter1, iter2):
""" """
""" """

View File

@@ -128,7 +128,7 @@ from zenmapCore.Paths import Path
FORMAT_RGBA = 4 FORMAT_RGBA = 4
FORMAT_RGB = 3 FORMAT_RGB = 3
def get_pixels_for_cairo_image_surface(pixbuf): def get_pixels_for_cairo_image_surface(pixbuf):
@@ -144,16 +144,16 @@ def get_pixels_for_cairo_image_surface(pixbuf):
j = 0 j = 0
while i < len(pixbuf.get_pixels()): while i < len(pixbuf.get_pixels()):
b, g, r = pixbuf.get_pixels()[i:i+FORMAT_RGB] b, g, r = pixbuf.get_pixels()[i:i + FORMAT_RGB]
if format == FORMAT_RGBA: if format == FORMAT_RGBA:
a = pixbuf.get_pixels()[i + FORMAT_RGBA - 1] a = pixbuf.get_pixels()[i + FORMAT_RGBA - 1]
elif format == FORMAT_RGB: elif format == FORMAT_RGB:
a = '\xff' a = '\xff'
else: else:
raise TypeError, 'unknown image format' raise TypeError('unknown image format')
data[j:j+FORMAT_RGBA] = array.ArrayType('c', [r, g, b, a]) data[j:j + FORMAT_RGBA] = array.ArrayType('c', [r, g, b, a])
i += format i += format
j += FORMAT_RGBA j += FORMAT_RGBA
@@ -170,13 +170,11 @@ class Image:
self.__path = path self.__path = path
self.__cache = dict() self.__cache = dict()
def set_path(self, path): def set_path(self, path):
""" """
""" """
self.__path = path self.__path = path
def get_pixbuf(self, icon, image_type='png'): def get_pixbuf(self, icon, image_type='png'):
""" """
""" """
@@ -186,11 +184,11 @@ class Image:
if icon + image_type not in self.__cache.keys(): if icon + image_type not in self.__cache.keys():
file = self.get_icon(icon, image_type) file = self.get_icon(icon, image_type)
self.__cache[icon + image_type] = gtk.gdk.pixbuf_new_from_file(file) self.__cache[icon + image_type] = \
gtk.gdk.pixbuf_new_from_file(file)
return self.__cache[icon + image_type] return self.__cache[icon + image_type]
def get_icon(self, icon, image_type='png'): def get_icon(self, icon, image_type='png'):
""" """
""" """
@@ -200,7 +198,6 @@ class Image:
return os.path.join(self.__path, icon + "." + image_type) return os.path.join(self.__path, icon + "." + image_type)
class Pixmaps(Image): class Pixmaps(Image):
""" """
""" """
@@ -210,7 +207,6 @@ class Pixmaps(Image):
Image.__init__(self, os.path.join(Path.pixmaps_dir, "radialnet")) Image.__init__(self, os.path.join(Path.pixmaps_dir, "radialnet"))
class Icons(Image): class Icons(Image):
""" """
""" """
@@ -220,7 +216,6 @@ class Icons(Image):
Image.__init__(self, os.path.join(Path.pixmaps_dir, "radialnet")) Image.__init__(self, os.path.join(Path.pixmaps_dir, "radialnet"))
class Application(Image): class Application(Image):
""" """
""" """

View File

@@ -129,27 +129,27 @@ from radialnet.bestwidgets.labels import *
from radialnet.bestwidgets.textview import * from radialnet.bestwidgets.textview import *
PORTS_HEADER = [_('Port'), _('Protocol'), _('State'), _('Service'), _('Method')] PORTS_HEADER = [
_('Port'), _('Protocol'), _('State'), _('Service'), _('Method')]
EXTRAPORTS_HEADER = [_('Count'), _('State'), _('Reasons')] EXTRAPORTS_HEADER = [_('Count'), _('State'), _('Reasons')]
SERVICE_COLORS = {'open' : '#ffd5d5', SERVICE_COLORS = {'open': '#ffd5d5',
'closed' : '#d5ffd5', 'closed': '#d5ffd5',
'filtered' : '#ffffd5', 'filtered': '#ffffd5',
'unfiltered' : '#ffd5d5', 'unfiltered': '#ffd5d5',
'open|filtered' : '#ffd5d5', 'open|filtered': '#ffd5d5',
'closed|filtered' : '#d5ffd5'} 'closed|filtered': '#d5ffd5'}
UNKNOWN_SERVICE_COLOR = '#d5d5d5' UNKNOWN_SERVICE_COLOR = '#d5d5d5'
TRACE_HEADER = [_('TTL'), _('RTT'), _('IP'), _('Hostname')] TRACE_HEADER = [_('TTL'), _('RTT'), _('IP'), _('Hostname')]
TRACE_TEXT = _("""\ TRACE_TEXT = _(
Traceroute on port <b>%s/%s</b> totalized <b>%d</b> known hops.\ "Traceroute on port <b>%s/%s</b> totalized <b>%d</b> known hops.")
""")
NO_TRACE_TEXT = _("No traceroute information available.") NO_TRACE_TEXT = _("No traceroute information available.")
HOP_COLOR = {'known' : '#ffffff', HOP_COLOR = {'known': '#ffffff',
'unknown' : '#cccccc'} 'unknown': '#cccccc'}
SYSTEM_ADDRESS_TEXT = "[%s] %s" SYSTEM_ADDRESS_TEXT = "[%s] %s"
@@ -162,6 +162,7 @@ TCP_SEQ_NOTE = _("""\
<b>*</b> TCP sequence <i>index</i> equal to %d and <i>difficulty</i> is "%s".\ <b>*</b> TCP sequence <i>index</i> equal to %d and <i>difficulty</i> is "%s".\
""") """)
def get_service_color(state): def get_service_color(state):
color = SERVICE_COLORS.get(state) color = SERVICE_COLORS.get(state)
if color is None: if color is None:
@@ -182,7 +183,6 @@ class NodeNotebook(gtk.Notebook):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -197,7 +197,6 @@ class NodeNotebook(gtk.Notebook):
self.append_page(self.__trace_page, BWLabel(_('Traceroute'))) self.append_page(self.__trace_page, BWLabel(_('Traceroute')))
class ServicesPage(gtk.Notebook): class ServicesPage(gtk.Notebook):
""" """
""" """
@@ -213,7 +212,6 @@ class ServicesPage(gtk.Notebook):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -256,13 +254,13 @@ class ServicesPage(gtk.Notebook):
color = get_service_color(port['state']['state']) color = get_service_color(port['state']['state'])
if port['service'].has_key('name'): if 'name' in port['service']:
service_name = port['service']['name'] service_name = port['service']['name']
else: else:
service_name = _('<unknown>') service_name = _('<unknown>')
if port['service'].has_key('method'): if 'method' in port['service']:
service_method = port['service']['method'] service_method = port['service']['method']
else: else:
@@ -330,7 +328,7 @@ class ServicesPage(gtk.Notebook):
column = gtk.TreeViewColumn(PORTS_HEADER[i], column = gtk.TreeViewColumn(PORTS_HEADER[i],
self.__cell, self.__cell,
text = i) text=i)
self.__ports_column.append(column) self.__ports_column.append(column)
@@ -338,9 +336,9 @@ class ServicesPage(gtk.Notebook):
self.__ports_column[i].set_resizable(True) self.__ports_column[i].set_resizable(True)
self.__ports_column[i].set_sort_column_id(i) self.__ports_column[i].set_sort_column_id(i)
self.__ports_column[i].set_attributes(self.__cell, self.__ports_column[i].set_attributes(self.__cell,
text = i, text=i,
background = 5, background=5,
editable = 6) editable=6)
self.__ports_treeview.append_column(self.__ports_column[i]) self.__ports_treeview.append_column(self.__ports_column[i])
@@ -364,12 +362,9 @@ class ServicesPage(gtk.Notebook):
color = get_service_color(xports['state']) color = get_service_color(xports['state'])
number_of_xports += xports['count'] number_of_xports += xports['count']
reference = self.__xports_store.append(None, reference = self.__xports_store.append(
[xports['count'], None, [xports['count'], xports['state'],
xports['state'], ", ".join(xports['reason']), color, True])
", ".join(xports['reason']),
color,
True])
for xreason in xports['all_reason']: for xreason in xports['all_reason']:
self.__xports_store.append(reference, self.__xports_store.append(reference,
@@ -385,7 +380,7 @@ class ServicesPage(gtk.Notebook):
column = gtk.TreeViewColumn(EXTRAPORTS_HEADER[i], column = gtk.TreeViewColumn(EXTRAPORTS_HEADER[i],
self.__cell, self.__cell,
text = i) text=i)
self.__xports_column.append(column) self.__xports_column.append(column)
@@ -393,9 +388,9 @@ class ServicesPage(gtk.Notebook):
self.__xports_column[i].set_resizable(True) self.__xports_column[i].set_resizable(True)
self.__xports_column[i].set_sort_column_id(i) self.__xports_column[i].set_sort_column_id(i)
self.__xports_column[i].set_attributes(self.__cell, self.__xports_column[i].set_attributes(self.__cell,
text = i, text=i,
background = 3, background=3,
editable = 4) editable=4)
self.__xports_treeview.append_column(self.__xports_column[i]) self.__xports_treeview.append_column(self.__xports_column[i])
@@ -411,7 +406,6 @@ class ServicesPage(gtk.Notebook):
if len(self.__text) > 0: if len(self.__text) > 0:
self.__select_combobox.set_active(0) self.__select_combobox.set_active(0)
def __change_text_value(self, widget): def __change_text_value(self, widget):
""" """
""" """
@@ -433,7 +427,6 @@ class SystemPage(BWScrolledWindow):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -516,7 +509,8 @@ class SystemPage(BWScrolledWindow):
sequences = self.__node.get_info('sequences') sequences = self.__node.get_info('sequences')
if len(sequences) > 0: if len(sequences) > 0:
self.__sequences_frame.bw_add(self.__create_sequences_widget(sequences)) self.__sequences_frame.bw_add(
self.__create_sequences_widget(sequences))
# operating system information widgets # operating system information widgets
self.__os = gtk.Notebook() self.__os = gtk.Notebook()
@@ -525,7 +519,7 @@ class SystemPage(BWScrolledWindow):
if os != None: if os != None:
if os.has_key('matches'): if 'matches' in os:
self.__match_scroll = BWScrolledWindow() self.__match_scroll = BWScrolledWindow()
@@ -550,15 +544,15 @@ class SystemPage(BWScrolledWindow):
column = gtk.TreeViewColumn(OSMATCH_HEADER[i], column = gtk.TreeViewColumn(OSMATCH_HEADER[i],
self.__cell, self.__cell,
text = i) text=i)
self.__match_column.append(column) self.__match_column.append(column)
self.__match_column[i].set_reorderable(True) self.__match_column[i].set_reorderable(True)
self.__match_column[i].set_resizable(True) self.__match_column[i].set_resizable(True)
self.__match_column[i].set_attributes(self.__cell, self.__match_column[i].set_attributes(self.__cell,
text = i, text=i,
editable = 3) editable=3)
self.__match_column[i].set_sort_column_id(i) self.__match_column[i].set_sort_column_id(i)
self.__match_treeview.append_column(self.__match_column[i]) self.__match_treeview.append_column(self.__match_column[i])
@@ -567,7 +561,7 @@ class SystemPage(BWScrolledWindow):
self.__os.append_page(self.__match_scroll, BWLabel(_('Match'))) self.__os.append_page(self.__match_scroll, BWLabel(_('Match')))
if os.has_key('classes'): if 'classes' in os:
self.__class_scroll = BWScrolledWindow() self.__class_scroll = BWScrolledWindow()
@@ -584,7 +578,7 @@ class SystemPage(BWScrolledWindow):
os_gen = '' os_gen = ''
if os_class.has_key('os_gen'): if 'os_gen' in os_class:
os_gen = os_class['os_gen'] os_gen = os_class['os_gen']
self.__class_store.append([os_class['accuracy'], self.__class_store.append([os_class['accuracy'],
@@ -600,15 +594,15 @@ class SystemPage(BWScrolledWindow):
column = gtk.TreeViewColumn(OSCLASS_HEADER[i], column = gtk.TreeViewColumn(OSCLASS_HEADER[i],
self.__cell, self.__cell,
text = i) text=i)
self.__class_column.append(column) self.__class_column.append(column)
self.__class_column[i].set_reorderable(True) self.__class_column[i].set_reorderable(True)
self.__class_column[i].set_resizable(True) self.__class_column[i].set_resizable(True)
self.__class_column[i].set_attributes(self.__cell, self.__class_column[i].set_attributes(self.__cell,
text = i, text=i,
editable = 5) editable=5)
self.__class_column[i].set_sort_column_id(i) self.__class_column[i].set_sort_column_id(i)
self.__class_treeview.append_column(self.__class_column[i]) self.__class_treeview.append_column(self.__class_column[i])
@@ -630,7 +624,7 @@ class SystemPage(BWScrolledWindow):
self.__fp_vbox = BWVBox() self.__fp_vbox = BWVBox()
if os.has_key('used_ports'): if 'used_ports' in os:
used_ports = os['used_ports'] used_ports = os['used_ports']
@@ -692,7 +686,8 @@ class SystemPage(BWScrolledWindow):
tcp_note.set_selectable(True) tcp_note.set_selectable(True)
tcp_note.set_line_wrap(False) tcp_note.set_line_wrap(False)
tcp_note.set_alignment(1.0, 0.5) tcp_note.set_alignment(1.0, 0.5)
tcp_note.set_markup(TCP_SEQ_NOTE % (tcp['index'], tcp['difficulty'])) tcp_note.set_markup(
TCP_SEQ_NOTE % (tcp['index'], tcp['difficulty']))
table.attach(tcp_note, 0, 3, 4, 5) table.attach(tcp_note, 0, 3, 4, 5)
@@ -733,8 +728,6 @@ class SystemPage(BWScrolledWindow):
return table return table
class TraceroutePage(BWVBox): class TraceroutePage(BWVBox):
""" """
""" """
@@ -748,7 +741,6 @@ class TraceroutePage(BWVBox):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -805,23 +797,22 @@ class TraceroutePage(BWVBox):
HOP_COLOR['unknown'], HOP_COLOR['unknown'],
True]) True])
self.__trace_column = list() self.__trace_column = list()
for i in range(len(TRACE_HEADER)): for i in range(len(TRACE_HEADER)):
column = gtk.TreeViewColumn(TRACE_HEADER[i], column = gtk.TreeViewColumn(TRACE_HEADER[i],
self.__cell, self.__cell,
text = i) text=i)
self.__trace_column.append(column) self.__trace_column.append(column)
self.__trace_column[i].set_reorderable(True) self.__trace_column[i].set_reorderable(True)
self.__trace_column[i].set_resizable(True) self.__trace_column[i].set_resizable(True)
self.__trace_column[i].set_attributes(self.__cell, self.__trace_column[i].set_attributes(self.__cell,
text = i, text=i,
background = 4, background=4,
editable = 5) editable=5)
self.__trace_treeview.append_column(self.__trace_column[i]) self.__trace_treeview.append_column(self.__trace_column[i])

View File

@@ -151,7 +151,6 @@ class NodeWindow(BWWindow):
self.__icon = Application() self.__icon = Application()
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -168,7 +167,8 @@ class NodeWindow(BWWindow):
self.__color_image.set_from_file(self.__icon.get_icon('border')) self.__color_image.set_from_file(self.__icon.get_icon('border'))
self.__color_box.add(self.__color_image) self.__color_box.add(self.__color_image)
self.__color_box.set_size_request(15, 15) self.__color_box.set_size_request(15, 15)
r, g, b = drawing.cairo_to_gdk_color(self.__node.get_draw_info('color')) r, g, b = drawing.cairo_to_gdk_color(
self.__node.get_draw_info('color'))
self.__color_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(r, g, b)) self.__color_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(r, g, b))
# title with the node ip and hostname # title with the node ip and hostname

File diff suppressed because it is too large Load Diff

View File

@@ -133,8 +133,8 @@ TYPES = ((_("By extension"), None, None),
(_("PNG"), RadialNet.FILE_TYPE_PNG, ".png"), (_("PNG"), RadialNet.FILE_TYPE_PNG, ".png"),
(_("PostScript"), RadialNet.FILE_TYPE_PS, ".ps"), (_("PostScript"), RadialNet.FILE_TYPE_PS, ".ps"),
(_("SVG"), RadialNet.FILE_TYPE_SVG, ".svg")) (_("SVG"), RadialNet.FILE_TYPE_SVG, ".svg"))
# Build a reverse index of extensions to file types, for the "By extension" file # Build a reverse index of extensions to file types, for the "By extension"
# type. # file type.
EXTENSIONS = {} EXTENSIONS = {}
for type in TYPES: for type in TYPES:
if type[2] is not None: if type[2] is not None:
@@ -181,7 +181,8 @@ class SaveDialog(zenmapGUI.FileChoosers.UnicodeFileChooserDialog):
self.set_current_folder(dir) self.set_current_folder(dir)
# Find the recommended extension. # Find the recommended extension.
new_ext = self.__combo.get_model().get_value(self.__combo.get_active_iter(), 2) new_ext = self.__combo.get_model().get_value(
self.__combo.get_active_iter(), 2)
if new_ext is not None: if new_ext is not None:
# Change the filename to use the recommended extension. # Change the filename to use the recommended extension.
root, ext = os.path.splitext(basename) root, ext = os.path.splitext(basename)
@@ -197,15 +198,17 @@ class SaveDialog(zenmapGUI.FileChoosers.UnicodeFileChooserDialog):
if ext == "": if ext == "":
filename = self.get_filename() or "" filename = self.get_filename() or ""
dir, basename = os.path.split(filename) dir, basename = os.path.split(filename)
alert = HIGAlertDialog(message_format=_("No filename extension"), alert = HIGAlertDialog(
secondary_text=_("""\ message_format=_("No filename extension"),
The filename "%s" does not have an extension, and no specific file type was chosen. secondary_text=_("""\
Enter a known extension or select the file type from the list.\ The filename "%s" does not have an extension, \
""" % basename)) and no specific file type was chosen.
Enter a known extension or select the file type from the list.""" % basename))
else: else:
alert = HIGAlertDialog(message_format=_("Unknown filename extension"), alert = HIGAlertDialog(
secondary_text=_("""\ message_format=_("Unknown filename extension"),
secondary_text=_("""\
There is no file type known for the filename extension "%s". There is no file type known for the filename extension "%s".
Enter a known extension or select the file type from the list.\ Enter a known extension or select the file type from the list.\
""") % self.__get_extension()) """) % self.__get_extension())
@@ -218,7 +221,8 @@ Enter a known extension or select the file type from the list.\
return os.path.splitext(self.get_filename())[1] return os.path.splitext(self.get_filename())[1]
def get_filetype(self): def get_filetype(self):
filetype = self.__combo.get_model().get_value(self.__combo.get_active_iter(), 1) filetype = self.__combo.get_model().get_value(
self.__combo.get_active_iter(), 1)
if filetype is None: if filetype is None:
# Guess based on extension. # Guess based on extension.
return EXTENSIONS.get(self.__get_extension()) return EXTENSIONS.get(self.__get_extension())

View File

@@ -136,7 +136,6 @@ HIDE = False
REFRESH_RATE = 500 REFRESH_RATE = 500
class ToolsMenu(gtk.Menu): class ToolsMenu(gtk.Menu):
""" """
""" """
@@ -149,7 +148,6 @@ class ToolsMenu(gtk.Menu):
self.__create_items() self.__create_items()
def __create_items(self): def __create_items(self):
""" """
""" """
@@ -163,7 +161,6 @@ class ToolsMenu(gtk.Menu):
self.__hosts.show_all() self.__hosts.show_all()
def __hosts_viewer_callback(self, widget): def __hosts_viewer_callback(self, widget):
""" """
""" """
@@ -171,20 +168,17 @@ class ToolsMenu(gtk.Menu):
window.show_all() window.show_all()
window.set_keep_above(True) window.set_keep_above(True)
def enable_dependents(self): def enable_dependents(self):
""" """
""" """
self.__hosts.set_sensitive(True) self.__hosts.set_sensitive(True)
def disable_dependents(self): def disable_dependents(self):
""" """
""" """
self.__hosts.set_sensitive(False) self.__hosts.set_sensitive(False)
class Toolbar(gtk.HBox): class Toolbar(gtk.HBox):
""" """
""" """
@@ -213,7 +207,6 @@ class Toolbar(gtk.HBox):
self.__create_widgets() self.__create_widgets()
def __create_widgets(self): def __create_widgets(self):
""" """
""" """
@@ -233,7 +226,8 @@ class Toolbar(gtk.HBox):
self.__hosts_button = BWStockButton(gtk.STOCK_INDEX, _("Hosts Viewer")) self.__hosts_button = BWStockButton(gtk.STOCK_INDEX, _("Hosts Viewer"))
self.__hosts_button.connect("clicked", self.__hosts_viewer_callback) self.__hosts_button.connect("clicked", self.__hosts_viewer_callback)
self.__control = BWToggleStockButton(gtk.STOCK_PROPERTIES, _("Controls")) self.__control = BWToggleStockButton(
gtk.STOCK_PROPERTIES, _("Controls"))
self.__control.connect('clicked', self.__control_callback) self.__control.connect('clicked', self.__control_callback)
self.__control.set_active(False) self.__control.set_active(False)
@@ -273,7 +267,6 @@ class Toolbar(gtk.HBox):
self.pack_start(self.__control, False) self.pack_start(self.__control, False)
self.pack_end(self.__save_button, False) self.pack_end(self.__save_button, False)
def disable_controls(self): def disable_controls(self):
""" """
""" """
@@ -282,7 +275,6 @@ class Toolbar(gtk.HBox):
self.__hosts_button.set_sensitive(False) self.__hosts_button.set_sensitive(False)
#self.__tools_menu.disable_dependents() #self.__tools_menu.disable_dependents()
def enable_controls(self): def enable_controls(self):
""" """
""" """
@@ -291,13 +283,11 @@ class Toolbar(gtk.HBox):
self.__hosts_button.set_sensitive(True) self.__hosts_button.set_sensitive(True)
#self.__tools_menu.enable_dependents() #self.__tools_menu.enable_dependents()
def __tools_callback(self, widget): def __tools_callback(self, widget):
""" """
""" """
self.__tools_menu.popup(None, None, None, 1, 0) self.__tools_menu.popup(None, None, None, 1, 0)
def __hosts_viewer_callback(self, widget): def __hosts_viewer_callback(self, widget):
""" """
""" """
@@ -305,7 +295,6 @@ class Toolbar(gtk.HBox):
window.show_all() window.show_all()
window.set_keep_above(True) window.set_keep_above(True)
def __save_image_callback(self, widget): def __save_image_callback(self, widget):
""" """
""" """
@@ -330,7 +319,6 @@ class Toolbar(gtk.HBox):
self.__save_chooser.hide() self.__save_chooser.hide()
def __control_callback(self, widget=None): def __control_callback(self, widget=None):
""" """
""" """
@@ -340,7 +328,6 @@ class Toolbar(gtk.HBox):
else: else:
self.__control_widget.hide() self.__control_widget.hide()
def __fisheye_callback(self, widget=None): def __fisheye_callback(self, widget=None):
""" """
""" """
@@ -356,14 +343,12 @@ class Toolbar(gtk.HBox):
self.__fisheye_widget.deactive_fisheye() self.__fisheye_widget.deactive_fisheye()
self.__fisheye_widget.hide() self.__fisheye_widget.hide()
def __about_callback(self, widget): def __about_callback(self, widget):
""" """
""" """
self.__about_dialog = AboutDialog() self.__about_dialog = AboutDialog()
self.__about_dialog.show_all() self.__about_dialog.show_all()
def __fullscreen_callback(self, widget=None): def __fullscreen_callback(self, widget=None):
""" """
""" """
@@ -372,4 +357,3 @@ class Toolbar(gtk.HBox):
else: else:
self.__window.unfullscreen() self.__window.unfullscreen()

View File

@@ -118,4 +118,3 @@
# * Nmap, and also available from https://svn.nmap.org/nmap/COPYING * # * Nmap, and also available from https://svn.nmap.org/nmap/COPYING *
# * * # * *
# ***************************************************************************/ # ***************************************************************************/

View File

@@ -118,4 +118,3 @@
# * Nmap, and also available from https://svn.nmap.org/nmap/COPYING * # * Nmap, and also available from https://svn.nmap.org/nmap/COPYING *
# * * # * *
# ***************************************************************************/ # ***************************************************************************/

View File

@@ -141,7 +141,7 @@ def is_in_circle(point, radius=1, center=(0, 0)):
x, y = point x, y = point
a, b = center a, b = center
if ((x - a)**2 + (y - b)**2) <= (radius**2): if ((x - a) ** 2 + (y - b) ** 2) <= (radius ** 2):
return True return True
return False return False

View File

@@ -135,16 +135,17 @@ BASE_RADIUS = 5.5
NONE_RADIUS = 4.5 NONE_RADIUS = 4.5
def set_node_info(node, host): def set_node_info(node, host):
""" """
""" """
node.set_host(host) node.set_host(host)
radius = BASE_RADIUS + 2 * math.log(node.get_info("number_of_open_ports") + 1) radius = BASE_RADIUS + 2 * math.log(
node.get_info("number_of_open_ports") + 1)
node.set_draw_info({"color": COLORS[node.get_info("vulnerability_score")],
"radius": radius})
node.set_draw_info({"color":COLORS[node.get_info("vulnerability_score")],
"radius":radius})
class TracerouteHostInfo(object): class TracerouteHostInfo(object):
"""This is a minimal implementation of HostInfo, sufficient to """This is a minimal implementation of HostInfo, sufficient to
@@ -164,15 +165,18 @@ class TracerouteHostInfo(object):
def get_best_osmatch(self): def get_best_osmatch(self):
if not self.osmatches: if not self.osmatches:
return None return None
def osmatch_key(osmatch): def osmatch_key(osmatch):
try: try:
return -float(osmatch["accuracy"]) return -float(osmatch["accuracy"])
except ValueError: except ValueError:
return 0 return 0
return sorted(self.osmatches, key = osmatch_key)[0]
return sorted(self.osmatches, key=osmatch_key)[0]
hostnames = property(lambda self: self.hostname and [self.hostname] or []) hostnames = property(lambda self: self.hostname and [self.hostname] or [])
def make_graph_from_hosts(hosts): def make_graph_from_hosts(hosts):
#hosts = parser.get_root().search_children('host', deep=True) #hosts = parser.get_root().search_children('host', deep=True)
graph = Graph() graph = Graph()
@@ -187,7 +191,8 @@ def make_graph_from_hosts(hosts):
localhost.ip = {"addr": "127.0.0.1/8", "type": "ipv4"} localhost.ip = {"addr": "127.0.0.1/8", "type": "ipv4"}
localhost.hostname = "localhost" localhost.hostname = "localhost"
main_node.set_host(localhost) main_node.set_host(localhost)
main_node.set_draw_info({"valid": True, "color":(0,0,0), "radius":NONE_RADIUS}) main_node.set_draw_info(
{"valid": True, "color": (0, 0, 0), "radius": NONE_RADIUS})
#Save endpoints for attaching scanned hosts to #Save endpoints for attaching scanned hosts to
endpoints = {} endpoints = {}
@@ -219,10 +224,14 @@ def make_graph_from_hosts(hosts):
nodes.append(node) nodes.append(node)
hop_host = TracerouteHostInfo() hop_host = TracerouteHostInfo()
hop_host.ip = {"addr": hop["ipaddr"], "type": "", "vendor": ""} hop_host.ip = {
node.set_draw_info({"valid":True}) "addr": hop["ipaddr"],
node.set_draw_info({"color":(1,1,1), "type": "",
"radius":NONE_RADIUS}) "vendor": ""
}
node.set_draw_info({"valid": True})
node.set_draw_info({"color": (1, 1, 1),
"radius": NONE_RADIUS})
if hop["host"] != "": if hop["host"] != "":
hop_host.hostname = hop["host"] hop_host.hostname = hop["host"]
@@ -240,8 +249,9 @@ def make_graph_from_hosts(hosts):
node = NetNode() node = NetNode()
nodes.append(node) nodes.append(node)
node.set_draw_info({"valid":False}) node.set_draw_info({"valid": False})
node.set_draw_info({"color":(1,1,1), "radius":NONE_RADIUS}) node.set_draw_info(
{"color": (1, 1, 1), "radius": NONE_RADIUS})
graph.set_connection(node, prev_node) graph.set_connection(node, prev_node)
@@ -259,12 +269,12 @@ def make_graph_from_hosts(hosts):
node = NetNode() node = NetNode()
nodes.append(node) nodes.append(node)
node.set_draw_info({"no_route":True}) node.set_draw_info({"no_route": True})
graph.set_connection(node, endpoints[host]) graph.set_connection(node, endpoints[host])
node.set_draw_info({"valid":True}) node.set_draw_info({"valid": True})
node.set_draw_info({"scanned":True}) node.set_draw_info({"scanned": True})
set_node_info(node, host) set_node_info(node, host)
node_cache[node.get_info("ip")] = node node_cache[node.get_info("ip")] = node

View File

@@ -124,7 +124,6 @@ from radialnet.util.geometry import *
import math import math
def ipv4_compare(ip1, ip2): def ipv4_compare(ip1, ip2):
""" """
""" """
@@ -174,5 +173,7 @@ def sort_children_by_angle(children):
""" """
vector = list(children) vector = list(children)
vector.sort(key = lambda c: normalize_angle(c.get_draw_info('angle_from_father'))) vector.sort(
key=lambda c: normalize_angle(
c.get_draw_info('angle_from_father')))
return vector return vector

View File

@@ -135,7 +135,8 @@ from glob import glob
from stat import * from stat import *
from zenmapCore.Version import VERSION from zenmapCore.Version import VERSION
from zenmapCore.Name import APP_NAME, APP_DISPLAY_NAME, APP_WEB_SITE, APP_DOWNLOAD_SITE, NMAP_DISPLAY_NAME from zenmapCore.Name import APP_NAME, APP_DISPLAY_NAME, APP_WEB_SITE,\
APP_DOWNLOAD_SITE, NMAP_DISPLAY_NAME
# The name of the file used to record the list of installed files, so that the # The name of the file used to record the list of installed files, so that the
# uninstall command can remove them. # uninstall command can remove them.
@@ -154,6 +155,7 @@ misc_dir = os.path.join(data_dir, 'misc')
# Where to install .desktop files. # Where to install .desktop files.
desktop_dir = os.path.join('share', 'applications') desktop_dir = os.path.join('share', 'applications')
def mo_find(result, dirname, fnames): def mo_find(result, dirname, fnames):
files = [] files = []
for f in fnames: for f in fnames:
@@ -164,29 +166,31 @@ def mo_find(result, dirname, fnames):
if files: if files:
result.append((dirname, files)) result.append((dirname, files))
################################################################################ ###############################################################################
# Installation variables # Installation variables
data_files = [ (pixmaps_dir, glob(os.path.join(pixmaps_dir, '*.gif')) + data_files = [
glob(os.path.join(pixmaps_dir, '*.png'))), (pixmaps_dir, glob(os.path.join(pixmaps_dir, '*.gif')) +
glob(os.path.join(pixmaps_dir, '*.png'))),
(os.path.join(pixmaps_dir, "radialnet"), (os.path.join(pixmaps_dir, "radialnet"),
glob(os.path.join(pixmaps_dir, "radialnet", '*.png'))), glob(os.path.join(pixmaps_dir, "radialnet", '*.png'))),
(config_dir, [os.path.join(config_dir, APP_NAME + '.conf')] + (config_dir, [os.path.join(config_dir, APP_NAME + '.conf'),
[os.path.join(config_dir, 'scan_profile.usp')] + os.path.join(config_dir, 'scan_profile.usp'),
[os.path.join(config_dir, APP_NAME + '_version')]), os.path.join(config_dir, APP_NAME + '_version')]),
(misc_dir, glob(os.path.join(misc_dir, '*.xml'))), (misc_dir, glob(os.path.join(misc_dir, '*.xml'))),
(docs_dir, [os.path.join(docs_dir, 'help.html')])] (docs_dir, [os.path.join(docs_dir, 'help.html')])
]
# Add i18n files to data_files list # Add i18n files to data_files list
os.path.walk(locale_dir, mo_find, data_files) os.path.walk(locale_dir, mo_find, data_files)
# path_startswith and path_strip_prefix are used to deal with the installation # path_startswith and path_strip_prefix are used to deal with the installation
# root (--root option, also known as DESTDIR). # root (--root option, also known as DESTDIR).
def path_startswith(path, prefix): def path_startswith(path, prefix):
"""Returns True if path starts with prefix. It's a little more intelligent """Returns True if path starts with prefix. It's a little more intelligent
than str.startswith because it normalizes the paths to remove multiple than str.startswith because it normalizes the paths to remove multiple
@@ -195,10 +199,11 @@ def path_startswith(path, prefix):
prefix = os.path.normpath(prefix) prefix = os.path.normpath(prefix)
return path.startswith(prefix) return path.startswith(prefix)
def path_strip_prefix(path, prefix): def path_strip_prefix(path, prefix):
"""Return path stripped of its directory prefix if it starts with prefix, """Return path stripped of its directory prefix if it starts with prefix,
otherwise return path unmodified. This only works correctly with Unix paths; otherwise return path unmodified. This only works correctly with Unix
for example it will not replace the drive letter on a Windows path. paths; for example it will not replace the drive letter on a Windows path.
Examples: Examples:
>>> path_strip_prefix('/tmp/destdir/usr/bin', '/tmp/destdir') >>> path_strip_prefix('/tmp/destdir/usr/bin', '/tmp/destdir')
'/usr/bin' '/usr/bin'
@@ -221,14 +226,16 @@ def path_strip_prefix(path, prefix):
assert os.path.isabs(path) == absolute assert os.path.isabs(path) == absolute
return path return path
################################################################################ ###############################################################################
# Distutils subclasses # Distutils subclasses
class my_install(install): class my_install(install):
def finalize_options(self): def finalize_options(self):
# Ubuntu's python2.6-2.6.4-0ubuntu3 package changes sys.prefix in # Ubuntu's python2.6-2.6.4-0ubuntu3 package changes sys.prefix in
# install.finalize_options when sys.prefix is "/usr/local" (our # install.finalize_options when sys.prefix is "/usr/local" (our
# default). Because we need the unchanged value later, remember it here. # default). Because we need the unchanged value later, remember it
# here.
self.saved_prefix = self.prefix self.saved_prefix = self.prefix
install.finalize_options(self) install.finalize_options(self)
@@ -252,14 +259,17 @@ class my_install(install):
# Recursively include all the directories in data_dir (share/zenmap). # Recursively include all the directories in data_dir (share/zenmap).
# This is mainly for convenience in listing locale directories. # This is mainly for convenience in listing locale directories.
installed_files.append(os.path.join(self.install_data, data_dir)) installed_files.append(os.path.join(self.install_data, data_dir))
for dirpath, dirs, files in os.walk(os.path.join(self.install_data, data_dir)): for dirpath, dirs, files in os.walk(
os.path.join(self.install_data, data_dir)):
for dir in dirs: for dir in dirs:
installed_files.append(os.path.join(dirpath, dir)) installed_files.append(os.path.join(dirpath, dir))
installed_files.append(os.path.join(self.install_scripts, "uninstall_" + APP_NAME)) installed_files.append(
os.path.join(self.install_scripts, "uninstall_" + APP_NAME))
return installed_files return installed_files
def create_uninstaller(self): def create_uninstaller(self):
uninstaller_filename = os.path.join(self.install_scripts, "uninstall_" + APP_NAME) uninstaller_filename = os.path.join(
self.install_scripts, "uninstall_" + APP_NAME)
uninstaller = """\ uninstaller = """\
#!/usr/bin/env python #!/usr/bin/env python
@@ -267,26 +277,28 @@ import errno, os, os.path, sys
print 'Uninstall %(name)s %(version)s' print 'Uninstall %(name)s %(version)s'
answer = raw_input('Are you sure that you want to uninstall %(name)s %(version)s? (yes/no) ') answer = raw_input('Are you sure that you want to uninstall '
'%(name)s %(version)s? (yes/no) ')
if answer != 'yes' and answer != 'y': if answer != 'yes' and answer != 'y':
print 'Not uninstalling.' print 'Not uninstalling.'
sys.exit(0) sys.exit(0)
""" % {'name':APP_DISPLAY_NAME, 'version':VERSION} """ % {'name': APP_DISPLAY_NAME, 'version': VERSION}
installed_files = [] installed_files = []
for output in self.get_installed_files(): for output in self.get_installed_files():
if self.root is not None: if self.root is not None:
# If we have a root (DESTDIR), we need to strip it off the front # If we have a root (DESTDIR), we need to strip it off the
# of paths so the uninstaller runs on the target host. The path # front of paths so the uninstaller runs on the target host.
# manipulations are tricky, but made easier because the # The path manipulations are tricky, but made easier because
# uninstaller only has to run on Unix. # the uninstaller only has to run on Unix.
if not path_startswith(output, self.root): if not path_startswith(output, self.root):
# This should never happen (everything gets installed inside # This should never happen (everything gets installed
# the root), but if it does, be safe and don't delete # inside the root), but if it does, be safe and don't
# anything. # 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 continue
output = path_strip_prefix(output, self.root) output = path_strip_prefix(output, self.root)
assert os.path.isabs(output) assert os.path.isabs(output)
@@ -356,7 +368,8 @@ for dir in dirs:
lines[i] = "INSTALL_LIB = %s\n" % repr(modules_dir) lines[i] = "INSTALL_LIB = %s\n" % repr(modules_dir)
break break
else: else:
raise ValueError("INSTALL_LIB replacement not found in %s" % app_file_name) raise ValueError(
"INSTALL_LIB replacement not found in %s" % app_file_name)
app_file = open(app_file_name, "w") app_file = open(app_file_name, "w")
app_file.writelines(lines) app_file.writelines(lines)
@@ -380,16 +393,17 @@ for dir in dirs:
S_IRGRP | \ S_IRGRP | \
S_IROTH) S_IROTH)
def fix_paths(self): def fix_paths(self):
"""Replace some hardcoded paths to match where files were installed.""" """Replace some hardcoded paths to match where files were installed."""
interesting_paths = {"CONFIG_DIR": os.path.join(self.saved_prefix, config_dir), interesting_paths = {
"DOCS_DIR": os.path.join(self.saved_prefix, docs_dir), "CONFIG_DIR": os.path.join(self.saved_prefix, config_dir),
"LOCALE_DIR": os.path.join(self.saved_prefix, locale_dir), "DOCS_DIR": os.path.join(self.saved_prefix, docs_dir),
"MISC_DIR": os.path.join(self.saved_prefix, misc_dir), "LOCALE_DIR": os.path.join(self.saved_prefix, locale_dir),
"PIXMAPS_DIR": os.path.join(self.saved_prefix, pixmaps_dir), "MISC_DIR": os.path.join(self.saved_prefix, misc_dir),
# See $(nmapdatadir) in nmap/Makefile.in. "PIXMAPS_DIR": os.path.join(self.saved_prefix, pixmaps_dir),
"NMAPDATADIR": os.path.join(self.saved_prefix, "share", "nmap"),} # See $(nmapdatadir) in nmap/Makefile.in.
"NMAPDATADIR": os.path.join(self.saved_prefix, "share", "nmap")
}
# Find and read the Paths.py file. # Find and read the Paths.py file.
pcontent = "" pcontent = ""
@@ -417,8 +431,10 @@ for dir in dirs:
# Rewrite the zenmap.desktop and zenmap-root.desktop files to point to # Rewrite the zenmap.desktop and zenmap-root.desktop files to point to
# the installed locations of the su-to-zenmap.sh script and application # the installed locations of the su-to-zenmap.sh script and application
# icon. # icon.
su_filename = os.path.join(self.saved_prefix, data_dir, "su-to-zenmap.sh") su_filename = os.path.join(
icon_filename = os.path.join(self.saved_prefix, pixmaps_dir, "zenmap.png") self.saved_prefix, data_dir, "su-to-zenmap.sh")
icon_filename = os.path.join(
self.saved_prefix, pixmaps_dir, "zenmap.png")
desktop_filename = None desktop_filename = None
root_desktop_filename = None root_desktop_filename = None
@@ -442,7 +458,9 @@ for dir in dirs:
df = open(root_desktop_filename, "r") df = open(root_desktop_filename, "r")
dcontent = df.read() dcontent = df.read()
df.close() df.close()
regex = re.compile("^((?:Exec|TryExec) *= *).*su-to-zenmap.sh(.*)$", re.MULTILINE) regex = re.compile(
"^((?:Exec|TryExec) *= *).*su-to-zenmap.sh(.*)$",
re.MULTILINE)
dcontent = regex.sub("\\1%s\\2" % su_filename, dcontent) dcontent = regex.sub("\\1%s\\2" % su_filename, dcontent)
regex = re.compile("^(Icon *= *).*$", re.MULTILINE) regex = re.compile("^(Icon *= *).*$", re.MULTILINE)
dcontent = regex.sub("\\1%s" % icon_filename, dcontent) dcontent = regex.sub("\\1%s" % icon_filename, dcontent)
@@ -456,7 +474,8 @@ for dir in dirs:
doesn't strip off the installation root, if any. File names containing doesn't strip off the installation root, if any. File names containing
newline characters are not handled.""" newline characters are not handled."""
if INSTALLED_FILES_NAME == self.record: if INSTALLED_FILES_NAME == self.record:
distutils.log.warn("warning: installation record is overwriting --record file '%s'." % self.record) distutils.log.warn("warning: installation record is overwriting "
"--record file '%s'." % self.record)
f = open(INSTALLED_FILES_NAME, "w") f = open(INSTALLED_FILES_NAME, "w")
try: try:
for output in self.get_installed_files(): for output in self.get_installed_files():
@@ -465,12 +484,14 @@ for dir in dirs:
finally: finally:
f.close() f.close()
class my_uninstall(Command): class my_uninstall(Command):
"""A distutils command that performs uninstallation. It reads the list of """A distutils command that performs uninstallation. It reads the list of
installed files written by the install command.""" installed files written by the install command."""
command_name = "uninstall" command_name = "uninstall"
description = "uninstall installed files recorded in '%s'" % INSTALLED_FILES_NAME description = "uninstall installed files recorded in '%s'" % (
INSTALLED_FILES_NAME)
user_options = [] user_options = []
def initialize_options(self): def initialize_options(self):
@@ -485,7 +506,8 @@ class my_uninstall(Command):
f = open(INSTALLED_FILES_NAME, "r") f = open(INSTALLED_FILES_NAME, "r")
except IOError, e: except IOError, e:
if e.errno == errno.ENOENT: if e.errno == errno.ENOENT:
log.error("Couldn't open the installation record '%s'. Have you installed yet?" % INSTALLED_FILES_NAME) log.error("Couldn't open the installation record '%s'. "
"Have you installed yet?" % INSTALLED_FILES_NAME)
return return
installed_files = [file.rstrip("\n") for file in f.readlines()] installed_files = [file.rstrip("\n") for file in f.readlines()]
f.close() f.close()
@@ -510,7 +532,7 @@ class my_uninstall(Command):
# Delete the directories. First reverse-sort the normalized paths by # Delete the directories. First reverse-sort the normalized paths by
# length so that child directories are deleted before their parents. # length so that child directories are deleted before their parents.
dirs = [os.path.normpath(dir) for dir in dirs] dirs = [os.path.normpath(dir) for dir in dirs]
dirs.sort(key = len, reverse = True) dirs.sort(key=len, reverse=True)
for dir in dirs: for dir in dirs:
try: try:
log.info("Removing the directory '%s'." % dir) log.info("Removing the directory '%s'." % dir)
@@ -523,8 +545,8 @@ class my_uninstall(Command):
log.error(str(e)) log.error(str(e))
# setup can be called in different ways depending on what we're doing. (For # setup can be called in different ways depending on what we're doing. (For
# example py2exe needs special handling.) These arguments are common between all # example py2exe needs special handling.) These arguments are common between
# the operations. # all the operations.
COMMON_SETUP_ARGS = { COMMON_SETUP_ARGS = {
'name': APP_NAME, 'name': APP_NAME,
'license': 'Nmap License (http://nmap.org/book/man-legal.html)', 'license': 'Nmap License (http://nmap.org/book/man-legal.html)',
@@ -533,14 +555,14 @@ COMMON_SETUP_ARGS = {
'author': 'Nmap Project', 'author': 'Nmap Project',
'maintainer': 'Nmap Project', 'maintainer': 'Nmap Project',
'description': "%s frontend and results viewer" % NMAP_DISPLAY_NAME, 'description': "%s frontend and results viewer" % NMAP_DISPLAY_NAME,
'long_description': """\ 'long_description': "%s is an %s frontend that is really useful"
%s is an %s frontend \ "for advanced users and easy to be used by newbies." % (
that is really useful for advanced users and easy to be used by newbies.""" \ APP_DISPLAY_NAME, NMAP_DISPLAY_NAME),
% (APP_DISPLAY_NAME, NMAP_DISPLAY_NAME),
'version': VERSION, 'version': VERSION,
'scripts': [APP_NAME], 'scripts': [APP_NAME],
'packages': ['zenmapCore', 'zenmapGUI', 'zenmapGUI.higwidgets', 'packages': ['zenmapCore', 'zenmapGUI', 'zenmapGUI.higwidgets',
'radialnet', 'radialnet.bestwidgets', 'radialnet.core', 'radialnet.gui', 'radialnet.util'], 'radialnet', 'radialnet.bestwidgets', 'radialnet.core',
'radialnet.gui', 'radialnet.util'],
'data_files': data_files, 'data_files': data_files,
} }
@@ -555,17 +577,24 @@ if 'py2exe' in sys.argv:
WINDOWS_SETUP_ARGS = { WINDOWS_SETUP_ARGS = {
'zipfile': 'py2exe/library.zip', 'zipfile': 'py2exe/library.zip',
'name': APP_NAME, 'name': APP_NAME,
'windows': [{"script": APP_NAME, 'windows': [{
"icon_resources": [(1, "install_scripts/windows/nmap-eye.ico")]}], "script": APP_NAME,
"icon_resources": [(1, "install_scripts/windows/nmap-eye.ico")]
}],
# On Windows we build Ndiff here in Zenmap's setup.py so the two Python # On Windows we build Ndiff here in Zenmap's setup.py so the two Python
# programs will share a common runtime. # programs will share a common runtime.
'console': [{"script": "../ndiff/scripts/ndiff", "description": "Nmap scan comparison tool"}], 'console': [{
"script": "../ndiff/scripts/ndiff",
"description": "Nmap scan comparison tool"
}],
'options': {"py2exe": { 'options': {"py2exe": {
"compressed": 1, "compressed": 1,
"optimize": 2, "optimize": 2,
"packages": ["encodings"], "packages": ["encodings"],
"includes": ["pango", "atk", "gobject", "gio", "pickle", "bz2", "encodings", "encodings.*", "cairo", "pangocairo"], "includes": ["pango", "atk", "gobject", "gio", "pickle", "bz2",
"dll_excludes": ["USP10.dll", "NSI.dll", "MSIMG32.dll", "DNSAPI.dll"] "encodings", "encodings.*", "cairo", "pangocairo"],
"dll_excludes": ["USP10.dll", "NSI.dll", "MSIMG32.dll",
"DNSAPI.dll"]
} }
} }
} }

View File

@@ -127,7 +127,7 @@ import sys
# recursively checked, up to a limit of SYMLINK_LIMIT. # recursively checked, up to a limit of SYMLINK_LIMIT.
# https://www.securecoding.cert.org/confluence/display/seccode/FIO15-C.+Ensure+that+file+operations+are+performed+in+a+secure+directory # https://www.securecoding.cert.org/confluence/display/seccode/FIO15-C.+Ensure+that+file+operations+are+performed+in+a+secure+directory
SYMLINK_LIMIT = 5 SYMLINK_LIMIT = 5
def is_secure_dir(path, num_symlinks = 0): def is_secure_dir(path, num_symlinks=0):
import os import os
import os.path import os.path
import stat import stat

View File

@@ -126,6 +126,7 @@ import sys
from zenmapCore.Name import APP_NAME from zenmapCore.Name import APP_NAME
def fs_dec(s): def fs_dec(s):
"""Decode s from the filesystem decoding, handling various possible """Decode s from the filesystem decoding, handling various possible
errors.""" errors."""
@@ -134,6 +135,7 @@ def fs_dec(s):
enc = "UTF-8" enc = "UTF-8"
return s.decode(enc) return s.decode(enc)
def fs_enc(u): def fs_enc(u):
"""Encode u to the filesystem decoding, handling various possible """Encode u to the filesystem decoding, handling various possible
errors.""" errors."""
@@ -146,20 +148,20 @@ def fs_enc(u):
# home directory, because os.path.expanduser doesn't properly decode the raw # home directory, because os.path.expanduser doesn't properly decode the raw
# byte string from the file system encoding. You get a UnicodeDecodeError on # byte string from the file system encoding. You get a UnicodeDecodeError on
# systems like Windows where the file system encoding is different from the # systems like Windows where the file system encoding is different from the
# result of sys.getdefaultencoding(). So we call os.path.expanduser with a plain # result of sys.getdefaultencoding(). So we call os.path.expanduser with a
# string and decode it from the filesystem encoding. # plain string and decode it from the filesystem encoding.
HOME = fs_dec(os.path.expanduser("~")) HOME = fs_dec(os.path.expanduser("~"))
# The base_paths dict in this file gives symbolic names to various files. For # The base_paths dict in this file gives symbolic names to various files. For
# example, use base_paths.target_list instead of 'target_list.txt'. # example, use base_paths.target_list instead of 'target_list.txt'.
base_paths = dict(user_config_file = APP_NAME + '.conf', base_paths = dict(user_config_file=APP_NAME + '.conf',
user_config_dir = os.path.join(HOME, '.' + APP_NAME), user_config_dir=os.path.join(HOME, '.' + APP_NAME),
scan_profile = 'scan_profile.usp', scan_profile='scan_profile.usp',
profile_editor = 'profile_editor.xml', profile_editor='profile_editor.xml',
recent_scans = 'recent_scans.txt', recent_scans='recent_scans.txt',
target_list = 'target_list.txt', target_list='target_list.txt',
options = 'options.xml', options='options.xml',
user_home = HOME, user_home=HOME,
db = APP_NAME + ".db", db=APP_NAME + ".db",
version = APP_NAME + "_version") version=APP_NAME + "_version")

View File

@@ -136,9 +136,11 @@ import zenmapCore.Paths
# The [paths] configuration from zenmap.conf, used to get ndiff_command_path. # The [paths] configuration from zenmap.conf, used to get ndiff_command_path.
paths_config = PathsConfig() paths_config = PathsConfig()
class NdiffParseException(Exception): class NdiffParseException(Exception):
pass pass
def get_path(): def get_path():
"""Return a value for the PATH environment variable that is appropriate """Return a value for the PATH environment variable that is appropriate
for the current platform. It will be the PATH from the environment plus for the current platform. It will be the PATH from the environment plus
@@ -153,8 +155,9 @@ def get_path():
search_paths.append(path) search_paths.append(path)
return os.pathsep.join(search_paths) return os.pathsep.join(search_paths)
class NdiffCommand(subprocess.Popen): class NdiffCommand(subprocess.Popen):
def __init__(self, filename_a, filename_b, temporary_filenames = []): def __init__(self, filename_a, filename_b, temporary_filenames=[]):
self.temporary_filenames = temporary_filenames self.temporary_filenames = temporary_filenames
search_paths = get_path() search_paths = get_path()
@@ -162,20 +165,38 @@ class NdiffCommand(subprocess.Popen):
env["PATH"] = search_paths env["PATH"] = search_paths
if getattr(sys, "frozen", None) == "macosx_app": if getattr(sys, "frozen", None) == "macosx_app":
# These variables are set by py2app, but they can interfere with # These variables are set by py2app, but they can interfere with
# Ndiff because Ndiff is also a Python application. Without removing # Ndiff because Ndiff is also a Python application. Without
# these, Ndiff will attempt to run using the py2app-bundled Python # removing these, Ndiff will attempt to run using the
# library, and may run into version or architecture mismatches. # py2app-bundled Python library, and may run into version or
if env.has_key("PYTHONPATH"): # architecture mismatches.
if "PYTHONPATH" in env:
del env["PYTHONPATH"] del env["PYTHONPATH"]
if env.has_key("PYTHONHOME"): if "PYTHONHOME" in env:
del env["PYTHONHOME"] del env["PYTHONHOME"]
command_list = [paths_config.ndiff_command_path, "--verbose", "--", filename_a, filename_b] command_list = [
self.stdout_file = tempfile.TemporaryFile(mode = "rb", prefix = APP_NAME + "-ndiff-", suffix = ".xml") paths_config.ndiff_command_path,
"--verbose",
"--",
filename_a,
filename_b
]
self.stdout_file = tempfile.TemporaryFile(
mode="rb",
prefix=APP_NAME + "-ndiff-",
suffix=".xml"
)
log.debug("Running command: %s" % repr(command_list)) log.debug("Running command: %s" % repr(command_list))
# See zenmapCore.NmapCommand.py for an explanation of the shell argument. # shell argument explained in zenmapCore.NmapCommand.py
subprocess.Popen.__init__(self, command_list, stdout = self.stdout_file, stderr = self.stdout_file, env = env, shell = (sys.platform == "win32")) subprocess.Popen.__init__(
self,
command_list,
stdout=self.stdout_file,
stderr=self.stdout_file,
env=env,
shell=(sys.platform == "win32")
)
def get_scan_diff(self): def get_scan_diff(self):
self.wait() self.wait()
@@ -194,13 +215,17 @@ class NdiffCommand(subprocess.Popen):
def kill(self): def kill(self):
self.close() self.close()
def ndiff(scan_a, scan_b): def ndiff(scan_a, scan_b):
"""Run Ndiff on two scan results, which may be filenames or NmapParserSAX """Run Ndiff on two scan results, which may be filenames or NmapParserSAX
objects, and return a running NdiffCommand object.""" objects, and return a running NdiffCommand object."""
temporary_filenames = [] temporary_filenames = []
if isinstance(scan_a, NmapParserSAX): if isinstance(scan_a, NmapParserSAX):
fd, filename_a = tempfile.mkstemp(prefix = APP_NAME + "-diff-", suffix = ".xml") fd, filename_a = tempfile.mkstemp(
prefix=APP_NAME + "-diff-",
suffix=".xml"
)
temporary_filenames.append(filename_a) temporary_filenames.append(filename_a)
f = os.fdopen(fd, "wb") f = os.fdopen(fd, "wb")
scan_a.write_xml(f) scan_a.write_xml(f)
@@ -209,7 +234,10 @@ def ndiff(scan_a, scan_b):
filename_a = scan_a filename_a = scan_a
if isinstance(scan_b, NmapParserSAX): if isinstance(scan_b, NmapParserSAX):
fd, filename_b = tempfile.mkstemp(prefix = APP_NAME + "-diff-", suffix = ".xml") fd, filename_b = tempfile.mkstemp(
prefix=APP_NAME + "-diff-",
suffix=".xml"
)
temporary_filenames.append(filename_b) temporary_filenames.append(filename_b)
f = os.fdopen(fd, "wb") f = os.fdopen(fd, "wb")
scan_b.write_xml(f) scan_b.write_xml(f)

View File

@@ -126,6 +126,7 @@ import sys
from zenmapCore.Name import APP_NAME from zenmapCore.Name import APP_NAME
def get_locales(): def get_locales():
"""Get a list of locales to use based on system configuration.""" """Get a list of locales to use based on system configuration."""
locales = [] locales = []
@@ -148,6 +149,7 @@ def get_locales():
pass pass
return locales return locales
def install_gettext(locale_dir): def install_gettext(locale_dir):
try: try:
locale.setlocale(locale.LC_ALL, '') locale.setlocale(locale.LC_ALL, '')
@@ -162,8 +164,9 @@ def install_gettext(locale_dir):
except ImportError: except ImportError:
pass pass
else: else:
t = gettext.translation(APP_NAME, locale_dir, languages = get_locales(), fallback = True) t = gettext.translation(
t.install(unicode = True) APP_NAME, locale_dir, languages=get_locales(), fallback=True)
t.install(unicode=True)
# Install a dummy _ function so modules can safely use it after importing this # Install a dummy _ function so modules can safely use it after importing this
# module, even if they don't install the gettext version. # module, even if they don't install the gettext version.

View File

@@ -122,11 +122,13 @@
import re import re
class NSEDocEvent (object): class NSEDocEvent (object):
def __init__(self, type, text = None): def __init__(self, type, text=None):
self.type = type self.type = type
self.text = text self.text = text
def nsedoc_parse_sub(text, pos): def nsedoc_parse_sub(text, pos):
"""Parse paragraph-level NSEDoc markup, inside of paragraphs and lists. """Parse paragraph-level NSEDoc markup, inside of paragraphs and lists.
Returns the position after the end of parsing followed by a list of Returns the position after the end of parsing followed by a list of
@@ -145,6 +147,7 @@ def nsedoc_parse_sub(text, pos):
return pos + m.end(), events return pos + m.end(), events
return pos, events return pos, events
def nsedoc_parse(text): def nsedoc_parse(text):
"""Parse text marked up for NSEDoc. This is a generator that returns a """Parse text marked up for NSEDoc. This is a generator that returns a
sequence of NSEDocEvents. The type of the event may be "paragraph_start", sequence of NSEDocEvents. The type of the event may be "paragraph_start",

View File

@@ -128,9 +128,11 @@ import zenmapCore.NmapParser
from zenmapGUI.SearchGUI import SearchParser from zenmapGUI.SearchGUI import SearchParser
from SearchResult import HostSearch from SearchResult import HostSearch
class NetworkInventory(object): class NetworkInventory(object):
"""This class acts as a container for aggregated scans. It is also """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): def __init__(self, filename=None):
# A list of all scans that make up this inventory # A list of all scans that make up this inventory
self.scans = [] self.scans = []
@@ -162,8 +164,8 @@ class NetworkInventory(object):
# Add this host to the hosts dictionary, mapped by IP address # Add this host to the hosts dictionary, mapped by IP address
self.hosts[addr] = host.make_clone() self.hosts[addr] = host.make_clone()
else: else:
# This host is already present in the host list, so we need to update its # This host is already present in the host list, so we need to
# info with the info held in the current host object # update its info with the info held in the current host object
old_host = self.hosts[addr] old_host = self.hosts[addr]
# We need to find old_host's scan date # We need to find old_host's scan date
old_date = localtime(0) old_date = localtime(0)
@@ -171,7 +173,8 @@ class NetworkInventory(object):
if old_host in old_scan.get_hosts(): if old_host in old_scan.get_hosts():
old_date = old_scan.get_date() old_date = old_scan.get_date()
new_date = 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) self.scans.append(scan)
@@ -179,7 +182,8 @@ class NetworkInventory(object):
basename = os.path.basename(filename) basename = os.path.basename(filename)
if basename in self.filenames.values(): 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 base = basename
ext = "xml" ext = "xml"
try: try:
@@ -195,7 +199,8 @@ class NetworkInventory(object):
self.filenames[scan] = basename self.filenames[scan] = basename
def remove_scan(self, scan): 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 # 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 # method will throw a ValueError Exception and will not finish
# Remove the scan from our scan list # Remove the scan from our scan list
@@ -214,12 +219,13 @@ class NetworkInventory(object):
if scan in self.filenames: if scan in self.filenames:
del self.filenames[scan] del self.filenames[scan]
# For each scan in the remembered list, append it to the scan list and update # For each scan in the remembered list, append it to the scan list and
# the host list accordingly # update the host list accordingly
for scan in scans: for scan in scans:
self.add_scan(scan) 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 """This function is called when a host needs to be added to the hosts
dictionary, but another HostInfo object for that host already exists dictionary, but another HostInfo object for that host already exists
in the dictionary (from a previous scan). In that case, we need to 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: for new_port in new_host.ports:
# Check if new_port is already present in old_host's ports # Check if new_port is already present in old_host's ports
for old_port in old_host.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) 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: if old_date < new_date:
index = old_host.ports.index(old_port) index = old_host.ports.index(old_port)
old_host.ports[index] = new_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 break
else: else:
# This new_port isn't present in old_host, so we simply append it to # This new_port isn't present in old_host, so we simply append
# old_host's port info # it to old_host's port info
old_host.ports.append(new_port) old_host.ports.append(new_port)
ports = new_scan.get_port_protocol_dict() ports = new_scan.get_port_protocol_dict()
#remove ports which are no longer up #remove ports which are no longer up
@@ -269,7 +277,8 @@ class NetworkInventory(object):
if old_host.comment == "": if old_host.comment == "":
old_host.comment = new_host.comment old_host.comment = new_host.comment
elif 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 # Hostnames
# Replace old_host's hostname with new_host's if old_host has no # 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 old_host.hostnames = new_host.hostnames
# MAC address # MAC address
# If there was no MAC address set in old_host, set it to whatever is in new_host.mac. # If there was no MAC address set in old_host, set it to whatever is in
# Do the same if both hosts have a MAC address set, but new_host's address is newer. # new_host.mac. Do the same if both hosts have a MAC address set, but
if old_host.mac is None or \ # new_host's address is newer.
(old_host.mac is not None and new_host.mac is not None and old_date < new_date): 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 old_host.mac = new_host.mac
# OS detection fields # OS detection fields
# Replace old_host's OS detection fields with new_host's if old_host has no # Replace old_host's OS detection fields with new_host's if old_host
# OS detection info or new_host's info is newer. # 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): 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.osmatches = new_host.osmatches
old_host.ports_used = new_host.ports_used old_host.ports_used = new_host.ports_used
# Traceroute information # 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 old_host.trace = new_host.trace
def get_scans(self): def get_scans(self):
@@ -317,7 +334,8 @@ class NetworkInventory(object):
self.add_scan(parsed, path) self.add_scan(parsed, path)
def open_from_dir(self, 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 from zenmapCore.NmapParser import NmapParser
for filename in os.listdir(path): for filename in os.listdir(path):
@@ -328,7 +346,7 @@ class NetworkInventory(object):
parsed.parse_file(fullpath) parsed.parse_file(fullpath)
self.add_scan(parsed, filename=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 """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 path. With format = "xml", saves Nmap XML; otherwise saves plain text
output.""" output."""
@@ -341,21 +359,24 @@ class NetworkInventory(object):
f.close() f.close()
def _generate_filenames(self, path): def _generate_filenames(self, path):
"""Generates filenames for all scans that don't already have a filename.""" """Generates filenames for all scans that don't already have a
# The directory must not contain filenames other than those in the self.filenames dictionary filename."""
# The directory must not contain filenames other than those in the
# self.filenames dictionary
for filename in os.listdir(path): for filename in os.listdir(path):
if os.path.basename(filename) not in self.filenames.values(): if os.path.basename(filename) not in self.filenames.values():
raise Exception("The destination directory contains a file (%s) that's not a part " raise Exception("The destination directory contains a file"
"of the current inventory. The inventory will not be saved." % "(%s) that's not a part of the current inventory."
os.path.basename(filename)) "The inventory will not be saved." %
os.path.basename(filename))
for scan in self.scans: for scan in self.scans:
if scan in self.filenames: if scan in self.filenames:
# This scan already has a filename # This scan already has a filename
continue continue
date = "%04d%02d%02d%02d%02d" % (scan.date[0], scan.date[1], scan.date[2], date = "%04d%02d%02d%02d%02d" % (scan.date[0], scan.date[1],
scan.date[3], scan.date[4]) scan.date[2], scan.date[3], scan.date[4])
filename = scan.get_scan_name() filename = scan.get_scan_name()
# Prepend the date # Prepend the date
@@ -367,20 +388,22 @@ class NetworkInventory(object):
filename = filename.replace(char, "_") filename = filename.replace(char, "_")
# Filename length check # 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: if len(filename) > 250:
filename = filename[:250] filename = filename[:250]
# TODO: Filename security checks? # TODO: Filename security checks?
# Try to open the file in append mode. If file.tell() returns a greater-than-zero # Try to open the file in append mode. If file.tell() returns a
# value, this means that the file already exists and has some data in it, so we # greater-than-zero value, this means that the file already exists
# choose another filename until we successfully open a zero-length file. # and has some data in it, so we choose another filename until we
# successfully open a zero-length file.
filename_full = filename + ".xml" filename_full = filename + ".xml"
counter = 2 counter = 2
while filename_full in self.filenames.values(): while filename_full in self.filenames.values():
# There's already a scan with this filename, so we generate a new name by appending # There's already a scan with this filename, so we generate a
# the counter value before the file extension. # new name by appending the counter value before the file
# extension.
filename_full = "%s %s.xml" % (filename, str(counter)) filename_full = "%s %s.xml" % (filename, str(counter))
counter += 1 counter += 1
@@ -413,12 +436,13 @@ class NetworkInventory(object):
f = StringIO() f = StringIO()
parsed.write_xml(f) parsed.write_xml(f)
scan = Scans(scan_name = parsed.scan_name, scan = Scans(scan_name=parsed.scan_name,
nmap_xml_output = f.getvalue(), nmap_xml_output=f.getvalue(),
date = time()) date=time())
class FilteredNetworkInventory(NetworkInventory): class FilteredNetworkInventory(NetworkInventory):
def __init__(self, filename = None): def __init__(self, filename=None):
NetworkInventory.__init__(self, filename) NetworkInventory.__init__(self, filename)
# A dictionary listing host filtering criteria # A dictionary listing host filtering criteria
@@ -459,18 +483,24 @@ class FilteredNetworkInventory(NetworkInventory):
return self.filtered_hosts return self.filtered_hosts
else: else:
return NetworkInventory.get_hosts(self) return NetworkInventory.get_hosts(self)
def get_hosts_up(self): def get_hosts_up(self):
if len(self.search_dict) > 0: 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: else:
return NetworkInventory.get_hosts_up(self) return NetworkInventory.get_hosts_up(self)
def get_hosts_down(self): def get_hosts_down(self):
if len(self.search_dict) > 0: 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: else:
return NetworkInventory.get_hosts_down(self) return NetworkInventory.get_hosts_down(self)
def get_total_host_count(self): def get_total_host_count(self):
return len(self.hosts) return len(self.hosts)
def _match_all_args(self, host, operator, args): def _match_all_args(self, host, operator, args):
"""A helper function that calls the matching function for the given """A helper function that calls the matching function for the given
operator and each of its arguments.""" operator and each of its arguments."""
@@ -479,48 +509,63 @@ class FilteredNetworkInventory(NetworkInventory):
if arg != "" and arg[0] == "!": if arg != "" and arg[0] == "!":
arg = arg[1:] arg = arg[1:]
positive = False 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 # No match for this operator
return False return False
else: else:
# if the operator is not supported, pretend its true # if the operator is not supported, pretend its true
# All arguments for this operator produced a match # All arguments for this operator produced a match
return True return True
def get_host_count(self): def get_host_count(self):
return len(self.network_inventory.hosts) return len(self.network_inventory.hosts)
def match_keyword(self, host, keyword): def match_keyword(self, host, keyword):
return self.match_os(host, keyword) or\ return self.match_os(host, keyword) or\
self.match_target(host, keyword) or\ self.match_target(host, keyword) or\
self.match_service(host, keyword) self.match_service(host, keyword)
def match_target(self, host, name): def match_target(self, host, name):
return HostSearch.match_target(host, name) return HostSearch.match_target(host, name)
def match_in_route(self, host, hop): def match_in_route(self, host, hop):
hops = host.get_trace().get('hops', []) hops = host.get_trace().get('hops', [])
return hop in hops return hop in hops
def match_hostname(self, host, hostname): def match_hostname(self, host, hostname):
return HostSearch.match_hostname(host, hostname) return HostSearch.match_hostname(host, hostname)
def match_service(self, host, service): def match_service(self, host, service):
return HostSearch.match_service(host, service) return HostSearch.match_service(host, service)
def match_os(self, host, os): def match_os(self, host, os):
return HostSearch.match_os(host, os) return HostSearch.match_os(host, os)
def match_open(self, host, portno): def match_open(self, host, portno):
host_ports = host.get_ports() host_ports = host.get_ports()
return HostSearch.match_port(host_ports, portno, "open") return HostSearch.match_port(host_ports, portno, "open")
def match_closed(self, host, portno): def match_closed(self, host, portno):
host_ports = host.get_ports() host_ports = host.get_ports()
return HostSearch.match_port(host_ports, portno, "closed") return HostSearch.match_port(host_ports, portno, "closed")
def match_filtered(self, host, portno): def match_filtered(self, host, portno):
host_ports = host.get_ports() host_ports = host.get_ports()
return HostSearch.match_port(host_ports, portno, "filtered") return HostSearch.match_port(host_ports, portno, "filtered")
def match_unfiltered(self, host, portno): def match_unfiltered(self, host, portno):
host_ports = host.get_ports() host_ports = host.get_ports()
return HostSearch.match_port(host_ports, portno, "unfiltered") return HostSearch.match_port(host_ports, portno, "unfiltered")
def match_open_filtered(self, host, portno): def match_open_filtered(self, host, portno):
host_ports = host.get_ports() host_ports = host.get_ports()
return HostSearch.match_port(host_ports, portno, "open|filtered") return HostSearch.match_port(host_ports, portno, "open|filtered")
def match_closed_filtered(self, host, portno): def match_closed_filtered(self, host, portno):
host_ports = host.get_ports() host_ports = host.get_ports()
return HostSearch.match_port(host_ports, portno, "closed|filtered") return HostSearch.match_port(host_ports, portno, "closed|filtered")
def apply_filter(self, filter_text): def apply_filter(self, filter_text):
self.filter_text = filter_text.lower() self.filter_text = filter_text.lower()
self.search_parser.update(self.filter_text) self.search_parser.update(self.filter_text)
@@ -537,10 +582,11 @@ class FilteredNetworkInventory(NetworkInventory):
# host satisfies all conditions # host satisfies all conditions
self.filtered_hosts.append(host) self.filtered_hosts.append(host)
class NetworkInventoryTest(unittest.TestCase): class NetworkInventoryTest(unittest.TestCase):
def test_no_external_modification(self): def test_no_external_modification(self):
"""Test that HostInfo objects passed into the inventory are not modified """Test that HostInfo objects passed into the inventory are not
during aggregation.""" modified during aggregation."""
scan_1 = zenmapCore.NmapParser.ParserBasics() scan_1 = zenmapCore.NmapParser.ParserBasics()
host_a = zenmapCore.NmapParser.HostInfo() host_a = zenmapCore.NmapParser.HostInfo()
host_a.hostnames = ["a"] host_a.hostnames = ["a"]
@@ -564,28 +610,30 @@ class NetworkInventoryTest(unittest.TestCase):
self.assertEqual(scan_1.nmap["hosts"], [host_a]) self.assertEqual(scan_1.nmap["hosts"], [host_a])
self.assertEqual(scan_2.nmap["hosts"], [host_b]) self.assertEqual(scan_2.nmap["hosts"], [host_b])
self.assertEqual(inv.get_hosts_up()[0].hostnames, ["b"]) self.assertEqual(inv.get_hosts_up()[0].hostnames, ["b"])
def test_cancel_and_remove_scan(self): def test_cancel_and_remove_scan(self):
"""Test that canceling and removing a scan does not blow away the inventory hosts""" """Test that canceling and removing a scan does not blow away the
added_ips = ['10.0.0.1','10.0.0.2'] inventory hosts"""
added_ips = ['10.0.0.1', '10.0.0.2']
removed_ips = ['10.0.0.3'] removed_ips = ['10.0.0.3']
scan_1 = zenmapCore.NmapParser.ParserBasics() scan_1 = zenmapCore.NmapParser.ParserBasics()
host_a = zenmapCore.NmapParser.HostInfo() host_a = zenmapCore.NmapParser.HostInfo()
host_a.hostnames = ["a"] 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.start = "1000000000"
scan_1.nmap["hosts"] = [host_a] scan_1.nmap["hosts"] = [host_a]
scan_2 = zenmapCore.NmapParser.ParserBasics() scan_2 = zenmapCore.NmapParser.ParserBasics()
host_b = zenmapCore.NmapParser.HostInfo() host_b = zenmapCore.NmapParser.HostInfo()
host_b.hostnames = ["b"] 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.start = "1000000001"
scan_2.nmap["hosts"] = [host_b] scan_2.nmap["hosts"] = [host_b]
scan_3 = zenmapCore.NmapParser.ParserBasics() scan_3 = zenmapCore.NmapParser.ParserBasics()
host_c = zenmapCore.NmapParser.HostInfo() host_c = zenmapCore.NmapParser.HostInfo()
host_c.hostnames = ["b"] 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.start = "1000000001"
scan_3.nmap["hosts"] = [host_c] scan_3.nmap["hosts"] = [host_c]
@@ -600,6 +648,7 @@ class NetworkInventoryTest(unittest.TestCase):
self.assertEqual(host_a.hostnames, ["a"]) self.assertEqual(host_a.hostnames, ["a"])
self.assertEqual(host_b.hostnames, ["b"]) self.assertEqual(host_b.hostnames, ["b"])
class FilteredNetworkInventoryTest(unittest.TestCase): class FilteredNetworkInventoryTest(unittest.TestCase):
def test_filter(self): def test_filter(self):
"""Test that the filter still works after moving code to the """ """Test that the filter still works after moving code to the """
@@ -613,6 +662,7 @@ class FilteredNetworkInventoryTest(unittest.TestCase):
inv.apply_filter(filter_text) inv.apply_filter(filter_text)
assert(len(inv.get_hosts()) == 2) assert(len(inv.get_hosts()) == 2)
class PortChangeTest(unittest.TestCase): class PortChangeTest(unittest.TestCase):
def test_port(self): def test_port(self):
"""Verify that the port status (open/filtered/closed) is diplayed """ \ """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) assert(len(inv.get_hosts()[0].ports) == 0)
# Additional test case for when the two scans have port scan ranges # Additional test case for when the two scans have port scan ranges
# which do not overlap. Example nmap -F -sU versus # which do not overlap. Example nmap -F -sU versus
# nmap -F scanme.nmap.org # nmap -F scanme.nmap.org
inv = NetworkInventory() inv = NetworkInventory()
scan4 = NmapParser() scan4 = NmapParser()
scan4.parse_file("test/xml_test16.xml") scan4.parse_file("test/xml_test16.xml")
inv.add_scan(scan4) inv.add_scan(scan4)
assert(len(inv.get_hosts()[0].ports)==3) assert(len(inv.get_hosts()[0].ports) == 3)
scan5 = NmapParser() scan5 = NmapParser()
scan5.parse_file("test/xml_test17.xml") scan5.parse_file("test/xml_test17.xml")
inv.add_scan(scan5) inv.add_scan(scan5)
assert(len(inv.get_hosts()[0].ports)==7) assert(len(inv.get_hosts()[0].ports) == 7)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -152,6 +152,7 @@ paths_config = PathsConfig()
log.debug(">>> Platform: %s" % sys.platform) log.debug(">>> Platform: %s" % sys.platform)
def wrap_file_in_preferred_encoding(f): def wrap_file_in_preferred_encoding(f):
"""Wrap an open file to automatically decode its contents when reading from """Wrap an open file to automatically decode its contents when reading from
the encoding given by locale.getpreferredencoding, or just return the file the encoding given by locale.getpreferredencoding, or just return the file
@@ -184,17 +185,19 @@ def wrap_file_in_preferred_encoding(f):
return f return f
def escape_nmap_filename(filename): def escape_nmap_filename(filename):
"""Escape '%' characters so they are not interpreted as strftime format """Escape '%' characters so they are not interpreted as strftime format
specifiers, which are not supported by Zenmap.""" specifiers, which are not supported by Zenmap."""
return filename.replace("%", "%%") return filename.replace("%", "%%")
class NmapCommand(object): class NmapCommand(object):
"""This class represents an Nmap command line. It is responsible for """This class represents an Nmap command line. It is responsible for
starting, stopping, and returning the results from a command-line scan. A starting, stopping, and returning the results from a command-line scan. A
command line is represented as a string but it is split into a list of command line is represented as a string but it is split into a list of
arguments for execution. arguments for execution.
The normal output (stdout and stderr) are written to the file object The normal output (stdout and stderr) are written to the file object
self.stdout_file.""" self.stdout_file."""
@@ -231,7 +234,8 @@ class NmapCommand(object):
self.ops[op] = escape_nmap_filename(self.ops[op]) self.ops[op] = escape_nmap_filename(self.ops[op])
if self.xml_is_temp: if self.xml_is_temp:
self.xml_output_filename = tempfile.mktemp(prefix = APP_NAME + "-", suffix = ".xml") self.xml_output_filename = tempfile.mktemp(
prefix=APP_NAME + "-", suffix=".xml")
self.ops["-oX"] = escape_nmap_filename(self.xml_output_filename) self.ops["-oX"] = escape_nmap_filename(self.xml_output_filename)
log.debug(">>> Temporary files:") log.debug(">>> Temporary files:")
@@ -261,7 +265,8 @@ class NmapCommand(object):
else: else:
try: try:
import ctypes import ctypes
ctypes.windll.kernel32.TerminateProcess(int(self.command_process._handle), -1) ctypes.windll.kernel32.TerminateProcess(
int(self.command_process._handle), -1)
except: except:
pass pass
@@ -279,13 +284,13 @@ class NmapCommand(object):
search_paths.append(path) search_paths.append(path)
return os.pathsep.join(search_paths) return os.pathsep.join(search_paths)
def run_scan(self, stderr = None): def run_scan(self, stderr=None):
"""Run the command represented by this class.""" """Run the command represented by this class."""
# We don't need a file name for stdout output, just a handle. A # We don't need a file name for stdout output, just a handle. A
# TemporaryFile is deleted as soon as it is closed, and in Unix is # TemporaryFile is deleted as soon as it is closed, and in Unix is
# unlinked immediately after creation so it's not even visible. # unlinked immediately after creation so it's not even visible.
f = tempfile.TemporaryFile(mode = "rb", prefix = APP_NAME + "-stdout-") f = tempfile.TemporaryFile(mode="rb", prefix=APP_NAME + "-stdout-")
self.stdout_file = wrap_file_in_preferred_encoding(f) self.stdout_file = wrap_file_in_preferred_encoding(f)
if stderr is None: if stderr is None:
stderr = f stderr = f
@@ -303,7 +308,8 @@ class NmapCommand(object):
# This keeps a terminal window from opening. # This keeps a terminal window from opening.
startupinfo = subprocess.STARTUPINFO() startupinfo = subprocess.STARTUPINFO()
try: try:
startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW startupinfo.dwFlags |= \
subprocess._subprocess.STARTF_USESHOWWINDOW
except AttributeError: except AttributeError:
# This name is used before Python 2.6.5. # This name is used before Python 2.6.5.
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
@@ -312,7 +318,7 @@ class NmapCommand(object):
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
stdout=f, stdout=f,
stderr=stderr, stderr=stderr,
startupinfo = startupinfo, startupinfo=startupinfo,
env=env) env=env)
def scan_state(self): def scan_state(self):
@@ -327,15 +333,18 @@ class NmapCommand(object):
state = self.command_process.poll() state = self.command_process.poll()
if state == None: if state == None:
return True # True means that the process is still running return True # True means that the process is still running
elif state == 0: elif state == 0:
return False # False means that the process had a successful exit return False # False means that the process had a successful exit
else: else:
log.warning("An error occurred during the scan execution!") log.warning("An error occurred during the scan execution!")
log.warning("Command that raised the exception: '%s'" % self.ops.render_string()) log.warning("Command that raised the exception: '%s'" %
self.ops.render_string())
log.warning("Scan output:\n%s" % self.get_output()) log.warning("Scan output:\n%s" % self.get_output())
raise Exception("An error occurred during the scan execution!\n\n'%s'" % self.get_output()) raise Exception(
"An error occurred during the scan execution!\n\n'%s'" %
self.get_output())
def get_output(self): def get_output(self):
"""Return the complete contents of the self.stdout_file. This modifies """Return the complete contents of the self.stdout_file. This modifies
@@ -348,4 +357,5 @@ class NmapCommand(object):
return self.xml_output_filename return self.xml_output_filename
if __name__ == '__main__': if __name__ == '__main__':
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(SplitQuotedTest)) unittest.TextTestRunner().run(
unittest.TestLoader().loadTestsFromTestCase(SplitQuotedTest))

View File

@@ -2,8 +2,8 @@
# This is an Nmap command line parser. It has two main parts: # This is an Nmap command line parser. It has two main parts:
# #
# getopt_long_only_extras, which is like getopt_long_only with robust handling # getopt_long_only_extras, which is like getopt_long_only with robust
# of unknown options. # handling of unknown options.
# #
# NmapOptions, a class representing a set of Nmap options. # NmapOptions, a class representing a set of Nmap options.
# #
@@ -30,9 +30,11 @@
# >>> ops["-v"] = 2 # >>> ops["-v"] = 2
# >>> ops["-oX"] = "output.xml" # >>> ops["-oX"] = "output.xml"
# >>> ops.render() # >>> ops.render()
# ['C:\\Program Files\\Nmap\\nmap.exe', '-v', '-v', '-oX', 'output.xml', '--script', 'safe', 'localhost'] # ['C:\\Program Files\\Nmap\\nmap.exe', '-v', '-v', '-oX', 'output.xml',
# '--script', 'safe', 'localhost']
# >>> ops.render_string() # >>> ops.render_string()
# '"C:\\Program Files\\Nmap\\nmap.exe" -v -v -oX output.xml --script safe localhost' # '"C:\\Program Files\\Nmap\\nmap.exe" -v -v -oX output.xml\
# --script safe localhost'
# #
# A primary design consideration was robust handling of unknown options. That # A primary design consideration was robust handling of unknown options. That
# gives this code a degree of independence from Nmap's own list of options. If # gives this code a degree of independence from Nmap's own list of options. If
@@ -45,17 +47,17 @@
# nmap -x -e eth0 scanme.nmap.org # nmap -x -e eth0 scanme.nmap.org
# If -x, whatever it is, does not take an argument, it is equivalent to # If -x, whatever it is, does not take an argument, it is equivalent to
# nmap -e eth0 scanme.nmap.org -x # nmap -e eth0 scanme.nmap.org -x
# that is, a scan of scanme.nmap.org over interface eth0. But if it does take an # that is, a scan of scanme.nmap.org over interface eth0. But if it does take
# argument, its argument is "-e", and the command line is the same as # an argument, its argument is "-e", and the command line is the same as
# nmap eth0 scanme.nmap.org -x -e # nmap eth0 scanme.nmap.org -x -e
# which is a scan of the two hosts eth0 and scanme.nmap.org, over the default # which is a scan of the two hosts eth0 and scanme.nmap.org, over the default
# interface. In either case scanme.nmap.org is a target but the other arguments # interface. In either case scanme.nmap.org is a target but the other arguments
# are ambiguous. To resolve this, once an unknown option is found, all following # are ambiguous. To resolve this, once an unknown option is found, all
# arguments that can be interpreted ambiguously are removed with it and placed # following arguments that can be interpreted ambiguously are removed with it
# in the extras, with normal option processing resumed only when there is no # and placed in the extras, with normal option processing resumed only when
# more ambiguity. This ensures that such options maintain their relative order # there is no more ambiguity. This ensures that such options maintain their
# when rendered again to output. In this example "-x -e eth0" will always appear # relative order when rendered again to output. In this example "-x -e eth0"
# in that order, and the -e option will be uninterpreted. # will always appear in that order, and the -e option will be uninterpreted.
# #
# To add a new option, one should do the following: # To add a new option, one should do the following:
# 1) Add a test case to the NmapOptionsTest::test_options() method for the new # 1) Add a test case to the NmapOptionsTest::test_options() method for the new
@@ -79,6 +81,7 @@
# get_option_check_auxiliary_widget in OptionBuilder.py. # get_option_check_auxiliary_widget in OptionBuilder.py.
# 7) Make sure the test case works now. # 7) Make sure the test case works now.
class option: class option:
"""A single option, part of a pool of potential options. It's just a name """A single option, part of a pool of potential options. It's just a name
and a flag saying if the option takes no argument, if an agument is and a flag saying if the option takes no argument, if an agument is
@@ -91,6 +94,7 @@ class option:
self.name = name self.name = name
self.has_arg = has_arg self.has_arg = has_arg
def split_quoted(s): def split_quoted(s):
"""Like str.split, except that no splits occur inside quoted strings, and """Like str.split, except that no splits occur inside quoted strings, and
quoted strings are unquoted.""" quoted strings are unquoted."""
@@ -114,8 +118,8 @@ def split_quoted(s):
i += 1 i += 1
if i < len(s): if i < len(s):
c = s[i] c = s[i]
# Otherwise, ignore the error and leave the backslash at # Otherwise, ignore the error and leave the backslash
# the end of the string. # at the end of the string.
part.append(c) part.append(c)
i += 1 i += 1
else: else:
@@ -127,6 +131,7 @@ def split_quoted(s):
return r return r
def maybe_quote(s): def maybe_quote(s):
"""Return s quoted if it needs to be, otherwise unchanged.""" """Return s quoted if it needs to be, otherwise unchanged."""
for c in s: for c in s:
@@ -146,9 +151,11 @@ def maybe_quote(s):
return "\"" + "".join(r) + "\"" return "\"" + "".join(r) + "\""
def join_quoted(l): def join_quoted(l):
return " ".join([maybe_quote(x) for x in l]) return " ".join([maybe_quote(x) for x in l])
def make_options(short_opts, long_opts): def make_options(short_opts, long_opts):
"""Parse a short option specification string and long option tuples into a """Parse a short option specification string and long option tuples into a
list of option objects.""" list of option objects."""
@@ -176,6 +183,7 @@ def make_options(short_opts, long_opts):
lookup_option_cache = {} lookup_option_cache = {}
def lookup_option(name, options): def lookup_option(name, options):
"""Find an option with the given (possibly abbreviated) name. None is """Find an option with the given (possibly abbreviated) name. None is
returned if no options match or if the name is ambiguous (more than one returned if no options match or if the name is ambiguous (more than one
@@ -197,7 +205,8 @@ def lookup_option(name, options):
return name.replace("_", "-") return name.replace("_", "-")
name = canonicalize_name(name) name = canonicalize_name(name)
matches = [o for o in options if canonicalize_name(o.name).startswith(name)] matches = [o for o in options
if canonicalize_name(o.name).startswith(name)]
if len(matches) == 0: if len(matches) == 0:
# No match. # No match.
lookup_option_cache[cache_code] = None lookup_option_cache[cache_code] = None
@@ -215,19 +224,22 @@ def lookup_option(name, options):
lookup_option_cache[cache_code] = None lookup_option_cache[cache_code] = None
return lookup_option_cache[cache_code] return lookup_option_cache[cache_code]
def split_option(cmd_arg, options): def split_option(cmd_arg, options):
"""Split an option into a name, argument (if any), and possible remainder. """Split an option into a name, argument (if any), and possible remainder.
It is not an error if the option does not include an argument even though it It is not an error if the option does not include an argument even though
is required; the caller must take the argument from the next command-line it is required; the caller must take the argument from the next
argument. The remainder is what's left over after stripping a single short command-line argument. The remainder is what's left over after stripping a
option that doesn't take an argument. At most one of argument and remainder single short option that doesn't take an argument. At most one of argument
will be non-None. and remainder will be non-None.
Examples: Examples:
>>> split_option("-v", [option("v", option.NO_ARGUMENT)]) >>> split_option("-v", [option("v", option.NO_ARGUMENT)])
('v', None, None) ('v', None, None)
>>> split_option("--min-rate", [option("min-rate", option.REQUIRED_ARGUMENT)]) >>> split_option("--min-rate",
... [option("min-rate", option.REQUIRED_ARGUMENT)])
('min-rate', None, None) ('min-rate', None, None)
>>> split_option("--min-rate=100", [option("min-rate", option.REQUIRED_ARGUMENT)]) >>> split_option("--min-rate=100",
... [option("min-rate", option.REQUIRED_ARGUMENT)])
('min-rate', '100', None) ('min-rate', '100', None)
>>> split_option("-d9", [option("d", option.OPTIONAL_ARGUMENT)]) >>> split_option("-d9", [option("d", option.OPTIONAL_ARGUMENT)])
('d', '9', None) ('d', '9', None)
@@ -273,15 +285,17 @@ def split_option(cmd_arg, options):
else: else:
assert False, cmd_arg assert False, cmd_arg
def get_option(cmd_args, options): def get_option(cmd_args, options):
"""Find and return the first option (plus a possible option argument) or """Find and return the first option (plus a possible option argument) or
positional argument from the command-line option list in cmd_args. The positional argument from the command-line option list in cmd_args. The
return value will have one of the following forms: return value will have one of the following forms:
a string, representing a positional argument; * a string, representing a positional argument;
an (option, argument) pair (argument may be None); * an (option, argument) pair (argument may be None);
a (None, extra, ...) tuple, where extra, ... is a chain of an unknown option * a (None, extra, ...) tuple, where extra, ... is a chain of an unknown
and its following arguments that cannot be interpreted unambiguously; or option and its following arguments that cannot be interpreted
None, at the end of the option list.""" unambiguously; or
* None, at the end of the option list."""
if len(cmd_args) == 0: if len(cmd_args) == 0:
return None return None
cmd_arg = cmd_args.pop(0) cmd_arg = cmd_args.pop(0)
@@ -305,9 +319,9 @@ def get_option(cmd_args, options):
return (None, cmd_arg) return (None, cmd_arg)
else: else:
extras = [None, cmd_arg] extras = [None, cmd_arg]
# We found an unknown option but we have a problem--we don't know if # We found an unknown option but we have a problem--we don't know
# it takes an argument or not. So what we do is, we simulate what # if it takes an argument or not. So what we do is, we simulate
# would happen both if the option took and argument and if it # what would happen both if the option took and argument and if it
# didn't. The sync function does that by calling this function in a # didn't. The sync function does that by calling this function in a
# loop. # loop.
rest = sync(cmd_args[1:], cmd_args[:], options) rest = sync(cmd_args[1:], cmd_args[:], options)
@@ -332,6 +346,7 @@ def get_option(cmd_args, options):
else: else:
return (option.name, arg) return (option.name, arg)
def sync(a, b, options): def sync(a, b, options):
"""Given two command-line argument lists, incrementally get an option from """Given two command-line argument lists, incrementally get an option from
whichever is longer until both lists are equal. Return the resulting whichever is longer until both lists are equal. Return the resulting
@@ -343,15 +358,17 @@ def sync(a, b, options):
get_option(b, options) get_option(b, options)
return a return a
def getopt_long_only_extras(cmd_args, short_opts, long_opts): def getopt_long_only_extras(cmd_args, short_opts, long_opts):
"""This is a generator version of getopt_long_only that additionally has """This is a generator version of getopt_long_only that additionally has
robust handling of unknown options. Each of the items in the sequence it robust handling of unknown options. Each of the items in the sequence it
yields will be one of the following: yields will be one of the following:
a string, representing a positional argument; * a string, representing a positional argument;
an (option, argument) pair (argument may be None); * an (option, argument) pair (argument may be None);
a (None, extra, ...) tuple, where extra, ... is a chain of an unknown option * a (None, extra, ...) tuple, where extra, ... is a chain of an unknown
and its following arguments that cannot be interpreted unambiguously; or option and its following arguments that cannot be interpreted
None, at the end of the option list.""" unambiguously; or
* None, at the end of the option list."""
options = make_options(short_opts, long_opts) options = make_options(short_opts, long_opts)
# get_option modifies its list of arguments in place. Don't modify the # get_option modifies its list of arguments in place. Don't modify the
# original list. # original list.
@@ -362,6 +379,7 @@ def getopt_long_only_extras(cmd_args, short_opts, long_opts):
break break
yield result yield result
class NmapOptions(object): class NmapOptions(object):
SHORT_OPTIONS = "6Ab:D:d::e:Ffg:hi:M:m:nO::o:P:p:RrS:s:T:v::V" SHORT_OPTIONS = "6Ab:D:d::e:Ffg:hi:M:m:nO::o:P:p:RrS:s:T:v::V"
LONG_OPTIONS = ( LONG_OPTIONS = (
@@ -492,7 +510,8 @@ class NmapOptions(object):
def _set_executable(self, executable): def _set_executable(self, executable):
self._executable = executable self._executable = executable
executable = property(lambda self: self._executable or "nmap", _set_executable) executable = property(lambda self: self._executable or "nmap",
_set_executable)
def canonicalize_name(self, name): def canonicalize_name(self, name):
opt, arg, remainder = split_option(name, self.options) opt, arg, remainder = split_option(name, self.options)
@@ -563,7 +582,8 @@ class NmapOptions(object):
"webxml", "webxml",
): ):
self["--" + opt] = True self["--" + opt] = True
elif opt in ("b", "D", "e", "g", "i", "iL", "m", "M", "o", "oA", "oG", "oM", "oN", "oS", "oX", "p", "S", "sI"): elif opt in ("b", "D", "e", "g", "i", "iL", "m", "M", "o", "oA", "oG",
"oM", "oN", "oS", "oX", "p", "S", "sI"):
assert arg is not None assert arg is not None
if self["-" + opt] is None: if self["-" + opt] is None:
self["-" + opt] = arg self["-" + opt] = arg
@@ -617,7 +637,8 @@ class NmapOptions(object):
try: try:
self["-d"] = int(arg) self["-d"] = int(arg)
except ValueError: except ValueError:
if reduce(lambda x, y: x and y, map(lambda z: z == "d", arg), True): if reduce(lambda x, y: x and y,
map(lambda z: z == "d", arg), True):
self.setdefault("-d", 0) self.setdefault("-d", 0)
self["-d"] += len(arg) + 1 self["-d"] += len(arg) + 1
else: else:
@@ -646,7 +667,8 @@ class NmapOptions(object):
self.extras.append("-O%s" % arg) self.extras.append("-O%s" % arg)
elif opt == "P": elif opt == "P":
type, ports = arg[:1], arg[1:] type, ports = arg[:1], arg[1:]
if type == "0" or type == "D" or type == "N" or type == "n" and ports == "": if (type == "0" or type == "D" or type == "N" or
type == "n" and ports == ""):
self["-Pn"] = True self["-Pn"] = True
elif (type == "" or type == "I" or type == "E") and ports == "": elif (type == "" or type == "I" or type == "E") and ports == "":
self["-PE"] = True self["-PE"] = True
@@ -693,7 +715,8 @@ class NmapOptions(object):
try: try:
self["-v"] = int(arg) self["-v"] = int(arg)
except ValueError: except ValueError:
if reduce(lambda x, y: x and y, map(lambda z: z == "v", arg), True): if reduce(lambda x, y: x and y,
map(lambda z: z == "v", arg), True):
self.setdefault("-v", 0) self.setdefault("-v", 0)
self["-v"] += len(arg) + 1 self["-v"] += len(arg) + 1
else: else:
@@ -707,7 +730,8 @@ class NmapOptions(object):
if len(opt_list) > 0: if len(opt_list) > 0:
self.executable = opt_list[0] self.executable = opt_list[0]
for result in getopt_long_only_extras(opt_list[1:], self.SHORT_OPTIONS, self.LONG_OPTIONS): for result in getopt_long_only_extras(
opt_list[1:], self.SHORT_OPTIONS, self.LONG_OPTIONS):
self.handle_result(result) self.handle_result(result)
def parse_string(self, opt_string): def parse_string(self, opt_string):
@@ -716,7 +740,8 @@ class NmapOptions(object):
def render(self): def render(self):
opt_list = [] opt_list = []
for opt in ("-sA", "-sC", "-sF", "-sL", "-sM", "-sN", "-sO", "-sn", "-sR", "-sS", "-sT", "-sU", "-sV", "-sW", "-sX", "-sY", "-sZ"): for opt in ("-sA", "-sC", "-sF", "-sL", "-sM", "-sN", "-sO", "-sn",
"-sR", "-sS", "-sT", "-sU", "-sV", "-sW", "-sX", "-sY", "-sZ"):
if self[opt]: if self[opt]:
opt_list.append(opt) opt_list.append(opt)
@@ -865,6 +890,7 @@ class NmapOptions(object):
import doctest import doctest
import unittest import unittest
class NmapOptionsTest(unittest.TestCase): class NmapOptionsTest(unittest.TestCase):
def test_clear(self): def test_clear(self):
"""Test that a new object starts without defining any options, that the """Test that a new object starts without defining any options, that the
@@ -901,7 +927,8 @@ class NmapOptionsTest(unittest.TestCase):
TEST = "nmap -T4 -A -v localhost --webxml" TEST = "nmap -T4 -A -v localhost --webxml"
ops = NmapOptions() ops = NmapOptions()
ops.parse_string(TEST) ops.parse_string(TEST)
self.assertTrue(type(ops.render()) == list, "type == %s" % type(ops.render)) self.assertTrue(type(ops.render()) == list,
"type == %s" % type(ops.render))
def test_quoted(self): def test_quoted(self):
"""Test that strings can be quoted.""" """Test that strings can be quoted."""
@@ -1123,7 +1150,8 @@ class NmapOptionsTest(unittest.TestCase):
ops.parse_string("nmap -min-rate=100") ops.parse_string("nmap -min-rate=100")
self.assertTrue(ops["--min-rate"] == "100") self.assertTrue(ops["--min-rate"] == "100")
# Short options not taking an argument can be followed by a long option. # Short options not taking an argument can be followed by a long
# option.
ops.parse_string("nmap -nFmin-rate 100") ops.parse_string("nmap -nFmin-rate 100")
self.assertTrue(ops["-n"]) self.assertTrue(ops["-n"])
self.assertTrue(ops["-F"]) self.assertTrue(ops["-F"])
@@ -1155,8 +1183,8 @@ class NmapOptionsTest(unittest.TestCase):
self.assertEqual(ops["--nonoption"], None) self.assertEqual(ops["--nonoption"], None)
def test_canonical_option_names(self): def test_canonical_option_names(self):
"""Test that equivalent option names are properly canonicalized, so that """Test that equivalent option names are properly canonicalized, so
ops["--timing"] and ops["-T"] mean the same thing, for example.""" that ops["--timing"] and ops["-T"] mean the same thing, for example."""
EQUIVS = ( EQUIVS = (
("--debug", "-d"), ("--debug", "-d"),
("--help", "-h"), ("--help", "-h"),
@@ -1334,11 +1362,17 @@ class NmapOptionsTest(unittest.TestCase):
ops.parse_string("nmap " + test) ops.parse_string("nmap " + test)
opt_list_1 = ops.render() opt_list_1 = ops.render()
self.assertTrue(len(opt_list_1) > 1, "%s missing on render" % test) self.assertTrue(len(opt_list_1) > 1, "%s missing on render" % test)
self.assertTrue(len(ops.extras) == 0, "%s caused extras: %s" % (test, repr(ops.extras))) self.assertTrue(len(ops.extras) == 0,
"%s caused extras: %s" % (test, repr(ops.extras)))
ops.parse(opt_list_1) ops.parse(opt_list_1)
opt_list_2 = ops.render() opt_list_2 = ops.render()
self.assertTrue(opt_list_1 == opt_list_2, "Result of parsing and rendering %s not parsable again" % test) self.assertTrue(opt_list_1 == opt_list_2,
self.assertTrue(len(ops.extras) == 0, "Result of parsing and rendering %s left extras: %s" % (test, ops.extras)) "Result of parsing and rendering %s not parsable again" % (
test))
self.assertTrue(len(ops.extras) == 0,
"Result of parsing and rendering %s left extras: %s" % (
test, ops.extras))
class SplitQuotedTest(unittest.TestCase): class SplitQuotedTest(unittest.TestCase):
"""A unittest class that tests the split_quoted function.""" """A unittest class that tests the split_quoted function."""
@@ -1359,6 +1393,7 @@ class SplitQuotedTest(unittest.TestCase):
self.assertEqual(split_quoted('\\"\\""'), ['\\"']) self.assertEqual(split_quoted('\\"\\""'), ['\\"'])
self.assertEqual(split_quoted('"\\"\\""'), ['""']) self.assertEqual(split_quoted('"\\"\\""'), ['""'])
if __name__ == "__main__": if __name__ == "__main__":
doctest.testmod() doctest.testmod()
unittest.main() unittest.main()

View File

@@ -144,9 +144,10 @@ from zenmapCore.StringPool import unique
# The version of the Nmap DTD this file understands and emits. # The version of the Nmap DTD this file understands and emits.
XML_OUTPUT_VERSION = "1.04" XML_OUTPUT_VERSION = "1.04"
class HostInfo(object): class HostInfo(object):
def __init__(self): def __init__(self):
self.comment = None; self.comment = None
self._tcpsequence = {} self._tcpsequence = {}
self._osmatches = [] self._osmatches = []
self._ports = [] self._ports = []
@@ -233,13 +234,14 @@ class HostInfo(object):
"""Return the OS match with the highest accuracy.""" """Return the OS match with the highest accuracy."""
if not self._osmatches: if not self._osmatches:
return None return None
def osmatch_key(osmatch): def osmatch_key(osmatch):
try: try:
return -float(osmatch["accuracy"]) return -float(osmatch["accuracy"])
except ValueError: except ValueError:
return 0 return 0
return sorted(self._osmatches, key = osmatch_key)[0]
return sorted(self._osmatches, key=osmatch_key)[0]
# ports_used is a list like # ports_used is a list like
# [{'state': u'open', 'portid': u'22', 'proto': u'tcp'}, # [{'state': u'open', 'portid': u'22', 'proto': u'tcp'},
@@ -262,7 +264,7 @@ class HostInfo(object):
return self._uptime return self._uptime
# Avoid empty dict return # Avoid empty dict return
return {"seconds":"", "lastboot":""} return {"seconds": "", "lastboot": ""}
# ports is an array containing dicts of the form # ports is an array containing dicts of the form
# {'port_state': u'open', 'portid': u'22', 'protocol': u'tcp', # {'port_state': u'open', 'portid': u'22', 'protocol': u'tcp',
@@ -323,14 +325,16 @@ class HostInfo(object):
l.append((1, socket.inet_aton(self.ip["addr"]))) l.append((1, socket.inet_aton(self.ip["addr"])))
if self.ipv6: if self.ipv6:
try: try:
l.append((1, socket.inet_pton(socket.AF_INET6, self.ipv6["addr"]))) l.append((1,
socket.inet_pton(socket.AF_INET6, self.ipv6["addr"])))
except AttributeError: except AttributeError:
# Windows doesn't have socket.inet_pton. Go alphabetical. # Windows doesn't have socket.inet_pton. Go alphabetical.
# Encode to a byte string for possible comparison with binary # Encode to a byte string for possible comparison with binary
# address strings (which can't be converted to unicode). # address strings (which can't be converted to unicode).
l.append((1, self.ipv6["addr"].encode("utf-8"))) l.append((1, self.ipv6["addr"].encode("utf-8")))
if self.mac: if self.mac:
l.append((3, "".join([chr(int(x, 16)) for x in self.mac["addr"].split(":")]))) l.append((3, "".join(
chr(int(x, 16)) for x in self.mac["addr"].split(":"))))
l.sort() l.sort()
return l return l
@@ -386,7 +390,8 @@ class HostInfo(object):
return self.get_port_count_by_states(('open', 'open|filtered')) return self.get_port_count_by_states(('open', 'open|filtered'))
def get_filtered_ports(self): def get_filtered_ports(self):
return self.get_port_count_by_states(('filtered', 'open|filtered', 'closed|filtered')) return self.get_port_count_by_states(
('filtered', 'open|filtered', 'closed|filtered'))
def get_closed_ports(self): def get_closed_ports(self):
return self.get_port_count_by_states(('closed', 'closed|filtered')) return self.get_port_count_by_states(('closed', 'closed|filtered'))
@@ -395,7 +400,7 @@ class HostInfo(object):
scanned = 0 scanned = 0
for p in self.ports: for p in self.ports:
scanned+=1 scanned += 1
for extra in self.get_extraports(): for extra in self.get_extraports():
scanned += int(extra["count"]) scanned += int(extra["count"])
@@ -405,14 +410,16 @@ class HostInfo(object):
def get_services(self): def get_services(self):
services = [] services = []
for p in self.ports: for p in self.ports:
services.append({"service_name":p.get("service_name", _("unknown")), services.append({
"portid":p.get("portid", ""), "service_name": p.get("service_name", _("unknown")),
"service_version":p.get("service_version", "portid": p.get("portid", ""),
_("Unknown version")), "service_version": p.get("service_version",
"service_product":p.get("service_product", ""), _("Unknown version")),
"service_extrainfo":p.get("service_extrainfo", ""), "service_product": p.get("service_product", ""),
"port_state":p.get("port_state", _("Unknown")), "service_extrainfo": p.get("service_extrainfo", ""),
"protocol":p.get("protocol", "")}) "port_state": p.get("port_state", _("Unknown")),
"protocol": p.get("protocol", "")
})
return services return services
def get_trace(self): def get_trace(self):
@@ -448,19 +455,22 @@ class HostInfo(object):
services = property(get_services) services = property(get_services)
trace = property(get_trace, set_trace) trace = property(get_trace, set_trace)
class ParserBasics(object): class ParserBasics(object):
def __init__ (self): def __init__(self):
# This flag informs us whether the XML output file is temporary (True), # This flag informs us whether the XML output file is temporary (True),
# or user specified (False). If any of them is user-specified, it # or user specified (False). If any of them is user-specified, it
# doesn't get stripped out of the command string in set_nmap_command. # doesn't get stripped out of the command string in set_nmap_command.
self.xml_is_temp = True self.xml_is_temp = True
self.nmap = {'nmaprun':{},\ self.nmap = {
'scaninfo':[],\ 'nmaprun': {},
'verbose':'',\ 'scaninfo': [],
'debugging':'',\ 'verbose': '',
'hosts':[],\ 'debugging': '',
'runstats':{}} 'hosts': [],
'runstats': {}
}
self.ops = NmapOptions() self.ops = NmapOptions()
self._nmap_output = None self._nmap_output = None
@@ -490,13 +500,13 @@ class ParserBasics(object):
def set_nmap_output(self, nmap_output): def set_nmap_output(self, nmap_output):
self._nmap_output = nmap_output self._nmap_output = nmap_output
def get_debugging_level (self): def get_debugging_level(self):
return self.nmap.get('debugging', '') return self.nmap.get('debugging', '')
def set_debugging_level(self, level): def set_debugging_level(self, level):
self.nmap['debugging'] = level self.nmap['debugging'] = level
def get_verbose_level (self): def get_verbose_level(self):
return self.nmap.get('verbose', '') return self.nmap.get('verbose', '')
def set_verbose_level(self, level): def set_verbose_level(self, level):
@@ -508,7 +518,7 @@ class ParserBasics(object):
def set_scaninfo(self, info): def set_scaninfo(self, info):
self.nmap['scaninfo'] = info self.nmap['scaninfo'] = info
def get_services_scanned (self): def get_services_scanned(self):
if self._services_scanned == None: if self._services_scanned == None:
return self._services_scanned return self._services_scanned
@@ -519,10 +529,10 @@ class ParserBasics(object):
self._services_scanned = ','.join(services) self._services_scanned = ','.join(services)
return self._services_scanned return self._services_scanned
def set_services_scanned (self, services_scanned): def set_services_scanned(self, services_scanned):
self._services_scanned = services_scanned self._services_scanned = services_scanned
def get_nmap_command (self): def get_nmap_command(self):
return self.ops.render_string() return self.ops.render_string()
def set_nmap_command(self, command): def set_nmap_command(self, command):
@@ -531,19 +541,19 @@ class ParserBasics(object):
self.ops["-oX"] = None self.ops["-oX"] = None
self.nmap['nmaprun']['args'] = self.ops.render_string() self.nmap['nmaprun']['args'] = self.ops.render_string()
def get_scan_type (self): def get_scan_type(self):
types = [] types = []
for t in self.nmap.get('scaninfo', []): for t in self.nmap.get('scaninfo', []):
types.append(t['type']) types.append(t['type'])
return types return types
def get_protocol (self): def get_protocol(self):
protocols = [] protocols = []
for proto in self.nmap.get('scaninfo', []): for proto in self.nmap.get('scaninfo', []):
protocols.append(proto['protocol']) protocols.append(proto['protocol'])
return protocols return protocols
def get_num_services (self): def get_num_services(self):
if self._num_services == None: if self._num_services == None:
return self._num_services return self._num_services
@@ -554,12 +564,12 @@ class ParserBasics(object):
self._num_services = num self._num_services = num
return self._num_services return self._num_services
def set_num_services (self, num_services): def set_num_services(self, num_services):
self._num_services = num_services self._num_services = num_services
def get_date (self): def get_date(self):
epoch = int(self.nmap['nmaprun'].get('start', '0')) epoch = int(self.nmap['nmaprun'].get('start', '0'))
return time.localtime (epoch) return time.localtime(epoch)
def get_start(self): def get_start(self):
return self.nmap['nmaprun'].get('start', '0') return self.nmap['nmaprun'].get('start', '0')
@@ -601,13 +611,13 @@ in epoch format!")
def get_formatted_date(self): def get_formatted_date(self):
return time.strftime("%B %d, %Y - %H:%M", self.get_date()) return time.strftime("%B %d, %Y - %H:%M", self.get_date())
def get_scanner (self): def get_scanner(self):
return self.nmap['nmaprun'].get('scanner', '') return self.nmap['nmaprun'].get('scanner', '')
def set_scanner(self, scanner): def set_scanner(self, scanner):
self.nmap['nmaprun']['scanner'] = scanner self.nmap['nmaprun']['scanner'] = scanner
def get_scanner_version (self): def get_scanner_version(self):
return self.nmap['nmaprun'].get('version', '') return self.nmap['nmaprun'].get('version', '')
def set_scanner_version(self, version): def set_scanner_version(self, version):
@@ -634,7 +644,7 @@ in epoch format!")
return [] return []
return [host.ipv6 for host in hosts if host.ipv6 is not None] return [host.ipv6 for host in hosts if host.ipv6 is not None]
def get_hostnames (self): def get_hostnames(self):
hostnames = [] hostnames = []
for host in self.nmap.get('hosts', []): for host in self.nmap.get('hosts', []):
hostnames += host.get_hostnames() hostnames += host.get_hostnames()
@@ -667,7 +677,7 @@ in epoch format!")
def set_hosts_scanned(self, scanned): def set_hosts_scanned(self, scanned):
self.nmap['runstats']['hosts_scanned'] = int(scanned) self.nmap['runstats']['hosts_scanned'] = int(scanned)
def get_finish_time (self): def get_finish_time(self):
return time.localtime(int(self.nmap['runstats'].get('finished_time', return time.localtime(int(self.nmap['runstats'].get('finished_time',
'0'))) '0')))
@@ -686,7 +696,8 @@ in epoch format!")
if scan_name: if scan_name:
return scan_name return scan_name
if self.profile_name and self.get_targets(): if self.profile_name and self.get_targets():
return _("%s on %s") % (self.profile_name, join_quoted(self.get_targets())) return _("%s on %s") % (self.profile_name,
join_quoted(self.get_targets()))
return self.get_nmap_command() return self.get_nmap_command()
def set_scan_name(self, scan_name): def set_scan_name(self, scan_name):
@@ -710,8 +721,8 @@ in epoch format!")
ports[int(item)] = [] ports[int(item)] = []
ports[int(item)].append(scaninfo['protocol']) ports[int(item)].append(scaninfo['protocol'])
else: else:
begin,end = item.split('-') begin, end = item.split('-')
for port in range(int(begin),int(end)+1): for port in range(int(begin), int(end) + 1):
if int(port) not in ports: if int(port) not in ports:
ports[int(port)] = [] ports[int(port)] = []
ports[int(port)].append(scaninfo['protocol']) ports[int(port)].append(scaninfo['protocol'])
@@ -752,6 +763,7 @@ in epoch format!")
_num_services = None _num_services = None
_services_scanned = None _services_scanned = None
class NmapParserSAX(ParserBasics, ContentHandler): class NmapParserSAX(ParserBasics, ContentHandler):
def __init__(self): def __init__(self):
ParserBasics.__init__(self) ParserBasics.__init__(self)
@@ -793,14 +805,15 @@ class NmapParserSAX(ParserBasics, ContentHandler):
def _parse_nmaprun(self, attrs): def _parse_nmaprun(self, attrs):
run_tag = "nmaprun" run_tag = "nmaprun"
if self._nmap_output is None and attrs.has_key("nmap_output"): if self._nmap_output is None and "nmap_output" in attrs:
self._nmap_output = attrs["nmap_output"] self._nmap_output = attrs["nmap_output"]
self.nmap[run_tag]["profile_name"] = attrs.get("profile_name", "") self.nmap[run_tag]["profile_name"] = attrs.get("profile_name", "")
self.nmap[run_tag]["start"] = attrs.get("start", "") self.nmap[run_tag]["start"] = attrs.get("start", "")
self.nmap[run_tag]["args"] = attrs.get("args", "") self.nmap[run_tag]["args"] = attrs.get("args", "")
self.nmap[run_tag]["scanner"] = attrs.get("scanner", "") self.nmap[run_tag]["scanner"] = attrs.get("scanner", "")
self.nmap[run_tag]["version"] = attrs.get("version", "") self.nmap[run_tag]["version"] = attrs.get("version", "")
self.nmap[run_tag]["xmloutputversion"] = attrs.get("xmloutputversion", "") self.nmap[run_tag]["xmloutputversion"] = attrs.get(
"xmloutputversion", "")
self.nmap_command = self.nmap[run_tag]["args"] self.nmap_command = self.nmap[run_tag]["args"]
@@ -844,9 +857,9 @@ class NmapParserSAX(ParserBasics, ContentHandler):
self.host_info.set_state(unique(attrs.get("state", ""))) self.host_info.set_state(unique(attrs.get("state", "")))
def _parse_host_address(self, attrs): def _parse_host_address(self, attrs):
address_attributes = {"type":unique(attrs.get("addrtype", "")), address_attributes = {"type": unique(attrs.get("addrtype", "")),
"vendor":attrs.get("vendor", ""), "vendor": attrs.get("vendor", ""),
"addr":attrs.get("addr", "")} "addr": attrs.get("addr", "")}
if address_attributes["type"] == "ipv4": if address_attributes["type"] == "ipv4":
self.host_info.set_ip(address_attributes) self.host_info.set_ip(address_attributes)
@@ -856,16 +869,16 @@ class NmapParserSAX(ParserBasics, ContentHandler):
self.host_info.set_mac(address_attributes) self.host_info.set_mac(address_attributes)
def _parse_host_hostname(self, attrs): def _parse_host_hostname(self, attrs):
self.list_hostnames.append({"hostname":attrs.get("name", ""), self.list_hostnames.append({"hostname": attrs.get("name", ""),
"hostname_type":attrs.get("type", "")}) "hostname_type": attrs.get("type", "")})
def _parse_host_extraports(self, attrs): def _parse_host_extraports(self, attrs):
self.list_extraports.append({"state":unique(attrs.get("state", "")), self.list_extraports.append({"state": unique(attrs.get("state", "")),
"count":attrs.get("count", "")}) "count": attrs.get("count", "")})
def _parse_host_port(self, attrs): def _parse_host_port(self, attrs):
self.dic_port = {"protocol":unique(attrs.get("protocol", "")), self.dic_port = {"protocol": unique(attrs.get("protocol", "")),
"portid":unique(attrs.get("portid", ""))} "portid": unique(attrs.get("portid", ""))}
def _parse_host_port_state(self, attrs): def _parse_host_port_state(self, attrs):
self.dic_port["port_state"] = unique(attrs.get("state", "")) self.dic_port["port_state"] = unique(attrs.get("state", ""))
@@ -886,10 +899,12 @@ class NmapParserSAX(ParserBasics, ContentHandler):
self.list_osmatch.append(osmatch) self.list_osmatch.append(osmatch)
def _parse_host_portused(self, attrs): def _parse_host_portused(self, attrs):
self.list_portused.append(self._parsing(attrs, ['state', 'proto', 'portid'], [])) self.list_portused.append(self._parsing(
attrs, ['state', 'proto', 'portid'], []))
def _parse_host_osclass(self, attrs): def _parse_host_osclass(self, attrs):
self.list_osclass.append(self._parsing(attrs, ['type', 'vendor', 'osfamily', 'osgen'], ['accuracy'])) self.list_osclass.append(self._parsing(
attrs, ['type', 'vendor', 'osfamily', 'osgen'], ['accuracy']))
def _parsing(self, attrs, unique_names, other_names): def _parsing(self, attrs, unique_names, other_names):
# Returns a dict with the attributes of a given tag with the # Returns a dict with the attributes of a given tag with the
@@ -902,17 +917,20 @@ class NmapParserSAX(ParserBasics, ContentHandler):
return dic return dic
def _parse_host_uptime(self, attrs): def _parse_host_uptime(self, attrs):
self.host_info.set_uptime(self._parsing(attrs, [], ["seconds", "lastboot"])) self.host_info.set_uptime(self._parsing(
attrs, [], ["seconds", "lastboot"]))
def _parse_host_tcpsequence(self, attrs): def _parse_host_tcpsequence(self, attrs):
self.host_info.set_tcpsequence(self._parsing(attrs, ['difficulty'], ['index', 'values'])) self.host_info.set_tcpsequence(self._parsing(
attrs, ['difficulty'], ['index', 'values']))
def _parse_host_tcptssequence(self, attrs): def _parse_host_tcptssequence(self, attrs):
self.host_info.set_tcptssequence(self._parsing(attrs, ['class'], ['values'])) self.host_info.set_tcptssequence(self._parsing(
attrs, ['class'], ['values']))
def _parse_host_ipidsequence(self, attrs): def _parse_host_ipidsequence(self, attrs):
self.host_info.set_ipidsequence(self._parsing(attrs, ['class'], ['values'])) self.host_info.set_ipidsequence(self._parsing(
attrs, ['class'], ['values']))
def _parse_host_trace(self, attrs): def _parse_host_trace(self, attrs):
trace = {} trace = {}
@@ -1002,7 +1020,6 @@ class NmapParserSAX(ParserBasics, ContentHandler):
elif self.in_host and self.in_trace and name == "error": elif self.in_host and self.in_trace and name == "error":
self._parse_host_trace_error(attrs) self._parse_host_trace_error(attrs)
def endElement(self, name): def endElement(self, name):
if name == "runstats": if name == "runstats":
self.in_interactive_output = False self.in_interactive_output = False
@@ -1052,7 +1069,8 @@ class NmapParserSAX(ParserBasics, ContentHandler):
writer = XMLGenerator(f) writer = XMLGenerator(f)
writer.startDocument() writer.startDocument()
if self.xml_stylesheet_data is not None: if self.xml_stylesheet_data is not None:
writer.processingInstruction("xml-stylesheet", self.xml_stylesheet_data) writer.processingInstruction(
"xml-stylesheet", self.xml_stylesheet_data)
self._write_nmaprun(writer) self._write_nmaprun(writer)
self._write_scaninfo(writer) self._write_scaninfo(writer)
self._write_verbose(writer) self._write_verbose(writer)
@@ -1092,18 +1110,18 @@ class NmapParserSAX(ParserBasics, ContentHandler):
## Finished element ## Finished element
writer.startElement("finished", writer.startElement("finished",
Attributes(dict(time = str(self.finish_epoc_time), Attributes(dict(time=str(self.finish_epoc_time),
timestr = time.ctime(time.mktime(self.get_finish_time()))))) timestr=time.ctime(time.mktime(
self.get_finish_time())))))
writer.endElement("finished") writer.endElement("finished")
## Hosts element ## Hosts element
writer.startElement("hosts", writer.startElement("hosts",
Attributes(dict(up = str(self.hosts_up), Attributes(dict(up=str(self.hosts_up),
down = str(self.hosts_down), down=str(self.hosts_down),
total = str(self.hosts_scanned)))) total=str(self.hosts_scanned))))
writer.endElement("hosts") writer.endElement("hosts")
writer.endElement("runstats") writer.endElement("runstats")
# End of Runstats element # End of Runstats element
######################### #########################
@@ -1119,7 +1137,6 @@ class NmapParserSAX(ParserBasics, ContentHandler):
Attributes(dict(state=host.state))) Attributes(dict(state=host.state)))
writer.endElement("status") writer.endElement("status")
################## ##################
# Address elements # Address elements
## IPv4 ## IPv4
@@ -1148,15 +1165,14 @@ class NmapParserSAX(ParserBasics, ContentHandler):
# End of Address elements # End of Address elements
######################### #########################
################### ###################
# Hostnames element # Hostnames element
writer.startElement("hostnames", Attributes({})) writer.startElement("hostnames", Attributes({}))
for hname in host.hostnames: for hname in host.hostnames:
writer.startElement("hostname", writer.startElement("hostname",
Attributes(dict(name = hname.get("hostname", ""), Attributes(dict(name=hname.get("hostname", ""),
type = hname.get("hostname_type", "")))) type=hname.get("hostname_type", ""))))
writer.endElement("hostname") writer.endElement("hostname")
@@ -1164,7 +1180,6 @@ class NmapParserSAX(ParserBasics, ContentHandler):
# End of Hostnames element # End of Hostnames element
########################## ##########################
############### ###############
# Ports element # Ports element
writer.startElement("ports", Attributes({})) writer.startElement("ports", Attributes({}))
@@ -1172,15 +1187,15 @@ class NmapParserSAX(ParserBasics, ContentHandler):
## Extraports elements ## Extraports elements
for ext in host.get_extraports(): for ext in host.get_extraports():
writer.startElement("extraports", writer.startElement("extraports",
Attributes(dict(count = ext.get("count", ""), Attributes(dict(count=ext.get("count", ""),
state = ext.get("state", "")))) state=ext.get("state", ""))))
writer.endElement("extraports") writer.endElement("extraports")
## Port elements ## Port elements
for p in host.ports: for p in host.ports:
writer.startElement("port", writer.startElement("port",
Attributes(dict(portid = p.get("portid", ""), Attributes(dict(portid=p.get("portid", ""),
protocol = p.get("protocol", "")))) protocol=p.get("protocol", ""))))
### Port state ### Port state
writer.startElement("state", writer.startElement("state",
@@ -1208,7 +1223,6 @@ class NmapParserSAX(ParserBasics, ContentHandler):
# End of Ports element # End of Ports element
###################### ######################
############ ############
# OS element # OS element
writer.startElement("os", Attributes({})) writer.startElement("os", Attributes({}))
@@ -1216,25 +1230,25 @@ class NmapParserSAX(ParserBasics, ContentHandler):
## Ports used elements ## Ports used elements
for pu in host.ports_used: for pu in host.ports_used:
writer.startElement("portused", writer.startElement("portused",
Attributes(dict(state = pu.get("state", ""), Attributes(dict(state=pu.get("state", ""),
proto = pu.get("proto", ""), proto=pu.get("proto", ""),
portid = pu.get("portid", "")))) portid=pu.get("portid", ""))))
writer.endElement("portused") writer.endElement("portused")
## Osmatch elements ## Osmatch elements
for om in host.osmatches: for om in host.osmatches:
writer.startElement("osmatch", writer.startElement("osmatch",
Attributes(dict(name = om.get("name", ""), Attributes(dict(name=om.get("name", ""),
accuracy = om.get("accuracy", ""), accuracy=om.get("accuracy", ""),
line = om.get("line", "")))) line=om.get("line", ""))))
## Osclass elements ## Osclass elements
for oc in om['osclasses']: for oc in om['osclasses']:
writer.startElement("osclass", writer.startElement("osclass",
Attributes(dict(vendor = oc.get("vendor", ""), Attributes(dict(vendor=oc.get("vendor", ""),
osfamily = oc.get("osfamily", ""), osfamily=oc.get("osfamily", ""),
type = oc.get("type", ""), type=oc.get("type", ""),
osgen = oc.get("osgen", ""), osgen=oc.get("osgen", ""),
accuracy = oc.get("accuracy", "")))) accuracy=oc.get("accuracy", ""))))
writer.endElement("osclass") writer.endElement("osclass")
writer.endElement("osmatch") writer.endElement("osmatch")
@@ -1244,8 +1258,8 @@ class NmapParserSAX(ParserBasics, ContentHandler):
# Uptime element # Uptime element
writer.startElement("uptime", writer.startElement("uptime",
Attributes(dict(seconds = host.uptime.get("seconds", ""), Attributes(dict(seconds=host.uptime.get("seconds", ""),
lastboot = host.uptime.get("lastboot", "")))) lastboot=host.uptime.get("lastboot", ""))))
writer.endElement("uptime") writer.endElement("uptime")
##################### #####################
@@ -1253,21 +1267,21 @@ class NmapParserSAX(ParserBasics, ContentHandler):
## TCP Sequence element ## TCP Sequence element
# Cannot use dict() here, because of the 'class' attribute. # Cannot use dict() here, because of the 'class' attribute.
writer.startElement("tcpsequence", writer.startElement("tcpsequence",
Attributes({"index":host.tcpsequence.get("index", ""), Attributes({"index": host.tcpsequence.get("index", ""),
"difficulty":host.tcpsequence.get("difficulty", ""), "difficulty": host.tcpsequence.get("difficulty", ""),
"values":host.tcpsequence.get("values", "")})) "values": host.tcpsequence.get("values", "")}))
writer.endElement("tcpsequence") writer.endElement("tcpsequence")
## IP ID Sequence element ## IP ID Sequence element
writer.startElement("ipidsequence", writer.startElement("ipidsequence",
Attributes({"class":host.ipidsequence.get("class", ""), Attributes({"class": host.ipidsequence.get("class", ""),
"values":host.ipidsequence.get("values", "")})) "values": host.ipidsequence.get("values", "")}))
writer.endElement("ipidsequence") writer.endElement("ipidsequence")
## TCP TS Sequence element ## TCP TS Sequence element
writer.startElement("tcptssequence", writer.startElement("tcptssequence",
Attributes({"class":host.tcptssequence.get("class", ""), Attributes({"class": host.tcptssequence.get("class", ""),
"values":host.tcptssequence.get("values", "")})) "values": host.tcptssequence.get("values", "")}))
writer.endElement("tcptssequence") writer.endElement("tcptssequence")
# End of sequences elements # End of sequences elements
########################### ###########################
@@ -1275,21 +1289,21 @@ class NmapParserSAX(ParserBasics, ContentHandler):
## Trace element ## Trace element
if len(host.trace) > 0: if len(host.trace) > 0:
writer.startElement("trace", writer.startElement("trace",
Attributes({"proto":host.trace.get("proto", ""), Attributes({"proto": host.trace.get("proto", ""),
"port":host.trace.get("port", "")})) "port": host.trace.get("port", "")}))
if "hops" in host.trace: if "hops" in host.trace:
for hop in host.trace["hops"]: for hop in host.trace["hops"]:
writer.startElement("hop", writer.startElement("hop",
Attributes({"ttl":hop["ttl"], Attributes({"ttl": hop["ttl"],
"rtt":hop["rtt"], "rtt": hop["rtt"],
"ipaddr":hop["ipaddr"], "ipaddr": hop["ipaddr"],
"host":hop["host"]})) "host": hop["host"]}))
writer.endElement("hop") writer.endElement("hop")
if "error" in host.trace: if "error" in host.trace:
writer.startElement("error", writer.startElement("error",
Attributes({"errorstr":host.trace["error"]})) Attributes({"errorstr": host.trace["error"]}))
writer.endElement("error") writer.endElement("error")
writer.endElement("trace") writer.endElement("trace")
@@ -1312,21 +1326,22 @@ class NmapParserSAX(ParserBasics, ContentHandler):
def _write_scaninfo(self, writer): def _write_scaninfo(self, writer):
for scan in self.scaninfo: for scan in self.scaninfo:
writer.startElement("scaninfo", writer.startElement("scaninfo",
Attributes(dict(type = scan.get("type", ""), Attributes(dict(type=scan.get("type", ""),
protocol = scan.get("protocol", ""), protocol=scan.get("protocol", ""),
numservices = scan.get("numservices", ""), numservices=scan.get("numservices", ""),
services = scan.get("services", "")))) services=scan.get("services", ""))))
writer.endElement("scaninfo") writer.endElement("scaninfo")
def _write_nmaprun(self, writer): def _write_nmaprun(self, writer):
writer.startElement("nmaprun", writer.startElement("nmaprun",
Attributes(dict(args = str(self.nmap_command), Attributes(dict(args=str(self.nmap_command),
profile_name = str(self.profile_name), profile_name=str(self.profile_name),
scanner = str(self.scanner), scanner=str(self.scanner),
start = str(self.start), start=str(self.start),
startstr = time.ctime(time.mktime(self.get_date())), startstr=time.ctime(
version = str(self.scanner_version), time.mktime(self.get_date())),
xmloutputversion = str(XML_OUTPUT_VERSION)))) version=str(self.scanner_version),
xmloutputversion=str(XML_OUTPUT_VERSION))))
def set_unsaved(self): def set_unsaved(self):
self.unsaved = True self.unsaved = True
@@ -1334,6 +1349,7 @@ class NmapParserSAX(ParserBasics, ContentHandler):
def is_unsaved(self): def is_unsaved(self):
return self.unsaved return self.unsaved
def nmap_parser_sax(): def nmap_parser_sax():
parser = make_parser() parser = make_parser()
nmap_parser = NmapParserSAX() nmap_parser = NmapParserSAX()
@@ -1345,6 +1361,7 @@ def nmap_parser_sax():
NmapParser = nmap_parser_sax NmapParser = nmap_parser_sax
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys

View File

@@ -133,6 +133,7 @@ from zenmapCore.Version import VERSION
from zenmapCore.Name import APP_NAME from zenmapCore.Name import APP_NAME
from zenmapCore.UmitOptionParser import option_parser from zenmapCore.UmitOptionParser import option_parser
# Find out the prefix under which data files (interface definition XML, # Find out the prefix under which data files (interface definition XML,
# pixmaps, etc.) are stored. This can vary depending on whether we are running # pixmaps, etc.) are stored. This can vary depending on whether we are running
# in an executable package and what type of package it is, which we check using # in an executable package and what type of package it is, which we check using
@@ -161,6 +162,8 @@ MISC_DIR = join(prefix, "share", APP_NAME, "misc")
PIXMAPS_DIR = join(prefix, "share", "zenmap", "pixmaps") PIXMAPS_DIR = join(prefix, "share", "zenmap", "pixmaps")
DOCS_DIR = join(prefix, "share", APP_NAME, "docs") DOCS_DIR = join(prefix, "share", APP_NAME, "docs")
NMAPDATADIR = join(prefix, "..") NMAPDATADIR = join(prefix, "..")
def get_extra_executable_search_paths(): def get_extra_executable_search_paths():
"""Return a list of additional executable search paths as a convenience for """Return a list of additional executable search paths as a convenience for
platforms where the default PATH is inadequate.""" platforms where the default PATH is inadequate."""
@@ -170,6 +173,7 @@ def get_extra_executable_search_paths():
return [dirname(sys.executable)] return [dirname(sys.executable)]
return [] return []
####### #######
# Paths # Paths
class Paths(object): class Paths(object):
@@ -194,7 +198,8 @@ class Paths(object):
def __init__(self): def __init__(self):
self.user_config_dir = option_parser.get_confdir() self.user_config_dir = option_parser.get_confdir()
self.user_config_file = os.path.join(self.user_config_dir, base_paths['user_config_file']) self.user_config_file = os.path.join(
self.user_config_dir, base_paths['user_config_file'])
self.config_dir = CONFIG_DIR self.config_dir = CONFIG_DIR
self.locale_dir = LOCALE_DIR self.locale_dir = LOCALE_DIR
self.pixmaps_dir = PIXMAPS_DIR self.pixmaps_dir = PIXMAPS_DIR
@@ -207,10 +212,12 @@ class Paths(object):
return self.__dict__[name] return self.__dict__[name]
elif name in self.config_files_list: elif name in self.config_files_list:
return return_if_exists(join(self.user_config_dir, base_paths[name])) return return_if_exists(
join(self.user_config_dir, base_paths[name]))
elif name in self.empty_config_files_list: elif name in self.empty_config_files_list:
return return_if_exists(join(self.user_config_dir, base_paths[name]), True) return return_if_exists(
join(self.user_config_dir, base_paths[name]), True)
elif name in self.misc_files_list: elif name in self.misc_files_list:
return return_if_exists(join(self.misc_dir, base_paths[name])) return return_if_exists(join(self.misc_dir, base_paths[name]))
@@ -223,15 +230,17 @@ class Paths(object):
def __setattr__(self, name, value): def __setattr__(self, name, value):
self.__dict__[name] = value self.__dict__[name] = value
def create_dir(path): def create_dir(path):
"""Create a directory with os.makedirs without raising an error if the """Create a directory with os.makedirs without raising an error if the
directory already exists.""" directory already exists."""
try: try:
os.makedirs(path) os.makedirs(path)
except OSError, e: except OSError, e:
if e.errno != errno.EEXIST: if e.errno != errno.EEXIST:
raise raise
def create_user_config_dir(user_dir, template_dir): def create_user_config_dir(user_dir, template_dir):
"""Create a user configuration directory by creating the directory if """Create a user configuration directory by creating the directory if
necessary, then copying all the files from the given template directory, necessary, then copying all the files from the given template directory,
@@ -253,6 +262,7 @@ def create_user_config_dir(user_dir, template_dir):
shutil.copyfile(template_filename, user_filename) shutil.copyfile(template_filename, user_filename)
log.debug(">>> Copy %s to %s." % (template_filename, user_filename)) log.debug(">>> Copy %s to %s." % (template_filename, user_filename))
def return_if_exists(path, create=False): def return_if_exists(path, create=False):
path = os.path.abspath(path) path = os.path.abspath(path)
if os.path.exists(path): if os.path.exists(path):

View File

@@ -124,6 +124,7 @@ from os import access, R_OK, W_OK
from os.path import dirname from os.path import dirname
from zenmapCore.Paths import Path from zenmapCore.Paths import Path
class RecentScans(object): class RecentScans(object):
def __init__(self): def __init__(self):
self.temp_list = [] self.temp_list = []

View File

@@ -131,6 +131,7 @@ quoted_re = re.compile(r'\s*(([\'"])(.*?[^\\])\2)\s*([},=]|$)')
# "^%s*(['\"])%1%s*[},=]" # "^%s*(['\"])%1%s*[},=]"
empty_re = re.compile(r'\s*(([\'"])\2)\s*([},=]|$)') empty_re = re.compile(r'\s*(([\'"])\2)\s*([},=]|$)')
def parse_string(s, start): def parse_string(s, start):
"""Parses a single string that is quoted, unquoted or empty. It returns the """Parses a single string that is quoted, unquoted or empty. It returns the
found string along with the next starting position """ found string along with the next starting position """
@@ -140,6 +141,7 @@ def parse_string(s, start):
return m.group(1), m.end(1) return m.group(1), m.end(1)
raise ValueError("No string found at %s." % repr(s[start:])) raise ValueError("No string found at %s." % repr(s[start:]))
def next_char(s, start): def next_char(s, start):
"""Returns the next character and position in the string.""" """Returns the next character and position in the string."""
while start < len(s) and s[start].isspace(): while start < len(s) and s[start].isspace():
@@ -149,6 +151,7 @@ def next_char(s, start):
else: else:
return None, start return None, start
def parse_value(s, start): def parse_value(s, start):
"""If the string starting from start is a name-value pair, returns a """If the string starting from start is a name-value pair, returns a
name-value tuple. Otherwise returns a plain string.""" name-value tuple. Otherwise returns a plain string."""
@@ -172,6 +175,7 @@ def parse_value(s, start):
else: else:
return s[start:j], j return s[start:j], j
def parse_table(s, start): def parse_table(s, start):
"""This function is responsible for parsing a table; i.e, a string that """This function is responsible for parsing a table; i.e, a string that
starts with '{'. It returns the position where the balancing pair of braces starts with '{'. It returns the position where the balancing pair of braces
@@ -192,6 +196,7 @@ def parse_table(s, start):
if nc == ",": if nc == ",":
j += 1 j += 1
def parse_script_args(s): def parse_script_args(s):
"""Main function responsible for parsing the script args and storing the """Main function responsible for parsing the script args and storing the
name-value pairs in a list. If an invalid argument is present it stores the name-value pairs in a list. If an invalid argument is present it stores the
@@ -202,7 +207,8 @@ def parse_script_args(s):
while nc is not None: while nc is not None:
val, j = parse_value(s, j) val, j = parse_value(s, j)
if type(val) == str: if type(val) == str:
raise ValueError("Only name-value pairs expected in parse_script_args.") raise ValueError(
"Only name-value pairs expected in parse_script_args.")
else: else:
args.append(val) args.append(val)
nc, j = next_char(s, j) nc, j = next_char(s, j)
@@ -213,6 +219,7 @@ def parse_script_args(s):
return None return None
return args return args
def parse_script_args_dict(raw_argument): def parse_script_args_dict(raw_argument):
"""Wrapper function that copies the name-value pairs from a list into a """Wrapper function that copies the name-value pairs from a list into a
dictionary.""" dictionary."""
@@ -221,7 +228,7 @@ def parse_script_args_dict(raw_argument):
if args is None: if args is None:
return None return None
for item in args: for item in args:
if(len(item) == 2): # only key/value pairs are stored if(len(item) == 2): # only key/value pairs are stored
args_dict[item[0]] = item[1] args_dict[item[0]] = item[1]
return args_dict return args_dict
@@ -234,7 +241,11 @@ if __name__ == '__main__':
('a={one,{two,{three}}}', [('a', '{one,{two,{three}}}')]), ('a={one,{two,{three}}}', [('a', '{one,{two,{three}}}')]),
('a={"quoted}quoted"}', [('a', '{"quoted}quoted"}')]), ('a={"quoted}quoted"}', [('a', '{"quoted}quoted"}')]),
('a="unterminated', None), ('a="unterminated', None),
('user=foo,pass=",{}=bar",whois={whodb=nofollow+ripe},userdb=C:\\Some\\Path\\To\\File', [('user', 'foo'), ('pass', '",{}=bar"'), ('whois', '{whodb=nofollow+ripe}'), ('userdb', 'C:\\Some\\Path\\To\\File')]), ('user=foo,pass=",{}=bar",whois={whodb=nofollow+ripe},'
'userdb=C:\\Some\\Path\\To\\File',
[('user', 'foo'), ('pass', '",{}=bar"'),
('whois', '{whodb=nofollow+ripe}'),
('userdb', 'C:\\Some\\Path\\To\\File')]),
) )
for test, expected in TESTS: for test, expected in TESTS:
@@ -242,7 +253,7 @@ if __name__ == '__main__':
print args_dict print args_dict
args = parse_script_args(test) args = parse_script_args(test)
if args == expected: if args == expected:
print "PASS" , test print "PASS", test
continue continue
print "FAIL", test print "FAIL", test
if args is None: if args is None:

View File

@@ -131,6 +131,7 @@ import sys
from zenmapCore.Paths import Path from zenmapCore.Paths import Path
from zenmapCore.UmitLogging import log from zenmapCore.UmitLogging import log
class ScriptDB (object): class ScriptDB (object):
"""Class responsible for parsing the script.db file, fetching script """Class responsible for parsing the script.db file, fetching script
names and categories.""" names and categories."""
@@ -138,7 +139,8 @@ class ScriptDB (object):
"a": "\a", "b": "\b", "f": "\f", "n": "\n", "r": "\r", "a": "\a", "b": "\b", "f": "\f", "n": "\n", "r": "\r",
"t": "\t", "v": "\v", "\\": "\\", "\"": "\"", "'": "'", "0": "\0" "t": "\t", "v": "\v", "\\": "\\", "\"": "\"", "'": "'", "0": "\0"
} }
def __init__(self, script_db_path = None):
def __init__(self, script_db_path=None):
self.unget_buf = "" self.unget_buf = ""
self.f = open(script_db_path, "r") self.f = open(script_db_path, "r")
@@ -162,7 +164,8 @@ class ScriptDB (object):
def parse(self): def parse(self):
"""Parses a script.db entry and returns it as a dictionary. An entry """Parses a script.db entry and returns it as a dictionary. An entry
looks like this: looks like this:
Entry { filename = "afp-brute.nse", categories = { "auth", "intrusive", } } Entry { filename = "afp-brute.nse", categories = \
{ "auth", "intrusive", } }
""" """
entries = [] entries = []
while True: while True:
@@ -238,7 +241,8 @@ class ScriptDB (object):
if not token or token[0] != "string": if not token or token[0] != "string":
raise ScriptDBSyntaxError() raise ScriptDBSyntaxError()
entry["filename"] = token[1] entry["filename"] = token[1]
self.expect((("delim", ","), ("ident", "categories"), ("delim", "="), ("delim", "{"))) self.expect((("delim", ","), ("ident", "categories"),
("delim", "="), ("delim", "{")))
entry["categories"] = [] entry["categories"] = []
token = self.token() token = self.token()
if token and token[0] == "string": if token and token[0] == "string":
@@ -263,6 +267,7 @@ class ScriptDB (object):
def get_entries_list(self): def get_entries_list(self):
return self.entries_list return self.entries_list
def nsedoc_tags_iter(f): def nsedoc_tags_iter(f):
in_doc_comment = False in_doc_comment = False
tag_name = None tag_name = None
@@ -296,6 +301,7 @@ def nsedoc_tags_iter(f):
tag_name = None tag_name = None
tag_text = None tag_text = None
class ScriptMetadata (object): class ScriptMetadata (object):
"""Class responsible for parsing all the script information.""" """Class responsible for parsing all the script information."""
@@ -305,14 +311,15 @@ class ScriptMetadata (object):
def __init__(self, filename): def __init__(self, filename):
self.filename = filename self.filename = filename
self.categories = [] self.categories = []
self.arguments = [] # Arguments including library arguments. self.arguments = [] # Arguments including library arguments.
self.license = "" self.license = ""
self.author = "" self.author = ""
self.description = "" self.description = ""
self.output = "" self.output = ""
self.usage = "" self.usage = ""
url = property(lambda self: "http://nmap.org/nsedoc/scripts/" + os.path.splitext(self.filename)[0] + ".html") url = property(lambda self: "http://nmap.org/nsedoc/scripts/"
"%s.html" % (os.path.splitext(self.filename)[0]))
def __init__(self, scripts_dir, nselib_dir): def __init__(self, scripts_dir, nselib_dir):
self.scripts_dir = scripts_dir self.scripts_dir = scripts_dir
@@ -351,13 +358,16 @@ class ScriptMetadata (object):
return contents return contents
def get_string_variable(self, filename, varname): def get_string_variable(self, filename, varname):
contents = ScriptMetadata.get_file_contents(os.path.join(self.scripts_dir, filename)) contents = ScriptMetadata.get_file_contents(
os.path.join(self.scripts_dir, filename))
# Short string? # Short string?
m = re.search(re.escape(varname) + r'\s*=\s*(["\'])(.*?[^\\])\1', contents) m = re.search(
re.escape(varname) + r'\s*=\s*(["\'])(.*?[^\\])\1', contents)
if m: if m:
return m.group(2) return m.group(2)
# Long string? # Long string?
m = re.search(re.escape(varname) + r'\s*=\s*\[(=*)\[(.*?)\]\1\]', contents, re.S) m = re.search(
re.escape(varname) + r'\s*=\s*\[(=*)\[(.*?)\]\1\]', contents, re.S)
if m: if m:
return m.group(2) return m.group(2)
return None return None
@@ -398,7 +408,7 @@ class ScriptMetadata (object):
for tag_name, tag_text in nsedoc_tags_iter(f): for tag_name, tag_text in nsedoc_tags_iter(f):
m = re.match(r'([\w._-]+)', tag_text) m = re.match(r'([\w._-]+)', tag_text)
if (tag_name == "arg" or tag_name == "args") and m: if (tag_name == "arg" or tag_name == "args") and m:
args.append((m.group(1), re.sub(r'^[\w._-]+','',tag_text))) args.append((m.group(1), re.sub(r'^[\w._-]+', '', tag_text)))
return args return args
def get_arguments(self, filename): def get_arguments(self, filename):
@@ -444,6 +454,7 @@ class ScriptMetadata (object):
self.library_arguments[libname] = self.get_script_args(filepath) self.library_arguments[libname] = self.get_script_args(filepath)
self.library_requires[libname] = self.get_requires(filepath) self.library_requires[libname] = self.get_requires(filepath)
def get_script_entries(scripts_dir, nselib_dir): def get_script_entries(scripts_dir, nselib_dir):
"""Merge the information obtained so far into one single entry for """Merge the information obtained so far into one single entry for
each script and return it.""" each script and return it."""

View File

@@ -134,6 +134,7 @@ from zenmapCore.NmapOptions import NmapOptions
from zenmapCore.NmapParser import NmapParser from zenmapCore.NmapParser import NmapParser
from zenmapCore.UmitLogging import log from zenmapCore.UmitLogging import log
class HostSearch(object): class HostSearch(object):
@staticmethod @staticmethod
def match_target(host, name): def match_target(host, name):
@@ -142,16 +143,20 @@ class HostSearch(object):
ip = host.get_ip() ip = host.get_ip()
ipv6 = host.get_ipv6() ipv6 = host.get_ipv6()
if mac and mac.has_key('addr'): if mac and 'addr' in mac:
if name in mac['addr'].lower(): return True if name in mac['addr'].lower():
if ip and ip.has_key('addr'): return True
if name in ip['addr'].lower(): return True if ip and 'addr' in ip:
if ipv6 and ipv6.has_key('addr'): if name in ip['addr'].lower():
if name in ipv6['addr'].lower(): return True return True
if ipv6 and 'addr' in ipv6:
if name in ipv6['addr'].lower():
return True
if HostSearch.match_hostname(host, name): if HostSearch.match_hostname(host, name):
return True return True
return False return False
@staticmethod @staticmethod
def match_hostname(host, hostname): def match_hostname(host, hostname):
hostname = hostname.lower() hostname = hostname.lower()
@@ -161,20 +166,27 @@ class HostSearch(object):
return True return True
else: else:
return False return False
@staticmethod @staticmethod
def match_service(host, service): def match_service(host, service):
for port in host.get_ports(): for port in host.get_ports():
# We concatenate all useful fields and add them to the list # We concatenate all useful fields and add them to the list
if port['port_state'] not in ['open','open|filtered']: if port['port_state'] not in ['open', 'open|filtered']:
continue continue
version = port.get("service_name", "") + " " + \ version = " ".join(
port.get("service_product", "") + " " + \ port.get(x, "") for x in (
port.get("service_version", "") + " " + \ "service_name",
port.get("service_extrainfo", "") "service_product",
"service_version",
"service_extrainfo"
)
)
if service in version.lower(): if service in version.lower():
return True return True
else: else:
return False return False
@staticmethod @staticmethod
def match_os(host, os): def match_os(host, os):
os = os.lower() os = os.lower()
@@ -191,6 +203,7 @@ class HostSearch(object):
return True return True
return False return False
@staticmethod @staticmethod
def match_port(host_ports, port, port_state): def match_port(host_ports, port, port_state):
# Check if the port is parsable, if not return False silently # Check if the port is parsable, if not return False silently
@@ -203,6 +216,7 @@ class HostSearch(object):
return False return False
class SearchResult(object): class SearchResult(object):
def __init__(self): def __init__(self):
"""This constructor is always called by SearchResult subclasses.""" """This constructor is always called by SearchResult subclasses."""
@@ -223,8 +237,8 @@ class SearchResult(object):
# No match => we discard this scan_result # No match => we discard this scan_result
break break
else: else:
# All operator-matching functions have returned True, so this scan_result # All operator-matching functions have returned True, so this
# satisfies all conditions # scan_result satisfies all conditions
yield self.parsed_scan yield self.parsed_scan
def _match_all_args(self, operator, args): def _match_all_args(self, operator, args):
@@ -250,7 +264,8 @@ class SearchResult(object):
if keyword == "*" or keyword == "": if keyword == "*" or keyword == "":
return True return True
return keyword.lower() in str(self.parsed_scan.__getattribute__(property)).lower() return keyword.lower() in str(
self.parsed_scan.__getattribute__(property)).lower()
def match_keyword(self, keyword): def match_keyword(self, keyword):
log.debug("Match keyword: %s" % keyword) log.debug("Match keyword: %s" % keyword)
@@ -261,7 +276,8 @@ class SearchResult(object):
def match_profile(self, profile): def match_profile(self, profile):
log.debug("Match profile: %s" % profile) log.debug("Match profile: %s" % profile)
log.debug("Comparing: %s == %s ??" % (str(self.parsed_scan.profile_name).lower(), log.debug("Comparing: %s == %s ??" % (
str(self.parsed_scan.profile_name).lower(),
"*%s*" % profile.lower())) "*%s*" % profile.lower()))
if profile == "*" or profile == "" or \ if profile == "*" or profile == "" or \
profile.lower() in str(self.parsed_scan.profile_name).lower(): profile.lower() in str(self.parsed_scan.profile_name).lower():
@@ -274,18 +290,20 @@ class SearchResult(object):
if option == "*" or option == "": if option == "*" or option == "":
return True return True
# NOTE: Option matching treats "_" and "-" the same, just like the optcmp # NOTE: Option matching treats "_" and "-" the same, just like the
# function in utils.cc . Also, option matching is case-sensitive. # optcmp function in utils.cc . Also, option matching is
# case-sensitive.
option = option.replace("_", "-") option = option.replace("_", "-")
ops = NmapOptions() ops = NmapOptions()
ops.parse_string(self.parsed_scan.get_nmap_command()) ops.parse_string(self.parsed_scan.get_nmap_command())
if "(" in option and ")" in option: if "(" in option and ")" in option:
# The syntax allows matching option arguments as "opt:option_name(value)". # The syntax allows matching option arguments as
# Since we've received only the "option_name(value)" part, we need to parse it. # "opt:option_name(value)". Since we've received only the
# "option_name(value)" part, we need to parse it.
optname = option[:option.find("(")] optname = option[:option.find("(")]
optval = option[option.find("(")+1:option.find(")")] optval = option[option.find("(") + 1:option.find(")")]
val = ops["--" + optname] val = ops["--" + optname]
if val is None: if val is None:
@@ -294,7 +312,8 @@ class SearchResult(object):
return False return False
return str(val) == optval or str(val) == optval return str(val) == optval or str(val) == optval
else: else:
return ops["--" + option] is not None or ops["-" + option] is not None return (ops["--" + option] is not None or
ops["-" + option] is not None)
def match_date(self, date_arg, operator="date"): def match_date(self, date_arg, operator="date"):
# The parsed scan's get_date() returns a time.struct_time, so we # The parsed scan's get_date() returns a time.struct_time, so we
@@ -314,15 +333,17 @@ class SearchResult(object):
year, month, day = date_arg.split("-") year, month, day = date_arg.split("-")
parsed_date = date(int(year), int(month), int(day)) parsed_date = date(int(year), int(month), int(day))
elif re.match("[-|\+]\d+$", date_arg): elif re.match("[-|\+]\d+$", date_arg):
# We need to convert from the "-n" format (n days ago) to a date object # We need to convert from the "-n" format (n days ago) to a date
# (I found this in some old code, don't ask :) ) # object (I found this in some old code, don't ask :) )
parsed_date = date.fromordinal(date.today().toordinal() + int(date_arg)) parsed_date = date.fromordinal(
date.today().toordinal() + int(date_arg))
else: else:
# Fail silently # Fail silently
return False return False
# Now that we have both the scan date and the user date converted to date objects, # Now that we have both the scan date and the user date converted to
# we need to make a comparison based on the operator (date, after, before). # date objects, we need to make a comparison based on the operator
# (date, after, before).
if operator == "date": if operator == "date":
return abs((scan_date - parsed_date).days) <= fuzz return abs((scan_date - parsed_date).days) <= fuzz
# We ignore fuzziness for after: and before: # We ignore fuzziness for after: and before:
@@ -351,10 +372,11 @@ class SearchResult(object):
return False return False
def match_os(self, os): def match_os(self, os):
# If you have lots of big scans in your DB (with a lot of hosts scanned), # If you have lots of big scans in your DB (with a lot of hosts
# you're probably better off using the keyword (freetext) search. Keyword # scanned), you're probably better off using the keyword (freetext)
# search just greps through the nmap output, while this function iterates # search. Keyword search just greps through the nmap output, while this
# through all parsed OS-related values for every host in every scan! # function iterates through all parsed OS-related values for every host
# in every scan!
hosts = self.parsed_scan.get_hosts() hosts = self.parsed_scan.get_hosts()
for host in hosts: for host in hosts:
if HostSearch.match_os(host, os): if HostSearch.match_os(host, os):
@@ -376,12 +398,13 @@ class SearchResult(object):
# Make a list of all scanned ports # Make a list of all scanned ports
services = [] services = []
for scaninfo in self.parsed_scan.get_scaninfo(): for scaninfo in self.parsed_scan.get_scaninfo():
services.append( scaninfo["services"].split(",") ) services.append(scaninfo["services"].split(","))
# These two loops iterate over search ports and over scanned ports. As soon as # These two loops iterate over search ports and over scanned ports. As
# the search finds a given port among the scanned ports, it breaks from the services # soon as the search finds a given port among the scanned ports, it
# loop and continues with the next port in the ports list. If a port isn't # breaks from the services loop and continues with the next port in the
# found in the services list, the function immediately returns False. # ports list. If a port isn't found in the services list, the function
# immediately returns False.
for port in ports: for port in ports:
for service in services: for service in services:
if "-" in service and \ if "-" in service and \
@@ -394,7 +417,8 @@ class SearchResult(object):
else: else:
return False return False
else: else:
# The ports loop finished for all ports, which means the search was successful. # The ports loop finished for all ports, which means the search was
# successful.
return True return True
def match_port(self, ports, port_state): def match_port(self, ports, port_state):
@@ -405,7 +429,8 @@ class SearchResult(object):
for host in self.parsed_scan.get_hosts(): for host in self.parsed_scan.get_hosts():
for port in ports: for port in ports:
if not HostSearch.match_port(host.get_ports(), port, port_state): if not HostSearch.match_port(
host.get_ports(), port, port_state):
break break
else: else:
return True return True
@@ -445,15 +470,16 @@ class SearchResult(object):
return True return True
host = host.lower() host = host.lower()
# Since the parser doesn't parse traceroute output, we need to cheat and look # Since the parser doesn't parse traceroute output, we need to cheat
# the host up in the Nmap output, in the Traceroute section of the scan. # and look the host up in the Nmap output, in the Traceroute section of
# the scan.
nmap_out = self.parsed_scan.get_nmap_output() nmap_out = self.parsed_scan.get_nmap_output()
tr_pos = 0 tr_pos = 0
traceroutes = [] # A scan holds one traceroute section per host traceroutes = [] # A scan holds one traceroute section per host
while tr_pos != -1: while tr_pos != -1:
# Find the beginning and the end of the traceroute section, and append # Find the beginning and the end of the traceroute section, and
# the substring to the traceroutes list # append the substring to the traceroutes list
tr_pos = nmap_out.find("TRACEROUTE", tr_pos+1) tr_pos = nmap_out.find("TRACEROUTE", tr_pos + 1)
tr_end_pos = nmap_out.find("\n\n", tr_pos) tr_end_pos = nmap_out.find("\n\n", tr_pos)
if tr_pos != -1: if tr_pos != -1:
traceroutes.append(nmap_out[tr_pos:tr_end_pos]) traceroutes.append(nmap_out[tr_pos:tr_end_pos])
@@ -465,15 +491,18 @@ class SearchResult(object):
return False return False
def match_dir(self, dir): def match_dir(self, dir):
# The dir: operator is handled by the SearchParser class, we ignore it here. # The dir: operator is handled by the SearchParser class, we ignore it
# here.
return True return True
class SearchDummy(SearchResult): class SearchDummy(SearchResult):
"""A dummy search class that returns no results. It is used as a placeholder """A dummy search class that returns no results. It is used as a
when SearchDB can't be used.""" placeholder when SearchDB can't be used."""
def get_scan_results(self): def get_scan_results(self):
return [] return []
class SearchDB(SearchResult, object): class SearchDB(SearchResult, object):
def __init__(self): def __init__(self):
SearchResult.__init__(self) SearchResult.__init__(self)
@@ -492,13 +521,15 @@ class SearchDB(SearchResult, object):
parsed.parse(buffer) parsed.parse(buffer)
buffer.close() buffer.close()
except Exception, e: except Exception, e:
log.warning(">>> Error loading scan with ID %u from database: %s" % (scan.scans_id, str(e))) log.warning(">>> Error loading scan with ID %u from database: "
"%s" % (scan.scans_id, str(e)))
else: else:
self.scan_results.append(parsed) self.scan_results.append(parsed)
def get_scan_results(self): def get_scan_results(self):
return self.scan_results return self.scan_results
class SearchDir(SearchResult, object): class SearchDir(SearchResult, object):
def __init__(self, search_directory, file_extensions=["usr"]): def __init__(self, search_directory, file_extensions=["usr"]):
SearchResult.__init__(self) SearchResult.__init__(self)
@@ -510,7 +541,8 @@ class SearchDir(SearchResult, object):
elif type(file_extensions) == type([]): elif type(file_extensions) == type([]):
self.file_extensions = file_extensions self.file_extensions = file_extensions
else: else:
raise Exception("Wrong file extension format! '%s'" % file_extensions) raise Exception(
"Wrong file extension format! '%s'" % file_extensions)
log.debug(">>> Getting directory's scan results") log.debug(">>> Getting directory's scan results")
self.scan_results = [] self.scan_results = []
@@ -534,6 +566,7 @@ class SearchDir(SearchResult, object):
def get_scan_results(self): def get_scan_results(self):
return self.scan_results return self.scan_results
class SearchResultTest(unittest.TestCase): class SearchResultTest(unittest.TestCase):
class SearchClass(SearchResult): class SearchClass(SearchResult):
"""This class is for use by the unit testing code""" """This class is for use by the unit testing code"""
@@ -544,6 +577,7 @@ class SearchResultTest(unittest.TestCase):
scan = NmapParser() scan = NmapParser()
scan.parse_file(filename) scan.parse_file(filename)
self.scan_results.append(scan) self.scan_results.append(scan)
def get_scan_results(self): def get_scan_results(self):
return self.scan_results return self.scan_results
@@ -553,31 +587,38 @@ class SearchResultTest(unittest.TestCase):
def _test_skeleton(self, key, val): def _test_skeleton(self, key, val):
results = [] results = []
search = {key:[val]} search = {key: [val]}
for scan in self.search_result.search(**search): for scan in self.search_result.search(**search):
results.append(scan) results.append(scan)
return len(results) return len(results)
def test_match_os(self): def test_match_os(self):
"""Test that checks if the match_os predicate works""" """Test that checks if the match_os predicate works"""
assert(self._test_skeleton('os','linux') == 2) assert(self._test_skeleton('os', 'linux') == 2)
def test_match_target(self): def test_match_target(self):
"""Test that checks if the match_target predicate works""" """Test that checks if the match_target predicate works"""
assert(self._test_skeleton('target','localhost') == 4) assert(self._test_skeleton('target', 'localhost') == 4)
def test_match_port_open(self): def test_match_port_open(self):
"""Test that checks if the match_open predicate works""" """Test that checks if the match_open predicate works"""
assert(self._test_skeleton('open', '22') == 7) assert(self._test_skeleton('open', '22') == 7)
def test_match_port_closed(self): def test_match_port_closed(self):
"""Test that checks if the match_closed predicate works""" """Test that checks if the match_closed predicate works"""
assert(self._test_skeleton('open', '22') == 7) assert(self._test_skeleton('open', '22') == 7)
assert(self._test_skeleton('closed', '22') == 9) assert(self._test_skeleton('closed', '22') == 9)
def test_match_service(self): def test_match_service(self):
"""Test that checks if the match_service predicate works""" """Test that checks if the match_service predicate works"""
assert(self._test_skeleton('service', 'apache') == 9) assert(self._test_skeleton('service', 'apache') == 9)
assert(self._test_skeleton('service', 'openssh') == 7) assert(self._test_skeleton('service', 'openssh') == 7)
def test_match_service_version(self): def test_match_service_version(self):
"""Test that checks if the match_service predicate works when """ """Test that checks if the match_service predicate works when """
"""checking version""" """checking version"""
assert(self._test_skeleton('service', '2.0.52') == 7) assert(self._test_skeleton('service', '2.0.52') == 7)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -121,6 +121,8 @@
# ***************************************************************************/ # ***************************************************************************/
UNIQUE_STRING_MAP = {} UNIQUE_STRING_MAP = {}
def unique(s): def unique(s):
"""Return a single unique representation of s (unique as to id), """Return a single unique representation of s (unique as to id),
letting s be garbage collected.""" letting s be garbage collected."""

View File

@@ -124,6 +124,7 @@ from os import access, R_OK, W_OK
from os.path import dirname from os.path import dirname
from zenmapCore.Paths import Path from zenmapCore.Paths import Path
class TargetList(object): class TargetList(object):
def __init__(self): def __init__(self):
self.temp_list = [] self.temp_list = []

View File

@@ -130,10 +130,10 @@ from zenmapCore.UmitLogging import log
from zenmapCore.UmitConfigParser import UmitConfigParser from zenmapCore.UmitConfigParser import UmitConfigParser
import zenmapCore.I18N import zenmapCore.I18N
# This is the global configuration parser object that represents the contents of # This is the global configuration parser object that represents the contents
# zenmap.conf. It should be initialized once by the application. Most # of zenmap.conf. It should be initialized once by the application. Most
# interaction with the global parser is done by other classes in this file, like # interaction with the global parser is done by other classes in this file,
# SearchConfig, that wrap specific configuration sections. # like SearchConfig, that wrap specific configuration sections.
config_parser = UmitConfigParser() config_parser = UmitConfigParser()
# Check if running on Maemo # Check if running on Maemo
@@ -144,9 +144,11 @@ try:
except ImportError: except ImportError:
pass pass
def is_maemo(): def is_maemo():
return MAEMO return MAEMO
class SearchConfig(UmitConfigParser, object): class SearchConfig(UmitConfigParser, object):
section_name = "search" section_name = "search"
@@ -245,10 +247,11 @@ class SearchConfig(UmitConfigParser, object):
class Profile(UmitConfigParser, object): class Profile(UmitConfigParser, object):
"""This class represents not just one profile, but a whole collection of """This class represents not just one profile, but a whole collection of
them found in a config file such as scan_profiles.usp. The methods therefore them found in a config file such as scan_profiles.usp. The methods
all take an argument that is the name of the profile to work on.""" therefore all take an argument that is the name of the profile to work
on."""
def __init__(self, user_profile = None, *args): def __init__(self, user_profile=None, *args):
UmitConfigParser.__init__(self, *args) UmitConfigParser.__init__(self, *args)
if not user_profile: if not user_profile:
@@ -272,10 +275,10 @@ class Profile(UmitConfigParser, object):
return self.set(profile, attribute, value) return self.set(profile, attribute, value)
def add_profile(self, profile_name, **attributes): def add_profile(self, profile_name, **attributes):
"""Add a profile with the given name and attributes to the collection of """Add a profile with the given name and attributes to the collection
profiles. If a profile with the same name exists, it is not overwritten, of profiles. If a profile with the same name exists, it is not
and the method returns immediately. The backing file for the profiles is overwritten, and the method returns immediately. The backing file for
automatically updated.""" the profiles is automatically updated."""
log.debug(">>> Add Profile '%s': %s" % (profile_name, attributes)) log.debug(">>> Add Profile '%s': %s" % (profile_name, attributes))
@@ -292,8 +295,10 @@ class Profile(UmitConfigParser, object):
self.save_changes() self.save_changes()
def remove_profile(self, profile_name): def remove_profile(self, profile_name):
try: self.remove_section(profile_name) try:
except: pass self.remove_section(profile_name)
except:
pass
self.save_changes() self.save_changes()
def _verify_profile(self, profile_name): def _verify_profile(self, profile_name):
@@ -301,16 +306,17 @@ class Profile(UmitConfigParser, object):
return False return False
return True return True
class CommandProfile (Profile, object): class CommandProfile (Profile, object):
"""This class is a wrapper around Profile that provides accessors for the """This class is a wrapper around Profile that provides accessors for the
attributes of a profile: command and description""" attributes of a profile: command and description"""
def __init__(self, user_profile = None): def __init__(self, user_profile=None):
Profile.__init__(self, user_profile) Profile.__init__(self, user_profile)
def get_command(self, profile): def get_command(self, profile):
command_string = self._get_it(profile, 'command') command_string = self._get_it(profile, 'command')
# Old versions of Zenmap used to append "%s" to commands and use that to # Old versions of Zenmap used to append "%s" to commands and use that
# substitute the target. Ignore it if present. # to substitute the target. Ignore it if present.
if command_string.endswith("%s"): if command_string.endswith("%s"):
command_string = command_string[:-len("%s")] command_string = command_string[:-len("%s")]
return command_string return command_string
@@ -325,9 +331,9 @@ class CommandProfile (Profile, object):
self._set_it(profile, 'description', description) self._set_it(profile, 'description', description)
def get_profile(self, profile_name): def get_profile(self, profile_name):
return {'profile':profile_name, \ return {'profile': profile_name, \
'command':self.get_command(profile_name), \ 'command': self.get_command(profile_name), \
'description':self.get_description(profile_name)} 'description': self.get_description(profile_name)}
class NmapOutputHighlight(object): class NmapOutputHighlight(object):
@@ -381,10 +387,14 @@ class NmapOutputHighlight(object):
tuple_regex = "[\(\[]\s?(\d+)\s?,\s?(\d+)\s?,\s?(\d+)\s?[\)\]]" tuple_regex = "[\(\[]\s?(\d+)\s?,\s?(\d+)\s?,\s?(\d+)\s?[\)\]]"
if isinstance(settings[3], basestring): if isinstance(settings[3], basestring):
settings[3] = [int(t) for t in re.findall(tuple_regex, settings[3])[0]] settings[3] = [
int(t) for t in re.findall(tuple_regex, settings[3])[0]
]
if isinstance(settings[4], basestring): if isinstance(settings[4], basestring):
settings[4]= [int(h) for h in re.findall(tuple_regex, settings[4])[0]] settings[4] = [
int(h) for h in re.findall(tuple_regex, settings[4])[0]
]
return settings return settings
@@ -446,7 +456,8 @@ class NmapOutputHighlight(object):
try: try:
enable = config_parser.get("output_highlight", "enable_highlight") enable = config_parser.get("output_highlight", "enable_highlight")
except NoSectionError: except NoSectionError:
config_parser.set("output_highlight", "enable_highlight", str(True)) config_parser.set(
"output_highlight", "enable_highlight", str(True))
if enable == "False" or enable == "0" or enable == "": if enable == "False" or enable == "0" or enable == "":
return False return False
@@ -454,9 +465,11 @@ class NmapOutputHighlight(object):
def set_enable(self, enable): def set_enable(self, enable):
if enable == False or enable == "0" or enable == None or enable == "": if enable == False or enable == "0" or enable == None or enable == "":
config_parser.set("output_highlight", "enable_highlight", str(False)) config_parser.set(
"output_highlight", "enable_highlight", str(False))
else: else:
config_parser.set("output_highlight", "enable_highlight", str(True)) config_parser.set(
"output_highlight", "enable_highlight", str(True))
date = property(get_date, set_date) date = property(get_date, set_date)
hostname = property(get_hostname, set_hostname) hostname = property(get_hostname, set_hostname)
@@ -468,56 +481,68 @@ class NmapOutputHighlight(object):
details = property(get_details, set_details) details = property(get_details, set_details)
enable = property(get_enable, set_enable) enable = property(get_enable, set_enable)
# These settings are made when there is nothing set yet. They set the "factory" \ # These settings are made when there is nothing set yet. They set the
# default to highlight colors # "factory" default to highlight colors
default_highlights = {"date":{"bold":str(True), default_highlights = {
"italic":str(False), "date": {
"underline":str(False), "bold": str(True),
"text":[0, 0, 0], "italic": str(False),
"highlight":[65535, 65535, 65535], "underline": str(False),
"regex":"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s.{1,4}"}, "text": [0, 0, 0],
"hostname":{"bold":str(True), "highlight": [65535, 65535, 65535],
"italic":str(True), "regex": "\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s.{1,4}"},
"underline":str(True), "hostname": {
"text":[0, 111, 65535], "bold": str(True),
"highlight":[65535, 65535, 65535], "italic": str(True),
"regex":"(\w{2,}://)*[\w-]{2,}\.[\w-]{2,}(\.[\w-]{2,})*(/[[\w-]{2,}]*)*"}, "underline": str(True),
"ip":{"bold":str(True), "text": [0, 111, 65535],
"italic":str(False), "highlight": [65535, 65535, 65535],
"underline":str(False), "regex": "(\w{2,}://)*[\w-]{2,}\.[\w-]{2,}"
"text":[0, 0, 0], "(\.[\w-]{2,})*(/[[\w-]{2,}]*)*"},
"highlight":[65535, 65535, 65535], "ip": {
"regex":"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"}, "bold": str(True),
"port_list":{"bold":str(True), "italic": str(False),
"italic":str(False), "underline": str(False),
"underline":str(False), "text": [0, 0, 0],
"text":[0, 1272, 28362], "highlight": [65535, 65535, 65535],
"highlight":[65535, 65535, 65535], "regex": "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"},
"regex":"PORT\s+STATE\s+SERVICE(\s+VERSION)?[^\n]*"}, "port_list": {
"open_port":{"bold":str(True), "bold": str(True),
"italic":str(False), "italic": str(False),
"underline":str(False), "underline": str(False),
"text":[0, 41036, 2396], "text": [0, 1272, 28362],
"highlight":[65535, 65535, 65535], "highlight": [65535, 65535, 65535],
"regex":"\d{1,5}/.{1,5}\s+open\s+.*"}, "regex": "PORT\s+STATE\s+SERVICE(\s+VERSION)?[^\n]*"},
"closed_port":{"bold":str(False), "open_port": {
"italic":str(False), "bold": str(True),
"underline":str(False), "italic": str(False),
"text":[65535, 0, 0], "underline": str(False),
"highlight":[65535, 65535, 65535], "text": [0, 41036, 2396],
"regex":"\d{1,5}/.{1,5}\s+closed\s+.*"}, "highlight": [65535, 65535, 65535],
"filtered_port":{"bold":str(False), "regex": "\d{1,5}/.{1,5}\s+open\s+.*"},
"italic":str(False), "closed_port": {
"underline":str(False), "bold": str(False),
"text":[38502, 39119, 0], "italic": str(False),
"highlight":[65535, 65535, 65535], "underline": str(False),
"regex":"\d{1,5}/.{1,5}\s+filtered\s+.*"}, "text": [65535, 0, 0],
"details":{"bold":str(True), "highlight": [65535, 65535, 65535],
"italic":str(False), "regex": "\d{1,5}/.{1,5}\s+closed\s+.*"},
"underline":str(True), "filtered_port": {
"text":[0, 0, 0], "bold": str(False),
"highlight":[65535, 65535, 65535], "italic": str(False),
"regex":"^(\w{2,}[\s]{,3}){,4}:"}} "underline": str(False),
"text": [38502, 39119, 0],
"highlight": [65535, 65535, 65535],
"regex": "\d{1,5}/.{1,5}\s+filtered\s+.*"},
"details": {
"bold": str(True),
"italic": str(False),
"underline": str(True),
"text": [0, 0, 0],
"highlight": [65535, 65535, 65535],
"regex": "^(\w{2,}[\s]{,3}){,4}:"}
}
# Retrieve details from zenmap.conf regarding paths subsection # Retrieve details from zenmap.conf regarding paths subsection
# (e.g. nmap_command_path) - jurand # (e.g. nmap_command_path) - jurand
@@ -530,8 +555,9 @@ class PathsConfig(object):
def __get_it(self, p_name, default): def __get_it(self, p_name, default):
try: try:
return config_parser.get(self.section_name, p_name) return config_parser.get(self.section_name, p_name)
except (NoOptionError,NoSectionError): except (NoOptionError, NoSectionError):
log.debug(">>> Using default \"%s\" for \"%s\"." % (default, p_name)) log.debug(
">>> Using default \"%s\" for \"%s\"." % (default, p_name))
return default return default
def __set_it(self, property_name, settings): def __set_it(self, property_name, settings):
@@ -550,17 +576,22 @@ class PathsConfig(object):
self.__set_it("ndiff_command_path", settings) self.__set_it("ndiff_command_path", settings)
nmap_command_path = property(get_nmap_command_path, set_nmap_command_path) nmap_command_path = property(get_nmap_command_path, set_nmap_command_path)
ndiff_command_path = property(get_ndiff_command_path, set_ndiff_command_path) ndiff_command_path = property(
get_ndiff_command_path, set_ndiff_command_path)
# Exceptions # Exceptions
class ProfileNotFound: class ProfileNotFound:
def __init__ (self, profile): def __init__(self, profile):
self.profile = profile self.profile = profile
def __str__ (self):
return "No profile named '"+self.profile+"' found!" def __str__(self):
return "No profile named '" + self.profile + "' found!"
class ProfileCouldNotBeSaved: class ProfileCouldNotBeSaved:
def __init__ (self, profile): def __init__(self, profile):
self.profile = profile self.profile = profile
def __str__ (self):
return "Profile named '"+self.profile+"' could not be saved!" def __str__(self):
return "Profile named '" + self.profile + "' could not be saved!"

View File

@@ -121,9 +121,11 @@
# ***************************************************************************/ # ***************************************************************************/
from os.path import exists from os.path import exists
from ConfigParser import ConfigParser, DEFAULTSECT, NoOptionError, NoSectionError from ConfigParser import ConfigParser, DEFAULTSECT, NoOptionError, \
NoSectionError
from zenmapCore.UmitLogging import log from zenmapCore.UmitLogging import log
class UmitConfigParser(ConfigParser): class UmitConfigParser(ConfigParser):
filenames = None filenames = None
fp = None fp = None
@@ -158,9 +160,11 @@ class UmitConfigParser(ConfigParser):
if len(self.filenames) == 1: if len(self.filenames) == 1:
filename = self.filenames[0] filename = self.filenames[0]
else: else:
raise ValueError("UmitConfigParser can't handle a list of filenames: %s" % self.filenames) raise ValueError("UmitConfigParser can't handle a list "
"of filenames: %s" % self.filenames)
else: else:
raise ValueError("UmitConfigParser can't handle a filename of type %s: %s" % (type(self.filenames), self.filenames)) raise ValueError("UmitConfigParser can't handle a filename of "
"type %s: %s" % (type(self.filenames), self.filenames))
self.write(open(filename, 'w')) self.write(open(filename, 'w'))
elif self.fp: elif self.fp:
self.write(self.fp) self.write(self.fp)
@@ -188,6 +192,7 @@ class UmitConfigParser(ConfigParser):
(key, str(value).replace('\n', '\n\t'))) (key, str(value).replace('\n', '\n\t')))
fp.write("\n") fp.write("\n")
def test_umit_conf_content(filename): def test_umit_conf_content(filename):
parser = ConfigParser() parser = ConfigParser()
parser.read(filename) parser.read(filename)

View File

@@ -175,8 +175,8 @@ if isinstance(umitdb, str):
fs_enc = "UTF-8" fs_enc = "UTF-8"
umitdb = umitdb.decode(fs_enc) umitdb = umitdb.decode(fs_enc)
# pyslite 2.4.0 doesn't handle a unicode database name, though earlier and later # pyslite 2.4.0 doesn't handle a unicode database name, though earlier and
# versions do. Encode to UTF-8 as pysqlite would do internally anyway. # later versions do. Encode to UTF-8 as pysqlite would do internally anyway.
umitdb = umitdb.encode("UTF-8") umitdb = umitdb.encode("UTF-8")
connection = sqlite.connect(umitdb) connection = sqlite.connect(umitdb)
@@ -192,6 +192,7 @@ except AttributeError:
# However, text_factory is available only in pysqlite 2.1.0 and later. # However, text_factory is available only in pysqlite 2.1.0 and later.
pass pass
class Table(object): class Table(object):
def __init__(self, table_name): def __init__(self, table_name):
self.table_name = table_name self.table_name = table_name
@@ -203,9 +204,11 @@ class Table(object):
if self.__getattribute__("_%s" % item_name): if self.__getattribute__("_%s" % item_name):
return self.__getattribute__("_%s" % item_name) return self.__getattribute__("_%s" % item_name)
sql = "SELECT %s FROM %s WHERE %s_id = %s" % (item_name, self.table_name, sql = "SELECT %s FROM %s WHERE %s_id = %s" % (
self.table_name, item_name,
self.__getattribute__(self.table_id)) self.table_name,
self.table_name,
self.__getattribute__(self.table_id))
self.cursor.execute(sql) self.cursor.execute(sql)
@@ -216,9 +219,11 @@ class Table(object):
if item_value == self.__getattribute__("_%s" % item_name): if item_value == self.__getattribute__("_%s" % item_name):
return None return None
sql = "UPDATE %s SET %s = ? WHERE %s_id = %s" % (self.table_name, item_name, sql = "UPDATE %s SET %s = ? WHERE %s_id = %s" % (
self.table_name, self.table_name,
self.__getattribute__(self.table_id)) item_name,
self.table_name,
self.__getattribute__(self.table_id))
self.cursor.execute(sql, (item_value,)) self.cursor.execute(sql, (item_value,))
connection.commit() connection.commit()
self.__setattr__("_%s" % item_name, item_value) self.__setattr__("_%s" % item_name, item_value)
@@ -247,31 +252,30 @@ class Table(object):
self.cursor.execute(sql) self.cursor.execute(sql)
return self.cursor.fetchall()[0][0] return self.cursor.fetchall()[0][0]
class UmitDB(object): class UmitDB(object):
def __init__(self): def __init__(self):
self.cursor = connection.cursor() self.cursor = connection.cursor()
def create_db(self): def create_db(self):
drop_string = ("DROP TABLE scans;",) drop_string = "DROP TABLE scans;"
try: try:
for d in drop_string: self.cursor.execute(drop_string)
self.cursor.execute(d)
except: except:
connection.rollback() connection.rollback()
else: else:
connection.commit() connection.commit()
creation_string = """CREATE TABLE scans (
scans_id INTEGER PRIMARY KEY AUTOINCREMENT,
scan_name TEXT,
nmap_xml_output TEXT,
digest TEXT,
date INTEGER)"""
creation_string = ("""CREATE TABLE scans (scans_id INTEGER PRIMARY KEY AUTOINCREMENT, self.cursor.execute(creation_string)
scan_name TEXT, connection.commit()
nmap_xml_output TEXT,
digest TEXT,
date INTEGER)""",)
for c in creation_string:
self.cursor.execute(c)
connection.commit()
def add_scan(self, **kargs): def add_scan(self, **kargs):
return Scans(**kargs) return Scans(**kargs)
@@ -289,11 +293,13 @@ class UmitDB(object):
def cleanup(self, save_time): def cleanup(self, save_time):
log.debug(">>> Cleaning up data base.") log.debug(">>> Cleaning up data base.")
log.debug(">>> Removing results olders than %s seconds" % save_time) log.debug(">>> Removing results olders than %s seconds" % save_time)
self.cursor.execute("SELECT scans_id FROM scans WHERE date < ?", (time() - save_time,)) self.cursor.execute("SELECT scans_id FROM scans WHERE date < ?",
(time() - save_time,))
for sid in [sid[0] for sid in self.cursor.fetchall()]: for sid in [sid[0] for sid in self.cursor.fetchall()]:
log.debug(">>> Removing results with scans_id %s" % sid) log.debug(">>> Removing results with scans_id %s" % sid)
self.cursor.execute("DELETE FROM scans WHERE scans_id = ?", (sid, )) self.cursor.execute("DELETE FROM scans WHERE scans_id = ?",
(sid, ))
else: else:
connection.commit() connection.commit()
log.debug(">>> Data base successfully cleaned up!") log.debug(">>> Data base successfully cleaned up!")
@@ -310,25 +316,30 @@ class Scans(Table, object):
for k in kargs.keys(): for k in kargs.keys():
if k not in fields: if k not in fields:
raise Exception("Wrong table field passed to creation method. '%s'" % k) raise Exception(
"Wrong table field passed to creation method. "
"'%s'" % k)
if "nmap_xml_output" not in kargs.keys() or not kargs["nmap_xml_output"]: if ("nmap_xml_output" not in kargs.keys() or
not kargs["nmap_xml_output"]):
raise Exception("Can't save result without xml output") raise Exception("Can't save result without xml output")
if not self.verify_digest(md5(kargs["nmap_xml_output"]).hexdigest()): if not self.verify_digest(
md5(kargs["nmap_xml_output"]).hexdigest()):
raise Exception("XML output registered already!") raise Exception("XML output registered already!")
self.scans_id = self.insert(**kargs) self.scans_id = self.insert(**kargs)
def verify_digest(self, digest): def verify_digest(self, digest):
self.cursor.execute("SELECT scans_id FROM scans WHERE digest = ?", (digest, )) self.cursor.execute(
"SELECT scans_id FROM scans WHERE digest = ?", (digest, ))
result = self.cursor.fetchall() result = self.cursor.fetchall()
if result: if result:
return False return False
return True return True
def add_host(self, **kargs): def add_host(self, **kargs):
kargs.update({self.table_id:self.scans_id}) kargs.update({self.table_id: self.scans_id})
return Hosts(**kargs) return Hosts(**kargs)
def get_hosts(self): def get_hosts(self):

View File

@@ -127,6 +127,7 @@ from zenmapCore.UmitOptionParser import option_parser
LOGLEVEL = option_parser.get_verbose() LOGLEVEL = option_parser.get_verbose()
class Log(Logger, object): class Log(Logger, object):
def __init__(self, name, level=0): def __init__(self, name, level=0):
Logger.__init__(self, name, level) Logger.__init__(self, name, level)
@@ -143,7 +144,6 @@ class Log(Logger, object):
def set_formatter(self, fmt): def set_formatter(self, fmt):
self.__formatter = Formatter(fmt) self.__formatter = Formatter(fmt)
format = "%(levelname)s - %(asctime)s - %(message)s" format = "%(levelname)s - %(asctime)s - %(message)s"
formatter = property(get_formatter, set_formatter, doc="") formatter = property(get_formatter, set_formatter, doc="")

View File

@@ -128,6 +128,7 @@ from zenmapCore.Version import VERSION
import zenmapCore.I18N import zenmapCore.I18N
from zenmapCore.BasePaths import base_paths from zenmapCore.BasePaths import base_paths
class UmitOptionParser(OptionParser): class UmitOptionParser(OptionParser):
def __init__(self, args=False): def __init__(self, args=False):
OptionParser.__init__(self, version="%%prog %s" % VERSION) OptionParser.__init__(self, version="%%prog %s" % VERSION)
@@ -135,10 +136,10 @@ class UmitOptionParser(OptionParser):
self.set_usage("%prog [options] [result files]") self.set_usage("%prog [options] [result files]")
self.add_option("--confdir", self.add_option("--confdir",
default = base_paths["user_config_dir"], default=base_paths["user_config_dir"],
dest = "confdir", dest="confdir",
metavar = "DIR", metavar="DIR",
help = _("\ help=_("\
Use DIR as the user configuration directory. Default: %default")) Use DIR as the user configuration directory. Default: %default"))
## Open Scan Results (GUI) ## Open Scan Results (GUI)
@@ -163,7 +164,8 @@ scan result files."))
default=[], default=[],
action="callback", action="callback",
callback=self.__nmap_callback, callback=self.__nmap_callback,
help=_("Run %s with the specified args.") % NMAP_DISPLAY_NAME) help=_("Run %s with the specified args."
) % NMAP_DISPLAY_NAME)
## Execute a profile against a target (GUI) ## Execute a profile against a target (GUI)
### Positional args should be taken as targets to feed this scan ### Positional args should be taken as targets to feed this scan

View File

@@ -126,7 +126,8 @@ import webbrowser
from zenmapGUI.higwidgets.higdialogs import HIGDialog from zenmapGUI.higwidgets.higdialogs import HIGDialog
from zenmapGUI.higwidgets.higwindows import HIGWindow from zenmapGUI.higwidgets.higwindows import HIGWindow
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, hig_box_space_holder from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, \
hig_box_space_holder
from zenmapGUI.higwidgets.higbuttons import HIGButton from zenmapGUI.higwidgets.higbuttons import HIGButton
from zenmapGUI.higwidgets.hignotebooks import HIGNotebook from zenmapGUI.higwidgets.hignotebooks import HIGNotebook
from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow
@@ -141,6 +142,7 @@ import zenmapCore.I18N
# For escaping text in marked-up labels. # For escaping text in marked-up labels.
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
class _program_entry(gtk.VBox): class _program_entry(gtk.VBox):
"""A little box containing labels with a program's name and """A little box containing labels with a program's name and
description and a clickable link to its web site.""" description and a clickable link to its web site."""
@@ -149,7 +151,7 @@ class _program_entry(gtk.VBox):
# web site button. # web site button.
NAME_WEB_SITE_SPACING = 20 NAME_WEB_SITE_SPACING = 20
def __init__(self, name = None, web_site = None, description = None): def __init__(self, name=None, web_site=None, description=None):
gtk.VBox.__init__(self) gtk.VBox.__init__(self)
self.hbox = gtk.HBox(False, self.NAME_WEB_SITE_SPACING) self.hbox = gtk.HBox(False, self.NAME_WEB_SITE_SPACING)
@@ -157,7 +159,9 @@ class _program_entry(gtk.VBox):
if name is not None: if name is not None:
name_label = gtk.Label() name_label = gtk.Label()
name_label.set_markup("<span size=\"large\" weight=\"bold\">%s</span>" % escape(name)) name_label.set_markup(
'<span size="large" weight="bold">%s</span>' % escape(
name))
self.hbox.pack_start(name_label, False) self.hbox.pack_start(name_label, False)
if web_site is not None: if web_site is not None:
@@ -180,41 +184,44 @@ class _program_entry(gtk.VBox):
def _link_button_open(self, widget): def _link_button_open(self, widget):
webbrowser.open(widget.get_uri()) webbrowser.open(widget.get_uri())
class About(HIGDialog): class About(HIGDialog):
"""An about dialog showing information about the program. It is meant to """An about dialog showing information about the program. It is meant to
have roughly the same feel as gtk.AboutDialog.""" have roughly the same feel as gtk.AboutDialog."""
def __init__(self): def __init__(self):
HIGDialog.__init__(self) HIGDialog.__init__(self)
self.set_title(_("About %s and %s") % (NMAP_DISPLAY_NAME, APP_DISPLAY_NAME)) self.set_title(_("About %s and %s") % (
NMAP_DISPLAY_NAME, APP_DISPLAY_NAME))
self.vbox.set_border_width(12) self.vbox.set_border_width(12)
self.vbox.set_spacing(12) self.vbox.set_spacing(12)
label = gtk.Label() label = gtk.Label()
label.set_markup("<span size=\"xx-large\" weight=\"bold\">%s %s</span>" \ label.set_markup(
% (escape(APP_DISPLAY_NAME), escape(VERSION))) '<span size="xx-large" weight="bold">%s %s</span>' % (
escape(APP_DISPLAY_NAME), escape(VERSION)))
label.set_selectable(True) label.set_selectable(True)
self.vbox.pack_start(label) self.vbox.pack_start(label)
label = gtk.Label() label = gtk.Label()
label.set_markup("<span size=\"small\">%s</span>" \ label.set_markup(
% (escape(APP_COPYRIGHT))) '<span size="small">%s</span>' % (escape(APP_COPYRIGHT)))
self.vbox.pack_start(label) self.vbox.pack_start(label)
entry = _program_entry(NMAP_DISPLAY_NAME, NMAP_WEB_SITE, _("""\ entry = _program_entry(NMAP_DISPLAY_NAME, NMAP_WEB_SITE, _(
%s is a free and open source utility for network exploration and security \ "%s is a free and open source utility for network exploration "
auditing.""") % NMAP_DISPLAY_NAME) "and security auditing.") % NMAP_DISPLAY_NAME)
self.vbox.pack_start(entry) self.vbox.pack_start(entry)
entry = _program_entry(APP_DISPLAY_NAME, APP_WEB_SITE, _("""\ entry = _program_entry(APP_DISPLAY_NAME, APP_WEB_SITE, _(
%s is a multi-platform graphical %s frontend and results viewer. It was \ "%s is a multi-platform graphical %s frontend and results viewer. "
originally derived from %s.""") \ "It was originally derived from %s.") % (
% (APP_DISPLAY_NAME, NMAP_DISPLAY_NAME, UMIT_DISPLAY_NAME)) APP_DISPLAY_NAME, NMAP_DISPLAY_NAME, UMIT_DISPLAY_NAME))
self.vbox.pack_start(entry) self.vbox.pack_start(entry)
entry = _program_entry(UMIT_DISPLAY_NAME, UMIT_WEB_SITE, _("""\ entry = _program_entry(UMIT_DISPLAY_NAME, UMIT_WEB_SITE, _(
%s is an %s GUI created as part of the Nmap/Google Summer of Code program.""") \ "%s is an %s GUI created as part of the Nmap/Google Summer "
% (UMIT_DISPLAY_NAME, NMAP_DISPLAY_NAME)) "of Code program.") % (UMIT_DISPLAY_NAME, NMAP_DISPLAY_NAME))
button = gtk.Button(_("%s credits") % UMIT_DISPLAY_NAME) button = gtk.Button(_("%s credits") % UMIT_DISPLAY_NAME)
button.connect("clicked", self._show_umit_credits) button.connect("clicked", self._show_umit_credits)
entry.hbox.pack_start(button, False) entry.hbox.pack_start(button, False)
@@ -246,17 +253,20 @@ originally derived from %s.""") \
return return
self._umit_credits_dialog = UmitCredits() self._umit_credits_dialog = UmitCredits()
def credits_destroyed(widget): def credits_destroyed(widget):
# Mark that the credits dialog has been destroyed. # Mark that the credits dialog has been destroyed.
self._umit_credits_dialog = None self._umit_credits_dialog = None
self._umit_credits_dialog.connect("destroy", credits_destroyed) self._umit_credits_dialog.connect("destroy", credits_destroyed)
self._umit_credits_dialog.show_all() self._umit_credits_dialog.show_all()
class UmitCredits(HIGWindow): class UmitCredits(HIGWindow):
def __init__(self): def __init__(self):
HIGWindow.__init__(self) HIGWindow.__init__(self)
self.set_title(_("%s credits") % UMIT_DISPLAY_NAME) self.set_title(_("%s credits") % UMIT_DISPLAY_NAME)
self.set_size_request(-1,250) self.set_size_request(-1, 250)
self.set_position(gtk.WIN_POS_CENTER) self.set_position(gtk.WIN_POS_CENTER)
self.__create_widgets() self.__create_widgets()
@@ -296,12 +306,18 @@ class UmitCredits(HIGWindow):
self.hbox._pack_expand_fill(hig_box_space_holder()) self.hbox._pack_expand_fill(hig_box_space_holder())
self.hbox._pack_noexpand_nofill(self.btn_close) self.hbox._pack_noexpand_nofill(self.btn_close)
self.notebook.append_page(self.written_by_scroll, gtk.Label(_("Written by"))) self.notebook.append_page(
self.notebook.append_page(self.design_scroll, gtk.Label(_("Design"))) self.written_by_scroll, gtk.Label(_("Written by")))
self.notebook.append_page(self.soc2007_scroll, gtk.Label(_("SoC 2007"))) self.notebook.append_page(
self.notebook.append_page(self.contributors_scroll, gtk.Label(_("Contributors"))) self.design_scroll, gtk.Label(_("Design")))
self.notebook.append_page(self.translation_scroll, gtk.Label(_("Translation"))) self.notebook.append_page(
self.notebook.append_page(self.nokia_scroll, gtk.Label(_("Maemo"))) self.soc2007_scroll, gtk.Label(_("SoC 2007")))
self.notebook.append_page(
self.contributors_scroll, gtk.Label(_("Contributors")))
self.notebook.append_page(
self.translation_scroll, gtk.Label(_("Translation")))
self.notebook.append_page(
self.nokia_scroll, gtk.Label(_("Maemo")))
self.written_by_scroll.add(self.written_by_text) self.written_by_scroll.add(self.written_by_text)
self.written_by_text.set_wrap_mode(gtk.WRAP_NONE) self.written_by_text.set_wrap_mode(gtk.WRAP_NONE)
@@ -321,7 +337,7 @@ class UmitCredits(HIGWindow):
self.nokia_scroll.add(self.nokia_text) self.nokia_scroll.add(self.nokia_text)
self.nokia_text.set_wrap_mode(gtk.WRAP_NONE) self.nokia_text.set_wrap_mode(gtk.WRAP_NONE)
self.btn_close.connect('clicked', lambda x,y=None:self.destroy()) self.btn_close.connect('clicked', lambda x, y=None: self.destroy())
def set_text(self): def set_text(self):
b = self.written_by_text.get_buffer() b = self.written_by_text.get_buffer()

View File

@@ -133,7 +133,7 @@ import ConfigParser
# Python 2.7 that otherwise causes an assertion failure. See # Python 2.7 that otherwise causes an assertion failure. See
# https://bugzilla.redhat.com/show_bug.cgi?id=620216#c10. # https://bugzilla.redhat.com/show_bug.cgi?id=620216#c10.
import warnings import warnings
warnings.filterwarnings("error", module = "gtk", append = "True") warnings.filterwarnings("error", module="gtk", append="True")
try: try:
import gtk import gtk
except Exception: except Exception:
@@ -171,6 +171,7 @@ from zenmapGUI.higwidgets.higdialogs import HIGAlertDialog
# gtk.main_quit. # gtk.main_quit.
open_windows = [] open_windows = []
def _destroy_callback(window): def _destroy_callback(window):
open_windows.remove(window) open_windows.remove(window)
if len(open_windows) == 0: if len(open_windows) == 0:
@@ -183,6 +184,7 @@ def _destroy_callback(window):
# Cleaning up data base # Cleaning up data base
UmitDB().cleanup(SearchConfig().converted_save_time) UmitDB().cleanup(SearchConfig().converted_save_time)
def new_window(): def new_window():
w = ScanWindow() w = ScanWindow()
w.connect("destroy", _destroy_callback) w.connect("destroy", _destroy_callback)
@@ -193,11 +195,14 @@ def new_window():
open_windows.append(w) open_windows.append(w)
return w return w
# Script found at http://www.py2exe.org/index.cgi/HowToDetermineIfRunningFromExe
# Script found at
# http://www.py2exe.org/index.cgi/HowToDetermineIfRunningFromExe
def main_is_frozen(): def main_is_frozen():
return (hasattr(sys, "frozen") # new py2exe return (hasattr(sys, "frozen") # new py2exe
or hasattr(sys, "importers") # old py2exe or hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) # tools/freeze or imp.is_frozen("__main__")) # tools/freeze
def is_root(): def is_root():
if 'NMAP_PRIVILEGED' in os.environ: if 'NMAP_PRIVILEGED' in os.environ:
@@ -207,6 +212,7 @@ def is_root():
else: else:
return sys.platform == "win32" or os.getuid() == 0 or is_maemo() return sys.platform == "win32" or os.getuid() == 0 or is_maemo()
def install_excepthook(): def install_excepthook():
# This will catch exceptions and send them to bugzilla # This will catch exceptions and send them to bugzilla
def excepthook(type, value, tb): def excepthook(type, value, tb):
@@ -218,7 +224,7 @@ def install_excepthook():
# produces a warning, but the lack of a display eventually causes a # produces a warning, but the lack of a display eventually causes a
# segmentation fault. See http://live.gnome.org/PyGTK/WhatsNew210. # segmentation fault. See http://live.gnome.org/PyGTK/WhatsNew210.
import warnings import warnings
warnings.filterwarnings("error", module = "gtk") warnings.filterwarnings("error", module="gtk")
import gtk import gtk
warnings.resetwarnings() warnings.resetwarnings()
@@ -229,8 +235,7 @@ def install_excepthook():
if type == ImportError: if type == ImportError:
d = HIGAlertDialog(type=gtk.MESSAGE_ERROR, d = HIGAlertDialog(type=gtk.MESSAGE_ERROR,
message_format=_("Import error"), message_format=_("Import error"),
secondary_text=_("""\ secondary_text=_("""A required module was not found.
A required module was not found.
""" + unicode(value))) """ + unicode(value)))
d.run() d.run()
@@ -246,6 +251,7 @@ A required module was not found.
sys.excepthook = excepthook sys.excepthook = excepthook
def safe_shutdown(signum, stack): def safe_shutdown(signum, stack):
"""Kills any active scans/tabs and shuts down the application.""" """Kills any active scans/tabs and shuts down the application."""
log.debug("\n\n%s\nSAFE SHUTDOWN!\n%s\n" % ("#" * 30, "#" * 30)) log.debug("\n\n%s\nSAFE SHUTDOWN!\n%s\n" % ("#" * 30, "#" * 30))
@@ -256,6 +262,7 @@ def safe_shutdown(signum, stack):
sys.exit(signum) sys.exit(signum)
def run(): def run():
if os.name == "posix": if os.name == "posix":
signal.signal(signal.SIGHUP, safe_shutdown) signal.signal(signal.SIGHUP, safe_shutdown)
@@ -271,19 +278,25 @@ def run():
try: try:
# Create the ~/.zenmap directory by copying from the system-wide # Create the ~/.zenmap directory by copying from the system-wide
# template directory. # template directory.
zenmapCore.Paths.create_user_config_dir(Path.user_config_dir, Path.config_dir) zenmapCore.Paths.create_user_config_dir(
Path.user_config_dir, Path.config_dir)
except (IOError, OSError), e: except (IOError, OSError), e:
error_dialog = HIGAlertDialog(message_format = _("Error creating the per-user configuration directory"), error_dialog = HIGAlertDialog(
secondary_text = _("""\ message_format=_(
"Error creating the per-user configuration directory"),
secondary_text=_("""\
There was an error creating the directory %s or one of the files in it. \ There was an error creating the directory %s or one of the files in it. \
The directory is created by copying the contents of %s. \ The directory is created by copying the contents of %s. \
The specific error was\n\ The specific error was
\n\
%s\n\ %s
\n\
%s needs to create this directory to store information such as the list of \ %s needs to create this directory to store information such as the list of \
scan profiles. Check for access to the directory and try again.\ scan profiles. Check for access to the directory and try again.""") % (
""") % (repr(Path.user_config_dir), repr(Path.config_dir), repr(str(e)), APP_DISPLAY_NAME)) repr(Path.user_config_dir), repr(Path.config_dir),
repr(str(e)), APP_DISPLAY_NAME
)
)
error_dialog.run() error_dialog.run()
error_dialog.destroy() error_dialog.destroy()
sys.exit(1) sys.exit(1)
@@ -292,16 +305,17 @@ scan profiles. Check for access to the directory and try again.\
# Read the ~/.zenmap/zenmap.conf configuration file. # Read the ~/.zenmap/zenmap.conf configuration file.
zenmapCore.UmitConf.config_parser.read(Path.user_config_file) zenmapCore.UmitConf.config_parser.read(Path.user_config_file)
except ConfigParser.ParsingError, e: except ConfigParser.ParsingError, e:
error_dialog = HIGAlertDialog(message_format = _("Error parsing the configuration file"), error_dialog = HIGAlertDialog(
secondary_text = _("""\ message_format=_("Error parsing the configuration file"),
secondary_text=_("""\
There was an error parsing the configuration file %s. \ There was an error parsing the configuration file %s. \
The specific error was\n\ The specific error was
\n\
%s\n\ %s
\n\
%s can continue without this file but any information in it will be ignored \ %s can continue without this file but any information in it will be ignored \
until it is repaired.\ until it is repaired.""") % (Path.user_config_file, str(e), APP_DISPLAY_NAME)
""") % (Path.user_config_file, str(e), APP_DISPLAY_NAME)) )
error_dialog.run() error_dialog.run()
error_dialog.destroy() error_dialog.destroy()
@@ -355,10 +369,13 @@ until it is repaired.\
if main_is_frozen(): if main_is_frozen():
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
class NonRootWarning (HIGAlertDialog): class NonRootWarning (HIGAlertDialog):
def __init__(self): def __init__(self):
warning_text = _('''You are trying to run %s with a non-root user!\n warning_text = _('''You are trying to run %s with a non-root user!
Some %s options need root privileges to work.''') % (APP_DISPLAY_NAME, NMAP_DISPLAY_NAME)
Some %s options need root privileges to work.''') % (
APP_DISPLAY_NAME, NMAP_DISPLAY_NAME)
HIGAlertDialog.__init__(self, message_format=_('Non-root user'), HIGAlertDialog.__init__(self, message_format=_('Non-root user'),
secondary_text=warning_text) secondary_text=warning_text)

View File

@@ -130,6 +130,7 @@ import zenmapCore.I18N
# For escaping text in marked-up labels. # For escaping text in marked-up labels.
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
class BugReport(gtk.Window, object): class BugReport(gtk.Window, object):
def __init__(self): def __init__(self):
gtk.Window.__init__(self) gtk.Window.__init__(self)
@@ -173,7 +174,11 @@ Code patches to fix bugs are even better than bug reports. Basic \
instructions for creating patch files with your changes are available at \ instructions for creating patch files with your changes are available at \
http://nmap.org/data/HACKING. Patches may be sent to nmap-dev \ http://nmap.org/data/HACKING. Patches may be sent to nmap-dev \
(recommended) or to Fyodor directly. (recommended) or to Fyodor directly.
""") % {"app": escape(APP_DISPLAY_NAME), "nmap": escape(NMAP_DISPLAY_NAME), "nmap_web": escape(NMAP_WEB_SITE)}) """) % {
"app": escape(APP_DISPLAY_NAME),
"nmap": escape(NMAP_DISPLAY_NAME),
"nmap_web": escape(NMAP_WEB_SITE)
})
self.vbox.add(self.text) self.vbox.add(self.text)
self.button_box.set_layout(gtk.BUTTONBOX_END) self.button_box.set_layout(gtk.BUTTONBOX_END)

View File

@@ -134,6 +134,7 @@ import zenmapCore.I18N
# For escaping text in marked-up labels. # For escaping text in marked-up labels.
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
class CrashReport(HIGDialog): class CrashReport(HIGDialog):
def __init__(self, type, value, tb): def __init__(self, type, value, tb):
HIGDialog.__init__(self) HIGDialog.__init__(self)
@@ -158,17 +159,16 @@ class CrashReport(HIGDialog):
self.description_text.set_editable(False) self.description_text.set_editable(False)
self.bug_text = gtk.Label() self.bug_text = gtk.Label()
self.bug_text.set_markup(_("""\ self.bug_text.set_markup(_('An unexpected error has crashed '
An unexpected error has crashed %(app_name)s. Please copy the stack trace below and \ '%(app_name)s. Please copy the stack trace below and send it to '
send it to the <a href="mailto:dev@nmap.org">dev@nmap.org</a> \ 'the <a href="mailto:dev@nmap.org">dev@nmap.org</a> mailing list. '
mailing list. (<a href="http://seclists.org/nmap-dev/">More about the list.</a>) \ '(<a href="http://seclists.org/nmap-dev/">More about the list.</a>'
The developers will see your report and try to fix the problem.""") % \ ') The developers will see your report and try to fix the problem.'
{ "app_name": escape(APP_DISPLAY_NAME) }) ) % {"app_name": escape(APP_DISPLAY_NAME)})
self.email_frame = gtk.Frame() self.email_frame = gtk.Frame()
self.email_label = gtk.Label() self.email_label = gtk.Label()
self.email_label.set_markup(_("""\ self.email_label.set_markup(_('<b>Copy and email to '
<b>Copy and email to <a href="mailto:dev@nmap.org">dev@nmap.org</a>:</b>\ '<a href="mailto:dev@nmap.org">dev@nmap.org</a>:</b>'))
"""))
self.btn_copy = gtk.Button(stock=gtk.STOCK_COPY) self.btn_copy = gtk.Button(stock=gtk.STOCK_COPY)
self.btn_ok = gtk.Button(stock=gtk.STOCK_OK) self.btn_ok = gtk.Button(stock=gtk.STOCK_OK)
@@ -176,7 +176,8 @@ The developers will see your report and try to fix the problem.""") % \
def _pack_widgets(self): def _pack_widgets(self):
self.description_scrolled.add(self.description_text) self.description_scrolled.add(self.description_text)
self.description_scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.description_scrolled.set_policy(
gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.description_scrolled.set_size_request(400, 150) self.description_scrolled.set_size_request(400, 150)
self.description_text.set_wrap_mode(gtk.WRAP_WORD) self.description_text.set_wrap_mode(gtk.WRAP_WORD)
@@ -223,7 +224,7 @@ The developers will see your report and try to fix the problem.""") % \
sys.exit(0) sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":
c = CrashReport(None,None,None) c = CrashReport(None, None, None)
c.show_all() c.show_all()
c.connect("delete-event", lambda x, y: gtk.main_quit()) c.connect("delete-event", lambda x, y: gtk.main_quit())

View File

@@ -129,7 +129,8 @@ import sys
import xml.sax import xml.sax
from zenmapGUI.higwidgets.higdialogs import HIGAlertDialog, HIGDialog from zenmapGUI.higwidgets.higdialogs import HIGAlertDialog, HIGDialog
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, hig_box_space_holder from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, \
hig_box_space_holder
from zenmapGUI.higwidgets.higlabels import HIGSectionLabel from zenmapGUI.higwidgets.higlabels import HIGSectionLabel
from zenmapGUI.higwidgets.higtables import HIGTable from zenmapGUI.higwidgets.higtables import HIGTable
from zenmapGUI.higwidgets.higbuttons import HIGButton from zenmapGUI.higwidgets.higbuttons import HIGButton
@@ -144,6 +145,7 @@ from zenmapGUI.FileChoosers import ResultsFileSingleChooserDialog
# In milliseconds. # In milliseconds.
NDIFF_CHECK_TIMEOUT = 200 NDIFF_CHECK_TIMEOUT = 200
class ScanChooser(HIGVBox): class ScanChooser(HIGVBox):
"""This class allows the selection of scan results from the list of open """This class allows the selection of scan results from the list of open
tabs or from a file. It emits the "changed" signal when the scan selection tabs or from a file. It emits the "changed" signal when the scan selection
@@ -193,7 +195,7 @@ class ScanChooser(HIGVBox):
def get_buffer(self): def get_buffer(self):
return self.txt_scan_result.get_buffer() return self.txt_scan_result.get_buffer()
def show_scan (self, widget): def show_scan(self, widget):
nmap_output = self.get_nmap_output() nmap_output = self.get_nmap_output()
if nmap_output is not None: if nmap_output is not None:
self.txt_scan_result.get_buffer().set_text(nmap_output) self.txt_scan_result.get_buffer().set_text(nmap_output)
@@ -201,14 +203,15 @@ class ScanChooser(HIGVBox):
def normalize_output(self, output): def normalize_output(self, output):
return "\n".join(output.split("\\n")) return "\n".join(output.split("\\n"))
def _pack_hbox (self): def _pack_hbox(self):
self.hbox._pack_noexpand_nofill(hig_box_space_holder()) self.hbox._pack_noexpand_nofill(hig_box_space_holder())
self.hbox._pack_expand_fill(self.table) self.hbox._pack_expand_fill(self.table)
def _attaching_widgets (self): def _attaching_widgets(self):
self.table.attach(self.combo_scan, 0,1,0,1, yoptions=0) self.table.attach(self.combo_scan, 0, 1, 0, 1, yoptions=0)
self.table.attach(self.btn_open_scan, 1,2,0,1, yoptions=0, xoptions=0) self.table.attach(
self.table.attach(self.exp_scan, 0,2,1,2) self.btn_open_scan, 1, 2, 0, 1, yoptions=0, xoptions=0)
self.table.attach(self.exp_scan, 0, 2, 1, 2)
def _set_scrolled(self): def _set_scrolled(self):
self.scrolled.set_border_width(5) self.scrolled.set_border_width(5)
@@ -223,19 +226,20 @@ class ScanChooser(HIGVBox):
# Setting scrolled window # Setting scrolled window
self.scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
def _set_text_view (self): def _set_text_view(self):
self.txg_table = self.txt_scan_result.get_buffer().get_tag_table() self.txg_table = self.txt_scan_result.get_buffer().get_tag_table()
self.txg_table.add(self.txg_tag) self.txg_table.add(self.txg_tag)
self.txg_tag.set_property("family", "Monospace") self.txg_tag.set_property("family", "Monospace")
self.txt_scan_result.set_wrap_mode(gtk.WRAP_WORD) self.txt_scan_result.set_wrap_mode(gtk.WRAP_WORD)
self.txt_scan_result.set_editable(False) self.txt_scan_result.set_editable(False)
self.txt_scan_result.get_buffer().connect("changed", self._text_changed_cb) self.txt_scan_result.get_buffer().connect(
"changed", self._text_changed_cb)
def _set_open_button (self): def _set_open_button(self):
self.btn_open_scan.connect('clicked', self.open_file) self.btn_open_scan.connect('clicked', self.open_file)
def open_file (self, widget): def open_file(self, widget):
file_chooser = ResultsFileSingleChooserDialog(_("Select Scan Result")) file_chooser = ResultsFileSingleChooserDialog(_("Select Scan Result"))
response = file_chooser.run() response = file_chooser.run()
@@ -248,15 +252,19 @@ class ScanChooser(HIGVBox):
except xml.sax.SAXParseException, e: except xml.sax.SAXParseException, e:
alert = HIGAlertDialog( alert = HIGAlertDialog(
message_format='<b>%s</b>' % _('Error parsing file'), message_format='<b>%s</b>' % _('Error parsing file'),
secondary_text=_("The file is not an Nmap XML output file. \ secondary_text=_(
The parsing error that occurred was\n%s") % str(e)) "The file is not an Nmap XML output file. "
"The parsing error that occurred was\n%s") % str(e))
alert.run() alert.run()
alert.destroy() alert.destroy()
return False return False
except Exception, e: except Exception, e:
alert = HIGAlertDialog( alert = HIGAlertDialog(
message_format='<b>%s</b>' % _('Cannot open selected file'), message_format='<b>%s</b>' % _(
secondary_text=_("This error occurred while trying to open the file:\n%s") % str(e)) 'Cannot open selected file'),
secondary_text=_("""\
This error occurred while trying to open the file:
%s""") % str(e))
alert.run() alert.run()
alert.destroy() alert.destroy()
return False return False
@@ -276,9 +284,10 @@ The parsing error that occurred was\n%s") % str(e))
self.list_scan.append([new_scan_name]) self.list_scan.append([new_scan_name])
self.scan_dict[new_scan_name] = parser self.scan_dict[new_scan_name] = parser
def _text_changed_cb (self, widget): def _text_changed_cb(self, widget):
buff = self.txt_scan_result.get_buffer () buff = self.txt_scan_result.get_buffer()
buff.apply_tag(self.txg_tag, buff.get_start_iter(), buff.get_end_iter()) buff.apply_tag(
self.txg_tag, buff.get_start_iter(), buff.get_end_iter())
def get_parsed_scan(self): def get_parsed_scan(self):
"""Return the currently selected scan's parsed output as an NmapParser """Return the currently selected scan's parsed output as an NmapParser
@@ -306,9 +315,10 @@ class DiffWindow(gtk.Window):
gtk.Window.__init__(self) gtk.Window.__init__(self)
self.set_title(_("Compare Results")) self.set_title(_("Compare Results"))
self.ndiff_process = None self.ndiff_process = None
# We allow the user to start a new diff before the old one has finished. # We allow the user to start a new diff before the old one has
# We have to keep references to old processes until they finish to avoid # finished. We have to keep references to old processes until they
# problems when tearing down the Python interpreter at program exit. # finish to avoid problems when tearing down the Python interpreter at
# program exit.
self.old_processes = [] self.old_processes = []
self.timer_id = None self.timer_id = None
@@ -358,12 +368,13 @@ class DiffWindow(gtk.Window):
self.scan_chooser_a.connect('changed', self.refresh_diff) self.scan_chooser_a.connect('changed', self.refresh_diff)
self.scan_chooser_b.connect('changed', self.refresh_diff) self.scan_chooser_b.connect('changed', self.refresh_diff)
def refresh_diff (self, widget): def refresh_diff(self, widget):
"""This method is called whenever the diff output might have changed, """This method is called whenever the diff output might have changed,
such as when a different scan was selected in one of the choosers.""" such as when a different scan was selected in one of the choosers."""
log.debug("Refresh diff.") log.debug("Refresh diff.")
if self.ndiff_process is not None and self.ndiff_process.poll() is None: if (self.ndiff_process is not None and
self.ndiff_process.poll() is None):
# Put this in the list of old processes we keep track of. # Put this in the list of old processes we keep track of.
self.old_processes.append(self.ndiff_process) self.old_processes.append(self.ndiff_process)
self.ndiff_process = None self.ndiff_process = None
@@ -378,14 +389,17 @@ class DiffWindow(gtk.Window):
self.ndiff_process = zenmapCore.Diff.ndiff(scan_a, scan_b) self.ndiff_process = zenmapCore.Diff.ndiff(scan_a, scan_b)
except OSError, e: except OSError, e:
alert = HIGAlertDialog( alert = HIGAlertDialog(
message_format = _("Error running ndiff"), message_format=_("Error running ndiff"),
secondary_text = _("There was an error running the ndiff program.\n\n") + str(e).decode(sys.getdefaultencoding(), "replace")) secondary_text=_(
"There was an error running the ndiff program.\n\n"
) + str(e).decode(sys.getdefaultencoding(), "replace"))
alert.run() alert.run()
alert.destroy() alert.destroy()
else: else:
self.progress.show() self.progress.show()
if self.timer_id is None: if self.timer_id is None:
self.timer_id = gobject.timeout_add(NDIFF_CHECK_TIMEOUT, self.check_ndiff_process) self.timer_id = gobject.timeout_add(
NDIFF_CHECK_TIMEOUT, self.check_ndiff_process)
def check_ndiff_process(self): def check_ndiff_process(self):
"""Check if the ndiff subprocess is done and show the diff if it is. """Check if the ndiff subprocess is done and show the diff if it is.
@@ -412,21 +426,23 @@ class DiffWindow(gtk.Window):
diff = self.ndiff_process.get_scan_diff() diff = self.ndiff_process.get_scan_diff()
except zenmapCore.Diff.NdiffParseException, e: except zenmapCore.Diff.NdiffParseException, e:
alert = HIGAlertDialog( alert = HIGAlertDialog(
message_format = _("Error parsing ndiff output"), message_format=_("Error parsing ndiff output"),
secondary_text = str(e)) secondary_text=str(e))
alert.run() alert.run()
alert.destroy() alert.destroy()
else: else:
self.diff_view.show_diff(diff) self.diff_view.show_diff(diff)
else: else:
# Unsuccessful completion. # Unsuccessful completion.
error_text = _("The ndiff process terminated with status code %d.") % status error_text = _(
"The ndiff process terminated with status code %d."
) % status
stderr = self.ndiff_process.stderr.read() stderr = self.ndiff_process.stderr.read()
if len(stderr) > 0: if len(stderr) > 0:
error_text += "\n\n" + stderr error_text += "\n\n" + stderr
alert = HIGAlertDialog( alert = HIGAlertDialog(
message_format = _("Error running ndiff"), message_format=_("Error running ndiff"),
secondary_text = error_text) secondary_text=error_text)
alert.run() alert.run()
alert.destroy() alert.destroy()
@@ -445,6 +461,7 @@ class DiffWindow(gtk.Window):
def close(self, widget=None, extra=None): def close(self, widget=None, extra=None):
self.destroy() self.destroy()
class DiffView(gtk.TextView): class DiffView(gtk.TextView):
REMOVE_COLOR = "#ffaaaa" REMOVE_COLOR = "#ffaaaa"
ADD_COLOR = "#ccffcc" ADD_COLOR = "#ccffcc"
@@ -456,9 +473,10 @@ class DiffView(gtk.TextView):
buff = self.get_buffer() buff = self.get_buffer()
# Create text markup tags. # Create text markup tags.
buff.create_tag("=", font = "Monospace") buff.create_tag("=", font="Monospace")
buff.create_tag("-", font = "Monospace", background = self.REMOVE_COLOR) buff.create_tag(
buff.create_tag("+", font = "Monospace", background = self.ADD_COLOR) "-", font="Monospace", background=self.REMOVE_COLOR)
buff.create_tag("+", font="Monospace", background=self.ADD_COLOR)
def clear(self): def clear(self):
self.get_buffer().set_text(u"") self.get_buffer().set_text(u"")
@@ -494,6 +512,6 @@ if __name__ == "__main__":
"Parsed 4": parsed4}) "Parsed 4": parsed4})
dw.show_all() dw.show_all()
dw.connect("delete-event", lambda x,y: gtk.main_quit()) dw.connect("delete-event", lambda x, y: gtk.main_quit())
gtk.main() gtk.main()

View File

@@ -128,6 +128,7 @@ import zenmapCore.I18N
RESPONSE_OPEN_DIRECTORY = 1 RESPONSE_OPEN_DIRECTORY = 1
class AllFilesFileFilter(gtk.FileFilter): class AllFilesFileFilter(gtk.FileFilter):
def __init__(self): def __init__(self):
gtk.FileFilter.__init__(self) gtk.FileFilter.__init__(self)
@@ -136,6 +137,7 @@ class AllFilesFileFilter(gtk.FileFilter):
self.add_pattern(pattern) self.add_pattern(pattern)
self.set_name(_("All files (%s)") % pattern) self.set_name(_("All files (%s)") % pattern)
class ResultsFileFilter(gtk.FileFilter): class ResultsFileFilter(gtk.FileFilter):
def __init__(self): def __init__(self):
gtk.FileFilter.__init__(self) gtk.FileFilter.__init__(self)
@@ -145,6 +147,7 @@ class ResultsFileFilter(gtk.FileFilter):
self.add_pattern(pattern) self.add_pattern(pattern)
self.set_name(_("Nmap XML files (%s)") % ", ".join(patterns)) self.set_name(_("Nmap XML files (%s)") % ", ".join(patterns))
class ScriptFileFilter(gtk.FileFilter): class ScriptFileFilter(gtk.FileFilter):
def __init__(self): def __init__(self):
gtk.FileFilter.__init__(self) gtk.FileFilter.__init__(self)
@@ -154,6 +157,7 @@ class ScriptFileFilter(gtk.FileFilter):
self.add_pattern(pattern) self.add_pattern(pattern)
self.set_name(_("NSE scripts (%s)") % ", ".join(patterns)) self.set_name(_("NSE scripts (%s)") % ", ".join(patterns))
class UnicodeFileChooserDialog(gtk.FileChooserDialog): class UnicodeFileChooserDialog(gtk.FileChooserDialog):
"""This is a base class for file choosers. It is designed to ease the """This is a base class for file choosers. It is designed to ease the
retrieval of Unicode file names. On most platforms, the file names returned retrieval of Unicode file names. On most platforms, the file names returned
@@ -173,6 +177,7 @@ class UnicodeFileChooserDialog(gtk.FileChooserDialog):
pass pass
return filename return filename
class AllFilesFileChooserDialog(UnicodeFileChooserDialog): class AllFilesFileChooserDialog(UnicodeFileChooserDialog):
def __init__(self, title="", parent=None, def __init__(self, title="", parent=None,
action=gtk.FILE_CHOOSER_ACTION_OPEN, action=gtk.FILE_CHOOSER_ACTION_OPEN,
@@ -184,6 +189,7 @@ class AllFilesFileChooserDialog(UnicodeFileChooserDialog):
self.set_default_response(gtk.RESPONSE_OK) self.set_default_response(gtk.RESPONSE_OK)
self.add_filter(AllFilesFileFilter()) self.add_filter(AllFilesFileFilter())
class ResultsFileSingleChooserDialog(UnicodeFileChooserDialog): class ResultsFileSingleChooserDialog(UnicodeFileChooserDialog):
"""This results file choose only allows the selection of single files, not """This results file choose only allows the selection of single files, not
directories.""" directories."""
@@ -198,6 +204,7 @@ class ResultsFileSingleChooserDialog(UnicodeFileChooserDialog):
for f in (ResultsFileFilter(), AllFilesFileFilter()): for f in (ResultsFileFilter(), AllFilesFileFilter()):
self.add_filter(f) self.add_filter(f)
class ResultsFileChooserDialog(UnicodeFileChooserDialog): class ResultsFileChooserDialog(UnicodeFileChooserDialog):
def __init__(self, title="", parent=None, def __init__(self, title="", parent=None,
action=gtk.FILE_CHOOSER_ACTION_OPEN, action=gtk.FILE_CHOOSER_ACTION_OPEN,
@@ -211,6 +218,7 @@ class ResultsFileChooserDialog(UnicodeFileChooserDialog):
for f in (ResultsFileFilter(), AllFilesFileFilter()): for f in (ResultsFileFilter(), AllFilesFileFilter()):
self.add_filter(f) self.add_filter(f)
class ScriptFileChooserDialog(UnicodeFileChooserDialog): class ScriptFileChooserDialog(UnicodeFileChooserDialog):
def __init__(self, title="", parent=None, def __init__(self, title="", parent=None,
action=gtk.FILE_CHOOSER_ACTION_OPEN, action=gtk.FILE_CHOOSER_ACTION_OPEN,
@@ -224,6 +232,7 @@ class ScriptFileChooserDialog(UnicodeFileChooserDialog):
for f in (ScriptFileFilter(), AllFilesFileFilter()): for f in (ScriptFileFilter(), AllFilesFileFilter()):
self.add_filter(f) self.add_filter(f)
class SaveResultsFileChooserDialog(UnicodeFileChooserDialog): class SaveResultsFileChooserDialog(UnicodeFileChooserDialog):
TYPES = ( TYPES = (
(_("By extension"), None, None), (_("By extension"), None, None),
@@ -286,12 +295,14 @@ class SaveResultsFileChooserDialog(UnicodeFileChooserDialog):
def get_format(self): def get_format(self):
"""Get the save format the user has chosen. It is a string, either """Get the save format the user has chosen. It is a string, either
"text" or "xml".""" "text" or "xml"."""
filetype = self.combo.get_model().get_value(self.combo.get_active_iter(), 1) filetype = self.combo.get_model().get_value(
self.combo.get_active_iter(), 1)
if filetype is None: if filetype is None:
# Guess based on extension. "xml" is the default if unknown. # Guess based on extension. "xml" is the default if unknown.
return self.EXTENSIONS.get(self.get_extension(), "xml") return self.EXTENSIONS.get(self.get_extension(), "xml")
return filetype return filetype
class DirectoryChooserDialog(UnicodeFileChooserDialog): class DirectoryChooserDialog(UnicodeFileChooserDialog):
def __init__(self, title="", parent=None, def __init__(self, title="", parent=None,
action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
@@ -301,6 +312,7 @@ class DirectoryChooserDialog(UnicodeFileChooserDialog):
UnicodeFileChooserDialog.__init__(self, title, parent, action, buttons) UnicodeFileChooserDialog.__init__(self, title, parent, action, buttons)
self.set_default_response(gtk.RESPONSE_OK) self.set_default_response(gtk.RESPONSE_OK)
class SaveToDirectoryChooserDialog(UnicodeFileChooserDialog): class SaveToDirectoryChooserDialog(UnicodeFileChooserDialog):
def __init__(self, title="", parent=None, def __init__(self, title="", parent=None,
action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,

View File

@@ -4,6 +4,7 @@ import gobject
from zenmapGUI.higwidgets.higboxes import HIGHBox from zenmapGUI.higwidgets.higboxes import HIGHBox
from zenmapGUI.higwidgets.higlabels import HintWindow from zenmapGUI.higwidgets.higlabels import HintWindow
class FilterBar(HIGHBox): class FilterBar(HIGHBox):
"""This is the bar that appears while the host filter is active. It allows """This is the bar that appears while the host filter is active. It allows
entering a string that restricts the set of visible hosts.""" entering a string that restricts the set of visible hosts."""

View File

@@ -171,13 +171,18 @@ if pixmap_path:
# Try again. # Try again.
pass pass
else: else:
log.warn('Could not find the icon for %s at any of (%s) in %s' % (icon_name, ', '.join(get_pixmap_file_names(icon_name, size)), pixmap_path)) log.warn('Could not find the icon for %s at '
'any of (%s) in %s' % (
icon_name,
', '.join(get_pixmap_file_names(icon_name, size)),
pixmap_path))
continue continue
iconset = gtk.IconSet(pixbuf) iconset = gtk.IconSet(pixbuf)
iconfactory.add(key, iconset) iconfactory.add(key, iconset)
log.debug('Register %s icon name for file %s' % (key, file_path)) log.debug('Register %s icon name for file %s' % (key, file_path))
iconfactory.add_default() iconfactory.add_default()
def get_os_icon(host): def get_os_icon(host):
osmatch = host.get_best_osmatch() osmatch = host.get_best_osmatch()
if osmatch and osmatch['osclasses']: if osmatch and osmatch['osclasses']:
@@ -190,6 +195,7 @@ def get_os_icon(host):
else: else:
return get_os(None, None, 'icon') return get_os(None, None, 'icon')
def get_os_logo(host): def get_os_logo(host):
osmatch = host.get_best_osmatch() osmatch = host.get_best_osmatch()
if osmatch and osmatch['osclasses']: if osmatch and osmatch['osclasses']:
@@ -202,51 +208,53 @@ def get_os_logo(host):
else: else:
return get_os(None, None, 'logo') return get_os(None, None, 'logo')
def get_os(osfamily, osmatch, type): def get_os(osfamily, osmatch, type):
if osfamily: if osfamily:
if osfamily == 'Linux': if osfamily == 'Linux':
if re.findall("ubuntu", osmatch.lower()): if re.findall("ubuntu", osmatch.lower()):
# Ubuntu icon # Ubuntu icon
return 'ubuntu_%s'%type return 'ubuntu_%s' % type
elif re.findall("red hat", osmatch.lower()): elif re.findall("red hat", osmatch.lower()):
# RedHat icon # RedHat icon
return 'redhat_%s'%type return 'redhat_%s' % type
else: else:
# Generic Linux icon # Generic Linux icon
return 'linux_%s'%type return 'linux_%s' % type
elif osfamily == 'Windows': elif osfamily == 'Windows':
# Windows icon # Windows icon
return 'win_%s'%type return 'win_%s' % type
elif osfamily == 'OpenBSD': elif osfamily == 'OpenBSD':
# OpenBSD icon # OpenBSD icon
return 'openbsd_%s'%type return 'openbsd_%s' % type
elif osfamily == 'FreeBSD': elif osfamily == 'FreeBSD':
# FreeBSD icon # FreeBSD icon
return 'freebsd_%s'%type return 'freebsd_%s' % type
elif osfamily == 'NetBSD': elif osfamily == 'NetBSD':
# NetBSD icon # NetBSD icon
return 'default_%s'%type return 'default_%s' % type
elif osfamily == 'Solaris': elif osfamily == 'Solaris':
# Solaris icon # Solaris icon
return 'solaris_%s'%type return 'solaris_%s' % type
elif osfamily == 'OpenSolaris': elif osfamily == 'OpenSolaris':
# OpenSolaris icon # OpenSolaris icon
return 'solaris_%s'%type return 'solaris_%s' % type
elif osfamily == 'IRIX': elif osfamily == 'IRIX':
# Irix icon # Irix icon
return 'irix_%s'%type return 'irix_%s' % type
elif osfamily == 'Mac OS X': elif osfamily == 'Mac OS X':
# Mac OS X icon # Mac OS X icon
return 'macosx_%s'%type return 'macosx_%s' % type
elif osfamily == 'Mac OS': elif osfamily == 'Mac OS':
# Mac OS icon # Mac OS icon
return 'macosx_%s'%type return 'macosx_%s' % type
else: else:
# Default OS icon # Default OS icon
return 'default_%s'%type return 'default_%s' % type
else: else:
# Unknown OS icon # Unknown OS icon
return 'unknown_%s'%type return 'unknown_%s' % type
def get_vulnerability_logo(open_ports): def get_vulnerability_logo(open_ports):
open_ports = int(open_ports) open_ports = int(open_ports)

View File

@@ -159,6 +159,7 @@ hildon = None
if is_maemo(): if is_maemo():
import hildon import hildon
class UmitScanWindow(hildon.Window): class UmitScanWindow(hildon.Window):
def __init__(self): def __init__(self):
hildon.Window.__init__(self) hildon.Window.__init__(self)
@@ -174,9 +175,10 @@ else:
HIGMainWindow.__init__(self) HIGMainWindow.__init__(self)
self.vbox = gtk.VBox() self.vbox = gtk.VBox()
def can_print(): def can_print():
"""Return true if we have printing operations (PyGTK 2.10 or later) or false """Return true if we have printing operations (PyGTK 2.10 or later) or
otherwise.""" false otherwise."""
try: try:
gtk.PrintOperation gtk.PrintOperation
except AttributeError: except AttributeError:
@@ -184,6 +186,7 @@ def can_print():
else: else:
return True return True
class ScanWindow(UmitScanWindow): class ScanWindow(UmitScanWindow):
def __init__(self): def __init__(self):
UmitScanWindow.__init__(self) UmitScanWindow.__init__(self)
@@ -199,7 +202,7 @@ class ScanWindow(UmitScanWindow):
# self.vbox is a container for the menubar and the scan interface # self.vbox is a container for the menubar and the scan interface
self.add(self.vbox) self.add(self.vbox)
self.connect ('delete-event', self._exit_cb) self.connect('delete-event', self._exit_cb)
self._create_ui_manager() self._create_ui_manager()
self._create_menubar() self._create_menubar()
self._create_scan_interface() self._create_scan_interface()
@@ -433,25 +436,29 @@ class ScanWindow(UmitScanWindow):
def _search_scan_result(self, widget): def _search_scan_result(self, widget):
"""Displays a search window.""" """Displays a search window."""
search_window = SearchWindow(self._load_search_result, self._append_search_result) search_window = SearchWindow(
self._load_search_result, self._append_search_result)
search_window.show_all() search_window.show_all()
def _filter_cb(self, widget): def _filter_cb(self, widget):
self.scan_interface.toggle_filter_bar() self.scan_interface.toggle_filter_bar()
def _load_search_result(self, results): def _load_search_result(self, results):
"""This function is passed as an argument to the SearchWindow.__init__ method. """This function is passed as an argument to the SearchWindow.__init__
When the user selects scans in the search window and clicks on \"Open\", this method. When the user selects scans in the search window and clicks on
function is called to load each of the selected scans into a new window.""" "Open", this function is called to load each of the selected scans into
a new window."""
for result in results: for result in results:
self._load(self.get_empty_interface(), parsed_result = results[result][1]) self._load(self.get_empty_interface(),
parsed_result=results[result][1])
def _append_search_result(self, results): def _append_search_result(self, results):
"""This function is passed as an argument to the SearchWindow.__init__ method. """This function is passed as an argument to the SearchWindow.__init__
When the user selects scans in the search window and clicks on \"Append\", this method. When the user selects scans in the search window and clicks on
function is called to append the selected scans into the current window.""" "Append", this function is called to append the selected scans into the
current window."""
for result in results: for result in results:
self._load(self.scan_interface, parsed_result = results[result][1]) self._load(self.scan_interface, parsed_result=results[result][1])
def store_result(self, scan_interface): def store_result(self, scan_interface):
"""Stores the network inventory into the database.""" """Stores the network inventory into the database."""
@@ -459,23 +466,28 @@ class ScanWindow(UmitScanWindow):
try: try:
scan_interface.inventory.save_to_db() scan_interface.inventory.save_to_db()
except Exception, e: except Exception, e:
alert = HIGAlertDialog(message_format = _("Can't save to database"), alert = HIGAlertDialog(
secondary_text = _("Can't store unsaved scans to the recent scans database:\n%s") % str(e)) message_format=_("Can't save to database"),
secondary_text=_("Can't store unsaved scans to the "
"recent scans database:\n%s") % str(e))
alert.run() alert.run()
alert.destroy() alert.destroy()
log.debug(">>> Can't save result to database: %s." % str(e)) log.debug(">>> Can't save result to database: %s." % str(e))
def get_recent_scans(self): def get_recent_scans(self):
"""Gets seven most recent scans and appends them to the default UI definition.""" """Gets seven most recent scans and appends them to the default UI
definition."""
r_scans = recent_scans.get_recent_scans_list() r_scans = recent_scans.get_recent_scans_list()
new_rscan_xml = '' new_rscan_xml = ''
for scan in r_scans[:7]: for scan in r_scans[:7]:
scan = scan.replace('\n','') scan = scan.replace('\n', '')
if os.access(split(scan)[0],os.R_OK) and isfile(scan): if os.access(split(scan)[0], os.R_OK) and isfile(scan):
scan = scan.replace('\n','') scan = scan.replace('\n', '')
new_rscan = (scan, None, scan, None, scan, self._load_recent_scan) new_rscan = (
new_rscan_xml += "<menuitem action=%s/>\n" % xml.sax.saxutils.quoteattr(scan) scan, None, scan, None, scan, self._load_recent_scan)
new_rscan_xml += "<menuitem action=%s/>\n" % (
xml.sax.saxutils.quoteattr(scan))
self.main_actions.append(new_rscan) self.main_actions.append(new_rscan)
else: else:
@@ -501,16 +513,19 @@ class ScanWindow(UmitScanWindow):
self.menubar.show_all() self.menubar.show_all()
def _create_scan_interface(self): def _create_scan_interface(self):
self.scan_interface.scan_result.scan_result_notebook.scans_list.append_button.connect("clicked", self._append_scan_results_cb) notebook = self.scan_interface.scan_result.scan_result_notebook
self.scan_interface.scan_result.scan_result_notebook.nmap_output.connect("changed", self._displayed_scan_change_cb) notebook.scans_list.append_button.connect(
"clicked", self._append_scan_results_cb)
notebook.nmap_output.connect("changed", self._displayed_scan_change_cb)
self._displayed_scan_change_cb(None) self._displayed_scan_change_cb(None)
self.scan_interface.show_all() self.scan_interface.show_all()
self.vbox.pack_start(self.scan_interface, True, True, 0) self.vbox.pack_start(self.scan_interface, True, True, 0)
def show_open_dialog(self, title = None): def show_open_dialog(self, title=None):
"""Show a load file chooser and return the filename chosen.""" """Show a load file chooser and return the filename chosen."""
if self._results_filechooser_dialog is None: if self._results_filechooser_dialog is None:
self._results_filechooser_dialog = ResultsFileChooserDialog(title = title) self._results_filechooser_dialog = ResultsFileChooserDialog(
title=title)
filename = None filename = None
response = self._results_filechooser_dialog.run() response = self._results_filechooser_dialog.run()
@@ -519,8 +534,9 @@ class ScanWindow(UmitScanWindow):
elif response == RESPONSE_OPEN_DIRECTORY: elif response == RESPONSE_OPEN_DIRECTORY:
filename = self._results_filechooser_dialog.get_filename() filename = self._results_filechooser_dialog.get_filename()
# Check if the selected filename is a directory. If not, we take only the # Check if the selected filename is a directory. If not, we take
# directory part of the path, omitting the actual name of the selected file. # only the directory part of the path, omitting the actual name of
# the selected file.
if filename is not None and not os.path.isdir(filename): if filename is not None and not os.path.isdir(filename):
filename = os.path.dirname(filename) filename = os.path.dirname(filename)
@@ -528,8 +544,9 @@ class ScanWindow(UmitScanWindow):
return filename return filename
def _load_scan_results_cb(self, p): def _load_scan_results_cb(self, p):
"""'Open Scan' callback function. Displays a file chooser dialog and loads the """'Open Scan' callback function. Displays a file chooser dialog and
scan from the selected file or from the selected directory.""" loads the scan from the selected file or from the selected
directory."""
filename = self.show_open_dialog(p.get_name()) filename = self.show_open_dialog(p.get_name())
if filename is not None: if filename is not None:
scan_interface = self.get_empty_interface() scan_interface = self.get_empty_interface()
@@ -539,8 +556,8 @@ class ScanWindow(UmitScanWindow):
self._load(scan_interface, filename) self._load(scan_interface, filename)
def _append_scan_results_cb(self, p): def _append_scan_results_cb(self, p):
"""'Append Scan' callback function. Displays a file chooser dialog and appends the """'Append Scan' callback function. Displays a file chooser dialog and
scan from the selected file into the current window.""" appends the scan from the selected file into the current window."""
filename = self.show_open_dialog(p.get_name()) filename = self.show_open_dialog(p.get_name())
if filename is not None: if filename is not None:
if os.path.isdir(filename): if os.path.isdir(filename):
@@ -559,7 +576,8 @@ class ScanWindow(UmitScanWindow):
widget.set_sensitive(entry is not None) widget.set_sensitive(entry is not None)
def _load_recent_scan(self, widget): def _load_recent_scan(self, widget):
"""A helper function for loading a recent scan directly from the menu.""" """A helper function for loading a recent scan directly from the
menu."""
self._load(self.get_empty_interface(), widget.get_name()) self._load(self.get_empty_interface(), widget.get_name())
def _load(self, scan_interface, filename=None, parsed_result=None): def _load(self, scan_interface, filename=None, parsed_result=None):
@@ -587,54 +605,59 @@ class ScanWindow(UmitScanWindow):
def _load_directory(self, scan_interface, directory): def _load_directory(self, scan_interface, directory):
for file in os.listdir(directory): for file in os.listdir(directory):
if os.path.isdir(os.path.join(directory,file)): if os.path.isdir(os.path.join(directory, file)):
continue continue
self._load(scan_interface, filename = os.path.join(directory, file)) self._load(scan_interface, filename=os.path.join(directory, file))
def _save_scan_results_cb(self, widget): def _save_scan_results_cb(self, widget):
"""'Save Scan' callback function. If it's OK to save the scan, it displays a """'Save Scan' callback function. If it's OK to save the scan, it
'Save File' dialog and saves the scan. If not, it displays an appropriate displays a 'Save File' dialog and saves the scan. If not, it displays
alert dialog.""" an appropriate alert dialog."""
num_scans = len(self.scan_interface.inventory.get_scans()) num_scans = len(self.scan_interface.inventory.get_scans())
if num_scans == 0: if num_scans == 0:
alert = HIGAlertDialog(message_format=_('Nothing to save'), alert = HIGAlertDialog(
secondary_text=_("""\ message_format=_('Nothing to save'),
There are no scans with results to be saved. Run a scan with the "Scan" button \ secondary_text=_(
first.""")) 'There are no scans with results to be saved. '
'Run a scan with the "Scan" button first.'))
alert.run() alert.run()
alert.destroy() alert.destroy()
return return
num_scans_running = self.scan_interface.num_scans_running() num_scans_running = self.scan_interface.num_scans_running()
if num_scans_running > 0: if num_scans_running > 0:
if num_scans_running == 1: if num_scans_running == 1:
text = _("There is a scan still running. Wait until it finishes and then save.") text = _("There is a scan still running. "
"Wait until it finishes and then save.")
else: else:
text = _("There are %u scans still running. Wait until they finish and then save.")\ text = _("There are %u scans still running. Wait until they "
% num_scans_running "finish and then save.") % num_scans_running
alert = HIGAlertDialog(message_format=_('Scan is running'), alert = HIGAlertDialog(message_format=_('Scan is running'),
secondary_text=text) secondary_text=text)
alert.run() alert.run()
alert.destroy() alert.destroy()
return return
# If there's more than one scan in the inventory, display a warning dialog saying # If there's more than one scan in the inventory, display a warning
# that only the most recent scan will be saved # dialog saying that only the most recent scan will be saved
selected = 0 selected = 0
if num_scans > 1: if num_scans > 1:
#text = _("You have %u scans loaded in the current view. Only the most recent scan " \ #text = _("You have %u scans loaded in the current view. "
# "will be saved." % num_scans) # "Only the most recent scan will be saved." % num_scans)
#alert = HIGAlertDialog(message_format=_("More than one scan loaded"), #alert = HIGAlertDialog(
# secondary_text=text) # message_format=_("More than one scan loaded"),
# secondary_text=text)
#alert.run() #alert.run()
#alert.destroy() #alert.destroy()
dlg = HIGDialog(title="Choose a scan to save", dlg = HIGDialog(
parent=self, title="Choose a scan to save",
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, parent=self,
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.STOCK_SAVE, gtk.RESPONSE_OK)) buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
dlg.vbox.pack_start(gtk.Label("You have %u scans loaded in the current view.\n" \ gtk.STOCK_SAVE, gtk.RESPONSE_OK))
"Select the scan which you would like to save." \ dlg.vbox.pack_start(gtk.Label(
% num_scans), False) "You have %u scans loaded in the current view.\n"
"Select the scan which you would like to save." % num_scans),
False)
scan_combo = gtk.combo_box_new_text() scan_combo = gtk.combo_box_new_text()
for scan in self.scan_interface.inventory.get_scans(): for scan in self.scan_interface.inventory.get_scans():
scan_combo.append_text(scan.nmap_command) scan_combo.append_text(scan.nmap_command)
@@ -653,7 +676,8 @@ first."""))
SaveResultsFileChooserDialog(title=_('Save Scan')) SaveResultsFileChooserDialog(title=_('Save Scan'))
# Supply a default file name if this scan was previously saved. # Supply a default file name if this scan was previously saved.
if self.scan_interface.saved_filename: if self.scan_interface.saved_filename:
self._save_results_filechooser_dialog.set_filename(self.scan_interface.saved_filename) self._save_results_filechooser_dialog.set_filename(
self.scan_interface.saved_filename)
response = self._save_results_filechooser_dialog.run() response = self._save_results_filechooser_dialog.run()
@@ -680,19 +704,21 @@ This scan has not been run yet. Start the scan with the "Scan" button first.'))
num_scans_running = self.scan_interface.num_scans_running() num_scans_running = self.scan_interface.num_scans_running()
if num_scans_running > 0: if num_scans_running > 0:
if num_scans_running == 1: if num_scans_running == 1:
text = _("There is a scan still running. Wait until it finishes and then save.") text = _("There is a scan still running. "
"Wait until it finishes and then save.")
else: else:
text = _("There are %u scans still running. Wait until they finish and then save.")\ text = _("There are %u scans still running. Wait until they "
% num_scans_running "finish and then save.") % num_scans_running
alert = HIGAlertDialog(message_format=_('Scan is running'), alert = HIGAlertDialog(message_format=_('Scan is running'),
secondary_text=text) secondary_text=text)
alert.run() alert.run()
alert.destroy() alert.destroy()
return return
# We have multiple scans in our network inventory, so we need to display a directory # We have multiple scans in our network inventory, so we need to
# chooser dialog # display a directory chooser dialog
dir_chooser = SaveToDirectoryChooserDialog(title=_("Choose a directory to save scans into")) dir_chooser = SaveToDirectoryChooserDialog(
title=_("Choose a directory to save scans into"))
if dir_chooser.run() == gtk.RESPONSE_OK: if dir_chooser.run() == gtk.RESPONSE_OK:
self._save_all(self.scan_interface, dir_chooser.get_filename()) self._save_all(self.scan_interface, dir_chooser.get_filename())
dir_chooser.destroy() dir_chooser.destroy()
@@ -729,16 +755,20 @@ This scan has not been run yet. Start the scan with the "Scan" button first.'))
recent_scans.add_recent_scan(filename) recent_scans.add_recent_scan(filename)
recent_scans.save() recent_scans.save()
def _save(self, scan_interface, saved_filename, selected_index, format = "xml"): def _save(self, scan_interface, saved_filename, selected_index,
format="xml"):
"""Saves the scan into a file with a given filename. Displays an alert """Saves the scan into a file with a given filename. Displays an alert
dialog if the save fails.""" dialog if the save fails."""
log.debug(">>> File being saved: %s" % saved_filename) log.debug(">>> File being saved: %s" % saved_filename)
try: try:
scan_interface.inventory.save_to_file(saved_filename, selected_index, format) scan_interface.inventory.save_to_file(
scan_interface.inventory.get_scans()[selected_index].unsaved = False saved_filename, selected_index, format)
scan_interface.inventory.get_scans()[selected_index].unsaved = \
False
except (OSError, IOError), e: except (OSError, IOError), e:
alert = HIGAlertDialog(message_format=_('Can\'t save file'), alert = HIGAlertDialog(
secondary_text=_('Can\'t open file to write.\n%s') % str(e)) message_format=_("Can't save file"),
secondary_text=_("Can't open file to write.\n%s") % str(e))
alert.run() alert.run()
alert.destroy() alert.destroy()
else: else:
@@ -766,12 +796,16 @@ This scan has not been run yet. Start the scan with the "Scan" button first.'))
return w return w
def _new_scan_profile_cb(self, p): def _new_scan_profile_cb(self, p):
pe = ProfileEditor(command=self.scan_interface.command_toolbar.command, deletable=False) pe = ProfileEditor(
command=self.scan_interface.command_toolbar.command,
deletable=False)
pe.set_scan_interface(self.scan_interface) pe.set_scan_interface(self.scan_interface)
pe.show_all() pe.show_all()
def _edit_scan_profile_cb(self, p): def _edit_scan_profile_cb(self, p):
pe = ProfileEditor(profile_name=self.scan_interface.toolbar.selected_profile,deletable=True,overwrite=True) pe = ProfileEditor(
profile_name=self.scan_interface.toolbar.selected_profile,
deletable=True, overwrite=True)
pe.set_scan_interface(self.scan_interface) pe.set_scan_interface(self.scan_interface)
pe.show_all() pe.show_all()
@@ -779,18 +813,20 @@ This scan has not been run yet. Start the scan with the "Scan" button first.'))
show_help() show_help()
def _exit_cb(self, *args): def _exit_cb(self, *args):
"""Closes the window, prompting for confirmation if necessary. If one of """Closes the window, prompting for confirmation if necessary. If one
the tabs couldn't be closed, the function returns True and doesn't exit of the tabs couldn't be closed, the function returns True and doesn't
the application.""" exit the application."""
if self.scan_interface.changed: if self.scan_interface.changed:
log.debug("Found changes on closing window") log.debug("Found changes on closing window")
dialog = HIGDialog(buttons=(_('Close anyway').encode('utf-8'), gtk.RESPONSE_CLOSE, dialog = HIGDialog(
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) buttons=(_('Close anyway').encode('utf-8'),
gtk.RESPONSE_CLOSE, gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL))
alert = HIGEntryLabel('<b>%s</b>' % _("Unsaved changes")) alert = HIGEntryLabel('<b>%s</b>' % _("Unsaved changes"))
text = HIGEntryLabel(_('The given scan has unsaved changes.\n\ text = HIGEntryLabel(_("The given scan has unsaved changes.\n"
What do you want to do?')) "What do you want to do?"))
hbox = HIGHBox() hbox = HIGHBox()
hbox.set_border_width(5) hbox.set_border_width(5)
hbox.set_spacing(12) hbox.set_spacing(12)
@@ -800,7 +836,8 @@ What do you want to do?'))
vbox.set_spacing(12) vbox.set_spacing(12)
image = gtk.Image() image = gtk.Image()
image.set_from_stock(gtk.STOCK_DIALOG_QUESTION,gtk.ICON_SIZE_DIALOG) image.set_from_stock(
gtk.STOCK_DIALOG_QUESTION, gtk.ICON_SIZE_DIALOG)
vbox.pack_start(alert) vbox.pack_start(alert)
vbox.pack_start(text) vbox.pack_start(text)
@@ -822,13 +859,16 @@ What do you want to do?'))
elif self.scan_interface.num_scans_running() > 0: elif self.scan_interface.num_scans_running() > 0:
log.debug("Trying to close a window with a running scan") log.debug("Trying to close a window with a running scan")
dialog = HIGDialog(buttons=(_('Close anyway').encode('utf-8'), gtk.RESPONSE_CLOSE, dialog = HIGDialog(
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) buttons=(_('Close anyway').encode('utf-8'),
gtk.RESPONSE_CLOSE, gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL))
alert = HIGEntryLabel('<b>%s</b>' % _("Trying to close")) alert = HIGEntryLabel('<b>%s</b>' % _("Trying to close"))
text = HIGEntryLabel(_('The window you are trying to close has a scan \ text = HIGEntryLabel(_(
running at the background.\nWhat do you want to do?')) "The window you are trying to close has a scan running in "
"the background.\nWhat do you want to do?"))
hbox = HIGHBox() hbox = HIGHBox()
hbox.set_border_width(5) hbox.set_border_width(5)
hbox.set_spacing(12) hbox.set_spacing(12)
@@ -838,7 +878,8 @@ running at the background.\nWhat do you want to do?'))
vbox.set_spacing(12) vbox.set_spacing(12)
image = gtk.Image() image = gtk.Image()
image.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) image.set_from_stock(
gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
vbox.pack_start(alert) vbox.pack_start(alert)
vbox.pack_start(text) vbox.pack_start(text)
@@ -865,7 +906,8 @@ running at the background.\nWhat do you want to do?'))
entry = self.scan_interface.scan_result.scan_result_notebook.nmap_output.get_active_entry() entry = self.scan_interface.scan_result.scan_result_notebook.nmap_output.get_active_entry()
if entry is None: if entry is None:
return False return False
zenmapGUI.Print.run_print_operation(self.scan_interface.inventory, entry) zenmapGUI.Print.run_print_operation(
self.scan_interface.inventory, entry)
def _quit_cb(self, *args): def _quit_cb(self, *args):
"""Close all open windows.""" """Close all open windows."""
@@ -874,12 +916,15 @@ running at the background.\nWhat do you want to do?'))
if window._exit_cb(): if window._exit_cb():
break break
def _load_diff_compare_cb (self, widget=None, extra=None): def _load_diff_compare_cb(self, widget=None, extra=None):
"""Loads all active scans into a dictionary, passes it to the DiffWindow """Loads all active scans into a dictionary, passes it to the
constructor, and then displays the 'Compare Results' window.""" DiffWindow constructor, and then displays the 'Compare Results'
self.diff_window = DiffWindow(self.scan_interface.inventory.get_scans()) window."""
self.diff_window = DiffWindow(
self.scan_interface.inventory.get_scans())
self.diff_window.show_all() self.diff_window.show_all()
def show_help(): def show_help():
import urllib import urllib
import webbrowser import webbrowser

View File

@@ -134,6 +134,7 @@ from zenmapGUI.higwidgets.higtables import HIGTable
from zenmapGUI.higwidgets.higlabels import HIGEntryLabel from zenmapGUI.higwidgets.higlabels import HIGEntryLabel
from zenmapGUI.higwidgets.higbuttons import HIGButton, HIGToggleButton from zenmapGUI.higwidgets.higbuttons import HIGButton, HIGToggleButton
class NmapOutputProperties(HIGDialog): class NmapOutputProperties(HIGDialog):
def __init__(self, nmap_output_view): def __init__(self, nmap_output_view):
HIGDialog.__init__(self, _("Nmap Output Properties"), HIGDialog.__init__(self, _("Nmap Output Properties"),
@@ -164,10 +165,14 @@ class NmapOutputProperties(HIGDialog):
############# #############
# Properties: # Properties:
self.property_names = {"details": [_("details"), "MAC Address:"], self.property_names = {"details": [_("details"), "MAC Address:"],
"port_list": [_("port listing title"), "PORT STATE SERVICE"], "port_list": [_("port listing title"),
"open_port": [_("open port"), "22/tcp open ssh"], "PORT STATE SERVICE"],
"closed_port": [_("closed port"), "70/tcp closed gopher"], "open_port": [_("open port"),
"filtered_port": [_("filtered port"), "80/tcp filtered http"], "22/tcp open ssh"],
"closed_port": [_("closed port"),
"70/tcp closed gopher"],
"filtered_port": [_("filtered port"),
"80/tcp filtered http"],
"date": [_("date"), "2006-05-26 11:14 BRT"], "date": [_("date"), "2006-05-26 11:14 BRT"],
"hostname": [_("hostname"), "scanme.nmap.org"], "hostname": [_("hostname"), "scanme.nmap.org"],
"ip": [_("ip"), "127.0.0.1"]} "ip": [_("ip"), "127.0.0.1"]}
@@ -182,18 +187,23 @@ class NmapOutputProperties(HIGDialog):
self.property_names[p].append(gtk.gdk.Color(*settings[4])) self.property_names[p].append(gtk.gdk.Color(*settings[4]))
self.property_names[p].append(settings[5]) self.property_names[p].append(settings[5])
# Creating properties and related widgets and attaching it to main table # Creating properties and related widgets and attaching it to main
# table
y1 = 0 y1 = 0
y2 = 1 y2 = 1
for p in self.property_names: for p in self.property_names:
hp = HighlightProperty(p, self.property_names[p]) hp = HighlightProperty(p, self.property_names[p])
self.highlight_main_table.attach(hp.property_name_label, 0, 1, y1, y2) self.highlight_main_table.attach(
hp.property_name_label, 0, 1, y1, y2)
self.highlight_main_table.attach(hp.example_label, 1, 2, y1, y2) self.highlight_main_table.attach(hp.example_label, 1, 2, y1, y2)
self.highlight_main_table.attach(hp.bold_tg_button, 2, 3, y1, y2) self.highlight_main_table.attach(hp.bold_tg_button, 2, 3, y1, y2)
self.highlight_main_table.attach(hp.italic_tg_button, 3, 4, y1, y2) self.highlight_main_table.attach(hp.italic_tg_button, 3, 4, y1, y2)
self.highlight_main_table.attach(hp.underline_tg_button, 4, 5, y1, y2) self.highlight_main_table.attach(
self.highlight_main_table.attach(hp.text_color_button, 5, 6, y1, y2) hp.underline_tg_button, 4, 5, y1, y2)
self.highlight_main_table.attach(hp.highlight_color_button, 6, 7, y1, y2) self.highlight_main_table.attach(
hp.text_color_button, 5, 6, y1, y2)
self.highlight_main_table.attach(
hp.highlight_color_button, 6, 7, y1, y2)
# Setting example styles and colors # Setting example styles and colors
hp.update_example() hp.update_example()
@@ -203,13 +213,13 @@ class NmapOutputProperties(HIGDialog):
y1 += 1 y1 += 1
y2 += 1 y2 += 1
# Packing main table into main vbox # Packing main table into main vbox
self.highlight_main_vbox.pack_start(self.highlight_main_table) self.highlight_main_vbox.pack_start(self.highlight_main_table)
# Adding color tab # Adding color tab
self.properties_notebook.append_page(self.highlight_main_vbox, self.properties_notebook.append_page(
gtk.Label(_("Highlight definitions"))) self.highlight_main_vbox,
gtk.Label(_("Highlight definitions")))
class HighlightProperty(object): class HighlightProperty(object):
@@ -235,8 +245,10 @@ class HighlightProperty(object):
self.bold_tg_button = HIGToggleButton("", gtk.STOCK_BOLD) self.bold_tg_button = HIGToggleButton("", gtk.STOCK_BOLD)
self.italic_tg_button = HIGToggleButton("", gtk.STOCK_ITALIC) self.italic_tg_button = HIGToggleButton("", gtk.STOCK_ITALIC)
self.underline_tg_button = HIGToggleButton("", gtk.STOCK_UNDERLINE) self.underline_tg_button = HIGToggleButton("", gtk.STOCK_UNDERLINE)
self.text_color_button = HIGButton(_("Text"), stock=gtk.STOCK_SELECT_COLOR) self.text_color_button = HIGButton(
self.highlight_color_button = HIGButton(_("Highlight"), stock=gtk.STOCK_SELECT_COLOR) _("Text"), stock=gtk.STOCK_SELECT_COLOR)
self.highlight_color_button = HIGButton(
_("Highlight"), stock=gtk.STOCK_SELECT_COLOR)
def __connect_buttons(self): def __connect_buttons(self):
self.bold_tg_button.connect("toggled", self.update_example) self.bold_tg_button.connect("toggled", self.update_example)
@@ -244,20 +256,23 @@ class HighlightProperty(object):
self.underline_tg_button.connect("toggled", self.update_example) self.underline_tg_button.connect("toggled", self.update_example)
self.text_color_button.connect("clicked", self.text_color_dialog) self.text_color_button.connect("clicked", self.text_color_dialog)
self.highlight_color_button.connect("clicked", self.highlight_color_dialog) self.highlight_color_button.connect(
"clicked", self.highlight_color_dialog)
#################################### ####################################
# Text color dialog # Text color dialog
def text_color_dialog(self, widget): def text_color_dialog(self, widget):
color_dialog = gtk.ColorSelectionDialog("%s %s" % (self.label, _("text color"))) color_dialog = gtk.ColorSelectionDialog(
"%s %s" % (self.label, _("text color")))
color_dialog.colorsel.set_current_color(self.text_color) color_dialog.colorsel.set_current_color(self.text_color)
color_dialog.ok_button.connect("clicked", self.text_color_dialog_ok, color_dialog) color_dialog.ok_button.connect(
color_dialog.cancel_button.connect("clicked", "clicked", self.text_color_dialog_ok, color_dialog)
self.text_color_dialog_cancel, color_dialog) color_dialog.cancel_button.connect(
color_dialog.connect("delete-event", self.text_color_dialog_close, color_dialog) "clicked", self.text_color_dialog_cancel, color_dialog)
color_dialog.connect(
"delete-event", self.text_color_dialog_close, color_dialog)
color_dialog.run() color_dialog.run()
@@ -272,18 +287,21 @@ class HighlightProperty(object):
def text_color_dialog_close(self, widget, extra, color_dialog): def text_color_dialog_close(self, widget, extra, color_dialog):
color_dialog.destroy() color_dialog.destroy()
######################################### #########################################
# Highlight color dialog # Highlight color dialog
def highlight_color_dialog(self, widget): def highlight_color_dialog(self, widget):
color_dialog = gtk.ColorSelectionDialog("%s %s" % (self.property_name, color_dialog = gtk.ColorSelectionDialog(
_("highlight color"))) "%s %s" % (self.property_name, _("highlight color")))
color_dialog.colorsel.set_current_color(self.highlight_color) color_dialog.colorsel.set_current_color(self.highlight_color)
color_dialog.ok_button.connect("clicked", self.highlight_color_dialog_ok, color_dialog) color_dialog.ok_button.connect(
color_dialog.cancel_button.connect("clicked", self.highlight_color_dialog_cancel, "clicked", self.highlight_color_dialog_ok, color_dialog)
color_dialog.cancel_button.connect(
"clicked", self.highlight_color_dialog_cancel,
color_dialog) color_dialog)
color_dialog.connect("delete-event", self.highlight_color_dialog_close, color_dialog) color_dialog.connect(
"delete-event", self.highlight_color_dialog_close,
color_dialog)
color_dialog.run() color_dialog.run()
@@ -304,8 +322,9 @@ class HighlightProperty(object):
attributes = pango.AttrList() attributes = pango.AttrList()
attributes.insert(pango.AttrForeground(self.text_color.red, self.text_color.green, attributes.insert(
self.text_color.blue, start, end)) pango.AttrForeground(self.text_color.red,
self.text_color.green, self.text_color.blue, start, end))
attributes.insert(pango.AttrBackground(self.highlight_color.red, attributes.insert(pango.AttrBackground(self.highlight_color.red,
self.highlight_color.green, self.highlight_color.green,
self.highlight_color.blue, self.highlight_color.blue,
@@ -315,7 +334,8 @@ class HighlightProperty(object):
if self.bold_tg_button.get_active(): if self.bold_tg_button.get_active():
attributes.insert(pango.AttrWeight(pango.WEIGHT_HEAVY, start, end)) attributes.insert(pango.AttrWeight(pango.WEIGHT_HEAVY, start, end))
else: else:
attributes.insert(pango.AttrWeight(pango.WEIGHT_NORMAL, start, end)) attributes.insert(
pango.AttrWeight(pango.WEIGHT_NORMAL, start, end))
# Italic verification # Italic verification
if self.italic_tg_button.get_active(): if self.italic_tg_button.get_active():
@@ -325,13 +345,14 @@ class HighlightProperty(object):
# Underline verification # Underline verification
if self.underline_tg_button.get_active(): if self.underline_tg_button.get_active():
attributes.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE, start, end)) attributes.insert(
pango.AttrUnderline(pango.UNDERLINE_SINGLE, start, end))
else: else:
attributes.insert(pango.AttrUnderline(pango.UNDERLINE_NONE, start, end)) attributes.insert(
pango.AttrUnderline(pango.UNDERLINE_NONE, start, end))
self.example_label.set_attributes(attributes) self.example_label.set_attributes(attributes)
def show_bold(self, widget): def show_bold(self, widget):
self.example_label.set_markup("<>") self.example_label.set_markup("<>")

View File

@@ -134,13 +134,14 @@ from zenmapCore.UmitConf import NmapOutputHighlight
from zenmapGUI.NmapOutputProperties import NmapOutputProperties from zenmapGUI.NmapOutputProperties import NmapOutputProperties
class NmapOutputViewer (gtk.VBox): class NmapOutputViewer (gtk.VBox):
HIGHLIGHT_PROPERTIES = ["details", "date", "hostname", "ip", "port_list", HIGHLIGHT_PROPERTIES = ["details", "date", "hostname", "ip", "port_list",
"open_port", "closed_port", "filtered_port"] "open_port", "closed_port", "filtered_port"]
def __init__ (self, refresh=1, stop=1): def __init__(self, refresh=1, stop=1):
self.nmap_highlight = NmapOutputHighlight() self.nmap_highlight = NmapOutputHighlight()
gtk.VBox.__init__ (self) gtk.VBox.__init__(self)
# Creating widgets # Creating widgets
self.__create_widgets() self.__create_widgets()
@@ -158,7 +159,7 @@ class NmapOutputViewer (gtk.VBox):
self.refreshing = True self.refreshing = True
# Adding widgets to the VBox # Adding widgets to the VBox
self.pack_start(self.scrolled, expand = True, fill = True) self.pack_start(self.scrolled, expand=True, fill=True)
# The NmapCommand instance, if any, whose output is shown in this # The NmapCommand instance, if any, whose output is shown in this
# display. # display.
@@ -166,16 +167,16 @@ class NmapOutputViewer (gtk.VBox):
# The position of the last read from the output stream. # The position of the last read from the output stream.
self.output_file_pointer = None self.output_file_pointer = None
def __create_widgets (self): def __create_widgets(self):
# Creating widgets # Creating widgets
self.scrolled = gtk.ScrolledWindow () self.scrolled = gtk.ScrolledWindow()
self.text_view = gtk.TextView () self.text_view = gtk.TextView()
def __set_scrolled_window (self): def __set_scrolled_window(self):
# Seting scrolled window # Seting scrolled window
self.scrolled.set_border_width (5) self.scrolled.set_border_width(5)
self.scrolled.add(self.text_view) self.scrolled.add(self.text_view)
self.scrolled.set_policy (gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) self.scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
def __set_text_view(self): def __set_text_view(self):
self.text_view.set_wrap_mode(gtk.WRAP_WORD) self.text_view.set_wrap_mode(gtk.WRAP_WORD)
@@ -205,8 +206,12 @@ class NmapOutputViewer (gtk.VBox):
text_color = settings[3] text_color = settings[3]
highlight_color = settings[4] highlight_color = settings[4]
tag.set_property("foreground", gtk.color_selection_palette_to_string([gtk.gdk.Color(*text_color),])) tag.set_property(
tag.set_property("background", gtk.color_selection_palette_to_string([gtk.gdk.Color(*highlight_color),])) "foreground", gtk.color_selection_palette_to_string(
[gtk.gdk.Color(*text_color), ]))
tag.set_property(
"background", gtk.color_selection_palette_to_string(
[gtk.gdk.Color(*highlight_color), ]))
def go_to_host(self, host): def go_to_host(self, host):
"""Go to host line on nmap output result""" """Go to host line on nmap output result"""
@@ -218,7 +223,8 @@ class NmapOutputViewer (gtk.VBox):
for i in xrange(len(output)): for i in xrange(len(output)):
if re_host.match(output[i]): if re_host.match(output[i]):
self.text_view.scroll_to_iter(buff.get_iter_at_line(i), 0, True, 0, 0) self.text_view.scroll_to_iter(
buff.get_iter_at_line(i), 0, True, 0, 0)
break break
def show_output_properties(self, widget): def show_output_properties(self, widget):
@@ -259,7 +265,7 @@ class NmapOutputViewer (gtk.VBox):
self.nmap_highlight.save_changes() self.nmap_highlight.save_changes()
self.apply_highlighting() self.apply_highlighting()
def apply_highlighting(self, start_iter = None, end_iter = None): def apply_highlighting(self, start_iter=None, end_iter=None):
buf = self.text_view.get_buffer() buf = self.text_view.get_buffer()
if start_iter is None: if start_iter is None:
@@ -302,7 +308,7 @@ class NmapOutputViewer (gtk.VBox):
self.output_file_pointer = None self.output_file_pointer = None
self.refresh_output() self.refresh_output()
def refresh_output(self, widget = None): def refresh_output(self, widget=None):
"""Update the output from the latest output of the command associated """Update the output from the latest output of the command associated
with this view, as set by set_command_execution. It has no effect if no with this view, as set by set_command_execution. It has no effect if no
command has been set.""" command has been set."""
@@ -316,7 +322,8 @@ class NmapOutputViewer (gtk.VBox):
pos = self.command_execution.stdout_file.tell() pos = self.command_execution.stdout_file.tell()
new_output = self.command_execution.stdout_file.read() new_output = self.command_execution.stdout_file.read()
self.output_file_pointer = self.command_execution.stdout_file.tell() self.output_file_pointer = self.command_execution.stdout_file.tell()
# print "read %d -> %d %d" % (pos, self.output_file_pointer, len(new_output)) # print "read %d -> %d %d" % (
# pos, self.output_file_pointer, len(new_output))
v_adj = self.scrolled.get_vadjustment() v_adj = self.scrolled.get_vadjustment()
if new_output and v_adj is not None: if new_output and v_adj is not None:
@@ -324,15 +331,19 @@ class NmapOutputViewer (gtk.VBox):
at_end = (v_adj.value >= v_adj.upper - v_adj.page_size) at_end = (v_adj.value >= v_adj.upper - v_adj.page_size)
buf = self.text_view.get_buffer() buf = self.text_view.get_buffer()
prev_end_mark = buf.create_mark(None, buf.get_end_iter(), left_gravity = True) prev_end_mark = buf.create_mark(
None, buf.get_end_iter(), left_gravity=True)
buf.insert(buf.get_end_iter(), new_output) buf.insert(buf.get_end_iter(), new_output)
# Highlight the new text. # Highlight the new text.
self.apply_highlighting(buf.get_iter_at_mark(prev_end_mark), buf.get_end_iter()) self.apply_highlighting(
buf.get_iter_at_mark(prev_end_mark), buf.get_end_iter())
if at_end: if at_end:
# If we were already scrolled to the bottom, scroll back to the # If we were already scrolled to the bottom, scroll back to the
# bottom again. Also do it in an idle handler in case the added # bottom again. Also do it in an idle handler in case the added
# text causes a scroll bar to appear and reflow the text, making # text causes a scroll bar to appear and reflow the text,
# the text a bit taller. # making the text a bit taller.
self.text_view.scroll_mark_onscreen(self.end_mark) self.text_view.scroll_mark_onscreen(self.end_mark)
gobject.idle_add(lambda: self.text_view.scroll_mark_onscreen(self.end_mark)) gobject.idle_add(
lambda: self.text_view.scroll_mark_onscreen(
self.end_mark))

View File

@@ -138,6 +138,7 @@ import zenmapCore.I18N
from zenmapCore.UmitLogging import log from zenmapCore.UmitLogging import log
from zenmapGUI.ScriptInterface import * from zenmapGUI.ScriptInterface import *
def get_option_check_auxiliary_widget(option, ops, check): def get_option_check_auxiliary_widget(option, ops, check):
if option in ("-sI", "-b", "--script", "--script-args", "--exclude", "-p", if option in ("-sI", "-b", "--script", "--script-args", "--exclude", "-p",
"-D", "-S", "--source-port", "-e", "--ttl", "-iR", "--max-retries", "-D", "-S", "--source-port", "-e", "--ttl", "-iR", "--max-retries",
@@ -159,6 +160,7 @@ def get_option_check_auxiliary_widget(option, ops, check):
else: else:
assert False, "Unknown option %s" % option assert False, "Unknown option %s" % option
class OptionEntry(gtk.Entry): class OptionEntry(gtk.Entry):
def __init__(self, option, ops, check): def __init__(self, option, ops, check):
gtk.Entry.__init__(self) gtk.Entry.__init__(self)
@@ -187,6 +189,7 @@ class OptionEntry(gtk.Entry):
self.check.set_active(True) self.check.set_active(True)
self.ops[self.option] = self.get_text().decode("UTF-8") self.ops[self.option] = self.get_text().decode("UTF-8")
class OptionExtras(gtk.Entry): class OptionExtras(gtk.Entry):
def __init__(self, option, ops, check): def __init__(self, option, ops, check):
gtk.Entry.__init__(self) gtk.Entry.__init__(self)
@@ -214,6 +217,7 @@ class OptionExtras(gtk.Entry):
self.check.set_active(True) self.check.set_active(True)
self.ops.extras = [self.get_text().decode("UTF-8")] self.ops.extras = [self.get_text().decode("UTF-8")]
class OptionLevel(gtk.SpinButton): class OptionLevel(gtk.SpinButton):
def __init__(self, option, ops, check): def __init__(self, option, ops, check):
gtk.SpinButton.__init__(self, gtk.Adjustment(0, 0, 10, 1), 0.0, 0) gtk.SpinButton.__init__(self, gtk.Adjustment(0, 0, 10, 1), 0.0, 0)
@@ -243,6 +247,7 @@ class OptionLevel(gtk.SpinButton):
self.check.set_active(True) self.check.set_active(True)
self.ops[self.option] = int(self.get_adjustment().get_value()) self.ops[self.option] = int(self.get_adjustment().get_value())
class OptionFile(gtk.HBox): class OptionFile(gtk.HBox):
__gsignals__ = { __gsignals__ = {
"changed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()) "changed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ())
@@ -257,7 +262,7 @@ class OptionFile(gtk.HBox):
self.entry = gtk.Entry() self.entry = gtk.Entry()
self.pack_start(self.entry, True, True) self.pack_start(self.entry, True, True)
button = HIGButton(stock = gtk.STOCK_OPEN) button = HIGButton(stock=gtk.STOCK_OPEN)
self.pack_start(button, False) self.pack_start(button, False)
button.connect("clicked", self.clicked_cb) button.connect("clicked", self.clicked_cb)
@@ -291,6 +296,7 @@ class OptionFile(gtk.HBox):
self.entry.set_text(dialog.get_filename()) self.entry.set_text(dialog.get_filename())
dialog.destroy() dialog.destroy()
class TargetEntry(gtk.Entry): class TargetEntry(gtk.Entry):
def __init__(self, ops): def __init__(self, ops):
gtk.Entry.__init__(self) gtk.Entry.__init__(self)
@@ -307,11 +313,12 @@ class TargetEntry(gtk.Entry):
def get_targets(self): def get_targets(self):
return split_quoted(self.get_text().decode("UTF-8")) return split_quoted(self.get_text().decode("UTF-8"))
class OptionTab(object): class OptionTab(object):
def __init__(self, root_tab, ops, update_command, help_buf): def __init__(self, root_tab, ops, update_command, help_buf):
actions = {'target':self.__parse_target, actions = {'target': self.__parse_target,
'option_list':self.__parse_option_list, 'option_list': self.__parse_option_list,
'option_check':self.__parse_option_check} 'option_check': self.__parse_option_check}
self.ops = ops self.ops = ops
self.update_command = update_command self.update_command = update_command
@@ -321,8 +328,10 @@ class OptionTab(object):
self.notscripttab = False # assume every tab is scripting tab self.notscripttab = False # assume every tab is scripting tab
self.widgets_list = [] self.widgets_list = []
for option_element in root_tab.childNodes: for option_element in root_tab.childNodes:
try:option_element.tagName try:
except:pass option_element.tagName
except:
pass
else: else:
if option_element.tagName in actions.keys(): if option_element.tagName in actions.keys():
parse_func = actions[option_element.tagName] parse_func = actions[option_element.tagName]
@@ -339,7 +348,8 @@ class OptionTab(object):
def __parse_option_list(self, option_list_element): def __parse_option_list(self, option_list_element):
children = option_list_element.getElementsByTagName(u'option') children = option_list_element.getElementsByTagName(u'option')
label_widget = HIGEntryLabel(_(option_list_element.getAttribute(u'label'))) label_widget = HIGEntryLabel(
_(option_list_element.getAttribute(u'label')))
option_list_widget = OptionList(self.ops) option_list_widget = OptionList(self.ops)
for child in children: for child in children:
@@ -348,8 +358,10 @@ class OptionTab(object):
label = _(child.getAttribute(u'label')) label = _(child.getAttribute(u'label'))
option_list_widget.append(option, argument, label) option_list_widget.append(option, argument, label)
self.profilehelp.add_label(option, label) self.profilehelp.add_label(option, label)
self.profilehelp.add_shortdesc(option, _(child.getAttribute(u'short_desc'))) self.profilehelp.add_shortdesc(
self.profilehelp.add_example(option, child.getAttribute(u'example')) option, _(child.getAttribute(u'short_desc')))
self.profilehelp.add_example(
option, child.getAttribute(u'example'))
option_list_widget.update() option_list_widget.update()
@@ -369,10 +381,12 @@ class OptionTab(object):
self.profilehelp.add_example(option, example) self.profilehelp.add_example(option, example)
check = OptionCheck(option, label) check = OptionCheck(option, label)
auxiliary_widget = get_option_check_auxiliary_widget(option, self.ops, check) auxiliary_widget = get_option_check_auxiliary_widget(
option, self.ops, check)
if auxiliary_widget is not None: if auxiliary_widget is not None:
auxiliary_widget.connect("changed", self.update_auxiliary_widget) auxiliary_widget.connect("changed", self.update_auxiliary_widget)
auxiliary_widget.connect('enter-notify-event', self.enter_notify_event_cb, option) auxiliary_widget.connect(
'enter-notify-event', self.enter_notify_event_cb, option)
else: else:
check.set_active(not not self.ops[option]) check.set_active(not not self.ops[option])
@@ -381,14 +395,14 @@ class OptionTab(object):
return check, auxiliary_widget return check, auxiliary_widget
def fill_table(self, table, expand_fill = True): def fill_table(self, table, expand_fill=True):
yopt = (0, gtk.EXPAND | gtk.FILL)[expand_fill] yopt = (0, gtk.EXPAND | gtk.FILL)[expand_fill]
for y, widget in enumerate(self.widgets_list): for y, widget in enumerate(self.widgets_list):
if widget[1] == None: if widget[1] == None:
table.attach(widget[0], 0, 2, y, y+1, yoptions=yopt) table.attach(widget[0], 0, 2, y, y + 1, yoptions=yopt)
else: else:
table.attach(widget[0], 0, 1, y, y+1, yoptions=yopt) table.attach(widget[0], 0, 1, y, y + 1, yoptions=yopt)
table.attach(widget[1], 1, 2, y, y+1, yoptions=yopt) table.attach(widget[1], 1, 2, y, y + 1, yoptions=yopt)
def update_auxiliary_widget(self, auxiliary_widget): def update_auxiliary_widget(self, auxiliary_widget):
self.update_command() self.update_command()
@@ -446,6 +460,7 @@ class OptionTab(object):
def enter_notify_event_cb(self, event, widget, option): def enter_notify_event_cb(self, event, widget, option):
self.show_help_for_option(option) self.show_help_for_option(option)
class OptionBuilder(object): class OptionBuilder(object):
def __init__(self, xml_file, ops, update_func, help_buf): def __init__(self, xml_file, ops, update_func, help_buf):
""" """
@@ -463,7 +478,6 @@ class OptionBuilder(object):
self.root_tag = "interface" self.root_tag = "interface"
self.xml = self.xml.getElementsByTagName(self.root_tag)[0] self.xml = self.xml.getElementsByTagName(self.root_tag)[0]
self.groups = self.__parse_groups() self.groups = self.__parse_groups()
@@ -490,11 +504,13 @@ class OptionBuilder(object):
dic = {} dic = {}
for tab_name in self.groups: for tab_name in self.groups:
if tab_name != "Scripting": if tab_name != "Scripting":
dic[tab_name] = OptionTab(self.xml.getElementsByTagName(tab_name)[0], dic[tab_name] = OptionTab(
self.ops, self.update_func, self.help_buf) self.xml.getElementsByTagName(tab_name)[0], self.ops,
self.update_func, self.help_buf)
dic[tab_name].notscripttab = True dic[tab_name].notscripttab = True
else: else:
dic[tab_name] =ScriptInterface(None,self.ops, self.update_func, self.help_buf) dic[tab_name] = ScriptInterface(
None, self.ops, self.update_func, self.help_buf)
return dic return dic
@@ -518,7 +534,8 @@ class OptionList(gtk.ComboBox):
opt, arg = row[0], row[1] opt, arg = row[0], row[1]
if opt == "": if opt == "":
continue continue
if (not arg and self.ops[opt]) or (arg and str(self.ops[opt]) == arg): if ((not arg and self.ops[opt]) or
(arg and str(self.ops[opt]) == arg)):
selected = i selected = i
self.set_active(selected) self.set_active(selected)
@@ -535,6 +552,7 @@ class OptionList(gtk.ComboBox):
self.list.append([option, argument, opt]) self.list.append([option, argument, opt])
self.options.append(option) self.options.append(option)
class OptionCheck(gtk.CheckButton): class OptionCheck(gtk.CheckButton):
def __init__(self, option, label): def __init__(self, option, label):
opt = label opt = label

View File

@@ -123,8 +123,8 @@
# This prints the normal (text) output of a single scan. Ideas for further # This prints the normal (text) output of a single scan. Ideas for further
# development: # development:
# #
# Print the topology graphic. The graphic is already made with Cairo so the same # Print the topology graphic. The graphic is already made with Cairo so the
# code can be used to draw on the print context. # same code can be used to draw on the print context.
# #
# Print in color with highlighting, like NmapOutputViewer. # Print in color with highlighting, like NmapOutputViewer.
# #
@@ -139,6 +139,7 @@ import pango
MONOSPACE_FONT_DESC = pango.FontDescription("Monospace 12") MONOSPACE_FONT_DESC = pango.FontDescription("Monospace 12")
class PrintState (object): class PrintState (object):
"""This is the userdatum passed to gtk.PrintOperation callbacks.""" """This is the userdatum passed to gtk.PrintOperation callbacks."""
@@ -169,7 +170,9 @@ class PrintState (object):
op.set_n_pages((len(self.lines) - 1) / self.lines_per_page + 1) op.set_n_pages((len(self.lines) - 1) / self.lines_per_page + 1)
def draw_page(self, op, context, page_nr): def draw_page(self, op, context, page_nr):
this_page_lines = self.lines[page_nr * self.lines_per_page:(page_nr + 1) * self.lines_per_page] this_page_lines = self.lines[
page_nr * self.lines_per_page:
(page_nr + 1) * self.lines_per_page]
layout = context.create_pango_layout() layout = context.create_pango_layout()
# Do no wrapping. # Do no wrapping.
layout.set_width(-1) layout.set_width(-1)
@@ -180,6 +183,7 @@ class PrintState (object):
cr = context.get_cairo_context() cr = context.get_cairo_context()
cr.show_layout(layout) cr.show_layout(layout)
def run_print_operation(inventory, entry): def run_print_operation(inventory, entry):
op = gtk.PrintOperation() op = gtk.PrintOperation()
state = PrintState(inventory, entry) state = PrintState(inventory, entry)

View File

@@ -125,6 +125,7 @@ import gtk
from zenmapCore.UmitConf import CommandProfile from zenmapCore.UmitConf import CommandProfile
import zenmapCore.I18N import zenmapCore.I18N
class ProfileCombo(gtk.ComboBoxEntry, object): class ProfileCombo(gtk.ComboBoxEntry, object):
def __init__(self): def __init__(self):
gtk.ComboBoxEntry.__init__(self, gtk.ListStore(str), 0) gtk.ComboBoxEntry.__init__(self, gtk.ListStore(str), 0)

View File

@@ -123,7 +123,8 @@
import gtk import gtk
from zenmapGUI.higwidgets.higwindows import HIGWindow from zenmapGUI.higwidgets.higwindows import HIGWindow
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer, hig_box_space_holder from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer, \
hig_box_space_holder
from zenmapGUI.higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel from zenmapGUI.higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel
from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow
from zenmapGUI.higwidgets.higtextviewers import HIGTextView from zenmapGUI.higwidgets.higtextviewers import HIGTextView
@@ -137,8 +138,10 @@ from zenmapCore.UmitLogging import log
import zenmapCore.I18N import zenmapCore.I18N
from zenmapCore.NmapOptions import NmapOptions from zenmapCore.NmapOptions import NmapOptions
class ProfileEditor(HIGWindow): class ProfileEditor(HIGWindow):
def __init__(self, command=None, profile_name=None, deletable=True, overwrite=False): def __init__(self, command=None, profile_name=None,
deletable=True, overwrite=False):
HIGWindow.__init__(self) HIGWindow.__init__(self)
self.connect("delete_event", self.exit) self.connect("delete_event", self.exit)
self.set_title(_('Profile Editor')) self.set_title(_('Profile Editor'))
@@ -148,8 +151,8 @@ class ProfileEditor(HIGWindow):
self.profile_name = profile_name self.profile_name = profile_name
self.overwrite = overwrite self.overwrite = overwrite
# Used to block recursive updating of the command entry when the command # Used to block recursive updating of the command entry when the
# entry causes the OptionBuilder widgets to change. # command entry causes the OptionBuilder widgets to change.
self.inhibit_command_update = False self.inhibit_command_update = False
self.__create_widgets() self.__create_widgets()
@@ -164,20 +167,27 @@ class ProfileEditor(HIGWindow):
# Interface settings # Interface settings
self.profile_name_entry.set_text(profile_name) self.profile_name_entry.set_text(profile_name)
self.profile_description_text.get_buffer().set_text(prof['description']) self.profile_description_text.get_buffer().set_text(
prof['description'])
command_string = prof['command'] command_string = prof['command']
self.ops.parse_string(command_string) self.ops.parse_string(command_string)
if command: if command:
self.ops.parse_string(command) self.ops.parse_string(command)
self.option_builder = OptionBuilder(Path.profile_editor, self.ops, self.update_command, self.help_field.get_buffer()) self.option_builder = OptionBuilder(
Path.profile_editor, self.ops,
self.update_command, self.help_field.get_buffer())
log.debug("Option groups: %s" % str(self.option_builder.groups)) log.debug("Option groups: %s" % str(self.option_builder.groups))
log.debug("Option section names: %s" % str(self.option_builder.section_names)) log.debug("Option section names: %s" % str(
self.option_builder.section_names))
#log.debug("Option tabs: %s" % str(self.option_builder.tabs)) #log.debug("Option tabs: %s" % str(self.option_builder.tabs))
for tab in self.option_builder.groups: for tab in self.option_builder.groups:
self.__create_tab(_(tab), _(self.option_builder.section_names[tab]), self.option_builder.tabs[tab]) self.__create_tab(
_(tab),
_(self.option_builder.section_names[tab]),
self.option_builder.tabs[tab])
self.update_command() self.update_command()
@@ -195,16 +205,18 @@ class ProfileEditor(HIGWindow):
# cause a change in the command entry. # cause a change in the command entry.
self.command_entry.handler_block(self.command_entry_changed_cb_id) self.command_entry.handler_block(self.command_entry_changed_cb_id)
self.command_entry.set_text(self.ops.render_string()) self.command_entry.set_text(self.ops.render_string())
self.command_entry.handler_unblock(self.command_entry_changed_cb_id) self.command_entry.handler_unblock(
self.command_entry_changed_cb_id)
def update_help_name(self, widget, extra): def update_help_name(self, widget, extra):
self.help_field.get_buffer().set_text("Profile name\n\nThis is how the" self.help_field.get_buffer().set_text(
+" profile will be identified in the drop-down combo box in the" "Profile name\n\nThis is how the profile will be identified "
+" scan tab.") "in the drop-down combo box in the scan tab.")
def update_help_desc(self, widget, extra): def update_help_desc(self, widget, extra):
self.help_field.get_buffer().set_text("Description\n\nThe description is a" self.help_field.get_buffer().set_text(
+ " full description of what the scan does, which may be long.") "Description\n\nThe description is a full description of what "
"the scan does, which may be long.")
def __create_widgets(self): def __create_widgets(self):
@@ -218,8 +230,8 @@ class ProfileEditor(HIGWindow):
#self.main_vbox = HIGVBox() #self.main_vbox = HIGVBox()
self.command_entry = gtk.Entry() self.command_entry = gtk.Entry()
self.command_entry_changed_cb_id = \ self.command_entry_changed_cb_id = self.command_entry.connect(
self.command_entry.connect("changed", self.command_entry_changed_cb) "changed", self.command_entry_changed_cb)
self.scan_button = HIGButton(_("Scan")) self.scan_button = HIGButton(_("Scan"))
self.scan_button.connect("clicked", self.run_scan) self.scan_button.connect("clicked", self.run_scan)
@@ -231,12 +243,14 @@ class ProfileEditor(HIGWindow):
self.profile_info_label = HIGSectionLabel(_('Profile Information')) self.profile_info_label = HIGSectionLabel(_('Profile Information'))
self.profile_name_label = HIGEntryLabel(_('Profile name')) self.profile_name_label = HIGEntryLabel(_('Profile name'))
self.profile_name_entry = gtk.Entry() self.profile_name_entry = gtk.Entry()
self.profile_name_entry.connect('enter-notify-event', self.update_help_name) self.profile_name_entry.connect(
'enter-notify-event', self.update_help_name)
self.profile_description_label = HIGEntryLabel(_('Description')) self.profile_description_label = HIGEntryLabel(_('Description'))
self.profile_description_scroll = HIGScrolledWindow() self.profile_description_scroll = HIGScrolledWindow()
self.profile_description_scroll.set_border_width(0) self.profile_description_scroll.set_border_width(0)
self.profile_description_text = HIGTextView() self.profile_description_text = HIGTextView()
self.profile_description_text.connect('motion-notify-event', self.update_help_desc) self.profile_description_text.connect(
'motion-notify-event', self.update_help_desc)
# Buttons # Buttons
self.buttons_hbox = HIGHBox() self.buttons_hbox = HIGHBox()
@@ -259,8 +273,9 @@ class ProfileEditor(HIGWindow):
self.help_field.set_cursor_visible(False) self.help_field.set_cursor_visible(False)
self.help_field.set_left_margin(5) self.help_field.set_left_margin(5)
self.help_field.set_editable(False) self.help_field.set_editable(False)
self.help_vbox.set_size_request(200,-1) self.help_vbox.set_size_request(200, -1)
### ###
def __pack_widgets(self): def __pack_widgets(self):
### ###
@@ -283,9 +298,9 @@ class ProfileEditor(HIGWindow):
self.main_whole_box._pack_noexpand_nofill(self.lower_box) self.main_whole_box._pack_noexpand_nofill(self.lower_box)
### ###
# Packing profile information tab on notebook # Packing profile information tab on notebook
self.notebook.append_page(self.profile_info_vbox, gtk.Label(_('Profile'))) self.notebook.append_page(
self.profile_info_vbox, gtk.Label(_('Profile')))
self.profile_info_vbox.set_border_width(5) self.profile_info_vbox.set_border_width(5)
table = HIGTable() table = HIGTable()
self.profile_info_vbox._pack_noexpand_nofill(self.profile_info_label) self.profile_info_vbox._pack_noexpand_nofill(self.profile_info_label)
@@ -300,10 +315,11 @@ class ProfileEditor(HIGWindow):
vbox_ann = HIGVBox() vbox_ann = HIGVBox()
vbox_ann._pack_expand_fill(hig_box_space_holder()) vbox_ann._pack_expand_fill(hig_box_space_holder())
table.attach(self.profile_name_label,0,1,0,1,xoptions=0,yoptions=0) table.attach(
table.attach(self.profile_name_entry,1,2,0,1,yoptions=0) self.profile_name_label, 0, 1, 0, 1, xoptions=0, yoptions=0)
table.attach(vbox_desc,0,1,1,2,xoptions=0) table.attach(self.profile_name_entry, 1, 2, 0, 1, yoptions=0)
table.attach(self.profile_description_scroll,1,2,1,2) table.attach(vbox_desc, 0, 1, 1, 2, xoptions=0)
table.attach(self.profile_description_scroll, 1, 2, 1, 2)
# Packing buttons on button_hbox # Packing buttons on button_hbox
self.buttons_hbox._pack_expand_fill(hig_box_space_holder()) self.buttons_hbox._pack_expand_fill(hig_box_space_holder())
@@ -327,7 +343,7 @@ class ProfileEditor(HIGWindow):
log.debug(">>> Tab name: %s" % tab_name) log.debug(">>> Tab name: %s" % tab_name)
log.debug(">>>Creating profile editor section: %s" % section_name) log.debug(">>>Creating profile editor section: %s" % section_name)
vbox = HIGVBox() vbox = HIGVBox()
if tab.notscripttab: # if notscripttab is set if tab.notscripttab: # if notscripttab is set
table = HIGTable() table = HIGTable()
table.set_row_spacings(2) table.set_row_spacings(2)
section = HIGSectionLabel(section_name) section = HIGSectionLabel(section_name)
@@ -337,7 +353,7 @@ class ProfileEditor(HIGWindow):
tab.fill_table(table, True) tab.fill_table(table, True)
else: else:
hbox = tab.get_hmain_box() hbox = tab.get_hmain_box()
vbox.pack_start(hbox,True,True,0) vbox.pack_start(hbox, True, True, 0)
self.notebook.append_page(vbox, gtk.Label(tab_name)) self.notebook.append_page(vbox, gtk.Label(tab_name))
def save_profile(self, widget): def save_profile(self, widget):
@@ -345,9 +361,10 @@ class ProfileEditor(HIGWindow):
self.profile.remove_profile(self.profile_name) self.profile.remove_profile(self.profile_name)
profile_name = self.profile_name_entry.get_text() profile_name = self.profile_name_entry.get_text()
if profile_name == '': if profile_name == '':
alert = HIGAlertDialog(message_format=_('Unnamed profile'),\ alert = HIGAlertDialog(
secondary_text=_('You must provide a name \ message_format=_('Unnamed profile'),
for this profile.')) secondary_text=_(
'You must provide a name for this profile.'))
alert.run() alert.run()
alert.destroy() alert.destroy()
@@ -366,11 +383,12 @@ for this profile.'))
command=command,\ command=command,\
description=description) description=description)
except ValueError: except ValueError:
alert = HIGAlertDialog(message_format=_('Disallowed profile name'),\ alert = HIGAlertDialog(
secondary_text=_('Sorry, the name "%s" \ message_format=_('Disallowed profile name'),
is not allowed due to technical limitations. (The underlying ConfigParser \ secondary_text=_('Sorry, the name "%s" is not allowed due '
used to store profiles does not allow it.) Choose a different \ 'to technical limitations. (The underlying '
name.' % profile_name)) 'ConfigParser used to store profiles does not allow '
'it.) Choose a different name.' % profile_name))
alert.run() alert.run()
alert.destroy() alert.destroy()
return return
@@ -392,9 +410,10 @@ name.' % profile_name))
if self.deletable: if self.deletable:
dialog = HIGDialog(buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK, dialog = HIGDialog(buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
alert = HIGEntryLabel('<b>'+_("Deleting Profile")+'</b>') alert = HIGEntryLabel('<b>' + _("Deleting Profile") + '</b>')
text = HIGEntryLabel(_('Your profile is going to be deleted! Click\ text = HIGEntryLabel(_(
Ok to continue, or Cancel to go back to Profile Editor.')) 'Your profile is going to be deleted! ClickOk to continue, '
'or Cancel to go back to Profile Editor.'))
hbox = HIGHBox() hbox = HIGHBox()
hbox.set_border_width(5) hbox.set_border_width(5)
hbox.set_spacing(12) hbox.set_spacing(12)
@@ -404,7 +423,8 @@ name.' % profile_name))
vbox.set_spacing(12) vbox.set_spacing(12)
image = gtk.Image() image = gtk.Image()
image.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) image.set_from_stock(
gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
vbox.pack_start(alert) vbox.pack_start(alert)
vbox.pack_start(text) vbox.pack_start(text)
@@ -433,7 +453,7 @@ name.' % profile_name))
self.scan_interface.toolbar.profile_entry.update() self.scan_interface.toolbar.profile_entry.update()
list = self.scan_interface.toolbar.profile_entry.get_model() list = self.scan_interface.toolbar.profile_entry.get_model()
length = len(list) length = len(list)
if length >0 : if length > 0:
self.scan_interface.toolbar.profile_entry.set_active(0) self.scan_interface.toolbar.profile_entry.set_active(0)

View File

@@ -122,6 +122,7 @@
from zenmapCore.UmitLogging import log from zenmapCore.UmitLogging import log
class ProfileHelp: class ProfileHelp:
def __init__(self, currentstate=None): def __init__(self, currentstate=None):
self.currentstate = "Default" self.currentstate = "Default"
@@ -139,7 +140,7 @@ class ProfileHelp:
if self.currentstate in self.labels.keys(): if self.currentstate in self.labels.keys():
return self.labels[self.currentstate] return self.labels[self.currentstate]
else: else:
return "" #blank return "" # blank
def add_shortdesc(self, option_name, text): def add_shortdesc(self, option_name, text):
self.descs[option_name] = text self.descs[option_name] = text
@@ -148,7 +149,7 @@ class ProfileHelp:
if self.currentstate in self.descs.keys(): if self.currentstate in self.descs.keys():
return self.descs[self.currentstate] return self.descs[self.currentstate]
else: else:
return "" #blank return "" # blank
def add_example(self, option_name, text): def add_example(self, option_name, text):
self.examples[option_name] = text self.examples[option_name] = text
@@ -157,8 +158,8 @@ class ProfileHelp:
if self.currentstate in self.examples.keys(): if self.currentstate in self.examples.keys():
return self.examples[self.currentstate] return self.examples[self.currentstate]
else: else:
return "" #blank return "" # blank
def handler(self,whichLabel): def handler(self, whichLabel):
log.debug("whichLabel: %s" % whichLabel) log.debug("whichLabel: %s" % whichLabel)
self.currentstate = whichLabel self.currentstate = whichLabel

View File

@@ -123,7 +123,8 @@
import gtk import gtk
from zenmapGUI.higwidgets.higexpanders import HIGExpander from zenmapGUI.higwidgets.higexpanders import HIGExpander
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, hig_box_space_holder from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox,\
hig_box_space_holder
from zenmapGUI.higwidgets.higlabels import HIGEntryLabel from zenmapGUI.higwidgets.higlabels import HIGEntryLabel
from zenmapGUI.higwidgets.higtables import HIGTable from zenmapGUI.higwidgets.higtables import HIGTable
from zenmapGUI.Icons import get_os_logo, get_vulnerability_logo from zenmapGUI.Icons import get_os_logo, get_vulnerability_logo
@@ -132,6 +133,7 @@ import zenmapCore.I18N
na = _('Not available') na = _('Not available')
class ScanHostDetailsPage(HIGExpander): class ScanHostDetailsPage(HIGExpander):
def __init__(self, host): def __init__(self, host):
HIGExpander.__init__(self, host.get_hostname()) HIGExpander.__init__(self, host.get_hostname())
@@ -139,6 +141,7 @@ class ScanHostDetailsPage(HIGExpander):
self.host_details = HostDetails(host) self.host_details = HostDetails(host)
self.hbox._pack_expand_fill(self.host_details) self.hbox._pack_expand_fill(self.host_details)
class HostDetails(HIGVBox): class HostDetails(HIGVBox):
def __init__(self, host): def __init__(self, host):
HIGVBox.__init__(self) HIGVBox.__init__(self)
@@ -147,7 +150,8 @@ class HostDetails(HIGVBox):
self.set_os_image(get_os_logo(host)) self.set_os_image(get_os_logo(host))
self.set_vulnerability_image(get_vulnerability_logo(host.get_open_ports())) self.set_vulnerability_image(
get_vulnerability_logo(host.get_open_ports()))
self.set_host_status({'state': host.get_state(), self.set_host_status({'state': host.get_state(),
'open': str(host.get_open_ports()), 'open': str(host.get_open_ports()),
@@ -179,16 +183,19 @@ class HostDetails(HIGVBox):
self.set_comment(host.comment) self.set_comment(host.comment)
def __create_widgets(self): def __create_widgets(self):
self.host_status_expander = gtk.Expander('<b>'+_('Host Status')+'</b>') self.host_status_expander = gtk.Expander(
self.address_expander = gtk.Expander('<b>'+_('Addresses')+'</b>') '<b>' + _('Host Status') + '</b>')
self.hostnames_expander = gtk.Expander('<b>'+_('Hostnames')+'</b>') self.address_expander = gtk.Expander('<b>' + _('Addresses') + '</b>')
self.os_expander = gtk.Expander('<b>'+_('Operating System')+'</b>') self.hostnames_expander = gtk.Expander('<b>' + _('Hostnames') + '</b>')
self.portsused_expander = gtk.Expander('<b>'+_('Ports used')+'</b>') self.os_expander = gtk.Expander('<b>' + _('Operating System') + '</b>')
self.osclass_expander = gtk.Expander('<b>'+_('OS Classes')+'</b>') self.portsused_expander = gtk.Expander(
self.tcp_expander = gtk.Expander('<b>'+_('TCP Sequence')+'</b>') '<b>' + _('Ports used') + '</b>')
self.ip_expander = gtk.Expander('<b>'+_('IP ID Sequence')+'</b>') self.osclass_expander = gtk.Expander('<b>' + _('OS Classes') + '</b>')
self.tcpts_expander = gtk.Expander('<b>'+_('TCP TS Sequence')+'</b>') self.tcp_expander = gtk.Expander('<b>' + _('TCP Sequence') + '</b>')
self.comment_expander = gtk.Expander('<b>'+_('Comments')+'</b>') self.ip_expander = gtk.Expander('<b>' + _('IP ID Sequence') + '</b>')
self.tcpts_expander = gtk.Expander(
'<b>' + _('TCP TS Sequence') + '</b>')
self.comment_expander = gtk.Expander('<b>' + _('Comments') + '</b>')
self.os_image = gtk.Image() self.os_image = gtk.Image()
self.vulnerability_image = gtk.Image() self.vulnerability_image = gtk.Image()
@@ -214,7 +221,6 @@ class HostDetails(HIGVBox):
self.lastboot_label = HIGEntryLabel(_('Last boot:')) self.lastboot_label = HIGEntryLabel(_('Last boot:'))
self.info_lastboot_label = HIGEntryLabel(na) self.info_lastboot_label = HIGEntryLabel(na)
# Addresses expander # Addresses expander
self.ipv4_label = HIGEntryLabel(_('IPv4:')) self.ipv4_label = HIGEntryLabel(_('IPv4:'))
self.info_ipv4_label = HIGEntryLabel(na) self.info_ipv4_label = HIGEntryLabel(na)
@@ -243,63 +249,78 @@ class HostDetails(HIGVBox):
table, hbox = self.create_table_hbox() table, hbox = self.create_table_hbox()
try: try:
if status['state'] == '': raise Exception if status['state'] == '':
raise Exception
self.info_host_state_label.set_text(status['state']) self.info_host_state_label.set_text(status['state'])
except:pass except:
pass
try: try:
if status['open'] == '': raise Exception if status['open'] == '':
raise Exception
self.info_open_ports.set_text(status['open']) self.info_open_ports.set_text(status['open'])
except:pass except:
pass
try: try:
if status['filtered'] == '': raise Exception if status['filtered'] == '':
raise Exception
self.info_filtered_label.set_text(status['filtered']) self.info_filtered_label.set_text(status['filtered'])
except:pass except:
pass
try: try:
if status['closed'] == '': raise Exception if status['closed'] == '':
raise Exception
self.info_closed_ports.set_text(status['closed']) self.info_closed_ports.set_text(status['closed'])
except:pass except:
pass
try: try:
if status['scanned'] == '': raise Exception if status['scanned'] == '':
raise Exception
self.info_scanned_label.set_text(status['scanned']) self.info_scanned_label.set_text(status['scanned'])
except:pass except:
pass
try: try:
if status['uptime'] == '': raise Exception if status['uptime'] == '':
raise Exception
self.info_uptime_label.set_text(status['uptime']) self.info_uptime_label.set_text(status['uptime'])
except:pass except:
pass
try: try:
if status['lastboot'] == '': raise Exception if status['lastboot'] == '':
raise Exception
self.info_lastboot_label.set_text(status['lastboot']) self.info_lastboot_label.set_text(status['lastboot'])
except:pass except:
pass
table.attach(self.host_state_label,0,1,0,1) table.attach(self.host_state_label, 0, 1, 0, 1)
table.attach(self.info_host_state_label,1,2,0,1) table.attach(self.info_host_state_label, 1, 2, 0, 1)
table.attach(self.open_label,0,1,1,2) table.attach(self.open_label, 0, 1, 1, 2)
table.attach(self.info_open_ports,1,2,1,2) table.attach(self.info_open_ports, 1, 2, 1, 2)
table.attach(self.filtered_label,0,1,2,3) table.attach(self.filtered_label, 0, 1, 2, 3)
table.attach(self.info_filtered_label,1,2,2,3) table.attach(self.info_filtered_label, 1, 2, 2, 3)
table.attach(self.closed_label,0,1,3,4) table.attach(self.closed_label, 0, 1, 3, 4)
table.attach(self.info_closed_ports,1,2,3,4) table.attach(self.info_closed_ports, 1, 2, 3, 4)
table.attach(self.scanned_label,0,1,4,5) table.attach(self.scanned_label, 0, 1, 4, 5)
table.attach(self.info_scanned_label,1,2,4,5) table.attach(self.info_scanned_label, 1, 2, 4, 5)
table.attach(self.uptime_label,0,1,5,6) table.attach(self.uptime_label, 0, 1, 5, 6)
table.attach(self.info_uptime_label,1,2,5,6) table.attach(self.info_uptime_label, 1, 2, 5, 6)
table.attach(self.lastboot_label,0,1,6,7) table.attach(self.lastboot_label, 0, 1, 6, 7)
table.attach(self.info_lastboot_label,1,2,6,7) table.attach(self.info_lastboot_label, 1, 2, 6, 7)
table.attach(self.os_image,2,4,0,3,xoptions=1,yoptions=0) table.attach(self.os_image, 2, 4, 0, 3, xoptions=1, yoptions=0)
table.attach(self.vulnerability_image,2,4,4,7,xoptions=1,yoptions=0) table.attach(
self.vulnerability_image, 2, 4, 4, 7, xoptions=1, yoptions=0)
table.set_col_spacing(1, 50) table.set_col_spacing(1, 50)
@@ -307,10 +328,10 @@ class HostDetails(HIGVBox):
self._pack_noexpand_nofill(self.host_status_expander) self._pack_noexpand_nofill(self.host_status_expander)
def set_os_image(self, image): def set_os_image(self, image):
self.os_image.set_from_stock(image,gtk.ICON_SIZE_DIALOG) self.os_image.set_from_stock(image, gtk.ICON_SIZE_DIALOG)
def set_vulnerability_image(self, image): def set_vulnerability_image(self, image):
self.vulnerability_image.set_from_stock(image,gtk.ICON_SIZE_DIALOG) self.vulnerability_image.set_from_stock(image, gtk.ICON_SIZE_DIALOG)
def set_addresses(self, address): def set_addresses(self, address):
self.address_expander.set_use_markup(True) self.address_expander.set_use_markup(True)
@@ -319,28 +340,34 @@ class HostDetails(HIGVBox):
#print '>>> Address:', address #print '>>> Address:', address
try: try:
if address['ipv4'] == 1: raise Exception if address['ipv4'] == 1:
raise Exception
self.info_ipv4_label.set_text(address['ipv4']) self.info_ipv4_label.set_text(address['ipv4'])
except:pass except:
pass
try: try:
if address['ipv6'] == 1: raise Exception if address['ipv6'] == 1:
raise Exception
self.info_ipv6_label.set_text(address['ipv6']) self.info_ipv6_label.set_text(address['ipv6'])
except:pass except:
pass
try: try:
if address['mac'] == 1: raise Exception if address['mac'] == 1:
raise Exception
self.info_mac_label.set_text(address['mac']) self.info_mac_label.set_text(address['mac'])
except:pass except:
pass
table.attach(self.ipv4_label,0,1,0,1) table.attach(self.ipv4_label, 0, 1, 0, 1)
table.attach(self.info_ipv4_label,1,2,0,1) table.attach(self.info_ipv4_label, 1, 2, 0, 1)
table.attach(self.ipv6_label,0,1,1,2) table.attach(self.ipv6_label, 0, 1, 1, 2)
table.attach(self.info_ipv6_label,1,2,1,2) table.attach(self.info_ipv6_label, 1, 2, 1, 2)
table.attach(self.mac_label,0,1,2,3) table.attach(self.mac_label, 0, 1, 2, 3)
table.attach(self.info_mac_label,1,2,2,3) table.attach(self.info_mac_label, 1, 2, 2, 3)
self.address_expander.add(hbox) self.address_expander.add(hbox)
self._pack_noexpand_nofill(self.address_expander) self._pack_noexpand_nofill(self.address_expander)
@@ -356,17 +383,21 @@ class HostDetails(HIGVBox):
for h in hostname: for h in hostname:
name = na name = na
try:name = h['hostname'] try:
except:pass name = h['hostname']
except:
pass
type = na type = na
try:type = h['hostname_type'] try:
except:pass type = h['hostname_type']
except:
pass
table.attach(HIGEntryLabel(_('Name - Type:')),0,1,y1,y2) table.attach(HIGEntryLabel(_('Name - Type:')), 0, 1, y1, y2)
table.attach(HIGEntryLabel(name+' - '+\ table.attach(HIGEntryLabel(name + ' - ' + type), 1, 2, y1, y2)
type),1,2,y1,y2) y1 += 1
y1+=1;y2+=1 y2 += 1
self.hostnames_expander.add(hbox) self.hostnames_expander.add(hbox)
self._pack_noexpand_nofill(self.hostnames_expander) self._pack_noexpand_nofill(self.hostnames_expander)
@@ -379,29 +410,34 @@ class HostDetails(HIGVBox):
progress = gtk.ProgressBar() progress = gtk.ProgressBar()
try: try:
progress.set_fraction(float(os['accuracy'])/100.0) progress.set_fraction(float(os['accuracy']) / 100.0)
progress.set_text(os['accuracy']+'%') progress.set_text(os['accuracy'] + '%')
except:progress.set_text(_('Not Available')) except:
progress.set_text(_('Not Available'))
table.attach(HIGEntryLabel(_('Name:')),0,1,0,1) table.attach(HIGEntryLabel(_('Name:')), 0, 1, 0, 1)
table.attach(HIGEntryLabel(os['name']),1,2,0,1) table.attach(HIGEntryLabel(os['name']), 1, 2, 0, 1)
table.attach(HIGEntryLabel(_('Accuracy:')),0,1,1,2) table.attach(HIGEntryLabel(_('Accuracy:')), 0, 1, 1, 2)
table.attach(progress,1,2,1,2) table.attach(progress, 1, 2, 1, 2)
y1=2;y2=3 y1 = 2
y2 = 3
try: try:
self.set_ports_used(os['portsused']) self.set_ports_used(os['portsused'])
table.attach(self.portsused_expander,0,2,y1,y2) table.attach(self.portsused_expander, 0, 2, y1, y2)
y1+=1;y2+=1 y1 += 1
except:pass y2 += 1
except:
pass
try: try:
self.set_osclass(os['osclasses']) self.set_osclass(os['osclasses'])
self.osclass_expander.set_use_markup(True) self.osclass_expander.set_use_markup(True)
table.attach(self.osclass_expander,0,2,y1,y2) table.attach(self.osclass_expander, 0, 2, y1, y2)
except:pass except:
pass
self.os_expander.add(hbox) self.os_expander.add(hbox)
self._pack_noexpand_nofill(self.os_expander) self._pack_noexpand_nofill(self.os_expander)
@@ -410,13 +446,17 @@ class HostDetails(HIGVBox):
self.portsused_expander.set_use_markup(True) self.portsused_expander.set_use_markup(True)
table, hbox = self.create_table_hbox() table, hbox = self.create_table_hbox()
y1=0;y2=1 y1 = 0
y2 = 1
for p in ports: for p in ports:
table.attach(HIGEntryLabel(_('Port-Protocol-State:')),0,1,y1,y2) table.attach(HIGEntryLabel(
table.attach(HIGEntryLabel(p['portid']+' - '+p['proto']+' - '+\ _('Port-Protocol-State:')), 0, 1, y1, y2)
p['state']),1,2,y1,y2) table.attach(HIGEntryLabel(
y1+=1;y2+=1 p['portid'] + ' - ' + p['proto'] + ' - ' + p['state']
), 1, 2, y1, y2)
y1 += 1
y2 += 1
self.portsused_expander.add(hbox) self.portsused_expander.add(hbox)
@@ -425,25 +465,27 @@ class HostDetails(HIGVBox):
self.osclass_expander.set_use_markup(True) self.osclass_expander.set_use_markup(True)
table, hbox = self.create_table_hbox() table, hbox = self.create_table_hbox()
table.attach(HIGEntryLabel(_('Type')),0,1,0,1) table.attach(HIGEntryLabel(_('Type')), 0, 1, 0, 1)
table.attach(HIGEntryLabel(_('Vendor')),1,2,0,1) table.attach(HIGEntryLabel(_('Vendor')), 1, 2, 0, 1)
table.attach(HIGEntryLabel(_('OS Family')),2,3,0,1) table.attach(HIGEntryLabel(_('OS Family')), 2, 3, 0, 1)
table.attach(HIGEntryLabel(_('OS Generation')),3,4,0,1) table.attach(HIGEntryLabel(_('OS Generation')), 3, 4, 0, 1)
table.attach(HIGEntryLabel(_('Accuracy')),4,5,0,1) table.attach(HIGEntryLabel(_('Accuracy')), 4, 5, 0, 1)
y1=1;y2=2 y1 = 1
y2 = 2
for o in osclass: for o in osclass:
table.attach(HIGEntryLabel(o['type']),0,1,y1,y2) table.attach(HIGEntryLabel(o['type']), 0, 1, y1, y2)
table.attach(HIGEntryLabel(o['vendor']),1,2,y1,y2) table.attach(HIGEntryLabel(o['vendor']), 1, 2, y1, y2)
table.attach(HIGEntryLabel(o['osfamily']),2,3,y1,y2) table.attach(HIGEntryLabel(o['osfamily']), 2, 3, y1, y2)
table.attach(HIGEntryLabel(o['osgen']),3,4,y1,y2) table.attach(HIGEntryLabel(o['osgen']), 3, 4, y1, y2)
progress = gtk.ProgressBar() progress = gtk.ProgressBar()
progress.set_text(o['accuracy']+'%') progress.set_text(o['accuracy'] + '%')
progress.set_fraction(float(o['accuracy'])/100.0) progress.set_fraction(float(o['accuracy']) / 100.0)
table.attach(progress,4,5,y1,y2) table.attach(progress, 4, 5, y1, y2)
y1+=1;y2+=1 y1 += 1
y2 += 1
self.osclass_expander.add(hbox) self.osclass_expander.add(hbox)
@@ -456,14 +498,14 @@ class HostDetails(HIGVBox):
for v in tcpseq['values'].split(','): for v in tcpseq['values'].split(','):
combo.append_text(v) combo.append_text(v)
table.attach(HIGEntryLabel(_('Difficulty:')),0,1,1,2) table.attach(HIGEntryLabel(_('Difficulty:')), 0, 1, 1, 2)
table.attach(HIGEntryLabel(tcpseq['difficulty']),1,2,1,2) table.attach(HIGEntryLabel(tcpseq['difficulty']), 1, 2, 1, 2)
table.attach(HIGEntryLabel(_('Index:')),0,1,2,3) table.attach(HIGEntryLabel(_('Index:')), 0, 1, 2, 3)
table.attach(HIGEntryLabel(tcpseq['index']),1,2,2,3) table.attach(HIGEntryLabel(tcpseq['index']), 1, 2, 2, 3)
table.attach(HIGEntryLabel(_('Values:')),0,1,3,4) table.attach(HIGEntryLabel(_('Values:')), 0, 1, 3, 4)
table.attach(combo,1,2,3,4) table.attach(combo, 1, 2, 3, 4)
self.tcp_expander.add(hbox) self.tcp_expander.add(hbox)
self._pack_noexpand_nofill(self.tcp_expander) self._pack_noexpand_nofill(self.tcp_expander)
@@ -478,11 +520,11 @@ class HostDetails(HIGVBox):
for i in ipseq['values'].split(','): for i in ipseq['values'].split(','):
combo.append_text(i) combo.append_text(i)
table.attach(HIGEntryLabel(_('Class:')),0,1,0,1) table.attach(HIGEntryLabel(_('Class:')), 0, 1, 0, 1)
table.attach(HIGEntryLabel(ipseq['class']),1,2,0,1) table.attach(HIGEntryLabel(ipseq['class']), 1, 2, 0, 1)
table.attach(HIGEntryLabel(_('Values:')),0,1,1,2) table.attach(HIGEntryLabel(_('Values:')), 0, 1, 1, 2)
table.attach(combo,1,2,1,2) table.attach(combo, 1, 2, 1, 2)
self.ip_expander.add(hbox) self.ip_expander.add(hbox)
self._pack_noexpand_nofill(self.ip_expander) self._pack_noexpand_nofill(self.ip_expander)
@@ -497,11 +539,11 @@ class HostDetails(HIGVBox):
for i in tcptsseq['values'].split(','): for i in tcptsseq['values'].split(','):
combo.append_text(i) combo.append_text(i)
table.attach(HIGEntryLabel(_('Class:')),0,1,0,1) table.attach(HIGEntryLabel(_('Class:')), 0, 1, 0, 1)
table.attach(HIGEntryLabel(tcptsseq['class']),1,2,0,1) table.attach(HIGEntryLabel(tcptsseq['class']), 1, 2, 0, 1)
table.attach(HIGEntryLabel(_('Values:')),0,1,1,2) table.attach(HIGEntryLabel(_('Values:')), 0, 1, 1, 2)
table.attach(combo,1,2,1,2) table.attach(combo, 1, 2, 1, 2)
self.tcpts_expander.add(hbox) self.tcpts_expander.add(hbox)
self._pack_noexpand_nofill(self.tcpts_expander) self._pack_noexpand_nofill(self.tcpts_expander)
@@ -515,8 +557,8 @@ class HostDetails(HIGVBox):
self.comment_scrolled = gtk.ScrolledWindow() self.comment_scrolled = gtk.ScrolledWindow()
self.comment_scrolled.set_border_width(5) self.comment_scrolled.set_border_width(5)
self.comment_scrolled.set_policy(gtk.POLICY_AUTOMATIC,\ self.comment_scrolled.set_policy(
gtk.POLICY_AUTOMATIC) gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.comment_txt_vw = gtk.TextView() self.comment_txt_vw = gtk.TextView()
self.comment_txt_vw.set_wrap_mode(gtk.WRAP_WORD) self.comment_txt_vw.set_wrap_mode(gtk.WRAP_WORD)

View File

@@ -127,16 +127,19 @@ from zenmapGUI.higwidgets.higboxes import HIGVBox
from zenmapGUI.Icons import get_os_icon from zenmapGUI.Icons import get_os_icon
import zenmapCore.I18N import zenmapCore.I18N
def treemodel_get_addrs_for_sort(model, iter): def treemodel_get_addrs_for_sort(model, iter):
host = model.get_value(iter, 0) host = model.get_value(iter, 0)
return host.get_addrs_for_sort() return host.get_addrs_for_sort()
# Used to sort hosts by address. # Used to sort hosts by address.
def cmp_treemodel_addr(model, iter_a, iter_b): def cmp_treemodel_addr(model, iter_a, iter_b):
addrs_a = treemodel_get_addrs_for_sort(model, iter_a) addrs_a = treemodel_get_addrs_for_sort(model, iter_a)
addrs_b = treemodel_get_addrs_for_sort(model, iter_b) addrs_b = treemodel_get_addrs_for_sort(model, iter_b)
return cmp(addrs_a, addrs_b) return cmp(addrs_a, addrs_b)
class ScanHostsView(HIGVBox, object): class ScanHostsView(HIGVBox, object):
HOST_MODE, SERVICE_MODE = range(2) HOST_MODE, SERVICE_MODE = range(2)
@@ -272,8 +275,8 @@ class ScanHostsView(HIGVBox, object):
self.host_column.pack_start(self.host_cell, True) self.host_column.pack_start(self.host_cell, True)
self.pic_column.set_min_width(35) self.pic_column.set_min_width(35)
self.pic_column.set_attributes(self.os_cell, stock_id = 1) self.pic_column.set_attributes(self.os_cell, stock_id=1)
self.host_column.set_attributes(self.host_cell, text = 2) self.host_column.set_attributes(self.host_cell, text=2)
def mass_update(self, hosts): def mass_update(self, hosts):
"""Update the internal ListStores to reflect the hosts and services """Update the internal ListStores to reflect the hosts and services

View File

@@ -145,7 +145,8 @@ from zenmapGUI.ScanScanListPage import ScanScanListPage
from zenmapGUI.ScansListStore import ScansListStore from zenmapGUI.ScansListStore import ScansListStore
from zenmapGUI.TopologyPage import TopologyPage from zenmapGUI.TopologyPage import TopologyPage
from zenmapCore.NetworkInventory import NetworkInventory, FilteredNetworkInventory from zenmapCore.NetworkInventory import NetworkInventory,\
FilteredNetworkInventory
from zenmapCore.NmapCommand import NmapCommand from zenmapCore.NmapCommand import NmapCommand
from zenmapCore.UmitConf import CommandProfile, ProfileNotFound, is_maemo from zenmapCore.UmitConf import CommandProfile, ProfileNotFound, is_maemo
from zenmapCore.NmapParser import NmapParser from zenmapCore.NmapParser import NmapParser
@@ -157,6 +158,7 @@ import zenmapCore.I18N
# How often the live output view refreshes, in milliseconds. # How often the live output view refreshes, in milliseconds.
NMAP_OUTPUT_REFRESH_INTERVAL = 1000 NMAP_OUTPUT_REFRESH_INTERVAL = 1000
class ScanInterface(HIGVBox): class ScanInterface(HIGVBox):
"""ScanInterface contains the scan toolbar and the scan results. Each """ScanInterface contains the scan toolbar and the scan results. Each
ScanInterface represents a single NetworkInventory as well as a set of ScanInterface represents a single NetworkInventory as well as a set of
@@ -204,20 +206,26 @@ class ScanInterface(HIGVBox):
scan_interface=self) scan_interface=self)
self.host_view_selection = self.scan_result.get_host_selection() self.host_view_selection = self.scan_result.get_host_selection()
self.service_view_selection = self.scan_result.get_service_selection() self.service_view_selection = self.scan_result.get_service_selection()
self.host_view_selection.connect('changed', self.host_selection_changed) self.host_view_selection.connect(
self.service_view_selection.connect('changed', self.service_selection_changed) 'changed', self.host_selection_changed)
self.service_view_selection.connect(
'changed', self.service_selection_changed)
host_page = self.scan_result.scan_result_notebook.open_ports.host host_page = self.scan_result.scan_result_notebook.open_ports.host
host_page.host_view.get_selection().connect('changed', self.service_host_selection_changed) host_page.host_view.get_selection().connect(
self.host_view_selection.connect('changed', self.host_selection_changed) 'changed', self.service_host_selection_changed)
self.host_view_selection.connect(
'changed', self.host_selection_changed)
self.scan_result.scan_result_notebook.nmap_output.connect("changed", self._displayed_scan_change_cb) self.scan_result.scan_result_notebook.nmap_output.connect(
self.scan_result.scan_result_notebook.scans_list.remove_button.connect("clicked", self._remove_scan_cb) "changed", self._displayed_scan_change_cb)
self.scan_result.scan_result_notebook.scans_list.remove_button.connect(
"clicked", self._remove_scan_cb)
# The hosts dict maps hostnames (as returned by HostInfo.get_hostname) # The hosts dict maps hostnames (as returned by HostInfo.get_hostname)
# to HostInfo objects. # to HostInfo objects.
self.hosts = {} self.hosts = {}
# The services dict maps service names ("http") to lists of dicts of the # The services dict maps service names ("http") to lists of dicts of
# form # the form
# {'host': <HostInfo object>, 'hostname': u'example.com', # {'host': <HostInfo object>, 'hostname': u'example.com',
# 'port_state': u'open', 'portid': u'22', 'protocol': u'tcp', # 'port_state': u'open', 'portid': u'22', 'protocol': u'tcp',
# 'service_conf': u'10', 'service_extrainfo': u'protocol 2.0', # 'service_conf': u'10', 'service_extrainfo': u'protocol 2.0',
@@ -236,7 +244,8 @@ class ScanInterface(HIGVBox):
self._pack_noexpand_nofill(self.top_box) self._pack_noexpand_nofill(self.top_box)
self._pack_expand_fill(self.scan_result) self._pack_expand_fill(self.scan_result)
self.scan_result.scan_result_notebook.scans_list.cancel_button.connect("clicked", self._cancel_scans_list_cb) self.scan_result.scan_result_notebook.scans_list.cancel_button.connect(
"clicked", self._cancel_scans_list_cb)
self.update_cancel_button() self.update_cancel_button()
# Create the filter GUI # Create the filter GUI
@@ -271,16 +280,18 @@ class ScanInterface(HIGVBox):
# Restart the timer to start the filter. # Restart the timer to start the filter.
if self.filter_timeout_id: if self.filter_timeout_id:
gobject.source_remove(self.filter_timeout_id) gobject.source_remove(self.filter_timeout_id)
self.filter_timeout_id = gobject.timeout_add(self.FILTER_DELAY, self.filter_hosts, filter_bar.get_filter_string()) self.filter_timeout_id = gobject.timeout_add(
self.FILTER_DELAY, self.filter_hosts,
filter_bar.get_filter_string())
def filter_hosts(self, filter_string): def filter_hosts(self, filter_string):
start = time.clock() start = time.clock()
self.inventory.apply_filter(filter_string) self.inventory.apply_filter(filter_string)
filter_time = time.clock() - start; filter_time = time.clock() - start
# Update the gui # Update the gui
start = time.clock() start = time.clock()
self.update_ui() self.update_ui()
gui_time = time.clock() - start; gui_time = time.clock() - start
if filter_time + gui_time > 0.0: if filter_time + gui_time > 0.0:
log.debug("apply_filter %g ms update_ui %g ms (%.0f%% filter)" % log.debug("apply_filter %g ms update_ui %g ms (%.0f%% filter)" %
@@ -302,8 +313,8 @@ class ScanInterface(HIGVBox):
return len(self.jobs) return len(self.jobs)
def select_default_profile(self): def select_default_profile(self):
"""Select a "default" profile. Currently this is defined to be the first """Select a "default" profile. Currently this is defined to be the
profile.""" first profile."""
if len(self.toolbar.profile_entry.get_model()) > 0: if len(self.toolbar.profile_entry.get_model()) > 0:
self.toolbar.profile_entry.set_active(0) self.toolbar.profile_entry.set_active(0)
@@ -314,21 +325,22 @@ class ScanInterface(HIGVBox):
def __create_toolbar(self): def __create_toolbar(self):
self.toolbar = ScanToolbar() self.toolbar = ScanToolbar()
self.target_entry_changed_handler = \ self.target_entry_changed_handler = self.toolbar.target_entry.connect(
self.toolbar.target_entry.connect('changed', self._target_entry_changed) 'changed', self._target_entry_changed)
self.profile_entry_changed_handler = \ self.profile_entry_changed_handler = \
self.toolbar.profile_entry.connect('changed', self._profile_entry_changed) self.toolbar.profile_entry.connect(
'changed', self._profile_entry_changed)
self.toolbar.scan_button.connect('clicked', self.start_scan_cb) self.toolbar.scan_button.connect('clicked', self.start_scan_cb)
self.toolbar.cancel_button.connect('clicked', self._cancel_scan_cb) self.toolbar.cancel_button.connect('clicked', self._cancel_scan_cb)
def __create_command_toolbar(self): def __create_command_toolbar(self):
self.command_toolbar = ScanCommandToolbar() self.command_toolbar = ScanCommandToolbar()
self.command_toolbar.command_entry.connect('activate', self.command_toolbar.command_entry.connect(
lambda x: self.toolbar.scan_button.clicked()) 'activate', lambda x: self.toolbar.scan_button.clicked())
self.command_entry_changed_handler = \ self.command_entry_changed_handler = \
self.command_toolbar.command_entry.connect('changed', self._command_entry_changed) self.command_toolbar.command_entry.connect(
'changed', self._command_entry_changed)
def _command_entry_changed(self, editable): def _command_entry_changed(self, editable):
ops = NmapOptions() ops = NmapOptions()
@@ -378,23 +390,29 @@ class ScanInterface(HIGVBox):
def set_command_quiet(self, command_string): def set_command_quiet(self, command_string):
"""Set the command used by this scan interface, ignoring any further """Set the command used by this scan interface, ignoring any further
"changed" signals.""" "changed" signals."""
self.command_toolbar.command_entry.handler_block(self.command_entry_changed_handler) self.command_toolbar.command_entry.handler_block(
self.command_entry_changed_handler)
self.command_toolbar.set_command(command_string) self.command_toolbar.set_command(command_string)
self.command_toolbar.command_entry.handler_unblock(self.command_entry_changed_handler) self.command_toolbar.command_entry.handler_unblock(
self.command_entry_changed_handler)
def set_target_quiet(self, target_string): def set_target_quiet(self, target_string):
"""Set the target string used by this scan interface, ignoring any """Set the target string used by this scan interface, ignoring any
further "changed" signals.""" further "changed" signals."""
self.toolbar.target_entry.handler_block(self.target_entry_changed_handler) self.toolbar.target_entry.handler_block(
self.target_entry_changed_handler)
self.toolbar.set_selected_target(target_string) self.toolbar.set_selected_target(target_string)
self.toolbar.target_entry.handler_unblock(self.target_entry_changed_handler) self.toolbar.target_entry.handler_unblock(
self.target_entry_changed_handler)
def set_profile_name_quiet(self, profile_name): def set_profile_name_quiet(self, profile_name):
"""Set the profile name used by this scan interface, ignoring any """Set the profile name used by this scan interface, ignoring any
further "changed" signals.""" further "changed" signals."""
self.toolbar.profile_entry.handler_block(self.profile_entry_changed_handler) self.toolbar.profile_entry.handler_block(
self.profile_entry_changed_handler)
self.toolbar.set_selected_profile(profile_name) self.toolbar.set_selected_profile(profile_name)
self.toolbar.profile_entry.handler_unblock(self.profile_entry_changed_handler) self.toolbar.profile_entry.handler_unblock(
self.profile_entry_changed_handler)
def start_scan_cb(self, widget=None): def start_scan_cb(self, widget=None):
target = self.toolbar.selected_target target = self.toolbar.selected_target
@@ -412,14 +430,17 @@ class ScanInterface(HIGVBox):
except IOError, e: except IOError, e:
# We failed to save target_list.txt; treat it as read-only. # We failed to save target_list.txt; treat it as read-only.
# Probably it's owned by root and this is a normal user. # Probably it's owned by root and this is a normal user.
log.debug(">>> Error saving %s: %s" % (Path.target_list, str(e))) log.debug(">>> Error saving %s: %s" % (
Path.target_list, str(e)))
if command == '': if command == '':
warn_dialog = HIGAlertDialog(message_format=_("Empty Nmap Command"), warn_dialog = HIGAlertDialog(
secondary_text=_("There is no command to \ message_format=_("Empty Nmap Command"),
execute. Maybe the selected/typed profile doesn't exist. Please, check the profile name \ secondary_text=_("There is no command to execute. "
or type the nmap command you would like to execute."), "Maybe the selected/typed profile doesn't exist. "
type=gtk.MESSAGE_ERROR) "Please check the profile name or type the nmap "
"command you would like to execute."),
type=gtk.MESSAGE_ERROR)
warn_dialog.run() warn_dialog.run()
warn_dialog.destroy() warn_dialog.destroy()
return return
@@ -467,8 +488,8 @@ or type the nmap command you would like to execute."),
self.inventory.remove_scan(entry.parsed) self.inventory.remove_scan(entry.parsed)
except ValueError: except ValueError:
pass pass
# Create TreeRowReferences because those persist while we change the # Create TreeRowReferences because those persist while we change
# model. # the model.
selected_refs.append(gtk.TreeRowReference(model, path)) selected_refs.append(gtk.TreeRowReference(model, path))
# Delete the entries from the ScansListStore. # Delete the entries from the ScansListStore.
for ref in selected_refs: for ref in selected_refs:
@@ -500,7 +521,7 @@ or type the nmap command you would like to execute."),
self.jobs.remove(command) self.jobs.remove(command)
self.update_cancel_button() self.update_cancel_button()
def execute_command(self, command, target = None, profile = None): def execute_command(self, command, target=None, profile=None):
"""Run the given Nmap command. Add it to the list of running scans. """Run the given Nmap command. Add it to the list of running scans.
Schedule a timer to refresh the output and check the scan for Schedule a timer to refresh the output and check the scan for
completion.""" completion."""
@@ -515,21 +536,27 @@ or type the nmap command you would like to execute."),
# Handle ENOENT specially. # Handle ENOENT specially.
if e.errno == errno.ENOENT: if e.errno == errno.ENOENT:
# nmap_command_path comes from zenmapCore.NmapCommand. # nmap_command_path comes from zenmapCore.NmapCommand.
text += "\n\n" + _("This means that the nmap executable was not found in your system PATH, which is") + "\n\n" + os.getenv("PATH", _("<undefined>")) text += "\n\n%s\n\n%s" % (
_("This means that the nmap executable was "
"not found in your system PATH, which is"),
os.getenv("PATH", _("<undefined>"))
)
path_env = os.getenv("PATH") path_env = os.getenv("PATH")
if path_env is None: if path_env is None:
default_paths = [] default_paths = []
else: else:
default_paths = path_env.split(os.pathsep) default_paths = path_env.split(os.pathsep)
extra_paths = get_extra_executable_search_paths() extra_paths = get_extra_executable_search_paths()
extra_paths = [p for p in extra_paths if p not in default_paths] extra_paths = [p for p in extra_paths if (
p not in default_paths)]
if len(extra_paths) > 0: if len(extra_paths) > 0:
if len(extra_paths) == 1: if len(extra_paths) == 1:
text += "\n\n" + _("plus the extra directory") text += "\n\n" + _("plus the extra directory")
else: else:
text += "\n\n" + _("plus the extra directories") text += "\n\n" + _("plus the extra directories")
text += "\n\n" + os.pathsep.join(extra_paths) text += "\n\n" + os.pathsep.join(extra_paths)
warn_dialog = HIGAlertDialog(message_format=_("Error executing command"), warn_dialog = HIGAlertDialog(
message_format=_("Error executing command"),
secondary_text=text, type=gtk.MESSAGE_ERROR) secondary_text=text, type=gtk.MESSAGE_ERROR)
warn_dialog.run() warn_dialog.run()
warn_dialog.destroy() warn_dialog.destroy()
@@ -546,7 +573,8 @@ or type the nmap command you would like to execute."),
self.scan_result.refresh_nmap_output() self.scan_result.refresh_nmap_output()
# Add a timeout function # Add a timeout function
self.verify_thread_timeout_id = gobject.timeout_add(NMAP_OUTPUT_REFRESH_INTERVAL, self.verify_execution) self.verify_thread_timeout_id = gobject.timeout_add(
NMAP_OUTPUT_REFRESH_INTERVAL, self.verify_execution)
def verify_execution(self): def verify_execution(self):
"""This is a callback that is called periodically to refresh the output """This is a callback that is called periodically to refresh the output
@@ -597,12 +625,12 @@ or type the nmap command you would like to execute."),
except: except:
st = None st = None
if st is None or st.st_size > 0: if st is None or st.st_size > 0:
warn_dialog = HIGAlertDialog(message_format = _("Parse error"), warn_dialog = HIGAlertDialog(
secondary_text = _(u"""\ message_format=_("Parse error"),
There was an error while parsing the XML file generated from the scan: secondary_text=_(
"There was an error while parsing the XML file "
%s\ "generated from the scan:\n\n%s""") % str(e),
""") % str(e), type = gtk.MESSAGE_ERROR) type=gtk.MESSAGE_ERROR)
warn_dialog.run() warn_dialog.run()
warn_dialog.destroy() warn_dialog.destroy()
else: else:
@@ -612,12 +640,12 @@ There was an error while parsing the XML file generated from the scan:
try: try:
self.inventory.add_scan(parsed) self.inventory.add_scan(parsed)
except Exception, e: except Exception, e:
warn_dialog = HIGAlertDialog(message_format = _("Cannot merge scan"), warn_dialog = HIGAlertDialog(
secondary_text = _(u"""\ message_format=_("Cannot merge scan"),
There was an error while merging the new scan's XML: secondary_text=_(
"There was an error while merging the new scan's "
%s\ "XML:\n\n%s") % str(e),
""") % str(e), type = gtk.MESSAGE_ERROR) type=gtk.MESSAGE_ERROR)
warn_dialog.run() warn_dialog.run()
warn_dialog.destroy() warn_dialog.destroy()
parsed.set_xml_is_temp(command.xml_is_temp) parsed.set_xml_is_temp(command.xml_is_temp)
@@ -686,27 +714,29 @@ There was an error while merging the new scan's XML:
if name not in self.services.keys(): if name not in self.services.keys():
self.services[name] = [] self.services[name] = []
hs = {"host":host, "hostname":hostname} hs = {"host": host, "hostname": hostname}
hs.update(service) hs.update(service)
self.services[name].append(hs) self.services[name].append(hs)
self.hosts[hostname] = host self.hosts[hostname] = host
# If the host and service selection is empty or has become empty, select # If the host and service selection is empty or has become empty,
# the first host if there is at least one. # select the first host if there is at least one.
if len(self.host_view_selection.get_selected_rows()[1]) == 0 \ if (len(self.service_view_selection.get_selected_rows()[1]) == 0 and
and len(self.service_view_selection.get_selected_rows()[1]) == 0 \ len(self.host_view_selection.get_selected_rows()[1]) == 0 and
and len(self.scan_result.scan_host_view.host_list) > 0: len(self.scan_result.scan_host_view.host_list) > 0):
self.host_view_selection.select_iter(self.scan_result.scan_host_view.host_list.get_iter_first()) self.host_view_selection.select_iter(
self.scan_result.scan_host_view.host_list.get_iter_first())
self.filter_bar.set_information_text(_("%d/%d hosts shown") % self.filter_bar.set_information_text(_("%d/%d hosts shown") %
(len(self.inventory.get_hosts_up()), (len(self.inventory.get_hosts_up()),
len(NetworkInventory.get_hosts_up(self.inventory)))) len(NetworkInventory.get_hosts_up(self.inventory))))
if self.scan_result.scan_host_view.mode == ScanHostsView.HOST_MODE: mode = self.scan_result.scan_host_view.mode
if mode == ScanHostsView.HOST_MODE:
self.refresh_port_output() self.refresh_port_output()
elif self.scan_result.scan_host_view.mode == ScanHostsView.SERVICE_MODE: elif mode == ScanHostsView.SERVICE_MODE:
self.refresh_host_output() self.refresh_host_output()
def refresh_port_output(self): def refresh_port_output(self):
@@ -714,11 +744,12 @@ There was an error while merging the new scan's XML:
current host selection.""" current host selection."""
self.scan_result.scan_result_notebook.port_mode() self.scan_result.scan_result_notebook.port_mode()
model_host_list, selection = self.host_view_selection.get_selected_rows() model_host_list, selection = \
self.host_view_selection.get_selected_rows()
host_objs = [] host_objs = []
for i in selection: for i in selection:
hostname = model_host_list[i[0]][2] hostname = model_host_list[i[0]][2]
if self.hosts.has_key(hostname): if hostname in self.hosts:
host_objs.append(self.hosts[hostname]) host_objs.append(self.hosts[hostname])
if len(host_objs) == 1: if len(host_objs) == 1:
@@ -732,11 +763,12 @@ There was an error while merging the new scan's XML:
current service selection.""" current service selection."""
self.scan_result.scan_result_notebook.host_mode() self.scan_result.scan_result_notebook.host_mode()
model_service_list, selection = self.service_view_selection.get_selected_rows() model_service_list, selection = \
self.service_view_selection.get_selected_rows()
serv_objs = [] serv_objs = []
for i in selection: for i in selection:
key = model_service_list[i[0]][0] key = model_service_list[i[0]][0]
if self.services.has_key(key): if key in self.services:
serv_objs.append(self.services[key]) serv_objs.append(self.services[key])
# Each element of serv_objs is a list of port dicts. # Each element of serv_objs is a list of port dicts.
@@ -745,7 +777,9 @@ There was an error while merging the new scan's XML:
else: else:
servs = [] servs = []
for s in serv_objs: for s in serv_objs:
servs.append({"service_name":s[0]["service_name"], "ports": s}) servs.append({
"service_name": s[0]["service_name"],
"ports": s})
self.set_multiple_service_host(servs) self.set_multiple_service_host(servs)
def host_selection_changed(self, widget): def host_selection_changed(self, widget):
@@ -791,7 +825,8 @@ There was an error while merging the new scan's XML:
"""Sets the comment on a host from the contents of the comment text """Sets the comment on a host from the contents of the comment text
entry.""" entry."""
buff = widget.get_buffer() buff = widget.get_buffer()
host.comment = buff.get_text(buff.get_start_iter(), buff.get_end_iter()) host.comment = buff.get_text(
buff.get_start_iter(), buff.get_end_iter())
for scan in self.inventory.get_scans(): for scan in self.inventory.get_scans():
if host in scan.get_hosts(): if host in scan.get_hosts():
scan.unsaved = True scan.unsaved = True
@@ -803,8 +838,10 @@ There was an error while merging the new scan's XML:
pages = [] pages = []
for host in hosts: for host in hosts:
page = ScanHostDetailsPage(host) page = ScanHostDetailsPage(host)
page.host_details.comment_txt_vw.connect("insert-at-cursor", self._save_comment, host) page.host_details.comment_txt_vw.connect(
page.host_details.comment_txt_vw.connect("focus-out-event", self._save_comment, host) "insert-at-cursor", self._save_comment, host)
page.host_details.comment_txt_vw.connect(
"focus-out-event", self._save_comment, host)
pages.append(page) pages.append(page)
return pages return pages
@@ -833,9 +870,9 @@ There was an error while merging the new scan's XML:
host_page.thaw() host_page.thaw()
def set_multiple_host_port(self, host_list): def set_multiple_host_port(self, host_list):
"""Change the "Ports / Hosts" tab to show the port output for all of the """Change the "Ports / Hosts" tab to show the port output for all of
hosts in host_list. When multiple hosts are selected, the port output the hosts in host_list. When multiple hosts are selected, the port
for each is contained in an expander.""" output for each is contained in an expander."""
host_page = self.scan_result.scan_result_notebook.open_ports.host host_page = self.scan_result.scan_result_notebook.open_ports.host
host_page.switch_port_to_tree_store() host_page.switch_port_to_tree_store()
@@ -846,19 +883,22 @@ There was an error while merging the new scan's XML:
host_page.thaw() host_page.thaw()
def set_multiple_service_host(self, service_list): def set_multiple_service_host(self, service_list):
"""Change the "Ports / Hosts" tab to show the hosts associated with each """Change the "Ports / Hosts" tab to show the hosts associated with
of the services in service_list. Each element of service_list must be a each of the services in service_list. Each element of service_list must
dict with the keys "service_name" and "ports". When multiple services be a dict with the keys "service_name" and "ports". When multiple
are selected, the hosts for each are contained in an expander.""" services are selected, the hosts for each are contained in an
expander."""
host_page = self.scan_result.scan_result_notebook.open_ports.host host_page = self.scan_result.scan_result_notebook.open_ports.host
host_page.switch_host_to_tree_store() host_page.switch_host_to_tree_store()
host_page.freeze() host_page.freeze()
host_page.clear_host_tree() host_page.clear_host_tree()
for service in service_list: for service in service_list:
host_page.add_to_host_tree(service["service_name"], service["ports"]) host_page.add_to_host_tree(
service["service_name"], service["ports"])
host_page.thaw() host_page.thaw()
class ScanResult(gtk.HPaned): class ScanResult(gtk.HPaned):
"""This is the pane that has the "Host"/"Service" column (ScanHostsView) on """This is the pane that has the "Host"/"Service" column (ScanHostsView) on
the left and the "Nmap Output"/"Ports / Hosts"/etc. (ScanResultNotebook) on the left and the "Nmap Output"/"Ports / Hosts"/etc. (ScanResultNotebook) on
@@ -915,7 +955,8 @@ class ScanResultNotebook(HIGNotebook):
self.__create_widgets(inventory, scans_store) self.__create_widgets(inventory, scans_store)
self.scans_list.scans_list.connect("row-activated", self._scan_row_activated) self.scans_list.scans_list.connect(
"row-activated", self._scan_row_activated)
self.append_page(self.nmap_output_page, gtk.Label(_('Nmap Output'))) self.append_page(self.nmap_output_page, gtk.Label(_('Nmap Output')))
self.append_page(self.open_ports_page, gtk.Label(_('Ports / Hosts'))) self.append_page(self.open_ports_page, gtk.Label(_('Ports / Hosts')))

View File

@@ -134,6 +134,7 @@ from zenmapCore.Paths import Path
from zenmapCore.UmitLogging import log from zenmapCore.UmitLogging import log
import zenmapCore.I18N import zenmapCore.I18N
def scan_entry_data_func(widget, cell_renderer, model, iter): def scan_entry_data_func(widget, cell_renderer, model, iter):
"""Set the properties of a cell renderer for a scan entry.""" """Set the properties of a cell renderer for a scan entry."""
cell_renderer.set_property("ellipsize", pango.ELLIPSIZE_END) cell_renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
@@ -150,12 +151,15 @@ def scan_entry_data_func(widget, cell_renderer, model, iter):
cell_renderer.set_property("strikethrough", True) cell_renderer.set_property("strikethrough", True)
cell_renderer.set_property("text", entry.get_command_string()) cell_renderer.set_property("text", entry.get_command_string())
class Throbber(gtk.Image): class Throbber(gtk.Image):
"""This is a little progress indicator that animates while a scan is """This is a little progress indicator that animates while a scan is
running.""" running."""
try: try:
still = gtk.gdk.pixbuf_new_from_file(os.path.join(Path.pixmaps_dir, "throbber.png")) still = gtk.gdk.pixbuf_new_from_file(
anim = gtk.gdk.PixbufAnimation(os.path.join(Path.pixmaps_dir, "throbber.gif")) os.path.join(Path.pixmaps_dir, "throbber.png"))
anim = gtk.gdk.PixbufAnimation(
os.path.join(Path.pixmaps_dir, "throbber.gif"))
except Exception, e: except Exception, e:
log.debug("Error loading throbber images: %s." % str(e)) log.debug("Error loading throbber images: %s." % str(e))
still = None still = None
@@ -177,6 +181,7 @@ class Throbber(gtk.Image):
self.set_from_pixbuf(self.still) self.set_from_pixbuf(self.still)
self.animating = False self.animating = False
class ScanNmapOutputPage(HIGVBox): class ScanNmapOutputPage(HIGVBox):
"""This is the "Nmap Output" scan results tab. It holds a text view of Nmap """This is the "Nmap Output" scan results tab. It holds a text view of Nmap
output. The constructor takes a ScansListStore, the contents of which are output. The constructor takes a ScansListStore, the contents of which are
@@ -223,8 +228,8 @@ class ScanNmapOutputPage(HIGVBox):
self._update() self._update()
def set_active_iter(self, i): def set_active_iter(self, i):
"""Set the active entry to an interator into the ScansListStore referred """Set the active entry to an interator into the ScansListStore
to by this object.""" referred to by this object."""
self.scans_list.set_active_iter(i) self.scans_list.set_active_iter(i)
def get_active_entry(self): def get_active_entry(self):
@@ -287,9 +292,11 @@ class ScanNmapOutputPage(HIGVBox):
if self._details_windows.get(entry) is None: if self._details_windows.get(entry) is None:
window = gtk.Window() window = gtk.Window()
window.add(ScanRunDetailsPage(entry.parsed)) window.add(ScanRunDetailsPage(entry.parsed))
def close_details(details, event, entry): def close_details(details, event, entry):
details.destroy() details.destroy()
del self._details_windows[entry] del self._details_windows[entry]
window.connect("delete-event", close_details, entry) window.connect("delete-event", close_details, entry)
window.show_all() window.show_all()
self._details_windows[entry] = window self._details_windows[entry] = window

View File

@@ -128,12 +128,14 @@ from zenmapGUI.higwidgets.higtables import HIGTable
from zenmapCore.UmitLogging import log from zenmapCore.UmitLogging import log
import zenmapCore.I18N import zenmapCore.I18N
def findout_service_icon(port_info): def findout_service_icon(port_info):
if port_info["port_state"] in ["open", "open|filtered"]: if port_info["port_state"] in ["open", "open|filtered"]:
return gtk.STOCK_YES return gtk.STOCK_YES
else: else:
return gtk.STOCK_NO return gtk.STOCK_NO
def get_version_string(d): def get_version_string(d):
"""Get a human-readable version string from the dict d. The keys used in d """Get a human-readable version string from the dict d. The keys used in d
are "service_product", "service_version", and "service_extrainfo" (all are are "service_product", "service_version", and "service_extrainfo" (all are
@@ -148,38 +150,45 @@ def get_version_string(d):
result.append("(" + d["service_extrainfo"] + ")") result.append("(" + d["service_extrainfo"] + ")")
return " ".join(result) return " ".join(result)
def get_addrs(host): def get_addrs(host):
if host is None: if host is None:
return None return None
return host.get_addrs_for_sort() return host.get_addrs_for_sort()
def cmp_addrs(host_a, host_b): def cmp_addrs(host_a, host_b):
return cmp(get_addrs(host_a), get_addrs(host_b)) return cmp(get_addrs(host_a), get_addrs(host_b))
def cmp_port_list_addr(model, iter_a, iter_b): def cmp_port_list_addr(model, iter_a, iter_b):
host_a = model.get_value(iter_a, 0) host_a = model.get_value(iter_a, 0)
host_b = model.get_value(iter_b, 0) host_b = model.get_value(iter_b, 0)
return cmp_addrs(host_a, host_b) return cmp_addrs(host_a, host_b)
def cmp_port_tree_addr(model, iter_a, iter_b): def cmp_port_tree_addr(model, iter_a, iter_b):
host_a = model.get_value(iter_a, 0) host_a = model.get_value(iter_a, 0)
host_b = model.get_value(iter_b, 0) host_b = model.get_value(iter_b, 0)
return cmp_addrs(host_a, host_b) return cmp_addrs(host_a, host_b)
def cmp_host_list_addr(model, iter_a, iter_b): def cmp_host_list_addr(model, iter_a, iter_b):
host_a = model.get_value(iter_a, 2) host_a = model.get_value(iter_a, 2)
host_b = model.get_value(iter_b, 2) host_b = model.get_value(iter_b, 2)
return cmp_addrs(host_a, host_b) return cmp_addrs(host_a, host_b)
def cmp_host_tree_addr(model, iter_a, iter_b): def cmp_host_tree_addr(model, iter_a, iter_b):
host_a = model.get_value(iter_a, 2) host_a = model.get_value(iter_a, 2)
host_b = model.get_value(iter_b, 2) host_b = model.get_value(iter_b, 2)
return cmp_addrs(host_a, host_b) return cmp_addrs(host_a, host_b)
class ScanOpenPortsPage(gtk.ScrolledWindow): class ScanOpenPortsPage(gtk.ScrolledWindow):
def __init__(self): def __init__(self):
gtk.ScrolledWindow.__init__(self) gtk.ScrolledWindow.__init__(self)
self.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.__create_widgets() self.__create_widgets()
@@ -188,6 +197,7 @@ class ScanOpenPortsPage(gtk.ScrolledWindow):
def __create_widgets(self): def __create_widgets(self):
self.host = HostOpenPorts() self.host = HostOpenPorts()
class HostOpenPorts(HIGVBox): class HostOpenPorts(HIGVBox):
def __init__(self): def __init__(self):
HIGVBox.__init__(self) HIGVBox.__init__(self)
@@ -203,8 +213,10 @@ class HostOpenPorts(HIGVBox):
# host hostname icon port protocol state service version # host hostname icon port protocol state service version
# The hostname column is shown only when more than one host is selected # The hostname column is shown only when more than one host is selected
# (hence port_tree not port_list is used). # (hence port_tree not port_list is used).
self.port_list = gtk.ListStore(object, str, str, int, str, str, str, str) self.port_list = gtk.ListStore(
self.port_tree = gtk.TreeStore(object, str, str, int, str, str, str, str) object, str, str, int, str, str, str, str)
self.port_tree = gtk.TreeStore(
object, str, str, int, str, str, str, str)
self.port_list.set_sort_func(1000, cmp_port_list_addr) self.port_list.set_sort_func(1000, cmp_port_list_addr)
self.port_list.set_sort_column_id(1000, gtk.SORT_ASCENDING) self.port_list.set_sort_column_id(1000, gtk.SORT_ASCENDING)
@@ -229,8 +241,10 @@ class HostOpenPorts(HIGVBox):
# service icon host hostname port protocol state version # service icon host hostname port protocol state version
# service is shown only when more than one service is selected (hence # service is shown only when more than one service is selected (hence
# host_tree not host_list is used). # host_tree not host_list is used).
self.host_list = gtk.ListStore(str, str, object, str, int, str, str, str) self.host_list = gtk.ListStore(
self.host_tree = gtk.TreeStore(str, str, object, str, int, str, str, str) str, str, object, str, int, str, str, str)
self.host_tree = gtk.TreeStore(
str, str, object, str, int, str, str, str)
self.host_list.set_sort_func(1000, cmp_host_list_addr) self.host_list.set_sort_func(1000, cmp_host_list_addr)
self.host_list.set_sort_column_id(1000, gtk.SORT_ASCENDING) self.host_list.set_sort_column_id(1000, gtk.SORT_ASCENDING)
@@ -285,7 +299,8 @@ class HostOpenPorts(HIGVBox):
self.host_columns['state'].pack_start(self.cell_port, True) self.host_columns['state'].pack_start(self.cell_port, True)
self.host_columns['service'].set_attributes(self.cell_port, text=0) self.host_columns['service'].set_attributes(self.cell_port, text=0)
self.host_columns['icon'].set_attributes(self.cell_host_icon, stock_id=1) self.host_columns['icon'].set_attributes(
self.cell_host_icon, stock_id=1)
self.host_columns['hostname'].set_attributes(self.cell_port, text=3) self.host_columns['hostname'].set_attributes(self.cell_port, text=3)
self.host_columns['port_number'].set_attributes(self.cell_port, text=4) self.host_columns['port_number'].set_attributes(self.cell_port, text=4)
self.host_columns['protocol'].set_attributes(self.cell_port, text=5) self.host_columns['protocol'].set_attributes(self.cell_port, text=5)
@@ -294,7 +309,8 @@ class HostOpenPorts(HIGVBox):
self.host_columns['service'].set_visible(False) self.host_columns['service'].set_visible(False)
self.scroll_ports_hosts.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scroll_ports_hosts.set_policy(
gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
def _set_port_list(self): def _set_port_list(self):
self.port_view.set_enable_search(True) self.port_view.set_enable_search(True)
@@ -315,7 +331,6 @@ class HostOpenPorts(HIGVBox):
self.port_columns[k].set_reorderable(True) self.port_columns[k].set_reorderable(True)
self.port_columns[k].set_resizable(True) self.port_columns[k].set_resizable(True)
self.port_columns['icon'].set_min_width(35) self.port_columns['icon'].set_min_width(35)
self.port_columns['hostname'].set_sort_column_id(1000) self.port_columns['hostname'].set_sort_column_id(1000)
@@ -368,10 +383,14 @@ class HostOpenPorts(HIGVBox):
def freeze(self): def freeze(self):
"""Freeze notifications and sorting to make adding lots of elements to """Freeze notifications and sorting to make adding lots of elements to
the model faster.""" the model faster."""
self.frozen_host_list_sort_column_id = self.host_list.get_sort_column_id() self.frozen_host_list_sort_column_id = \
self.frozen_host_tree_sort_column_id = self.host_tree.get_sort_column_id() self.host_list.get_sort_column_id()
self.frozen_port_list_sort_column_id = self.port_list.get_sort_column_id() self.frozen_host_tree_sort_column_id = \
self.frozen_port_tree_sort_column_id = self.port_tree.get_sort_column_id() self.host_tree.get_sort_column_id()
self.frozen_port_list_sort_column_id = \
self.port_list.get_sort_column_id()
self.frozen_port_tree_sort_column_id = \
self.port_tree.get_sort_column_id()
self.host_list.set_default_sort_func(lambda *args: -1) self.host_list.set_default_sort_func(lambda *args: -1)
self.host_tree.set_default_sort_func(lambda *args: -1) self.host_tree.set_default_sort_func(lambda *args: -1)
self.port_list.set_default_sort_func(lambda *args: -1) self.port_list.set_default_sort_func(lambda *args: -1)
@@ -387,13 +406,17 @@ class HostOpenPorts(HIGVBox):
"""Restore notifications and sorting (after making changes to the """Restore notifications and sorting (after making changes to the
model).""" model)."""
if self.frozen_host_list_sort_column_id != (None, None): if self.frozen_host_list_sort_column_id != (None, None):
self.host_list.set_sort_column_id(*self.frozen_host_list_sort_column_id) self.host_list.set_sort_column_id(
*self.frozen_host_list_sort_column_id)
if self.frozen_host_tree_sort_column_id != (None, None): if self.frozen_host_tree_sort_column_id != (None, None):
self.host_tree.set_sort_column_id(*self.frozen_host_tree_sort_column_id) self.host_tree.set_sort_column_id(
*self.frozen_host_tree_sort_column_id)
if self.frozen_port_list_sort_column_id != (None, None): if self.frozen_port_list_sort_column_id != (None, None):
self.port_list.set_sort_column_id(*self.frozen_port_list_sort_column_id) self.port_list.set_sort_column_id(
*self.frozen_port_list_sort_column_id)
if self.frozen_port_tree_sort_column_id != (None, None): if self.frozen_port_tree_sort_column_id != (None, None):
self.port_tree.set_sort_column_id(*self.frozen_port_tree_sort_column_id) self.port_tree.set_sort_column_id(
*self.frozen_port_tree_sort_column_id)
self.host_view.set_model(self.frozen_host_view_model) self.host_view.set_model(self.frozen_host_view_model)
self.port_view.set_model(self.frozen_port_view_model) self.port_view.set_model(self.frozen_port_view_model)
self.host_view.thaw_child_notify() self.host_view.thaw_child_notify()
@@ -414,7 +437,8 @@ class HostOpenPorts(HIGVBox):
self.host_list.append(entry) self.host_list.append(entry)
def add_to_port_tree(self, host): def add_to_port_tree(self, host):
parent = self.port_tree.append(None, [host, host.get_hostname(), None, 0,'','','','']) parent = self.port_tree.append(
None, [host, host.get_hostname(), None, 0, '', '', '', ''])
for p in host.get_ports(): for p in host.get_ports():
self.port_tree.append(parent, self.port_tree.append(parent,
[None, '', findout_service_icon(p), int(p.get('portid', "0")), [None, '', findout_service_icon(p), int(p.get('portid', "0")),
@@ -422,12 +446,21 @@ class HostOpenPorts(HIGVBox):
p.get('service_name', _("Unknown")), get_version_string(p)]) p.get('service_name', _("Unknown")), get_version_string(p)])
def add_to_host_tree(self, service_name, ports): def add_to_host_tree(self, service_name, ports):
parent = self.host_tree.append(None, [service_name, '', None, '', 0, '', '', '']) parent = self.host_tree.append(
None, [service_name, '', None, '', 0, '', '', ''])
for p in ports: for p in ports:
self.host_tree.append(parent, self.host_tree.append(parent,
['', findout_service_icon(p), p["host"], p["host"].get_hostname(), [
int(p.get('portid', "0")), p.get('protocol', ""), '',
p.get('port_state', _("Unknown")), get_version_string(p)]) findout_service_icon(p),
p["host"],
p["host"].get_hostname(),
int(p.get('portid', "0")),
p.get('protocol', ""),
p.get('port_state', _("Unknown")),
get_version_string(p)
]
)
def switch_port_to_list_store(self): def switch_port_to_list_store(self):
if self.port_view.get_model() != self.port_list: if self.port_view.get_model() != self.port_list:

View File

@@ -121,12 +121,14 @@
# ***************************************************************************/ # ***************************************************************************/
import gtk import gtk
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, hig_box_space_holder from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox,\
hig_box_space_holder
from zenmapGUI.higwidgets.higtables import HIGTable from zenmapGUI.higwidgets.higtables import HIGTable
from zenmapGUI.higwidgets.higlabels import HIGEntryLabel from zenmapGUI.higwidgets.higlabels import HIGEntryLabel
import zenmapCore.I18N import zenmapCore.I18N
class ScanRunDetailsPage(HIGVBox): class ScanRunDetailsPage(HIGVBox):
def __init__(self, scan): def __init__(self, scan):
HIGVBox.__init__(self) HIGVBox.__init__(self)
@@ -146,7 +148,8 @@ class ScanRunDetailsPage(HIGVBox):
self.debug_label = HIGEntryLabel(_('Debug level:')) self.debug_label = HIGEntryLabel(_('Debug level:'))
self.info_debug_label = HIGEntryLabel(na) self.info_debug_label = HIGEntryLabel(na)
self.command_expander = gtk.Expander("<b>"+_("Command Info")+"</b>") self.command_expander = gtk.Expander(
"<b>" + _("Command Info") + "</b>")
self.command_expander.set_use_markup(True) self.command_expander.set_use_markup(True)
self.command_table = HIGTable() self.command_table = HIGTable()
@@ -158,17 +161,17 @@ class ScanRunDetailsPage(HIGVBox):
self.command_hbox._pack_noexpand_nofill(hig_box_space_holder()) self.command_hbox._pack_noexpand_nofill(hig_box_space_holder())
self.command_hbox._pack_noexpand_nofill(self.command_table) self.command_hbox._pack_noexpand_nofill(self.command_table)
self.command_table.attach(self.command_label,0,1,0,1) self.command_table.attach(self.command_label, 0, 1, 0, 1)
self.command_table.attach(self.info_command_label,1,2,0,1) self.command_table.attach(self.info_command_label, 1, 2, 0, 1)
self.command_table.attach(self.nmap_version_label,0,1,1,2) self.command_table.attach(self.nmap_version_label, 0, 1, 1, 2)
self.command_table.attach(self.info_nmap_version_label,1,2,1,2) self.command_table.attach(self.info_nmap_version_label, 1, 2, 1, 2)
self.command_table.attach(self.verbose_label,0,1,2,3) self.command_table.attach(self.verbose_label, 0, 1, 2, 3)
self.command_table.attach(self.info_verbose_label,1,2,2,3) self.command_table.attach(self.info_verbose_label, 1, 2, 2, 3)
self.command_table.attach(self.debug_label,0,1,3,4) self.command_table.attach(self.debug_label, 0, 1, 3, 4)
self.command_table.attach(self.info_debug_label,1,2,3,4) self.command_table.attach(self.info_debug_label, 1, 2, 3, 4)
self.command_expander.add(self.command_hbox) self.command_expander.add(self.command_hbox)
self._pack_noexpand_nofill(self.command_expander) self._pack_noexpand_nofill(self.command_expander)
@@ -199,7 +202,8 @@ class ScanRunDetailsPage(HIGVBox):
self.closed_label = HIGEntryLabel(_('Closed ports:')) self.closed_label = HIGEntryLabel(_('Closed ports:'))
self.info_closed_label = HIGEntryLabel(na) self.info_closed_label = HIGEntryLabel(na)
self.general_expander = gtk.Expander("<b>"+_("General Info")+"</b>") self.general_expander = gtk.Expander(
"<b>" + _("General Info") + "</b>")
self.general_expander.set_use_markup(True) self.general_expander.set_use_markup(True)
self.general_table = HIGTable() self.general_table = HIGTable()
@@ -211,29 +215,29 @@ class ScanRunDetailsPage(HIGVBox):
self.general_hbox._pack_noexpand_nofill(hig_box_space_holder()) self.general_hbox._pack_noexpand_nofill(hig_box_space_holder())
self.general_hbox._pack_noexpand_nofill(self.general_table) self.general_hbox._pack_noexpand_nofill(self.general_table)
self.general_table.attach(self.start_label,0,1,0,1) self.general_table.attach(self.start_label, 0, 1, 0, 1)
self.general_table.attach(self.info_start_label,1,2,0,1) self.general_table.attach(self.info_start_label, 1, 2, 0, 1)
self.general_table.attach(self.finished_label,0,1,1,2) self.general_table.attach(self.finished_label, 0, 1, 1, 2)
self.general_table.attach(self.info_finished_label,1,2,1,2) self.general_table.attach(self.info_finished_label, 1, 2, 1, 2)
self.general_table.attach(self.host_up_label,0,1,2,3) self.general_table.attach(self.host_up_label, 0, 1, 2, 3)
self.general_table.attach(self.info_hosts_up_label,1,2,2,3) self.general_table.attach(self.info_hosts_up_label, 1, 2, 2, 3)
self.general_table.attach(self.host_down_label,0,1,3,4) self.general_table.attach(self.host_down_label, 0, 1, 3, 4)
self.general_table.attach(self.info_hosts_down_label,1,2,3,4) self.general_table.attach(self.info_hosts_down_label, 1, 2, 3, 4)
self.general_table.attach(self.host_scanned_label,0,1,4,5) self.general_table.attach(self.host_scanned_label, 0, 1, 4, 5)
self.general_table.attach(self.info_hosts_scanned_label,1,2,4,5) self.general_table.attach(self.info_hosts_scanned_label, 1, 2, 4, 5)
self.general_table.attach(self.open_label,0,1,5,6) self.general_table.attach(self.open_label, 0, 1, 5, 6)
self.general_table.attach(self.info_open_label,1,2,5,6) self.general_table.attach(self.info_open_label, 1, 2, 5, 6)
self.general_table.attach(self.filtered_label,0,1,6,7) self.general_table.attach(self.filtered_label, 0, 1, 6, 7)
self.general_table.attach(self.info_filtered_label,1,2,6,7) self.general_table.attach(self.info_filtered_label, 1, 2, 6, 7)
self.general_table.attach(self.closed_label,0,1,7,8) self.general_table.attach(self.closed_label, 0, 1, 7, 8)
self.general_table.attach(self.info_closed_label,1,2,7,8) self.general_table.attach(self.info_closed_label, 1, 2, 7, 8)
self.general_expander.add(self.general_hbox) self.general_expander.add(self.general_hbox)
self._pack_noexpand_nofill(self.general_expander) self._pack_noexpand_nofill(self.general_expander)
@@ -260,7 +264,8 @@ class ScanRunDetailsPage(HIGVBox):
self.info_closed_label.set_text(str(scan.get_closed_ports())) self.info_closed_label.set_text(str(scan.get_closed_ports()))
for scaninfo in scan.get_scaninfo(): for scaninfo in scan.get_scaninfo():
exp = gtk.Expander('<b>%s - %s</b>' % (_('Scan Info'), scaninfo['type'].capitalize())) exp = gtk.Expander('<b>%s - %s</b>' % (
_('Scan Info'), scaninfo['type'].capitalize()))
exp.set_use_markup(True) exp.set_use_markup(True)
display = self.make_scaninfo_display(scaninfo) display = self.make_scaninfo_display(scaninfo)
@@ -277,17 +282,18 @@ class ScanRunDetailsPage(HIGVBox):
table.set_row_spacings(6) table.set_row_spacings(6)
table.set_col_spacings(6) table.set_col_spacings(6)
table.attach(HIGEntryLabel(_('Scan type:')),0,1,0,1) table.attach(HIGEntryLabel(_('Scan type:')), 0, 1, 0, 1)
table.attach(HIGEntryLabel(scaninfo['type']),1,2,0,1) table.attach(HIGEntryLabel(scaninfo['type']), 1, 2, 0, 1)
table.attach(HIGEntryLabel(_('Protocol:')),0,1,1,2) table.attach(HIGEntryLabel(_('Protocol:')), 0, 1, 1, 2)
table.attach(HIGEntryLabel(scaninfo['protocol']),1,2,1,2) table.attach(HIGEntryLabel(scaninfo['protocol']), 1, 2, 1, 2)
table.attach(HIGEntryLabel(_('# scanned ports:')),0,1,2,3) table.attach(HIGEntryLabel(_('# scanned ports:')), 0, 1, 2, 3)
table.attach(HIGEntryLabel(scaninfo['numservices']),1,2,2,3) table.attach(HIGEntryLabel(scaninfo['numservices']), 1, 2, 2, 3)
table.attach(HIGEntryLabel(_('Services:')),0,1,3,4) table.attach(HIGEntryLabel(_('Services:')), 0, 1, 3, 4)
table.attach(self.make_services_display(scaninfo['services']),1,2,3,4) table.attach(
self.make_services_display(scaninfo['services']), 1, 2, 3, 4)
hbox._pack_noexpand_nofill(hig_box_space_holder()) hbox._pack_noexpand_nofill(hig_box_space_holder())
hbox._pack_noexpand_nofill(table) hbox._pack_noexpand_nofill(table)

View File

@@ -128,6 +128,7 @@ from zenmapGUI.higwidgets.higbuttons import HIGButton
from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow
import zenmapCore.I18N import zenmapCore.I18N
def status_data_func(widget, cell_renderer, model, iter): def status_data_func(widget, cell_renderer, model, iter):
entry = model.get_value(iter, 0) entry = model.get_value(iter, 0)
if entry.running: if entry.running:
@@ -143,14 +144,17 @@ def status_data_func(widget, cell_renderer, model, iter):
status = _("Canceled") status = _("Canceled")
cell_renderer.set_property("text", status) cell_renderer.set_property("text", status)
def command_data_func(widget, cell_renderer, model, iter): def command_data_func(widget, cell_renderer, model, iter):
entry = model.get_value(iter, 0) entry = model.get_value(iter, 0)
cell_renderer.set_property("ellipsize", pango.ELLIPSIZE_END) cell_renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
cell_renderer.set_property("text", entry.get_command_string()) cell_renderer.set_property("text", entry.get_command_string())
class ScanScanListPage(HIGVBox): class ScanScanListPage(HIGVBox):
"""This is the "Scans" scan results tab. It the list of running and finished """This is the "Scans" scan results tab. It the list of running and
scans contained in the ScansListStore passed to the constructor.""" finished scans contained in the ScansListStore passed to the
constructor."""
def __init__(self, scans_store): def __init__(self, scans_store):
HIGVBox.__init__(self) HIGVBox.__init__(self)
@@ -159,7 +163,8 @@ class ScanScanListPage(HIGVBox):
scans_store.connect("row-changed", self._row_changed) scans_store.connect("row-changed", self._row_changed)
self.scans_list = gtk.TreeView(scans_store) self.scans_list = gtk.TreeView(scans_store)
self.scans_list.get_selection().connect("changed", self._selection_changed) self.scans_list.get_selection().connect(
"changed", self._selection_changed)
status_col = gtk.TreeViewColumn(_("Status")) status_col = gtk.TreeViewColumn(_("Status"))
cell = gtk.CellRendererText() cell = gtk.CellRendererText()
@@ -193,9 +198,9 @@ class ScanScanListPage(HIGVBox):
self.cancel_button = HIGButton(_("Cancel Scan"), gtk.STOCK_CANCEL) self.cancel_button = HIGButton(_("Cancel Scan"), gtk.STOCK_CANCEL)
buttonbox.pack_start(self.cancel_button, False) buttonbox.pack_start(self.cancel_button, False)
hbox.pack_start(buttonbox, padding = 4) hbox.pack_start(buttonbox, padding=4)
self.pack_start(hbox, False, padding = 4) self.pack_start(hbox, False, padding=4)
self._update() self._update()
@@ -206,13 +211,13 @@ class ScanScanListPage(HIGVBox):
self._update() self._update()
def _update(self): def _update(self):
# Make the Cancel button sensitive or not depending on whether a running # Make the Cancel button sensitive or not depending on whether a
# scan is selected. # running scan is selected.
tree_selection = self.scans_list.get_selection() tree_selection = self.scans_list.get_selection()
if tree_selection is None: if tree_selection is None:
# I can't find anything in the PyGTK documentation that suggests # I can't find anything in the PyGTK documentation that suggests
# this is possible, but we received many crash reports that indicate # this is possible, but we received many crash reports that
# it is. # indicate it is.
model, selection = None, [] model, selection = None, []
else: else:
model, selection = tree_selection.get_selected_rows() model, selection = tree_selection.get_selected_rows()

View File

@@ -133,7 +133,8 @@ from zenmapGUI.TargetCombo import TargetCombo
class ScanCommandToolbar(HIGHBox): class ScanCommandToolbar(HIGHBox):
"""This class builds the toolbar devoted to Command entry. It allows you to retrieve and edit the current command entered.""" """This class builds the toolbar devoted to Command entry. It allows you to
retrieve and edit the current command entered."""
def __init__(self): def __init__(self):
"""Initialize command toolbar""" """Initialize command toolbar"""
HIGHBox.__init__(self) HIGHBox.__init__(self)
@@ -249,6 +250,6 @@ if __name__ == "__main__":
box.pack_start(stool) box.pack_start(stool)
box.pack_start(sctool) box.pack_start(sctool)
w.connect("delete-event", lambda x,y: gtk.main_quit()) w.connect("delete-event", lambda x, y: gtk.main_quit())
w.show_all() w.show_all()
gtk.main() gtk.main()

View File

@@ -122,6 +122,7 @@
import gtk import gtk
class ScansListStoreEntry(object): class ScansListStoreEntry(object):
"""This class is an abstraction for running and completed scans, which are """This class is an abstraction for running and completed scans, which are
otherwise represented by very different classes.""" otherwise represented by very different classes."""
@@ -134,11 +135,11 @@ class ScansListStoreEntry(object):
self.command = None self.command = None
self.parsed = None self.parsed = None
def set_running(self, command = None): def set_running(self, command=None):
self.state = self.RUNNING self.state = self.RUNNING
self.command = command self.command = command
def set_finished(self, parsed = None): def set_finished(self, parsed=None):
self.state = self.FINISHED self.state = self.FINISHED
self.parsed = parsed self.parsed = parsed
@@ -161,6 +162,7 @@ class ScansListStoreEntry(object):
failed = property(lambda self: self.state == self.FAILED) failed = property(lambda self: self.state == self.FAILED)
canceled = property(lambda self: self.state == self.CANCELED) canceled = property(lambda self: self.state == self.CANCELED)
class ScansListStore(gtk.ListStore): class ScansListStore(gtk.ListStore):
"""This is a specialization of a gtk.ListStore that holds running, """This is a specialization of a gtk.ListStore that holds running,
completed, and failed scans.""" completed, and failed scans."""

View File

@@ -129,7 +129,8 @@ import re
import xml.sax import xml.sax
from zenmapGUI.higwidgets.higwindows import HIGWindow from zenmapGUI.higwidgets.higwindows import HIGWindow
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer, hig_box_space_holder from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer,\
hig_box_space_holder
from zenmapGUI.higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel from zenmapGUI.higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel
from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow
from zenmapGUI.higwidgets.higtextviewers import HIGTextView from zenmapGUI.higwidgets.higtextviewers import HIGTextView
@@ -149,11 +150,12 @@ from zenmapCore.Name import APP_NAME
paths_config = PathsConfig() paths_config = PathsConfig()
def text_buffer_insert_nsedoc(buf, nsedoc): def text_buffer_insert_nsedoc(buf, nsedoc):
"""Inserts NSEDoc at the end of the buffer, with markup turned into proper """Inserts NSEDoc at the end of the buffer, with markup turned into proper
tags.""" tags."""
if not buf.tag_table.lookup("NSEDOC_CODE_TAG"): if not buf.tag_table.lookup("NSEDOC_CODE_TAG"):
buf.create_tag("NSEDOC_CODE_TAG", font = "Monospace") buf.create_tag("NSEDOC_CODE_TAG", font="Monospace")
for event in zenmapCore.NSEDocParser.nsedoc_parse(nsedoc): for event in zenmapCore.NSEDocParser.nsedoc_parse(nsedoc):
if event.type == "paragraph_start": if event.type == "paragraph_start":
buf.insert(buf.get_end_iter(), "\n") buf.insert(buf.get_end_iter(), "\n")
@@ -164,13 +166,15 @@ def text_buffer_insert_nsedoc(buf, nsedoc):
elif event.type == "list_end": elif event.type == "list_end":
pass pass
elif event.type == "list_item_start": elif event.type == "list_item_start":
buf.insert(buf.get_end_iter(), u"\u2022\u00a0") # bullet nbsp buf.insert(buf.get_end_iter(), u"\u2022\u00a0") # bullet nbsp
elif event.type == "list_item_end": elif event.type == "list_item_end":
buf.insert(buf.get_end_iter(), "\n") buf.insert(buf.get_end_iter(), "\n")
elif event.type == "text": elif event.type == "text":
buf.insert(buf.get_end_iter(), event.text) buf.insert(buf.get_end_iter(), event.text)
elif event.type == "code": elif event.type == "code":
buf.insert_with_tags_by_name(buf.get_end_iter(), event.text, "NSEDOC_CODE_TAG") buf.insert_with_tags_by_name(
buf.get_end_iter(), event.text, "NSEDOC_CODE_TAG")
class ScriptHelpXMLContentHandler (xml.sax.handler.ContentHandler): class ScriptHelpXMLContentHandler (xml.sax.handler.ContentHandler):
"""A very simple parser for --script-help XML output. This could extract """A very simple parser for --script-help XML output. This could extract
@@ -183,11 +187,13 @@ class ScriptHelpXMLContentHandler (xml.sax.handler.ContentHandler):
def startElement(self, name, attrs): def startElement(self, name, attrs):
if name == u"directory": if name == u"directory":
if not attrs.has_key(u"name"): if u"name" not in attrs:
raise ValueError(u"\"directory\" element did not have \"name\" attribute") raise ValueError(
u'"directory" element did not have "name" attribute')
dirname = attrs[u"name"] dirname = attrs[u"name"]
if not attrs.has_key(u"path"): if u"path" not in attrs:
raise ValueError(u"\"directory\" element did not have \"path\" attribute") raise ValueError(
u'"directory" element did not have "path" attribute')
path = attrs[u"path"] path = attrs[u"path"]
if dirname == u"scripts": if dirname == u"scripts":
self.scripts_dir = path self.scripts_dir = path
@@ -197,8 +203,9 @@ class ScriptHelpXMLContentHandler (xml.sax.handler.ContentHandler):
# Ignore. # Ignore.
pass pass
elif name == u"script": elif name == u"script":
if not attrs.has_key(u"filename"): if u"filename" not in attrs:
raise ValueError(u"\"script\" element did not have \"filename\" attribute") raise ValueError(
u'"script" element did not have "filename" attribute')
self.script_filenames.append(attrs[u"filename"]) self.script_filenames.append(attrs[u"filename"])
@staticmethod @staticmethod
@@ -209,6 +216,7 @@ class ScriptHelpXMLContentHandler (xml.sax.handler.ContentHandler):
parser.parse(f) parser.parse(f)
return handler return handler
class ScriptInterface: class ScriptInterface:
# Timeout, in milliseconds, after the user stops typing and we update the # Timeout, in milliseconds, after the user stops typing and we update the
# interface from --script. # interface from --script.
@@ -216,9 +224,9 @@ class ScriptInterface:
# Timeout, in milliseconds, between polls of the Nmap subprocess. # Timeout, in milliseconds, between polls of the Nmap subprocess.
NMAP_DELAY = 200 NMAP_DELAY = 200
def __init__(self,root_tabs,ops,update_command,help_buf): def __init__(self, root_tabs, ops, update_command, help_buf):
self.hmainbox = HIGHBox(False,0) self.hmainbox = HIGHBox(False, 0)
self.notscripttab = False # to show profile editor that it is a script tab self.notscripttab = False # show profile editor it is a script tab
self.nmap_process = None self.nmap_process = None
self.script_list_timeout_id = None self.script_list_timeout_id = None
self.nmap_timeout_id = None self.nmap_timeout_id = None
@@ -240,16 +248,16 @@ class ScriptInterface:
# Arg name, arg value, (name, desc) tuple. # Arg name, arg value, (name, desc) tuple.
self.arg_liststore = gtk.ListStore(str, str, object) self.arg_liststore = gtk.ListStore(str, str, object)
# This is what is shown initially. After the initial Nmap run to get the # This is what is shown initially. After the initial Nmap run to get
# list of script is finished, this will be replaced with a TreeView # the list of script is finished, this will be replaced with a TreeView
# showing the scripts or an error message. # showing the scripts or an error message.
self.script_list_container = gtk.VBox() self.script_list_container = gtk.VBox()
self.script_list_container.pack_start(self.make_please_wait_widget()) self.script_list_container.pack_start(self.make_please_wait_widget())
self.hmainbox.pack_start(self.script_list_container, False, False, 0) self.hmainbox.pack_start(self.script_list_container, False, False, 0)
self.nmap_error_widget = gtk.Label(_("""\ self.nmap_error_widget = gtk.Label(_(
There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\ "There was an error getting the list of scripts from Nmap. "
""")) "Try upgrading Nmap."))
self.nmap_error_widget.set_line_wrap(True) self.nmap_error_widget.set_line_wrap(True)
self.nmap_error_widget.show_all() self.nmap_error_widget.show_all()
@@ -269,8 +277,8 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
def get_script_list(self, rules, callback): def get_script_list(self, rules, callback):
"""Start an Nmap subprocess in the background with """Start an Nmap subprocess in the background with
"--script-help=<rules> -oX -", and set it up to call the given callback when "--script-help=<rules> -oX -", and set it up to call the given callback
finished.""" when finished."""
ops = NmapOptions() ops = NmapOptions()
ops.executable = paths_config.nmap_command_path ops.executable = paths_config.nmap_command_path
@@ -279,11 +287,12 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
command_string = ops.render_string() command_string = ops.render_string()
# Separate stderr to avoid breaking XML parsing with "Warning: File # Separate stderr to avoid breaking XML parsing with "Warning: File
# ./nse_main.lua exists, but Nmap is using...". # ./nse_main.lua exists, but Nmap is using...".
stderr = tempfile.TemporaryFile(mode = "rb", prefix = APP_NAME + "-script-help-stderr-") stderr = tempfile.TemporaryFile(
mode="rb", prefix=APP_NAME + "-script-help-stderr-")
log.debug("Script interface: running %s" % repr(command_string)) log.debug("Script interface: running %s" % repr(command_string))
nmap_process = NmapCommand(command_string) nmap_process = NmapCommand(command_string)
try: try:
nmap_process.run_scan(stderr = stderr) nmap_process.run_scan(stderr=stderr)
except Exception, e: except Exception, e:
callback(False, None) callback(False, None)
stderr.close() stderr.close()
@@ -292,14 +301,17 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
self.script_list_widget.set_sensitive(False) self.script_list_widget.set_sensitive(False)
gobject.timeout_add(self.NMAP_DELAY, self.script_list_timer_callback, nmap_process, callback) gobject.timeout_add(
self.NMAP_DELAY, self.script_list_timer_callback,
nmap_process, callback)
def script_list_timer_callback(self, process, callback): def script_list_timer_callback(self, process, callback):
try: try:
status = process.scan_state() status = process.scan_state()
except: except:
status = None status = None
log.debug("Script interface: script_list_timer_callback %s" % repr(status)) log.debug("Script interface: script_list_timer_callback %s" % \
repr(status))
if status == True: if status == True:
# Still running, schedule this timer to check again. # Still running, schedule this timer to check again.
@@ -326,7 +338,8 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
def handle_initial_script_list_output(self, process): def handle_initial_script_list_output(self, process):
process.stdout_file.seek(0) process.stdout_file.seek(0)
try: try:
handler = ScriptHelpXMLContentHandler.parse_nmap_script_help(process.stdout_file) handler = ScriptHelpXMLContentHandler.parse_nmap_script_help(
process.stdout_file)
except (ValueError, xml.sax.SAXParseException), e: except (ValueError, xml.sax.SAXParseException), e:
log.debug("--script-help parse exception: %s" % str(e)) log.debug("--script-help parse exception: %s" % str(e))
return False return False
@@ -342,12 +355,14 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
log.debug("--script-help error: no nselib directory") log.debug("--script-help error: no nselib directory")
return False return False
log.debug("Script interface: scripts dir %s" % repr(handler.scripts_dir)) log.debug("Script interface: scripts dir %s" % repr(
log.debug("Script interface: nselib dir %s" % repr(handler.nselib_dir)) handler.scripts_dir))
log.debug("Script interface: nselib dir %s" % repr(handler.nselib_dir))
# Make a dict of script metadata entries. # Make a dict of script metadata entries.
entries = {} entries = {}
for entry in get_script_entries(handler.scripts_dir, handler.nselib_dir): for entry in get_script_entries(
handler.scripts_dir, handler.nselib_dir):
entries[entry.filename] = entry entries[entry.filename] = entry
self.liststore.clear() self.liststore.clear()
@@ -367,7 +382,8 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
def update_script_list_from_spec(self, spec): def update_script_list_from_spec(self, spec):
"""Callback method for user edit delay.""" """Callback method for user edit delay."""
log.debug("Script interface: update_script_list_from_spec %s" % repr(spec)) log.debug("Script interface: update_script_list_from_spec %s" % repr(
spec))
if spec: if spec:
self.get_script_list(spec, self.update_script_list_cb) self.get_script_list(spec, self.update_script_list_cb)
else: else:
@@ -383,7 +399,8 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
def handle_update_script_list_output(self, process): def handle_update_script_list_output(self, process):
process.stdout_file.seek(0) process.stdout_file.seek(0)
try: try:
handler = ScriptHelpXMLContentHandler.parse_nmap_script_help(process.stdout_file) handler = ScriptHelpXMLContentHandler.parse_nmap_script_help(
process.stdout_file)
except (ValueError, xml.sax.SAXParseException), e: except (ValueError, xml.sax.SAXParseException), e:
log.debug("--script-help parse exception: %s" % str(e)) log.debug("--script-help parse exception: %s" % str(e))
return False return False
@@ -422,29 +439,41 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
character.""" character."""
if self.script_list_timeout_id: if self.script_list_timeout_id:
gobject.source_remove(self.script_list_timeout_id) gobject.source_remove(self.script_list_timeout_id)
self.script_list_timeout_id = gobject.timeout_add(self.SCRIPT_LIST_DELAY, self.update_script_list_from_spec, spec) self.script_list_timeout_id = gobject.timeout_add(
self.SCRIPT_LIST_DELAY,
self.update_script_list_from_spec, spec)
def parse_script_args(self, raw_argument):
def parse_script_args(self,raw_argument):
"""When the command line is edited, this function is called to update """When the command line is edited, this function is called to update
the script arguments display according to the value of --script-args.""" the script arguments display according to the value of
--script-args."""
arg_dict = parse_script_args_dict(raw_argument) arg_dict = parse_script_args_dict(raw_argument)
if arg_dict is None: # if there is parsing error args_dict holds none if arg_dict is None: # if there is parsing error args_dict holds none
self.arg_values.clear() self.arg_values.clear()
else: else:
for key in arg_dict.keys(): for key in arg_dict.keys():
self.arg_values[key] = arg_dict[key] self.arg_values[key] = arg_dict[key]
def update_argument_values(self,raw_argument): def update_argument_values(self, raw_argument):
"""When scripting tab starts up, argument values are updated.""" """When scripting tab starts up, argument values are updated."""
if raw_argument is not None: if raw_argument is not None:
self.parse_script_args(raw_argument) self.parse_script_args(raw_argument)
def set_help_texts(self): def set_help_texts(self):
"""Sets the help texts to be displayed.""" """Sets the help texts to be displayed."""
self.list_scripts_help = _("List of scripts\n\nA list of all installed scripts. Activate or deactivate a script by clicking the box next to the script name.") self.list_scripts_help = _("""List of scripts
self.description_help = _("Description\n\nThis box shows the categories a script belongs to. In addition, it gives a detailed description of the script which is present in script. A URL points to online NSEDoc documentation.")
self.argument_help = _("Arguments\n\nA list of arguments that affect the selected script. Enter a value by clicking in the value field beside the argument name.") A list of all installed scripts. Activate or deactivate a script \
by clicking the box next to the script name.""")
self.description_help = _("""Description
This box shows the categories a script belongs to. In addition, it gives a \
detailed description of the script which is present in script. A URL points \
to online NSEDoc documentation.""")
self.argument_help = _("""Arguments
A list of arguments that affect the selected script. Enter a value by \
clicking in the value field beside the argument name.""")
def make_please_wait_widget(self): def make_please_wait_widget(self):
vbox = gtk.VBox() vbox = gtk.VBox()
@@ -454,7 +483,8 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
return vbox return vbox
def make_script_list_widget(self): def make_script_list_widget(self):
"""Creates and packs widgets associated with left hand side of Interface.""" """Creates and packs widgets associated with left hand side of
Interface."""
vbox = gtk.VBox() vbox = gtk.VBox()
scrolled_window = HIGScrolledWindow() scrolled_window = HIGScrolledWindow()
@@ -485,7 +515,8 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
vbox.pack_start(scrolled_window, True, True, 0) vbox.pack_start(scrolled_window, True, True, 0)
self.file_scrolled_window = HIGScrolledWindow() self.file_scrolled_window = HIGScrolledWindow()
self.file_scrolled_window.set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS) self.file_scrolled_window.set_policy(
gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)
self.file_scrolled_window.set_size_request(175, -1) self.file_scrolled_window.set_size_request(175, -1)
self.file_scrolled_window.hide() self.file_scrolled_window.hide()
self.file_scrolled_window.set_no_show_all(True) self.file_scrolled_window.set_no_show_all(True)
@@ -511,11 +542,12 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
vbox.pack_start(self.file_scrolled_window, False) vbox.pack_start(self.file_scrolled_window, False)
hbox = HIGHBox(False, 2) hbox = HIGHBox(False, 2)
self.remove_file_button = HIGButton(stock = gtk.STOCK_REMOVE) self.remove_file_button = HIGButton(stock=gtk.STOCK_REMOVE)
self.remove_file_button.connect("clicked", self.remove_file_button_clicked_cb) self.remove_file_button.connect(
"clicked", self.remove_file_button_clicked_cb)
self.remove_file_button.set_sensitive(False) self.remove_file_button.set_sensitive(False)
hbox.pack_end(self.remove_file_button) hbox.pack_end(self.remove_file_button)
add_file_button = HIGButton(stock = gtk.STOCK_ADD) add_file_button = HIGButton(stock=gtk.STOCK_ADD)
add_file_button.connect("clicked", self.add_file_button_clicked_cb) add_file_button.connect("clicked", self.add_file_button_clicked_cb)
hbox.pack_end(add_file_button) hbox.pack_end(add_file_button)
@@ -542,7 +574,7 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
else: else:
self.file_liststore.append([filename, True]) self.file_liststore.append([filename, True])
def strip_file_name(self,filename): def strip_file_name(self, filename):
"""Removes a ".nse" extension from filename if present.""" """Removes a ".nse" extension from filename if present."""
if(filename.endswith(".nse")): if(filename.endswith(".nse")):
return filename[:-4] return filename[:-4]
@@ -579,8 +611,8 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
text_view = gtk.TextView() text_view = gtk.TextView()
text_view.connect("enter-notify-event", self.update_help_desc_cb) text_view.connect("enter-notify-event", self.update_help_desc_cb)
self.text_buffer = text_view.get_buffer() self.text_buffer = text_view.get_buffer()
self.text_buffer.create_tag("Usage", font = "Monospace") self.text_buffer.create_tag("Usage", font="Monospace")
self.text_buffer.create_tag("Output", font = "Monospace") self.text_buffer.create_tag("Output", font="Monospace")
text_view.set_wrap_mode(gtk.WRAP_WORD) text_view.set_wrap_mode(gtk.WRAP_WORD)
text_view.set_editable(False) text_view.set_editable(False)
text_view.set_justification(gtk.JUSTIFY_LEFT) text_view.set_justification(gtk.JUSTIFY_LEFT)
@@ -606,7 +638,7 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
arg_listview.append_column(val_col) arg_listview.append_column(val_col)
arg_col.pack_start(argument, True) arg_col.pack_start(argument, True)
arg_col.add_attribute(argument, "text", 0) arg_col.add_attribute(argument, "text", 0)
val_col.pack_start(self.value,True) val_col.pack_start(self.value, True)
val_col.add_attribute(self.value, "text", 1) val_col.add_attribute(self.value, "text", 1)
arg_window.add(arg_listview) arg_window.add(arg_listview)
@@ -614,7 +646,7 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
return vbox return vbox
def value_edited_cb(self,cell,path,new_text,model): def value_edited_cb(self, cell, path, new_text, model):
"""Called when the argument cell is edited.""" """Called when the argument cell is edited."""
self.arg_list = [] self.arg_list = []
model[path][1] = new_text model[path][1] = new_text
@@ -637,21 +669,22 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
self.ops["--script-args"] = ",".join(self.arg_list) self.ops["--script-args"] = ",".join(self.arg_list)
self.update_command() self.update_command()
def selection_changed_cb(self,selection): def selection_changed_cb(self, selection):
"""Called back when the list of scripts is selected.""" """Called back when the list of scripts is selected."""
model, selection = selection.get_selected_rows() model, selection = selection.get_selected_rows()
for path in selection: for path in selection:
check_value = model.get_value(model.get_iter(path),1) check_value = model.get_value(model.get_iter(path), 1)
entry = model.get_value(model.get_iter(path),2) entry = model.get_value(model.get_iter(path), 2)
self.set_description(entry) self.set_description(entry)
self.populate_arg_list(entry) self.populate_arg_list(entry)
self.focussedentry = entry #Remember the currently pointing script entry # Remember the currently pointing script entry
self.focussedentry = entry
def update_help_ls_cb(self,widget,extra): # list of scripts def update_help_ls_cb(self, widget, extra): # list of scripts
"""Callback method to display the help for the list of scripts.""" """Callback method to display the help for the list of scripts."""
self.help_buf.set_text(self.list_scripts_help) self.help_buf.set_text(self.list_scripts_help)
def update_help_desc_cb(self,widget,extra): def update_help_desc_cb(self, widget, extra):
"""Callback method for displaying description.""" """Callback method for displaying description."""
self.help_buf.set_text(self.description_help) self.help_buf.set_text(self.description_help)
@@ -672,14 +705,17 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
arg_name, arg_desc = model.get_value(model.get_iter(path), 2) arg_name, arg_desc = model.get_value(model.get_iter(path), 2)
if arg_desc is not None: if arg_desc is not None:
self.help_buf.set_text("") self.help_buf.set_text("")
self.help_buf.insert(self.help_buf.get_end_iter(), text = "%s\n" % arg_name) self.help_buf.insert(
self.help_buf.get_end_iter(), text="%s\n" % arg_name)
text_buffer_insert_nsedoc(self.help_buf, arg_desc) text_buffer_insert_nsedoc(self.help_buf, arg_desc)
else: else:
self.help_buf.set_text("") self.help_buf.set_text("")
def add_file_button_clicked_cb(self, button): def add_file_button_clicked_cb(self, button):
if self.script_file_chooser is None: if self.script_file_chooser is None:
self.script_file_chooser = zenmapGUI.FileChoosers.ScriptFileChooserDialog(title = _("Select script files")) self.script_file_chooser = \
zenmapGUI.FileChoosers.ScriptFileChooserDialog(
title=_("Select script files"))
response = self.script_file_chooser.run() response = self.script_file_chooser.run()
filenames = self.script_file_chooser.get_filenames() filenames = self.script_file_chooser.get_filenames()
self.script_file_chooser.hide() self.script_file_chooser.hide()
@@ -702,7 +738,7 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
self.remove_file_button.set_sensitive(False) self.remove_file_button.set_sensitive(False)
self.set_script_from_selection() self.set_script_from_selection()
def set_description(self,entry): def set_description(self, entry):
"""Sets the content that is to be displayed in the description box.""" """Sets the content that is to be displayed in the description box."""
self.text_buffer.set_text(u"") self.text_buffer.set_text(u"")
@@ -711,20 +747,25 @@ Categories: %(cats)s
""" % {"cats": ", ".join(entry.categories)}) """ % {"cats": ", ".join(entry.categories)})
text_buffer_insert_nsedoc(self.text_buffer, entry.description) text_buffer_insert_nsedoc(self.text_buffer, entry.description)
if entry.usage: if entry.usage:
self.text_buffer.insert(self.text_buffer.get_end_iter(), "\nUsage\n") self.text_buffer.insert(
self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(), entry.usage, "Usage") self.text_buffer.get_end_iter(), "\nUsage\n")
self.text_buffer.insert_with_tags_by_name(
self.text_buffer.get_end_iter(), entry.usage, "Usage")
if entry.output: if entry.output:
self.text_buffer.insert(self.text_buffer.get_end_iter(), "\nOutput\n") self.text_buffer.insert(
self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(), entry.output, "Output") self.text_buffer.get_end_iter(), "\nOutput\n")
self.text_buffer.insert_with_tags_by_name(
self.text_buffer.get_end_iter(), entry.output, "Output")
if entry.url: if entry.url:
self.text_buffer.insert(self.text_buffer.get_end_iter(), "\n" + entry.url) self.text_buffer.insert(
self.text_buffer.get_end_iter(), "\n" + entry.url)
def populate_arg_list(self,entry): def populate_arg_list(self, entry):
"""Called when a particular script is hovered over to display its """Called when a particular script is hovered over to display its
arguments and values (if any).""" arguments and values (if any)."""
self.arg_liststore.clear() self.arg_liststore.clear()
self.current_arguments = [] self.current_arguments = []
self.value.set_property('editable',True) self.value.set_property('editable', True)
for arg in entry.arguments: for arg in entry.arguments:
arg_name, arg_desc = arg arg_name, arg_desc = arg
self.current_arguments.append(arg) self.current_arguments.append(arg)

View File

@@ -128,8 +128,10 @@ import copy
from zenmapGUI.higwidgets.higwindows import HIGWindow from zenmapGUI.higwidgets.higwindows import HIGWindow
from zenmapGUI.higwidgets.higboxes import HIGVBox from zenmapGUI.higwidgets.higboxes import HIGVBox
from zenmapGUI.higwidgets.higbuttons import HIGButton, HIGToggleButton from zenmapGUI.higwidgets.higbuttons import HIGButton, HIGToggleButton
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer, hig_box_space_holder from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer,\
from zenmapGUI.higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel, HintWindow hig_box_space_holder
from zenmapGUI.higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel,\
HintWindow
from zenmapGUI.higwidgets.higtables import HIGTable from zenmapGUI.higwidgets.higtables import HIGTable
from zenmapGUI.higwidgets.higdialogs import HIGAlertDialog from zenmapGUI.higwidgets.higdialogs import HIGAlertDialog
@@ -161,14 +163,16 @@ class SearchParser(object):
self.search_gui = search_gui self.search_gui = search_gui
self.search_dict = search_gui.search_dict self.search_dict = search_gui.search_dict
# We need to make an operator->searchkey mapping, since the search entry # We need to make an operator->searchkey mapping, since the search
# field and the search classes have different syntax. # entry field and the search classes have different syntax.
# #
# NOTE: if you want to add a new search key not handled by the SearchResult # NOTE: if you want to add a new search key not handled by the
# class, you should add a new method match_CRITERIANAME to the SearchResult class. # SearchResult class, you should add a new method match_CRITERIANAME to
# For example, if you'd like a "noodles" criteria, you need to create the method # the SearchResult class. For example, if you'd like a "noodles"
# SearchResult.match_noodles(self, noodles_string). To see how searches are # criteria, you need to create the method
# actually performed, start reading from the SearchResult.search() method. # SearchResult.match_noodles(self, noodles_string). To see how searches
# are actually performed, start reading from the SearchResult.search()
# method.
self.ops2keys = copy.deepcopy(search_keywords) self.ops2keys = copy.deepcopy(search_keywords)
# This is not really an operator (see below) # This is not really an operator (see below)
@@ -198,16 +202,18 @@ class SearchParser(object):
else: else:
self.search_dict["keyword"] = [word] self.search_dict["keyword"] = [word]
# Check if we have any dir: operators in our map, and if so, add them to the # Check if we have any dir: operators in our map, and if so, add them
# search_gui object and remove them from the map. The dir: operator isn't a real # to the search_gui object and remove them from the map. The dir:
# operator, in a sense that it doesn't need to be processed by the # operator isn't a real operator, in a sense that it doesn't need to be
# SearchResult.search() function. It is needed only to create a new SearchDir # processed by the SearchResult.search() function. It is needed only to
# object, which is then used to perform the actual search(). # create a new SearchDir object, which is then used to perform the
# actual search().
if "dir" in self.search_dict: if "dir" in self.search_dict:
self.search_gui.init_search_dirs(self.search_dict["dir"]) self.search_gui.init_search_dirs(self.search_dict["dir"])
else: else:
self.search_gui.init_search_dirs([]) self.search_gui.init_search_dirs([])
class SearchGUI(gtk.VBox, object): class SearchGUI(gtk.VBox, object):
"""This class is a VBox that holds the search entry field and buttons on """This class is a VBox that holds the search entry field and buttons on
top, and the results list on the bottom. The "Cancel" and "Open" buttons top, and the results list on the bottom. The "Cancel" and "Open" buttons
@@ -230,25 +236,28 @@ class SearchGUI(gtk.VBox, object):
self.id = 0 self.id = 0
self.search_window = search_window self.search_window = search_window
# The Search* objects are created once per Search Window invocation, so that # The Search* objects are created once per Search Window invocation, so
# they get a list of scans only once, not whenever the search conditions change # that they get a list of scans only once, not whenever the search
# conditions change
if self.options["search_db"]: if self.options["search_db"]:
try: try:
self.search_db = SearchDB() self.search_db = SearchDB()
except ImportError, e: except ImportError, e:
self.search_db = SearchDummy() self.search_db = SearchDummy()
self.no_db_warning.show() self.no_db_warning.show()
self.no_db_warning.set_text("""\ self.no_db_warning.set_text(
Warning: The database of saved scans is not available. (%s.) Use \ 'Warning: The database of saved scans is not '
"Include Directory" under "Expressions" to search a directory.\ 'available. (%s.) Use "Include Directory" under '
""" % str(e)) '"Expressions" to search a directory.' % str(e))
# Search directories can be added via the "dir:" operator, so it needs to be a map # Search directories can be added via the "dir:" operator, so it needs
# to be a map
self.search_dirs = {} self.search_dirs = {}
self.init_search_dirs() self.init_search_dirs()
# We create an empty search dictionary, since SearchParser will fill it # We create an empty search dictionary, since SearchParser will fill it
# with keywords as it encounters different operators in the search string. # with keywords as it encounters different operators in the search
# string.
self.search_dict = dict() self.search_dict = dict()
# We need to define our own keyword search dictionary # We need to define our own keyword search dictionary
search_keywords = dict() search_keywords = dict()
@@ -286,42 +295,48 @@ Warning: The database of saved scans is not available. (%s.) Use \
search_keywords["ir"] = "in_route" search_keywords["ir"] = "in_route"
self.search_parser = SearchParser(self, search_keywords) self.search_parser = SearchParser(self, search_keywords)
# This list holds the (operator, argument) tuples, parsed from the GUI criteria rows # This list holds the (operator, argument) tuples, parsed from the GUI
# criteria rows
self.gui_criteria_list = [] self.gui_criteria_list = []
# Do an initial "empty" search, so that the results window initially holds # Do an initial "empty" search, so that the results window initially
# all scans in the database # holds all scans in the database
self.search_parser.update("") self.search_parser.update("")
self.start_search() self.start_search()
def init_search_dirs(self, dirs = []): def init_search_dirs(self, dirs=[]):
# Start fresh # Start fresh
self.search_dirs.clear() self.search_dirs.clear()
# If specified, add the search directory from the Zenmap config file to the map # If specified, add the search directory from the Zenmap config file to
# the map
conf_dir = self.options["directory"] conf_dir = self.options["directory"]
if conf_dir: if conf_dir:
self.search_dirs[conf_dir] = SearchDir(conf_dir, self.options["file_extension"]) self.search_dirs[conf_dir] = SearchDir(
conf_dir, self.options["file_extension"])
# Process any other dirs (as added by the dir: operator) # Process any other dirs (as added by the dir: operator)
for dir in dirs: for dir in dirs:
self.search_dirs[dir] = SearchDir(dir, self.options["file_extension"]) self.search_dirs[dir] = SearchDir(
dir, self.options["file_extension"])
def _create_widgets(self): def _create_widgets(self):
# Search box and buttons # Search box and buttons
self.search_top_hbox = HIGHBox() self.search_top_hbox = HIGHBox()
self.search_label = HIGSectionLabel(_("Search:")) self.search_label = HIGSectionLabel(_("Search:"))
self.search_entry = gtk.Entry() self.search_entry = gtk.Entry()
self.expressions_btn = HIGToggleButton(_("Expressions "), gtk.STOCK_EDIT) self.expressions_btn = HIGToggleButton(
_("Expressions "), gtk.STOCK_EDIT)
# The quick reference tooltip button # The quick reference tooltip button
self.search_tooltip_btn = HIGButton(" ", gtk.STOCK_INFO) self.search_tooltip_btn = HIGButton(" ", gtk.STOCK_INFO)
# The expression VBox. This is only visible once the user clicks on "Expressions" # The expression VBox. This is only visible once the user clicks on
# "Expressions"
self.expr_vbox = gtk.VBox() self.expr_vbox = gtk.VBox()
# Results section # Results section
self.result_list = gtk.ListStore(str, str, int) # title, date, id self.result_list = gtk.ListStore(str, str, int) # title, date, id
self.result_view = gtk.TreeView(self.result_list) self.result_view = gtk.TreeView(self.result_list)
self.result_scrolled = gtk.ScrolledWindow() self.result_scrolled = gtk.ScrolledWindow()
self.result_title_column = gtk.TreeViewColumn(_("Scan")) self.result_title_column = gtk.TreeViewColumn(_("Scan"))
@@ -341,13 +356,14 @@ Warning: The database of saved scans is not available. (%s.) Use \
self.search_top_hbox.pack_start(self.expressions_btn, False) self.search_top_hbox.pack_start(self.expressions_btn, False)
self.search_top_hbox.pack_start(self.search_tooltip_btn, False) self.search_top_hbox.pack_start(self.search_tooltip_btn, False)
# The expressions (if any) should be tightly packed so that they don't take # The expressions (if any) should be tightly packed so that they don't
# too much screen real-estate # take too much screen real-estate
self.expr_vbox.set_spacing(0) self.expr_vbox.set_spacing(0)
# Packing the result section # Packing the result section
self.result_scrolled.add(self.result_view) self.result_scrolled.add(self.result_view)
self.result_scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.result_scrolled.set_policy(
gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
# Packing it all together # Packing it all together
self.set_spacing(4) self.set_spacing(4)
@@ -366,21 +382,24 @@ Warning: The database of saved scans is not available. (%s.) Use \
hint_window.show_all() hint_window.show_all()
def expressions_clicked(self, widget=None, extra=None): def expressions_clicked(self, widget=None, extra=None):
if len(self.expr_vbox.get_children()) == 0 and self.search_entry.get_text() == "": if (len(self.expr_vbox.get_children()) == 0 and
self.search_entry.get_text() == ""):
# This is the first time the user has clicked on "Show Expressions" # This is the first time the user has clicked on "Show Expressions"
# and the search entry box is empty, so we add a single Criterion row # and the search entry box is empty, so we add a single Criterion
# row
self.expr_vbox.pack_start(Criterion(self)) self.expr_vbox.pack_start(Criterion(self))
if self.expressions_btn.get_active(): if self.expressions_btn.get_active():
# The Expressions GUI is about to be displayed. It needs to reflect all the # The Expressions GUI is about to be displayed. It needs to reflect
# conditions in the search entry field, so a comparison between the entry field # all the conditions in the search entry field, so a comparison
# and the GUI needs to be performed. # between the entry field and the GUI needs to be performed.
# Make the search entry field insensitive while expressions are visible # Make the search entry field insensitive while expressions are
# visible
self.search_entry.set_sensitive(False) self.search_entry.set_sensitive(False)
# Get a map of operator => argument from the Expressions GUI so that # Get a map of operator => argument from the Expressions GUI so
# we can compare them with the ones in the search entry field # that we can compare them with the ones in the search entry field
gui_ops = {} gui_ops = {}
for criterion in self.expr_vbox.get_children(): for criterion in self.expr_vbox.get_children():
if criterion.operator in gui_ops: if criterion.operator in gui_ops:
@@ -389,19 +408,22 @@ Warning: The database of saved scans is not available. (%s.) Use \
gui_ops[criterion.operator] = [criterion.argument] gui_ops[criterion.operator] = [criterion.argument]
# We compare the search entry field to the Expressions GUI. Every # We compare the search entry field to the Expressions GUI. Every
# (operator, value) pair must be present in the GUI after this loop is done. # (operator, value) pair must be present in the GUI after this loop
# is done.
for op, args in self.search_dict.iteritems(): for op, args in self.search_dict.iteritems():
for arg in args: for arg in args:
if (op not in gui_ops) or (arg not in gui_ops[op]): if (op not in gui_ops) or (arg not in gui_ops[op]):
# We need to add this pair to the GUI # We need to add this pair to the GUI
self.expr_vbox.pack_start(Criterion(self, op, arg), False) self.expr_vbox.pack_start(
Criterion(self, op, arg), False)
# Now we check if there are any leftover criterion rows that aren't present # Now we check if there are any leftover criterion rows that aren't
# in the search_dict (for example, if a user has deleted something from the # present in the search_dict (for example, if a user has deleted
# search entry field) # something from the search entry field)
for criterion in self.expr_vbox.get_children(): for criterion in self.expr_vbox.get_children():
if criterion.operator not in self.search_dict or \ if (criterion.operator not in self.search_dict or
criterion.argument not in self.search_dict[criterion.operator]: criterion.argument not in self.search_dict[
criterion.operator]):
criterion.destroy() criterion.destroy()
# If we have deleted all rows, add an empty one # If we have deleted all rows, add an empty one
if len(self.expr_vbox.get_children()) == 0: if len(self.expr_vbox.get_children()) == 0:
@@ -410,8 +432,9 @@ Warning: The database of saved scans is not available. (%s.) Use \
# Display all elements # Display all elements
self.expr_vbox.show_all() self.expr_vbox.show_all()
else: else:
# The Expressions GUI is about to be hidden. No updates to the search entry field # The Expressions GUI is about to be hidden. No updates to the
# are necessary, since it gets updated on every change in one of the criterion rows. # search entry field are necessary, since it gets updated on every
# change in one of the criterion rows.
self.expr_vbox.hide_all() self.expr_vbox.hide_all()
self.search_entry.set_sensitive(True) self.search_entry.set_sensitive(True)
@@ -450,7 +473,8 @@ Warning: The database of saved scans is not available. (%s.) Use \
def add_search_dir(self, dir): def add_search_dir(self, dir):
if dir not in self.search_dirs: if dir not in self.search_dirs:
self.search_dirs[dir] = SearchDir(dir, self.options["file_extension"]) self.search_dirs[dir] = SearchDir(
dir, self.options["file_extension"])
def update_search_entry(self, widget, extra=None): def update_search_entry(self, widget, extra=None):
"""Called when the search entry field is modified.""" """Called when the search entry field is modified."""
@@ -459,10 +483,14 @@ Warning: The database of saved scans is not available. (%s.) Use \
def start_search(self): def start_search(self):
if not self.options["search_db"] and not self.options["directory"]: if not self.options["search_db"] and not self.options["directory"]:
d = HIGAlertDialog(message_format=_("No search method selected!"), d = HIGAlertDialog(
secondary_text=_("%s can search results on directories or \ message_format=_("No search method selected!"),
inside it's own database. Please, select a method by choosing a directory or by checking \ secondary_text=_(
the search data base option at the 'Search options' tab before start the search") % APP_DISPLAY_NAME) "%s can search results on directories or inside its "
"own database. Please select a method by choosing a "
"directory or by checking the search data base option "
"in the 'Search options' tab before starting a search"
) % APP_DISPLAY_NAME)
d.run() d.run()
d.destroy() d.destroy()
return return
@@ -488,8 +516,9 @@ the search data base option at the 'Search options' tab before start the search"
# self.append_result(result) # self.append_result(result)
# matched += 1 # matched += 1
self.search_window.set_label_text("Matched <b>%s</b> out of <b>%s</b> scans." % \ self.search_window.set_label_text(
(str(matched), str(total))) "Matched <b>%s</b> out of <b>%s</b> scans." % (
str(matched), str(total)))
def clear_result_list(self): def clear_result_list(self):
for i in range(len(self.result_list)): for i in range(len(self.result_list)):
@@ -505,7 +534,6 @@ the search data base option at the 'Search options' tab before start the search"
except ValueError: except ValueError:
date_field = _("Unknown") date_field = _("Unknown")
self.parsed_results[self.id] = [title, parsed_result] self.parsed_results[self.id] = [title, parsed_result]
self.result_list.append([title, date_field, self.id]) self.result_list.append([title, date_field, self.id])
self.id += 1 self.id += 1
@@ -554,11 +582,11 @@ the search data base option at the 'Search options' tab before start the search"
class Criterion(gtk.HBox): class Criterion(gtk.HBox):
"""This class holds one criterion row, represented as an HBox. """This class holds one criterion row, represented as an HBox. It holds a
It holds a ComboBox and a Subcriterion's subclass instance, depending on the ComboBox and a Subcriterion's subclass instance, depending on the selected
selected entry in the ComboBox. For example, when the 'Target' option is entry in the ComboBox. For example, when the 'Target' option is selected, a
selected, a SimpleSubcriterion widget is displayed, but when the 'Date' SimpleSubcriterion widget is displayed, but when the 'Date' operator is
operator is selected, a DateSubcriterion widget is displayed.""" selected, a DateSubcriterion widget is displayed."""
def __init__(self, search_window, operator="keyword", argument=""): def __init__(self, search_window, operator="keyword", argument=""):
"""A reference to the search window is passed so that we can call """A reference to the search window is passed so that we can call
@@ -571,17 +599,18 @@ class Criterion(gtk.HBox):
# We need this as a map, so that we can pass the operator into # We need this as a map, so that we can pass the operator into
# the SimpleSubcriterion instance # the SimpleSubcriterion instance
self.combo_entries = {"Keyword" : ["keyword"], self.combo_entries = {"Keyword": ["keyword"],
"Profile Name" : ["profile"], "Profile Name": ["profile"],
"Target" : ["target"], "Target": ["target"],
"Options" : ["option"], "Options": ["option"],
"Date" : ["date", "after", "before"], "Date": ["date", "after", "before"],
"Operating System" : ["os"], "Operating System": ["os"],
"Port" : ["open", "scanned", "closed", "filtered", "Port": ["open", "scanned", "closed", "filtered",
"unfiltered", "open_filtered", "closed_filtered"], "unfiltered", "open_filtered",
"Service" : ["service"], "closed_filtered"],
"Host In Route" : ["inroute"], "Service": ["service"],
"Include Directory" : ["dir"]} "Host In Route": ["inroute"],
"Include Directory": ["dir"]}
self._create_widgets() self._create_widgets()
self._pack_widgets() self._pack_widgets()
@@ -591,7 +620,8 @@ class Criterion(gtk.HBox):
# A ComboBox containing the list of operators # A ComboBox containing the list of operators
self.operator_combo = gtk.combo_box_new_text() self.operator_combo = gtk.combo_box_new_text()
# Sort all the keys from combo_entries and make an entry for each of them # Sort all the keys from combo_entries and make an entry for each of
# them
sorted_entries = self.combo_entries.keys() sorted_entries = self.combo_entries.keys()
sorted_entries.sort() sorted_entries.sort()
for name in sorted_entries: for name in sorted_entries:
@@ -605,7 +635,8 @@ class Criterion(gtk.HBox):
break break
# Create a subcriterion # Create a subcriterion
self.subcriterion = self.new_subcriterion(self.default_operator, self.default_argument) self.subcriterion = self.new_subcriterion(
self.default_operator, self.default_argument)
# The "add" and "remove" buttons # The "add" and "remove" buttons
self.add_btn = HIGButton(" ", gtk.STOCK_ADD) self.add_btn = HIGButton(" ", gtk.STOCK_ADD)
@@ -674,6 +705,7 @@ class Criterion(gtk.HBox):
operator = property(get_operator) operator = property(get_operator)
argument = property(get_argument) argument = property(get_argument)
class Subcriterion(gtk.HBox): class Subcriterion(gtk.HBox):
"""This class is a base class for all subcriterion types. Depending on the """This class is a base class for all subcriterion types. Depending on the
criterion selected in the Criterion's ComboBox, a subclass of Subcriterion criterion selected in the Criterion's ComboBox, a subclass of Subcriterion
@@ -685,9 +717,11 @@ class Subcriterion(gtk.HBox):
self.argument = "" self.argument = ""
def value_changed(self): def value_changed(self):
"""Propagates the operator and the argument up to the Criterion parent.""" """Propagates the operator and the argument up to the Criterion
parent."""
self.get_parent().value_changed(self.operator, self.argument) self.get_parent().value_changed(self.operator, self.argument)
class SimpleSubcriterion(Subcriterion): class SimpleSubcriterion(Subcriterion):
"""This class represents all 'simple' criterion types that need only an """This class represents all 'simple' criterion types that need only an
entry box in order to define the criterion.""" entry box in order to define the criterion."""
@@ -716,6 +750,7 @@ class SimpleSubcriterion(Subcriterion):
self.argument = widget.get_text() self.argument = widget.get_text()
self.value_changed() self.value_changed()
class PortSubcriterion(Subcriterion): class PortSubcriterion(Subcriterion):
"""This class shows the port criterion GUI.""" """This class shows the port criterion GUI."""
def __init__(self, operator="open", argument=""): def __init__(self, operator="open", argument=""):
@@ -736,11 +771,12 @@ class PortSubcriterion(Subcriterion):
self.label = gtk.Label(" is ") self.label = gtk.Label(" is ")
self.port_state_combo = gtk.combo_box_new_text() self.port_state_combo = gtk.combo_box_new_text()
states = ["open", "scanned", "closed", "filtered", "unfiltered", "open|filtered", states = ["open", "scanned", "closed", "filtered", "unfiltered",
"closed|filtered"] "open|filtered", "closed|filtered"]
for state in states: for state in states:
self.port_state_combo.append_text(state) self.port_state_combo.append_text(state)
self.port_state_combo.set_active(states.index(self.operator.replace("_", "|"))) self.port_state_combo.set_active(
states.index(self.operator.replace("_", "|")))
def _pack_widgets(self): def _pack_widgets(self):
self.pack_start(self.entry, True) self.pack_start(self.entry, True)
@@ -759,6 +795,7 @@ class PortSubcriterion(Subcriterion):
self.operator = widget.get_active_text() self.operator = widget.get_active_text()
self.value_changed() self.value_changed()
class DirSubcriterion(Subcriterion): class DirSubcriterion(Subcriterion):
def __init__(self, operator="dir", argument=""): def __init__(self, operator="dir", argument=""):
Subcriterion.__init__(self) Subcriterion.__init__(self)
@@ -797,13 +834,14 @@ class DirSubcriterion(Subcriterion):
self.argument = widget.get_text() self.argument = widget.get_text()
self.value_changed() self.value_changed()
class DateSubcriterion(Subcriterion): class DateSubcriterion(Subcriterion):
def __init__(self, operator="date", argument=""): def __init__(self, operator="date", argument=""):
Subcriterion.__init__(self) Subcriterion.__init__(self)
self.text2op = {"is" : "date", self.text2op = {"is": "date",
"after" : "after", "after": "after",
"before" : "before"} "before": "before"}
self.operator = operator self.operator = operator
@@ -811,7 +849,8 @@ class DateSubcriterion(Subcriterion):
self._pack_widgets() self._pack_widgets()
self._connect_widgets() self._connect_widgets()
# Count the fuzzy operators, so that we can append them to the argument later # Count the fuzzy operators, so that we can append them to the argument
# later
self.fuzzies = argument.count("~") self.fuzzies = argument.count("~")
argument = argument.replace("~", "") argument = argument.replace("~", "")
self.minus_notation = False self.minus_notation = False
@@ -821,9 +860,11 @@ class DateSubcriterion(Subcriterion):
self.argument = argument self.argument = argument
elif re.match("[-|\+]\d+$", argument) != None: elif re.match("[-|\+]\d+$", argument) != None:
# Convert the date from the "-n" notation into YYYY-MM-DD # Convert the date from the "-n" notation into YYYY-MM-DD
parsed_date = datetime.date.fromordinal(datetime.date.today().toordinal() + int(argument)) parsed_date = datetime.date.fromordinal(
datetime.date.today().toordinal() + int(argument))
self.argument = argument self.argument = argument
self.date = datetime.date(parsed_date.year, parsed_date.month, parsed_date.day) self.date = datetime.date(
parsed_date.year, parsed_date.month, parsed_date.day)
self.minus_notation = True self.minus_notation = True
else: else:
@@ -851,7 +892,8 @@ class DateSubcriterion(Subcriterion):
self.pack_start(self.date_button, True) self.pack_start(self.date_button, True)
def _connect_widgets(self): def _connect_widgets(self):
self.date_criterion_combo.connect("changed", self.date_criterion_changed) self.date_criterion_combo.connect(
"changed", self.date_criterion_changed)
self.date_button.connect("clicked", self.show_calendar) self.date_button.connect("clicked", self.show_calendar)
def date_criterion_changed(self, widget=None, extra=None): def date_criterion_changed(self, widget=None, extra=None):
@@ -897,6 +939,7 @@ class DateSubcriterion(Subcriterion):
date = property(get_date, set_date) date = property(get_date, set_date)
_date = datetime.date.today() _date = datetime.date.today()
class DateCalendar(gtk.Window, object): class DateCalendar(gtk.Window, object):
def __init__(self): def __init__(self):
gtk.Window.__init__(self, gtk.WINDOW_POPUP) gtk.Window.__init__(self, gtk.WINDOW_POPUP)
@@ -906,7 +949,7 @@ class DateCalendar(gtk.Window, object):
self.add(self.calendar) self.add(self.calendar)
def connect_calendar(self, update_button_cb): def connect_calendar(self, update_button_cb):
self.calendar.connect("day-selected-double-click", \ self.calendar.connect("day-selected-double-click",
self.kill_calendar, update_button_cb) self.kill_calendar, update_button_cb)
def kill_calendar(self, widget, method): def kill_calendar(self, widget, method):

View File

@@ -135,6 +135,7 @@ hildon = None
if is_maemo(): if is_maemo():
import hildon import hildon
class BaseSearchWindow(hildon.Window): class BaseSearchWindow(hildon.Window):
def __init__(self): def __init__(self):
hildon.Window.__init__(self) hildon.Window.__init__(self)
@@ -151,6 +152,7 @@ else:
def _pack_widgets(self): def _pack_widgets(self):
self.vbox.set_border_width(4) self.vbox.set_border_width(4)
class SearchWindow(BaseSearchWindow, object): class SearchWindow(BaseSearchWindow, object):
def __init__(self, load_method, append_method): def __init__(self, load_method, append_method):
BaseSearchWindow.__init__(self) BaseSearchWindow.__init__(self)
@@ -200,7 +202,8 @@ class SearchWindow(BaseSearchWindow, object):
def _connect_widgets(self): def _connect_widgets(self):
# Double click on result, opens it # Double click on result, opens it
self.search_gui.result_view.connect("row-activated", self.open_selected) self.search_gui.result_view.connect(
"row-activated", self.open_selected)
self.btn_open.connect("clicked", self.open_selected) self.btn_open.connect("clicked", self.open_selected)
self.btn_append.connect("clicked", self.append_selected) self.btn_append.connect("clicked", self.append_selected)
@@ -214,14 +217,16 @@ class SearchWindow(BaseSearchWindow, object):
def set_label_text(self, text): def set_label_text(self, text):
self.bottom_label.set_label(text) self.bottom_label.set_label(text)
def open_selected(self, widget=None, path=None, view_column=None, extra=None): def open_selected(self, widget=None, path=None, view_column=None,
extra=None):
# Open selected results # Open selected results
self.load_method(self.results) self.load_method(self.results)
# Close Search Window # Close Search Window
self.close() self.close()
def append_selected(self, widget=None, path=None, view_column=None, extra=None): def append_selected(self, widget=None, path=None, view_column=None,
extra=None):
# Append selected results # Append selected results
self.append_method(self.results) self.append_method(self.results)

View File

@@ -124,6 +124,7 @@ import gtk
from zenmapCore.TargetList import target_list from zenmapCore.TargetList import target_list
class TargetCombo(gtk.ComboBoxEntry): class TargetCombo(gtk.ComboBoxEntry):
def __init__(self): def __init__(self):
gtk.ComboBoxEntry.__init__(self, gtk.ListStore(str), 0) gtk.ComboBoxEntry.__init__(self, gtk.ListStore(str), 0)
@@ -143,7 +144,7 @@ class TargetCombo(gtk.ComboBoxEntry):
t_list = target_list.get_target_list() t_list = target_list.get_target_list()
for target in t_list[:15]: for target in t_list[:15]:
t_model.append([target.replace('\n','')]) t_model.append([target.replace('\n', '')])
def add_new_target(self, target): def add_new_target(self, target):
target_list.add_target(target) target_list.add_target(target)

View File

@@ -144,6 +144,7 @@ from radialnet.util.integration import make_graph_from_hosts
SLOW_LIMIT = 1000 SLOW_LIMIT = 1000
class TopologyPage(HIGVBox): class TopologyPage(HIGVBox):
def __init__(self, inventory): def __init__(self, inventory):
HIGVBox.__init__(self) HIGVBox.__init__(self)
@@ -200,12 +201,14 @@ class TopologyPage(HIGVBox):
self.display_panel.pack_start(self.radialnet, True, True) self.display_panel.pack_start(self.radialnet, True, True)
def add_scan(self, scan): def add_scan(self, scan):
"""Parses a given XML file and adds the parsed result to the network inventory.""" """Parses a given XML file and adds the parsed result to the network
inventory."""
self.network_inventory.add_scan(scan) self.network_inventory.add_scan(scan)
self.update_radialnet() self.update_radialnet()
def update_radialnet(self): def update_radialnet(self):
"""Creates a graph from network inventory's host list and displays it.""" """Creates a graph from network inventory's host list and displays
it."""
hosts_up = self.network_inventory.get_hosts_up() hosts_up = self.network_inventory.get_hosts_up()
self.slow_label.set_text(_("""\ self.slow_label.set_text(_("""\

View File

@@ -136,23 +136,24 @@ import gobject
gtk_version_major, gtk_version_minor, gtk_version_release = gtk.gtk_version gtk_version_major, gtk_version_minor, gtk_version_release = gtk.gtk_version
assert gtk_version_major == 2 assert gtk_version_major == 2
def gtk_constant_name(group, value): def gtk_constant_name(group, value):
""" """
Returns the (py)GTK+ name of a constant, given its group name Returns the (py)GTK+ name of a constant, given its group name
""" """
group_response = { -1 : 'gtk.RESPONSE_NONE', group_response = {-1: 'gtk.RESPONSE_NONE',
-2 : 'gtk.RESPONSE_REJECT', -2: 'gtk.RESPONSE_REJECT',
-3 : 'gtk.RESPONSE_ACCEPT', -3: 'gtk.RESPONSE_ACCEPT',
-4 : 'gtk.RESPONSE_DELETE_EVENT', -4: 'gtk.RESPONSE_DELETE_EVENT',
-5 : 'gtk.RESPONSE_OK', -5: 'gtk.RESPONSE_OK',
-6 : 'gtk.RESPONSE_CANCEL', -6: 'gtk.RESPONSE_CANCEL',
-7 : 'gtk.RESPONSE_CLOSE', -7: 'gtk.RESPONSE_CLOSE',
-8 : 'gtk.RESPONSE_YES', -8: 'gtk.RESPONSE_YES',
-9 : 'gtk.RESPONSE_NO', -9: 'gtk.RESPONSE_NO',
-10 : 'gtk.RESPONSE_APPLY', -10: 'gtk.RESPONSE_APPLY',
-11 : 'gtk.RESPONSE_HELP' } -11: 'gtk.RESPONSE_HELP'}
groups = {'response' : group_response} groups = {'response': group_response}
return groups.get(group, {}).get(value, 'Error: constant value not found') return groups.get(group, {}).get(value, 'Error: constant value not found')

View File

@@ -130,6 +130,7 @@ __all__ = ['HIGHBox', 'HIGVBox']
import gtk import gtk
class HIGBox(gtk.Box): class HIGBox(gtk.Box):
def _pack_noexpand_nofill(self, widget): def _pack_noexpand_nofill(self, widget):
self.pack_start(widget, expand=False, fill=False) self.pack_start(widget, expand=False, fill=False)
@@ -137,6 +138,7 @@ class HIGBox(gtk.Box):
def _pack_expand_fill(self, widget): def _pack_expand_fill(self, widget):
self.pack_start(widget, expand=True, fill=True) self.pack_start(widget, expand=True, fill=True)
class HIGHBox(gtk.HBox, HIGBox): class HIGHBox(gtk.HBox, HIGBox):
def __init__(self, homogeneous=False, spacing=12): def __init__(self, homogeneous=False, spacing=12):
gtk.HBox.__init__(self, homogeneous, spacing) gtk.HBox.__init__(self, homogeneous, spacing)
@@ -145,6 +147,7 @@ class HIGHBox(gtk.HBox, HIGBox):
pack_label = HIGBox._pack_noexpand_nofill pack_label = HIGBox._pack_noexpand_nofill
pack_entry = HIGBox._pack_expand_fill pack_entry = HIGBox._pack_expand_fill
class HIGVBox(gtk.VBox, HIGBox): class HIGVBox(gtk.VBox, HIGBox):
def __init__(self, homogeneous=False, spacing=12): def __init__(self, homogeneous=False, spacing=12):
gtk.VBox.__init__(self, homogeneous, spacing) gtk.VBox.__init__(self, homogeneous, spacing)
@@ -152,6 +155,7 @@ class HIGVBox(gtk.VBox, HIGBox):
# Packs a widget as a line, so it doesn't expand vertically # Packs a widget as a line, so it doesn't expand vertically
pack_line = HIGBox._pack_noexpand_nofill pack_line = HIGBox._pack_noexpand_nofill
class HIGSpacer(HIGHBox): class HIGSpacer(HIGHBox):
def __init__(self, widget=None): def __init__(self, widget=None):
HIGHBox.__init__(self) HIGHBox.__init__(self)
@@ -166,5 +170,6 @@ class HIGSpacer(HIGHBox):
def get_child(self): def get_child(self):
return self.child return self.child
def hig_box_space_holder(): def hig_box_space_holder():
return gtk.Label(" ") return gtk.Label(" ")

View File

@@ -130,6 +130,7 @@ __all__ = ['HIGMixButton', 'HIGButton']
import gtk import gtk
class HIGMixButton (gtk.HBox): class HIGMixButton (gtk.HBox):
def __init__(self, title, stock): def __init__(self, title, stock):
gtk.HBox.__init__(self, False, 4) gtk.HBox.__init__(self, False, 4)
@@ -146,8 +147,9 @@ class HIGMixButton (gtk.HBox):
self.pack_start(self.align) self.pack_start(self.align)
self.pack_start(self.hbox1) self.pack_start(self.hbox1)
class HIGButton (gtk.Button): class HIGButton (gtk.Button):
def __init__ (self, title="", stock=None): def __init__(self, title="", stock=None):
if title and stock: if title and stock:
gtk.Button.__init__(self) gtk.Button.__init__(self)
content = HIGMixButton(title, stock) content = HIGMixButton(title, stock)
@@ -159,6 +161,7 @@ class HIGButton (gtk.Button):
else: else:
gtk.Button.__init__(self) gtk.Button.__init__(self)
class HIGToggleButton(gtk.ToggleButton): class HIGToggleButton(gtk.ToggleButton):
def __init__(self, title="", stock=None): def __init__(self, title="", stock=None):
if title and stock: if title and stock:

View File

@@ -132,6 +132,7 @@ import gtk
from gtkutils import gtk_version_minor from gtkutils import gtk_version_minor
class HIGDialog(gtk.Dialog): class HIGDialog(gtk.Dialog):
""" """
HIGFied Dialog HIGFied Dialog
@@ -142,6 +143,7 @@ class HIGDialog(gtk.Dialog):
self.vbox.set_border_width(2) self.vbox.set_border_width(2)
self.vbox.set_spacing(6) self.vbox.set_spacing(6)
class HIGAlertDialog(gtk.MessageDialog): class HIGAlertDialog(gtk.MessageDialog):
""" """
HIGfied Alert Dialog. HIGfied Alert Dialog.

View File

@@ -130,6 +130,7 @@ import gtk
HIGTextEntry = gtk.Entry HIGTextEntry = gtk.Entry
class HIGPasswordEntry(HIGTextEntry): class HIGPasswordEntry(HIGTextEntry):
""" """
An entry that masks its text An entry that masks its text

View File

@@ -132,6 +132,7 @@ import gtk
from higboxes import HIGHBox, hig_box_space_holder from higboxes import HIGHBox, hig_box_space_holder
class HIGExpander(gtk.Expander): class HIGExpander(gtk.Expander):
def __init__(self, label): def __init__(self, label):
gtk.Expander.__init__(self) gtk.Expander.__init__(self)

View File

@@ -130,6 +130,7 @@ __all__ = ['HIGFrame']
import gtk import gtk
class HIGFrame(gtk.Frame): class HIGFrame(gtk.Frame):
""" """
Frame without border with bold label. Frame without border with bold label.

View File

@@ -126,10 +126,13 @@ higwidgets/higlabels.py
labels related classes labels related classes
""" """
__all__ = ['HIGSectionLabel', 'HIGHintSectionLabel', 'HIGEntryLabel', 'HIGDialogLabel'] __all__ = [
'HIGSectionLabel', 'HIGHintSectionLabel', 'HIGEntryLabel', 'HIGDialogLabel'
]
import gtk import gtk
class HIGSectionLabel(gtk.Label): class HIGSectionLabel(gtk.Label):
""" """
Bold label, used to define sections Bold label, used to define sections
@@ -142,10 +145,11 @@ class HIGSectionLabel(gtk.Label):
self.set_alignment(0, 0.50) self.set_alignment(0, 0.50)
self.set_line_wrap(True) self.set_line_wrap(True)
class HIGHintSectionLabel(gtk.HBox, object): class HIGHintSectionLabel(gtk.HBox, object):
""" """
Bold label used to define sections, with a little icon that shows up a hint when mouse is Bold label used to define sections, with a little icon that shows up a hint
over it. when mouse is over it.
""" """
def __init__(self, text=None, hint=None): def __init__(self, text=None, hint=None):
gtk.HBox.__init__(self) gtk.HBox.__init__(self)
@@ -156,13 +160,15 @@ class HIGHintSectionLabel(gtk.HBox, object):
self.pack_start(self.label, False, False) self.pack_start(self.label, False, False)
self.pack_start(self.hint, False, False, 5) self.pack_start(self.hint, False, False, 5)
class Hint(gtk.EventBox, object): class Hint(gtk.EventBox, object):
def __init__(self, hint): def __init__(self, hint):
gtk.EventBox.__init__(self) gtk.EventBox.__init__(self)
self.hint = hint self.hint = hint
self.hint_image = gtk.Image() self.hint_image = gtk.Image()
self.hint_image.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_SMALL_TOOLBAR) self.hint_image.set_from_stock(
gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_SMALL_TOOLBAR)
self.add(self.hint_image) self.add(self.hint_image)
@@ -172,6 +178,7 @@ class Hint(gtk.EventBox, object):
hint_window = HintWindow(self.hint) hint_window = HintWindow(self.hint)
hint_window.show_all() hint_window.show_all()
class HintWindow(gtk.Window): class HintWindow(gtk.Window):
def __init__(self, hint): def __init__(self, hint):
gtk.Window.__init__(self, gtk.WINDOW_POPUP) gtk.Window.__init__(self, gtk.WINDOW_POPUP)
@@ -208,6 +215,7 @@ class HIGEntryLabel(gtk.Label):
self.set_use_markup(True) self.set_use_markup(True)
self.set_line_wrap(True) self.set_line_wrap(True)
class HIGDialogLabel(gtk.Label): class HIGDialogLabel(gtk.Label):
""" """
Centered, line-wrappable label, usually used on dialogs. Centered, line-wrappable label, usually used on dialogs.

View File

@@ -135,6 +135,7 @@ from higlabels import HIGEntryLabel
from higtables import HIGTable from higtables import HIGTable
from higentries import HIGTextEntry, HIGPasswordEntry from higentries import HIGTextEntry, HIGPasswordEntry
class HIGLoginDialog(HIGDialog): class HIGLoginDialog(HIGDialog):
""" """
A dialog that asks for basic login information (username / password) A dialog that asks for basic login information (username / password)

View File

@@ -133,8 +133,11 @@ class HIGNotebook(gtk.Notebook):
gtk.Notebook.__init__(self) gtk.Notebook.__init__(self)
self.popup_enable() self.popup_enable()
class HIGClosableTabLabel(HIGHBox): class HIGClosableTabLabel(HIGHBox):
__gsignals__ = { 'close-clicked' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } __gsignals__ = {
'close-clicked': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
}
def __init__(self, label_text=""): def __init__(self, label_text=""):
gobject.GObject.__init__(self) gobject.GObject.__init__(self)

View File

@@ -132,6 +132,7 @@ import gtk
from higboxes import HIGHBox from higboxes import HIGHBox
class HIGLabeledProgressBar(HIGHBox): class HIGLabeledProgressBar(HIGHBox):
def __init__(self, label=None): def __init__(self, label=None):
HIGHBox.__init__(self) HIGHBox.__init__(self)

View File

@@ -130,6 +130,7 @@ __all__ = ['HIGScrolledWindow']
import gtk import gtk
class HIGScrolledWindow(gtk.ScrolledWindow): class HIGScrolledWindow(gtk.ScrolledWindow):
def __init__(self): def __init__(self):
gtk.ScrolledWindow.__init__(self) gtk.ScrolledWindow.__init__(self)

View File

@@ -134,12 +134,14 @@ import gobject
from gtkutils import gobject_register from gtkutils import gobject_register
class HIGSpinnerImages: class HIGSpinnerImages:
def __init__(self): def __init__(self):
"""This class holds list of GDK Pixbuffers. """This class holds list of GDK Pixbuffers.
- static_pixbufs is used for multiple static pixbuffers - static_pixbufs is used for multiple static pixbuffers
- self.animated_pixbufs is used for the pixbuffers that make up the animation - self.animated_pixbufs is used for the pixbuffers that make up the
animation
""" """
dprint('HIGSpinnerImages::__init__') dprint('HIGSpinnerImages::__init__')
@@ -182,7 +184,7 @@ class HIGSpinnerImages:
dprint('HIGSpinnerImages::set_rest_pixbuf') dprint('HIGSpinnerImages::set_rest_pixbuf')
if not self.static_pixbufs.has_key(name): if name not in self.static_pixbufs:
raise StaticPixbufNotFound raise StaticPixbufNotFound
# self.rest_pixbuf holds the *real* pixbuf, not it's name # self.rest_pixbuf holds the *real* pixbuf, not it's name
@@ -322,6 +324,7 @@ class HIGSpinnerCache:
self.spinner_images.static_pixbufs[key_name].save(path_name, self.spinner_images.static_pixbufs[key_name].save(path_name,
image_format) image_format)
class HIGSpinner(gtk.EventBox): class HIGSpinner(gtk.EventBox):
"""Simple spinner, such as the one found in webbrowsers and file managers. """Simple spinner, such as the one found in webbrowsers and file managers.
@@ -331,8 +334,8 @@ class HIGSpinner(gtk.EventBox):
* height, the height that will be set for the images * height, the height that will be set for the images
""" """
__gsignals__ = { 'expose-event' : 'override', __gsignals__ = {'expose-event': 'override',
'size-request' : 'override' } 'size-request': 'override'}
def __init__(self): def __init__(self):
gtk.EventBox.__init__(self) gtk.EventBox.__init__(self)
@@ -384,8 +387,8 @@ class HIGSpinner(gtk.EventBox):
if self.timer_task == 0: if self.timer_task == 0:
self.current_pixbuf = self.cache.spinner_images.rest_pixbuf self.current_pixbuf = self.cache.spinner_images.rest_pixbuf
else: else:
self.current_pixbuf = self.cache.spinner_images.animated_pixbufs\ self.current_pixbuf = self.cache.spinner_images.animated_pixbufs[
[self.animated_pixbuf_index] self.animated_pixbuf_index]
def start(self): def start(self):
"""Starts the animation""" """Starts the animation"""
@@ -401,11 +404,11 @@ class HIGSpinner(gtk.EventBox):
self.timer_task = 0 self.timer_task = 0
self.queue_draw() self.queue_draw()
def stop(self): def stop(self):
"""Stops the animation """Stops the animation
Do the same stuff as pause, but returns the animation to the beggining.""" Do the same stuff as pause, but returns the animation to the
beginning."""
self.pause() self.pause()
self.animated_pixbuf_index = 0 self.animated_pixbuf_index = 0

View File

@@ -133,6 +133,7 @@ import gtk
#from higlabels import * #from higlabels import *
#from higentries import * #from higentries import *
class HIGTable(gtk.Table): class HIGTable(gtk.Table):
""" """
A HIGFied table A HIGFied table
@@ -154,4 +155,4 @@ class HIGTable(gtk.Table):
self.attach(widget, x0, x, y0, y, xoptions=gtk.FILL) self.attach(widget, x0, x, y0, y, xoptions=gtk.FILL)
def attach_entry(self, widget, x0, x, y0, y): def attach_entry(self, widget, x0, x, y0, y):
self.attach(widget, x0, x, y0, y, xoptions=gtk.FILL|gtk.EXPAND) self.attach(widget, x0, x, y0, y, xoptions=gtk.FILL | gtk.EXPAND)

View File

@@ -130,6 +130,7 @@ __all__ = ['HIGTextView']
import gtk import gtk
class HIGTextView(gtk.TextView): class HIGTextView(gtk.TextView):
def __init__(self, text=''): def __init__(self, text=''):
gtk.TextView.__init__(self) gtk.TextView.__init__(self)

View File

@@ -128,6 +128,7 @@ higwidgets/higwindows.py
import gtk import gtk
class HIGWindow(gtk.Window): class HIGWindow(gtk.Window):
"""HIGFied Window""" """HIGFied Window"""
def __init__(self, type=gtk.WINDOW_TOPLEVEL): def __init__(self, type=gtk.WINDOW_TOPLEVEL):

View File

@@ -130,6 +130,7 @@ __all__ = ['HIGSpinner']
import gobject import gobject
def gobject_register(klass): def gobject_register(klass):
if gtk_version_minor < 8: if gtk_version_minor < 8:
gobject.type_register(klass) gobject.type_register(klass)