# Gufw 10.10.1 - http://gufw.tuxfamily.org
# Copyright (C) 2008-2010 Marcos Alvarez Costales <marcos@ubuntu-ast.org>
#
# Gufw 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; either version 3 of the License, or
# (at your option) any later version.
# 
# Gufw 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 Gufw; if not, see http://www.gnu.org/licenses for more
# information.

import pygtk
import gtk, gtk.glade
import gobject
import sys
import locale
import gettext
import commands
import threading

# Locale translations
DIR = "/usr/share/locale-langpack"
_ = gettext.gettext
gettext.bindtextdomain("gufw", DIR)
gettext.textdomain("gufw")
gtk.glade.bindtextdomain("gufw", DIR)
gtk.glade.textdomain("gufw")


class GuiGufw:
    """All events of glade file"""
    def __init__(self, firewall):
        self.firewall = firewall

        # Set GUI objects
        self.glade  = gtk.glade.XML(sys.path[0] + "/glade/gufw.glade")
        self.model_rules  = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING,
                                          gobject.TYPE_STRING, gobject.TYPE_STRING) 
        self.model_report = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING,
                                          gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) 
        self.render = gtk.CellRendererText()
        
        self.set_glade_objects()
        self.set_initial_GUI_values()
        self.set_window_values("")
        
        # Connect events & launch main window
        self.glade.signal_autoconnect(self)
        self.glade.get_widget("winMain").show()
        gtk.main()
    
    def set_glade_objects(self):
        """Relation between GUI & Glade objects"""
        # Main Window
        self.win_main              = self.glade.get_widget("winMain")
        self.cb_enabled_firewall   = self.glade.get_widget("cbEnabledFirewall")
        self.cb_policy_incoming    = self.glade.get_widget("cbPolicyIncoming")
        self.cb_policy_outgoing    = self.glade.get_widget("cbPolicyOutgoing")
        self.shield                = self.glade.get_widget("imgShield")
        self.blockReport           = self.glade.get_widget("blockReport")
        self.btn_add_window        = self.glade.get_widget("btnAddWindow")
        self.btn_remove_rule       = self.glade.get_widget("btnRemove")
        self.status_bar            = self.glade.get_widget("statusBar")
        self.progress_bar          = self.glade.get_widget("progressBar")
        self.separator_progressbar = self.glade.get_widget("separator_progressbar")
        
        # Font
        self.render.set_property("font", "monospace 10")
        # Rules
        self.tv_rules = self.glade.get_widget("tvRules")
        self.tv_rules.set_model(self.model_rules)
        self.tv_rules.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        # The format columns
        tree_header = gtk.TreeViewColumn (_("To"), self.render, text=1, foreground=4)
        tree_header.set_resizable(True)
        self.tv_rules.append_column (tree_header)
        tree_header = gtk.TreeViewColumn (_("Action"), self.render, text=2, foreground=4)
        tree_header.set_resizable(True)
        self.tv_rules.append_column (tree_header)
        tree_header = gtk.TreeViewColumn (_("From"), self.render, text=3, foreground=4)
        self.tv_rules.append_column (tree_header)
        
        # Listening Report
        self.tv_report = self.glade.get_widget("tvReport")
        self.tv_report.set_model(self.model_report)
        self.tv_report.get_selection().set_mode(gtk.SELECTION_NONE)
        # The format columns
        tree_header = gtk.TreeViewColumn (_("Protocol"), self.render, text=1, foreground=5)
        tree_header.set_resizable(True)
        self.tv_report.append_column (tree_header)
        tree_header = gtk.TreeViewColumn (_("Port"), self.render, text=2, foreground=5)
        tree_header.set_resizable(True)
        self.tv_report.append_column (tree_header)
        tree_header = gtk.TreeViewColumn (_("Address"), self.render, text=3, foreground=5)
        tree_header.set_resizable(True)
        self.tv_report.append_column (tree_header)
        tree_header = gtk.TreeViewColumn (_("Application"), self.render, text=4, foreground=5)
        self.tv_report.append_column (tree_header)
        
        # Preconf
        self.extended_actions          = self.glade.get_widget("cbExtendedActions")
        self.insert_number_preconf     = self.glade.get_widget("sbInsertNumberPreconf")
        self.box_insert_number_preconf = self.glade.get_widget("boxInsertNumberPreconf")
        self.direction_preconf         = self.glade.get_widget("cbDirectionPreconf")
        self.action_preconf            = self.glade.get_widget("cbActionPreconf")
        self.direction_preconf         = self.glade.get_widget("cbDirectionPreconf")
        self.log_preconf               = self.glade.get_widget("cbLogPreconf")
        self.box_log_preconf           = self.glade.get_widget("boxLogPreconf")
        self.type_preconf              = self.glade.get_widget("cbTypePreconf")
        self.service_preconf           = self.glade.get_widget("cbServicePreconf")
        self.box_service_preconf       = self.glade.get_widget("boxServicePreconf")
        self.program_preconf           = self.glade.get_widget("cbProgramPreconf")
        self.box_program_preconf       = self.glade.get_widget("boxProgramPreconf")
        # Simple
        self.insert_number_simple     = self.glade.get_widget("sbInsertNumberSimple")
        self.box_insert_number_simple = self.glade.get_widget("boxInsertNumberSimple")
        self.direction_simple         = self.glade.get_widget("cbDirectionSimple")
        self.action_simple            = self.glade.get_widget("cbActionSimple")
        self.direction_simple         = self.glade.get_widget("cbDirectionSimple")
        self.log_simple               = self.glade.get_widget("cbLogSimple")
        self.box_log_simple           = self.glade.get_widget("boxLogSimple")
        self.port_simple              = self.glade.get_widget("entryPortSimple")
        self.proto_simple             = self.glade.get_widget("cbProtoSimple")
        # Advanced
        self.insert_number_advanced     = self.glade.get_widget("sbInsertNumberAdvanced")
        self.box_insert_number_advanced = self.glade.get_widget("boxInsertNumberAdvanced")
        self.action_advanced            = self.glade.get_widget("cbActionAdvanced")
        self.direction_advanced         = self.glade.get_widget("cbDirectionAdvanced")
        self.direction_advanced         = self.glade.get_widget("cbDirectionAdvanced")
        self.log_advanced               = self.glade.get_widget("cbLogAdvanced")
        self.box_log_advanced           = self.glade.get_widget("boxLogAdvanced")
        self.proto_advanced             = self.glade.get_widget("cbProtoAdvanced")
        self.fromip_advanced            = self.glade.get_widget("entryFromIpAdvanced")
        self.portfrom_advanced          = self.glade.get_widget("entryPortFromAdvanced")
        self.toip_advanced              = self.glade.get_widget("entryToIpAdvanced")
        self.portto_advanced            = self.glade.get_widget("entryPortToAdvanced")
        self.rules_notebook             = self.glade.get_widget("rulesNotebook")
        self.add_btn_add                = self.glade.get_widget("btnAddRule")
        # Log Window
        self.winlog         = self.glade.get_widget("winLog")
        self.log_txt        = self.glade.get_widget("logTxt")
        self.log_txt_buffer = self.log_txt.get_buffer()
        self.log_btn_close  = self.glade.get_widget("btnCloseLog")
        self.server_script  = self.glade.get_widget("cbServerScript")
        # Preference Window
        self.winpreferences = self.glade.get_widget("winPreferences")
        self.cb_report      = self.glade.get_widget("cbReport")
        self.cb_ufw_log     = self.glade.get_widget("cbUfwLog")
        self.lbl_ufw_level  = self.glade.get_widget("lblLogLevel")
        self.cb_ufw_level   = self.glade.get_widget("cbLogLevel")
        self.cb_gufw_log    = self.glade.get_widget("cbGufwLog") 
        self.pref_btn_close = self.glade.get_widget("btnClosePref")
        # Menu
        self.menu_log    = self.glade.get_widget("menuLog")
        self.menu_pref   = self.glade.get_widget("menuPreferences")
        self.menu_add    = self.glade.get_widget("menuAddRule")
        self.menu_remove = self.glade.get_widget("menuRemoveRule")
        # About Dialog
        self.winabout = self.glade.get_widget("winAbout")
        self.winabout.set_translator_credits(_("translator-credits"))
    
    def set_initial_GUI_values(self):
        """Set initial values in Interface"""
        # Restore previus size window
        self.set_old_size_window()
        # ComboBoxs active item (Bug http://acurti.es/wwa)
        self.direction_simple.set_active(0)
        self.action_simple.set_active(0)     
        self.log_simple.set_active(0)
        self.proto_simple.set_active(0)    
        self.direction_preconf.set_active(0)
        self.action_preconf.set_active(0)    
        self.log_preconf.set_active(0)
        self.type_preconf.set_active(0)      
        self.service_preconf.set_active(0)   
        self.program_preconf.set_active(0)
        self.direction_advanced.set_active(0)
        self.action_advanced.set_active(0)   
        self.log_advanced.set_active(0)
        self.proto_advanced.set_active(0)    
        # Focus
        self.btn_add_window.grab_focus()
        
        if self.firewall.get_report() == "enable":
            self.blockReport.show()
            self.start_refresh = "enable"
            self.refresh_report()
        else:
            self.blockReport.hide()
            self.start_refresh = "disable"
        
    def set_old_size_window(self):
        """Save Actual size window"""
        width_height = commands.getstatusoutput("grep sizewin /etc/gufw/gufw.cfg")
        if width_height[0] == 0:
            width_height_split = (width_height[1].replace("sizewin=", "")).split("x")
            width  = int(width_height_split[0])
            height = int(width_height_split[1])
        else:
            width  = 336
            height = 334
            
        screen_width  = gtk.gdk.screen_width()
        screen_height = gtk.gdk.screen_height()

        if ( width == screen_width ) and ( height== screen_height ):
            self.win_main.maximize()
        else:
            self.win_main.resize(width,height)
    
    def set_window_values(self, msg_status_bar):
        """Set initials status to glade objects"""
        # Firewall Enable
        self.cb_enabled_firewall.set_sensitive(1)
        if self.firewall.get_status() == "enable":
            self.cb_enabled_firewall.set_active(1)
        
        # Listening report
        if self.firewall.get_report() == "enable":
            self.blockReport.show()
        else:
            self.blockReport.hide()
        
        # Allow/Deny/Reject Incoming
        if self.firewall.get_default_policy("incoming") == "deny":
            self.cb_policy_incoming.set_active(0)
        elif self.firewall.get_default_policy("incoming") == "reject":
            self.cb_policy_incoming.set_active(1)
        elif self.firewall.get_default_policy("incoming") == "allow":
            self.cb_policy_incoming.set_active(2)
            
        # Allow/Deny/Reject Outgoing
        if self.firewall.get_default_policy("outgoing") == "deny":
            self.cb_policy_outgoing.set_active(0)
        elif self.firewall.get_default_policy("outgoing") == "reject":
            self.cb_policy_outgoing.set_active(1)
        elif self.firewall.get_default_policy("outgoing") == "allow":
            self.cb_policy_outgoing.set_active(2)
               
        # Msg status bar GUI
        self.status_bar.push(1, msg_status_bar)
        
        # Set sensitive values by status firewall
        if self.firewall.get_status() == "disable":
            self.cb_policy_incoming.set_sensitive(0)
            self.cb_policy_outgoing.set_sensitive(0)
            self.add_btn_add.set_sensitive(0)
            self.btn_remove_rule.set_sensitive(0)
            self.menu_remove.set_sensitive(0)
            self.shield.set_from_file("/usr/share/pixmaps/gufw/disable_disable.png")
        else:
            self.cb_policy_incoming.set_sensitive(1)
            self.cb_policy_outgoing.set_sensitive(1)
            self.add_btn_add.set_sensitive(1)
            if len(self.firewall.get_rules()) == 0:
                self.btn_remove_rule.set_sensitive(0)
                self.menu_remove.set_sensitive(0)
            else:
                self.btn_remove_rule.set_sensitive(1)
                self.menu_remove.set_sensitive(1)
            
            shield = "/usr/share/pixmaps/gufw/" +                   \
                     self.firewall.get_default_policy("incoming") + \
                     "_" +                                          \
                     self.firewall.get_default_policy("outgoing") + \
                     ".png"
            self.shield.set_from_file(shield)
                
        # Menu
        self.menu_pref.set_sensitive(1)
        if self.firewall.get_gufw_logging() == "enable":
            self.menu_log.set_sensitive(1)
        else:
            self.menu_log.set_sensitive(0)
           
        # Set actual rules
        self.set_text_rules()
        
    def set_text_rules(self):
        """Show rules in GUI"""
        self.model_rules.clear() 
        
        if self.firewall.get_status() == "disable":
            return
        
        row = 0
        # GNOME Palette
        color = { "gray"   : "#BAB5AB",  # Basic 3D Medium
                  "green"  : "#267726",  # Accent Green Dark
                  "red"    : "#DF421E",  # Accent Red
                  "orange" : "#D1940C",  # Accent Yellow Dark
                  "blue"   : "#314E6C" } # Blue Shadow
        
        rules = self.firewall.get_rules()
        for rule in rules:
            row += 1
            iterador = self.model_rules.insert(row)
            
            # Color Allow/Deny/Reject/Limit
            # IN mode (equal to normal mode, persist code for clear read)
            if rule.find("ALLOW IN") != -1:
                split_str = "ALLOW IN"
                if self.firewall.get_default_policy("incoming") != "allow":
                    self.model_rules.set_value(iterador, 4, color["red"])
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Deny?
            elif rule.find("DENY IN") != -1:
                split_str = "DENY IN"
                if self.firewall.get_default_policy("incoming") != "deny":
                    self.model_rules.set_value(iterador, 4, color["green"])
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Reject
            elif rule.find("REJECT IN") != -1:
                split_str = "REJECT IN"
                if self.firewall.get_default_policy("incoming") != "reject":
                    self.model_rules.set_value(iterador, 4, color["blue"])
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Limit?
            elif rule.find("LIMIT IN") != -1:
                split_str = "LIMIT IN"
                self.model_rules.set_value(iterador, 4, color["orange"])
            
            # OUT mode
            elif rule.find("ALLOW OUT") != -1: 
                split_str = "ALLOW OUT"
                if self.firewall.get_default_policy("outgoing") != "allow":
                    self.model_rules.set_value(iterador, 4, color["red"]) 
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Deny?
            elif rule.find("DENY OUT") != -1:
                split_str = "DENY OUT"
                if self.firewall.get_default_policy("outgoing") != "deny":
                    self.model_rules.set_value(iterador, 4, color["green"])
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Reject
            elif rule.find("REJECT OUT") != -1:
                split_str = "REJECT OUT"
                if self.firewall.get_default_policy("outgoing") != "reject":
                    self.model_rules.set_value(iterador, 4, color["blue"])
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Limit?
            elif rule.find("LIMIT OUT") != -1:
                split_str = "LIMIT OUT"
                self.model_rules.set_value(iterador, 4, color["orange"])
                
            # NORMAL mode
            # Allow?
            elif rule.find("ALLOW") != -1: 
                split_str = "ALLOW"
                if self.firewall.get_default_policy("incoming") != "allow":
                    self.model_rules.set_value(iterador, 4, color["red"]) 
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Deny?
            elif rule.find("DENY") != -1:
                split_str = "DENY"
                if self.firewall.get_default_policy("incoming") != "deny":
                    self.model_rules.set_value(iterador, 4, color["green"])
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Reject
            elif rule.find("REJECT") != -1:
                split_str = "REJECT"
                if self.firewall.get_default_policy("incoming") != "reject":
                    self.model_rules.set_value(iterador, 4, color["blue"])
                else:
                    self.model_rules.set_value(iterador, 4, color["gray"])
            # Limit?
            elif rule.find("LIMIT") != -1:
                split_str = "LIMIT"
                self.model_rules.set_value(iterador, 4, color["orange"])
            
            # Values
            rule_split = rule.split(split_str)
            self.model_rules.set_value(iterador, 0, row) # Row (use for remove rule)
            self.model_rules.set_value(iterador, 1, rule_split[0].strip())
            self.model_rules.set_value(iterador, 2, split_str)
            self.model_rules.set_value(iterador, 3, rule_split[1].strip())
            
    # Save Actual size window
    def save_actual_window_size(self):
        """Save actual size main window for next instances"""
        new_size = "sizewin=&1x&2"
        width, height = self.win_main.get_size()
        new_size = new_size.replace("&1", str(width))
        new_size = new_size.replace("&2", str(height))
        cmd = "sed -i 's/sizewin.*$/new_size_window/' /etc/gufw/gufw.cfg"
        cmd = cmd.replace("new_size_window", new_size)
        commands.getstatusoutput(cmd)

    # Save Actual listening report
    def save_actual_report(self):
        """Save actual listening report for next instances"""
        if self.firewall.get_report() == "enable":
            cmd = "sed -i 's/report.*$/report=enable/' /etc/gufw/gufw.cfg"
            commands.getstatusoutput(cmd)
        else:
            cmd = "sed -i 's/report.*$/report=disable/' /etc/gufw/gufw.cfg"
            commands.getstatusoutput(cmd)






    # EVENTS
    """Events Glade"""
    
    # Close Windows
    def winMain_delete_event_cb(self, widget, event):
        self.save_actual_window_size()
        self.save_actual_report()
        gtk.main_quit()

    # Menu Quit
    def menuQuit_activate_cb(self, widget):
        self.save_actual_window_size()
        self.save_actual_report()
        gtk.main_quit()
    
    # Button Add
    def btnAddWindow_clicked_cb(self, widget):
        self.glade.get_widget("winAdd").show()
        self.add_btn_add.grab_focus()
        self.btn_add_window.set_sensitive(0)
        self.menu_add.set_sensitive(0)
    
    # Menu Add Rule
    def menuAddRule_activate_cb(self,widget):
        self.glade.get_widget("winAdd").show()
        self.add_btn_add.grab_focus()
        self.btn_add_window.set_sensitive(0)
        self.menu_add.set_sensitive(0)

    # Close Window Add Rules
    def winAdd_delete_event_cb(self, widget, event):
        self.glade.get_widget("winAdd").hide()
        self.btn_add_window.set_sensitive(1)
        self.menu_add.set_sensitive(1)
        return True
       
    # Button Close Add Rules
    def btnCloseAdd_clicked_cb(self, widget):
        self.glade.get_widget("winAdd").hide()
        self.btn_add_window.set_sensitive(1)
        self.menu_add.set_sensitive(1)
        return True
    
    # Close preferences Window
    def winPreferences_delete_event_cb(self, widget, event):
        self.glade.get_widget("winPreferences").hide()
        return True
    
    # Close preferences Button
    def btnClosePref_clicked_cb(self, widget):
        self.glade.get_widget("winPreferences").hide()
        return True
    
    # Close Log Window
    def winLog_delete_event_cb(self, widget, event):
        self.glade.get_widget("winLog").hide()
        return True
    
    # Close Log button
    def btnCloseLog_clicked_cb(self, widget):
        self.glade.get_widget("winLog").hide()
        return True
    
    # Press Scape Key Add Window
    def winAdd_key_press_event_cb(self, widget, event):
        if event.keyval == gtk.keysyms.Escape :
            self.glade.get_widget("winAdd").hide()
            self.btn_add_window.set_sensitive(1)
            self.menu_add.set_sensitive(1)
            return True    
    
    # Press Scape Key Preferences Window
    def winPreferences_key_press_event_cb(self, widget, event):
        if event.keyval == gtk.keysyms.Escape :
            self.glade.get_widget("winPreferences").hide()
            return True  
    
    # Press Scape Key Log Window
    def winLog_key_press_event_cb(self, widget, event):
        if event.keyval == gtk.keysyms.Escape :
            self.glade.get_widget("winLog").hide()
            return True  





    # MENU
    """Menu GUI events"""
    
    # Show Preferences
    def menuPreferences_activate_cb(self, widget):
        # Set initial values
        if self.firewall.get_report() == "enable":
            self.cb_report.set_active(1)
        else:
            self.cb_report.set_active(0)
        
        if self.firewall.get_status() == "disable":
            self.cb_ufw_log.set_active(0)
            self.cb_ufw_log.set_sensitive(0)
            self.cb_ufw_level.set_sensitive(0)
            self.lbl_ufw_level.set_sensitive(0)
        else:
            self.firewall.refresh_ufw_logging()
            if self.firewall.get_ufw_logging() == "off":
                self.cb_ufw_log.set_active(0)
                self.cb_ufw_log.set_sensitive(1)
                self.cb_ufw_level.set_sensitive(0)
                self.lbl_ufw_level.set_sensitive(0)
            else:
                self.cb_ufw_log.set_active(1)
                self.cb_ufw_log.set_sensitive(1)
                self.cb_ufw_level.set_sensitive(1)
                self.lbl_ufw_level.set_sensitive(1)
                if self.firewall.get_ufw_logging() == "low":
                    self.cb_ufw_level.set_active(0)
                elif self.firewall.get_ufw_logging() == "medium":
                    self.cb_ufw_level.set_active(1)
                elif self.firewall.get_ufw_logging() == "high":
                    self.cb_ufw_level.set_active(2)
                else:
                    self.cb_ufw_level.set_active(3)
            
        if self.firewall.get_gufw_logging() == "enable":
            self.cb_gufw_log.set_active(1)
        else:
            self.cb_gufw_log.set_active(0)
            
        # Show Window
        self.status_bar.push(1, "")
        self.winpreferences.show()
        self.pref_btn_close.grab_focus()
    
    # Change Logging Level
    def cbLogLevel_changed_cb(self, widget):
        if ( self.cb_ufw_level.get_active() == 0 ) and ( self.firewall.get_ufw_logging() != "low" ):
            self.firewall.set_ufw_logging("low")
        elif ( self.cb_ufw_level.get_active() == 1 ) and ( self.firewall.get_ufw_logging() != "medium" ):
            self.firewall.set_ufw_logging("medium")
        elif ( self.cb_ufw_level.get_active() == 2 ) and ( self.firewall.get_ufw_logging() != "high" ):
            self.firewall.set_ufw_logging("high")
        elif ( self.cb_ufw_level.get_active() == 3 ) and ( self.firewall.get_ufw_logging() != "full" ):
            self.firewall.set_ufw_logging("full")
    
    # Open About Dialog
    def menuAbout_activate_cb(self, widget):
        self.status_bar.push(1, "")
        self.winabout.show()
        self.winabout.run()
        self.winabout.hide()
    
    # Log Window
    def menuLog_activate_cb(self, widget):
        # Set Log Text
        local_log, server_log = self.firewall.get_gufw_log()
        if self.server_script.get_active() == 1:
            self.log_txt_buffer.set_text(server_log)
        else:
            self.log_txt_buffer.set_text(local_log)
        self.status_bar.push(1, "")
        # Show Window
        self.winlog.show()
        self.log_btn_close.grab_focus()
    
    # Reset all rules
    def menuReset_activate_cb(self, widget):
        reset_dialog = gtk.MessageDialog(parent=self.win_main,
                                         flags=0,
                                         type=gtk.MESSAGE_WARNING,
                                         buttons=gtk.BUTTONS_OK_CANCEL,
                                         message_format=_("You will remove all rules and reset the firewall!"))
        reset_dialog.format_secondary_markup(_("Do you want to continue?"))
        reset_dialog.set_title(_("Reset to initial configuration"))
        reset_dialog.set_default_response(gtk.RESPONSE_CANCEL)
        reset_answer = reset_dialog.run()
        reset_dialog.destroy()
        if reset_answer == gtk.RESPONSE_OK:
            if self.firewall.get_status() == "enable":
                self.cb_enabled_firewall.set_active(0)
            self.firewall.reset_configuration()
            self.set_window_values(_("Removed rules and reset firewall!"))






    # BUTTONS PREFERENCE WINDOW 
    """Button preference window"""

    # ufw Log CheckButton
    def cbUfwLog_toggled_cb(self, widget):
        if self.firewall.get_ufw_logging() != "off" and self.cb_ufw_log.get_active() == 0:
            self.firewall.set_ufw_logging("off")
            self.cb_ufw_log.set_active(0)
            self.cb_ufw_level.set_sensitive(0)
            self.lbl_ufw_level.set_sensitive(0)
            
        elif self.firewall.get_ufw_logging() == "off" and self.cb_ufw_log.get_active() == 1:
            self.firewall.set_ufw_logging("on")
            self.cb_ufw_log.set_active(1)
            self.cb_ufw_level.set_sensitive(1)
            self.cb_ufw_level.set_active(0)
            self.lbl_ufw_level.set_sensitive(1)
            
    # Gufw Log CheckButton   
    def cbGufwLog_toggled_cb(self, widget):
        if self.firewall.get_gufw_logging() != "enable" and self.cb_gufw_log.get_active() == 1:
            self.firewall.set_gufw_logging("enable")
        elif self.firewall.get_gufw_logging() != "disable" and self.cb_gufw_log.get_active() == 0:
            self.firewall.set_gufw_logging("disable")
        self.set_window_values("")
    
    # Listening report
    def cbReport_toggled_cb(self, widget):
        if self.firewall.get_report() == "disable" and self.cb_report.get_active() == 1:
            self.firewall.set_report("enable")
            self.blockReport.show()
            self.start_refresh = "enable"
        
        elif self.firewall.get_report() == "enable" and self.cb_report.get_active() == 0:
            self.firewall.set_report("disable")
            self.blockReport.hide()
            self.start_refresh = "disable"
        
        self.refresh_report()







    # BUTTONS LOG WINDOW
    """Events buttons log window"""

    # Clear Log
    def btnClearLog_clicked_cb(self, widget):
        self.firewall.remove_gufw_log()
        self.log_txt_buffer.set_text("")
        self.log_btn_close.grab_focus()
    
    # Server Script
    def cbServerScript_toggled_cb(self, widget):
        # Set Log Text
        local_log, server_log = self.firewall.get_gufw_log()
        if self.server_script.get_active() == 1:
            self.log_txt_buffer.set_text(server_log)
        else:
            self.log_txt_buffer.set_text(local_log)







    # BUTTONS MAIN WINDOW
    """Events buttons main window"""
    
    # Button Firewall Enabled
    def cbEnabledFirewall_clicked_cb(self, widget):
        if self.firewall.get_status() == "enable":
            self.firewall.set_status("disable")
            self.add_btn_add.set_sensitive(0)
            self.set_window_values(_("Disabled firewall"))
        else:
            self.firewall.set_status("enable")
            self.add_btn_add.set_sensitive(1)
            self.set_window_values(_("Enabled firewall"))
    
    # Policy (Deny/Allow/Reject All) Incoming
    def cbPolicyIncoming_changed_cb(self, widget):
        # Apply?
        if self.firewall.get_default_policy("incoming") == "deny"   and self.cb_policy_incoming.get_active() == 0:
            return
        if self.firewall.get_default_policy("incoming") == "reject" and self.cb_policy_incoming.get_active() == 1:
            return
        if self.firewall.get_default_policy("incoming") == "allow"  and self.cb_policy_incoming.get_active() == 2:
            return
        
        if self.cb_policy_incoming.get_active() == 0:
            self.firewall.set_default_policy("incoming","deny")
            self.set_window_values(_("Deny all INCOMING traffic"))
            return
        elif self.cb_policy_incoming.get_active() == 1:
            self.firewall.set_default_policy("incoming","reject")
            self.set_window_values(_("Reject all INCOMING traffic"))
            return
        elif self.cb_policy_incoming.get_active() == 2:
            self.firewall.set_default_policy("incoming","allow")
            self.set_window_values(_("Allow all INCOMING traffic"))
            
            
    # Policy (Deny/Allow/Reject All) Outgoing
    def cbPolicyOutgoing_changed_cb(self, widget):
        # Apply?
        if self.firewall.get_default_policy("outgoing") == "deny"   and self.cb_policy_outgoing.get_active() == 0:
            return
        if self.firewall.get_default_policy("outgoing") == "reject" and self.cb_policy_outgoing.get_active() == 1:
            return
        if self.firewall.get_default_policy("outgoing") == "allow"  and self.cb_policy_outgoing.get_active() == 2:
            return
        
        if self.cb_policy_outgoing.get_active() == 0:
            self.firewall.set_default_policy("outgoing","deny")
            self.set_window_values(_("Deny all OUTGOING traffic"))
            return
        elif self.cb_policy_outgoing.get_active() == 1:
            self.firewall.set_default_policy("outgoing","reject")
            self.set_window_values(_("Reject all OUTGOING traffic"))
            return
        elif self.cb_policy_outgoing.get_active() == 2:
            self.firewall.set_default_policy("outgoing","allow")
            self.set_window_values(_("Allow all OUTGOING traffic"))
    
    # Menu Remove Rule
    def menuRemoveRule_activate_cb(self, widget):
        # Remove in 2 plan
        task = self.remove_rules()
        gobject.idle_add(task.next)
    
    # Button Remove Rules(s)
    def btnRemove_clicked_cb(self, widget):
        # Remove in 2 plan
        task = self.remove_rules()
        gobject.idle_add(task.next)
            
    # Refresh method in background (no freeze)
    def do_refresh_report(self):
        listening_lines = self.firewall.get_listening_report()
        background_job = RefreshReport(self.firewall.get_status(),self.model_report, listening_lines)
        background_job.start()
        if self.start_refresh == "enable":
            return True
        else:
            return False
    
    # Button refresh Listening report
    def refresh_report(self):
        gobject.timeout_add(1500, self.do_refresh_report)
        
    # Remove Rules Method
    def remove_rules(self):
        tree,iter  = self.tv_rules.get_selection().get_selected_rows()
        removed    = 0
        actual_row = 0
        total_rows = len(iter)
           
        if total_rows == 0:
            self.set_window_values(_("Select rule(s)"))
            yield None
            return

        # No sensitive buttons
        # Main Window
        self.status_bar.push(1, _("Removing rules..."))
        self.progress_bar.show()
        self.separator_progressbar.show()
        self.cb_enabled_firewall.set_sensitive(0)
        self.cb_policy_incoming.set_sensitive(0)
        self.btn_remove_rule.set_sensitive(0)
        self.menu_remove.set_sensitive(0)
        # Rules Window
        self.add_btn_add.set_sensitive(0)
        # Menus
        self.menu_pref.set_sensitive(0)

        # For one row selected
        iter.reverse() # Remove first the last rules for not overwrite rules
        for item in iter:
            
            # Get rule selected (row number)
            number_rule_row = tree.get_value(tree.get_iter(item),0)
            
            # Move Progress Bar
            actual_row += 1
            progress = float(actual_row) / float(total_rows)
            if progress > 1:
                progress = 1.0
            self.progress_bar.set_fraction(progress)
            yield True
            
            result = self.firewall.remove_rule(number_rule_row)
            if result == 0:
                removed += 1

        # Clean Progress Bar
        self.progress_bar.set_fraction(0)
        self.progress_bar.hide()
        self.separator_progressbar.hide()
        
        if removed == 1:
            self.set_window_values(_("Rule removed"))
        elif removed > 1:
            self.set_window_values(_("Rules removed"))
        else:
            self.set_window_values(_("Error performing operation"))
        
        yield None


        

# BUTTONS ADD WINDOW
    
    # Add rule Button
    def btnAddRule_clicked_cb(self, widget):
        # Add a simple rule
        if self.rules_notebook.get_current_page() == 0:
            self.add_rule_preconf()
        # Add a preconfigured rule
        elif self.rules_notebook.get_current_page() == 1:
            self.add_rule_simple()
        # Add an advanced rule
        elif self.rules_notebook.get_current_page() == 2:
            self.add_rule_advanced()
    
    def add_rule_preconf(self):
        """Add a preconfigured rule"""
        # Define Programs (Split by #)
        programs = { "Amule"        : "4662tcp#4672udp",
                     "Deluge"       : "6881:6891tcp",
                     "KTorrent"     : "6881tcp#4444udp",
                     "Nicotine"     : "2234:2239tcp#2242tcp",
                     "qBittorrent"  : "6881tcp",
                     "Transmission" : "51413tcp#51413udp" }
        # Define Services 
        services = { "FTP"         : "ftp",
                     "HTTP"        : "http",
                     "IMAP"        : "imap",
                     "NFS"         : "nfs",
                     "POP3"        : "pop3",
                     "Samba"       : "135,139,445tcp|137,138udp",
                     "SMTP"        : "smtp",
                     "ssh"         : "ssh",
                     "VNC"         : "5900tcp",
                     "zeroconf"    : "5353udp" }
        # Insert Number
        if self.extended_actions.get_active() != 0: # Visible?
            insert_number = str(self.insert_number_preconf.get_value_as_int())
        else:
            insert_number = "0"
        
        # Allow|deny|Limit
        if self.action_preconf.get_active() == 0:
            action = "allow"
        elif self.action_preconf.get_active() == 1:
            action = "deny"
        elif self.action_preconf.get_active() == 2:
            action = "reject"
        else:
            action = "limit"
            
        # IN/OUT
        if self.direction_preconf.get_active() == 0:
            direction = "in"
        else:
            direction = "out"
            
        # Log
        if self.extended_actions.get_active() != 0: # Visible?
            if self.log_preconf.get_active() == 0:
                log = "log-default"
            elif self.log_preconf.get_active() == 1:
                log = "log"
            else:
                log = "log-all"
        else:
            log = "log-default"
            
        # Service?
        if self.type_preconf.get_active() == 1:
            service_txt = services[self.service_preconf.get_active_text()]
            
            operation_done = " "
            all_ports = service_txt.split("|")
            for port_proto in all_ports:
            
                if port_proto.find("tcp") != -1:
                    port     = port_proto.replace("tcp", "")
                    protocol = "tcp"
                    is_program = True
                elif port_proto.find("udp") != -1:
                    port     = port_proto.replace("udp", "")
                    protocol = "udp"
                    is_program = True
                elif port_proto.find("both") != -1:
                    port     = port_proto.replace("both", "")
                    protocol = "both"
                    is_program = True
                else:
                    port     = port_proto
                    protocol = ""
                    is_program = False
                    
                # TODO Add rule service
                result = self.firewall.add_rule(is_program, insert_number, action, direction, log, protocol, "", "", "", port)
                if result == 0:
                    operation_done = "X"
                    
            if operation_done == "X":
                self.set_window_values(_("Rule added"))
            else:
                self.set_window_values(_("Error performing operation"))
              
        # Program?
        else:
            port_proto   = programs[self.program_preconf.get_active_text()]
            ports_protos = port_proto.split("#")
            added = 0
            
            for prog in ports_protos:
                if prog.find("tcp") != -1:
                    port     = prog.replace("tcp", "")
                    protocol = "tcp"
                elif prog.find("udp") != -1:
                    port     = prog.replace("udp", "")
                    protocol = "udp"
                elif prog.find("both") != -1:
                    port     = prog.replace("both", "")
                    protocol = "both"
                    
                # TODO Add rule program
                result = self.firewall.add_rule(True, insert_number, action, direction, log, protocol, "", "", "", port)
                if result == 0:
                    added += 1
                    
            if added == 1: 
                self.set_window_values(_("Rule added"))
            elif added > 1:
                self.set_window_values(_("Rules added"))
            else:
                self.set_window_values(_("Error performing operation"))
    
    def add_rule_simple(self):
        """Add a simple rule"""
        # Insert Number
        if self.extended_actions.get_active() != 0: # Visible?
            insert_number = str(self.insert_number_simple.get_value_as_int())
        else:
            insert_number = "0"
        
        # Allow|deny|Limit
        if self.action_simple.get_active() == 0:
            action = "allow"
        elif self.action_simple.get_active() == 1:
            action = "deny"
        elif self.action_simple.get_active() == 2:
            action = "reject"
        else:
            action = "limit"
            
        # IN/OUT
        if self.direction_simple.get_active() == 0:
            direction = "in"
        else:
            direction = "out"
        
        # Log
        if self.extended_actions.get_active() != 0: # Visible?
            if self.log_simple.get_active() == 0:
                log = "log-default"
            elif self.log_simple.get_active() == 1:
                log = "log"
            else:
                log = "log-all"
        else:
            log = "log-default"
            
        # Protocol
        if self.proto_simple.get_active() == 0:
            protocol = "tcp"
        elif self.proto_simple.get_active() == 1:
            protocol = "udp"
        else:
            protocol = "both"

        # Port
        port = self.port_simple.get_text()
        
        # ? -> !
        if port == "freedom":
            dlg_egg = gtk.MessageDialog(parent=self.win_main, flags=0, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_CLOSE, message_format="I could have made money this way, and perhaps amused myself writing code. But I knew that at the end of my career, I would look back on years of building walls to divide people, and feel I had spent my life making the world a worse place.")
            dlg_egg.format_secondary_markup("Richard Stallman")
            dlg_egg.set_title("It's time to think!")
            dlg_egg.run()
            dlg_egg.destroy()
            return
        
        # Validate port
        if port == "":
            self.set_window_values(_("Error: Insert a port number"))
            return
            
        # Validate both and not range ports
        if ( port.find(":") != -1 ) and protocol == "both":
            self.set_window_values(_("Error: Range ports only with tcp or udp protocol"))
            return
            
        # Add rule
        result = self.firewall.add_rule(True, insert_number, action, direction, log, protocol, "", "", "", port)
        if result == 0:
            self.set_window_values(_("Rule added"))
        else:
            self.set_window_values(_("Error performing operation"))
        
    def add_rule_advanced(self):
        """Add an advanced rule"""
        # Insert Number
        if self.extended_actions.get_active() != 0: # Visible?
            insert_number = str(self.insert_number_advanced.get_value_as_int())
        else:
            insert_number = "0"

        # Deny|Reject|Allow|Limit
        if self.action_advanced.get_active() == 0:
            action = "allow"
        elif self.action_advanced.get_active() == 1:
            action = "deny"
        elif self.action_advanced.get_active() == 2:
            action = "reject"
        else:
            action = "limit"
            
        # IN/OUT
        if self.direction_advanced.get_active() == 0:
            direction = "in"
        else:
            direction = "out"
            
        # Log
        if self.extended_actions.get_active() != 0: # Visible?
            if self.log_advanced.get_active() == 0:
                log = "log-default"
            elif self.log_advanced.get_active() == 1:
                log = "log"
            else:
                log = "log-all"
        else:
            log = "log-default"
            
        # Protocol
        if self.proto_advanced.get_active() == 0:
            protocol = "tcp"
        elif self.proto_advanced.get_active() == 1:
            protocol = "udp"
        else:
            protocol = "both"
                
        # From
        fromip   = self.fromip_advanced.get_text()
        fromport = self.portfrom_advanced.get_text()
        
        # To
        toip   = self.toip_advanced.get_text()
        toport = self.portto_advanced.get_text() 
        
        # Validate values
        if fromip == "" and fromport == "" and toip == "" and toport == "":
            self.set_window_values(_("Error: Fields filled out incorrectly"))
            return

        # Validate both and not range ports in FROM
        if ( fromport != "" and fromport.find(":") != -1 ) and protocol == "both":
            self.set_window_values(_("Error: Range ports only with tcp or udp protocol"))
            return
        # Validate both and not range ports in TO            
        if ( toport != "" and toport.find(":") != -1 ) and protocol == "both":
            self.set_window_values(_("Error: Range ports only with tcp or udp protocol"))
            return
                    
        # Add rule program
        result = self.firewall.add_rule(True, insert_number, action, direction, log, protocol, fromip, fromport, toip, toport)
        if result == 0:
            self.set_window_values(_("Rule added"))
        else:
            self.set_window_values(_("Error performing operation"))
    
    # Change between Service/Program
    def cbTypePreconf_changed_cb(self, widget):
        if self.type_preconf.get_active() == 0:
            self.box_service_preconf.hide()   
            self.box_program_preconf.show()   
        else:
            self.box_service_preconf.show()   
            self.box_program_preconf.hide()   
    
    # Clear values
    def btnCleanAdvanced_clicked_cb(self, widget):
        self.fromip_advanced.set_text("")
        self.portfrom_advanced.set_text("")
        self.toip_advanced.set_text("")
        self.portto_advanced.set_text("")
    
    # Extended actions
    def cbExtendedActions_toggled_cb(self, widget):
        # Set hide extended actions
        if self.extended_actions.get_active() == 0:
            self.box_insert_number_preconf.hide()
            self.box_insert_number_simple.hide()
            self.box_insert_number_advanced.hide()

            self.box_log_preconf.hide()
            self.box_log_simple.hide()
            self.box_log_advanced.hide()
            
        else:
            self.box_insert_number_preconf.show()
            self.box_insert_number_simple.show()
            self.box_insert_number_advanced.show()

            self.box_log_preconf.show()
            self.box_log_simple.show()
            self.box_log_advanced.show()









class RefreshReport(threading.Thread):
    """Refresh Listening report in background"""
    def __init__(self, firewall_status, model, lines):
        threading.Thread.__init__(self)
        self.firewall_status = firewall_status
        self.model_report = model
        self.listening = lines
    
    def run(self):
        """Show listening report in GUI"""
        self.model_report.clear() 
        
        row = 0
        # GNOME Palette
        color = { "green"  : "#267726",  # Accent Green Dark
                  "red"    : "#DF421E",  # Accent Red
                  "orange" : "#D1940C",  # Accent Yellow Dark
                  "blue"   : "#314E6C" } # Blue Shadow
        
        for report in self.listening:
            row += 1
            iterador = self.model_report.insert(row)
            report_split = report.split("%")
            
            self.model_report.set_value(iterador, 0, row)
            self.model_report.set_value(iterador, 1, report_split[0].strip()) # Protocol
            self.model_report.set_value(iterador, 2, report_split[1].strip()) # Port
            self.model_report.set_value(iterador, 3, report_split[2].strip()) # Address
            self.model_report.set_value(iterador, 4, report_split[3].strip()) # App
            # Only apply colors when firewall rules apply to that (fw = enabled)
            if self.firewall_status == "enable":
                if report_split[4] == "allow":
                    self.model_report.set_value(iterador, 5, color["red"])
                elif report_split[4] == "deny":
                    self.model_report.set_value(iterador, 5, color["green"])
                elif report_split[4] == "reject":
                    self.model_report.set_value(iterador, 5, color["blue"])
                elif report_split[4] == "limit":
                    self.model_report.set_value(iterador, 5, color["orange"])

