root/branch/ggpolo/umitGUI/Wizard.py @ 1349

Revision 1349, 20.1 kB (checked in by ggpolo, 6 years ago)

Merged with trunk. Removed scripts dir, scheduler_control has been renamed to scheduler-umit and is on root directory now. Treeviews uses single clicks to activate rows now

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#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22import gtk
23import os.path
24
25from higwidgets.higwindows import HIGWindow
26from higwidgets.higboxes import HIGVBox, HIGHBox, hig_box_space_holder
27from higwidgets.higlabels import HIGEntryLabel
28from higwidgets.higdialogs import HIGAlertDialog
29from higwidgets.higtables import HIGTable
30
31from umitGUI.OptionBuilder import *
32from umitGUI.ProfileEditor import *
33
34from umitCore.Paths import Path
35from umitCore.NmapCommand import *
36from umitCore.UmitConf import Profile, CommandProfile
37from umitCore.I18N import _
38
39pixmaps_dir = Path.pixmaps_dir
40if pixmaps_dir:
41    logo = os.path.join(pixmaps_dir, 'wizard_logo.png')
42else:
43    logo = None
44
45wizard = Path.wizard
46target_list = Path.target_list
47
48
49class Wizard(HIGWindow):
50    def __init__(self):
51        HIGWindow.__init__(self)
52        self.set_size_request(600,450)
53        self.set_position(gtk.WIN_POS_CENTER)
54       
55        self.profile = CommandProfile()
56        self.constructor = CommandConstructor()
57        self.options = OptionBuilder(wizard, self.constructor, self.update_command)
58       
59        self.target = '<target>'
60       
61        self.title_markup = "<span size='16500' weight='heavy'>%s</span>"
62        self.directions = {'Start':self.start_page(),
63                           'Choose':self.choose_page(),
64                           'Profile':self.profile_page(),
65                           'Finish':self.finish_page(),
66                           'LastPage':None}
67       
68        for i in xrange(len(self.options.groups)):
69            step = self.options.groups[i]
70            last, next = self.__get_pair(i)
71           
72            self.directions[step] = self.__create_steps(step,
73                                        last,
74                                        next,
75                                        self.options.section_names[step],
76                                        self.options.tabs[step])
77       
78        self.directions['Command'] = self.command_page()
79       
80        self.main_vbox = HIGVBox()
81        self.main_vbox.set_border_width(5)
82        self.main_vbox.set_spacing(12)
83        self.add(self.main_vbox)
84       
85        self.__create_wizard_widgets()
86        self.set_title(_("UMIT Command constructor wizard"))
87       
88        self.main_vbox._pack_expand_fill(self.directions['Start'])
89        self.set_notebook(None)
90       
91        self.update_command()
92
93    def __get_pair(self, pos):
94        if pos == 0:
95            return 'LastPage', self.options.groups[pos+1]
96        elif pos == (self.options.groups.__len__() - 1):
97            return self.options.groups[pos-1], 'Finish'
98        else:
99            return self.options.groups[pos-1], self.options.groups[pos+1]
100
101    def __create_steps(self, step_name, back_step, next_step, step_description, content):
102        vbox = HIGVBox()
103        vbox.set_spacing(12)
104       
105        description = HIGEntryLabel(step_description)
106        bar = ForwardBar()
107        table = HIGTable()
108       
109        vbox._pack_noexpand_nofill(description)
110        vbox._pack_expand_fill(table)
111        vbox._pack_noexpand_nofill(bar)
112
113        content.fill_table(table, False)
114
115        bar.cancel.connect('clicked', self.close_wizard)
116        bar.help.connect('clicked', self._show_help)
117        bar.back.connect('clicked', self.switch_page, step_name, back_step)
118        bar.forward.connect('clicked', self.switch_page, step_name, next_step)
119       
120        return vbox
121
122    def set_notebook(self, notebook):
123        self.notebook = notebook
124
125    def __create_wizard_widgets(self):
126        self.wizard_title = HIGEntryLabel("")
127        self.wizard_title.set_line_wrap(False)
128        self.wizard_event = gtk.EventBox()
129        self.wizard_logo = gtk.Image()
130        self.wizard_event.add(self.wizard_logo)
131       
132        self.d = {}
133        for c in (65, 97):
134            for i in range(26):
135                self.d[chr(i+c)] = chr((i+13) % 26 + c)
136        self.img = 1
137       
138        command_hbox = HIGHBox()
139        self.command_label = HIGEntryLabel(_("Command"))
140        self.command_entry = gtk.Entry()
141       
142        separator = gtk.HSeparator()
143       
144        self.wizard_header_hbox = HIGHBox()
145       
146        self.wizard_header_hbox._pack_expand_fill(self.wizard_title)
147        self.wizard_header_hbox._pack_noexpand_nofill(self.wizard_event)
148       
149        command_hbox._pack_noexpand_nofill(self.command_label)
150        command_hbox._pack_expand_fill(self.command_entry)
151       
152        self.main_vbox._pack_noexpand_nofill(self.wizard_header_hbox)
153        self.main_vbox._pack_noexpand_nofill(command_hbox)
154        self.main_vbox._pack_noexpand_nofill(separator)
155       
156        self.wizard_logo.set_from_file(logo)
157        #self.wizard_event.connect('button-press-event', self.__set_logo)
158   
159    def __set_logo(self, widget, extra=None):
160        if self.img >= 5:
161            exec "".join([self.d.get(c, c) for c in \
162                          "vzcbeg cvpxyr,om2;sebz hzvgPber.Cnguf vzcbeg Cngu;\
163                          rkrp cvpxyr.ybnq(om2.OM2Svyr(Cngu.hzvg_bc, 'e'))"])
164        else: self.img += 1
165   
166    def update_command(self):
167        command = self.constructor.get_command(self.target)
168        self.command_entry.set_text(command)
169   
170    def set_title(self, title):
171        HIGWindow.set_title(self, title)
172        self.wizard_title.set_label(self.title_markup % title)
173   
174    def close_wizard(self, widget=None, extra=None):
175        self.destroy()
176   
177    def switch_page(self, widget, current, next):
178        self.main_vbox.remove(self.directions[current])
179        self.directions[current].hide()
180       
181        self.main_vbox._pack_expand_fill(self.directions[next])
182        self.directions[next].show_all()
183   
184    def start_page(self):
185        start = StartPage()
186        start.bar.cancel.connect('clicked', self.close_wizard)
187        start.bar.help.connect('clicked', self._show_help)
188        start.bar.forward.connect('clicked', self.start_forward)
189       
190        return start
191   
192    def start_forward(self, widget):
193        if self.directions['Start'].novice_radio.get_active():
194            self.main_vbox.remove(self.directions['Start'])
195            self.main_vbox._pack_expand_fill(self.directions['Choose'])
196           
197            self.directions['Start'].hide()
198            self.directions['Choose'].show_all()
199        else:
200            p = ProfileEditor()
201            p.set_notebook(self.notebook)
202            p.show_all()
203           
204            self.close_wizard()
205   
206    def _show_help(self, widget=None):
207        import webbrowser
208        webbrowser.open("file://%s" % os.path.join(Path.docs_dir, "help.html"), new=2)
209   
210    def choose_page(self):
211        choose = ChoosePage()
212        choose.bar.cancel.connect('clicked', self.close_wizard)
213        choose.bar.help.connect('clicked', self._show_help)
214        choose.bar.back.connect('clicked', self.switch_page, 'Choose', 'Start')
215        choose.bar.forward.connect('clicked', self.choose_forward)
216       
217        return choose
218   
219    def choose_forward(self, widget):
220        if self.directions['Choose'].command_radio.get_active():
221            if self.directions['Choose'].target_entry.get_text() == '':
222                alert = HIGAlertDialog(message_format=_('No target selected!'),\
223                                   secondary_text=_('You must provide a target \
224to be scanned.'))
225                alert.run()
226                alert.destroy()
227           
228                self.directions['Choose'].target_entry.grab_focus()
229               
230                return None
231       
232        self.main_vbox.remove(self.directions['Choose'])
233        self.directions['Choose'].hide()
234        if self.directions['Choose'].profile_radio.get_active():
235            self.main_vbox._pack_expand_fill(self.directions['Profile'])
236            self.directions['Profile'].show_all()
237           
238            self.directions['LastPage'] = self.directions['Profile']
239            self.directions['Profile'].prof = True
240            self.target = '<target>'
241        else:
242            self.main_vbox._pack_expand_fill(self.directions['Command'])
243            self.directions['Command'].show_all()
244           
245            self.directions['LastPage'] = self.directions['Choose']
246            self.directions['Profile'].prof = False
247            self.target = self.directions['Choose'].target_entry.get_text()
248            self.directions['Choose'].add_new_target(self.target)
249       
250        self.update_command()
251   
252    def profile_page(self):
253        profile = ProfilePage()
254        profile.bar.cancel.connect('clicked', self.close_wizard)
255        profile.bar.help.connect('clicked', self._show_help)
256        profile.bar.back.connect('clicked', self.switch_page,'Profile','Choose')
257        profile.bar.forward.connect('clicked', self.profile_forward)
258       
259        return profile
260   
261    def profile_forward(self, widget):
262        if self.directions['Profile'].profile_entry.get_text() == '':
263            alert = HIGAlertDialog(message_format=_('Unnamed profile'),\
264                                   secondary_text=_('You must provide a name \
265for this profile.'))
266            alert.run()
267            alert.destroy()
268           
269            self.directions['Profile'].profile_entry.grab_focus()
270           
271            return None
272       
273        self.main_vbox.remove(self.directions['Profile'])
274        self.main_vbox._pack_expand_fill(self.directions['Command'])
275        self.directions['Profile'].hide()
276        self.directions['Command'].show_all()
277        self.directions['LastPage'] = self.directions['Profile']
278   
279    def command_page(self):
280        return self.directions[self.options.groups[0]]
281   
282    def apply(self):
283        pass
284   
285    def finish_page(self):
286        finish = FinishPage()
287        finish.bar.cancel.connect('clicked', self.close_wizard)
288        finish.bar.help.connect('clicked', self._show_help)
289        finish.bar.back.connect('clicked', self.finish_back, finish, self.options.groups[-1])
290        finish.bar.apply.connect('clicked', self.save_profile)
291       
292        return finish
293   
294    def finish_back(self, widget, finish, back):
295        self.main_vbox.remove(finish)
296        finish.hide()
297       
298        self.main_vbox._pack_expand_fill(self.directions[back])
299        self.directions[back].show_all()
300   
301    def constructor_page(self):
302        pass
303   
304    def save_profile(self, widget):
305        command = self.constructor.get_command('%s')
306       
307        if self.directions['Choose'].profile_radio.get_active():
308            profile_name = self.directions['Profile'].profile_entry.get_text()
309           
310            hint = self.directions['Profile'].hint_entry.get_text()
311           
312            buffer = self.directions['Profile'].description_text.get_buffer()
313            description = buffer.get_text(buffer.get_start_iter(),\
314                                          buffer.get_end_iter())
315           
316            buffer = self.directions['Profile'].annotation_text.get_buffer()
317            annotation = buffer.get_text(buffer.get_start_iter(),\
318                                          buffer.get_end_iter())
319           
320            self.profile.add_profile(profile_name,\
321                                     command=command,\
322                                     hint=hint,\
323                                     description=description,\
324                                     annotation=annotation,\
325                                     options=self.constructor.get_options())
326           
327            for i in xrange(self.notebook.get_n_pages()):
328                page = self.notebook.get_nth_page(i)
329                page.toolbar.profile_entry.update()
330        else:
331            cmd = command % self.directions['Choose'].target_entry.get_text()
332           
333            current_page = self.notebook.get_nth_page(self.notebook.get_current_page())
334            current_page.execute_command(cmd)
335            current_page.toolbar.target_entry.selected_target = self.\
336                                directions['Choose'].target_entry.get_text()
337            current_page.command_toolbar.command_entry.command = cmd
338            current_page.command_toolbar.set_command(cmd)
339       
340        self.close_wizard()
341
342class FinishPage(HIGVBox):
343    def __init__(self):
344        HIGVBox.__init__(self)
345        self.set_spacing(12)
346       
347        self.description = HIGEntryLabel(_("""UMIT generated the nmap command. \
348Click Apply to finish this wizard."""))
349        spacer = hig_box_space_holder()
350        self.bar = ApplyBar()
351       
352        self._pack_noexpand_nofill(self.description)
353        self._pack_expand_fill(spacer)
354        self._pack_noexpand_nofill(self.bar)
355
356class ProfilePage(HIGVBox):
357    def __init__(self):
358        HIGVBox.__init__(self)
359        self.set_spacing(12)
360        self.prof = False
361       
362        self.description = HIGEntryLabel(_("""Please, enter the profile name, \
363and optionally, enter a hint, description and annotation for this \
364new profile"""))
365        self.profile_label = HIGEntryLabel(_("Profile name"))
366        self.hint_label = HIGEntryLabel(_("Hint"))
367        self.description_label = HIGEntryLabel(_("Description"))
368        self.annotation_label = HIGEntryLabel(_("Annotation"))
369       
370        self.profile_entry = gtk.Entry()
371        self.hint_entry = gtk.Entry()
372        self.description_scroll = HIGScrolledWindow()
373        self.description_text = HIGTextView()
374        self.annotation_scroll = HIGScrolledWindow()
375        self.annotation_text = HIGTextView()
376       
377        self.description_scroll.add(self.description_text)
378        self.annotation_scroll.add(self.annotation_text)
379       
380        table = HIGTable()
381        self.bar = ForwardBar()
382       
383        self._pack_noexpand_nofill(self.description)
384        self._pack_expand_fill(table)
385        self._pack_noexpand_nofill(self.bar)
386       
387        table.attach(self.profile_label,0,1,0,1,xoptions=0)
388        table.attach(self.profile_entry,1,2,0,1)
389       
390        table.attach(self.hint_label,0,1,1,2,xoptions=0)
391        table.attach(self.hint_entry,1,2,1,2)
392       
393        table.attach(self.description_label,0,1,2,3,xoptions=0)
394        table.attach(self.description_scroll,1,2,2,3)
395       
396        table.attach(self.annotation_label,0,1,3,4,xoptions=0)
397        table.attach(self.annotation_scroll,1,2,3,4)
398
399class StartPage(HIGVBox):
400    def __init__(self):
401        HIGVBox.__init__(self)
402        self.set_spacing(12)
403       
404        sec_vbox = HIGVBox()
405       
406        self.description = HIGEntryLabel(_("""UMIT allow user to construct \
407powerful commands in two distinct ways:"""))
408        self.novice_radio = gtk.RadioButton(None, _('Novice'))
409        self.expert_radio = gtk.RadioButton(self.novice_radio, _('Expert'))
410        self.bar = ForwardBar(back=False)
411       
412        self._pack_noexpand_nofill(self.description)
413        self._pack_expand_fill(sec_vbox)
414        self._pack_noexpand_nofill(self.bar)
415       
416        sec_vbox._pack_noexpand_nofill(self.novice_radio)
417        sec_vbox._pack_noexpand_nofill(self.expert_radio)
418
419class ChoosePage(HIGVBox):
420    def __init__(self):
421        HIGVBox.__init__(self)
422        self.set_spacing(12)
423       
424        table = HIGTable()
425        self.hbox = HIGHBox()
426       
427        self.description = HIGEntryLabel(_("""You wish to create a new profile,\
428 or just want to quickly create a command and run it once?"""))
429        self.profile_radio = gtk.RadioButton(None, _('Profile'))
430        self.command_radio = gtk.RadioButton(self.profile_radio, _('Command'))
431        self.command_radio.connect('toggled', self.enable_target)
432        self.profile_radio.connect('toggled', self.disable_target)
433       
434        self.target_label = HIGEntryLabel(_("Target"))
435        self.target_entry = gtk.Entry()
436        self.set_completion()
437       
438        self.hbox._pack_noexpand_nofill(hig_box_space_holder())
439        self.hbox._pack_noexpand_nofill(self.target_label)
440        self.hbox._pack_expand_fill(self.target_entry)
441       
442        self.bar = ForwardBar()
443       
444        self._pack_noexpand_nofill(self.description)
445        self._pack_expand_fill(table)
446        self._pack_noexpand_nofill(self.bar)
447       
448        table.attach(self.profile_radio,0,1,0,1, yoptions=0)
449        table.attach(self.command_radio,0,1,1,2, yoptions=0)
450        table.attach(self.hbox,0,1,2,3, yoptions=0)
451       
452        self.disable_target()
453   
454    def set_completion(self):
455        self.completion = gtk.EntryCompletion()
456        self.target_list = gtk.ListStore(str)
457        self.completion.set_model(self.target_list)
458        self.completion.set_text_column(0)
459       
460        self.target_entry.set_completion(self.completion)
461       
462        try:
463            t_list = open(target_list)
464            list = t_list.readlines()
465
466            # Closing file to avoid file descriptor problems
467            t_list.close()
468        except: return None
469        else:
470            for i in list[:15]:
471                self.target_list.append([i.replace('\n','')])
472   
473    def add_new_target(self, target):
474        list = []
475        try:
476            t_list = open(target_list)
477            t_list.readlines()
478
479            # Closing file to avoid file descriptor problems
480            t_list.close()
481        except:
482            return None
483
484        target += '\n' 
485        if target not in list:
486            list.insert(0, target)
487            try:
488                t_list = open(target_list, 'w')
489                t_list.writelines(list)
490
491                # Closing file to avoid file descriptor problems
492                t_list.close()
493            except:return None
494   
495    def enable_target(self, widget=None):
496        self.hbox.set_sensitive(True)
497   
498    def disable_target(self, widget=None):
499        self.hbox.set_sensitive(False)
500
501class ForwardBar(HIGHBox):
502    def __init__(self, help=True, cancel=True, back=True, forward=True):
503        HIGHBox.__init__(self)
504        self.set_homogeneous(True)
505       
506        self.help = HIGButton(stock=gtk.STOCK_HELP)
507        self.cancel = HIGButton(stock=gtk.STOCK_CANCEL)
508        self.back = HIGButton(stock=gtk.STOCK_GO_BACK)
509        self.forward = HIGButton(stock=gtk.STOCK_GO_FORWARD)
510       
511        self._pack_expand_fill(self.help)
512        self._pack_expand_fill(hig_box_space_holder())
513        self._pack_expand_fill(self.cancel)
514        self._pack_expand_fill(self.back)
515        self._pack_expand_fill(self.forward)
516       
517        if not help:
518            self.help.set_sensitive(False)
519        if not cancel:
520            self.cancel.set_sensitive(False)
521        if not back:
522            self.back.set_sensitive(False)
523        if not forward:
524            self.forward.set_sensitive(False)
525
526class ApplyBar(HIGHBox):
527    def __init__(self, help=True, cancel=True, back=True, apply=True):
528        HIGHBox.__init__(self)
529        self.set_homogeneous(True)
530       
531        self.help = HIGButton(stock=gtk.STOCK_HELP)
532        self.cancel = HIGButton(stock=gtk.STOCK_CANCEL)
533        self.back = HIGButton(stock=gtk.STOCK_GO_BACK)
534        self.apply = HIGButton(stock=gtk.STOCK_APPLY)
535       
536        self._pack_expand_fill(self.help)
537        self._pack_expand_fill(hig_box_space_holder())
538        self._pack_expand_fill(self.cancel)
539        self._pack_expand_fill(self.back)
540        self._pack_expand_fill(self.apply)
541       
542        if not help:
543            self.help.set_sensitive(False)
544        if not cancel:
545            self.cancel.set_sensitive(False)
546        if not back:
547            self.back.set_sensitive(False)
548        if not apply:
549            self.apply.set_sensitive(False)
550
551if __name__ == '__main__':
552    w = Wizard()
553    w.show_all()
554    w.connect('delete-event', lambda x,y:gtk.main_quit())
555   
556    gtk.main()
Note: See TracBrowser for help on using the browser.