#!/usr/bin/perl # # Copyright (C) 2001 by Sebastien DUPONT # 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: # # Drakbacup is use 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) # # Drakbacup allow you to backup your system on: # - Harddrive. # - NFS. # - CDROM (CDRW), DVDROM (with autoboot, rescue and autoinstall.). # - FTP. # - Rsync. # - Webdav. # - Tape. # # Drakbacup allow you to Restore your system on # choosen directory. # # Per default all backup will be stored on your # /var/drakbackup directory # # configuration file: # /etc/drakconf/drakbackup/drakbakup.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.* # #________________________________________________________________ # # REQUIRE: cron if daemon # cdrecord & mkisofs # ftp || perl Net::FTP # ssh-askpass # # PBS persistants: # selection des sources a inclure dans le backup cd. # et dans le restore_step_user # # # WARNING: ne pas ecraser les fichiers /etc/passwd fstab # after a other install # # # TODO: # during restore step catch the most recent date # and put in list all backup between the fisrt date # and the select date. # 1bis - refaire en clist. # 3 - add port for ftp backup. # 4 - change NET::FTP to ftp cmds. # 5 - add icons (win & lin) on adv_what_all. # 6 - calcul disk space. # use quota. # 7 - ssh & rsync -> expect or .identity.pub/authorized_keys # 8 - write on cd # 9 - cd writer detection -> cdrw: /sys/dev/cdrom/info /scsi/host0/bus0/target4/lun0 # 10- total backup.( all partitions wanted, windows partitions for example!) # dump use for total backup. # 11- send mail with results. # 12- custom deamon # 13- placer README dans $save_path -> prevenir des danger de supprimer la premier version # explain configuration file variables (mainly for non X users) # 13bis - option mode update tar u .... # 14- webdav # 15- backend : --resore_all, --restore_sys, --restore_users # --build_cd_autoinst # --backup_now --backup_default_now # 16- tape device support # 17- cpio use !! # 18- boot floppy disk (with dialog) # 19- build autoboot with backup and install cd # 20- use .backupignore like on CVS # # # DONE TODAY: #________________________________________________________________ use Gtk; use lib qw(/usr/lib/libDrakX ); use interactive; use standalone; use my_gtk qw(:helpers :wrappers); use common; use strict; use Time::localtime; my $in = 'interactive'->vnew('', 'default'); $::isEmbedded = ($::XID, $::CCPID) = "@ARGV" =~ /--embedded (\w+) (\w+)/; if ("@ARGV" =~ /--help|-h/) { print q(Backup and monitoring application --list : list of files or directories to backup. --default : save default directories. --build_cd : build restore iso with the currents backups files & rescue options. --build_floppy : build restore floppy. --save_dir : by default the backup files are saved in in /var/backup directory so write other directory to change to change it. --conf_file : to read other configuration file. ); exit(0); } # Backend Options. my $default = 0; my $build_cd = 0; my $build_floppy = 0; my $mode = 0; my $conf_file = 0; my @list_arg = (); my $central_widget; my $previous_widget; my $current_widget; my $interactive; my $up_box; my $advanced_box; my $box; my $box2; my $backup_choice = 0; my $cfg_file_exist = 0; my @user_and_path_list; my @all_user_list; my $list_other; my $label_cfg_file; 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 $retore_box2; my $cd_devive_entry; my $custom_help; my $button_box; my $button_box_tmp; my $next_widget; my $system_state; my $restore_state; my $save_path_entry; my $restore_find_path_entry; my $pbar; my $pbar1; my $pbar2; my $pbar3; my $the_time; my @user_list_to_restore2 = (); my @data_backuped = (); my $box_tail; my $label_tail; my @user_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 = (); # config. FILES -> Default PATH & Global variables. my @sys_files = ("/etc"); my @user_list; my @list_other = () ; my $cfg_file = "/etc/drakxtools/drakbackup/drakbackup.conf"; my $save_path = "/var/drakbackup"; my $restore_path = "/tmp"; 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 $what_no_browser = 1; my $cdrw = 0; my $net_proto= ''; my $host_path = ''; my $login_user = ''; my $net_daemon = 0; my $hd_daemon = 0; my $cd_daemon = 0; my $hd_quota = 0; my $where_net_ftp = 0; my $where_net_ssh = 0; my $where_net = 0; my $where_hd = 1; my $where_cd = 0; my $where_tape = 0; my $cd_time = 650; my $when_space; my $cd_with_install_boot = 0; my $cd_devive = ''; my $host_name = ''; my $backupignore = 0; my $auth_choice = 0; my $remember_pass = 0; my $passwd_user= ''; my $save_device_tape = (); my $cdrw_erase = 0; my $no_critical_sys = 1; foreach (@ARGV) { /--default/ and $default = 1, $mode=-1; /--build_cd/ and $build_cd = 1, $mode=-1; /--build_floppy/ and $build_floppy = 1, $mode=-1; /--conf_file/ and $mode = 0, next; /--list/ and $mode = 1, next; /--debug/ and $DEBUG = 1, next; $mode == 1 and push @list_arg, $_; } $build_floppy || $build_cd || $default || @list_arg || $conf_file ? backend_mod() : interactive_mode(); sub read_passwd { my @tmp1; my @tmp2; @user_and_path_list = map { (split(':', $_))[0] . ":" . (split(':', $_))[5] } grep {( split(':', $_))[2] > 500} split ('\n', cat_('/etc/passwd')); $DEBUG and print "user_and_path_list: ".$_."\n" foreach (@user_and_path_list); @user_list = (); @all_user_list = (); push @user_and_path_list, 'root:/root'; push @user_list, (split(':', $_))[0] foreach (@user_and_path_list); push @all_user_list, (split(':', $_))[0] foreach (@user_and_path_list); @tmp1 = sort @user_list; @user_list = @tmp1; @tmp2 = sort @all_user_list; @all_user_list = @tmp2; } sub the_time { $the_time = "_"; $the_time .= localtime->year() + 1900; $the_time .= localtime->mon() +1; $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(); } sub save_conf_file { 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", "DAEMON_TIME_SPACE=$when_space\n", "CDRW_DEVICE=$cd_devive\n", "LOGIN=$login_user\n", "TAPE_DEVICE=$save_device_tape\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" ; $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" ; $cdrw_erase and push @cfg_list, "CDRW_ERASE\n" ; $where_net_ftp and push @cfg_list, "USE_NET_FTP\n" ; $where_net_ssh and push @cfg_list, "USE_NET_SSH\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" ; $auth_choice or push @cfg_list, "AUTH_CHOICE=0\n" ; if ($auth_choice == 1) { push @cfg_list, "AUTH_CHOICE=1\n" ;} if ($auth_choice == 2) { push @cfg_list, "AUTH_CHOICE=2\n" ;} $cd_with_install_boot and push @cfg_list, "CD_WITH_INSTALL_BOOT\n" ; $net_daemon and push @cfg_list, "NET_DAEMON\n" ; $hd_daemon and push @cfg_list, "HD_DAEMON\n" ; $cd_daemon and push @cfg_list, "CD_DAEMON\n" ; $hd_quota and push @cfg_list, "HD_QUOTA\n" ; $where_hd and push @cfg_list, "USE_HD\n" ; $where_cd and push @cfg_list, "USE_CD\n" ; $where_net and push @cfg_list, "USE_NET\n" ; $cdrw and push @cfg_list, "CDRW\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" } output_p($cfg_file, @cfg_list); save_cron_files(); } sub read_cron_files { if (-f '/etc/cron.hourly/drakbackup') { $when_space = 'hourly'; } elsif (-f '/etc/cron.daily/drakbackup') { $when_space = 'daily'; } elsif (-f '/etc/cron.weekly/drakbackup') { $when_space = 'weekly';} elsif (-f '/etc/cron.monthly/drakbackup') { $when_space = 'monthly';} else {$backup_daemon = 0; } } sub save_cron_files { my @cron_file = ("#!/bin/sh\n", "\n", "/seb/cvs/gi/perl-install/standalone --default" ); if ($backup_daemon) { foreach ('hourly', 'daily', 'weekly', 'monthly'){ -f "/etc/cron.$_/drakbackup" and rm_rf("/etc/cron.$_/drakbackup"); } if ( $when_space eq _("hourly")) { output_p('/etc/cron.hourly/drakbackup', @cron_file )} elsif ( $when_space eq _("daily")) { output_p('/etc/cron.daily/drakbackup', @cron_file )} elsif ( $when_space eq _("weekly")) { output_p('/etc/cron.weekly/drakbackup', @cron_file )} elsif ( $when_space eq _("monthly")) { output_p('/etc/cron.monthly/drakbackup', @cron_file )} } else { foreach ('hourly', 'daily', 'weekly', 'monthly'){ -f "/etc/cron.$_/drakbackup" and rm_rf("/etc/cron.$_/drakbackup"); } } } sub read_conf_file { read_passwd(); if (-e $cfg_file) { open ( CONF_FILE, "<"."$cfg_file") || die; while () { 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 (/^NET_PROTO/) { s/^NET_PROTO=//gi; $net_proto = $_; } if (/^HOST_PATH/) { s/^HOST_PATH=//gi; $host_path = $_; } if (/^NET_DAEMON/) { $net_daemon = 1; } if (/^HD_DAEMON/) { $hd_daemon = 1; } if (/^CD_DAEMON/) { $cd_daemon = 1; } if (/^HD_QUOTA/) { $hd_quota = 1; } if (/^USE_HD/) { $where_hd = 1; } if (/^USE_CD/) { $where_cd = 1; } if (/^USE_NET/) { $where_net = 1; } if (/^USE_TAPE/) { $where_tape = 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 (/^CDRW_DEVICE/) { s/^CDRW_DEVICE=//gi; $cd_devive = $_;} if (/^HOST_NAME/) { s/^HOST_NAME=//gi; $host_name = $_;} if (/^AUTH_CHOICE/) { s/^AUTH_CHOICE=//gi; $auth_choice = $_; } if (/^REMEMBER_PASS/) { $remember_pass = 1; } if (/^LOGIN/) { s/^LOGIN=//gi; $login_user = $_; $remember_pass = 1; } if (/^PASSWD/) { s/^PASSWD=//gi; $passwd_user = $_; $remember_pass = 1; } if (/^USE_NET_FTP/) { $where_net_ftp = 1; } if (/^USE_NET_SSH/) { $where_net_ssh = 1; } if (/^TAPE_DEVICE/) { s/TAPE_DEVICE=//gi; $save_device_tape = $_;} if (/^CDRW_ERASE/) { $cdrw_erase = 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 (/^NO_CRITICAL_SYS/) { $no_critical_sys = 1;} if (/^CRITICAL_SYS/) { $no_critical_sys = 0;} } read_cron_files(); $cfg_file_exist = 1; } else { $cfg_file_exist = 0; } close CONF_FILE; } sub return_path { my $name = $_; foreach (@user_and_path_list) { if (grep /^$name\:/, $_) { s/^$name\://gi; return $_; } } } sub ftp_client { use Net::FTP; my $ftp = Net::FTP->new("$host_name"); $ftp->login("$login_user","$passwd_user"); $ftp->cwd("$host_path"); # $ftp->get("/ce/repertoire/ce.fichier"); $ftp->send("$save_path/*"); $ftp->quit; } sub return_file_date { my($more_recent) = @_; my $file_date; $_ = $more_recent; s/backup\_incr\_sys\_//gi; s/backup\_base\_sys\_//gi; s/backup\_incr\_user\_//gi; s/backup\_base\_user\_//gi; s/.tar.\w+$//gi; s/\_/ /gi; my $date = substr($_, 0, 8); my $hour = substr($_, 9, 2); my $min = substr($_, 11, 2); $file_date = $date . ' ' . $hour . ':' . $min; return $file_date; } 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 $tar_ext; my $vartemp; my $base_sys_exist = 0; my $base_user_exist = 0; my $base_other_exist = 0; my @list_temp = (); my @list_other_; my @dir_content = (); my $file_date; the_time(); -d $save_path or mkdir_p($save_path); if ($comp_mode) { $tar_cmd = "tar cv --use-compress-program /usr/bin/bzip2 "; $tar_ext = "tar.bz2" } else { $tar_cmd = "tar cvzp "; $tar_ext = "tar.gz"} $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"; $what_no_browser and $tar_cmd_user .= "--exclude NewCache --exclude Cache --exclude cache"; @dir_content = all($save_path); grep (/backup_base_sys/, @dir_content) and $base_sys_exist = 1; grep (/backup_base_other/, @dir_content) and $base_other_exist = 1; # fixme use incremental backup #tar -cvf tarfilename --after-date="sept 1, 2000" /home # tar -cf archive.tar --newer="`date -r file`" /home # algo: liste des fichiers du meme nom, on prend le dernier puis on applique le tar ci-dessus. # faire fonctions qui retourne le plus recent element. if ($where_hd) { $interactive and progress($pbar, 0.5, _("Backup system files...")); if ($backup_sys) { if ($backup_sys_versions) { if (grep(/backup_incr_sys/, @dir_content)) { my @more_recent = grep /backup_incr_sys/, @dir_content; @list_temp = sort @more_recent; $more_recent = pop @list_temp; $file_date = return_file_date($more_recent); } else { my @more_recent = grep /backup_base_sys/, @dir_content; $more_recent = @more_recent[0]; $file_date = return_file_date($more_recent); } if (!$base_sys_exist) { system("$tar_cmd_sys -f $save_path/backup_base_sys$the_time.$tar_ext @sys_files"); } else { system("$tar_cmd_sys -f $save_path/backup_incr_sys$the_time.$tar_ext --after-date='$file_date' @sys_files"); } } 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"); } } $interactive and progress($pbar, 0.5, _("Backup system files...")); $interactive and progress($pbar3, 0.3, _("Hard Disk Backup files...")); if (@list_other) { # if ($backup_other_versions) { # $base_other_exist or system("$tar_cmd_other -f $save_path/backup_base_other$the_time.$tar_ext @list_other"); # $base_other_exist and system("$tar_cmd_other -f $save_path/backup_incr_other$the_time.$tar_ext @list_other"); # } 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"); # } system("cd $save_path && rm -f backup_other* "); system("$tar_cmd_other -f $save_path/backup_other$the_time.$tar_ext @list_other"); foreach (@list_other) { push @list_other_, $_ . "\n"; } output_p( $save_path . '/list_other', @list_other_); } $interactive and progress($pbar1, 1, _("Backup User files...")); $interactive and progress($pbar3, 0.3, _("Hard Disk Backup Progress...")); if ($backup_user) { foreach (@user_list) { my $user = $_; if (grep (/backup_base_user_$user/, @dir_content)) { $base_user_exist = 1; } else { $base_user_exist = 0; } $path_name = return_path($user); if ($backup_user_versions) { if (grep(/backup_incr_user/, @dir_content)) { my @more_recent = grep /backup_incr_user/, @dir_content; @list_temp = sort @more_recent; $more_recent = pop @list_temp; $file_date = return_file_date($more_recent); } else { my @more_recent = grep /backup_base_user/, @dir_content; $more_recent = @more_recent[0]; $file_date = return_file_date($more_recent); } if (!$base_user_exist) { system("$tar_cmd_user -f $save_path/backup_base_user_$user$the_time.$tar_ext $path_name");} else { system("$tar_cmd_user -f $save_path/backup_incr_user_$user$the_time.$tar_ext --after-date='$file_date' $path_name");} } 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"); } } } $interactive and progress($pbar2, 1, _("Backup Other files...")); $interactive and progress($pbar3, 0.4, _("Hard Disk Backup files...")); } if ($where_net_ssh) { # $res = Net::SSLeay::write($ssl, $msg); # Perl knows how long $msg is # die_if_ssl_error("ssl write"); # shutdown S, 1; # Half close --> No more output, sends EOF to server # $got = Net::SSLeay::read($ssl); # Perl returns undef on failure # die_if_ssl_error("ssl read"); # print $got; # Net::SSLeay::free ($ssl); # Tear down connection # Net::SSLeay::CTX_free ($ctx); # close S; } if ($where_net_ftp) { } if ($where_cd) { } } sub list_remove { my($widget, $list) = @_; my @to_remove; push @to_remove, $list->child_position($_) foreach($list->selection); splice @list_other, $_, 1 foreach(reverse sort @to_remove); $list->remove_items($list->selection); } sub file_ok_sel { my ( $widget, $file_selection ) = @_; my $file_name = $file_selection->get_filename(); if(!member($file_name, @list_other)) { push(@list_other, $file_name); $list_other->add(gtkshow(new Gtk::ListItem($file_name))); } } sub filedialog_where_hd { my $file_dialog; $file_dialog = gtksignal_connect(new Gtk::FileSelection(_("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 Gtk::FileSelection(_("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 { my $file_dialog; $file_dialog = gtksignal_connect(new Gtk::FileSelection(_("File Selection")), destroy => sub { $file_dialog->destroy(); } ); $file_dialog->ok_button->signal_connect(clicked => \&file_ok_sel, $file_dialog); $file_dialog->ok_button->child->set(_("Add")); $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy() }); $file_dialog->cancel_button->child->set(_("Close")); $file_dialog->set_filename(_("Select the files or directories and click on 'Add'")); $file_dialog->show(); } ################################################ ADVANCED ################################################ sub advanced_what_sys { my $box_what_sys; gtkpack($advanced_box, $box_what_sys = gtkpack_(new Gtk::VBox(0, 15), 1, _("\nPlease check all options that you need.\n"), 1, _("This options can backup and restore all files on your /etc directory.\n"), 0, my $check_what_sys = new Gtk::CheckButton( _("Backup your System files. ( /etc directory )")), 0, my $check_what_versions = new Gtk::CheckButton( _("Use incremental backup (do not replace old backups)") ), 0, my $check_what_critical = new Gtk::CheckButton( _("Do not include critical files (passwd, goup, fstab)") ), 0, _("With this option you will be able to restore any version\n of your /etc directory."), 1, new Gtk::VBox(0, 15), ), ); foreach ([$check_what_sys, \$backup_sys], [$check_what_critical, \$no_critical_sys]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], ${$ref}), toggled => sub { ${$ref} = ${$ref} ? 0 : 1; }) } gtksignal_connect(gtkset_active($check_what_versions, $backup_sys_versions), toggled => sub { $backup_sys_versions = $backup_sys_versions ? 0 : 1; }); $custom_help = "what"; $current_widget = \&advanced_what_sys; $previous_widget =\&advanced_what; $central_widget = \$box_what_sys; $up_box->show_all(); } sub advanced_what_user { my ($previous_function) = @_, my $box_what_user; my %check_what_user; gtkpack($advanced_box, $box_what_user = gtkpack_(new Gtk::VBox(0, 15), 0, _("Please check all user that you want to include inb your backup."), 0, new Gtk::HSeparator, 1, createScrolledWindow( gtkpack__(new Gtk::VBox(0,0), map { my $name = $_; my @user_list_tmp; my $b = new Gtk::CheckButton($name); if (grep /^$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 Gtk::CheckButton( _(" do not include the browser cache") ), 0, my $check_what_user_versions = new Gtk::CheckButton( _("Use Incremental Backups (do not replace old backups)") ), ), ); foreach ([$check_what_browser, \$what_no_browser]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], ${$ref}), toggled => sub { ${$ref} = ${$ref} ? 0 : 1; }) } gtksignal_connect(gtkset_active($check_what_user_versions, $backup_user_versions), toggled => sub { $backup_user_versions = $backup_user_versions ? 0 : 1; }); $custom_help = "what"; if ($previous_function) { $previous_widget =\&$previous_function; $next_widget =\&$previous_function; } else { $previous_widget =\&advanced_what; } $current_widget = \&advanced_what_user; $central_widget = \$box_what_user; $up_box->show_all(); } sub advanced_what_other { my $box_what_other; $list_other = new Gtk::List(); $list_other->set_selection_mode(-extended); $list_other->add(gtkshow(new Gtk::ListItem($_))) foreach (@list_other); gtkpack($advanced_box, $box_what_other = gtkpack_(new Gtk::VBox(0, 15), 1, gtkpack_(new Gtk::HBox(0,4), 1, createScrolledWindow($list_other), ), 0, gtkadd(gtkset_layout(new Gtk::HButtonBox, -spread), gtksignal_connect(new Gtk::Button(_("Add")), clicked => sub {filedialog() }), gtksignal_connect(new Gtk::Button(_("Remove Selected")), clicked => \&list_remove, $list_other), ), 0, gtkset_sensitive(my $check_what_other_versions = new Gtk::CheckButton( _("Use Incremental Backups (do not replace old backups)") ), 0), ), ); gtksignal_connect(gtkset_active($check_what_other_versions, $backup_other_versions), toggled => sub { $backup_other_versions = $backup_other_versions ? 0 : 1; }); $custom_help = "what"; $current_widget = \&advanced_what_other; $previous_widget =\&advanced_what; $central_widget = \$box_what_other; $up_box->show_all(); } sub advanced_what_entire_sys{ my $box_what; my ($pix_user_map, $pix_user_mask) = gtkcreate_png("user"); my ($pix_other_map, $pix_other_mask) = gtkcreate_png("net_u"); my ($pix_sys_map, $pix_sys_mask) = gtkcreate_png("bootloader"); gtkpack($advanced_box, $box_what = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtksignal_connect(my $button_what_other = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); message_underdevel(); }), 1, gtksignal_connect(my $button_what_all = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); message_underdevel(); }), 1, new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $button_what_other->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_sys_map, $pix_sys_mask), new Gtk::Label(_(" Linux ")), new Gtk::HBox(0, 5) )); $button_what_all->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_user_map, $pix_user_mask), new Gtk::Label(_(" Windows (FAT32) ")), new Gtk::HBox(0, 5) )); $custom_help = ""; $current_widget = \&advanced_what_entire_sys; $previous_widget =\&advanced_what; $central_widget = \$box_what; $up_box->show_all(); } sub advanced_what{ my $box_what; my ($pix_user_map, $pix_user_mask) = gtkcreate_png("ic82-users-40"); my ($pix_other_map, $pix_other_mask) = gtkcreate_png("ic82-others-40"); my ($pix_sys_map, $pix_sys_mask) = gtkcreate_png("ic82-system-40"); my ($pix_sysp_map, $pix_sysp_mask) = gtkcreate_png("ic82-systemeplus-40"); gtkpack($advanced_box, $box_what = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtksignal_connect(my $button_what_sys = new Gtk::Button(), clicked => sub { $box_what->destroy(); advanced_what_sys(); }), 1, gtksignal_connect(my $button_what_user = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_what_user();}), 1, gtksignal_connect(my $button_what_other = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_what_other(); }), 1, gtksignal_connect(my $button_what_all = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_what_entire_sys(); }), 1, new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $button_what_sys->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_sys_map, $pix_sys_mask), new Gtk::Label(_(" System ")), new Gtk::HBox(0, 5) )); $button_what_user->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_user_map, $pix_user_mask), new Gtk::Label(_(" Users ")), new Gtk::HBox(0, 5) )); $button_what_other->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_other_map, $pix_other_mask), new Gtk::Label(_(" Other ")), new Gtk::HBox(0, 5) )); $button_what_all->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_sysp_map, $pix_sysp_mask), new Gtk::Label(_(" A Entire System ")), new Gtk::HBox(0, 5) )); $custom_help = ""; $current_widget = \&advanced_what; $previous_widget =\&advanced_box; $central_widget = \$box_what; $up_box->show_all(); } sub advanced_where_net_ftp { my ($previous_function) = @_, my $box_where_net; gtkpack($advanced_box, $box_where_net = gtkpack_(new Gtk::VBox(0, 15), 0, new Gtk::HSeparator, 0, my $check_where_net_ftp = new Gtk::CheckButton( _(" Use FTP connexion to backup") ), 0, new Gtk::HSeparator, 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("please entrer the host name or IP.")), $where_net_ftp), 1, new Gtk::HBox(0,10), 0, gtkset_sensitive(my $host_name_entry = new Gtk::Entry(), $where_net_ftp), ), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer the directory to\n put the backup on this host. ")), $where_net_ftp), 1, new Gtk::HBox(0,10), 0, gtkset_sensitive(my $host_path_entry = new Gtk::Entry(), $where_net_ftp), ), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("please entrer your login")), $where_net_ftp), 1, new Gtk::HBox(0,10), 0, gtkset_sensitive(my $login_user_entry = new Gtk::Entry(), $where_net_ftp), ), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("please entrer your passord")), $where_net_ftp), 1, new Gtk::HBox(0,10), 0, gtkset_sensitive(my $passwd_user_entry = new Gtk::Entry(), $where_net_ftp), ), 0, gtkpack_(new Gtk::HBox(0,10), 1, new Gtk::HBox(0,10), 0, gtkset_sensitive(my $check_remember_pass = new Gtk::CheckButton( _(" remember this password")), $where_net_ftp), ), ), ); $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()}); foreach ([$check_remember_pass, \$remember_pass]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], ${$ref}), toggled => sub { ${$ref} = ${$ref} ? 0 : 1; }) } gtksignal_connect(gtkset_active($check_where_net_ftp, $where_net_ftp), toggled => sub { $where_net_ftp = $where_net_ftp ? 0 : 1; ${$central_widget}->destroy(); $current_widget->(); }); $custom_help = "ftp"; if ($previous_function) { $previous_widget =\&$previous_function; } else { $previous_widget =\&advanced_where_net; } $current_widget = \&advanced_where_net_ftp; $central_widget = \$box_where_net; $up_box->show_all(); } sub advanced_where_net_ssh { my ($previous_function) = @_, my $box_where_ssh; gtkpack($advanced_box, $box_where_ssh = gtkpack_(new Gtk::VBox(0, 15), 1, gtkpack(new Gtk::HBox(0, 15), new Gtk::VBox(0, 15), gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtksignal_connect(new Gtk::Button("rsync"), clicked => sub { ${$central_widget}->destroy(); message_underdevel(); }), 1, gtksignal_connect(new Gtk::Button("WebDav"), clicked => sub { ${$central_widget}->destroy(); message_underdevel(); }), 1, gtksignal_connect(new Gtk::Button("scp"), clicked => sub { ${$central_widget}->destroy(); message_underdevel(); }), 1, new Gtk::VBox(0, 5), ), new Gtk::VBox(0, 15), ), ), ); # test si x11 #print system("xterm -fn 7x14 -bg black -fg white -e ssh-keygen -f ~/.ssh/identity-backup && scp ") . "\n"; if ($previous_function) { $previous_widget =\&$previous_function; } else { $previous_widget =\&advanced_where_net; } $custom_help = "ssh"; $current_widget = \&advanced_where_net_ssh; $previous_widget = \&advanced_where_net; $central_widget = \$box_where_ssh; $up_box->show_all(); } sub advanced_where_net { my ($previous_function) = @_, my $box_where_net; gtkpack($advanced_box, $box_where_net = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, new Gtk::VBox(0,10), 1, gtksignal_connect(new Gtk::Button(_(" FTP Connexion")), clicked => sub { $box_where_net->destroy(); if ($previous_function ) { advanced_where_net_ftp(\&$previous_function); } else { advanced_where_net_ftp(); }}), 1, gtksignal_connect(new Gtk::Button(_(" Secure Connexion ")), clicked => sub { $box_where_net->destroy(); if ($previous_function ) { advanced_where_net_ssh(\&$previous_function); } else { advanced_where_net_ssh(); }}), 1, new Gtk::VBox(0, 5), 1, new Gtk::VBox(0,10), ), 1, new Gtk::VBox(0, 5), ), ); if ($previous_function) { $previous_widget =\&$previous_function; } else { $previous_widget =\&advanced_where; } $custom_help = ""; $current_widget = \&advanced_where_net; $central_widget = \$box_where_net; $up_box->show_all(); } sub advanced_where_cd { my ($previous_function) = @_, my $box_where_cd; my $combo_where_cd_time = new Gtk::Combo(); $combo_where_cd_time->set_popdown_strings ("650","700", "750", "800"); gtkpack($advanced_box, $box_where_cd = gtkpack_(new Gtk::VBox(0, 6), 0, my $check_where_cd = new Gtk::CheckButton( _(" Use CD/DVDROM to backup")), 0, new Gtk::HSeparator, 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("please choose your CD space")), $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(gtkset_usize($combo_where_cd_time, 200, 20), $where_cd), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_(" Please check if you are using CDRW media")), $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(my $check_cdrw = new Gtk::CheckButton(), $where_cd), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please check if you want to erase your CDRW before")), $cdrw && $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(my $check_cdrw_erase = new Gtk::CheckButton(), $cdrw && $where_cd), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_(" Please check if you want to include\n install boot on your CD.")), $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(my $check_cd_with_install_boot = new Gtk::CheckButton(), $where_cd), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("please enter your CD Writer device name\n ex: 0,1,0")), $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_usize(gtkset_sensitive($cd_devive_entry = new Gtk::Entry(), $where_cd), 200, 20), ), ), ); foreach ([$check_cdrw_erase, \$cdrw_erase], [$check_cd_with_install_boot, \$cd_with_install_boot ]) { 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; ${$central_widget}->destroy(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_cdrw, $cdrw), toggled => sub { $cdrw = $cdrw ? 0 : 1; ${$central_widget}->destroy(); $current_widget->(); }); $custom_help = ""; $cd_devive_entry->set_text( $cd_devive ); $cd_devive_entry->signal_connect( 'changed', sub { $cd_devive = $cd_devive_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()}); $current_widget = \&advanced_where_cd; if ($previous_function) { $previous_widget =\&$previous_function; } else { $previous_widget =\&advanced_where; } $central_widget = \$box_where_cd; $up_box->show_all(); } sub advanced_where_tape { my ($previous_function) = @_, my $box_where_tape; my $button; my $adj = new Gtk::Adjustment 550.0, 1.0, 10000.0, 1.0, 5.0, 0.0; my ($pix_fs_map, $pix_fs_mask) = gtkcreate_png("filedialog"); gtkpack($advanced_box, $box_where_tape = gtkpack_(new Gtk::VBox(0, 6), 0, new Gtk::HSeparator, 0, my $check_where_tape = new Gtk::CheckButton( _(" Use tape to backup") ), 0, new Gtk::HSeparator, 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer device name where backup ")), $where_tape ), 1, new Gtk::VBox(0, 6), 0, gtkset_usize(gtkset_sensitive(my $save_device_tape_entry = new Gtk::Entry(), $where_tape), 200, 20), ), 0, new Gtk::VBox(0, 6), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer the maximum size\n allowed for Drakbackup ")), $where_tape), 1, new Gtk::VBox(0, 6), 0, gtkset_usize(gtkset_sensitive(my $spinner = new Gtk::SpinButton( $adj, 0, 0), $where_tape ), 200, 20), ), 0, gtkpack_(new Gtk::HBox(0,10), ), ), ); gtksignal_connect(gtkset_active($check_where_tape, $where_tape), toggled => sub { $where_tape = $where_tape ? 0 : 1; ${$central_widget}->destroy(); $current_widget->(); }); $custom_help = ""; $save_device_tape_entry->set_text( $save_device_tape ); $save_device_tape_entry->signal_connect( 'changed', sub { $save_device_tape = $save_device_tape_entry->get_text()}); $current_widget = \&advanced_where_tape; if ($previous_function) { $previous_widget =\&$previous_function; } else { $previous_widget =\&advanced_where; } $central_widget = \$box_where_tape; $up_box->show_all(); } sub advanced_where_hd { my ($previous_function) = @_, my $box_where_hd; my $button; my $adj = new Gtk::Adjustment 550.0, 1.0, 10000.0, 1.0, 5.0, 0.0; my ($pix_fs_map, $pix_fs_mask) = gtkcreate_png("ic82-dossier-32"); gtkpack($advanced_box, $box_where_hd = gtkpack_(new Gtk::VBox(0, 6), 0, new Gtk::HSeparator, 0, my $check_where_hd = new Gtk::CheckButton( _(" Use Hard Disk to backup") ), 0, new Gtk::HSeparator, 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer the directory to save: ")), $where_hd ), 1, new Gtk::VBox(0, 6), 0, gtkset_usize(gtkset_sensitive($save_path_entry = new Gtk::Entry(), $where_hd), 152, 20), 0, gtkset_sensitive($button = gtksignal_connect(new Gtk::Button(), clicked => sub { filedialog_where_hd();}), $where_hd ), ), 0, new Gtk::VBox(0, 6), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer the maximum size\n allowed for Drakbackup ")), $where_hd ), 1, new Gtk::VBox(0, 6), 0, gtkset_usize(gtkset_sensitive(my $spinner = new Gtk::SpinButton( $adj, 0, 0), $where_hd ), 200, 20), ), 0, gtkpack_(new Gtk::HBox(0,10), 1, new Gtk::VBox(0, 6), 0, gtkset_sensitive(my $check_where_hd_quota = new Gtk::CheckButton( _(" Use quota for backup files.")), $where_hd ), 0, new Gtk::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; }) } gtksignal_connect(gtkset_active($check_where_hd, $where_hd), toggled => sub { # $where_hd = $where_hd ? 0 : 1; $where_hd = 1; ${$central_widget}->destroy(); $current_widget->(); }); $custom_help = ""; $button->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_fs_map, $pix_fs_mask))); $save_path_entry->set_text( $save_path ); $save_path_entry->signal_connect( 'changed', sub { $save_path = $save_path_entry->get_text()}); $current_widget = \&advanced_where_hd; if ($previous_function) { $previous_widget =\&$previous_function; } else { $previous_widget =\&advanced_where; } $central_widget = \$box_where_hd; $up_box->show_all(); } sub advanced_where{ my $box_where; my ($pix_net_map, $pix_net_mask) = gtkcreate_png("ic82-network-40"); my ($pix_cd_map, $pix_cd_mask) = gtkcreate_png("ic82-CD-40"); my ($pix_hd_map, $pix_hd_mask) = gtkcreate_png("ic82-discdurwhat-40"); my ($pix_tape_map, $pix_tape_mask) = gtkcreate_png("ic82-tape-40"); gtkpack($advanced_box, $box_where = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtksignal_connect(my $button_where_net = new Gtk::Button(), clicked => sub { $box_where->destroy(); advanced_where_net(); }), 1, gtksignal_connect(my $button_where_cd = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_where_cd(); }), 1, gtksignal_connect(my $button_where_hd = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_where_hd(); }), 1, gtksignal_connect(my $button_where_tape = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_where_tape(); }), 1, new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $button_where_net->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_net_map, $pix_net_mask), new Gtk::Label(_(" Network ")), new Gtk::HBox(0, 5) )); $button_where_cd->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_cd_map, $pix_cd_mask), new Gtk::Label(_(" CDROM / DVDROM ")), new Gtk::HBox(0, 5) )); $button_where_hd->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_hd_map, $pix_hd_mask), new Gtk::Label(_(" HardDrive / NFS ")), new Gtk::HBox(0, 5) )); $button_where_tape->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_tape_map, $pix_tape_mask), new Gtk::Label(_(" Tape ")), new Gtk::HBox(0, 5) )); $custom_help = ""; $current_widget = \&advanced_where; $previous_widget =\&advanced_box; $central_widget = \$box_where; $up_box->show_all(); } sub advanced_when{ my $box_when; my $check_where_cd_daemon; my $check_where_hd_daemon; my $check_where_net_daemon; my ($pix_time_map, $pix_time_mask) = gtkcreate_png("ic82-when-40"); my $combo_when_space = new Gtk::Combo(); $combo_when_space->set_popdown_strings (_("hourly"),_("daily"),_("weekly"),_("monthly")); gtkpack($advanced_box, $box_when = gtkpack_(new Gtk::VBox(0, 15), 0, gtkpack_(new Gtk::HBox(0,10), 1, new Gtk::HBox(0,10), 1, new Gtk::Pixmap($pix_time_map, $pix_time_mask), 0, my $check_when_daemon = new Gtk::CheckButton( _(" Use daemon") ), 1, new Gtk::HBox(0,10), ), 0, new Gtk::HSeparator, 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please choose interval \nspace between each backup ")), $backup_daemon), 1, new Gtk::HBox(0,10), 0, gtkset_sensitive($combo_when_space, $backup_daemon), ), 0, new Gtk::HBox(0,10), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please choose\nmedia to backup. ")), $backup_daemon), 1, new Gtk::HBox(0,10), 0, gtkpack_(new Gtk::VBox(0,10), 0, gtkset_sensitive($check_where_cd_daemon = new Gtk::CheckButton(_(" Use CD/DVDROM with daemon")), $backup_daemon), 0, gtkset_sensitive($check_where_hd_daemon = new Gtk::CheckButton( _(" Use Hard Drive with daemon")), $backup_daemon), 0, gtkset_sensitive($check_where_net_daemon = new Gtk::CheckButton( _(" Use Network with daemon")), $backup_daemon), ), ), 0, new Gtk::HSeparator, 1, gtkset_sensitive(new Gtk::Label(_("Please be careful that cron deamon is include on your services. ")), $backup_daemon), ), ); foreach ([$check_where_cd_daemon, \$cd_daemon], [$check_where_hd_daemon, \$hd_daemon], [$check_where_net_daemon, \$net_daemon]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], ${$ref}), toggled => sub { ${$ref} = ${$ref} ? 0 : 1; }) } gtksignal_connect(gtkset_active($check_when_daemon, $backup_daemon), toggled => sub { $backup_daemon = $backup_daemon ? 0 : 1; ${$central_widget}->destroy(); advanced_when(); }); $custom_help = ""; $combo_when_space->entry->set_text( $when_space ); $combo_when_space->entry->signal_connect( 'changed', sub { $when_space = $combo_when_space->entry->get_text(); print $when_space."\n";}); $current_widget = \&advanced_when; $previous_widget =\&advanced_box; $central_widget = \$box_when; $up_box->show_all(); } sub advanced_options{ my $box_options; my ($pix_options_map, $pix_options_mask) = gtkcreate_png("ic82-moreoption-40"); gtkpack($advanced_box, $box_options = gtkpack_(new Gtk::VBox(0, 15), 0, gtkpack_(new Gtk::HBox(0,10), 1, new Gtk::VBox(0,10), 1, new Gtk::Pixmap($pix_options_map, $pix_options_mask), 1, _("Please choose correct options to backup. "), 1, new Gtk::VBox(0,10), ), 0, new Gtk::HSeparator, 0, gtkpack_(new Gtk::VBox(0,10), 0, my $check_tar_bz2 = new Gtk::CheckButton( _(" Use Tar and bzip2 ( very slow) [please be careful if you\n (un)select this option all your old backups will be deleted ]") ), 0, gtkset_sensitive(my $check_backupignore = new Gtk::CheckButton( _(" Use .backupignore files")), 0), ), ), ); foreach ([$check_tar_bz2, \$comp_mode], [$check_backupignore, \$backupignore]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], ${$ref}), toggled => sub { ${$ref} = ${$ref} ? 0 : 1; }) } $custom_help = "options"; $current_widget = \&advanced_options; $previous_widget =\&advanced_box; $central_widget = \$box_options; $up_box->show_all(); } sub advanced_box{ my $box_adv; my ($pix_hd_map, $pix_hd_mask) = gtkcreate_png("ic82-discdurwhat-40"); my ($pix_time_map, $pix_time_mask) = gtkcreate_png("ic82-when-40"); my ($pix_net_map, $pix_net_mask) = gtkcreate_png("ic82-where-40"); my ($pix_options_map, $pix_options_mask) = gtkcreate_png("ic82-moreoption-40"); gtkpack($advanced_box, $box_adv = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtksignal_connect(my $button_what = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_what(); }), 1, gtksignal_connect(my $button_where = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_where(); }), 1, gtksignal_connect(my $button_when = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_when(); }), 1, gtksignal_connect(my $button_options = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); advanced_options();}), 1, new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $button_what->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_hd_map, $pix_hd_mask), new Gtk::Label(_(" What ")), new Gtk::HBox(0, 5) )); $button_where->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_net_map, $pix_net_mask), new Gtk::Label(_(" Where ")), new Gtk::HBox(0, 5) )); $button_when->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_time_map, $pix_time_mask), new Gtk::Label(_(" When ")), new Gtk::HBox(0, 5) )); $button_options->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_options_map, $pix_options_mask), new Gtk::Label(_(" More Options")), new Gtk::HBox(0, 5) )); $custom_help = ""; $previous_widget =\&interactive_mode_box; $current_widget = \&advanced_box; $central_widget = \$box_adv; $up_box->show_all(); } ################################################ WIZARD ################################################ sub wizard_step3 { my $box2; my $text = new Gtk::Text(undef, undef); system_state(); gtktext_insert($text, $system_state); button_box_restore_main(); gtkpack($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, gtkpack_(new Gtk::VBox(0,10), 0, _(" Drakbackup Configuration "), 1, createScrolledWindow($text), ), ), ); button_box_wizard_end(); $custom_help = ""; $central_widget = \$box2; $current_widget = \&wizard_step3; $previous_widget =\&wizard_step2; $up_box->show_all(); } sub wizard_step2 { my $box2; gtkpack($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 0, _("Please choose where you want to backup"), 0, gtkpack_(new Gtk::HBox(0, 15), 0, my $check_wizard_hd = new Gtk::CheckButton(_("on Hard Drive")), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(gtksignal_connect(new Gtk::Button(_("Configure it")), clicked => sub { ${$central_widget}->destroy(); advanced_where_hd(\&wizard_step2); }), $where_hd ), ), 0, gtkpack_(new Gtk::HBox(0, 15), 0, my $check_wizard_net = new Gtk::CheckButton(_("across Network")), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(gtksignal_connect(new Gtk::Button(_("Configure it")), clicked => sub { ${$central_widget}->destroy(); advanced_where_net(\&wizard_step2); }), $where_net ), ), 0, gtkpack_(new Gtk::HBox(0, 15), 0, my $check_wizard_cd = new Gtk::CheckButton(_("on CDROM")), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(gtksignal_connect(new Gtk::Button(_("Configure it")), clicked => sub { ${$central_widget}->destroy(); advanced_where_cd(\&wizard_step2); }), $where_cd ), ), 0, gtkpack_(new Gtk::HBox(0, 15), 0, my $check_wizard_tape = new Gtk::CheckButton(_("on Tape Device")), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(gtksignal_connect(new Gtk::Button(_("Configure it")), clicked => sub { ${$central_widget}->destroy(); advanced_where_tape(\&wizard_step2); }), $where_tape), ), 1, new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $where_net = $where_net_ssh || $where_net_ftp; foreach ([$check_wizard_hd, \$where_hd], [$check_wizard_cd, \$where_cd], [$check_wizard_net, \$where_net], [$check_wizard_tape, \$where_tape]) { 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; } if(!$where_net) {$where_net_ssh = 0; $where_net_ftp = 0; } else {$where_net_ftp = 1;} ${$central_widget}->destroy(); wizard_step2(); }) } if (!$where_hd && !$where_cd && !$where_net) { $next_widget = \&message_noselect_box; } else { $next_widget = \&wizard_step3; } button_box_wizard(); $custom_help = ""; $central_widget = \$box2; $current_widget = \&wizard_step2; $previous_widget =\&wizard; $up_box->show_all(); } sub wizard { my $box2; gtkpack($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 0, _("Please choose that you want to backup"), 0, my $check_wizard_sys = new Gtk::CheckButton(_("Backup system")), 0, my $check_wizard_user = new Gtk::CheckButton(_("Backup Users")), 0, gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 0, gtksignal_connect(new Gtk::Button(_("Select user manually")), clicked => sub { ${$central_widget}->destroy(); advanced_what_user(\&wizard); }), ), 1, new Gtk::VBox(0, 5), ), 1, new Gtk::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 ) { $next_widget = \&wizard_step2; } else { $next_widget = \&message_noselect_what_box; } button_box_wizard(); $custom_help = ""; $central_widget = \$box2; $current_widget = \&wizard; $previous_widget =\&interactive_mode_box; $up_box->show_all(); } ################################################ RESTORE ################################################ sub find_backup_to_restore { # fixme: # faire test existance cd # faire reponse si non existance de $path_to_find_restore my @list_backup = (); my @list_backup_tmp2 = (); my $to_put; @sys_backuped = (); my @list_backup_tmp; my @user_backuped_tmp; @user_backuped = (); -d $path_to_find_restore and my @list_backup_tmp2 = all($path_to_find_restore); foreach (@list_backup_tmp2) { s/\_base//gi; s/\_incr//gi; push @list_backup , $_; } if (grep /^backup_other/, @list_backup) {$other_backuped = 1;} if (grep /^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; grep ( /^$nom$/, @user_list_backuped) or push @user_list_backuped, $nom; } } sub system_state { $system_state = (); if ($cfg_file_exist) { $system_state .= _("\nBackup Sources: \n"); $backup_sys and $system_state .= _("\n- System Files:\n"); $backup_sys and $system_state .= _("\t\t$_\n") foreach @sys_files; $backup_user and $system_state .= _("\n- Users Files:\n"); $backup_user and $system_state .= _("\t\t$_\n") foreach @user_list; @list_other and $system_state .= _("\n- Other Files:\n"); @list_other and $system_state .= _("\t\t$_\n") foreach @list_other; $system_state .= _("\n- Path to save backups: $save_path\n"); $system_state .= _("\n- Options:\n"); $backup_sys or $system_state .= _("\tDo not include System Files\n"); if ($comp_mode) { $system_state .= _("\tBackups use tar and bzip2\n "); } else { $system_state .= _("\tBackups use tar and gzip\n"); } } else {$system_state = _("No configuration please click Wizard or Advanced.\n")} } sub restore_state { $restore_state = _("List of data to restore:\n\n"); if ($restore_sys) { $restore_state .= "- Restore System Files.\n" } if ($restore_user) { $restore_state .= "- Restore Users 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; 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 @list_backup = (); my @list_tmp = (); -d $path_to_find_restore and my @list_backup_tmp2 = all($path_to_find_restore); foreach (@list_backup_tmp2) { s/\_base//gi; s/\_incr//gi; push @list_backup , $_; } foreach my $var_tmp (@user_list_backuped) { my $more_recent = (split( ' ', select_most_recent_selected_of($var_tmp)))[0]; print "more_recent: $more_recent\n"; foreach (grep /^backup_user_$var_tmp/, sort @list_backup) { s/.tar.gz//gi; s/.tar.bz2//gi; if ($more_recent) { print "to compare $more_recent avec $_\n"; if ( $_ =~ /$more_recent/ ) { print "egalite ....\n"; push @list_tmp , $_; next; } else { push @list_tmp , $_;} } } print "______________________ end\n"; } print "tmp_list : $_ \n" foreach (@list_tmp); } sub restore_backend { my $untar_cmd; if (grep /tar.gz$/, all($path_to_find_restore)) { $untar_cmd = 0; } else { $untar_cmd = 1; } select_user_data_to_restore(); if ($restore_user) { # $untar_cmd or system(" echo 'user: $_' && cd /tmp && tar xfz $path_to_find_restore/backup_user_$_.tar.gz -C $restore_path") foreach @user_list_to_restore; # $untar_cmd and system("echo 'user: $_' && cd /tmp && /usr/bin/bzip2 -cd $path_to_find_restore/backup_user_$_.tar.bz2 | tar xf -C $restore_path ") foreach @user_list_to_restore; # print "user list too restore : $_\n"foreach @user_list_to_restore2; } ## fixme if ($restore_sys) { # $untar_cmd or system("echo backup_sys && cd /tmp && tar xfz $path_to_find_restore/backup_sys.tar.gz -C $restore_path "); # $untar_cmd and system("echo backup_sys cd /tmp && /usr/bin/bzip2 -cd $path_to_find_restore/backup_sys.tar.bz2 | tar xf -C $restore_path "); # print " restore sys\n"; } ## fixme if ($restore_other) { # $untar_cmd or system("echo backup_other && cd /tmp && tar xfz $path_to_find_restore/backup_other.tar.gz -C $restore_path "); # $untar_cmd and system("echo backup_other && cd /tmp && /usr/bin/bzip2 -cd $path_to_find_restore/backup_other.tar.bz2 | tar xf -C $restore_path "); # print "restore other \n"; } print "End of restore\n"; } 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(); build_backup_files(); read_conf_file(); $table->destroy(); } restore_do2(); } sub restore_do2 { my $do_restore; my $button_restore; my $text = new Gtk::Text(undef, undef); restore_state(); gtktext_insert($text, $restore_state); button_box_restore_main(); gtkpack($advanced_box, $do_restore = gtkpack_(new Gtk::VBox(0,10), 0, _(" Restore Configuration "), 1, createScrolledWindow($text), ), ); button_box_restore_end(); $previous_widget =\&restore_box; $custom_help = "restore"; $current_widget = \&restore_do2; $central_widget = \$do_restore; $up_box->show_all(); } sub restore_step_other { my $retore_step_other; my $text = new Gtk::Text(undef, undef); my $other_rest = cat_("$path_to_find_restore/list_other"); gtktext_insert($text, $other_rest); gtkpack($advanced_box, $retore_step_other = gtkpack_(new Gtk::VBox(0,10), 1, new Gtk::VBox(0,10), 1, createScrolledWindow($text), 0, my $check_restore_other_sure = new Gtk::CheckButton(_(" Sure to restore the other files .")), 1, new Gtk::VBox(0,10), ), ); foreach ([$check_restore_other_sure, \$restore_other]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], ${$ref}), toggled => sub { ${$ref} = ${$ref} ? 0 : 1; }) } $next_widget = \&restore_do; $previous_widget = \&restore_step2; $custom_help = "restore"; $current_widget = \&restore_step_other; $central_widget = \$retore_step_other; $up_box->show_all(); } my %check_user_to_restore; sub restore_step_user { my $retore_step_user; my @tmp_list = sort @user_backuped; # @user_list_to_restore2 = sort @user_backuped; @user_backuped = @tmp_list; #= @user_list_to_restore2; gtkpack($advanced_box, $retore_step_user = gtkpack_(new Gtk::VBox(0,10), 0, new Gtk::VBox(0,10), 0, _("User list to restore (only the more recent date per user is important)"), 1, createScrolledWindow( gtkpack__(new Gtk::VBox(0,0), map { my @name_l = split(/,/, $_); my $name_complet = $_; my @user_list_tmp = (); my $name = $name_l[0]; my $b = new Gtk::CheckButton($name_complet); if ( grep $name_complet, @user_list_to_restore2) { gtkset_active($b, 1); } else { gtkset_active($b, 0); } $b->signal_connect(toggled => sub { if ($check_user_to_restore{$name_complet}[1] ) { $check_user_to_restore{$name_complet}[1] = 0; if (!member(/$name_complet/, @user_list_to_restore2) ) { push @user_list_to_restore2, $name_complet;} } else { $check_user_to_restore{$name_complet}[1] = 1; foreach (@user_list_to_restore2) { if ($name_complet ne $_) { push @user_list_tmp, $_; } } @user_list_to_restore2 = @user_list_tmp; } }); $b } (@user_backuped) ), ), ), ); if ($restore_other) { $next_widget = \&restore_step_other;} else{ $next_widget = \&restore_do;} $custom_help = "restore"; $current_widget = \&restore_step_user; $central_widget = \$retore_step_user; $up_box->show_all(); } sub restore_step_sys { my $restore_step_sys; my $combo_restore_step_sys = new Gtk::Combo(); $combo_restore_step_sys->set_popdown_strings (@sys_backuped); gtkpack($advanced_box, $restore_step_sys = gtkpack_(new Gtk::VBox(0,10), 1, new Gtk::VBox(0,10), 0, my $check_backup_before = new Gtk::CheckButton(_(" Backup the system files before.")), 0, gtkpack_(new Gtk::HBox(0,10), 1, _("please choose the date to restore"), 0, $combo_restore_step_sys, 0, new Gtk::HBox(0,10), ), 1, new Gtk::VBox(0,10), ), ); $combo_restore_step_sys->entry->signal_connect( 'changed', sub { $restore_step_sys_date = $combo_restore_step_sys->entry->get_text(); print $restore_step_sys_date. "\n"; }); $combo_restore_step_sys->entry->set_text($restore_step_sys_date); if ($restore_user) { $next_widget = \&restore_step_user;} elsif ($restore_other){ $next_widget = \&restore_step_other;} else{ $next_widget = \&restore_do;} $custom_help = "restore"; $current_widget = \&restore_step_sys; $central_widget = \$restore_step_sys; $up_box->show_all(); } sub restore_other_media_hd { my ($previous_function) = @_, my $box_where_hd; my $button; my $adj = new Gtk::Adjustment 550.0, 1.0, 10000.0, 1.0, 5.0, 0.0; my ($pix_fs_map, $pix_fs_mask) = gtkcreate_png("filedialog"); gtkpack($advanced_box, $box_where_hd = gtkpack_(new Gtk::VBox(0, 6), 0, new Gtk::HSeparator, 0, my $check_where_hd = new Gtk::CheckButton( _(" Use Hard Disk to backup") ), 0, new Gtk::HSeparator, 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer the directory to save: ")), $where_hd ), 1, new Gtk::VBox(0, 6), 0, gtkset_usize(gtkset_sensitive($save_path_entry = new Gtk::Entry(), $where_hd), 152, 20), 0, gtkset_sensitive($button = gtksignal_connect(new Gtk::Button(), clicked => sub { filedialog_where_hd();}), $where_hd ), ), 0, new Gtk::VBox(0, 6), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer the maximum size\n allowed for Drakbackup ")), $where_hd ), 1, new Gtk::VBox(0, 6), 0, gtkset_usize(gtkset_sensitive(my $spinner = new Gtk::SpinButton( $adj, 0, 0), $where_hd ), 200, 20), ), 0, gtkpack_(new Gtk::HBox(0,10), 1, new Gtk::VBox(0, 6), 0, gtkset_sensitive(my $check_where_hd_quota = new Gtk::CheckButton( _(" Use quota for backup files.")), $where_hd ), 0, new Gtk::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; }) } gtksignal_connect(gtkset_active($check_where_hd, $where_hd), toggled => sub { $where_hd = $where_hd ? 0 : 1; ${$central_widget}->destroy(); $current_widget->(); }); $custom_help = ""; $button->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_fs_map, $pix_fs_mask))); $save_path_entry->set_text( $save_path ); $save_path_entry->signal_connect( 'changed', sub { $save_path = $save_path_entry->get_text()}); $current_widget = \&advanced_where_hd; if ($previous_function) { $previous_widget =\&$previous_function; } else { $previous_widget =\&advanced_where; } $central_widget = \$box_where_hd; $up_box->show_all(); } sub restore_find_net { my ($previous_function) = @_, my $box_where_net; gtkpack($advanced_box, $box_where_net = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, new Gtk::VBox(0,10), 1, gtksignal_connect(new Gtk::Button(_(" FTP Connexion")), clicked => sub { $box_where_net->destroy(); if ($previous_function ) { advanced_where_net_ftp(\&$previous_function); } else { advanced_where_net_ftp(); }}), 1, gtksignal_connect(new Gtk::Button(_(" Secure Connexion ")), clicked => sub { $box_where_net->destroy(); if ($previous_function ) { advanced_where_net_ssh(\&$previous_function); } else { advanced_where_net_ssh(); }}), 1, new Gtk::VBox(0, 5), 1, new Gtk::VBox(0,10), ), 1, new Gtk::VBox(0, 5), ), ); if ($previous_function) { $previous_widget =\&$previous_function; } else { $previous_widget =\&advanced_where; } $custom_help = ""; $current_widget = \&advanced_where_net; $central_widget = \$box_where_net; $up_box->show_all(); } sub restore_other_media { my $box_find_restore; my $button; my $adj = new Gtk::Adjustment 550.0, 1.0, 10000.0, 1.0, 5.0, 0.0; my ($pix_fs_map, $pix_fs_mask) = gtkcreate_png("filedialog"); gtkpack($advanced_box, $box_find_restore = gtkpack_(new Gtk::VBox(0, 6), 0, new Gtk::HSeparator, 0, my $check_other_media_hd = new Gtk::CheckButton( _(" Use Hard Disk to find backups") ), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer the directory to find backup ")), $other_media_hd ), 1, new Gtk::VBox(0, 6), 0, gtkset_usize(gtkset_sensitive($restore_find_path_entry = new Gtk::Entry(), $other_media_hd), 152, 20), 0, gtkset_sensitive($button = gtksignal_connect(new Gtk::Button(), clicked => sub { filedialog_restore_find_path();}), $other_media_hd ), ), 1, new Gtk::VBox(0, 6), 0, new Gtk::HSeparator, 0, my $check_other_media_net = new Gtk::CheckButton( _(" Use Network to find backups") ), 0, new Gtk::VBox(0, 6), 1, gtkpack(new Gtk::HBox(0,10), new Gtk::VBox(0, 6), gtkset_sensitive(gtksignal_connect(new Gtk::Button("Network"), clicked => sub { ${$central_widget}->destroy(); restore_find_net(\&restore_other_media);}), !$other_media_hd ), new Gtk::VBox(0, 6), ), 1, new Gtk::VBox(0, 6), 0, new Gtk::HSeparator, 0, new Gtk::VBox(0, 6), ), ); gtksignal_connect(gtkset_active($check_other_media_hd, $other_media_hd), toggled => sub { $other_media_hd = $other_media_hd ? 0 : 1; ${$central_widget}->destroy(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_other_media_net, !$other_media_hd), toggled => sub { $other_media_hd = $other_media_hd ? 0 : 1; ${$central_widget}->destroy(); $current_widget->(); }); $button->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_fs_map, $pix_fs_mask))); $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()}); $current_widget = \&restore_other_media; $central_widget = \$box_find_restore; $previous_widget =\&restore_step2; $custom_help = "other_media"; $up_box->show_all(); } sub restore_step2 { my $retore_step2; gtkpack($advanced_box, $retore_step2 = gtkpack_(new Gtk::VBox(0,10), 1, new Gtk::VBox(0,10), 1, new Gtk::VBox(0,10), 0, gtkpack_(new Gtk::HBox(0,10), 0, my $check_restore_other_src = new Gtk::CheckButton(_("select an other media to find backups")), 1, new Gtk::HBox(0,10), 0, gtkset_sensitive(gtksignal_connect(new Gtk::Button(_("Other Media")), clicked => sub { ${$central_widget}->destroy(); restore_other_media(); }), $restore_other_src ), ), 0, my $check_restore_sys = new Gtk::CheckButton(_("Restore system")), 0, my $check_restore_user = new Gtk::CheckButton(_("Restore Users")), 0, my $check_restore_other = new Gtk::CheckButton(_("Restore Other")), 0, gtkpack_(new Gtk::HBox(0,10), 0, my $check_restore_other_path = new Gtk::CheckButton(_("select path to restore (instead of / ) ")), 1, new Gtk::HBox(0,10), 0, gtkset_sensitive(my $restore_path_entry = new Gtk::Entry(), $restore_other_path), ), 0, gtkset_sensitive(my $check_backup_bef_restore = new Gtk::CheckButton(_("do new backup before restore (only for incremental backups.)")), $backup_sys_versions || $backup_user_versions ), 1, new Gtk::VBox(0,10), ), ); foreach ([$check_restore_sys, \$restore_sys], [$check_backup_bef_restore, \$backup_bef_restore], [$check_restore_user, \$restore_user], [$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; ${$central_widget}->destroy(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_restore_other_src, $restore_other_src), toggled => sub { $restore_other_src = $restore_other_src ? 0 : 1; ${$central_widget}->destroy(); $current_widget->(); }); 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(); }); $custom_help = "restore"; $previous_widget =\&restore_box; $current_widget = \&restore_step2; $central_widget = \$retore_step2; $up_box->show_all(); } sub restore_box { my $retore_box; my $retore_box3; my $check_restore_sys; my $check_restore_user; my $check_restore_other; $path_to_find_restore = $save_path; find_backup_to_restore(); button_box_restore_main(); if ($other_backuped || $sys_backuped || @user_backuped) { gtkpack($advanced_box, $retore_box = gtkpack_(new Gtk::HBox(0,1), 1, new Gtk::VBox(0,10), 1, gtkpack_(new Gtk::VBox(0,10), 1, new Gtk::VBox(0,10), 1, new Gtk::VBox(0,10), 1, gtksignal_connect(new Gtk::Button(_("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(new Gtk::Button(_("Custom Restore")), clicked => sub { $retore_box->destroy(); button_box_restore(); restore_step2(); }), 1, new Gtk::VBox(0,10), 1, new Gtk::VBox(0,10), ), 1, new Gtk::HBox(0,10), ), ); } else { gtkpack($advanced_box, $retore_box = gtkpack_(new Gtk::HBox(0,1), message_norestorefile_box(), ), ), } $custom_help = "restore"; $previous_widget =\&interactive_mode_box; $current_widget = \&restore_box; $central_widget = \$retore_box; $up_box->show_all(); } ################################################ BUTTON_BOX ################################################ sub button_box_adv { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk::HButtonBox, 0, gtksignal_connect(new Gtk::Button(_(" Cancel ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), 0, gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&$current_widget,$custom_help ); }), 1, new Gtk::HBox(0, 1), 0, gtksignal_connect(new Gtk::Button(_(" Previous ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), 0, gtksignal_connect(new Gtk::Button(_(" Save ")), clicked => sub { ${$central_widget}->destroy(); save_conf_file(); $previous_widget->(); }), ), ); } sub button_box_restore_main { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(gtkpack_(new Gtk::HButtonBox, 0, gtksignal_connect(new Gtk::Button(_(" Cancel ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), 0, gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&$current_widget, $custom_help); }), 1, new Gtk::HBox(0, 1), 0, gtksignal_connect(new Gtk::Button(_(" Previous ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), 0, gtksignal_connect(new Gtk::Button(_(" Ok ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), ), ), ); } sub button_box_backup_end { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk::HButtonBox, 0, gtksignal_connect(new Gtk::Button(_(" Cancel ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), 0, gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&$current_widget,$custom_help ); }), 1, new Gtk::HBox(0, 1), 0, gtksignal_connect(new Gtk::Button(_(" Previous ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), 0, gtksignal_connect(new Gtk::Button(_(" Build Backup ")), clicked => sub { ${$central_widget}->destroy(); build_backup_status(); build_backup_files(); }), ), ); } sub button_box_wizard_end { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk::HButtonBox, 0, gtksignal_connect(new Gtk::Button(_(" Cancel ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), 0, gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&$current_widget,$custom_help ); }), 1, new Gtk::HBox(0, 1), 0, gtksignal_connect(new Gtk::Button(_(" Previous ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), 0, gtksignal_connect(new Gtk::Button(_(" Save ")), clicked => sub { ${$central_widget}->destroy(); save_conf_file(); interactive_mode_box(); }), ), ); } sub button_box_restore_end { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk::HButtonBox, 0, gtksignal_connect(new Gtk::Button(_(" Cancel ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), 0, gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&$current_widget,$custom_help ); }), 1, new Gtk::HBox(0, 1), 0, gtksignal_connect(new Gtk::Button(_(" Previous ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), 0, gtksignal_connect(new Gtk::Button(_(" Restore ")), clicked => sub { ${$central_widget}->destroy(); restore_backend(); }), ), ); } sub button_box_build_backup_end { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk::HButtonBox, 1, new Gtk::HBox(0, 5), 1, new Gtk::HBox(0, 5), 0, gtksignal_connect(new Gtk::Button(_(" Ok ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), ), ); } sub button_box_build_backup { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk::HButtonBox, 1, gtksignal_connect(new Gtk::Button(_(" Cancel ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), 1, gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&$current_widget,$custom_help); }), 1, new Gtk::HBox(0, 0), 0, gtksignal_connect(new Gtk::Button(_(" Previous ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), 1, gtksignal_connect(new Gtk::Button(_(" Next ")), clicked => sub { ${$central_widget}->destroy(); $next_widget->(); }), ), ); } sub button_box_restore { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk::HButtonBox, 1, gtksignal_connect(new Gtk::Button(_(" Cancel ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), 1, gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&$current_widget,$custom_help); }), 1, new Gtk::HBox(0, 0), 0, gtksignal_connect(new Gtk::Button(_(" Previous ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), 1, gtksignal_connect(new Gtk::Button(_(" Next ")), clicked => sub { ${$central_widget}->destroy(); $next_widget->(); }), ), ); } sub button_box_wizard { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk::HButtonBox, 1, gtksignal_connect(new Gtk::Button(_(" Cancel ")), clicked => sub { ${$central_widget}->destroy(); interactive_mode_box(); }), 1, gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&$current_widget,$custom_help); }), 1, new Gtk::HBox(0, 0), 0, gtksignal_connect(new Gtk::Button(_(" Previous ")), clicked => sub { ${$central_widget}->destroy(); $previous_widget->(); }), 1, gtksignal_connect(new Gtk::Button(_(" Next ")), clicked => sub { ${$central_widget}->destroy(); $next_widget->(); }), ), ); } sub button_box_main { $button_box_tmp->destroy(); gtkpack($button_box, $button_box_tmp = gtkpack(gtkset_layout(new Gtk::HButtonBox, -start), gtksignal_connect(new Gtk::Button(_("close")), clicked => sub { Gtk->main_quit() }), gtksignal_connect(new Gtk::Button(_(" Help ")), clicked => sub { ${$central_widget}->destroy(); adv_help(\&interactive_mode_box,$custom_help) }), ), ); } ################################################ MESSAGES ################################################ sub message_norestorefile_box { $box2->destroy(); my ($pix_warn_map, $pix_warn_mask) = gtkcreate_png('warning'); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack(new Gtk::HBox(0, 15), new Gtk::VBox(0, 5), new Gtk::Pixmap($pix_warn_map, $pix_warn_mask), _("Please Build backup before to restore it...\n or verify that your path to save is correct."), new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); button_box_restore_main(); $central_widget = \$box2; $up_box->show_all(); } sub message_norestore_box { $box2->destroy(); my ($pix_warn_map, $pix_warn_mask) = gtkcreate_png('warning'); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack(new Gtk::HBox(0, 15), new Gtk::VBox(0, 5), new Gtk::Pixmap($pix_warn_map, $pix_warn_mask), _(" Please check data to restore..."), new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); button_box_restore_main(); $central_widget = \$box2; $up_box->show_all(); } sub message_noselect_box { $box2->destroy(); my ($pix_warn_map, $pix_warn_mask) = gtkcreate_png('warning'); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack(new Gtk::HBox(0, 15), new Gtk::VBox(0, 5), new Gtk::Pixmap($pix_warn_map, $pix_warn_mask), _(" Please check way where backup..."), new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $previous_widget = \&wizard_step2; $next_widget = \&wizard_step2; $central_widget = \$box2; $up_box->show_all(); } sub message_noselect_what_box { $box2->destroy(); my ($pix_warn_map, $pix_warn_mask) = gtkcreate_png('warning'); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack(new Gtk::HBox(0, 15), new Gtk::VBox(0, 5), new Gtk::Pixmap($pix_warn_map, $pix_warn_mask), _(" Please check data to backup..."), new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $previous_widget = \&wizard; $next_widget = \&wizard; $central_widget = \$box2; $up_box->show_all(); } sub message_noconf_box { $box2->destroy(); my ($pix_warn_map, $pix_warn_mask) = gtkcreate_png('warning'); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack(new Gtk::HBox(0, 15), new Gtk::VBox(0, 5), new Gtk::Pixmap($pix_warn_map, $pix_warn_mask), _(" No configuration file found \nplease click Wizard or Advanced."), new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); button_box_restore_main(); $central_widget = \$box2; $up_box->show_all(); } sub message_underdevel { $box2->destroy(); my ($pix_warn_map, $pix_warn_mask) = gtkcreate_png('warning'); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack(new Gtk::HBox(0, 15), new Gtk::VBox(0, 5), new Gtk::Pixmap($pix_warn_map, $pix_warn_mask), _(" Under Devel ... please wait."), new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $central_widget = \$box2; $up_box->show_all(); } ################################################ BUILD_BACKUP ################################################ sub progress { my ($progressbar, $incr, $label_text) = @_; my($new_val) = $progressbar->get_current_percentage; $new_val += $incr; if ($new_val > 1) {$new_val = 1} $progressbar->update($new_val); $progressbar->{label}->set($label_text); Gtk->main_iteration while Gtk->events_pending; } sub find_backup_to_put_on_cd { my @list_backup_tmp; my @data_backuped_tmp; @data_backuped = (); -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 /^backup_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 /^backup_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 Gtk::ProgressBar; $pbar1 = new Gtk::ProgressBar; $pbar2 = new Gtk::ProgressBar; $pbar3 = new Gtk::ProgressBar; button_box_build_backup_end(); gtkpack($advanced_box, $table = create_packtable({ col_spacings => 10, row_spacings => 5}, [""], [""], [""], [""], [""], [""], [""], [""], [_("Backup system files")], [ $pbar, $pbar->{label} = new Gtk::Label(' ' )], [_("Backup user files") ], [$pbar1,$pbar1->{label} = new Gtk::Label(' ' ) ], [_("Backup other files")], [ $pbar2, $pbar2->{label} = new Gtk::Label(' ' ) ], [_("Total Progress")], [$pbar3,$pbar3->{label} = new Gtk::Label(' ' ) ], ), ); $custom_help = "options"; $central_widget = \$table; $up_box->show_all(); Gtk->main_iteration while Gtk->events_pending; } sub build_backup_box_see_conf { my $box2; my $text = new Gtk::Text(undef, undef); system_state(); gtktext_insert($text, $system_state); button_box_restore_main(); gtkpack($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, gtkpack_(new Gtk::VBox(0,10), 0, _(" Drakbackup Configuration "), 1, createScrolledWindow($text), ), ), ); button_box_backup_end(); $custom_help = ""; $central_widget = \$box2; $current_widget = \&build_backup_box_see_conf; $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 @user_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"); } my %check_data_to_backup_cd; sub build_backup_cd_select_data { my $retore_step_user; find_backup_to_put_on_cd(); @user_list_to_build_on_cd = sort @data_backuped; @data_backuped = @user_list_to_build_on_cd; gtkpack($advanced_box, $retore_step_user = gtkpack_(new Gtk::VBox(0,10), 0, new Gtk::VBox(0,10), 0, _(" Data list to include on CDROM. "), 1, createScrolledWindow( gtkpack__(new Gtk::VBox(0,0), map { my $name = $_; my @user_list_tmp = (); my $b = new Gtk::CheckButton($name); if ( grep $name , @user_list_to_build_on_cd) { gtkset_active($b, 1); } else { gtkset_active($b, 0); } $b->signal_connect(toggled => sub { if ($check_data_to_backup_cd{$name}[1] ) { $check_data_to_backup_cd{$name}[1] = 0; if (!member( /$name$/, @user_list_to_build_on_cd) ) { push @user_list_to_build_on_cd, $name;} } else { $check_data_to_backup_cd{$name}[1] = 1; foreach (@user_list_to_build_on_cd) { if ($name ne $_) { push @user_list_tmp, $_; } } @user_list_to_build_on_cd = @user_list_tmp; } aff_total_tail(); }); $b } (@data_backuped) ), ), 0, new Gtk::HSeparator, 0, $label_tail = new Gtk::Label(" "), 0, new Gtk::HSeparator, ), ); aff_total_tail(); $next_widget = \&build_backup_box_see_conf; $custom_help = "restore"; $previous_widget = \&build_backup_cd_box; $current_widget = \&restore_step_user; $central_widget = \$retore_step_user; $up_box->show_all(); } sub build_backup_cd_box { my $box_build_backup_cd; my $combo_where_cd_time = new Gtk::Combo(); my $adj = new Gtk::Adjustment 4.0, 1.0, 10000.0, 1.0, 5.0, 0.0; $combo_where_cd_time->set_popdown_strings ("650","700", "750", "800"); button_box_build_backup(); gtkpack($advanced_box, $box_build_backup_cd = gtkpack_(new Gtk::VBox(0, 6), 0, my $check_where_cd = new Gtk::CheckButton( _(" Use CD/DVDROM to backup")), 0, new Gtk::HSeparator, 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please choose your CD space")), $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_usize(gtkset_sensitive($combo_where_cd_time, $where_cd), 100, 20), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please entrer the cd writer speed ")), $where_cd ), 1, new Gtk::VBox(0, 6), 0, gtkset_usize(gtkset_sensitive(my $spinner = new Gtk::SpinButton( $adj, 0, 0), $where_cd ), 100, 20), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please check if you are using CDRW media")), $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(my $check_cdrw = new Gtk::CheckButton(), $where_cd), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please check if you want to erase your CDRW before")), $cdrw && $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(my $check_cdrw_erase = new Gtk::CheckButton(), $cdrw && $where_cd), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please enter your CD Writer device name (ex: 0,1,0)")), $where_cd), 1, new Gtk::VBox(0, 5), 0, gtkset_usize(gtkset_sensitive($cd_devive_entry = new Gtk::Entry(), $where_cd), 100, 20), ), 0, new Gtk::VBox(0, 5), 0, gtkpack_(new Gtk::HBox(0,10), 0, gtkset_sensitive(new Gtk::Label(_("Please check if you want to include install boot on your CD.")), 0), 1, new Gtk::VBox(0, 5), 0, gtkset_sensitive(my $check_cd_with_install_boot = new Gtk::CheckButton(), 0), ), ), ); foreach ([$check_cdrw_erase, \$cdrw_erase], [$check_cd_with_install_boot, \$cd_with_install_boot ]) { 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; ${$central_widget}->destroy(); $current_widget->(); if($where_cd) { $next_widget = \&build_backup_cd_select_data;} else { $next_widget = \&build_backup_cd_box;} }); gtksignal_connect(gtkset_active($check_cdrw, $cdrw), toggled => sub { $cdrw = $cdrw ? 0 : 1; ${$central_widget}->destroy(); $current_widget->(); }); if($where_cd) { $next_widget = \&build_backup_cd_select_data;} else { $next_widget = \&build_backup_cd_box;} $cd_devive_entry->set_text( $cd_devive ); $cd_devive_entry->signal_connect( 'changed', sub { $cd_devive = $cd_devive_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()}); $current_widget = \&build_backup_cd_box; $previous_widget =\&build_backup_box; $central_widget = \$box_build_backup_cd; $up_box->show_all(); } sub build_backup_box { $box2->destroy(); my ($pix_cd_map, $pix_cd_mask) = gtkcreate_png("ic82-CD-40"); my ($pix_hd_map, $pix_hd_mask) = gtkcreate_png("ic82-discdurwhat-40"); my ($pix_options_map, $pix_options_mask) = gtkcreate_png("ic82-moreoption-40"); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtksignal_connect(my $button_from_conf_file = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); build_backup_box_see_conf(); }), 0, new Gtk::VBox(0, 5), 1, gtksignal_connect(my $button_on_cd = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); $where_cd = 1; build_backup_cd_box(); }), 0, new Gtk::VBox(0, 5), 1, gtksignal_connect(my $button_see_conf = new Gtk::Button(), clicked => sub { ${$central_widget}->destroy(); build_backup_box_see_conf(); }), 1, new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); $button_from_conf_file->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_hd_map, $pix_hd_mask), new Gtk::Label(_(" Backup Now from configuration file ")), new Gtk::HBox(0, 5) )); $button_on_cd->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_cd_map, $pix_cd_mask), new Gtk::Label(_(" Backup Now on CDROM ")), new Gtk::HBox(0, 5) )); $button_see_conf->add(gtkpack(new Gtk::HBox(0,10), new Gtk::Pixmap($pix_options_map, $pix_options_mask), new Gtk::Label(_(" View Backup Configuration. ")), new Gtk::HBox(0, 5) )); $custom_help = "options"; button_box_restore_main(); $central_widget = \$box2; $previous_widget = \&interactive_mode_box; $current_widget = \&build_backup_box; $up_box->show_all(); } ################################################ INTERACTIVE ################################################ sub interactive_mode_box { $box2->destroy(); read_conf_file(); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk::HBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtkpack_(new Gtk::VBox(0, 15), 1, new Gtk::VBox(0, 5), 1, gtksignal_connect(new Gtk::Button(_(" Wizard Configuration ")), clicked => sub { ${$central_widget}->destroy(); read_conf_file(); wizard(); }), 1, gtksignal_connect(new Gtk::Button(_(" Advanced Configuration ")), clicked => sub { button_box_adv(); ${$central_widget}->destroy(); advanced_box(); }), 1, gtksignal_connect(new Gtk::Button(_(" Backup Now ")), clicked => sub { ${$central_widget}->destroy(); if ($cfg_file_exist) { build_backup_box();} else { message_noconf_box();} }), 1, gtksignal_connect(new Gtk::Button(_(" Restore ")), clicked => sub {${$central_widget}->destroy(); restore_box();}), 1, new Gtk::VBox(0, 5), ), 1, new Gtk::VBox(0, 5), ), ); button_box_main(); $custom_help = "main"; $central_widget = \$box2; $up_box->show_all(); } sub interactive_mode { $interactive = 1; my $box; my $window1 = $::isEmbedded ? new Gtk::Plug ($::XID) : new Gtk::Window -toplevel; init Gtk; $window1->signal_connect (delete_event => sub { Gtk->exit(0) }); $window1->set_position(1); $window1->set_title(_("Drakbackup")); my ($pix_u_map, $pix_u_mask) = gtkcreate_png("BDO-drakebackup1"); read_conf_file(); gtkadd($window1, gtkpack(new Gtk::VBox(0,0), gtkpack(gtkset_usize($up_box = new Gtk::VBox(0, 5), 540, 400), $box = gtkpack_(new Gtk::VBox(0, 3), 0, new Gtk::Pixmap($pix_u_map, $pix_u_mask), 1, gtkpack_(new Gtk::HBox(0, 3), 1, gtkpack_(new Gtk::HBox(0, 15), 0, new Gtk::HBox(0, 5), 1, $advanced_box = gtkpack_(new Gtk::HBox(0, 15), 1, $box2 = gtkpack_(new Gtk::VBox(0, 15), ), ), 0, new Gtk::HBox(0, 5), ), ), 0, new Gtk::HSeparator, 0, $button_box = gtkpack(new Gtk::VBox(0, 15), $button_box_tmp = gtkpack(new Gtk::VBox(0, 0), ), ), ), ), ), ); interactive_mode_box(); $custom_help = "main"; button_box_main(); $central_widget = \$box2; $window1->show_all; $window1->realize; $window1->show_all(); Gtk->main; Gtk->exit(0); } ################################################ HELP & ABOUT ################################################ sub about { my $text = new Gtk::Text(undef, undef); my $about_box; gtkpack($up_box, $about_box = gtkpack_(new Gtk::VBox(0,10), 1, gtkpack_(new Gtk::HBox(0,0), 1, gtktext_insert(gtkset_editable($text, 1), _(" ")), 0, new Gtk::VScrollbar($text->vadj), ), 0, gtkadd(gtkset_layout(new Gtk::HButtonBox, -spread), gtksignal_connect(new Gtk::Button(_("OK")), clicked => sub { ${$central_widget}->destroy(); interactive_mode(); }), ), ) ); $central_widget = \$about_box; $up_box->show_all(); } sub adv_help { my ($function, $custom_help) = @_, my $text = new Gtk::Text(undef, undef); my $advanced_box_help; if ($custom_help eq "toto") { gtktext_insert($text, _("toto")); } elsif ($custom_help eq "options") { gtktext_insert($text, _("options description: In this step Drakbacup allow you to change: - the compression mode: if you check bzip2 compression, you will compress better than gzip your data (about 2-10 %). This options are not checked by default because this compression mode need more time ( about 1000% more). - the udpate mode: This options will update your backup, but this options are not really interesting because you need to decompress your backup before to update it. - the .backupignore mode: Like with cvs, Drakbackup will ignore all references included on .backupignore files in each directories. ex: \$> cat .backupignore *.o *~ ... ")); } elsif ($custom_help eq "what") { gtktext_insert($text, _("options description: - Backup system files: This options allow you to backup your /etc directory, which contain all configuration files please be carreful during restore step to not overwriting /etc/passwd /etc/group /etc/fstab - Backup User files: This option allow to select all users that you want to backup. To preserve disk space, it recommeded to not include browsers cache. - Backup Other files: This option allow to add more data to save. With the other backup it's not possible in moment to select select incremental backup. - Incremental Backups: The incremental backup is the most powerfull option to use backup, this option allow you to backup all your data the first time, and only the changed after. So you will be able during the restore step, to restore your data from a specified date. If you have not selected this options all old backups are deleted before each backup. ")); } elsif ($custom_help eq "restore") { gtktext_insert($text, _("restore description: Only the most recent date will be used ,because with incremental backups it is necesarry to restore one by one each older backups. So if you don't like to restore an user please unselect all his check box. Otherwise, you are able to select only one of this - Incremental Backups: The incremental backup is the most powerfull option to use backup, this option allow you to backup all your data the first time, and only the changed after. So you will be able during the restore step, to restore your data from a specified date. If you have not selected this options all old backups are deleted before each backup. ")); } elsif ($custom_help eq "main") { gtktext_insert($text, _(" Copyright (C) 2001 by MandrakeSoft (sdupont\@mandrakesoft.com) 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: Drakbacup is use 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) Drakbacup allow you to backup your system on: - Harddrive. - NFS. - CDROM (CDRW), DVDROM (with autoboot, rescue and autoinstall.). - FTP. - Rsync. - Webdav. - Tape. Drakbacup allow you to Restore your system on choosen directory. Per default all backup will be stored on your /var/drakbackup directory configuration file: /etc/drakconf/drakbackup/drakbakup.conf ")); } elsif ($custom_help eq "ftp") { gtktext_insert($text, _("options description: Please be careful when you are using ftp backup, because only backup already build are send on server. So in moment, you need to build backup on your hard drive before to send it. ")); } else { gtktext_insert($text, _(" Copyright (C) 2001 by MandrakeSoft (sdupont\@mandrakesoft.com) 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: Drakbacup is use 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) Drakbacup allow you to backup your system on: - Harddrive. - NFS. - CDROM (CDRW), DVDROM (with autoboot, rescue and autoinstall.). - FTP. - Rsync. - Webdav. - Tape. Drakbacup allow you to Restore your system on choosen directory. Per default all backup will be stored on your /var/drakbackup directory configuration file: /etc/drakconf/drakbackup/drakbakup.conf "));} gtkpack($advanced_box, $advanced_box_help = gtkpack_(new Gtk::VBox(0,10), 1, gtkpack_(new Gtk::HBox(0,0), 1, $text, 0, new Gtk::VScrollbar($text->vadj), ), 0, gtkadd(gtkset_layout(new Gtk::HButtonBox, -spread), gtksignal_connect(new Gtk::Button(_("OK")), clicked => sub { ${$central_widget}->destroy(); $function->(); }), ), ) ); $central_widget = \$advanced_box_help; $up_box->show_all(); } sub restore_help { my $text = new Gtk::Text(undef, undef); my $about_box; gtkpack($up_box, $about_box = gtkpack_(new Gtk::VBox(0,10), 1, gtkpack_(new Gtk::HBox(0,0), 1, gtktext_insert(gtkset_editable($text, 1), _(" Description: Drakbacup Restore Mode. Drakbacup allow to restore the system (etc, var files) from starup or on drakconf utility. system backup: backup_sys.tar.gz user backup backup_user_james.tar.gz backup_user_seb.tar.gz other directories backup_other.tar.gz ")), 0, new Gtk::VScrollbar($text->vadj), ), 0, gtkadd(gtkset_layout(new Gtk::HButtonBox, -spread), gtksignal_connect(new Gtk::Button(_("OK")), clicked => sub { ${$central_widget}->destroy(); restore(); }), ), ) ); $central_widget = \$about_box; $up_box->show_all(); } # _____________________________________________________________ DOCS ##### tester taille decompressee #(seb@lutin)[~]-% gzip -l old_drakbackup.tar.gz #compressed uncompr. ratio uncompressed_name # 128662 174080 26.1% old_drakbackup.tar #### tester integrite archive # idem pour bzip2 -t # (seb@lutin)[~]-% gzip -t drakbackup.tar.gz # # gzip: drakbackup.tar.gz: invalid compressed data--crc error # # gzip: drakbackup.tar.gz: invalid compressed data--length error # Comment récupérer la date du jour ? # Cf perldoc -f localtime # ($seconde,$minute,$heure,$jour_du_mois,$annee, # $jour_de_la_semaine,$jour_de_l _annee,$drapeau_heure_ete) = localtime(time); # Il faut ajouter 1900 a l'année pour une date correcte ($annee+=1900) et 1 au jour du mois pour obtenir une date correcte ($jour_du_mois++). # [Perl] Comment récupérer des informations sur un fichier ? # Cf perldoc -f stat # Exemple pour récupérer mtime (date de dernière modification du fichier) # my(@etat); my($fchier)="/tmp/toto"; # # Si le fichier existe on récupère des infos dessus # if (-e $fchier) {@etat=stat($fchier); } # # On convertit avec localtime la valeur de mtime. # my($date)= localtime($etat[9]); # print $date; #Telnet : En utilisant le package Net::Telnet # use strict; # use Net::Telnet; # use CGI qw/:standard :html3 :netscape escape unescape/; # use CGI::Carp qw/fatalsToBrowser/; # my $username="alian"; # my $passwd="password"; # my $HOST="indy.alianet"; # print header; # my $t = new Net::Telnet (Timeout=>undef) or die "Can't connect:$!"; # $t->open($HOST); # $t->login($username, $passwd); # my @lines = $t->cmd("/ma/commande/a/executer"); # print join(' ',@lines); # _____________________________________________________________ DOCS2 # Linux backups HOWTO1 # Add***jbw # Audience: All??? # /Add***jbw # Jerry Winegarden # Revised 4-04-00 # Revised***jbw # There are several utilities that can be used for backups under Linux. Which is the best? # There isn't any one utility that is best. It depends on the media to which you are backing up, # whether you are backing up just one machine or several over the network, and what you intend to # do with the backup. There are both free utilities which come standard with a Red Hat Linux # installation and third-party packages (some free, others not). # /Revised***jbw # List of backup utilities # Add***jbw # Standard Red Hat Linux (GNU) backup utilities # /Add***jbw # * # tar 2 # * # dump # Add***jbw # * rdump # /Add***jbw # * # cpio # * # (There are others: sharutil,find + dd, cp) 3 # Add***jbw # Third-party backup packages # * BRU # * Networker # * Matt: These two are just placeholders - I need to get a proper list (I've got saved email that # lists some - just had time to look thru them yet) # /Add***jbw # There are different types of backups: # * # full 4 # * # incremental # Add***jbw # * partial # * local # * remote (network) # /Add***jbw # Add***jbw # Full backups # Full backups are intended to be a complete backup of every file. Users should not be logged in during a # full backup so that files are not left open for writing and thus somehow not included in a full backup. # Partial backups # Partial backups include only a specified set of files or directories. # Incremental backups # Incremental backups are intended to backup only files that have changed since a previous backup. # A common backup scheme is to do a full backup on the weekend when no one is in the office, with # incremental backups being done each night of the things that changed that day. Incremental backups # can even be added to the same tape, without rewinding. To restore a file from backup that was # changed recently, it is often quicker to find the most recent version on an incremental tape backup # than to have to search all the way through all the files on a long full backup tape. Thus, full # backups tend to be done once a week only with incrementals in between. # /Add***jbw # Delete***jbw # /Delete***jbw # tar # tar ("tape archive" isn't just for tapes) is the most commonly used # backup utility. 5 # To produce a backup of a directory to a file on the disk (e.g. in /tmp): # tar cvf /tmp/foo.tar . (output file by default is /dev/tape, so # the output file name must be specified # with the f option; here, /tmp/foo.tar) # c option = Create archive (wrap it up # into a "tar archive") # v option = "verbose" - messages to screen # when reading/writing each file # f option = specify output file name # /tmp/foo.tar = output file name specified # . = source directory to create archive of # (wraps up everything under the # current directory) # addition of the "z" option will gzip the output file to compress it into gzip format: # tar cvzf /tmp/foo.tar.gz # To move a directory: # cd fromdir; tar cvf - . | (cd todir; tar xvf -) # To unpack an archive of a directory: # cd destdir; tar xvf /tmp/foo.tar 6 # Further tar options: # * # x option = eXtract archive # it will unpack it into the current default dir (so, first: cd destdir) # * # v option = verbose # Can be included with any other options (good to always include this flag) # * # f option + file name = specify the INPUT file name # (the name of the archive file being extracted). # "Incremental" backup with tar: # tar -cvf tarfilename --after-date="sept 1, 2000" /home # Add***jbw # dump # Dump is used to backup complete file systems, such as /, /home, or whatever file systems you have # defined. (File systems are listed in the file: /etc/fstab). Dump works on one file system at a time. # Dump has the concept of a dump "level", which is indicated by a non-negative integer, usually 0-6. # Level 0 dumps would be a full backup (of the specified file systems, which might be partial or # complete depending on whether all file systems are specified). Level 1 and higher dumps are used # for "incremental" backups. A level 1 dump will backup files which have changed (been "touched") # since the last level 0 dump. A level 2 dump will backup anything changed since the last level 1 # dump. This scheme can be used to produce a full backup on weekend (level 0 dump), followed by # a level n dump, where n is the day of the week (Monday = 1). # The other important dump parameter is "-f", which refers to the "file" or device to dump to. # Thus, the dump backup of a file system can be written to a disk drive (in another file system) # or to a tape drive or a zip drive. In the case of a tape drive, the file name is the special # character device name: /dev/rmt0 or /dev/nrmt0 ("no-rewind" tape device) or /dev/tape or whatever # the device name of your tape drive. # A dump is performed as follows: # dump -0f /dev/rmt0 /filesystemname # (full backup) # or, # dump -2f /dev/nrmt0 /filesystemname # (incremental, level 2 backup to the no-rewind tape device (don't rewind the tape before or after writing. # Just add the backup to the existing tape. This is often done to have incremental backups added to the same tape). # To extract files from a dump backup, use the utility: restore # Restores can be done "interactively": # restore -i # Dump/restore to be continued... # cpio # CPIO is another system backup utility. The rpm package installation utility actually uses cpio # format to package software for system installation. # CPIO - to be continued # 1This actually reads like, not a "backups HOWTO", but a "backups using tar HOWTO". You mention # other archiving utilities, but don't explain how to use them, and also don't explain why tar # is used in this document instead of the others. # ***jbw: I haven't gotten around to writing the details on how to for dump, cpio. Sorry. I'll work # on it. This doc is definitely not just a tar howto (heh, I use dump myself, most often, even # though some duluggers call dump "evil" under linux). # 2What does each utility do? Sure, tar means "tape archiver", which is alluded to later; what about the others? # 3Is this a list that is incomplete, and the author will add to it later? Why the ellipsis? # ***jbw - Right! List is incomplete and to be finished later. I did add to the list, parenthetically, # but I didn't describe those additions. (e.g. find + dd is a two-step method: find ... | dd ...) # 4It would be helpful to explain the difference between the two. For example: # A full backup makes an archive of the entire contents of a user's... hard drive? Filesystem? Home directory? # An incremental backup only includes those parts of the... hard drive? Filesystem? Home directory? ...which # have changed since the last time a backup was made. # ***jbw # I added the paragraphs describing full, partial, and incremental backups, and I explained the strategy of # how they are used (full once a week, incrementals every night) and why such a strategy is used (easier to # find one file to be restored from an incremental backup tape, which will have many fewer files written). # 5Any particular reason this section is pre-formatted? # YES!!! As with anything that's sort of a "man page" or a real, live, .conf file, it's often done with # tag. That is quite intentional to # get things formatted in an easily readable format without too much work! # The # tag is intentional here. It is even desirable here, # WITHOUT quot or footnote or other tags!!! It's sort of comparable to # getting a screen shot to show exactly how something is seen. # 6This is the only part of the HOWTO that actually shows "HOW TO" do something. Even so, the reasons # why you'd want to do this aren't explained.