Merge pull request #13464 from WeeRox/master
Refactor ZipExtension and ZipFile to use ZipArchive
This commit is contained in:
commit
1c2ca25aed
@ -7,7 +7,7 @@
|
||||
*/
|
||||
namespace PhpMyAdmin;
|
||||
|
||||
use PhpMyAdmin\ZipFile;
|
||||
use PhpMyAdmin\ZipExtension;
|
||||
|
||||
/**
|
||||
* Simplfied OpenDocument creator class
|
||||
@ -38,10 +38,9 @@ EOT;
|
||||
*/
|
||||
public static function create($mime, $data)
|
||||
{
|
||||
$zipfile = new ZipFile();
|
||||
$zipfile -> addFile($mime, 'mimetype');
|
||||
$zipfile -> addFile($data, 'content.xml');
|
||||
$zipfile -> addFile(
|
||||
$data = array(
|
||||
$mime,
|
||||
$data,
|
||||
'<?xml version="1.0" encoding="UTF-8"?' . '>'
|
||||
. '<office:document-meta '
|
||||
. 'xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" '
|
||||
@ -55,9 +54,6 @@ EOT;
|
||||
. '</meta:creation-date>'
|
||||
. '</office:meta>'
|
||||
. '</office:document-meta>',
|
||||
'meta.xml'
|
||||
);
|
||||
$zipfile -> addFile(
|
||||
'<?xml version="1.0" encoding="UTF-8"?' . '>'
|
||||
. '<office:document-styles ' . OpenDocument::NS
|
||||
. ' office:version="1.0">'
|
||||
@ -153,9 +149,6 @@ EOT;
|
||||
. '<style:master-page style:name="Standard" style:page-layout-name="pm1"/>'
|
||||
. '</office:master-styles>'
|
||||
. '</office:document-styles>',
|
||||
'styles.xml'
|
||||
);
|
||||
$zipfile -> addFile(
|
||||
'<?xml version="1.0" encoding="UTF-8"?' . '>'
|
||||
. '<manifest:manifest'
|
||||
. ' xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">'
|
||||
@ -167,9 +160,17 @@ EOT;
|
||||
. ' manifest:full-path="meta.xml"/>'
|
||||
. '<manifest:file-entry manifest:media-type="text/xml"'
|
||||
. ' manifest:full-path="styles.xml"/>'
|
||||
. '</manifest:manifest>',
|
||||
. '</manifest:manifest>'
|
||||
);
|
||||
|
||||
$name = array(
|
||||
'mimetype',
|
||||
'content.xml',
|
||||
'meta.xml',
|
||||
'styles.xml',
|
||||
'META-INF/manifest.xml'
|
||||
);
|
||||
return $zipfile -> file();
|
||||
|
||||
return ZipExtension::createFile($data, $name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ class ZipExtension
|
||||
/**
|
||||
* Gets zip file contents
|
||||
*
|
||||
* @param string $file zip file
|
||||
* @param string $file path to zip file
|
||||
* @param string $specific_entry regular expression to match a file
|
||||
*
|
||||
* @return array ($error_message, $file_data); $error_message
|
||||
@ -27,138 +27,117 @@ class ZipExtension
|
||||
*/
|
||||
public static function getContents($file, $specific_entry = null)
|
||||
{
|
||||
/**
|
||||
* This function is used to "import" a SQL file which has been exported earlier
|
||||
* That means that this function works on the assumption that the zip file contains only a single SQL file
|
||||
* It might also be an ODS file, look below
|
||||
*/
|
||||
|
||||
$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));
|
||||
}
|
||||
$zip = new ZipArchive;
|
||||
$res = $zip->open($file);
|
||||
|
||||
/* 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 ($res === TRUE) {
|
||||
if ($zip->numFiles === 0) {
|
||||
$error_message = __('No files found inside ZIP archive!');
|
||||
$zip->close();
|
||||
return (array('error' => $error_message, 'data' => $file_data));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
/* Is the the zip really an ODS file? */
|
||||
$ods_mime = 'application/vnd.oasis.opendocument.spreadsheet';
|
||||
$first_zip_entry = $zip->getFromIndex(0);
|
||||
if (!strcmp($ods_mime, $first_zip_entry)) {
|
||||
$specific_entry = '/^content\.xml$/';
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (!isset($specific_entry)) {
|
||||
$file_data = $first_zip_entry;
|
||||
$zip->close();
|
||||
return (array('error' => $error_message, 'data' => $file_data));
|
||||
}
|
||||
|
||||
/* Return the correct contents, not just the first entry */
|
||||
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||
if (@preg_match($specific_entry, $zip->getNameIndex($i))) {
|
||||
$file_data = $zip->getFromIndex($i);
|
||||
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));
|
||||
/* Couldn't find any files that matched $specific_entry */
|
||||
if (empty($file_data)) {
|
||||
$error_message = __('Error in ZIP archive:')
|
||||
. ' Could not find "' . $specific_entry . '"';
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
return (array('error' => $error_message, 'data' => $file_data));
|
||||
} else {
|
||||
$error_message = __('Error in ZIP archive:') . ' ' . $zip->getStatusString();
|
||||
$zip->close();
|
||||
return (array('error' => $error_message, 'data' => $file_data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file name of the first file that matches the given $file_regexp.
|
||||
* Returns the filename 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
|
||||
* @param string $file path to zip file
|
||||
* @param string $regex regular expression for the file name to match
|
||||
*
|
||||
* @return string the file name of the first file that matches the given regexp
|
||||
* @return string the file name of the first file that matches the given regular expression
|
||||
*/
|
||||
public static function findFile($file_regexp, $file)
|
||||
public static function findFile($file, $regex)
|
||||
{
|
||||
$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;
|
||||
$zip = new ZipArchive;
|
||||
$res = $zip->open($file);
|
||||
|
||||
if ($res === TRUE) {
|
||||
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||
if (preg_match($regex, $zip->getNameIndex($i))) {
|
||||
$filename = $zip->getNameIndex($i);
|
||||
$zip->close();
|
||||
return $filename;
|
||||
}
|
||||
$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
|
||||
* @param string $file path to zip file
|
||||
*
|
||||
* @return int the number of files in the zip archive
|
||||
* @return int the number of files in the zip archive or 0, either if there wern't any files or an error occured.
|
||||
*/
|
||||
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);
|
||||
$num = 0;
|
||||
$zip = new ZipArchive;
|
||||
$res = $zip->open($file);
|
||||
|
||||
if ($res === TRUE) {
|
||||
$num = $zip->numFiles;
|
||||
}
|
||||
return $count;
|
||||
return $num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a set of files from the given zip archive to a given destinations.
|
||||
* Extracts the content of $entry.
|
||||
*
|
||||
* @param string $zip_path path to the zip archive
|
||||
* @param string $entry file in the archive that should be extracted
|
||||
* @param string $file path to zip file
|
||||
* @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)
|
||||
public static function extract($file, $entry)
|
||||
{
|
||||
$zip = new ZipArchive;
|
||||
if ($zip->open($zip_path) === true) {
|
||||
if ($zip->open($file) === true) {
|
||||
$result = $zip->getFromName($entry);
|
||||
$zip->close();
|
||||
return $result;
|
||||
@ -167,34 +146,128 @@ class ZipExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets zip error message
|
||||
*
|
||||
* @param resource $code error code
|
||||
*
|
||||
* @return string error message
|
||||
* Creates a zip file.
|
||||
* If $data is an array and $name is a string, the filenames will be indexed.
|
||||
* The function will return false if $data is a string but $name is an array or if $data is an array and $name is an array, but they don't have the same amount of elements.
|
||||
*
|
||||
* @param array|string $data contents of the file/files
|
||||
* @param array|string $name name of the file/files in the archive
|
||||
* @param integer $time the current timestamp
|
||||
*
|
||||
* @return string|bool the ZIP file contents, or false if there was an error.
|
||||
*/
|
||||
public static function getError($code)
|
||||
public static function createFile($data, $name, $time = 0)
|
||||
{
|
||||
// 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;
|
||||
$datasec = array(); // Array to store compressed data
|
||||
$ctrl_dir = array(); // Central directory
|
||||
$old_offset = 0; // Last offset position
|
||||
$eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; // End of central directory record
|
||||
$index = false; // Whether or not to index files
|
||||
|
||||
if (count($name) === 1) {
|
||||
$index = true;
|
||||
$name = str_replace('\\', '/', $name);
|
||||
$extension_pos = strpos($name, '.');
|
||||
$extension = substr($name, $extension_pos);
|
||||
$name = substr($name, 0, -$extension_pos - 1);
|
||||
} else {
|
||||
if (count($name) != count($data)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $message;
|
||||
|
||||
for ($i = 0; $i < count($data); $i++) {
|
||||
if ($index) {
|
||||
$temp_name = $name . '_' . $i . $extension;
|
||||
} else {
|
||||
$temp_name = str_replace('\\', '/', $name[$i]);
|
||||
}
|
||||
|
||||
/* Convert Unix timestamp to DOS timestamp */
|
||||
$timearray = ($time == 0) ? getdate() : getdate($time);
|
||||
|
||||
if ($timearray['year'] < 1980) {
|
||||
$timearray['year'] = 1980;
|
||||
$timearray['mon'] = 1;
|
||||
$timearray['mday'] = 1;
|
||||
$timearray['hours'] = 0;
|
||||
$timearray['minutes'] = 0;
|
||||
$timearray['seconds'] = 0;
|
||||
}
|
||||
|
||||
$time = (($timearray['year'] - 1980) << 25)
|
||||
| ($timearray['mon'] << 21)
|
||||
| ($timearray['mday'] << 16)
|
||||
| ($timearray['hours'] << 11)
|
||||
| ($timearray['minutes'] << 5)
|
||||
| ($timearray['seconds'] >> 1);
|
||||
|
||||
$hexdtime = pack('V', $time);
|
||||
|
||||
$fr = "\x50\x4b\x03\x04";
|
||||
$fr .= "\x14\x00"; // ver needed to extract
|
||||
$fr .= "\x00\x00"; // gen purpose bit flag
|
||||
$fr .= "\x08\x00"; // compression method
|
||||
$fr .= $hexdtime; // last mod time and date
|
||||
|
||||
// "local file header" segment
|
||||
$unc_len = strlen($data[$i]);
|
||||
$crc = crc32($data[$i]);
|
||||
$zdata = gzcompress($data[$i]);
|
||||
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
|
||||
$c_len = strlen($zdata);
|
||||
$fr .= pack('V', $crc); // crc32
|
||||
$fr .= pack('V', $c_len); // compressed filesize
|
||||
$fr .= pack('V', $unc_len); // uncompressed filesize
|
||||
$fr .= pack('v', strlen($temp_name)); // length of filename
|
||||
$fr .= pack('v', 0); // extra field length
|
||||
$fr .= $temp_name;
|
||||
|
||||
// "file data" segment
|
||||
$fr .= $zdata;
|
||||
|
||||
$datasec[] = $fr;
|
||||
|
||||
// now add to central directory record
|
||||
$cdrec = "\x50\x4b\x01\x02";
|
||||
$cdrec .= "\x00\x00"; // version made by
|
||||
$cdrec .= "\x14\x00"; // version needed to extract
|
||||
$cdrec .= "\x00\x00"; // gen purpose bit flag
|
||||
$cdrec .= "\x08\x00"; // compression method
|
||||
$cdrec .= $hexdtime; // last mod time & date
|
||||
$cdrec .= pack('V', $crc); // crc32
|
||||
$cdrec .= pack('V', $c_len); // compressed filesize
|
||||
$cdrec .= pack('V', $unc_len); // uncompressed filesize
|
||||
$cdrec .= pack('v', strlen($temp_name)); // length of filename
|
||||
$cdrec .= pack('v', 0); // extra field length
|
||||
$cdrec .= pack('v', 0); // file comment length
|
||||
$cdrec .= pack('v', 0); // disk number start
|
||||
$cdrec .= pack('v', 0); // internal file attributes
|
||||
$cdrec .= pack('V', 32); // external file attributes
|
||||
// - 'archive' bit set
|
||||
|
||||
$cdrec .= pack('V', $old_offset); // relative offset of local header
|
||||
$old_offset += strlen($fr);
|
||||
|
||||
$cdrec .= $temp_name;
|
||||
|
||||
// optional extra field, file comment goes here
|
||||
// save to central directory
|
||||
$ctrl_dir[] = $cdrec;
|
||||
}
|
||||
|
||||
/* Build string to return */
|
||||
$temp_ctrldir = implode('', $ctrl_dir);
|
||||
$header = $temp_ctrldir .
|
||||
$eof_ctrl_dir .
|
||||
pack('v', sizeof($ctrl_dir)) . //total #of entries "on this disk"
|
||||
pack('v', sizeof($ctrl_dir)) . //total #of entries overall
|
||||
pack('V', strlen($temp_ctrldir)) . //size of central dir
|
||||
pack('V', $old_offset) . //offset to start of central dir
|
||||
"\x00\x00"; //.zip file comment length
|
||||
|
||||
$data = implode('', $datasec);
|
||||
|
||||
return $data . $header;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,202 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Zip file creation
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
namespace PhpMyAdmin;
|
||||
|
||||
/**
|
||||
* Zip file creation class.
|
||||
* Makes zip files.
|
||||
*
|
||||
* @access public
|
||||
* @package PhpMyAdmin
|
||||
* @see Official ZIP file format: https://www.pkware.com/support/zip-app-note
|
||||
*/
|
||||
class ZipFile
|
||||
{
|
||||
/**
|
||||
* Whether to echo zip as it's built or return as string from -> file
|
||||
*
|
||||
* @var boolean $doWrite
|
||||
*/
|
||||
var $doWrite = false;
|
||||
/**
|
||||
* Array to store compressed data
|
||||
*
|
||||
* @var array $datasec
|
||||
*/
|
||||
var $datasec = array();
|
||||
/**
|
||||
* Central directory
|
||||
*
|
||||
* @var array $ctrl_dir
|
||||
*/
|
||||
var $ctrl_dir = array();
|
||||
/**
|
||||
* End of central directory record
|
||||
*
|
||||
* @var string $eof_ctrl_dir
|
||||
*/
|
||||
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
|
||||
/**
|
||||
* Last offset position
|
||||
*
|
||||
* @var integer $old_offset
|
||||
*/
|
||||
var $old_offset = 0;
|
||||
|
||||
/**
|
||||
* Sets member variable this -> doWrite to true
|
||||
* - Should be called immediately after class instantiation
|
||||
* - If set to true, then ZIP archive are echo'ed to STDOUT as each
|
||||
* file is added via this -> addfile(), and central directories are
|
||||
* echoed to STDOUT on final call to this -> file(). Also,
|
||||
* this -> file() returns an empty string so it is safe to issue a
|
||||
* "echo $zipfile;" command
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function setDoWrite()
|
||||
{
|
||||
$this->doWrite = true;
|
||||
} // end of the 'setDoWrite()' method
|
||||
|
||||
/**
|
||||
* Converts an Unix timestamp to a four byte DOS date and time format (date
|
||||
* in high two bytes, time in low two bytes allowing magnitude comparison).
|
||||
*
|
||||
* @param integer $unixtime the current Unix timestamp
|
||||
*
|
||||
* @return integer the current date in a four byte DOS format
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
function unix2DosTime($unixtime = 0)
|
||||
{
|
||||
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
|
||||
|
||||
if ($timearray['year'] < 1980) {
|
||||
$timearray['year'] = 1980;
|
||||
$timearray['mon'] = 1;
|
||||
$timearray['mday'] = 1;
|
||||
$timearray['hours'] = 0;
|
||||
$timearray['minutes'] = 0;
|
||||
$timearray['seconds'] = 0;
|
||||
} // end if
|
||||
|
||||
return (($timearray['year'] - 1980) << 25)
|
||||
| ($timearray['mon'] << 21)
|
||||
| ($timearray['mday'] << 16)
|
||||
| ($timearray['hours'] << 11)
|
||||
| ($timearray['minutes'] << 5)
|
||||
| ($timearray['seconds'] >> 1);
|
||||
} // end of the 'unix2DosTime()' method
|
||||
|
||||
/**
|
||||
* Adds "file" to archive
|
||||
*
|
||||
* @param string $data file contents
|
||||
* @param string $name name of the file in the archive (may contains the path)
|
||||
* @param integer $time the current timestamp
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function addFile($data, $name, $time = 0)
|
||||
{
|
||||
$name = str_replace('\\', '/', $name);
|
||||
|
||||
$hexdtime = pack('V', $this->unix2DosTime($time));
|
||||
|
||||
$fr = "\x50\x4b\x03\x04";
|
||||
$fr .= "\x14\x00"; // ver needed to extract
|
||||
$fr .= "\x00\x00"; // gen purpose bit flag
|
||||
$fr .= "\x08\x00"; // compression method
|
||||
$fr .= $hexdtime; // last mod time and date
|
||||
|
||||
// "local file header" segment
|
||||
$unc_len = strlen($data);
|
||||
$crc = crc32($data);
|
||||
$zdata = gzcompress($data);
|
||||
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
|
||||
$c_len = strlen($zdata);
|
||||
$fr .= pack('V', $crc); // crc32
|
||||
$fr .= pack('V', $c_len); // compressed filesize
|
||||
$fr .= pack('V', $unc_len); // uncompressed filesize
|
||||
$fr .= pack('v', strlen($name)); // length of filename
|
||||
$fr .= pack('v', 0); // extra field length
|
||||
$fr .= $name;
|
||||
|
||||
// "file data" segment
|
||||
$fr .= $zdata;
|
||||
|
||||
// echo this entry on the fly, ...
|
||||
if ($this->doWrite) {
|
||||
echo $fr;
|
||||
} else { // ... OR add this entry to array
|
||||
$this->datasec[] = $fr;
|
||||
}
|
||||
|
||||
// now add to central directory record
|
||||
$cdrec = "\x50\x4b\x01\x02";
|
||||
$cdrec .= "\x00\x00"; // version made by
|
||||
$cdrec .= "\x14\x00"; // version needed to extract
|
||||
$cdrec .= "\x00\x00"; // gen purpose bit flag
|
||||
$cdrec .= "\x08\x00"; // compression method
|
||||
$cdrec .= $hexdtime; // last mod time & date
|
||||
$cdrec .= pack('V', $crc); // crc32
|
||||
$cdrec .= pack('V', $c_len); // compressed filesize
|
||||
$cdrec .= pack('V', $unc_len); // uncompressed filesize
|
||||
$cdrec .= pack('v', strlen($name)); // length of filename
|
||||
$cdrec .= pack('v', 0); // extra field length
|
||||
$cdrec .= pack('v', 0); // file comment length
|
||||
$cdrec .= pack('v', 0); // disk number start
|
||||
$cdrec .= pack('v', 0); // internal file attributes
|
||||
$cdrec .= pack('V', 32); // external file attributes
|
||||
// - 'archive' bit set
|
||||
|
||||
$cdrec .= pack('V', $this->old_offset); // relative offset of local header
|
||||
$this->old_offset += strlen($fr);
|
||||
|
||||
$cdrec .= $name;
|
||||
|
||||
// optional extra field, file comment goes here
|
||||
// save to central directory
|
||||
$this->ctrl_dir[] = $cdrec;
|
||||
} // end of the 'addFile()' method
|
||||
|
||||
/**
|
||||
* Echo central dir if ->doWrite==true, else build string to return
|
||||
*
|
||||
* @return string if ->doWrite {empty string} else the ZIP file contents
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function file()
|
||||
{
|
||||
$ctrldir = implode('', $this->ctrl_dir);
|
||||
$header = $ctrldir .
|
||||
$this->eof_ctrl_dir .
|
||||
pack('v', sizeof($this->ctrl_dir)) . //total #of entries "on this disk"
|
||||
pack('v', sizeof($this->ctrl_dir)) . //total #of entries overall
|
||||
pack('V', strlen($ctrldir)) . //size of central dir
|
||||
pack('V', $this->old_offset) . //offset to start of central dir
|
||||
"\x00\x00"; //.zip file comment length
|
||||
|
||||
if ($this->doWrite) { // Send central directory & end ctrl dir to STDOUT
|
||||
echo $header;
|
||||
|
||||
return ""; // Return empty string
|
||||
} else { // Return entire ZIP archive as string
|
||||
$data = implode('', $this->datasec);
|
||||
|
||||
return $data . $header;
|
||||
}
|
||||
} // end of the 'file()' method
|
||||
} // end of the 'PhpMyAdmin\ZipFile' class
|
||||
@ -10,7 +10,7 @@ use PhpMyAdmin\Encoding;
|
||||
use PhpMyAdmin\Message;
|
||||
use PMA\libraries\plugins\ExportPlugin;
|
||||
use PhpMyAdmin\Table;
|
||||
use PhpMyAdmin\ZipFile;
|
||||
use PhpMyAdmin\ZipExtension;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Sanitize;
|
||||
|
||||
@ -405,24 +405,7 @@ function PMA_compressExport($dump_buffer, $compression, $filename)
|
||||
{
|
||||
if ($compression == 'zip' && @function_exists('gzcompress')) {
|
||||
$filename = substr($filename, 0, -4); // remove extension (.zip)
|
||||
$zipfile = new ZipFile();
|
||||
if (is_array($dump_buffer)) {
|
||||
foreach ($dump_buffer as $table => $dump) {
|
||||
$ext_pos = strpos($filename, '.');
|
||||
$extension = substr($filename, $ext_pos);
|
||||
$zipfile->addFile(
|
||||
$dump,
|
||||
str_replace(
|
||||
$extension,
|
||||
'_' . $table . $extension,
|
||||
$filename
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$zipfile->addFile($dump_buffer, $filename);
|
||||
}
|
||||
$dump_buffer = $zipfile->file();
|
||||
$dump_buffer = ZipExtension::createFile($dump_buffer, $filename);
|
||||
} elseif ($compression == 'gzip' && PMA_gzencodeNeeded()) {
|
||||
// without the optional parameter level because it bugs
|
||||
$dump_buffer = gzencode($dump_buffer);
|
||||
|
||||
@ -92,8 +92,8 @@ class ImportShp extends ImportPlugin
|
||||
// and use the files in it for import
|
||||
if ($compression == 'application/zip' && ! is_null($temp)) {
|
||||
$dbf_file_name = ZipExtension::findFile(
|
||||
'/^.*\.dbf$/i',
|
||||
$import_file
|
||||
$import_file,
|
||||
'/^.*\.dbf$/i'
|
||||
);
|
||||
// If the corresponding .dbf file is in the zip archive
|
||||
if ($dbf_file_name) {
|
||||
|
||||
@ -17,9 +17,9 @@ require_once 'test/PMATestCase.php';
|
||||
class ZipExtensionTest extends PMATestCase
|
||||
{
|
||||
/**
|
||||
* Test zip file content
|
||||
* Test for ZipExtension::getContents
|
||||
*
|
||||
* @param string $file zip file
|
||||
* @param string $file path to zip file
|
||||
* @param string $specific_entry regular expression to match a file
|
||||
* @param mixed $output expected output
|
||||
*
|
||||
@ -62,19 +62,19 @@ class ZipExtensionTest extends PMATestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Find file in Zip Archive
|
||||
* Test for ZipExtension::findFile
|
||||
*
|
||||
* @param string $file path to zip file
|
||||
* @param string $file_regexp regular expression for the file name to match
|
||||
* @param string $file zip archive
|
||||
* @param mixed $output expected output
|
||||
*
|
||||
* @dataProvider provideTestFindFile
|
||||
* @return void
|
||||
*/
|
||||
public function testFindFile($file_regexp, $file, $output)
|
||||
public function testFindFile($file, $file_regexp, $output)
|
||||
{
|
||||
$this->assertEquals(
|
||||
ZipExtension::findFile($file_regexp, $file),
|
||||
ZipExtension::findFile($file, $file_regexp),
|
||||
$output
|
||||
);
|
||||
}
|
||||
@ -88,8 +88,8 @@ class ZipExtensionTest extends PMATestCase
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'/test/',
|
||||
'./test/test_data/test.zip',
|
||||
'/test/',
|
||||
'test.file'
|
||||
)
|
||||
);
|
||||
@ -130,54 +130,20 @@ class ZipExtensionTest extends PMATestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for ZipExtension::getError
|
||||
* Test for ZipExtension::createFile
|
||||
*
|
||||
* @param int $code error code
|
||||
* @param mixed $output expected output
|
||||
*
|
||||
* @dataProvider provideTestGetError
|
||||
* @return void
|
||||
*/
|
||||
public function testGetError($code, $output)
|
||||
public function testCreateFile()
|
||||
{
|
||||
$this->assertEquals(
|
||||
ZipExtension::getError($code),
|
||||
$output
|
||||
);
|
||||
}
|
||||
$file = ZipExtension::createFile("Test content", "test.txt");
|
||||
$this->assertTrue(!empty($file));
|
||||
|
||||
/**
|
||||
* Provider for testGetZipError
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provideTestGetError()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
1,
|
||||
'Multi-disk zip archives not supported'
|
||||
),
|
||||
array(
|
||||
5,
|
||||
'Read error'
|
||||
),
|
||||
array(
|
||||
7,
|
||||
'CRC error'
|
||||
),
|
||||
array(
|
||||
19,
|
||||
'Not a zip archive'
|
||||
),
|
||||
array(
|
||||
21,
|
||||
'Zip archive inconsistent'
|
||||
),
|
||||
array(
|
||||
404,
|
||||
404
|
||||
)
|
||||
$this->assertEquals(
|
||||
false,
|
||||
ZipExtension::createFile(
|
||||
"Content",
|
||||
array("name1.txt", "name2.txt"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,123 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests PhpMyAdmin\ZipFile
|
||||
*
|
||||
* @package PhpMyAdmin-test
|
||||
*/
|
||||
|
||||
use PhpMyAdmin\ZipFile;
|
||||
|
||||
require_once 'test/PMATestCase.php';
|
||||
|
||||
/**
|
||||
* Tests for PhpMyAdmin\ZipFile
|
||||
*
|
||||
* @package PhpMyAdmin-test
|
||||
*/
|
||||
class ZipFileTest extends PMATestCase
|
||||
{
|
||||
/**
|
||||
* @access protected
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
$this->object = new ZipFile();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
unset($this->object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for setDoWrite
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetDoWrite()
|
||||
{
|
||||
$this->object->setDoWrite();
|
||||
$this->assertTrue($this->object->doWrite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for unix2DosTime
|
||||
*
|
||||
* @param int $unixTime UNIX timestamp
|
||||
* @param int $output DOS timestamp
|
||||
*
|
||||
* @dataProvider providerForTestUnix2DosTime
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUnix2DosTime($unixTime, $output)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$this->object->unix2DosTime($unixTime),
|
||||
$output
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for testUnix2DosTime
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerForTestUnix2DosTime()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
123456,
|
||||
2162688
|
||||
),
|
||||
array(
|
||||
234232,
|
||||
2162688
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for addFile
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAddFile()
|
||||
{
|
||||
$this->assertEquals(
|
||||
$this->object->addFile('This is test content for the file', 'Test file'),
|
||||
''
|
||||
);
|
||||
$this->assertTrue(!empty($this->object->ctrl_dir));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFile()
|
||||
{
|
||||
$file = $this->object->file();
|
||||
$this->assertTrue(
|
||||
!empty($file)
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user