Index: /branch/max/umitGUI/ScriptManager.py
===================================================================
--- /branch/max/umitGUI/ScriptManager.py (revision 615)
+++ /branch/max/umitGUI/ScriptManager.py (revision 615)
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+
+import os, os.path
+import re
+
+from umitCore.Paths import Search
+from umitCore.I18N import _
+
+import gtk
+from umitGUI.FileChoosers import DirectoryChooserDialog, AllFilesFileChooserDialog
+from higwidgets.higwindows import HIGWindow
+from higwidgets.higboxes import HIGVBox, HIGHBox, HIGSpacer, hig_box_space_holder
+from higwidgets.higexpanders import HIGExpander
+from higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel
+from higwidgets.higscrollers import HIGScrolledWindow
+from higwidgets.higtextviewers import HIGTextView
+from higwidgets.higbuttons import HIGButton
+from higwidgets.higtables import HIGTable
+from higwidgets.higdialogs import HIGAlertDialog, HIGDialog
+
+class Script(object):
+    def __init__(self, path):
+        self.data = file(path, 'r').read()
+        self.id = self._get_attr('id')
+        self.desc = self._get_attr('description')
+
+    def __eq__(self, other):
+        return self.id.__eq__(other.id)
+    
+    def _get_attr(self, attr):
+        r = re.findall(attr + '\s*=\s*"([^\"]+)"', self.data)
+        res = r[0]
+        res = res.replace('\\', ' ')
+        res = res.replace('\n', ' ')
+        return res.strip()
+
+class ScriptManagerWindow(HIGWindow):
+    def __init__(self):
+        HIGWindow.__init__(self)
+        self.scripts = []
+        self.set_title(_("Script Manager"))
+        self.set_position(gtk.WIN_POS_CENTER)
+        self._create_widgets()
+        self._pack_widgets()
+        self._connect_widgets()
+
+    def _create_widgets(self):
+        self.main_vbox = HIGVBox()
+        self.buttons_hbox = HIGHBox()
+        self.btn_add_file = HIGButton(_("Add file"), stock=gtk.STOCK_OPEN)
+        self.btn_add_dir = HIGButton(_("Add dir"), stock=gtk.STOCK_DIRECTORY)
+        self.btn_delete = HIGButton(stock=gtk.STOCK_DELETE)
+        self.btn_close = HIGButton(stock=gtk.STOCK_CLOSE)
+        self.scripts_hbox = HIGHBox()
+        #self.scripts_vbox_id = HIGVBox()
+        #self.scripts_vbox_desc = HIGVBox()
+        self.lbl_desc = HIGSectionLabel("<b>%s</b>" % _("Description"))
+        self.desc_scroll = HIGScrolledWindow()
+        self.desc_textview = HIGTextView()
+        self.desc_textview.set_editable(False)
+        self.lbl_id = HIGSectionLabel("<b>%s</b>" % _("id"))
+        self.id_scroll = HIGScrolledWindow()
+        self.id_liststore = gtk.ListStore(str)
+        self.id_listview = gtk.TreeView(self.id_liststore)
+        self.id_listview.set_headers_visible(False)
+        cols = ['id']
+        for i, col in enumerate(cols):
+            tv = gtk.TreeViewColumn(col)
+            cell = gtk.CellRendererText()
+            tv.pack_start(cell, True)
+            tv.add_attribute(cell, 'text', i)
+            self.id_listview.append_column(tv)
+        self.update_liststore()
+
+    def _pack_widgets(self):
+        self.set_size_request(600, 400)
+        self.add(self.main_vbox)
+
+        self.main_vbox._pack_expand_fill(self.scripts_hbox)
+        self.main_vbox._pack_noexpand_nofill(self.buttons_hbox)
+        
+        self.scripts_hbox.pack_start(self.id_scroll)
+        #self.scripts_vbox_id._pack_noexpand_nofill(self.lbl_id)
+        #self.scripts_vbox_id._pack_expand_fill(self.id_scroll)
+        self.id_scroll.add(self.id_listview)
+        self.scripts_hbox.pack_start(self.desc_scroll)
+        self.desc_scroll.add(self.desc_textview)
+
+        self.buttons_hbox.pack_start(self.btn_add_file)
+        self.buttons_hbox.pack_start(self.btn_add_dir)
+        self.buttons_hbox.pack_start(self.btn_delete)
+        self.buttons_hbox.pack_start(self.btn_close)
+        self.buttons_hbox.set_border_width(5)
+        self.buttons_hbox.set_spacing(6)
+
+    def _connect_widgets(self):
+        self.id_listview.connect('cursor-changed', self.id_select_cb)
+        self.btn_add_file.connect('clicked', self.add_file_cb)
+        self.btn_add_dir.connect('clicked', self.add_dir_cb)
+        self.btn_delete.connect('clicked', self.delete_cur_cb)
+        self.btn_close.connect('clicked', lambda x,y=None:self.destroy())
+        
+    def update_liststore(self):
+        self.id_liststore.clear()
+        for script in self.scripts:
+            it = self.id_liststore.append([script.id])
+
+    def id_select_cb(self, widget):
+        (model, it) = self.id_listview.get_selection().get_selected()
+        if it:
+            cur = self.id_liststore.get_path(it)[0]
+            b = self.desc_textview.get_buffer()
+            b.set_text(self.scripts[cur].desc)
+        
+    def add_file_cb(self, widget):
+        file_chooser = AllFilesFileChooserDialog(_("Select Script"))
+        file_chooser.run()
+        name = file_chooser.get_filename()
+        file_chooser.destroy()
+        if name:
+            self.add_file(name, True)
+
+    def add_dir_cb(self, widget):
+        file_chooser = DirectoryChooserDialog(_("Select Scripts Directory"))
+        file_chooser.run()
+        dirname = file_chooser.get_filename()
+        file_chooser.destroy()
+        if dirname:
+            self.add_dir(dirname, True)
+
+    def delete_cur_cb(self, widget):
+        (model, it) = self.id_listview.get_selection().get_selected()
+        if it:
+            cur = self.id_liststore.get_path(it)[0]
+            self.id_liststore.remove(it)
+            del self.scripts[cur]
+            self.id_listview.get_selection().select_path((cur,))
+            self.id_select_cb(None)
+
+    def add_file(self, filename, gui_err = False):
+        if Search.check_access(filename, os.R_OK):
+            try:
+                script = Script(filename)
+            except:
+                if not err:
+                    return None
+                alert = HIGAlertDialog(
+                    message_format='<b>%s</b>' % _('File is not a NSE script file'),
+                    secondary_text=_("Selected file is not a NSE script file. \
+Umit can not parse this file. Please, select another."))
+                alert.run()
+                alert.destroy()
+                return None
+            # add only unique scripts
+            if not script in self.scripts: 
+                self.scripts.append(script)
+                self.update_liststore()
+            self.scripts.sort(cmp=lambda x,y: cmp(x.id, y.id))
+            return script
+        else:
+            if not err:
+                return None
+            alert = HIGAlertDialog(
+                message_format='<b>%s</b>' % _('Can not open selected file'),
+                secondary_text=_("Umit can not open selected file. Please, select \
+another."))
+            alert.run()
+            alert.destroy()
+            return None
+
+    def add_dir(self, dirname, gui_err = False):
+        res = False
+        for (dirpath, dirnames, filenames) in os.walk(dirname):
+            for name in filenames:
+                if name.endswith('.nse'):
+                    if self.add_file(os.path.join(dirpath, name)):
+                        res = True
+            break # only root files (?)
+        if res:
+            self.update_liststore()
+        elif gui_err:
+            alert = HIGAlertDialog(
+                message_format='<b>%s</b>' % _('Can not find any NSE script files in the directory'),
+                secondary_text=_("Umit can not find any NSE script files in the selected \
+directory. Please, select another."))
+            alert.run()
+            alert.destroy()
+
+
+if __name__ == "__main__":
+    sm = ScriptManagerWindow()
+    sm.add_dir('/usr/local/share/nmap/scripts/')
+    sm.show_all()
+    gtk.main()
Index: /branch/max/umitGUI/ProfileEditor.py
===================================================================
--- /branch/max/umitGUI/ProfileEditor.py (revision 508)
+++ /branch/max/umitGUI/ProfileEditor.py (revision 615)
@@ -40,5 +40,4 @@
 profile_editor = Path.profile_editor
 
-
 class ProfileEditor(HIGWindow):
     def __init__(self, profile_name=None, delete=True):
Index: /branch/max/umitGUI/MainWindow.py
===================================================================
--- /branch/max/umitGUI/MainWindow.py (revision 489)
+++ /branch/max/umitGUI/MainWindow.py (revision 615)
@@ -43,4 +43,5 @@
 from umitGUI.SearchWindow import SearchWindow
 from umitGUI.BugReport import BugReport
+from umitGUI.ScriptManager import ScriptManagerWindow
 
 from umitCore.Paths import Path
@@ -203,5 +204,11 @@
                 _('Compare Scan Results using Diffies'),
                 self._load_diff_compare_cb),
-            
+
+            ('Script Manager',
+                gtk.STOCK_INDEX,
+                _('Script Manager'),
+                "<Control>M",
+                _('Manage available scripts'),
+                self._load_script_manager_cb),
             
             # Top Level
@@ -252,4 +259,5 @@
             <menuitem action='Search Scan'/>
             <menuitem action='Compare Results'/>
+            <menuitem action='Script Manager'/>
             <separator />
             %s
@@ -842,5 +850,8 @@
         self.diff_window.show_all()
 
-
+    def _load_script_manager_cb(self, widget = None, extra = None):
+        self.script_manager_window = ScriptManagerWindow()
+        self.script_manager_window.show_all()
+        
 class NonRootWarning (HIGAlertDialog):
     def __init__(self):
Index: /branch/max/umitGUI/OptionBuilder.py
===================================================================
--- /branch/max/umitGUI/OptionBuilder.py (revision 489)
+++ /branch/max/umitGUI/OptionBuilder.py (revision 615)
@@ -90,5 +90,5 @@
         label = HIGEntryLabel(option_list.getAttribute(u'label'))
         opt_list = OptionList()
-        
+
         for opt in options:
             opt_list.append(self.options.get_option\
Index: /branch/max/umitCore/UmitDB.py
===================================================================
--- /branch/max/umitCore/UmitDB.py (revision 516)
+++ /branch/max/umitCore/UmitDB.py (revision 615)
@@ -153,5 +153,5 @@
             self.scans_id = kargs["scans_id"]
         else:
-            log.debug(">>>Ceating new scan result entry at data base")
+            log.debug(">>>Creating new scan result entry at data base")
             fields = ["scan_name", "nmap_xml_output", "date"]
             
Index: /branch/max/config/profile_editor.xml
===================================================================
--- /branch/max/config/profile_editor.xml (revision 510)
+++ /branch/max/config/profile_editor.xml (revision 615)
@@ -6,4 +6,5 @@
     <group name="Target"/>
     <group name="Source"/>
+    <group name="Scripts"/>
     <group name="Other"/>
     <group name="Advanced"/>
@@ -67,4 +68,6 @@
     <option_check label="Set network interface" option="Set network interface" arg_type="str"/>
   </Source>
+  <Scripts label="Scripts options">
+  </Scripts>
   <Other label="Other options">
     <option_check label="Extra options definied by user" option="Extra" arg_type="str"/>
Index: /branch/max/config/options.xml
===================================================================
--- /branch/max/config/options.xml (revision 510)
+++ /branch/max/config/options.xml (revision 615)
@@ -402,3 +402,4 @@
           arguments=""
           need_root="0"/>
+
 </nmap_options>
