def delete_profile(self, widget=None, extra=None): 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.')) hbox = HIGHBox() hbox.set_border_width(5) hbox.set_spacing(12) vbox = HIGVBox() vbox.set_border_width(5) vbox.set_spacing(12) image = gtk.Image() image.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) vbox.pack_start(alert) vbox.pack_start(text) hbox.pack_start(image) hbox.pack_start(vbox) dialog.vbox.pack_start(hbox) dialog.vbox.show_all() response = dialog.run() dialog.destroy() if response == gtk.RESPONSE_CANCEL: return True self.profile.remove_profile(self.profile_name) self.update_profile_entry() self.destroy()
class ProfileEditor(HIGWindow): 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')) self.set_position(gtk.WIN_POS_CENTER) self.deletable = deletable 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. self.inhibit_command_update = False self.__create_widgets() self.__pack_widgets() self.profile = CommandProfile() self.ops = NmapOptions() if profile_name: log.debug("Showing profile %s" % profile_name) prof = self.profile.get_profile(profile_name) # Interface settings self.profile_name_entry.set_text(profile_name) 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()) 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 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.update_command() def command_entry_changed_cb(self, widget): command_string = self.command_entry.get_text().decode("UTF-8") self.ops.parse_string(command_string) self.inhibit_command_update = True self.option_builder.update() self.inhibit_command_update = False def update_command(self): """Regenerate and display the command.""" if not self.inhibit_command_update: # Block recursive updating of the OptionBuilder widgets when they # 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) 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.") 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.") def __create_widgets(self): ### # Vertical box to keep 3 boxes self.main_whole_box = HIGVBox() self.upper_box = HIGHBox() self.middle_box = HIGHBox() self.lower_box = HIGHBox() #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.scan_button = HIGButton(_("Scan")) self.scan_button.connect("clicked", self.run_scan) self.notebook = gtk.Notebook() # Profile info page self.profile_info_vbox = HIGVBox() 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_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) # Buttons self.buttons_hbox = HIGHBox() self.cancel_button = HIGButton(stock=gtk.STOCK_CANCEL) self.cancel_button.connect('clicked', self.exit) self.delete_button = HIGButton(stock=gtk.STOCK_DELETE) self.delete_button.connect('clicked', self.delete_profile) self.save_button = HIGButton(_("Save Changes"), stock=gtk.STOCK_SAVE) self.save_button.connect('clicked', self.save_profile) ### self.help_vbox = HIGVBox() self.help_label = HIGSectionLabel(_('Help')) self.help_scroll = HIGScrolledWindow() self.help_scroll.set_border_width(0) self.help_field = HIGTextView() 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) ### def __pack_widgets(self): ### self.add(self.main_whole_box) # Packing command entry to upper box self.upper_box._pack_expand_fill(self.command_entry) self.upper_box._pack_noexpand_nofill(self.scan_button) # Packing notebook (left) and help box (right) to middle box self.middle_box._pack_expand_fill(self.notebook) self.middle_box._pack_expand_fill(self.help_vbox) # Packing buttons to lower box self.lower_box.pack_end(self.buttons_hbox) # Packing the three vertical boxes to the main box self.main_whole_box._pack_noexpand_nofill(self.upper_box) self.main_whole_box._pack_expand_fill(self.middle_box) 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.profile_info_vbox.set_border_width(5) table = HIGTable() self.profile_info_vbox._pack_noexpand_nofill(self.profile_info_label) self.profile_info_vbox._pack_expand_fill(HIGSpacer(table)) self.profile_description_scroll.add(self.profile_description_text) vbox_desc = HIGVBox() vbox_desc._pack_noexpand_nofill(self.profile_description_label) vbox_desc._pack_expand_fill(hig_box_space_holder()) 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) # Packing buttons on button_hbox self.buttons_hbox._pack_expand_fill(hig_box_space_holder()) if self.deletable: self.buttons_hbox._pack_noexpand_nofill(self.delete_button) self.buttons_hbox._pack_noexpand_nofill(self.cancel_button) self.buttons_hbox._pack_noexpand_nofill(self.save_button) self.buttons_hbox.set_border_width(5) self.buttons_hbox.set_spacing(6) ### self.help_vbox._pack_noexpand_nofill(self.help_label) self.help_vbox._pack_expand_fill(self.help_scroll) self.help_scroll.add(self.help_field) self.help_vbox.set_border_width(1) self.help_vbox.set_spacing(1) ### def __create_tab(self, tab_name, section_name, tab): 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 table = HIGTable() table.set_row_spacings(2) section = HIGSectionLabel(section_name) vbox._pack_noexpand_nofill(section) vbox._pack_noexpand_nofill(HIGSpacer(table)) vbox.set_border_width(5) tab.fill_table(table, True) else: hbox = tab.get_hmain_box() vbox.pack_start(hbox, True, True, 0) self.notebook.append_page(vbox, gtk.Label(tab_name)) def save_profile(self, widget): if self.overwrite: 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.run() alert.destroy() self.profile_name_entry.grab_focus() return None command = self.ops.render_string() buf = self.profile_description_text.get_buffer() description = buf.get_text( buf.get_start_iter(), buf.get_end_iter()) try: self.profile.add_profile( profile_name, 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.run() alert.destroy() return self.scan_interface.toolbar.profile_entry.update() self.destroy() def clean_profile_info(self): self.profile_name_entry.set_text('') self.profile_description_text.get_buffer().set_text('') def set_scan_interface(self, interface): self.scan_interface = interface def exit(self, *args): self.destroy() def delete_profile(self, widget=None, extra=None): 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! ClickOk to continue, ' 'or Cancel to go back to Profile Editor.')) hbox = HIGHBox() hbox.set_border_width(5) hbox.set_spacing(12) vbox = HIGVBox() vbox.set_border_width(5) vbox.set_spacing(12) image = gtk.Image() image.set_from_stock( gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) vbox.pack_start(alert) vbox.pack_start(text) hbox.pack_start(image) hbox.pack_start(vbox) dialog.vbox.pack_start(hbox) dialog.vbox.show_all() response = dialog.run() dialog.destroy() if response == gtk.RESPONSE_CANCEL: return True self.profile.remove_profile(self.profile_name) self.update_profile_entry() self.destroy() def run_scan(self, widget=None): command_string = self.command_entry.get_text().decode("UTF-8") self.scan_interface.command_toolbar.command = command_string self.scan_interface.start_scan_cb() self.exit() def update_profile_entry(self, widget=None, extra=None): self.scan_interface.toolbar.profile_entry.update() list = self.scan_interface.toolbar.profile_entry.get_model() length = len(list) if length > 0: self.scan_interface.toolbar.profile_entry.set_active(0)
class ScanInterface(HIGVBox): """ScanInterface contains the scan toolbar and the scan results. Each ScanInterface represents a single NetworkInventory as well as a set of running scans.""" # The time delay between when you stop typing a filter string and filtering # actually begins, in milliseconds. FILTER_DELAY = 1000 def __init__(self): HIGVBox.__init__(self) # The borders are consuming too much space on Maemo. Setting it to # 0 pixels while on Maemo if is_maemo(): self.set_border_width(0) self.set_spacing(0) # True if nothing has happened here page yet, i.e., it's okay to load a # scan from a file here. self.empty = True # The most recent name the inventory on this page has been saved under. self.saved_filename = None # The network inventory shown by this page. It may consist of multiple # scans. self.inventory = FilteredNetworkInventory() # The list of currently running scans (NmapCommand objects). self.jobs = [] # The list of running and finished scans shown on the Nmap Output page. self.scans_store = ScansListStore() self.top_box = HIGVBox() self.__create_toolbar() self.__create_command_toolbar() self.select_default_profile() self.scan_result = ScanResult(self.inventory, self.scans_store, 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) 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) 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 # {'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', # 'service_method': u'probed', 'service_name': u'ssh', # 'service_product': u'OpenSSH', 'service_version': u'4.3'} # In other words each dict has the same keys as an entry in # HostInfo.ports, with the addition of "host" and "hostname" keys. self.services = {} self.top_box.set_border_width(6) self.top_box.set_spacing(5) self.top_box._pack_noexpand_nofill(self.toolbar) self.top_box._pack_noexpand_nofill(self.command_toolbar) 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.update_cancel_button() # Create the filter GUI self.filter_bar = FilterBar() self.pack_start(self.filter_bar, False, True, 0) self.filter_bar.set_no_show_all(True) self.filter_timeout_id = None self.filter_bar.connect("changed", self.filter_changed) self.scan_result.filter_toggle_button.connect("toggled", self.filter_toggle_toggled) self.scan_result.filter_toggle_button.show() def toggle_filter_bar(self): self.scan_result.filter_toggle_button.clicked() def filter_toggle_toggled(self, widget): if self.scan_result.filter_toggle_button.get_active(): # Show the filter bar self.filter_bar.show() self.filter_bar.grab_focus() self.filter_hosts(self.filter_bar.get_filter_string()) else: # Hide the filter bar self.filter_bar.hide() self.filter_hosts("") self.update_ui() def filter_changed(self, filter_bar): # 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()) def filter_hosts(self, filter_string): start = time.clock() self.inventory.apply_filter(filter_string) filter_time = time.clock() - start # Update the gui start = time.clock() self.update_ui() gui_time = time.clock() - start if filter_time + gui_time > 0.0: log.debug("apply_filter %g ms update_ui %g ms (%.0f%% filter)" % (filter_time * 1000.0, gui_time * 1000.0, 100.0 * filter_time / (filter_time + gui_time))) self.filter_timeout_id = None return False def is_changed(self): """Return true if this window has unsaved changes.""" for scan in self.inventory.get_scans(): if scan.unsaved: return True return False changed = property(is_changed) def num_scans_running(self): return len(self.jobs) def select_default_profile(self): """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) def go_to_host(self, hostname): """Scroll the text output to the appearance of the named host.""" self.scan_result.scan_result_notebook.nmap_output.nmap_output.go_to_host(hostname) # noqa def __create_toolbar(self): self.toolbar = ScanToolbar() 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.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_entry_changed_handler = \ self.command_toolbar.command_entry.connect( 'changed', self._command_entry_changed) def _command_entry_changed(self, editable): ops = NmapOptions() ops.parse_string(self.command_toolbar.get_command()) # Set the target and profile without propagating the "changed" signal # back to the command entry. self.set_target_quiet(join_quoted(ops.target_specs)) self.set_profile_name_quiet("") def _target_entry_changed(self, editable): target_string = self.toolbar.get_selected_target() targets = split_quoted(target_string) ops = NmapOptions() ops.parse_string(self.command_toolbar.get_command()) ops.target_specs = targets self.set_command_quiet(ops.render_string()) def _profile_entry_changed(self, widget): """Update the command based on the contents of the target and profile entries. If the command corresponding to the current profile is not blank, use it. Otherwise use the current contents of the command entry.""" profile_name = self.toolbar.get_selected_profile() target_string = self.toolbar.get_selected_target() cmd_profile = CommandProfile() command_string = cmd_profile.get_command(profile_name) del(cmd_profile) if command_string == "": command_string = self.command_toolbar.get_command() ops = NmapOptions() ops.parse_string(command_string) # Use the targets from the command entry, if there are any, otherwise # use any targets from the profile. targets = split_quoted(target_string) if len(targets) > 0: ops.target_specs = targets else: self.toolbar.set_selected_target(join_quoted(ops.target_specs)) self.set_command_quiet(ops.render_string()) 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.set_command(command_string) 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.set_selected_target(target_string) 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.set_selected_profile(profile_name) self.toolbar.profile_entry.handler_unblock( self.profile_entry_changed_handler) def start_scan_cb(self, widget=None): target = self.toolbar.selected_target command = self.command_toolbar.command profile = self.toolbar.selected_profile log.debug(">>> Start Scan:") log.debug(">>> Target: '%s'" % target) log.debug(">>> Profile: '%s'" % profile) log.debug(">>> Command: '%s'" % command) if target != '': try: self.toolbar.add_new_target(target) 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))) 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.run() warn_dialog.destroy() return self.execute_command(command, target, profile)
class ScanHostsView(HIGVBox, object): HOST_MODE, SERVICE_MODE = range(2) def __init__(self, scan_interface): HIGVBox.__init__(self) self._scan_interface = scan_interface self._create_widgets() self._connect_widgets() self._pack_widgets() self._set_scrolled() self._set_host_list() self._set_service_list() self._pack_expand_fill(self.main_vbox) self.mode = None # Default mode is host mode self.host_mode(self.host_mode_button) self.host_view.show_all() self.service_view.show_all() def _create_widgets(self): # Mode buttons self.host_mode_button = gtk.ToggleButton(_("Hosts")) self.service_mode_button = gtk.ToggleButton(_("Services")) self.buttons_box = gtk.HBox() # Main window vbox self.main_vbox = HIGVBox() # Host list self.host_list = gtk.ListStore(object, str, str) self.host_list.set_sort_func(1000, cmp_treemodel_addr) self.host_list.set_sort_column_id(1000, gtk.SORT_ASCENDING) self.host_view = gtk.TreeView(self.host_list) self.pic_column = gtk.TreeViewColumn(_('OS')) self.host_column = gtk.TreeViewColumn(_('Host')) self.os_cell = gtk.CellRendererPixbuf() self.host_cell = gtk.CellRendererText() # Service list self.service_list = gtk.ListStore(str) self.service_list.set_sort_column_id(0, gtk.SORT_ASCENDING) self.service_view = gtk.TreeView(self.service_list) self.service_column = gtk.TreeViewColumn(_('Service')) self.service_cell = gtk.CellRendererText() self.scrolled = gtk.ScrolledWindow() def _pack_widgets(self): self.main_vbox.set_spacing(0) self.main_vbox.set_border_width(0) self.main_vbox._pack_noexpand_nofill(self.buttons_box) self.main_vbox._pack_expand_fill(self.scrolled) self.host_mode_button.set_active(True) self.buttons_box.set_border_width(5) self.buttons_box.pack_start(self.host_mode_button) self.buttons_box.pack_start(self.service_mode_button) def _connect_widgets(self): self.host_mode_button.connect("toggled", self.host_mode) self.service_mode_button.connect("toggled", self.service_mode) def host_mode(self, widget): self._remove_scrolled_child() if widget.get_active(): self.mode = self.HOST_MODE self.service_mode_button.set_active(False) self.scrolled.add(self.host_view) else: self.service_mode_button.set_active(True) def service_mode(self, widget): self._remove_scrolled_child() if widget.get_active(): self.mode = self.SERVICE_MODE self.host_mode_button.set_active(False) self.scrolled.add(self.service_view) else: self.host_mode_button.set_active(True) def _remove_scrolled_child(self): try: child = self.scrolled.get_child() self.scrolled.remove(child) except: pass def _set_scrolled(self): self.scrolled.set_border_width(5) self.scrolled.set_size_request(150, -1) self.scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) def _set_service_list(self): self.service_view.set_enable_search(True) self.service_view.set_search_column(0) selection = self.service_view.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) self.service_view.append_column(self.service_column) self.service_column.set_resizable(True) self.service_column.set_sort_column_id(0) self.service_column.set_reorderable(True) self.service_column.pack_start(self.service_cell, True) self.service_column.set_attributes(self.service_cell, text=0) def _set_host_list(self): self.host_view.set_enable_search(True) self.host_view.set_search_column(1) selection = self.host_view.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) self.host_view.append_column(self.pic_column) self.host_view.append_column(self.host_column) self.host_column.set_resizable(True) self.pic_column.set_resizable(True) self.host_column.set_sort_column_id(1000) self.pic_column.set_sort_column_id(1) self.host_column.set_reorderable(True) self.pic_column.set_reorderable(True) self.pic_column.pack_start(self.os_cell, True) 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) def mass_update(self, hosts): """Update the internal ListStores to reflect the hosts and services passed in. Hosts that have not changed are left alone.""" hosts = set(hosts) services = set() for h in hosts: services.update([s["service_name"] for s in h.services]) # Disable sorting while elements are added. See the PyGTK FAQ 13.43, # "Are there tips for improving performance when adding many rows to a # Treeview?" sort_column_id = self.host_list.get_sort_column_id() self.host_list.set_default_sort_func(lambda *args: -1) self.host_list.set_sort_column_id(-1, gtk.SORT_ASCENDING) self.host_view.freeze_child_notify() self.host_view.set_model(None) it = self.host_list.get_iter_first() # Remove any of our ListStore hosts that aren't in the list passed in. while it: host = self.host_list.get_value(it, 0) if host in hosts: hosts.remove(host) self.host_list.set(it, 1, get_os_icon(host)) it = self.host_list.iter_next(it) else: if not self.host_list.remove(it): it = None # Add any remaining hosts into our ListStore. for host in hosts: self.add_host(host) # Reenable sorting. if sort_column_id != (None, None): self.host_list.set_sort_column_id(*sort_column_id) self.host_view.set_model(self.host_list) self.host_view.thaw_child_notify() it = self.service_list.get_iter_first() # Remove any of our ListStore services that aren't in the list passed # in. while it: service_name = self.service_list.get_value(it, 0) if service_name in services: services.remove(service_name) it = self.service_list.iter_next(it) else: if not self.service_list.remove(it): it = None # Add any remaining services into our ListStore. for service_name in services: self.add_service(service_name) def add_host(self, host): self.host_list.append([host, get_os_icon(host), host.get_hostname()]) def add_service(self, service): self.service_list.append([service])
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_position(gtk.WIN_POS_CENTER) self.__create_widgets() self.__packing() self.set_text() def __create_widgets(self): self.vbox = HIGVBox() self.hbox = HIGHBox() self.notebook = HIGNotebook() self.btn_close = HIGButton(stock=gtk.STOCK_CLOSE) self.written_by_scroll = HIGScrolledWindow() self.written_by_text = HIGTextView() self.design_scroll = HIGScrolledWindow() self.design_text = HIGTextView() self.soc2007_scroll = HIGScrolledWindow() self.soc2007_text = HIGTextView() self.contributors_scroll = HIGScrolledWindow() self.contributors_text = HIGTextView() self.translation_scroll = HIGScrolledWindow() self.translation_text = HIGTextView() self.nokia_scroll = HIGScrolledWindow() self.nokia_text = HIGTextView() def __packing(self): self.add(self.vbox) self.vbox.set_spacing(12) self.vbox._pack_expand_fill(self.notebook) self.vbox._pack_noexpand_nofill(self.hbox) 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.written_by_scroll.add(self.written_by_text) self.written_by_text.set_wrap_mode(gtk.WRAP_NONE) self.design_scroll.add(self.design_text) self.design_text.set_wrap_mode(gtk.WRAP_NONE) self.soc2007_scroll.add(self.soc2007_text) self.soc2007_text.set_wrap_mode(gtk.WRAP_NONE) self.contributors_scroll.add(self.contributors_text) self.contributors_text.set_wrap_mode(gtk.WRAP_NONE) self.translation_scroll.add(self.translation_text) self.translation_text.set_wrap_mode(gtk.WRAP_NONE) 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()) def set_text(self): b = self.written_by_text.get_buffer() b.set_text("""Adriano Monteiro Marques <*****@*****.**>""") b = self.design_text.get_buffer() b.set_text("""Operating System and Vulnerability Icons: Takeshi Alexandre Gondo <*****@*****.**> Logo, Application Icons and Splash screen: Virgílio Carlo de Menezes Vasconcelos <*****@*****.**> The Umit Project Web Site Design: Joao Paulo Pacheco <*****@*****.**>""") b = self.soc2007_text.get_buffer() b.set_text("""Independent Features: Adriano Monteiro Marques <*****@*****.**> Frederico Silva Ribeiro <*****@*****.**> Network Inventory: Guilherme Henrique Polo Gonçalves <*****@*****.**> Umit Radial Mapper: João Paulo de Souza Medeiros <*****@*****.**> Profile/Wizard interface editor: Luis Antonio Bastião Silva <*****@*****.**> NSE Facilitator: Maxim I. Gavrilov <*****@*****.**> Umit Web: Rodolfo da Silva Carvalho <*****@*****.**>""") b = self.contributors_text.get_buffer() b.set_text("""Sponsored by (SoC 2005, 2006 and 2007): Google <*****@*****.**> Mentor of Umit for Google SoC 2005 and 2006: Fyodor <*****@*****.**> Mentor of Umit for Google SoC 2007 Projects: Adriano Monteiro Marques <*****@*****.**> Initial development: Adriano Monteiro Marques <*****@*****.**> Cleber Rodrigues Rosa Junior <*****@*****.**> Nmap students from Google SoC 2007 that helped Umit: Eddie Bell <*****@*****.**> David Fifield <*****@*****.**> Kris Katterjohn <*****@*****.**> The Umit Project WebSite: AbraoBarbosa dos Santos Neto <*****@*****.**> Adriano Monteiro Marques <*****@*****.**> Heitor de Lima Matos <*****@*****.**> Joao Paulo Pacheco <*****@*****.**> João Paulo de Souza Medeiros <*****@*****.**> Luis Antonio Bastião Silva <*****@*****.**> Rodolfo da Silva Carvalho <*****@*****.**> Beta testers for 0.9.5RC1: Drew Miller <*****@*****.**> Igor Feghali <*****@*****.**> Joao Paulo Pacheco <*****@*****.**> Luis Antonio Bastião Silva <*****@*****.**> <*****@*****.**> <*****@*****.**> <*****@*****.**> Initial attempt on Maemo port: Adriano Monteiro Marques <*****@*****.**> Osvaldo Santana Neto <*****@*****.**>""") b = self.translation_text.get_buffer() b.set_text("""Brazilian Portuguese: Adriano Monteiro Marques <*****@*****.**>""") b = self.nokia_text.get_buffer() b.set_text("""Adriano Monteiro Marques <*****@*****.**>""")
class SearchWindow(BaseSearchWindow, object): def __init__(self, load_method, append_method): BaseSearchWindow.__init__(self) self.set_default_size(600, 400) self.load_method = load_method self.append_method = append_method self._create_widgets() self._pack_widgets() self._connect_widgets() def _create_widgets(self): self.vbox = HIGVBox() self.bottom_hbox = gtk.HBox() self.bottom_label = gtk.Label() self.btn_box = gtk.HButtonBox() self.btn_open = HIGButton(stock=gtk.STOCK_OPEN) self.btn_append = HIGButton(_("Append"), gtk.STOCK_ADD) self.btn_close = HIGButton(stock=gtk.STOCK_CLOSE) self.search_gui = SearchGUI(self) def _pack_widgets(self): BaseSearchWindow._pack_widgets(self) self.btn_box.set_layout(gtk.BUTTONBOX_END) self.btn_box.set_spacing(4) self.btn_box.pack_start(self.btn_close) self.btn_box.pack_start(self.btn_append) self.btn_box.pack_start(self.btn_open) self.bottom_label.set_alignment(0.0, 0.5) self.bottom_label.set_use_markup(True) self.bottom_hbox.set_spacing(4) self.bottom_hbox.pack_start(self.bottom_label, True) self.bottom_hbox.pack_start(self.btn_box, False) self.vbox.set_spacing(4) self.vbox.pack_start(self.search_gui, True, True) self.vbox.pack_start(self.bottom_hbox, False) self.add(self.vbox) def _connect_widgets(self): # Double click on result, opens it 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) self.btn_close.connect("clicked", self.close) self.connect("delete-event", self.close) def close(self, widget=None, event=None): self.search_gui.close() self.destroy() 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): # 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): # Append selected results self.append_method(self.results) # Close Search Window self.close() def get_results(self): # Return list with parsed objects from result list store return self.search_gui.selected_results results = property(get_results)
class ScanInterface(HIGVBox): """ScanInterface contains the scan toolbar and the scan results. Each ScanInterface represents a single NetworkInventory as well as a set of running scans.""" # The time delay between when you stop typing a filter string and filtering # actually begins, in milliseconds. FILTER_DELAY = 1000 def __init__(self): HIGVBox.__init__(self) # The borders are consuming too much space on Maemo. Setting it to # 0 pixels while on Maemo if is_maemo(): self.set_border_width(0) self.set_spacing(0) # True if nothing has happened here page yet, i.e., it's okay to load a # scan from a file here. self.empty = True # The most recent name the inventory on this page has been saved under. self.saved_filename = None # The network inventory shown by this page. It may consist of multiple # scans. self.inventory = FilteredNetworkInventory() # The list of currently running scans (NmapCommand objects). self.jobs = [] # The list of running and finished scans shown on the Nmap Output page. self.scans_store = ScansListStore() self.top_box = HIGVBox() self.__create_toolbar() self.__create_command_toolbar() self.select_default_profile() self.scan_result = ScanResult(self.inventory, self.scans_store, 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) 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) 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 # {'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', # 'service_method': u'probed', 'service_name': u'ssh', # 'service_product': u'OpenSSH', 'service_version': u'4.3'} # In other words each dict has the same keys as an entry in # HostInfo.ports, with the addition of "host" and "hostname" keys. self.services = {} self.top_box.set_border_width(6) self.top_box.set_spacing(5) self.top_box._pack_noexpand_nofill(self.toolbar) self.top_box._pack_noexpand_nofill(self.command_toolbar) 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.update_cancel_button() # Create the filter GUI self.filter_bar = FilterBar() self.pack_start(self.filter_bar, False, True, 0) self.filter_bar.set_no_show_all(True) self.filter_timeout_id = None self.filter_bar.connect("changed", self.filter_changed) self.scan_result.filter_toggle_button.connect( "toggled", self.filter_toggle_toggled) self.scan_result.filter_toggle_button.show() def toggle_filter_bar(self): self.scan_result.filter_toggle_button.clicked() def filter_toggle_toggled(self, widget): if self.scan_result.filter_toggle_button.get_active(): # Show the filter bar self.filter_bar.show() self.filter_bar.grab_focus() self.filter_hosts(self.filter_bar.get_filter_string()) else: # Hide the filter bar self.filter_bar.hide() self.filter_hosts("") self.update_ui() def filter_changed(self, filter_bar): # 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()) def filter_hosts(self, filter_string): start = time.clock() self.inventory.apply_filter(filter_string) filter_time = time.clock() - start # Update the gui start = time.clock() self.update_ui() gui_time = time.clock() - start if filter_time + gui_time > 0.0: log.debug( "apply_filter %g ms update_ui %g ms (%.0f%% filter)" % (filter_time * 1000.0, gui_time * 1000.0, 100.0 * filter_time / (filter_time + gui_time))) self.filter_timeout_id = None return False def is_changed(self): """Return true if this window has unsaved changes.""" for scan in self.inventory.get_scans(): if scan.unsaved: return True return False changed = property(is_changed) def num_scans_running(self): return len(self.jobs) def select_default_profile(self): """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) def go_to_host(self, hostname): """Scroll the text output to the appearance of the named host.""" self.scan_result.scan_result_notebook.nmap_output.nmap_output.go_to_host( hostname) # noqa def __create_toolbar(self): self.toolbar = ScanToolbar() 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.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_entry_changed_handler = \ self.command_toolbar.command_entry.connect( 'changed', self._command_entry_changed) def _command_entry_changed(self, editable): ops = NmapOptions() ops.parse_string(self.command_toolbar.get_command()) # Set the target and profile without propagating the "changed" signal # back to the command entry. self.set_target_quiet(join_quoted(ops.target_specs)) self.set_profile_name_quiet("") def _target_entry_changed(self, editable): target_string = self.toolbar.get_selected_target() targets = split_quoted(target_string) ops = NmapOptions() ops.parse_string(self.command_toolbar.get_command()) ops.target_specs = targets self.set_command_quiet(ops.render_string()) def _profile_entry_changed(self, widget): """Update the command based on the contents of the target and profile entries. If the command corresponding to the current profile is not blank, use it. Otherwise use the current contents of the command entry.""" profile_name = self.toolbar.get_selected_profile() target_string = self.toolbar.get_selected_target() cmd_profile = CommandProfile() command_string = cmd_profile.get_command(profile_name) del (cmd_profile) if command_string == "": command_string = self.command_toolbar.get_command() ops = NmapOptions() ops.parse_string(command_string) # Use the targets from the command entry, if there are any, otherwise # use any targets from the profile. targets = split_quoted(target_string) if len(targets) > 0: ops.target_specs = targets else: self.toolbar.set_selected_target(join_quoted(ops.target_specs)) self.set_command_quiet(ops.render_string()) 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.set_command(command_string) 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.set_selected_target(target_string) 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.set_selected_profile(profile_name) self.toolbar.profile_entry.handler_unblock( self.profile_entry_changed_handler) def start_scan_cb(self, widget=None): target = self.toolbar.selected_target command = self.command_toolbar.command profile = self.toolbar.selected_profile log.debug(">>> Start Scan:") log.debug(">>> Target: '%s'" % target) log.debug(">>> Profile: '%s'" % profile) log.debug(">>> Command: '%s'" % command) if target != '': try: self.toolbar.add_new_target(target) 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))) 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.run() warn_dialog.destroy() return self.execute_command(command, target, profile)
class SearchWindow(BaseSearchWindow, object): def __init__(self, load_method, append_method): BaseSearchWindow.__init__(self) self.set_default_size(600, 400) self.load_method = load_method self.append_method = append_method self._create_widgets() self._pack_widgets() self._connect_widgets() def _create_widgets(self): self.vbox = HIGVBox() self.bottom_hbox = gtk.HBox() self.bottom_label = gtk.Label() self.btn_box = gtk.HButtonBox() self.btn_open = HIGButton(stock=gtk.STOCK_OPEN) self.btn_append = HIGButton(_("Append"), gtk.STOCK_ADD) self.btn_close = HIGButton(stock=gtk.STOCK_CLOSE) self.search_gui = SearchGUI(self) def _pack_widgets(self): BaseSearchWindow._pack_widgets(self) self.btn_box.set_layout(gtk.BUTTONBOX_END) self.btn_box.set_spacing(4) self.btn_box.pack_start(self.btn_close) self.btn_box.pack_start(self.btn_append) self.btn_box.pack_start(self.btn_open) self.bottom_label.set_alignment(0.0, 0.5) self.bottom_label.set_use_markup(True) self.bottom_hbox.set_spacing(4) self.bottom_hbox.pack_start(self.bottom_label, True) self.bottom_hbox.pack_start(self.btn_box, False) self.vbox.set_spacing(4) self.vbox.pack_start(self.search_gui, True, True) self.vbox.pack_start(self.bottom_hbox, False) self.add(self.vbox) def _connect_widgets(self): # Double click on result, opens it 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) self.btn_close.connect("clicked", self.close) self.connect("delete-event", self.close) def close(self, widget=None, event=None): self.search_gui.close() self.destroy() 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): # 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): # Append selected results self.append_method(self.results) # Close Search Window self.close() def get_results(self): # Return list with parsed objects from result list store return self.search_gui.selected_results results = property(get_results)
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_position(gtk.WIN_POS_CENTER) self.__create_widgets() self.__packing() self.set_text() def __create_widgets(self): self.vbox = HIGVBox() self.hbox = HIGHBox() self.notebook = HIGNotebook() self.btn_close = HIGButton(stock=gtk.STOCK_CLOSE) self.written_by_scroll = HIGScrolledWindow() self.written_by_text = HIGTextView() self.design_scroll = HIGScrolledWindow() self.design_text = HIGTextView() self.soc2007_scroll = HIGScrolledWindow() self.soc2007_text = HIGTextView() self.contributors_scroll = HIGScrolledWindow() self.contributors_text = HIGTextView() self.translation_scroll = HIGScrolledWindow() self.translation_text = HIGTextView() self.nokia_scroll = HIGScrolledWindow() self.nokia_text = HIGTextView() def __packing(self): self.add(self.vbox) self.vbox.set_spacing(12) self.vbox._pack_expand_fill(self.notebook) self.vbox._pack_noexpand_nofill(self.hbox) 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.written_by_scroll.add(self.written_by_text) self.written_by_text.set_wrap_mode(gtk.WRAP_NONE) self.design_scroll.add(self.design_text) self.design_text.set_wrap_mode(gtk.WRAP_NONE) self.soc2007_scroll.add(self.soc2007_text) self.soc2007_text.set_wrap_mode(gtk.WRAP_NONE) self.contributors_scroll.add(self.contributors_text) self.contributors_text.set_wrap_mode(gtk.WRAP_NONE) self.translation_scroll.add(self.translation_text) self.translation_text.set_wrap_mode(gtk.WRAP_NONE) 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()) def set_text(self): b = self.written_by_text.get_buffer() b.set_text("""Adriano Monteiro Marques <*****@*****.**>""") b = self.design_text.get_buffer() b.set_text("""Operating System and Vulnerability Icons: Takeshi Alexandre Gondo <*****@*****.**> Logo, Application Icons and Splash screen: Virgílio Carlo de Menezes Vasconcelos <*****@*****.**> The Umit Project Web Site Design: Joao Paulo Pacheco <*****@*****.**>""") b = self.soc2007_text.get_buffer() b.set_text("""Independent Features: Adriano Monteiro Marques <*****@*****.**> Frederico Silva Ribeiro <*****@*****.**> Network Inventory: Guilherme Henrique Polo Gonçalves <*****@*****.**> Umit Radial Mapper: João Paulo de Souza Medeiros <*****@*****.**> Profile/Wizard interface editor: Luis Antonio Bastião Silva <*****@*****.**> NSE Facilitator: Maxim I. Gavrilov <*****@*****.**> Umit Web: Rodolfo da Silva Carvalho <*****@*****.**>""") b = self.contributors_text.get_buffer() b.set_text("""Sponsored by (SoC 2005, 2006 and 2007): Google <*****@*****.**> Mentor of Umit for Google SoC 2005 and 2006: Fyodor <*****@*****.**> Mentor of Umit for Google SoC 2007 Projects: Adriano Monteiro Marques <*****@*****.**> Initial development: Adriano Monteiro Marques <*****@*****.**> Cleber Rodrigues Rosa Junior <*****@*****.**> Nmap students from Google SoC 2007 that helped Umit: Eddie Bell <*****@*****.**> David Fifield <*****@*****.**> Kris Katterjohn <*****@*****.**> The Umit Project WebSite: AbraoBarbosa dos Santos Neto <*****@*****.**> Adriano Monteiro Marques <*****@*****.**> Heitor de Lima Matos <*****@*****.**> Joao Paulo Pacheco <*****@*****.**> João Paulo de Souza Medeiros <*****@*****.**> Luis Antonio Bastião Silva <*****@*****.**> Rodolfo da Silva Carvalho <*****@*****.**> Beta testers for 0.9.5RC1: Drew Miller <*****@*****.**> Igor Feghali <*****@*****.**> Joao Paulo Pacheco <*****@*****.**> Luis Antonio Bastião Silva <*****@*****.**> <*****@*****.**> <*****@*****.**> <*****@*****.**> Initial attempt on Maemo port: Adriano Monteiro Marques <*****@*****.**> Osvaldo Santana Neto <*****@*****.**>""") b = self.translation_text.get_buffer() b.set_text("""Brazilian Portuguese: Adriano Monteiro Marques <*****@*****.**>""") b = self.nokia_text.get_buffer() b.set_text("""Adriano Monteiro Marques <*****@*****.**>""")
class ProfileEditor(HIGWindow): 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')) self.set_position(gtk.WIN_POS_CENTER) self.deletable = deletable 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. self.inhibit_command_update = False self.__create_widgets() self.__pack_widgets() self.profile = CommandProfile() self.ops = NmapOptions() if profile_name: log.debug("Showing profile %s" % profile_name) prof = self.profile.get_profile(profile_name) # Interface settings self.profile_name_entry.set_text(profile_name) 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()) 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 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.update_command() def command_entry_changed_cb(self, widget): command_string = self.command_entry.get_text().decode("UTF-8") self.ops.parse_string(command_string) self.inhibit_command_update = True self.option_builder.update() self.inhibit_command_update = False def update_command(self): """Regenerate and display the command.""" if not self.inhibit_command_update: # Block recursive updating of the OptionBuilder widgets when they # 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) 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.") 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.") def __create_widgets(self): ### # Vertical box to keep 3 boxes self.main_whole_box = HIGVBox() self.upper_box = HIGHBox() self.middle_box = HIGHBox() self.lower_box = HIGHBox() #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.scan_button = HIGButton(_("Scan")) self.scan_button.connect("clicked", self.run_scan) self.notebook = gtk.Notebook() # Profile info page self.profile_info_vbox = HIGVBox() 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_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) # Buttons self.buttons_hbox = HIGHBox() self.cancel_button = HIGButton(stock=gtk.STOCK_CANCEL) self.cancel_button.connect('clicked', self.exit) self.delete_button = HIGButton(stock=gtk.STOCK_DELETE) self.delete_button.connect('clicked', self.delete_profile) self.save_button = HIGButton(_("Save Changes"), stock=gtk.STOCK_SAVE) self.save_button.connect('clicked', self.save_profile) ### self.help_vbox = HIGVBox() self.help_label = HIGSectionLabel(_('Help')) self.help_scroll = HIGScrolledWindow() self.help_scroll.set_border_width(0) self.help_field = HIGTextView() 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) ### def __pack_widgets(self): ### self.add(self.main_whole_box) # Packing command entry to upper box self.upper_box._pack_expand_fill(self.command_entry) self.upper_box._pack_noexpand_nofill(self.scan_button) # Packing notebook (left) and help box (right) to middle box self.middle_box._pack_expand_fill(self.notebook) self.middle_box._pack_expand_fill(self.help_vbox) # Packing buttons to lower box self.lower_box.pack_end(self.buttons_hbox) # Packing the three vertical boxes to the main box self.main_whole_box._pack_noexpand_nofill(self.upper_box) self.main_whole_box._pack_expand_fill(self.middle_box) 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.profile_info_vbox.set_border_width(5) table = HIGTable() self.profile_info_vbox._pack_noexpand_nofill(self.profile_info_label) self.profile_info_vbox._pack_expand_fill(HIGSpacer(table)) self.profile_description_scroll.add(self.profile_description_text) vbox_desc = HIGVBox() vbox_desc._pack_noexpand_nofill(self.profile_description_label) vbox_desc._pack_expand_fill(hig_box_space_holder()) 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) # Packing buttons on button_hbox self.buttons_hbox._pack_expand_fill(hig_box_space_holder()) if self.deletable: self.buttons_hbox._pack_noexpand_nofill(self.delete_button) self.buttons_hbox._pack_noexpand_nofill(self.cancel_button) self.buttons_hbox._pack_noexpand_nofill(self.save_button) self.buttons_hbox.set_border_width(5) self.buttons_hbox.set_spacing(6) ### self.help_vbox._pack_noexpand_nofill(self.help_label) self.help_vbox._pack_expand_fill(self.help_scroll) self.help_scroll.add(self.help_field) self.help_vbox.set_border_width(1) self.help_vbox.set_spacing(1) ### def __create_tab(self, tab_name, section_name, tab): 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 table = HIGTable() table.set_row_spacings(2) section = HIGSectionLabel(section_name) vbox._pack_noexpand_nofill(section) vbox._pack_noexpand_nofill(HIGSpacer(table)) vbox.set_border_width(5) tab.fill_table(table, True) else: hbox = tab.get_hmain_box() vbox.pack_start(hbox, True, True, 0) self.notebook.append_page(vbox, gtk.Label(tab_name)) def save_profile(self, widget): if self.overwrite: 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.run() alert.destroy() self.profile_name_entry.grab_focus() return None command = self.ops.render_string() buf = self.profile_description_text.get_buffer() description = buf.get_text(buf.get_start_iter(), buf.get_end_iter()) try: self.profile.add_profile(profile_name, 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.run() alert.destroy() return self.scan_interface.toolbar.profile_entry.update() self.destroy() def clean_profile_info(self): self.profile_name_entry.set_text('') self.profile_description_text.get_buffer().set_text('') def set_scan_interface(self, interface): self.scan_interface = interface def exit(self, *args): self.destroy() def delete_profile(self, widget=None, extra=None): 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! ClickOk to continue, ' 'or Cancel to go back to Profile Editor.')) hbox = HIGHBox() hbox.set_border_width(5) hbox.set_spacing(12) vbox = HIGVBox() vbox.set_border_width(5) vbox.set_spacing(12) image = gtk.Image() image.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) vbox.pack_start(alert) vbox.pack_start(text) hbox.pack_start(image) hbox.pack_start(vbox) dialog.vbox.pack_start(hbox) dialog.vbox.show_all() response = dialog.run() dialog.destroy() if response == gtk.RESPONSE_CANCEL: return True self.profile.remove_profile(self.profile_name) self.update_profile_entry() self.destroy() def run_scan(self, widget=None): command_string = self.command_entry.get_text().decode("UTF-8") self.scan_interface.command_toolbar.command = command_string self.scan_interface.start_scan_cb() self.exit() def update_profile_entry(self, widget=None, extra=None): self.scan_interface.toolbar.profile_entry.update() list = self.scan_interface.toolbar.profile_entry.get_model() length = len(list) if length > 0: self.scan_interface.toolbar.profile_entry.set_active(0)
class ProfileEditor(HIGWindow): def __init__(self, profile_name=None, deletable=True, overwrite=False): HIGWindow.__init__(self) self.connect("delete_event", self.exit) self.set_title(_('Profile Editor')) self.set_position(gtk.WIN_POS_CENTER) self.deletable = deletable self.profile_name = profile_name self.overwrite = overwrite self.__create_widgets() self.__pack_widgets() self.profile = CommandProfile() options_used = {} if profile_name: log.debug("Showing profile %s" % profile_name) prof = self.profile.get_profile(profile_name) options_used = prof['options'] # Interface settings self.profile_name_entry.set_text(profile_name) self.profile_description_text.get_buffer().set_text( prof['description']) self.constructor = CommandConstructor(options_used) ### self.profilehelp = ProfileHelp(options_used) ### self.options = OptionBuilder(Path.profile_editor, self.constructor, self.update_command, self.profilehelp) log.debug("Option groups: %s" % str(self.options.groups)) log.debug("Option section names: %s" % str(self.options.section_names)) #log.debug("Option tabs: %s" % str(self.options.tabs)) for tab in self.options.groups: self.__create_tab(tab, self.options.section_names[tab], self.options.tabs[tab]) self.update_command() def update_command(self): """Regenerate command with target '<target>' and set the value for the command entry""" self.command_entry.set_text(self.constructor.get_command('<target>')) ### whenever the command would be updated, thats when we update the help self.update_help() def update_help(self, text=None): helpText = self.help_field.get_buffer() if text: helpText.set_text(text) else: tempText = "" if self.profilehelp.get_currentstate() == "Default": helpText.set_text(" ") else: tempText += self.profilehelp.get_label() tempText += "\n\n" tempText += self.profilehelp.get_shortdesc() if self.profilehelp.get_example(): tempText += "\n\nExample input:\n" tempText += self.profilehelp.get_example() helpText.set_text(tempText) def update_help_name(self, widget, extra): self.update_help( 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.update_help( text="Description\n\nThe description is a" + " full description of what the scan does, which may be long.") def help(self, widget): d = HIGAlertDialog( parent=self, message_format=_("Help not implemented"), secondary_text=_("Profile editor help is not implemented yet.")) d.run() d.destroy() def __create_widgets(self): ### # Vertical box to keep 3 boxes self.main_whole_box = HIGVBox() self.upper_box = HIGVBox() self.middle_box = HIGHBox() self.lower_box = HIGHBox() #self.main_vbox = HIGVBox() self.command_expander = HIGExpander('<b>' + _('Command') + '</b>') self.command_expander.set_expanded(True) self.command_entry = gtk.Entry() self.command_entry.set_editable(False) self.notebook = gtk.Notebook() # Profile info page self.profile_info_vbox = HIGVBox() 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_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) # Buttons self.buttons_hbox = HIGHBox() self.help_button = HIGButton(stock=gtk.STOCK_HELP) self.help_button.connect('clicked', self.help) self.cancel_button = HIGButton(stock=gtk.STOCK_CANCEL) self.cancel_button.connect('clicked', self.exit) self.delete_button = HIGButton(stock=gtk.STOCK_DELETE) self.delete_button.connect('clicked', self.delete_profile) self.ok_button = HIGButton(stock=gtk.STOCK_OK) self.ok_button.connect('clicked', self.save_profile) ### self.help_vbox = HIGVBox() self.help_label = HIGSectionLabel(_('Help')) self.help_scroll = HIGScrolledWindow() self.help_scroll.set_border_width(0) self.help_field = HIGTextView() 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) ### def __pack_widgets(self): ### self.add(self.main_whole_box) # Packing command expander to upper box self.upper_box._pack_noexpand_nofill(self.command_expander) # Packing notebook (left) and help box (right) to middle box self.middle_box._pack_expand_fill(self.notebook) self.middle_box._pack_expand_fill(self.help_vbox) # Packing buttons to lower box self.lower_box.pack_end(self.buttons_hbox) # Packing the three vertical boxes to the main box self.main_whole_box._pack_noexpand_nofill(self.upper_box) self.main_whole_box._pack_noexpand_nofill(self.middle_box) self.main_whole_box._pack_noexpand_nofill(self.lower_box) ### # Packing command_entry on command_expander self.command_expander.hbox.pack_start(self.command_entry) # Packing profile information tab on notebook 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) self.profile_info_vbox._pack_expand_fill(HIGSpacer(table)) self.profile_description_scroll.add(self.profile_description_text) vbox_desc = HIGVBox() vbox_desc._pack_noexpand_nofill(self.profile_description_label) vbox_desc._pack_expand_fill(hig_box_space_holder()) 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) # Packing buttons on button_hbox #self.buttons_hbox.pack_start(self.help_button) self.buttons_hbox._pack_expand_fill(hig_box_space_holder()) if self.deletable: self.buttons_hbox._pack_noexpand_nofill(self.delete_button) self.buttons_hbox._pack_noexpand_nofill(self.cancel_button) self.buttons_hbox._pack_noexpand_nofill(self.ok_button) self.buttons_hbox.set_border_width(5) self.buttons_hbox.set_spacing(6) ### self.help_vbox._pack_noexpand_nofill(self.help_label) self.help_vbox._pack_expand_fill(self.help_scroll) self.help_scroll.add(self.help_field) self.help_vbox.set_border_width(1) self.help_vbox.set_spacing(1) ### def __create_tab(self, tab_name, section_name, tab): log.debug(">>> Tab name: %s" % tab_name) log.debug(">>>Creating profile editor section: %s" % section_name) vbox = HIGVBox() table = HIGTable() table.set_row_spacings(2) section = HIGSectionLabel(section_name) vbox._pack_noexpand_nofill(section) vbox._pack_noexpand_nofill(HIGSpacer(table)) vbox.set_border_width(5) tab.fill_table(table, True) self.notebook.append_page(vbox, gtk.Label(tab_name)) def save_profile(self, widget): if self.overwrite: 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.run() alert.destroy() self.profile_name_entry.grab_focus() return None command = self.constructor.get_command('%s') buf = self.profile_description_text.get_buffer() description = buf.get_text(buf.get_start_iter(),\ buf.get_end_iter()) self.profile.add_profile(profile_name,\ command=command,\ description=description,\ options=self.constructor.get_options()) self.scan_interface.toolbar.profile_entry.update() self.scan_interface.refresh_command(None) self.destroy() def clean_profile_info(self): self.profile_name_entry.set_text('') self.profile_description_text.get_buffer().set_text('') def set_scan_interface(self, interface): self.scan_interface = interface def exit(self, *args): self.destroy() def delete_profile(self, widget=None, extra=None): 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.')) hbox = HIGHBox() hbox.set_border_width(5) hbox.set_spacing(12) vbox = HIGVBox() vbox.set_border_width(5) vbox.set_spacing(12) image = gtk.Image() image.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) vbox.pack_start(alert) vbox.pack_start(text) hbox.pack_start(image) hbox.pack_start(vbox) dialog.vbox.pack_start(hbox) dialog.vbox.show_all() response = dialog.run() dialog.destroy() if response == gtk.RESPONSE_CANCEL: return True self.profile.remove_profile(self.profile_name) self.update_profile_entry() self.destroy() def update_profile_entry(self, widget=None, extra=None): self.scan_interface.toolbar.profile_entry.update() list = self.scan_interface.toolbar.profile_entry.get_model() length = len(list) if length > 0: self.scan_interface.toolbar.profile_entry.set_active(0)
class ScanHostsView(HIGVBox, object): HOST_MODE, SERVICE_MODE = range(2) def __init__(self, scan_interface): HIGVBox.__init__(self) self._scan_interface = scan_interface self._create_widgets() self._connect_widgets() self._pack_widgets() self._set_scrolled() self._set_host_list() self._set_service_list() self._pack_expand_fill(self.main_vbox) self.mode = None # Default mode is host mode self.host_mode(self.host_mode_button) self.host_view.show_all() self.service_view.show_all() def _create_widgets(self): # Mode buttons self.host_mode_button = gtk.ToggleButton(_("Hosts")) self.service_mode_button = gtk.ToggleButton(_("Services")) self.buttons_box = gtk.HBox() # Main window vbox self.main_vbox = HIGVBox() # Host list self.host_list = gtk.ListStore(object, str, str) self.host_list.set_sort_func(1000, cmp_treemodel_addr) self.host_list.set_sort_column_id(1000, gtk.SORT_ASCENDING) self.host_view = gtk.TreeView(self.host_list) self.pic_column = gtk.TreeViewColumn(_('OS')) self.host_column = gtk.TreeViewColumn(_('Host')) self.os_cell = gtk.CellRendererPixbuf() self.host_cell = gtk.CellRendererText() # Service list self.service_list = gtk.ListStore(str) self.service_list.set_sort_column_id(0, gtk.SORT_ASCENDING) self.service_view = gtk.TreeView(self.service_list) self.service_column = gtk.TreeViewColumn(_('Service')) self.service_cell = gtk.CellRendererText() self.scrolled = gtk.ScrolledWindow() def _pack_widgets(self): self.main_vbox.set_spacing(0) self.main_vbox.set_border_width(0) self.main_vbox._pack_noexpand_nofill(self.buttons_box) self.main_vbox._pack_expand_fill(self.scrolled) self.host_mode_button.set_active(True) self.buttons_box.set_border_width(5) self.buttons_box.pack_start(self.host_mode_button) self.buttons_box.pack_start(self.service_mode_button) def _connect_widgets(self): self.host_mode_button.connect("toggled", self.host_mode) self.service_mode_button.connect("toggled", self.service_mode) def host_mode(self, widget): self._remove_scrolled_child() if widget.get_active(): self.mode = self.HOST_MODE self.service_mode_button.set_active(False) self.scrolled.add(self.host_view) else: self.service_mode_button.set_active(True) def service_mode(self, widget): self._remove_scrolled_child() if widget.get_active(): self.mode = self.SERVICE_MODE self.host_mode_button.set_active(False) self.scrolled.add(self.service_view) else: self.host_mode_button.set_active(True) def _remove_scrolled_child(self): try: child = self.scrolled.get_child() self.scrolled.remove(child) except Exception: pass def _set_scrolled(self): self.scrolled.set_border_width(5) self.scrolled.set_size_request(150, -1) self.scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) def _set_service_list(self): self.service_view.set_enable_search(True) self.service_view.set_search_column(0) selection = self.service_view.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) self.service_view.append_column(self.service_column) self.service_column.set_resizable(True) self.service_column.set_sort_column_id(0) self.service_column.set_reorderable(True) self.service_column.pack_start(self.service_cell, True) self.service_column.set_attributes(self.service_cell, text=0) def _set_host_list(self): self.host_view.set_enable_search(True) self.host_view.set_search_column(1) selection = self.host_view.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) self.host_view.append_column(self.pic_column) self.host_view.append_column(self.host_column) self.host_column.set_resizable(True) self.pic_column.set_resizable(True) self.host_column.set_sort_column_id(1000) self.pic_column.set_sort_column_id(1) self.host_column.set_reorderable(True) self.pic_column.set_reorderable(True) self.pic_column.pack_start(self.os_cell, True) 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) def mass_update(self, hosts): """Update the internal ListStores to reflect the hosts and services passed in. Hosts that have not changed are left alone.""" hosts = set(hosts) services = set() for h in hosts: services.update([s["service_name"] for s in h.services]) # Disable sorting while elements are added. See the PyGTK FAQ 13.43, # "Are there tips for improving performance when adding many rows to a # Treeview?" sort_column_id = self.host_list.get_sort_column_id() self.host_list.set_default_sort_func(lambda *args: -1) self.host_list.set_sort_column_id(-1, gtk.SORT_ASCENDING) self.host_view.freeze_child_notify() self.host_view.set_model(None) it = self.host_list.get_iter_first() # Remove any of our ListStore hosts that aren't in the list passed in. while it: host = self.host_list.get_value(it, 0) if host in hosts: hosts.remove(host) self.host_list.set(it, 1, get_os_icon(host)) it = self.host_list.iter_next(it) else: if not self.host_list.remove(it): it = None # Add any remaining hosts into our ListStore. for host in hosts: self.add_host(host) # Reenable sorting. if sort_column_id != (None, None): self.host_list.set_sort_column_id(*sort_column_id) self.host_view.set_model(self.host_list) self.host_view.thaw_child_notify() it = self.service_list.get_iter_first() # Remove any of our ListStore services that aren't in the list passed # in. while it: service_name = self.service_list.get_value(it, 0) if service_name in services: services.remove(service_name) it = self.service_list.iter_next(it) else: if not self.service_list.remove(it): it = None # Add any remaining services into our ListStore. for service_name in services: self.add_service(service_name) def add_host(self, host): self.host_list.append([host, get_os_icon(host), host.get_hostname()]) def add_service(self, service): self.service_list.append([service])
class ScanHostsView(HIGVBox, object): def __init__(self, hosts={}, services={}): HIGVBox.__init__(self) self._create_widgets() self._connect_widgets() self._pack_widgets() self._set_scrolled() self._set_host_list(hosts) self._set_service_list(services) self._pack_expand_fill(self.main_vbox) # Default mode is host mode self.host_mode(self.host_mode_button) self.host_view.show_all() self.service_view.show_all() def _create_widgets(self): # Mode buttons self.host_mode_button = gtk.ToggleButton(_("Hosts")) self.service_mode_button = gtk.ToggleButton(_("Services")) self.buttons_box = gtk.HBox() # Main window vbox self.main_vbox = HIGVBox() # Host list self.host_list = gtk.ListStore(str, str) self.host_view = gtk.TreeView(self.host_list) self.pic_column = gtk.TreeViewColumn(_('OS')) self.host_column = gtk.TreeViewColumn(_('Host')) self.os_cell = gtk.CellRendererPixbuf() self.host_cell = gtk.CellRendererText() # Service list self.service_list = gtk.ListStore(str) self.service_view = gtk.TreeView(self.service_list) self.service_column = gtk.TreeViewColumn(_('Service')) self.service_cell = gtk.CellRendererText() self.scrolled = gtk.ScrolledWindow() def _pack_widgets(self): self.main_vbox.set_spacing(0) self.main_vbox.set_border_width(0) self.main_vbox._pack_noexpand_nofill(self.buttons_box) self.main_vbox._pack_expand_fill(self.scrolled) self.host_mode_button.set_active(True) self.buttons_box.set_border_width(5) self.buttons_box.pack_start(self.host_mode_button) self.buttons_box.pack_start(self.service_mode_button) def _connect_widgets(self): self.host_mode_button.connect("toggled", self.host_mode) self.service_mode_button.connect("toggled", self.service_mode) def host_mode(self, widget): self._remove_scrolled_child() if widget.get_active(): self.service_mode_button.set_active(False) self.scrolled.add(self.host_view) else: self.service_mode_button.set_active(True) def service_mode(self, widget): self._remove_scrolled_child() if widget.get_active(): self.host_mode_button.set_active(False) self.scrolled.add(self.service_view) else: self.host_mode_button.set_active(True) def _remove_scrolled_child(self): try: child = self.scrolled.get_child() self.scrolled.remove(child) except: pass def _set_scrolled(self): self.scrolled.set_border_width(5) self.scrolled.set_size_request(150, -1) self.scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) def _set_service_list(self, services): self.service_view.set_enable_search(True) self.service_view.set_search_column(0) selection = self.service_view.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) self.service_view.append_column(self.service_column) self.service_column.set_resizable(True) self.service_column.set_sort_column_id(0) self.service_column.set_reorderable(True) self.service_column.pack_start(self.service_cell, True) self.service_column.set_attributes(self.service_cell, text=0) self.set_services(services) def _set_host_list(self, hosts): self.host_view.set_enable_search(True) self.host_view.set_search_column(1) selection = self.host_view.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) self.host_view.append_column(self.pic_column) self.host_view.append_column(self.host_column) self.host_column.set_resizable(True) self.pic_column.set_resizable(True) self.host_column.set_sort_column_id(1) self.pic_column.set_sort_column_id(1) self.host_column.set_reorderable(True) self.pic_column.set_reorderable(True) self.pic_column.pack_start(self.os_cell, True) self.host_column.pack_start(self.host_cell, True) self.pic_column.set_attributes(self.os_cell, stock_id=0) self.pic_column.set_min_width(35) self.host_column.set_attributes(self.host_cell, text=1) self.set_hosts(hosts) def clear_host_list(self): for i in range(len(self.host_list)): iter = self.host_list.get_iter_root() del (self.host_list[iter]) def clear_service_list(self): for i in range(len(self.service_list)): iter = self.service_list.get_iter_root() del (self.service_list[iter]) def set_hosts(self, hosts): self.hosts = hosts self.clear_host_list() for host in hosts: self.host_list.append([hosts[host]['stock'], host]) def set_services(self, services): self.services = services self.clear_service_list() for service in services: self.service_list.append([service]) def add_host(self, host): for h in host: self.host_list.append([host[h]['stock'], h]) def add_service(self, service): if type(service) == type([]): for s in service: self.service_list.append([s]) elif type(service) in StringTypes: self.service_list.append([service]) def get_action(self, host): try: return self.hosts[host]['action'] except: return False