root/branch/ggpolo/umitGUI/MainWindow.py @ 773

Revision 773, 35.8 kB (checked in by ggpolo, 6 years ago)

Merged trunk changes. Scheduler is stopped upon umit finalization (this may be a option later)

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