'''
exploittab.py

Copyright 2007 Andres Riancho

This file is part of w3af, w3af.sourceforge.net .

w3af is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 2 of the License.

w3af is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with w3af; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
'''

import gtk, gobject
from . import prompt, helpers, entries, confpanel
from core.ui.gtkUi.pluginEditor import pluginEditor

import core.data.kb.knowledgeBase as kb
from core.data.kb.vuln import vuln as vulnType
from core.controllers.w3afException import w3afException, w3afMustStopException
import operator


class Shells(gtk.TreeView):
    '''The list of shells produced from vulnerabilities.

    @author: Facundo Batista <facundobatista =at= taniquetil.com.ar>
    '''
    def __init__(self, w3af):
        self.w3af = w3af

        # create the ListStore, with the shell name and id
        self.liststore = gtk.ListStore(str, str)
        self.listholder = {}

        # create the TreeView using liststore
        super(Shells,self).__init__(self.liststore)

        # create a TreeViewColumn for the text
        tvcolumn = gtk.TreeViewColumn('Shells')
        cell = gtk.CellRendererText()
        tvcolumn.pack_start(cell, True)
        tvcolumn.add_attribute(cell, 'text', 0)
        self.append_column(tvcolumn)

        self.connect('row-activated', self.useShell)
        gobject.timeout_add(500, self._update)
        self.show()

    def _update(self):
        '''Updates the list of shells.

        @return: True, to keep gobject.timeout_add calling it.
        '''
        shells = kb.kb.getAllShells()
        for shell in shells:
            shellid = str(id(shell))
            if shellid not in self.listholder:
                try:
                    self.liststore.append([str(shell), shellid])
                except w3afException, w3:
                    msg = _("An error ocurren while generating the shell object: ") + str(w3)
                    dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, msg)
                    dlg.destroy()

                # I always perform this because I just want to be warned once
                self.listholder[shellid] = shell
        return True

    def useShell(self, treeview, path, view_column):
        '''Raises a prompt dialog to use the shell.'''
        shellid = self.liststore[path][1]
        shell = self.listholder[shellid]
        try:
            title = "Shell - " + shell.getRemoteSystem()
        except w3afException, w3:
            msg = _("Failed to get the remote system name from the shell object.\n")
            msg += _("Original exception: ") + str(w3)
            dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, msg)
            dlg.destroy()
        else:
            promptText = shell.getRemoteUser()+'@'+shell.getRemoteSystemName()
            prompt.PromptDialog( title, promptText, shell.generic_user_input)


class ExploitAllDialog(gtk.Dialog):
    '''A dialog with the About information.

    @author: Facundo Batista <facundobatista =at= taniquetil.com.ar>
    '''
    def __init__(self, w3af):
        super(ExploitAllDialog,self).__init__("Multiple Exploit", None, gtk.DIALOG_MODAL,
                      (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_EXECUTE,gtk.RESPONSE_OK))

        self.liststore = gtk.ListStore(str, gobject.TYPE_BOOLEAN)

        # just build the tree with the plugin names
        for plugin in sorted(w3af.getPluginList("attack")):
            self.liststore.append([plugin, 1])

        # create the TreeView using liststore
        treeview = gtk.TreeView(self.liststore)
        self.vbox.pack_start(treeview)

        # create a TreeViewColumn for the text
        tvcolumn = gtk.TreeViewColumn(_('Exploits'))
        cell = gtk.CellRendererText()
        tvcolumn.pack_start(cell, True)
        tvcolumn.add_attribute(cell, 'text', 0)
        treeview.append_column(tvcolumn)

        # create a TreeViewColumn for the checkbox
        tvcolumn = gtk.TreeViewColumn(_('Active'))
        cell = gtk.CellRendererToggle()
        cell.set_property('activatable', True)
        cell.connect('toggled', self._toggle)
        tvcolumn.pack_start(cell, False)
        tvcolumn.add_attribute(cell, 'active', 1)
        treeview.append_column(tvcolumn)

        # stop on first
        self.but_sof = gtk.CheckButton(_("First successful"))
        if hasattr(self.but_sof, "set_tooltip_text"):
            self.but_sof.set_tooltip_text(_("Stop on first successful exploit"))
        self.vbox.pack_start(self.but_sof)

        # the cancel button
        but = self.action_area.get_children()[1]
        but.connect("clicked", lambda x: self.destroy())

        # the ok button
        but = self.action_area.get_children()[0]
        but.connect("clicked", self._ok)

        self.connect("delete-event", lambda x,y: self.destroy())
        self.activatedPlugins = None
        self.stopOnFirst = None
        self.show_all()

    def _ok(self, w):
        '''Collects the information.'''
        self.activatedPlugins = [name for (name,act) in self.liststore if act]
        self.stopOnFirst = self.but_sof.get_active()
        self.destroy()

    def _toggle(self, cell, path):
        '''Toggles the plugin on/off.

        @param cell: the cell that generated the signal.
        @param path: the path that clicked the user.
        '''
        listrow = self.liststore[path]
        listrow[1] = not listrow[1]


class ExploitTree(gtk.TreeView):
    '''A list showing all the plugins of "attack" type.

    @param w3af: The main core class.

    @author: Facundo Batista <facundobatista =at= taniquetil.com.ar>
    '''
    def __init__(self, w3af):
        self.w3af = w3af

        # create the ListStore, with the plugin name twice (the first could
        # go bold, the second is the original name always)
        self.liststore = gtk.ListStore(str, str)

        # just build the tree with the plugin names
        for plugin in sorted(w3af.getPluginList("attack")):
            self.liststore.append([plugin, plugin])

        # we will not ask for the plugin instances until needed, we'll
        # keep them here:
        self.plugin_instances = {}

        # create the TreeView using liststore
        super(ExploitTree,self).__init__(self.liststore)

        # signals
        self.connect('button-release-event', self.popup_menu)
        self.connect('cursor-changed', self._changedSelection)

        # create a TreeViewColumn for the text
        tvcolumn = gtk.TreeViewColumn(_('Exploits'))
        cell = gtk.CellRendererText()
        tvcolumn.pack_start(cell, True)
        tvcolumn.add_attribute(cell, 'markup', 0)
        self.append_column(tvcolumn)

        # drag and drop setup, this is the SOURCE
        target = [("explot-activ", 0, 1)]
        self.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, target, gtk.gdk.ACTION_COPY)

        #self.set_enable_tree_lines(True)
        self.show()

    def setFilter(self, vuln):
        new_liststore = gtk.ListStore(str, str)
        for pname in sorted(self.w3af.getPluginList("attack")):
            exploit = self.w3af.getPluginInstance(pname, "attack")
            thisvulns = getExploitableVulns(exploit)
            markedname = ("<b>%s</b>" % pname) if vuln in thisvulns else pname
            new_liststore.append([markedname, pname])
        self.set_model(new_liststore)
        self.liststore = new_liststore

    def _changedSelection(self, *w):
        '''Changed which exploit is selected.'''
        exploit = self.getSelectedExploit()
        self.vulnerabs.setFilter(exploit)

        # un-bold the rest
        for row in self.liststore:
            if row[1] != exploit.pname:
                row[0] = row[1]

    def getSelectedExploit(self):
        '''Returns the selected exploit.

        @return: The selected exploit.
        '''
        (path, column) = self.get_cursor()
        if path is None:
            return None

        # Get the information about the click
        plugin = self.getPluginInstance(path)
        return plugin

    def popup_menu( self, tv, event ):
        '''Shows a menu when you right click on a plugin.

        @param tv: the treeview.
        @parameter event: The GTK event
        '''
        if event.button != 3:
            return

        (path, column) = tv.get_cursor()
        # Is it over a plugin name ?
        if path is not None and len(path) == 1:
            # Get the information about the click
            plugin = self.getPluginInstance(path)
            pname = self.liststore[path][1]

            # Ok, now I show the popup menu !
            # Create the popup menu
            gm = gtk.Menu()

            # And the items
            e = gtk.MenuItem(_("Edit plugin..."))
            e.connect('activate', self._handleEditPluginEvent, pname, path)
            gm.append( e )
            e = gtk.MenuItem(_("Configure plugin..."))
            e.connect('activate', self._configureExploit, plugin, pname)
            gm.append( e )
            e = gtk.MenuItem(_("Exploit ALL vulns"))
            e.connect('activate', self._exploitAll, pname, False)
            gm.append( e )
            e = gtk.MenuItem(_("Exploit all until first successful"))
            e.connect('activate', self._exploitAll, pname, True)
            gm.append( e )

            gm.show_all()
            gm.popup( None, None, None, event.button, event.time)

    def _handleEditPluginEvent(self, widget, pluginName, path):
        '''
        I get here when the user right clicks on a plugin name, then he clicks on "Edit..."
        This method calls the plugin editor with the corresponding parameters.
        '''
        def f(t, n):
            self._finishedEditingPlugin(path, pluginName)
        pluginEditor("attack",  pluginName, f)

    def _finishedEditingPlugin(self, path, pluginName):
        '''
        This is a callback that is called when the plugin editor finishes.
        '''
        del self.plugin_instances[path]
        self.w3af.reloadModifiedPlugin('attack',  pluginName)

    def _exploitAll(self, widget, pname, stoponfirst):
        '''Exploit all the vulns.'''
        effectivelyExploitAll(self.w3af, [pname], stoponfirst)

    def _configureExploit(self, widget, plugin, pname):
        '''Configure the exploit plugin.'''
        title = "Configure " + pname
        confpanel.ConfigDialog(title, self.w3af, plugin, showDesc=True)

    def getPluginInstance(self, path):
        '''Caches the plugin instance.

        @param path: where the user is in the plugin list
        @return The plugin
        '''
        try:
            return self.plugin_instances[path]
        except KeyError:
            pass

        # path can be a tuple of one or two values here
        pname = self.liststore[path][1]
        plugin = self.w3af.getPluginInstance(pname, "attack")
        plugin.pname = pname
        plugin.ptype = "attack"
        self.plugin_instances[path] = plugin
        return plugin


class VulnerabList(gtk.TreeView):
    '''A tree showing all the found vulnerabilities.

    @param w3af: The w3af core.
    @param exploitlist: The widget that keeps the list of exploits

    @author: Facundo Batista <facundobatista =at= taniquetil.com.ar>
    '''
    def __init__(self, w3af, exploitlist):
        self.w3af = w3af
        self.exploitlist = exploitlist

        # simple empty List Store
        # columns: the string to show, the string to order, the key
        # for the plugin instance, and the icon
        self.liststore = gtk.ListStore(str, str, str, gtk.gdk.Pixbuf)
        gtk.TreeView.__init__(self, self.liststore)

        # the text & icon column
        tvcolumn = gtk.TreeViewColumn(_("Vulnerabilities"))
        cell = gtk.CellRendererPixbuf()
        tvcolumn.pack_start(cell, expand=False)
        tvcolumn.add_attribute(cell, "pixbuf", 3)
        cell = gtk.CellRendererText()
        tvcolumn.pack_start(cell, expand=True)
        tvcolumn.add_attribute(cell, "markup", 0)
        self.append_column(tvcolumn)

        # here we will hold the instances, the key will be stored in the store
        self.instances = {}
        self.listholder = set()

        # initial filters
        self.applicable = []

        # drag and drop setup, this is the DESTINATION
        target = [("explot-activ", 0, 1)]
        self.enable_model_drag_dest(target, gtk.gdk.ACTION_COPY)
        self.connect("drag-data-received", self._dragDropped)

        self.connect('cursor-changed', self._changedSelection)

        # get the knowledge base and go live
        self.fullkb = kb.kb.dump()
        gobject.timeout_add(500, self._updateList)
        self.lastcheck = False
        self.show()
    
    def _changedSelection(self, *w):
        '''Changed which exploit is selected.'''
        (path, column) = self.get_cursor()
        vuln = self.getInstance(path)
        self.exploitlist.setFilter(vuln)

        # un-bold the rest
        selected = vuln.getName()
        for row in self.liststore:
            if row[1] != selected:
                row[0] = row[1]

    def setFilter(self, exploit):
        '''Sets a new filter and update the list.

        @param active: which types should be shown.
        '''
        vulns = getExploitableVulns(exploit)
        if vulns is None:
            self.applicable = []
        else:
            self.applicable = vulns
        new_liststore = gtk.ListStore(str, str, str, gtk.gdk.Pixbuf)
        new_listholder = set()
        self._updateList(new_liststore, new_listholder)
        self.set_model(new_liststore)
        self.liststore = new_liststore
        self.listholder = new_listholder

    def _filterKB(self):
        '''Calculates the difference between the KB and the list.

        This way, only is added to the list those nodes that are new.

        @return: The filtered KB.
        '''
        # let's filter the real kb, to see what we should add
        filteredkb = []

        # iterate the first layer, plugin names
        for pluginname, plugvalues in self.fullkb.items():
            # iterate the second layer, variable names
            for variabname, variabobjects in plugvalues.items():
                # iterate the third layer, the variable objects
                if isinstance(variabobjects, list):
                    for obj in variabobjects:
                        if type(obj) == vulnType:
                            severity = obj.getSeverity()
                            filteredkb.append((obj, severity))
        return filteredkb

    def _getBestObjName(self,  obj):
        '''
        @return: The best obj name possible
        '''

        if hasattr(obj, "getName"):
            realname = obj.getName()
        else:
            realname = repr(obj)
        if obj in self.applicable:
            showname = "<b>%s</b>" % realname
        else:
            showname = "%s" % realname
        return showname, realname

    def _updateList(self, liststore=None, listholder=None):
        '''Updates the GUI with the KB.

        @return: True to keep being called by gobject.
        '''
        # if the core is not running, don't have anything to update
        if not self.w3af.isRunning():
            if self.lastcheck:
                return True
            else:
                self.lastcheck = True
        self.lastcheck = False

        # get the filtered knowledge base info
        filteredKB = self._filterKB()
        if liststore is None:
            liststore = self.liststore
            listholder = self.listholder

        new_ones = []
        for obj, severity in filteredKB:
            idinstance = str(id(obj))
            if idinstance in listholder:
                continue

            # it's new!
            (showname, realname) = self._getBestObjName(obj)
            newicon = helpers.KB_ICONS.get(("vuln", severity))
            if newicon is not None:
                newicon = newicon.get_pixbuf()

            new_ones.append(
                (idinstance, obj, showname, realname, newicon))

        if new_ones:
            self._addVulns(listholder, liststore, new_ones)

        return True

    def _addVulns(self, listholder, liststore, vulns):
        '''Adds an element to the liststore.

        @param listholder: the holder to check for instances
        @param liststore: the list itself
        @param vulns: what to add
        '''
        # order it by realname, in reverse to be able to do nice pops
        vulns.sort(key=operator.itemgetter(3), reverse=True)

        # add to listholder and instances
        for idinstance, obj, showname, realname, newicon in vulns:
            listholder.add(idinstance)
            self.instances[idinstance] = obj

        # add to the liststore, inserting into the right place to keep order
        storelen = len(liststore)
        ind = 0
        idinstance, obj, showname, realname, newicon = vulns.pop()
        while ind < storelen:
            prvshowname,prvrealname, vln,icn = liststore[ind]
            if realname <= prvrealname:
                liststore.insert(ind, (showname,realname,idinstance,newicon))
                storelen += 1

                try:
                    idinstance, obj, showname, realname, newicon = vulns.pop()
                except IndexError:
                    break
            ind += 1
        else:
            # we had some more, add them at the end
            liststore.append((showname,realname,idinstance,newicon))
            for idinstance, obj, showname, realname, newicon in vulns[::-1]:
                liststore.append((showname,realname,idinstance,newicon))

    def getInstance(self, path):
        '''Extracts the instance from the tree.

        @param path: where the user is in the tree
        @return The instance
        '''
        instanckey = self.liststore[path][2]
        instance = self.instances.get(instanckey)
        return instance

    def _dragDropped(self, tv, drag_context, x, y, selection_data, info, timestamp):
        '''Something was dropped (after a drag) on us.'''
        droppoint = tv.get_dest_row_at_pos(x, y)
        if droppoint is None:
            return True

        # collect info about source and dest
        (destpath, where) = droppoint
        sourcepath = self.exploitlist.get_cursor()[0]
        sourcerow = self.exploitlist.liststore[sourcepath]

        # it should select a destination row
        if where not in (gtk.TREE_VIEW_DROP_INTO_OR_AFTER, gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
            self.w3af.mainwin.sb(_("You must drop into a row, not in the middle of two"))
            return

        # get real objects
        exploit = self.exploitlist.getPluginInstance(sourcepath)
        dstvuln = self.getInstance(destpath)
        if dstvuln is None:
            self.w3af.mainwin.sb(_("You must select a vulnerability as destination"))
            return

        self._executeExploit(exploit, dstvuln)
        return

    def _executeExploit(self, expl, vuln):
        '''Exploits a vulnerability.

        This raises a text dialog that informs how the exploit
        is going until it finishes.
        
        This method is going to:
            a) Create the TextDialog
            b) spawn a thread to launch the exploit process
            c) spawn a thread to read from the output manager queue
        
        b and c both write messages to the TextDialog.

        @param expl: the exploit to use
        @param vuln: the vulnerability to exploit
        '''
        
        dlg = entries.TextDialog("Exploit!")
        
        # Start the generator that writes the messages from output manager
        console_task = helpers.write_console_messages(dlg)
        gobject.idle_add(console_task.next)
        
        # Start the generator that launches the exploit
        exploit_task = self._launch_exploit(dlg, expl, vuln)
        gobject.idle_add(exploit_task.next)
        
        return

    def _launch_exploit(self, dlg, expl, vuln):
        '''
        Launch the exploit and write messages to the TextDialog.
        
        @parameter dlg: The TextDialog.
        '''
        # get the info, and see if we can go for it
        dlg.addMessage("Checking suitability...\n")
        vuln_id_list = vuln.getId()
        
        yield True
        
        try:
            canexploit = expl.canExploit(vuln_id_list)
        except w3afException, e:
            dlg.addMessage(_("\nERROR: "))
            dlg.addMessage(str(e) + '\n')
            dlg.done() # set button to sensitive
            dlg.dialog_run() # wait for user response
            yield False

        if not canexploit:
            dlg.addMessage(_("Sorry, this attack plugin can not exploit this vulnerability\n"))
            dlg.done() # set button to sensitive
            dlg.dialog_run() # wait for user response
            yield False
        
        # ok, go for it!    
        dlg.addMessage(_("Ok, exploiting...\n"))
        yield True

        try:
            expl.exploit()
            yield True # print the console messages to the dialog
        except w3afException, e:
            dlg.addMessage(str(e) + '\n')
        else:
            dlg.addMessage(_("Done\n"))
            yield True

        dlg.done() # set button to sensitive
        dlg.dialog_run() # wait for user response
        
        yield False


class Proxies(gtk.Label):
    '''Dummy class to alert that this will be done later.

    @author: Facundo Batista <facundobatista =at= taniquetil.com.ar>
    '''
    def __init__(self):
        msg = "The 'Proxies' functionality\nwill be implemented\nin the future."
        super(Proxies,self).__init__(msg)
        self.set_justify(gtk.JUSTIFY_CENTER)
        self.show()

def getExploitableVulns(exploit):
    '''Returns the exploitable vulnerabilities.

    @param exploit: the exploit to search.
    '''
    try:
        vulns = exploit.getExploitableVulns()
    except w3afException:
        print "WARNING: The %r exploit has no getExploitableVulns method!" % exploit
        vulns = []
    return vulns


def effectivelyExploitAll(w3af, activatedPlugins, stopOnFirst):
    '''Exploit all the vulnerabilities.

    Just like in the 1-to-1 exploit, I'll create two generators that will perform the work
    in a "threaded" way.

    @param w3af: the core
    @param activatedPlugins: Which plugins are to be used.
    @param stopOnFirst: if the exploit should stop in the first exploited vuln.
    '''
    dlg = entries.TextDialog("Multiple Exploit!")
    
    # Start the generator that writes the messages from output manager
    console_task = helpers.write_console_messages(dlg)
    gobject.idle_add(console_task.next)
    
    # Start the generator that launches the exploit
    exploit_task = _launch_exploit_all(dlg, w3af, activatedPlugins, stopOnFirst)
    gobject.idle_add(exploit_task.next)

def _launch_exploit_all(dlg, w3af, activatedPlugins, stopOnFirst):
    '''
    A generator that will perform the exploitation of all the vulnerabilities.
    
    @param dlg: The dialog where I'm going to write the messages
    @param w3af: the core
    @param activatedPlugins: Which plugins are to be used.
    @param stopOnFirst: if the exploit should stop in the first exploited vuln.    
    '''
    for exploitname in activatedPlugins:
        dlg.addMessage(_("\nExploiting %r...\n") % exploitname)
        exploit = w3af.getPluginInstance(exploitname, "attack")
        vulns = getExploitableVulns(exploit)
        dlg.addMessage(_("  %d vulnerabilites to exploit\n") % len(vulns))
        
        yield True
        
        for vuln in vulns:
            
            # Let GTK handle events, I want a responsive GUI!
            yield True
            
            # check if o
            dlg.addMessage(("Checking suitability for vuln %r...\n") % vuln.getName())
            try:
                canexploit = exploit.canExploit(vuln.getId())
            except w3afException, e:
                dlg.addMessage(_("\nERROR: "))
                dlg.addMessage(str(e) + '\n')
                dlg.done()
                dlg.dialog_run()
                yield False
            except w3afMustStopException, wmse:
                dlg.addMessage(_("\nERROR: "))
                dlg.addMessage(str(wmse) + '\n')
                dlg.done()
                dlg.dialog_run()
                yield False
            if not canexploit:
                dlg.addMessage(_("  nop\n"))
                yield True
                continue
            dlg.addMessage(_("  ok\n"))

            # exploitable, go for it!
            dlg.addMessage(_("Exploiting...\n"))
            try:
                exploit.exploit()
            except w3afException, e:
                dlg.addMessage(str(e) + '\n')
                yield True
                continue
            except w3afMustStopException, wmse:
                dlg.addMessage(_("\nERROR:"))
                dlg.addMessage(str(wmse) + '\n')
                dlg.done()
                dlg.dialog_run()
                yield False
            
            # Let GTK handle events, I want a responsive GUI!
            yield True
            
            # it was succesful!
            if stopOnFirst:
                dlg.addMessage(_("Done\n"))
                dlg.done()
                dlg.dialog_run()
                yield False

    dlg.addMessage(_("Done\n"))
    dlg.done()
    dlg.dialog_run()
    yield False


class ExploitBody(entries.RememberingHPaned):
    '''Body of the exploit tab.

    @param w3af: the Core instance.

    @author: Facundo Batista <facundobatista =at= taniquetil.com.ar>
    '''
    def __init__(self, w3af):
        super(ExploitBody,self).__init__(w3af, "pane-exploitbody")
        self.w3af = w3af
        self.panels = {}
        
        # This is the index to use in the message diverter
        #
        # The first window that is poped up, gets 0 and starts from there
        # that window consumes messages and increases this number.
        #
        # The next window will show messages starting from were the
        # other window left the pointer.
        #
        # All the message_index handling is done with:
        #       - self.get_message_index()
        #       - self.inc_message_index()
        #
        self._message_index = 0
        kb.kb.save('get_message_index', 'get_message_index', self.get_message_index)
        kb.kb.save('inc_message_index', 'inc_message_index', self.inc_message_index)
        
        # left & right
        exploitvuln = self._buildExplVuln()
        interac = self._buildInteraction()
        self.panels["exploitvuln"] = exploitvuln
        self.panels["interac"] = interac

        # pack it all and show
        self.pack1(exploitvuln)
        self.pack2(interac)

        self.panactiv = dict((x,True) for x in self.panels)
        self.show()
        
    def inc_message_index(self):
        self._message_index += 1
        
    def get_message_index(self):
        return self._message_index

    def _buildExplVuln(self):
        '''The pane with the exploit list and vulnerabilities tree.'''
        pan = entries.RememberingHPaned(self.w3af, "pane-epxlvuln", 200)

        # left
        exploitlist = ExploitTree(self.w3af)
        scrollwin1 = gtk.ScrolledWindow()
        scrollwin1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scrollwin1.add_with_viewport(exploitlist)
        scrollwin1.show()

        # rigth
        interac = VulnerabList(self.w3af, exploitlist)
        exploitlist.vulnerabs = interac
        scrollwin2 = gtk.ScrolledWindow()
        scrollwin2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scrollwin2.add_with_viewport(interac)
        scrollwin2.show()

        # pack it all and show
        pan.pack1(scrollwin1)
        pan.pack2(scrollwin2)
        pan.show()
        return pan


    def _buildInteraction(self):
        '''The pane with the shells and proxies list.'''
        pan = entries.RememberingVPaned(self.w3af, "pane-explinteraction")

        # left
        shells = Shells(self.w3af)
        scrollwin1 = gtk.ScrolledWindow()
        scrollwin1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scrollwin1.add_with_viewport(shells)
        scrollwin1.show()

        # rigth
        proxies = Proxies()
        scrollwin2 = gtk.ScrolledWindow()
        scrollwin2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scrollwin2.add_with_viewport(proxies)
        scrollwin2.show()

        # pack it all and show
        pan.pack1(scrollwin1)
        pan.pack2(scrollwin2)
        pan.show()
        return pan

    def togglePanels(self, panel, active):
        '''Turn on and off the panels.

        @param panel: The panel to turn on and off
        @param active: If it should be activated or deactivated
        '''
        widg = self.panels[panel]
        if active:
            widg.show()
        else:
            widg.hide()
        self.panactiv[panel] = active

    def exploitAll(self):
        '''Exploit all vulns with all plugins.'''

        ea = ExploitAllDialog(self.w3af)
        resp = ea.run()
        if resp != gtk.RESPONSE_OK:
            return

        effectivelyExploitAll(self.w3af, ea.activatedPlugins, ea.stopOnFirst)
        return
