root/trunk/umitGUI/MainWindow.py @ 1242

Revision 1242, 31.2 kB (checked in by boltrix, 6 years ago)

Approach on solving Bug #1750194. While running on python versions lower than 2.5 webbrowser.open won't be called with the new=2 parameter.

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (C) 2005 Insecure.Com LLC.
5#
6# Author: Adriano Monteiro Marques <py.adriano@gmail.com>
7#         Cleber Rodrigues <cleber.gnu@gmail.com>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23import gtk
24
25import sys
26import os
27import os.path
28
29from types import StringTypes
30from time import time
31from tempfile import mktemp
32
33from higwidgets.higwindows import HIGMainWindow
34from higwidgets.higdialogs import HIGDialog, HIGAlertDialog
35from higwidgets.higlabels import HIGEntryLabel
36from higwidgets.higboxes import HIGHBox, HIGVBox
37
38from umitGUI.FileChoosers import ResultsFileChooserDialog, SaveResultsFileChooserDialog
39from umitGUI.ScanNotebook import ScanNotebook, ScanNotebookPage
40from umitGUI.ProfileEditor import ProfileEditor
41from umitGUI.Wizard import Wizard
42from umitGUI.About import About
43from umitGUI.DiffCompare import DiffWindow
44from umitGUI.SearchWindow import SearchWindow
45from umitGUI.BugReport import BugReport
46
47from umitCore.Paths import Path
48from umitCore.Logging import log
49from umitCore.I18N import _
50from umitCore.UmitOptionParser import option_parser
51from umitCore.UmitConf import SearchConfig, is_maemo
52from umitCore.UmitDB import Scans, UmitDB
53
54root = False
55try:
56    if sys.platform == 'win32':
57        root = True
58    elif is_maemo():
59        root = True
60    elif os.getuid() == 0:
61        root = True
62except: pass
63
64
65UmitMainWindow = None
66hildon = None
67
68if is_maemo():
69    import hildon
70    class UmitMainWindow(hildon.Window):
71        def __init__(self):
72            hildon.Window.__init__(self)
73            self.set_resizable(False)
74            self.set_border_width(0)
75            self.vbox = gtk.VBox()
76            self.vbox.set_border_width(0)
77            self.vbox.set_spacing(0)
78
79else:
80    class UmitMainWindow(HIGMainWindow):
81        def __init__(self):
82            HIGMainWindow.__init__(self)
83            self.vbox = gtk.VBox()
84
85
86class MainWindow(UmitMainWindow):
87    def __init__(self):
88        UmitMainWindow.__init__(self)
89        self.set_title(_("Umit"))
90
91        self._icontheme = gtk.IconTheme()
92        self.main_accel_group = gtk.AccelGroup()
93       
94        self.add_accel_group(self.main_accel_group)
95       
96        self.add(self.vbox)
97       
98        self.connect ('delete-event', self._exit_cb)
99        self._create_ui_manager()
100        self._create_menubar()
101        self._create_toolbar()
102        self._create_scan_notebook()
103        self._verify_root()
104       
105        # These dialogs should be instanciated on demand
106        # Unfortunately, due to a GTK bug on the filefilters (or our own
107        # stupidity), we are creating/destroying them at each callback
108        # invocation. sigh.
109        self._profile_filechooser_dialog = None
110        self._results_filechooser_dialog = None
111
112        # Loading files passed as argument
113        files = option_parser.get_open_results()
114        if len(files) >= 1:
115            for file in files:
116                self._load(filename=file)
117
118    def configure_focus_chain(self):
119        self.vbox.set_focus_chain()
120
121    def _verify_root(self):
122        if not root:
123            non_root = NonRootWarning()
124
125    def _create_ui_manager(self):
126        self.ui_manager = gtk.UIManager()
127       
128        # See info on ActionGroup at:
129        # * http://www.pygtk.org/pygtk2reference/class-gtkactiongroup.html
130        # * http://www.gtk.org/api/2.6/gtk/GtkActionGroup.html
131        self.main_action_group = gtk.ActionGroup('MainActionGroup')
132       
133        # See info on Action at:
134        # * http://www.pygtk.org/pygtk2reference/class-gtkaction.html
135        # * http://www.gtk.org/api/2.6/gtk/GtkAction.html
136       
137        # Each action tuple can go from 1 to six fields, example:
138        # ('Open Scan Results',      -> Name of the action
139        #   gtk.STOCK_OPEN,          ->
140        #   _('_Open Scan Results'), ->
141        #   None,
142        #   _('Open the results of a previous scan'),
143        #   lambda x: True)
144       
145        about_icon = None
146        try: about_icon = gtk.STOCK_ABOUT
147        except: pass
148       
149        self.main_actions = [ \
150            # Top level
151            ('Scan', None, _('Sc_an'), None), 
152           
153            ('Wizard',
154                gtk.STOCK_CONVERT,
155                _('_Command Wizard'),
156                '<Control>i',
157                _('Open nmap command constructor wizard'),
158                self._wizard_cb),
159           
160            ('Save Scan',
161                gtk.STOCK_SAVE,
162                _('_Save Scan'),
163                None,
164                _('Save current scan results'),
165                self._save_scan_results_cb),
166           
167            ('Open Scan',
168                gtk.STOCK_OPEN,
169                _('_Open Scan'),
170                None,
171                _('Open the results of a previous scan'),
172                self._load_scan_results_cb),
173                   
174           
175            ('Tools', None, _('_Tools'), None), 
176           
177            ('New Scan',
178                gtk.STOCK_NEW,
179                _('_New Scan'),
180                "<Control>T",
181                _('Create a new Scan Tab'),
182                self._new_scan_cb),
183           
184            ('Close Scan',
185                gtk.STOCK_CLOSE,
186                _('Close Scan'),
187                "<Control>w",
188                _('Close current scan tab'),
189                self._close_scan_cb),
190           
191            ('New Profile',
192                gtk.STOCK_JUSTIFY_LEFT,
193                _('New _Profile'),
194                '<Control>p',
195                _('Create a new scan profile'),
196                self._new_scan_profile_cb),
197
198            ('Search Scan',
199                gtk.STOCK_FIND,
200                _('Search Scan Results'),
201                '<Control>f',
202                _('Search for a scan result'),
203                self._search_scan_result),
204           
205            ('Edit Profile',
206                gtk.STOCK_PROPERTIES,
207                _('_Edit Selected Profile'),
208                '<Control>e',
209                _('Edit selected scan profile'),
210                self._edit_scan_profile_cb),
211           
212            ('New Profile with Selected',
213                gtk.STOCK_PROPERTIES,
214                _('New P_rofile with Selected'),
215                '<Control>r',
216                _('Use the selected scan profile to create another'),
217                self._new_scan_profile_with_selected_cb),
218           
219            ('Quit',
220                gtk.STOCK_QUIT,
221                _('_Quit'),
222                None,
223            _('Quit this application'),
224                self._exit_cb),
225           
226           
227            # Top Level
228            ('Profile', None, _('_Profile'), None),
229           
230            ('Compare Results',
231                gtk.STOCK_DND_MULTIPLE,
232                _('Compare Results'),
233                "<Control>D",
234                _('Compare Scan Results using Diffies'),
235                self._load_diff_compare_cb),
236           
237           
238            # Top Level
239            ('Help', None, _('_Help'), None),
240
241            ('Report a bug',
242                gtk.STOCK_DIALOG_INFO,
243                _('_Report a bug'),
244                '<Control>b',
245                _("Report a bug"),
246                self._show_bug_report
247                ),
248           
249            ('About',
250                about_icon,
251                _('_About'),
252                '<Control>a',
253                _("About UMIT"),
254                self._show_about_cb
255                ),
256           
257            ('Show Help',
258                gtk.STOCK_HELP,
259                _('_Help'),
260                None,
261                _('Shows the application help'),
262                self._show_help),
263            ]
264       
265        # See info on UIManager at:
266        # * http://www.pygtk.org/pygtk2reference/class-gtkuimanager.html       
267        # * http://www.gtk.org/api/2.6/gtk/GtkUIManager.html
268       
269        # UIManager supports UI "merging" and "unmerging". So, suppose there's
270        # no scan running or scan results opened, we should have a minimal
271        # interface. When we one scan running, we should "merge" the scan UI.
272        # When we get multiple tabs opened, we might merge the tab UI.
273       
274        # This is the default, minimal UI
275        self.default_ui = """<menubar>
276        <menu action='Scan'>
277            <menuitem action='New Scan'/>
278            <menuitem action='Close Scan'/>
279            <menuitem action='Save Scan'/>
280            <menuitem action='Open Scan'/>
281             %s
282            <menuitem action='Quit'/>
283        </menu>
284
285        <menu action='Tools'>
286            <menuitem action='Wizard'/>
287            <menuitem action='Compare Results'/>
288            <menuitem action='Search Scan'/>
289         </menu>
290       
291        <menu action='Profile'>
292            <menuitem action='New Profile'/>
293            <menuitem action='New Profile with Selected'/>
294            <menuitem action='Edit Profile'/>
295        </menu>
296       
297        <menu action='Help'>
298            <menuitem action='Show Help'/>
299            <menuitem action='Report a bug'/>
300            <menuitem action='About'/>
301        </menu>
302       
303        </menubar>
304       
305        <toolbar>
306            <toolitem action='New Scan'/>
307            <toolitem action='Wizard'/>
308            <toolitem action='Save Scan'/>
309            <toolitem action='Open Scan'/>
310            <separator/>
311            <toolitem action='Report a bug'/>
312            <toolitem action='Show Help'/>
313        </toolbar>
314        """
315       
316        self.get_recent_scans()
317       
318        self.main_action_group.add_actions(self.main_actions)
319       
320        for action in self.main_action_group.list_actions():
321            action.set_accel_group(self.main_accel_group)
322            action.connect_accelerator()
323       
324        self.ui_manager.insert_action_group(self.main_action_group, 0)
325        self.ui_manager.add_ui_from_string(self.default_ui)
326
327    def _show_bug_report(self, widget):
328        bug = BugReport()
329        bug.show_all()
330
331    def _search_scan_result(self, widget):
332        search_window = SearchWindow(self._load_search_result)
333        search_window.show_all()
334
335    def _load_search_result(self, results):
336        for result in results:
337            page = self._load(parsed_result=results[result][1],
338                              title=results[result][1].scan_name)
339            page.status.set_search_loaded()
340
341    def _close_scan_cb(self, widget, data=None):
342        # data can be none, if the current page is to be closed
343        if data == None:
344            page_num = self.scan_notebook.get_current_page()
345        # but can also be this page's content, which will be used
346        # to find this page number
347        else:
348            page_num = self.scan_notebook.page_num(data)
349        page = self.scan_notebook.get_nth_page(page_num)
350        filename = None
351       
352        if page.status.unsaved_unchanged \
353               or page.status.unsaved_changed\
354               or page.status.loaded_changed:
355           
356            log.debug("Found changes on closing tab")
357            dialog = HIGDialog(buttons=(gtk.STOCK_SAVE, gtk.RESPONSE_OK,
358                            _('Close anyway'), gtk.RESPONSE_CLOSE,
359                            gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
360           
361            title = self.scan_notebook.get_tab_title(page)
362           
363            alert = None
364            if title:
365                alert = HIGEntryLabel('<b>%s "%s"</b>' % (_("Save changes on"), title))
366            else:
367                alert = HIGEntryLabel('<b>%s</b>' % _("Save changes"))
368           
369            text = HIGEntryLabel(_('The given scan has unsaved changes.\n\
370What do you want to do?'))
371            hbox = HIGHBox()
372            hbox.set_border_width(5)
373            hbox.set_spacing(12)
374           
375            vbox = HIGVBox()
376            vbox.set_border_width(5)
377            vbox.set_spacing(12)
378           
379            image = gtk.Image()
380            image.set_from_stock(gtk.STOCK_DIALOG_QUESTION,gtk.ICON_SIZE_DIALOG)
381           
382            vbox.pack_start(alert)
383            vbox.pack_start(text)
384            hbox.pack_start(image)
385            hbox.pack_start(vbox)
386           
387            dialog.vbox.pack_start(hbox)
388            dialog.vbox.show_all()
389           
390            response = dialog.run()
391            dialog.destroy()
392           
393            if response == gtk.RESPONSE_OK:
394                filename = self._save_scan_results_cb(page)
395                # filename = None means that user didn't saved the result
396            elif response == gtk.RESPONSE_CANCEL:
397                return False
398
399            self.store_result(page, filename)
400           
401        elif page.status.scanning:
402            log.debug("Trying to close a tab with a running scan")
403            dialog = HIGDialog(buttons=(_('Close anyway'), gtk.RESPONSE_CLOSE,
404                                        gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
405           
406            title = self.scan_notebook.get_tab_title(page)
407           
408            alert = None
409            if title:
410                alert = HIGEntryLabel('<b>%s "%s"</b>' % (_("Trying to close"), title))
411            else:
412                alert = HIGEntryLabel('<b>%s</b>' % _("Trying to close"))
413           
414            text = HIGEntryLabel(_('The page you are trying to close has a scan \
415running at the background.\nWhat do you want to do?'))
416            hbox = HIGHBox()
417            hbox.set_border_width(5)
418            hbox.set_spacing(12)
419           
420            vbox = HIGVBox()
421            vbox.set_border_width(5)
422            vbox.set_spacing(12)
423           
424            image = gtk.Image()
425            image.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
426           
427            vbox.pack_start(alert)
428            vbox.pack_start(text)
429            hbox.pack_start(image)
430            hbox.pack_start(vbox)
431           
432            dialog.vbox.pack_start(hbox)
433            dialog.vbox.show_all()
434           
435            response = dialog.run()
436            dialog.destroy()
437           
438            if response == gtk.RESPONSE_CLOSE:
439                page.kill_scan()
440            elif response == gtk.RESPONSE_CANCEL:
441                return False
442        elif not page.status.empty:
443            alert = HIGAlertDialog(message_format=_('Closing current Scan Tab'),
444                                   secondary_text=_('Are you sure you want to close current \
445Scan Tab?'),
446                                   buttons=gtk.BUTTONS_OK_CANCEL,
447                                   type=gtk.MESSAGE_WARNING)
448            response = alert.run()
449            alert.destroy()
450
451            if response != gtk.RESPONSE_OK:
452                return False
453       
454        page.close_tab()
455        del(page)
456        self.scan_notebook.remove_page(page_num)
457        return True
458
459    def store_result(self, page, filename):
460        page.parsed.scan_name = self.scan_notebook.get_tab_title(page)
461       
462        if not filename:
463            filename = mktemp()
464            f = open(filename, "w")
465            page.parsed.write_xml(f)
466            f.close()
467
468        search_config = SearchConfig()
469        if search_config.store_results:
470            try:
471                log.debug(">>> Saving result into data base...")
472                scan = Scans(scan_name=self.scan_notebook.get_tab_title(page),
473                             nmap_xml_output=open(filename).read(),
474                             date=time())
475            except:
476                log.debug("Error while trying to store result in Data Base!")
477
478
479
480    def get_recent_scans(self):
481        r_scans = []
482        new_rscan_xml = ''
483       
484        try:
485            recent = open(Path.recent_scans)
486            r_scans = recent.readlines()
487
488            recent.close()
489        except: pass
490       
491        for scan in r_scans[:7]:
492            scan = scan.replace('\n','')
493            #print '>>> Exists:', scan, os.path.isfile(scan)
494            if os.access(os.path.split(scan)[0],os.R_OK) and os.path.isfile(scan):
495               
496                scan = scan.replace('\n','')
497                new_rscan = (scan, None, scan, None, scan, self._load_recent_scan)
498                new_rscan_xml += "<menuitem action='%s'/>\n" % scan
499               
500                self.main_actions.append(new_rscan)
501        else:
502            new_rscan_xml += "<separator />\n"
503       
504        self.default_ui %= new_rscan_xml
505   
506    def _create_menubar(self):
507        # Get and pack the menubar
508        menubar = self.ui_manager.get_widget('/menubar')
509       
510        if is_maemo():
511            menu = gtk.Menu()
512            for child in menubar.get_children():
513                child.reparent(menu)
514            self.set_menu(menu)
515            menubar.destroy()
516            self.menubar = menu
517        else:
518            self.menubar = menubar
519            self.vbox.pack_start(self.menubar, False, False, 0)
520
521        self.menubar.show_all()
522
523    def _create_toolbar(self):
524        toolbar = self.ui_manager.get_widget('/toolbar')
525       
526        if is_maemo():
527            tb = gtk.Toolbar()
528            for child in toolbar.get_children():
529                child.reparent(tb)
530            self.add_toolbar(tb)
531            self.toolbar = tb
532            toolbar.destroy()
533        else:
534            self.toolbar = toolbar
535            self.vbox.pack_start(self.toolbar, False, False, 0)
536
537        self.toolbar.show_all()
538
539    def _create_scan_notebook(self):
540        self.scan_notebook = ScanNotebook()
541        page = self._new_scan_cb()
542        self.scan_notebook.show_all()
543
544        # Applying some command line options
545        target = option_parser.get_target()
546        profile = option_parser.get_profile()
547        nmap = option_parser.get_nmap()
548
549        if nmap:
550            page.command_toolbar.command = " ".join(nmap)
551            page.start_scan_cb()
552
553        else:
554            if target:
555                page.toolbar.selected_target = target
556
557            if profile:
558                page.toolbar.selected_profile = profile
559
560            if target and profile:
561                log.debug(">>> Executing scan with the given args: %s \
562with %s" % (target, profile))
563                page.start_scan_cb()
564
565        if is_maemo():
566            # No padding. We need space!
567            self.vbox.pack_start(self.scan_notebook, True, True, 0)
568        else:
569            self.vbox.pack_start(self.scan_notebook, True, True, 4)
570
571    def _create_statusbar(self):
572        self.statusbar = gtk.Statusbar()
573        self.vbox.pack_start(self.statusbar, False, False, 0)
574
575    def _wizard_cb(self, widget):
576        w = Wizard()
577        w.set_notebook(self.scan_notebook)
578       
579        w.show_all()
580
581    def _load_scan_results_cb(self, p):
582        self._results_filechooser_dialog = ResultsFileChooserDialog(title=p.get_name())
583       
584        if (self._results_filechooser_dialog.run() == gtk.RESPONSE_OK):
585            self._load(filename=self._results_filechooser_dialog.get_filename())
586       
587        self._results_filechooser_dialog.destroy()
588        self._results_filechooser_dialog = None
589   
590    def _load_recent_scan(self, widget):
591        self._load(widget.get_name())
592
593    def _verify_page_usage(self, page):
594        """Verifies if given page is empty and can be used to load a result, or
595        if it's not empty and shouldn't be used to load a result. Returns True, if
596        it's ok to be used, and False if not.
597        """
598        if page == None \
599               or page.status.saved\
600               or page.status.unsaved_unchanged\
601               or page.status.unsaved_changed\
602               or page.status.loaded_unchanged\
603               or page.status.loaded_changed\
604               or page.status.parsing_result\
605               or page.status.scanning\
606               or page.status.search_loaded:
607            return False
608        else:
609            return True
610   
611    def _load(self, filename=None, parsed_result=None, title=None):
612        scan_page = None
613       
614        if filename or parsed_result:
615            current_page = self.scan_notebook.get_nth_page(self.scan_notebook.get_current_page())
616
617            if self._verify_page_usage(current_page):
618                log.debug(">>> Loading inside current scan page.")
619                scan_page = current_page
620            else:
621                log.debug(">>> Creating a new page to load it.")
622                scan_page = self._new_scan_cb()
623
624            log.debug(">>> Enabling page widgets")
625            scan_page.enable_widgets()
626
627        if filename and os.access(filename, os.R_OK):
628            # Load scan result from file
629            log.debug(">>> Loading file: %s" % filename)
630            log.debug(">>> Permissions to access file? %s" % os.access(filename, os.R_OK))
631
632            # Parse result
633            f = open(filename)
634            scan_page.parse_result(f)
635            scan_page.saved_filename = filename
636           
637            # Closing file to avoid problems with file descriptors
638            f.close()
639
640            log.debug(">>> Setting tab label")
641            self.scan_notebook.set_tab_title(scan_page, title)
642           
643        elif parsed_result:
644            # Load scan result from parsed object
645            scan_page.load_from_parsed_result(parsed_result)
646
647            log.debug(">>> Setting tab label")
648            self.scan_notebook.set_tab_title(scan_page, None)
649
650        elif filename and not os.access(filename, os.R_OK):
651            alert = HIGAlertDialog(message_format=_('Permission denied'),
652                                   secondary_text=_('Don\'t have read access to the path'))
653            alert.run()
654            alert.destroy()
655            return 
656        else:
657            alert = HIGAlertDialog(message_format=_('Could not load result'),
658                                   secondary_text=_('An unidentified error occouried and the \
659scan result was unable to be loaded properly.'))
660            alert.run()
661            alert.destroy()
662            return 
663
664        log.debug(">>> Setting flag that defines that there is no changes at \
665this scan result yet")
666        scan_page.changes = False
667        scan_page.status.set_loaded_unchanged()
668
669        log.debug(">>> Showing loaded result page")
670        self.scan_notebook.set_current_page(self.scan_notebook.get_n_pages()-1)
671        return scan_page
672   
673    def _save_scan_results_cb(self, saving_page):
674        current_page = self.scan_notebook.get_nth_page(self.scan_notebook.get_current_page())
675
676        try:
677            status = current_page.status
678        except:
679            alert = HIGAlertDialog(message_format=_('No scan tab'),
680                                   secondary_text=_('There is no scan tab or scan result \
681been shown. Run a scan and then try to save it.'))
682            alert.run()
683            alert.destroy()
684            return None
685
686
687        log.debug(">>> Page status: %s" % current_page.status.status)
688
689        if status.empty or status.unknown:    # EMPTY or UNKNOWN
690            # Show a dialog saying that there is nothing to be saved
691            alert = HIGAlertDialog(message_format=_('Nothing to save'),
692                                   secondary_text=_('No scan on this tab. Start a scan an \
693then try again'))
694            alert.run()
695            alert.destroy()
696
697        elif status.scan_failed:
698            alert = HIGAlertDialog(message_format=_('Nothing to save'),
699                                   secondary_text=_('The scan has failed! There is nothing \
700to be saved.'))
701            alert.run()
702            alert.destroy()
703
704        elif status.parsing_result:    # PARSING_RESULT
705            # Say that the result is been parsed
706            alert = HIGAlertDialog(message_format=_('Parsing the result'),
707                                   secondary_text=_('The result is still been parsed. \
708You can not save the result yet.'))
709            alert.run()
710            alert.destroy()
711
712        elif status.scanning:    # SCANNING
713            # Say that the scan is still running
714            alert = HIGAlertDialog(message_format=_('Scan is running'),
715                                   secondary_text=_('The scan process is not finished yet. \
716Wait until the scan is finished and then try to save it again.'))
717            alert.run()
718            alert.destroy()
719
720        elif status.unsaved_unchanged or status.unsaved_changed or status.search_loaded:
721            # UNSAVED_UNCHANGED and UNSAVED_CHANGED
722            # Show the dialog to choose the path to save scan result
723            self._save_results_filechooser_dialog = SaveResultsFileChooserDialog(\
724                                                                    title=_('Save Scan'))   
725            response = self._save_results_filechooser_dialog.run()
726
727            filename = None
728            if (response == gtk.RESPONSE_OK):
729                filename = self._save_results_filechooser_dialog.get_filename()
730                self._save(current_page, filename)
731               
732            self._save_results_filechooser_dialog.destroy()
733            self._save_results_filechooser_dialog = None
734
735            return filename
736
737        elif status.loaded_changed:    # LOADED_CHANGED
738            # Save the current result at the loaded file
739            self._save(current_page, current_page.saved_filename)
740        elif status.saved or status.loaded_unchanged:
741            pass
742        else:    # UNDEFINED status
743            alert = HIGAlertDialog(message_format=_('Nothing to save'),
744                                   secondary_text=_('No scan on this tab. Start a scan \
745 an then try again'))
746            alert.run()
747            alert.destroy()
748
749    def _show_about_cb(self, widget):
750        a = About()
751        a.show_all()
752   
753    def _save(self, saving_page, saved_filename):
754        log.debug(">>> File been saved: %s" % saved_filename)
755        if os.access(os.path.split(saved_filename)[0], os.W_OK):
756            f = None
757            try:
758                f = open(saved_filename, 'w')
759            except:
760                alert = HIGAlertDialog(message_format=_('Can\'t save file'),
761                            secondary_text=_('Can\'t open file to write'))
762                alert.run()
763                alert.destroy()
764            else:
765                saving_page.saved = True
766                saving_page.changes = False
767                saving_page.saved_filename = saved_filename
768                saving_page.collect_umit_info()
769
770                log.debug(">>> Page saved? %s" % saving_page.status.saved)
771                log.debug(">>> Changes on page? %s" % saving_page.status.status)
772                log.debug(">>> File to be saved at: %s" % saving_page.saved_filename)
773               
774                saving_page.parsed.write_xml(f)
775
776                # Closing file to avoid problems with file descriptors
777                f.close()
778
779                # Setting page status to saved
780                saving_page.status.set_saved()
781
782                # Saving recent scan information
783                rs = ['']
784                try:
785                    recent = open(Path.recent_scans)
786                    rs = recent.readlines()
787
788                    recent.close()
789                except:
790                    return None
791                else:
792                    rs.insert(0, saved_filename+'\n')
793
794                try:
795                    recent = open(Path.recent_scans,'w')
796                    recent.writelines(rs[:7])
797
798                    recent.close()
799                except:
800                    pass
801               
802        else:
803            alert = HIGAlertDialog(message_format=_('Permission denied'),
804                                   secondary_text=_('Don\'t have write access to this path.'))
805            alert.run()
806            alert.destroy()
807   
808    def _new_scan_cb(self, widget=None, data=None):
809        """Append a new ScanNotebookPage to ScanNotebook
810        New tab properties:
811        - Empty
812        - Disabled widgets
813        - Ready to start a new scan
814        - Untitled scan
815        """
816        page = ScanNotebookPage()
817        page.select_first_profile()
818       
819        self.scan_notebook.append_page(page, self._close_scan_cb, tab_title=data)
820        page.show_all()
821       
822        self.scan_notebook.set_current_page(-1)
823
824        # Put focus at the target combo, so user can open umit and start writing the target
825        page.target_focus()
826
827        return page
828
829    def _new_scan_profile_cb(self, p):
830        pe = ProfileEditor()
831        pe.set_notebook(self.scan_notebook)
832       
833        pe.show_all()
834   
835    def _edit_scan_profile_cb(self, p):
836        page = self.scan_notebook.get_nth_page\
837                (self.scan_notebook.get_current_page())
838        profile = page.toolbar.selected_profile
839       
840        pe = ProfileEditor(profile)
841        pe.set_notebook(self.scan_notebook)
842       
843        pe.show_all()
844   
845    def _new_scan_profile_with_selected_cb(self, p):
846        page = self.scan_notebook.get_nth_page(self.scan_notebook.get_current_page())
847        profile = page.toolbar.selected_profile
848       
849        pe = ProfileEditor(profile, delete=False)
850        pe.clean_profile_info()
851        pe.set_notebook(self.scan_notebook)
852       
853        pe.show_all()
854   
855    def _alert_with_action_name_cb(self, p):
856        d = HIGAlertDialog(parent=self,
857                           message_format=p.get_name(),
858                           secondary_text=_("The text above is this action's name"))
859        d.run()
860        d.destroy()
861
862    def _show_help(self, action):
863        import webbrowser
864        new = 0
865        try:
866            if float(sys.version[:3]) >= 2.5:
867                new = 2
868        except ValueError:
869            pass
870
871        webbrowser.open("file://%s" % os.path.join(Path.docs_dir,
872                                                   "help.html"),
873                        new=new)
874       
875
876    def _exit_cb (self, widget=None, extra=None):
877        for page in self.scan_notebook.get_children():
878            if not self._close_scan_cb(page):
879                self.show_all()
880                return True
881        else:
882            # Cleaning up data base
883            UmitDB().cleanup(SearchConfig().converted_save_time)
884           
885            gtk.main_quit()
886
887    def _load_diff_compare_cb (self, widget=None, extra=None):
888        # We must change this test dict
889        # This dict has the following sintax:
890        # key = Scan name
891        # value = nmap output in string format
892        dic = {}
893       
894        for i in range(self.scan_notebook.get_n_pages()):
895            page = self.scan_notebook.get_nth_page(i)
896            scan_name = self.scan_notebook.get_tab_title(page)
897
898            if not scan_name:
899                scan_name = _("Scan ") + str(i+1)
900           
901            dic[scan_name] = page.parsed
902       
903        self.diff_window = DiffWindow(dic)
904       
905        self.diff_window.show_all()
906
907
908class NonRootWarning (HIGAlertDialog):
909    def __init__(self):
910        warning_text = _('''You are trying to run UMIT with a non-root user!\n
911Some nmap options need root privileges to work.''')
912       
913        HIGAlertDialog.__init__(self, message_format=_('Non root user'),
914                                secondary_text=warning_text)
915
916        self.run()
917        self.destroy()
918
919
920if __name__ == '__main__':
921    w = MainWindow()
922    w.show_all()
923    gtk.main()
Note: See TracBrowser for help on using the browser.