Miglioramento gestione ZIP

This commit is contained in:
Thomas Zilio 2018-09-19 16:51:37 +02:00
parent d8c6f731ce
commit f6820ccee5
7 changed files with 217 additions and 244 deletions

View File

@ -101,122 +101,37 @@ function directory($path)
*/ */
function copyr($source, $destination, $ignores = []) function copyr($source, $destination, $ignores = [])
{ {
$finder = Symfony\Component\Finder\Finder::create() if (!directory($destination)) {
return false;
}
$files = Symfony\Component\Finder\Finder::create()
->files() ->files()
->exclude((array) $ignores['dirs']) ->exclude((array) $ignores['dirs'])
->ignoreDotFiles(true) ->ignoreDotFiles(false)
->ignoreVCS(true) ->ignoreVCS(true)
->in($source); ->in($source);
foreach ((array) $ignores['files'] as $value) { foreach ((array) $ignores['files'] as $value) {
$finder->notName($value); $files->notName($value);
} }
foreach ($finder as $file) { $result = true;
$filename = rtrim($destination, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file->getRelativePathname();
// Filesystem Symfony // Filesystem Symfony
$fs = new Symfony\Component\Filesystem\Filesystem(); $fs = new Symfony\Component\Filesystem\Filesystem();
foreach ($files as $file) {
$filename = rtrim($destination, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file->getRelativePathname();
// Copia // Copia
try { try {
$fs->copy($file, $filename); $fs->copy($file, $filename);
} catch (Symfony\Component\Filesystem\Exception\IOException $e) { } catch (Symfony\Component\Filesystem\Exception\IOException $e) {
$result = false;
} }
} }
return true; return $resul;
}
/**
* 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;
}
} }
/** /**

View File

@ -2,6 +2,8 @@
include_once __DIR__.'/../../core.php'; include_once __DIR__.'/../../core.php';
use Util\Zip;
if (!setting('Attiva aggiornamenti')) { if (!setting('Attiva aggiornamenti')) {
die(tr('Accesso negato')); die(tr('Accesso negato'));
} }
@ -14,25 +16,7 @@ if (!extension_loaded('zip')) {
return; return;
} }
$file = $_FILES['blob']; $extraction_dir = Zip::extract($_FILES['blob']['tmp_name']);
$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();
// Aggiornamento del progetto // Aggiornamento del progetto
if (file_exists($extraction_dir.'/VERSION')) { if (file_exists($extraction_dir.'/VERSION')) {

View File

@ -47,53 +47,10 @@ if (filter('op') == 'restore') {
} }
if (post('folder') == null) { if (post('folder') == null) {
$file = $_FILES['blob']['tmp_name'] ?: post('zip'); $path = $_FILES['blob']['tmp_name'] ?: $backup_dir.'/'.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();
} else { } else {
$extraction_dir = $backup_dir.'/'.post('folder'); $path = $backup_dir.'/'.post('folder');
} }
// Rimozione del database Backup::restore($path, post('folder') == null);
$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');
} }

View File

@ -2,6 +2,8 @@
include_once __DIR__.'/../../core.php'; include_once __DIR__.'/../../core.php';
use Util\Zip;
switch (post('op')) { switch (post('op')) {
case 'export-bulk': case 'export-bulk':
$dir = DOCROOT.'/files/export_fatture/'; $dir = DOCROOT.'/files/export_fatture/';
@ -35,7 +37,7 @@ switch (post('op')) {
// Creazione zip // Creazione zip
if (extension_loaded('zip')) { if (extension_loaded('zip')) {
create_zip($dir.'tmp/', $file); Zip::create($dir.'tmp/', $file);
// Invio al browser dello zip // Invio al browser dello zip
download($file); download($file);

View File

@ -6,6 +6,8 @@ if (file_exists(__DIR__.'/../../../core.php')) {
include_once __DIR__.'/../../core.php'; include_once __DIR__.'/../../core.php';
} }
use Util\Zip;
include_once Modules::filepath('Fatture di vendita', 'modutil.php'); include_once Modules::filepath('Fatture di vendita', 'modutil.php');
switch (post('op')) { switch (post('op')) {
@ -42,7 +44,7 @@ switch (post('op')) {
// Creazione zip // Creazione zip
if (extension_loaded('zip')) { if (extension_loaded('zip')) {
create_zip($dir.'tmp/', $file); Zip::create($dir.'tmp/', $file);
// Invio al browser dello zip // Invio al browser dello zip
download($file); download($file);

View File

@ -1,5 +1,8 @@
<?php <?php
use Util\Zip;
use Ifsnop\Mysqldump\Mysqldump;
/** /**
* Classe per la gestione dei backup. * Classe per la gestione dei backup.
* *
@ -166,27 +169,20 @@ class Backup
], ],
]; ];
// Lista dei file da inserire nel backup
$files = Symfony\Component\Finder\Finder::create()
->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 // Creazione backup in formato ZIP
if (extension_loaded('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 // Creazione backup attraverso la copia dei file
else { else {
$result = self::folderBackup($files, $backup_dir.'/'.$backup_name); $result = copyr([
DOCROOT,
self::getDatabaseDirectory()
], $backup_dir.'/'.$backup_name.'.zip', $ignores);
} }
// Rimozione cartella temporanea // Rimozione cartella temporanea
@ -197,68 +193,6 @@ class Backup
return $result; 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. * Effettua il dump del database.
* *
@ -268,7 +202,7 @@ class Backup
{ {
$config = App::getConfig(); $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, 'add-drop-table' => true,
]); ]);
@ -290,4 +224,43 @@ class Backup
delete($backups[$i]); 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');
}
} }

140
src/Util/Zip.php Normal file
View File

@ -0,0 +1,140 @@
<?php
namespace Util;
use ZipArchive;
use Symfony\Component\Finder\Finder;
/**
* Classe dedicata alla gestione dei contenuti ZIP.
*
* @since 2.4.2
*/
class Zip
{
/**
* Controlla i requisiti per la gestione dei file ZIP.
*
* @return bool
*/
public static function requirements()
{
return extension_loaded('zip');
}
/**
* Estrae i contenuti di un file ZIP in una cartella temporanea.
*
* @param string $path
* @return string
*/
public static function extract($path)
{
// Lettura dell'archivio
$zip = new ZipArchive();
if (!$zip->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;
}
}
}