ONO::Cron::CronSync::Backup

package ONO::Cron::CronSync::Backup;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as other parts of the ONO Software Project or related
# elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# 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.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################

use strict;

use ONO::IO;
use ONO::Core::HostIO;
use ONO::Cron::CronSync::ToolBox;
use ONO::Lib::DateTime::ToolBox;
use ONO::Lib::Code::RandomID;
use ONO::ToolBox::SendMail;
use ONO::Render;

###############################################################################
# ONO
###############################################################################

#: Backup related services for ONO's CronSync service.

sub run {

my (
$self,
$CRON_DIR,
$job,
$data_ref,
$TYPE_ref,
$vars_ref,
$vpath,
$sec,$min,$hour,
$mday,$mon,$year,
$wday,$yday,
$timestamp,
$switches,
) = @_;

#: Execution logic.

my %data = %$data_ref;
my %TYPE = %$TYPE_ref;
my %vars = %$vars_ref;

my ($DATA,$MAIL);

if ($data{'type'} eq "bak_local") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': $TYPE{$data{'type'}} ($data{'type'})",$switches);
$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': backup target: $data{'bak_target'}",$switches);

my $ID = ONO::Lib::Code::RandomID->make;
my $ori_target = $data{'bak_target'};

if ($data{'bak_target'} =~ /[A-Za-z0-9]/) {

ONO::IO->mkdir("$data{'bak_target'}",777);
ONO::IO->htaccess("$data{'bak_target'}",":");

my $title = lc $data{'title'};
$title =~ s~( |_)~~g;
$title =~ s~[^a-z0-9\-]~~g;

$data{'bak_target'} .= "/$title";

ONO::IO->mkdir("$data{'bak_target'}",777);
ONO::IO->mkdir("$data{'bak_target'}/$ID",777);

}

if (ONO::IO->exists("$data{'bak_target'}/$ID")) {

if (!$data{'bak_sql_setup_mysqldump'}) {
$data{'bak_sql_setup_mysqldump'} = ONO::IO->which("mysqldump");
}

if ($data{'bak_sql'} && $data{'bak_sql_setup_mysqldump'} =~ m~^/~ && $data{'bak_sql_setup_username'} && $data{'bak_sql_setup_database'}) {

foreach my $opt ('bak_sql_setup_mysqldump','bak_sql_setup_username','bak_sql_setup_password','bak_sql_setup_database') {
$data{$opt} =~ s~[^A-Za-z0-9\/]~~g;
}

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': creating backup: ONO SQL DB ...",$switches);

ONO::IO->mkdir("$data{'bak_target'}/$ID/sql",777);

ONO::IO->store(
"$data{'bak_target'}/$ID/sql/$data{'bak_sql_setup_database'}.sql",
ONO::IO->exec3("$data{'bak_sql_setup_mysqldump'} --user=$data{'bak_sql_setup_username'} --password=$data{'bak_sql_setup_password'} --databases $data{'bak_sql_setup_database'}"),
);

}

foreach my $opt ('images','media','var') {

if ($data{"bak_dir_$opt"}) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': creating backup: $opt/ -> $data{'bak_target'}",$switches);

ONO::IO->mkdir("$data{'bak_target'}/$ID/$opt",777);

foreach my $dir (ONO::IO->ls("$opt")) {

if ($dir =~ /[A-Za-z0-9]/) {

ONO::IO->cpr("$opt/$dir","$data{'bak_target'}/$ID/$opt/$dir");

if ($data{"bak_zip_$opt"}) {

ONO::IO->tar("$data{'bak_target'}/$ID/$opt/$dir","$data{'bak_target'}/$ID/$opt/$dir.gz");

if ($data{"bak_zipcleanup_$opt"}) {

ONO::IO->rmdir("$data{'bak_target'}/$ID/$opt/$dir");

}

}

}

}

}

}

if ($data{'bak_dir_var_community'}) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': creating backup: var/community/ -> $data{'bak_target'}",$switches);

ONO::IO->mkdir("$data{'bak_target'}/$ID/community",777);

foreach my $dir (ONO::IO->ls("var/community")) {

if ($dir =~ /[A-Za-z0-9]/) {

ONO::IO->cpr("var/community/$dir","$data{'bak_target'}/$ID/community/$dir");

if ($data{'bak_zip_var_community'}) {

ONO::IO->tar("$data{'bak_target'}/$ID/community/$dir","$data{'bak_target'}/$ID/community/$dir.gz");

if ($data{'bak_zipcleanup_var_community'}) {

ONO::IO->rmdir("$data{'bak_target'}/$ID/community/$dir");

}

}

}

}

}

if ($data{'bak_dir_web'}) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': creating backup: web/ -> $data{'bak_target'}",$switches);

my $sites = 0;

foreach my $opt ('web','schoolweb') {

if (ONO::IO->exists($opt)) {

ONO::IO->mkdir("$data{'bak_target'}/$ID/$opt");

foreach my $d1 (ONO::IO->ls("$opt/")) {
if ($d1 =~ /[A-Za-z0-9]/ && $d1 !~ /\./ && length $d1 == 1) {

foreach my $d2 (ONO::IO->ls("$opt/$d1")) {
if ($d2 =~ /[A-Za-z0-9]/ && length $d2 == 2) {

foreach my $d3 (ONO::IO->ls("$opt/$d1/$d2")) {
if ($d3 =~ /[A-Za-z0-9]/ && length $d3 == 3) {

foreach my $d4 (ONO::IO->ls("$opt/$d1/$d2/$d3")) {
if ($d4 =~ /[A-Za-z0-9]/ && length $d4 == 10) {

$sites++;

ONO::IO->cpr("$opt/$d1/$d2/$d3/$d4","$data{'bak_target'}/$ID/$opt");

if ($data{'bak_zip_web'}) {

ONO::IO->tar("$data{'bak_target'}/$ID/$opt/$d4","$data{'bak_target'}/$ID/$opt/$d4.gz");

if ($data{'bak_zipcleanup_web'}) {

ONO::IO->rmdir("$data{'bak_target'}/$ID/$opt/$d4");

}

}


# still missing: SQL table entries

# still missing: publisher texts linked via SQL

}
}
}
}
}
}
}
}
}
}

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': $sites websites saved",$switches);

}

if ($data{'bak_dir_community_portal'}) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': creating backup: community/portal/ -> $data{'bak_target'}",$switches);

ONO::IO->mkdir("$data{'bak_target'}/$ID/school");

foreach my $opt ('data','school') {

ONO::IO->mkdir("$data{'bak_target'}/$ID/school/$opt");

my $counter = 0;

foreach my $dir (ONO::IO->ls("community/portal/$opt")) {

if ($dir =~ /[0-9]/) {

$counter++;

ONO::IO->cpr("community/portal/$opt/$dir","$data{'bak_target'}/$ID/school/$opt");

if ($data{'bak_zip_community_portal'}) {

ONO::IO->tar("$data{'bak_target'}/$ID/school/$opt/$dir","$data{'bak_target'}/$ID/school/$opt/$dir.gz");

if ($data{'bak_zipcleanup_community_portal'}) {

ONO::IO->rmdir("$data{'bak_target'}/$ID/school/$opt/$dir");

}

}

}

}

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': $counter $opt dirs saved",$switches);

}

}

foreach my $copy ('daily','weekly','monthly','yearly') {

if ($copy eq "daily" || ($copy eq "weekly" && $wday == 0) || ($copy eq "monthly" && $mday == 1) || ($copy eq "yearly" && $mday == 1 && $mon == 1)) {

if ($data{"bak_opt_keep_$copy"}) {

my $copydir = "$year$mon$mday";
if ($copy eq "weekly") {
}
if ($copy eq "monthly") {
$copydir = "$year$mon";
}
if ($copy eq "yearly") {
$copydir = $year;
}

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': preparing for a $copy copy ($copydir) ...",$switches);

my $BAKDIR = "$data{'bak_target'}/$copydir/";
$BAKDIR =~ s~//~/~g;

ONO::IO->mkdir($BAKDIR,777);
ONO::IO->cpr("$data{'bak_target'}/$ID/",$BAKDIR);

}

}

}

ONO::IO->mv("$data{'bak_target'}/latest","$data{'bak_target'}/remove_$ID" );
ONO::IO->mv("$data{'bak_target'}/$ID", "$data{'bak_target'}/latest" );

ONO::IO->rmdir("$data{'bak_target'}/remove_$ID");

ONO::IO->cp("$CRON_DIR/lastrun/job_$job.txt","$ori_target/BACKUP_TIMESTAMP.txt");

} else {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': ERROR: target directory '$data{'bak_target'}' could not be created - ABORT",$switches);

}

}

if ($data{'type'} eq "bak_local_os") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': $TYPE{$data{'type'}} ($data{'type'})",$switches);
$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': backup target: /backups/os/",$switches);

if (ONO::Core::HostIO->exists("/backups/os")) {

foreach my $dir (
'/bin',
'/boot',
'/etc',
'/lib',
'/lib64',
'/opt',
'/sbin',
'/usr',
) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': running backup: /$dir -> /backups/os/$dir ...",$switches);
ONO::IO->exec3("rsync -ar $dir /backups/os/ --delete");
}

ONO::IO->exec3("cp $vpath/$CRON_DIR/lastrun/job_$job.txt /backups/os/BACKUP_TIMESTAMP.txt");

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': backup completed [OK]",$switches);

} else {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': target does not exist [ABORT]",$switches);

}

}

if ($data{'type'} eq "bak_remote") {

if (!$data{'bak_protocol'}) {
$data{'bak_protocol'} = "scp";
}

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': $TYPE{$data{'type'}} ($data{'type'})",$switches);

# backup /var/mail first

if ($data{'bak_mail'}) {

# $DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': starting local /var/mail backups...",$switches);
#
# ONO::IO->mkdir("var/mail");
# ONO::IO->mkdir("var/mail/$year$mon$mday");
#
# foreach my $mailbox (ONO::Core::HostIO->ls("/var/mail")) {
#
# if ($mailbox =~ /^ono-mail-/) {
#
# $DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': copying: $mailbox to ONO's /var/mail...",$switches);
#
# ONO::Core::HostIO->cpr("/var/mail/$mailbox","$vpath/var/mail/$year$mon$mday");
#
# }
#
# }
#
# # ONO::IO->chmod("var/mail/$year$mon$mday","-R 777");
#
# # remove older mail backups
#
# foreach my $old (ONO::IO->ls("var/mail")) {
# $old =~ s~[^0-9]~~g;
# if (length $old == 8 && $old ne "$year$mon$mday") {
# ONO::IO->rmdir("var/mail/$old");
# }
# }

}

# get the target

my $TARGET = $data{'bak_target'};
$TARGET =~ s~^(.*)\@~~;
$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': backup target: $TARGET",$switches);

# dirs

my @dirs;

if ($data{'bak_site'}) {

foreach my $dir (ONO::IO->ls("/")) {

if ($dir =~ /[A-Za-z0-9]/ && $dir !~ /^(\.|\_)/ && $dir !~ /^cgi-bin/ && $dir !~ /^ono/ && $dir !~ /^syslog/ && $dir !~ /^(bak|backup)/) {

@dirs = (@dirs,$dir);

}

}

} else {

if ($data{'bak_dir_var_community'}) {

@dirs = (@dirs,"var/community");

}

if ($data{'bak_dir_images'}) {

@dirs = (@dirs,"images");

}

if ($data{'bak_dir_media'}) {

@dirs = (@dirs,"media");

}

if ($data{'bak_dir_web'}) {

@dirs = (@dirs,"web","schoolweb");

}

if ($data{'bak_dir_community_portal'}) {

@dirs = (@dirs,"community/portal");

}

}

if ($data{'bak_cgibin'}) {

@dirs = (@dirs,"cgi-bin");

}

if ($data{'bak_ono'}) {

@dirs = (@dirs,"ono");

}

my ($status,$user,$pass,$server,$path) = &bak_target("",$data{'bak_target'});

if ($status) {

foreach my $dir (@dirs) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': backup via $data{'bak_protocol'}: $dir",$switches);

if (!$data{'bak_protocol'} || $data{'bak_protocol'} eq "scp") {

my $RES = ONO::IO->exec2(qq~sshpass -p "$pass" scp -r $vpath/$dir $user\@$server:$path~);

}

if ($data{'bak_protocol'} eq "rsync") {

ONO::IO->exec3(qq~sshpass -p "$pass" rsync -ar --perms --chmod=a+rwx $vpath/$dir $user\@$server:$path --delete~);

}

}

# sql

if ($data{'bak_sql'} || $data{'bak_site'}) {

if (!$data{'bak_sql_setup_mysqldump'}) {
$data{'bak_sql_setup_mysqldump'} = ONO::IO->which("mysqldump");
}

foreach my $opt ('bak_sql_setup_mysqldump','bak_sql_setup_username','bak_sql_setup_password','bak_sql_setup_database') {
$data{$opt} =~ s~[^A-Za-z0-9\/]~~g;
}

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': creating backup: ONO SQL DB ...",$switches);

ONO::IO->mkdir("var/tmp/sql",777);

ONO::IO->store(
"var/tmp/sql/mysqldump_$year$mon$mday.sql",
ONO::IO->exec3("$data{'bak_sql_setup_mysqldump'} --user=$data{'bak_sql_setup_username'} --password=$data{'bak_sql_setup_password'} --databases $data{'bak_sql_setup_database'}"),
);

if (!$data{'bak_protocol'} || $data{'bak_protocol'} eq "scp") {

my $SSH = qq~sshpass -p "$pass" scp -r $vpath/var/tmp/sql/mysqldump_$year$mon$mday.sql $user\@$server:$path/var/BACKUP_MYSQLDUMP.sql~;
my $RES = ONO::IO->exec2($SSH);

}

if ($data{'bak_protocol'} eq "rsync") {

my $RSY = qq~sshpass -p "$pass" rsync -ar $vpath/var/tmp/sql/mysqldump_$year$mon$mday.sql $user\@$server:$path/var/BACKUP_MYSQLDUMP.sql~;
my $RES = ONO::IO->exec2($RSY);

}

ONO::IO->rm("var/tmp/sql/mysqldump_$year$mon$mday.sql");

}

if (!$data{'bak_protocol'} || $data{'bak_protocol'} eq "scp") {

my $SSH = qq~sshpass -p "$pass" scp -r $vpath/$CRON_DIR/lastrun/job_$job.txt $user\@$server:$path/var/BACKUP_TIMESTAMP.txt~;
my $RES = ONO::IO->exec2($SSH);

}

if ($data{'bak_protocol'} eq "rsync") {

my $RSY = qq~sshpass -p "$pass" rsync -ar $vpath/$CRON_DIR/lastrun/job_$job.txt $user\@$server:$path/var/BACKUP_TIMESTAMP.txt~;
my $RES = ONO::IO->exec2($RSY);

}

}

}

if ($data{'type'} eq "bak_server") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': $TYPE{$data{'type'}} ($data{'type'})",$switches);

$data{'bak_target'} =~ s~[^A-Za-z0-9\:\@\.\-\_\/\[\]]~~gi;

my ($status,$user,$pass,$server,$path) = &bak_target("",$data{'bak_target'});

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': backup target: $path",$switches);

my $PORT;
$data{'bak_port'} =~ s~[^0-9]~~gi;
if ($data{'bak_port'}) {
$PORT = "-e 'ssh -p$data{'bak_port'}'";
}

if (!$data{'bak_format'} || $data{'bak_format'} eq "files") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': starting complete backup (files)",$switches);

foreach my $dir (
'/bin',
'/boot',
'/etc',
'/lib',
'/lib64',
'/opt',
'/sbin',
'/usr',
'/var',
) {
ONO::IO->exec3(qq~sshpass -p "$pass" rsync -ar $PORT $dir $user\@$server:$path --delete~);
}

ONO::IO->exec3(qq~sshpass -p "$pass" scp -r $vpath/$CRON_DIR/lastrun/job_$job.txt $user\@$server:${path}BACKUP_TIMESTAMP.txt~);

}

if ($data{'bak_format'} eq "tar") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': starting complete backup (archives)",$switches);

ONO::IO->exec3("mkdir /tmp/ono/");

# everything except var

foreach my $dir (ONO::IO->sys("ls","/")) {

if ($dir !~ /^\./ && $dir !~ /^(backups|dev|disks|proc|sys|tmp|run|mnt|media|lost\+found|var)$/ && $dir !~ /^(Network|Volumes)$/) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': tar: /$dir",$switches);

ONO::IO->exec3("tar cpzf /tmp/ono/$dir.tar.gz /$dir");
ONO::IO->exec3(qq~sshpass -p "$pass" rsync -aAXr $PORT /tmp/ono/$dir.tar.gz $user\@$server:$path/$dir.tar.gz~);
ONO::IO->exec3("rm /tmp/ono/$dir.tar.gz");

}

}

# everything in var, except www

foreach my $dir (ONO::IO->sys("ls","/var")) {

if ($dir ne "." && $dir ne ".." && $dir ne "www") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': tar: /var/$dir",$switches);

ONO::IO->exec3("tar cpzf /tmp/ono/var_$dir.tar.gz /var/$dir");
ONO::IO->exec3(qq~sshpass -p "$pass" rsync -aAXr $PORT /tmp/ono/var_$dir.tar.gz $user\@$server:$path~);
ONO::IO->exec3("rm /tmp/ono/var_$dir.tar.gz");

}

}

# var/www

foreach my $dir (ONO::IO->sys("ls","/var/www")) {

if ($dir ne "." && $dir ne "..") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': tar: /var/www/$dir",$switches);

ONO::IO->exec3("tar cpzf /tmp/ono/var_www_$dir.tar.gz /var/www/$dir");
ONO::IO->exec3(qq~sshpass -p "$pass" rsync -aAXr $PORT /tmp/ono/var_www_$dir.tar.gz $user\@$server:$path~);
ONO::IO->exec3("rm /tmp/ono/var_www_$dir.tar.gz");

}

}

}
}

if ($data{'type'} eq "bak_mail") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': $TYPE{$data{'type'}} ($data{'type'})",$switches);

$data{'bak_target'} =~ s~[^A-Za-z0-9\:\@\.\-\_\/\[\]]~~gi;

my ($status,$user,$pass,$server,$path) = &bak_target("",$data{'bak_target'});

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': backup target: $server:$path",$switches);

if ($status) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': starting mail backup (files)",$switches);

ONO::IO->exec3(qq~sshpass -p "$pass" rsync -ar /var/mail/* $user\@$server:$path --delete~);

foreach my $dir ('postfix','dovecot','courier','mail','passwd','spamassassin','default') {
ONO::IO->exec3(qq~sshpass -p "$pass" rsync -ar /etc/$dir $user\@$server:$path --delete~);
}

ONO::IO->exec3(qq~sshpass -p "$pass" scp -r $vpath/$CRON_DIR/lastrun/job_$job.txt $user\@$server:${path}BACKUP_TIMESTAMP.txt~);

} else {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': config error [ABORT]",$switches);

}

}

if ($data{'type'} eq "bak_restore_live") {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': $TYPE{$data{'type'}} ($data{'type'})",$switches);

foreach my $dir (ONO::Core::HostIO->ls("/var/www")) {

if ($dir !~ /^\./ && $dir =~ /[A-Za-z0-9]/ && ONO::Core::HostIO->exists("/var/www/$dir/html/var")) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': - Checking web '$dir' has been found",$switches);

if (ONO::Core::HostIO->exists("/var/www/$dir/html/var/BACKUP_TIMESTAMP.txt") && !ONO::Core::HostIO->exists("/var/www/$dir/html/var/BACKUP_RESTORED.txt")) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': - Web '$dir' is a backup that can be restored [PROCESSING...]",$switches);

# instantly mark dir web as being processed...

ONO::Core::HostIO->store("/var/www/$dir/html/var/BACKUP_RESTORED.txt",$timestamp);

# SQL processing...

if (ONO::Core::HostIO->exists("/var/www/$dir/html/var/BACKUP_MYSQLDUMP.sql")) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': - Processing SQL DB for '$dir' ...",$switches);

my $mysql = ONO::IO->which("mysql");

if ($mysql) {

my %db_conf;

foreach my $line (ONO::Core::HostIO->list("/var/www/$dir/html/etc/sql/ono.conf")) {
$line =~ s~(\n|\r|\t)~~g;
$line =~ m~^(.*?) (.*?)$~;
$db_conf{$1} = $2;
}

if ($db_conf{'username'} && $db_conf{'password'} && $db_conf{'database'}) {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': - SQL config is looking good [EXECUTE]",$switches);

ONO::IO->exec3("$mysql --user=$db_conf{'username'} --password=$db_conf{'password'} < /var/www/$dir/html/var/BACKUP_MYSQLDUMP.sql");

} else {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': - ERROR: /etc/ono.conf is missing, or data is missing [ABORT]",$switches);

}

} else {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': ERROR: mysql command not found [ABORT]",$switches);

}

}

# make sure the mark can be removed, so that rsync may delete it when completing the next backing

ONO::Core::HostIO->chmod("/var/www/$dir/html/var/BACKUP_RESTORED.txt",777);

} else {

$DATA .= ONO::Cron::CronSync::ToolBox->print("Job '$data{'title'}': - Web '$dir' is not a backup, or it has already been restored [ABORT]",$switches);

}
}
}
}

return ($DATA,$MAIL);

}

sub bak_target {

# username:password@server:/path/...

my $string = $_[1];

$string =~ s~[^A-Za-z0-9\:\@\.\-\_\/\[\]]~~gi;

my ($user,$pass,$server,$path);

if ($string =~ m~^(.*?):(.*?)\@(.*):(.*?)$~) {

$user = $1;
$pass = $2;
$server = $3;
$path = $4;

$user =~ s~[^A-Za-z0-9]~~gi;
$pass =~ s~[^A-Za-z0-9]~~gi;
$server =~ s~[^A-Za-z0-9\-\.\:]~~gi;
$path =~ s~[^A-Za-z0-9\-\_\.\:\/]~~gi;

if ($server =~ /:/ && $server !~ /\[/) {
$server = "\\\[$server\\\]";
}

if ($user && $pass && $server && $path) {

return (1,$user,$pass,$server,$path);

} else {

return (0);

}

} else {

return (0);

}

}

###############################################################################
# end of script
###############################################################################

1;

__END__