#!/usr/bin/perl
#
#  Copyright (C) 2001-2002 MandrakeSoft by Sebastien DUPONT <dupont_s@epita.fr>
#  Updated 2002 by Stew Benedict <sbenedict@mandrakesoft.com>
#  Redistribution of this file is permitted under the terms of the GNU
#  Public License (GPL)
#
#  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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#________________________________________________________________
#
#  Description:
#
#   Drakbackup is used to backup your system.
#   During the configuration you can select 
# 	- System files, 
# 	- Users files, 
# 	- Other files.
# 	or All your system ...  and Other (like windows Partitions)
#
#   Drakbackup allows you to backup your system on:
# 	- Harddrive.
# 	- NFS.
# 	- CDROM (CDRW), DVDROM (with autoboot, rescue and autoinstall.).
# 	- FTP.
# 	- Rsync.
# 	- Webdav.
# 	- Tape.
#
#   Drakbackup allows you to Restore your system on
#   choosen directory.
#
#   Per default all backup will be stored on your
#   /var/lib/drakbackup directory
#
#   Configuration file:
# 	/etc/drakconf/drakbackup/drakbackup.conf
#
#________________________________________________________________
#
#  Backup files formats:
#	
#	no incremental backup:
#			backup_sys_date_hour.tar.*
#			backup_user_toto_date_hour.tar.*
#			backup_other_date_hour.tar.*
#
#	first incremental backup: (if backup_base* does not exist)
#
#			backup_base_sys_date_hour.tar.*
#			backup_base_user_toto_date_hour.tar.*
#			backup_base_other_date_hour.tar.*
#			
#	other incremental backup: (if backup_base* already exist)
#
#			backup_incr_sys_date_hour.tar.*
#			backup_incr_user_toto_date_hour.tar.*
#			backup_incr_other_date_hour.tar.*
#
#	all backup runs will generate:
#
#			drakbackup_date_hour.txt
#
#			this will contain media & hostname	
#________________________________________________________________
# 
# REQUIRE:      cron if daemon
#               cdrecord & mkisofs
#		perl Net::FTP
#		ssh-askpass
#		sitecopy - for webdav
#		rsync
#		perl Expect
	
# BUGS:
#DONE		restore->other_media->next->previous => crash ...
#DONE		selection des sources a inclure dans le backup cd. 
#DONE		help -> ok after install_rpm
#    	sort of fixed - doesn't always land where you would expect
#		but at least it doesn't die
#           
# TODO:
#		1 - print ftp problem for user. 
#	    2 - calcul disk space.
#		   use quota.
#WHY? - Apple can read Joliet - would you really be restoring on MacOS?		
#Or for bootable - PPC is being deprecated anyway ;(
#		4 - write on cd --> ! change Joliet to HFS for Apple
#		6 - total backup.( all partitions wanted, windows partitions for example!)
#		    dump use for total backup.
#		7 - custom deamon
#	    10- backend: --resore_all, --restore_sys, --restore_users
#WHAT IS THIS?
#			  --build_cd_autoinst 	
#		12- cpio use !!
#		13- boot floppy disk (with dialog)
#		14- build autoboot with backup and install cd 
#DONE		15- use .backupignore like on CVS
#		16- afficher les modif dans un fichier texte du meme nom 
#			pour afficher durant le restore.
#		17- futur: could be possible to restore a specific file 
#			or directory at specific date. 
#		18- possible all files each time from directory.
#		               
# DONE TODAY:
#________________________________________________________________


use lib qw(/usr/lib/libDrakX);
use standalone;     #- warning, standalone must be loaded very first, for 'explanations'
use strict;

use interactive;
use common;
use Time::localtime;
use detect_devices;

# Backend Options.
# make this global for status screen      
my ($window1, $my_win);
my $central_widget;
my $previous_widget;
my $current_widget;
my $interactive;
my $up_box;
my $advanced_box;
my $box2;
my $cfg_file_exist = 0;
my @all_user_list;
my $list_other;
my $DEBUG = 0;
my $restore_sys = 1; 
my $restore_user = 1; 
my $restore_other = 1; 
my $restore_step_sys_date = "";
my @user_backuped;
my @sys_backuped;
my $sys_backuped = 0;
my $other_backuped = 0;
my @user_list_to_restore;
my @sys_list_to_restore;
my $cd_device_entry;
my $custom_help;
my $button_box;
my $button_box_tmp;
my $next_widget;
my $sav_next_widget;
my $system_state;
my $restore_state;
my $save_path_entry;
my $restore_find_path_entry;
my $new_path_entry;
my $pbar;
my $pbar1;
my $pbar2;
my $pbar3;
my $plabel;
my $plabel1;
my $plabel2;
my $plabel3;
my $stext;
my $list_model;
my $iter;
my $the_time;
my @user_list_to_restore2;
my @data_backuped;
my $label_tail;
my @list_to_build_on_cd; 
my $restore_path = "/";
my $restore_other_path = 0;
my $restore_other_src;
my $path_to_find_restore;
my $other_media_hd;
my $backup_bef_restore = 0;
my $table;
my @user_list_backuped;
my @files_corrupted;
#- ack - not a great default - changed 20020814 (SB)
my $remove_user_before_restore = 0;
my @file_list_to_send_by_ftp;
my $results;
my @net_methods = ("ftp", "rsync", "ssh", "webdav");
my @media_types = ("cd", "hd", "tape");
my %cd_devices;
my $std_device;
my @tape_devices;
my $tar_ext = "tar.gz";

# config. FILES -> Default PATH  & Global variables.
my %config;
my @sys_files = "/etc";
my @user_list;
my @list_other;
my $cfg_dir = "/etc/drakxtools/drakbackup/";
my $cfg_file = $cfg_dir . "drakbackup.conf";
my $save_path = "/var/lib/drakbackup";
my $log_file = "/var/log/drakbackup";
my $log_buff;
my $comp_mode = 0;
my $backup_sys = 1;
my $backup_user = 1;
my $backup_daemon = 1;
my $backup_sys_versions = 0;
my $backup_user_versions = 0;
my $backup_other_versions = 0;
my $sys_diff_mode = 0;
my $user_diff_mode = 0;
my $other_diff_mode = 0;
my $what_no_browser = 1;
my $cdrw = 0;
my $dvdr = 0;
my $dvdram = 0;
my $net_proto = '';
my $host_path = '';
my $login_user = '';
my $daemon = 0;
my $backend_only = 0;
my $daemon_media = '';
my $hd_quota = 0;

#- 7/4/2002 SB - consolidate net methods
my $where_use_net = 0;

my $where_net = 0;
my $where_hd = 1;
my $del_hd_files = 0;
my $where_cd = 0;
my $where_tape = 0;
my $cd_time = 650;
my $when_space;
my $cd_with_install_boot = 0;
my $cd_device = '';
my $host_name = '';
my $backupignore = 0; 
my $remember_pass = 0;
my $passwd_user = '';
my $tape_device;
my $media_erase = 0;
my $media_eject = 0;
my $multi_session = 0;
my $session_offset = '';
my $tape_norewind = 0;
my $no_critical_sys = 1;
my $send_mail = 0;
my $user_mail;
my $scp_port = 22;
my $use_expect = 0;
my $xfer_keys = 0;
my $user_keys = 1;
my $user_home = $ENV{HOME};
my $backup_key = $user_home . "/.ssh/identity-drakbackup";
my $nonroot_user = 0;
my $not_warned = 0;
my $media_problem = 0;
my $vol_name = 'Drakbackup';
my $good_restore_path = 1;
my $max_space = 1000.0;
my @no_devices = translate("No devices found");

foreach (@ARGV) {

    /--default/ and backend_mode();
    /--daemon/ and daemon_mode();
    /--show-conf/ and show_conf();
	/--config-info/ and explain_conf();
	/--cd-info/ and get_cd_info(), exit(0);
    /--debug/ and $DEBUG = 1, next;
}

# allow not-root user with own config
if ($ENV{HOME} ne '/root') {
	standalone::explanations("Running as $ENV{USER}...");
	$cfg_dir = "$user_home/.drakbackup/";
	$save_path = $cfg_dir . "backups";
	$log_file = $cfg_dir . "drakbackup.log";
	-d $save_path or mkdir_p $save_path;
	$nonroot_user = 1;
	$not_warned = 1;
	$backup_sys = 0;
	$backup_daemon = 0;
	$daemon = 0;
	@user_list = $ENV{USER};
}
$cfg_file = $cfg_dir . "drakbackup.conf";

sub show_conf() {
    print "DrakBackup configuration:\n\n";
    read_conf_file();
    system_state();
    print "$system_state\n";
    exit(0);
}

sub explain_conf() {
	print "\nConfiguration File Options: \n\n";
	print "Configuration file is located in:\n";
	print "                            Root Mode: /etc/drakxtools/drakbackup/drakbackup.conf.\n";
	print "                            User Mode: ~/.drakbackup/drakbackup.conf.\n\n";
	print "SYS_FILES=                 Space seperated list of system directories to backup.\n";
	print "HOME_FILES=                Space seperated list of user home directories to backup.\n";
	print "OTHER_FILES=               Space seperated list of other files to backup.\n";
	print "PATH_TO_SAVE=              Default Hard Drive path to create backup files in.\n";
	print "                            Root Mode: default is /var/lib/drakbackup.\n";
	print "                            User Mode: default is ~/.drakbackup/backups.\n";
	print "NO_SYS_FILES               Don't backup system files.\n";
	print "NO_USER_FILES              Don't backup user files.\n";
	print "BACKUPIGNORE               Honor .backupignore files in backup directories\n";
	print "OPTION_COMP                Compression option - TAR.GZ or TAR.BZ2 (tar.gz is default).\n";
	print "BROWSER_CACHE              Backup web browser cache also.\n";
	print "CDRW                       Backup media is re-writable CD.\n";
	print "DVDR                       Backup media is recordable DVD (not fully supported yet).\n";
	print "DVDRAM                     Backup media is DVDRAM (not fully supported yet).\n";
	print "NET_PROTO=                 Network protocol to use for remote backups: \n";
	print "                             ftp, rsync, ssh, or webdav.\n";
	print "HOST_NAME=                 Remote backup host.\n";
	print "HOST_PATH=                 Backup storage path or module on remote host.\n";
	print "REMEMBER_PASS              Remember password on remote host in config file.\n";
	print "USER_KEYS                  Ssh keys are already setup for communicating with remote host.\n";
	print "DRAK_KEYS                  Use special drakbackup generated host keys.\n";
	print "                             (requires perl-Expect).\n";
	print "USE_EXPECT                 Use expect to do the whole scp transfer, without keys.\n";
	print "                             (requires perl-Expect).\n";
	print "LOGIN=                     Remote host login name.\n";
	print "PASSWD=                    Password on remote host (if REMEMBER_PASS is enabled).\n";
	print "DAEMON_MEDIA=              Daemon mode backup via given media.\n";
	print "                             (hd, cd, tape, ftp, rsync, ssh, or webdav).\n";
	print "HD_QUOTA                   Use quota to limit hard drive space used for backups.\n";
	print "                             (not supported yet).\n";
	print "USE_HD                     Use Hard Drive for backups (currently all modes use HD also).\n";
	print "MAX_SPACE=                 Maximum Hard Drive Space(Mb) to consume for backups. \n";   	
	print "USE_CD                     Use CD for backups.\n";
	print "USE_NET                    Use network for backups (driven by NET_PROTO).\n";
	print "USE_TAPE                   Use tape for backup.\n";
	print "DEL_HD_FILES               Delete local hard drive tar files after backup to other media.\n";
	print "TAPE_NOREWIND              Use non-rewinding tape device.\n";
	print "CD_TIME=                   Length of CD media (not currently utilized).\n";
	print "DAEMON_TIME_SPACE=         Interval between daemon backup runs (hourly, daily, weekly)..\n";
	print "CD_WITH_INSTALL_BOOT       Build a bootable restore CD (currently not utilized).\n";
	print "CD_DEVICE=                 Cdrecord style CD device name (ie: 1,3,0).\n";
	print "USER_MAIL=                 User to send backup results to via email.\n";
	print "SEND_MAIL                  Do send backup results via email.\n";
	print "TAPE_DEVICE                Device to use for tape backup (ie: /dev/st0).\n";
	print "MEDIA_ERASE                Erase media before new backup (applies to tape, CD).\n";
	print "MEDIA_EJECT                Eject media after backup completes.\n";
	print "MULTI_SESSION              Allow muliple sessions to be written to CD media.\n";
	print "SYS_INCREMENTAL_BACKUPS    Do incremental or differential backups of system files.\n";
	print "USER_INCREMENTAL_BACKUPS   Do incremental or differential backups of user files.\n";
	print "OTHER_INCREMENTAL_BACKUPS  Do incremental or differential backups if other files.\n";
	print "SYS_DIFFERENTIAL_BACKUPS   Do differential backups of system files.\n";
	print "USER_DIFFERENTIAL_BACKUPS  Do differential backups of user files.\n";
	print "OTHER_DIFFERENTIAL_BACKUPS Do differential backups if other files.\n";
	print "NO_CRITICAL_SYS            Do not backup critical system files:\n";
	print "                             passwd, fstab, group, mtab\n";
	print "CRITICAL_SYS               Do backup above system files.\n";
	exit(0);
}

sub backend_mode() {
	$backend_only = 1;
    build_backup_files();
    exit(0);
}

sub daemon_mode() {
    $daemon = 1;
    build_backup_files();
    exit(0);
}

if (check_for_xserver()) {
	# I give up, if I don't wrap this somehow, it never comes back when run in 
	# console or daemon mode - just pegs cpu to 100%
	# perl_checker has fits though
	eval { require ugtk2 };
	die "Can't load ugtk2...\n" if $@;
	ugtk2->import(qw(:helpers :wrappers :create));
	interactive_mode();
} else {
	die "Can't run in console mode...";
}

sub all_user_list() {
    my $passwdfile = "/etc/passwd";
    my $user;
    my $uid;
    @all_user_list = ();

	local *PASSWD;
    open(PASSWD, $passwdfile) or exit 1; 
    while (defined(my $line = <PASSWD>)) {
		chomp($line);
		($user, $uid) = (split(/:/, $line))[0, 2];
		if ($uid >= 500 || $uid == 0) {
	    	push @all_user_list, $user;
		}
    }
    close(PASSWD);
    if ($DEBUG) {
		print "/--  User list  --/ \n";
		print " -> $_\n" foreach @all_user_list;
		print "\n";
    }
}

sub the_time() {
    $the_time = "_";
    $the_time .= localtime->year + 1900;
    if (localtime->mon < 9) { $the_time .= "0" }
    $the_time .= localtime->mon + 1;
    if (localtime->mday < 10) { $the_time .= "0" }
    $the_time .= localtime->mday;
    $the_time .= "_";
    if (localtime->hour < 10) { $the_time .= "0" }
    $the_time .= localtime->hour;
    if (localtime->min < 10) { $the_time .= "0" }
    $the_time .= localtime->min;
    if (localtime->sec < 10) { $the_time .= "0" }
    $the_time .= localtime->sec;    
}

sub get_tape_info() {
	my @line_data;
	my $info = "/tmp/dmesg";
	@tape_devices = ();
	system("dmesg | grep 'st[0-9] at' > $info");

	local *INFO;
	open INFO, $info or warn("Can't open $info\n");
	local $_;
	while (<INFO>) {
		@line_data = split(/[ \t,]+/, $_);
		push @tape_devices, "/dev/" . $line_data[3]; 
	}
 	close INFO;
	unlink($info);
}

sub get_free_space {
	my ($dir) = @_;
	my @line_data;
	my $free = "/tmp/free_space";
	system("df -P $dir | tail -1 > $free");

	local *FREE;
	open FREE, $free or warn("Can't open $free\n");
	local $_;
	while (<FREE>) {
		@line_data = split(/[ \t,]+/, $_); 
	}
 	close FREE;
#	unlink($free);
	my $free_space = int($line_data[3] / 1024);
	return $free_space;	
}

sub check_storage_quota {
	my ($dir) = @_;
	my $used = "/tmp/used_space";
	my $used_space;
	system("du $dir > $used");
	
	local *USED;
	open USED, $used or warn("Can't open $used\n");
	local $_;
	while (<USED>) {
		$used_space = $_ / 1024;
	}
	close USED;
	unlink($used);
	if ($used_space > $max_space) {
		return $used_space;
	} else {
		return 0;
	}
}

sub get_cd_info() {
	my @cd_info = cat_("/proc/sys/dev/cdrom/info");
	my @line_data;
	my @drive_names;
	my $i;
	my $info;

	my %data = (
                  "drive speed" => 'speed',
                  "Can change speed" => 'chg_speed',
                  "Can read multisession" => 'multisession',
                  "Can write CD-R" => 'cdr',
                  "Can write CD-RW" => 'cdrw',
                  "Can write DVD-R" => 'dvdr',
                  "Can write DVD-RAM" => 'dvdram'
                  );

	
	#- kind of ugly - I'm sure Pixel could improve this, but it works
	#- parse /proc/sys/dev/cdrom/info and get all the cd device capabilities
 	my $cd_drives;
	foreach (@cd_info) {
	  @line_data = split(/[:\t]+/, $_);
          if ($line_data[0] =~ /drive name/) {
              $cd_drives = @line_data-1;
              chop($line_data[$cd_drives]);
              @drive_names = @line_data;
              print "drives: $cd_drives\n" unless $interactive;
          }
	  chop($line_data[$cd_drives]) if $cd_drives;
          foreach my $key (keys %data) {
              if ($line_data[0] =~ $key) {
                  for ($i = 1; $i <= $cd_drives; $i++) {
                      $cd_devices{$drive_names[$i]}{$data{$key}} = $line_data[$i];
                  }
              }
          }

	}
	
	#- now we know all the capabilities, we need the cdrecord device id
	#- this is scsi-channel, id, lun from /dev/scsi/host*
	#- oops - can't count on devfs - use dmesg

	$info = "/tmp/dmesg";
	system("dmesg | grep sr[0-9] > $info");
	local *INFO;
	open INFO, $info or warn("Can't open $info\n");
 	local $_;
	while (<INFO>) {
		if (/sr[0-9] at/) {
			@line_data = split(/[ \t,]+/, $_);
			chop($line_data[11]);
			$line_data[5] =~ s/scsi//;
			$cd_devices{$line_data[3]}{rec_dev} = $line_data[5] . "," . $line_data[9] . "," . $line_data[11];
		}
    	}
    	close INFO;
    	unlink($info);

	#- should we also try to get the human readable name for display purposes?
	
	#- now just report the data if we called --cd-info from the command line
	if (!$interactive) {
		foreach my $key (keys %cd_devices) {
			print "\n{$key}->{rec_dev} = $cd_devices{$key}->{rec_dev}\n"; 
			print "{$key}->{speed} = $cd_devices{$key}->{speed}\n";
			print "{$key}->{chg_speed} = $cd_devices{$key}->{chg_speed}\n";
			print "{$key}->{multisession} = $cd_devices{$key}->{multisession}\n";
			print "{$key}->{cdr} = $cd_devices{$key}->{cdr}\n";
			print "{$key}->{cdrw} = $cd_devices{$key}->{cdrw}\n";
			print "{$key}->{dvdr} = $cd_devices{$key}->{dvdr}\n";
			print "{$key}->{dvdram} = $cd_devices{$key}->{dvdram}\n"; 
		}
	} else {
		#- in non-interactive mode we just let all the devices through
		#- as a general purpose probe - in reality we want only burners
		foreach my $key (keys %cd_devices) {
			delete $cd_devices{$key} if $cd_devices{$key}{rec_dev} eq ''
   		}
	}
}

sub save_conf_file() {
    write_sitecopyrc() if $net_proto eq 'webdav';
    write_password_file() if $net_proto eq 'rsync' && $passwd_user;
    
    my @cfg_list = ("SYS_FILES=@sys_files\n",
		    "HOME_FILES=@user_list\n", 
		    "OTHER_FILES=@list_other\n",
		    "PATH_TO_SAVE=$save_path\n",
		    "HOST_PATH=$host_path\n",
		    "NET_PROTO=$net_proto\n",
		    "CD_TIME=$cd_time\n",
		    "USER_MAIL=$user_mail\n",		     
		    "DAEMON_TIME_SPACE=$when_space\n",
		    "CD_DEVICE=$cd_device\n",
		    "LOGIN=$login_user\n",
		    "TAPE_DEVICE=$tape_device\n",
		    "HOST_NAME=$host_name\n"
		    );
    $no_critical_sys and push @cfg_list, "NO_CRITICAL_SYS\n"; 
    $no_critical_sys or push @cfg_list, "CRITICAL_SYS\n";
	$backupignore and push @cfg_list, "BACKUPIGNORE\n"; 
    $send_mail and push @cfg_list, "SEND_MAIL\n";
    $backup_sys_versions and push @cfg_list, "SYS_INCREMENTAL_BACKUPS\n"; 
    $backup_user_versions and push @cfg_list, "USER_INCREMENTAL_BACKUPS\n"; 
    $backup_other_versions  and push @cfg_list, "OTHER_INCREMENTAL_BACKUPS\n";
	$sys_diff_mode and $backup_sys_versions and push @cfg_list, "SYS_DIFFERENTIAL_BACKUPS\n"; 
    $user_diff_mode and $backup_user_versions and push @cfg_list, "USER_DIFFERENTIAL_BACKUPS\n"; 
    $other_diff_mode  and $backup_other_versions and push @cfg_list, "OTHER_DIFFERENTIAL_BACKUPS\n"; 
    $media_erase and push @cfg_list, "MEDIA_ERASE\n"; 
    $media_eject and push @cfg_list, "MEDIA_EJECT\n"; 
    $multi_session and push @cfg_list, "MULTI_SESSION\n"; 
    $remember_pass and push @cfg_list, "LOGIN=$login_user\n"; 
    $remember_pass and push @cfg_list, "PASSWD=$passwd_user\n";
    $remember_pass and push @cfg_list, "REMEMBER_PASS\n";
    $user_keys and push @cfg_list, "USER_KEYS\n";
    $xfer_keys and push @cfg_list, "DRAK_KEYS\n";
    $use_expect and push @cfg_list, "USE_EXPECT\n";	
    $cd_with_install_boot and push @cfg_list, "CD_WITH_INSTALL_BOOT\n";
    $daemon_media eq 'ssh' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=ssh\n";
    $daemon_media eq 'ftp' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=ftp\n";
    $daemon_media eq 'hd' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=hd\n";
    $daemon_media eq 'cd' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=cd\n";
    $daemon_media eq 'tape' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=tape\n";
    $daemon_media eq 'webdav' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=webdav\n";
    $daemon_media eq 'rsync' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=rsync\n";
    $hd_quota and  push @cfg_list, "HD_QUOTA\n";
    $where_hd and  push @cfg_list, "USE_HD\n";
	$where_hd and push @cfg_list, "MAX_SPACE=$max_space\n";
    $where_cd and  push @cfg_list, "USE_CD\n";
    $where_tape and push @cfg_list, "USE_TAPE\n";
    $tape_norewind and push @cfg_list, "TAPE_NOREWIND\n";
    $where_net and  push @cfg_list, "USE_NET\n";
    $cdrw and push @cfg_list, "CDRW\n"; 
    $dvdr and push @cfg_list, "DVDR\n"; 
    $dvdram and push @cfg_list, "DVDRAM\n"; 
    $what_no_browser or push @cfg_list, "BROWSER_CACHE\n";
    $backup_sys or push @cfg_list,  "NO_SYS_FILES\n";
    if ($comp_mode) {
	push @cfg_list, "OPTION_COMP=TAR.BZ2\n";
    } else { 
	push @cfg_list, "OPTION_COMP=TAR.GZ\n";   
    }
    $del_hd_files and push @cfg_list, "DEL_HD_FILES\n";
    output_p($cfg_file, @cfg_list);
    chmod(0600, $cfg_file);
    save_cron_files();
}

sub read_cron_files() {
    my $daemon_found = 0;
    foreach (qw(hourly daily weekly monthly)) {
		if (-f "/etc/cron.$_/drakbackup") {
	    	$when_space = $_;	    
	    	$daemon_found = 1;
	    	last;
		}
    }
    !$daemon_found and $backup_daemon = 0; 
}

sub save_cron_files() {
	if ($nonroot_user) {
		show_warning("w", N("Cron not available yet as non-root")) if $not_warned;
		$not_warned = 0;
		$backup_daemon = 0;
		return 1;
	}
    my @cron_file = ("#!/bin/sh\n", "export USER=root\n", "/usr/sbin/drakbackup --daemon > /dev/null 2>&1\n");

    if ($backup_daemon) {
		foreach (qw(hourly daily weekly monthly)) {
	    	-f "/etc/cron.$_/drakbackup" and rm_rf("/etc/cron.$_/drakbackup");
		}
		output_p("/etc/cron.$when_space/drakbackup",  @cron_file);
		system("chmod +x /etc/cron.$when_space/drakbackup");
    } else {
		foreach (qw(hourly daily weekly monthly)) {
	    	-f "/etc/cron.$_/drakbackup" and rm_rf("/etc/cron.$_/drakbackup");
		}
    }
}

sub read_conf_file() {
    if (-e $cfg_file) {
#        %config = getVarsFromSh($cfg_file) || print "You must be root to read configuration file. \n";
		local *CONF_FILE;
        open(CONF_FILE, "<" . $cfg_file) || print "You must be root to read configuration file. \n";
        local $_;
        while (<CONF_FILE>) {
	    	next unless /\S/;
	    	next if /^#/;
	    	chomp;
			if (/^SYS_FILES/)      { s/^SYS_FILES=//gi;    @sys_files = split(' ', $_) }
			if (/^HOME_FILES/)     { s/^HOME_FILES=//gi;   @user_list = split(' ', $_) }
			if (/^OTHER_FILES/)    { s/^OTHER_FILES=//gi;  @list_other = split(' ', $_) }
			if (/^PATH_TO_SAVE/)   { s/^PATH_TO_SAVE=//gi; $save_path = $_ }
			if (/^NO_SYS_FILES/)   { $backup_sys = 0 }
			if (/^NO_USER_FILES/)  { $backup_user = 0 }
			if (/^OPTION_COMP/)    { s/^OPTION_COMP=//gi; /TAR.GZ/ and  $comp_mode = 0; /TAR.BZ2/ and $comp_mode = 1 }
			if (/^BROWSER_CACHE/)  { $what_no_browser = 0 }
			if (/^CDRW/)           { $cdrw = 1 }
			if (/^DVDR/)           { $dvdr = 1 }
			if (/^DVDRAM/)         { $dvdram = 1 }
			if (/^NET_PROTO/)      { s/^NET_PROTO=//gi; $net_proto = $_ }
			if (/^HOST_PATH/)      { s/^HOST_PATH=//gi; $host_path = $_ } 
			if (/^DAEMON_MEDIA/)   { s/^DAEMON_MEDIA=//gi; $daemon_media = $_ }
			if (/^HD_QUOTA/)       { $hd_quota = 1 }
			if (/^USE_HD/)         { $where_hd = 1 }
			if (/^MAX_SPACE/)	   { s/^MAX_SPACE=//gi; $max_space = $_ }
			if (/^USE_CD/)         { $where_cd = 1 }
			if (/^USE_NET/)        { $where_net = 1 }
			if (/^USE_TAPE/)       { $where_tape = 1 }
			if (/^TAPE_NOREWIND/)  { $tape_norewind = 1 }
			if (/^CD_TIME/)        { s/^CD_TIME=//gi; $cd_time = $_ }
			if (/^DAEMON_TIME_SPACE/) { s/^DAEMON_TIME_SPACE=//gi; $when_space = $_ }
			if (/^CD_WITH_INSTALL_BOOT/) { $cd_with_install_boot = 1 }
			if (/^CD_DEVICE/)      { s/^CD_DEVICE=//gi; $cd_device = $_ }
			if (/^HOST_NAME/)      { s/^HOST_NAME=//gi; $host_name = $_ } 
			if (/^REMEMBER_PASS/)  { $remember_pass = 1 }
			if (/^USER_KEYS/)      { $user_keys = 1 }
			if (/^DRAK_KEYS/)      { $xfer_keys = 1; $user_keys = 0 }
			if (/^USE_EXPECT/)     { $use_expect = 1; $user_keys = 0 }
			if (/^LOGIN/)          { s/^LOGIN=//gi;  $login_user  = $_ }
			if (/^PASSWD/)         { s/^PASSWD=//gi; $passwd_user = $_; $remember_pass = 1 }
			if (/^USER_MAIL/)      { s/^USER_MAIL=//gi; $user_mail = $_ }		     
			if (/^SEND_MAIL/)      { $send_mail = 1 }
			if (/^TAPE_DEVICE/)    { s/TAPE_DEVICE=//gi; $tape_device = $_ }
			if (/^MEDIA_ERASE/)    { $media_erase = 1 }
			if (/^MEDIA_EJECT/)    { $media_eject = 1 }
			if (/^MULTI_SESSION/)  { $multi_session = 1 }
			if (/^SYS_INCREMENTAL_BACKUPS/)   { $backup_sys_versions = 1 }
			if (/^USER_INCREMENTAL_BACKUPS/)  { $backup_user_versions = 1 }
			if (/^OTHER_INCREMENTAL_BACKUPS/) { $backup_other_versions = 1 }
			if (/^SYS_DIFFERENTIAL_BACKUPS/)   { $sys_diff_mode = 1 }
			if (/^USER_DIFFERENTIAL_BACKUPS/)  { $user_diff_mode = 1 }
			if (/^OTHER_DIFFERENTIAL_BACKUPS/) { $other_diff_mode = 1 }
			if (/^NO_CRITICAL_SYS/) { $no_critical_sys = 1 }
			if (/^CRITICAL_SYS/)   { $no_critical_sys = 0 }
			if (/^BACKUPIGNORE/)   { $backupignore = 1 }
			if (/^DEL_HD_FILES/)   { $del_hd_files = 1 }
	    }
		close(CONF_FILE);
		read_cron_files();
		$cfg_file_exist = 1;
    } else { 
    	$cfg_file_exist = 0;
		#- these were 1 by default, but that made it so the user could never save the 
		#- inverse behavior. this allows incremental as the default if not configured
		$backup_sys_versions = 1;
		$backup_user_versions = 1; 
    }    
}

sub write_sitecopyrc() {
	#- FIXME - how to deal with existing sitecopyrc
    my @cfg_list = ("site drakbackup\n",
		     "\tserver $host_name\n",
		     "\tremote /$host_path\n",
		     "\tlocal $save_path\n",
		     "\tusername $login_user\n",
		     "\tpassword $passwd_user\n",
		     "\tprotocol webdav\n"
			);
    output_p("$user_home/.sitecopyrc", @cfg_list);
    chmod(0600, "$user_home/.sitecopyrc");
    -d "$user_home/.sitecopy" or mkdir_p("$user_home/.sitecopy");
    chmod(0700, "$user_home/.sitecopy");
}

sub write_password_file() {
	output_p("$cfg_dir/rsync.user", "$passwd_user\n");
	chmod(0600, "$cfg_dir/rsync.user");
}

my $in;

sub show_warning {
	my ($mode, $warning) = @_;
	$mode = N("WARNING") if $mode eq "w";
	$mode = N("FATAL") if $mode eq "f";
	$mode = N("INFO") if $mode eq "i";
	if ($interactive) {
		$in->ask_warn('', translate($mode).": ".translate($warning));
	} else {
		warn "$mode: $warning\n";
	}
	$log_buff .= "\n$mode: $warning\n";
}
	
sub complete_results() {
    system_state();
    $results .=  "***********************************************************************\n\n";
    $daemon or $results .=  N("\n                      DrakBackup Report \n");
    $daemon and $results .= N("\n                      DrakBackup Daemon Report\n");
	my $datem = `date`;
	$results .=               "                      $datem\n\n";	
    $results .=  "***********************************************************************\n\n";
    $results .= $system_state;
    $results .=  "\n\n***********************************************************************\n\n";
    $results .=             N("\n                    DrakBackup Report Details\n\n\n");
    $results .=  "***********************************************************************\n\n";
}

sub ftp_client() {
    use Net::FTP; 
    my $ftp;

    $DEBUG and print "file list to send: $_\n "  foreach @file_list_to_send_by_ftp;
    if ($DEBUG && $interactive) { $ftp = Net::FTP->new($host_name, Debug => 1) or return 1 }
    elsif ($interactive)  {  $ftp = Net::FTP->new($host_name, Debug => 0) or return 1 }
    else {  $ftp = Net::FTP->new($host_name, Debug => 0) or return 1 }
    $ftp->login($login_user, $passwd_user);
    $ftp->cwd($host_path); 
    foreach (@file_list_to_send_by_ftp) {
		$interactive and $pbar->set_fraction(0);
		$interactive and progress($pbar, $plabel, 0.5, $_);
		$interactive and $pbar->set_text($_);
		#- make perl_checker happy...
		$ftp->put($_, undef, undef);
		$interactive and progress($pbar, $plabel, 0.5, $_);
		$interactive and $pbar->set_text($_);
		$interactive and progress($pbar3, $plabel3, 1/@file_list_to_send_by_ftp, N("Total progess"));
    }
    $ftp->quit; 
    return 0;
}

sub do_expect {

	#- Sort of a general purpose expect routine, we use it to backup files to
	#- a remote server, as well as transfer a key and restore.
	#- Using the key after it is setup is preferred.
	
	my ($mode) = @_;
		
	eval { require Expect };
	
	if ($@) {
		if ($mode eq 'sendkey') {
			destroy_widget();
			check_pkg_needs();
		} else { 
			$log_buff .= "perl-Expect not installed!", 
		}
		return 1;
	}
	
	#- for debugging set to 1
	$Expect::Exp_Internal = 0;
	#- for debugging set to 1
	$Expect::Debug = 0;
	$Expect::Log_Stdout = 0; 

	my $spawn_ok;
	my $no_perm;
	my $bad_passwd;
	my $bad_dir;
	my $timeout  = 20;
	
	my $exp_command;
	my @send_files = "$backup_key.pub";
	
	#- just bypass progress for sendkey for now
	$interactive = 0 if $mode eq "sendkey";
	
	@send_files = @file_list_to_send_by_ftp if $mode eq "backup";
	
	$interactive and $pbar->set_fraction(0);
	$interactive and $pbar3->set_fraction(0);
	$interactive and progress($pbar, $plabel, 0.5, "File Transfer...");

	foreach (@send_files) {
		$exp_command = "scp -P $scp_port $_ $login_user\@$host_name:$host_path" if $mode eq "backup";
		$exp_command = "ssh-copy-id -i $_ $login_user\@$host_name" if $mode eq "sendkey";
	
		if (-e $backup_key && $mode eq "sendkey") {
			if ($in->ask_yesorno('', N("%s exists, delete?\n\nWarning: If you've already done this process you'll probably\n need to purge the entry from authorized_keys on the server.", $backup_key))) {
				unlink($backup_key);
				unlink($backup_key . '.pub');
			} else {
				return 0;
			}
		}
	
		if (!(-e $backup_key) && $mode eq "sendkey") {	
			$in->ask_warn('', N("This may take a moment to generate the keys."));
			cursor_wait();
			#- not using a passphrase for the moment
			system("ssh-keygen -P '' -t dsa -f $backup_key");
			cursor_norm();
		}
		
		my $exp = Expect->spawn($exp_command) or $in->ask_warn('', N("ERROR: Cannot spawn %s.", $exp_command));

		$interactive and progress($pbar3, $plabel3, 1/@send_files, N("Total progess"));
		$interactive and $stext->set_text($_);
	
		#- run scp, look for some common errors and try to track successful progress for GUI
		$exp->expect($timeout,
			[ qr 'password: $', sub { 
				$spawn_ok = 1;
				my $fh = shift;
				$fh->send("$passwd_user\n");
				Expect::exp_continue() } ],
			[ '-re', 'please try again', sub { $bad_passwd = 1; Expect::exp_continue() } ],
			[ '-re', 'Permission denied', sub { $no_perm = 1; Expect::exp_continue() } ],
			[ '-re', 'No such file or directory', sub { $bad_dir = 1; Expect::exp_continue() } ],
#			[ '-re', '%', sub { update_scp_progress(); Expect::exp_continue(); } ],
			[ eof => sub {
					if (!$spawn_ok) { show_warning("f", N("No password prompt on %s at port %s", $host_name, $scp_port)) }					
					if ($bad_passwd) { show_warning("f", N("Bad password on %s", $host_name)) }
					if ($no_perm) { show_warning("f", N("Permission denied transferring %s to %s", $_, $host_name)) }
					if ($bad_dir) { show_warning("f", N("Can't find %s on %s", $host_path, $host_name)) }
				} 
			],
			[ timeout => sub { show_warning("f", N("%s not responding", $host_name)) } ],
		); 

		my $exit_stat = $exp->exitstatus;
		$in->ask_warn('', N("Transfer successful\nYou may want to verify you can login to the server with:\n\nssh -i %s %s\@%s\n\nwithout being prompted for a password.", $backup_key, $login_user, $host_name)) if $exit_stat == 0 && $mode eq "sendkey";
		$log_buff .= "$_\n" if $exit_stat == 0 && $mode eq "backup";
		$exp->hard_close;
	}
	$interactive and progress($pbar, $plabel, 0.5, "Done...");
	$interactive = 1 if $mode eq "sendkey";
}

sub ssh_client() {
    $DEBUG and print "file list to send: $_\n "  foreach @file_list_to_send_by_ftp;
	my $command;
	my $value;
	
    foreach (@file_list_to_send_by_ftp) {
		if ($user_keys) {
			$command = "scp -P $scp_port $_ $login_user\@$host_name:$host_path";
		} else {
			$command = "scp -P $scp_port -i $backup_key $_ $login_user\@$host_name:$host_path";
		}
		$interactive and $pbar->set_fraction(0);
		$interactive and progress($pbar, $plabel, 0.5, "File Transfer...");
		$interactive and $stext->set_text($_);
		$log_buff .= $command . "\n\n";
        local *TMP;
		open TMP, "$command 2>&1 |";
		while ($value = <TMP>) {
			$log_buff .= $value;
		}
		close TMP;
		$log_buff .= "\n";
		$interactive and progress($pbar, $plabel, 0.5, "Done...");
		$interactive and progress($pbar3, $plabel3, 1/@file_list_to_send_by_ftp, N("Total progess"));
    }
    return 0;
}

sub webdav_client() {
    $DEBUG and print "file list to send: $_\n "  foreach @file_list_to_send_by_ftp;
	if (!(-e "$user_home/.sitecopy/drakbackup")) {
		my $command = "sitecopy -f $host_path";
		spawn_progress($command, "Initializing sitecopy");
	}
	my $command = "sitecopy -u drakbackup";
	spawn_progress($command, "Running sitecopy...");
		if ($log_buff =~ /Nothing to do - no changes found/) {
		show_warning("w", N("WebDAV remote site already in sync!"));
		return 1;
	}
	if ($log_buff !~ /Update completed successfully/) {
		show_warning("f", N("WebDAV transfer failed!"));
		return 1;
	}
	return 0;
}

sub rsync_client() {
    $DEBUG and print "file list to send: $_\n "  foreach @file_list_to_send_by_ftp;
	my $rsync_cmd = "rsync -tv $save_path/* ";
	$rsync_cmd = $rsync_cmd . "--password-file=$cfg_dir/rsync.user " if $passwd_user;
	$rsync_cmd = $rsync_cmd . "$login_user\@" if $login_user;
	$rsync_cmd = $rsync_cmd . $host_name . "::" . $host_path;
	spawn_progress($rsync_cmd, "Running rsync");
	return 0;
}

sub check_for_cd() {	
	#- check for a cd
	my $command = "cdrecord dev=$cd_device -atip";
	spawn_progress($command, "Check for media in drive");
	if ($log_buff =~ /No disk/) {
		show_warning("f", N("No CDR/DVDR in drive!"));
		return 1;
	}
	if ($log_buff !~ /ATIP info from disk/) {
		show_warning("f", N("Does not appear to be recordable media!"));
		return 1;
	}
	if ($log_buff =~ /Is not erasable/ && $media_erase) {
		show_warning("f", N("Not erasable media!"));
		return 1;
	}
	 
	if ($multi_session) {
		$command = "cdrecord dev=$cd_device -msinfo";
		spawn_progress($command, "Check for previous session status");
		#- if we don't find a previous session, start fresh
		if ($log_buff =~ /Cannot read session offset/) {
			$media_erase = 1;
			return 0;
		} else {
			#- extract the session info from $log_buff
			my $code_loc = rindex($log_buff, "msinfo") + 8;
			if ($code_loc != -1) { 
				my $bufflen = length($log_buff);
				$session_offset = substr($log_buff, $code_loc, $bufflen-$code_loc-1);
				return 0;
			}
			return 1;
		}
	}
}
	
sub write_on_cd() {	
	my $command = "cdrecord -v dev=$cd_device -data ";
	#- only blank if it's the first session
	$command .= "blank=fast " if $media_erase && $session_offset eq '';
	#- multi-session mode
	$command .= "-multi -pad " if $multi_session;
	$command .= "$save_path/drakbackup.iso"; 
	
	spawn_progress($command, "Running cdrecord");
	unlink("$save_path/drakbackup.iso");
}

sub erase_cdrw() {
	#- we can only hit this via interactive
	$interactive = 0;
	$in->ask_warn('', N("This may take a moment to erase the media."));
	cursor_wait();
	my $command = "cdrecord dev=$cd_device -blank=fast";
	spawn_progress($command, "Erasing CDRW...");
	cursor_norm();	
	$interactive = 1;
}

sub spawn_progress {
	my ($command, $descr) = @_;
	my $value;
	my $timer;
print "$descr\n";
	$interactive and progress($pbar3, $plabel3, 0, translate($descr));
	$interactive and $pbar3->set_fraction(0);
	$interactive and $timer = Glib::Timeout->add(2, \&progress_timeout);

	$log_buff .= "\n" . $descr . ":\n";
	$log_buff .= $command . "\n\n";
	
	local *TMP;
	open TMP, "$command 2>&1 |";
	while ($value = <TMP>) {
		$log_buff .= $value;
		if ($interactive) {
			$stext->set_text($value);
			gtkflush();
		}			
	}
	close TMP;
	$interactive and Glib::Source->remove($timer);
}

sub progress_timeout() {
	my $new_val;
	$new_val = $pbar3->get_fraction + 0.1;
    if ($new_val > 1) { $new_val = 0 }
	$pbar3->set_fraction($new_val);	
	return 1;
}

sub get_cd_device() {
	my $check_device = "/dev/cdrom";
	get_cd_info();
	foreach  (keys %cd_devices) {
		if ($cd_devices{$_}{rec_dev} eq $cd_device) {
			s/sr/scd/;
			$check_device = "/dev/" . $_;				
		}
	}
	$check_device;
}

sub get_cd_volname() {
	#- we want the volname for the catalog
	my $check_device = get_cd_device();
     local *TMP;
	open TMP, "volname $check_device 2>&1 |";
     local $_;
	while (<TMP>) {
		$vol_name = $_;		
	}
	close TMP;
	$vol_name =~ s/[ \t]+\n$//;
	$vol_name; 			
}

sub build_iso() {	
	if ($multi_session && $session_offset) {
		$vol_name = get_cd_volname();
	} else {
		$vol_name = "Drakbackup" . $the_time;
	}
	#this is safe to change the volname on rewrites, as is seems to get ignored anyway
	my $command = "mkisofs -r -J -T -v -V '$vol_name' ";
	$command .= "-C $session_offset -M $cd_device " if $multi_session && $session_offset;
	$command .= "-o $save_path/drakbackup.iso @file_list_to_send_by_ftp";
	spawn_progress($command, "Running mkisofs...");
}

sub build_cd() {
	if (!check_for_cd()) {
		build_iso();
		if ($log_buff =~ /Permission denied/) {
			show_warning("f", N("Permission problem accessing CD."));
			$media_problem = 1;
			return 1;
		} else {
			write_on_cd();
		}
	}
}

sub get_tape_label {
	my ($device) = @_;
	cursor_wait();
	system("mt -f $device rewind");
	system("tar -C $cfg_dir -xf $device");
	my @volname = cat_("$cfg_dir/drakbackup.label");
	unlink("$cfg_dir/drakbackup.label");
	$vol_name = $volname[0];
	cursor_norm();
	$vol_name;
}

sub build_tape() {
	my $command;
	#- do we have a tape?
	$command = "mt -f $tape_device status"; 
	spawn_progress($command, "Checking for tape");
	if ($log_buff =~ /DR_OPEN/) {
		show_warning("f", N("No tape in %s!", $tape_device));
		return 1;
	}	
	
	#- try to roll to the end of the data if we're not erasing
	if (!$media_erase) {
		$command = "mt -f $tape_device rewind";
		spawn_progress($command, "Rewind to find tape label");
		$command = "tar -tf $tape_device";
		spawn_progress($command, "Check for label");
		if ($log_buff =~ /drakbackup.label/) {
			if ($tape_norewind) {
				$command = "mt -f $tape_device rewind";
				spawn_progress($command, "Rewind to get tape label");
			}
			$command = "tar -C $cfg_dir -xf $tape_device";
			spawn_progress($command, "Reading tape label");		
			my @volname = cat_("$cfg_dir/drakbackup.label");
			unlink("$cfg_dir/drakbackup.label");
			$vol_name = $volname[0];
		}
		$command = "mt -f $tape_device eod"; 
		spawn_progress($command, "Running mt to find eod");
	} else {
		$command = "mt -f $tape_device rewind"; 
		spawn_progress($command, "Running mt to rewind");		
		# make a tape label for the catalog
		# if we're using the rewinding device, change modes briefly
		if (!$tape_norewind) {
			$tape_device =~ s|/st|/nst|;
		}
		$vol_name = "Drakbackup" . $the_time;
		my $f = "$cfg_dir/drakbackup.label";
		output($f, $vol_name);
		$command = "tar -C $cfg_dir -cf $tape_device drakbackup.label;";
		spawn_progress($command, "Creating tape label");
		unlink $f;
		if (!$tape_norewind) {
			$tape_device =~ s|/nst|/st|;
		}
	}
	
	#- do the backup
	$command = "tar -cvf $tape_device @file_list_to_send_by_ftp";
	spawn_progress($command, "Running tar to tape");
	
	#- eject the tape?
	if ($media_eject) {
		$command = "mt -f $tape_device rewoff";
		spawn_progress($command, "Running mt to eject tape");
	}
}

# share this with logdrake
sub send_mail {
    my ($result) = @_;
    my $datem = `date`;

    local *F;
    open F, "|/usr/sbin/sendmail -f$user_mail $user_mail" or return 1;
    print F "From: drakbackup\n";
    print F "To: $user_mail \n";
    print F "Subject: DrakBackup report on $datem \n";
    print F "\n";
    print F "$result\n";
    close F or  return 1;
    return 0;
}

sub build_backup_files() {
    my $path_name;
    my $tar_cmd;
    my $more_recent;
    my $tar_cmd_sys;
    my $tar_cmd_user;
    my $tar_cmd_other;
    my $base_sys_exist = 0;
    my @dir_content;
	my $incr;
	
	local $_;
    $results = "";
	$log_buff = "";
	#- flush this so if the user does 2 runs in a row we don't try to send the same files
	@file_list_to_send_by_ftp = ();
		
	$interactive and cursor_wait();
    read_conf_file();
    the_time();    
    $send_mail and complete_results();
    -d  $save_path or mkdir_p($save_path);
		
    if ($comp_mode) { 
		$DEBUG and $tar_cmd = "tar cv --use-compress-program /usr/bin/bzip2 ";
		$DEBUG or $tar_cmd = "tar c --use-compress-program /usr/bin/bzip2 "; 
		$tar_ext = "tar.bz2";
    } else { 
		$DEBUG and $tar_cmd = "tar cvpz "; 
		$DEBUG or $tar_cmd = "tar cpz "; 
		$tar_ext = "tar.gz"
	}
	my $used_space = check_storage_quota($save_path);
	if ($used_space) {
		my $msg = N("Backup quota exceeded!\n%d Mb used vs %d Mb allocated.", $used_space, $max_space);
		show_warning("f", $msg);
		$interactive and cursor_norm();
		$results .= $msg;
		$interactive and show_status();
		results_to_logfile();
		return 1; 
	}
	$tar_cmd_sys = $tar_cmd;
    $tar_cmd_user = $tar_cmd;
    $tar_cmd_other = $tar_cmd;
    $no_critical_sys and $tar_cmd_sys .= "--exclude passwd --exclude fstab --exclude group --exclude mtab";
    $what_no_browser and $tar_cmd_user .= "--exclude NewCache --exclude Cache --exclude cache";
	$nonroot_user and $tar_cmd_user .= " --exclude .drakbackup";

    -d $save_path and @dir_content = all($save_path);
    any { /^backup_base_sys/ } @dir_content and $base_sys_exist = 1;

    if ($where_hd && !$daemon || $daemon) {
	  $interactive and progress($pbar, $plabel, 0.5, N("Backup system files..."));
	  if ($backup_sys) { 
	    if ($backup_sys_versions) {
			$incr = "incr_sys";
			$incr =~ s/incr/diff/ if $sys_diff_mode;
			#- 8/19/2002 - changed these greps to look at the list, rather than the tar file
			#- we retain the list for other media backups, but the tar file goes away, potentially
 			if ((any { /^list_incr_sys/ } @dir_content) && !$sys_diff_mode) { 
		    	my @more_recent = grep { /^list_incr_sys/ } sort @dir_content; 
		    	$more_recent = pop @more_recent;
		    	$DEBUG and print "more recent file: $more_recent\n";
				system("find @sys_files -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_incr_sys$the_time.txt");
		    	if (!cat_("$save_path/list_incr_sys$the_time.txt")) {
					system("rm $save_path/list_incr_sys$the_time.txt");
		    	} else {
					system("$tar_cmd_sys -f $save_path/backup_incr_sys$the_time.$tar_ext -T $save_path/list_incr_sys$the_time.txt");
					push @file_list_to_send_by_ftp, "$save_path/backup_incr_sys$the_time.$tar_ext";
					push @file_list_to_send_by_ftp, "$save_path/list_incr_sys$the_time.txt";
					$results .= "\nfile: $save_path/backup_incr_sys$the_time.$tar_ext\n";
					$results .= cat_("$save_path/list_incr_sys$the_time.txt");
		    	}
			} elsif (any { /^list_base_sys/ }  @dir_content) { 
		    	my @more_recent = grep { /^list_base_sys/ } sort @dir_content; 
		    	$more_recent = pop @more_recent;
		    	$DEBUG and print "more recent file: $more_recent\n";
  		  		system("find @sys_files -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_$incr$the_time.txt");
		    	if (!cat_("$save_path/list_$incr$the_time.txt")) {
					system("rm $save_path/list_$incr$the_time.txt");
		    	} else {
					system("$tar_cmd_sys -f $save_path/backup_$incr$the_time.$tar_ext -T $save_path/list_$incr$the_time.txt");
					push @file_list_to_send_by_ftp, "$save_path/backup_$incr$the_time.$tar_ext";
					push @file_list_to_send_by_ftp, "$save_path/list_$incr$the_time.txt";
					$results .= "\nfile: $save_path/backup_$incr$the_time.$tar_ext\n";
					$results .= cat_("$save_path/list_$incr$the_time.txt");
		    	}
			} else {
				#- need this for the first pass too, if we're offloading the backups to other media (sb)
				system("find @sys_files ! -type d -print > $save_path/list_base_sys$the_time.txt"); 
				system("$tar_cmd_sys -f $save_path/backup_base_sys$the_time.$tar_ext @sys_files"); 
				push @file_list_to_send_by_ftp, "$save_path/backup_base_sys$the_time.$tar_ext";
				push @file_list_to_send_by_ftp, "$save_path/list_base_sys$the_time.txt";
				$results .= "\nfile: $save_path/backup_base_sys$the_time.$tar_ext\n";
			}
	  	} else {
			system("cd $save_path && rm -f backup_sys* backup_base_sys* backup_incr_sys*");
			system("$tar_cmd_sys -f $save_path/backup_sys$the_time.$tar_ext @sys_files");
			push @file_list_to_send_by_ftp, "$save_path/backup_sys$the_time.$tar_ext";
			$results .= "\nfile: $save_path/backup_sys$the_time.$tar_ext\n";
	  	}
	  }
	  $interactive and progress($pbar, $plabel, 0.5, N("Backup system files..."));
	  $interactive and progress($pbar3, $plabel3, 0.3, N("Hard Disk Backup files..."));
	
	  if ($backup_user) {
	    foreach (@user_list) {
		  my $user = $_;
		  $path_name = return_path($user);
		  if ($backup_user_versions) {
			$incr = "incr_user_";
			$incr =~ s/incr/diff/ if $user_diff_mode;
			#- 8/19/2002 - changed these greps to look at the list, rather than the tar file
			#- we retain the list for other media backups, but the tar file goes away, potentially
		    if ((any { /^list_incr_user_$user/ } @dir_content) && !$user_diff_mode) { 
				my @more_recent = grep { /^list_incr_user_$user/ } sort @dir_content; 
				$more_recent = pop @more_recent;
				$DEBUG and print "more recent file: $more_recent\n";
				system("find $path_name -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_incr_user_$user$the_time.txt");
				if (!cat_("$save_path/list_incr_user_$user$the_time.txt")) {
			    	system("rm $save_path/list_incr_user_$user$the_time.txt");
				} else {
					system("$tar_cmd_user -f $save_path/backup_incr_user_$user$the_time.$tar_ext -T $save_path/list_incr_user_$user$the_time.txt");
					push @file_list_to_send_by_ftp, "$save_path/backup_incr_user_$user$the_time.$tar_ext";
					push @file_list_to_send_by_ftp, "$save_path/list_incr_user_$user$the_time.txt";
					$results .= " \nfile: $save_path/backup_incr_user_$user$the_time.$tar_ext\n";
					$results .= cat_("$save_path/list_incr_user_$user$the_time.txt");
				}
		    } elsif (any { /^list_base_user_$user/ } @dir_content) { 
				my @more_recent = grep { /^list_base_user_$user/ } sort @dir_content; 
				$more_recent = pop @more_recent;			
				$DEBUG and print "more recent file: $more_recent\n";
				system("find $path_name -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_$incr$user$the_time.txt");
				if (!cat_("$save_path/list_$incr$user$the_time.txt")) {
			    	system("rm $save_path/list_$incr$user$the_time.txt");
				} else {
					system("$tar_cmd_user -f $save_path/backup_$incr$user$the_time.$tar_ext -T $save_path/list_$incr$user$the_time.txt");
					push @file_list_to_send_by_ftp, "$save_path/backup_$incr$user$the_time.$tar_ext";
					push @file_list_to_send_by_ftp, "$save_path/list_$incr$user$the_time.txt";
					$results .= "\nfile: $save_path/backup_$incr$user$the_time.$tar_ext\n";
					$results .= cat_("$save_path/list_$incr$user$the_time.txt");
				}
		    } else {
				#- need this for the first pass too, if we're offloading the backups to other media (sb)
				system("find $path_name ! -type d -print > $save_path/list_base_user_$user$the_time.txt");
				system("$tar_cmd_user -f $save_path/backup_base_user_$user$the_time.$tar_ext $path_name");
				push @file_list_to_send_by_ftp, "$save_path/backup_base_user_$user$the_time.$tar_ext";
				push @file_list_to_send_by_ftp, "$save_path/list_base_user_$user$the_time.txt";
				$results .= "\nfile: $save_path/backup_base_user_$user$the_time.$tar_ext\n";
		    }
		  } else {
		    system("cd $save_path && rm -f backup_user_$_* backup_base_user_$_* backup_incr_user_$_*");
		    system("$tar_cmd_user -f $save_path/backup_user_$_$the_time.$tar_ext $path_name");
		    push @file_list_to_send_by_ftp, "$save_path/backup_user_$_$the_time.$tar_ext";
		    $results .= "\nfile: $save_path/backup_user_$user$the_time.$tar_ext\n";
		  }
	    }
	  }
	  $interactive and progress($pbar2, $plabel1, 1, N("Backup User files..."));
	  $interactive and progress($pbar3, $plabel3, 0.4, N("Hard Disk Backup files..."));

	  if (@list_other) {
		if ($backup_other_versions) {
			$incr = "incr_other";
			$incr =~ s/incr/diff/ if $other_diff_mode;
 			if ((any { /^list_incr_other/ } @dir_content) && !$user_diff_mode) { 
		    	my @more_recent = grep { /^list_incr_other/ } sort @dir_content; 
		    	$more_recent = pop @more_recent;
		    	$DEBUG and print "more recent file: $more_recent\n";
				system("find @list_other -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_incr_other$the_time.txt");
		    	if (!cat_("$save_path/list_incr_other$the_time.txt")) {
					system("rm $save_path/list_incr_other$the_time.txt");
		    	} else {
					system("$tar_cmd_other -f $save_path/backup_incr_other$the_time.$tar_ext -T $save_path/list_incr_other$the_time.txt");
					push @file_list_to_send_by_ftp, "$save_path/backup_incr_other$the_time.$tar_ext";
					push @file_list_to_send_by_ftp, "$save_path/list_incr_other$the_time.txt";
					$results .= "\nfile: $save_path/backup_incr_other$the_time.$tar_ext\n";
					$results .= cat_("$save_path/list_incr_other$the_time.txt");
		    	}
			} elsif (any { /^list_base_other/ }  @dir_content) { 
		    	my @more_recent = grep { /^list_base_other/ } sort @dir_content; 
		    	$more_recent = pop @more_recent;
		    	$DEBUG and print "more recent file: $more_recent\n";
  		  		system("find @list_other -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_$incr$the_time.txt");
		    	if (!cat_("$save_path/list_$incr$the_time.txt")) {
					system("rm $save_path/list_$incr$the_time.txt");
		    	} else {
					system("$tar_cmd_other -f $save_path/backup_$incr$the_time.$tar_ext -T $save_path/list_$incr$the_time.txt");
					push @file_list_to_send_by_ftp, "$save_path/backup_$incr$the_time.$tar_ext";
					push @file_list_to_send_by_ftp, "$save_path/list_$incr$the_time.txt";
					$results .= "\nfile: $save_path/backup_$incr$the_time.$tar_ext\n";
					$results .= cat_("$save_path/list_$incr$the_time.txt");
		    	}
			} else {
				#- need this for the first pass too, if we're offloading the backups to other media (sb)
				system("find @list_other ! -type d -print > $save_path/list_base_other$the_time.txt"); 
				system("$tar_cmd_other -f $save_path/backup_base_other$the_time.$tar_ext @list_other"); 
				push @file_list_to_send_by_ftp, "$save_path/backup_base_other$the_time.$tar_ext";
				push @file_list_to_send_by_ftp, "$save_path/list_base_other$the_time.txt";
				$results .= "\nfile: $save_path/backup_base_other$the_time.$tar_ext\n";
			}
	  	} else {
			system("cd $save_path && rm -f backup_other* backup_base_other* backup_incr_other*");
			system("$tar_cmd_other -f $save_path/backup_other$the_time.$tar_ext @list_other");
			push @file_list_to_send_by_ftp, "$save_path/backup_other$the_time.$tar_ext";
			$results .= "\nfile: $save_path/backup_other$the_time.$tar_ext\n";
	  	}
	  }
	  $interactive and progress($pbar1, $plabel2, 1, N("Backup Other files..."));
	  $interactive and progress($pbar3, $plabel3, 0.3, N("Hard Disk Backup Progress..."));
	}
	  
	my $filecount = @file_list_to_send_by_ftp;
	if (!$filecount) {
		my $msg = N("No changes to backup!");
		show_warning("w", $msg);
		$interactive and cursor_norm();
		$interactive and interactive_mode();
		results_to_logfile();
		return 1;		
	}
		
	#- should hit this block if running daemon mode only
	if ($daemon && $daemon_media) {
#		ftp_client() if $ftp_daemon;
		rsync_client() if $daemon_media eq 'rsync';
		ssh_client() if $daemon_media eq 'ssh' && !$use_expect;
		do_expect("backup") if $daemon_media eq 'ssh' && $use_expect;
		webdav_client() if $daemon_media eq 'webdav';
		build_cd() if $daemon_media eq 'cd';
		build_tape() if $daemon_media eq 'tape';

		$results .= N("\nDrakbackup activities via %s:\n\n", $daemon_media);
		$results .= $log_buff;
	}
	
	#- leave this one alone for now - works well
	#- integrate with other methods later
    if (($where_net && !$daemon && $net_proto eq 'ftp') || $daemon && $daemon_media eq 'ftp') {
		$results .= N("file list sent by FTP: %s\n ", $_)  foreach @file_list_to_send_by_ftp;
		$interactive and build_backup_ftp_status();
		if (ftp_client()) { 
	    	$results .= N("\n FTP connection problem: It was not possible to send your backup files by FTP.\n");
	    	$interactive and client_ftp_pb();
		} 
    }
	
	#- consolidate all the other methods under here - interactive and --default should land here
	if (!$daemon) {
	
		if ($where_net && $net_proto && $net_proto ne 'ftp') {
			rsync_client() if $net_proto eq 'rsync';
			ssh_client() if $net_proto eq 'ssh' && !$use_expect;
			do_expect("backup") if $net_proto eq 'ssh' && $use_expect;
			webdav_client() if $net_proto eq 'webdav';
			$results .= N("\nDrakbackup activities via %s:\n\n", $net_proto);
		}
		
		if ($where_cd) {
			build_cd();
			$results .= N("\nDrakbackup activities via CD:\n\n");
		}
	
		if ($where_tape) {
			build_tape();
			$results .= N("\nDrakbackup activities via tape:\n\n");
		}
		$results .= $log_buff;
		results_to_logfile();
	}
	
    if ($send_mail) { 
		if (send_mail($results)) { 
	    	$interactive and send_mail_pb();
	    	$interactive or print N(" Error while sending mail. \n");
		} 
    }
	
	#- write our catalog file
	if (!$media_problem) {
		my $catalog = substr($the_time, 1);
		if (!$where_net && !$where_tape && !$where_cd) { 
			$catalog .= ":HD:localhost:$save_path";
			$net_proto = '';
		} 
		$catalog .= ":$net_proto:$login_user\@$host_name:$host_path" if $net_proto;
		$catalog .= ":CD:$vol_name:$cd_device" if $where_cd;
		$catalog .= ":Tape:$vol_name:$tape_device" if $where_tape;
		$catalog .= ":System" if $backup_sys;
		$catalog .= ":I" if $backup_sys_versions && $backup_sys && !$sys_diff_mode;
		$catalog .= ":D" if $backup_sys_versions && $backup_sys && $sys_diff_mode;
		$catalog .= ":F" if !$backup_sys_versions && $backup_sys;
		$catalog .= ":Users=(@user_list)" if $backup_user;
		$catalog .= ":I" if $backup_user_versions && $backup_user && !$user_diff_mode;
		$catalog .= ":D" if $backup_user_versions && $backup_user && $user_diff_mode;
		$catalog .= ":F" if !$backup_user_versions && $backup_user;;
		$catalog .= ":Other=(@list_other)" if @list_other;
		$catalog .= ":I" if $backup_other_versions && @list_other && !$other_diff_mode;
		$catalog .= ":D" if $backup_other_versions && @list_other && $other_diff_mode;
		$catalog .= ":F" if !$backup_other_versions && @list_other;
		$catalog .= "\n";
			
		local *CATALOG;
		open CATALOG, ">> $cfg_dir/drakbackup_catalog" or show_warning("w", N("Can't create catalog!"));
		print CATALOG $catalog;
		close CATALOG;
	}
	
	#- clean up HD files if del_hd_files and media isn't hd
	if ($del_hd_files && ($where_cd || $where_tape || $where_net) && $daemon_media ne 'hd')  {
		foreach (@file_list_to_send_by_ftp) {
#			unlink($_) if (/$tar_ext$/) && (!/backup_base/);
			unlink($_) if /$tar_ext$/;
		}
	}
		
	#- if we had a media problem then get rid of the text log of the backed up files too
	if ($media_problem) {
		system("rm $save_path/list*$the_time.txt");
	}
	
	$interactive and cursor_norm();
	$interactive and show_status();
}

my @list_of_rpm_to_install;
sub require_rpm {
    my $all_rpms_found = 1;
    my $res;
#    my @file_cache =  cat_("/var/log/rpmpkgs");
    @list_of_rpm_to_install = ();
#- reverted to old method - /var/log/rpmpkgs is not always accurate
#    my($pkg) = @_;
    foreach my $pkg (@_) {
#	   $res = grep /$pkg/, @file_cache;
		$res = system("rpm -q $pkg > /dev/null");
		if ($res == 256) { 
			$all_rpms_found = 0; 
			push @list_of_rpm_to_install, $pkg;
		}
    }
    return $all_rpms_found;
}

sub check_pkg_needs() {
	my $extra_pkg = '';
	if ($where_net) {
		$extra_pkg = 'rsync' if $net_proto eq 'rsync';
		$extra_pkg = 'sitecopy wget' if $net_proto eq 'webdav';
		$extra_pkg = 'perl-Expect' if $net_proto eq 'ssh' && ($use_expect || $xfer_keys);
	}
	$extra_pkg = 'mt-st' if $where_tape;
	if ($extra_pkg) {
		if (require_rpm($extra_pkg)) {
			return 0;
		} else {
			#- this isn't entirely good, but it's the only way we get here currently
			#- was getting strange return behavior before
			#- still a problem, we can also get here from the cron screen
			install_rpm(\&advanced_where);
			return 1;
		}		
	}	
}

sub cursor_wait() {
	# turn the cursor to a watch
	$window1->window->set_cursor(new Gtk2::Gdk::Cursor("GDK_WATCH"));    
	gtkflush();
}

sub cursor_norm() {
	# restore normal cursor
	$window1->window->set_cursor(new Gtk2::Gdk::Cursor("GDK_LEFT_PTR"));
	gtkflush();
}

sub show_status() {
    my $text = new Gtk2::TextView;	
	destroy_widget();
	my $scrolled_window = Gtk2::ScrolledWindow->new;
	$scrolled_window->set_border_width(10);
	$scrolled_window->add_with_viewport($text);
	gtktext_insert(gtkset_editable($text, 0), [ [ $results ] ]);

    gtkpack($advanced_box,
		$table = gtkpack_(new Gtk2::VBox(0,10), 1, $scrolled_window)
	);
    $central_widget = \$table;
    $table->show_all;    
}

sub results_to_logfile() {
		local *LOG;
		open LOG, "> $log_file" or show_warning("w", N("Can't create log file!"));
		print LOG "$results\n";
		close LOG;
}

sub file_ok_sel { 
    my ($file_selection) = @_;     
    my $file_name = $file_selection->get_filename;
    if (!member($file_name, @list_other)) {
		push(@list_other, $file_name);
		$list_model->append($iter);
		$list_model->set($iter, [ 0 => $file_name ]);
    }
}

sub filedialog_where_hd() {
    my $file_dialog;

    $file_dialog = gtksignal_connect(new Gtk2::FileSelection(N("File Selection")), destroy => sub { $file_dialog->destroy });
    $file_dialog->ok_button->signal_connect(clicked => sub { 
	$save_path_entry->set_text($file_dialog->get_filename); 
	$file_dialog->destroy });
    $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy });
    $file_dialog->show;
}

sub filedialog_restore_find_path() {
    my $file_dialog;

    $file_dialog = gtksignal_connect(new Gtk2::FileSelection(N("File Selection")), destroy => sub { $file_dialog->destroy });
    $file_dialog->ok_button->signal_connect(clicked => sub { 
		$restore_find_path_entry->set_text($file_dialog->get_filename);
		$file_dialog->destroy;
	});
    $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy });
    $file_dialog->show;
}

sub filedialog_generic {
	#- a more generic file dialog
	#- a title prompt, the widget to get updated and the variable to update
	my ($prompt, $widget, $set_var) = @_; 
	my $file_dialog;
	
    $file_dialog = gtksignal_connect(new Gtk2::FileSelection(translate($prompt)), destroy => sub { $file_dialog->destroy });
    $file_dialog->ok_button->signal_connect(clicked => sub { 
		$$set_var = $file_dialog->get_filename;
		$$widget->set_text($$set_var); 
		$file_dialog->destroy;
	});
    $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy });
    $file_dialog->show;
}

sub filedialog() {
    my $file_dialog;

    $file_dialog = gtksignal_connect(new Gtk2::FileSelection(N("Select the files or directories and click on 'OK'")), destroy => sub { $file_dialog->destroy });
    $file_dialog->ok_button->signal_connect(clicked => sub { file_ok_sel($file_dialog) });
    $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy });
    $file_dialog->show;
}

################################################  ADVANCED  ################################################  

sub check_list {
    foreach (@_) {
	my $ref = $_->[1];
		gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { 
			invbool $ref; 
			destroy_widget();
			$current_widget->();
		});
	}
}

sub fonction_env {
    ($central_widget, $current_widget, $previous_widget, $custom_help, $next_widget) = @_;
}

sub advanced_what_sys() {
    my $box_what_sys;
    
    gtkpack($advanced_box,
	    $box_what_sys =  gtkpack_(new Gtk2::VBox(0, 15),
		     1, N("\nPlease check all options that you need.\n"),
		     1, N("These options can backup and restore all files in your /etc directory.\n"),
		     0, my $check_what_sys = new Gtk2::CheckButton(N("Backup your System files. (/etc directory)")),
		     0, my $check_what_versions = new Gtk2::CheckButton(N("Use Incremental/Differential Backups  (do not replace old backups)")),
		     0, gtkpack__(new Gtk2::HBox(0,0),	
				my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")),
			 ),
			 0, my $check_what_critical = new Gtk2::CheckButton(N("Do not include critical files (passwd, group, fstab)")),
		     0, N("With this option you will be able to restore any version\n of your /etc directory."),     
			 1, new Gtk2::VBox(0, 15),
		),
	);
    check_list([$check_what_sys, \$backup_sys], [$check_what_critical, \$no_critical_sys]);
	$check_what_versions->set_active($backup_sys_versions);
	$check_what_versions->signal_connect('toggled' => sub {
		invbool \$backup_sys_versions;
		$mode_buttons[0]->set_sensitive($backup_sys_versions);
		$mode_buttons[1]->set_sensitive($backup_sys_versions);
			
	});
	$mode_buttons[1]->set_active($sys_diff_mode);
	$mode_buttons[0]->signal_connect('toggled' => sub { $sys_diff_mode = $mode_buttons[1]->get_active });
	$mode_buttons[0]->set_sensitive($backup_sys_versions);
	$mode_buttons[1]->set_sensitive($backup_sys_versions);
    fonction_env(\$box_what_sys, \&advanced_what_sys, \&advanced_what, "what");
    $up_box->show_all;
}

sub advanced_what_user {
    my ($previous_function) = @_;
    my $box_what_user;
    my %check_what_user;
    
    all_user_list();
    gtkpack($advanced_box,
	    $box_what_user = gtkpack_(new Gtk2::VBox(0, 15),
			0, N("Please check all users that you want to include in your backup."),
			0, new Gtk2::HSeparator,
			1, create_scrolled_window( 
				gtkpack__(new Gtk2::VBox(0,0),
					map { my $name = $_;
						my @user_list_tmp;
						my $b = new Gtk2::CheckButton($name); 
						if (any { /^$name$/ } @user_list) {
							$check_what_user{$_}[1] = 1;
							gtkset_active($b, 1);
						} else {
							$check_what_user{$_}[1] = 0;
							gtkset_active($b, 0);
						}
						$b->signal_connect(toggled => sub { 
							if ($check_what_user{$name}[1]) {
								$check_what_user{$name}[1] = 0;
								@user_list_tmp = grep { !/^$name$/ } @user_list;
								@user_list = @user_list_tmp;
							} else { 
								$check_what_user{$name}[1] = 1;
								if (!member($name, @user_list)) { push @user_list, $name }
							}
						});
					$b } (@all_user_list) 
				),
			),
			0, my $check_what_browser = new Gtk2::CheckButton(N("Do not include the browser cache")),
			0, my $check_what_user_versions = new Gtk2::CheckButton(N("Use Incremental/Differential Backups  (do not replace old backups)")), 
		    0, gtkpack__(new Gtk2::HBox(0,0),	
				my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")),
			),
		),
	);
    check_list([$check_what_browser, \$what_no_browser]);
	$check_what_user_versions->set_active($backup_user_versions);
	$check_what_user_versions->signal_connect('toggled' => sub {
		invbool \$backup_user_versions; 
		$mode_buttons[0]->set_sensitive($backup_user_versions);
		$mode_buttons[1]->set_sensitive($backup_user_versions);	
	});
	$mode_buttons[1]->set_active($user_diff_mode);
	$mode_buttons[0]->signal_connect('toggled' => sub { $user_diff_mode = $mode_buttons[1]->get_active });
	$mode_buttons[0]->set_sensitive($backup_user_versions);
	$mode_buttons[1]->set_sensitive($backup_user_versions);
    if ($previous_function) { fonction_env(\$box_what_user, \&advanced_what_user, \&$previous_function, "what", \&$previous_function) }
    else { fonction_env(\$box_what_user, \&advanced_what_user, \&advanced_what, "what") }
    $up_box->show_all;
}

sub advanced_what_other() {
    my $box_what_other;
	my $file_iter;
	my $other_file;
			
	$list_model = Gtk2::ListStore->new("Glib::String");
	my $list_others = Gtk2::TreeView->new_with_model($list_model);
	$list_others->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0));
	$list_others->set_headers_visible(0);	
		
	foreach (@list_other) {
    	$list_model->append_set(undef, $_);		
	}
	
	$list_others->get_selection->signal_connect(changed => sub {
    	my ($model, $iter) = $_[0]->get_selected;
    	$model && $iter or return;
    	$other_file = $model->get($iter, 0);
		$file_iter = $iter;
	});
	    
    gtkpack($advanced_box,
	    $box_what_other = gtkpack_(new Gtk2::VBox(0, 15),
			1, gtkpack_(new Gtk2::HBox(0,4),
				1, create_scrolled_window($list_others),
			),
			0, gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'),
				gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub { filedialog() }),
				gtksignal_connect(Gtk2::Button->new(N("Remove Selected")), clicked => sub { 
					$list_model->remove($file_iter); 
					my $iindex = 0; 
					foreach (@list_other) {
						if ($list_other[$iindex] eq $other_file) {
							splice(@list_other, $iindex, 1); 
							last;
						}
						$iindex++;
					}
				}),
			),
			0, my $check_what_other_versions = new Gtk2::CheckButton(N("Use Incremental/Differential Backups  (do not replace old backups)")),
			0, gtkpack__(new Gtk2::HBox(0,0),	
				my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")),
			),
		),
		
	);
	$check_what_other_versions->set_active($backup_other_versions);
	$check_what_other_versions->signal_connect('toggled' => sub {
		invbool \$backup_other_versions; 
		$mode_buttons[0]->set_sensitive($backup_other_versions);
		$mode_buttons[1]->set_sensitive($backup_other_versions);	
	});
	$mode_buttons[1]->set_active($other_diff_mode);
	$mode_buttons[0]->signal_connect('toggled' => sub { $other_diff_mode = $mode_buttons[1]->get_active });
	$mode_buttons[0]->set_sensitive($backup_other_versions);
	$mode_buttons[1]->set_sensitive($backup_other_versions);
    fonction_env(\$box_what_other, \&advanced_what_other, \&advanced_what, "what");
    $up_box->show_all;			
}

sub advanced_what_entire_sys() {
    my $box_what;
    
    gtkpack($advanced_box,
	    $box_what = gtkpack_(new Gtk2::HBox(0, 15),
		     1, new Gtk2::VBox(0, 5),
		     1, gtkpack_(new Gtk2::VBox(0, 15),	
				 1, new Gtk2::VBox(0, 5),
				 1, gtksignal_connect(my $button_what_other = Gtk2::Button->new, 
						      clicked => sub { destroy_widget(); message_underdevel() }),
				 1, gtksignal_connect(my $button_what_all = Gtk2::Button->new, 
						      clicked => sub { destroy_widget(); message_underdevel() }),
				 1, new Gtk2::VBox(0, 5),
				 ),
		     1, new Gtk2::VBox(0, 5),	
		     ),
	    );
    $button_what_other->add(gtkpack(new Gtk2::HBox(0,10),
				    gtkcreate_img("bootloader"),
				    new Gtk2::Label(N("Linux")),
				    new Gtk2::HBox(0, 5)
				    ));
    $button_what_all->add(gtkpack(new Gtk2::HBox(0,10),
				  gtkcreate_img("user"),
				  new Gtk2::Label(N("Windows (FAT32)")),
				  new Gtk2::HBox(0, 5)
				  ));
    fonction_env(\$box_what, \&advanced_what_entire_sys, \&advanced_what, "");
    $up_box->show_all;
}

sub advanced_what() {
    my $box_what;    

    gtkpack($advanced_box,
	    $box_what =  gtkpack_(new Gtk2::HBox(0, 15),
		     1, new Gtk2::VBox(0, 5),
		     1, gtkpack_(new Gtk2::VBox(0, 15),	
				 1, new Gtk2::VBox(0, 5),
				 1, gtksignal_connect(my $button_what_sys = Gtk2::Button->new, 
						      clicked => sub { $box_what->destroy; advanced_what_sys() }),
				 1, gtksignal_connect(my $button_what_user = Gtk2::Button->new, 
						      clicked => sub { destroy_widget(); advanced_what_user() }),
				 1, gtksignal_connect(my $button_what_other = Gtk2::Button->new, 
						      clicked => sub { destroy_widget(); advanced_what_other() }),
#				 1, gtksignal_connect(my $button_what_all = Gtk2::Button->new, 
#						  clicked => sub { destroy_widget(); advanced_what_entire_sys(); }),
				 1, new Gtk2::VBox(0, 5),
				 ),
		     1, new Gtk2::VBox(0, 5),	
				 ),
	    );
    $button_what_sys->add(gtkpack(new Gtk2::HBox(0,10),
				    gtkcreate_img("ic82-system-40"),
				    new Gtk2::Label(N("System")),
				    new Gtk2::HBox(0, 5)
				    ));
    $button_what_user->add(gtkpack(new Gtk2::HBox(0,10),
				    gtkcreate_img("ic82-users-40"),
				    new Gtk2::Label(N("Users")),
				    new Gtk2::HBox(0, 5)
				    ));
    $button_what_other->add(gtkpack(new Gtk2::HBox(0,10),
				    gtkcreate_img("ic82-others-40"),
				    new Gtk2::Label(N("Other")),
				    new Gtk2::HBox(0, 5)
				    ));
#     $button_what_all->add(gtkpack(new Gtk2::HBox(0,10),
# 				    gtkcreate_img("ic82-systemeplus-40"),
# 				    new Gtk2::Label(N("An Entire System")),
# 				    new Gtk2::HBox(0, 5)
# 				    ));

    fonction_env(\$box_what, \&advanced_what, \&advanced_box, "");
    $up_box->show_all;
}

sub advanced_where_net_types {
    my ($previous_function) = @_;
    my $box_where_net;
	        
    gtkpack($advanced_box,
	    $box_where_net = gtkpack_(new Gtk2::VBox(0, 10),
	 		0, new Gtk2::HSeparator,
	 		0, gtkpack_(new Gtk2::HBox(0,10),
	 			0, my $check_where_use_net = new Gtk2::CheckButton(N("Use network connection to backup")),
				1, new Gtk2::HBox(0,10),
	 			0, new Gtk2::Label(N("Net Method:")),
	 			0, gtkset_sensitive(my $entry_net_type = new Gtk2::OptionMenu(), $where_net),
	 		),	 
	 		0, gtkpack_(new Gtk2::HBox(0,5),
	   			0, gtkset_sensitive(my $check_use_expect = new Gtk2::CheckButton(N("Use Expect for SSH")), ($where_net && $net_proto eq 'ssh')),
	   			0, gtkset_sensitive(my $check_xfer_keys = new Gtk2::CheckButton(N("Create/Transfer\nbackup keys for SSH")), ($where_net && $net_proto eq 'ssh')),
				0, gtkset_sensitive(my $button_xfer_keys = Gtk2::Button->new_from_stock(N("  Transfer  \nNow")), $xfer_keys),
	   			0, gtkset_sensitive(my $check_user_keys = new Gtk2::CheckButton(N("Other (not drakbackup)\nkeys in place already")), ($where_net && $net_proto eq 'ssh')),
			),
	 		0, new Gtk2::HSeparator,
	 		0, gtkpack_(new Gtk2::HBox(0,10),
		    	0, gtkset_sensitive(new Gtk2::Label(N("Host name or IP.")), $where_net),
		    	1, new Gtk2::HBox(0,10),
		    	0, gtkset_sensitive(my $host_name_entry = new Gtk2::Entry(), $where_net),
		    ),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
	 			0, gtkset_sensitive(new Gtk2::Label(N("Directory (or module) to\n put the backup on this host.")), $where_net),
		     	1, new Gtk2::HBox(0,10),
		     	0, gtkset_sensitive(my $host_path_entry = new Gtk2::Entry(), $where_net), 
		    ),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
		    	0, gtkset_sensitive(new Gtk2::Label(N("Login name")), $where_net),
				1, new Gtk2::HBox(0,10),
				0, gtkset_sensitive(my $login_user_entry = new Gtk2::Entry(), $where_net),
			),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
				0, gtkset_sensitive(new Gtk2::Label(N("Password")),  $where_net),
				1, new Gtk2::HBox(0,10),
				0, gtkset_sensitive(my $passwd_user_entry = new Gtk2::Entry(), $where_net),
			),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
				1, new Gtk2::HBox(0,10),
				0, gtkset_sensitive(my $check_remember_pass = new Gtk2::CheckButton(N("Remember this password")), $where_net),
	 		),
	 	),   
	);
	$entry_net_type->set_popdown_strings(@net_methods);
	$entry_net_type->entry->set_text($net_proto);
	$button_xfer_keys->signal_connect('clicked', sub { 
		if ($passwd_user && $login_user && $host_name) {
			do_expect("sendkey");
		} else {
			$in->ask_warn('', N("Need hostname, username and password!"));
		}
	}); 	
    $passwd_user_entry->set_visibility(0);
    $passwd_user_entry->set_text($passwd_user);
    $passwd_user_entry->signal_connect('changed', sub { $passwd_user = $passwd_user_entry->get_text });
    $host_path_entry->set_text($host_path);
    $host_name_entry->set_text($host_name);
    $login_user_entry->set_text($login_user);
    $host_name_entry->signal_connect('changed', sub { $host_name = $host_name_entry->get_text });
    $host_path_entry->signal_connect('changed', sub { $host_path = $host_path_entry->get_text });
    $login_user_entry->signal_connect('changed', sub { $login_user = $login_user_entry->get_text });
    $entry_net_type->entry->signal_connect('changed', sub { 
		$net_proto = $entry_net_type->entry->get_text;
		my $sensitive = 0;
		$sensitive = 1 if $net_proto eq 'ssh';
		$check_use_expect->set_sensitive($sensitive);
		$check_xfer_keys->set_sensitive($sensitive);
		$button_xfer_keys->set_sensitive($sensitive);
		$check_user_keys->set_sensitive($sensitive);
	});
    check_list([$check_remember_pass, \$remember_pass]);
    gtksignal_connect(gtkset_active($check_where_use_net, $where_net), toggled => sub { 
		invbool \$where_net;
 		#- assure other methods disabled
		if ($where_net == 1) {
			$where_cd = 0;
			$where_tape = 0;
		}
		$net_proto = '' if $where_net == 0; 
		destroy_widget();
 		$current_widget->();
    });
	gtksignal_connect(gtkset_active($check_use_expect, $use_expect), toggled => sub { 
		invbool \$use_expect;
 		#- assure other methods disabled
		if ($use_expect == 1) {
			$xfer_keys = 0;
			$user_keys = 0;
		}
		destroy_widget();
 		$current_widget->();
    });
	gtksignal_connect(gtkset_active($check_xfer_keys, $xfer_keys), toggled => sub { 
		invbool \$xfer_keys;
		#- assure other methods disabled
		if ($xfer_keys == 1) {
			$use_expect = 0;
			$user_keys = 0;
		}
		destroy_widget();
 		$current_widget->();
    });
	gtksignal_connect(gtkset_active($check_user_keys, $user_keys), toggled => sub { 
		invbool \$user_keys;
 		#- assure other methods disabled
		if ($user_keys == 1) {
			$xfer_keys = 0;
			$use_expect = 0;
		}
		destroy_widget();
 		$current_widget->();
    });
    if ($previous_function) { 
		fonction_env(\$box_where_net, \&advanced_where_net_types, \&$previous_function, "net");
    } else { 
		fonction_env(\$box_where_net, \&advanced_where_net_types, \&advanced_where, "net");
	}
    $up_box->show_all;
}

sub advanced_where_cd {
    my ($previous_function) = @_;
    my $box_where_cd;
	
	get_cd_info();
	
	my $combo_where_cd_device = new Gtk2::OptionMenu();
	if (keys %cd_devices) {
    	$combo_where_cd_device->set_popdown_strings(sort keys %cd_devices);
	} else {
		$combo_where_cd_device->set_popdown_strings(@no_devices);
	}  
	
    my $combo_where_cd_time = new Gtk2::OptionMenu();
    $combo_where_cd_time->set_popdown_strings("650 Mb", "700 Mb", "750 Mb", "800 Mb");    
 
	my $combo_where_cdrecord_device = new Gtk2::Combo();
	my @dev_codes;
	
	foreach my $key (keys %cd_devices) {
		push(@dev_codes, $cd_devices{$key}{rec_dev}); 
	}
	
    $combo_where_cdrecord_device->set_popdown_strings(@dev_codes) if keys %cd_devices;  	 

    gtkpack($advanced_box,
		$box_where_cd = gtkpack_(new Gtk2::VBox(0, 6),
			0, my $check_where_cd = new Gtk2::CheckButton(N("Use CD/DVDROM to backup")),
			0, new Gtk2::HSeparator,
			0, gtkpack_(new Gtk2::HBox(0,10),
			0, gtkset_sensitive(new Gtk2::Label(N("Choose your CD/DVD device")), $where_cd),
				1, new Gtk2::VBox(0, 5),
				0, gtkset_sensitive($combo_where_cd_device, $where_cd),
			),
			0, gtkpack_(new Gtk2::HBox(0,10),
			0, gtkset_sensitive(new Gtk2::Label(N("Choose your CD/DVD media size (Mb)")), $where_cd),
				1, new Gtk2::VBox(0, 5),
				0, gtkset_sensitive($combo_where_cd_time, $where_cd),
			),
			0, new Gtk2::VBox(0, 5),
			0, gtkpack_(new Gtk2::HBox(0,10),
				1, new Gtk2::VBox(0, 5),
				0, gtkset_sensitive(new Gtk2::Label(N("Multisession CD")), $where_cd),
				0, gtkset_sensitive(my $check_multisession = new Gtk2::CheckButton(), $where_cd),
				0, gtkset_sensitive(new Gtk2::Label(N("CDRW media")), $where_cd),
				0, gtkset_sensitive(my $check_cdrw = new Gtk2::CheckButton(), $where_cd),
			),
			0, new Gtk2::VBox(0, 5),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
	 			0, gtkset_sensitive(new Gtk2::Label(N("Erase your RW media (1st Session)")), $cdrw && $where_cd),
				0, gtkset_sensitive(my $button_erase_now = Gtk2::Button->new_from_stock(N(" Erase Now ")), $cdrw),			
	    		1, new Gtk2::VBox(0, 5),
	    		0, gtkset_sensitive(my $check_cdrw_erase = new Gtk2::CheckButton(), $cdrw && $where_cd),
			),
			0, new Gtk2::VBox(0, 5),
			0, gtkpack_(new Gtk2::HBox(0,10),
				1, new Gtk2::VBox(0, 5),
				0, gtkset_sensitive(new Gtk2::Label(N("DVDR device")), $where_cd),
				0, gtkset_sensitive(my $check_dvdr = new Gtk2::CheckButton(), $where_cd),
				0, gtkset_sensitive(new Gtk2::Label(N("DVDRAM device")), $where_cd),
				0, gtkset_sensitive(my $check_dvdram = new Gtk2::CheckButton(), $where_cd),
			),
# don't know what this is about - hold off for now (SB)
#			0, new Gtk2::VBox(0, 5),
#			0, gtkpack_(new Gtk2::HBox(0,10),
#				0, gtkset_sensitive(new Gtk2::Label(N("Please check if you want to include\n install boot on your CD.")),  $where_cd),
#				1, new Gtk2::VBox(0, 5),
#				0, gtkset_sensitive(my $check_cd_with_install_boot = new Gtk2::CheckButton(), $where_cd),
#			),
			0, new Gtk2::VBox(0, 5),
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, gtkset_sensitive(new Gtk2::Label(N("Enter your CD Writer device name\n ex: 0,1,0")),  $where_cd),
				1, new Gtk2::VBox(0, 5),
#				0, gtkset_size_request(gtkset_sensitive($cd_device_entry = new Gtk2::Entry(), $where_cd), 200, 20),
				0, gtkset_sensitive(gtkset_size_request($combo_where_cdrecord_device, 200, 20), $where_cd),
			),
		),
	);

#    foreach ([$check_cdrw_erase, \$media_erase], [$check_cd_with_install_boot, \$cd_with_install_boot ]) {
    foreach ([$check_cdrw_erase, \$media_erase], [$check_dvdr, \$dvdr], [$check_dvdram, \$dvdram], [$check_multisession, \$multi_session]) {
		my $ref = $_->[1];
		gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1 })
	}
    gtksignal_connect(gtkset_active($check_where_cd, $where_cd), toggled => sub { 
		$where_cd = $where_cd ? 0 : 1;
		#- toggle where_net, where_tape off
		if ($where_cd == 1) {
			$where_net = 0;
			$where_tape = 0;
		}
		destroy_widget();
		$current_widget->();
    });
    gtksignal_connect(gtkset_active($check_cdrw, $cdrw), toggled => sub { 
		$cdrw = $cdrw ? 0 : 1;
		$check_cdrw_erase->set_sensitive($cdrw);
		destroy_widget();
		$current_widget->();
    });
	$button_erase_now->signal_connect('clicked', sub { 
		if ($cd_device) {
			erase_cdrw();
		} else {
			$in->ask_warn('', N("No CD device defined!"));
		}
	}); 	
    $combo_where_cdrecord_device->entry->set_text($cd_device);
    $combo_where_cdrecord_device->entry->signal_connect('changed', sub { $cd_device = $combo_where_cdrecord_device->entry->get_text });
    
	$combo_where_cd_time->entry->set_text($cd_time);
    $combo_where_cd_time->entry->signal_connect('changed', sub { $cd_time = $combo_where_cd_time->entry->get_text });

	#- this one drives changes in the other entries
	#- still not getting quite the desired behavior, but combo box signals seem to be limited
	#- tried to trigger from the selection, but it either does nothing or crashes!
	
#-	$combo_where_cd_device->entry->set_text($std_device);
	$combo_where_cd_device->entry->signal_connect('activate', sub {
		$std_device = $combo_where_cd_device->entry->get_text;
		$combo_where_cdrecord_device->entry->set_text($cd_devices{$std_device}{rec_dev});
		$check_dvdr->set_active($cd_devices{$std_device}{dvdr});
		$check_dvdram->set_active($cd_devices{$std_device}{dvdram});
		#- do this one last or the widget destory mucks up the others
		$check_cdrw->set_active($cd_devices{$std_device}{cdrw});			
	});
	
    if ($previous_function) { 
		fonction_env(\$box_where_cd, \&advanced_where_cd, \&$previous_function, ""); 
	} else { 
		fonction_env(\$box_where_cd, \&advanced_where_cd, \&advanced_where, ""); 
	}
    $up_box->show_all;
}

sub advanced_where_tape {
    my ($previous_function) = @_;

	#- look for tape devices;
	get_tape_info();

	my $combo_where_tape_device = new Gtk2::OptionMenu();
    if (@tape_devices) {  
		$combo_where_tape_device->set_popdown_strings(@tape_devices) 
	} else {
		$combo_where_tape_device->set_popdown_strings(@no_devices);
	}
	
    my $box_where_tape;
    local $_;
	
    gtkpack($advanced_box,
		$box_where_tape = gtkpack_(new Gtk2::VBox(0, 6),
			0, new Gtk2::HSeparator,
		 	0, my $check_where_tape = new Gtk2::CheckButton(N("Use tape to backup")),
		 	0, new Gtk2::HSeparator,
		 	0, gtkpack_(new Gtk2::HBox(0,10),
				0, gtkset_sensitive(new Gtk2::Label(N("Device name to use for backup")), $where_tape),
				1, new Gtk2::VBox(0, 6),
				#0, gtkset_sensitive(gtkset_size_request($combo_where_tape_device, 200, 20), $where_tape),
				0, gtkset_sensitive($combo_where_tape_device, $where_tape),

			),
			0, new Gtk2::VBox(0, 5),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
	    		0, gtkset_sensitive(new Gtk2::Label(N("Don't rewind tape after backup")), $where_tape),
	    		1, new Gtk2::VBox(0, 5),
	    		0, gtkset_sensitive(my $check_tape_rewind = new Gtk2::CheckButton(), $where_tape),
			),
			0, new Gtk2::VBox(0, 5),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
	    		0, gtkset_sensitive(new Gtk2::Label(N("Erase tape before backup")), $where_tape),
	    		1, new Gtk2::VBox(0, 5),
	    		0, gtkset_sensitive(my $check_tape_erase = new Gtk2::CheckButton(), $where_tape),
			),
			0, new Gtk2::VBox(0, 5),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
	    		0, gtkset_sensitive(new Gtk2::Label(N("Eject tape after the backup")), $where_tape),
	    		1, new Gtk2::VBox(0, 5),
	    		0, gtkset_sensitive(my $check_tape_eject = new Gtk2::CheckButton(), $where_tape),
			),
			0, new Gtk2::VBox(0, 6),
# not appropriate - disable
#			0, gtkpack_(new Gtk2::HBox(0,10),
#				0, gtkset_sensitive(new Gtk2::Label(N("Please enter the maximum size\n allowed for Drakbackup (Mb)")), $where_tape),
#				1, new Gtk2::VBox(0, 6),
#				0, gtkset_size_request(gtkset_sensitive($spinner = new Gtk2::SpinButton($adj, 0, 0), $where_tape), 200, 20),
#			),
			0, gtkpack_(new Gtk2::HBox(0,10),),
		),
	);
    gtksignal_connect(gtkset_active($check_where_tape, $where_tape), toggled => sub { 
		$where_tape = $where_tape ? 0 : 1;
		#- assure other methods are off
		if ($where_tape == 1) {
			$where_net = 0;
			$where_cd = 0;
		}
		destroy_widget();
		$current_widget->();
    });
	gtksignal_connect(gtkset_active($check_tape_rewind, $tape_norewind), toggled => sub { 
		$tape_norewind = $tape_norewind ? 0 : 1;
		$_ = $tape_device;
		if ($tape_norewind) {
			$tape_device =~ s|/st|/nst|;
		} else {
			$tape_device =~ s|/nst|/st|;
		}
		$combo_where_tape_device->entry->set_text($tape_device);
		destroy_widget();
		$current_widget->();

    });
	gtksignal_connect(gtkset_active($check_tape_erase, $media_erase), toggled => sub { 
		$media_erase = $media_erase ? 0 : 1;
		destroy_widget();
		$current_widget->();
    });
	gtksignal_connect(gtkset_active($check_tape_eject, $media_eject), toggled => sub { 
		$media_eject = $media_eject ? 0 : 1;
		destroy_widget();
		$current_widget->();
    });
    $combo_where_tape_device->entry->set_text($tape_device);
	$combo_where_tape_device->entry->signal_connect('changed', sub {
		$tape_device = $combo_where_tape_device->entry->get_text;
	}); 
    if ($previous_function) { 
		fonction_env(\$box_where_tape, \&advanced_where_tape, \&$previous_function, ""); 
	} else { 
		fonction_env(\$box_where_tape, \&advanced_where_tape, \&advanced_where, ""); 
	}
    $up_box->show_all;
}

sub advanced_where_hd {
    my ($previous_function) = @_;
    my $box_where_hd;
    my $button;
	if ($max_space == 1000.0) {
		$max_space = int(0.8 * get_free_space($save_path)) if -d $save_path;
    }
	my $adj = new Gtk2::Adjustment($max_space, 0.0, $max_space, 10.0, 5.0, 0.0);
    my $spinner;
	
    gtkpack($advanced_box,
	    $box_where_hd = gtkpack_(new Gtk2::VBox(0, 6),
			0, new Gtk2::HSeparator,
#	 0, my $check_where_hd = new Gtk2::CheckButton( N("Use Hard Disk to backup")),
#	 0, new Gtk2::HSeparator,
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, gtkset_sensitive(new Gtk2::Label(N("Enter the directory to save to:")), $where_hd),
				1, new Gtk2::VBox(0, 6),
				0, gtkset_size_request(gtkset_sensitive($save_path_entry = new Gtk2::Entry(), $where_hd), 152, 20),
				0, gtkset_sensitive($button = gtksignal_connect(Gtk2::Button->new,  clicked => sub {
					filedialog_where_hd() 
				}), $where_hd),
			),
			0, new Gtk2::VBox(0, 6),
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, gtkset_sensitive(new Gtk2::Label(N("Maximum size\n allowed for Drakbackup (Mb)")),  $where_hd),
				1, new Gtk2::VBox(0, 6),
				0, gtkset_size_request(gtkset_sensitive($spinner = new Gtk2::SpinButton($adj, 0, 0), $where_hd), 200, 20),
			),
# just disable for now - doesn't do anything anyway (sb)
#			0, gtkpack_(new Gtk2::HBox(0,10),
#				1, new Gtk2::VBox(0, 6),
#	   			0, gtkset_sensitive(my $check_where_hd_quota = new Gtk2::CheckButton(N("Use quota for backup files.")), $where_hd),
#		    	0, new Gtk2::VBox(0, 6),
#			),
		),
	);
#    foreach ([$check_where_hd_quota, \$hd_quota]) {
#		my $ref = $_->[1];
#		gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1 })
#	}
    $button->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-dossier-32")));
    $save_path_entry->set_text($save_path);
	$spinner->signal_connect('changed', sub { $max_space = $spinner->get_text });
    $save_path_entry->signal_connect('changed', 
		sub { 
			$save_path = $save_path_entry->get_text;
			if (-d $save_path) { 
				$max_space = int(0.8 * get_free_space($save_path));
				# seems to be the easiest way to avoid the widgets fighting over values
				# and getting grabage in $max_value
				destroy_widget();
				advanced_where_hd();
			}
		});
    if ($previous_function) { 
		fonction_env(\$box_where_hd, \&advanced_where_hd, \&$previous_function, ""); 
	} else { 
		fonction_env(\$box_where_hd, \&advanced_where_hd, \&advanced_where, ""); 
	}
    $up_box->show_all;
}

sub advanced_where() {
    my $box_where;

    gtkpack($advanced_box,
	    $box_where = gtkpack_(new Gtk2::HBox(0, 15),
				  1, new Gtk2::VBox(0, 5),
				  1, gtkpack_(new Gtk2::VBox(0, 15),	
					  1, new Gtk2::VBox(0, 5),
					  1, gtksignal_connect(my $button_where_net = Gtk2::Button->new, clicked => sub { 
					      destroy_widget();
					      advanced_where_net_types(); 
					  }),
					  1, gtksignal_connect(my $button_where_cd = Gtk2::Button->new,  clicked => sub { 
					      destroy_widget(); 
					      if (require_rpm("mkisofs", "cdrecord")) { 
					      	advanced_where_cd();
					      } else { 
						  	destroy_widget();
						  	install_rpm(\&advanced_where);
						  }
					  }),
					  1, gtksignal_connect(my $button_where_hd = Gtk2::Button->new,  clicked => sub { 
					      destroy_widget(); 
					      advanced_where_hd();
					  }),
					  1, gtksignal_connect(my $button_where_tape = Gtk2::Button->new,  clicked => sub { 
					      destroy_widget(); 
						  advanced_where_tape() }),
					  1, new Gtk2::VBox(0, 5),
					     ),
				  1, new Gtk2::VBox(0, 5),	
				  ),
	    );
    $button_where_net->add(gtkpack(new Gtk2::HBox(0,10),
		gtkcreate_img("ic82-network-40"),
		new Gtk2::Label(N("Network")),
		new Gtk2::HBox(0, 5)
	));
    $button_where_cd->add(gtkpack(new Gtk2::HBox(0,10),
		gtkcreate_img("ic82-CD-40"),
		new Gtk2::Label(N("CDROM / DVDROM")),
		new Gtk2::HBox(0, 5)
	));
    $button_where_hd->add(gtkpack(new Gtk2::HBox(0,10),
		gtkcreate_img("ic82-discdurwhat-40"),
		new Gtk2::Label(N("HardDrive / NFS")),
		new Gtk2::HBox(0, 5)
	));
    $button_where_tape->add(gtkpack(new Gtk2::HBox(0,10),
 		gtkcreate_img("ic82-tape-40"),
 		new Gtk2::Label(N("Tape")),
 		new Gtk2::HBox(0, 5)
 	));
    fonction_env(\$box_where, \&advanced_where, \&advanced_box, ""); 
    $up_box->show_all;
}

#- 7/7/2002 - S.Benedict reworked when - drop all the checkboxes and use a list
#- chances that we want to do backups via multiple medias in cron are slim
sub advanced_when() {
    my $box_when;
#   $daemon_media = '';
    my $combo_when_space = new Gtk2::OptionMenu();
    my %trans = (N("hourly") => 'hourly',
		 N("daily") => 'daily',
		 N("weekly") => 'weekly',
		 N("monthly") => 'monthly');
    my %trans2 = ('hourly' => N("hourly"),
		  'daily' => N("daily"),
		  'weekly' => N("weekly"),
		  'monthly' => N("monthly"));
    $combo_when_space->set_popdown_strings(N("hourly"), N("daily"), N("weekly"), N("monthly"));    

	#- drop down list of possible medias - default to config value
    my $entry_media_type = new Gtk2::OptionMenu();
    $entry_media_type->set_popdown_strings(@media_types, @net_methods);
	$entry_media_type->entry->set_text($daemon_media);
	
    gtkpack($advanced_box,
		$box_when = gtkpack_(new Gtk2::VBox(0, 15),
			0, gtkpack_(new Gtk2::HBox(0,10),
				1, new Gtk2::HBox(0,10),
				1, gtkcreate_img("ic82-when-40"),
				0, my $check_when_daemon  = new Gtk2::CheckButton(N("Use daemon")), 
				1, new Gtk2::HBox(0,10),
			),
			0, new Gtk2::HSeparator,
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, gtkset_sensitive(new Gtk2::Label(N("Please choose the time \ninterval between each backup")),  $backup_daemon),
				1, new Gtk2::HBox(0,10),
				0, gtkset_sensitive($combo_when_space, $backup_daemon),
			),
			0, new Gtk2::HBox(0,10),
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, gtkset_sensitive(new Gtk2::Label(N("Please choose the\nmedia for backup.")), $backup_daemon),
				1, new Gtk2::HBox(0,10),
				0, gtkpack_(new Gtk2::VBox(0,10),
					0, gtkset_sensitive($entry_media_type, $backup_daemon),
				),
			),
			0, new Gtk2::HSeparator,
			1, gtkset_sensitive(new Gtk2::Label(N("Please be sure that the cron daemon is included in your services. 
\nNote that currently all 'net' medias also use the hard drive.")),  $backup_daemon),
		),
	);

    gtksignal_connect(gtkset_active($check_when_daemon, $backup_daemon), toggled => sub { 
		$backup_daemon = $backup_daemon ? 0 : 1;
		destroy_widget();
		advanced_when();
    });
    $combo_when_space->entry->set_text($trans2{$when_space});
    $combo_when_space->entry->signal_connect('changed', sub { $when_space = $trans{$combo_when_space->entry->get_text} });
	$entry_media_type->entry->signal_connect('changed', sub { 
		$daemon_media = $entry_media_type->entry->get_text;
	});
    fonction_env(\$box_when, \&advanced_when, \&advanced_box, "");
    $up_box->show_all;
}

sub advanced_options() {
    my $box_options;
    
	gtkpack($advanced_box,
		$box_options = gtkpack_(new Gtk2::VBox(0, 15),
# 				 0, gtkpack_(new Gtk2::HBox(0,10),
# 					     1, new Gtk2::VBox(0,10),
# 					     1, gtkcreate_img("ic82-moreoption-40"),
# 					     1, N("Please choose correct options to backup."),
# 					     1, new Gtk2::VBox(0,10),
# 					     ),
# 				 0, new Gtk2::HSeparator,
# 				 0, gtkpack_(new Gtk2::VBox(0,10),
# 					     0, gtkset_sensitive(my $check_tar_bz2  = new Gtk2::CheckButton( N("Use Tar and bzip2 (very slow) [Please be careful if you\n (un)select this option, as all your old backups will be deleted.]")), 0),
 			0, my $check_backupignore = new Gtk2::CheckButton(N("Use .backupignore files")),
#			0, new Gtk2::VBox(0,10),
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, my $check_mail = new Gtk2::CheckButton(N("Send mail report after each backup to:")),
				1, new Gtk2::HBox(0,10),
				0, my $mail_entry = new Gtk2::Entry(),
			),
#					     ),
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, my $check_del_hd_files = new Gtk2::CheckButton(N("Delete Hard Drive tar files after backup to other media.")),
			),
		),
	);
    check_list([$check_mail, \$send_mail], [$check_del_hd_files, \$del_hd_files], [$check_backupignore, \$backupignore]);
#    check_list([$check_mail, \$send_mail], [$check_tar_bz2, \$comp_mode], [$check_backupignore, \$backupignore]);
    $mail_entry->set_text($user_mail);
    $mail_entry->signal_connect('changed', sub { $user_mail = $mail_entry->get_text });
    fonction_env(\$box_options, \&advanced_options, \&advanced_box, "options");
    $up_box->show_all;
}

sub advanced_box() {
    my $box_adv;

    gtkpack($advanced_box,
		$box_adv = gtkpack_(new Gtk2::HBox(0, 15),
			1, new Gtk2::VBox(0, 5),	
			1, gtkpack_(new Gtk2::VBox(0, 15),	
				1, new Gtk2::VBox(0, 5),	
				1, gtksignal_connect(my $button_what = Gtk2::Button->new, clicked => sub { 
				    destroy_widget(); advanced_what() }),
				1, gtksignal_connect(my $button_where = Gtk2::Button->new, clicked => sub { 
				    destroy_widget();  advanced_where() }),
				1, gtksignal_connect(my $button_when = Gtk2::Button->new, clicked => sub { 
				    destroy_widget();  advanced_when() }),
				1, gtksignal_connect(my $button_options = Gtk2::Button->new, clicked => sub {
					destroy_widget(); advanced_options() }),
				1, new Gtk2::VBox(0, 5),	
			),
			1, new Gtk2::VBox(0, 5),	
		),
	);
    $button_what->add(gtkpack(new Gtk2::HBox(0,10),
		gtkcreate_img("ic82-discdurwhat-40"),
		new Gtk2::Label(N("What")),
		new Gtk2::HBox(0, 5)
	));
    $button_where->add(gtkpack(new Gtk2::HBox(0,10),
	    gtkcreate_img("ic82-where-40"),
	    new Gtk2::Label(N("Where")),
	    new Gtk2::HBox(0, 5)
	));
    $button_when->add(gtkpack(new Gtk2::HBox(0,10),
	    gtkcreate_img("ic82-when-40"),
	    new Gtk2::Label(N("When")),
	    new Gtk2::HBox(0, 5)
	));
    $button_options->add(gtkpack(new Gtk2::HBox(0,10),
	    gtkcreate_img("ic82-moreoption-40"),
	    new Gtk2::Label(N("More Options")),
	    new Gtk2::HBox(0, 5)
	));
    fonction_env(\$box_adv, \&advanced_box, \&interactive_mode_box, "");
    $up_box->show_all;
}

################################################  WIZARD  ################################################  

sub wizard_step3() {
    my $box2;    
    my $text = new Gtk2::TextView;
	save_conf_file();
    read_conf_file();
    system_state();
    gtktext_insert($text, [ [ $system_state ] ]);
    button_box_restore_main();

    gtkpack($advanced_box,
		$box2 =  gtkpack_(new Gtk2::HBox(0, 15),	
			1, gtkpack_(new Gtk2::VBox(0,10),
				0, N("Drakbackup Configuration"),
				1, create_scrolled_window($text),
			),
		),
	);
    fonction_env(\$box2, \&wizard_step3, \&wizard_step2, "");
    button_box_wizard_end();
    $up_box->show_all;
}

sub wizard_step2() {
    my $box2;    
    
    gtkpack($advanced_box,
		$box2 =  gtkpack_(new Gtk2::HBox(0, 15),	
			1, new Gtk2::VBox(0, 5),	
			1, gtkpack_(new Gtk2::VBox(0, 15),	
				1, new Gtk2::VBox(0, 5),
				0, N("Please choose where you want to backup"),
				0, gtkpack_(new Gtk2::HBox(0, 15),	      
					0, my $check_wizard_hd = new Gtk2::CheckButton(N("on Hard Drive")),
					1, new Gtk2::VBox(0, 5),
					0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Configure")), clicked => sub {
						destroy_widget();
						to_ok();
						advanced_where_hd(\&wizard_step2);
						to_normal();
					}), $where_hd),
				),
				0, gtkpack_(new Gtk2::HBox(0, 15),	      
					0, my $check_wizard_net = new Gtk2::CheckButton(N("across Network")),
					1, new Gtk2::VBox(0, 5),
					0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Configure")), clicked => sub {
						destroy_widget();
						to_ok();
						advanced_where_net_types(\&wizard_step2);
						to_normal();
					}), $where_net),
				),
 				0, gtkpack_(new Gtk2::HBox(0, 15),	      
 					0, my $check_wizard_cd = new Gtk2::CheckButton(N("on CDROM")),
 					1, new Gtk2::VBox(0, 5),	
 					0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Configure")), clicked => sub {
 						destroy_widget();
 						advanced_where_cd(\&wizard_step2);
 					}), $where_cd),
 				),
 				0, gtkpack_(new Gtk2::HBox(0, 15),	      
 					0, my $check_wizard_tape = new Gtk2::CheckButton(N("on Tape Device")),
 					1, new Gtk2::VBox(0, 5),
 					0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Configure")), clicked => sub {
 						destroy_widget();
 						advanced_where_tape(\&wizard_step2);
 					}), $where_tape),
 				),
				1, new Gtk2::VBox(0, 5),
			),
			1, new Gtk2::VBox(0, 5),
		),
	);
    foreach ([$check_wizard_hd, \$where_hd], 
	     [$check_wizard_cd, \$where_cd], 
	     [$check_wizard_tape, \$where_tape],
	     [$check_wizard_net, \$where_net]) {
			my $ref = $_->[1];
			gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { 
				$$ref = $$ref ? 0 : 1;
				$where_hd = 1;
				if (!$where_hd && !$where_cd && !$where_net) {  
					$next_widget = \&message_noselect_box
				} else { 
					$next_widget = \&wizard_step3 
				}
				destroy_widget();
				wizard_step2();
			})
	}
    if (!$where_hd && !$where_cd && !$where_net) { fonction_env(\$box2, \&wizard_step2, \&wizard, "", \&message_noselect_box) }
    else { fonction_env(\$box2, \&wizard_step2, \&wizard, "", \&wizard_step3) }
    button_box_wizard();
    $up_box->show_all;
}

sub wizard()   {
	my $box2;    
    
	gtkpack($advanced_box,
		$box2 =  gtkpack_(new Gtk2::HBox(0, 15),	
			1, new Gtk2::VBox(0, 5),	
			1, gtkpack_(new Gtk2::VBox(0, 15),	
				1, new Gtk2::VBox(0, 5),
				0, N("Please choose what you want to backup"),
				0, my $check_wizard_sys = new Gtk2::CheckButton(N("Backup system")),
				0, my $check_wizard_user = new Gtk2::CheckButton(N("Backup Users")),
				0, gtkpack_(new Gtk2::HBox(0, 15),
					1, new Gtk2::VBox(0, 5),	
					0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Select user manually")), clicked => sub {
						destroy_widget();
						advanced_what_user(\&wizard);
					}),
				),
				1, new Gtk2::VBox(0, 5),	
			),
			1, new Gtk2::VBox(0, 5),	
		),
	);
    foreach ([$check_wizard_sys, \$backup_sys], [$check_wizard_user, \$backup_user]) {
		my $ref = $_->[1];
		gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { 
			$$ref = $$ref ? 0 : 1;
			if ($backup_sys || $backup_user && @user_list) { 
				$next_widget = \&wizard_step2 
			} else { 
				$next_widget = \&message_noselect_what_box }
			})
	}
    if ($backup_sys || $backup_user && @user_list) { fonction_env(\$box2, \&wizard, \&interactive_mode_box, "", \&wizard_step2) } 
    else { fonction_env(\$box2, \&wizard, \&interactive_mode_box, "", \&message_noselect_what_box) } 
    button_box_wizard();
    $up_box->show_all;
}

################################################  RESTORE  ################################################  

sub find_backup_to_restore() {
    my @list_backup;
    my @list_backup_tmp2;
    my $to_put;
    @sys_backuped = ();
	local $_;
	
    @user_backuped = ();
    -d $path_to_find_restore and @list_backup_tmp2 = all($path_to_find_restore);
    	
	foreach (@list_backup_tmp2) {
		s/_base//gi;
		s/_incr//gi;
		push @list_backup , $_;
    }
    if (any { /^backup_other/ } @list_backup) { $other_backuped = 1 }
    if (any { /^backup_sys/ } @list_backup) { $sys_backuped = 1 }
    foreach (grep { /^backup_sys_/ } @list_backup) {
		chomp;
		s/^backup_sys_//gi;
		s/.tar.gz$//gi;
		s/.tar.bz2$//gi;
 		my ($date, $heure) = /^(.*)_([^_]*)$/; 
		my $year = substr($date, 0, 4);
		my $month = substr($date, 4,  2);
		my $day =  substr($date, 6, 2);
		my $hour = substr($heure, 0,  2);
		my $min =  substr($heure, 2, 2);
		$to_put = "$day/$month/$year $hour:$min                   $_";
 		push @sys_backuped , $to_put;
    }
    $restore_step_sys_date  = $to_put;
    foreach (grep { /^backup_user_/ } @list_backup) {
		chomp;
		s/^backup_user_//gi;
		s/.tar.gz$//gi;
		s/.tar.bz2$//gi;
		my ($nom, $date, $heure) = /^(.*)_([^_]*)_([^_]*)$/;
		my $year = substr($date, 0, 4);
		my $month = substr($date, 4,  2);
		my $day =  substr($date, 6, 2);
		my $hour = substr($heure, 0,  2);
		my $min =  substr($heure, 2, 2);
#	my $to_put = "  $nom,  (date: $date, hour: $heure)";
		$to_put = "$_       user: $nom,   date: $day/$month/$year,   hour: $hour:$min";
		push @user_backuped , $to_put;
		any { /^$nom$/ } @user_list_backuped or push @user_list_backuped, $nom;
    }
}

sub system_state() {
#    $system_state;

    if ($cfg_file_exist) { 
		$system_state = N("\nBackup Sources: \n");
        $backup_sys and $system_state .= N("\n- System Files:\n"); 
        $backup_sys and $system_state .= "\t\t$_\n" foreach @sys_files; 
        $backup_user and $system_state .= N("\n- User Files:\n");
        $backup_user and $system_state .= "\t\t$_\n" foreach @user_list;
        @list_other and $system_state .= N("\n- Other Files:\n"); 
        @list_other and $system_state .= "\t\t$_\n" foreach @list_other;
        $where_hd and $system_state .= N("\n- Save on Hard drive on path: %s\n", $save_path);
		$where_hd and $system_state .= N("\tLimit disk usage to %s Mb\n", $max_space);

		if ($del_hd_files && ($where_cd || $where_tape || $where_net) && $daemon_media ne 'hd')  {
			$system_state .= N("\n- Delete hard drive tar files after backup.\n");	
		}
		
		#- tape and CDRW share some features
		my $erase_media = 'NO';
		$erase_media = 'YES' if $media_erase && ($where_cd || $where_tape); 
		$where_cd and $system_state .= N("\n- Burn to CD");
		$where_cd and $cdrw and $system_state .= N("RW");
		$where_cd and $system_state .= N(" on device: %s", $cd_device);
		$where_cd and $multi_session and $system_state .= N(" (multi-session)");
		$where_tape and $system_state .= N("\n- Save to Tape on device: %s", $tape_device);
		(($where_cd || $where_tape) && $media_erase) and $system_state .= N("\t\tErase=%s", $erase_media);
		$where_cd || $where_tape and $system_state .= "\n";
		
		$where_net and $system_state .= N("\n- Save via %s on host: %s\n", $net_proto, $host_name);
		$where_net and $system_state .= N("\t\t user name: %s\n\t\t on path: %s \n", $login_user, $host_path);
		$system_state .= N("\n- Options:\n");
		$backup_sys or $system_state .= N("\tDo not include System Files\n");
		
		if ($comp_mode) { 
			$system_state .= N("\tBackups use tar and bzip2\n"); 
		} else { 
			$system_state .= N("\tBackups use tar and gzip\n");
		}   

		$daemon_media and $system_state .= N("\n- Daemon (%s) include:\n", $when_space);
		$daemon_media eq 'hd' and $system_state .= N("\t-Hard drive.\n");    
		$daemon_media eq 'cd' and $system_state .= N("\t-CDROM.\n");
		$daemon_media eq 'tape' and $system_state .= N("\t-Tape \n");    
		$daemon_media eq 'ftp' and $system_state .= N("\t-Network by FTP.\n");    
		$daemon_media eq 'ssh' and $system_state .= N("\t-Network by SSH.\n");    
		$daemon_media eq 'rsync' and $system_state .= N("\t-Network by rsync.\n");    
		$daemon_media eq 'webdav' and $system_state .= N("\t-Network by webdav.\n");    
    } else {
    	$system_state = N("No configuration, please click Wizard or Advanced.\n");
    }
}

sub restore_state() {
    my @tmp = split(' ', $restore_step_sys_date);
    $restore_state = N("List of data to restore:\n\n");
    if ($restore_sys) { $restore_state .= "- Restore System Files.\n";
			$restore_state .= "   - from date: $tmp[0] $tmp[1]\n";
	}
    if ($restore_user) { 
		$restore_state .= "- Restore User Files: \n";
		$restore_state .= "\t\t$_\n" foreach @user_list_to_restore2;
		push @user_list_to_restore, (split(',', $_))[0] foreach @user_list_to_restore2;
    }
    if ($restore_other) { 
		$restore_state .= "- Restore Other Files: \n";
		-f "$path_to_find_restore/list_other" and $restore_state .= "\t\t$_\n" foreach split("\n", cat_("$path_to_find_restore/list_other"));  
    }
    if ($restore_other_path) {
		$restore_state .= "- Path to Restore: $restore_path \n";
    }
}

sub select_most_recent_selected_of {
    my ($user_name) = @_;
    my @list_tmp2;
	local $_;
    my @tmp = sort @user_list_to_restore2;
    foreach (grep { /$user_name/ } sort @tmp) { push @list_tmp2 , $_ }
    return pop @list_tmp2;
}

sub select_user_data_to_restore() {
    my $var_eq = 1;
    my @list_backup;
    my @list_tmp;
    my @list_tmp2;
    @user_list_to_restore = ();
	local $_;

    -d $path_to_find_restore and my @list_backup_tmp2 = grep { /^backup/ } all($path_to_find_restore);
    @list_tmp2 = @list_backup_tmp2;
    foreach (@list_backup_tmp2) {
		s/_base//gi;
		s/_incr//gi;
		push @list_backup , $_;
    }
    foreach my $var_tmp (@user_list_backuped) {
		$var_eq = 1;
		my $more_recent = (split(' ', select_most_recent_selected_of($var_tmp)))[0]; 
		foreach (grep { /^backup_user_$var_tmp/ } sort @list_backup) {
	    	s/.tar.gz//gi;
	    	s/.tar.bz2//gi;
	    	if ($more_recent) {
				if (/$more_recent/) {
		    		push @list_tmp , $_;
		    		$var_eq = 0;    
				} else {
					#- only if user asked for it - previously this was restoring everything (SB)
					my $tmp_name = $_;
					s/backup_user_//gi;
					foreach my $buff (@user_list_to_restore2) {
						if (index($buff, $_) >= 0) { 
							$var_eq and push @list_tmp , $tmp_name;
						}
					}
				}
	    	}
		}
    }
	foreach my $var_to_restore (@list_tmp) {
		$var_to_restore =~ s/backup_//gi;
		foreach my $var_exist (sort @list_tmp2) {
	    	if ($var_exist =~ /$var_to_restore/) {
				push @user_list_to_restore, $var_exist;
	    	}
		}
    }
    $DEBUG and print "real user list to restore:  $_ \n" foreach @user_list_to_restore;
}

sub select_sys_data_to_restore() {
    my $var_eq = 1;
    my @list_tmp;
	local $_;
	
    -d $path_to_find_restore and @list_tmp = grep { /^backup/ } all($path_to_find_restore);
    my @more_recent = split(' ', $restore_step_sys_date); 
    my $more_recent = pop @more_recent;
    foreach my $var_exist (grep { /_sys_/ } sort @list_tmp) {
		if ($var_exist =~ /$more_recent/) {
	    	push @sys_list_to_restore, $var_exist;
	    	$var_eq = 0; 
	    } else {  
	    	$var_eq and push @sys_list_to_restore, $var_exist; 
	    }
    }
    $DEBUG and print "sys list to restore: $_\n " foreach @sys_list_to_restore;
}

sub show_backup_details {
	my ($function, $mode, $name) = @_;
	my $archive_file_detail;
	my $value;
# dies in gtk2
#	my $fixed_font = Gtk2::Gdk::Font->load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-*-*");
	my $command2;
	my $tarfile;
	
	# FIXME - only tar.gz at the moment	
	my $extension = ".tar.gz";
		    
	if ($mode eq "user") {
		#- we've only got a partial filename in this case
		$tarfile = "$path_to_find_restore/backup_*" . $name . $extension;
	}
	if ($mode eq "sys") {
		#- funky string here we need to use to reconstruct the filename
		my @flist = split(/[ \t,]+/, $name);
		$tarfile = "$path_to_find_restore/backup_*" .  $flist[2] . $extension;
	}
	my $command1 = "stat " . $tarfile;
	$command2 = "tar -tzvf " . $tarfile;
	
     local *TMP;
	open TMP, "$command1 2>&1 |";
	while ($value = <TMP>) {
		$archive_file_detail .= $value;			
	}
	close TMP;
	$archive_file_detail .= "\n\n";
	open TMP, "$command2 2>&1 |";
	while ($value = <TMP>) {
		#- drop the permissions display for the sake of readability	
		$archive_file_detail .= substr($value, 11);
	}
	close TMP;	

    my $text = new Gtk2::TextView;
    my $advanced_box_archive;
    gtktext_insert(gtkset_editable($text, 0), $archive_file_detail);
    gtkpack($advanced_box,
	    $advanced_box_archive = gtkpack_(new Gtk2::VBox(0,10),
			1, gtkpack_(new Gtk2::HBox(0,0),
				1, create_scrolled_window($text), 
			),
			0, gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'),
				gtksignal_connect(Gtk2::Button->new_from_stock(N("Done")), clicked => sub { 
					destroy_widget(); 
					$function->() }),
			),
		)
	);
    $central_widget = \$advanced_box_archive;
    $up_box->show_all;
}

sub valid_backup_test {
    my (@files_list) = @_;
    @files_corrupted = ();
    my $is_corrupted = 0;
    foreach (@files_list) {
		#- let's quiet this down (SB)
		if (system("gzip -l $path_to_find_restore/$_ > /dev/null 2>&1") > 1) {
	    	push @files_corrupted, $_;
	    	$is_corrupted = -1;
		}
    }
    return $is_corrupted;
}

sub restore_aff_backup_problems() {
    my $do_restore;
    my $text = new Gtk2::TextView;
    my $restore_pbs_state = N("List of data corrupted:\n\n");
    $restore_pbs_state .= "\t\t$_\n" foreach @files_corrupted;
    $restore_pbs_state .= N("Please uncheck or remove it on next time.");
    gtktext_insert($text, [ [ $restore_pbs_state ] ]);
    button_box_restore_main();    

    gtkpack($advanced_box,
	    $do_restore = gtkpack_(new Gtk2::VBox(0,10),
			0, new Gtk2::VBox(0,10),
			1, gtkpack_(new Gtk2::HBox(0, 15),	
				1, new Gtk2::VBox(0, 5),	
				0, gtkcreate_img('warning'),
				0, N("Backup files are corrupted"),
				1, new Gtk2::VBox(0, 5),	
			),
			0, new Gtk2::VBox(0,10),
			1, create_scrolled_window($text),
		),
	);
    button_box_restore_pbs_end();
    fonction_env(\$do_restore, \&restore_aff_backup_problems, "", "restore_pbs");
    $up_box->show_all;
}

sub restore_aff_result() {
    my $do_restore;
    my $text = new Gtk2::TextView;
    gtktext_insert($text, [ [ $restore_state ] ]);
    button_box_restore_main();
    
    gtkpack($advanced_box,
		$do_restore = gtkpack_(new Gtk2::VBox(0,10),
			1, new Gtk2::VBox(0,10),
			0, N("          All of your selected data have been          "),
			0, N("          Successfuly Restored on %s       ", $restore_path),
			1, new Gtk2::VBox(0,10),
		),
	);
    button_box_build_backup_end();
    $central_widget = \$do_restore;
    $up_box->show_all;

}

sub return_path {
    my ($username) = @_;
    my $usr;
    my $home_dir;
    my $passwdfile = "/etc/passwd";
	local *PASSWD;
    open(PASSWD, $passwdfile) or exit 1; 
    while (defined(my $line = <PASSWD>)) {
		chomp($line);
		($usr, $home_dir) = (split(/:/, $line))[0,5];
		last if $usr eq $username; 
    }
    close(PASSWD);
    return $home_dir;
}

sub restore_backend() {
    my $untar_cmd;
    my $exist_problem = 0;
    my $user_dir;
	my $tnom;
	my $username;
	my $theure2;
	local $_;
	-d $restore_path or mkdir_p $restore_path;
	
    if (any { /tar.gz$/ } all($path_to_find_restore)) { 
    	$untar_cmd = 0; 
    } else { 
    	$untar_cmd = 1; 
    }
    
	if ($restore_user)  {
		select_user_data_to_restore();
	    if (valid_backup_test(@user_list_to_restore) == -1) {
			$exist_problem = 1;
			restore_aff_backup_problems();
	    } else { 
	    	foreach (@user_list_to_restore) {
		    	if ($backup_user_versions) {
					($tnom, $username, $theure2) = /^(\w+_\w+_user_)(.*)_(\d+_\d+.*)$/;
				} else {
					($tnom, $username, $theure2) = /^(\w+_user_)(.*)_(\d+_\d+.*)$/;
				}

				$user_dir = return_path($username);
				-d $user_dir and rm_rf($user_dir) if $remove_user_before_restore;

		    	$DEBUG and print "user name to restore: $username, user directory: $user_dir\n";		    
		    	$untar_cmd or system(" tar xfz  $path_to_find_restore/$_ -C $restore_path");
		    	$untar_cmd and system("/usr/bin/bzip2 -cd $path_to_find_restore/$_ | tar xf -C $restore_path ");
			}
			#- flush this out for another cycle (SB)
			@user_list_to_restore2 = ();
	    }
		
    }
    
	if ($restore_sys)   { 
		if ($backup_sys_versions) {
			select_sys_data_to_restore();
	    	if (valid_backup_test(@sys_list_to_restore) == -1) {
				$exist_problem = 1;
				restore_aff_backup_problems();
	    	} else {
				$untar_cmd or system("tar xfz $path_to_find_restore/$_  -C $restore_path ") foreach @sys_list_to_restore;
				$untar_cmd and system("/usr/bin/bzip2 -cd $path_to_find_restore/$_  | tar xf -C $restore_path ") foreach @sys_list_to_restore;
			}
		} else {
			$untar_cmd or system("tar xfz $path_to_find_restore/backup_sys.tar.gz  -C $restore_path ");
			$untar_cmd and system("/usr/bin/bzip2 -cd $path_to_find_restore/backup_sys.tar.bz2  | tar xf -C $restore_path ");
		}	    
    }
    if ($restore_other) { 
		$untar_cmd or system("tar xfz $path_to_find_restore/backup_other.tar.gz  -C $restore_path ");
		$untar_cmd and system("/usr/bin/bzip2 -cd $path_to_find_restore/backup_other.tar.bz2  | tar xf -C $restore_path ");
    }
    $exist_problem or restore_aff_result();
}

sub restore_do() {
    if ($backup_bef_restore) {
		if ($restore_sys) { 
			$backup_sys = 1;
		} else { 
			$backup_sys = 0;
		}
		if ($restore_user) { 
	    	$backup_user = 1;
	    	@user_list = @user_list_to_restore;
		} else { 
			$backup_user = 0;
		}
		build_backup_status();
		read_conf_file();
		build_backup_files();
		$table->destroy;
    }
    restore_do2();
}

sub restore_do2() {
    my $do_restore;
    my $text = new Gtk2::TextView;
    restore_state();
    gtktext_insert($text, [ [ $restore_state ] ]);
    button_box_restore_main();
    
	gtkpack($advanced_box,
		$do_restore = gtkpack_(new Gtk2::VBox(0,10),
			0, N("         Restore Configuration       "),
			1, create_scrolled_window($text),
		),
	);
    button_box_restore_end();
    fonction_env(\$do_restore, \&restore_do2, \&restore_box, "restore");
    $up_box->show_all;
}

sub restore_step_other() {
    my $retore_step_other;
    my $text = new Gtk2::TextView;
    my $other_rest = cat_("$path_to_find_restore/list_other");
    gtktext_insert($text, [ [ $other_rest ] ]); 
    gtkpack($advanced_box,
		$retore_step_other = gtkpack_(new Gtk2::VBox(0,10),
			1, new Gtk2::VBox(0,10),
			1, create_scrolled_window($text),
			0, my $check_restore_other_sure = new Gtk2::CheckButton(N("OK to restore the other files.")),
			1, new Gtk2::VBox(0,10),
		),
	);
    check_list([$check_restore_other_sure, \$restore_other]);
    fonction_env(\$retore_step_other, \&restore_step_other, \&restore_step2, "restore", \&restore_do);
    $up_box->show_all;
}

my %check_user_to_restore;
sub restore_step_user() {
    my $retore_step_user;
    my @tmp_list = sort @user_backuped;
    @user_backuped = @tmp_list;
    gtkpack($advanced_box,
		$retore_step_user = gtkpack_(new Gtk2::VBox(0,10),
			0, new Gtk2::VBox(0,10),
			0, N("User list to restore (only the most recent date per user is important)"),
			1, create_scrolled_window(gtkpack__(new Gtk2::VBox(0,0),
				map { my $name;
					my $var2;
					my $name_complet = $_;
					$name = (split(' ', $name_complet))[0];
					my @user_list_tmp;
					my $restore_row = new Gtk2::HBox(0,5);
					my $b = new Gtk2::CheckButton($name_complet);
					my $details = Gtk2::Button->new_from_stock(" Details ");
					
					$restore_row->pack_start($b, 1, 1, 0);
					$restore_row->pack_end(new Gtk2::VBox(1,5), 0, 0, 0);
					$restore_row->pack_end($details, 0, 0, 0);
					
# this doesn't work - I don't understand why - but you end up with
# everything selected when you hit the screen a second time, after selecting one				
#					if (grep $name_complet, @user_list_to_restore2)  {
#						gtkset_active($b, 1);
#						$check_user_to_restore{$name_complet}[1] = 1;
#					} else {
#						gtkset_active($b, 0);
#						$check_user_to_restore{$name_complet}[1] = 0;
#					}

# this doesn't work right either - returning to the screen only 1 is selected
# yet several are scheduled to be restored
					foreach (@user_list_to_restore2) {
						if ($name_complet eq $_) {
							gtkset_active($b, 1);
							$check_user_to_restore{$name_complet}[1] = 1;
						} else {
							gtkset_active($b, 0);
							$check_user_to_restore{$name_complet}[1] = 0;
						}
					}
					$b->signal_connect(toggled => sub { 
						if (!$check_user_to_restore{$name_complet}[1]) {
							$check_user_to_restore{$name_complet}[1] = 1;
							if (!any { /$name/ } @user_list_to_restore2) {
								push @user_list_to_restore2, $name_complet 
							}
						} else {
							$check_user_to_restore{$name_complet}[1] = 0;
							foreach (@user_list_to_restore2) {
								$var2 =  (split(' ', $_))[0];
								if ($name ne $var2) {
									push @user_list_tmp, $_;
								}
							}
							@user_list_to_restore2 = @user_list_tmp;
						}
					});
					$details->signal_connect('clicked', sub { 
						#- we're only passing a portion of the filename to
						#- the subroutine so we need to let it know this
						destroy_widget();
						show_backup_details(\&restore_step_user, "user", $name);
					}); 	
					$restore_row } (@user_backuped) 
				),
			),
		),
	);
    if ($restore_other) { fonction_env(\$retore_step_user, \&restore_step_user, "", "restore", \&restore_step_other) }
	elsif ($restore_sys) { fonction_env(\$retore_step_user, \&restore_step_user, \&restore_step_sys, "restore", \&restore_step_other) }
    else { fonction_env(\$retore_step_user, \&restore_step_user, \&restore_step2, "restore", \&restore_do) }
    $up_box->show_all;
}

sub restore_step_sys() {
    my $restore_step_sys;
	my $check_backup_before;
    my $combo_restore_step_sys = new Gtk2::OptionMenu();
    $combo_restore_step_sys->set_popdown_strings(@sys_backuped);
    gtkpack($advanced_box,
		$restore_step_sys = gtkpack_(new Gtk2::VBox(0,10),
			1, new Gtk2::VBox(0,10),
			0, $check_backup_before = new Gtk2::CheckButton(N("Backup the system files before:")),
			0, gtkpack_(new Gtk2::HBox(0,10),
				1, N("please choose the date to restore"),
				0, $combo_restore_step_sys,
				0, my $details = Gtk2::Button->new_from_stock(" Details "),
				0, new Gtk2::HBox(0,10),
			),
			1, new Gtk2::VBox(0,10),
			
		),
	);
    $combo_restore_step_sys->entry->signal_connect('changed', sub {
		$restore_step_sys_date = $combo_restore_step_sys->entry->get_text;
	});
	$details->signal_connect('clicked', sub { 
		#- we're only passing a portion of the filename to
		#- the subroutine so we need to let it know this
		my $backup_date = $combo_restore_step_sys->entry->get_text;
		destroy_widget();
		show_backup_details(\&restore_step_sys, "sys", $backup_date);
	}); 	
    $combo_restore_step_sys->entry->set_text($restore_step_sys_date);
    fonction_env(\$restore_step_sys, \&restore_step_sys,  \&restore_step2, "restore");
    if ($restore_user) { fonction_env(\$restore_step_sys, \&restore_step_sys,  \&restore_step2, "restore", \&restore_step_user) }
    elsif ($restore_other) { fonction_env(\$restore_step_sys, \&restore_step_sys,  \&restore_step2, "restore", \&restore_step_other) }
    else { fonction_env(\$restore_step_sys, \&restore_step_sys,  \&restore_step2, "restore", \&restore_do) }
    $up_box->show_all;
}

sub restore_other_media_hd {
    my ($previous_function) = @_;
    my $box_where_hd;
    my $button;
    my $adj = new Gtk2::Adjustment(550.0, 10.0, 10000.0, 10.0, 5.0, 0.0);
    my $spinner;
	 
    gtkpack($advanced_box,
	    $box_where_hd = gtkpack_(new Gtk2::VBox(0, 6),
			0, new Gtk2::HSeparator,
			0, my $check_where_hd = new Gtk2::CheckButton(N("Use Hard Disk to backup")),
			0, new Gtk2::HSeparator,
			0, gtkpack_(new Gtk2::HBox(0,10),
		    	0, gtkset_sensitive(new Gtk2::Label(N("Enter the directory to save:")), $where_hd),
		    	1, new Gtk2::VBox(0, 6),
		    	0, gtkset_size_request(gtkset_sensitive($save_path_entry = new Gtk2::Entry(), $where_hd), 152, 20),
		    	0, gtkset_sensitive($button = gtksignal_connect(Gtk2::Button->new,  clicked => sub {
				filedialog_where_hd() }), $where_hd),
			),
	 		0, new Gtk2::VBox(0, 6),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
	    		0, gtkset_sensitive(new Gtk2::Label(N("Enter the maximum size\n allowed for Drakbackup (Mb)")),  $where_hd),
	    		1, new Gtk2::VBox(0, 6),
	    		0, gtkset_size_request(gtkset_sensitive($spinner = new Gtk2::SpinButton($adj, 0, 0), $where_hd), 200, 20),
			),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
	    		1, new Gtk2::VBox(0, 6),
	    		0, gtkset_sensitive(my $check_where_hd_quota = new Gtk2::CheckButton(N("Use quota for backup files.")), $where_hd),
	    		0, new Gtk2::VBox(0, 6),
			),
	 	),
	);
    check_list([$check_where_hd_quota, \$hd_quota]);
    gtksignal_connect(gtkset_active($check_where_hd, $where_hd), toggled => sub { 
		$where_hd = $where_hd ? 0 : 1;
		destroy_widget();
		$current_widget->();
    });
    $button->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-dossier-32")));
    $save_path_entry->set_text($save_path);
    $save_path_entry->signal_connect('changed', sub { $save_path = $save_path_entry->get_text });
    if ($previous_function) { fonction_env(\$box_where_hd, \&advanced_where_hd, \&$previous_function, "") }
    else { fonction_env(\$box_where_hd, \&advanced_where_hd, \&advanced_where, "") }
    $up_box->show_all;
}

sub restore_other_media() {
    my $box_find_restore;
    my $button;
    
    gtkpack($advanced_box,
		$box_find_restore = gtkpack_(new Gtk2::VBox(0, 6),
			0, new Gtk2::HSeparator,
			0, my $check_other_media_hd = new Gtk2::CheckButton(N("Restore from Hard Disk.")),
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, gtkset_sensitive(new Gtk2::Label(N("Enter the directory where backups are stored")), $other_media_hd),
				1, new Gtk2::VBox(0, 6),
				0, gtkset_size_request(gtkset_sensitive($restore_find_path_entry = new Gtk2::Entry(), $other_media_hd), 152, 20),
				0, gtkset_sensitive($button = gtksignal_connect(Gtk2::Button->new,  clicked => sub {
				     filedialog_restore_find_path(); 
				}), $other_media_hd),
			),
			1, new Gtk2::VBox(0, 6),
#					 0, new Gtk2::HSeparator,
# 					 0, my $check_other_media_net = new Gtk2::CheckButton( N("Restore from Network")),
# 					 0, new Gtk2::VBox(0, 6),
# 					 1, gtkpack(new Gtk2::HBox(0,10),
# 						    new Gtk2::VBox(0, 6),
# 						    gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock("Network"),  clicked => sub {
# 							destroy_widget();
# 							restore_find_net(\&restore_other_media);}), !$other_media_hd),
# 						    new Gtk2::VBox(0, 6),
# 						    ),
# 					 1, new Gtk2::VBox(0, 6),
# 					 0, new Gtk2::HSeparator,
			0, new Gtk2::VBox(0, 6),
		),
	);
	gtksignal_connect(gtkset_active($check_other_media_hd, $other_media_hd), toggled => sub { 
		$other_media_hd = $other_media_hd ? 0 : 1;
		destroy_widget();
		$current_widget->();
    });
#     gtksignal_connect(gtkset_active($check_other_media_net, !$other_media_hd), toggled => sub { 
# 	$other_media_hd = $other_media_hd ? 0 : 1;
# 	destroy_widget();
# 	$current_widget->();
#    });
    $button->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-dossier-32")));
    $restore_find_path_entry->set_text($path_to_find_restore);
    $restore_find_path_entry->signal_connect('changed', sub { $path_to_find_restore = $restore_find_path_entry->get_text });
#- not sure if this was the original intent - address the crash at "Next"
    fonction_env(\$box_find_restore, \&restore_other_media, \&restore_step2, "other_media", \&restore_do);
    $up_box->show_all;
}

sub restore_step2() {
    my $retore_step2;
    my $other_exist;
    my $sys_exist;
    my $user_exist;
	local $_;
	
	my $restore_info_path = $save_path;
	$restore_info_path = $path_to_find_restore if $where_hd || $where_cd;
	my $info_prefix = "backup";
	$info_prefix = "list" if $where_net || $where_tape;
	
    if (-f "$restore_info_path/$info_prefix" . "_other*") { $other_exist = 1 } 
    else { $other_exist = 0; $restore_other = 0 }
    if (any  { /_sys_/ } grep { /^$info_prefix/ } all("$restore_info_path/")) { $sys_exist = 1 } 
    else { $sys_exist = 0; $restore_sys = 0 }
    if (any { /_user_/ } grep { /^$info_prefix/ } all("$restore_info_path/")) { $user_exist = 1 } 
    else { $user_exist = 0; $restore_user = 0 }

# disabling this (sb) - very nicely wipes out your backup media if the user isn't very careful
# cycling through the GUI turns it back on for you!!!
#    $backup_sys_versions || $backup_user_versions and $backup_bef_restore = 1;

    gtkpack($advanced_box,
		$retore_step2 = gtkpack_(new Gtk2::VBox(0,10),
			1, new Gtk2::VBox(0,10),
			1, new Gtk2::VBox(0,10),
			0, gtkpack_(new Gtk2::HBox(0,10),
				0, my $check_restore_other_src = new Gtk2::CheckButton(N("Select another media to restore from")),
				1, new Gtk2::HBox(0,10),
				0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Other Media")), clicked => sub {
					destroy_widget();
					restore_other_media();
				}), $restore_other_src),
			),
	 		0, gtkset_sensitive(my $check_restore_sys = new Gtk2::CheckButton(N("Restore system")), $sys_exist),
	 		0, gtkset_sensitive(my $check_restore_user = new Gtk2::CheckButton(N("Restore Users")), $user_exist),
	 		0, gtkset_sensitive(my $check_restore_other = new Gtk2::CheckButton(N("Restore Other")), $other_exist),
	 		0, gtkpack_(new Gtk2::HBox(0,10),
		     	0, my $check_restore_other_path = new Gtk2::CheckButton(N("select path to restore (instead of /)")),
		     	1, new Gtk2::HBox(0,10),
		    	0, gtkset_sensitive(my $restore_path_entry = new Gtk2::Entry(), $restore_other_path),
			),
	 		0, gtkset_sensitive(my $check_backup_bef_restore = new Gtk2::CheckButton(N("Do new backup before restore (only for incremental backups.)")), 
				$backup_sys_versions || $backup_user_versions),
	 		0, gtkset_sensitive(my $check_remove_user_dir = new Gtk2::CheckButton(N("Remove user directories before restore.")), $user_exist),
	 		1, new Gtk2::VBox(0,10),
	 	),
	);
	
	foreach  ([$check_restore_sys, \$restore_sys], 
	      [$check_backup_bef_restore, \$backup_bef_restore],
	      [$check_restore_user, \$restore_user],
	      [$check_remove_user_dir, \$remove_user_before_restore],
	      [$check_restore_other, \$restore_other]) {
			my $ref = $_->[1];
			gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { 
	    		$$ref = $$ref ? 0 : 1;
	    		if (!$restore_sys && !$restore_user && !$restore_other) { $next_widget = \&message_norestore_box }
	    		elsif ($restore_sys && $backup_sys_versions) { $next_widget = \&restore_step_sys }
	    		elsif ($restore_user) { $next_widget = \&restore_step_user }
	    		elsif ($restore_other) { $next_widget = \&restore_step_other }
	    		else { $next_widget = \&restore_do }
			})
	}
    gtksignal_connect(gtkset_active($check_restore_other_path, $restore_other_path), toggled => sub {
		$restore_other_path = $restore_other_path ? 0 : 1;
		destroy_widget();
		$current_widget->();
    });
    gtksignal_connect(gtkset_active($check_restore_other_src, $restore_other_src), toggled => sub {
		$restore_other_src = $restore_other_src ? 0 : 1;
		destroy_widget();
		$current_widget->();
    });
	$central_widget = \$retore_step2;
    fonction_env(\$retore_step2, \&restore_step2, \&restore_box, "restore");
    if (!$restore_sys && !$restore_user && !$restore_other) { $next_widget = \&message_norestore_box }
    elsif ($restore_sys && $backup_sys_versions) { $next_widget = \&restore_step_sys }
    elsif ($restore_user) { $next_widget = \&restore_step_user }
    elsif ($restore_other) { $next_widget = \&restore_step_other }
    else { $next_widget = \&restore_do }
    $restore_path_entry->set_text($restore_path); 
    $restore_path_entry->signal_connect('changed', sub { $restore_path = $restore_path_entry->get_text });
    $up_box->show_all;
}

sub find_files_to_restore() {
	local $_;
	my $file_restore;
	my $start_restore;
	
	#- file info in tree view
	my $model = Gtk2::TreeStore->new("Glib::String");
    my $file_list = Gtk2::TreeView->new_with_model($model);
	my $file_wildcard_entry = new Gtk2::Entry();
	
    gtkpack($advanced_box,
		$file_restore = gtkpack_(new Gtk2::VBox(0,10),
		    0, new Gtk2::Label(N("Filename to search for (wildcards allowed):")),
			0, gtkpack_(new Gtk2::HBox(0,10),
				1, $file_wildcard_entry,
				0, gtksignal_connect(new Gtk2::Button(N("Search Backups")), clicked => sub {
					# FIXME - search the file listings and offer a list of possible matches
					my $wildcard = $file_wildcard_entry->get_text;
					show_warning("w", N("Search For...\n%s", $wildcard));
					gtkset_sensitive($start_restore, 1);
				}),
			),
			1, create_scrolled_window($file_list),
			0, gtkset_sensitive(gtksignal_connect($start_restore = new Gtk2::Button(N("Restore Selected")), clicked => sub {
				# FIXME - search the file listings and offer a list of possible matches
				show_warning("w", N("Start Search..."));
			}), 0),
		),
	);

	$central_widget = \$file_restore;
}

sub catalog_restore() {
	my $catalog_box;
	my $cat_entry;
	my @restore_files;
	my $restore_path_entry;
		
	#- catalog info in tree view
	my $model = Gtk2::TreeStore->new("Glib::String");
	my $tree_catalog = Gtk2::TreeView->new_with_model($model);
	$tree_catalog->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0));
    
	$tree_catalog->set_headers_visible(0);
	$tree_catalog->get_selection->set_mode('single');
	
	# file details in list widget	
	my $lmodel = Gtk2::ListStore->new("Glib::String");
    my $tree_files = Gtk2::TreeView->new_with_model($lmodel);
    $tree_files->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0));
    
	$tree_files->set_headers_visible(0);
    $tree_files->get_selection->set_mode('multiple');

	#- read the catalog
	my @catalog = cat_("$cfg_dir/drakbackup_catalog");
    my %full_cat_entry;
	
	foreach (@catalog) {
		chop;
		my @line_data = split(':', $_);
		my $t = $line_data[0];
		$full_cat_entry{$t} = $_;
		
		my $t_catalog = $model->append_set(undef, [ 0 => $t ]);
		
		$tree_catalog->get_selection->signal_connect(changed => sub {			
			my ($model, $iter) = $_[0]->get_selected;
        	$model && $iter or return;
			$cat_entry = $model->get($iter, 0);
			if ($cat_entry != $t) {
				$cat_entry = '';
				return;
			}
			cursor_wait();
			@restore_files = ();
			$lmodel->clear;
			foreach my $filename (glob("$save_path/list*$cat_entry.txt")) {
				my @contents = cat_($filename);
				foreach (@contents) {
					chop;
					my $s = $_;
					$lmodel->append_set(undef, $s);
					$tree_files->get_selection->signal_connect(changed => sub {
						my (@what) = $_[0]->get_selected_rows;
						@restore_files = ();
						foreach (@what) {
							my $iter = $lmodel->get_iter($_);
    						$s = $lmodel->get($iter, 0);
							push @restore_files, $s;
						}
					});
				}
			}
			cursor_norm();
			$cat_entry = $full_cat_entry{$t};
		});

		my $indexer = 0;
		foreach (@line_data) {
			if ($indexer != 0) {
				my $m;
				$m = "Media: " if $indexer == 1;
				$m = "Label or Host: " if $indexer == 2;
				$m = "Device or Path: " if $indexer == 3;
				$m = "Type: Incremental" if $_ eq "I";
				$m = "Type: Differential" if $_ eq "D";
				$m = "Type: Full" if $_ eq "F";
				$m .= $_ if $_ ne "I" && $_ ne "F" && $_ ne "D";
				$model->append_set($t_catalog, [ 0 => $m ]);
			}
			$indexer++;
		}
	}	
		
	gtkpack($advanced_box,
		$catalog_box = gtkpack_(new Gtk2::HBox(0,10),
			0, new Gtk2::VBox(0,10),
			1, gtkpack_(new Gtk2::VBox(0,5),
				1, gtkpack_(new Gtk2::VBox(0, 10),
					1, create_scrolled_window($tree_catalog),
					1, create_scrolled_window($tree_files),
				),
				0, gtkpack_(new Gtk2::HBox(1, 10),
					1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Restore Selected\nCatalog Entry")), clicked => sub { 
						if ($cat_entry) {
							my $media_check = restore_catalog_entry($cat_entry, ());
							if ($media_check) {
								destroy_widget();
								interactive_mode_box();
							} 
						} 
					}),
					1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Restore Selected\nFiles")), clicked => sub { 							
						my $files = @restore_files;
						#- grab the array before the widget clears it 
						my @passed_files = @restore_files;
						if ($cat_entry && $files) {
							my $media_check = restore_catalog_entry($cat_entry, @passed_files);
							if ($media_check) {
								destroy_widget();
								interactive_mode_box();
							} 
						}
					}),
					1, gtkpack_(new Gtk2::VBox(0, 5),
						0, new Gtk2::Label("Restore To Path"),
		    			0, $restore_path_entry = new Gtk2::Entry(),
					),
					1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Change\nRestore Path")), clicked => sub { 							
						filedialog_generic("Path To Restore To", \$restore_path_entry, \$restore_path);
					}),						
				),
				0, new Gtk2::VBox(0,10),
			),
			0, new Gtk2::VBox(0,10),
		),
	);		
	
	$restore_path_entry->set_text($restore_path);
	gtksignal_connect($restore_path_entry, changed => sub { $restore_path = $restore_path_entry->get_text });
	
	button_box_restore();		
	fonction_env(\$catalog_box, \&catalog_restore, \&restore_find_media_box, "restore", \&catalog_restore);
	$central_widget = \$catalog_box;	
    $up_box->show_all;
}

sub restore_catalog_entry {
	#FIXME
	# we're working from a catalog entry, which means we know the
	# the tar file wildcards and some info on where the backup was stored
	# if it's a local device (HD, tape, CD) - prompt for the media
	# for tape, find how many other catalog entries had the same 
	# label and calculate the record offset
	# if it's remote storage, display what we know of the connection
	# parameters and get the user's verification, then connect
	
	restore_status();
	
	my ($cat_entry, @restore_files) = @_;
	my $username;
	my $userpass = $passwd_user;
	my $restore_result = 1;
		
	my @line_data = split(':', $cat_entry);
	my $backup_time = $line_data[0];
	
	#- use our own variables here so we don't trash a saved config accidentally
	my $media = $line_data[1];
	
	#- can be a volume name or a host name
	my $vol_host = $line_data[2];
	
	#- see if we have a username embedded in the host
	if (index($vol_host, "@")) {
		my @user_host = split("@", $vol_host);
		$username = $user_host[0];
		$vol_host = $user_host[1];
	} else {
		$username = $login_user;
	}
	
	#- create a restore work directory if we don't have one
	-d "$cfg_dir/restores" or mkdir_p "$cfg_dir/restores";

	#- can be a device name or a path
	my $dev_path = $line_data[3];
	
	if ($media eq 'HD') {
		#- shouldn't really happen, should have just browsed 
		#- to the $save_path in the previous step - deal with it anyway
		my @restore_tar_files = glob("$dev_path/*$backup_time*$tar_ext");
		my $matches = @restore_tar_files;
		if ($matches == 0) {
			show_warning("f", N("Backup files not found at %s.", $dev_path));
			return 0;
		} else {
			my $save_path_org = $save_path;
			$save_path = $dev_path;
			$restore_result = restore_hd_or_cd($cat_entry, $dev_path, @restore_files);
			$save_path = $save_path_org;
		}			
	}
	
	if ($media eq 'CD') {
		#- we know the cdrecord device, and the label
		#- prompt the user for the right CD
		$in->ask_okcancel(N("Restore From CD"), N("Insert the CD with volume label %s\n in the CD drive under mount point /mnt/cdrom", $vol_host) ,1) ? ($vol_name = get_cd_volname()) : return 0;
		if ($vol_name ne $vol_host) {
			show_warning("f", N("Not the correct CD label. Disk is labelled %s.", $vol_name));
			return 0;
		} else {
			$restore_result = restore_hd_or_cd($cat_entry, '/mnt/cdrom', @restore_files);
		}	
	}
	
	if ($media eq 'Tape') {
		#- a little more complicated, we need to check if other backups
		#- were done on this tape, and try to find the offset to this one
		$in->ask_okcancel(N("Restore From Tape"), N("Insert the tape with volume label %s\n in the tape drive device %s", $vol_host, $dev_path) ,1) ? ($vol_name = get_tape_label($dev_path)) : return 0;
		if ($vol_name ne $vol_host) {
			show_warning("f", N("Not the correct tape label. Tape is labelled %s.", $vol_name));
			return 0;
		} else {
			$restore_result = restore_tape($cat_entry, $dev_path, @restore_files);
		}			
	}
	
	if ($media eq 'ftp' || $media eq 'webdav' || $media eq 'ssh' || $media eq 'rsync') { 
		#- show the user what we know of the connection from the catalog 
		#- and the config file, let them override if necessary
		
		#- the various protocols are going to have different requirements
		#- webdav - it should already be in sitecopyrc - compare it?
		#- ssh - the only method we have enabled at the moment is with keys 
		#-	- no passwd needed
		#-  - if we use expect, it is needed
		#-  - if we use drackbackup keys, then a different ssh call is needed
		#- rsync - uses a config file with username - rsync.user
		#- ftp needs all parameters entered
		
		$in->ask_from(N("Restore Via Network"), N("Restore Via Network Protocol: %s", $media),
			      [ { label => N("Host Name"), val => \$vol_host },
				{ label => N("Host Path or Module"), val => \$dev_path },
				{ label => N("Username"), val => \$username },
				{ label => N("Password"), val => \$userpass, hidden => 1  },
				]) or goto return 0;
		
		if ($media eq 'ftp' || $media eq 'rsync') {
			if ($userpass eq '') {
				show_warning("f", N("Password required")); 
				return 0;
			}
		} 
		if ($media eq 'ftp' || $media eq 'rsync' || $media eq 'ssh') {
			if ($username eq '') {
				show_warning("f", N("Username required"));
				return 0; 
			} elsif ($vol_host eq '') {
				show_warning("f", N("Hostname required")); 
				return 0;
			}
		}
		if ($dev_path eq '') {
			show_warning("f", N("Path or Module required")); 
			return 0;
		}
			
		$restore_result = restore_ftp($cat_entry, $vol_host, $dev_path, $username, $userpass, @restore_files) if $media eq 'ftp';
		$restore_result = restore_rsync_ssh_webdav($cat_entry, $vol_host, $dev_path, $username, $media, @restore_files) 
			if $media eq 'rsync' || $media eq 'ssh' || $media eq 'webdav';
	}

	# cleanup our restore dir - unlink fails here?
	system("rm -f $cfg_dir/restores/*");

	if (!$restore_result) {
		show_warning("i", N("Files Restored..."));
		return 0;
	} else {
		show_warning("f", N("Restore Failed..."));
		return 1;
	}

}

sub restore_hd_or_cd {
	my ($cat_entry, $tarfile_dir, @restore_files) = @_;
	my $indv_files = @restore_files;
	my $command;
		
	my $wild_card = catalog_to_wildcard($cat_entry);
		
	if ($indv_files == 0) {
		#- full catalog specified
		foreach (wildcard_to_tarfile($wild_card)) {
			$command = "tar -C $restore_path -xzf $tarfile_dir/$_";
			spawn_progress($command, "Untarring from \n$_ \nto $restore_path.");
		}
	} else {
		#- individual files - pull from appropriate catalog
		foreach (@restore_files) {
			my $tarfile = file_to_tarfile($_, $wild_card);
			$_ = substr($_, 1);
			$command = "tar -C $restore_path -xzf $tarfile_dir/$tarfile $_";
			spawn_progress($command, "Untarring \n$_ from \n$tarfile \nto $restore_path.");
		}
	}
    return 0;
}

sub restore_tape {
	my ($cat_entry, $dev_path, @restore_files) = @_;
	my $indv_files = @restore_files;
	my $command;
		
	my $wild_card = catalog_to_wildcard($cat_entry);
	$dev_path =~ s|/st|/nst|;
		
	if ($indv_files == 0) {
		#- full catalog specified
		foreach (wildcard_to_tarfile($wild_card)) {
			my $offset = find_tape_offset($cat_entry);
			$command = "mt -f $dev_path rewind";
			spawn_progress($command, "Rewinding tape on $dev_path.");
			$command = "mt -f $dev_path fsf $offset";
			spawn_progress($command, "Moving forward $offset file records.");
			$command = "tar -C cfg_dir/restores -xf $dev_path";
			spawn_progress($command, "Untarring from $dev_path to work directory.");
			if (-e "$cfg_dir/restores/$_") {
				$command = "tar -C $restore_path -xzf $cfg_dir/restores/$_";
				spawn_progress($command, "Untarring \n$_ \nto $restore_path.");
			} else {
				return 1;
			}
		}
	} else {
		#- individual files - pull from appropriate catalog
		foreach (@restore_files) {
			my $tarfile = file_to_tarfile($_, $wild_card);
			$_ = substr($_, 1);
			if (!-e "$cfg_dir/restores/$tarfile") {
				my $offset = find_tape_offset($cat_entry);
				$command = "mt -f $dev_path rewind";
				spawn_progress($command, "Rewinding tape on $dev_path.");
				$command = "mt -f $dev_path fsf $offset";
				spawn_progress($command, "Moving forward $offset file records.");
				$command = "tar -C cfg_dir/restores -xf $dev_path";
				spawn_progress($command, "Untarring from $dev_path to work directory.");
			}
			if (-e "$cfg_dir/restores/$tarfile") {
				$command = "tar -C $restore_path -xzf $cfg_dir/restores/$tarfile $_";
				spawn_progress($command, "Untarring \n$_ from \n$tarfile \nto $restore_path.");
			} else {
				return 1;
			}
		}
	}
    return 0;
}

sub restore_ftp {
    use Net::FTP; 
    my $ftp;
	my ($cat_entry, $hostname, $hostpath, $username, $userpass, @restore_files) = @_;
	my $indv_files = @restore_files;
	my $command;
		
    $DEBUG and print "file list to retrieve: $cat_entry\n ";
    if ($DEBUG && $interactive) { $ftp = Net::FTP->new($hostname, Debug => 1) or return 1 }
    elsif ($interactive)  {  $ftp = Net::FTP->new($hostname, Debug => 0) or return 1 }
    else {  $ftp = Net::FTP->new($hostname, Debug => 0) or return 1 }
    $ftp->login($username, $userpass);
    $ftp->cwd($hostpath);

	my $wild_card = catalog_to_wildcard($cat_entry);
		
	if ($indv_files == 0) {
		#- full catalog specified
		foreach (wildcard_to_tarfile($wild_card)) {
			$ftp->get($_, "$cfg_dir/restores/$_");
			$command = "tar -C $restore_path -xzf $cfg_dir/restores/$_";
			spawn_progress($command, "Untarring \n$_ \nto $restore_path.");
		}
	} else {
		#- individual files - pull from appropriate catalog
		foreach (@restore_files) {
			my $tarfile = file_to_tarfile($_, $wild_card);
			$_ = substr($_, 1);
			if (!-e "$cfg_dir/restores/$tarfile") {
				$ftp->get($tarfile, "$cfg_dir/restores/$tarfile");
			}
			$command = "tar -C $restore_path -xzf $cfg_dir/restores/$tarfile $_";
			spawn_progress($command, "Untarring \n$_ from \n$tarfile \nto $restore_path.");
		}
	}
    $ftp->quit; 
    return 0;
}

sub restore_rsync_ssh_webdav {
	my ($cat_entry, $hostname, $hostpath, $username, $mode, @restore_files) = @_;
	my $indv_files = @restore_files;
	my $command;
	my $wild_card = catalog_to_wildcard($cat_entry);
	if ($indv_files == 0) {
		#- full catalog specified
		foreach (wildcard_to_tarfile($wild_card)) {
			if ($mode eq 'ssh') {
				$command = "scp $username\@$hostname:$hostpath/$_ $cfg_dir/restores/";
			} elsif ($mode eq 'rsync') {
				$command = "rsync --password-file=$cfg_dir/rsync.user $username\@$hostname" . "::" . "$hostpath/$_ $cfg_dir/restores/";
			} else {
				$command = "wget http://$hostname/$hostpath/$_ -P $cfg_dir/restores/";
			}
			spawn_progress($command, "Retrieving backup file \n$_ \nvia $mode.");
			if (-e "$cfg_dir/restores/$_") {
				$command = "tar -C $restore_path -xzf $cfg_dir/restores/$_";
				spawn_progress($command, "Untarring \n$_ \nto $restore_path.");
			} else {
				return 1;
			}
		}
	} else {
		#- individual files - pull from appropriate catalog
		foreach (@restore_files) {
			my $tarfile = file_to_tarfile($_, $wild_card);
			$_ = substr($_, 1);
			if (!-e "$cfg_dir/restores/$tarfile") {
				if ($mode eq 'ssh') {
					$command = "scp $username\@$hostname:$hostpath/$tarfile $cfg_dir/restores/";
				} elsif ($mode eq 'rsync') {
					$command = "rsync --password-file=$cfg_dir/rsync.user $username\@$hostname" . "::" . "$hostpath/$tarfile $cfg_dir/restores/";
				} else {
					$command = "wget http://$hostname/$hostpath/$tarfile -P $cfg_dir/restores/";
				}
				spawn_progress($command, "Retrieving backup file \n$tarfile \nvia $mode.");
			}
			if (-e "$cfg_dir/restores/$tarfile") {
				$command = "tar -C $restore_path -xzf $cfg_dir/restores/$tarfile $_";
				spawn_progress($command, "Untarring \n$_ from \n$tarfile \nto $restore_path.");
			} else {
				return 1;
			}
		}
	}
    return 0;
}

sub catalog_to_wildcard {
	my ($cat_entry) = @_;
	my @line_data = split(':', $cat_entry);
	my $wildcard = $line_data[0];
	$wildcard;
}

sub wildcard_to_tarfile {
	my ($wildcard) = @_;
	my (@tarfile) = glob("$save_path/*$wildcard.txt");
	foreach (@tarfile) {
		$_ = basename($_);
		s/txt/$tar_ext/;
		s/list/backup/;
	}
	@tarfile;
}

sub file_to_tarfile {
	my ($restore_file, $wildcard) = @_;
	my $tarfile = `grep -l $restore_file $save_path/*$wildcard.txt`;
	chop $tarfile;
	$tarfile = basename($tarfile);
	$tarfile =~ s/txt/$tar_ext/;
	$tarfile =~ s/list/backup/;
	$tarfile;
}

sub find_tape_offset {
	my ($cat_entry) = @_;
	my @line_data = split(':', $cat_entry);
	my $label = $line_data[2];
	my @catalog = cat_("$cfg_dir/drakbackup_catalog");
	# always off by 1 for tape label.
	my $offset = 1;
	foreach (@catalog) {
		if (index($_, $label)) {
			if (!index($_, $cat_entry)) {
				# tar seems to need 2 of these to get located
				$offset++;
				$offset++;
			} else {
				return $offset;
			}
		} 
	}	
}

sub restore_box() {
    my $retore_box;
    
	if ($good_restore_path) {
		$path_to_find_restore = $save_path if $where_hd;
		$path_to_find_restore = "/mnt/cdrom" if $where_cd;
	}
	
    find_backup_to_restore();
    button_box_restore_main();

    if ($other_backuped || $sys_backuped || @user_backuped) {
		gtkpack($advanced_box,
			$retore_box = gtkpack_(new Gtk2::HBox(0,1),
				1, new Gtk2::VBox(0,10),
				1, gtkpack_(new Gtk2::VBox(0,10),
					1, new Gtk2::VBox(0,10),
					1, new Gtk2::VBox(0,10),
					1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Search for files to restore")), clicked => sub { 
						$retore_box->destroy;
						button_box_file_restore();
						find_files_to_restore() 
					}),
					1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Restore all backups")), clicked => sub { 
						$retore_box->destroy;
						button_box_restore();
						@user_list_to_restore2 = sort @user_backuped; 
						$restore_sys = 1;
						$restore_other = 1;
						$restore_user = 1;
						restore_do() 
					}),
					1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Custom Restore")), clicked => sub { 
						$retore_box->destroy;
						button_box_restore(); 
						restore_step2();
					}),
					1, new Gtk2::VBox(0,10),
					1, new Gtk2::VBox(0,10),
				),
				1, new Gtk2::HBox(0,10),
			),
		);
    } else {
		destroy_widget();
		restore_find_media_box(),
	}
    fonction_env(\$retore_box, \&restore_box, \&interactive_mode_box, "restore");
    $central_widget = \$retore_box;
	$up_box->show_all;
}

sub restore_find_media_box() {
    my $mount_media = 1;
    $good_restore_path = 0;
    my $message = "Unable to find backups to restore...\n";
    $message .= "Verify that $path_to_find_restore is the correct path" if $where_hd && $where_cd;
    $message .= " and the CD is in the drive" if $where_cd;
    if ($where_tape || $net_proto) {
		$message .= "Backups on unmountable media - Use Catalog to restore";
		$mount_media = 0;
    }
    $message .= ".";
    
    gtkpack($advanced_box,
		$box2 = gtkpack_(new Gtk2::VBox(0, 5),	
			1, gtkpack(new Gtk2::HBox(0, 15),	
				new Gtk2::VBox(0, 5),	
				gtkcreate_img('warning'), 
				translate($message),
				new Gtk2::VBox(0, 5),	
			),
			1, gtkpack(new Gtk2::HBox(0, 15),
				new Gtk2::VBox(0, 5),
				gtkpack(new Gtk2::VBox(0, 10),
					gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("CD in place - continue.")), clicked => sub {  
						$good_restore_path = 1;
						interactive_mode_box("restore");
					}), $mount_media),
					$new_path_entry = gtkset_sensitive(new Gtk2::Entry(), $mount_media),
					gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Browse to new restore repository.")), clicked => sub {  
						filedialog_generic("Directory To Restore From", \$new_path_entry, \$path_to_find_restore);
					}), $mount_media),
					gtksignal_connect(Gtk2::Button->new_from_stock(N("Restore From Catalog")), clicked => sub {  
						$box2->destroy;
						catalog_restore();
					}),
				),
				new Gtk2::VBox(0, 5),
			),
			1, new Gtk2::VBox(0, 5),	
		),
	);
	$new_path_entry->set_text($path_to_find_restore);
	$central_widget = \$box2;
	
	button_box_find_media($mount_media);  
    $up_box->show_all;
}

sub restore_status() {
	destroy_widget();
    $pbar3 =  new Gtk2::ProgressBar;
    $stext = new Gtk2::Label("");
    gtkpack($advanced_box,
		$table = gtkpack(new Gtk2::VBox(0, 5),
			new Gtk2::HBox(0,5),
	    	create_packtable({ col_spacings => 10, row_spacings => 5 },
				[""],
				[""],
				[""],
				[""], 
				[N("Restore Progress")],
				[""],
				[""],
				[$pbar3],
				[""],
				[""],
				[$plabel3 = new Gtk2::Label(' ')],
				[""],
			),
			$stext,
		),
	);
    $custom_help = "options";
    $central_widget = \$table;
    $up_box->show_all;
    gtkflush();
}

################################################  BUTTON_BOX  ################################################  

sub button_box_adv() {
    $button_box_tmp->destroy;
    gtkpack($button_box,
		$button_box_tmp = gtkpack_(new Gtk2::HButtonBox,
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { 
				adv_help();
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				interactive_mode_box();
			}),
			1, new Gtk2::HBox(0, 1),	
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { 
				destroy_widget();
				$previous_widget->();
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-save'), clicked => sub { 
				destroy_widget();
				unless (check_pkg_needs()) {
					save_conf_file();
					$previous_widget->();
				}
			}),
		),
	);
}

sub button_box_restore_main() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(gtkpack_(new Gtk2::HButtonBox, 
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub {
				adv_help();
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				destroy_widget(); 
				interactive_mode_box();
			}),
			1, new Gtk2::HBox(0, 1),	
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { 
				destroy_widget(); 
				interactive_mode_box() 
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-ok'), clicked => sub { 
				destroy_widget(); 
				interactive_mode_box() }),
			),
		),
	);
}

sub button_box_file_restore() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(gtkpack_(new Gtk2::HButtonBox, 
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub {
				adv_help();
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				destroy_widget(); 
				restore_box();
			}),
			1, new Gtk2::HBox(0, 1),	
			),
		),
	);
}

sub button_box_log_main() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(gtkpack_(new Gtk2::HButtonBox, 
			1, new Gtk2::HBox(0, 1),	
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-ok'), clicked => sub { 
				destroy_widget(); 
				interactive_mode_box() }),
			),
		),
	);
}


sub button_box_backup_end() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(new Gtk2::HButtonBox,
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { 
				adv_help() 
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				destroy_widget(); 
				interactive_mode_box() 
			}),
			1, new Gtk2::HBox(0, 1),	
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { 
				destroy_widget(); 
				$previous_widget->() 
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Build Backup")), clicked => sub { 
				destroy_widget();
				build_backup_status();
				build_backup_files(); 
			}),
		),
	);
}

sub button_box_wizard_end() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
		$button_box_tmp = gtkpack_(new Gtk2::HButtonBox,
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { 
				adv_help();
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				destroy_widget();
				interactive_mode_box();
			}),
			1, new Gtk2::HBox(0, 1),	
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { 
				destroy_widget(); 
				$previous_widget->();
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-save'), clicked => sub { 
				destroy_widget();
				save_conf_file();
				interactive_mode_box();
			}),
		),
	);
}

sub button_box_restore_end() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(new Gtk2::HButtonBox,
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { 
				adv_help();
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				destroy_widget();
				interactive_mode_box();
			}),
			1, new Gtk2::HBox(0, 1),	
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { 
				destroy_widget();
				$previous_widget->();
			}),
			0, gtksignal_connect(Gtk2::Button->new(N("Restore")), clicked => sub { 
 				destroy_widget();
				restore_backend(); 
			}),
		),
	);
}

sub button_box_build_backup_end() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 
			1, new Gtk2::HBox(0, 5),	
			1, new Gtk2::HBox(0, 5),	
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-ok'), clicked => sub { 
#				destroy_widget();
				interactive_mode_box();  
			}),
		),
	);
}

sub button_box_restore_pbs_end() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
		$button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 
			1, new Gtk2::HBox(0, 5),	
			1, new Gtk2::HBox(0, 5),	
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub {
				adv_help();
			}),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-ok'), clicked => sub { 
				destroy_widget();
				interactive_mode_box();
			}),
		),
	);
}

sub button_box_build_backup() {
    $button_box_tmp->destroy;

	gtkpack($button_box,
		$button_box_tmp = gtkpack_(new Gtk2::HButtonBox,
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub {
				adv_help(); 
			}),
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				destroy_widget(); 
				interactive_mode_box();
			}),
			1, new Gtk2::HBox(0, 0),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { 
				destroy_widget();
				$previous_widget->();
			}),
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-forward'), clicked => sub {
				destroy_widget();
				$next_widget->();
			}),
		),
	);
}

sub button_box_restore() {

    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(new Gtk2::HButtonBox,
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub {
				adv_help();
			}),
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				destroy_widget(); 
				interactive_mode_box();  
			}),
			1, new Gtk2::HBox(0, 0),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { 
				destroy_widget(); 
				$previous_widget->(); 
			}),
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-forward'), clicked => sub {
				destroy_widget(); 
				$next_widget->();
			}),
		),
	);
}

sub button_box_find_media {

	my ($mount_media) = @_;
	
	#- $central_widget is not known yet?
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(new Gtk2::HButtonBox,
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub {
				$central_widget = \$box2; 
				adv_help();
			}),
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				$central_widget = \$box2;
				interactive_mode_box();  
			}),
			1, new Gtk2::HBox(0, 0),
			0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub {
				$central_widget = \$box2;
				interactive_mode_box();  
			}),
			1, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-forward'), clicked => sub {
				interactive_mode_box("restore"); 
			}), $mount_media),
		),
	);
}

sub button_box_wizard() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack_(new Gtk2::HButtonBox,
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub {
				adv_help() 
			}),
			1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { 
				destroy_widget(); 
				interactive_mode_box() 
			}),
			1, new Gtk2::HBox(0, 0),
			0, gtksignal_connect(Gtk2::Button->new_from_stock($next_widget ? 'gtk-go-back' : 'gtk-ok'), clicked => sub { 
				destroy_widget();
				$previous_widget ? $previous_widget->() : $next_widget->();
			}),
			if_($next_widget, 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-forward'), clicked => sub {
				destroy_widget();
				$next_widget ? $next_widget->() : $previous_widget->();
			})),
		),
	);
}

sub button_box_main() {
    $button_box_tmp->destroy;

    gtkpack($button_box,
	    $button_box_tmp = gtkpack(Gtk2::HButtonBox->new,
			gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { 
				adv_help() 
			}),
			gtksignal_connect(Gtk2::Button->new_from_stock('gtk-close'), clicked => sub { ugtk2->exit(0) }),
		),
	);
}

################################################  MESSAGES  ################################################  

sub dialog_one {
	destroy_widget();
    my ($label) = @_;
    
    gtkadd($advanced_box,
           $box2 = gtkpack_(new Gtk2::HBox(0, 15),	
                            1, new Gtk2::VBox(0, 5),	
                            0, gtkpack_(new Gtk2::HBox(0, 15),	
                                        0, new Gtk2::VBox(0, 5),	
                                        0, gtkcreate_img('warning'),
                                        0, $label),
                            0, new Gtk2::VBox(0, 5),	
                            1, new Gtk2::VBox(0, 5),	
                            ),
           );
    button_box_restore_main();
    $custom_help = "mail_pb";
    $central_widget = \$box2;
    $up_box->show_all;    
}

sub send_mail_pb() {
    dialog_one(N("Error during sendmail.
  Your report mail was not sent.
  Please configure sendmail"));
}

sub client_ftp_pb() {
    dialog_one(N("Error during sending file via FTP.
 Please correct your FTP configuration."));
}

sub install_rpm {
    my ($previous_function) = @_;
	#- catch a crash when calling help
	#- this GUI control technique is kind of funky
	if ($previous_function eq '') {
		$previous_function = \&advanced_where;
	}
    my $box_what_user;
    gtkpack($advanced_box,
	    $box_what_user = gtkpack_(new Gtk2::VBox(0, 15),
			0, N("The following packages need to be installed:\n") . join(' ', @list_of_rpm_to_install),
				0, new Gtk2::HSeparator,
				0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Install")), clicked => sub {  
					system("/usr/sbin/urpmi --X @list_of_rpm_to_install"); 
					destroy_widget();
					$previous_widget->();		  
				}),
		),
	);
    fonction_env(\$box_what_user, \&install_rpm, \&$previous_function, "what");
    $up_box->show_all;
}


sub message_norestore_box() {
    $box2->destroy;
    
    gtkadd($advanced_box,
		$box2 = gtkpack_(new Gtk2::HBox(0, 15),	
			1, new Gtk2::VBox(0, 5),	
			1, gtkpack(new Gtk2::HBox(0, 15),	
				new Gtk2::VBox(0, 5),	
				gtkcreate_img('warning'),
				N("Please select data to restore..."),
				new Gtk2::VBox(0, 5),	
			),
			1, new Gtk2::VBox(0, 5),	
		),
	);
    button_box_restore_main();
    $central_widget = \$box2;
    $up_box->show_all;    
}


sub message_common_box {
    $box2->destroy;
    my ($label) = @_;
    
    gtkadd($advanced_box,
           $box2 = gtkpack_(new Gtk2::HBox(0, 15),	
                            1, new Gtk2::VBox(0, 5),	
                            1, gtkpack(new Gtk2::HBox(0, 15),	
                                       new Gtk2::VBox(0, 5),	
                                       gtkcreate_img('warning'),
                                       $label,
                                       new Gtk2::VBox(0, 5),	
                                       ),
                            1, new Gtk2::VBox(0, 5),	
                            ),
           );
    $previous_widget = \&wizard;
    $next_widget = \&wizard;
    $central_widget = \$box2;
    $up_box->show_all;    
}

sub message_noselect_box() {
    message_common_box(N("Please select media for backup..."));
    $previous_widget = \&wizard_step2;
    $next_widget = \&wizard_step2;
    $central_widget = \$box2;
    $up_box->show_all;    
}

sub message_noselect_what_box() {
    message_common_box(N("Please select data to backup..."));
    $previous_widget = \&wizard;
    $next_widget = \&wizard;
    $central_widget = \$box2;
    $up_box->show_all;    
}

sub message_common_box_2 {
    my ($label, $restore_main) = @_;

    $box2->destroy;

    gtkadd($advanced_box,
		$box2 = gtkpack_(new Gtk2::HBox(0, 15),	
			1, new Gtk2::VBox(0, 5),	
			1, gtkpack(new Gtk2::HBox(0, 15),	
				new Gtk2::VBox(0, 5),	
				gtkcreate_img('warning'),
				N("%s", $label),
				new Gtk2::VBox(0, 5),	
			),
			1, new Gtk2::VBox(0, 5),	
		),
	);
    button_box_restore_main() if $restore_main;
    $central_widget = \$box2;
    $up_box->show_all;    
}
sub message_noconf_box() {
    message_common_box_2(N("No configuration file found \nplease click Wizard or Advanced."), 1);
}

sub message_underdevel() {
    message_common_box_2(N("Under Devel ... please wait."), 1);
}

################################################  BUILD_BACKUP  ################################################  

sub progress {
    my ($progressbar, $plabel, $incr, $label_text) = @_;
    my ($new_val) = $progressbar->get_fraction;
    $new_val += $incr;
    if ($new_val > 1) { $new_val = 1 }
    $progressbar->set_fraction($new_val);
    $plabel->set_text($label_text);
    gtkflush();
}

sub find_backup_to_put_on_cd() {
    @data_backuped = ();
	local $_;
	
    -d $save_path and my @list_backup = all($save_path);
    foreach (grep { /^backup_other/ } @list_backup) {
		$other_backuped = 1;
		chomp;
		my $tail  = (split(' ', `du $save_path/$_`))[0];
		s/^backup_other//gi;
		s/.tar.gz$//gi;
		s/.tar.bz2$//gi;
		my @user_date = split /_20/;
		my @user_date2 = split(/_/, $user_date[1]);
		my $to_put = "  other_data,          (tail: $tail ko, date: 20$user_date2[0], hour: $user_date2[1])";
		push @data_backuped , $to_put;
    }
    foreach (grep { /_sys_/ } @list_backup) {
		$sys_backuped = 1;
		chomp;
		my $tail  = (split(' ', `du $save_path/$_`))[0];
		s/^backup_other//gi;
		s/.tar.gz$//gi;
		s/.tar.bz2$//gi;
		my @user_date = split /_20/;
		my @user_date2 = split(/_/, $user_date[1]);
		my $to_put = "  system,          (tail: $tail ko, date: 20$user_date2[0], hour: $user_date2[1])";
		push @data_backuped , $to_put;
    }
    foreach (grep { /user_/ } @list_backup) {
		chomp;
		my $tail  = (split(' ', `du $save_path/$_`))[0];
		s/^backup_user_//gi;
		s/.tar.gz$//gi;
		s/.tar.bz2$//gi;
		my @user_date = split /_20/;
		my @user_date2 = split(/_/, $user_date[1]);
		my $to_put = "  $user_date[0],          (tail: $tail ko, date: 20$user_date2[0], hour: $user_date2[1])";
		push @data_backuped , $to_put;
    }
}

sub build_backup_status() {
    $pbar =   new Gtk2::ProgressBar;
    $pbar1 =  new Gtk2::ProgressBar;
    $pbar2 =  new Gtk2::ProgressBar;
    $pbar3 =  new Gtk2::ProgressBar;
	$plabel = new Gtk2::Label(" ");
	$plabel1 = new Gtk2::Label(" ");
	$plabel2 = new Gtk2::Label(" ");
	$plabel3 = new Gtk2::Label(" ");
	
    $stext = new Gtk2::Label("");
	button_box_build_backup_end();

	my $table = Gtk2::Table->new(10, 2, 1);
	$table->set_row_spacings(5);
	$table->set_col_spacings(10);
	
	$table->attach_defaults(new Gtk2::Label(N("Backup system files")), 0, 1, 0, 1);
	$table->attach_defaults($pbar, 0, 1, 1, 2);
	$table->attach_defaults($plabel, 1, 2, 1, 2);	
	$table->attach_defaults(new Gtk2::Label(N("Backup user files")), 0, 1, 2, 3);
	$table->attach_defaults($pbar1, 0, 1, 3, 4);
	$table->attach_defaults($plabel1, 1, 2, 3, 4);	
	$table->attach_defaults(new Gtk2::Label(N("Backup other files")), 0, 1, 4, 5);
	$table->attach_defaults($pbar2, 0, 1, 5, 6);
	$table->attach_defaults($plabel2, 1, 2, 5, 6);	
	$table->attach_defaults(new Gtk2::Label(N("Total Progress")), 0, 1, 6, 7);
	$table->attach_defaults($pbar3, 0, 1, 7, 8);
	$table->attach_defaults($plabel3, 1, 2, 7, 8);	

    gtkpack($advanced_box,
		my $tbox = gtkpack(new Gtk2::VBox(0, 5),
			$table,
			$stext,
		),
	);

    $custom_help = "options";
    $central_widget = \$tbox;
    $up_box->show_all;
    gtkflush();
}


sub build_backup_ftp_status() {
    $pbar =   new Gtk2::ProgressBar;
    $pbar3 =  new Gtk2::ProgressBar;
	destroy_widget();
    button_box_build_backup_end();
    $pbar->set_fraction(0);
    $pbar3->set_fraction(0);


    gtkpack($advanced_box,
		$table =  gtkpack_(new Gtk2::VBox(0, 15),
			1, N("Sending files by FTP"),
			1, new Gtk2::VBox(0, 15),
			1, create_packtable ({ col_spacings => 10, row_spacings => 5 },
				[N("Sending files...")],
				[""], 
				[ $plabel = new Gtk2::Label(' ') ],
				[ $pbar ],
				[""], 
				[N("Total Progress")],
				[ $plabel3 = new Gtk2::Label(' ') ],
				[$pbar3],
			),
			1, new Gtk2::VBox(0, 15),
		),
	);
    $custom_help = "options";
    $central_widget = \$table;
    $up_box->show_all;
    gtkflush();
}

sub build_backup_box_see_conf {
	my ($caller) = @_;
    my $box2;
    my $text = new Gtk2::TextView;
    system_state();
    gtktext_insert($text, [ [ $system_state ] ]);
    button_box_restore_main();

    gtkpack($advanced_box,
	    $box2 = gtkpack_(new Gtk2::HBox(0, 15),	
			1, gtkpack_(new Gtk2::VBox(0,10),
				0, N("Drakbackup Configuration"),
				1, create_scrolled_window($text),
			),
		),
	);
    button_box_backup_end();
    $custom_help = "";
    $central_widget = \$box2;
    $current_widget = \&build_backup_box_see_conf;
	if ($caller eq "interactive") {
		$previous_widget = \&interactive_mode_box;
	} else {
    	$previous_widget = \&build_backup_box;
    }
	$up_box->show_all;
}

sub build_backup_box_progress() {
#    build_backup_files(); 
}

sub aff_total_tail() {
    my @toto;
    my $total = 0;
    push @toto, (split(",", $_))[1] foreach @list_to_build_on_cd;
    foreach (@toto) {
	s/\s+\(tail://gi;
	s/\s+//gi;
	s/ko//gi;
	$total += $_; 
	}
    $label_tail->set("total tail: $total ko");
}

sub build_backup_box() {
	destroy_widget();

    gtkadd($advanced_box,
		$box2 = gtkpack_(new Gtk2::HBox(0, 15),	
			1, new Gtk2::VBox(0, 5),	
			1, gtkpack_(new Gtk2::VBox(0, 15),	
				1, new Gtk2::VBox(0, 5),	
				1, gtksignal_connect(my $button_from_conf_file = Gtk2::Button->new, clicked => sub { 
					destroy_widget();
					build_backup_box_see_conf();
				}),
 				0, new Gtk2::VBox(0, 5),	
				1, gtksignal_connect(my $button_see_conf = Gtk2::Button->new, clicked => sub { 
					destroy_widget();
					build_backup_box_see_conf();
				}),
				1, new Gtk2::VBox(0, 5),	
			),
			1, new Gtk2::VBox(0, 5),	
		),
	 );

    $button_from_conf_file->add(gtkpack(new Gtk2::HBox(0,10),
		gtkcreate_img("ic82-discdurwhat-40"),
		new Gtk2::Label(N("Backup Now from configuration file")),
		new Gtk2::HBox(0, 5)
	));
    $button_see_conf->add(gtkpack(new Gtk2::HBox(0,10),
		gtkcreate_img("ic82-moreoption-40"),
		new Gtk2::Label(N("View Backup Configuration.")),
		new Gtk2::HBox(0, 5)
	));

    button_box_restore_main();
    fonction_env(\$box2, \&build_backup_box, \&interactive_mode_box, "options");
    $up_box->show_all;
}

################################################  INTERACTIVE  ################################################  

sub interactive_mode_box {

	my ($mode) = @_;
	if ($mode eq "restore") {
    	$central_widget = \$box2;
		restore_box();
		return 0;
	}
	    
	destroy_widget();
    gtkadd($advanced_box,
		$box2 = gtkpack_(new Gtk2::HBox(0, 15),	
			1, new Gtk2::VBox(0, 5),	
			1, gtkpack_(new Gtk2::VBox(0, 5),	
				1, new Gtk2::VBox(0, 5),	
				0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Wizard Configuration")), clicked => sub { 
					destroy_widget();
					read_conf_file();
					wizard(); 
				}),
				0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Advanced Configuration")), clicked => sub { 
					button_box_adv();
					destroy_widget();
					advanced_box(); 
				}),
				0, gtksignal_connect(Gtk2::Button->new_from_stock(N("View Configuration")), clicked => sub { 
					destroy_widget();
					build_backup_box_see_conf("interactive");
				}),
				0, gtksignal_connect(Gtk2::Button->new_from_stock(N("View Last Log")), clicked => sub { 
					$results = cat_($log_file);
					button_box_log_main();
					show_status();
				}),				
				0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Backup Now")), clicked => sub { 
					if ($cfg_file_exist) { 
						build_backup_box();
					} else { 
						message_noconf_box();
					}
				}),
				0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Restore")), clicked => sub {
					destroy_widget(); 
					restore_box();
				}),
				1, new Gtk2::VBox(0, 5),	
			),
			1, new Gtk2::VBox(0, 5),	
		),
	);
    $central_widget = \$box2;
    button_box_main();
    $custom_help = "main";
    $up_box->show_all;
}

sub interactive_mode() {
    $interactive = 1;

    $in = 'interactive'->vnew;

    my $box;
	my $winht = 400;
	$winht = 320 if $::isEmbedded;
	
    $my_win = ugtk2->new('drakbackup');
    $window1 = $my_win->{window};
    unless ($::isEmbedded) {
	   $my_win->{rwindow}->set_position('center');
	   $my_win->{rwindow}->set_title(N("Drakbackup"));
	   $window1->set_size_request(600, 500);
    }
    $my_win->{rwindow}->signal_connect(delete_event => sub { ugtk2->exit(0) });
    read_conf_file();     

    gtkadd($window1,
		gtkpack(new Gtk2::VBox(0,0),
			gtkpack(gtkset_size_request($up_box = new Gtk2::VBox(0, 5), 540, $winht),
				$box = gtkpack_(new Gtk2::VBox(0, 3),
					if_(!$::isEmbedded, 0, gtkcreate_img("drakbackup.540x57")),
					1, gtkpack_(new Gtk2::HBox(0, 3),
				  		1, gtkpack_(new Gtk2::HBox(0, 15),	
							0, new Gtk2::HBox(0, 5),	
					    	1, $advanced_box = gtkpack_(new Gtk2::HBox(0, 15),	
							),
					    	0, new Gtk2::HBox(0, 5),	
						),
					),
					0, new Gtk2::HSeparator,
					0, $button_box = gtkpack(new Gtk2::VBox(0, 15),	
						$button_box_tmp = gtkpack(new Gtk2::VBox(0, 0),),
					),
				),
			),
		),
	);
    interactive_mode_box();
    $custom_help = "main";
    button_box_main();
    $central_widget = \$box2;
    $window1->show_all;
    $window1->realize;
    $window1->show_all;    
    $my_win->main;
    $my_win->exit(0);
}

################################################  HELP & ABOUT  ################################################  

sub adv_help() {
	exec("drakhelp Drakxtools-Guide.html/drakbackup.html") unless fork();
}

sub to_ok() {
    $sav_next_widget = $next_widget;
    $next_widget = undef;
    button_box_wizard();
}

sub to_normal() {
    $next_widget = $sav_next_widget;
}

sub destroy_widget() {
	if ($central_widget ne '') {
		$$central_widget->destroy;
		$central_widget = '';
	}
}