Merge pull request #13360 from mauriciofauth/zip-lib

Refactor zip functions into static methods
This commit is contained in:
Michal Čihař 2017-06-06 10:58:28 +02:00 committed by GitHub
commit 7c3cc91e70
5 changed files with 230 additions and 223 deletions

View File

@ -8,6 +8,7 @@
namespace PMA\libraries;
use PMA\libraries\config\ConfigFile;
use PMA\libraries\ZipExtension;
/**
* File wrapper class
@ -671,8 +672,7 @@ class File
*/
public function openZip($specific_entry = null)
{
include_once './libraries/zip_extension.lib.php';
$result = PMA_getZipContents($this->getName(), $specific_entry);
$result = ZipExtension::getContents($this->getName(), $specific_entry);
if (! empty($result['error'])) {
$this->_error_message = Message::rawError($result['error']);
return false;

201
libraries/ZipExtension.php Normal file
View File

@ -0,0 +1,201 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Interface for the zip extension
*
* @package PhpMyAdmin
*/
namespace PMA\libraries;
use ZipArchive;
/**
* Transformations class
*
* @package PhpMyAdmin
*/
class ZipExtension
{
/**
* Gets zip file contents
*
* @param string $file zip file
* @param string $specific_entry regular expression to match a file
*
* @return array ($error_message, $file_data); $error_message
* is empty if no error
*/
public static function getContents($file, $specific_entry = null)
{
$error_message = '';
$file_data = '';
$zip_handle = zip_open($file);
if (!is_resource($zip_handle)) {
$error_message = __('Error in ZIP archive:')
. ' ' . self::getError($zip_handle);
return (array('error' => $error_message, 'data' => $file_data));
}
$first_zip_entry = zip_read($zip_handle);
if (false === $first_zip_entry) {
$error_message = __('No files found inside ZIP archive!');
zip_close($zip_handle);
return (array('error' => $error_message, 'data' => $file_data));
}
/* Is the the zip really an ODS file? */
$read = zip_entry_read($first_zip_entry);
$ods_mime = 'application/vnd.oasis.opendocument.spreadsheet';
if (!strcmp($ods_mime, $read)) {
$specific_entry = '/^content\.xml$/';
}
if (!isset($specific_entry)) {
zip_entry_open($zip_handle, $first_zip_entry, 'r');
/* File pointer has already been moved,
* so include what was read above */
$file_data = $read;
$file_data .= zip_entry_read(
$first_zip_entry,
zip_entry_filesize($first_zip_entry)
);
zip_entry_close($first_zip_entry);
zip_close($zip_handle);
return (array('error' => $error_message, 'data' => $file_data));
}
/* Return the correct contents, not just the first entry */
for ( ; ; ) {
$entry = zip_read($zip_handle);
if (is_resource($entry)) {
if (preg_match($specific_entry, zip_entry_name($entry))) {
zip_entry_open($zip_handle, $entry, 'r');
$file_data = zip_entry_read(
$entry,
zip_entry_filesize($entry)
);
zip_entry_close($entry);
break;
}
} else {
/**
* Either we have reached the end of the zip and still
* haven't found $specific_entry or there was a parsing
* error that we must display
*/
if ($entry === false) {
$error_message = __('Error in ZIP archive:')
. ' Could not find "' . $specific_entry . '"';
} else {
$error_message = __('Error in ZIP archive:')
. ' ' . self::getError($zip_handle);
}
break;
}
}
zip_close($zip_handle);
return (array('error' => $error_message, 'data' => $file_data));
}
/**
* Returns the file name of the first file that matches the given $file_regexp.
*
* @param string $file_regexp regular expression for the file name to match
* @param string $file zip archive
*
* @return string the file name of the first file that matches the given regexp
*/
public static function findFile($file_regexp, $file)
{
$zip_handle = zip_open($file);
if (is_resource($zip_handle)) {
$entry = zip_read($zip_handle);
while (is_resource($entry)) {
if (preg_match($file_regexp, zip_entry_name($entry))) {
$file_name = zip_entry_name($entry);
zip_close($zip_handle);
return $file_name;
}
$entry = zip_read($zip_handle);
}
}
zip_close($zip_handle);
return false;
}
/**
* Returns the number of files in the zip archive.
*
* @param string $file zip archive
*
* @return int the number of files in the zip archive
*/
public static function getNumberOfFiles($file)
{
$count = 0;
$zip_handle = zip_open($file);
if (is_resource($zip_handle)) {
$entry = zip_read($zip_handle);
while (is_resource($entry)) {
$count++;
$entry = zip_read($zip_handle);
}
zip_close($zip_handle);
}
return $count;
}
/**
* Extracts a set of files from the given zip archive to a given destinations.
*
* @param string $zip_path path to the zip archive
* @param string $entry file in the archive that should be extracted
*
* @return string|bool data on sucess, false otherwise
*/
public static function extract($zip_path, $entry)
{
$zip = new ZipArchive;
if ($zip->open($zip_path) === true) {
$result = $zip->getFromName($entry);
$zip->close();
return $result;
}
return false;
}
/**
* Gets zip error message
*
* @param resource $code error code
*
* @return string error message
*/
public static function getError($code)
{
// I don't think this needs translation
switch ($code) {
case ZIPARCHIVE::ER_MULTIDISK:
$message = 'Multi-disk zip archives not supported';
break;
case ZIPARCHIVE::ER_READ:
$message = 'Read error';
break;
case ZIPARCHIVE::ER_CRC:
$message = 'CRC error';
break;
case ZIPARCHIVE::ER_NOZIP:
$message = 'Not a zip archive';
break;
case ZIPARCHIVE::ER_INCONS:
$message = 'Zip archive inconsistent';
break;
default:
$message = $code;
}
return $message;
}
}

View File

@ -16,6 +16,7 @@ use PMA\libraries\gis\GISMultilinestring;
use PMA\libraries\gis\GISMultipoint;
use PMA\libraries\gis\GISPoint;
use PMA\libraries\gis\GISPolygon;
use PMA\libraries\ZipExtension;
/**
* Handles the import for ESRI Shape files
@ -70,7 +71,7 @@ class ImportShp extends ImportPlugin
// If the zip archive has more than one file,
// get the correct content to the buffer from .shp file.
if ($compression == 'application/zip'
&& PMA_getNoOfFilesInZip($import_file) > 1
&& ZipExtension::getNumberOfFiles($import_file) > 1
) {
if ($GLOBALS['import_handle']->openZip('/^.*\.shp$/i') === false) {
$message = PMA\libraries\Message::error(
@ -89,14 +90,14 @@ class ImportShp extends ImportPlugin
// If we can extract the zip archive to 'TempDir'
// and use the files in it for import
if ($compression == 'application/zip' && ! is_null($temp)) {
$dbf_file_name = PMA_findFileFromZipArchive(
$dbf_file_name = ZipExtension::findFile(
'/^.*\.dbf$/i',
$import_file
);
// If the corresponding .dbf file is in the zip archive
if ($dbf_file_name) {
// Extract the .dbf file and point to it.
$extracted = PMA_zipExtract(
$extracted = ZipExtension::extract(
$import_file,
$dbf_file_name
);

View File

@ -1,192 +0,0 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Interface for the zip extension
*
* @package PhpMyAdmin
*/
if (! defined('PHPMYADMIN')) {
exit;
}
/**
* Gets zip file contents
*
* @param string $file zip file
* @param string $specific_entry regular expression to match a file
*
* @return array ($error_message, $file_data); $error_message
* is empty if no error
*/
function PMA_getZipContents($file, $specific_entry = null)
{
$error_message = '';
$file_data = '';
$zip_handle = zip_open($file);
if (!is_resource($zip_handle)) {
$error_message = __('Error in ZIP archive:')
. ' ' . PMA_getZipError($zip_handle);
return (array('error' => $error_message, 'data' => $file_data));
}
$first_zip_entry = zip_read($zip_handle);
if (false === $first_zip_entry) {
$error_message = __('No files found inside ZIP archive!');
zip_close($zip_handle);
return (array('error' => $error_message, 'data' => $file_data));
}
/* Is the the zip really an ODS file? */
$read = zip_entry_read($first_zip_entry);
$ods_mime = 'application/vnd.oasis.opendocument.spreadsheet';
if (!strcmp($ods_mime, $read)) {
$specific_entry = '/^content\.xml$/';
}
if (!isset($specific_entry)) {
zip_entry_open($zip_handle, $first_zip_entry, 'r');
/* File pointer has already been moved,
* so include what was read above */
$file_data = $read;
$file_data .= zip_entry_read(
$first_zip_entry,
zip_entry_filesize($first_zip_entry)
);
zip_entry_close($first_zip_entry);
zip_close($zip_handle);
return (array('error' => $error_message, 'data' => $file_data));
}
/* Return the correct contents, not just the first entry */
for ( ; ; ) {
$entry = zip_read($zip_handle);
if (is_resource($entry)) {
if (preg_match($specific_entry, zip_entry_name($entry))) {
zip_entry_open($zip_handle, $entry, 'r');
$file_data = zip_entry_read(
$entry,
zip_entry_filesize($entry)
);
zip_entry_close($entry);
break;
}
} else {
/**
* Either we have reached the end of the zip and still
* haven't found $specific_entry or there was a parsing
* error that we must display
*/
if ($entry === false) {
$error_message = __('Error in ZIP archive:')
. ' Could not find "' . $specific_entry . '"';
} else {
$error_message = __('Error in ZIP archive:')
. ' ' . PMA_getZipError($zip_handle);
}
break;
}
}
zip_close($zip_handle);
return (array('error' => $error_message, 'data' => $file_data));
}
/**
* Returns the file name of the first file that matches the given $file_regexp.
*
* @param string $file_regexp regular expression for the file name to match
* @param string $file zip archive
*
* @return string the file name of the first file that matches the given regexp
*/
function PMA_findFileFromZipArchive($file_regexp, $file)
{
$zip_handle = zip_open($file);
if (is_resource($zip_handle)) {
$entry = zip_read($zip_handle);
while (is_resource($entry)) {
if (preg_match($file_regexp, zip_entry_name($entry))) {
$file_name = zip_entry_name($entry);
zip_close($zip_handle);
return $file_name;
}
$entry = zip_read($zip_handle);
}
}
zip_close($zip_handle);
return false;
}
/**
* Returns the number of files in the zip archive.
*
* @param string $file zip archive
*
* @return int the number of files in the zip archive
*/
function PMA_getNoOfFilesInZip($file)
{
$count = 0;
$zip_handle = zip_open($file);
if (is_resource($zip_handle)) {
$entry = zip_read($zip_handle);
while (is_resource($entry)) {
$count++;
$entry = zip_read($zip_handle);
}
zip_close($zip_handle);
}
return $count;
}
/**
* Extracts a set of files from the given zip archive to a given destinations.
*
* @param string $zip_path path to the zip archive
* @param string $entry file in the archive that should be extracted
*
* @return string|bool data on sucess, false otherwise
*/
function PMA_zipExtract($zip_path, $entry)
{
$zip = new ZipArchive;
if ($zip->open($zip_path) === true) {
$result = $zip->getFromName($entry);
$zip->close();
return $result;
}
return false;
}
/**
* Gets zip error message
*
* @param resource $code error code
*
* @return string error message
*/
function PMA_getZipError($code)
{
// I don't think this needs translation
switch ($code) {
case ZIPARCHIVE::ER_MULTIDISK:
$message = 'Multi-disk zip archives not supported';
break;
case ZIPARCHIVE::ER_READ:
$message = 'Read error';
break;
case ZIPARCHIVE::ER_CRC:
$message = 'CRC error';
break;
case ZIPARCHIVE::ER_NOZIP:
$message = 'Not a zip archive';
break;
case ZIPARCHIVE::ER_INCONS:
$message = 'Zip archive inconsistent';
break;
default:
$message = $code;
}
return $message;
}

View File

@ -5,18 +5,16 @@
* @package PhpMyAdmin-test
*/
/*
* Include to test.
*/
use PMA\libraries\ZipExtension;
require_once 'libraries/zip_extension.lib.php';
require_once 'test/PMATestCase.php';
/**
* Tests zip extension usage.
*
* @package PhpMyAdmin-test
*/
class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
class ZipExtensionTest extends PMATestCase
{
/**
* Test zip file content
@ -25,13 +23,13 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
* @param string $specific_entry regular expression to match a file
* @param mixed $output expected output
*
* @dataProvider providerForTestGetZipContents
* @dataProvider provideTestGetContents
* @return void
*/
public function testGetZipContents($file, $specific_entry, $output)
public function testGetContents($file, $specific_entry, $output)
{
$this->assertEquals(
PMA_getZipContents($file, $specific_entry),
ZipExtension::getContents($file, $specific_entry),
$output
);
}
@ -41,7 +39,7 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
*
* @return array
*/
public function providerForTestGetZipContents()
public function provideTestGetContents()
{
return array(
array(
@ -70,13 +68,13 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
* @param string $file zip archive
* @param mixed $output expected output
*
* @dataProvider providerForTestFindFileFromZipArchive
* @dataProvider provideTestFindFile
* @return void
*/
public function testFindFileFromZipArchive($file_regexp, $file, $output)
public function testFindFile($file_regexp, $file, $output)
{
$this->assertEquals(
PMA_findFileFromZipArchive($file_regexp, $file),
ZipExtension::findFile($file_regexp, $file),
$output
);
}
@ -86,7 +84,7 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
*
* @return array Test data
*/
public function providerForTestFindFileFromZipArchive()
public function provideTestFindFile()
{
return array(
array(
@ -98,52 +96,52 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
}
/**
* Test for PMA_getNoOfFilesInZip
* Test for ZipExtension::getNumberOfFiles
*
* @return void
*/
public function testGetNoOfFilesInZip()
public function testGetNumberOfFiles()
{
$this->assertEquals(
PMA_getNoOfFilesInZip('./test/test_data/test.zip'),
ZipExtension::getNumberOfFiles('./test/test_data/test.zip'),
1
);
}
/**
* Test for PMA_zipExtract
* Test for ZipExtension::extract
*
* @return void
*/
public function testZipExtract()
public function testExtract()
{
$this->assertEquals(
false,
PMA_zipExtract(
ZipExtension::extract(
'./test/test_data/test.zip', 'wrongName'
)
);
$this->assertEquals(
"TEST FILE\n",
PMA_zipExtract(
ZipExtension::extract(
'./test/test_data/test.zip', 'test.file'
)
);
}
/**
* Test for PMA_getZipError
* Test for ZipExtension::getError
*
* @param int $code error code
* @param mixed $output expected output
*
* @dataProvider providerForTestGetZipError
* @dataProvider provideTestGetError
* @return void
*/
public function testGetZipError($code, $output)
public function testGetError($code, $output)
{
$this->assertEquals(
PMA_getZipError($code),
ZipExtension::getError($code),
$output
);
}
@ -153,7 +151,7 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
*
* @return array
*/
public function providerForTestGetZipError()
public function provideTestGetError()
{
return array(
array(
@ -183,4 +181,3 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
);
}
}