def __init__(self): gtk.VBox.__init__(self, False, 2) self.entry = FilterEntry() self.tree = AuditOutputTree() self.toolbar = gtk.Toolbar() self.toolbar.set_style(gtk.TOOLBAR_ICONS) action = gtk.Action('save', _('Save log'), _('Save log to file'), gtk.STOCK_SAVE) action.connect('activate', self.tree.on_save_log) item = action.create_tool_item() self.toolbar.insert(item, -1) item = gtk.ToolItem() item.add(self.entry) item.set_expand(True) self.toolbar.insert(item, -1) self.pack_start(self.toolbar, False, False) self.pack_end(self.tree) self.entry.get_entry().connect('changed', self.__on_filter)
class AuditOutput(gtk.VBox): def __init__(self): gtk.VBox.__init__(self, False, 2) self.entry = FilterEntry() self.tree = AuditOutputTree() self.toolbar = gtk.Toolbar() self.toolbar.set_style(gtk.TOOLBAR_ICONS) action = gtk.Action('save', _('Save log'), _('Save log to file'), gtk.STOCK_SAVE) action.connect('activate', self.tree.on_save_log) item = action.create_tool_item() self.toolbar.insert(item, -1) item = gtk.ToolItem() item.add(self.entry) item.set_expand(True) self.toolbar.insert(item, -1) self.pack_start(self.toolbar, False, False) self.pack_end(self.tree) self.entry.get_entry().connect('changed', self.__on_filter) def __on_filter(self, widget): self.tree.filter(widget.get_text())
def __create_toolbar(self): self.toolbar = gtk.Toolbar() self.toolbar.set_style(gtk.TOOLBAR_ICONS) stocks = ( gtk.STOCK_REFRESH, gtk.STOCK_MEDIA_STOP, gtk.STOCK_NETWORK ) callbacks = ( self.__on_restart, self.__on_stop, self.__on_reorder ) tooltips = ( _('Restart capturing'), _('Stop capturing'), _('Reorder flow') ) for tooltip, stock, callback in zip(tooltips, stocks, callbacks): action = gtk.Action(None, None, tooltip, stock) action.connect('activate', callback) self.toolbar.insert(action.create_tool_item(), -1) self.filter = FilterEntry() item = gtk.ToolItem() item.add(self.filter) item.set_expand(True) self.toolbar.insert(item, -1) self.pack_start(self.toolbar, False, False)
class SniffPage(Perspective): COL_NO = 0 COL_TIME = 1 COL_SRC = 2 COL_DST = 3 COL_PROTO = 4 COL_INFO = 5 COL_COLOR = 6 COL_OBJECT = 7 icon = 'sniff_small' title = _('Sniff perspective') COLORS = ( gtk.gdk.color_parse('#FFFA99'), gtk.gdk.color_parse('#8DFF7F'), gtk.gdk.color_parse('#FFE3E5'), gtk.gdk.color_parse('#C797FF'), gtk.gdk.color_parse('#A0A0A0'), gtk.gdk.color_parse('#D6E8FF'), gtk.gdk.color_parse('#C2C2FF'), ) def create_ui(self): self.use_colors = True self.set_border_width(2) self.__create_toolbar() self.__create_view() self.statusbar = HIGAnimatedBar('', gtk.STOCK_INFO) self.pack_start(self.statusbar, False, False) self.show_all() Prefs()['gui.maintab.sniffview.font'].connect(self.__modify_font) Prefs()['gui.maintab.sniffview.usecolors'].connect(self.__modify_colors) self.tree.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.tree.get_selection().connect('changed', self.__on_selection_changed) self.filter.get_entry().connect('activate',self.__on_apply_filter) self.tree.connect('button-press-event', self.__on_popup) self.connect('realize', self.__on_realize) self.timeout_id = None self.reload() def __on_realize(self, window): self.tree.set_model(self.list_store) def __create_toolbar(self): self.toolbar = gtk.Toolbar() self.toolbar.set_style(gtk.TOOLBAR_ICONS) stocks = ( gtk.STOCK_REFRESH, gtk.STOCK_MEDIA_STOP, gtk.STOCK_NETWORK ) callbacks = ( self.__on_restart, self.__on_stop, self.__on_reorder ) tooltips = ( _('Restart capturing'), _('Stop capturing'), _('Reorder flow') ) for tooltip, stock, callback in zip(tooltips, stocks, callbacks): action = gtk.Action(None, None, tooltip, stock) action.connect('activate', callback) self.toolbar.insert(action.create_tool_item(), -1) self.filter = FilterEntry() item = gtk.ToolItem() item.add(self.filter) item.set_expand(True) self.toolbar.insert(item, -1) self.pack_start(self.toolbar, False, False) def __create_view(self): sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) # We have to create two seperate objects if we want to have more # performance while sniffing. We'll use the tree_store only for # reflowing without a model filter. self.tree_store = gtk.TreeStore(object) self.list_store = gtk.ListStore(object) self.active_model = self.list_store self.tree = gtk.TreeView(self.active_model) self.active_filter = None self.model_filter = self.list_store.filter_new() self.model_filter.set_visible_func(self.__filter_func) idx = 0 rend = GridRenderer() rend.set_property('ellipsize', pango.ELLIPSIZE_END) columns_str = Prefs()['gui.maintab.sniffview.columns'].value for column_str in columns_str.split(','): try: label, pixel_size, eval_str = column_str.split('|', 2) pixel_size = int(pixel_size) if eval_str[-1] != '%' or eval_str[0] != '%': continue eval_str = eval_str[1:-1] col = gtk.TreeViewColumn(label, rend) col.set_min_width(pixel_size) col.set_fixed_width(pixel_size) col.set_resizable(True) if eval_str == 'number': col.set_cell_data_func(rend, self.__cell_data_number) else: func = getattr(MetaPacket, eval_str, None) or \ getattr(MetaPacket, 'get_' + eval_str, None) if not func: col.set_cell_data_func(rend, self.__cell_data_cfield, eval_str) else: col.set_cell_data_func(rend, self.__cell_data_func, func) self.tree.insert_column(col, idx) idx += 1 except Exception: pass # Set the fixed height mode property to True to speeds up self.tree.set_fixed_height_mode(True) sw.add(self.tree) self.pack_start(sw) def __cell_data_number(self, col, cell, model, iter): packet = model.get_value(iter, 0) cell.set_property('text', "%s)" % ".".join( [str(i + 1) \ for i in model.get_path(iter)] )) cell.set_property('cell-background-gdk', self.__get_color(packet)) def __cell_data_cfield(self, col, cell, model, iter, cfield): packet = model.get_value(iter, 0) data = packet.cfields.get(cfield, '') if isinstance(data, basestring): cell.set_property('text', data) else: cell.set_property('text', None) cell.set_property('cell-background-gdk', self.__get_color(packet)) def __cell_data_func(self, col, cell, model, iter, func): packet = model.get_value(iter, 0) data = func(packet) if isinstance(data, basestring): cell.set_property('text', data) else: cell.set_property('text', None) cell.set_property('cell-background-gdk', self.__get_color(packet)) def __modify_font(self, font): try: desc = pango.FontDescription(font) for col in self.tree.get_columns(): for rend in col.get_cell_renderers(): rend.set_property('font-desc', desc) self.__redraw_rows() except: # Block change return True def __modify_colors(self, value): self.use_colors = value self.tree.set_rules_hint(not self.use_colors) self.__redraw_rows() def __redraw_rows(self): #def emit_row_changed(model, path, iter): # model.row_changed(path, iter) #self.active_model.foreach(emit_row_changed) # Queue draw should be enough here self.queue_draw() def __get_color(self, packet): if self.use_colors: proto = packet.get_protocol_str() return self.COLORS[hash(proto) % len(self.COLORS)] else: return None def __update_tree(self): if isinstance(self.session.context, SniffContext): self.session.context.check_finished() self.tree.freeze_child_notify() for packet in self.session.context.get_data(): self.list_store.append([packet]) #while gtk.events_pending(): # gtk.main_iteration_do() self.tree.thaw_child_notify() # TODO: better handle the situation. if getattr(self.session.context, 'auto_scroll', True) and \ len(self.active_model) > 0: self.tree.scroll_to_cell(len(self.active_model) - 1) alive = self.session.context.is_alive() if not alive: self.statusbar.label = "<b>%s</b>" % self.session.context.summary self.statusbar.image = gtk.STOCK_INFO self.statusbar.show() return alive # Public functions def clear(self): self.tree_store.clear() self.list_store.clear() # Maybe we have to switch back to list store mode? def redraw(self, packet=None): model, lst = self.tree.get_selection().get_selected_rows() for idx in lst: iter = model.get_iter(lst[0]) model.row_changed(idx, iter) def reload(self): for packet in self.session.context.get_data(): self.list_store.append([packet]) while gtk.events_pending(): gtk.main_iteration_do() self.statusbar.label = "<b>%s</b>" % self.session.context.summary if self.timeout_id: gobject.source_remove(self.timeout_id) if isinstance(self.session.context, backend.TimedContext) and \ self.session.context.state != self.session.context.NOT_RUNNING: self.timeout_id = gobject.timeout_add(300, self.__update_tree) # Signals callbacks def __on_selection_changed(self, selection): model, lst = selection.get_selected_rows() # Only if i have one row selected if len(lst) == 1: iter = model.get_iter(lst[0]) self.session.set_active_packet(model.get_value(iter, 0)) else: self.session.set_active_packet(None) def __on_popup(self, tree, evt): if evt.button != 3: return model, lst = self.tree.get_selection().get_selected_rows() if not lst: return menu = gtk.Menu() labels = (_('Create a sequence'), _('Save selected')) stocks = (gtk.STOCK_INDEX, gtk.STOCK_SAVE_AS) callbacks = (self.__on_create_seq, self.__on_save_selection) for lbl, stock, cb in zip(labels, stocks, callbacks): action = gtk.Action(None, lbl, None, stock) action.connect('activate', cb) menu.append(action.create_menu_item()) menu.show_all() menu.popup(None, None, None, evt.button, evt.time) return True def get_selected_packets(self, tree=False): """ @return a list or a Tree contanining the selected packets """ if tree: node = Node() def add_to_tree(model, path, iter, tree): obj = copy.deepcopy(model.get_value(iter, 0)) parent = model.iter_parent(iter) if not parent: tree.append_node(Node(obj)) else: path = tree.find(model.get_value(parent, 0)) if not path: tree.append_node(Node(obj)) else: node = tree.get_from_path(path) node.append_node(Node(obj)) self.tree.get_selection().selected_foreach(add_to_tree, node) for child in node: child.data = backend.SequencePacket(child.data) return node else: ret = [] model, lst = self.tree.get_selection().get_selected_rows() for path in lst: ret.append(model.get_value(model.get_iter(path), 0)) return ret def __on_create_seq(self, action): ServiceBus().call('pm.sessions', 'create_sequence_session', self.get_selected_packets(True)) def __on_save_selection(self, action): dialog = self.session.create_save_dialog() if dialog.run() == gtk.RESPONSE_ACCEPT: ctx = backend.StaticContext('', dialog.get_filename()) ctx.data = self.get_selected_packets() if ctx.save(): self.statusbar.image = gtk.STOCK_HARDDISK self.statusbar.label = \ _('<b>%d selected packets saved to %s</b>') % \ (len(ctx.data), ctx.cap_file) else: self.statusbar.image = gtk.STOCK_DIALOG_ERROR self.statusbar.label = "<b>%s</b>" % ctx.summary self.statusbar.start_animation(True) dialog.hide() dialog.destroy() def __on_reorder(self, action): if isinstance(self.session.context, backend.TimedContext): if self.session.context.state == self.session.context.NOT_RUNNING: packets = self.session.context.get_all_data() else: self.statusbar.label = \ _('<b>Cannot reorganize the flow while sniffing</b>') self.statusbar.start_animation(True) return elif isinstance(self.session.context, backend.StaticContext): packets = self.session.context.get_data() else: return tree = backend.analyze_connections(packets) if tree: self.tree_store.clear() for (root, lst) in tree: iter = self.tree_store.append(None, [root]) for child in lst: self.tree_store.append(iter, [child]) self._switch_model(self.tree_store) def _switch_model(self, model): """ Switch to the new model and reset the filter """ if self.active_model is not model: self.active_model = model self.model_filter = model.filter_new() self.model_filter.set_visible_func(self.__filter_func) if self.active_filter: self.model_filter.refilter() self.tree.set_model(self.model_filter) elif self.tree.get_model() is not model: self.tree.set_model(model) def __on_apply_filter(self, entry): self.active_filter = self.filter.get_text() or None self._switch_model(self.active_model) def __filter_func(self, model, iter): if not self.active_filter: return True packet = model.get_value(iter, 0) if not packet: return False strs = ( str(model.get_path(iter)[0] + 1), packet.get_time(), packet.get_source(), packet.get_dest(), packet.get_protocol_str(), packet.summary() ) # TODO: implement a search engine like num: summary: ? for pattern in strs: if self.active_filter in pattern: return True return False def __on_stop(self, action): self.session.context.stop() def __on_restart(self, action): self.session.context.restart()