Skip to content

Commit d296003

Browse files
committed
fix query calls, bad escaping of db name, and include zip fixes from !1345
1 parent 17a4a5d commit d296003

File tree

1 file changed

+37
-26
lines changed

1 file changed

+37
-26
lines changed

server/lib/classes/backup.inc.php

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -736,11 +736,12 @@ protected static function backups_garbage_collection($server_id, $backup_type =
736736
//First check that all records in database have related files and delete records without files on disk
737737
$args = array();
738738
$args_domains = array();
739+
$args_domains_with_backups = array();
739740
$server_config = $app->getconf->get_server_config($server_id, 'server');
740741
$backup_dir = trim($server_config['backup_dir']);
741742
$sql = "SELECT * FROM web_backup WHERE server_id = ?";
742743
$sql_domains = "SELECT domain_id,document_root,system_user,system_group,backup_interval FROM web_domain WHERE server_id = ? AND (type = 'vhost' OR type = 'vhostsubdomain' OR type = 'vhostalias')";
743-
$sql_domains_with_backups = "SELECT domain_id,document_root,system_user,system_group,backup_interval FROM web_domain WHERE domain_id in (SELECT * FROM web_backup WHERE server_id = ?" . ((!empty($backup_type)) ? " AND backup_type = ?" : "") . ") AND (type = 'vhost' OR type = 'vhostsubdomain' OR type = 'vhostalias')";
744+
$sql_domains_with_backups = "SELECT domain_id,document_root,system_user,system_group,backup_interval FROM web_domain WHERE domain_id in (SELECT parent_domain_id FROM web_backup WHERE server_id = ?" . ((!empty($backup_type)) ? " AND backup_type = ?" : "") . ") AND (type = 'vhost' OR type = 'vhostsubdomain' OR type = 'vhostalias')";
744745
array_push($args, $server_id);
745746
array_push($args_domains, $server_id);
746747
array_push($args_domains_with_backups, $server_id);
@@ -759,7 +760,7 @@ protected static function backups_garbage_collection($server_id, $backup_type =
759760
}
760761
array_unshift($args, $sql);
761762
array_unshift($args_domains, $sql_domains);
762-
array_unshift($args_domains_with_backups, $sql_domains);
763+
array_unshift($args_domains_with_backups, $sql_domains_with_backups);
763764

764765
$db_list = array($app->db);
765766
if ($app->db->dbHost != $app->dbmaster->dbHost)
@@ -779,7 +780,7 @@ protected static function backups_garbage_collection($server_id, $backup_type =
779780
}
780781

781782
// Cleanup backup files with missing web_backup entries (runs on all servers)
782-
$domains = $app->dbmaster->queryAllRecords($args_domains_with_backups);
783+
$domains = call_user_func_array(array($app->dbmaster, "queryAllRecords"), $args_domains_with_backups);
783784
foreach ($domains as $rec) {
784785
$domain_id = $rec['domain_id'];
785786
$domain_backup_dir = $backup_dir . '/web' . $domain_id;
@@ -788,29 +789,29 @@ protected static function backups_garbage_collection($server_id, $backup_type =
788789
if (!empty($files)) {
789790
// leave out server_id here, in case backup storage is shared between servers
790791
$sql = "SELECT backup_id, filename FROM web_backup WHERE parent_domain_id = ?";
792+
$untracked_backup_files = array();
791793
foreach ($db_list as $db) {
792-
$backup_record_exists = false;
793-
$backups = $db->queryAllRecords($sql, $server_id, $domain_id);
794+
$backups = $db->queryAllRecords($sql, $domain_id);
794795
foreach ($backups as $backup) {
795-
if (in_array($backup['filename'],$files)) {
796-
$backup_record_exists = true;
796+
if (!in_array($backup['filename'],$files)) {
797+
$untracked_backup_files[] = $backup['filename'];
797798
}
798799
}
799-
if (!$backup_record_exists) {
800-
$backup_file = $backup_dir . '/web' . $domain_id . '/' . $backup['filename'];
801-
$app->log('Backup file ' . $backup_file . ' is not contained in database, deleting this file from disk', LOGLEVEL_DEBUG);
802-
@unlink($backup_file);
803-
}
800+
}
801+
array_unique( $untracked_backup_files );
802+
foreach ($untracked_backup_files as $f) {
803+
$backup_file = $backup_dir . '/web' . $domain_id . '/' . $f;
804+
$app->log('Backup file ' . $backup_file . ' is not contained in database, deleting this file from disk', LOGLEVEL_DEBUG);
805+
@unlink($backup_file);
804806
}
805807
}
806808
}
807809

808810
// This cleanup only runs on web servers
809-
$domains = $app->db->queryAllRecords($args_domains);
811+
$domains = call_user_func_array(array($app->db, "queryAllRecords"), $args_domains);
810812
foreach ($domains as $rec) {
811813
$domain_id = $rec['domain_id'];
812814
$domain_backup_dir = $backup_dir . '/web' . $domain_id;
813-
$files = self::get_files($domain_backup_dir);
814815

815816
// Remove backupdir symlink and create as directory instead
816817
if (is_link($backup_download_dir) || !is_dir($backup_download_dir)) {
@@ -836,7 +837,7 @@ protected static function backups_garbage_collection($server_id, $backup_type =
836837
$now = time();
837838
while (false !== ($entry = $dir_handle->read())) {
838839
$full_filename = $backup_download_dir . '/' . $entry;
839-
if ($entry != '.' && $entry != '..' && is_file($full_filename)) {
840+
if ($entry != '.' && $entry != '..' && is_file($full_filename) && ! is_link($full_filename)) {
840841
// delete files older than 3 days
841842
if ($now - filemtime($full_filename) >= 60 * 60 * 24 * 3) {
842843
$app->log('Backup file ' . $full_filename . ' is too old, deleting this file from disk', LOGLEVEL_DEBUG);
@@ -919,16 +920,24 @@ protected static function get_files($directory, $prefix_list = null, $endings_li
919920
* Generates excludes list for compressors
920921
* @param string[] $backup_excludes
921922
* @param string $arg
923+
* @param string $pre
924+
* @param string $post
922925
* @return string
923926
* @author Ramil Valitov <ramilvalitov@gmail.com>
924927
*/
925-
protected static function generateExcludeList($backup_excludes, $arg)
928+
protected static function generateExcludeList($backup_excludes, $arg, $pre='', $post='')
926929
{
927-
$excludes = implode(" " . $arg, $backup_excludes);
928-
if (!empty($excludes)) {
929-
$excludes = $arg . $excludes;
930+
$excludes = "";
931+
foreach ($backup_excludes as $ex) {
932+
# pass through escapeshellarg if not already done
933+
if ( preg_match( "/^'.+'$/", $ex ) ) {
934+
$excludes .= "${arg}${pre}${ex}${post} ";
935+
} else {
936+
$excludes .= "${arg}" . escapeshellarg("${pre}${ex}${post}") . " ";
937+
}
930938
}
931-
return $excludes;
939+
940+
return trim( $excludes );
932941
}
933942

934943
/**
@@ -987,12 +996,14 @@ protected static function runWebCompression($format, $backup_excludes, $backup_m
987996
if (!empty($password)) {
988997
$zip_options .= ' --password ' . escapeshellarg($password);
989998
}
999+
$excludes = self::generateExcludeList($backup_excludes, '-x ');
1000+
$excludes .= " " . self::generateExcludeList($backup_excludes, '-x ', '', '/*');
9901001
if ($backup_mode == 'user_zip') {
9911002
//Standard casual behaviour of ISPConfig
992-
$app->system->exec_safe($find_user_files . ' | zip ' . $zip_options . ' -b ? ' . $excludes . ' --symlinks ? -@', $web_path, $web_user, $web_group, $http_server_user, $backup_tmp, $web_backup_dir . '/' . $web_backup_file);
1003+
$app->system->exec_safe($find_user_files . ' | zip ' . $zip_options . ' -b ? --symlinks ? -@ ' . $excludes, $web_path, $web_user, $web_group, $http_server_user, $backup_tmp, $web_backup_dir . '/' . $web_backup_file);
9931004
} else {
994-
//Use cd to have a correct directory structure inside the archive, extra options to zip hidden (dot) files
995-
$app->system->exec_safe('cd ? && zip ' . $zip_options . ' -b ? ' . $excludes . ' --symlinks -r ? * .* -x "../*"', $web_path, $backup_tmp, $web_backup_dir . '/' . $web_backup_file);
1005+
//Use cd to have a correct directory structure inside the archive, zip current directory "." to include hidden (dot) files
1006+
$app->system->exec_safe('cd ? && zip ' . $zip_options . ' -b ? --symlinks -r ? . ' . $excludes, $web_path, $backup_tmp, $web_backup_dir . '/' . $web_backup_file);
9961007
}
9971008
$exit_code = $app->system->last_exec_retcode();
9981009
// zip can return 12(due to harmless warnings) and still create valid backups
@@ -1237,8 +1248,8 @@ protected static function make_database_backup($web_domain, $backup_job)
12371248
//* Remove old backups
12381249
self::backups_garbage_collection($server_id, 'mysql', $domain_id);
12391250
$prefix_list = array(
1240-
'db_'.escapeshellarg($db_name).'_',
1241-
'manual-db_'.escapeshellarg($db_name).'_',
1251+
"db_${db_name}_",
1252+
"manual-db_${db_name}_",
12421253
);
12431254
self::clearBackups($server_id, $domain_id, intval($rec['backup_copies']), $db_backup_dir, $prefix_list);
12441255
} else {
@@ -1313,7 +1324,7 @@ protected static function make_web_backup($web_domain, $backup_job)
13131324

13141325
# default exclusions
13151326
$backup_excludes = array(
1316-
escapeshellarg('./backup\*'),
1327+
'./backup*',
13171328
'./bin', './dev', './etc', './lib', './lib32', './lib64', './opt', './sys', './usr', './var', './proc', './run', './tmp',
13181329
);
13191330

0 commit comments

Comments
 (0)