root/trunk/umit/gui/NmapOutputViewer.py @ 4476

Revision 4476, 16.2 kB (checked in by gpolo, 4 years ago)

Fixed ticket #259: Improved scroller handling for the nmap output
viewer.

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Copyright (C) 2005-2006 Insecure.Com LLC.
5# Copyright (C) 2007-2008 Adriano Monteiro Marques
6#
7# Author: Adriano Monteiro Marques <adriano@umitproject.org>
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
23import sys
24import gtk
25import gtk.gdk
26import pango
27import re
28
29from threading import Thread
30
31from higwidgets.higbuttons import HIGButton
32from higwidgets.higboxes import HIGVBox
33
34from umit.core.I18N import _, enc
35from umit.core.UmitLogging import log
36from umit.core.UmitConf import NmapOutputHighlight
37
38from umit.gui.NmapOutputProperties import NmapOutputProperties
39
40class NmapOutputViewer (HIGVBox):
41    def __init__ (self, refresh=1, stop=1):
42        self.nmap_highlight = NmapOutputHighlight()
43        HIGVBox.__init__ (self)
44       
45        # Creating widgets
46        self.__create_widgets()
47       
48        # Setting scrolled window
49        self.__set_scrolled_window()
50       
51        # Setting text view
52        self.__set_text_view()
53       
54        # Setting buttons
55        self.__set_buttons()
56       
57        # Getting text buffer
58        self.text_buffer = self.text_view.get_buffer()
59       
60        self.refreshing = True
61        self.thread = Thread()
62       
63        # Adding widgets to the VPaned
64        self._pack_expand_fill(self.scrolled)
65        self._pack_noexpand_nofill(self.hbox_buttons)
66       
67        self.nmap_output_file = None
68        self.nmap_previous_output = ''
69        self.brazil = True
70
71        # We have to create a mark to follow changes in the view with left grav.
72        self.mark = self.text_buffer.create_mark(
73            'start', 
74            self.text_buffer.get_start_iter(),
75            True
76        )
77       
78        self.__create_tags()
79
80
81    def __create_tags(self):
82        tag_table = self.text_buffer.get_tag_table()
83        tag_table.foreach(lambda tag, table: table.remove(tag), tag_table)
84       
85        properties = ["details",
86              "date",
87              "hostname",
88              "ip",
89              "port_list",
90              "open_port",
91              "closed_port",
92              "filtered_port"]
93       
94        for p in xrange(len(properties)):
95            settings = self.nmap_highlight.__getattribute__(properties[p])
96           
97            # Create a tag name
98            tag = gtk.TextTag(properties[p])
99               
100            if settings[0]:
101                tag.set_property("weight", pango.WEIGHT_HEAVY)
102            else:
103                tag.set_property("weight", pango.WEIGHT_NORMAL)
104               
105            if settings[1]:
106                tag.set_property("style", pango.STYLE_ITALIC)
107            else:
108                tag.set_property("style", pango.STYLE_NORMAL)
109           
110            if settings[2]:
111                tag.set_property("underline", pango.UNDERLINE_SINGLE)
112            else:
113                tag.set_property("underline", pango.UNDERLINE_NONE)
114
115            text_color = settings[3]
116            highlight_color = settings[4]
117
118            tag.set_property("foreground",
119gtk.color_selection_palette_to_string([gtk.gdk.Color(*text_color),]))
120            tag.set_property("background",
121gtk.color_selection_palette_to_string([gtk.gdk.Color(*highlight_color),]))
122
123            tag_table.add(tag)
124            tag.set_priority(p)
125       
126        # brasil tags
127        names = ('brasil1', 'brasil2', 'brasil3')
128        prop = ('foreground', 'background', 'weight')
129        values = (('#EAFF00', '#21C800', pango.WEIGHT_HEAVY),
130                  ('#0006FF', '#21C800', pango.WEIGHT_HEAVY),
131                  ('#FFFFFF', '#21C800', pango.WEIGHT_HEAVY))
132       
133        for i in xrange(len(names)):
134            tag = gtk.TextTag(names[i])
135            for tup in zip(prop, values[i]):
136                tag.set_property(tup[0], tup[1])
137            tag_table.add(tag)
138
139        self.txg_font = gtk.TextTag()
140        self.txg_date = gtk.TextTag()
141        self.txg_font.set_property("family", "Monospace")
142
143        tag_table.add(self.txg_font)
144        tag_table.add(self.txg_date)
145   
146    def __create_widgets (self):
147        # Creating widgets
148        self.scrolled = gtk.ScrolledWindow ()
149        self.text_view = gtk.TextView ()
150        self.btn_refresh = gtk.Button (stock=gtk.STOCK_REFRESH)
151        self.check_enable_color = gtk.CheckButton(\
152            _("Enable Nmap output highlight"))
153        self.btn_output_properties = HIGButton(stock=gtk.STOCK_PREFERENCES)
154        self.hbox_buttons = gtk.HBox (spacing=5)
155   
156    def __set_scrolled_window(self):
157        # By default the vertical scroller remains at bottom
158        self._scroll_at_bottom = True
159
160        # Seting scrolled window
161        self.scrolled.set_border_width(5)
162        self.scrolled.add(self.text_view)
163        self.scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
164        self.scrolled.set_size_request(450, 350)
165        vadjust = self.scrolled.get_vadjustment()
166        vadjust.connect('changed', self.__adjustment_update)
167        vadjust.connect('value-changed', self.__adjustment_at_bottom)
168
169    def __adjustment_at_bottom(self, adjustment):
170        print "update"
171        vadjust_end = adjustment.upper - adjustment.page_size
172        self._scroll_at_bottom = adjustment.value == vadjust_end
173
174    def __adjustment_update(self, adjustment):
175        if self._scroll_at_bottom:
176            adjustment.set_value(adjustment.upper - adjustment.page_size)
177
178    def __set_text_view(self):
179        self.text_view.set_wrap_mode(gtk.WRAP_WORD)
180        self.text_view.set_editable(False)
181       
182    def __set_buttons (self):
183        self.check_enable_color.set_active(self.nmap_highlight.enable)
184       
185        # Connecting events
186        self.btn_refresh.connect('clicked',
187                                 self.refresh_output)
188        self.btn_output_properties.connect("clicked",
189                                           self.show_output_properties)
190        self.check_enable_color.connect("toggled",
191                                        self.enable_color_highlight)
192       
193        # Setting hbox
194        self.hbox_buttons.set_border_width(5)
195       
196        # Packing buttons
197        self.hbox_buttons.pack_start(self.check_enable_color)
198        self.hbox_buttons.pack_start(self.btn_output_properties)
199        self.hbox_buttons.pack_start(self.btn_refresh)
200
201    def enable_color_highlight(self, widget):
202        if widget.get_active():
203            self.nmap_highlight.enable = 1
204        else:
205            self.nmap_highlight.enable = 0
206
207        self.update_output_colors()
208
209    def show_output_properties(self, widget):
210        nmap_out_prop = NmapOutputProperties(self.text_view)
211        nmap_out_prop.run()
212       
213        for prop in nmap_out_prop.property_names:
214            widget = nmap_out_prop.property_names[prop][8]
215
216            wid_props = []
217
218            if widget.bold:
219                wid_props.append(1)
220            else:
221                wid_props.append(0)
222
223            if widget.italic:
224                wid_props.append(1)
225            else:
226                wid_props.append(0)
227
228            if widget.underline:
229                wid_props.append(1)
230            else:
231                wid_props.append(0)
232 
233            wid_props.append("(%s, %s, %s)" % (widget.text_color.red,
234                                               widget.text_color.green,
235                                               widget.text_color.blue))
236            wid_props.append("(%s, %s, %s)" % (widget.highlight_color.red,
237                                               widget.highlight_color.green,
238                                               widget.highlight_color.blue))
239
240            self.nmap_highlight.__setattr__(widget.property_name, wid_props)
241           
242        nmap_out_prop.destroy()
243        self.nmap_highlight.save_changes()
244       
245        # TODO: Foreach in all tabs to update ?
246        self.__create_tags()
247
248        self.update_output_colors()
249   
250    def update_output_colors(self, dialog=None, response_id=None):
251        self.text_buffer.move_mark(self.mark, self.text_buffer.get_start_iter())
252
253        buff = self.text_view.get_buffer()
254        tag_table = buff.get_tag_table()
255       
256        # Get the not-parsed text
257        start = self.text_buffer.get_iter_at_mark(self.mark)
258        end = self.text_buffer.get_end_iter()
259       
260        self.text_buffer.remove_all_tags(start, end)
261        self.text_buffer.apply_tag(self.txg_font, start, end)
262       
263        if not self.nmap_highlight.enable or start == end:
264            return
265       
266        text = buff.get_text(start, end)
267       
268        # Get the line offset
269        offset = start.get_line()
270       
271        if text:
272            text = text.split("\n")
273            properties = ["details",
274                          "date",
275                          "hostname",
276                          "ip",
277                          "port_list",
278                          "open_port",
279                          "closed_port",
280                          "filtered_port"]
281           
282            for pos in xrange(len(text)):
283                if not text[pos]:
284                    continue
285               
286                for p in xrange(len(properties)):
287                    settings = self.nmap_highlight.__getattribute__(\
288                        properties[p])
289                    match = re.finditer(settings[5], text[pos])
290                   
291                    for m in match:
292                        buff.apply_tag(tag_table.lookup(properties[p]),
293                                       buff.get_iter_at_line_index(pos + offset,
294                                                                   m.start()),
295                                       buff.get_iter_at_line_index(pos + offset,
296                                                                   m.end()))
297                   
298                    tag1 = tag_table.lookup('brasil1')
299                    tag2 = tag_table.lookup('brasil2')
300                    tag3 = tag_table.lookup('brasil3')
301                   
302                    match = re.finditer("Bra[sz]il", text[pos])
303                   
304                    for m in match:
305                        buff.apply_tag(tag1,
306                                       buff.get_iter_at_line_index(pos + offset,
307                                                                   m.start()),
308                                       buff.get_iter_at_line_index(pos + offset,
309                                                                   m.end() - 5))
310
311                        buff.apply_tag(tag2,
312                                       buff.get_iter_at_line_index(pos + offset,
313                                                                m.start() + 1),
314                                       buff.get_iter_at_line_index(pos + offset,
315                                                                   m.end() -4))
316
317                        buff.apply_tag(tag3,
318                                       buff.get_iter_at_line_index(pos + offset,
319                                                                m.start() + 2),
320                                       buff.get_iter_at_line_index(pos + offset,
321                                                                   m.end() - 3))
322                       
323                        buff.apply_tag(tag1,
324                                       buff.get_iter_at_line_index(pos + offset,
325                                                                m.start() + 3),
326                                       buff.get_iter_at_line_index(pos + offset,
327                                                                   m.end() - 2))
328
329                        buff.apply_tag(tag2,
330                                       buff.get_iter_at_line_index(pos + offset,
331                                                                m.start() + 4),
332                                       buff.get_iter_at_line_index(pos + offset,
333                                                                   m.end() - 1))
334
335                        buff.apply_tag(tag3,
336                                       buff.get_iter_at_line_index(pos + offset,
337                                                                m.start() + 5),
338                                       buff.get_iter_at_line_index(pos + offset,
339                                                                   m.end()))
340                    else:
341                        self._brasil_log()
342                   
343                    match = re.finditer("BRT", text[pos])
344                   
345                    for m in match:
346                        buff.apply_tag(tag1,
347                                       buff.get_iter_at_line_index(pos + offset,
348                                                                   m.start()),
349                                       buff.get_iter_at_line_index(pos + offset,
350                                                                   m.end() - 2))
351
352                        buff.apply_tag(tag2,
353                                       buff.get_iter_at_line_index(pos + offset,
354                                                                m.start() + 1),
355                                       buff.get_iter_at_line_index(pos + offset,
356                                                                   m.end() -1))
357
358                        buff.apply_tag(tag3,
359                                       buff.get_iter_at_line_index(pos + offset,
360                                                                m.start() + 2),
361                                       buff.get_iter_at_line_index(pos + offset,
362                                                                   m.end()))
363                    else:
364                        self._brasil_log()
365                   
366        self.text_buffer.move_mark(self.mark, self.text_buffer.get_end_iter())
367
368    def _brasil_log(self):
369        if self.brazil:
370            log.info("Isto aqui, o o")
371            log.info("E um pouquinho de Brasil, io io")
372            log.info("Deste Brasil que canta e e feliz")
373            log.info("Feliz, feliz")
374            log.info("")
375            log.info("E tambem um pouco de uma raca")
376            log.info("Que nao tem medo de fumaca ai, ai")
377            log.info("E nao se entrega, nao ")
378            log.info("")
379            log.info('Olha o jeito das "cadera"  que ela sabe dar')
380            log.info("Olha o tombo nos quadris que ela sabe dar")
381            log.info("Olha o passe de batuque que ela sabe dar")
382            log.info("Olha so o remelexo que ela sabe dar")
383            log.info("")
384            log.info("Morena boa me faz chorar")
385            log.info("Poe a sandalia de prata")
386            log.info("e vem pro samba sambar")
387           
388            self.brazil = False
389   
390    def show_nmap_output(self, file):
391        self.nmap_output_file = file
392        self.text_buffer.set_text("")
393        self.refresh_output()
394
395    def refresh_output(self, widget=None):
396        log.debug("Refresh nmap output")
397
398        if self.nmap_output_file is not None:
399            nmap_of = open(self.nmap_output_file, "r")
400
401            new_output = nmap_of.read()
402
403            if self.nmap_previous_output != new_output:
404                # Setting text and moving mark to the start
405                # to update_colors correctly
406                text_prev_len = len(self.nmap_previous_output)
407
408                self.text_buffer.insert(
409                        self.text_buffer.get_end_iter(),
410                        enc(new_output[text_prev_len:]))
411
412                self.nmap_previous_output = new_output
413
414                self.update_output_colors()
415
416            nmap_of.close()
417
418
419if __name__ == '__main__':
420    w = gtk.Window()
421    n = NmapOutputViewer()
422    w.add(n)
423    w.show_all()
424    w.connect('delete-event', lambda x,y,z=None:gtk.main_quit())
425
426    buff = n.text_view.get_buffer()
427    buff.set_text(open("file_with_encoding_issues.txt", 'rb').read())
428
429    gtk.main()
Note: See TracBrowser for help on using the browser.