Logo Search packages:      
Sourcecode: sbackup version File versions  Download package

simple-backup-config.py

#!/usr/bin/python
#
# Simple Backup suit
#
# Running this command will start a configuration dialog
#
# Author: Aigars Mahinovs <aigarius@debian.org>
#
#    This program 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 2 of the License, or
#    (at your option) any later version.
#
#    This program 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 this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

# Imports

import sys
import os
import pygtk
import gtk
import ConfigParser
import gtk.glade
import gobject
import re
import time
import locale
import gettext
import gnome.ui
from gettext import gettext as _

try:
    import gnomevfs
except ImportError:
    import gnome.vfs as gnomevfs


class MyConfigParser(ConfigParser.ConfigParser):
        def optionxform(self, option):
                  return str( option )

class SBConf:
      def __init__ (self):
            # Startup part
            
            self.conf = MyConfigParser()
            
            # Default values
            self.configfile = "/etc/sbackup.conf"
            
            self.regex = r"\.mp3,\.avi,\.mpeg,\.mkv,\.ogg,\.iso"+",/home/[^/]+?/\.thumbnails/,/home/[^/]+?/\.Trash,/home/[^/]+?/\..+/[cC]ache"
            self.dirconfig = [('/etc/', '1'), ('/var/', '1'), ('/home/', '1'), ('/var/cache/', '0'), ('/var/tmp/', '0'), ('/var/spool/', '0'), ('/usr/local/', '1'), ('/media/', '0')]
            self.maxsize = str(10*1024*1024)
            self.target = "/var/backup"
            self.maxincrement = str(7)
            self.prefix = "/usr"
            good = 0

            self.known_ftypes = { "mp3": _("MP3 Music"), "avi": _("AVI Video"), "mpeg": _("MPEG Video"), "mpg": _("MPEG Video"), "mkv": _("Matrjoshka Video"), "ogg": _("OGG Multimedia container"), "iso": _("CD Images")}

            self.conf.add_section( "general" )
            self.conf.set( "general", "target", self.target )
            self.conf.set( "general", "lockfile", "/var/lock/sbackup.lock")
            self.conf.set( "general", "maxincrement",  self.maxincrement )
            self.conf.set( "general", "format", "1" )
            self.conf.set( "general", "purge", "log" )
            self.conf.add_section( "dirconfig" )
            self.conf.add_section( "exclude" )
            self.conf.set( "exclude", "regex",  self.regex )
            self.conf.set( "exclude", "maxsize", self.maxsize )
        
            self.conf.add_section( "places" )
            self.conf.set( "places", "prefix", self.prefix )

            # Read the config file only if the file exists
            if os.path.exists( self.configfile ) :
                  self.conf.read( self.configfile )
            self.servicefile = self.conf.get("places", "prefix") + "/share/sbackup/sbackup"
            
            # Setup glade and signals
            gtk.glade.textdomain("sbackup")
            self.widgets = gtk.glade.XML(self.conf.get("places", "prefix") + "/share/sbackup/simple-backup-config.glade")
            self.widgets.get_widget("backup_properties_dialog").set_icon_from_file(self.conf.get("places", "prefix") + "/share/pixmaps/sbackup-conf.png")

            # Initiate all data structures
            # Paths to be included or excluded
            self.include = gtk.ListStore( str )
            self.includetv = self.widgets.get_widget("includetv")
            self.includetv.set_model( self.include )
            cell = gtk.CellRendererText()
            cell.set_property('editable', True)
            cell.connect('edited', self.cell_edited_callback, (self.include, "dirconfig", 1))
            column = gtk.TreeViewColumn('Name', cell, text=0)
            self.includetv.append_column(column)

            self.ex_paths = gtk.ListStore( str )
            self.ex_pathstv = self.widgets.get_widget("ex_pathstv")
            self.ex_pathstv.set_model( self.ex_paths )
            cell1 = gtk.CellRendererText()
            cell1.set_property('editable', True)
            cell1.connect('edited', self.cell_edited_callback, (self.ex_paths, "dirconfig", 0))
            column1 = gtk.TreeViewColumn('Name', cell1, text=0)
            self.ex_pathstv.append_column(column1)

            # Excluded file types and general regular expressions
            self.ex_ftype = gtk.ListStore( str, str )
            self.ex_ftypetv = self.widgets.get_widget("ex_ftypetv")
            self.ex_ftypetv.set_model( self.ex_ftype )
            cell3 = gtk.CellRendererText()
            column3 = gtk.TreeViewColumn('File Type', cell3, text=0)
            cell2 = gtk.CellRendererText()
            column2 = gtk.TreeViewColumn('Ext.', cell2, text=1)
            self.ex_ftypetv.append_column(column3)
            self.ex_ftypetv.append_column(column2)

            self.ex_regex = gtk.ListStore( str )
            self.ex_regextv = self.widgets.get_widget("ex_regextv")
            self.ex_regextv.set_model( self.ex_regex )
            cell4 = gtk.CellRendererText()
            cell4.set_property('editable', True)
            cell4.connect('edited', self.cell_regex_edited_callback)
            column4 = gtk.TreeViewColumn('Name', cell4, text=0)
            self.ex_regextv.append_column(column4)

            # Day of month table
            self.time_dom = gtk.ListStore( str )
            self.time_domtv = self.widgets.get_widget("time_domtv")
            self.time_domtv.set_model( self.time_dom )
            cell6 = gtk.CellRendererText()
            column6 = gtk.TreeViewColumn('Name', cell6, text=0)
            self.time_domtv.append_column(column6)

            for i in range(1, 32):
                  self.time_dom.append( [str(i)] )

            # Day of week table
            self.time_dow = gtk.ListStore( str )
            self.time_dowtv = self.widgets.get_widget("time_dowtv")
            self.time_dowtv.set_model( self.time_dow )
            cell7 = gtk.CellRendererText()
            column7 = gtk.TreeViewColumn('Name', cell7, text=0)
            self.time_dowtv.append_column(column7)

            for i in range(0,7):
                  self.time_dow.append([ time.strftime( "%A", (2000,1,1,1,1,1,i,1,1)) ])

            good = self.parse_conf()
            
            # Set the time information
            cronline = False
            cronlink = False
            try: cronline = open("/etc/cron.d/sbackup", "r").readline()
            except: pass
            if not cronline:
                  self.widgets.get_widget("main_radio3").set_active( True )
                  self.widgets.get_widget("anacronRadio").set_sensitive( True )
                  self.widgets.get_widget("preciselyRadio").set_sensitive( True )
                  self.widgets.get_widget("time_min").set_sensitive( False )
                  self.widgets.get_widget("time_hour").set_sensitive( False )
                  self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                  self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                  self.widgets.get_widget("ccronline").set_sensitive( False )
                  # check if we use anacron
                  self.widgets.get_widget("anacronRadio").set_active( True )
                  # hourly
                  if os.path.exists("/etc/cron.hourly/sbackup"):
                        self.widgets.get_widget("time_freq").set_active( 1 )
                        cronlink = True
                  # daily
                  elif os.path.exists("/etc/cron.daily/sbackup"):
                        self.widgets.get_widget("time_freq").set_active( 2 )
                        cronlink = True
                  # weekly
                  elif os.path.exists("/etc/cron.weekly/sbackup"):
                        self.widgets.get_widget("time_freq").set_active( 3 )
                        cronlink = True
                  # monthly
                  elif os.path.exists("/etc/cron.monthly/sbackup"):
                        self.widgets.get_widget("time_freq").set_active( 4 )
                        cronlink = True
                  # None has been set
                  else :                  
                        self.widgets.get_widget("time_freq").set_active( 0 )
                        self.widgets.get_widget("anacronRadio").set_sensitive( False )
                        self.widgets.get_widget("preciselyRadio").set_sensitive( False )
            else:
                  # /etc/cron.d/sbackup exists, we don't use anacron
                  self.widgets.get_widget("anacronRadio").set_active( False )
                  self.widgets.get_widget("preciselyRadio").set_active( True )
                  parsed = False
                  croninfo = cronline.split()
                  if croninfo[0] == "@hourly":
                        self.widgets.get_widget("time_min").set_value( 0 )
                        self.widgets.get_widget("time_hour").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                        self.widgets.get_widget("ccronline").set_sensitive( False )
                        self.widgets.get_widget("time_freq").set_active( 1 )
                  elif croninfo[0] == "@daily":
                        good = good + 1
                        self.widgets.get_widget("time_min").set_value( 0 )
                        self.widgets.get_widget("time_hour").set_value( 0 )
                        self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                        self.widgets.get_widget("ccronline").set_sensitive( False )
                        self.widgets.get_widget("time_freq").set_active( 2 )
                  elif croninfo[0] == "@weekly":
                        self.widgets.get_widget("time_min").set_value( 0 )
                        self.widgets.get_widget("time_hour").set_value( 0 )
                        self.widgets.get_widget("time_dowtv").get_selection().select_path( (0) )
                        self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                        self.widgets.get_widget("ccronline").set_sensitive( False )
                        self.widgets.get_widget("time_freq").set_active( 3 )
                  elif croninfo[0] == "@monthly":
                        self.widgets.get_widget("time_min").set_value( 0 )
                        self.widgets.get_widget("time_hour").set_value( 0 )
                        self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                        self.widgets.get_widget("time_domtv").get_selection().select_path( (0) )
                        self.widgets.get_widget("ccronline").set_sensitive( False )
                        self.widgets.get_widget("time_freq").set_active( 4 )
                  elif croninfo[0][0]=="@":
                        self.widgets.get_widget("time_min").set_sensitive( False )
                        self.widgets.get_widget("time_hour").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                        self.widgets.get_widget("ccronline").set_sensitive( True )
                        self.widgets.get_widget("time_freq").set_active( 5 )
                        self.widgets.get_widget("ccronline").set_text( croninfo[0] )
                        
                  else:
                        if croninfo[0].isdigit() and croninfo[1]=="*" and croninfo[2]=="*" and croninfo[3]=="*" and croninfo[4]=="*":
                              self.widgets.get_widget("time_min").set_value( int(croninfo[0]) )
                              self.widgets.get_widget("time_hour").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                              self.widgets.get_widget("ccronline").set_sensitive( False )
                              self.widgets.get_widget("time_freq").set_active( 1 )
                        elif croninfo[0].isdigit() and croninfo[1].isdigit() and croninfo[2]=="*" and croninfo[3]=="*" and croninfo[4]=="*":
                              self.widgets.get_widget("time_min").set_value( int(croninfo[0]) )
                              self.widgets.get_widget("time_hour").set_value( int(croninfo[1]) )
                              self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                              self.widgets.get_widget("ccronline").set_sensitive( False )
                              self.widgets.get_widget("time_freq").set_active( 2 )
                        elif croninfo[0].isdigit() and croninfo[1].isdigit() and croninfo[2]=="*" and croninfo[3]=="*" and croninfo[4].isdigit():
                              self.widgets.get_widget("time_min").set_value( int(croninfo[0]) )
                              self.widgets.get_widget("time_hour").set_value( int(croninfo[1]) )
                              self.widgets.get_widget("time_dowtv").get_selection().select_path( (int(croninfo[4])-1) )
                              self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                              self.widgets.get_widget("ccronline").set_sensitive( False )
                              self.widgets.get_widget("time_freq").set_active( 3 )
                        elif croninfo[0].isdigit() and croninfo[1].isdigit() and croninfo[2].isdigit() and croninfo[3]=="*" and croninfo[4]=="*":
                              self.widgets.get_widget("time_min").set_value( int(croninfo[0]) )
                              self.widgets.get_widget("time_hour").set_value( int(croninfo[1]) )
                              self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                              self.widgets.get_widget("time_domtv").get_selection().select_path( (int(croninfo[2])-1) )
                              self.widgets.get_widget("ccronline").set_sensitive( False )
                              self.widgets.get_widget("time_freq").set_active( 4 )
                        else:
                              self.widgets.get_widget("time_min").set_sensitive( False )
                              self.widgets.get_widget("time_hour").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                              self.widgets.get_widget("ccronline").set_sensitive( True )
                              self.widgets.get_widget("time_freq").set_active( 5 )
                              self.widgets.get_widget("ccronline").set_text( " ".join(croninfo[0:5]) )

            # Parse the purge settings
            if self.conf.get("general", "purge") == "0":
                # Purge disabled
                self.widgets.get_widget("purge").set_active( False )
                self.widgets.get_widget("purge1").set_sensitive( False )
                self.widgets.get_widget("purge2").set_sensitive( False )
                self.widgets.get_widget("purgedays").set_sensitive( False )
            elif self.conf.get("general", "purge") == "log":
                # Logarithmic purge
                good += 1
                self.widgets.get_widget("purge").set_active( True )
                self.widgets.get_widget("purge1").set_sensitive( True )
                self.widgets.get_widget("purge2").set_sensitive( True )
                self.widgets.get_widget("purgedays").set_sensitive( False )
                self.widgets.get_widget("purge2").set_active( True )
            else:
                purgedays = int( self.conf.get("general", "purge") )
                if not ( purgedays > 1 and purgedays < 10000 ):
                  self.widgets.get_widget("purge").set_active( False )
                  self.widgets.get_widget("purge1").set_sensitive( False )
                  self.widgets.get_widget("purge2").set_sensitive( False )
                  self.widgets.get_widget("purgedays").set_sensitive( False )
                else:
                  # Regular purge
                  self.widgets.get_widget("purgedays").set_text( str(purgedays) )
                  self.widgets.get_widget("purge").set_active( True )
                  self.widgets.get_widget("purge1").set_sensitive( True )
                  self.widgets.get_widget("purge2").set_sensitive( True )
                  self.widgets.get_widget("purgedays").set_sensitive( True )
                  self.widgets.get_widget("purge1").set_active( True )
          
                  
            if cronline and good == 6:
                  self.widgets.get_widget("main_radio1").set_active( True )
            elif cronline or cronlink :
                  self.widgets.get_widget("main_radio2").set_active( True )
            else:
                  self.widgets.get_widget("main_radio3").set_active( True )

            self.widgets.get_widget("eventbox1").set_visible_window(False)

            self.widgets.signal_autoconnect(self)

            gnome.ui.authentication_manager_init()
            

      def parse_conf( self, *args ):
            good = 0

            if self.conf.items( "dirconfig" ) == self.dirconfig:
                  good == good + 1
            
            self.include.clear()
            self.ex_paths.clear()

            for i,v in self.conf.items( "dirconfig" ):
                  if v=="1":
                        self.include.append( [i] )
                  else:
                        self.ex_paths.append( [i] )

            if self.conf.get("exclude", "regex") == self.regex:
                  good = good+1

            self.ex_ftype.clear()
            self.ex_regex.clear()

            list = str(self.conf.get( "exclude", "regex" )).split(",")
            for i in list:
                  if re.match( r"\\\.\w+", i ):
                        if i[2:] in self.known_ftypes:
                              self.ex_ftype.append( [self.known_ftypes[i[2:]], i[2:]] )
                        else:
                              self.ex_ftype.append( [_("Custom"), i[2:]] )
                  else:
                        self.ex_regex.append( [i] )

            # Set maximum size limits
            self.widgets.get_widget("ex_maxsize").set_value( self.conf.getint("exclude", "maxsize")/(1024*1024) )
            if self.conf.getint("exclude", "maxsize") < 0:
                  self.widgets.get_widget("ex_maxsize").set_sensitive( False )
                  self.widgets.get_widget("ex_max").set_active( False )
            else:
                  self.widgets.get_widget("ex_maxsize").set_sensitive( True )
                  self.widgets.get_widget("ex_max").set_active( True )
            if self.conf.get("exclude", "maxsize" ) == self.maxsize:
                  good = good + 1
            
            # Set the maximum time between full backups
            self.widgets.get_widget("time_maxinc").set_value( int(self.conf.get("general", "maxincrement")))
            if self.conf.get("general", "maxincrement" ) == self.maxincrement:
                  good = good + 1

            # Parse the target value

            if self.conf.get("general", "target" ) == self.target:
                  good = good + 1
            ctarget = self.conf.get("general", "target")

            # Checking if the target directory is local or remote
            local = True
            
            try:
                if gnomevfs.get_uri_scheme( ctarget ) == "file":
                    ctarget = gnomevfs.get_local_path_from_uri( ctarget )
                else:
                    local = False
            except:
                pass

            
            if ctarget == self.target:
                  self.widgets.get_widget("dest1").set_active( True )
                  self.widgets.get_widget("hbox11").set_sensitive( False )
                  self.widgets.get_widget("hbox26").set_sensitive( False )
            elif local:
                  self.widgets.get_widget("dest2").set_active( True )               
                  self.widgets.get_widget("hbox11").set_sensitive( True )
                  self.widgets.get_widget("dest_localpath").set_current_folder( ctarget )
                  self.widgets.get_widget("hbox26").set_sensitive( False )
            else:
                  self.widgets.get_widget("dest3").set_active( True )               
                  self.widgets.get_widget("hbox11").set_sensitive( False )
                  self.widgets.get_widget("hbox26").set_sensitive( True )
                  self.widgets.get_widget("dest_remote").set_text( ctarget )

            return good
            
      #   configlist is like self.conf.items( "dirconfig" ) 
      #     return True if the dir is already included
      #                 False if not
      #
      def already_inc (self, configlist, toInclude):
            for i,v in configlist :
                  if v=="1" and i == toInclude :
                        # the chosen item match an included one 
                        dialog = gtk.MessageDialog(flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=gtk.BUTTONS_CLOSE, message_format=_("Already included item !"))
                        dialog.run()
                        dialog.destroy()
                        return True
            # No match found
            return False
      
      #   configlist is like self.conf.items( "dirconfig" ) 
      #     return True if the dir is already excluded
      #                 False if not
      #
      def already_ex (self, configlist, toExclude):
            for i,v in configlist :
                  if v=="0" and i == toExclude :
                        # the chosen item match an included one 
                        dialog = gtk.MessageDialog(flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=gtk.BUTTONS_CLOSE, message_format=_("Already excluded item !"))
                        dialog.run()
                        dialog.destroy()
                        return True
            # No match found
            return False
            
# Callbacks

        def on_about_clicked(self, *args):
            about = gtk.AboutDialog()
            about.set_name(_("Simple Backup Suite"))
            about.set_version("0.10.4")
            about.set_comments(_("This is a user friendly backup solution for common desktop needs. The project was sponsored by Google during Google Summer of Code 2005 and mentored by Ubuntu."))
            about.set_transient_for(self.widgets.get_widget("backup_properties_dialog"))
            about.set_copyright("Aigars Mahinovs <aigarius@debian.org>")
            about.set_translator_credits(_("translator-credits"))
            about.set_authors(["Aigars Mahinovs <aigarius@debian.org>",
                           "Jonh Wendell <wendell@bani.com.br>", "Oumar Aziz Ouattara <wattazoum@gmail.com>" ])
            about.set_website("http://sourceforge.net/projects/sbackup/")
            about.set_logo(gtk.gdk.pixbuf_new_from_file(self.conf.get("places", "prefix") + "/share/pixmaps/sbackup-conf.png"))
            about.run()
            about.destroy()
            

        def on_backupnow_clicked(self, *args):
                pid = os.spawnl( os.P_NOWAIT, self.conf.get("places", "prefix") + "/sbin/sbackupd" )
            dialog = gtk.MessageDialog(flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=gtk.BUTTONS_CLOSE, message_format=_("A backup run is initiated in the background. The process id is: ")+str(pid)+".")
            dialog.run()
            dialog.destroy()
            
        def on_save_clicked(self, *args):
                  
                  def erase_services():
                        try : os.unlink("/etc/cron.hourly/sbackup")
                        except: pass
                        try : os.unlink("/etc/cron.daily/sbackup")
                        except: pass
                        try : os.unlink("/etc/cron.weekly/sbackup")
                        except: pass
                        try : os.unlink("/etc/cron.monthly/sbackup")
                        except: pass
                        try : os.remove("/etc/cron.d/sbackup")
                        except: pass
                  
                  self.conf.write( open( "/etc/sbackup.conf", "w" ) )
                  
                  cronline = ""

                  cfreq = self.widgets.get_widget("time_freq").get_active()
                  cmin  = int(self.widgets.get_widget("time_min").get_value())
                  if self.widgets.get_widget("time_hour").get_property("sensitive"):
                        chour = int(self.widgets.get_widget("time_hour").get_value())
                  else:   chour = False
                  if self.widgets.get_widget("scrolledwindow7").get_property("sensitive"):
                        cdow  = self.widgets.get_widget("time_dowtv").get_selection().get_selected_rows()[1]
                        try:  cdow = cdow[0][0]+1
                        except: cdow = 1
                  else:   cdow  = False
                  if self.widgets.get_widget("scrolledwindow6").get_property("sensitive"):
                        cdom  = self.widgets.get_widget("time_domtv").get_selection().get_selected_rows()[1]
                        try:  cdom = cdom[0][0]+1
                        except: cdom = 1
                  else:   cdom  = False
                  
                  if   cfreq == 0:
                        erase_services()
                        cronline == False
                  else:
                        if not self.widgets.get_widget("anacronRadio").get_active() :
                              if cfreq == 1 and cmin == 0:
                                    cronline = "@hourly"
                              elif cfreq == 2 and cmin == 0 and chour == 0:
                                    cronline = "@daily"
                              elif cfreq == 3 and cmin == 0 and chour == 0 and cdow == 1:
                                    cronline = "@weekly"
                              elif cfreq == 4 and cmin == 0 and chour == 0 and cdom == 1:
                                    cronline = "@montly"
                              elif cfreq == 5:
                                    cronline = self.widgets.get_widget("ccronline").get_text()
                              else:
                                    # minutes
                                    cronline = str(cmin) + " "
                                    # hours
                                    if not chour == False: cronline = cronline + str(chour) + " "
                                    else:     cronline = cronline + "* "
                                    # days of mounth
                                    if not cdom == False: cronline = cronline + str(cdom) + " "
                                    else:     cronline = cronline + "* "
                                    # mounth of year
                                    cronline = cronline + "* "
                                    # day of week
                                    if not cdow == False: cronline = cronline + str(cdow)
                                    else:     cronline = cronline + "*"
                        else :
                              if cfreq == 1 :
                                    erase_services()
                                    os.symlink(self.servicefile,"/etc/cron.hourly/sbackup")
                              elif cfreq == 2 :
                                    erase_services()
                                    os.symlink(self.servicefile,"/etc/cron.daily/sbackup")
                              elif cfreq == 3 :
                                    erase_services()
                                    os.symlink(self.servicefile,"/etc/cron.weekly/sbackup")
                              elif cfreq == 4 :
                                    erase_services()
                                    os.symlink(self.servicefile,"/etc/cron.monthly/sbackup")

                  if cronline: 
                        try :
                              erase_services()
                              cron = open( "/etc/cron.d/sbackup", "w" )
                              tail = "\troot\tif [ -x " + self.conf.get("places", "prefix") + "/sbin/sbackupd ]; then " + self.conf.get("places", "prefix") + "/sbin/sbackupd; fi;"
                              cronline = cronline + tail + "\n"
                        except IOError: 
                              print ("Can \'t open file /etc/cron.d/sbackup for writing")

                  if cronline and not self.widgets.get_widget("main_radio3").get_active(): 
                        cron.write( cronline )
                        cron.close()

                  if not cronline:
                        # We are using anacron or we are not using cron feature at all
                        try: os.remove("/etc/cron.d/sbackup")
                        except: pass
                  dialog = gtk.MessageDialog(flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=gtk.BUTTONS_CLOSE, message_format=_("Configuration save successful"))
                  dialog.run()
                  dialog.destroy()
            
        def on_main_radio_group_changed(self, *args):
                  if self.widgets.get_widget("main_radio1").get_active():
                        # set all values to defaults
                  
                        self.conf = ConfigParser.ConfigParser()
                        self.conf.add_section( "general" )
                        self.conf.set( "general", "target", self.target )
                        self.conf.set( "general", "lockfile", "/var/lock/sbackup.lock")
                        self.conf.set( "general", "maxincrement",  self.maxincrement )
                        self.conf.set( "general", "format", "1" )
                        self.conf.add_section( "dirconfig" )
                        for i in self.dirconfig:
                              self.conf.set( "dirconfig", i[0], i[1] )
                        self.conf.add_section( "exclude" )
                        self.conf.set( "exclude", "regex",  self.regex )
                        self.conf.set( "exclude", "maxsize", self.maxsize )
                        self.conf.add_section( "places" )
                        self.conf.set( "places", "prefix", self.prefix )
                        
                        self.parse_conf()

                        self.widgets.get_widget("time_freq").set_active( 2 )
                        # choose between anacron or cron here (old behaviour has been kept for the moment.
                        self.widgets.get_widget("preciselyRadio").set_active( True )
                        self.widgets.get_widget("anacronRadio").set_active( False )
                        
                        self.widgets.get_widget("time_min").set_sensitive( True )
                        self.widgets.get_widget("time_hour").set_sensitive( True )
                        self.widgets.get_widget("time_min").set_value( 0 )
                        self.widgets.get_widget("time_hour").set_value( 0 )
                        self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                        self.widgets.get_widget("ccronline").set_sensitive( False )

                        self.widgets.get_widget("purge").set_active( True )
                        self.widgets.get_widget("purge1").set_active( 1 )
                        self.widgets.get_widget("purgedays").set_sensitive( False )

                        # disable all tabs
                        self.widgets.get_widget("vbox11").set_sensitive( False )
                        self.widgets.get_widget("notebook2").set_sensitive( False )
                        self.widgets.get_widget("vbox14").set_sensitive( False )
                        self.widgets.get_widget("vbox21").set_sensitive( False )

                  elif self.widgets.get_widget("main_radio2").get_active():
                        # enable all tabs
                        self.widgets.get_widget("vbox11").set_sensitive( True )
                        self.widgets.get_widget("notebook2").set_sensitive( True )
                        self.widgets.get_widget("vbox14").set_sensitive( True )
                        self.widgets.get_widget("vbox21").set_sensitive( True )
                        self.widgets.get_widget("time_freq").set_active( 2 )
                        # Use anacron
                        self.widgets.get_widget("preciselyRadio").set_active( False )
                        self.widgets.get_widget("anacronRadio").set_active( True )
                        
                  else:
                        # enable all tabs
                        self.widgets.get_widget("vbox11").set_sensitive( True )
                        self.widgets.get_widget("notebook2").set_sensitive( True )
                        self.widgets.get_widget("vbox14").set_sensitive( True )
                        # disable Time tab
                        self.widgets.get_widget("time_freq").set_active( 0 )
                        self.widgets.get_widget("time_min").set_sensitive( False )
                        self.widgets.get_widget("time_hour").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                        self.widgets.get_widget("ccronline").set_sensitive( False )
                        # disable regular backups
                        #try: os.remove("/etc/cron.d/sbackup")
                        #except: pass

        def on_inc_addfile_clicked(self, *args):
            dialog = gtk.FileChooserDialog(_("Include file ..."), None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
            dialog.set_default_response(gtk.RESPONSE_OK)
            filter = gtk.FileFilter()
            filter.set_name(_("All files"))
            filter.add_pattern("*")
            dialog.add_filter(filter)
            
            response = dialog.run()
            if response == gtk.RESPONSE_OK and not self.already_inc(self.conf.items( "dirconfig" ),dialog.get_filename()):
                  self.include.append( [dialog.get_filename()] )
                  self.conf.set( "dirconfig", dialog.get_filename(), "1" )
            elif response == gtk.RESPONSE_CANCEL:
                pass
            dialog.destroy()

        def on_inc_adddir_clicked(self, *args):
                dialog = gtk.FileChooserDialog(_("Include folder ..."), None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
            dialog.set_default_response(gtk.RESPONSE_OK)
            
            response = dialog.run()
            if response == gtk.RESPONSE_OK and not self.already_inc(self.conf.items( "dirconfig" ),dialog.get_filename()+"/"):
                  self.include.append( [dialog.get_filename()+"/"] )
                  self.conf.set( "dirconfig", dialog.get_filename()+"/", "1" )
            elif response == gtk.RESPONSE_CANCEL:
                pass
            dialog.destroy()

        def on_inc_del_clicked(self, *args):
            (store, iter) = self.includetv.get_selection().get_selected()
            if store and iter:
                  value = store.get_value( iter, 0 )
                  self.conf.remove_option( "dirconfig", value )
                  store.remove( iter )

        def on_ex_addfile_clicked(self, *args):
            dialog = gtk.FileChooserDialog(_("Exclude file ..."), None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
            dialog.set_default_response(gtk.RESPONSE_OK)
            filter = gtk.FileFilter()
            filter.set_name(_("All files"))
            filter.add_pattern("*")
            dialog.add_filter(filter)
            
            response = dialog.run()
            if response == gtk.RESPONSE_OK and not self.already_ex(self.conf.items( "dirconfig" ),dialog.get_filename()):
                  self.ex_paths.append( [dialog.get_filename()] )
                  self.conf.set( "dirconfig", dialog.get_filename(), "0" )
            elif response == gtk.RESPONSE_CANCEL:
                pass
            dialog.destroy()

        def on_ex_adddir_clicked(self, *args):
                dialog = gtk.FileChooserDialog(_("Exclude folder ..."), None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
            dialog.set_default_response(gtk.RESPONSE_OK)
            
            response = dialog.run()
            if response == gtk.RESPONSE_OK and not self.already_ex(self.conf.items( "dirconfig" ),dialog.get_filename()+"/"):
                  self.ex_paths.append( [dialog.get_filename()+"/"] )
                  self.conf.set( "dirconfig", dialog.get_filename()+"/", "0" )
            elif response == gtk.RESPONSE_CANCEL:
                pass
            dialog.destroy()
                
        def on_ex_delpath_clicked(self, *args):
            (store, iter) = self.ex_pathstv.get_selection().get_selected()
            if store and iter:
                  value = store.get_value( iter, 0 )
                  self.conf.remove_option( "dirconfig", value )
                  store.remove( iter )          
             
        def on_addftype_clicked(self, *args):
            dialog = self.widgets.get_widget("ftypedialog")
            response = dialog.run()
            dialog.hide()
            if response == gtk.RESPONSE_OK:
                  if self.widgets.get_widget("ftype_st").get_active():
                        ftype = self.widgets.get_widget("ftype_box").get_model()[self.widgets.get_widget("ftype_box").get_active()][0]
                  else:
                        ftype = self.widgets.get_widget("ftype_custom_ex").get_text()

                  if ftype in self.known_ftypes:
                        self.ex_ftype.append( [self.known_ftypes[ftype], ftype] )
                  else:
                        self.ex_ftype.append( [_("Custom"), ftype] )

                  r = self.conf.get( "exclude", "regex" )
                  r = r + r",\." + ftype.strip()
                  self.conf.set( "exclude", "regex", r )
            elif response == gtk.RESPONSE_CANCEL:
                  pass                        

        def on_delftype_clicked(self, *args):
            (store, iter) = self.ex_ftypetv.get_selection().get_selected()
            if store and iter:
                  value = store.get_value( iter, 1 )
                  r = self.conf.get( "exclude", "regex" )
                  r = ","+r+","
                  r = re.sub( r",\\."+re.escape(value)+"," , ",", r )
                  r = r.lstrip( "," ).rstrip( "," )
                  self.conf.set( "exclude", "regex", r )
                  store.remove( iter )          
                
        def on_ex_addregex_clicked(self, *args):
            dialog = self.widgets.get_widget("regexdialog")
            response = dialog.run()
            dialog.hide()
            if response == gtk.RESPONSE_OK:
                  regex = self.widgets.get_widget("regex_box").get_text()
                  
                  self.ex_regex.append( [regex] )
                  r = self.conf.get( "exclude", "regex" )
                  r = r + r"," + regex.strip()
                  self.conf.set( "exclude", "regex", r )
            elif response == gtk.RESPONSE_CANCEL:
                  pass                        

        def on_ex_delregex_clicked(self, *args):
            (store, iter) = self.ex_regextv.get_selection().get_selected()
            if store and iter:
                  value = store.get_value( iter, 0 )
                  r = self.conf.get( "exclude", "regex" )
                  r = re.sub( r","+re.escape(value) , "", r )
                  self.conf.set( "exclude", "regex", r )
                  store.remove( iter )
      
      def cell_regex_edited_callback(self, cell, path, new_text):
            # Check if new path is empty
            if (new_text == None) or (new_text == ""):
                  dialog = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=gtk.BUTTONS_CLOSE, message_format=_("Empty expression. Please enter a valid regular expression."))
                  dialog.run()
                  dialog.destroy()
                  return
            
            # Remove old expression and add the new one
            value = self.ex_regex[path][0]
            r = self.conf.get( "exclude", "regex" )
            r = re.sub( r","+re.escape(value) , "", r )
            r = r + r"," + new_text.strip()
            self.conf.set( "exclude", "regex", r )
            self.ex_regex[path][0] = new_text
            

      def cell_edited_callback(self, cell, path, new_text, data):
            # Check if new path is empty
            if (new_text == None) or (new_text == ""):
                  dialog = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=gtk.BUTTONS_CLOSE, message_format=_("Empty filename or path. Please enter a valid filename or path."))
                  dialog.run()
                  dialog.destroy()
                  return
            # Check if new path exists and asks the user if path does not exists
            if not os.path.exists(new_text):
                  dialog = gtk.MessageDialog(type=gtk.MESSAGE_QUESTION, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=gtk.BUTTONS_YES_NO, message_format=_("It seems the path you entered does not exists. Do you want to add this wrong path?"))
                  response = dialog.run()
                  dialog.destroy()
                  if response == gtk.RESPONSE_NO:
                        return
                        
            model, section, value = data
            self.conf.remove_option(section, model[path][0])
            model[path][0] = new_text
            self.conf.set(section, new_text, value)
                
        def on_ex_max_toggled(self, *args):
                if not self.widgets.get_widget("ex_max").get_active():
                  self.widgets.get_widget("ex_maxsize").set_sensitive( False )
                  self.conf.set( "exclude", "maxsize", "-1" )
            else:
                  self.widgets.get_widget("ex_maxsize").set_sensitive( True )
                  self.conf.set( "exclude", "maxsize", str(int(self.widgets.get_widget("ex_maxsize").get_value())*1024*1024) )

      def on_ex_maxsize_changed(self, *args):
            self.conf.set( "exclude", "maxsize", str(int(self.widgets.get_widget("ex_maxsize").get_value())*1024*1024) )

        def on_dest_group_changed(self, *args):
                if   self.widgets.get_widget("dest1").get_active():
                  self.widgets.get_widget("hbox11").set_sensitive( False )
                  self.widgets.get_widget("hbox26").set_sensitive( False )
                  self.widgets.get_widget("dest_unusable").hide()
                  self.conf.set( "general", "target", self.target )
            elif self.widgets.get_widget("dest2").get_active():
                  self.widgets.get_widget("hbox11").set_sensitive( True )
                  self.widgets.get_widget("hbox26").set_sensitive( False )
                  self.on_dest_localpath_selection_changed()
            else:
                  self.widgets.get_widget("hbox11").set_sensitive( False )
                  self.widgets.get_widget("hbox26").set_sensitive( True )
                  self.on_dest_remote_changed()

        def on_dest_localpath_selection_changed(self, *args):
                t = self.widgets.get_widget("dest_localpath").get_filename()
            if (os.path.isdir( t ) and os.access( t, os.R_OK | os.W_OK | os.X_OK ) ):
                  self.conf.set( "general", "target", t )
                  self.widgets.get_widget("dest_unusable").hide()
            else:
                  self.widgets.get_widget("dest_unusable").show()
                  
    
      def on_dest_remote_changed(self, *args):
            self.widgets.get_widget("dest_remote_light").set_from_stock( gtk.STOCK_DIALOG_WARNING , gtk.ICON_SIZE_BUTTON)
            gtk.tooltips_data_get(self.widgets.get_widget("eventbox1"))[0].set_tip(self.widgets.get_widget("eventbox1"), "Please test writability of the target directory by pressing \"Test\" button on the right.")

        def on_dest_remotetest_clicked(self, *args):
            t = self.widgets.get_widget("dest_remote").get_text()
            ok = -1
            tinfo = False
            try:  # Get target directory info
                    tinfo = gnomevfs.get_file_info( t )
            except:
                  try:  # Try to create it, in case, it doesn't exist
                        gnomevfs.make_directory( t, 0750 )
                        tinfo = gnomevfs.get_file_info( t )
                  except:
                        ok = False

            try:
                if tinfo.valid_fields == 0:
                  ok = False
            except:
                ok = False
                
            if ok==-1:
                  # Now try to write to the target dir
                  try:
                        test = str( time.time() )
                        gnomevfs.make_directory( t+"/"+test, 0700 )
                        gnomevfs.remove_directory( t+"/"+test )
                        ok = True
                  except:
                        ok = False
            
            if ok:
                  self.conf.set( "general", "target", t )
                  self.widgets.get_widget("dest_unusable").hide()
                  self.widgets.get_widget("dest_remote_light").set_from_stock( gtk.STOCK_YES , gtk.ICON_SIZE_BUTTON )
                  gtk.tooltips_data_get(self.widgets.get_widget("eventbox1"))[0].set_tip(self.widgets.get_widget("eventbox1"), "Target directory is writable.")
            else:
                  self.widgets.get_widget("dest_remote_light").set_from_stock( gtk.STOCK_DIALOG_ERROR , gtk.ICON_SIZE_BUTTON )
                  gtk.tooltips_data_get(self.widgets.get_widget("eventbox1"))[0].set_tip(self.widgets.get_widget("eventbox1"), "Please change target directory and test writability of the target directory by pressing \"Test\" button on the right.")
                  self.widgets.get_widget("dest_unusable").show()
        
        def on_anacronRadio_toggled(self, *args):
            if self.widgets.get_widget("anacronRadio").get_active() :
                self.widgets.get_widget("time_min").set_sensitive( False )
                self.widgets.get_widget("time_hour").set_sensitive( False )
                self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                self.widgets.get_widget("ccronline").set_sensitive( False )
                self.widgets.get_widget("anacronRadio").set_sensitive( True )
                self.widgets.get_widget("preciselyRadio").set_sensitive( True )
            elif self.widgets.get_widget("preciselyRadio").get_active() :
                self.on_time_freq_changed(self)
        
        def on_time_freq_changed(self, *args):
            if self.widgets.get_widget("time_freq").get_active()==0:
                  self.widgets.get_widget("time_min").set_sensitive( False )
                  self.widgets.get_widget("time_hour").set_sensitive( False )
                  self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                  self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                  self.widgets.get_widget("ccronline").set_sensitive( False )
                  self.widgets.get_widget("anacronRadio").set_sensitive( False )
                  self.widgets.get_widget("preciselyRadio").set_sensitive( False )
                  self.widgets.get_widget("main_radio3").set_active(True)
            elif self.widgets.get_widget("time_freq").get_active()==5:
                  # In custom mode we can't use anacron
                  self.widgets.get_widget("main_radio3").set_active(False)
                  self.widgets.get_widget("main_radio2").set_active(True)
                  self.widgets.get_widget("preciselyRadio").set_active( True )
                  self.widgets.get_widget("anacronRadio").set_active( False )
                  self.widgets.get_widget("anacronRadio").set_sensitive( False )
                  self.widgets.get_widget("preciselyRadio").set_sensitive( False )
                  self.widgets.get_widget("time_min").set_sensitive( False )
                  self.widgets.get_widget("time_hour").set_sensitive( False )
                  self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                  self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                  self.widgets.get_widget("ccronline").set_sensitive( True )
            else :
                  if not self.widgets.get_widget("main_radio1").get_active() :
                        self.widgets.get_widget("main_radio3").set_active(False)
                        self.widgets.get_widget("main_radio2").set_active(True)
                  self.widgets.get_widget("anacronRadio").set_sensitive( True )
                  self.widgets.get_widget("preciselyRadio").set_sensitive( True )
                  if self.widgets.get_widget("preciselyRadio").get_active() :
                        if self.widgets.get_widget("time_freq").get_active()==1:                
                              self.widgets.get_widget("time_min").set_sensitive( True )
                              self.widgets.get_widget("time_hour").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                              self.widgets.get_widget("ccronline").set_sensitive( False )
                        elif self.widgets.get_widget("time_freq").get_active()==2:
                              self.widgets.get_widget("time_min").set_sensitive( True )
                              self.widgets.get_widget("time_hour").set_sensitive( True )
                              self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                              self.widgets.get_widget("ccronline").set_sensitive( False )
                        elif self.widgets.get_widget("time_freq").get_active()==3:
                              self.widgets.get_widget("time_min").set_sensitive( True )
                              self.widgets.get_widget("time_hour").set_sensitive( True )
                              self.widgets.get_widget("scrolledwindow7").set_sensitive( True )
                              self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                              self.widgets.get_widget("ccronline").set_sensitive( False )
                        elif self.widgets.get_widget("time_freq").get_active()==4:
                              self.widgets.get_widget("time_min").set_sensitive( True )
                              self.widgets.get_widget("time_hour").set_sensitive( True )
                              self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                              self.widgets.get_widget("scrolledwindow6").set_sensitive( True )
                              self.widgets.get_widget("ccronline").set_sensitive( False )
                              # TODO : put current cronline into the ccronline widget here
                  # We are in anacron mode (everything is disable)
                  else :
                        self.widgets.get_widget("time_min").set_sensitive( False )
                        self.widgets.get_widget("time_hour").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow6").set_sensitive( False )
                        self.widgets.get_widget("scrolledwindow7").set_sensitive( False )
                        self.widgets.get_widget("ccronline").set_sensitive( False )
            
        def on_time_maxinc_value_changed(self, *args):
            self.conf.set( "general", "maxincrement", str(int(self.widgets.get_widget("time_maxinc").get_value())) )
                
        def on_ftype_group_changed(self, *args):
            if self.widgets.get_widget("ftype_st").get_active():
                  self.widgets.get_widget("ftype_box").set_sensitive( True )
                  self.widgets.get_widget("ftype_custom_ex").set_sensitive( False )
            else:
                  self.widgets.get_widget("ftype_box").set_sensitive( False )
                  self.widgets.get_widget("ftype_custom_ex").set_sensitive( True )

      def on_purge_toggled( self, *args):
            if not self.widgets.get_widget("purge").get_active():
                  self.widgets.get_widget("purge1").set_sensitive( False )
                  self.widgets.get_widget("purge2").set_sensitive( False )
                  self.widgets.get_widget("purgedays").set_sensitive( False )
                  self.conf.set( "general", "purge", "0" )
            else:
                  self.widgets.get_widget("purge1").set_sensitive( True )
                  self.widgets.get_widget("purge2").set_sensitive( True )
                  if self.widgets.get_widget("purge1").get_active():
                      self.widgets.get_widget("purgedays").set_sensitive( True )
                      try: i = int(self.widgets.get_widget("purgedays").get_text())
                      except: i = -1
                      if not ( i>0 and i<10000 ):     i=30
                      self.widgets.get_widget("purgedays").set_text(str(i))
                      self.conf.set( "general", "purge", str(i) )
                  else:
                      self.widgets.get_widget("purgedays").set_sensitive( False )
                      self.conf.set( "general", "purge", "log" )

      def on_purge_group_changed( self, *args ):
            if self.widgets.get_widget("purge1").get_active():
                self.widgets.get_widget("purgedays").set_sensitive( True )
                try: i = int(self.widgets.get_widget("purgedays").get_text())
                except: i = -1
                if not ( i>0 and i<10000 ):     i=30
                self.widgets.get_widget("purgedays").set_text(str(i))
                self.conf.set( "general", "purge", str(i) )
            else:
                self.widgets.get_widget("purgedays").set_sensitive( False )
                self.conf.set( "general", "purge", "log" )

      def on_purgedays_changed( self, *args ):
            try: i = int(self.widgets.get_widget("purgedays").get_text())
            except: i = -1
            if not ( i>0 and i<10000 ):   i=30
            print i
            self.conf.set( "general", "purge", str(i) )

      def gtk_main_quit( self, *args):
            gtk.main_quit()


# i18n init
gettext.textdomain("sbackup")

#Check our user id
if os.geteuid() != 0: sys.exit (_("Currently backup configuration is only runnable by root"))
if __name__ == "__main__":
      i = SBConf()
      gtk.main()

Generated by  Doxygen 1.6.0   Back to index