From f6820ccee586ad7aa8ebf10cc8d006a8ebd997d8 Mon Sep 17 00:00:00 2001 From: Thomas Zilio Date: Wed, 19 Sep 2018 16:51:37 +0200 Subject: [PATCH] Miglioramento gestione ZIP --- lib/functions.php | 113 +++--------------- modules/aggiornamenti/upload_modules.php | 22 +--- modules/backup/actions.php | 49 +------- modules/fatture/bulk.php | 4 +- modules/interventi/bulk.php | 4 +- src/Backup.php | 129 +++++++++------------ src/Util/Zip.php | 140 +++++++++++++++++++++++ 7 files changed, 217 insertions(+), 244 deletions(-) create mode 100644 src/Util/Zip.php diff --git a/lib/functions.php b/lib/functions.php index b84527626..95b1d0a75 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -101,122 +101,37 @@ function directory($path) */ function copyr($source, $destination, $ignores = []) { - $finder = Symfony\Component\Finder\Finder::create() + if (!directory($destination)) { + return false; + } + + $files = Symfony\Component\Finder\Finder::create() ->files() ->exclude((array) $ignores['dirs']) - ->ignoreDotFiles(true) + ->ignoreDotFiles(false) ->ignoreVCS(true) ->in($source); foreach ((array) $ignores['files'] as $value) { - $finder->notName($value); + $files->notName($value); } - foreach ($finder as $file) { - $filename = rtrim($destination, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file->getRelativePathname(); + $result = true; - // Filesystem Symfony - $fs = new Symfony\Component\Filesystem\Filesystem(); + // Filesystem Symfony + $fs = new Symfony\Component\Filesystem\Filesystem(); + foreach ($files as $file) { + $filename = rtrim($destination, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file->getRelativePathname(); // Copia try { $fs->copy($file, $filename); } catch (Symfony\Component\Filesystem\Exception\IOException $e) { + $result = false; } } - return true; -} - -/** - * Crea un file zip comprimendo ricorsivamente tutte le sottocartelle a partire da una cartella specificata. - * *. - * - * @param string $source - * @param string $destination - * @param array $ignores - */ -function create_zip($source, $destination, $ignores = []) -{ - if (!extension_loaded('zip')) { - flash()->error(tr('Estensione zip non supportata!')); - - return false; - } - - $zip = new ZipArchive(); - $result = $zip->open($destination, ZIPARCHIVE::CREATE); - if ($result === true && is_writable(dirname($destination))) { - $finder = Symfony\Component\Finder\Finder::create() - ->files() - ->exclude((array) $ignores['dirs']) - ->ignoreDotFiles(true) - ->ignoreVCS(true) - ->in($source); - - foreach ((array) $ignores['files'] as $value) { - $finder->notName($value); - } - - foreach ($finder as $file) { - $zip->addFile($file, $file->getRelativePathname()); - } - $zip->close(); - } else { - flash()->error(tr("Errore durante la creazione dell'archivio!")); - } - - return $result === true; -} - -/** - * Controllo dei file zip e gestione errori. - * - * @param string $zip_file - * - * @return string|bool - */ -function checkZip($zip_file) -{ - $errno = zip_open($zip_file); - zip_close($errno); - - if (!is_resource($errno)) { - // using constant name as a string to make this function PHP4 compatible - $errors = [ - ZIPARCHIVE::ER_MULTIDISK => tr('archivi multi-disco non supportati'), - ZIPARCHIVE::ER_RENAME => tr('ridenominazione del file temporaneo fallita'), - ZIPARCHIVE::ER_CLOSE => tr('impossibile chiudere il file zip'), - ZIPARCHIVE::ER_SEEK => tr('errore durante la ricerca dei file'), - ZIPARCHIVE::ER_READ => tr('errore di lettura'), - ZIPARCHIVE::ER_WRITE => tr('errore di scrittura'), - ZIPARCHIVE::ER_CRC => tr('errore CRC'), - ZIPARCHIVE::ER_ZIPCLOSED => tr("l'archivio zip è stato chiuso"), - ZIPARCHIVE::ER_NOENT => tr('file non trovato'), - ZIPARCHIVE::ER_EXISTS => tr('il file esiste già'), - ZIPARCHIVE::ER_OPEN => tr('impossibile aprire il file'), - ZIPARCHIVE::ER_TMPOPEN => tr('impossibile creare il file temporaneo'), - ZIPARCHIVE::ER_ZLIB => tr('errore nella libreria Zlib'), - ZIPARCHIVE::ER_MEMORY => tr("fallimento nell'allocare memoria"), - ZIPARCHIVE::ER_CHANGED => tr('voce modificata'), - ZIPARCHIVE::ER_COMPNOTSUPP => tr('metodo di compressione non supportato'), - ZIPARCHIVE::ER_EOF => tr('fine del file non prevista'), - ZIPARCHIVE::ER_INVAL => tr('argomento non valido'), - ZIPARCHIVE::ER_NOZIP => tr('file zip non valido'), - ZIPARCHIVE::ER_INTERNAL => tr('errore interno'), - ZIPARCHIVE::ER_INCONS => tr('archivio zip inconsistente'), - ZIPARCHIVE::ER_REMOVE => tr('impossibile rimuovere la voce'), - ZIPARCHIVE::ER_DELETED => tr('voce eliminata'), - ]; - - if (isset($errors[$errno])) { - return tr('Errore').': '.$errors[$errno]; - } - - return false; - } else { - return true; - } + return $resul; } /** diff --git a/modules/aggiornamenti/upload_modules.php b/modules/aggiornamenti/upload_modules.php index 8dc9d4a90..7f24c24c2 100644 --- a/modules/aggiornamenti/upload_modules.php +++ b/modules/aggiornamenti/upload_modules.php @@ -2,6 +2,8 @@ include_once __DIR__.'/../../core.php'; +use Util\Zip; + if (!setting('Attiva aggiornamenti')) { die(tr('Accesso negato')); } @@ -14,25 +16,7 @@ if (!extension_loaded('zip')) { return; } -$file = $_FILES['blob']; -$type = $_POST['type']; - -// Lettura dell'archivio -$zip = new ZipArchive(); -if (!$zip->open($file['tmp_name'])) { - flash()->error(tr('File di installazione non valido!')); - flash()->error(checkZip($file['tmp_name'])); - - return; -} - -// Percorso di estrazione -$extraction_dir = $docroot.'/tmp'; -directory($extraction_dir); - -// Estrazione dell'archivio -$zip->extractTo($extraction_dir); -$zip->close(); +$extraction_dir = Zip::extract($_FILES['blob']['tmp_name']); // Aggiornamento del progetto if (file_exists($extraction_dir.'/VERSION')) { diff --git a/modules/backup/actions.php b/modules/backup/actions.php index 02d6164ca..3eb784122 100644 --- a/modules/backup/actions.php +++ b/modules/backup/actions.php @@ -47,53 +47,10 @@ if (filter('op') == 'restore') { } if (post('folder') == null) { - $file = $_FILES['blob']['tmp_name'] ?: post('zip'); - - // Lettura dell'archivio - $zip = new ZipArchive(); - if (!$zip->open($file)) { - flash()->error(tr('File di installazione non valido!')); - flash()->error(checkZip($file)); - - return; - } - - // Percorso di estrazione - $extraction_dir = $docroot.'/tmp'; - directory($extraction_dir); - - // Estrazione dell'archivio - $zip->extractTo($extraction_dir); - $zip->close(); + $path = $_FILES['blob']['tmp_name'] ?: $backup_dir.'/'.post('zip'); } else { - $extraction_dir = $backup_dir.'/'.post('folder'); + $path = $backup_dir.'/'.post('folder'); } - // Rimozione del database - $tables = include $docroot.'/update/tables.php'; - - $database->query('SET foreign_key_checks = 0'); - foreach ($tables as $tables) { - $database->query('DROP TABLE `'.$tables.'`'); - } - $database->query('DROP TABLE `updates`'); - - // Ripristino del database - $database->multiQuery($extraction_dir.'/database.sql'); - $database->query('SET foreign_key_checks = 1'); - - // Salva il file di configurazione - $config = file_get_contents($docroot.'/config.inc.php'); - - // Copia i file dalla cartella temporanea alla root - copyr($extraction_dir, $docroot); - - // Ripristina il file di configurazione dell'installazione - file_put_contents($docroot.'/config.inc.php', $config); - - // Pulizia - if (post('folder') == null) { - delete($extraction_dir); - } - delete($docroot.'/database.sql'); + Backup::restore($path, post('folder') == null); } diff --git a/modules/fatture/bulk.php b/modules/fatture/bulk.php index 1f6be9829..7ec05bdf4 100644 --- a/modules/fatture/bulk.php +++ b/modules/fatture/bulk.php @@ -2,6 +2,8 @@ include_once __DIR__.'/../../core.php'; +use Util\Zip; + switch (post('op')) { case 'export-bulk': $dir = DOCROOT.'/files/export_fatture/'; @@ -35,7 +37,7 @@ switch (post('op')) { // Creazione zip if (extension_loaded('zip')) { - create_zip($dir.'tmp/', $file); + Zip::create($dir.'tmp/', $file); // Invio al browser dello zip download($file); diff --git a/modules/interventi/bulk.php b/modules/interventi/bulk.php index 67fb41bba..58765261f 100644 --- a/modules/interventi/bulk.php +++ b/modules/interventi/bulk.php @@ -6,6 +6,8 @@ if (file_exists(__DIR__.'/../../../core.php')) { include_once __DIR__.'/../../core.php'; } +use Util\Zip; + include_once Modules::filepath('Fatture di vendita', 'modutil.php'); switch (post('op')) { @@ -42,7 +44,7 @@ switch (post('op')) { // Creazione zip if (extension_loaded('zip')) { - create_zip($dir.'tmp/', $file); + Zip::create($dir.'tmp/', $file); // Invio al browser dello zip download($file); diff --git a/src/Backup.php b/src/Backup.php index ab4ddcae4..a26876cf6 100644 --- a/src/Backup.php +++ b/src/Backup.php @@ -1,5 +1,8 @@ files() - ->exclude($ignores['dirs']) - ->ignoreDotFiles(false) - ->ignoreVCS(true) - ->in(DOCROOT) - ->in(self::getDatabaseDirectory()); - - foreach ($ignores['files'] as $value) { - $files->notName($value); - } - // Creazione backup in formato ZIP if (extension_loaded('zip')) { - $result = self::zipBackup($files, $backup_dir.'/'.$backup_name.'.zip'); + $result = Zip::create([ + DOCROOT, + self::getDatabaseDirectory() + ], $backup_dir.'/'.$backup_name.'.zip', $ignores); } // Creazione backup attraverso la copia dei file else { - $result = self::folderBackup($files, $backup_dir.'/'.$backup_name); + $result = copyr([ + DOCROOT, + self::getDatabaseDirectory() + ], $backup_dir.'/'.$backup_name.'.zip', $ignores); } // Rimozione cartella temporanea @@ -197,68 +193,6 @@ class Backup return $result; } - /** - * Effettua il backup in formato ZIP. - * - * @param Iterator|array $files File da includere - * @param string $destination Nome del file ZIP - * - * @return bool - */ - protected static function zipBackup($files, $destination) - { - if (!directory(dirname($destination))) { - return false; - } - - $zip = new ZipArchive(); - - $result = $zip->open($destination, ZipArchive::CREATE); - if ($result === true) { - foreach ($files as $file) { - $zip->addFile($file, $file->getRelativePathname()); - } - - $zip->close(); - - return true; - } - - return false; - } - - /** - * Effettua il backup attraverso la copia dei file. - * - * @param array $files Elenco dei file da includere - * @param string $destination Nome della cartella - * - * @return bool - */ - protected static function folderBackup($files, $destination) - { - if (!directory($destination)) { - return false; - } - - $result = true; - - // Filesystem Symfony - $fs = new Symfony\Component\Filesystem\Filesystem(); - foreach ($files as $file) { - $filename = $destination.DIRECTORY_SEPARATOR.$file->getRelativePathname(); - - // Copia - try { - $fs->copy($file, $filename); - } catch (Symfony\Component\Filesystem\Exception\IOException $e) { - $result = false; - } - } - - return $result; - } - /** * Effettua il dump del database. * @@ -268,7 +202,7 @@ class Backup { $config = App::getConfig(); - $dump = new Ifsnop\Mysqldump\Mysqldump('mysql:host='.$config['db_host'].';dbname='.$config['db_name'], $config['db_username'], $config['db_password'], [ + $dump = new Mysqldump('mysql:host='.$config['db_host'].';dbname='.$config['db_name'], $config['db_username'], $config['db_password'], [ 'add-drop-table' => true, ]); @@ -290,4 +224,43 @@ class Backup delete($backups[$i]); } } + + /** + * Ripristina un backup esistente. + * + * @param string $path + */ + public static function restore($path, $cleanup = true) + { + $database = database(); + $extraction_dir = is_dir($path) ? $path : Zip::extract($path); + + // Rimozione del database + $tables = include DOCROOT.'/update/tables.php'; + + $database->query('SET foreign_key_checks = 0'); + foreach ($tables as $tables) { + $database->query('DROP TABLE `'.$tables.'`'); + } + $database->query('DROP TABLE `updates`'); + + // Ripristino del database + $database->multiQuery($extraction_dir.'/database.sql'); + $database->query('SET foreign_key_checks = 1'); + + // Salva il file di configurazione + $config = file_get_contents(DOCROOT.'/config.inc.php'); + + // Copia i file dalla cartella temporanea alla root + copyr($extraction_dir, DOCROOT); + + // Ripristina il file di configurazione dell'installazione + file_put_contents(DOCROOT.'/config.inc.php', $config); + + // Pulizia + if (!empty($cleanup)) { + delete($extraction_dir); + } + delete(DOCROOT.'/database.sql'); + } } diff --git a/src/Util/Zip.php b/src/Util/Zip.php new file mode 100644 index 000000000..8535d85d7 --- /dev/null +++ b/src/Util/Zip.php @@ -0,0 +1,140 @@ +open($path)) { + flash()->error(self::check($path)); + + return; + } + + // Percorso di estrazione + $extraction_dir = DOCROOT.'/tmp'; + directory($extraction_dir); + + // Estrazione dell'archivio + $zip->extractTo($extraction_dir); + $zip->close(); + + return $extraction_dir; + } + + /** + * Crea un file zip comprimendo ricorsivamente tutte le sottocartelle a partire da una cartella specificata. + * + * @param string $source + * @param string $destination + * @param array $ignores + */ + public static function create($source, $destination, $ignores = []) + { + if (!directory(dirname($destination))) { + return false; + } + + $zip = new ZipArchive(); + + $result = $zip->open($destination, ZipArchive::CREATE); + if ($result === true && is_writable(dirname($destination))) { + $finder = Finder::create() + ->files() + ->exclude((array) $ignores['dirs']) + ->ignoreDotFiles(false) + ->ignoreVCS(true) + ->in($source); + + foreach ((array) $ignores['files'] as $value) { + $finder->notName($value); + } + + foreach ($finder as $file) { + $zip->addFile($file, $file->getRelativePathname()); + } + $zip->close(); + } else { + flash()->error(tr("Errore durante la creazione dell'archivio!")); + } + + return $result === true; + } + + /** + * Controllo dei file zip e gestione errori. + * + * @param string $path + * + * @return string|bool + */ + public static function check($path) + { + $errno = zip_open($path); + zip_close($errno); + + if (!is_resource($errno)) { + // using constant name as a string to make this function PHP4 compatible + $errors = [ + ZipArchive::ER_MULTIDISK => tr('archivi multi-disco non supportati'), + ZipArchive::ER_RENAME => tr('ridenominazione del file temporaneo fallita'), + ZipArchive::ER_CLOSE => tr('impossibile chiudere il file zip'), + ZipArchive::ER_SEEK => tr('errore durante la ricerca dei file'), + ZipArchive::ER_READ => tr('errore di lettura'), + ZipArchive::ER_WRITE => tr('errore di scrittura'), + ZipArchive::ER_CRC => tr('errore CRC'), + ZipArchive::ER_ZIPCLOSED => tr("l'archivio zip è stato chiuso"), + ZipArchive::ER_NOENT => tr('file non trovato'), + ZipArchive::ER_EXISTS => tr('il file esiste già'), + ZipArchive::ER_OPEN => tr('impossibile aprire il file'), + ZipArchive::ER_TMPOPEN => tr('impossibile creare il file temporaneo'), + ZipArchive::ER_ZLIB => tr('errore nella libreria Zlib'), + ZipArchive::ER_MEMORY => tr("fallimento nell'allocare memoria"), + ZipArchive::ER_CHANGED => tr('voce modificata'), + ZipArchive::ER_COMPNOTSUPP => tr('metodo di compressione non supportato'), + ZipArchive::ER_EOF => tr('fine del file non prevista'), + ZipArchive::ER_INVAL => tr('argomento non valido'), + ZipArchive::ER_NOZIP => tr('file zip non valido'), + ZipArchive::ER_INTERNAL => tr('errore interno'), + ZipArchive::ER_INCONS => tr('archivio zip inconsistente'), + ZipArchive::ER_REMOVE => tr('impossibile rimuovere la voce'), + ZipArchive::ER_DELETED => tr('voce eliminata'), + ]; + + if (isset($errors[$errno])) { + return tr('Errore').': '.$errors[$errno]; + } + + return false; + } else { + return true; + } + } +}