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:
@@ -119,4 +119,4 @@
|
||||
# * *
|
||||
# ***************************************************************************/
|
||||
|
||||
__all__ = ["bestwidgets", "core", "gui", "util"];
|
||||
__all__ = ["bestwidgets", "core", "gui", "util"]
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
import gtk
|
||||
|
||||
|
||||
|
||||
class BWBox(gtk.Box):
|
||||
"""
|
||||
"""
|
||||
@@ -131,38 +130,32 @@ class BWBox(gtk.Box):
|
||||
"""
|
||||
self.pack_start(widget, True, True, padding)
|
||||
|
||||
|
||||
def bw_pack_start_expand_nofill(self, widget, padding=0):
|
||||
"""
|
||||
"""
|
||||
self.pack_start(widget, True, False, padding)
|
||||
|
||||
|
||||
def bw_pack_start_noexpand_nofill(self, widget, padding=0):
|
||||
"""
|
||||
"""
|
||||
self.pack_start(widget, False, False, padding)
|
||||
|
||||
|
||||
def bw_pack_end_expand_fill(self, widget, padding=0):
|
||||
"""
|
||||
"""
|
||||
self.pack_end(widget, True, True, padding)
|
||||
|
||||
|
||||
def bw_pack_end_expand_nofill(self, widget, padding=0):
|
||||
"""
|
||||
"""
|
||||
self.pack_end(widget, True, False, padding)
|
||||
|
||||
|
||||
def bw_pack_end_noexpand_nofill(self, widget, padding=0):
|
||||
"""
|
||||
"""
|
||||
self.pack_end(widget, False, False, padding)
|
||||
|
||||
|
||||
|
||||
class BWHBox(gtk.HBox, BWBox):
|
||||
"""
|
||||
"""
|
||||
@@ -172,7 +165,6 @@ class BWHBox(gtk.HBox, BWBox):
|
||||
gtk.HBox.__init__(self, homogeneous, spacing)
|
||||
|
||||
|
||||
|
||||
class BWVBox(gtk.VBox, BWBox):
|
||||
"""
|
||||
"""
|
||||
@@ -182,7 +174,6 @@ class BWVBox(gtk.VBox, BWBox):
|
||||
gtk.VBox.__init__(self, homogeneous, spacing)
|
||||
|
||||
|
||||
|
||||
class BWStatusbar(gtk.Statusbar, BWBox):
|
||||
"""
|
||||
"""
|
||||
@@ -192,7 +183,6 @@ class BWStatusbar(gtk.Statusbar, BWBox):
|
||||
gtk.HBox.__init__(self, homogeneous, spacing)
|
||||
|
||||
|
||||
|
||||
class BWTable(gtk.Table, BWBox):
|
||||
"""
|
||||
"""
|
||||
@@ -207,14 +197,12 @@ class BWTable(gtk.Table, BWBox):
|
||||
|
||||
self.__last_point = (0, 0)
|
||||
|
||||
|
||||
def bw_set_spacing(self, spacing):
|
||||
"""
|
||||
"""
|
||||
self.set_row_spacings(spacing)
|
||||
self.set_col_spacings(spacing)
|
||||
|
||||
|
||||
def bw_resize(self, rows, columns):
|
||||
"""
|
||||
"""
|
||||
@@ -223,11 +211,10 @@ class BWTable(gtk.Table, BWBox):
|
||||
|
||||
self.resize(rows, columns)
|
||||
|
||||
|
||||
def bw_attach_next(self,
|
||||
child,
|
||||
xoptions=gtk.EXPAND|gtk.FILL,
|
||||
yoptions=gtk.EXPAND|gtk.FILL,
|
||||
xoptions=gtk.EXPAND | gtk.FILL,
|
||||
yoptions=gtk.EXPAND | gtk.FILL,
|
||||
xpadding=0,
|
||||
ypadding=0):
|
||||
"""
|
||||
@@ -257,7 +244,6 @@ class BWTable(gtk.Table, BWBox):
|
||||
self.__last_point = (row, column)
|
||||
|
||||
|
||||
|
||||
class BWScrolledWindow(gtk.ScrolledWindow):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
import gtk
|
||||
|
||||
|
||||
|
||||
class BWStockButton(gtk.Button):
|
||||
"""
|
||||
"""
|
||||
@@ -138,7 +137,6 @@ class BWStockButton(gtk.Button):
|
||||
self.set_image(self.__image)
|
||||
|
||||
|
||||
|
||||
class BWToggleStockButton(gtk.ToggleButton):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -123,7 +123,6 @@ import gtk
|
||||
import gobject
|
||||
|
||||
|
||||
|
||||
class BWChangeableComboBoxEntry(gtk.ComboBoxEntry):
|
||||
"""
|
||||
"""
|
||||
@@ -139,20 +138,17 @@ class BWChangeableComboBoxEntry(gtk.ComboBoxEntry):
|
||||
|
||||
self.__last_active = None
|
||||
|
||||
|
||||
def __changed(self, widget):
|
||||
"""
|
||||
"""
|
||||
if self.get_active() != -1:
|
||||
self.__last_active = self.get_active()
|
||||
|
||||
|
||||
def bw_get_lenght(self):
|
||||
"""
|
||||
"""
|
||||
return len(self.__liststore)
|
||||
|
||||
|
||||
def __entry_changed(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -163,7 +159,6 @@ class BWChangeableComboBoxEntry(gtk.ComboBoxEntry):
|
||||
iter = self.get_model().get_iter((self.__last_active,))
|
||||
self.__liststore.set_value(iter, 0, widget.get_text().strip())
|
||||
|
||||
|
||||
def bw_get_active(self):
|
||||
"""
|
||||
"""
|
||||
@@ -173,7 +168,6 @@ class BWChangeableComboBoxEntry(gtk.ComboBoxEntry):
|
||||
return self.get_active()
|
||||
|
||||
|
||||
|
||||
# testing widget
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -182,7 +176,6 @@ if __name__ == "__main__":
|
||||
"""
|
||||
combo.append_text('New')
|
||||
|
||||
|
||||
window = gtk.Window()
|
||||
window.connect("destroy", lambda w: gtk.main_quit())
|
||||
|
||||
|
||||
@@ -139,13 +139,11 @@ class BWExpander(gtk.Expander):
|
||||
|
||||
self.add(self.__alignment)
|
||||
|
||||
|
||||
def bw_set_label_text(self, text):
|
||||
"""
|
||||
"""
|
||||
self.__label.bw_set_text(text)
|
||||
|
||||
|
||||
def bw_add(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -154,7 +152,6 @@ class BWExpander(gtk.Expander):
|
||||
|
||||
self.__alignment.add(widget)
|
||||
|
||||
|
||||
def bw_no_padding(self):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
import gtk
|
||||
|
||||
|
||||
|
||||
class BWFrame(gtk.Frame):
|
||||
"""
|
||||
"""
|
||||
@@ -141,20 +140,17 @@ class BWFrame(gtk.Frame):
|
||||
|
||||
self.bw_set_label(label)
|
||||
|
||||
|
||||
def bw_set_label(self, label):
|
||||
"""
|
||||
"""
|
||||
self.set_label("<b>" + label + "</b>")
|
||||
self.get_label_widget().set_use_markup(True)
|
||||
|
||||
|
||||
def bw_add(self, widget):
|
||||
"""
|
||||
"""
|
||||
self.__alignment.add(widget)
|
||||
|
||||
|
||||
def bw_remove(self, widget):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
import gtk
|
||||
|
||||
|
||||
|
||||
class BWLabel(gtk.Label):
|
||||
"""
|
||||
"""
|
||||
@@ -137,7 +136,6 @@ class BWLabel(gtk.Label):
|
||||
self.set_line_wrap(True)
|
||||
|
||||
|
||||
|
||||
class BWSectionLabel(gtk.Label):
|
||||
"""
|
||||
"""
|
||||
@@ -151,7 +149,6 @@ class BWSectionLabel(gtk.Label):
|
||||
self.set_alignment(0, 0.50)
|
||||
self.set_line_wrap(True)
|
||||
|
||||
|
||||
def bw_set_text(self, text):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -135,7 +135,6 @@ class BWTextView(BWScrolledWindow):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -144,25 +143,21 @@ class BWTextView(BWScrolledWindow):
|
||||
|
||||
self.add_with_viewport(self.__textview)
|
||||
|
||||
|
||||
def bw_set_auto_scroll(self, value):
|
||||
"""
|
||||
"""
|
||||
self.__auto_scroll = value
|
||||
|
||||
|
||||
def bw_set_editable(self, editable):
|
||||
"""
|
||||
"""
|
||||
self.__textview.set_editable(False)
|
||||
|
||||
|
||||
def bw_modify_font(self, font):
|
||||
"""
|
||||
"""
|
||||
self.__textview.modify_font(font)
|
||||
|
||||
|
||||
def bw_set_text(self, text):
|
||||
"""
|
||||
"""
|
||||
@@ -171,27 +166,23 @@ class BWTextView(BWScrolledWindow):
|
||||
if self.__auto_scroll:
|
||||
self.bw_set_scroll_down()
|
||||
|
||||
|
||||
def bw_get_text(self):
|
||||
"""
|
||||
"""
|
||||
return self.__textbuffer.get_text(self.__textbuffer.get_start_iter(),
|
||||
self.__textbuffer.get_end_iter())
|
||||
|
||||
|
||||
def bw_set_scroll_down(self):
|
||||
"""
|
||||
"""
|
||||
self.get_vadjustment().set_value(self.get_vadjustment().upper)
|
||||
|
||||
|
||||
def bw_get_textbuffer(self):
|
||||
"""
|
||||
"""
|
||||
return self.__textbuffer
|
||||
|
||||
|
||||
|
||||
class BWTextEditor(BWScrolledWindow):
|
||||
"""
|
||||
"""
|
||||
@@ -205,7 +196,6 @@ class BWTextEditor(BWScrolledWindow):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -225,33 +215,28 @@ class BWTextEditor(BWScrolledWindow):
|
||||
|
||||
self.add_with_viewport(self.__hbox)
|
||||
|
||||
|
||||
def __expose(self, widget, event):
|
||||
"""
|
||||
"""
|
||||
# code to fix a gtk issue that don't show text correctly
|
||||
self.__hbox.check_resize()
|
||||
|
||||
|
||||
def bw_set_auto_scroll(self, value):
|
||||
"""
|
||||
"""
|
||||
self.__auto_scroll = value
|
||||
|
||||
|
||||
def bw_set_editable(self, editable):
|
||||
"""
|
||||
"""
|
||||
self.__textview.set_editable(False)
|
||||
|
||||
|
||||
def bw_modify_font(self, font):
|
||||
"""
|
||||
"""
|
||||
self.__textview.modify_font(font)
|
||||
self.__lineview.modify_font(font)
|
||||
|
||||
|
||||
def bw_set_text(self, text):
|
||||
"""
|
||||
"""
|
||||
@@ -273,14 +258,12 @@ class BWTextEditor(BWScrolledWindow):
|
||||
self.__textbuffer.set_text("")
|
||||
self.__linebuffer.set_text("")
|
||||
|
||||
|
||||
def bw_get_text(self):
|
||||
"""
|
||||
"""
|
||||
return self.__textbuffer.get_text(self.__textbuffer.get_start_iter(),
|
||||
self.__textbuffer.get_end_iter())
|
||||
|
||||
|
||||
def bw_set_scroll_down(self):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -125,7 +125,6 @@ from radialnet.bestwidgets import gtk_version_minor
|
||||
PRIMARY_TEXT_MARKUP = '<span weight="bold" size="larger">%s</span>'
|
||||
|
||||
|
||||
|
||||
class BWAlertDialog(gtk.MessageDialog):
|
||||
"""
|
||||
"""
|
||||
@@ -149,14 +148,12 @@ class BWAlertDialog(gtk.MessageDialog):
|
||||
if gtk_version_minor > 4:
|
||||
self.format_secondary_text(secondary_text)
|
||||
|
||||
|
||||
def __destroy(self, dialog, id):
|
||||
"""
|
||||
"""
|
||||
self.destroy()
|
||||
|
||||
|
||||
|
||||
class BWWindow(gtk.Window):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -130,7 +130,6 @@ class ArgvHandle:
|
||||
"""
|
||||
self.__argv = argv
|
||||
|
||||
|
||||
def get_option(self, option):
|
||||
"""
|
||||
"""
|
||||
@@ -143,20 +142,17 @@ class ArgvHandle:
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def has_option(self, option):
|
||||
"""
|
||||
"""
|
||||
return option in self.__argv
|
||||
|
||||
|
||||
def get_last_value(self):
|
||||
"""
|
||||
"""
|
||||
return self.__argv[-1]
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
import sys
|
||||
|
||||
@@ -141,31 +141,26 @@ class PolarCoordinate:
|
||||
self.__t = t
|
||||
"""Angle (theta) of polar coordinate in radians"""
|
||||
|
||||
|
||||
def get_theta(self):
|
||||
"""
|
||||
"""
|
||||
return math.degrees(self.__t)
|
||||
|
||||
|
||||
def get_radius(self):
|
||||
"""
|
||||
"""
|
||||
return self.__r
|
||||
|
||||
|
||||
def set_theta(self, t):
|
||||
"""
|
||||
"""
|
||||
self.__t = math.radians(t)
|
||||
|
||||
|
||||
def set_radius(self, r):
|
||||
"""
|
||||
"""
|
||||
self.__r = r
|
||||
|
||||
|
||||
def get_coordinate(self):
|
||||
"""
|
||||
Set polar coordinate
|
||||
@@ -174,7 +169,6 @@ class PolarCoordinate:
|
||||
"""
|
||||
return (self.__r, math.degrees(self.__t))
|
||||
|
||||
|
||||
def set_coordinate(self, r, t):
|
||||
"""
|
||||
Set polar coordinate
|
||||
@@ -186,7 +180,6 @@ class PolarCoordinate:
|
||||
self.__r = r
|
||||
self.__t = math.radians(t)
|
||||
|
||||
|
||||
def to_cartesian(self):
|
||||
"""
|
||||
Convert polar in cartesian coordinate
|
||||
@@ -199,12 +192,10 @@ class PolarCoordinate:
|
||||
return (x, y)
|
||||
|
||||
|
||||
|
||||
class CartesianCoordinate:
|
||||
"""
|
||||
Class to implement a cartesian coordinate object
|
||||
"""
|
||||
|
||||
def __init__(self, x=0, y=0):
|
||||
"""
|
||||
Constructor method of CartesianCoordinate class
|
||||
@@ -218,7 +209,6 @@ class CartesianCoordinate:
|
||||
self.__y = y
|
||||
"""Y component of cartesian coordinate"""
|
||||
|
||||
|
||||
def get_coordinate(self):
|
||||
"""
|
||||
Get cartesian coordinate
|
||||
@@ -227,7 +217,6 @@ class CartesianCoordinate:
|
||||
"""
|
||||
return (self.__x, self.__y)
|
||||
|
||||
|
||||
def set_coordinate(self, x, y):
|
||||
"""
|
||||
Set cartesian coordinate
|
||||
@@ -239,25 +228,24 @@ class CartesianCoordinate:
|
||||
self.__x = x
|
||||
self.__y = y
|
||||
|
||||
|
||||
def to_polar(self):
|
||||
"""
|
||||
Convert cartesian in polar coordinate
|
||||
@rtype: tuple
|
||||
@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.__y >= 0:
|
||||
t = math.atan( self.__y / self.__x )
|
||||
t = math.atan(self.__y / self.__x)
|
||||
|
||||
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:
|
||||
t = math.atan( self.__y / self.__x ) + math.pi
|
||||
t = math.atan(self.__y / self.__x) + math.pi
|
||||
|
||||
elif self.__x == 0:
|
||||
|
||||
@@ -273,12 +261,11 @@ class CartesianCoordinate:
|
||||
return (r, t)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Testing application
|
||||
|
||||
polar = PolarCoordinate(1, math.pi)
|
||||
polar = PolarCoordinate(1, math.pi)
|
||||
cartesian = CartesianCoordinate(-1, 0)
|
||||
|
||||
print polar.to_cartesian()
|
||||
|
||||
@@ -135,15 +135,12 @@ class Node(object):
|
||||
self.__edges = []
|
||||
"""List of edges to other nodes"""
|
||||
|
||||
|
||||
def get_data(self):
|
||||
return self.__data
|
||||
|
||||
|
||||
def set_data(self, data):
|
||||
self.__data = data
|
||||
|
||||
|
||||
def get_edge(self, dest):
|
||||
"""
|
||||
Return the edge connecting to dest, or None if none
|
||||
@@ -153,19 +150,16 @@ class Node(object):
|
||||
return edge
|
||||
return None
|
||||
|
||||
|
||||
def get_edges(self):
|
||||
"""
|
||||
Return the list of edges
|
||||
"""
|
||||
return self.__edges
|
||||
|
||||
|
||||
def add_edge(self, edge):
|
||||
self.__edges.append(edge)
|
||||
|
||||
|
||||
|
||||
class Edge:
|
||||
"""
|
||||
"""
|
||||
@@ -176,41 +170,34 @@ class Edge:
|
||||
self.__nodes = nodes
|
||||
self.__weights_mean = None
|
||||
|
||||
|
||||
def get_nodes(self):
|
||||
"""
|
||||
"""
|
||||
return self.__nodes
|
||||
|
||||
|
||||
def get_weights(self):
|
||||
"""
|
||||
"""
|
||||
return self.__weights
|
||||
|
||||
|
||||
def set_weights(self, weights):
|
||||
"""
|
||||
"""
|
||||
self.__weights = weights
|
||||
self.__weights_mean = sum(self.__weights) / len(self.__weights)
|
||||
|
||||
|
||||
def add_weight(self, weight):
|
||||
"""
|
||||
"""
|
||||
self.__weights.append(weight)
|
||||
self.__weights_mean = sum(self.__weights) / len(self.__weights)
|
||||
|
||||
|
||||
def get_weights_mean(self):
|
||||
"""
|
||||
"""
|
||||
return self.__weights_mean
|
||||
|
||||
|
||||
|
||||
|
||||
class Graph:
|
||||
"""
|
||||
Network Graph class
|
||||
@@ -227,19 +214,16 @@ class Graph:
|
||||
self.__max_edge_mean_value = None
|
||||
self.__min_edge_mean_value = None
|
||||
|
||||
|
||||
def set_nodes(self, nodes):
|
||||
"""
|
||||
"""
|
||||
self.__nodes = nodes
|
||||
|
||||
|
||||
def get_nodes(self):
|
||||
"""
|
||||
"""
|
||||
return self.__nodes
|
||||
|
||||
|
||||
def get_number_of_nodes(self):
|
||||
"""
|
||||
Get the number of nodes in graph
|
||||
@@ -248,7 +232,6 @@ class Graph:
|
||||
"""
|
||||
return len(self.__nodes)
|
||||
|
||||
|
||||
def set_main_node(self, node):
|
||||
"""
|
||||
Set the main node
|
||||
@@ -257,7 +240,6 @@ class Graph:
|
||||
"""
|
||||
self.__main_node = node
|
||||
|
||||
|
||||
def get_main_node(self):
|
||||
"""
|
||||
Get the main node
|
||||
@@ -266,7 +248,6 @@ class Graph:
|
||||
"""
|
||||
return self.__main_node
|
||||
|
||||
|
||||
def set_connection(self, a, b, weight=None):
|
||||
"""
|
||||
Set node connections
|
||||
@@ -287,12 +268,13 @@ class Graph:
|
||||
edge.add_weight(weight)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
def get_edges(self):
|
||||
"""
|
||||
An iterator that yields all edges
|
||||
@@ -302,7 +284,6 @@ class Graph:
|
||||
if edge.get_nodes()[0] == node:
|
||||
yield edge
|
||||
|
||||
|
||||
def get_node_connections(self, node):
|
||||
"""
|
||||
"""
|
||||
@@ -319,16 +300,12 @@ class Graph:
|
||||
|
||||
return connections
|
||||
|
||||
|
||||
def get_max_edge_mean_weight(self):
|
||||
"""
|
||||
"""
|
||||
return self.__max_edge_mean_value
|
||||
|
||||
|
||||
def get_min_edge_mean_weight(self):
|
||||
"""
|
||||
"""
|
||||
return self.__min_edge_mean_value
|
||||
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
import os
|
||||
|
||||
|
||||
INFO = {'name' : 'RadialNet',
|
||||
INFO = {'name': 'RadialNet',
|
||||
'version': '0.44',
|
||||
'website': 'http://www.dca.ufrn.br/~joaomedeiros/radialnet/',
|
||||
'authors': ['João Paulo de Souza Medeiros'],
|
||||
|
||||
@@ -136,7 +136,6 @@ class Linear2DInterpolator:
|
||||
self.__interpolated_points = []
|
||||
"""Interpolated points vector"""
|
||||
|
||||
|
||||
def set_start_point(self, a, b):
|
||||
"""
|
||||
Set initial coordinate
|
||||
@@ -148,7 +147,6 @@ class Linear2DInterpolator:
|
||||
"""
|
||||
self.__start_point = (a, b)
|
||||
|
||||
|
||||
def set_final_point(self, a, b):
|
||||
"""
|
||||
Set final coordinate
|
||||
@@ -159,7 +157,6 @@ class Linear2DInterpolator:
|
||||
"""
|
||||
self.__final_point = (a, b)
|
||||
|
||||
|
||||
def get_weighed_points(self, number_of_pass, pass_vector):
|
||||
"""
|
||||
Return the vector of coordinates between the initial and final
|
||||
@@ -188,7 +185,6 @@ class Linear2DInterpolator:
|
||||
|
||||
return self.__interpolated_points
|
||||
|
||||
|
||||
def get_points(self, number_of_pass):
|
||||
"""
|
||||
Return the vector of coordinates between the initial and final
|
||||
@@ -213,7 +209,6 @@ class Linear2DInterpolator:
|
||||
return self.__interpolated_points
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Testing application
|
||||
@@ -224,4 +219,3 @@ if __name__ == "__main__":
|
||||
i.set_final_point(1, 1)
|
||||
|
||||
print len(i.get_points(10)), i.get_points(10)
|
||||
|
||||
|
||||
@@ -124,14 +124,12 @@ import xml.sax.saxutils
|
||||
from xml.sax.xmlreader import AttributesImpl as Attributes
|
||||
|
||||
|
||||
|
||||
def convert_to_utf8(text):
|
||||
"""
|
||||
"""
|
||||
return text.encode('utf8', 'replace')
|
||||
|
||||
|
||||
|
||||
class XMLNode:
|
||||
"""
|
||||
"""
|
||||
@@ -143,70 +141,59 @@ class XMLNode:
|
||||
self.__attrs = dict()
|
||||
self.__children = []
|
||||
|
||||
|
||||
def set_text(self, text):
|
||||
"""
|
||||
"""
|
||||
self.__text = text
|
||||
|
||||
|
||||
def get_text(self):
|
||||
"""
|
||||
"""
|
||||
return self.__text
|
||||
|
||||
|
||||
def set_name(self, name):
|
||||
"""
|
||||
"""
|
||||
self.__name = name
|
||||
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
"""
|
||||
return self.__name
|
||||
|
||||
|
||||
def add_attr(self, key, value):
|
||||
"""
|
||||
"""
|
||||
self.__attrs[key] = value
|
||||
|
||||
|
||||
def add_child(self, child):
|
||||
"""
|
||||
"""
|
||||
self.__children.append(child)
|
||||
|
||||
|
||||
def get_keys(self):
|
||||
"""
|
||||
"""
|
||||
return self.__attrs.keys()
|
||||
|
||||
|
||||
def get_attr(self, attr):
|
||||
"""
|
||||
"""
|
||||
if self.__attrs.has_key(attr):
|
||||
if attr in self.__attrs:
|
||||
return self.__attrs[attr]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_attrs(self):
|
||||
"""
|
||||
"""
|
||||
return self.__attrs
|
||||
|
||||
|
||||
def get_children(self):
|
||||
"""
|
||||
"""
|
||||
return self.__children
|
||||
|
||||
|
||||
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_attrs().has_key(attr):
|
||||
if attr in child.get_attrs():
|
||||
|
||||
c_value = child.get_attr(attr)
|
||||
|
||||
@@ -243,7 +230,6 @@ class XMLNode:
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def search_children(self, name, first=False, deep=False):
|
||||
"""
|
||||
"""
|
||||
@@ -276,7 +262,6 @@ class XMLNode:
|
||||
return result
|
||||
|
||||
|
||||
|
||||
class XMLWriter(xml.sax.saxutils.XMLGenerator):
|
||||
"""
|
||||
"""
|
||||
@@ -287,13 +272,11 @@ class XMLWriter(xml.sax.saxutils.XMLGenerator):
|
||||
|
||||
self.__root = root
|
||||
|
||||
|
||||
def set_root(self, root):
|
||||
"""
|
||||
"""
|
||||
self.__root = root
|
||||
|
||||
|
||||
def write(self):
|
||||
"""
|
||||
"""
|
||||
@@ -301,7 +284,6 @@ class XMLWriter(xml.sax.saxutils.XMLGenerator):
|
||||
self.write_xml_node([self.__root])
|
||||
self.endDocument()
|
||||
|
||||
|
||||
def write_xml_node(self, root):
|
||||
"""
|
||||
"""
|
||||
@@ -317,7 +299,6 @@ class XMLWriter(xml.sax.saxutils.XMLGenerator):
|
||||
self.endElement(child.get_name())
|
||||
|
||||
|
||||
|
||||
class XMLReader(xml.sax.ContentHandler):
|
||||
"""
|
||||
"""
|
||||
@@ -330,41 +311,35 @@ class XMLReader(xml.sax.ContentHandler):
|
||||
self.__file = file
|
||||
self.__root = None
|
||||
|
||||
self.__parser = xml.sax.make_parser();
|
||||
self.__parser.setContentHandler(self);
|
||||
|
||||
self.__parser = xml.sax.make_parser()
|
||||
self.__parser.setContentHandler(self)
|
||||
|
||||
def set_file(self, file, root):
|
||||
"""
|
||||
"""
|
||||
self.__file = file
|
||||
|
||||
|
||||
def get_file(self):
|
||||
"""
|
||||
"""
|
||||
return self.__file
|
||||
|
||||
|
||||
def get_root(self):
|
||||
"""
|
||||
"""
|
||||
return self.__root
|
||||
|
||||
|
||||
def parse(self):
|
||||
"""
|
||||
"""
|
||||
if self.__file != None:
|
||||
self.__parser.parse(self.__file)
|
||||
|
||||
|
||||
def startDocument(self):
|
||||
"""
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
"""
|
||||
"""
|
||||
@@ -384,7 +359,6 @@ class XMLReader(xml.sax.ContentHandler):
|
||||
|
||||
self.__status.append(node)
|
||||
|
||||
|
||||
def endElement(self, name):
|
||||
"""
|
||||
"""
|
||||
@@ -393,20 +367,17 @@ class XMLReader(xml.sax.ContentHandler):
|
||||
self.__text = ""
|
||||
self.__status.pop()
|
||||
|
||||
|
||||
def endDocument(self):
|
||||
"""
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def characters(self, text):
|
||||
"""
|
||||
"""
|
||||
self.__text += text
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import sys
|
||||
|
||||
@@ -118,4 +118,3 @@
|
||||
# * Nmap, and also available from https://svn.nmap.org/nmap/COPYING *
|
||||
# * *
|
||||
# ***************************************************************************/
|
||||
|
||||
|
||||
@@ -135,7 +135,6 @@ from radialnet.bestwidgets.boxes import *
|
||||
DIMENSION = (640, 480)
|
||||
|
||||
|
||||
|
||||
class Application(BWMainWindow):
|
||||
"""
|
||||
"""
|
||||
@@ -149,7 +148,6 @@ class Application(BWMainWindow):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -188,7 +186,6 @@ class Application(BWMainWindow):
|
||||
self.__fisheye.hide()
|
||||
self.__toolbar.disable_controls()
|
||||
|
||||
|
||||
def parse_nmap_xml_file(self, file):
|
||||
"""
|
||||
"""
|
||||
@@ -217,7 +214,6 @@ class Application(BWMainWindow):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -143,7 +143,6 @@ OPTIONS = ['address',
|
||||
REFRESH_RATE = 500
|
||||
|
||||
|
||||
|
||||
class ControlWidget(BWVBox):
|
||||
"""
|
||||
"""
|
||||
@@ -157,7 +156,6 @@ class ControlWidget(BWVBox):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
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.
|
||||
pass
|
||||
|
||||
|
||||
class ControlAction(BWExpander):
|
||||
"""
|
||||
"""
|
||||
@@ -192,7 +191,6 @@ class ControlAction(BWExpander):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -253,7 +251,6 @@ class ControlAction(BWExpander):
|
||||
self.__region_color.set_no_show_all(True)
|
||||
self.__region_color.hide()
|
||||
|
||||
|
||||
def __change_pointer(self, widget, pointer):
|
||||
"""
|
||||
"""
|
||||
@@ -265,14 +262,12 @@ class ControlAction(BWExpander):
|
||||
else:
|
||||
self.__region_color.hide()
|
||||
|
||||
|
||||
def __change_region(self, widget):
|
||||
"""
|
||||
"""
|
||||
self.radialnet.set_region_color(self.__region_color.get_active())
|
||||
|
||||
|
||||
|
||||
class ControlVariableWidget(gtk.DrawingArea):
|
||||
"""
|
||||
"""
|
||||
@@ -307,7 +302,6 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
|
||||
gobject.timeout_add(REFRESH_RATE, self.verify_value)
|
||||
|
||||
|
||||
def verify_value(self):
|
||||
"""
|
||||
"""
|
||||
@@ -318,7 +312,6 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def button_press(self, widget, event):
|
||||
"""
|
||||
"""
|
||||
@@ -331,7 +324,6 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
self.__active_increment = True
|
||||
self.__increment_value()
|
||||
|
||||
|
||||
def button_release(self, widget, event):
|
||||
"""
|
||||
"""
|
||||
@@ -342,7 +334,6 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
|
||||
self.queue_draw()
|
||||
|
||||
|
||||
def motion_notify(self, widget, event):
|
||||
"""
|
||||
Drawing callback
|
||||
@@ -363,7 +354,6 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
|
||||
self.queue_draw()
|
||||
|
||||
|
||||
def expose(self, widget, event):
|
||||
"""
|
||||
Drawing callback
|
||||
@@ -381,7 +371,6 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def __draw(self):
|
||||
"""
|
||||
"""
|
||||
@@ -394,7 +383,7 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
|
||||
# draw line
|
||||
self.context.set_line_width(1)
|
||||
self.context.set_dash([1,2])
|
||||
self.context.set_dash([1, 2])
|
||||
self.context.move_to(self.__radius,
|
||||
yc + self.__radius)
|
||||
self.context.line_to(2 * xc - 5,
|
||||
@@ -402,7 +391,7 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
self.context.stroke()
|
||||
|
||||
# draw text
|
||||
self.context.set_dash([1,0])
|
||||
self.context.set_dash([1, 0])
|
||||
self.context.set_font_size(10)
|
||||
|
||||
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.stroke()
|
||||
|
||||
|
||||
def __button_is_clicked(self, pointer):
|
||||
"""
|
||||
"""
|
||||
@@ -440,7 +428,6 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __increment_value(self):
|
||||
"""
|
||||
"""
|
||||
@@ -453,20 +440,17 @@ class ControlVariableWidget(gtk.DrawingArea):
|
||||
gobject.timeout_add(self.__increment_time,
|
||||
self.__increment_value)
|
||||
|
||||
|
||||
def set_value_function(self, value):
|
||||
"""
|
||||
"""
|
||||
self.__value = value
|
||||
|
||||
|
||||
def set_update_function(self, update):
|
||||
"""
|
||||
"""
|
||||
self.__update = update
|
||||
|
||||
|
||||
|
||||
class ControlVariable(BWHBox):
|
||||
"""
|
||||
"""
|
||||
@@ -485,7 +469,6 @@ class ControlVariable(BWHBox):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -516,14 +499,12 @@ class ControlVariable(BWHBox):
|
||||
self.bw_pack_start_expand_fill(self.__control)
|
||||
self.bw_pack_start_noexpand_nofill(self.__right_button)
|
||||
|
||||
|
||||
def __pressed(self, widget, increment):
|
||||
"""
|
||||
"""
|
||||
self.__increment = True
|
||||
self.__increment_function(increment)
|
||||
|
||||
|
||||
def __increment_function(self, increment):
|
||||
"""
|
||||
"""
|
||||
@@ -536,15 +517,12 @@ class ControlVariable(BWHBox):
|
||||
self.__increment_function,
|
||||
increment)
|
||||
|
||||
|
||||
def __released(self, widget):
|
||||
"""
|
||||
"""
|
||||
self.__increment = False
|
||||
|
||||
|
||||
|
||||
|
||||
class ControlFisheye(BWVBox):
|
||||
"""
|
||||
"""
|
||||
@@ -559,7 +537,6 @@ class ControlFisheye(BWVBox):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -606,7 +583,6 @@ class ControlFisheye(BWVBox):
|
||||
|
||||
gobject.timeout_add(REFRESH_RATE, self.__update_fisheye)
|
||||
|
||||
|
||||
def __update_fisheye(self):
|
||||
"""
|
||||
"""
|
||||
@@ -648,7 +624,6 @@ class ControlFisheye(BWVBox):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def active_fisheye(self):
|
||||
"""
|
||||
"""
|
||||
@@ -656,13 +631,11 @@ class ControlFisheye(BWVBox):
|
||||
self.__change_ring()
|
||||
self.__change_interest()
|
||||
|
||||
|
||||
def deactive_fisheye(self):
|
||||
"""
|
||||
"""
|
||||
self.radialnet.set_fisheye(False)
|
||||
|
||||
|
||||
def __change_ring(self, widget=None):
|
||||
"""
|
||||
"""
|
||||
@@ -671,7 +644,6 @@ class ControlFisheye(BWVBox):
|
||||
else:
|
||||
self.__ring.set_value(self.radialnet.get_fisheye_ring())
|
||||
|
||||
|
||||
def __change_interest(self, widget=None):
|
||||
"""
|
||||
"""
|
||||
@@ -680,7 +652,6 @@ class ControlFisheye(BWVBox):
|
||||
else:
|
||||
self.__interest.set_value(self.radialnet.get_fisheye_interest())
|
||||
|
||||
|
||||
def __change_spread(self, widget=None):
|
||||
"""
|
||||
"""
|
||||
@@ -690,7 +661,6 @@ class ControlFisheye(BWVBox):
|
||||
self.__spread.set_value(self.radialnet.get_fisheye_spread())
|
||||
|
||||
|
||||
|
||||
class ControlInterpolation(BWExpander):
|
||||
"""
|
||||
"""
|
||||
@@ -703,14 +673,14 @@ class ControlInterpolation(BWExpander):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
self.__vbox = BWVBox()
|
||||
|
||||
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.__change_system,
|
||||
INTERPOLATION_CARTESIAN)
|
||||
@@ -741,7 +711,6 @@ class ControlInterpolation(BWExpander):
|
||||
|
||||
gobject.timeout_add(REFRESH_RATE, self.__update_animation)
|
||||
|
||||
|
||||
def __update_animation(self):
|
||||
"""
|
||||
"""
|
||||
@@ -755,7 +724,6 @@ class ControlInterpolation(BWExpander):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def __change_system(self, widget, value):
|
||||
"""
|
||||
"""
|
||||
@@ -769,7 +737,6 @@ class ControlInterpolation(BWExpander):
|
||||
else:
|
||||
self.__polar_radio.set_active(True)
|
||||
|
||||
|
||||
def __change_frames(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -777,7 +744,6 @@ class ControlInterpolation(BWExpander):
|
||||
self.__frames.set_value(self.radialnet.get_number_of_frames())
|
||||
|
||||
|
||||
|
||||
class ControlLayout(BWExpander):
|
||||
"""
|
||||
"""
|
||||
@@ -790,7 +756,6 @@ class ControlLayout(BWExpander):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -811,7 +776,6 @@ class ControlLayout(BWExpander):
|
||||
|
||||
self.__check_layout()
|
||||
|
||||
|
||||
def __check_layout(self):
|
||||
"""
|
||||
"""
|
||||
@@ -823,14 +787,12 @@ class ControlLayout(BWExpander):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def __force_update(self, widget):
|
||||
"""
|
||||
"""
|
||||
self.__fisheye_ring = self.radialnet.get_fisheye_ring()
|
||||
self.radialnet.update_layout()
|
||||
|
||||
|
||||
def __change_layout(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -841,7 +803,6 @@ class ControlLayout(BWExpander):
|
||||
self.__check_layout()
|
||||
|
||||
|
||||
|
||||
class ControlRingGap(BWVBox):
|
||||
"""
|
||||
"""
|
||||
@@ -854,7 +815,6 @@ class ControlRingGap(BWVBox):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
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.__lower_hbox)
|
||||
|
||||
|
||||
def __change_lower(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -886,7 +845,6 @@ class ControlRingGap(BWVBox):
|
||||
self.__adjustment.set_value(self.radialnet.get_min_ring_gap())
|
||||
|
||||
|
||||
|
||||
class ControlOptions(BWScrolledWindow):
|
||||
"""
|
||||
"""
|
||||
@@ -902,7 +860,6 @@ class ControlOptions(BWScrolledWindow):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -943,23 +900,23 @@ class ControlOptions(BWScrolledWindow):
|
||||
|
||||
gobject.timeout_add(REFRESH_RATE, self.__update_options)
|
||||
|
||||
|
||||
def __update_options(self):
|
||||
"""
|
||||
"""
|
||||
model = self.__liststore
|
||||
|
||||
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('latency')][0] = self.radialnet.get_show_latency()
|
||||
model[OPTIONS.index('ring')][0] = self.radialnet.get_show_ring()
|
||||
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
|
||||
|
||||
|
||||
def __change_option(self, cell, option, model):
|
||||
"""
|
||||
"""
|
||||
@@ -988,7 +945,6 @@ class ControlOptions(BWScrolledWindow):
|
||||
self.radialnet.set_slow_inout(model[option][0])
|
||||
|
||||
|
||||
|
||||
class ControlView(BWExpander):
|
||||
"""
|
||||
"""
|
||||
@@ -1002,7 +958,6 @@ class ControlView(BWExpander):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -1026,7 +981,6 @@ class ControlView(BWExpander):
|
||||
self.bw_add(self.__vbox)
|
||||
|
||||
|
||||
|
||||
class ControlNavigation(gtk.DrawingArea):
|
||||
"""
|
||||
"""
|
||||
@@ -1047,12 +1001,12 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
self.__move_position = (0, 0)
|
||||
self.__move_addition = [(-1, 0),
|
||||
(-1,-1),
|
||||
( 0,-1),
|
||||
( 1,-1),
|
||||
( 1, 0),
|
||||
( 1, 1),
|
||||
( 0, 1),
|
||||
(-1, -1),
|
||||
(0, -1),
|
||||
(1, -1),
|
||||
(1, 0),
|
||||
(1, 1),
|
||||
(0, 1),
|
||||
(-1, 1)]
|
||||
|
||||
self.__move_factor = 1
|
||||
@@ -1086,7 +1040,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
self.__rotate_node.set_coordinate(40, self.radialnet.get_rotation())
|
||||
|
||||
|
||||
def key_press(self, widget, event):
|
||||
"""
|
||||
"""
|
||||
@@ -1096,7 +1049,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def key_release(self, widget, event):
|
||||
"""
|
||||
"""
|
||||
@@ -1106,13 +1058,11 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def enter_notify(self, widget, event):
|
||||
"""
|
||||
"""
|
||||
return False
|
||||
|
||||
|
||||
def leave_notify(self, widget, event):
|
||||
"""
|
||||
"""
|
||||
@@ -1120,7 +1070,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def button_press(self, widget, event):
|
||||
"""
|
||||
Drawing callback
|
||||
@@ -1159,7 +1108,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def button_release(self, widget, event):
|
||||
"""
|
||||
Drawing callback
|
||||
@@ -1181,7 +1129,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def motion_notify(self, widget, event):
|
||||
"""
|
||||
Drawing callback
|
||||
@@ -1213,7 +1160,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def expose(self, widget, event):
|
||||
"""
|
||||
Drawing callback
|
||||
@@ -1231,7 +1177,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __draw_rotate_control(self):
|
||||
"""
|
||||
"""
|
||||
@@ -1251,14 +1196,14 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
self.context.stroke()
|
||||
|
||||
# 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.set_source_rgb(0.0, 0.0, 0.0)
|
||||
self.context.set_line_width(1)
|
||||
self.context.stroke()
|
||||
|
||||
# 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)
|
||||
|
||||
if self.__rotating == True:
|
||||
@@ -1274,14 +1219,13 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __draw_move_control(self):
|
||||
"""
|
||||
"""
|
||||
xc, yc = self.__center_of_widget
|
||||
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.set_source_rgb(0.0, 0.0, 0.0)
|
||||
self.context.set_line_width(1)
|
||||
@@ -1292,13 +1236,14 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
pc.set_coordinate(23, 45 * i)
|
||||
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.line_to(xc + x, yc - y)
|
||||
self.context.stroke()
|
||||
|
||||
self.context.set_dash([1,0])
|
||||
self.context.arc(xc + x, yc - y, self.__move_radius, 0, 2 * math.pi)
|
||||
self.context.set_dash([1, 0])
|
||||
self.context.arc(
|
||||
xc + x, yc - y, self.__move_radius, 0, 2 * math.pi)
|
||||
|
||||
if i == self.__moving:
|
||||
self.context.set_source_rgb(0.0, 0.0, 0.0)
|
||||
@@ -1322,7 +1267,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __draw(self):
|
||||
"""
|
||||
Drawing method
|
||||
@@ -1338,7 +1282,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __move_in_direction(self, direction):
|
||||
"""
|
||||
"""
|
||||
@@ -1360,7 +1303,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __rotate_is_clicked(self, pointer):
|
||||
"""
|
||||
"""
|
||||
@@ -1375,7 +1317,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __center_is_clicked(self, pointer):
|
||||
"""
|
||||
"""
|
||||
@@ -1388,7 +1329,6 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __move_is_clicked(self, pointer):
|
||||
"""
|
||||
"""
|
||||
@@ -1409,5 +1349,3 @@ class ControlNavigation(gtk.DrawingArea):
|
||||
return i
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
||||
@@ -126,7 +126,6 @@ from radialnet.core.Info import INFO
|
||||
from radialnet.gui.Image import Pixmaps
|
||||
|
||||
|
||||
|
||||
class AboutDialog(gtk.AboutDialog):
|
||||
"""
|
||||
"""
|
||||
@@ -146,7 +145,6 @@ class AboutDialog(gtk.AboutDialog):
|
||||
|
||||
self.connect('response', self.__destroy)
|
||||
|
||||
|
||||
def __destroy(self, dialog, id):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -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}$'
|
||||
|
||||
|
||||
|
||||
class HostsViewer(BWMainWindow):
|
||||
"""
|
||||
"""
|
||||
@@ -155,7 +154,6 @@ class HostsViewer(BWMainWindow):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -170,8 +168,6 @@ class HostsViewer(BWMainWindow):
|
||||
|
||||
self.add(self.__panel)
|
||||
|
||||
|
||||
|
||||
def change_notebook(self, node):
|
||||
"""
|
||||
"""
|
||||
@@ -187,7 +183,6 @@ class HostsViewer(BWMainWindow):
|
||||
self.__panel.add2(self.__view)
|
||||
|
||||
|
||||
|
||||
class HostsList(gtk.ScrolledWindow):
|
||||
"""
|
||||
"""
|
||||
@@ -203,7 +198,6 @@ class HostsList(gtk.ScrolledWindow):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -239,16 +233,16 @@ class HostsList(gtk.ScrolledWindow):
|
||||
|
||||
column = gtk.TreeViewColumn(HOSTS_HEADER[i],
|
||||
self.__cell,
|
||||
text = i)
|
||||
text=i)
|
||||
|
||||
self.__hosts_column.append(column)
|
||||
|
||||
self.__hosts_column[i].set_reorderable(True)
|
||||
self.__hosts_column[i].set_resizable(True)
|
||||
self.__hosts_column[i].set_attributes(self.__cell,
|
||||
text = i,
|
||||
background = 3,
|
||||
editable = 4)
|
||||
text=i,
|
||||
background=3,
|
||||
editable=4)
|
||||
|
||||
self.__hosts_treeview.append_column(self.__hosts_column[2])
|
||||
|
||||
@@ -262,7 +256,6 @@ class HostsList(gtk.ScrolledWindow):
|
||||
self.__hosts_treeview.set_cursor((0,))
|
||||
self.__cursor_callback(self.__hosts_treeview)
|
||||
|
||||
|
||||
def __cursor_callback(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -276,7 +269,6 @@ class HostsList(gtk.ScrolledWindow):
|
||||
|
||||
self.__parent.change_notebook(node)
|
||||
|
||||
|
||||
def __host_sort(self, treemodel, iter1, iter2):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -128,7 +128,7 @@ from zenmapCore.Paths import Path
|
||||
|
||||
|
||||
FORMAT_RGBA = 4
|
||||
FORMAT_RGB = 3
|
||||
FORMAT_RGB = 3
|
||||
|
||||
|
||||
def get_pixels_for_cairo_image_surface(pixbuf):
|
||||
@@ -144,16 +144,16 @@ def get_pixels_for_cairo_image_surface(pixbuf):
|
||||
j = 0
|
||||
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:
|
||||
a = pixbuf.get_pixels()[i + FORMAT_RGBA - 1]
|
||||
elif format == FORMAT_RGB:
|
||||
a = '\xff'
|
||||
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
|
||||
j += FORMAT_RGBA
|
||||
@@ -170,13 +170,11 @@ class Image:
|
||||
self.__path = path
|
||||
self.__cache = dict()
|
||||
|
||||
|
||||
def set_path(self, path):
|
||||
"""
|
||||
"""
|
||||
self.__path = path
|
||||
|
||||
|
||||
def get_pixbuf(self, icon, image_type='png'):
|
||||
"""
|
||||
"""
|
||||
@@ -186,11 +184,11 @@ class Image:
|
||||
if icon + image_type not in self.__cache.keys():
|
||||
|
||||
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]
|
||||
|
||||
|
||||
def get_icon(self, icon, image_type='png'):
|
||||
"""
|
||||
"""
|
||||
@@ -200,7 +198,6 @@ class Image:
|
||||
return os.path.join(self.__path, icon + "." + image_type)
|
||||
|
||||
|
||||
|
||||
class Pixmaps(Image):
|
||||
"""
|
||||
"""
|
||||
@@ -210,7 +207,6 @@ class Pixmaps(Image):
|
||||
Image.__init__(self, os.path.join(Path.pixmaps_dir, "radialnet"))
|
||||
|
||||
|
||||
|
||||
class Icons(Image):
|
||||
"""
|
||||
"""
|
||||
@@ -220,7 +216,6 @@ class Icons(Image):
|
||||
Image.__init__(self, os.path.join(Path.pixmaps_dir, "radialnet"))
|
||||
|
||||
|
||||
|
||||
class Application(Image):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -129,27 +129,27 @@ from radialnet.bestwidgets.labels 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')]
|
||||
|
||||
SERVICE_COLORS = {'open' : '#ffd5d5',
|
||||
'closed' : '#d5ffd5',
|
||||
'filtered' : '#ffffd5',
|
||||
'unfiltered' : '#ffd5d5',
|
||||
'open|filtered' : '#ffd5d5',
|
||||
'closed|filtered' : '#d5ffd5'}
|
||||
SERVICE_COLORS = {'open': '#ffd5d5',
|
||||
'closed': '#d5ffd5',
|
||||
'filtered': '#ffffd5',
|
||||
'unfiltered': '#ffd5d5',
|
||||
'open|filtered': '#ffd5d5',
|
||||
'closed|filtered': '#d5ffd5'}
|
||||
UNKNOWN_SERVICE_COLOR = '#d5d5d5'
|
||||
|
||||
TRACE_HEADER = [_('TTL'), _('RTT'), _('IP'), _('Hostname')]
|
||||
|
||||
TRACE_TEXT = _("""\
|
||||
Traceroute on port <b>%s/%s</b> totalized <b>%d</b> known hops.\
|
||||
""")
|
||||
TRACE_TEXT = _(
|
||||
"Traceroute on port <b>%s/%s</b> totalized <b>%d</b> known hops.")
|
||||
|
||||
NO_TRACE_TEXT = _("No traceroute information available.")
|
||||
|
||||
HOP_COLOR = {'known' : '#ffffff',
|
||||
'unknown' : '#cccccc'}
|
||||
HOP_COLOR = {'known': '#ffffff',
|
||||
'unknown': '#cccccc'}
|
||||
|
||||
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".\
|
||||
""")
|
||||
|
||||
|
||||
def get_service_color(state):
|
||||
color = SERVICE_COLORS.get(state)
|
||||
if color is None:
|
||||
@@ -182,7 +183,6 @@ class NodeNotebook(gtk.Notebook):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -197,7 +197,6 @@ class NodeNotebook(gtk.Notebook):
|
||||
self.append_page(self.__trace_page, BWLabel(_('Traceroute')))
|
||||
|
||||
|
||||
|
||||
class ServicesPage(gtk.Notebook):
|
||||
"""
|
||||
"""
|
||||
@@ -213,7 +212,6 @@ class ServicesPage(gtk.Notebook):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -256,13 +254,13 @@ class ServicesPage(gtk.Notebook):
|
||||
|
||||
color = get_service_color(port['state']['state'])
|
||||
|
||||
if port['service'].has_key('name'):
|
||||
if 'name' in port['service']:
|
||||
service_name = port['service']['name']
|
||||
|
||||
else:
|
||||
service_name = _('<unknown>')
|
||||
|
||||
if port['service'].has_key('method'):
|
||||
if 'method' in port['service']:
|
||||
service_method = port['service']['method']
|
||||
|
||||
else:
|
||||
@@ -330,7 +328,7 @@ class ServicesPage(gtk.Notebook):
|
||||
|
||||
column = gtk.TreeViewColumn(PORTS_HEADER[i],
|
||||
self.__cell,
|
||||
text = i)
|
||||
text=i)
|
||||
|
||||
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_sort_column_id(i)
|
||||
self.__ports_column[i].set_attributes(self.__cell,
|
||||
text = i,
|
||||
background = 5,
|
||||
editable = 6)
|
||||
text=i,
|
||||
background=5,
|
||||
editable=6)
|
||||
|
||||
self.__ports_treeview.append_column(self.__ports_column[i])
|
||||
|
||||
@@ -364,12 +362,9 @@ class ServicesPage(gtk.Notebook):
|
||||
color = get_service_color(xports['state'])
|
||||
number_of_xports += xports['count']
|
||||
|
||||
reference = self.__xports_store.append(None,
|
||||
[xports['count'],
|
||||
xports['state'],
|
||||
", ".join(xports['reason']),
|
||||
color,
|
||||
True])
|
||||
reference = self.__xports_store.append(
|
||||
None, [xports['count'], xports['state'],
|
||||
", ".join(xports['reason']), color, True])
|
||||
|
||||
for xreason in xports['all_reason']:
|
||||
self.__xports_store.append(reference,
|
||||
@@ -385,7 +380,7 @@ class ServicesPage(gtk.Notebook):
|
||||
|
||||
column = gtk.TreeViewColumn(EXTRAPORTS_HEADER[i],
|
||||
self.__cell,
|
||||
text = i)
|
||||
text=i)
|
||||
|
||||
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_sort_column_id(i)
|
||||
self.__xports_column[i].set_attributes(self.__cell,
|
||||
text = i,
|
||||
background = 3,
|
||||
editable = 4)
|
||||
text=i,
|
||||
background=3,
|
||||
editable=4)
|
||||
|
||||
self.__xports_treeview.append_column(self.__xports_column[i])
|
||||
|
||||
@@ -411,7 +406,6 @@ class ServicesPage(gtk.Notebook):
|
||||
if len(self.__text) > 0:
|
||||
self.__select_combobox.set_active(0)
|
||||
|
||||
|
||||
def __change_text_value(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -433,7 +427,6 @@ class SystemPage(BWScrolledWindow):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -516,7 +509,8 @@ class SystemPage(BWScrolledWindow):
|
||||
|
||||
sequences = self.__node.get_info('sequences')
|
||||
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
|
||||
self.__os = gtk.Notebook()
|
||||
@@ -525,7 +519,7 @@ class SystemPage(BWScrolledWindow):
|
||||
|
||||
if os != None:
|
||||
|
||||
if os.has_key('matches'):
|
||||
if 'matches' in os:
|
||||
|
||||
self.__match_scroll = BWScrolledWindow()
|
||||
|
||||
@@ -550,15 +544,15 @@ class SystemPage(BWScrolledWindow):
|
||||
|
||||
column = gtk.TreeViewColumn(OSMATCH_HEADER[i],
|
||||
self.__cell,
|
||||
text = i)
|
||||
text=i)
|
||||
|
||||
self.__match_column.append(column)
|
||||
|
||||
self.__match_column[i].set_reorderable(True)
|
||||
self.__match_column[i].set_resizable(True)
|
||||
self.__match_column[i].set_attributes(self.__cell,
|
||||
text = i,
|
||||
editable = 3)
|
||||
text=i,
|
||||
editable=3)
|
||||
|
||||
self.__match_column[i].set_sort_column_id(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')))
|
||||
|
||||
if os.has_key('classes'):
|
||||
if 'classes' in os:
|
||||
|
||||
self.__class_scroll = BWScrolledWindow()
|
||||
|
||||
@@ -584,7 +578,7 @@ class SystemPage(BWScrolledWindow):
|
||||
|
||||
os_gen = ''
|
||||
|
||||
if os_class.has_key('os_gen'):
|
||||
if 'os_gen' in os_class:
|
||||
os_gen = os_class['os_gen']
|
||||
|
||||
self.__class_store.append([os_class['accuracy'],
|
||||
@@ -600,15 +594,15 @@ class SystemPage(BWScrolledWindow):
|
||||
|
||||
column = gtk.TreeViewColumn(OSCLASS_HEADER[i],
|
||||
self.__cell,
|
||||
text = i)
|
||||
text=i)
|
||||
|
||||
self.__class_column.append(column)
|
||||
|
||||
self.__class_column[i].set_reorderable(True)
|
||||
self.__class_column[i].set_resizable(True)
|
||||
self.__class_column[i].set_attributes(self.__cell,
|
||||
text = i,
|
||||
editable = 5)
|
||||
text=i,
|
||||
editable=5)
|
||||
|
||||
self.__class_column[i].set_sort_column_id(i)
|
||||
self.__class_treeview.append_column(self.__class_column[i])
|
||||
@@ -630,7 +624,7 @@ class SystemPage(BWScrolledWindow):
|
||||
|
||||
self.__fp_vbox = BWVBox()
|
||||
|
||||
if os.has_key('used_ports'):
|
||||
if 'used_ports' in os:
|
||||
|
||||
used_ports = os['used_ports']
|
||||
|
||||
@@ -692,7 +686,8 @@ class SystemPage(BWScrolledWindow):
|
||||
tcp_note.set_selectable(True)
|
||||
tcp_note.set_line_wrap(False)
|
||||
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)
|
||||
|
||||
@@ -733,8 +728,6 @@ class SystemPage(BWScrolledWindow):
|
||||
return table
|
||||
|
||||
|
||||
|
||||
|
||||
class TraceroutePage(BWVBox):
|
||||
"""
|
||||
"""
|
||||
@@ -748,7 +741,6 @@ class TraceroutePage(BWVBox):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -805,23 +797,22 @@ class TraceroutePage(BWVBox):
|
||||
HOP_COLOR['unknown'],
|
||||
True])
|
||||
|
||||
|
||||
self.__trace_column = list()
|
||||
|
||||
for i in range(len(TRACE_HEADER)):
|
||||
|
||||
column = gtk.TreeViewColumn(TRACE_HEADER[i],
|
||||
self.__cell,
|
||||
text = i)
|
||||
text=i)
|
||||
|
||||
self.__trace_column.append(column)
|
||||
|
||||
self.__trace_column[i].set_reorderable(True)
|
||||
self.__trace_column[i].set_resizable(True)
|
||||
self.__trace_column[i].set_attributes(self.__cell,
|
||||
text = i,
|
||||
background = 4,
|
||||
editable = 5)
|
||||
text=i,
|
||||
background=4,
|
||||
editable=5)
|
||||
|
||||
self.__trace_treeview.append_column(self.__trace_column[i])
|
||||
|
||||
|
||||
@@ -151,7 +151,6 @@ class NodeWindow(BWWindow):
|
||||
self.__icon = Application()
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -168,7 +167,8 @@ class NodeWindow(BWWindow):
|
||||
self.__color_image.set_from_file(self.__icon.get_icon('border'))
|
||||
self.__color_box.add(self.__color_image)
|
||||
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))
|
||||
|
||||
# title with the node ip and hostname
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -133,8 +133,8 @@ TYPES = ((_("By extension"), None, None),
|
||||
(_("PNG"), RadialNet.FILE_TYPE_PNG, ".png"),
|
||||
(_("PostScript"), RadialNet.FILE_TYPE_PS, ".ps"),
|
||||
(_("SVG"), RadialNet.FILE_TYPE_SVG, ".svg"))
|
||||
# Build a reverse index of extensions to file types, for the "By extension" file
|
||||
# type.
|
||||
# Build a reverse index of extensions to file types, for the "By extension"
|
||||
# file type.
|
||||
EXTENSIONS = {}
|
||||
for type in TYPES:
|
||||
if type[2] is not None:
|
||||
@@ -181,7 +181,8 @@ class SaveDialog(zenmapGUI.FileChoosers.UnicodeFileChooserDialog):
|
||||
self.set_current_folder(dir)
|
||||
|
||||
# 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:
|
||||
# Change the filename to use the recommended extension.
|
||||
root, ext = os.path.splitext(basename)
|
||||
@@ -197,15 +198,17 @@ class SaveDialog(zenmapGUI.FileChoosers.UnicodeFileChooserDialog):
|
||||
if ext == "":
|
||||
filename = self.get_filename() or ""
|
||||
dir, basename = os.path.split(filename)
|
||||
alert = HIGAlertDialog(message_format=_("No filename extension"),
|
||||
secondary_text=_("""\
|
||||
The filename "%s" does not have an extension, and no specific file type was chosen.
|
||||
Enter a known extension or select the file type from the list.\
|
||||
""" % basename))
|
||||
alert = HIGAlertDialog(
|
||||
message_format=_("No filename extension"),
|
||||
secondary_text=_("""\
|
||||
The filename "%s" does not have an extension, \
|
||||
and no specific file type was chosen.
|
||||
Enter a known extension or select the file type from the list.""" % basename))
|
||||
|
||||
else:
|
||||
alert = HIGAlertDialog(message_format=_("Unknown filename extension"),
|
||||
secondary_text=_("""\
|
||||
alert = HIGAlertDialog(
|
||||
message_format=_("Unknown filename extension"),
|
||||
secondary_text=_("""\
|
||||
There is no file type known for the filename extension "%s".
|
||||
Enter a known extension or select the file type from the list.\
|
||||
""") % 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]
|
||||
|
||||
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:
|
||||
# Guess based on extension.
|
||||
return EXTENSIONS.get(self.__get_extension())
|
||||
|
||||
@@ -136,7 +136,6 @@ HIDE = False
|
||||
REFRESH_RATE = 500
|
||||
|
||||
|
||||
|
||||
class ToolsMenu(gtk.Menu):
|
||||
"""
|
||||
"""
|
||||
@@ -149,7 +148,6 @@ class ToolsMenu(gtk.Menu):
|
||||
|
||||
self.__create_items()
|
||||
|
||||
|
||||
def __create_items(self):
|
||||
"""
|
||||
"""
|
||||
@@ -163,7 +161,6 @@ class ToolsMenu(gtk.Menu):
|
||||
|
||||
self.__hosts.show_all()
|
||||
|
||||
|
||||
def __hosts_viewer_callback(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -171,20 +168,17 @@ class ToolsMenu(gtk.Menu):
|
||||
window.show_all()
|
||||
window.set_keep_above(True)
|
||||
|
||||
|
||||
def enable_dependents(self):
|
||||
"""
|
||||
"""
|
||||
self.__hosts.set_sensitive(True)
|
||||
|
||||
|
||||
def disable_dependents(self):
|
||||
"""
|
||||
"""
|
||||
self.__hosts.set_sensitive(False)
|
||||
|
||||
|
||||
|
||||
class Toolbar(gtk.HBox):
|
||||
"""
|
||||
"""
|
||||
@@ -213,7 +207,6 @@ class Toolbar(gtk.HBox):
|
||||
|
||||
self.__create_widgets()
|
||||
|
||||
|
||||
def __create_widgets(self):
|
||||
"""
|
||||
"""
|
||||
@@ -233,7 +226,8 @@ class Toolbar(gtk.HBox):
|
||||
self.__hosts_button = BWStockButton(gtk.STOCK_INDEX, _("Hosts Viewer"))
|
||||
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.set_active(False)
|
||||
|
||||
@@ -273,7 +267,6 @@ class Toolbar(gtk.HBox):
|
||||
self.pack_start(self.__control, False)
|
||||
self.pack_end(self.__save_button, False)
|
||||
|
||||
|
||||
def disable_controls(self):
|
||||
"""
|
||||
"""
|
||||
@@ -282,7 +275,6 @@ class Toolbar(gtk.HBox):
|
||||
self.__hosts_button.set_sensitive(False)
|
||||
#self.__tools_menu.disable_dependents()
|
||||
|
||||
|
||||
def enable_controls(self):
|
||||
"""
|
||||
"""
|
||||
@@ -291,13 +283,11 @@ class Toolbar(gtk.HBox):
|
||||
self.__hosts_button.set_sensitive(True)
|
||||
#self.__tools_menu.enable_dependents()
|
||||
|
||||
|
||||
def __tools_callback(self, widget):
|
||||
"""
|
||||
"""
|
||||
self.__tools_menu.popup(None, None, None, 1, 0)
|
||||
|
||||
|
||||
def __hosts_viewer_callback(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -305,7 +295,6 @@ class Toolbar(gtk.HBox):
|
||||
window.show_all()
|
||||
window.set_keep_above(True)
|
||||
|
||||
|
||||
def __save_image_callback(self, widget):
|
||||
"""
|
||||
"""
|
||||
@@ -330,7 +319,6 @@ class Toolbar(gtk.HBox):
|
||||
|
||||
self.__save_chooser.hide()
|
||||
|
||||
|
||||
def __control_callback(self, widget=None):
|
||||
"""
|
||||
"""
|
||||
@@ -340,7 +328,6 @@ class Toolbar(gtk.HBox):
|
||||
else:
|
||||
self.__control_widget.hide()
|
||||
|
||||
|
||||
def __fisheye_callback(self, widget=None):
|
||||
"""
|
||||
"""
|
||||
@@ -356,14 +343,12 @@ class Toolbar(gtk.HBox):
|
||||
self.__fisheye_widget.deactive_fisheye()
|
||||
self.__fisheye_widget.hide()
|
||||
|
||||
|
||||
def __about_callback(self, widget):
|
||||
"""
|
||||
"""
|
||||
self.__about_dialog = AboutDialog()
|
||||
self.__about_dialog.show_all()
|
||||
|
||||
|
||||
def __fullscreen_callback(self, widget=None):
|
||||
"""
|
||||
"""
|
||||
@@ -372,4 +357,3 @@ class Toolbar(gtk.HBox):
|
||||
|
||||
else:
|
||||
self.__window.unfullscreen()
|
||||
|
||||
|
||||
@@ -118,4 +118,3 @@
|
||||
# * Nmap, and also available from https://svn.nmap.org/nmap/COPYING *
|
||||
# * *
|
||||
# ***************************************************************************/
|
||||
|
||||
|
||||
@@ -118,4 +118,3 @@
|
||||
# * Nmap, and also available from https://svn.nmap.org/nmap/COPYING *
|
||||
# * *
|
||||
# ***************************************************************************/
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ def is_in_circle(point, radius=1, center=(0, 0)):
|
||||
x, y = point
|
||||
a, b = center
|
||||
|
||||
if ((x - a)**2 + (y - b)**2) <= (radius**2):
|
||||
if ((x - a) ** 2 + (y - b) ** 2) <= (radius ** 2):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -135,16 +135,17 @@ BASE_RADIUS = 5.5
|
||||
NONE_RADIUS = 4.5
|
||||
|
||||
|
||||
|
||||
def set_node_info(node, 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):
|
||||
"""This is a minimal implementation of HostInfo, sufficient to
|
||||
@@ -164,15 +165,18 @@ class TracerouteHostInfo(object):
|
||||
def get_best_osmatch(self):
|
||||
if not self.osmatches:
|
||||
return None
|
||||
|
||||
def osmatch_key(osmatch):
|
||||
try:
|
||||
return -float(osmatch["accuracy"])
|
||||
except ValueError:
|
||||
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 [])
|
||||
|
||||
|
||||
def make_graph_from_hosts(hosts):
|
||||
#hosts = parser.get_root().search_children('host', deep=True)
|
||||
graph = Graph()
|
||||
@@ -187,7 +191,8 @@ def make_graph_from_hosts(hosts):
|
||||
localhost.ip = {"addr": "127.0.0.1/8", "type": "ipv4"}
|
||||
localhost.hostname = "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
|
||||
endpoints = {}
|
||||
@@ -219,10 +224,14 @@ def make_graph_from_hosts(hosts):
|
||||
nodes.append(node)
|
||||
|
||||
hop_host = TracerouteHostInfo()
|
||||
hop_host.ip = {"addr": hop["ipaddr"], "type": "", "vendor": ""}
|
||||
node.set_draw_info({"valid":True})
|
||||
node.set_draw_info({"color":(1,1,1),
|
||||
"radius":NONE_RADIUS})
|
||||
hop_host.ip = {
|
||||
"addr": hop["ipaddr"],
|
||||
"type": "",
|
||||
"vendor": ""
|
||||
}
|
||||
node.set_draw_info({"valid": True})
|
||||
node.set_draw_info({"color": (1, 1, 1),
|
||||
"radius": NONE_RADIUS})
|
||||
|
||||
if hop["host"] != "":
|
||||
hop_host.hostname = hop["host"]
|
||||
@@ -240,8 +249,9 @@ def make_graph_from_hosts(hosts):
|
||||
node = NetNode()
|
||||
nodes.append(node)
|
||||
|
||||
node.set_draw_info({"valid":False})
|
||||
node.set_draw_info({"color":(1,1,1), "radius":NONE_RADIUS})
|
||||
node.set_draw_info({"valid": False})
|
||||
node.set_draw_info(
|
||||
{"color": (1, 1, 1), "radius": NONE_RADIUS})
|
||||
|
||||
graph.set_connection(node, prev_node)
|
||||
|
||||
@@ -259,12 +269,12 @@ def make_graph_from_hosts(hosts):
|
||||
node = NetNode()
|
||||
nodes.append(node)
|
||||
|
||||
node.set_draw_info({"no_route":True})
|
||||
node.set_draw_info({"no_route": True})
|
||||
|
||||
graph.set_connection(node, endpoints[host])
|
||||
|
||||
node.set_draw_info({"valid":True})
|
||||
node.set_draw_info({"scanned":True})
|
||||
node.set_draw_info({"valid": True})
|
||||
node.set_draw_info({"scanned": True})
|
||||
set_node_info(node, host)
|
||||
node_cache[node.get_info("ip")] = node
|
||||
|
||||
|
||||
@@ -124,7 +124,6 @@ from radialnet.util.geometry import *
|
||||
import math
|
||||
|
||||
|
||||
|
||||
def ipv4_compare(ip1, ip2):
|
||||
"""
|
||||
"""
|
||||
@@ -174,5 +173,7 @@ def sort_children_by_angle(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
|
||||
|
||||
143
zenmap/setup.py
143
zenmap/setup.py
@@ -135,7 +135,8 @@ from glob import glob
|
||||
from stat import *
|
||||
|
||||
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
|
||||
# uninstall command can remove them.
|
||||
@@ -154,6 +155,7 @@ misc_dir = os.path.join(data_dir, 'misc')
|
||||
# Where to install .desktop files.
|
||||
desktop_dir = os.path.join('share', 'applications')
|
||||
|
||||
|
||||
def mo_find(result, dirname, fnames):
|
||||
files = []
|
||||
for f in fnames:
|
||||
@@ -164,29 +166,31 @@ def mo_find(result, dirname, fnames):
|
||||
if files:
|
||||
result.append((dirname, files))
|
||||
|
||||
################################################################################
|
||||
###############################################################################
|
||||
# Installation variables
|
||||
|
||||
data_files = [ (pixmaps_dir, glob(os.path.join(pixmaps_dir, '*.gif')) +
|
||||
glob(os.path.join(pixmaps_dir, '*.png'))),
|
||||
data_files = [
|
||||
(pixmaps_dir, glob(os.path.join(pixmaps_dir, '*.gif')) +
|
||||
glob(os.path.join(pixmaps_dir, '*.png'))),
|
||||
|
||||
(os.path.join(pixmaps_dir, "radialnet"),
|
||||
glob(os.path.join(pixmaps_dir, "radialnet", '*.png'))),
|
||||
(os.path.join(pixmaps_dir, "radialnet"),
|
||||
glob(os.path.join(pixmaps_dir, "radialnet", '*.png'))),
|
||||
|
||||
(config_dir, [os.path.join(config_dir, APP_NAME + '.conf')] +
|
||||
[os.path.join(config_dir, 'scan_profile.usp')] +
|
||||
[os.path.join(config_dir, APP_NAME + '_version')]),
|
||||
(config_dir, [os.path.join(config_dir, APP_NAME + '.conf'),
|
||||
os.path.join(config_dir, 'scan_profile.usp'),
|
||||
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
|
||||
os.path.walk(locale_dir, mo_find, data_files)
|
||||
|
||||
|
||||
# path_startswith and path_strip_prefix are used to deal with the installation
|
||||
# root (--root option, also known as DESTDIR).
|
||||
|
||||
def path_startswith(path, prefix):
|
||||
"""Returns True if path starts with prefix. It's a little more intelligent
|
||||
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)
|
||||
return path.startswith(prefix)
|
||||
|
||||
|
||||
def path_strip_prefix(path, prefix):
|
||||
"""Return path stripped of its directory prefix if it starts with prefix,
|
||||
otherwise return path unmodified. This only works correctly with Unix paths;
|
||||
for example it will not replace the drive letter on a Windows path.
|
||||
otherwise return path unmodified. This only works correctly with Unix
|
||||
paths; for example it will not replace the drive letter on a Windows path.
|
||||
Examples:
|
||||
>>> path_strip_prefix('/tmp/destdir/usr/bin', '/tmp/destdir')
|
||||
'/usr/bin'
|
||||
@@ -221,14 +226,16 @@ def path_strip_prefix(path, prefix):
|
||||
assert os.path.isabs(path) == absolute
|
||||
return path
|
||||
|
||||
################################################################################
|
||||
###############################################################################
|
||||
# Distutils subclasses
|
||||
|
||||
|
||||
class my_install(install):
|
||||
def finalize_options(self):
|
||||
# Ubuntu's python2.6-2.6.4-0ubuntu3 package changes sys.prefix in
|
||||
# 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
|
||||
install.finalize_options(self)
|
||||
|
||||
@@ -252,14 +259,17 @@ class my_install(install):
|
||||
# Recursively include all the directories in data_dir (share/zenmap).
|
||||
# This is mainly for convenience in listing locale directories.
|
||||
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:
|
||||
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
|
||||
|
||||
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 = """\
|
||||
#!/usr/bin/env python
|
||||
@@ -267,26 +277,28 @@ import errno, os, os.path, sys
|
||||
|
||||
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':
|
||||
print 'Not uninstalling.'
|
||||
sys.exit(0)
|
||||
|
||||
""" % {'name':APP_DISPLAY_NAME, 'version':VERSION}
|
||||
""" % {'name': APP_DISPLAY_NAME, 'version': VERSION}
|
||||
|
||||
installed_files = []
|
||||
for output in self.get_installed_files():
|
||||
if self.root is not None:
|
||||
# If we have a root (DESTDIR), we need to strip it off the front
|
||||
# of paths so the uninstaller runs on the target host. The path
|
||||
# manipulations are tricky, but made easier because the
|
||||
# uninstaller only has to run on Unix.
|
||||
# If we have a root (DESTDIR), we need to strip it off the
|
||||
# front of paths so the uninstaller runs on the target host.
|
||||
# The path manipulations are tricky, but made easier because
|
||||
# the uninstaller only has to run on Unix.
|
||||
if not path_startswith(output, self.root):
|
||||
# This should never happen (everything gets installed inside
|
||||
# the root), but if it does, be safe and don't delete
|
||||
# anything.
|
||||
uninstaller += "print '%s was not installed inside the root %s; skipping.'\n" % (output, self.root)
|
||||
# This should never happen (everything gets installed
|
||||
# inside the root), but if it does, be safe and don't
|
||||
# delete anything.
|
||||
uninstaller += ("print '%s was not installed inside "
|
||||
"the root %s; skipping.'\n" % (output, self.root))
|
||||
continue
|
||||
output = path_strip_prefix(output, self.root)
|
||||
assert os.path.isabs(output)
|
||||
@@ -356,7 +368,8 @@ for dir in dirs:
|
||||
lines[i] = "INSTALL_LIB = %s\n" % repr(modules_dir)
|
||||
break
|
||||
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.writelines(lines)
|
||||
@@ -380,16 +393,17 @@ for dir in dirs:
|
||||
S_IRGRP | \
|
||||
S_IROTH)
|
||||
|
||||
|
||||
def fix_paths(self):
|
||||
"""Replace some hardcoded paths to match where files were installed."""
|
||||
interesting_paths = {"CONFIG_DIR": os.path.join(self.saved_prefix, config_dir),
|
||||
"DOCS_DIR": os.path.join(self.saved_prefix, docs_dir),
|
||||
"LOCALE_DIR": os.path.join(self.saved_prefix, locale_dir),
|
||||
"MISC_DIR": os.path.join(self.saved_prefix, misc_dir),
|
||||
"PIXMAPS_DIR": os.path.join(self.saved_prefix, pixmaps_dir),
|
||||
# See $(nmapdatadir) in nmap/Makefile.in.
|
||||
"NMAPDATADIR": os.path.join(self.saved_prefix, "share", "nmap"),}
|
||||
interesting_paths = {
|
||||
"CONFIG_DIR": os.path.join(self.saved_prefix, config_dir),
|
||||
"DOCS_DIR": os.path.join(self.saved_prefix, docs_dir),
|
||||
"LOCALE_DIR": os.path.join(self.saved_prefix, locale_dir),
|
||||
"MISC_DIR": os.path.join(self.saved_prefix, misc_dir),
|
||||
"PIXMAPS_DIR": os.path.join(self.saved_prefix, pixmaps_dir),
|
||||
# See $(nmapdatadir) in nmap/Makefile.in.
|
||||
"NMAPDATADIR": os.path.join(self.saved_prefix, "share", "nmap")
|
||||
}
|
||||
|
||||
# Find and read the Paths.py file.
|
||||
pcontent = ""
|
||||
@@ -417,8 +431,10 @@ for dir in dirs:
|
||||
# Rewrite the zenmap.desktop and zenmap-root.desktop files to point to
|
||||
# the installed locations of the su-to-zenmap.sh script and application
|
||||
# icon.
|
||||
su_filename = os.path.join(self.saved_prefix, data_dir, "su-to-zenmap.sh")
|
||||
icon_filename = os.path.join(self.saved_prefix, pixmaps_dir, "zenmap.png")
|
||||
su_filename = os.path.join(
|
||||
self.saved_prefix, data_dir, "su-to-zenmap.sh")
|
||||
icon_filename = os.path.join(
|
||||
self.saved_prefix, pixmaps_dir, "zenmap.png")
|
||||
|
||||
desktop_filename = None
|
||||
root_desktop_filename = None
|
||||
@@ -442,7 +458,9 @@ for dir in dirs:
|
||||
df = open(root_desktop_filename, "r")
|
||||
dcontent = df.read()
|
||||
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)
|
||||
regex = re.compile("^(Icon *= *).*$", re.MULTILINE)
|
||||
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
|
||||
newline characters are not handled."""
|
||||
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")
|
||||
try:
|
||||
for output in self.get_installed_files():
|
||||
@@ -465,12 +484,14 @@ for dir in dirs:
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
|
||||
class my_uninstall(Command):
|
||||
"""A distutils command that performs uninstallation. It reads the list of
|
||||
installed files written by the install command."""
|
||||
|
||||
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 = []
|
||||
|
||||
def initialize_options(self):
|
||||
@@ -485,7 +506,8 @@ class my_uninstall(Command):
|
||||
f = open(INSTALLED_FILES_NAME, "r")
|
||||
except IOError, e:
|
||||
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
|
||||
installed_files = [file.rstrip("\n") for file in f.readlines()]
|
||||
f.close()
|
||||
@@ -510,7 +532,7 @@ class my_uninstall(Command):
|
||||
# Delete the directories. First reverse-sort the normalized paths by
|
||||
# length so that child directories are deleted before their parents.
|
||||
dirs = [os.path.normpath(dir) for dir in dirs]
|
||||
dirs.sort(key = len, reverse = True)
|
||||
dirs.sort(key=len, reverse=True)
|
||||
for dir in dirs:
|
||||
try:
|
||||
log.info("Removing the directory '%s'." % dir)
|
||||
@@ -523,8 +545,8 @@ class my_uninstall(Command):
|
||||
log.error(str(e))
|
||||
|
||||
# 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
|
||||
# the operations.
|
||||
# example py2exe needs special handling.) These arguments are common between
|
||||
# all the operations.
|
||||
COMMON_SETUP_ARGS = {
|
||||
'name': APP_NAME,
|
||||
'license': 'Nmap License (http://nmap.org/book/man-legal.html)',
|
||||
@@ -533,14 +555,14 @@ COMMON_SETUP_ARGS = {
|
||||
'author': 'Nmap Project',
|
||||
'maintainer': 'Nmap Project',
|
||||
'description': "%s frontend and results viewer" % NMAP_DISPLAY_NAME,
|
||||
'long_description': """\
|
||||
%s is an %s frontend \
|
||||
that is really useful for advanced users and easy to be used by newbies.""" \
|
||||
% (APP_DISPLAY_NAME, NMAP_DISPLAY_NAME),
|
||||
'long_description': "%s is an %s frontend that is really useful"
|
||||
"for advanced users and easy to be used by newbies." % (
|
||||
APP_DISPLAY_NAME, NMAP_DISPLAY_NAME),
|
||||
'version': VERSION,
|
||||
'scripts': [APP_NAME],
|
||||
'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,
|
||||
}
|
||||
|
||||
@@ -555,17 +577,24 @@ if 'py2exe' in sys.argv:
|
||||
WINDOWS_SETUP_ARGS = {
|
||||
'zipfile': 'py2exe/library.zip',
|
||||
'name': APP_NAME,
|
||||
'windows': [{"script": APP_NAME,
|
||||
"icon_resources": [(1, "install_scripts/windows/nmap-eye.ico")]}],
|
||||
'windows': [{
|
||||
"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
|
||||
# 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": {
|
||||
"compressed": 1,
|
||||
"optimize": 2,
|
||||
"packages": ["encodings"],
|
||||
"includes": ["pango", "atk", "gobject", "gio", "pickle", "bz2", "encodings", "encodings.*", "cairo", "pangocairo"],
|
||||
"dll_excludes": ["USP10.dll", "NSI.dll", "MSIMG32.dll", "DNSAPI.dll"]
|
||||
"includes": ["pango", "atk", "gobject", "gio", "pickle", "bz2",
|
||||
"encodings", "encodings.*", "cairo", "pangocairo"],
|
||||
"dll_excludes": ["USP10.dll", "NSI.dll", "MSIMG32.dll",
|
||||
"DNSAPI.dll"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ import sys
|
||||
# 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
|
||||
SYMLINK_LIMIT = 5
|
||||
def is_secure_dir(path, num_symlinks = 0):
|
||||
def is_secure_dir(path, num_symlinks=0):
|
||||
import os
|
||||
import os.path
|
||||
import stat
|
||||
|
||||
@@ -126,6 +126,7 @@ import sys
|
||||
|
||||
from zenmapCore.Name import APP_NAME
|
||||
|
||||
|
||||
def fs_dec(s):
|
||||
"""Decode s from the filesystem decoding, handling various possible
|
||||
errors."""
|
||||
@@ -134,6 +135,7 @@ def fs_dec(s):
|
||||
enc = "UTF-8"
|
||||
return s.decode(enc)
|
||||
|
||||
|
||||
def fs_enc(u):
|
||||
"""Encode u to the filesystem decoding, handling various possible
|
||||
errors."""
|
||||
@@ -146,20 +148,20 @@ def fs_enc(u):
|
||||
# home directory, because os.path.expanduser doesn't properly decode the raw
|
||||
# byte string from the file system encoding. You get a UnicodeDecodeError on
|
||||
# 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
|
||||
# string and decode it from the filesystem encoding.
|
||||
# result of sys.getdefaultencoding(). So we call os.path.expanduser with a
|
||||
# plain string and decode it from the filesystem encoding.
|
||||
HOME = fs_dec(os.path.expanduser("~"))
|
||||
|
||||
# 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'.
|
||||
|
||||
base_paths = dict(user_config_file = APP_NAME + '.conf',
|
||||
user_config_dir = os.path.join(HOME, '.' + APP_NAME),
|
||||
scan_profile = 'scan_profile.usp',
|
||||
profile_editor = 'profile_editor.xml',
|
||||
recent_scans = 'recent_scans.txt',
|
||||
target_list = 'target_list.txt',
|
||||
options = 'options.xml',
|
||||
user_home = HOME,
|
||||
db = APP_NAME + ".db",
|
||||
version = APP_NAME + "_version")
|
||||
base_paths = dict(user_config_file=APP_NAME + '.conf',
|
||||
user_config_dir=os.path.join(HOME, '.' + APP_NAME),
|
||||
scan_profile='scan_profile.usp',
|
||||
profile_editor='profile_editor.xml',
|
||||
recent_scans='recent_scans.txt',
|
||||
target_list='target_list.txt',
|
||||
options='options.xml',
|
||||
user_home=HOME,
|
||||
db=APP_NAME + ".db",
|
||||
version=APP_NAME + "_version")
|
||||
|
||||
@@ -136,9 +136,11 @@ import zenmapCore.Paths
|
||||
# The [paths] configuration from zenmap.conf, used to get ndiff_command_path.
|
||||
paths_config = PathsConfig()
|
||||
|
||||
|
||||
class NdiffParseException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_path():
|
||||
"""Return a value for the PATH environment variable that is appropriate
|
||||
for the current platform. It will be the PATH from the environment plus
|
||||
@@ -153,8 +155,9 @@ def get_path():
|
||||
search_paths.append(path)
|
||||
return os.pathsep.join(search_paths)
|
||||
|
||||
|
||||
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
|
||||
|
||||
search_paths = get_path()
|
||||
@@ -162,20 +165,38 @@ class NdiffCommand(subprocess.Popen):
|
||||
env["PATH"] = search_paths
|
||||
if getattr(sys, "frozen", None) == "macosx_app":
|
||||
# These variables are set by py2app, but they can interfere with
|
||||
# Ndiff because Ndiff is also a Python application. Without removing
|
||||
# these, Ndiff will attempt to run using the py2app-bundled Python
|
||||
# library, and may run into version or architecture mismatches.
|
||||
if env.has_key("PYTHONPATH"):
|
||||
# Ndiff because Ndiff is also a Python application. Without
|
||||
# removing these, Ndiff will attempt to run using the
|
||||
# py2app-bundled Python library, and may run into version or
|
||||
# architecture mismatches.
|
||||
if "PYTHONPATH" in env:
|
||||
del env["PYTHONPATH"]
|
||||
if env.has_key("PYTHONHOME"):
|
||||
if "PYTHONHOME" in env:
|
||||
del env["PYTHONHOME"]
|
||||
|
||||
command_list = [paths_config.ndiff_command_path, "--verbose", "--", filename_a, filename_b]
|
||||
self.stdout_file = tempfile.TemporaryFile(mode = "rb", prefix = APP_NAME + "-ndiff-", suffix = ".xml")
|
||||
command_list = [
|
||||
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))
|
||||
# See zenmapCore.NmapCommand.py for an explanation of the shell argument.
|
||||
subprocess.Popen.__init__(self, command_list, stdout = self.stdout_file, stderr = self.stdout_file, env = env, shell = (sys.platform == "win32"))
|
||||
# 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")
|
||||
)
|
||||
|
||||
def get_scan_diff(self):
|
||||
self.wait()
|
||||
@@ -194,13 +215,17 @@ class NdiffCommand(subprocess.Popen):
|
||||
def kill(self):
|
||||
self.close()
|
||||
|
||||
|
||||
def ndiff(scan_a, scan_b):
|
||||
"""Run Ndiff on two scan results, which may be filenames or NmapParserSAX
|
||||
objects, and return a running NdiffCommand object."""
|
||||
temporary_filenames = []
|
||||
|
||||
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)
|
||||
f = os.fdopen(fd, "wb")
|
||||
scan_a.write_xml(f)
|
||||
@@ -209,7 +234,10 @@ def ndiff(scan_a, scan_b):
|
||||
filename_a = scan_a
|
||||
|
||||
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)
|
||||
f = os.fdopen(fd, "wb")
|
||||
scan_b.write_xml(f)
|
||||
|
||||
@@ -126,6 +126,7 @@ import sys
|
||||
|
||||
from zenmapCore.Name import APP_NAME
|
||||
|
||||
|
||||
def get_locales():
|
||||
"""Get a list of locales to use based on system configuration."""
|
||||
locales = []
|
||||
@@ -148,6 +149,7 @@ def get_locales():
|
||||
pass
|
||||
return locales
|
||||
|
||||
|
||||
def install_gettext(locale_dir):
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
@@ -162,8 +164,9 @@ def install_gettext(locale_dir):
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
t = gettext.translation(APP_NAME, locale_dir, languages = get_locales(), fallback = True)
|
||||
t.install(unicode = True)
|
||||
t = gettext.translation(
|
||||
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
|
||||
# module, even if they don't install the gettext version.
|
||||
|
||||
@@ -122,11 +122,13 @@
|
||||
|
||||
import re
|
||||
|
||||
|
||||
class NSEDocEvent (object):
|
||||
def __init__(self, type, text = None):
|
||||
def __init__(self, type, text=None):
|
||||
self.type = type
|
||||
self.text = text
|
||||
|
||||
|
||||
def nsedoc_parse_sub(text, pos):
|
||||
"""Parse paragraph-level NSEDoc markup, inside of paragraphs and lists.
|
||||
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, events
|
||||
|
||||
|
||||
def nsedoc_parse(text):
|
||||
"""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",
|
||||
|
||||
@@ -128,9 +128,11 @@ import zenmapCore.NmapParser
|
||||
from zenmapGUI.SearchGUI import SearchParser
|
||||
from SearchResult import HostSearch
|
||||
|
||||
|
||||
class NetworkInventory(object):
|
||||
"""This class acts as a container for aggregated scans. It is also
|
||||
responsible for opening/saving the aggregation from/to persistent storage."""
|
||||
responsible for opening/saving the aggregation from/to persistent
|
||||
storage."""
|
||||
def __init__(self, filename=None):
|
||||
# A list of all scans that make up this inventory
|
||||
self.scans = []
|
||||
@@ -162,8 +164,8 @@ class NetworkInventory(object):
|
||||
# Add this host to the hosts dictionary, mapped by IP address
|
||||
self.hosts[addr] = host.make_clone()
|
||||
else:
|
||||
# This host is already present in the host list, so we need to update its
|
||||
# info with the info held in the current host object
|
||||
# This host is already present in the host list, so we need to
|
||||
# update its info with the info held in the current host object
|
||||
old_host = self.hosts[addr]
|
||||
# We need to find old_host's scan date
|
||||
old_date = localtime(0)
|
||||
@@ -171,7 +173,8 @@ class NetworkInventory(object):
|
||||
if old_host in old_scan.get_hosts():
|
||||
old_date = old_scan.get_date()
|
||||
new_date = scan.get_date()
|
||||
self._update_host_info(old_host, host, old_date, new_date, scan)
|
||||
self._update_host_info(
|
||||
old_host, host, old_date, new_date, scan)
|
||||
|
||||
self.scans.append(scan)
|
||||
|
||||
@@ -179,7 +182,8 @@ class NetworkInventory(object):
|
||||
basename = os.path.basename(filename)
|
||||
|
||||
if basename in self.filenames.values():
|
||||
# We need to generate a new filename, since this basename already exists
|
||||
# We need to generate a new filename, since this basename
|
||||
# already exists
|
||||
base = basename
|
||||
ext = "xml"
|
||||
try:
|
||||
@@ -195,7 +199,8 @@ class NetworkInventory(object):
|
||||
self.filenames[scan] = basename
|
||||
|
||||
def remove_scan(self, scan):
|
||||
"""Removes a scan and any host information it contained from the inventory."""
|
||||
"""Removes a scan and any host information it contained from the
|
||||
inventory."""
|
||||
# Note: If a scan is passed in that isn't in the inventory then this
|
||||
# method will throw a ValueError Exception and will not finish
|
||||
# Remove the scan from our scan list
|
||||
@@ -214,12 +219,13 @@ class NetworkInventory(object):
|
||||
if scan in self.filenames:
|
||||
del self.filenames[scan]
|
||||
|
||||
# For each scan in the remembered list, append it to the scan list and update
|
||||
# the host list accordingly
|
||||
# For each scan in the remembered list, append it to the scan list and
|
||||
# update the host list accordingly
|
||||
for scan in scans:
|
||||
self.add_scan(scan)
|
||||
|
||||
def _update_host_info(self, old_host, new_host, old_date, new_date, new_scan):
|
||||
def _update_host_info(self, old_host, new_host,
|
||||
old_date, new_date, new_scan):
|
||||
"""This function is called when a host needs to be added to the hosts
|
||||
dictionary, but another HostInfo object for that host already exists
|
||||
in the dictionary (from a previous scan). In that case, we need to
|
||||
@@ -232,19 +238,21 @@ class NetworkInventory(object):
|
||||
for new_port in new_host.ports:
|
||||
# Check if new_port is already present in old_host's ports
|
||||
for old_port in old_host.ports:
|
||||
if old_port["portid"] == new_port["portid"] and old_port["protocol"] == new_port["protocol"]:
|
||||
if (old_port["portid"] == new_port["portid"] and
|
||||
old_port["protocol"] == new_port["protocol"]):
|
||||
old_list.remove(old_port)
|
||||
# We update old_host's port information to reflect the latest known port state
|
||||
# We update old_host's port information to reflect the
|
||||
# latest known port state
|
||||
if old_date < new_date:
|
||||
index = old_host.ports.index(old_port)
|
||||
old_host.ports[index] = new_port
|
||||
# Finished processing this new_port, we jump to the next one
|
||||
# Finished processing this new_port, we jump to the next
|
||||
break
|
||||
else:
|
||||
# This new_port isn't present in old_host, so we simply append it to
|
||||
# old_host's port info
|
||||
# This new_port isn't present in old_host, so we simply append
|
||||
# it to old_host's port info
|
||||
old_host.ports.append(new_port)
|
||||
|
||||
|
||||
ports = new_scan.get_port_protocol_dict()
|
||||
|
||||
#remove ports which are no longer up
|
||||
@@ -269,7 +277,8 @@ class NetworkInventory(object):
|
||||
if old_host.comment == "":
|
||||
old_host.comment = new_host.comment
|
||||
elif new_host.comment != "":
|
||||
old_host.comment = "%s\n\n%s" % (old_host.comment, new_host.comment)
|
||||
old_host.comment = "%s\n\n%s" % (
|
||||
old_host.comment, new_host.comment)
|
||||
|
||||
# Hostnames
|
||||
# Replace old_host's hostname with new_host's if old_host has no
|
||||
@@ -279,21 +288,29 @@ class NetworkInventory(object):
|
||||
old_host.hostnames = new_host.hostnames
|
||||
|
||||
# MAC address
|
||||
# If there was no MAC address set in old_host, set it to whatever is in new_host.mac.
|
||||
# Do the same if both hosts have a MAC address set, but new_host's address is newer.
|
||||
if old_host.mac is None or \
|
||||
(old_host.mac is not None and new_host.mac is not None and old_date < new_date):
|
||||
# If there was no MAC address set in old_host, set it to whatever is in
|
||||
# new_host.mac. Do the same if both hosts have a MAC address set, but
|
||||
# new_host's address is newer.
|
||||
if (old_host.mac is None or
|
||||
(old_host.mac is not None and
|
||||
new_host.mac is not None and
|
||||
old_date < new_date)
|
||||
):
|
||||
old_host.mac = new_host.mac
|
||||
|
||||
# OS detection fields
|
||||
# Replace old_host's OS detection fields with new_host's if old_host has no
|
||||
# OS detection info or new_host's info is newer.
|
||||
if len(new_host.osmatches) > 0 and (len(old_host.osmatches) == 0 or old_date < new_date):
|
||||
# Replace old_host's OS detection fields with new_host's if old_host
|
||||
# has no OS detection info or new_host's info is newer.
|
||||
if (len(new_host.osmatches) > 0 and
|
||||
(len(old_host.osmatches) == 0 or old_date < new_date)
|
||||
):
|
||||
old_host.osmatches = new_host.osmatches
|
||||
old_host.ports_used = new_host.ports_used
|
||||
|
||||
# Traceroute information
|
||||
if len(new_host.trace) > 0 and (len(old_host.trace) == 0 or old_date < new_date):
|
||||
if (len(new_host.trace) > 0 and
|
||||
(len(old_host.trace) == 0 or old_date < new_date)
|
||||
):
|
||||
old_host.trace = new_host.trace
|
||||
|
||||
def get_scans(self):
|
||||
@@ -317,7 +334,8 @@ class NetworkInventory(object):
|
||||
self.add_scan(parsed, path)
|
||||
|
||||
def open_from_dir(self, path):
|
||||
"""Loads all scans from the given directory into the network inventory."""
|
||||
"""Loads all scans from the given directory into the network
|
||||
inventory."""
|
||||
from zenmapCore.NmapParser import NmapParser
|
||||
|
||||
for filename in os.listdir(path):
|
||||
@@ -328,7 +346,7 @@ class NetworkInventory(object):
|
||||
parsed.parse_file(fullpath)
|
||||
self.add_scan(parsed, filename=fullpath)
|
||||
|
||||
def save_to_file(self, path, index, format = "xml"):
|
||||
def save_to_file(self, path, index, format="xml"):
|
||||
"""Saves the scan with the given list index into a file with a given
|
||||
path. With format = "xml", saves Nmap XML; otherwise saves plain text
|
||||
output."""
|
||||
@@ -341,21 +359,24 @@ class NetworkInventory(object):
|
||||
f.close()
|
||||
|
||||
def _generate_filenames(self, path):
|
||||
"""Generates filenames for all scans that don't already have a filename."""
|
||||
# The directory must not contain filenames other than those in the self.filenames dictionary
|
||||
"""Generates filenames for all scans that don't already have a
|
||||
filename."""
|
||||
# The directory must not contain filenames other than those in the
|
||||
# self.filenames dictionary
|
||||
for filename in os.listdir(path):
|
||||
if os.path.basename(filename) not in self.filenames.values():
|
||||
raise Exception("The destination directory contains a file (%s) that's not a part "
|
||||
"of the current inventory. The inventory will not be saved." %
|
||||
os.path.basename(filename))
|
||||
raise Exception("The destination directory contains a file"
|
||||
"(%s) that's not a part of the current inventory."
|
||||
"The inventory will not be saved." %
|
||||
os.path.basename(filename))
|
||||
|
||||
for scan in self.scans:
|
||||
if scan in self.filenames:
|
||||
# This scan already has a filename
|
||||
continue
|
||||
|
||||
date = "%04d%02d%02d%02d%02d" % (scan.date[0], scan.date[1], scan.date[2],
|
||||
scan.date[3], scan.date[4])
|
||||
date = "%04d%02d%02d%02d%02d" % (scan.date[0], scan.date[1],
|
||||
scan.date[2], scan.date[3], scan.date[4])
|
||||
filename = scan.get_scan_name()
|
||||
|
||||
# Prepend the date
|
||||
@@ -367,20 +388,22 @@ class NetworkInventory(object):
|
||||
filename = filename.replace(char, "_")
|
||||
|
||||
# Filename length check
|
||||
# (http://en.wikipedia.org/wiki/Filename#Comparison_of_file_name_limitations)
|
||||
# https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
|
||||
if len(filename) > 250:
|
||||
filename = filename[:250]
|
||||
|
||||
# TODO: Filename security checks?
|
||||
|
||||
# Try to open the file in append mode. If file.tell() returns a greater-than-zero
|
||||
# value, this means that the file already exists and has some data in it, so we
|
||||
# choose another filename until we successfully open a zero-length file.
|
||||
# Try to open the file in append mode. If file.tell() returns a
|
||||
# greater-than-zero value, this means that the file already exists
|
||||
# and has some data in it, so we choose another filename until we
|
||||
# successfully open a zero-length file.
|
||||
filename_full = filename + ".xml"
|
||||
counter = 2
|
||||
while filename_full in self.filenames.values():
|
||||
# There's already a scan with this filename, so we generate a new name by appending
|
||||
# the counter value before the file extension.
|
||||
# There's already a scan with this filename, so we generate a
|
||||
# new name by appending the counter value before the file
|
||||
# extension.
|
||||
filename_full = "%s %s.xml" % (filename, str(counter))
|
||||
counter += 1
|
||||
|
||||
@@ -413,12 +436,13 @@ class NetworkInventory(object):
|
||||
f = StringIO()
|
||||
parsed.write_xml(f)
|
||||
|
||||
scan = Scans(scan_name = parsed.scan_name,
|
||||
nmap_xml_output = f.getvalue(),
|
||||
date = time())
|
||||
scan = Scans(scan_name=parsed.scan_name,
|
||||
nmap_xml_output=f.getvalue(),
|
||||
date=time())
|
||||
|
||||
|
||||
class FilteredNetworkInventory(NetworkInventory):
|
||||
def __init__(self, filename = None):
|
||||
def __init__(self, filename=None):
|
||||
NetworkInventory.__init__(self, filename)
|
||||
|
||||
# A dictionary listing host filtering criteria
|
||||
@@ -459,18 +483,24 @@ class FilteredNetworkInventory(NetworkInventory):
|
||||
return self.filtered_hosts
|
||||
else:
|
||||
return NetworkInventory.get_hosts(self)
|
||||
|
||||
def get_hosts_up(self):
|
||||
if len(self.search_dict) > 0:
|
||||
return filter(lambda h: h.get_state() == 'up', self.filtered_hosts)
|
||||
return filter(lambda h: h.get_state() == 'up',
|
||||
self.filtered_hosts)
|
||||
else:
|
||||
return NetworkInventory.get_hosts_up(self)
|
||||
|
||||
def get_hosts_down(self):
|
||||
if len(self.search_dict) > 0:
|
||||
return filter(lambda h: h.get_state() == 'down', self.filtered_hosts)
|
||||
return filter(lambda h: h.get_state() == 'down',
|
||||
self.filtered_hosts)
|
||||
else:
|
||||
return NetworkInventory.get_hosts_down(self)
|
||||
|
||||
def get_total_host_count(self):
|
||||
return len(self.hosts)
|
||||
|
||||
def _match_all_args(self, host, operator, args):
|
||||
"""A helper function that calls the matching function for the given
|
||||
operator and each of its arguments."""
|
||||
@@ -479,48 +509,63 @@ class FilteredNetworkInventory(NetworkInventory):
|
||||
if arg != "" and arg[0] == "!":
|
||||
arg = arg[1:]
|
||||
positive = False
|
||||
if positive != self.__getattribute__("match_%s" % operator)(host, arg):
|
||||
if positive != self.__getattribute__(
|
||||
"match_%s" % operator)(host, arg):
|
||||
# No match for this operator
|
||||
return False
|
||||
else:
|
||||
# if the operator is not supported, pretend its true
|
||||
# All arguments for this operator produced a match
|
||||
return True
|
||||
|
||||
def get_host_count(self):
|
||||
return len(self.network_inventory.hosts)
|
||||
|
||||
def match_keyword(self, host, keyword):
|
||||
return self.match_os(host, keyword) or\
|
||||
self.match_target(host, keyword) or\
|
||||
self.match_service(host, keyword)
|
||||
|
||||
def match_target(self, host, name):
|
||||
return HostSearch.match_target(host, name)
|
||||
|
||||
def match_in_route(self, host, hop):
|
||||
hops = host.get_trace().get('hops', [])
|
||||
return hop in hops
|
||||
|
||||
def match_hostname(self, host, hostname):
|
||||
return HostSearch.match_hostname(host, hostname)
|
||||
|
||||
def match_service(self, host, service):
|
||||
return HostSearch.match_service(host, service)
|
||||
|
||||
def match_os(self, host, os):
|
||||
return HostSearch.match_os(host, os)
|
||||
|
||||
def match_open(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "open")
|
||||
|
||||
def match_closed(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "closed")
|
||||
|
||||
def match_filtered(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "filtered")
|
||||
|
||||
def match_unfiltered(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "unfiltered")
|
||||
|
||||
def match_open_filtered(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "open|filtered")
|
||||
|
||||
def match_closed_filtered(self, host, portno):
|
||||
host_ports = host.get_ports()
|
||||
return HostSearch.match_port(host_ports, portno, "closed|filtered")
|
||||
|
||||
def apply_filter(self, filter_text):
|
||||
self.filter_text = filter_text.lower()
|
||||
self.search_parser.update(self.filter_text)
|
||||
@@ -537,10 +582,11 @@ class FilteredNetworkInventory(NetworkInventory):
|
||||
# host satisfies all conditions
|
||||
self.filtered_hosts.append(host)
|
||||
|
||||
|
||||
class NetworkInventoryTest(unittest.TestCase):
|
||||
def test_no_external_modification(self):
|
||||
"""Test that HostInfo objects passed into the inventory are not modified
|
||||
during aggregation."""
|
||||
"""Test that HostInfo objects passed into the inventory are not
|
||||
modified during aggregation."""
|
||||
scan_1 = zenmapCore.NmapParser.ParserBasics()
|
||||
host_a = zenmapCore.NmapParser.HostInfo()
|
||||
host_a.hostnames = ["a"]
|
||||
@@ -564,28 +610,30 @@ class NetworkInventoryTest(unittest.TestCase):
|
||||
self.assertEqual(scan_1.nmap["hosts"], [host_a])
|
||||
self.assertEqual(scan_2.nmap["hosts"], [host_b])
|
||||
self.assertEqual(inv.get_hosts_up()[0].hostnames, ["b"])
|
||||
|
||||
def test_cancel_and_remove_scan(self):
|
||||
"""Test that canceling and removing a scan does not blow away the inventory hosts"""
|
||||
added_ips = ['10.0.0.1','10.0.0.2']
|
||||
"""Test that canceling and removing a scan does not blow away the
|
||||
inventory hosts"""
|
||||
added_ips = ['10.0.0.1', '10.0.0.2']
|
||||
removed_ips = ['10.0.0.3']
|
||||
scan_1 = zenmapCore.NmapParser.ParserBasics()
|
||||
host_a = zenmapCore.NmapParser.HostInfo()
|
||||
host_a.hostnames = ["a"]
|
||||
host_a.set_ip({'addr':added_ips[0]})
|
||||
host_a.set_ip({'addr': added_ips[0]})
|
||||
scan_1.start = "1000000000"
|
||||
scan_1.nmap["hosts"] = [host_a]
|
||||
|
||||
scan_2 = zenmapCore.NmapParser.ParserBasics()
|
||||
host_b = zenmapCore.NmapParser.HostInfo()
|
||||
host_b.hostnames = ["b"]
|
||||
host_b.set_ip({'addr':added_ips[1]})
|
||||
host_b.set_ip({'addr': added_ips[1]})
|
||||
scan_2.start = "1000000001"
|
||||
scan_2.nmap["hosts"] = [host_b]
|
||||
|
||||
scan_3 = zenmapCore.NmapParser.ParserBasics()
|
||||
host_c = zenmapCore.NmapParser.HostInfo()
|
||||
host_c.hostnames = ["b"]
|
||||
host_c.set_ip({'addr':removed_ips[0]})
|
||||
host_c.set_ip({'addr': removed_ips[0]})
|
||||
scan_3.start = "1000000001"
|
||||
scan_3.nmap["hosts"] = [host_c]
|
||||
|
||||
@@ -600,6 +648,7 @@ class NetworkInventoryTest(unittest.TestCase):
|
||||
self.assertEqual(host_a.hostnames, ["a"])
|
||||
self.assertEqual(host_b.hostnames, ["b"])
|
||||
|
||||
|
||||
class FilteredNetworkInventoryTest(unittest.TestCase):
|
||||
def test_filter(self):
|
||||
"""Test that the filter still works after moving code to the """
|
||||
@@ -613,6 +662,7 @@ class FilteredNetworkInventoryTest(unittest.TestCase):
|
||||
inv.apply_filter(filter_text)
|
||||
assert(len(inv.get_hosts()) == 2)
|
||||
|
||||
|
||||
class PortChangeTest(unittest.TestCase):
|
||||
def test_port(self):
|
||||
"""Verify that the port status (open/filtered/closed) is diplayed """ \
|
||||
@@ -632,17 +682,17 @@ class PortChangeTest(unittest.TestCase):
|
||||
assert(len(inv.get_hosts()[0].ports) == 0)
|
||||
|
||||
# Additional test case for when the two scans have port scan ranges
|
||||
# which do not overlap. Example nmap -F -sU versus
|
||||
# nmap -F scanme.nmap.org
|
||||
# which do not overlap. Example nmap -F -sU versus
|
||||
# nmap -F scanme.nmap.org
|
||||
inv = NetworkInventory()
|
||||
scan4 = NmapParser()
|
||||
scan4.parse_file("test/xml_test16.xml")
|
||||
inv.add_scan(scan4)
|
||||
assert(len(inv.get_hosts()[0].ports)==3)
|
||||
assert(len(inv.get_hosts()[0].ports) == 3)
|
||||
scan5 = NmapParser()
|
||||
scan5.parse_file("test/xml_test17.xml")
|
||||
inv.add_scan(scan5)
|
||||
assert(len(inv.get_hosts()[0].ports)==7)
|
||||
assert(len(inv.get_hosts()[0].ports) == 7)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -152,6 +152,7 @@ paths_config = PathsConfig()
|
||||
|
||||
log.debug(">>> Platform: %s" % sys.platform)
|
||||
|
||||
|
||||
def wrap_file_in_preferred_encoding(f):
|
||||
"""Wrap an open file to automatically decode its contents when reading from
|
||||
the encoding given by locale.getpreferredencoding, or just return the file
|
||||
@@ -184,17 +185,19 @@ def wrap_file_in_preferred_encoding(f):
|
||||
|
||||
return f
|
||||
|
||||
|
||||
def escape_nmap_filename(filename):
|
||||
"""Escape '%' characters so they are not interpreted as strftime format
|
||||
specifiers, which are not supported by Zenmap."""
|
||||
return filename.replace("%", "%%")
|
||||
|
||||
|
||||
class NmapCommand(object):
|
||||
"""This class represents an Nmap command line. It is responsible for
|
||||
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
|
||||
arguments for execution.
|
||||
|
||||
|
||||
The normal output (stdout and stderr) are written to the file object
|
||||
self.stdout_file."""
|
||||
|
||||
@@ -231,7 +234,8 @@ class NmapCommand(object):
|
||||
self.ops[op] = escape_nmap_filename(self.ops[op])
|
||||
|
||||
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)
|
||||
|
||||
log.debug(">>> Temporary files:")
|
||||
@@ -261,7 +265,8 @@ class NmapCommand(object):
|
||||
else:
|
||||
try:
|
||||
import ctypes
|
||||
ctypes.windll.kernel32.TerminateProcess(int(self.command_process._handle), -1)
|
||||
ctypes.windll.kernel32.TerminateProcess(
|
||||
int(self.command_process._handle), -1)
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -279,13 +284,13 @@ class NmapCommand(object):
|
||||
search_paths.append(path)
|
||||
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."""
|
||||
|
||||
# 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
|
||||
# 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)
|
||||
if stderr is None:
|
||||
stderr = f
|
||||
@@ -303,7 +308,8 @@ class NmapCommand(object):
|
||||
# This keeps a terminal window from opening.
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
try:
|
||||
startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
|
||||
startupinfo.dwFlags |= \
|
||||
subprocess._subprocess.STARTF_USESHOWWINDOW
|
||||
except AttributeError:
|
||||
# This name is used before Python 2.6.5.
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
@@ -312,7 +318,7 @@ class NmapCommand(object):
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=f,
|
||||
stderr=stderr,
|
||||
startupinfo = startupinfo,
|
||||
startupinfo=startupinfo,
|
||||
env=env)
|
||||
|
||||
def scan_state(self):
|
||||
@@ -327,15 +333,18 @@ class NmapCommand(object):
|
||||
state = self.command_process.poll()
|
||||
|
||||
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:
|
||||
return False # False means that the process had a successful exit
|
||||
return False # False means that the process had a successful exit
|
||||
else:
|
||||
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())
|
||||
|
||||
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):
|
||||
"""Return the complete contents of the self.stdout_file. This modifies
|
||||
@@ -348,4 +357,5 @@ class NmapCommand(object):
|
||||
return self.xml_output_filename
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(SplitQuotedTest))
|
||||
unittest.TextTestRunner().run(
|
||||
unittest.TestLoader().loadTestsFromTestCase(SplitQuotedTest))
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
# 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
|
||||
# of unknown options.
|
||||
# getopt_long_only_extras, which is like getopt_long_only with robust
|
||||
# handling of unknown options.
|
||||
#
|
||||
# NmapOptions, a class representing a set of Nmap options.
|
||||
#
|
||||
@@ -30,9 +30,11 @@
|
||||
# >>> ops["-v"] = 2
|
||||
# >>> ops["-oX"] = "output.xml"
|
||||
# >>> 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()
|
||||
# '"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
|
||||
# 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
|
||||
# If -x, whatever it is, does not take an argument, it is equivalent to
|
||||
# nmap -e eth0 scanme.nmap.org -x
|
||||
# that is, a scan of scanme.nmap.org over interface eth0. But if it does take an
|
||||
# argument, its argument is "-e", and the command line is the same as
|
||||
# that is, a scan of scanme.nmap.org over interface eth0. But if it does take
|
||||
# an argument, its argument is "-e", and the command line is the same as
|
||||
# nmap eth0 scanme.nmap.org -x -e
|
||||
# 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
|
||||
# are ambiguous. To resolve this, once an unknown option is found, all following
|
||||
# arguments that can be interpreted ambiguously are removed with it and placed
|
||||
# in the extras, with normal option processing resumed only when there is no
|
||||
# more ambiguity. This ensures that such options maintain their relative order
|
||||
# when rendered again to output. In this example "-x -e eth0" will always appear
|
||||
# in that order, and the -e option will be uninterpreted.
|
||||
# are ambiguous. To resolve this, once an unknown option is found, all
|
||||
# following arguments that can be interpreted ambiguously are removed with it
|
||||
# and placed in the extras, with normal option processing resumed only when
|
||||
# there is no more ambiguity. This ensures that such options maintain their
|
||||
# relative order when rendered again to output. In this example "-x -e eth0"
|
||||
# will always appear in that order, and the -e option will be uninterpreted.
|
||||
#
|
||||
# To add a new option, one should do the following:
|
||||
# 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.
|
||||
# 7) Make sure the test case works now.
|
||||
|
||||
|
||||
class option:
|
||||
"""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
|
||||
@@ -91,6 +94,7 @@ class option:
|
||||
self.name = name
|
||||
self.has_arg = has_arg
|
||||
|
||||
|
||||
def split_quoted(s):
|
||||
"""Like str.split, except that no splits occur inside quoted strings, and
|
||||
quoted strings are unquoted."""
|
||||
@@ -114,8 +118,8 @@ def split_quoted(s):
|
||||
i += 1
|
||||
if i < len(s):
|
||||
c = s[i]
|
||||
# Otherwise, ignore the error and leave the backslash at
|
||||
# the end of the string.
|
||||
# Otherwise, ignore the error and leave the backslash
|
||||
# at the end of the string.
|
||||
part.append(c)
|
||||
i += 1
|
||||
else:
|
||||
@@ -127,6 +131,7 @@ def split_quoted(s):
|
||||
|
||||
return r
|
||||
|
||||
|
||||
def maybe_quote(s):
|
||||
"""Return s quoted if it needs to be, otherwise unchanged."""
|
||||
for c in s:
|
||||
@@ -146,9 +151,11 @@ def maybe_quote(s):
|
||||
|
||||
return "\"" + "".join(r) + "\""
|
||||
|
||||
|
||||
def join_quoted(l):
|
||||
return " ".join([maybe_quote(x) for x in l])
|
||||
|
||||
|
||||
def make_options(short_opts, long_opts):
|
||||
"""Parse a short option specification string and long option tuples into a
|
||||
list of option objects."""
|
||||
@@ -176,6 +183,7 @@ def make_options(short_opts, long_opts):
|
||||
|
||||
lookup_option_cache = {}
|
||||
|
||||
|
||||
def lookup_option(name, options):
|
||||
"""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
|
||||
@@ -197,7 +205,8 @@ def lookup_option(name, options):
|
||||
return name.replace("_", "-")
|
||||
|
||||
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:
|
||||
# No match.
|
||||
lookup_option_cache[cache_code] = None
|
||||
@@ -215,19 +224,22 @@ def lookup_option(name, options):
|
||||
lookup_option_cache[cache_code] = None
|
||||
return lookup_option_cache[cache_code]
|
||||
|
||||
|
||||
def split_option(cmd_arg, options):
|
||||
"""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
|
||||
is required; the caller must take the argument from the next command-line
|
||||
argument. The remainder is what's left over after stripping a single short
|
||||
option that doesn't take an argument. At most one of argument and remainder
|
||||
will be non-None.
|
||||
It is not an error if the option does not include an argument even though
|
||||
it is required; the caller must take the argument from the next
|
||||
command-line argument. The remainder is what's left over after stripping a
|
||||
single short option that doesn't take an argument. At most one of argument
|
||||
and remainder will be non-None.
|
||||
Examples:
|
||||
>>> split_option("-v", [option("v", option.NO_ARGUMENT)])
|
||||
('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)
|
||||
>>> 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)
|
||||
>>> split_option("-d9", [option("d", option.OPTIONAL_ARGUMENT)])
|
||||
('d', '9', None)
|
||||
@@ -273,15 +285,17 @@ def split_option(cmd_arg, options):
|
||||
else:
|
||||
assert False, cmd_arg
|
||||
|
||||
|
||||
def get_option(cmd_args, options):
|
||||
"""Find and return the first option (plus a possible option argument) or
|
||||
positional argument from the command-line option list in cmd_args. The
|
||||
return value will have one of the following forms:
|
||||
a string, representing a positional argument;
|
||||
an (option, argument) pair (argument may be None);
|
||||
a (None, extra, ...) tuple, where extra, ... is a chain of an unknown option
|
||||
and its following arguments that cannot be interpreted unambiguously; or
|
||||
None, at the end of the option list."""
|
||||
* a string, representing a positional argument;
|
||||
* an (option, argument) pair (argument may be None);
|
||||
* a (None, extra, ...) tuple, where extra, ... is a chain of an unknown
|
||||
option and its following arguments that cannot be interpreted
|
||||
unambiguously; or
|
||||
* None, at the end of the option list."""
|
||||
if len(cmd_args) == 0:
|
||||
return None
|
||||
cmd_arg = cmd_args.pop(0)
|
||||
@@ -305,9 +319,9 @@ def get_option(cmd_args, options):
|
||||
return (None, cmd_arg)
|
||||
else:
|
||||
extras = [None, cmd_arg]
|
||||
# We found an unknown option but we have a problem--we don't know if
|
||||
# it takes an argument or not. So what we do is, we simulate what
|
||||
# would happen both if the option took and argument and if it
|
||||
# We found an unknown option but we have a problem--we don't know
|
||||
# if it takes an argument or not. So what we do is, we simulate
|
||||
# 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
|
||||
# loop.
|
||||
rest = sync(cmd_args[1:], cmd_args[:], options)
|
||||
@@ -332,6 +346,7 @@ def get_option(cmd_args, options):
|
||||
else:
|
||||
return (option.name, arg)
|
||||
|
||||
|
||||
def sync(a, b, options):
|
||||
"""Given two command-line argument lists, incrementally get an option from
|
||||
whichever is longer until both lists are equal. Return the resulting
|
||||
@@ -343,15 +358,17 @@ def sync(a, b, options):
|
||||
get_option(b, options)
|
||||
return a
|
||||
|
||||
|
||||
def getopt_long_only_extras(cmd_args, short_opts, long_opts):
|
||||
"""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
|
||||
yields will be one of the following:
|
||||
a string, representing a positional argument;
|
||||
an (option, argument) pair (argument may be None);
|
||||
a (None, extra, ...) tuple, where extra, ... is a chain of an unknown option
|
||||
and its following arguments that cannot be interpreted unambiguously; or
|
||||
None, at the end of the option list."""
|
||||
* a string, representing a positional argument;
|
||||
* an (option, argument) pair (argument may be None);
|
||||
* a (None, extra, ...) tuple, where extra, ... is a chain of an unknown
|
||||
option and its following arguments that cannot be interpreted
|
||||
unambiguously; or
|
||||
* None, at the end of the option list."""
|
||||
options = make_options(short_opts, long_opts)
|
||||
# get_option modifies its list of arguments in place. Don't modify the
|
||||
# original list.
|
||||
@@ -362,6 +379,7 @@ def getopt_long_only_extras(cmd_args, short_opts, long_opts):
|
||||
break
|
||||
yield result
|
||||
|
||||
|
||||
class NmapOptions(object):
|
||||
SHORT_OPTIONS = "6Ab:D:d::e:Ffg:hi:M:m:nO::o:P:p:RrS:s:T:v::V"
|
||||
LONG_OPTIONS = (
|
||||
@@ -492,7 +510,8 @@ class NmapOptions(object):
|
||||
def _set_executable(self, 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):
|
||||
opt, arg, remainder = split_option(name, self.options)
|
||||
@@ -563,7 +582,8 @@ class NmapOptions(object):
|
||||
"webxml",
|
||||
):
|
||||
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
|
||||
if self["-" + opt] is None:
|
||||
self["-" + opt] = arg
|
||||
@@ -617,7 +637,8 @@ class NmapOptions(object):
|
||||
try:
|
||||
self["-d"] = int(arg)
|
||||
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["-d"] += len(arg) + 1
|
||||
else:
|
||||
@@ -646,7 +667,8 @@ class NmapOptions(object):
|
||||
self.extras.append("-O%s" % arg)
|
||||
elif opt == "P":
|
||||
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
|
||||
elif (type == "" or type == "I" or type == "E") and ports == "":
|
||||
self["-PE"] = True
|
||||
@@ -693,7 +715,8 @@ class NmapOptions(object):
|
||||
try:
|
||||
self["-v"] = int(arg)
|
||||
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["-v"] += len(arg) + 1
|
||||
else:
|
||||
@@ -707,7 +730,8 @@ class NmapOptions(object):
|
||||
if len(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)
|
||||
|
||||
def parse_string(self, opt_string):
|
||||
@@ -716,7 +740,8 @@ class NmapOptions(object):
|
||||
def render(self):
|
||||
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]:
|
||||
opt_list.append(opt)
|
||||
|
||||
@@ -865,6 +890,7 @@ class NmapOptions(object):
|
||||
import doctest
|
||||
import unittest
|
||||
|
||||
|
||||
class NmapOptionsTest(unittest.TestCase):
|
||||
def test_clear(self):
|
||||
"""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"
|
||||
ops = NmapOptions()
|
||||
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):
|
||||
"""Test that strings can be quoted."""
|
||||
@@ -1123,7 +1150,8 @@ class NmapOptionsTest(unittest.TestCase):
|
||||
ops.parse_string("nmap -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")
|
||||
self.assertTrue(ops["-n"])
|
||||
self.assertTrue(ops["-F"])
|
||||
@@ -1155,8 +1183,8 @@ class NmapOptionsTest(unittest.TestCase):
|
||||
self.assertEqual(ops["--nonoption"], None)
|
||||
|
||||
def test_canonical_option_names(self):
|
||||
"""Test that equivalent option names are properly canonicalized, so that
|
||||
ops["--timing"] and ops["-T"] mean the same thing, for example."""
|
||||
"""Test that equivalent option names are properly canonicalized, so
|
||||
that ops["--timing"] and ops["-T"] mean the same thing, for example."""
|
||||
EQUIVS = (
|
||||
("--debug", "-d"),
|
||||
("--help", "-h"),
|
||||
@@ -1334,11 +1362,17 @@ class NmapOptionsTest(unittest.TestCase):
|
||||
ops.parse_string("nmap " + test)
|
||||
opt_list_1 = ops.render()
|
||||
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)
|
||||
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(len(ops.extras) == 0, "Result of parsing and rendering %s left extras: %s" % (test, ops.extras))
|
||||
self.assertTrue(opt_list_1 == opt_list_2,
|
||||
"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):
|
||||
"""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('"\\"\\""'), ['""'])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
doctest.testmod()
|
||||
unittest.main()
|
||||
|
||||
@@ -144,9 +144,10 @@ from zenmapCore.StringPool import unique
|
||||
# The version of the Nmap DTD this file understands and emits.
|
||||
XML_OUTPUT_VERSION = "1.04"
|
||||
|
||||
|
||||
class HostInfo(object):
|
||||
def __init__(self):
|
||||
self.comment = None;
|
||||
self.comment = None
|
||||
self._tcpsequence = {}
|
||||
self._osmatches = []
|
||||
self._ports = []
|
||||
@@ -233,13 +234,14 @@ class HostInfo(object):
|
||||
"""Return the OS match with the highest accuracy."""
|
||||
if not self._osmatches:
|
||||
return None
|
||||
|
||||
def osmatch_key(osmatch):
|
||||
try:
|
||||
return -float(osmatch["accuracy"])
|
||||
except ValueError:
|
||||
return 0
|
||||
return sorted(self._osmatches, key = osmatch_key)[0]
|
||||
|
||||
return sorted(self._osmatches, key=osmatch_key)[0]
|
||||
|
||||
# ports_used is a list like
|
||||
# [{'state': u'open', 'portid': u'22', 'proto': u'tcp'},
|
||||
@@ -262,7 +264,7 @@ class HostInfo(object):
|
||||
return self._uptime
|
||||
|
||||
# Avoid empty dict return
|
||||
return {"seconds":"", "lastboot":""}
|
||||
return {"seconds": "", "lastboot": ""}
|
||||
|
||||
# ports is an array containing dicts of the form
|
||||
# {'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"])))
|
||||
if self.ipv6:
|
||||
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:
|
||||
# Windows doesn't have socket.inet_pton. Go alphabetical.
|
||||
# Encode to a byte string for possible comparison with binary
|
||||
# address strings (which can't be converted to unicode).
|
||||
l.append((1, self.ipv6["addr"].encode("utf-8")))
|
||||
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()
|
||||
return l
|
||||
|
||||
@@ -386,7 +390,8 @@ class HostInfo(object):
|
||||
return self.get_port_count_by_states(('open', 'open|filtered'))
|
||||
|
||||
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):
|
||||
return self.get_port_count_by_states(('closed', 'closed|filtered'))
|
||||
@@ -395,7 +400,7 @@ class HostInfo(object):
|
||||
scanned = 0
|
||||
|
||||
for p in self.ports:
|
||||
scanned+=1
|
||||
scanned += 1
|
||||
|
||||
for extra in self.get_extraports():
|
||||
scanned += int(extra["count"])
|
||||
@@ -405,14 +410,16 @@ class HostInfo(object):
|
||||
def get_services(self):
|
||||
services = []
|
||||
for p in self.ports:
|
||||
services.append({"service_name":p.get("service_name", _("unknown")),
|
||||
"portid":p.get("portid", ""),
|
||||
"service_version":p.get("service_version",
|
||||
_("Unknown version")),
|
||||
"service_product":p.get("service_product", ""),
|
||||
"service_extrainfo":p.get("service_extrainfo", ""),
|
||||
"port_state":p.get("port_state", _("Unknown")),
|
||||
"protocol":p.get("protocol", "")})
|
||||
services.append({
|
||||
"service_name": p.get("service_name", _("unknown")),
|
||||
"portid": p.get("portid", ""),
|
||||
"service_version": p.get("service_version",
|
||||
_("Unknown version")),
|
||||
"service_product": p.get("service_product", ""),
|
||||
"service_extrainfo": p.get("service_extrainfo", ""),
|
||||
"port_state": p.get("port_state", _("Unknown")),
|
||||
"protocol": p.get("protocol", "")
|
||||
})
|
||||
return services
|
||||
|
||||
def get_trace(self):
|
||||
@@ -448,19 +455,22 @@ class HostInfo(object):
|
||||
services = property(get_services)
|
||||
trace = property(get_trace, set_trace)
|
||||
|
||||
|
||||
class ParserBasics(object):
|
||||
def __init__ (self):
|
||||
def __init__(self):
|
||||
# This flag informs us whether the XML output file is temporary (True),
|
||||
# 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.
|
||||
self.xml_is_temp = True
|
||||
|
||||
self.nmap = {'nmaprun':{},\
|
||||
'scaninfo':[],\
|
||||
'verbose':'',\
|
||||
'debugging':'',\
|
||||
'hosts':[],\
|
||||
'runstats':{}}
|
||||
self.nmap = {
|
||||
'nmaprun': {},
|
||||
'scaninfo': [],
|
||||
'verbose': '',
|
||||
'debugging': '',
|
||||
'hosts': [],
|
||||
'runstats': {}
|
||||
}
|
||||
|
||||
self.ops = NmapOptions()
|
||||
self._nmap_output = None
|
||||
@@ -490,13 +500,13 @@ class ParserBasics(object):
|
||||
def set_nmap_output(self, nmap_output):
|
||||
self._nmap_output = nmap_output
|
||||
|
||||
def get_debugging_level (self):
|
||||
def get_debugging_level(self):
|
||||
return self.nmap.get('debugging', '')
|
||||
|
||||
def set_debugging_level(self, level):
|
||||
self.nmap['debugging'] = level
|
||||
|
||||
def get_verbose_level (self):
|
||||
def get_verbose_level(self):
|
||||
return self.nmap.get('verbose', '')
|
||||
|
||||
def set_verbose_level(self, level):
|
||||
@@ -508,7 +518,7 @@ class ParserBasics(object):
|
||||
def set_scaninfo(self, info):
|
||||
self.nmap['scaninfo'] = info
|
||||
|
||||
def get_services_scanned (self):
|
||||
def get_services_scanned(self):
|
||||
if self._services_scanned == None:
|
||||
return self._services_scanned
|
||||
|
||||
@@ -519,10 +529,10 @@ class ParserBasics(object):
|
||||
self._services_scanned = ','.join(services)
|
||||
return self._services_scanned
|
||||
|
||||
def set_services_scanned (self, services_scanned):
|
||||
def set_services_scanned(self, services_scanned):
|
||||
self._services_scanned = services_scanned
|
||||
|
||||
def get_nmap_command (self):
|
||||
def get_nmap_command(self):
|
||||
return self.ops.render_string()
|
||||
|
||||
def set_nmap_command(self, command):
|
||||
@@ -531,19 +541,19 @@ class ParserBasics(object):
|
||||
self.ops["-oX"] = None
|
||||
self.nmap['nmaprun']['args'] = self.ops.render_string()
|
||||
|
||||
def get_scan_type (self):
|
||||
def get_scan_type(self):
|
||||
types = []
|
||||
for t in self.nmap.get('scaninfo', []):
|
||||
types.append(t['type'])
|
||||
return types
|
||||
|
||||
def get_protocol (self):
|
||||
def get_protocol(self):
|
||||
protocols = []
|
||||
for proto in self.nmap.get('scaninfo', []):
|
||||
protocols.append(proto['protocol'])
|
||||
return protocols
|
||||
|
||||
def get_num_services (self):
|
||||
def get_num_services(self):
|
||||
if self._num_services == None:
|
||||
return self._num_services
|
||||
|
||||
@@ -554,12 +564,12 @@ class ParserBasics(object):
|
||||
self._num_services = num
|
||||
return self._num_services
|
||||
|
||||
def set_num_services (self, num_services):
|
||||
def set_num_services(self, num_services):
|
||||
self._num_services = num_services
|
||||
|
||||
def get_date (self):
|
||||
def get_date(self):
|
||||
epoch = int(self.nmap['nmaprun'].get('start', '0'))
|
||||
return time.localtime (epoch)
|
||||
return time.localtime(epoch)
|
||||
|
||||
def get_start(self):
|
||||
return self.nmap['nmaprun'].get('start', '0')
|
||||
@@ -601,13 +611,13 @@ in epoch format!")
|
||||
def get_formatted_date(self):
|
||||
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', '')
|
||||
|
||||
def set_scanner(self, scanner):
|
||||
self.nmap['nmaprun']['scanner'] = scanner
|
||||
|
||||
def get_scanner_version (self):
|
||||
def get_scanner_version(self):
|
||||
return self.nmap['nmaprun'].get('version', '')
|
||||
|
||||
def set_scanner_version(self, version):
|
||||
@@ -634,7 +644,7 @@ in epoch format!")
|
||||
return []
|
||||
return [host.ipv6 for host in hosts if host.ipv6 is not None]
|
||||
|
||||
def get_hostnames (self):
|
||||
def get_hostnames(self):
|
||||
hostnames = []
|
||||
for host in self.nmap.get('hosts', []):
|
||||
hostnames += host.get_hostnames()
|
||||
@@ -667,7 +677,7 @@ in epoch format!")
|
||||
def set_hosts_scanned(self, 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',
|
||||
'0')))
|
||||
|
||||
@@ -686,7 +696,8 @@ in epoch format!")
|
||||
if scan_name:
|
||||
return scan_name
|
||||
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()
|
||||
|
||||
def set_scan_name(self, scan_name):
|
||||
@@ -710,8 +721,8 @@ in epoch format!")
|
||||
ports[int(item)] = []
|
||||
ports[int(item)].append(scaninfo['protocol'])
|
||||
else:
|
||||
begin,end = item.split('-')
|
||||
for port in range(int(begin),int(end)+1):
|
||||
begin, end = item.split('-')
|
||||
for port in range(int(begin), int(end) + 1):
|
||||
if int(port) not in ports:
|
||||
ports[int(port)] = []
|
||||
ports[int(port)].append(scaninfo['protocol'])
|
||||
@@ -752,6 +763,7 @@ in epoch format!")
|
||||
_num_services = None
|
||||
_services_scanned = None
|
||||
|
||||
|
||||
class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
def __init__(self):
|
||||
ParserBasics.__init__(self)
|
||||
@@ -793,14 +805,15 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
def _parse_nmaprun(self, attrs):
|
||||
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[run_tag]["profile_name"] = attrs.get("profile_name", "")
|
||||
self.nmap[run_tag]["start"] = attrs.get("start", "")
|
||||
self.nmap[run_tag]["args"] = attrs.get("args", "")
|
||||
self.nmap[run_tag]["scanner"] = attrs.get("scanner", "")
|
||||
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"]
|
||||
|
||||
@@ -844,9 +857,9 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
self.host_info.set_state(unique(attrs.get("state", "")))
|
||||
|
||||
def _parse_host_address(self, attrs):
|
||||
address_attributes = {"type":unique(attrs.get("addrtype", "")),
|
||||
"vendor":attrs.get("vendor", ""),
|
||||
"addr":attrs.get("addr", "")}
|
||||
address_attributes = {"type": unique(attrs.get("addrtype", "")),
|
||||
"vendor": attrs.get("vendor", ""),
|
||||
"addr": attrs.get("addr", "")}
|
||||
|
||||
if address_attributes["type"] == "ipv4":
|
||||
self.host_info.set_ip(address_attributes)
|
||||
@@ -856,16 +869,16 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
self.host_info.set_mac(address_attributes)
|
||||
|
||||
def _parse_host_hostname(self, attrs):
|
||||
self.list_hostnames.append({"hostname":attrs.get("name", ""),
|
||||
"hostname_type":attrs.get("type", "")})
|
||||
self.list_hostnames.append({"hostname": attrs.get("name", ""),
|
||||
"hostname_type": attrs.get("type", "")})
|
||||
|
||||
def _parse_host_extraports(self, attrs):
|
||||
self.list_extraports.append({"state":unique(attrs.get("state", "")),
|
||||
"count":attrs.get("count", "")})
|
||||
self.list_extraports.append({"state": unique(attrs.get("state", "")),
|
||||
"count": attrs.get("count", "")})
|
||||
|
||||
def _parse_host_port(self, attrs):
|
||||
self.dic_port = {"protocol":unique(attrs.get("protocol", "")),
|
||||
"portid":unique(attrs.get("portid", ""))}
|
||||
self.dic_port = {"protocol": unique(attrs.get("protocol", "")),
|
||||
"portid": unique(attrs.get("portid", ""))}
|
||||
|
||||
def _parse_host_port_state(self, attrs):
|
||||
self.dic_port["port_state"] = unique(attrs.get("state", ""))
|
||||
@@ -886,10 +899,12 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
self.list_osmatch.append(osmatch)
|
||||
|
||||
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):
|
||||
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):
|
||||
# Returns a dict with the attributes of a given tag with the
|
||||
@@ -902,17 +917,20 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
return dic
|
||||
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
trace = {}
|
||||
@@ -1002,7 +1020,6 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
elif self.in_host and self.in_trace and name == "error":
|
||||
self._parse_host_trace_error(attrs)
|
||||
|
||||
|
||||
def endElement(self, name):
|
||||
if name == "runstats":
|
||||
self.in_interactive_output = False
|
||||
@@ -1052,7 +1069,8 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
writer = XMLGenerator(f)
|
||||
writer.startDocument()
|
||||
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_scaninfo(writer)
|
||||
self._write_verbose(writer)
|
||||
@@ -1092,18 +1110,18 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
|
||||
## Finished element
|
||||
writer.startElement("finished",
|
||||
Attributes(dict(time = str(self.finish_epoc_time),
|
||||
timestr = time.ctime(time.mktime(self.get_finish_time())))))
|
||||
Attributes(dict(time=str(self.finish_epoc_time),
|
||||
timestr=time.ctime(time.mktime(
|
||||
self.get_finish_time())))))
|
||||
writer.endElement("finished")
|
||||
|
||||
## Hosts element
|
||||
writer.startElement("hosts",
|
||||
Attributes(dict(up = str(self.hosts_up),
|
||||
down = str(self.hosts_down),
|
||||
total = str(self.hosts_scanned))))
|
||||
Attributes(dict(up=str(self.hosts_up),
|
||||
down=str(self.hosts_down),
|
||||
total=str(self.hosts_scanned))))
|
||||
writer.endElement("hosts")
|
||||
|
||||
|
||||
writer.endElement("runstats")
|
||||
# End of Runstats element
|
||||
#########################
|
||||
@@ -1119,7 +1137,6 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
Attributes(dict(state=host.state)))
|
||||
writer.endElement("status")
|
||||
|
||||
|
||||
##################
|
||||
# Address elements
|
||||
## IPv4
|
||||
@@ -1148,15 +1165,14 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
# End of Address elements
|
||||
#########################
|
||||
|
||||
|
||||
###################
|
||||
# Hostnames element
|
||||
writer.startElement("hostnames", Attributes({}))
|
||||
|
||||
for hname in host.hostnames:
|
||||
writer.startElement("hostname",
|
||||
Attributes(dict(name = hname.get("hostname", ""),
|
||||
type = hname.get("hostname_type", ""))))
|
||||
Attributes(dict(name=hname.get("hostname", ""),
|
||||
type=hname.get("hostname_type", ""))))
|
||||
|
||||
writer.endElement("hostname")
|
||||
|
||||
@@ -1164,7 +1180,6 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
# End of Hostnames element
|
||||
##########################
|
||||
|
||||
|
||||
###############
|
||||
# Ports element
|
||||
writer.startElement("ports", Attributes({}))
|
||||
@@ -1172,15 +1187,15 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
## Extraports elements
|
||||
for ext in host.get_extraports():
|
||||
writer.startElement("extraports",
|
||||
Attributes(dict(count = ext.get("count", ""),
|
||||
state = ext.get("state", ""))))
|
||||
Attributes(dict(count=ext.get("count", ""),
|
||||
state=ext.get("state", ""))))
|
||||
writer.endElement("extraports")
|
||||
|
||||
## Port elements
|
||||
for p in host.ports:
|
||||
writer.startElement("port",
|
||||
Attributes(dict(portid = p.get("portid", ""),
|
||||
protocol = p.get("protocol", ""))))
|
||||
Attributes(dict(portid=p.get("portid", ""),
|
||||
protocol=p.get("protocol", ""))))
|
||||
|
||||
### Port state
|
||||
writer.startElement("state",
|
||||
@@ -1208,7 +1223,6 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
# End of Ports element
|
||||
######################
|
||||
|
||||
|
||||
############
|
||||
# OS element
|
||||
writer.startElement("os", Attributes({}))
|
||||
@@ -1216,25 +1230,25 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
## Ports used elements
|
||||
for pu in host.ports_used:
|
||||
writer.startElement("portused",
|
||||
Attributes(dict(state = pu.get("state", ""),
|
||||
proto = pu.get("proto", ""),
|
||||
portid = pu.get("portid", ""))))
|
||||
Attributes(dict(state=pu.get("state", ""),
|
||||
proto=pu.get("proto", ""),
|
||||
portid=pu.get("portid", ""))))
|
||||
writer.endElement("portused")
|
||||
|
||||
## Osmatch elements
|
||||
for om in host.osmatches:
|
||||
writer.startElement("osmatch",
|
||||
Attributes(dict(name = om.get("name", ""),
|
||||
accuracy = om.get("accuracy", ""),
|
||||
line = om.get("line", ""))))
|
||||
Attributes(dict(name=om.get("name", ""),
|
||||
accuracy=om.get("accuracy", ""),
|
||||
line=om.get("line", ""))))
|
||||
## Osclass elements
|
||||
for oc in om['osclasses']:
|
||||
writer.startElement("osclass",
|
||||
Attributes(dict(vendor = oc.get("vendor", ""),
|
||||
osfamily = oc.get("osfamily", ""),
|
||||
type = oc.get("type", ""),
|
||||
osgen = oc.get("osgen", ""),
|
||||
accuracy = oc.get("accuracy", ""))))
|
||||
Attributes(dict(vendor=oc.get("vendor", ""),
|
||||
osfamily=oc.get("osfamily", ""),
|
||||
type=oc.get("type", ""),
|
||||
osgen=oc.get("osgen", ""),
|
||||
accuracy=oc.get("accuracy", ""))))
|
||||
writer.endElement("osclass")
|
||||
writer.endElement("osmatch")
|
||||
|
||||
@@ -1244,8 +1258,8 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
|
||||
# Uptime element
|
||||
writer.startElement("uptime",
|
||||
Attributes(dict(seconds = host.uptime.get("seconds", ""),
|
||||
lastboot = host.uptime.get("lastboot", ""))))
|
||||
Attributes(dict(seconds=host.uptime.get("seconds", ""),
|
||||
lastboot=host.uptime.get("lastboot", ""))))
|
||||
writer.endElement("uptime")
|
||||
|
||||
#####################
|
||||
@@ -1253,21 +1267,21 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
## TCP Sequence element
|
||||
# Cannot use dict() here, because of the 'class' attribute.
|
||||
writer.startElement("tcpsequence",
|
||||
Attributes({"index":host.tcpsequence.get("index", ""),
|
||||
"difficulty":host.tcpsequence.get("difficulty", ""),
|
||||
"values":host.tcpsequence.get("values", "")}))
|
||||
Attributes({"index": host.tcpsequence.get("index", ""),
|
||||
"difficulty": host.tcpsequence.get("difficulty", ""),
|
||||
"values": host.tcpsequence.get("values", "")}))
|
||||
writer.endElement("tcpsequence")
|
||||
|
||||
## IP ID Sequence element
|
||||
writer.startElement("ipidsequence",
|
||||
Attributes({"class":host.ipidsequence.get("class", ""),
|
||||
"values":host.ipidsequence.get("values", "")}))
|
||||
Attributes({"class": host.ipidsequence.get("class", ""),
|
||||
"values": host.ipidsequence.get("values", "")}))
|
||||
writer.endElement("ipidsequence")
|
||||
|
||||
## TCP TS Sequence element
|
||||
writer.startElement("tcptssequence",
|
||||
Attributes({"class":host.tcptssequence.get("class", ""),
|
||||
"values":host.tcptssequence.get("values", "")}))
|
||||
Attributes({"class": host.tcptssequence.get("class", ""),
|
||||
"values": host.tcptssequence.get("values", "")}))
|
||||
writer.endElement("tcptssequence")
|
||||
# End of sequences elements
|
||||
###########################
|
||||
@@ -1275,21 +1289,21 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
## Trace element
|
||||
if len(host.trace) > 0:
|
||||
writer.startElement("trace",
|
||||
Attributes({"proto":host.trace.get("proto", ""),
|
||||
"port":host.trace.get("port", "")}))
|
||||
Attributes({"proto": host.trace.get("proto", ""),
|
||||
"port": host.trace.get("port", "")}))
|
||||
|
||||
if "hops" in host.trace:
|
||||
for hop in host.trace["hops"]:
|
||||
writer.startElement("hop",
|
||||
Attributes({"ttl":hop["ttl"],
|
||||
"rtt":hop["rtt"],
|
||||
"ipaddr":hop["ipaddr"],
|
||||
"host":hop["host"]}))
|
||||
Attributes({"ttl": hop["ttl"],
|
||||
"rtt": hop["rtt"],
|
||||
"ipaddr": hop["ipaddr"],
|
||||
"host": hop["host"]}))
|
||||
writer.endElement("hop")
|
||||
|
||||
if "error" in host.trace:
|
||||
writer.startElement("error",
|
||||
Attributes({"errorstr":host.trace["error"]}))
|
||||
Attributes({"errorstr": host.trace["error"]}))
|
||||
writer.endElement("error")
|
||||
|
||||
writer.endElement("trace")
|
||||
@@ -1312,21 +1326,22 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
def _write_scaninfo(self, writer):
|
||||
for scan in self.scaninfo:
|
||||
writer.startElement("scaninfo",
|
||||
Attributes(dict(type = scan.get("type", ""),
|
||||
protocol = scan.get("protocol", ""),
|
||||
numservices = scan.get("numservices", ""),
|
||||
services = scan.get("services", ""))))
|
||||
Attributes(dict(type=scan.get("type", ""),
|
||||
protocol=scan.get("protocol", ""),
|
||||
numservices=scan.get("numservices", ""),
|
||||
services=scan.get("services", ""))))
|
||||
writer.endElement("scaninfo")
|
||||
|
||||
def _write_nmaprun(self, writer):
|
||||
writer.startElement("nmaprun",
|
||||
Attributes(dict(args = str(self.nmap_command),
|
||||
profile_name = str(self.profile_name),
|
||||
scanner = str(self.scanner),
|
||||
start = str(self.start),
|
||||
startstr = time.ctime(time.mktime(self.get_date())),
|
||||
version = str(self.scanner_version),
|
||||
xmloutputversion = str(XML_OUTPUT_VERSION))))
|
||||
Attributes(dict(args=str(self.nmap_command),
|
||||
profile_name=str(self.profile_name),
|
||||
scanner=str(self.scanner),
|
||||
start=str(self.start),
|
||||
startstr=time.ctime(
|
||||
time.mktime(self.get_date())),
|
||||
version=str(self.scanner_version),
|
||||
xmloutputversion=str(XML_OUTPUT_VERSION))))
|
||||
|
||||
def set_unsaved(self):
|
||||
self.unsaved = True
|
||||
@@ -1334,6 +1349,7 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
||||
def is_unsaved(self):
|
||||
return self.unsaved
|
||||
|
||||
|
||||
def nmap_parser_sax():
|
||||
parser = make_parser()
|
||||
nmap_parser = NmapParserSAX()
|
||||
@@ -1345,6 +1361,7 @@ def nmap_parser_sax():
|
||||
|
||||
NmapParser = nmap_parser_sax
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ from zenmapCore.Version import VERSION
|
||||
from zenmapCore.Name import APP_NAME
|
||||
from zenmapCore.UmitOptionParser import option_parser
|
||||
|
||||
|
||||
# Find out the prefix under which data files (interface definition XML,
|
||||
# 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
|
||||
@@ -161,6 +162,8 @@ MISC_DIR = join(prefix, "share", APP_NAME, "misc")
|
||||
PIXMAPS_DIR = join(prefix, "share", "zenmap", "pixmaps")
|
||||
DOCS_DIR = join(prefix, "share", APP_NAME, "docs")
|
||||
NMAPDATADIR = join(prefix, "..")
|
||||
|
||||
|
||||
def get_extra_executable_search_paths():
|
||||
"""Return a list of additional executable search paths as a convenience for
|
||||
platforms where the default PATH is inadequate."""
|
||||
@@ -170,6 +173,7 @@ def get_extra_executable_search_paths():
|
||||
return [dirname(sys.executable)]
|
||||
return []
|
||||
|
||||
|
||||
#######
|
||||
# Paths
|
||||
class Paths(object):
|
||||
@@ -194,7 +198,8 @@ class Paths(object):
|
||||
|
||||
def __init__(self):
|
||||
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.locale_dir = LOCALE_DIR
|
||||
self.pixmaps_dir = PIXMAPS_DIR
|
||||
@@ -207,10 +212,12 @@ class Paths(object):
|
||||
return self.__dict__[name]
|
||||
|
||||
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:
|
||||
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:
|
||||
return return_if_exists(join(self.misc_dir, base_paths[name]))
|
||||
@@ -223,15 +230,17 @@ class Paths(object):
|
||||
def __setattr__(self, name, value):
|
||||
self.__dict__[name] = value
|
||||
|
||||
|
||||
def create_dir(path):
|
||||
"""Create a directory with os.makedirs without raising an error if the
|
||||
directory already exists."""
|
||||
directory already exists."""
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError, e:
|
||||
if e.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
|
||||
def create_user_config_dir(user_dir, template_dir):
|
||||
"""Create a user configuration directory by creating the directory if
|
||||
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)
|
||||
log.debug(">>> Copy %s to %s." % (template_filename, user_filename))
|
||||
|
||||
|
||||
def return_if_exists(path, create=False):
|
||||
path = os.path.abspath(path)
|
||||
if os.path.exists(path):
|
||||
|
||||
@@ -124,6 +124,7 @@ from os import access, R_OK, W_OK
|
||||
from os.path import dirname
|
||||
from zenmapCore.Paths import Path
|
||||
|
||||
|
||||
class RecentScans(object):
|
||||
def __init__(self):
|
||||
self.temp_list = []
|
||||
|
||||
@@ -131,6 +131,7 @@ quoted_re = re.compile(r'\s*(([\'"])(.*?[^\\])\2)\s*([},=]|$)')
|
||||
# "^%s*(['\"])%1%s*[},=]"
|
||||
empty_re = re.compile(r'\s*(([\'"])\2)\s*([},=]|$)')
|
||||
|
||||
|
||||
def parse_string(s, start):
|
||||
"""Parses a single string that is quoted, unquoted or empty. It returns the
|
||||
found string along with the next starting position """
|
||||
@@ -140,6 +141,7 @@ def parse_string(s, start):
|
||||
return m.group(1), m.end(1)
|
||||
raise ValueError("No string found at %s." % repr(s[start:]))
|
||||
|
||||
|
||||
def next_char(s, start):
|
||||
"""Returns the next character and position in the string."""
|
||||
while start < len(s) and s[start].isspace():
|
||||
@@ -149,6 +151,7 @@ def next_char(s, start):
|
||||
else:
|
||||
return None, start
|
||||
|
||||
|
||||
def parse_value(s, start):
|
||||
"""If the string starting from start is a name-value pair, returns a
|
||||
name-value tuple. Otherwise returns a plain string."""
|
||||
@@ -172,6 +175,7 @@ def parse_value(s, start):
|
||||
else:
|
||||
return s[start:j], j
|
||||
|
||||
|
||||
def parse_table(s, start):
|
||||
"""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
|
||||
@@ -192,6 +196,7 @@ def parse_table(s, start):
|
||||
if nc == ",":
|
||||
j += 1
|
||||
|
||||
|
||||
def parse_script_args(s):
|
||||
"""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
|
||||
@@ -202,7 +207,8 @@ def parse_script_args(s):
|
||||
while nc is not None:
|
||||
val, j = parse_value(s, j)
|
||||
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:
|
||||
args.append(val)
|
||||
nc, j = next_char(s, j)
|
||||
@@ -213,6 +219,7 @@ def parse_script_args(s):
|
||||
return None
|
||||
return args
|
||||
|
||||
|
||||
def parse_script_args_dict(raw_argument):
|
||||
"""Wrapper function that copies the name-value pairs from a list into a
|
||||
dictionary."""
|
||||
@@ -221,7 +228,7 @@ def parse_script_args_dict(raw_argument):
|
||||
if args is None:
|
||||
return None
|
||||
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]
|
||||
return args_dict
|
||||
|
||||
@@ -234,7 +241,11 @@ if __name__ == '__main__':
|
||||
('a={one,{two,{three}}}', [('a', '{one,{two,{three}}}')]),
|
||||
('a={"quoted}quoted"}', [('a', '{"quoted}quoted"}')]),
|
||||
('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:
|
||||
@@ -242,7 +253,7 @@ if __name__ == '__main__':
|
||||
print args_dict
|
||||
args = parse_script_args(test)
|
||||
if args == expected:
|
||||
print "PASS" , test
|
||||
print "PASS", test
|
||||
continue
|
||||
print "FAIL", test
|
||||
if args is None:
|
||||
|
||||
@@ -131,6 +131,7 @@ import sys
|
||||
from zenmapCore.Paths import Path
|
||||
from zenmapCore.UmitLogging import log
|
||||
|
||||
|
||||
class ScriptDB (object):
|
||||
"""Class responsible for parsing the script.db file, fetching script
|
||||
names and categories."""
|
||||
@@ -138,7 +139,8 @@ class ScriptDB (object):
|
||||
"a": "\a", "b": "\b", "f": "\f", "n": "\n", "r": "\r",
|
||||
"t": "\t", "v": "\v", "\\": "\\", "\"": "\"", "'": "'", "0": "\0"
|
||||
}
|
||||
def __init__(self, script_db_path = None):
|
||||
|
||||
def __init__(self, script_db_path=None):
|
||||
self.unget_buf = ""
|
||||
|
||||
self.f = open(script_db_path, "r")
|
||||
@@ -162,7 +164,8 @@ class ScriptDB (object):
|
||||
def parse(self):
|
||||
"""Parses a script.db entry and returns it as a dictionary. An entry
|
||||
looks like this:
|
||||
Entry { filename = "afp-brute.nse", categories = { "auth", "intrusive", } }
|
||||
Entry { filename = "afp-brute.nse", categories = \
|
||||
{ "auth", "intrusive", } }
|
||||
"""
|
||||
entries = []
|
||||
while True:
|
||||
@@ -238,7 +241,8 @@ class ScriptDB (object):
|
||||
if not token or token[0] != "string":
|
||||
raise ScriptDBSyntaxError()
|
||||
entry["filename"] = token[1]
|
||||
self.expect((("delim", ","), ("ident", "categories"), ("delim", "="), ("delim", "{")))
|
||||
self.expect((("delim", ","), ("ident", "categories"),
|
||||
("delim", "="), ("delim", "{")))
|
||||
entry["categories"] = []
|
||||
token = self.token()
|
||||
if token and token[0] == "string":
|
||||
@@ -263,6 +267,7 @@ class ScriptDB (object):
|
||||
def get_entries_list(self):
|
||||
return self.entries_list
|
||||
|
||||
|
||||
def nsedoc_tags_iter(f):
|
||||
in_doc_comment = False
|
||||
tag_name = None
|
||||
@@ -296,6 +301,7 @@ def nsedoc_tags_iter(f):
|
||||
tag_name = None
|
||||
tag_text = None
|
||||
|
||||
|
||||
class ScriptMetadata (object):
|
||||
"""Class responsible for parsing all the script information."""
|
||||
|
||||
@@ -305,14 +311,15 @@ class ScriptMetadata (object):
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.categories = []
|
||||
self.arguments = [] # Arguments including library arguments.
|
||||
self.arguments = [] # Arguments including library arguments.
|
||||
self.license = ""
|
||||
self.author = ""
|
||||
self.description = ""
|
||||
self.output = ""
|
||||
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):
|
||||
self.scripts_dir = scripts_dir
|
||||
@@ -351,13 +358,16 @@ class ScriptMetadata (object):
|
||||
return contents
|
||||
|
||||
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?
|
||||
m = re.search(re.escape(varname) + r'\s*=\s*(["\'])(.*?[^\\])\1', contents)
|
||||
m = re.search(
|
||||
re.escape(varname) + r'\s*=\s*(["\'])(.*?[^\\])\1', contents)
|
||||
if m:
|
||||
return m.group(2)
|
||||
# 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:
|
||||
return m.group(2)
|
||||
return None
|
||||
@@ -398,7 +408,7 @@ class ScriptMetadata (object):
|
||||
for tag_name, tag_text in nsedoc_tags_iter(f):
|
||||
m = re.match(r'([\w._-]+)', tag_text)
|
||||
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
|
||||
|
||||
def get_arguments(self, filename):
|
||||
@@ -444,6 +454,7 @@ class ScriptMetadata (object):
|
||||
self.library_arguments[libname] = self.get_script_args(filepath)
|
||||
self.library_requires[libname] = self.get_requires(filepath)
|
||||
|
||||
|
||||
def get_script_entries(scripts_dir, nselib_dir):
|
||||
"""Merge the information obtained so far into one single entry for
|
||||
each script and return it."""
|
||||
|
||||
@@ -134,6 +134,7 @@ from zenmapCore.NmapOptions import NmapOptions
|
||||
from zenmapCore.NmapParser import NmapParser
|
||||
from zenmapCore.UmitLogging import log
|
||||
|
||||
|
||||
class HostSearch(object):
|
||||
@staticmethod
|
||||
def match_target(host, name):
|
||||
@@ -142,16 +143,20 @@ class HostSearch(object):
|
||||
ip = host.get_ip()
|
||||
ipv6 = host.get_ipv6()
|
||||
|
||||
if mac and mac.has_key('addr'):
|
||||
if name in mac['addr'].lower(): return True
|
||||
if ip and ip.has_key('addr'):
|
||||
if name in ip['addr'].lower(): return True
|
||||
if ipv6 and ipv6.has_key('addr'):
|
||||
if name in ipv6['addr'].lower(): return True
|
||||
if mac and 'addr' in mac:
|
||||
if name in mac['addr'].lower():
|
||||
return True
|
||||
if ip and 'addr' in ip:
|
||||
if name in ip['addr'].lower():
|
||||
return True
|
||||
if ipv6 and 'addr' in ipv6:
|
||||
if name in ipv6['addr'].lower():
|
||||
return True
|
||||
|
||||
if HostSearch.match_hostname(host, name):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def match_hostname(host, hostname):
|
||||
hostname = hostname.lower()
|
||||
@@ -161,20 +166,27 @@ class HostSearch(object):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def match_service(host, service):
|
||||
for port in host.get_ports():
|
||||
# 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
|
||||
version = port.get("service_name", "") + " " + \
|
||||
port.get("service_product", "") + " " + \
|
||||
port.get("service_version", "") + " " + \
|
||||
port.get("service_extrainfo", "")
|
||||
version = " ".join(
|
||||
port.get(x, "") for x in (
|
||||
"service_name",
|
||||
"service_product",
|
||||
"service_version",
|
||||
"service_extrainfo"
|
||||
)
|
||||
)
|
||||
|
||||
if service in version.lower():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def match_os(host, os):
|
||||
os = os.lower()
|
||||
@@ -191,6 +203,7 @@ class HostSearch(object):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def match_port(host_ports, port, port_state):
|
||||
# Check if the port is parsable, if not return False silently
|
||||
@@ -203,6 +216,7 @@ class HostSearch(object):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class SearchResult(object):
|
||||
def __init__(self):
|
||||
"""This constructor is always called by SearchResult subclasses."""
|
||||
@@ -223,8 +237,8 @@ class SearchResult(object):
|
||||
# No match => we discard this scan_result
|
||||
break
|
||||
else:
|
||||
# All operator-matching functions have returned True, so this scan_result
|
||||
# satisfies all conditions
|
||||
# All operator-matching functions have returned True, so this
|
||||
# scan_result satisfies all conditions
|
||||
yield self.parsed_scan
|
||||
|
||||
def _match_all_args(self, operator, args):
|
||||
@@ -250,7 +264,8 @@ class SearchResult(object):
|
||||
if keyword == "*" or keyword == "":
|
||||
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):
|
||||
log.debug("Match keyword: %s" % keyword)
|
||||
@@ -261,7 +276,8 @@ class SearchResult(object):
|
||||
|
||||
def match_profile(self, 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()))
|
||||
if profile == "*" or profile == "" or \
|
||||
profile.lower() in str(self.parsed_scan.profile_name).lower():
|
||||
@@ -274,18 +290,20 @@ class SearchResult(object):
|
||||
if option == "*" or option == "":
|
||||
return True
|
||||
|
||||
# NOTE: Option matching treats "_" and "-" the same, just like the optcmp
|
||||
# function in utils.cc . Also, option matching is case-sensitive.
|
||||
# NOTE: Option matching treats "_" and "-" the same, just like the
|
||||
# optcmp function in utils.cc . Also, option matching is
|
||||
# case-sensitive.
|
||||
option = option.replace("_", "-")
|
||||
|
||||
ops = NmapOptions()
|
||||
ops.parse_string(self.parsed_scan.get_nmap_command())
|
||||
|
||||
if "(" in option and ")" in option:
|
||||
# The syntax allows matching option arguments as "opt:option_name(value)".
|
||||
# Since we've received only the "option_name(value)" part, we need to parse it.
|
||||
# The syntax allows matching option arguments as
|
||||
# "opt:option_name(value)". Since we've received only the
|
||||
# "option_name(value)" part, we need to parse it.
|
||||
optname = option[:option.find("(")]
|
||||
optval = option[option.find("(")+1:option.find(")")]
|
||||
optval = option[option.find("(") + 1:option.find(")")]
|
||||
|
||||
val = ops["--" + optname]
|
||||
if val is None:
|
||||
@@ -294,7 +312,8 @@ class SearchResult(object):
|
||||
return False
|
||||
return str(val) == optval or str(val) == optval
|
||||
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"):
|
||||
# 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("-")
|
||||
parsed_date = date(int(year), int(month), int(day))
|
||||
elif re.match("[-|\+]\d+$", date_arg):
|
||||
# We need to convert from the "-n" format (n days ago) to a date object
|
||||
# (I found this in some old code, don't ask :) )
|
||||
parsed_date = date.fromordinal(date.today().toordinal() + int(date_arg))
|
||||
# We need to convert from the "-n" format (n days ago) to a date
|
||||
# object (I found this in some old code, don't ask :) )
|
||||
parsed_date = date.fromordinal(
|
||||
date.today().toordinal() + int(date_arg))
|
||||
else:
|
||||
# Fail silently
|
||||
return False
|
||||
|
||||
# Now that we have both the scan date and the user date converted to date objects,
|
||||
# we need to make a comparison based on the operator (date, after, before).
|
||||
# Now that we have both the scan date and the user date converted to
|
||||
# date objects, we need to make a comparison based on the operator
|
||||
# (date, after, before).
|
||||
if operator == "date":
|
||||
return abs((scan_date - parsed_date).days) <= fuzz
|
||||
# We ignore fuzziness for after: and before:
|
||||
@@ -351,10 +372,11 @@ class SearchResult(object):
|
||||
return False
|
||||
|
||||
def match_os(self, os):
|
||||
# If you have lots of big scans in your DB (with a lot of hosts scanned),
|
||||
# you're probably better off using the keyword (freetext) search. Keyword
|
||||
# search just greps through the nmap output, while this function iterates
|
||||
# through all parsed OS-related values for every host in every scan!
|
||||
# If you have lots of big scans in your DB (with a lot of hosts
|
||||
# scanned), you're probably better off using the keyword (freetext)
|
||||
# search. Keyword search just greps through the nmap output, while this
|
||||
# function iterates through all parsed OS-related values for every host
|
||||
# in every scan!
|
||||
hosts = self.parsed_scan.get_hosts()
|
||||
for host in hosts:
|
||||
if HostSearch.match_os(host, os):
|
||||
@@ -376,12 +398,13 @@ class SearchResult(object):
|
||||
# Make a list of all scanned ports
|
||||
services = []
|
||||
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
|
||||
# the search finds a given port among the scanned ports, it breaks from the services
|
||||
# loop and continues with the next port in the ports list. If a port isn't
|
||||
# found in the services list, the function immediately returns False.
|
||||
# These two loops iterate over search ports and over scanned ports. As
|
||||
# soon as the search finds a given port among the scanned ports, it
|
||||
# breaks from the services loop and continues with the next port in the
|
||||
# ports list. If a port isn't found in the services list, the function
|
||||
# immediately returns False.
|
||||
for port in ports:
|
||||
for service in services:
|
||||
if "-" in service and \
|
||||
@@ -394,7 +417,8 @@ class SearchResult(object):
|
||||
else:
|
||||
return False
|
||||
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
|
||||
|
||||
def match_port(self, ports, port_state):
|
||||
@@ -405,7 +429,8 @@ class SearchResult(object):
|
||||
|
||||
for host in self.parsed_scan.get_hosts():
|
||||
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
|
||||
else:
|
||||
return True
|
||||
@@ -445,15 +470,16 @@ class SearchResult(object):
|
||||
return True
|
||||
host = host.lower()
|
||||
|
||||
# Since the parser doesn't parse traceroute output, we need to cheat and look
|
||||
# the host up in the Nmap output, in the Traceroute section of the scan.
|
||||
# Since the parser doesn't parse traceroute output, we need to cheat
|
||||
# and look the host up in the Nmap output, in the Traceroute section of
|
||||
# the scan.
|
||||
nmap_out = self.parsed_scan.get_nmap_output()
|
||||
tr_pos = 0
|
||||
traceroutes = [] # A scan holds one traceroute section per host
|
||||
while tr_pos != -1:
|
||||
# Find the beginning and the end of the traceroute section, and append
|
||||
# the substring to the traceroutes list
|
||||
tr_pos = nmap_out.find("TRACEROUTE", tr_pos+1)
|
||||
# Find the beginning and the end of the traceroute section, and
|
||||
# append the substring to the traceroutes list
|
||||
tr_pos = nmap_out.find("TRACEROUTE", tr_pos + 1)
|
||||
tr_end_pos = nmap_out.find("\n\n", tr_pos)
|
||||
if tr_pos != -1:
|
||||
traceroutes.append(nmap_out[tr_pos:tr_end_pos])
|
||||
@@ -465,15 +491,18 @@ class SearchResult(object):
|
||||
return False
|
||||
|
||||
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
|
||||
|
||||
|
||||
class SearchDummy(SearchResult):
|
||||
"""A dummy search class that returns no results. It is used as a placeholder
|
||||
when SearchDB can't be used."""
|
||||
"""A dummy search class that returns no results. It is used as a
|
||||
placeholder when SearchDB can't be used."""
|
||||
def get_scan_results(self):
|
||||
return []
|
||||
|
||||
|
||||
class SearchDB(SearchResult, object):
|
||||
def __init__(self):
|
||||
SearchResult.__init__(self)
|
||||
@@ -492,13 +521,15 @@ class SearchDB(SearchResult, object):
|
||||
parsed.parse(buffer)
|
||||
buffer.close()
|
||||
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:
|
||||
self.scan_results.append(parsed)
|
||||
|
||||
def get_scan_results(self):
|
||||
return self.scan_results
|
||||
|
||||
|
||||
class SearchDir(SearchResult, object):
|
||||
def __init__(self, search_directory, file_extensions=["usr"]):
|
||||
SearchResult.__init__(self)
|
||||
@@ -510,7 +541,8 @@ class SearchDir(SearchResult, object):
|
||||
elif type(file_extensions) == type([]):
|
||||
self.file_extensions = file_extensions
|
||||
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")
|
||||
self.scan_results = []
|
||||
@@ -534,6 +566,7 @@ class SearchDir(SearchResult, object):
|
||||
def get_scan_results(self):
|
||||
return self.scan_results
|
||||
|
||||
|
||||
class SearchResultTest(unittest.TestCase):
|
||||
class SearchClass(SearchResult):
|
||||
"""This class is for use by the unit testing code"""
|
||||
@@ -544,6 +577,7 @@ class SearchResultTest(unittest.TestCase):
|
||||
scan = NmapParser()
|
||||
scan.parse_file(filename)
|
||||
self.scan_results.append(scan)
|
||||
|
||||
def get_scan_results(self):
|
||||
return self.scan_results
|
||||
|
||||
@@ -553,31 +587,38 @@ class SearchResultTest(unittest.TestCase):
|
||||
|
||||
def _test_skeleton(self, key, val):
|
||||
results = []
|
||||
search = {key:[val]}
|
||||
search = {key: [val]}
|
||||
for scan in self.search_result.search(**search):
|
||||
results.append(scan)
|
||||
return len(results)
|
||||
|
||||
def test_match_os(self):
|
||||
"""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):
|
||||
"""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):
|
||||
"""Test that checks if the match_open predicate works"""
|
||||
assert(self._test_skeleton('open', '22') == 7)
|
||||
|
||||
def test_match_port_closed(self):
|
||||
"""Test that checks if the match_closed predicate works"""
|
||||
assert(self._test_skeleton('open', '22') == 7)
|
||||
assert(self._test_skeleton('closed', '22') == 9)
|
||||
|
||||
def test_match_service(self):
|
||||
"""Test that checks if the match_service predicate works"""
|
||||
assert(self._test_skeleton('service', 'apache') == 9)
|
||||
assert(self._test_skeleton('service', 'openssh') == 7)
|
||||
|
||||
def test_match_service_version(self):
|
||||
"""Test that checks if the match_service predicate works when """
|
||||
"""checking version"""
|
||||
assert(self._test_skeleton('service', '2.0.52') == 7)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -121,6 +121,8 @@
|
||||
# ***************************************************************************/
|
||||
|
||||
UNIQUE_STRING_MAP = {}
|
||||
|
||||
|
||||
def unique(s):
|
||||
"""Return a single unique representation of s (unique as to id),
|
||||
letting s be garbage collected."""
|
||||
|
||||
@@ -124,6 +124,7 @@ from os import access, R_OK, W_OK
|
||||
from os.path import dirname
|
||||
from zenmapCore.Paths import Path
|
||||
|
||||
|
||||
class TargetList(object):
|
||||
def __init__(self):
|
||||
self.temp_list = []
|
||||
|
||||
@@ -130,10 +130,10 @@ from zenmapCore.UmitLogging import log
|
||||
from zenmapCore.UmitConfigParser import UmitConfigParser
|
||||
import zenmapCore.I18N
|
||||
|
||||
# This is the global configuration parser object that represents the contents 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
|
||||
# SearchConfig, that wrap specific configuration sections.
|
||||
# This is the global configuration parser object that represents the contents
|
||||
# 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 SearchConfig, that wrap specific configuration sections.
|
||||
config_parser = UmitConfigParser()
|
||||
|
||||
# Check if running on Maemo
|
||||
@@ -144,9 +144,11 @@ try:
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def is_maemo():
|
||||
return MAEMO
|
||||
|
||||
|
||||
class SearchConfig(UmitConfigParser, object):
|
||||
section_name = "search"
|
||||
|
||||
@@ -245,10 +247,11 @@ class SearchConfig(UmitConfigParser, object):
|
||||
|
||||
class Profile(UmitConfigParser, object):
|
||||
"""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
|
||||
all take an argument that is the name of the profile to work on."""
|
||||
them found in a config file such as scan_profiles.usp. The methods
|
||||
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)
|
||||
|
||||
if not user_profile:
|
||||
@@ -272,10 +275,10 @@ class Profile(UmitConfigParser, object):
|
||||
return self.set(profile, attribute, value)
|
||||
|
||||
def add_profile(self, profile_name, **attributes):
|
||||
"""Add a profile with the given name and attributes to the collection of
|
||||
profiles. If a profile with the same name exists, it is not overwritten,
|
||||
and the method returns immediately. The backing file for the profiles is
|
||||
automatically updated."""
|
||||
"""Add a profile with the given name and attributes to the collection
|
||||
of profiles. If a profile with the same name exists, it is not
|
||||
overwritten, and the method returns immediately. The backing file for
|
||||
the profiles is automatically updated."""
|
||||
|
||||
log.debug(">>> Add Profile '%s': %s" % (profile_name, attributes))
|
||||
|
||||
@@ -292,8 +295,10 @@ class Profile(UmitConfigParser, object):
|
||||
self.save_changes()
|
||||
|
||||
def remove_profile(self, profile_name):
|
||||
try: self.remove_section(profile_name)
|
||||
except: pass
|
||||
try:
|
||||
self.remove_section(profile_name)
|
||||
except:
|
||||
pass
|
||||
self.save_changes()
|
||||
|
||||
def _verify_profile(self, profile_name):
|
||||
@@ -301,16 +306,17 @@ class Profile(UmitConfigParser, object):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class CommandProfile (Profile, object):
|
||||
"""This class is a wrapper around Profile that provides accessors for the
|
||||
attributes of a profile: command and description"""
|
||||
def __init__(self, user_profile = None):
|
||||
def __init__(self, user_profile=None):
|
||||
Profile.__init__(self, user_profile)
|
||||
|
||||
def get_command(self, profile):
|
||||
command_string = self._get_it(profile, 'command')
|
||||
# Old versions of Zenmap used to append "%s" to commands and use that to
|
||||
# substitute the target. Ignore it if present.
|
||||
# Old versions of Zenmap used to append "%s" to commands and use that
|
||||
# to substitute the target. Ignore it if present.
|
||||
if command_string.endswith("%s"):
|
||||
command_string = command_string[:-len("%s")]
|
||||
return command_string
|
||||
@@ -325,9 +331,9 @@ class CommandProfile (Profile, object):
|
||||
self._set_it(profile, 'description', description)
|
||||
|
||||
def get_profile(self, profile_name):
|
||||
return {'profile':profile_name, \
|
||||
'command':self.get_command(profile_name), \
|
||||
'description':self.get_description(profile_name)}
|
||||
return {'profile': profile_name, \
|
||||
'command': self.get_command(profile_name), \
|
||||
'description': self.get_description(profile_name)}
|
||||
|
||||
|
||||
class NmapOutputHighlight(object):
|
||||
@@ -381,10 +387,14 @@ class NmapOutputHighlight(object):
|
||||
|
||||
tuple_regex = "[\(\[]\s?(\d+)\s?,\s?(\d+)\s?,\s?(\d+)\s?[\)\]]"
|
||||
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):
|
||||
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
|
||||
|
||||
@@ -446,7 +456,8 @@ class NmapOutputHighlight(object):
|
||||
try:
|
||||
enable = config_parser.get("output_highlight", "enable_highlight")
|
||||
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 == "":
|
||||
return False
|
||||
@@ -454,9 +465,11 @@ class NmapOutputHighlight(object):
|
||||
|
||||
def set_enable(self, 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:
|
||||
config_parser.set("output_highlight", "enable_highlight", str(True))
|
||||
config_parser.set(
|
||||
"output_highlight", "enable_highlight", str(True))
|
||||
|
||||
date = property(get_date, set_date)
|
||||
hostname = property(get_hostname, set_hostname)
|
||||
@@ -468,56 +481,68 @@ class NmapOutputHighlight(object):
|
||||
details = property(get_details, set_details)
|
||||
enable = property(get_enable, set_enable)
|
||||
|
||||
# These settings are made when there is nothing set yet. They set the "factory" \
|
||||
# default to highlight colors
|
||||
default_highlights = {"date":{"bold":str(True),
|
||||
"italic":str(False),
|
||||
"underline":str(False),
|
||||
"text":[0, 0, 0],
|
||||
"highlight":[65535, 65535, 65535],
|
||||
"regex":"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s.{1,4}"},
|
||||
"hostname":{"bold":str(True),
|
||||
"italic":str(True),
|
||||
"underline":str(True),
|
||||
"text":[0, 111, 65535],
|
||||
"highlight":[65535, 65535, 65535],
|
||||
"regex":"(\w{2,}://)*[\w-]{2,}\.[\w-]{2,}(\.[\w-]{2,})*(/[[\w-]{2,}]*)*"},
|
||||
"ip":{"bold":str(True),
|
||||
"italic":str(False),
|
||||
"underline":str(False),
|
||||
"text":[0, 0, 0],
|
||||
"highlight":[65535, 65535, 65535],
|
||||
"regex":"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"},
|
||||
"port_list":{"bold":str(True),
|
||||
"italic":str(False),
|
||||
"underline":str(False),
|
||||
"text":[0, 1272, 28362],
|
||||
"highlight":[65535, 65535, 65535],
|
||||
"regex":"PORT\s+STATE\s+SERVICE(\s+VERSION)?[^\n]*"},
|
||||
"open_port":{"bold":str(True),
|
||||
"italic":str(False),
|
||||
"underline":str(False),
|
||||
"text":[0, 41036, 2396],
|
||||
"highlight":[65535, 65535, 65535],
|
||||
"regex":"\d{1,5}/.{1,5}\s+open\s+.*"},
|
||||
"closed_port":{"bold":str(False),
|
||||
"italic":str(False),
|
||||
"underline":str(False),
|
||||
"text":[65535, 0, 0],
|
||||
"highlight":[65535, 65535, 65535],
|
||||
"regex":"\d{1,5}/.{1,5}\s+closed\s+.*"},
|
||||
"filtered_port":{"bold":str(False),
|
||||
"italic":str(False),
|
||||
"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}:"}}
|
||||
# These settings are made when there is nothing set yet. They set the
|
||||
# "factory" default to highlight colors
|
||||
default_highlights = {
|
||||
"date": {
|
||||
"bold": str(True),
|
||||
"italic": str(False),
|
||||
"underline": str(False),
|
||||
"text": [0, 0, 0],
|
||||
"highlight": [65535, 65535, 65535],
|
||||
"regex": "\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s.{1,4}"},
|
||||
"hostname": {
|
||||
"bold": str(True),
|
||||
"italic": str(True),
|
||||
"underline": str(True),
|
||||
"text": [0, 111, 65535],
|
||||
"highlight": [65535, 65535, 65535],
|
||||
"regex": "(\w{2,}://)*[\w-]{2,}\.[\w-]{2,}"
|
||||
"(\.[\w-]{2,})*(/[[\w-]{2,}]*)*"},
|
||||
"ip": {
|
||||
"bold": str(True),
|
||||
"italic": str(False),
|
||||
"underline": str(False),
|
||||
"text": [0, 0, 0],
|
||||
"highlight": [65535, 65535, 65535],
|
||||
"regex": "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"},
|
||||
"port_list": {
|
||||
"bold": str(True),
|
||||
"italic": str(False),
|
||||
"underline": str(False),
|
||||
"text": [0, 1272, 28362],
|
||||
"highlight": [65535, 65535, 65535],
|
||||
"regex": "PORT\s+STATE\s+SERVICE(\s+VERSION)?[^\n]*"},
|
||||
"open_port": {
|
||||
"bold": str(True),
|
||||
"italic": str(False),
|
||||
"underline": str(False),
|
||||
"text": [0, 41036, 2396],
|
||||
"highlight": [65535, 65535, 65535],
|
||||
"regex": "\d{1,5}/.{1,5}\s+open\s+.*"},
|
||||
"closed_port": {
|
||||
"bold": str(False),
|
||||
"italic": str(False),
|
||||
"underline": str(False),
|
||||
"text": [65535, 0, 0],
|
||||
"highlight": [65535, 65535, 65535],
|
||||
"regex": "\d{1,5}/.{1,5}\s+closed\s+.*"},
|
||||
"filtered_port": {
|
||||
"bold": str(False),
|
||||
"italic": str(False),
|
||||
"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
|
||||
# (e.g. nmap_command_path) - jurand
|
||||
@@ -530,8 +555,9 @@ class PathsConfig(object):
|
||||
def __get_it(self, p_name, default):
|
||||
try:
|
||||
return config_parser.get(self.section_name, p_name)
|
||||
except (NoOptionError,NoSectionError):
|
||||
log.debug(">>> Using default \"%s\" for \"%s\"." % (default, p_name))
|
||||
except (NoOptionError, NoSectionError):
|
||||
log.debug(
|
||||
">>> Using default \"%s\" for \"%s\"." % (default, p_name))
|
||||
return default
|
||||
|
||||
def __set_it(self, property_name, settings):
|
||||
@@ -550,17 +576,22 @@ class PathsConfig(object):
|
||||
self.__set_it("ndiff_command_path", settings)
|
||||
|
||||
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
|
||||
class ProfileNotFound:
|
||||
def __init__ (self, profile):
|
||||
def __init__(self, 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:
|
||||
def __init__ (self, profile):
|
||||
def __init__(self, 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!"
|
||||
|
||||
@@ -121,9 +121,11 @@
|
||||
# ***************************************************************************/
|
||||
|
||||
from os.path import exists
|
||||
from ConfigParser import ConfigParser, DEFAULTSECT, NoOptionError, NoSectionError
|
||||
from ConfigParser import ConfigParser, DEFAULTSECT, NoOptionError, \
|
||||
NoSectionError
|
||||
from zenmapCore.UmitLogging import log
|
||||
|
||||
|
||||
class UmitConfigParser(ConfigParser):
|
||||
filenames = None
|
||||
fp = None
|
||||
@@ -158,9 +160,11 @@ class UmitConfigParser(ConfigParser):
|
||||
if len(self.filenames) == 1:
|
||||
filename = self.filenames[0]
|
||||
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:
|
||||
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'))
|
||||
elif self.fp:
|
||||
self.write(self.fp)
|
||||
@@ -188,6 +192,7 @@ class UmitConfigParser(ConfigParser):
|
||||
(key, str(value).replace('\n', '\n\t')))
|
||||
fp.write("\n")
|
||||
|
||||
|
||||
def test_umit_conf_content(filename):
|
||||
parser = ConfigParser()
|
||||
parser.read(filename)
|
||||
|
||||
@@ -175,8 +175,8 @@ if isinstance(umitdb, str):
|
||||
fs_enc = "UTF-8"
|
||||
umitdb = umitdb.decode(fs_enc)
|
||||
|
||||
# pyslite 2.4.0 doesn't handle a unicode database name, though earlier and later
|
||||
# versions do. Encode to UTF-8 as pysqlite would do internally anyway.
|
||||
# pyslite 2.4.0 doesn't handle a unicode database name, though earlier and
|
||||
# later versions do. Encode to UTF-8 as pysqlite would do internally anyway.
|
||||
umitdb = umitdb.encode("UTF-8")
|
||||
|
||||
connection = sqlite.connect(umitdb)
|
||||
@@ -192,6 +192,7 @@ except AttributeError:
|
||||
# However, text_factory is available only in pysqlite 2.1.0 and later.
|
||||
pass
|
||||
|
||||
|
||||
class Table(object):
|
||||
def __init__(self, table_name):
|
||||
self.table_name = table_name
|
||||
@@ -203,9 +204,11 @@ class Table(object):
|
||||
if 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,
|
||||
self.table_name,
|
||||
self.__getattribute__(self.table_id))
|
||||
sql = "SELECT %s FROM %s WHERE %s_id = %s" % (
|
||||
item_name,
|
||||
self.table_name,
|
||||
self.table_name,
|
||||
self.__getattribute__(self.table_id))
|
||||
|
||||
self.cursor.execute(sql)
|
||||
|
||||
@@ -216,9 +219,11 @@ class Table(object):
|
||||
if item_value == self.__getattribute__("_%s" % item_name):
|
||||
return None
|
||||
|
||||
sql = "UPDATE %s SET %s = ? WHERE %s_id = %s" % (self.table_name, item_name,
|
||||
self.table_name,
|
||||
self.__getattribute__(self.table_id))
|
||||
sql = "UPDATE %s SET %s = ? WHERE %s_id = %s" % (
|
||||
self.table_name,
|
||||
item_name,
|
||||
self.table_name,
|
||||
self.__getattribute__(self.table_id))
|
||||
self.cursor.execute(sql, (item_value,))
|
||||
connection.commit()
|
||||
self.__setattr__("_%s" % item_name, item_value)
|
||||
@@ -247,31 +252,30 @@ class Table(object):
|
||||
self.cursor.execute(sql)
|
||||
return self.cursor.fetchall()[0][0]
|
||||
|
||||
|
||||
class UmitDB(object):
|
||||
def __init__(self):
|
||||
self.cursor = connection.cursor()
|
||||
|
||||
def create_db(self):
|
||||
drop_string = ("DROP TABLE scans;",)
|
||||
drop_string = "DROP TABLE scans;"
|
||||
|
||||
try:
|
||||
for d in drop_string:
|
||||
self.cursor.execute(d)
|
||||
self.cursor.execute(drop_string)
|
||||
except:
|
||||
connection.rollback()
|
||||
else:
|
||||
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,
|
||||
scan_name TEXT,
|
||||
nmap_xml_output TEXT,
|
||||
digest TEXT,
|
||||
date INTEGER)""",)
|
||||
|
||||
for c in creation_string:
|
||||
self.cursor.execute(c)
|
||||
connection.commit()
|
||||
self.cursor.execute(creation_string)
|
||||
connection.commit()
|
||||
|
||||
def add_scan(self, **kargs):
|
||||
return Scans(**kargs)
|
||||
@@ -289,11 +293,13 @@ class UmitDB(object):
|
||||
def cleanup(self, save_time):
|
||||
log.debug(">>> Cleaning up data base.")
|
||||
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()]:
|
||||
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:
|
||||
connection.commit()
|
||||
log.debug(">>> Data base successfully cleaned up!")
|
||||
@@ -310,25 +316,30 @@ class Scans(Table, object):
|
||||
|
||||
for k in kargs.keys():
|
||||
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")
|
||||
|
||||
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!")
|
||||
|
||||
self.scans_id = self.insert(**kargs)
|
||||
|
||||
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()
|
||||
if result:
|
||||
return False
|
||||
return True
|
||||
|
||||
def add_host(self, **kargs):
|
||||
kargs.update({self.table_id:self.scans_id})
|
||||
kargs.update({self.table_id: self.scans_id})
|
||||
return Hosts(**kargs)
|
||||
|
||||
def get_hosts(self):
|
||||
|
||||
@@ -127,6 +127,7 @@ from zenmapCore.UmitOptionParser import option_parser
|
||||
|
||||
LOGLEVEL = option_parser.get_verbose()
|
||||
|
||||
|
||||
class Log(Logger, object):
|
||||
def __init__(self, name, level=0):
|
||||
Logger.__init__(self, name, level)
|
||||
@@ -143,7 +144,6 @@ class Log(Logger, object):
|
||||
def set_formatter(self, fmt):
|
||||
self.__formatter = Formatter(fmt)
|
||||
|
||||
|
||||
format = "%(levelname)s - %(asctime)s - %(message)s"
|
||||
|
||||
formatter = property(get_formatter, set_formatter, doc="")
|
||||
|
||||
@@ -128,6 +128,7 @@ from zenmapCore.Version import VERSION
|
||||
import zenmapCore.I18N
|
||||
from zenmapCore.BasePaths import base_paths
|
||||
|
||||
|
||||
class UmitOptionParser(OptionParser):
|
||||
def __init__(self, args=False):
|
||||
OptionParser.__init__(self, version="%%prog %s" % VERSION)
|
||||
@@ -135,10 +136,10 @@ class UmitOptionParser(OptionParser):
|
||||
self.set_usage("%prog [options] [result files]")
|
||||
|
||||
self.add_option("--confdir",
|
||||
default = base_paths["user_config_dir"],
|
||||
dest = "confdir",
|
||||
metavar = "DIR",
|
||||
help = _("\
|
||||
default=base_paths["user_config_dir"],
|
||||
dest="confdir",
|
||||
metavar="DIR",
|
||||
help=_("\
|
||||
Use DIR as the user configuration directory. Default: %default"))
|
||||
|
||||
## Open Scan Results (GUI)
|
||||
@@ -163,7 +164,8 @@ scan result files."))
|
||||
default=[],
|
||||
action="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)
|
||||
### Positional args should be taken as targets to feed this scan
|
||||
|
||||
@@ -126,7 +126,8 @@ import webbrowser
|
||||
|
||||
from zenmapGUI.higwidgets.higdialogs import HIGDialog
|
||||
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.hignotebooks import HIGNotebook
|
||||
from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow
|
||||
@@ -141,6 +142,7 @@ import zenmapCore.I18N
|
||||
# For escaping text in marked-up labels.
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
|
||||
class _program_entry(gtk.VBox):
|
||||
"""A little box containing labels with a program's name and
|
||||
description and a clickable link to its web site."""
|
||||
@@ -149,7 +151,7 @@ class _program_entry(gtk.VBox):
|
||||
# web site button.
|
||||
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)
|
||||
|
||||
self.hbox = gtk.HBox(False, self.NAME_WEB_SITE_SPACING)
|
||||
@@ -157,7 +159,9 @@ class _program_entry(gtk.VBox):
|
||||
|
||||
if name is not None:
|
||||
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)
|
||||
|
||||
if web_site is not None:
|
||||
@@ -180,41 +184,44 @@ class _program_entry(gtk.VBox):
|
||||
def _link_button_open(self, widget):
|
||||
webbrowser.open(widget.get_uri())
|
||||
|
||||
|
||||
class About(HIGDialog):
|
||||
"""An about dialog showing information about the program. It is meant to
|
||||
have roughly the same feel as gtk.AboutDialog."""
|
||||
def __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_spacing(12)
|
||||
|
||||
label = gtk.Label()
|
||||
label.set_markup("<span size=\"xx-large\" weight=\"bold\">%s %s</span>" \
|
||||
% (escape(APP_DISPLAY_NAME), escape(VERSION)))
|
||||
label.set_markup(
|
||||
'<span size="xx-large" weight="bold">%s %s</span>' % (
|
||||
escape(APP_DISPLAY_NAME), escape(VERSION)))
|
||||
label.set_selectable(True)
|
||||
self.vbox.pack_start(label)
|
||||
|
||||
label = gtk.Label()
|
||||
label.set_markup("<span size=\"small\">%s</span>" \
|
||||
% (escape(APP_COPYRIGHT)))
|
||||
label.set_markup(
|
||||
'<span size="small">%s</span>' % (escape(APP_COPYRIGHT)))
|
||||
self.vbox.pack_start(label)
|
||||
|
||||
entry = _program_entry(NMAP_DISPLAY_NAME, NMAP_WEB_SITE, _("""\
|
||||
%s is a free and open source utility for network exploration and security \
|
||||
auditing.""") % NMAP_DISPLAY_NAME)
|
||||
entry = _program_entry(NMAP_DISPLAY_NAME, NMAP_WEB_SITE, _(
|
||||
"%s is a free and open source utility for network exploration "
|
||||
"and security auditing.") % NMAP_DISPLAY_NAME)
|
||||
self.vbox.pack_start(entry)
|
||||
|
||||
entry = _program_entry(APP_DISPLAY_NAME, APP_WEB_SITE, _("""\
|
||||
%s is a multi-platform graphical %s frontend and results viewer. It was \
|
||||
originally derived from %s.""") \
|
||||
% (APP_DISPLAY_NAME, NMAP_DISPLAY_NAME, UMIT_DISPLAY_NAME))
|
||||
entry = _program_entry(APP_DISPLAY_NAME, APP_WEB_SITE, _(
|
||||
"%s is a multi-platform graphical %s frontend and results viewer. "
|
||||
"It was originally derived from %s.") % (
|
||||
APP_DISPLAY_NAME, NMAP_DISPLAY_NAME, UMIT_DISPLAY_NAME))
|
||||
self.vbox.pack_start(entry)
|
||||
|
||||
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.""") \
|
||||
% (UMIT_DISPLAY_NAME, NMAP_DISPLAY_NAME))
|
||||
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.") % (UMIT_DISPLAY_NAME, NMAP_DISPLAY_NAME))
|
||||
button = gtk.Button(_("%s credits") % UMIT_DISPLAY_NAME)
|
||||
button.connect("clicked", self._show_umit_credits)
|
||||
entry.hbox.pack_start(button, False)
|
||||
@@ -246,17 +253,20 @@ originally derived from %s.""") \
|
||||
return
|
||||
|
||||
self._umit_credits_dialog = UmitCredits()
|
||||
|
||||
def credits_destroyed(widget):
|
||||
# Mark that the credits dialog has been destroyed.
|
||||
self._umit_credits_dialog = None
|
||||
|
||||
self._umit_credits_dialog.connect("destroy", credits_destroyed)
|
||||
self._umit_credits_dialog.show_all()
|
||||
|
||||
|
||||
class UmitCredits(HIGWindow):
|
||||
def __init__(self):
|
||||
HIGWindow.__init__(self)
|
||||
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.__create_widgets()
|
||||
@@ -296,12 +306,18 @@ class UmitCredits(HIGWindow):
|
||||
self.hbox._pack_expand_fill(hig_box_space_holder())
|
||||
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.design_scroll, gtk.Label(_("Design")))
|
||||
self.notebook.append_page(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.notebook.append_page(
|
||||
self.written_by_scroll, gtk.Label(_("Written by")))
|
||||
self.notebook.append_page(
|
||||
self.design_scroll, gtk.Label(_("Design")))
|
||||
self.notebook.append_page(
|
||||
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_text.set_wrap_mode(gtk.WRAP_NONE)
|
||||
@@ -321,7 +337,7 @@ class UmitCredits(HIGWindow):
|
||||
self.nokia_scroll.add(self.nokia_text)
|
||||
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):
|
||||
b = self.written_by_text.get_buffer()
|
||||
|
||||
@@ -133,7 +133,7 @@ import ConfigParser
|
||||
# Python 2.7 that otherwise causes an assertion failure. See
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=620216#c10.
|
||||
import warnings
|
||||
warnings.filterwarnings("error", module = "gtk", append = "True")
|
||||
warnings.filterwarnings("error", module="gtk", append="True")
|
||||
try:
|
||||
import gtk
|
||||
except Exception:
|
||||
@@ -171,6 +171,7 @@ from zenmapGUI.higwidgets.higdialogs import HIGAlertDialog
|
||||
# gtk.main_quit.
|
||||
open_windows = []
|
||||
|
||||
|
||||
def _destroy_callback(window):
|
||||
open_windows.remove(window)
|
||||
if len(open_windows) == 0:
|
||||
@@ -183,6 +184,7 @@ def _destroy_callback(window):
|
||||
# Cleaning up data base
|
||||
UmitDB().cleanup(SearchConfig().converted_save_time)
|
||||
|
||||
|
||||
def new_window():
|
||||
w = ScanWindow()
|
||||
w.connect("destroy", _destroy_callback)
|
||||
@@ -193,11 +195,14 @@ def new_window():
|
||||
open_windows.append(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():
|
||||
return (hasattr(sys, "frozen") # new py2exe
|
||||
or hasattr(sys, "importers") # old py2exe
|
||||
or imp.is_frozen("__main__")) # tools/freeze
|
||||
return (hasattr(sys, "frozen") # new py2exe
|
||||
or hasattr(sys, "importers") # old py2exe
|
||||
or imp.is_frozen("__main__")) # tools/freeze
|
||||
|
||||
|
||||
def is_root():
|
||||
if 'NMAP_PRIVILEGED' in os.environ:
|
||||
@@ -207,6 +212,7 @@ def is_root():
|
||||
else:
|
||||
return sys.platform == "win32" or os.getuid() == 0 or is_maemo()
|
||||
|
||||
|
||||
def install_excepthook():
|
||||
# This will catch exceptions and send them to bugzilla
|
||||
def excepthook(type, value, tb):
|
||||
@@ -218,7 +224,7 @@ def install_excepthook():
|
||||
# produces a warning, but the lack of a display eventually causes a
|
||||
# segmentation fault. See http://live.gnome.org/PyGTK/WhatsNew210.
|
||||
import warnings
|
||||
warnings.filterwarnings("error", module = "gtk")
|
||||
warnings.filterwarnings("error", module="gtk")
|
||||
import gtk
|
||||
warnings.resetwarnings()
|
||||
|
||||
@@ -229,8 +235,7 @@ def install_excepthook():
|
||||
if type == ImportError:
|
||||
d = HIGAlertDialog(type=gtk.MESSAGE_ERROR,
|
||||
message_format=_("Import error"),
|
||||
secondary_text=_("""\
|
||||
A required module was not found.
|
||||
secondary_text=_("""A required module was not found.
|
||||
|
||||
""" + unicode(value)))
|
||||
d.run()
|
||||
@@ -246,6 +251,7 @@ A required module was not found.
|
||||
|
||||
sys.excepthook = excepthook
|
||||
|
||||
|
||||
def safe_shutdown(signum, stack):
|
||||
"""Kills any active scans/tabs and shuts down the application."""
|
||||
log.debug("\n\n%s\nSAFE SHUTDOWN!\n%s\n" % ("#" * 30, "#" * 30))
|
||||
@@ -256,6 +262,7 @@ def safe_shutdown(signum, stack):
|
||||
|
||||
sys.exit(signum)
|
||||
|
||||
|
||||
def run():
|
||||
if os.name == "posix":
|
||||
signal.signal(signal.SIGHUP, safe_shutdown)
|
||||
@@ -271,19 +278,25 @@ def run():
|
||||
try:
|
||||
# Create the ~/.zenmap directory by copying from the system-wide
|
||||
# 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:
|
||||
error_dialog = HIGAlertDialog(message_format = _("Error creating the per-user configuration directory"),
|
||||
secondary_text = _("""\
|
||||
error_dialog = HIGAlertDialog(
|
||||
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. \
|
||||
The directory is created by copying the contents of %s. \
|
||||
The specific error was\n\
|
||||
\n\
|
||||
%s\n\
|
||||
\n\
|
||||
The specific error was
|
||||
|
||||
%s
|
||||
|
||||
%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.\
|
||||
""") % (repr(Path.user_config_dir), repr(Path.config_dir), repr(str(e)), APP_DISPLAY_NAME))
|
||||
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
|
||||
)
|
||||
)
|
||||
error_dialog.run()
|
||||
error_dialog.destroy()
|
||||
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.
|
||||
zenmapCore.UmitConf.config_parser.read(Path.user_config_file)
|
||||
except ConfigParser.ParsingError, e:
|
||||
error_dialog = HIGAlertDialog(message_format = _("Error parsing the configuration file"),
|
||||
secondary_text = _("""\
|
||||
error_dialog = HIGAlertDialog(
|
||||
message_format=_("Error parsing the configuration file"),
|
||||
secondary_text=_("""\
|
||||
There was an error parsing the configuration file %s. \
|
||||
The specific error was\n\
|
||||
\n\
|
||||
%s\n\
|
||||
\n\
|
||||
The specific error was
|
||||
|
||||
%s
|
||||
|
||||
%s can continue without this file but any information in it will be ignored \
|
||||
until it is repaired.\
|
||||
""") % (Path.user_config_file, str(e), APP_DISPLAY_NAME))
|
||||
until it is repaired.""") % (Path.user_config_file, str(e), APP_DISPLAY_NAME)
|
||||
)
|
||||
error_dialog.run()
|
||||
error_dialog.destroy()
|
||||
|
||||
@@ -355,10 +369,13 @@ until it is repaired.\
|
||||
if main_is_frozen():
|
||||
gtk.gdk.threads_leave()
|
||||
|
||||
|
||||
class NonRootWarning (HIGAlertDialog):
|
||||
def __init__(self):
|
||||
warning_text = _('''You are trying to run %s with a non-root user!\n
|
||||
Some %s options need root privileges to work.''') % (APP_DISPLAY_NAME, NMAP_DISPLAY_NAME)
|
||||
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)
|
||||
|
||||
HIGAlertDialog.__init__(self, message_format=_('Non-root user'),
|
||||
secondary_text=warning_text)
|
||||
|
||||
@@ -130,6 +130,7 @@ import zenmapCore.I18N
|
||||
# For escaping text in marked-up labels.
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
|
||||
class BugReport(gtk.Window, object):
|
||||
def __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 \
|
||||
http://nmap.org/data/HACKING. Patches may be sent to nmap-dev \
|
||||
(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.button_box.set_layout(gtk.BUTTONBOX_END)
|
||||
|
||||
@@ -134,6 +134,7 @@ import zenmapCore.I18N
|
||||
# For escaping text in marked-up labels.
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
|
||||
class CrashReport(HIGDialog):
|
||||
def __init__(self, type, value, tb):
|
||||
HIGDialog.__init__(self)
|
||||
@@ -158,17 +159,16 @@ class CrashReport(HIGDialog):
|
||||
self.description_text.set_editable(False)
|
||||
|
||||
self.bug_text = gtk.Label()
|
||||
self.bug_text.set_markup(_("""\
|
||||
An unexpected error has crashed %(app_name)s. Please copy the stack trace below and \
|
||||
send it to the <a href="mailto:dev@nmap.org">dev@nmap.org</a> \
|
||||
mailing list. (<a href="http://seclists.org/nmap-dev/">More about the list.</a>) \
|
||||
The developers will see your report and try to fix the problem.""") % \
|
||||
{ "app_name": escape(APP_DISPLAY_NAME) })
|
||||
self.bug_text.set_markup(_('An unexpected error has crashed '
|
||||
'%(app_name)s. Please copy the stack trace below and send it to '
|
||||
'the <a href="mailto:dev@nmap.org">dev@nmap.org</a> mailing list. '
|
||||
'(<a href="http://seclists.org/nmap-dev/">More about the list.</a>'
|
||||
') The developers will see your report and try to fix the problem.'
|
||||
) % {"app_name": escape(APP_DISPLAY_NAME)})
|
||||
self.email_frame = gtk.Frame()
|
||||
self.email_label = gtk.Label()
|
||||
self.email_label.set_markup(_("""\
|
||||
<b>Copy and email to <a href="mailto:dev@nmap.org">dev@nmap.org</a>:</b>\
|
||||
"""))
|
||||
self.email_label.set_markup(_('<b>Copy and email to '
|
||||
'<a href="mailto:dev@nmap.org">dev@nmap.org</a>:</b>'))
|
||||
self.btn_copy = gtk.Button(stock=gtk.STOCK_COPY)
|
||||
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):
|
||||
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_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)
|
||||
|
||||
if __name__ == "__main__":
|
||||
c = CrashReport(None,None,None)
|
||||
c = CrashReport(None, None, None)
|
||||
c.show_all()
|
||||
c.connect("delete-event", lambda x, y: gtk.main_quit())
|
||||
|
||||
|
||||
@@ -129,7 +129,8 @@ import sys
|
||||
import xml.sax
|
||||
|
||||
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.higtables import HIGTable
|
||||
from zenmapGUI.higwidgets.higbuttons import HIGButton
|
||||
@@ -144,6 +145,7 @@ from zenmapGUI.FileChoosers import ResultsFileSingleChooserDialog
|
||||
# In milliseconds.
|
||||
NDIFF_CHECK_TIMEOUT = 200
|
||||
|
||||
|
||||
class ScanChooser(HIGVBox):
|
||||
"""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
|
||||
@@ -193,7 +195,7 @@ class ScanChooser(HIGVBox):
|
||||
def get_buffer(self):
|
||||
return self.txt_scan_result.get_buffer()
|
||||
|
||||
def show_scan (self, widget):
|
||||
def show_scan(self, widget):
|
||||
nmap_output = self.get_nmap_output()
|
||||
if nmap_output is not None:
|
||||
self.txt_scan_result.get_buffer().set_text(nmap_output)
|
||||
@@ -201,14 +203,15 @@ class ScanChooser(HIGVBox):
|
||||
def normalize_output(self, output):
|
||||
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_expand_fill(self.table)
|
||||
|
||||
def _attaching_widgets (self):
|
||||
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.exp_scan, 0,2,1,2)
|
||||
def _attaching_widgets(self):
|
||||
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.exp_scan, 0, 2, 1, 2)
|
||||
|
||||
def _set_scrolled(self):
|
||||
self.scrolled.set_border_width(5)
|
||||
@@ -223,19 +226,20 @@ class ScanChooser(HIGVBox):
|
||||
# Setting scrolled window
|
||||
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.add(self.txg_tag)
|
||||
self.txg_tag.set_property("family", "Monospace")
|
||||
|
||||
self.txt_scan_result.set_wrap_mode(gtk.WRAP_WORD)
|
||||
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)
|
||||
|
||||
def open_file (self, widget):
|
||||
def open_file(self, widget):
|
||||
file_chooser = ResultsFileSingleChooserDialog(_("Select Scan Result"))
|
||||
|
||||
response = file_chooser.run()
|
||||
@@ -248,15 +252,19 @@ class ScanChooser(HIGVBox):
|
||||
except xml.sax.SAXParseException, e:
|
||||
alert = HIGAlertDialog(
|
||||
message_format='<b>%s</b>' % _('Error parsing file'),
|
||||
secondary_text=_("The file is not an Nmap XML output file. \
|
||||
The parsing error that occurred was\n%s") % str(e))
|
||||
secondary_text=_(
|
||||
"The file is not an Nmap XML output file. "
|
||||
"The parsing error that occurred was\n%s") % str(e))
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
return False
|
||||
except Exception, e:
|
||||
alert = HIGAlertDialog(
|
||||
message_format='<b>%s</b>' % _('Cannot open selected file'),
|
||||
secondary_text=_("This error occurred while trying to open the file:\n%s") % str(e))
|
||||
message_format='<b>%s</b>' % _(
|
||||
'Cannot open selected file'),
|
||||
secondary_text=_("""\
|
||||
This error occurred while trying to open the file:
|
||||
%s""") % str(e))
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
return False
|
||||
@@ -276,9 +284,10 @@ The parsing error that occurred was\n%s") % str(e))
|
||||
self.list_scan.append([new_scan_name])
|
||||
self.scan_dict[new_scan_name] = parser
|
||||
|
||||
def _text_changed_cb (self, widget):
|
||||
buff = self.txt_scan_result.get_buffer ()
|
||||
buff.apply_tag(self.txg_tag, buff.get_start_iter(), buff.get_end_iter())
|
||||
def _text_changed_cb(self, widget):
|
||||
buff = self.txt_scan_result.get_buffer()
|
||||
buff.apply_tag(
|
||||
self.txg_tag, buff.get_start_iter(), buff.get_end_iter())
|
||||
|
||||
def get_parsed_scan(self):
|
||||
"""Return the currently selected scan's parsed output as an NmapParser
|
||||
@@ -306,9 +315,10 @@ class DiffWindow(gtk.Window):
|
||||
gtk.Window.__init__(self)
|
||||
self.set_title(_("Compare Results"))
|
||||
self.ndiff_process = None
|
||||
# We allow the user to start a new diff before the old one has finished.
|
||||
# We have to keep references to old processes until they finish to avoid
|
||||
# problems when tearing down the Python interpreter at program exit.
|
||||
# We allow the user to start a new diff before the old one has
|
||||
# finished. We have to keep references to old processes until they
|
||||
# finish to avoid problems when tearing down the Python interpreter at
|
||||
# program exit.
|
||||
self.old_processes = []
|
||||
self.timer_id = None
|
||||
|
||||
@@ -358,12 +368,13 @@ class DiffWindow(gtk.Window):
|
||||
self.scan_chooser_a.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,
|
||||
such as when a different scan was selected in one of the choosers."""
|
||||
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.
|
||||
self.old_processes.append(self.ndiff_process)
|
||||
self.ndiff_process = None
|
||||
@@ -378,14 +389,17 @@ class DiffWindow(gtk.Window):
|
||||
self.ndiff_process = zenmapCore.Diff.ndiff(scan_a, scan_b)
|
||||
except OSError, e:
|
||||
alert = HIGAlertDialog(
|
||||
message_format = _("Error running ndiff"),
|
||||
secondary_text = _("There was an error running the ndiff program.\n\n") + str(e).decode(sys.getdefaultencoding(), "replace"))
|
||||
message_format=_("Error running ndiff"),
|
||||
secondary_text=_(
|
||||
"There was an error running the ndiff program.\n\n"
|
||||
) + str(e).decode(sys.getdefaultencoding(), "replace"))
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
else:
|
||||
self.progress.show()
|
||||
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):
|
||||
"""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()
|
||||
except zenmapCore.Diff.NdiffParseException, e:
|
||||
alert = HIGAlertDialog(
|
||||
message_format = _("Error parsing ndiff output"),
|
||||
secondary_text = str(e))
|
||||
message_format=_("Error parsing ndiff output"),
|
||||
secondary_text=str(e))
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
else:
|
||||
self.diff_view.show_diff(diff)
|
||||
else:
|
||||
# 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()
|
||||
if len(stderr) > 0:
|
||||
error_text += "\n\n" + stderr
|
||||
alert = HIGAlertDialog(
|
||||
message_format = _("Error running ndiff"),
|
||||
secondary_text = error_text)
|
||||
message_format=_("Error running ndiff"),
|
||||
secondary_text=error_text)
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
|
||||
@@ -445,6 +461,7 @@ class DiffWindow(gtk.Window):
|
||||
def close(self, widget=None, extra=None):
|
||||
self.destroy()
|
||||
|
||||
|
||||
class DiffView(gtk.TextView):
|
||||
REMOVE_COLOR = "#ffaaaa"
|
||||
ADD_COLOR = "#ccffcc"
|
||||
@@ -456,9 +473,10 @@ class DiffView(gtk.TextView):
|
||||
|
||||
buff = self.get_buffer()
|
||||
# Create text markup tags.
|
||||
buff.create_tag("=", font = "Monospace")
|
||||
buff.create_tag("-", font = "Monospace", background = self.REMOVE_COLOR)
|
||||
buff.create_tag("+", font = "Monospace", background = self.ADD_COLOR)
|
||||
buff.create_tag("=", font="Monospace")
|
||||
buff.create_tag(
|
||||
"-", font="Monospace", background=self.REMOVE_COLOR)
|
||||
buff.create_tag("+", font="Monospace", background=self.ADD_COLOR)
|
||||
|
||||
def clear(self):
|
||||
self.get_buffer().set_text(u"")
|
||||
@@ -494,6 +512,6 @@ if __name__ == "__main__":
|
||||
"Parsed 4": parsed4})
|
||||
|
||||
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()
|
||||
|
||||
@@ -128,6 +128,7 @@ import zenmapCore.I18N
|
||||
|
||||
RESPONSE_OPEN_DIRECTORY = 1
|
||||
|
||||
|
||||
class AllFilesFileFilter(gtk.FileFilter):
|
||||
def __init__(self):
|
||||
gtk.FileFilter.__init__(self)
|
||||
@@ -136,6 +137,7 @@ class AllFilesFileFilter(gtk.FileFilter):
|
||||
self.add_pattern(pattern)
|
||||
self.set_name(_("All files (%s)") % pattern)
|
||||
|
||||
|
||||
class ResultsFileFilter(gtk.FileFilter):
|
||||
def __init__(self):
|
||||
gtk.FileFilter.__init__(self)
|
||||
@@ -145,6 +147,7 @@ class ResultsFileFilter(gtk.FileFilter):
|
||||
self.add_pattern(pattern)
|
||||
self.set_name(_("Nmap XML files (%s)") % ", ".join(patterns))
|
||||
|
||||
|
||||
class ScriptFileFilter(gtk.FileFilter):
|
||||
def __init__(self):
|
||||
gtk.FileFilter.__init__(self)
|
||||
@@ -154,6 +157,7 @@ class ScriptFileFilter(gtk.FileFilter):
|
||||
self.add_pattern(pattern)
|
||||
self.set_name(_("NSE scripts (%s)") % ", ".join(patterns))
|
||||
|
||||
|
||||
class UnicodeFileChooserDialog(gtk.FileChooserDialog):
|
||||
"""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
|
||||
@@ -173,6 +177,7 @@ class UnicodeFileChooserDialog(gtk.FileChooserDialog):
|
||||
pass
|
||||
return filename
|
||||
|
||||
|
||||
class AllFilesFileChooserDialog(UnicodeFileChooserDialog):
|
||||
def __init__(self, title="", parent=None,
|
||||
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
@@ -184,6 +189,7 @@ class AllFilesFileChooserDialog(UnicodeFileChooserDialog):
|
||||
self.set_default_response(gtk.RESPONSE_OK)
|
||||
self.add_filter(AllFilesFileFilter())
|
||||
|
||||
|
||||
class ResultsFileSingleChooserDialog(UnicodeFileChooserDialog):
|
||||
"""This results file choose only allows the selection of single files, not
|
||||
directories."""
|
||||
@@ -198,6 +204,7 @@ class ResultsFileSingleChooserDialog(UnicodeFileChooserDialog):
|
||||
for f in (ResultsFileFilter(), AllFilesFileFilter()):
|
||||
self.add_filter(f)
|
||||
|
||||
|
||||
class ResultsFileChooserDialog(UnicodeFileChooserDialog):
|
||||
def __init__(self, title="", parent=None,
|
||||
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
@@ -211,6 +218,7 @@ class ResultsFileChooserDialog(UnicodeFileChooserDialog):
|
||||
for f in (ResultsFileFilter(), AllFilesFileFilter()):
|
||||
self.add_filter(f)
|
||||
|
||||
|
||||
class ScriptFileChooserDialog(UnicodeFileChooserDialog):
|
||||
def __init__(self, title="", parent=None,
|
||||
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
@@ -224,6 +232,7 @@ class ScriptFileChooserDialog(UnicodeFileChooserDialog):
|
||||
for f in (ScriptFileFilter(), AllFilesFileFilter()):
|
||||
self.add_filter(f)
|
||||
|
||||
|
||||
class SaveResultsFileChooserDialog(UnicodeFileChooserDialog):
|
||||
TYPES = (
|
||||
(_("By extension"), None, None),
|
||||
@@ -286,12 +295,14 @@ class SaveResultsFileChooserDialog(UnicodeFileChooserDialog):
|
||||
def get_format(self):
|
||||
"""Get the save format the user has chosen. It is a string, either
|
||||
"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:
|
||||
# Guess based on extension. "xml" is the default if unknown.
|
||||
return self.EXTENSIONS.get(self.get_extension(), "xml")
|
||||
return filetype
|
||||
|
||||
|
||||
class DirectoryChooserDialog(UnicodeFileChooserDialog):
|
||||
def __init__(self, title="", parent=None,
|
||||
action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
@@ -301,6 +312,7 @@ class DirectoryChooserDialog(UnicodeFileChooserDialog):
|
||||
UnicodeFileChooserDialog.__init__(self, title, parent, action, buttons)
|
||||
self.set_default_response(gtk.RESPONSE_OK)
|
||||
|
||||
|
||||
class SaveToDirectoryChooserDialog(UnicodeFileChooserDialog):
|
||||
def __init__(self, title="", parent=None,
|
||||
action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
|
||||
@@ -4,6 +4,7 @@ import gobject
|
||||
from zenmapGUI.higwidgets.higboxes import HIGHBox
|
||||
from zenmapGUI.higwidgets.higlabels import HintWindow
|
||||
|
||||
|
||||
class FilterBar(HIGHBox):
|
||||
"""This is the bar that appears while the host filter is active. It allows
|
||||
entering a string that restricts the set of visible hosts."""
|
||||
|
||||
@@ -171,13 +171,18 @@ if pixmap_path:
|
||||
# Try again.
|
||||
pass
|
||||
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
|
||||
iconset = gtk.IconSet(pixbuf)
|
||||
iconfactory.add(key, iconset)
|
||||
log.debug('Register %s icon name for file %s' % (key, file_path))
|
||||
iconfactory.add_default()
|
||||
|
||||
|
||||
def get_os_icon(host):
|
||||
osmatch = host.get_best_osmatch()
|
||||
if osmatch and osmatch['osclasses']:
|
||||
@@ -190,6 +195,7 @@ def get_os_icon(host):
|
||||
else:
|
||||
return get_os(None, None, 'icon')
|
||||
|
||||
|
||||
def get_os_logo(host):
|
||||
osmatch = host.get_best_osmatch()
|
||||
if osmatch and osmatch['osclasses']:
|
||||
@@ -202,51 +208,53 @@ def get_os_logo(host):
|
||||
else:
|
||||
return get_os(None, None, 'logo')
|
||||
|
||||
|
||||
def get_os(osfamily, osmatch, type):
|
||||
if osfamily:
|
||||
if osfamily == 'Linux':
|
||||
if re.findall("ubuntu", osmatch.lower()):
|
||||
# Ubuntu icon
|
||||
return 'ubuntu_%s'%type
|
||||
return 'ubuntu_%s' % type
|
||||
elif re.findall("red hat", osmatch.lower()):
|
||||
# RedHat icon
|
||||
return 'redhat_%s'%type
|
||||
return 'redhat_%s' % type
|
||||
else:
|
||||
# Generic Linux icon
|
||||
return 'linux_%s'%type
|
||||
return 'linux_%s' % type
|
||||
elif osfamily == 'Windows':
|
||||
# Windows icon
|
||||
return 'win_%s'%type
|
||||
return 'win_%s' % type
|
||||
elif osfamily == 'OpenBSD':
|
||||
# OpenBSD icon
|
||||
return 'openbsd_%s'%type
|
||||
return 'openbsd_%s' % type
|
||||
elif osfamily == 'FreeBSD':
|
||||
# FreeBSD icon
|
||||
return 'freebsd_%s'%type
|
||||
return 'freebsd_%s' % type
|
||||
elif osfamily == 'NetBSD':
|
||||
# NetBSD icon
|
||||
return 'default_%s'%type
|
||||
return 'default_%s' % type
|
||||
elif osfamily == 'Solaris':
|
||||
# Solaris icon
|
||||
return 'solaris_%s'%type
|
||||
return 'solaris_%s' % type
|
||||
elif osfamily == 'OpenSolaris':
|
||||
# OpenSolaris icon
|
||||
return 'solaris_%s'%type
|
||||
return 'solaris_%s' % type
|
||||
elif osfamily == 'IRIX':
|
||||
# Irix icon
|
||||
return 'irix_%s'%type
|
||||
return 'irix_%s' % type
|
||||
elif osfamily == 'Mac OS X':
|
||||
# Mac OS X icon
|
||||
return 'macosx_%s'%type
|
||||
return 'macosx_%s' % type
|
||||
elif osfamily == 'Mac OS':
|
||||
# Mac OS icon
|
||||
return 'macosx_%s'%type
|
||||
return 'macosx_%s' % type
|
||||
else:
|
||||
# Default OS icon
|
||||
return 'default_%s'%type
|
||||
return 'default_%s' % type
|
||||
else:
|
||||
# Unknown OS icon
|
||||
return 'unknown_%s'%type
|
||||
return 'unknown_%s' % type
|
||||
|
||||
|
||||
def get_vulnerability_logo(open_ports):
|
||||
open_ports = int(open_ports)
|
||||
|
||||
@@ -159,6 +159,7 @@ hildon = None
|
||||
|
||||
if is_maemo():
|
||||
import hildon
|
||||
|
||||
class UmitScanWindow(hildon.Window):
|
||||
def __init__(self):
|
||||
hildon.Window.__init__(self)
|
||||
@@ -174,9 +175,10 @@ else:
|
||||
HIGMainWindow.__init__(self)
|
||||
self.vbox = gtk.VBox()
|
||||
|
||||
|
||||
def can_print():
|
||||
"""Return true if we have printing operations (PyGTK 2.10 or later) or false
|
||||
otherwise."""
|
||||
"""Return true if we have printing operations (PyGTK 2.10 or later) or
|
||||
false otherwise."""
|
||||
try:
|
||||
gtk.PrintOperation
|
||||
except AttributeError:
|
||||
@@ -184,6 +186,7 @@ def can_print():
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class ScanWindow(UmitScanWindow):
|
||||
def __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.add(self.vbox)
|
||||
|
||||
self.connect ('delete-event', self._exit_cb)
|
||||
self.connect('delete-event', self._exit_cb)
|
||||
self._create_ui_manager()
|
||||
self._create_menubar()
|
||||
self._create_scan_interface()
|
||||
@@ -433,25 +436,29 @@ class ScanWindow(UmitScanWindow):
|
||||
|
||||
def _search_scan_result(self, widget):
|
||||
"""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()
|
||||
|
||||
def _filter_cb(self, widget):
|
||||
self.scan_interface.toggle_filter_bar()
|
||||
|
||||
def _load_search_result(self, results):
|
||||
"""This function is passed as an argument to the SearchWindow.__init__ method.
|
||||
When the user selects scans in the search window and clicks on \"Open\", this
|
||||
function is called to load each of the selected scans into a new window."""
|
||||
"""This function is passed as an argument to the SearchWindow.__init__
|
||||
method. When the user selects scans in the search window and clicks on
|
||||
"Open", this function is called to load each of the selected scans into
|
||||
a new window."""
|
||||
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):
|
||||
"""This function is passed as an argument to the SearchWindow.__init__ method.
|
||||
When the user selects scans in the search window and clicks on \"Append\", this
|
||||
function is called to append the selected scans into the current window."""
|
||||
"""This function is passed as an argument to the SearchWindow.__init__
|
||||
method. When the user selects scans in the search window and clicks on
|
||||
"Append", this function is called to append the selected scans into the
|
||||
current window."""
|
||||
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):
|
||||
"""Stores the network inventory into the database."""
|
||||
@@ -459,23 +466,28 @@ class ScanWindow(UmitScanWindow):
|
||||
try:
|
||||
scan_interface.inventory.save_to_db()
|
||||
except Exception, e:
|
||||
alert = HIGAlertDialog(message_format = _("Can't save to database"),
|
||||
secondary_text = _("Can't store unsaved scans to the recent scans database:\n%s") % str(e))
|
||||
alert = HIGAlertDialog(
|
||||
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.destroy()
|
||||
log.debug(">>> Can't save result to database: %s." % str(e))
|
||||
|
||||
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()
|
||||
new_rscan_xml = ''
|
||||
|
||||
for scan in r_scans[:7]:
|
||||
scan = scan.replace('\n','')
|
||||
if os.access(split(scan)[0],os.R_OK) and isfile(scan):
|
||||
scan = scan.replace('\n','')
|
||||
new_rscan = (scan, None, scan, None, scan, self._load_recent_scan)
|
||||
new_rscan_xml += "<menuitem action=%s/>\n" % xml.sax.saxutils.quoteattr(scan)
|
||||
scan = scan.replace('\n', '')
|
||||
if os.access(split(scan)[0], os.R_OK) and isfile(scan):
|
||||
scan = scan.replace('\n', '')
|
||||
new_rscan = (
|
||||
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)
|
||||
else:
|
||||
@@ -501,16 +513,19 @@ class ScanWindow(UmitScanWindow):
|
||||
self.menubar.show_all()
|
||||
|
||||
def _create_scan_interface(self):
|
||||
self.scan_interface.scan_result.scan_result_notebook.scans_list.append_button.connect("clicked", self._append_scan_results_cb)
|
||||
self.scan_interface.scan_result.scan_result_notebook.nmap_output.connect("changed", self._displayed_scan_change_cb)
|
||||
notebook = self.scan_interface.scan_result.scan_result_notebook
|
||||
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.scan_interface.show_all()
|
||||
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."""
|
||||
if self._results_filechooser_dialog is None:
|
||||
self._results_filechooser_dialog = ResultsFileChooserDialog(title = title)
|
||||
self._results_filechooser_dialog = ResultsFileChooserDialog(
|
||||
title=title)
|
||||
|
||||
filename = None
|
||||
response = self._results_filechooser_dialog.run()
|
||||
@@ -519,8 +534,9 @@ class ScanWindow(UmitScanWindow):
|
||||
elif response == RESPONSE_OPEN_DIRECTORY:
|
||||
filename = self._results_filechooser_dialog.get_filename()
|
||||
|
||||
# Check if the selected filename is a directory. If not, we take only the
|
||||
# directory part of the path, omitting the actual name of the selected file.
|
||||
# Check if the selected filename is a directory. If not, we take
|
||||
# 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):
|
||||
filename = os.path.dirname(filename)
|
||||
|
||||
@@ -528,8 +544,9 @@ class ScanWindow(UmitScanWindow):
|
||||
return filename
|
||||
|
||||
def _load_scan_results_cb(self, p):
|
||||
"""'Open Scan' callback function. Displays a file chooser dialog and loads the
|
||||
scan from the selected file or from the selected directory."""
|
||||
"""'Open Scan' callback function. Displays a file chooser dialog and
|
||||
loads the scan from the selected file or from the selected
|
||||
directory."""
|
||||
filename = self.show_open_dialog(p.get_name())
|
||||
if filename is not None:
|
||||
scan_interface = self.get_empty_interface()
|
||||
@@ -539,8 +556,8 @@ class ScanWindow(UmitScanWindow):
|
||||
self._load(scan_interface, filename)
|
||||
|
||||
def _append_scan_results_cb(self, p):
|
||||
"""'Append Scan' callback function. Displays a file chooser dialog and appends the
|
||||
scan from the selected file into the current window."""
|
||||
"""'Append Scan' callback function. Displays a file chooser dialog and
|
||||
appends the scan from the selected file into the current window."""
|
||||
filename = self.show_open_dialog(p.get_name())
|
||||
if filename is not None:
|
||||
if os.path.isdir(filename):
|
||||
@@ -559,7 +576,8 @@ class ScanWindow(UmitScanWindow):
|
||||
widget.set_sensitive(entry is not None)
|
||||
|
||||
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())
|
||||
|
||||
def _load(self, scan_interface, filename=None, parsed_result=None):
|
||||
@@ -587,54 +605,59 @@ class ScanWindow(UmitScanWindow):
|
||||
|
||||
def _load_directory(self, scan_interface, 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
|
||||
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):
|
||||
"""'Save Scan' callback function. If it's OK to save the scan, it displays a
|
||||
'Save File' dialog and saves the scan. If not, it displays an appropriate
|
||||
alert dialog."""
|
||||
"""'Save Scan' callback function. If it's OK to save the scan, it
|
||||
displays a 'Save File' dialog and saves the scan. If not, it displays
|
||||
an appropriate alert dialog."""
|
||||
num_scans = len(self.scan_interface.inventory.get_scans())
|
||||
if num_scans == 0:
|
||||
alert = HIGAlertDialog(message_format=_('Nothing to save'),
|
||||
secondary_text=_("""\
|
||||
There are no scans with results to be saved. Run a scan with the "Scan" button \
|
||||
first."""))
|
||||
alert = HIGAlertDialog(
|
||||
message_format=_('Nothing to save'),
|
||||
secondary_text=_(
|
||||
'There are no scans with results to be saved. '
|
||||
'Run a scan with the "Scan" button first.'))
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
return
|
||||
num_scans_running = self.scan_interface.num_scans_running()
|
||||
if num_scans_running > 0:
|
||||
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:
|
||||
text = _("There are %u scans still running. Wait until they finish and then save.")\
|
||||
% num_scans_running
|
||||
text = _("There are %u scans still running. Wait until they "
|
||||
"finish and then save.") % num_scans_running
|
||||
alert = HIGAlertDialog(message_format=_('Scan is running'),
|
||||
secondary_text=text)
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
return
|
||||
|
||||
# If there's more than one scan in the inventory, display a warning dialog saying
|
||||
# that only the most recent scan will be saved
|
||||
# If there's more than one scan in the inventory, display a warning
|
||||
# dialog saying that only the most recent scan will be saved
|
||||
selected = 0
|
||||
if num_scans > 1:
|
||||
#text = _("You have %u scans loaded in the current view. Only the most recent scan " \
|
||||
# "will be saved." % num_scans)
|
||||
#alert = HIGAlertDialog(message_format=_("More than one scan loaded"),
|
||||
# secondary_text=text)
|
||||
#text = _("You have %u scans loaded in the current view. "
|
||||
# "Only the most recent scan will be saved." % num_scans)
|
||||
#alert = HIGAlertDialog(
|
||||
# message_format=_("More than one scan loaded"),
|
||||
# secondary_text=text)
|
||||
#alert.run()
|
||||
#alert.destroy()
|
||||
dlg = HIGDialog(title="Choose a scan to save",
|
||||
parent=self,
|
||||
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
|
||||
dlg.vbox.pack_start(gtk.Label("You have %u scans loaded in the current view.\n" \
|
||||
"Select the scan which you would like to save." \
|
||||
% num_scans), False)
|
||||
dlg = HIGDialog(
|
||||
title="Choose a scan to save",
|
||||
parent=self,
|
||||
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
|
||||
dlg.vbox.pack_start(gtk.Label(
|
||||
"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()
|
||||
for scan in self.scan_interface.inventory.get_scans():
|
||||
scan_combo.append_text(scan.nmap_command)
|
||||
@@ -653,7 +676,8 @@ first."""))
|
||||
SaveResultsFileChooserDialog(title=_('Save Scan'))
|
||||
# Supply a default file name if this scan was previously saved.
|
||||
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()
|
||||
|
||||
@@ -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()
|
||||
if num_scans_running > 0:
|
||||
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:
|
||||
text = _("There are %u scans still running. Wait until they finish and then save.")\
|
||||
% num_scans_running
|
||||
text = _("There are %u scans still running. Wait until they "
|
||||
"finish and then save.") % num_scans_running
|
||||
alert = HIGAlertDialog(message_format=_('Scan is running'),
|
||||
secondary_text=text)
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
return
|
||||
|
||||
# We have multiple scans in our network inventory, so we need to display a directory
|
||||
# chooser dialog
|
||||
dir_chooser = SaveToDirectoryChooserDialog(title=_("Choose a directory to save scans into"))
|
||||
# We have multiple scans in our network inventory, so we need to
|
||||
# display a directory chooser dialog
|
||||
dir_chooser = SaveToDirectoryChooserDialog(
|
||||
title=_("Choose a directory to save scans into"))
|
||||
if dir_chooser.run() == gtk.RESPONSE_OK:
|
||||
self._save_all(self.scan_interface, dir_chooser.get_filename())
|
||||
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.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
|
||||
dialog if the save fails."""
|
||||
log.debug(">>> File being saved: %s" % saved_filename)
|
||||
try:
|
||||
scan_interface.inventory.save_to_file(saved_filename, selected_index, format)
|
||||
scan_interface.inventory.get_scans()[selected_index].unsaved = False
|
||||
scan_interface.inventory.save_to_file(
|
||||
saved_filename, selected_index, format)
|
||||
scan_interface.inventory.get_scans()[selected_index].unsaved = \
|
||||
False
|
||||
except (OSError, IOError), e:
|
||||
alert = HIGAlertDialog(message_format=_('Can\'t save file'),
|
||||
secondary_text=_('Can\'t open file to write.\n%s') % str(e))
|
||||
alert = HIGAlertDialog(
|
||||
message_format=_("Can't save file"),
|
||||
secondary_text=_("Can't open file to write.\n%s") % str(e))
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
else:
|
||||
@@ -766,12 +796,16 @@ This scan has not been run yet. Start the scan with the "Scan" button first.'))
|
||||
return w
|
||||
|
||||
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.show_all()
|
||||
|
||||
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.show_all()
|
||||
|
||||
@@ -779,18 +813,20 @@ This scan has not been run yet. Start the scan with the "Scan" button first.'))
|
||||
show_help()
|
||||
|
||||
def _exit_cb(self, *args):
|
||||
"""Closes the window, prompting for confirmation if necessary. If one of
|
||||
the tabs couldn't be closed, the function returns True and doesn't exit
|
||||
the application."""
|
||||
"""Closes the window, prompting for confirmation if necessary. If one
|
||||
of the tabs couldn't be closed, the function returns True and doesn't
|
||||
exit the application."""
|
||||
if self.scan_interface.changed:
|
||||
log.debug("Found changes on closing window")
|
||||
dialog = HIGDialog(buttons=(_('Close anyway').encode('utf-8'), gtk.RESPONSE_CLOSE,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
|
||||
dialog = HIGDialog(
|
||||
buttons=(_('Close anyway').encode('utf-8'),
|
||||
gtk.RESPONSE_CLOSE, gtk.STOCK_CANCEL,
|
||||
gtk.RESPONSE_CANCEL))
|
||||
|
||||
alert = HIGEntryLabel('<b>%s</b>' % _("Unsaved changes"))
|
||||
|
||||
text = HIGEntryLabel(_('The given scan has unsaved changes.\n\
|
||||
What do you want to do?'))
|
||||
text = HIGEntryLabel(_("The given scan has unsaved changes.\n"
|
||||
"What do you want to do?"))
|
||||
hbox = HIGHBox()
|
||||
hbox.set_border_width(5)
|
||||
hbox.set_spacing(12)
|
||||
@@ -800,7 +836,8 @@ What do you want to do?'))
|
||||
vbox.set_spacing(12)
|
||||
|
||||
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(text)
|
||||
@@ -822,13 +859,16 @@ What do you want to do?'))
|
||||
|
||||
elif self.scan_interface.num_scans_running() > 0:
|
||||
log.debug("Trying to close a window with a running scan")
|
||||
dialog = HIGDialog(buttons=(_('Close anyway').encode('utf-8'), gtk.RESPONSE_CLOSE,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
|
||||
dialog = HIGDialog(
|
||||
buttons=(_('Close anyway').encode('utf-8'),
|
||||
gtk.RESPONSE_CLOSE, gtk.STOCK_CANCEL,
|
||||
gtk.RESPONSE_CANCEL))
|
||||
|
||||
alert = HIGEntryLabel('<b>%s</b>' % _("Trying to close"))
|
||||
|
||||
text = HIGEntryLabel(_('The window you are trying to close has a scan \
|
||||
running at the background.\nWhat do you want to do?'))
|
||||
text = HIGEntryLabel(_(
|
||||
"The window you are trying to close has a scan running in "
|
||||
"the background.\nWhat do you want to do?"))
|
||||
hbox = HIGHBox()
|
||||
hbox.set_border_width(5)
|
||||
hbox.set_spacing(12)
|
||||
@@ -838,7 +878,8 @@ running at the background.\nWhat do you want to do?'))
|
||||
vbox.set_spacing(12)
|
||||
|
||||
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(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()
|
||||
if entry is None:
|
||||
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):
|
||||
"""Close all open windows."""
|
||||
@@ -874,12 +916,15 @@ running at the background.\nWhat do you want to do?'))
|
||||
if window._exit_cb():
|
||||
break
|
||||
|
||||
def _load_diff_compare_cb (self, widget=None, extra=None):
|
||||
"""Loads all active scans into a dictionary, passes it to the DiffWindow
|
||||
constructor, and then displays the 'Compare Results' window."""
|
||||
self.diff_window = DiffWindow(self.scan_interface.inventory.get_scans())
|
||||
def _load_diff_compare_cb(self, widget=None, extra=None):
|
||||
"""Loads all active scans into a dictionary, passes it to the
|
||||
DiffWindow constructor, and then displays the 'Compare Results'
|
||||
window."""
|
||||
self.diff_window = DiffWindow(
|
||||
self.scan_interface.inventory.get_scans())
|
||||
self.diff_window.show_all()
|
||||
|
||||
|
||||
def show_help():
|
||||
import urllib
|
||||
import webbrowser
|
||||
|
||||
@@ -134,6 +134,7 @@ from zenmapGUI.higwidgets.higtables import HIGTable
|
||||
from zenmapGUI.higwidgets.higlabels import HIGEntryLabel
|
||||
from zenmapGUI.higwidgets.higbuttons import HIGButton, HIGToggleButton
|
||||
|
||||
|
||||
class NmapOutputProperties(HIGDialog):
|
||||
def __init__(self, nmap_output_view):
|
||||
HIGDialog.__init__(self, _("Nmap Output Properties"),
|
||||
@@ -164,10 +165,14 @@ class NmapOutputProperties(HIGDialog):
|
||||
#############
|
||||
# Properties:
|
||||
self.property_names = {"details": [_("details"), "MAC Address:"],
|
||||
"port_list": [_("port listing title"), "PORT STATE SERVICE"],
|
||||
"open_port": [_("open port"), "22/tcp open ssh"],
|
||||
"closed_port": [_("closed port"), "70/tcp closed gopher"],
|
||||
"filtered_port": [_("filtered port"), "80/tcp filtered http"],
|
||||
"port_list": [_("port listing title"),
|
||||
"PORT STATE SERVICE"],
|
||||
"open_port": [_("open port"),
|
||||
"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"],
|
||||
"hostname": [_("hostname"), "scanme.nmap.org"],
|
||||
"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(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
|
||||
y2 = 1
|
||||
for p in self.property_names:
|
||||
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.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.underline_tg_button, 4, 5, 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)
|
||||
self.highlight_main_table.attach(
|
||||
hp.underline_tg_button, 4, 5, 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
|
||||
hp.update_example()
|
||||
@@ -203,13 +213,13 @@ class NmapOutputProperties(HIGDialog):
|
||||
y1 += 1
|
||||
y2 += 1
|
||||
|
||||
|
||||
# Packing main table into main vbox
|
||||
self.highlight_main_vbox.pack_start(self.highlight_main_table)
|
||||
|
||||
# Adding color tab
|
||||
self.properties_notebook.append_page(self.highlight_main_vbox,
|
||||
gtk.Label(_("Highlight definitions")))
|
||||
self.properties_notebook.append_page(
|
||||
self.highlight_main_vbox,
|
||||
gtk.Label(_("Highlight definitions")))
|
||||
|
||||
|
||||
class HighlightProperty(object):
|
||||
@@ -235,8 +245,10 @@ class HighlightProperty(object):
|
||||
self.bold_tg_button = HIGToggleButton("", gtk.STOCK_BOLD)
|
||||
self.italic_tg_button = HIGToggleButton("", gtk.STOCK_ITALIC)
|
||||
self.underline_tg_button = HIGToggleButton("", gtk.STOCK_UNDERLINE)
|
||||
self.text_color_button = HIGButton(_("Text"), stock=gtk.STOCK_SELECT_COLOR)
|
||||
self.highlight_color_button = HIGButton(_("Highlight"), stock=gtk.STOCK_SELECT_COLOR)
|
||||
self.text_color_button = HIGButton(
|
||||
_("Text"), stock=gtk.STOCK_SELECT_COLOR)
|
||||
self.highlight_color_button = HIGButton(
|
||||
_("Highlight"), stock=gtk.STOCK_SELECT_COLOR)
|
||||
|
||||
def __connect_buttons(self):
|
||||
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.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
|
||||
|
||||
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.ok_button.connect("clicked", self.text_color_dialog_ok, color_dialog)
|
||||
color_dialog.cancel_button.connect("clicked",
|
||||
self.text_color_dialog_cancel, color_dialog)
|
||||
color_dialog.connect("delete-event", self.text_color_dialog_close, color_dialog)
|
||||
color_dialog.ok_button.connect(
|
||||
"clicked", self.text_color_dialog_ok, color_dialog)
|
||||
color_dialog.cancel_button.connect(
|
||||
"clicked", self.text_color_dialog_cancel, color_dialog)
|
||||
color_dialog.connect(
|
||||
"delete-event", self.text_color_dialog_close, color_dialog)
|
||||
|
||||
color_dialog.run()
|
||||
|
||||
@@ -272,18 +287,21 @@ class HighlightProperty(object):
|
||||
def text_color_dialog_close(self, widget, extra, color_dialog):
|
||||
color_dialog.destroy()
|
||||
|
||||
|
||||
#########################################
|
||||
# Highlight color dialog
|
||||
def highlight_color_dialog(self, widget):
|
||||
color_dialog = gtk.ColorSelectionDialog("%s %s" % (self.property_name,
|
||||
_("highlight color")))
|
||||
color_dialog = gtk.ColorSelectionDialog(
|
||||
"%s %s" % (self.property_name, _("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.cancel_button.connect("clicked", self.highlight_color_dialog_cancel,
|
||||
color_dialog.ok_button.connect(
|
||||
"clicked", self.highlight_color_dialog_ok, color_dialog)
|
||||
color_dialog.cancel_button.connect(
|
||||
"clicked", self.highlight_color_dialog_cancel,
|
||||
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()
|
||||
|
||||
@@ -304,8 +322,9 @@ class HighlightProperty(object):
|
||||
|
||||
attributes = pango.AttrList()
|
||||
|
||||
attributes.insert(pango.AttrForeground(self.text_color.red, self.text_color.green,
|
||||
self.text_color.blue, start, end))
|
||||
attributes.insert(
|
||||
pango.AttrForeground(self.text_color.red,
|
||||
self.text_color.green, self.text_color.blue, start, end))
|
||||
attributes.insert(pango.AttrBackground(self.highlight_color.red,
|
||||
self.highlight_color.green,
|
||||
self.highlight_color.blue,
|
||||
@@ -315,7 +334,8 @@ class HighlightProperty(object):
|
||||
if self.bold_tg_button.get_active():
|
||||
attributes.insert(pango.AttrWeight(pango.WEIGHT_HEAVY, start, end))
|
||||
else:
|
||||
attributes.insert(pango.AttrWeight(pango.WEIGHT_NORMAL, start, end))
|
||||
attributes.insert(
|
||||
pango.AttrWeight(pango.WEIGHT_NORMAL, start, end))
|
||||
|
||||
# Italic verification
|
||||
if self.italic_tg_button.get_active():
|
||||
@@ -325,13 +345,14 @@ class HighlightProperty(object):
|
||||
|
||||
# Underline verification
|
||||
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:
|
||||
attributes.insert(pango.AttrUnderline(pango.UNDERLINE_NONE, start, end))
|
||||
attributes.insert(
|
||||
pango.AttrUnderline(pango.UNDERLINE_NONE, start, end))
|
||||
|
||||
self.example_label.set_attributes(attributes)
|
||||
|
||||
|
||||
def show_bold(self, widget):
|
||||
self.example_label.set_markup("<>")
|
||||
|
||||
|
||||
@@ -134,13 +134,14 @@ from zenmapCore.UmitConf import NmapOutputHighlight
|
||||
|
||||
from zenmapGUI.NmapOutputProperties import NmapOutputProperties
|
||||
|
||||
|
||||
class NmapOutputViewer (gtk.VBox):
|
||||
HIGHLIGHT_PROPERTIES = ["details", "date", "hostname", "ip", "port_list",
|
||||
"open_port", "closed_port", "filtered_port"]
|
||||
|
||||
def __init__ (self, refresh=1, stop=1):
|
||||
def __init__(self, refresh=1, stop=1):
|
||||
self.nmap_highlight = NmapOutputHighlight()
|
||||
gtk.VBox.__init__ (self)
|
||||
gtk.VBox.__init__(self)
|
||||
|
||||
# Creating widgets
|
||||
self.__create_widgets()
|
||||
@@ -158,7 +159,7 @@ class NmapOutputViewer (gtk.VBox):
|
||||
self.refreshing = True
|
||||
|
||||
# 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
|
||||
# display.
|
||||
@@ -166,16 +167,16 @@ class NmapOutputViewer (gtk.VBox):
|
||||
# The position of the last read from the output stream.
|
||||
self.output_file_pointer = None
|
||||
|
||||
def __create_widgets (self):
|
||||
def __create_widgets(self):
|
||||
# Creating widgets
|
||||
self.scrolled = gtk.ScrolledWindow ()
|
||||
self.text_view = gtk.TextView ()
|
||||
self.scrolled = gtk.ScrolledWindow()
|
||||
self.text_view = gtk.TextView()
|
||||
|
||||
def __set_scrolled_window (self):
|
||||
def __set_scrolled_window(self):
|
||||
# Seting scrolled window
|
||||
self.scrolled.set_border_width (5)
|
||||
self.scrolled.set_border_width(5)
|
||||
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):
|
||||
self.text_view.set_wrap_mode(gtk.WRAP_WORD)
|
||||
@@ -205,8 +206,12 @@ class NmapOutputViewer (gtk.VBox):
|
||||
text_color = settings[3]
|
||||
highlight_color = settings[4]
|
||||
|
||||
tag.set_property("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),]))
|
||||
tag.set_property(
|
||||
"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):
|
||||
"""Go to host line on nmap output result"""
|
||||
@@ -218,7 +223,8 @@ class NmapOutputViewer (gtk.VBox):
|
||||
|
||||
for i in xrange(len(output)):
|
||||
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
|
||||
|
||||
def show_output_properties(self, widget):
|
||||
@@ -259,7 +265,7 @@ class NmapOutputViewer (gtk.VBox):
|
||||
self.nmap_highlight.save_changes()
|
||||
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()
|
||||
|
||||
if start_iter is None:
|
||||
@@ -302,7 +308,7 @@ class NmapOutputViewer (gtk.VBox):
|
||||
self.output_file_pointer = None
|
||||
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
|
||||
with this view, as set by set_command_execution. It has no effect if no
|
||||
command has been set."""
|
||||
@@ -316,7 +322,8 @@ class NmapOutputViewer (gtk.VBox):
|
||||
pos = self.command_execution.stdout_file.tell()
|
||||
new_output = self.command_execution.stdout_file.read()
|
||||
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()
|
||||
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)
|
||||
|
||||
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)
|
||||
# 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 we were already scrolled to the bottom, scroll back to the
|
||||
# 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
|
||||
# the text a bit taller.
|
||||
# text causes a scroll bar to appear and reflow the text,
|
||||
# making the text a bit taller.
|
||||
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))
|
||||
|
||||
@@ -138,6 +138,7 @@ import zenmapCore.I18N
|
||||
from zenmapCore.UmitLogging import log
|
||||
from zenmapGUI.ScriptInterface import *
|
||||
|
||||
|
||||
def get_option_check_auxiliary_widget(option, ops, check):
|
||||
if option in ("-sI", "-b", "--script", "--script-args", "--exclude", "-p",
|
||||
"-D", "-S", "--source-port", "-e", "--ttl", "-iR", "--max-retries",
|
||||
@@ -159,6 +160,7 @@ def get_option_check_auxiliary_widget(option, ops, check):
|
||||
else:
|
||||
assert False, "Unknown option %s" % option
|
||||
|
||||
|
||||
class OptionEntry(gtk.Entry):
|
||||
def __init__(self, option, ops, check):
|
||||
gtk.Entry.__init__(self)
|
||||
@@ -187,6 +189,7 @@ class OptionEntry(gtk.Entry):
|
||||
self.check.set_active(True)
|
||||
self.ops[self.option] = self.get_text().decode("UTF-8")
|
||||
|
||||
|
||||
class OptionExtras(gtk.Entry):
|
||||
def __init__(self, option, ops, check):
|
||||
gtk.Entry.__init__(self)
|
||||
@@ -214,6 +217,7 @@ class OptionExtras(gtk.Entry):
|
||||
self.check.set_active(True)
|
||||
self.ops.extras = [self.get_text().decode("UTF-8")]
|
||||
|
||||
|
||||
class OptionLevel(gtk.SpinButton):
|
||||
def __init__(self, option, ops, check):
|
||||
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.ops[self.option] = int(self.get_adjustment().get_value())
|
||||
|
||||
|
||||
class OptionFile(gtk.HBox):
|
||||
__gsignals__ = {
|
||||
"changed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ())
|
||||
@@ -257,7 +262,7 @@ class OptionFile(gtk.HBox):
|
||||
|
||||
self.entry = gtk.Entry()
|
||||
self.pack_start(self.entry, True, True)
|
||||
button = HIGButton(stock = gtk.STOCK_OPEN)
|
||||
button = HIGButton(stock=gtk.STOCK_OPEN)
|
||||
self.pack_start(button, False)
|
||||
|
||||
button.connect("clicked", self.clicked_cb)
|
||||
@@ -291,6 +296,7 @@ class OptionFile(gtk.HBox):
|
||||
self.entry.set_text(dialog.get_filename())
|
||||
dialog.destroy()
|
||||
|
||||
|
||||
class TargetEntry(gtk.Entry):
|
||||
def __init__(self, ops):
|
||||
gtk.Entry.__init__(self)
|
||||
@@ -307,11 +313,12 @@ class TargetEntry(gtk.Entry):
|
||||
def get_targets(self):
|
||||
return split_quoted(self.get_text().decode("UTF-8"))
|
||||
|
||||
|
||||
class OptionTab(object):
|
||||
def __init__(self, root_tab, ops, update_command, help_buf):
|
||||
actions = {'target':self.__parse_target,
|
||||
'option_list':self.__parse_option_list,
|
||||
'option_check':self.__parse_option_check}
|
||||
actions = {'target': self.__parse_target,
|
||||
'option_list': self.__parse_option_list,
|
||||
'option_check': self.__parse_option_check}
|
||||
|
||||
self.ops = ops
|
||||
self.update_command = update_command
|
||||
@@ -321,8 +328,10 @@ class OptionTab(object):
|
||||
self.notscripttab = False # assume every tab is scripting tab
|
||||
self.widgets_list = []
|
||||
for option_element in root_tab.childNodes:
|
||||
try:option_element.tagName
|
||||
except:pass
|
||||
try:
|
||||
option_element.tagName
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
if option_element.tagName in actions.keys():
|
||||
parse_func = actions[option_element.tagName]
|
||||
@@ -339,7 +348,8 @@ class OptionTab(object):
|
||||
def __parse_option_list(self, option_list_element):
|
||||
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)
|
||||
|
||||
for child in children:
|
||||
@@ -348,8 +358,10 @@ class OptionTab(object):
|
||||
label = _(child.getAttribute(u'label'))
|
||||
option_list_widget.append(option, argument, label)
|
||||
self.profilehelp.add_label(option, label)
|
||||
self.profilehelp.add_shortdesc(option, _(child.getAttribute(u'short_desc')))
|
||||
self.profilehelp.add_example(option, child.getAttribute(u'example'))
|
||||
self.profilehelp.add_shortdesc(
|
||||
option, _(child.getAttribute(u'short_desc')))
|
||||
self.profilehelp.add_example(
|
||||
option, child.getAttribute(u'example'))
|
||||
|
||||
option_list_widget.update()
|
||||
|
||||
@@ -369,10 +381,12 @@ class OptionTab(object):
|
||||
self.profilehelp.add_example(option, example)
|
||||
|
||||
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:
|
||||
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:
|
||||
check.set_active(not not self.ops[option])
|
||||
|
||||
@@ -381,14 +395,14 @@ class OptionTab(object):
|
||||
|
||||
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]
|
||||
for y, widget in enumerate(self.widgets_list):
|
||||
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:
|
||||
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[0], 0, 1, y, y + 1, yoptions=yopt)
|
||||
table.attach(widget[1], 1, 2, y, y + 1, yoptions=yopt)
|
||||
|
||||
def update_auxiliary_widget(self, auxiliary_widget):
|
||||
self.update_command()
|
||||
@@ -446,6 +460,7 @@ class OptionTab(object):
|
||||
def enter_notify_event_cb(self, event, widget, option):
|
||||
self.show_help_for_option(option)
|
||||
|
||||
|
||||
class OptionBuilder(object):
|
||||
def __init__(self, xml_file, ops, update_func, help_buf):
|
||||
"""
|
||||
@@ -463,7 +478,6 @@ class OptionBuilder(object):
|
||||
|
||||
self.root_tag = "interface"
|
||||
|
||||
|
||||
self.xml = self.xml.getElementsByTagName(self.root_tag)[0]
|
||||
|
||||
self.groups = self.__parse_groups()
|
||||
@@ -490,11 +504,13 @@ class OptionBuilder(object):
|
||||
dic = {}
|
||||
for tab_name in self.groups:
|
||||
if tab_name != "Scripting":
|
||||
dic[tab_name] = OptionTab(self.xml.getElementsByTagName(tab_name)[0],
|
||||
self.ops, self.update_func, self.help_buf)
|
||||
dic[tab_name] = OptionTab(
|
||||
self.xml.getElementsByTagName(tab_name)[0], self.ops,
|
||||
self.update_func, self.help_buf)
|
||||
dic[tab_name].notscripttab = True
|
||||
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
|
||||
|
||||
|
||||
@@ -518,7 +534,8 @@ class OptionList(gtk.ComboBox):
|
||||
opt, arg = row[0], row[1]
|
||||
if opt == "":
|
||||
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
|
||||
self.set_active(selected)
|
||||
|
||||
@@ -535,6 +552,7 @@ class OptionList(gtk.ComboBox):
|
||||
self.list.append([option, argument, opt])
|
||||
self.options.append(option)
|
||||
|
||||
|
||||
class OptionCheck(gtk.CheckButton):
|
||||
def __init__(self, option, label):
|
||||
opt = label
|
||||
|
||||
@@ -123,8 +123,8 @@
|
||||
# This prints the normal (text) output of a single scan. Ideas for further
|
||||
# development:
|
||||
#
|
||||
# Print the topology graphic. The graphic is already made with Cairo so the same
|
||||
# code can be used to draw on the print context.
|
||||
# Print the topology graphic. The graphic is already made with Cairo so the
|
||||
# same code can be used to draw on the print context.
|
||||
#
|
||||
# Print in color with highlighting, like NmapOutputViewer.
|
||||
#
|
||||
@@ -139,6 +139,7 @@ import pango
|
||||
|
||||
MONOSPACE_FONT_DESC = pango.FontDescription("Monospace 12")
|
||||
|
||||
|
||||
class PrintState (object):
|
||||
"""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)
|
||||
|
||||
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()
|
||||
# Do no wrapping.
|
||||
layout.set_width(-1)
|
||||
@@ -180,6 +183,7 @@ class PrintState (object):
|
||||
cr = context.get_cairo_context()
|
||||
cr.show_layout(layout)
|
||||
|
||||
|
||||
def run_print_operation(inventory, entry):
|
||||
op = gtk.PrintOperation()
|
||||
state = PrintState(inventory, entry)
|
||||
|
||||
@@ -125,6 +125,7 @@ import gtk
|
||||
from zenmapCore.UmitConf import CommandProfile
|
||||
import zenmapCore.I18N
|
||||
|
||||
|
||||
class ProfileCombo(gtk.ComboBoxEntry, object):
|
||||
def __init__(self):
|
||||
gtk.ComboBoxEntry.__init__(self, gtk.ListStore(str), 0)
|
||||
|
||||
@@ -123,7 +123,8 @@
|
||||
import gtk
|
||||
|
||||
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.higscrollers import HIGScrolledWindow
|
||||
from zenmapGUI.higwidgets.higtextviewers import HIGTextView
|
||||
@@ -137,8 +138,10 @@ from zenmapCore.UmitLogging import log
|
||||
import zenmapCore.I18N
|
||||
from zenmapCore.NmapOptions import NmapOptions
|
||||
|
||||
|
||||
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)
|
||||
self.connect("delete_event", self.exit)
|
||||
self.set_title(_('Profile Editor'))
|
||||
@@ -148,8 +151,8 @@ class ProfileEditor(HIGWindow):
|
||||
self.profile_name = profile_name
|
||||
self.overwrite = overwrite
|
||||
|
||||
# Used to block recursive updating of the command entry when the command
|
||||
# entry causes the OptionBuilder widgets to change.
|
||||
# Used to block recursive updating of the command entry when the
|
||||
# command entry causes the OptionBuilder widgets to change.
|
||||
self.inhibit_command_update = False
|
||||
|
||||
self.__create_widgets()
|
||||
@@ -164,20 +167,27 @@ class ProfileEditor(HIGWindow):
|
||||
|
||||
# Interface settings
|
||||
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']
|
||||
self.ops.parse_string(command_string)
|
||||
if 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 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))
|
||||
|
||||
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()
|
||||
|
||||
@@ -195,16 +205,18 @@ class ProfileEditor(HIGWindow):
|
||||
# cause a change in the command entry.
|
||||
self.command_entry.handler_block(self.command_entry_changed_cb_id)
|
||||
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):
|
||||
self.help_field.get_buffer().set_text("Profile name\n\nThis is how the"
|
||||
+" profile will be identified in the drop-down combo box in the"
|
||||
+" scan tab.")
|
||||
self.help_field.get_buffer().set_text(
|
||||
"Profile name\n\nThis is how the profile will be identified "
|
||||
"in the drop-down combo box in the scan tab.")
|
||||
|
||||
def update_help_desc(self, widget, extra):
|
||||
self.help_field.get_buffer().set_text("Description\n\nThe description is a"
|
||||
+ " full description of what the scan does, which may be long.")
|
||||
self.help_field.get_buffer().set_text(
|
||||
"Description\n\nThe description is a full description of what "
|
||||
"the scan does, which may be long.")
|
||||
|
||||
def __create_widgets(self):
|
||||
|
||||
@@ -218,8 +230,8 @@ class ProfileEditor(HIGWindow):
|
||||
|
||||
#self.main_vbox = HIGVBox()
|
||||
self.command_entry = gtk.Entry()
|
||||
self.command_entry_changed_cb_id = \
|
||||
self.command_entry.connect("changed", self.command_entry_changed_cb)
|
||||
self.command_entry_changed_cb_id = self.command_entry.connect(
|
||||
"changed", self.command_entry_changed_cb)
|
||||
|
||||
self.scan_button = HIGButton(_("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_name_label = HIGEntryLabel(_('Profile name'))
|
||||
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_scroll = HIGScrolledWindow()
|
||||
self.profile_description_scroll.set_border_width(0)
|
||||
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
|
||||
self.buttons_hbox = HIGHBox()
|
||||
@@ -259,8 +273,9 @@ class ProfileEditor(HIGWindow):
|
||||
self.help_field.set_cursor_visible(False)
|
||||
self.help_field.set_left_margin(5)
|
||||
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):
|
||||
|
||||
###
|
||||
@@ -283,9 +298,9 @@ class ProfileEditor(HIGWindow):
|
||||
self.main_whole_box._pack_noexpand_nofill(self.lower_box)
|
||||
###
|
||||
|
||||
|
||||
# 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)
|
||||
table = HIGTable()
|
||||
self.profile_info_vbox._pack_noexpand_nofill(self.profile_info_label)
|
||||
@@ -300,10 +315,11 @@ class ProfileEditor(HIGWindow):
|
||||
vbox_ann = HIGVBox()
|
||||
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(self.profile_name_entry,1,2,0,1,yoptions=0)
|
||||
table.attach(vbox_desc,0,1,1,2,xoptions=0)
|
||||
table.attach(self.profile_description_scroll,1,2,1,2)
|
||||
table.attach(
|
||||
self.profile_name_label, 0, 1, 0, 1, xoptions=0, yoptions=0)
|
||||
table.attach(self.profile_name_entry, 1, 2, 0, 1, yoptions=0)
|
||||
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
|
||||
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(">>>Creating profile editor section: %s" % section_name)
|
||||
vbox = HIGVBox()
|
||||
if tab.notscripttab: # if notscripttab is set
|
||||
if tab.notscripttab: # if notscripttab is set
|
||||
table = HIGTable()
|
||||
table.set_row_spacings(2)
|
||||
section = HIGSectionLabel(section_name)
|
||||
@@ -337,7 +353,7 @@ class ProfileEditor(HIGWindow):
|
||||
tab.fill_table(table, True)
|
||||
else:
|
||||
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))
|
||||
|
||||
def save_profile(self, widget):
|
||||
@@ -345,9 +361,10 @@ class ProfileEditor(HIGWindow):
|
||||
self.profile.remove_profile(self.profile_name)
|
||||
profile_name = self.profile_name_entry.get_text()
|
||||
if profile_name == '':
|
||||
alert = HIGAlertDialog(message_format=_('Unnamed profile'),\
|
||||
secondary_text=_('You must provide a name \
|
||||
for this profile.'))
|
||||
alert = HIGAlertDialog(
|
||||
message_format=_('Unnamed profile'),
|
||||
secondary_text=_(
|
||||
'You must provide a name for this profile.'))
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
|
||||
@@ -366,11 +383,12 @@ for this profile.'))
|
||||
command=command,\
|
||||
description=description)
|
||||
except ValueError:
|
||||
alert = HIGAlertDialog(message_format=_('Disallowed profile name'),\
|
||||
secondary_text=_('Sorry, the name "%s" \
|
||||
is not allowed due to technical limitations. (The underlying ConfigParser \
|
||||
used to store profiles does not allow it.) Choose a different \
|
||||
name.' % profile_name))
|
||||
alert = HIGAlertDialog(
|
||||
message_format=_('Disallowed profile name'),
|
||||
secondary_text=_('Sorry, the name "%s" is not allowed due '
|
||||
'to technical limitations. (The underlying '
|
||||
'ConfigParser used to store profiles does not allow '
|
||||
'it.) Choose a different name.' % profile_name))
|
||||
alert.run()
|
||||
alert.destroy()
|
||||
return
|
||||
@@ -392,9 +410,10 @@ name.' % profile_name))
|
||||
if self.deletable:
|
||||
dialog = HIGDialog(buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
|
||||
alert = HIGEntryLabel('<b>'+_("Deleting Profile")+'</b>')
|
||||
text = HIGEntryLabel(_('Your profile is going to be deleted! Click\
|
||||
Ok to continue, or Cancel to go back to Profile Editor.'))
|
||||
alert = HIGEntryLabel('<b>' + _("Deleting Profile") + '</b>')
|
||||
text = HIGEntryLabel(_(
|
||||
'Your profile is going to be deleted! ClickOk to continue, '
|
||||
'or Cancel to go back to Profile Editor.'))
|
||||
hbox = HIGHBox()
|
||||
hbox.set_border_width(5)
|
||||
hbox.set_spacing(12)
|
||||
@@ -404,7 +423,8 @@ name.' % profile_name))
|
||||
vbox.set_spacing(12)
|
||||
|
||||
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(text)
|
||||
@@ -433,7 +453,7 @@ name.' % profile_name))
|
||||
self.scan_interface.toolbar.profile_entry.update()
|
||||
list = self.scan_interface.toolbar.profile_entry.get_model()
|
||||
length = len(list)
|
||||
if length >0 :
|
||||
if length > 0:
|
||||
self.scan_interface.toolbar.profile_entry.set_active(0)
|
||||
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
|
||||
from zenmapCore.UmitLogging import log
|
||||
|
||||
|
||||
class ProfileHelp:
|
||||
def __init__(self, currentstate=None):
|
||||
self.currentstate = "Default"
|
||||
@@ -139,7 +140,7 @@ class ProfileHelp:
|
||||
if self.currentstate in self.labels.keys():
|
||||
return self.labels[self.currentstate]
|
||||
else:
|
||||
return "" #blank
|
||||
return "" # blank
|
||||
|
||||
def add_shortdesc(self, option_name, text):
|
||||
self.descs[option_name] = text
|
||||
@@ -148,7 +149,7 @@ class ProfileHelp:
|
||||
if self.currentstate in self.descs.keys():
|
||||
return self.descs[self.currentstate]
|
||||
else:
|
||||
return "" #blank
|
||||
return "" # blank
|
||||
|
||||
def add_example(self, option_name, text):
|
||||
self.examples[option_name] = text
|
||||
@@ -157,8 +158,8 @@ class ProfileHelp:
|
||||
if self.currentstate in self.examples.keys():
|
||||
return self.examples[self.currentstate]
|
||||
else:
|
||||
return "" #blank
|
||||
return "" # blank
|
||||
|
||||
def handler(self,whichLabel):
|
||||
def handler(self, whichLabel):
|
||||
log.debug("whichLabel: %s" % whichLabel)
|
||||
self.currentstate = whichLabel
|
||||
|
||||
@@ -123,7 +123,8 @@
|
||||
import gtk
|
||||
|
||||
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.higtables import HIGTable
|
||||
from zenmapGUI.Icons import get_os_logo, get_vulnerability_logo
|
||||
@@ -132,6 +133,7 @@ import zenmapCore.I18N
|
||||
|
||||
na = _('Not available')
|
||||
|
||||
|
||||
class ScanHostDetailsPage(HIGExpander):
|
||||
def __init__(self, host):
|
||||
HIGExpander.__init__(self, host.get_hostname())
|
||||
@@ -139,6 +141,7 @@ class ScanHostDetailsPage(HIGExpander):
|
||||
self.host_details = HostDetails(host)
|
||||
self.hbox._pack_expand_fill(self.host_details)
|
||||
|
||||
|
||||
class HostDetails(HIGVBox):
|
||||
def __init__(self, host):
|
||||
HIGVBox.__init__(self)
|
||||
@@ -147,7 +150,8 @@ class HostDetails(HIGVBox):
|
||||
|
||||
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(),
|
||||
'open': str(host.get_open_ports()),
|
||||
@@ -179,16 +183,19 @@ class HostDetails(HIGVBox):
|
||||
self.set_comment(host.comment)
|
||||
|
||||
def __create_widgets(self):
|
||||
self.host_status_expander = gtk.Expander('<b>'+_('Host Status')+'</b>')
|
||||
self.address_expander = gtk.Expander('<b>'+_('Addresses')+'</b>')
|
||||
self.hostnames_expander = gtk.Expander('<b>'+_('Hostnames')+'</b>')
|
||||
self.os_expander = gtk.Expander('<b>'+_('Operating System')+'</b>')
|
||||
self.portsused_expander = gtk.Expander('<b>'+_('Ports used')+'</b>')
|
||||
self.osclass_expander = gtk.Expander('<b>'+_('OS Classes')+'</b>')
|
||||
self.tcp_expander = gtk.Expander('<b>'+_('TCP Sequence')+'</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.host_status_expander = gtk.Expander(
|
||||
'<b>' + _('Host Status') + '</b>')
|
||||
self.address_expander = gtk.Expander('<b>' + _('Addresses') + '</b>')
|
||||
self.hostnames_expander = gtk.Expander('<b>' + _('Hostnames') + '</b>')
|
||||
self.os_expander = gtk.Expander('<b>' + _('Operating System') + '</b>')
|
||||
self.portsused_expander = gtk.Expander(
|
||||
'<b>' + _('Ports used') + '</b>')
|
||||
self.osclass_expander = gtk.Expander('<b>' + _('OS Classes') + '</b>')
|
||||
self.tcp_expander = gtk.Expander('<b>' + _('TCP Sequence') + '</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.vulnerability_image = gtk.Image()
|
||||
|
||||
@@ -214,7 +221,6 @@ class HostDetails(HIGVBox):
|
||||
self.lastboot_label = HIGEntryLabel(_('Last boot:'))
|
||||
self.info_lastboot_label = HIGEntryLabel(na)
|
||||
|
||||
|
||||
# Addresses expander
|
||||
self.ipv4_label = HIGEntryLabel(_('IPv4:'))
|
||||
self.info_ipv4_label = HIGEntryLabel(na)
|
||||
@@ -243,63 +249,78 @@ class HostDetails(HIGVBox):
|
||||
table, hbox = self.create_table_hbox()
|
||||
|
||||
try:
|
||||
if status['state'] == '': raise Exception
|
||||
if status['state'] == '':
|
||||
raise Exception
|
||||
self.info_host_state_label.set_text(status['state'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if status['open'] == '': raise Exception
|
||||
if status['open'] == '':
|
||||
raise Exception
|
||||
self.info_open_ports.set_text(status['open'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if status['filtered'] == '': raise Exception
|
||||
if status['filtered'] == '':
|
||||
raise Exception
|
||||
self.info_filtered_label.set_text(status['filtered'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if status['closed'] == '': raise Exception
|
||||
if status['closed'] == '':
|
||||
raise Exception
|
||||
self.info_closed_ports.set_text(status['closed'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if status['scanned'] == '': raise Exception
|
||||
if status['scanned'] == '':
|
||||
raise Exception
|
||||
self.info_scanned_label.set_text(status['scanned'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if status['uptime'] == '': raise Exception
|
||||
if status['uptime'] == '':
|
||||
raise Exception
|
||||
self.info_uptime_label.set_text(status['uptime'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if status['lastboot'] == '': raise Exception
|
||||
if status['lastboot'] == '':
|
||||
raise Exception
|
||||
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.info_host_state_label,1,2,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.open_label,0,1,1,2)
|
||||
table.attach(self.info_open_ports,1,2,1,2)
|
||||
table.attach(self.open_label, 0, 1, 1, 2)
|
||||
table.attach(self.info_open_ports, 1, 2, 1, 2)
|
||||
|
||||
table.attach(self.filtered_label,0,1,2,3)
|
||||
table.attach(self.info_filtered_label,1,2,2,3)
|
||||
table.attach(self.filtered_label, 0, 1, 2, 3)
|
||||
table.attach(self.info_filtered_label, 1, 2, 2, 3)
|
||||
|
||||
table.attach(self.closed_label,0,1,3,4)
|
||||
table.attach(self.info_closed_ports,1,2,3,4)
|
||||
table.attach(self.closed_label, 0, 1, 3, 4)
|
||||
table.attach(self.info_closed_ports, 1, 2, 3, 4)
|
||||
|
||||
table.attach(self.scanned_label,0,1,4,5)
|
||||
table.attach(self.info_scanned_label,1,2,4,5)
|
||||
table.attach(self.scanned_label, 0, 1, 4, 5)
|
||||
table.attach(self.info_scanned_label, 1, 2, 4, 5)
|
||||
|
||||
table.attach(self.uptime_label,0,1,5,6)
|
||||
table.attach(self.info_uptime_label,1,2,5,6)
|
||||
table.attach(self.uptime_label, 0, 1, 5, 6)
|
||||
table.attach(self.info_uptime_label, 1, 2, 5, 6)
|
||||
|
||||
table.attach(self.lastboot_label,0,1,6,7)
|
||||
table.attach(self.info_lastboot_label,1,2,6,7)
|
||||
table.attach(self.lastboot_label, 0, 1, 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.vulnerability_image,2,4,4,7,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.set_col_spacing(1, 50)
|
||||
|
||||
@@ -307,10 +328,10 @@ class HostDetails(HIGVBox):
|
||||
self._pack_noexpand_nofill(self.host_status_expander)
|
||||
|
||||
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):
|
||||
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):
|
||||
self.address_expander.set_use_markup(True)
|
||||
@@ -319,28 +340,34 @@ class HostDetails(HIGVBox):
|
||||
|
||||
#print '>>> Address:', address
|
||||
try:
|
||||
if address['ipv4'] == 1: raise Exception
|
||||
if address['ipv4'] == 1:
|
||||
raise Exception
|
||||
self.info_ipv4_label.set_text(address['ipv4'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if address['ipv6'] == 1: raise Exception
|
||||
if address['ipv6'] == 1:
|
||||
raise Exception
|
||||
self.info_ipv6_label.set_text(address['ipv6'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if address['mac'] == 1: raise Exception
|
||||
if address['mac'] == 1:
|
||||
raise Exception
|
||||
self.info_mac_label.set_text(address['mac'])
|
||||
except:pass
|
||||
except:
|
||||
pass
|
||||
|
||||
table.attach(self.ipv4_label,0,1,0,1)
|
||||
table.attach(self.info_ipv4_label,1,2,0,1)
|
||||
table.attach(self.ipv4_label, 0, 1, 0, 1)
|
||||
table.attach(self.info_ipv4_label, 1, 2, 0, 1)
|
||||
|
||||
table.attach(self.ipv6_label,0,1,1,2)
|
||||
table.attach(self.info_ipv6_label,1,2,1,2)
|
||||
table.attach(self.ipv6_label, 0, 1, 1, 2)
|
||||
table.attach(self.info_ipv6_label, 1, 2, 1, 2)
|
||||
|
||||
table.attach(self.mac_label,0,1,2,3)
|
||||
table.attach(self.info_mac_label,1,2,2,3)
|
||||
table.attach(self.mac_label, 0, 1, 2, 3)
|
||||
table.attach(self.info_mac_label, 1, 2, 2, 3)
|
||||
|
||||
self.address_expander.add(hbox)
|
||||
self._pack_noexpand_nofill(self.address_expander)
|
||||
@@ -356,17 +383,21 @@ class HostDetails(HIGVBox):
|
||||
|
||||
for h in hostname:
|
||||
name = na
|
||||
try:name = h['hostname']
|
||||
except:pass
|
||||
try:
|
||||
name = h['hostname']
|
||||
except:
|
||||
pass
|
||||
|
||||
type = na
|
||||
try:type = h['hostname_type']
|
||||
except:pass
|
||||
try:
|
||||
type = h['hostname_type']
|
||||
except:
|
||||
pass
|
||||
|
||||
table.attach(HIGEntryLabel(_('Name - Type:')),0,1,y1,y2)
|
||||
table.attach(HIGEntryLabel(name+' - '+\
|
||||
type),1,2,y1,y2)
|
||||
y1+=1;y2+=1
|
||||
table.attach(HIGEntryLabel(_('Name - Type:')), 0, 1, y1, y2)
|
||||
table.attach(HIGEntryLabel(name + ' - ' + type), 1, 2, y1, y2)
|
||||
y1 += 1
|
||||
y2 += 1
|
||||
|
||||
self.hostnames_expander.add(hbox)
|
||||
self._pack_noexpand_nofill(self.hostnames_expander)
|
||||
@@ -379,29 +410,34 @@ class HostDetails(HIGVBox):
|
||||
progress = gtk.ProgressBar()
|
||||
|
||||
try:
|
||||
progress.set_fraction(float(os['accuracy'])/100.0)
|
||||
progress.set_text(os['accuracy']+'%')
|
||||
except:progress.set_text(_('Not Available'))
|
||||
progress.set_fraction(float(os['accuracy']) / 100.0)
|
||||
progress.set_text(os['accuracy'] + '%')
|
||||
except:
|
||||
progress.set_text(_('Not Available'))
|
||||
|
||||
table.attach(HIGEntryLabel(_('Name:')),0,1,0,1)
|
||||
table.attach(HIGEntryLabel(os['name']),1,2,0,1)
|
||||
table.attach(HIGEntryLabel(_('Name:')), 0, 1, 0, 1)
|
||||
table.attach(HIGEntryLabel(os['name']), 1, 2, 0, 1)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Accuracy:')),0,1,1,2)
|
||||
table.attach(progress,1,2,1,2)
|
||||
table.attach(HIGEntryLabel(_('Accuracy:')), 0, 1, 1, 2)
|
||||
table.attach(progress, 1, 2, 1, 2)
|
||||
|
||||
y1=2;y2=3
|
||||
y1 = 2
|
||||
y2 = 3
|
||||
|
||||
try:
|
||||
self.set_ports_used(os['portsused'])
|
||||
table.attach(self.portsused_expander,0,2,y1,y2)
|
||||
y1+=1;y2+=1
|
||||
except:pass
|
||||
table.attach(self.portsused_expander, 0, 2, y1, y2)
|
||||
y1 += 1
|
||||
y2 += 1
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.set_osclass(os['osclasses'])
|
||||
self.osclass_expander.set_use_markup(True)
|
||||
table.attach(self.osclass_expander,0,2,y1,y2)
|
||||
except:pass
|
||||
table.attach(self.osclass_expander, 0, 2, y1, y2)
|
||||
except:
|
||||
pass
|
||||
|
||||
self.os_expander.add(hbox)
|
||||
self._pack_noexpand_nofill(self.os_expander)
|
||||
@@ -410,13 +446,17 @@ class HostDetails(HIGVBox):
|
||||
self.portsused_expander.set_use_markup(True)
|
||||
table, hbox = self.create_table_hbox()
|
||||
|
||||
y1=0;y2=1
|
||||
y1 = 0
|
||||
y2 = 1
|
||||
|
||||
for p in ports:
|
||||
table.attach(HIGEntryLabel(_('Port-Protocol-State:')),0,1,y1,y2)
|
||||
table.attach(HIGEntryLabel(p['portid']+' - '+p['proto']+' - '+\
|
||||
p['state']),1,2,y1,y2)
|
||||
y1+=1;y2+=1
|
||||
table.attach(HIGEntryLabel(
|
||||
_('Port-Protocol-State:')), 0, 1, y1, y2)
|
||||
table.attach(HIGEntryLabel(
|
||||
p['portid'] + ' - ' + p['proto'] + ' - ' + p['state']
|
||||
), 1, 2, y1, y2)
|
||||
y1 += 1
|
||||
y2 += 1
|
||||
|
||||
self.portsused_expander.add(hbox)
|
||||
|
||||
@@ -425,25 +465,27 @@ class HostDetails(HIGVBox):
|
||||
self.osclass_expander.set_use_markup(True)
|
||||
table, hbox = self.create_table_hbox()
|
||||
|
||||
table.attach(HIGEntryLabel(_('Type')),0,1,0,1)
|
||||
table.attach(HIGEntryLabel(_('Vendor')),1,2,0,1)
|
||||
table.attach(HIGEntryLabel(_('OS Family')),2,3,0,1)
|
||||
table.attach(HIGEntryLabel(_('OS Generation')),3,4,0,1)
|
||||
table.attach(HIGEntryLabel(_('Accuracy')),4,5,0,1)
|
||||
table.attach(HIGEntryLabel(_('Type')), 0, 1, 0, 1)
|
||||
table.attach(HIGEntryLabel(_('Vendor')), 1, 2, 0, 1)
|
||||
table.attach(HIGEntryLabel(_('OS Family')), 2, 3, 0, 1)
|
||||
table.attach(HIGEntryLabel(_('OS Generation')), 3, 4, 0, 1)
|
||||
table.attach(HIGEntryLabel(_('Accuracy')), 4, 5, 0, 1)
|
||||
|
||||
y1=1;y2=2
|
||||
y1 = 1
|
||||
y2 = 2
|
||||
|
||||
for o in osclass:
|
||||
table.attach(HIGEntryLabel(o['type']),0,1,y1,y2)
|
||||
table.attach(HIGEntryLabel(o['vendor']),1,2,y1,y2)
|
||||
table.attach(HIGEntryLabel(o['osfamily']),2,3,y1,y2)
|
||||
table.attach(HIGEntryLabel(o['osgen']),3,4,y1,y2)
|
||||
table.attach(HIGEntryLabel(o['type']), 0, 1, y1, y2)
|
||||
table.attach(HIGEntryLabel(o['vendor']), 1, 2, y1, y2)
|
||||
table.attach(HIGEntryLabel(o['osfamily']), 2, 3, y1, y2)
|
||||
table.attach(HIGEntryLabel(o['osgen']), 3, 4, y1, y2)
|
||||
|
||||
progress = gtk.ProgressBar()
|
||||
progress.set_text(o['accuracy']+'%')
|
||||
progress.set_fraction(float(o['accuracy'])/100.0)
|
||||
table.attach(progress,4,5,y1,y2)
|
||||
y1+=1;y2+=1
|
||||
progress.set_text(o['accuracy'] + '%')
|
||||
progress.set_fraction(float(o['accuracy']) / 100.0)
|
||||
table.attach(progress, 4, 5, y1, y2)
|
||||
y1 += 1
|
||||
y2 += 1
|
||||
|
||||
self.osclass_expander.add(hbox)
|
||||
|
||||
@@ -456,14 +498,14 @@ class HostDetails(HIGVBox):
|
||||
for v in tcpseq['values'].split(','):
|
||||
combo.append_text(v)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Difficulty:')),0,1,1,2)
|
||||
table.attach(HIGEntryLabel(tcpseq['difficulty']),1,2,1,2)
|
||||
table.attach(HIGEntryLabel(_('Difficulty:')), 0, 1, 1, 2)
|
||||
table.attach(HIGEntryLabel(tcpseq['difficulty']), 1, 2, 1, 2)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Index:')),0,1,2,3)
|
||||
table.attach(HIGEntryLabel(tcpseq['index']),1,2,2,3)
|
||||
table.attach(HIGEntryLabel(_('Index:')), 0, 1, 2, 3)
|
||||
table.attach(HIGEntryLabel(tcpseq['index']), 1, 2, 2, 3)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Values:')),0,1,3,4)
|
||||
table.attach(combo,1,2,3,4)
|
||||
table.attach(HIGEntryLabel(_('Values:')), 0, 1, 3, 4)
|
||||
table.attach(combo, 1, 2, 3, 4)
|
||||
|
||||
self.tcp_expander.add(hbox)
|
||||
self._pack_noexpand_nofill(self.tcp_expander)
|
||||
@@ -478,11 +520,11 @@ class HostDetails(HIGVBox):
|
||||
for i in ipseq['values'].split(','):
|
||||
combo.append_text(i)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Class:')),0,1,0,1)
|
||||
table.attach(HIGEntryLabel(ipseq['class']),1,2,0,1)
|
||||
table.attach(HIGEntryLabel(_('Class:')), 0, 1, 0, 1)
|
||||
table.attach(HIGEntryLabel(ipseq['class']), 1, 2, 0, 1)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Values:')),0,1,1,2)
|
||||
table.attach(combo,1,2,1,2)
|
||||
table.attach(HIGEntryLabel(_('Values:')), 0, 1, 1, 2)
|
||||
table.attach(combo, 1, 2, 1, 2)
|
||||
|
||||
self.ip_expander.add(hbox)
|
||||
self._pack_noexpand_nofill(self.ip_expander)
|
||||
@@ -497,11 +539,11 @@ class HostDetails(HIGVBox):
|
||||
for i in tcptsseq['values'].split(','):
|
||||
combo.append_text(i)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Class:')),0,1,0,1)
|
||||
table.attach(HIGEntryLabel(tcptsseq['class']),1,2,0,1)
|
||||
table.attach(HIGEntryLabel(_('Class:')), 0, 1, 0, 1)
|
||||
table.attach(HIGEntryLabel(tcptsseq['class']), 1, 2, 0, 1)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Values:')),0,1,1,2)
|
||||
table.attach(combo,1,2,1,2)
|
||||
table.attach(HIGEntryLabel(_('Values:')), 0, 1, 1, 2)
|
||||
table.attach(combo, 1, 2, 1, 2)
|
||||
|
||||
self.tcpts_expander.add(hbox)
|
||||
self._pack_noexpand_nofill(self.tcpts_expander)
|
||||
@@ -515,8 +557,8 @@ class HostDetails(HIGVBox):
|
||||
|
||||
self.comment_scrolled = gtk.ScrolledWindow()
|
||||
self.comment_scrolled.set_border_width(5)
|
||||
self.comment_scrolled.set_policy(gtk.POLICY_AUTOMATIC,\
|
||||
gtk.POLICY_AUTOMATIC)
|
||||
self.comment_scrolled.set_policy(
|
||||
gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
|
||||
self.comment_txt_vw = gtk.TextView()
|
||||
self.comment_txt_vw.set_wrap_mode(gtk.WRAP_WORD)
|
||||
|
||||
@@ -127,16 +127,19 @@ from zenmapGUI.higwidgets.higboxes import HIGVBox
|
||||
from zenmapGUI.Icons import get_os_icon
|
||||
import zenmapCore.I18N
|
||||
|
||||
|
||||
def treemodel_get_addrs_for_sort(model, iter):
|
||||
host = model.get_value(iter, 0)
|
||||
return host.get_addrs_for_sort()
|
||||
|
||||
|
||||
# Used to sort hosts by address.
|
||||
def cmp_treemodel_addr(model, iter_a, iter_b):
|
||||
addrs_a = treemodel_get_addrs_for_sort(model, iter_a)
|
||||
addrs_b = treemodel_get_addrs_for_sort(model, iter_b)
|
||||
return cmp(addrs_a, addrs_b)
|
||||
|
||||
|
||||
class ScanHostsView(HIGVBox, object):
|
||||
HOST_MODE, SERVICE_MODE = range(2)
|
||||
|
||||
@@ -272,8 +275,8 @@ class ScanHostsView(HIGVBox, object):
|
||||
self.host_column.pack_start(self.host_cell, True)
|
||||
|
||||
self.pic_column.set_min_width(35)
|
||||
self.pic_column.set_attributes(self.os_cell, stock_id = 1)
|
||||
self.host_column.set_attributes(self.host_cell, text = 2)
|
||||
self.pic_column.set_attributes(self.os_cell, stock_id=1)
|
||||
self.host_column.set_attributes(self.host_cell, text=2)
|
||||
|
||||
def mass_update(self, hosts):
|
||||
"""Update the internal ListStores to reflect the hosts and services
|
||||
|
||||
@@ -145,7 +145,8 @@ from zenmapGUI.ScanScanListPage import ScanScanListPage
|
||||
from zenmapGUI.ScansListStore import ScansListStore
|
||||
from zenmapGUI.TopologyPage import TopologyPage
|
||||
|
||||
from zenmapCore.NetworkInventory import NetworkInventory, FilteredNetworkInventory
|
||||
from zenmapCore.NetworkInventory import NetworkInventory,\
|
||||
FilteredNetworkInventory
|
||||
from zenmapCore.NmapCommand import NmapCommand
|
||||
from zenmapCore.UmitConf import CommandProfile, ProfileNotFound, is_maemo
|
||||
from zenmapCore.NmapParser import NmapParser
|
||||
@@ -157,6 +158,7 @@ import zenmapCore.I18N
|
||||
# How often the live output view refreshes, in milliseconds.
|
||||
NMAP_OUTPUT_REFRESH_INTERVAL = 1000
|
||||
|
||||
|
||||
class ScanInterface(HIGVBox):
|
||||
"""ScanInterface contains the scan toolbar and the scan results. Each
|
||||
ScanInterface represents a single NetworkInventory as well as a set of
|
||||
@@ -204,20 +206,26 @@ class ScanInterface(HIGVBox):
|
||||
scan_interface=self)
|
||||
self.host_view_selection = self.scan_result.get_host_selection()
|
||||
self.service_view_selection = self.scan_result.get_service_selection()
|
||||
self.host_view_selection.connect('changed', self.host_selection_changed)
|
||||
self.service_view_selection.connect('changed', self.service_selection_changed)
|
||||
self.host_view_selection.connect(
|
||||
'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.host_view.get_selection().connect('changed', self.service_host_selection_changed)
|
||||
self.host_view_selection.connect('changed', self.host_selection_changed)
|
||||
host_page.host_view.get_selection().connect(
|
||||
'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.scans_list.remove_button.connect("clicked", self._remove_scan_cb)
|
||||
self.scan_result.scan_result_notebook.nmap_output.connect(
|
||||
"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)
|
||||
# to HostInfo objects.
|
||||
self.hosts = {}
|
||||
# The services dict maps service names ("http") to lists of dicts of the
|
||||
# form
|
||||
# The services dict maps service names ("http") to lists of dicts of
|
||||
# the form
|
||||
# {'host': <HostInfo object>, 'hostname': u'example.com',
|
||||
# 'port_state': u'open', 'portid': u'22', 'protocol': u'tcp',
|
||||
# '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_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()
|
||||
|
||||
# Create the filter GUI
|
||||
@@ -271,16 +280,18 @@ class ScanInterface(HIGVBox):
|
||||
# Restart the timer to start the filter.
|
||||
if 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):
|
||||
start = time.clock()
|
||||
self.inventory.apply_filter(filter_string)
|
||||
filter_time = time.clock() - start;
|
||||
filter_time = time.clock() - start
|
||||
# Update the gui
|
||||
start = time.clock()
|
||||
self.update_ui()
|
||||
gui_time = time.clock() - start;
|
||||
gui_time = time.clock() - start
|
||||
|
||||
if filter_time + gui_time > 0.0:
|
||||
log.debug("apply_filter %g ms update_ui %g ms (%.0f%% filter)" %
|
||||
@@ -302,8 +313,8 @@ class ScanInterface(HIGVBox):
|
||||
return len(self.jobs)
|
||||
|
||||
def select_default_profile(self):
|
||||
"""Select a "default" profile. Currently this is defined to be the first
|
||||
profile."""
|
||||
"""Select a "default" profile. Currently this is defined to be the
|
||||
first profile."""
|
||||
if len(self.toolbar.profile_entry.get_model()) > 0:
|
||||
self.toolbar.profile_entry.set_active(0)
|
||||
|
||||
@@ -314,21 +325,22 @@ class ScanInterface(HIGVBox):
|
||||
def __create_toolbar(self):
|
||||
self.toolbar = ScanToolbar()
|
||||
|
||||
self.target_entry_changed_handler = \
|
||||
self.toolbar.target_entry.connect('changed', self._target_entry_changed)
|
||||
self.target_entry_changed_handler = self.toolbar.target_entry.connect(
|
||||
'changed', self._target_entry_changed)
|
||||
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.cancel_button.connect('clicked', self._cancel_scan_cb)
|
||||
|
||||
|
||||
def __create_command_toolbar(self):
|
||||
self.command_toolbar = ScanCommandToolbar()
|
||||
self.command_toolbar.command_entry.connect('activate',
|
||||
lambda x: self.toolbar.scan_button.clicked())
|
||||
self.command_toolbar.command_entry.connect(
|
||||
'activate', lambda x: self.toolbar.scan_button.clicked())
|
||||
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):
|
||||
ops = NmapOptions()
|
||||
@@ -378,23 +390,29 @@ class ScanInterface(HIGVBox):
|
||||
def set_command_quiet(self, command_string):
|
||||
"""Set the command used by this scan interface, ignoring any further
|
||||
"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.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):
|
||||
"""Set the target string used by this scan interface, ignoring any
|
||||
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.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):
|
||||
"""Set the profile name used by this scan interface, ignoring any
|
||||
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.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):
|
||||
target = self.toolbar.selected_target
|
||||
@@ -412,14 +430,17 @@ class ScanInterface(HIGVBox):
|
||||
except IOError, e:
|
||||
# We failed to save target_list.txt; treat it as read-only.
|
||||
# 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 == '':
|
||||
warn_dialog = HIGAlertDialog(message_format=_("Empty Nmap Command"),
|
||||
secondary_text=_("There is no command to \
|
||||
execute. Maybe the selected/typed profile doesn't exist. Please, check the profile name \
|
||||
or type the nmap command you would like to execute."),
|
||||
type=gtk.MESSAGE_ERROR)
|
||||
warn_dialog = HIGAlertDialog(
|
||||
message_format=_("Empty Nmap Command"),
|
||||
secondary_text=_("There is no command to execute. "
|
||||
"Maybe the selected/typed profile doesn't exist. "
|
||||
"Please check the profile name or type the nmap "
|
||||
"command you would like to execute."),
|
||||
type=gtk.MESSAGE_ERROR)
|
||||
warn_dialog.run()
|
||||
warn_dialog.destroy()
|
||||
return
|
||||
@@ -467,8 +488,8 @@ or type the nmap command you would like to execute."),
|
||||
self.inventory.remove_scan(entry.parsed)
|
||||
except ValueError:
|
||||
pass
|
||||
# Create TreeRowReferences because those persist while we change the
|
||||
# model.
|
||||
# Create TreeRowReferences because those persist while we change
|
||||
# the model.
|
||||
selected_refs.append(gtk.TreeRowReference(model, path))
|
||||
# Delete the entries from the ScansListStore.
|
||||
for ref in selected_refs:
|
||||
@@ -500,7 +521,7 @@ or type the nmap command you would like to execute."),
|
||||
self.jobs.remove(command)
|
||||
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.
|
||||
Schedule a timer to refresh the output and check the scan for
|
||||
completion."""
|
||||
@@ -515,21 +536,27 @@ or type the nmap command you would like to execute."),
|
||||
# Handle ENOENT specially.
|
||||
if e.errno == errno.ENOENT:
|
||||
# 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")
|
||||
if path_env is None:
|
||||
default_paths = []
|
||||
else:
|
||||
default_paths = path_env.split(os.pathsep)
|
||||
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) == 1:
|
||||
text += "\n\n" + _("plus the extra directory")
|
||||
else:
|
||||
text += "\n\n" + _("plus the extra directories")
|
||||
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)
|
||||
warn_dialog.run()
|
||||
warn_dialog.destroy()
|
||||
@@ -546,7 +573,8 @@ or type the nmap command you would like to execute."),
|
||||
self.scan_result.refresh_nmap_output()
|
||||
|
||||
# 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):
|
||||
"""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:
|
||||
st = None
|
||||
if st is None or st.st_size > 0:
|
||||
warn_dialog = HIGAlertDialog(message_format = _("Parse error"),
|
||||
secondary_text = _(u"""\
|
||||
There was an error while parsing the XML file generated from the scan:
|
||||
|
||||
%s\
|
||||
""") % str(e), type = gtk.MESSAGE_ERROR)
|
||||
warn_dialog = HIGAlertDialog(
|
||||
message_format=_("Parse error"),
|
||||
secondary_text=_(
|
||||
"There was an error while parsing the XML file "
|
||||
"generated from the scan:\n\n%s""") % str(e),
|
||||
type=gtk.MESSAGE_ERROR)
|
||||
warn_dialog.run()
|
||||
warn_dialog.destroy()
|
||||
else:
|
||||
@@ -612,12 +640,12 @@ There was an error while parsing the XML file generated from the scan:
|
||||
try:
|
||||
self.inventory.add_scan(parsed)
|
||||
except Exception, e:
|
||||
warn_dialog = HIGAlertDialog(message_format = _("Cannot merge scan"),
|
||||
secondary_text = _(u"""\
|
||||
There was an error while merging the new scan's XML:
|
||||
|
||||
%s\
|
||||
""") % str(e), type = gtk.MESSAGE_ERROR)
|
||||
warn_dialog = HIGAlertDialog(
|
||||
message_format=_("Cannot merge scan"),
|
||||
secondary_text=_(
|
||||
"There was an error while merging the new scan's "
|
||||
"XML:\n\n%s") % str(e),
|
||||
type=gtk.MESSAGE_ERROR)
|
||||
warn_dialog.run()
|
||||
warn_dialog.destroy()
|
||||
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():
|
||||
self.services[name] = []
|
||||
|
||||
hs = {"host":host, "hostname":hostname}
|
||||
hs = {"host": host, "hostname": hostname}
|
||||
hs.update(service)
|
||||
|
||||
self.services[name].append(hs)
|
||||
|
||||
self.hosts[hostname] = host
|
||||
|
||||
# If the host and service selection is empty or has become empty, select
|
||||
# the first host if there is at least one.
|
||||
if len(self.host_view_selection.get_selected_rows()[1]) == 0 \
|
||||
and len(self.service_view_selection.get_selected_rows()[1]) == 0 \
|
||||
and 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())
|
||||
# If the host and service selection is empty or has become empty,
|
||||
# select the first host if there is at least one.
|
||||
if (len(self.service_view_selection.get_selected_rows()[1]) == 0 and
|
||||
len(self.host_view_selection.get_selected_rows()[1]) == 0 and
|
||||
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.filter_bar.set_information_text(_("%d/%d hosts shown") %
|
||||
(len(self.inventory.get_hosts_up()),
|
||||
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()
|
||||
elif self.scan_result.scan_host_view.mode == ScanHostsView.SERVICE_MODE:
|
||||
elif mode == ScanHostsView.SERVICE_MODE:
|
||||
self.refresh_host_output()
|
||||
|
||||
def refresh_port_output(self):
|
||||
@@ -714,11 +744,12 @@ There was an error while merging the new scan's XML:
|
||||
current host selection."""
|
||||
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 = []
|
||||
for i in selection:
|
||||
hostname = model_host_list[i[0]][2]
|
||||
if self.hosts.has_key(hostname):
|
||||
if hostname in self.hosts:
|
||||
host_objs.append(self.hosts[hostname])
|
||||
|
||||
if len(host_objs) == 1:
|
||||
@@ -732,11 +763,12 @@ There was an error while merging the new scan's XML:
|
||||
current service selection."""
|
||||
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 = []
|
||||
for i in selection:
|
||||
key = model_service_list[i[0]][0]
|
||||
if self.services.has_key(key):
|
||||
if key in self.services:
|
||||
serv_objs.append(self.services[key])
|
||||
|
||||
# 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:
|
||||
servs = []
|
||||
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)
|
||||
|
||||
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
|
||||
entry."""
|
||||
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():
|
||||
if host in scan.get_hosts():
|
||||
scan.unsaved = True
|
||||
@@ -803,8 +838,10 @@ There was an error while merging the new scan's XML:
|
||||
pages = []
|
||||
for host in hosts:
|
||||
page = ScanHostDetailsPage(host)
|
||||
page.host_details.comment_txt_vw.connect("insert-at-cursor", self._save_comment, host)
|
||||
page.host_details.comment_txt_vw.connect("focus-out-event", self._save_comment, host)
|
||||
page.host_details.comment_txt_vw.connect(
|
||||
"insert-at-cursor", self._save_comment, host)
|
||||
page.host_details.comment_txt_vw.connect(
|
||||
"focus-out-event", self._save_comment, host)
|
||||
pages.append(page)
|
||||
return pages
|
||||
|
||||
@@ -833,9 +870,9 @@ There was an error while merging the new scan's XML:
|
||||
host_page.thaw()
|
||||
|
||||
def set_multiple_host_port(self, host_list):
|
||||
"""Change the "Ports / Hosts" tab to show the port output for all of the
|
||||
hosts in host_list. When multiple hosts are selected, the port output
|
||||
for each is contained in an expander."""
|
||||
"""Change the "Ports / Hosts" tab to show the port output for all of
|
||||
the hosts in host_list. When multiple hosts are selected, the port
|
||||
output for each is contained in an expander."""
|
||||
host_page = self.scan_result.scan_result_notebook.open_ports.host
|
||||
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()
|
||||
|
||||
def set_multiple_service_host(self, service_list):
|
||||
"""Change the "Ports / Hosts" tab to show the hosts associated with each
|
||||
of the services in service_list. Each element of service_list must be a
|
||||
dict with the keys "service_name" and "ports". When multiple services
|
||||
are selected, the hosts for each are contained in an expander."""
|
||||
"""Change the "Ports / Hosts" tab to show the hosts associated with
|
||||
each of the services in service_list. Each element of service_list must
|
||||
be a dict with the keys "service_name" and "ports". When multiple
|
||||
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.switch_host_to_tree_store()
|
||||
|
||||
host_page.freeze()
|
||||
host_page.clear_host_tree()
|
||||
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()
|
||||
|
||||
|
||||
class ScanResult(gtk.HPaned):
|
||||
"""This is the pane that has the "Host"/"Service" column (ScanHostsView) 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.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.open_ports_page, gtk.Label(_('Ports / Hosts')))
|
||||
|
||||
@@ -134,6 +134,7 @@ from zenmapCore.Paths import Path
|
||||
from zenmapCore.UmitLogging import log
|
||||
import zenmapCore.I18N
|
||||
|
||||
|
||||
def scan_entry_data_func(widget, cell_renderer, model, iter):
|
||||
"""Set the properties of a cell renderer for a scan entry."""
|
||||
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("text", entry.get_command_string())
|
||||
|
||||
|
||||
class Throbber(gtk.Image):
|
||||
"""This is a little progress indicator that animates while a scan is
|
||||
running."""
|
||||
try:
|
||||
still = gtk.gdk.pixbuf_new_from_file(os.path.join(Path.pixmaps_dir, "throbber.png"))
|
||||
anim = gtk.gdk.PixbufAnimation(os.path.join(Path.pixmaps_dir, "throbber.gif"))
|
||||
still = gtk.gdk.pixbuf_new_from_file(
|
||||
os.path.join(Path.pixmaps_dir, "throbber.png"))
|
||||
anim = gtk.gdk.PixbufAnimation(
|
||||
os.path.join(Path.pixmaps_dir, "throbber.gif"))
|
||||
except Exception, e:
|
||||
log.debug("Error loading throbber images: %s." % str(e))
|
||||
still = None
|
||||
@@ -177,6 +181,7 @@ class Throbber(gtk.Image):
|
||||
self.set_from_pixbuf(self.still)
|
||||
self.animating = False
|
||||
|
||||
|
||||
class ScanNmapOutputPage(HIGVBox):
|
||||
"""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
|
||||
@@ -223,8 +228,8 @@ class ScanNmapOutputPage(HIGVBox):
|
||||
self._update()
|
||||
|
||||
def set_active_iter(self, i):
|
||||
"""Set the active entry to an interator into the ScansListStore referred
|
||||
to by this object."""
|
||||
"""Set the active entry to an interator into the ScansListStore
|
||||
referred to by this object."""
|
||||
self.scans_list.set_active_iter(i)
|
||||
|
||||
def get_active_entry(self):
|
||||
@@ -287,9 +292,11 @@ class ScanNmapOutputPage(HIGVBox):
|
||||
if self._details_windows.get(entry) is None:
|
||||
window = gtk.Window()
|
||||
window.add(ScanRunDetailsPage(entry.parsed))
|
||||
|
||||
def close_details(details, event, entry):
|
||||
details.destroy()
|
||||
del self._details_windows[entry]
|
||||
|
||||
window.connect("delete-event", close_details, entry)
|
||||
window.show_all()
|
||||
self._details_windows[entry] = window
|
||||
|
||||
@@ -128,12 +128,14 @@ from zenmapGUI.higwidgets.higtables import HIGTable
|
||||
from zenmapCore.UmitLogging import log
|
||||
import zenmapCore.I18N
|
||||
|
||||
|
||||
def findout_service_icon(port_info):
|
||||
if port_info["port_state"] in ["open", "open|filtered"]:
|
||||
return gtk.STOCK_YES
|
||||
else:
|
||||
return gtk.STOCK_NO
|
||||
|
||||
|
||||
def get_version_string(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
|
||||
@@ -148,38 +150,45 @@ def get_version_string(d):
|
||||
result.append("(" + d["service_extrainfo"] + ")")
|
||||
return " ".join(result)
|
||||
|
||||
|
||||
def get_addrs(host):
|
||||
if host is None:
|
||||
return None
|
||||
return host.get_addrs_for_sort()
|
||||
|
||||
|
||||
def cmp_addrs(host_a, host_b):
|
||||
return cmp(get_addrs(host_a), get_addrs(host_b))
|
||||
|
||||
|
||||
def cmp_port_list_addr(model, iter_a, iter_b):
|
||||
host_a = model.get_value(iter_a, 0)
|
||||
host_b = model.get_value(iter_b, 0)
|
||||
return cmp_addrs(host_a, host_b)
|
||||
|
||||
|
||||
def cmp_port_tree_addr(model, iter_a, iter_b):
|
||||
host_a = model.get_value(iter_a, 0)
|
||||
host_b = model.get_value(iter_b, 0)
|
||||
return cmp_addrs(host_a, host_b)
|
||||
|
||||
|
||||
def cmp_host_list_addr(model, iter_a, iter_b):
|
||||
host_a = model.get_value(iter_a, 2)
|
||||
host_b = model.get_value(iter_b, 2)
|
||||
return cmp_addrs(host_a, host_b)
|
||||
|
||||
|
||||
def cmp_host_tree_addr(model, iter_a, iter_b):
|
||||
host_a = model.get_value(iter_a, 2)
|
||||
host_b = model.get_value(iter_b, 2)
|
||||
return cmp_addrs(host_a, host_b)
|
||||
|
||||
|
||||
class ScanOpenPortsPage(gtk.ScrolledWindow):
|
||||
def __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()
|
||||
|
||||
@@ -188,6 +197,7 @@ class ScanOpenPortsPage(gtk.ScrolledWindow):
|
||||
def __create_widgets(self):
|
||||
self.host = HostOpenPorts()
|
||||
|
||||
|
||||
class HostOpenPorts(HIGVBox):
|
||||
def __init__(self):
|
||||
HIGVBox.__init__(self)
|
||||
@@ -203,8 +213,10 @@ class HostOpenPorts(HIGVBox):
|
||||
# host hostname icon port protocol state service version
|
||||
# The hostname column is shown only when more than one host is selected
|
||||
# (hence port_tree not port_list is used).
|
||||
self.port_list = gtk.ListStore(object, str, str, int, str, str, str, str)
|
||||
self.port_tree = gtk.TreeStore(object, str, str, int, str, str, str, str)
|
||||
self.port_list = gtk.ListStore(
|
||||
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_column_id(1000, gtk.SORT_ASCENDING)
|
||||
@@ -229,8 +241,10 @@ class HostOpenPorts(HIGVBox):
|
||||
# service icon host hostname port protocol state version
|
||||
# service is shown only when more than one service is selected (hence
|
||||
# host_tree not host_list is used).
|
||||
self.host_list = gtk.ListStore(str, str, object, str, int, str, str, str)
|
||||
self.host_tree = gtk.TreeStore(str, str, object, str, int, str, str, str)
|
||||
self.host_list = gtk.ListStore(
|
||||
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_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['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['port_number'].set_attributes(self.cell_port, text=4)
|
||||
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.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):
|
||||
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_resizable(True)
|
||||
|
||||
|
||||
self.port_columns['icon'].set_min_width(35)
|
||||
|
||||
self.port_columns['hostname'].set_sort_column_id(1000)
|
||||
@@ -368,10 +383,14 @@ class HostOpenPorts(HIGVBox):
|
||||
def freeze(self):
|
||||
"""Freeze notifications and sorting to make adding lots of elements to
|
||||
the model faster."""
|
||||
self.frozen_host_list_sort_column_id = self.host_list.get_sort_column_id()
|
||||
self.frozen_host_tree_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.frozen_host_list_sort_column_id = \
|
||||
self.host_list.get_sort_column_id()
|
||||
self.frozen_host_tree_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_tree.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
|
||||
model)."""
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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.port_view.set_model(self.frozen_port_view_model)
|
||||
self.host_view.thaw_child_notify()
|
||||
@@ -414,7 +437,8 @@ class HostOpenPorts(HIGVBox):
|
||||
self.host_list.append(entry)
|
||||
|
||||
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():
|
||||
self.port_tree.append(parent,
|
||||
[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)])
|
||||
|
||||
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:
|
||||
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):
|
||||
if self.port_view.get_model() != self.port_list:
|
||||
|
||||
@@ -121,12 +121,14 @@
|
||||
# ***************************************************************************/
|
||||
|
||||
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.higlabels import HIGEntryLabel
|
||||
|
||||
import zenmapCore.I18N
|
||||
|
||||
|
||||
class ScanRunDetailsPage(HIGVBox):
|
||||
def __init__(self, scan):
|
||||
HIGVBox.__init__(self)
|
||||
@@ -146,7 +148,8 @@ class ScanRunDetailsPage(HIGVBox):
|
||||
self.debug_label = HIGEntryLabel(_('Debug level:'))
|
||||
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_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(self.command_table)
|
||||
|
||||
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.command_label, 0, 1, 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.info_nmap_version_label,1,2,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.verbose_label,0,1,2,3)
|
||||
self.command_table.attach(self.info_verbose_label,1,2,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.debug_label,0,1,3,4)
|
||||
self.command_table.attach(self.info_debug_label,1,2,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_expander.add(self.command_hbox)
|
||||
self._pack_noexpand_nofill(self.command_expander)
|
||||
@@ -199,7 +202,8 @@ class ScanRunDetailsPage(HIGVBox):
|
||||
self.closed_label = HIGEntryLabel(_('Closed ports:'))
|
||||
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_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(self.general_table)
|
||||
|
||||
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.start_label, 0, 1, 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.info_finished_label,1,2,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.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.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.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.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.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.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.open_label,0,1,5,6)
|
||||
self.general_table.attach(self.info_open_label,1,2,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.filtered_label,0,1,6,7)
|
||||
self.general_table.attach(self.info_filtered_label,1,2,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.closed_label,0,1,7,8)
|
||||
self.general_table.attach(self.info_closed_label,1,2,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_expander.add(self.general_hbox)
|
||||
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()))
|
||||
|
||||
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)
|
||||
|
||||
display = self.make_scaninfo_display(scaninfo)
|
||||
@@ -277,17 +282,18 @@ class ScanRunDetailsPage(HIGVBox):
|
||||
table.set_row_spacings(6)
|
||||
table.set_col_spacings(6)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Scan type:')),0,1,0,1)
|
||||
table.attach(HIGEntryLabel(scaninfo['type']),1,2,0,1)
|
||||
table.attach(HIGEntryLabel(_('Scan type:')), 0, 1, 0, 1)
|
||||
table.attach(HIGEntryLabel(scaninfo['type']), 1, 2, 0, 1)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Protocol:')),0,1,1,2)
|
||||
table.attach(HIGEntryLabel(scaninfo['protocol']),1,2,1,2)
|
||||
table.attach(HIGEntryLabel(_('Protocol:')), 0, 1, 1, 2)
|
||||
table.attach(HIGEntryLabel(scaninfo['protocol']), 1, 2, 1, 2)
|
||||
|
||||
table.attach(HIGEntryLabel(_('# scanned ports:')),0,1,2,3)
|
||||
table.attach(HIGEntryLabel(scaninfo['numservices']),1,2,2,3)
|
||||
table.attach(HIGEntryLabel(_('# scanned ports:')), 0, 1, 2, 3)
|
||||
table.attach(HIGEntryLabel(scaninfo['numservices']), 1, 2, 2, 3)
|
||||
|
||||
table.attach(HIGEntryLabel(_('Services:')),0,1,3,4)
|
||||
table.attach(self.make_services_display(scaninfo['services']),1,2,3,4)
|
||||
table.attach(HIGEntryLabel(_('Services:')), 0, 1, 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(table)
|
||||
|
||||
@@ -128,6 +128,7 @@ from zenmapGUI.higwidgets.higbuttons import HIGButton
|
||||
from zenmapGUI.higwidgets.higscrollers import HIGScrolledWindow
|
||||
import zenmapCore.I18N
|
||||
|
||||
|
||||
def status_data_func(widget, cell_renderer, model, iter):
|
||||
entry = model.get_value(iter, 0)
|
||||
if entry.running:
|
||||
@@ -143,14 +144,17 @@ def status_data_func(widget, cell_renderer, model, iter):
|
||||
status = _("Canceled")
|
||||
cell_renderer.set_property("text", status)
|
||||
|
||||
|
||||
def command_data_func(widget, cell_renderer, model, iter):
|
||||
entry = model.get_value(iter, 0)
|
||||
cell_renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
|
||||
cell_renderer.set_property("text", entry.get_command_string())
|
||||
|
||||
|
||||
class ScanScanListPage(HIGVBox):
|
||||
"""This is the "Scans" scan results tab. It the list of running and finished
|
||||
scans contained in the ScansListStore passed to the constructor."""
|
||||
"""This is the "Scans" scan results tab. It the list of running and
|
||||
finished scans contained in the ScansListStore passed to the
|
||||
constructor."""
|
||||
def __init__(self, scans_store):
|
||||
HIGVBox.__init__(self)
|
||||
|
||||
@@ -159,7 +163,8 @@ class ScanScanListPage(HIGVBox):
|
||||
scans_store.connect("row-changed", self._row_changed)
|
||||
|
||||
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"))
|
||||
cell = gtk.CellRendererText()
|
||||
@@ -193,9 +198,9 @@ class ScanScanListPage(HIGVBox):
|
||||
self.cancel_button = HIGButton(_("Cancel Scan"), gtk.STOCK_CANCEL)
|
||||
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()
|
||||
|
||||
@@ -206,13 +211,13 @@ class ScanScanListPage(HIGVBox):
|
||||
self._update()
|
||||
|
||||
def _update(self):
|
||||
# Make the Cancel button sensitive or not depending on whether a running
|
||||
# scan is selected.
|
||||
# Make the Cancel button sensitive or not depending on whether a
|
||||
# running scan is selected.
|
||||
tree_selection = self.scans_list.get_selection()
|
||||
if tree_selection is None:
|
||||
# I can't find anything in the PyGTK documentation that suggests
|
||||
# this is possible, but we received many crash reports that indicate
|
||||
# it is.
|
||||
# this is possible, but we received many crash reports that
|
||||
# indicate it is.
|
||||
model, selection = None, []
|
||||
else:
|
||||
model, selection = tree_selection.get_selected_rows()
|
||||
|
||||
@@ -133,7 +133,8 @@ from zenmapGUI.TargetCombo import TargetCombo
|
||||
|
||||
|
||||
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):
|
||||
"""Initialize command toolbar"""
|
||||
HIGHBox.__init__(self)
|
||||
@@ -249,6 +250,6 @@ if __name__ == "__main__":
|
||||
box.pack_start(stool)
|
||||
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()
|
||||
gtk.main()
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class ScansListStoreEntry(object):
|
||||
"""This class is an abstraction for running and completed scans, which are
|
||||
otherwise represented by very different classes."""
|
||||
@@ -134,11 +135,11 @@ class ScansListStoreEntry(object):
|
||||
self.command = None
|
||||
self.parsed = None
|
||||
|
||||
def set_running(self, command = None):
|
||||
def set_running(self, command=None):
|
||||
self.state = self.RUNNING
|
||||
self.command = command
|
||||
|
||||
def set_finished(self, parsed = None):
|
||||
def set_finished(self, parsed=None):
|
||||
self.state = self.FINISHED
|
||||
self.parsed = parsed
|
||||
|
||||
@@ -161,6 +162,7 @@ class ScansListStoreEntry(object):
|
||||
failed = property(lambda self: self.state == self.FAILED)
|
||||
canceled = property(lambda self: self.state == self.CANCELED)
|
||||
|
||||
|
||||
class ScansListStore(gtk.ListStore):
|
||||
"""This is a specialization of a gtk.ListStore that holds running,
|
||||
completed, and failed scans."""
|
||||
|
||||
@@ -129,7 +129,8 @@ import re
|
||||
import xml.sax
|
||||
|
||||
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.higscrollers import HIGScrolledWindow
|
||||
from zenmapGUI.higwidgets.higtextviewers import HIGTextView
|
||||
@@ -149,11 +150,12 @@ from zenmapCore.Name import APP_NAME
|
||||
|
||||
paths_config = PathsConfig()
|
||||
|
||||
|
||||
def text_buffer_insert_nsedoc(buf, nsedoc):
|
||||
"""Inserts NSEDoc at the end of the buffer, with markup turned into proper
|
||||
tags."""
|
||||
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):
|
||||
if event.type == "paragraph_start":
|
||||
buf.insert(buf.get_end_iter(), "\n")
|
||||
@@ -164,13 +166,15 @@ def text_buffer_insert_nsedoc(buf, nsedoc):
|
||||
elif event.type == "list_end":
|
||||
pass
|
||||
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":
|
||||
buf.insert(buf.get_end_iter(), "\n")
|
||||
elif event.type == "text":
|
||||
buf.insert(buf.get_end_iter(), event.text)
|
||||
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):
|
||||
"""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):
|
||||
if name == u"directory":
|
||||
if not attrs.has_key(u"name"):
|
||||
raise ValueError(u"\"directory\" element did not have \"name\" attribute")
|
||||
if u"name" not in attrs:
|
||||
raise ValueError(
|
||||
u'"directory" element did not have "name" attribute')
|
||||
dirname = attrs[u"name"]
|
||||
if not attrs.has_key(u"path"):
|
||||
raise ValueError(u"\"directory\" element did not have \"path\" attribute")
|
||||
if u"path" not in attrs:
|
||||
raise ValueError(
|
||||
u'"directory" element did not have "path" attribute')
|
||||
path = attrs[u"path"]
|
||||
if dirname == u"scripts":
|
||||
self.scripts_dir = path
|
||||
@@ -197,8 +203,9 @@ class ScriptHelpXMLContentHandler (xml.sax.handler.ContentHandler):
|
||||
# Ignore.
|
||||
pass
|
||||
elif name == u"script":
|
||||
if not attrs.has_key(u"filename"):
|
||||
raise ValueError(u"\"script\" element did not have \"filename\" attribute")
|
||||
if u"filename" not in attrs:
|
||||
raise ValueError(
|
||||
u'"script" element did not have "filename" attribute')
|
||||
self.script_filenames.append(attrs[u"filename"])
|
||||
|
||||
@staticmethod
|
||||
@@ -209,6 +216,7 @@ class ScriptHelpXMLContentHandler (xml.sax.handler.ContentHandler):
|
||||
parser.parse(f)
|
||||
return handler
|
||||
|
||||
|
||||
class ScriptInterface:
|
||||
# Timeout, in milliseconds, after the user stops typing and we update the
|
||||
# interface from --script.
|
||||
@@ -216,9 +224,9 @@ class ScriptInterface:
|
||||
# Timeout, in milliseconds, between polls of the Nmap subprocess.
|
||||
NMAP_DELAY = 200
|
||||
|
||||
def __init__(self,root_tabs,ops,update_command,help_buf):
|
||||
self.hmainbox = HIGHBox(False,0)
|
||||
self.notscripttab = False # to show profile editor that it is a script tab
|
||||
def __init__(self, root_tabs, ops, update_command, help_buf):
|
||||
self.hmainbox = HIGHBox(False, 0)
|
||||
self.notscripttab = False # show profile editor it is a script tab
|
||||
self.nmap_process = None
|
||||
self.script_list_timeout_id = None
|
||||
self.nmap_timeout_id = None
|
||||
@@ -240,16 +248,16 @@ class ScriptInterface:
|
||||
# Arg name, arg value, (name, desc) tuple.
|
||||
self.arg_liststore = gtk.ListStore(str, str, object)
|
||||
|
||||
# This is what is shown initially. After the initial Nmap run to get the
|
||||
# list of script is finished, this will be replaced with a TreeView
|
||||
# This is what is shown initially. After the initial Nmap run to get
|
||||
# the list of script is finished, this will be replaced with a TreeView
|
||||
# showing the scripts or an error message.
|
||||
self.script_list_container = gtk.VBox()
|
||||
self.script_list_container.pack_start(self.make_please_wait_widget())
|
||||
self.hmainbox.pack_start(self.script_list_container, False, False, 0)
|
||||
|
||||
self.nmap_error_widget = gtk.Label(_("""\
|
||||
There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
|
||||
"""))
|
||||
self.nmap_error_widget = gtk.Label(_(
|
||||
"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.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):
|
||||
"""Start an Nmap subprocess in the background with
|
||||
"--script-help=<rules> -oX -", and set it up to call the given callback when
|
||||
finished."""
|
||||
"--script-help=<rules> -oX -", and set it up to call the given callback
|
||||
when finished."""
|
||||
|
||||
ops = NmapOptions()
|
||||
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()
|
||||
# Separate stderr to avoid breaking XML parsing with "Warning: File
|
||||
# ./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))
|
||||
nmap_process = NmapCommand(command_string)
|
||||
try:
|
||||
nmap_process.run_scan(stderr = stderr)
|
||||
nmap_process.run_scan(stderr=stderr)
|
||||
except Exception, e:
|
||||
callback(False, None)
|
||||
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)
|
||||
|
||||
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):
|
||||
try:
|
||||
status = process.scan_state()
|
||||
except:
|
||||
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:
|
||||
# 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):
|
||||
process.stdout_file.seek(0)
|
||||
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:
|
||||
log.debug("--script-help parse exception: %s" % str(e))
|
||||
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")
|
||||
return False
|
||||
|
||||
log.debug("Script interface: scripts dir %s" % repr(handler.scripts_dir))
|
||||
log.debug("Script interface: nselib dir %s" % repr(handler.nselib_dir))
|
||||
log.debug("Script interface: scripts dir %s" % repr(
|
||||
handler.scripts_dir))
|
||||
log.debug("Script interface: nselib dir %s" % repr(handler.nselib_dir))
|
||||
|
||||
# Make a dict of script metadata 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
|
||||
|
||||
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):
|
||||
"""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:
|
||||
self.get_script_list(spec, self.update_script_list_cb)
|
||||
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):
|
||||
process.stdout_file.seek(0)
|
||||
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:
|
||||
log.debug("--script-help parse exception: %s" % str(e))
|
||||
return False
|
||||
@@ -422,29 +439,41 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
|
||||
character."""
|
||||
if 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
|
||||
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)
|
||||
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()
|
||||
else:
|
||||
for key in arg_dict.keys():
|
||||
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."""
|
||||
if raw_argument is not None:
|
||||
self.parse_script_args(raw_argument)
|
||||
|
||||
def set_help_texts(self):
|
||||
"""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.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.")
|
||||
self.list_scripts_help = _("""List of scripts
|
||||
|
||||
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):
|
||||
vbox = gtk.VBox()
|
||||
@@ -454,7 +483,8 @@ There was an error getting the list of scripts from Nmap. Try upgrading Nmap.\
|
||||
return vbox
|
||||
|
||||
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()
|
||||
|
||||
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)
|
||||
|
||||
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.hide()
|
||||
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)
|
||||
|
||||
hbox = HIGHBox(False, 2)
|
||||
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 = HIGButton(stock=gtk.STOCK_REMOVE)
|
||||
self.remove_file_button.connect(
|
||||
"clicked", self.remove_file_button_clicked_cb)
|
||||
self.remove_file_button.set_sensitive(False)
|
||||
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)
|
||||
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:
|
||||
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."""
|
||||
if(filename.endswith(".nse")):
|
||||
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.connect("enter-notify-event", self.update_help_desc_cb)
|
||||
self.text_buffer = text_view.get_buffer()
|
||||
self.text_buffer.create_tag("Usage", font = "Monospace")
|
||||
self.text_buffer.create_tag("Output", font = "Monospace")
|
||||
self.text_buffer.create_tag("Usage", font="Monospace")
|
||||
self.text_buffer.create_tag("Output", font="Monospace")
|
||||
text_view.set_wrap_mode(gtk.WRAP_WORD)
|
||||
text_view.set_editable(False)
|
||||
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_col.pack_start(argument, True)
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
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."""
|
||||
self.arg_list = []
|
||||
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.update_command()
|
||||
|
||||
def selection_changed_cb(self,selection):
|
||||
def selection_changed_cb(self, selection):
|
||||
"""Called back when the list of scripts is selected."""
|
||||
model, selection = selection.get_selected_rows()
|
||||
for path in selection:
|
||||
check_value = model.get_value(model.get_iter(path),1)
|
||||
entry = model.get_value(model.get_iter(path),2)
|
||||
check_value = model.get_value(model.get_iter(path), 1)
|
||||
entry = model.get_value(model.get_iter(path), 2)
|
||||
self.set_description(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."""
|
||||
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."""
|
||||
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)
|
||||
if arg_desc is not None:
|
||||
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)
|
||||
else:
|
||||
self.help_buf.set_text("")
|
||||
|
||||
def add_file_button_clicked_cb(self, button):
|
||||
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()
|
||||
filenames = self.script_file_chooser.get_filenames()
|
||||
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.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."""
|
||||
self.text_buffer.set_text(u"")
|
||||
|
||||
@@ -711,20 +747,25 @@ Categories: %(cats)s
|
||||
""" % {"cats": ", ".join(entry.categories)})
|
||||
text_buffer_insert_nsedoc(self.text_buffer, entry.description)
|
||||
if entry.usage:
|
||||
self.text_buffer.insert(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")
|
||||
self.text_buffer.insert(
|
||||
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:
|
||||
self.text_buffer.insert(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")
|
||||
self.text_buffer.insert(
|
||||
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:
|
||||
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
|
||||
arguments and values (if any)."""
|
||||
self.arg_liststore.clear()
|
||||
self.current_arguments = []
|
||||
self.value.set_property('editable',True)
|
||||
self.value.set_property('editable', True)
|
||||
for arg in entry.arguments:
|
||||
arg_name, arg_desc = arg
|
||||
self.current_arguments.append(arg)
|
||||
|
||||
@@ -128,8 +128,10 @@ import copy
|
||||
from zenmapGUI.higwidgets.higwindows import HIGWindow
|
||||
from zenmapGUI.higwidgets.higboxes import HIGVBox
|
||||
from zenmapGUI.higwidgets.higbuttons import HIGButton, HIGToggleButton
|
||||
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer, hig_box_space_holder
|
||||
from zenmapGUI.higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel, HintWindow
|
||||
from zenmapGUI.higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer,\
|
||||
hig_box_space_holder
|
||||
from zenmapGUI.higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel,\
|
||||
HintWindow
|
||||
from zenmapGUI.higwidgets.higtables import HIGTable
|
||||
from zenmapGUI.higwidgets.higdialogs import HIGAlertDialog
|
||||
|
||||
@@ -161,14 +163,16 @@ class SearchParser(object):
|
||||
self.search_gui = search_gui
|
||||
self.search_dict = search_gui.search_dict
|
||||
|
||||
# We need to make an operator->searchkey mapping, since the search entry
|
||||
# field and the search classes have different syntax.
|
||||
# We need to make an operator->searchkey mapping, since the search
|
||||
# entry field and the search classes have different syntax.
|
||||
#
|
||||
# NOTE: if you want to add a new search key not handled by the SearchResult
|
||||
# class, you should add a new method match_CRITERIANAME to the SearchResult class.
|
||||
# For example, if you'd like a "noodles" criteria, you need to create the method
|
||||
# SearchResult.match_noodles(self, noodles_string). To see how searches are
|
||||
# actually performed, start reading from the SearchResult.search() method.
|
||||
# NOTE: if you want to add a new search key not handled by the
|
||||
# SearchResult class, you should add a new method match_CRITERIANAME to
|
||||
# the SearchResult class. For example, if you'd like a "noodles"
|
||||
# criteria, you need to create the 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)
|
||||
|
||||
# This is not really an operator (see below)
|
||||
@@ -198,16 +202,18 @@ class SearchParser(object):
|
||||
else:
|
||||
self.search_dict["keyword"] = [word]
|
||||
|
||||
# Check if we have any dir: operators in our map, and if so, add them to the
|
||||
# search_gui object and remove them from the map. The dir: operator isn't a real
|
||||
# operator, in a sense that it doesn't need to be processed by the
|
||||
# SearchResult.search() function. It is needed only to create a new SearchDir
|
||||
# object, which is then used to perform the actual search().
|
||||
# Check if we have any dir: operators in our map, and if so, add them
|
||||
# to the search_gui object and remove them from the map. The dir:
|
||||
# operator isn't a real operator, in a sense that it doesn't need to be
|
||||
# processed by the SearchResult.search() function. It is needed only to
|
||||
# create a new SearchDir object, which is then used to perform the
|
||||
# actual search().
|
||||
if "dir" in self.search_dict:
|
||||
self.search_gui.init_search_dirs(self.search_dict["dir"])
|
||||
else:
|
||||
self.search_gui.init_search_dirs([])
|
||||
|
||||
|
||||
class SearchGUI(gtk.VBox, object):
|
||||
"""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
|
||||
@@ -230,25 +236,28 @@ class SearchGUI(gtk.VBox, object):
|
||||
self.id = 0
|
||||
self.search_window = search_window
|
||||
|
||||
# The Search* objects are created once per Search Window invocation, so that
|
||||
# they get a list of scans only once, not whenever the search conditions change
|
||||
# The Search* objects are created once per Search Window invocation, so
|
||||
# that they get a list of scans only once, not whenever the search
|
||||
# conditions change
|
||||
if self.options["search_db"]:
|
||||
try:
|
||||
self.search_db = SearchDB()
|
||||
except ImportError, e:
|
||||
self.search_db = SearchDummy()
|
||||
self.no_db_warning.show()
|
||||
self.no_db_warning.set_text("""\
|
||||
Warning: The database of saved scans is not available. (%s.) Use \
|
||||
"Include Directory" under "Expressions" to search a directory.\
|
||||
""" % str(e))
|
||||
self.no_db_warning.set_text(
|
||||
'Warning: The database of saved scans is not '
|
||||
'available. (%s.) Use "Include Directory" under '
|
||||
'"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.init_search_dirs()
|
||||
|
||||
# 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()
|
||||
# We need to define our own keyword search dictionary
|
||||
search_keywords = dict()
|
||||
@@ -286,42 +295,48 @@ Warning: The database of saved scans is not available. (%s.) Use \
|
||||
search_keywords["ir"] = "in_route"
|
||||
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 = []
|
||||
|
||||
# Do an initial "empty" search, so that the results window initially holds
|
||||
# all scans in the database
|
||||
# Do an initial "empty" search, so that the results window initially
|
||||
# holds all scans in the database
|
||||
self.search_parser.update("")
|
||||
self.start_search()
|
||||
|
||||
def init_search_dirs(self, dirs = []):
|
||||
def init_search_dirs(self, dirs=[]):
|
||||
# Start fresh
|
||||
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"]
|
||||
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)
|
||||
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):
|
||||
# Search box and buttons
|
||||
self.search_top_hbox = HIGHBox()
|
||||
self.search_label = HIGSectionLabel(_("Search:"))
|
||||
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
|
||||
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()
|
||||
|
||||
# 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_scrolled = gtk.ScrolledWindow()
|
||||
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.search_tooltip_btn, False)
|
||||
|
||||
# The expressions (if any) should be tightly packed so that they don't take
|
||||
# too much screen real-estate
|
||||
# The expressions (if any) should be tightly packed so that they don't
|
||||
# take too much screen real-estate
|
||||
self.expr_vbox.set_spacing(0)
|
||||
|
||||
# Packing the result section
|
||||
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
|
||||
self.set_spacing(4)
|
||||
@@ -366,21 +382,24 @@ Warning: The database of saved scans is not available. (%s.) Use \
|
||||
hint_window.show_all()
|
||||
|
||||
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"
|
||||
# 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))
|
||||
|
||||
if self.expressions_btn.get_active():
|
||||
# The Expressions GUI is about to be displayed. It needs to reflect all the
|
||||
# conditions in the search entry field, so a comparison between the entry field
|
||||
# and the GUI needs to be performed.
|
||||
# The Expressions GUI is about to be displayed. It needs to reflect
|
||||
# all the conditions in the search entry field, so a comparison
|
||||
# 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)
|
||||
|
||||
# Get a map of operator => argument from the Expressions GUI so that
|
||||
# we can compare them with the ones in the search entry field
|
||||
# Get a map of operator => argument from the Expressions GUI so
|
||||
# that we can compare them with the ones in the search entry field
|
||||
gui_ops = {}
|
||||
for criterion in self.expr_vbox.get_children():
|
||||
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]
|
||||
|
||||
# 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 arg in args:
|
||||
if (op not in gui_ops) or (arg not in gui_ops[op]):
|
||||
# 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
|
||||
# in the search_dict (for example, if a user has deleted something from the
|
||||
# search entry field)
|
||||
# Now we check if there are any leftover criterion rows that aren't
|
||||
# present in the search_dict (for example, if a user has deleted
|
||||
# something from the search entry field)
|
||||
for criterion in self.expr_vbox.get_children():
|
||||
if criterion.operator not in self.search_dict or \
|
||||
criterion.argument not in self.search_dict[criterion.operator]:
|
||||
if (criterion.operator not in self.search_dict or
|
||||
criterion.argument not in self.search_dict[
|
||||
criterion.operator]):
|
||||
criterion.destroy()
|
||||
# If we have deleted all rows, add an empty one
|
||||
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
|
||||
self.expr_vbox.show_all()
|
||||
else:
|
||||
# The Expressions GUI is about to be hidden. No updates to the search entry field
|
||||
# are necessary, since it gets updated on every change in one of the criterion rows.
|
||||
# The Expressions GUI is about to be hidden. No updates to the
|
||||
# search entry field are necessary, since it gets updated on every
|
||||
# change in one of the criterion rows.
|
||||
self.expr_vbox.hide_all()
|
||||
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):
|
||||
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):
|
||||
"""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):
|
||||
if not self.options["search_db"] and not self.options["directory"]:
|
||||
d = HIGAlertDialog(message_format=_("No search method selected!"),
|
||||
secondary_text=_("%s can search results on directories or \
|
||||
inside it's own database. Please, select a method by choosing a directory or by checking \
|
||||
the search data base option at the 'Search options' tab before start the search") % APP_DISPLAY_NAME)
|
||||
d = HIGAlertDialog(
|
||||
message_format=_("No search method selected!"),
|
||||
secondary_text=_(
|
||||
"%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.destroy()
|
||||
return
|
||||
@@ -488,8 +516,9 @@ the search data base option at the 'Search options' tab before start the search"
|
||||
# self.append_result(result)
|
||||
# matched += 1
|
||||
|
||||
self.search_window.set_label_text("Matched <b>%s</b> out of <b>%s</b> scans." % \
|
||||
(str(matched), str(total)))
|
||||
self.search_window.set_label_text(
|
||||
"Matched <b>%s</b> out of <b>%s</b> scans." % (
|
||||
str(matched), str(total)))
|
||||
|
||||
def clear_result_list(self):
|
||||
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:
|
||||
date_field = _("Unknown")
|
||||
|
||||
|
||||
self.parsed_results[self.id] = [title, parsed_result]
|
||||
self.result_list.append([title, date_field, self.id])
|
||||
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):
|
||||
"""This class holds one criterion row, represented as an HBox.
|
||||
It holds a ComboBox and a Subcriterion's subclass instance, depending on the
|
||||
selected entry in the ComboBox. For example, when the 'Target' option is
|
||||
selected, a SimpleSubcriterion widget is displayed, but when the 'Date'
|
||||
operator is selected, a DateSubcriterion widget is displayed."""
|
||||
"""This class holds one criterion row, represented as an HBox. It holds a
|
||||
ComboBox and a Subcriterion's subclass instance, depending on the selected
|
||||
entry in the ComboBox. For example, when the 'Target' option is selected, a
|
||||
SimpleSubcriterion widget is displayed, but when the 'Date' operator is
|
||||
selected, a DateSubcriterion widget is displayed."""
|
||||
|
||||
def __init__(self, search_window, operator="keyword", argument=""):
|
||||
"""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
|
||||
# the SimpleSubcriterion instance
|
||||
self.combo_entries = {"Keyword" : ["keyword"],
|
||||
"Profile Name" : ["profile"],
|
||||
"Target" : ["target"],
|
||||
"Options" : ["option"],
|
||||
"Date" : ["date", "after", "before"],
|
||||
"Operating System" : ["os"],
|
||||
"Port" : ["open", "scanned", "closed", "filtered",
|
||||
"unfiltered", "open_filtered", "closed_filtered"],
|
||||
"Service" : ["service"],
|
||||
"Host In Route" : ["inroute"],
|
||||
"Include Directory" : ["dir"]}
|
||||
self.combo_entries = {"Keyword": ["keyword"],
|
||||
"Profile Name": ["profile"],
|
||||
"Target": ["target"],
|
||||
"Options": ["option"],
|
||||
"Date": ["date", "after", "before"],
|
||||
"Operating System": ["os"],
|
||||
"Port": ["open", "scanned", "closed", "filtered",
|
||||
"unfiltered", "open_filtered",
|
||||
"closed_filtered"],
|
||||
"Service": ["service"],
|
||||
"Host In Route": ["inroute"],
|
||||
"Include Directory": ["dir"]}
|
||||
|
||||
self._create_widgets()
|
||||
self._pack_widgets()
|
||||
@@ -591,7 +620,8 @@ class Criterion(gtk.HBox):
|
||||
# A ComboBox containing the list of operators
|
||||
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.sort()
|
||||
for name in sorted_entries:
|
||||
@@ -605,7 +635,8 @@ class Criterion(gtk.HBox):
|
||||
break
|
||||
|
||||
# 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
|
||||
self.add_btn = HIGButton(" ", gtk.STOCK_ADD)
|
||||
@@ -674,6 +705,7 @@ class Criterion(gtk.HBox):
|
||||
operator = property(get_operator)
|
||||
argument = property(get_argument)
|
||||
|
||||
|
||||
class Subcriterion(gtk.HBox):
|
||||
"""This class is a base class for all subcriterion types. Depending on the
|
||||
criterion selected in the Criterion's ComboBox, a subclass of Subcriterion
|
||||
@@ -685,9 +717,11 @@ class Subcriterion(gtk.HBox):
|
||||
self.argument = ""
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class SimpleSubcriterion(Subcriterion):
|
||||
"""This class represents all 'simple' criterion types that need only an
|
||||
entry box in order to define the criterion."""
|
||||
@@ -716,6 +750,7 @@ class SimpleSubcriterion(Subcriterion):
|
||||
self.argument = widget.get_text()
|
||||
self.value_changed()
|
||||
|
||||
|
||||
class PortSubcriterion(Subcriterion):
|
||||
"""This class shows the port criterion GUI."""
|
||||
def __init__(self, operator="open", argument=""):
|
||||
@@ -736,11 +771,12 @@ class PortSubcriterion(Subcriterion):
|
||||
self.label = gtk.Label(" is ")
|
||||
|
||||
self.port_state_combo = gtk.combo_box_new_text()
|
||||
states = ["open", "scanned", "closed", "filtered", "unfiltered", "open|filtered",
|
||||
"closed|filtered"]
|
||||
states = ["open", "scanned", "closed", "filtered", "unfiltered",
|
||||
"open|filtered", "closed|filtered"]
|
||||
for state in states:
|
||||
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):
|
||||
self.pack_start(self.entry, True)
|
||||
@@ -759,6 +795,7 @@ class PortSubcriterion(Subcriterion):
|
||||
self.operator = widget.get_active_text()
|
||||
self.value_changed()
|
||||
|
||||
|
||||
class DirSubcriterion(Subcriterion):
|
||||
def __init__(self, operator="dir", argument=""):
|
||||
Subcriterion.__init__(self)
|
||||
@@ -797,13 +834,14 @@ class DirSubcriterion(Subcriterion):
|
||||
self.argument = widget.get_text()
|
||||
self.value_changed()
|
||||
|
||||
|
||||
class DateSubcriterion(Subcriterion):
|
||||
def __init__(self, operator="date", argument=""):
|
||||
Subcriterion.__init__(self)
|
||||
|
||||
self.text2op = {"is" : "date",
|
||||
"after" : "after",
|
||||
"before" : "before"}
|
||||
self.text2op = {"is": "date",
|
||||
"after": "after",
|
||||
"before": "before"}
|
||||
|
||||
self.operator = operator
|
||||
|
||||
@@ -811,7 +849,8 @@ class DateSubcriterion(Subcriterion):
|
||||
self._pack_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("~")
|
||||
argument = argument.replace("~", "")
|
||||
self.minus_notation = False
|
||||
@@ -821,9 +860,11 @@ class DateSubcriterion(Subcriterion):
|
||||
self.argument = argument
|
||||
elif re.match("[-|\+]\d+$", argument) != None:
|
||||
# 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.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
|
||||
else:
|
||||
@@ -851,7 +892,8 @@ class DateSubcriterion(Subcriterion):
|
||||
self.pack_start(self.date_button, True)
|
||||
|
||||
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)
|
||||
|
||||
def date_criterion_changed(self, widget=None, extra=None):
|
||||
@@ -897,6 +939,7 @@ class DateSubcriterion(Subcriterion):
|
||||
date = property(get_date, set_date)
|
||||
_date = datetime.date.today()
|
||||
|
||||
|
||||
class DateCalendar(gtk.Window, object):
|
||||
def __init__(self):
|
||||
gtk.Window.__init__(self, gtk.WINDOW_POPUP)
|
||||
@@ -906,7 +949,7 @@ class DateCalendar(gtk.Window, object):
|
||||
self.add(self.calendar)
|
||||
|
||||
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)
|
||||
|
||||
def kill_calendar(self, widget, method):
|
||||
|
||||
@@ -135,6 +135,7 @@ hildon = None
|
||||
|
||||
if is_maemo():
|
||||
import hildon
|
||||
|
||||
class BaseSearchWindow(hildon.Window):
|
||||
def __init__(self):
|
||||
hildon.Window.__init__(self)
|
||||
@@ -151,6 +152,7 @@ else:
|
||||
def _pack_widgets(self):
|
||||
self.vbox.set_border_width(4)
|
||||
|
||||
|
||||
class SearchWindow(BaseSearchWindow, object):
|
||||
def __init__(self, load_method, append_method):
|
||||
BaseSearchWindow.__init__(self)
|
||||
@@ -200,7 +202,8 @@ class SearchWindow(BaseSearchWindow, object):
|
||||
|
||||
def _connect_widgets(self):
|
||||
# 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_append.connect("clicked", self.append_selected)
|
||||
@@ -214,14 +217,16 @@ class SearchWindow(BaseSearchWindow, object):
|
||||
def set_label_text(self, 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
|
||||
self.load_method(self.results)
|
||||
|
||||
# Close Search Window
|
||||
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
|
||||
self.append_method(self.results)
|
||||
|
||||
|
||||
@@ -124,6 +124,7 @@ import gtk
|
||||
|
||||
from zenmapCore.TargetList import target_list
|
||||
|
||||
|
||||
class TargetCombo(gtk.ComboBoxEntry):
|
||||
def __init__(self):
|
||||
gtk.ComboBoxEntry.__init__(self, gtk.ListStore(str), 0)
|
||||
@@ -143,7 +144,7 @@ class TargetCombo(gtk.ComboBoxEntry):
|
||||
|
||||
t_list = target_list.get_target_list()
|
||||
for target in t_list[:15]:
|
||||
t_model.append([target.replace('\n','')])
|
||||
t_model.append([target.replace('\n', '')])
|
||||
|
||||
def add_new_target(self, target):
|
||||
target_list.add_target(target)
|
||||
|
||||
@@ -144,6 +144,7 @@ from radialnet.util.integration import make_graph_from_hosts
|
||||
|
||||
SLOW_LIMIT = 1000
|
||||
|
||||
|
||||
class TopologyPage(HIGVBox):
|
||||
def __init__(self, inventory):
|
||||
HIGVBox.__init__(self)
|
||||
@@ -200,12 +201,14 @@ class TopologyPage(HIGVBox):
|
||||
self.display_panel.pack_start(self.radialnet, True, True)
|
||||
|
||||
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.update_radialnet()
|
||||
|
||||
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()
|
||||
|
||||
self.slow_label.set_text(_("""\
|
||||
|
||||
@@ -136,23 +136,24 @@ import gobject
|
||||
gtk_version_major, gtk_version_minor, gtk_version_release = gtk.gtk_version
|
||||
assert gtk_version_major == 2
|
||||
|
||||
|
||||
def gtk_constant_name(group, value):
|
||||
"""
|
||||
Returns the (py)GTK+ name of a constant, given its group name
|
||||
"""
|
||||
group_response = { -1 : 'gtk.RESPONSE_NONE',
|
||||
-2 : 'gtk.RESPONSE_REJECT',
|
||||
-3 : 'gtk.RESPONSE_ACCEPT',
|
||||
-4 : 'gtk.RESPONSE_DELETE_EVENT',
|
||||
-5 : 'gtk.RESPONSE_OK',
|
||||
-6 : 'gtk.RESPONSE_CANCEL',
|
||||
-7 : 'gtk.RESPONSE_CLOSE',
|
||||
-8 : 'gtk.RESPONSE_YES',
|
||||
-9 : 'gtk.RESPONSE_NO',
|
||||
-10 : 'gtk.RESPONSE_APPLY',
|
||||
-11 : 'gtk.RESPONSE_HELP' }
|
||||
group_response = {-1: 'gtk.RESPONSE_NONE',
|
||||
-2: 'gtk.RESPONSE_REJECT',
|
||||
-3: 'gtk.RESPONSE_ACCEPT',
|
||||
-4: 'gtk.RESPONSE_DELETE_EVENT',
|
||||
-5: 'gtk.RESPONSE_OK',
|
||||
-6: 'gtk.RESPONSE_CANCEL',
|
||||
-7: 'gtk.RESPONSE_CLOSE',
|
||||
-8: 'gtk.RESPONSE_YES',
|
||||
-9: 'gtk.RESPONSE_NO',
|
||||
-10: 'gtk.RESPONSE_APPLY',
|
||||
-11: 'gtk.RESPONSE_HELP'}
|
||||
|
||||
groups = {'response' : group_response}
|
||||
groups = {'response': group_response}
|
||||
|
||||
return groups.get(group, {}).get(value, 'Error: constant value not found')
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ __all__ = ['HIGHBox', 'HIGVBox']
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class HIGBox(gtk.Box):
|
||||
def _pack_noexpand_nofill(self, widget):
|
||||
self.pack_start(widget, expand=False, fill=False)
|
||||
@@ -137,6 +138,7 @@ class HIGBox(gtk.Box):
|
||||
def _pack_expand_fill(self, widget):
|
||||
self.pack_start(widget, expand=True, fill=True)
|
||||
|
||||
|
||||
class HIGHBox(gtk.HBox, HIGBox):
|
||||
def __init__(self, homogeneous=False, spacing=12):
|
||||
gtk.HBox.__init__(self, homogeneous, spacing)
|
||||
@@ -145,6 +147,7 @@ class HIGHBox(gtk.HBox, HIGBox):
|
||||
pack_label = HIGBox._pack_noexpand_nofill
|
||||
pack_entry = HIGBox._pack_expand_fill
|
||||
|
||||
|
||||
class HIGVBox(gtk.VBox, HIGBox):
|
||||
def __init__(self, homogeneous=False, spacing=12):
|
||||
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
|
||||
pack_line = HIGBox._pack_noexpand_nofill
|
||||
|
||||
|
||||
class HIGSpacer(HIGHBox):
|
||||
def __init__(self, widget=None):
|
||||
HIGHBox.__init__(self)
|
||||
@@ -166,5 +170,6 @@ class HIGSpacer(HIGHBox):
|
||||
def get_child(self):
|
||||
return self.child
|
||||
|
||||
|
||||
def hig_box_space_holder():
|
||||
return gtk.Label(" ")
|
||||
|
||||
@@ -130,6 +130,7 @@ __all__ = ['HIGMixButton', 'HIGButton']
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class HIGMixButton (gtk.HBox):
|
||||
def __init__(self, title, stock):
|
||||
gtk.HBox.__init__(self, False, 4)
|
||||
@@ -146,8 +147,9 @@ class HIGMixButton (gtk.HBox):
|
||||
self.pack_start(self.align)
|
||||
self.pack_start(self.hbox1)
|
||||
|
||||
|
||||
class HIGButton (gtk.Button):
|
||||
def __init__ (self, title="", stock=None):
|
||||
def __init__(self, title="", stock=None):
|
||||
if title and stock:
|
||||
gtk.Button.__init__(self)
|
||||
content = HIGMixButton(title, stock)
|
||||
@@ -159,6 +161,7 @@ class HIGButton (gtk.Button):
|
||||
else:
|
||||
gtk.Button.__init__(self)
|
||||
|
||||
|
||||
class HIGToggleButton(gtk.ToggleButton):
|
||||
def __init__(self, title="", stock=None):
|
||||
if title and stock:
|
||||
|
||||
@@ -132,6 +132,7 @@ import gtk
|
||||
|
||||
from gtkutils import gtk_version_minor
|
||||
|
||||
|
||||
class HIGDialog(gtk.Dialog):
|
||||
"""
|
||||
HIGFied Dialog
|
||||
@@ -142,6 +143,7 @@ class HIGDialog(gtk.Dialog):
|
||||
self.vbox.set_border_width(2)
|
||||
self.vbox.set_spacing(6)
|
||||
|
||||
|
||||
class HIGAlertDialog(gtk.MessageDialog):
|
||||
"""
|
||||
HIGfied Alert Dialog.
|
||||
|
||||
@@ -130,6 +130,7 @@ import gtk
|
||||
|
||||
HIGTextEntry = gtk.Entry
|
||||
|
||||
|
||||
class HIGPasswordEntry(HIGTextEntry):
|
||||
"""
|
||||
An entry that masks its text
|
||||
|
||||
@@ -132,6 +132,7 @@ import gtk
|
||||
|
||||
from higboxes import HIGHBox, hig_box_space_holder
|
||||
|
||||
|
||||
class HIGExpander(gtk.Expander):
|
||||
def __init__(self, label):
|
||||
gtk.Expander.__init__(self)
|
||||
|
||||
@@ -130,6 +130,7 @@ __all__ = ['HIGFrame']
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class HIGFrame(gtk.Frame):
|
||||
"""
|
||||
Frame without border with bold label.
|
||||
|
||||
@@ -126,10 +126,13 @@ higwidgets/higlabels.py
|
||||
labels related classes
|
||||
"""
|
||||
|
||||
__all__ = ['HIGSectionLabel', 'HIGHintSectionLabel', 'HIGEntryLabel', 'HIGDialogLabel']
|
||||
__all__ = [
|
||||
'HIGSectionLabel', 'HIGHintSectionLabel', 'HIGEntryLabel', 'HIGDialogLabel'
|
||||
]
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class HIGSectionLabel(gtk.Label):
|
||||
"""
|
||||
Bold label, used to define sections
|
||||
@@ -142,10 +145,11 @@ class HIGSectionLabel(gtk.Label):
|
||||
self.set_alignment(0, 0.50)
|
||||
self.set_line_wrap(True)
|
||||
|
||||
|
||||
class HIGHintSectionLabel(gtk.HBox, object):
|
||||
"""
|
||||
Bold label used to define sections, with a little icon that shows up a hint when mouse is
|
||||
over it.
|
||||
Bold label used to define sections, with a little icon that shows up a hint
|
||||
when mouse is over it.
|
||||
"""
|
||||
def __init__(self, text=None, hint=None):
|
||||
gtk.HBox.__init__(self)
|
||||
@@ -156,13 +160,15 @@ class HIGHintSectionLabel(gtk.HBox, object):
|
||||
self.pack_start(self.label, False, False)
|
||||
self.pack_start(self.hint, False, False, 5)
|
||||
|
||||
|
||||
class Hint(gtk.EventBox, object):
|
||||
def __init__(self, hint):
|
||||
gtk.EventBox.__init__(self)
|
||||
self.hint = hint
|
||||
|
||||
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)
|
||||
|
||||
@@ -172,6 +178,7 @@ class Hint(gtk.EventBox, object):
|
||||
hint_window = HintWindow(self.hint)
|
||||
hint_window.show_all()
|
||||
|
||||
|
||||
class HintWindow(gtk.Window):
|
||||
def __init__(self, hint):
|
||||
gtk.Window.__init__(self, gtk.WINDOW_POPUP)
|
||||
@@ -208,6 +215,7 @@ class HIGEntryLabel(gtk.Label):
|
||||
self.set_use_markup(True)
|
||||
self.set_line_wrap(True)
|
||||
|
||||
|
||||
class HIGDialogLabel(gtk.Label):
|
||||
"""
|
||||
Centered, line-wrappable label, usually used on dialogs.
|
||||
|
||||
@@ -135,6 +135,7 @@ from higlabels import HIGEntryLabel
|
||||
from higtables import HIGTable
|
||||
from higentries import HIGTextEntry, HIGPasswordEntry
|
||||
|
||||
|
||||
class HIGLoginDialog(HIGDialog):
|
||||
"""
|
||||
A dialog that asks for basic login information (username / password)
|
||||
|
||||
@@ -133,8 +133,11 @@ class HIGNotebook(gtk.Notebook):
|
||||
gtk.Notebook.__init__(self)
|
||||
self.popup_enable()
|
||||
|
||||
|
||||
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=""):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
@@ -132,6 +132,7 @@ import gtk
|
||||
|
||||
from higboxes import HIGHBox
|
||||
|
||||
|
||||
class HIGLabeledProgressBar(HIGHBox):
|
||||
def __init__(self, label=None):
|
||||
HIGHBox.__init__(self)
|
||||
|
||||
@@ -130,6 +130,7 @@ __all__ = ['HIGScrolledWindow']
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class HIGScrolledWindow(gtk.ScrolledWindow):
|
||||
def __init__(self):
|
||||
gtk.ScrolledWindow.__init__(self)
|
||||
|
||||
@@ -134,12 +134,14 @@ import gobject
|
||||
|
||||
from gtkutils import gobject_register
|
||||
|
||||
|
||||
class HIGSpinnerImages:
|
||||
def __init__(self):
|
||||
"""This class holds list of GDK 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__')
|
||||
@@ -182,7 +184,7 @@ class HIGSpinnerImages:
|
||||
|
||||
dprint('HIGSpinnerImages::set_rest_pixbuf')
|
||||
|
||||
if not self.static_pixbufs.has_key(name):
|
||||
if name not in self.static_pixbufs:
|
||||
raise StaticPixbufNotFound
|
||||
|
||||
# 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,
|
||||
image_format)
|
||||
|
||||
|
||||
class HIGSpinner(gtk.EventBox):
|
||||
"""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
|
||||
"""
|
||||
|
||||
__gsignals__ = { 'expose-event' : 'override',
|
||||
'size-request' : 'override' }
|
||||
__gsignals__ = {'expose-event': 'override',
|
||||
'size-request': 'override'}
|
||||
|
||||
def __init__(self):
|
||||
gtk.EventBox.__init__(self)
|
||||
@@ -384,8 +387,8 @@ class HIGSpinner(gtk.EventBox):
|
||||
if self.timer_task == 0:
|
||||
self.current_pixbuf = self.cache.spinner_images.rest_pixbuf
|
||||
else:
|
||||
self.current_pixbuf = self.cache.spinner_images.animated_pixbufs\
|
||||
[self.animated_pixbuf_index]
|
||||
self.current_pixbuf = self.cache.spinner_images.animated_pixbufs[
|
||||
self.animated_pixbuf_index]
|
||||
|
||||
def start(self):
|
||||
"""Starts the animation"""
|
||||
@@ -401,11 +404,11 @@ class HIGSpinner(gtk.EventBox):
|
||||
self.timer_task = 0
|
||||
self.queue_draw()
|
||||
|
||||
|
||||
def stop(self):
|
||||
"""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.animated_pixbuf_index = 0
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ import gtk
|
||||
#from higlabels import *
|
||||
#from higentries import *
|
||||
|
||||
|
||||
class HIGTable(gtk.Table):
|
||||
"""
|
||||
A HIGFied table
|
||||
@@ -154,4 +155,4 @@ class HIGTable(gtk.Table):
|
||||
self.attach(widget, x0, x, y0, y, xoptions=gtk.FILL)
|
||||
|
||||
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)
|
||||
|
||||
@@ -130,6 +130,7 @@ __all__ = ['HIGTextView']
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class HIGTextView(gtk.TextView):
|
||||
def __init__(self, text=''):
|
||||
gtk.TextView.__init__(self)
|
||||
|
||||
@@ -128,6 +128,7 @@ higwidgets/higwindows.py
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class HIGWindow(gtk.Window):
|
||||
"""HIGFied Window"""
|
||||
def __init__(self, type=gtk.WINDOW_TOPLEVEL):
|
||||
|
||||
@@ -130,6 +130,7 @@ __all__ = ['HIGSpinner']
|
||||
|
||||
import gobject
|
||||
|
||||
|
||||
def gobject_register(klass):
|
||||
if gtk_version_minor < 8:
|
||||
gobject.type_register(klass)
|
||||
|
||||
Reference in New Issue
Block a user