From e1d655a3ac3e36b7a0bc6ef68ec2d1261f69588b Mon Sep 17 00:00:00 2001 From: Gert Date: Mon, 27 Apr 2015 12:40:30 +0200 Subject: [PATCH 1/6] move backup code into Grav\Common --- system/src/Grav/Common/Backup/ZipBackup.php | 103 ++++++++++++++++++ system/src/Grav/Console/Cli/BackupCommand.php | 51 ++++----- 2 files changed, 122 insertions(+), 32 deletions(-) create mode 100644 system/src/Grav/Common/Backup/ZipBackup.php diff --git a/system/src/Grav/Common/Backup/ZipBackup.php b/system/src/Grav/Common/Backup/ZipBackup.php new file mode 100644 index 000000000..1836c56df --- /dev/null +++ b/system/src/Grav/Common/Backup/ZipBackup.php @@ -0,0 +1,103 @@ +findResource('cache://', true); + $destination = $destination . DS . 'tmp/Grav-' . uniqid(); + Folder::mkdir($destination); + } + + $name = basename(GRAV_ROOT); + + if (is_dir($destination)) { + $date = date('YmdHis', time()); + $filename = $name . '-' . $date . '.zip'; + $destination = rtrim($destination, DS) . DS . $filename; + } + + $messager && $messager([ + 'type' => 'message', + 'level' => 'info', + 'message' => 'Creating new Backup "' . $destination . '"' + ]); + $messager && $messager([ + 'type' => 'message', + 'level' => 'info', + 'message' => '' + ]); + + $zip = new \ZipArchive(); + $zip->open($destination, \ZipArchive::CREATE); + $zip->addEmptyDir($name); + + static::folderToZip(GRAV_ROOT, $zip, strlen(rtrim(GRAV_ROOT, DS) . DS), $messager); + + $messager && $messager([ + 'type' => 'progress', + 'percentage' => false, + 'complete' => true + ]); + + $messager && $messager([ + 'type' => 'message', + 'level' => 'info', + 'message' => '' + ]); + $messager && $messager([ + 'type' => 'message', + 'level' => 'info', + 'message' => 'Saving and compressing archive...' + ]); + + $zip->close(); + + return $destination; + } + + /** + * @param $folder + * @param $zipFile + * @param $exclusiveLength + * @param $messager + */ + private static function folderToZip($folder, \ZipArchive &$zipFile, $exclusiveLength, callable $messager = null) + { + $handle = opendir($folder); + while (false !== $f = readdir($handle)) { + if ($f != '.' && $f != '..') { + $filePath = "$folder/$f"; + // Remove prefix from file path before add to zip. + $localPath = substr($filePath, $exclusiveLength); + if (is_file($filePath)) { + $zipFile->addFile($filePath, $localPath); + + $messager && $messager([ + 'type' => 'progress', + 'percentage' => false, + 'complete' => false + ]); + } elseif (is_dir($filePath)) { + // Add sub-directory. + $zipFile->addEmptyDir($localPath); + static::folderToZip($filePath, $zipFile, $exclusiveLength, $messager); + } + } + } + closedir($handle); + } +} diff --git a/system/src/Grav/Console/Cli/BackupCommand.php b/system/src/Grav/Console/Cli/BackupCommand.php index 050301762..46590bf39 100644 --- a/system/src/Grav/Console/Cli/BackupCommand.php +++ b/system/src/Grav/Console/Cli/BackupCommand.php @@ -7,6 +7,7 @@ use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Grav\Common\Backup\ZipBackup; /** * Class BackupCommand @@ -23,6 +24,10 @@ class BackupCommand extends Command * @var */ protected $progress; + /** + * @var + */ + protected $output; /** * @@ -52,6 +57,8 @@ class BackupCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->output = $output; + $output->getFormatter()->setStyle('red', new OutputFormatterStyle('red')); $output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan')); $output->getFormatter()->setStyle('green', new OutputFormatterStyle('green')); @@ -60,25 +67,10 @@ class BackupCommand extends Command $this->progress = new ProgressBar($output); $this->progress->setFormat('Archiving %current% files [%bar%] %elapsed:6s% %memory:6s%'); - $name = basename($this->source); - $dir = dirname($this->source); - $date = date('YmdHis', time()); - $filename = $name . '-' . $date . '.zip'; - $destination = ($input->getArgument('destination')) ? $input->getArgument('destination') : ROOT_DIR; - $destination = rtrim($destination, DS) . DS . $filename; - $output->writeln(''); - $output->writeln('Creating new Backup "' . $destination . '"'); - $this->progress->start(); + ZipBackup::backup($destination, [$this, 'output']); - $zip = new \ZipArchive(); - $zip->open($destination, \ZipArchive::CREATE); - $zip->addEmptyDir($name); - - $this->folderToZip($this->source, $zip, strlen($dir . DS), $this->progress); - $zip->close(); - $this->progress->finish(); $output->writeln(''); $output->writeln(''); @@ -90,25 +82,20 @@ class BackupCommand extends Command * @param $exclusiveLength * @param $progress */ - private static function folderToZip($folder, \ZipArchive &$zipFile, $exclusiveLength, ProgressBar $progress) + public function output($args) { - $handle = opendir($folder); - while (false !== $f = readdir($handle)) { - if ($f != '.' && $f != '..') { - $filePath = "$folder/$f"; - // Remove prefix from file path before add to zip. - $localPath = substr($filePath, $exclusiveLength); - if (is_file($filePath)) { - $zipFile->addFile($filePath, $localPath); - $progress->advance(); - } elseif (is_dir($filePath)) { - // Add sub-directory. - $zipFile->addEmptyDir($localPath); - self::folderToZip($filePath, $zipFile, $exclusiveLength, $progress); + switch ($args['type']) { + case 'message': + $this->output->writeln($args['message']); + break; + case 'progress': + if ($args['complete']) { + $this->progress->finish(); + } else { + $this->progress->advance(); } - } + break; } - closedir($handle); } } From bbdb0189f1594900fafb0cb33fba3e2c7e15ec16 Mon Sep 17 00:00:00 2001 From: Gert Date: Mon, 27 Apr 2015 16:13:48 +0200 Subject: [PATCH 2/6] use site name for backup archive name --- system/src/Grav/Common/Backup/ZipBackup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Backup/ZipBackup.php b/system/src/Grav/Common/Backup/ZipBackup.php index 1836c56df..48991b7b5 100644 --- a/system/src/Grav/Common/Backup/ZipBackup.php +++ b/system/src/Grav/Common/Backup/ZipBackup.php @@ -22,7 +22,7 @@ class ZipBackup Folder::mkdir($destination); } - $name = basename(GRAV_ROOT); + $name = self::getGrav()['config']->get('site.title', basename(GRAV_ROOT)); if (is_dir($destination)) { $date = date('YmdHis', time()); From c481acbb7185c3a0408ade4cc8e7a8d83e07b8cb Mon Sep 17 00:00:00 2001 From: Gert Date: Mon, 27 Apr 2015 16:24:17 +0200 Subject: [PATCH 3/6] implement ignore for backups --- system/src/Grav/Common/Backup/ZipBackup.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Backup/ZipBackup.php b/system/src/Grav/Common/Backup/ZipBackup.php index 48991b7b5..cdef16efc 100644 --- a/system/src/Grav/Common/Backup/ZipBackup.php +++ b/system/src/Grav/Common/Backup/ZipBackup.php @@ -14,6 +14,13 @@ class ZipBackup { use GravTrait; + protected static $ignore = [ + '.git', + 'cache', + 'images', + 'logs' + ]; + public static function backup($destination = null, callable $messager = null) { if (!$destination) { @@ -43,7 +50,6 @@ class ZipBackup $zip = new \ZipArchive(); $zip->open($destination, \ZipArchive::CREATE); - $zip->addEmptyDir($name); static::folderToZip(GRAV_ROOT, $zip, strlen(rtrim(GRAV_ROOT, DS) . DS), $messager); @@ -83,6 +89,11 @@ class ZipBackup $filePath = "$folder/$f"; // Remove prefix from file path before add to zip. $localPath = substr($filePath, $exclusiveLength); + + if (in_array($localPath, static::$ignore)) { + continue; + } + if (is_file($filePath)) { $zipFile->addFile($filePath, $localPath); From 5ccefee2889daa2a7e4664d1d7397451d457a8c0 Mon Sep 17 00:00:00 2001 From: Gert Date: Mon, 27 Apr 2015 21:45:42 +0200 Subject: [PATCH 4/6] backup to backup folder --- .gitignore | 2 ++ backup/.gitkeep | 0 system/src/Grav/Common/Backup/ZipBackup.php | 8 ++++++-- system/src/Grav/Common/Config/Config.php | 6 ++++++ system/src/Grav/Console/Cli/SandboxCommand.php | 1 + 5 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 backup/.gitkeep diff --git a/.gitignore b/.gitignore index d436576ff..da248e548 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ vendor/ .sass-cache # Grav Specific +backup/* +!backup/.* cache/* !cache/.* assets/* diff --git a/backup/.gitkeep b/backup/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/system/src/Grav/Common/Backup/ZipBackup.php b/system/src/Grav/Common/Backup/ZipBackup.php index cdef16efc..2951cf9bf 100644 --- a/system/src/Grav/Common/Backup/ZipBackup.php +++ b/system/src/Grav/Common/Backup/ZipBackup.php @@ -16,6 +16,7 @@ class ZipBackup protected static $ignore = [ '.git', + 'backup', 'cache', 'images', 'logs' @@ -24,8 +25,11 @@ class ZipBackup public static function backup($destination = null, callable $messager = null) { if (!$destination) { - $destination = self::getGrav()['locator']->findResource('cache://', true); - $destination = $destination . DS . 'tmp/Grav-' . uniqid(); + $destination = self::getGrav()['locator']->findResource('backup://', true); + + if (!$destination) + throw new \RuntimeException('The backup folder is missing.'); + Folder::mkdir($destination); } diff --git a/system/src/Grav/Common/Config/Config.php b/system/src/Grav/Common/Config/Config.php index 1fe373a40..60f443108 100644 --- a/system/src/Grav/Common/Config/Config.php +++ b/system/src/Grav/Common/Config/Config.php @@ -72,6 +72,12 @@ class Config extends Data 'prefixes' => [ '' => ['logs'] ] + ], + 'backup' => [ + 'type' => 'Stream', + 'prefixes' => [ + '' => ['backup'] + ] ] ]; diff --git a/system/src/Grav/Console/Cli/SandboxCommand.php b/system/src/Grav/Console/Cli/SandboxCommand.php index 4d984d219..ef85e42bb 100644 --- a/system/src/Grav/Console/Cli/SandboxCommand.php +++ b/system/src/Grav/Console/Cli/SandboxCommand.php @@ -20,6 +20,7 @@ class SandboxCommand extends Command * @var array */ protected $directories = array( + '/backup', '/cache', '/logs', '/images', From e364616730b98888d1f969382af548a7debd019c Mon Sep 17 00:00:00 2001 From: Gert Date: Mon, 27 Apr 2015 21:53:08 +0200 Subject: [PATCH 5/6] add server directives to block access to backup folder --- .htaccess | 2 +- nginx.conf | 6 ++- web.config | 106 +++++++++++++++++++++++++++-------------------------- 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/.htaccess b/.htaccess index ce48b2674..ecf1097c0 100644 --- a/.htaccess +++ b/.htaccess @@ -44,7 +44,7 @@ RewriteRule .* index.php [L] ## Begin - Security # Block all direct access for these folders -RewriteRule ^(cache|bin|logs)/(.*) error [L] +RewriteRule ^(cache|bin|logs|backup)/(.*) error [L] # Block access to specific file types for these folders RewriteRule ^(system|user|vendor)/(.*)\.(txt|md|html|yaml|php|twig|sh|bat)$ error [L] ## End - Security diff --git a/nginx.conf b/nginx.conf index 12a48054a..afa450c23 100644 --- a/nginx.conf +++ b/nginx.conf @@ -25,7 +25,7 @@ http { index index.php; if (!-e $request_filename){ rewrite ^(.*)$ /index.php last; } } - + location /images/ { # Serve images as static } @@ -44,6 +44,10 @@ http { rewrite ^/bin/(.*)$ /error redirect; } + location /backup { + rewrite ^/backup/(.*) /error redirect; + } + location /system { rewrite ^/system/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect; } diff --git a/web.config b/web.config index 85d2c1b1b..c3dd31424 100644 --- a/web.config +++ b/web.config @@ -1,51 +1,55 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From bbfc63e94308adb0b48fbcf778e0c3fa12110f38 Mon Sep 17 00:00:00 2001 From: Gert Date: Tue, 28 Apr 2015 23:35:58 +0200 Subject: [PATCH 6/6] ignore all .git folders --- system/src/Grav/Common/Backup/ZipBackup.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/system/src/Grav/Common/Backup/ZipBackup.php b/system/src/Grav/Common/Backup/ZipBackup.php index 2951cf9bf..d275d21eb 100644 --- a/system/src/Grav/Common/Backup/ZipBackup.php +++ b/system/src/Grav/Common/Backup/ZipBackup.php @@ -14,14 +14,17 @@ class ZipBackup { use GravTrait; - protected static $ignore = [ - '.git', + protected static $ignorePaths = [ 'backup', 'cache', 'images', 'logs' ]; + protected static $ignoreFolders = [ + '.git' + ]; + public static function backup($destination = null, callable $messager = null) { if (!$destination) { @@ -94,7 +97,7 @@ class ZipBackup // Remove prefix from file path before add to zip. $localPath = substr($filePath, $exclusiveLength); - if (in_array($localPath, static::$ignore)) { + if (in_array($f, static::$ignoreFolders) || in_array($localPath, static::$ignorePaths)) { continue; }