From d58b192527181d9035d2c760b2f738c9bbb2f7c5 Mon Sep 17 00:00:00 2001 From: Marc Delisle Date: Sat, 9 Aug 2008 17:14:28 +0000 Subject: [PATCH] bug #2033962 [import] Cannot import zip file --- ChangeLog | 1 + Documentation.html | 1 + import.php | 23 +- libraries/File.class.php | 28 +-- libraries/display_import.lib.php | 2 +- libraries/unzip.lib.php | 493 --------------------------------------- libraries/zip_extension.lib.php | 69 ++++++ 7 files changed, 97 insertions(+), 520 deletions(-) delete mode 100644 libraries/unzip.lib.php create mode 100644 libraries/zip_extension.lib.php diff --git a/ChangeLog b/ChangeLog index 2f91478b9e..9502747d00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -69,6 +69,7 @@ danbarry + [import] Speed optimization to be able to import the sakila database + [doc] Documentation for distributing phpMyAdmin in README.VENDOR. + [display] headwords for sorted column +- bug #2033962 [import] Cannot import zip file 2.11.9.0 (not yet released) - bug #2031221 [auth] Links to version number on login screen diff --git a/Documentation.html b/Documentation.html index 794d1c7e1f..04b0f64106 100644 --- a/Documentation.html +++ b/Documentation.html @@ -61,6 +61,7 @@ FAQ 1.31) and the Standard PHP Library (SPL) extension. +
  • To support uploading of ZIP files, you need the PHP zip extension.
  • You need GD2 support in PHP to display inline thumbnails of JPEGs ("image/jpeg: inline") with their original aspect ratio
  • diff --git a/import.php b/import.php index 61e9201809..c4cf612731 100644 --- a/import.php +++ b/import.php @@ -250,7 +250,10 @@ if ($import_file != 'none' && !$error) { } } - // Handle file compression + /** + * Handle file compression + * @todo duplicate code exists in File.class.php + */ $compression = PMA_detectCompression($import_file); if ($compression === FALSE) { $message = PMA_Message::error('strFileCouldNotBeRead'); @@ -276,21 +279,15 @@ if ($import_file != 'none' && !$error) { } break; case 'application/zip': - if ($cfg['GZipDump'] && @function_exists('gzinflate')) { - include_once './libraries/unzip.lib.php'; - $import_handle = new SimpleUnzip(); - $import_handle->ReadFile($import_file); - if ($import_handle->Count() == 0) { - $message = PMA_Message::error('strNoFilesFoundInZip'); - $error = TRUE; - } elseif ($import_handle->GetError(0) != 0) { - $message = PMA_Message::rawError($strErrorInZipFile . ' ' . $import_handle->GetErrorMsg(0)); + if ($cfg['ZipDump'] && @function_exists('zip_open')) { + include_once './libraries/zip_extension.lib.php'; + $result = PMA_getZipContents($import_file); + if (! empty($result['error'])) { + $message = PMA_Message::rawError($result['error']); $error = TRUE; } else { - $import_text = $import_handle->GetData(0); + $import_text = $result['data']; } - // We don't need to store it further - $import_handle = ''; } else { $message = PMA_Message::error('strUnsupportedCompressionDetected'); $message->addParam($compression); diff --git a/libraries/File.class.php b/libraries/File.class.php index ca1f7a7451..117429f1b4 100644 --- a/libraries/File.class.php +++ b/libraries/File.class.php @@ -675,21 +675,16 @@ class PMA_File } break; case 'application/zip': - if ($GLOBALS['cfg']['GZipDump'] && @function_exists('gzinflate')) { - include_once './libraries/unzip.lib.php'; - $this->_handle = new SimpleUnzip(); - $this->_handle->ReadFile($this->getName()); - if ($this->_handle->Count() == 0) { - $this->_error_message = $GLOBALS['strNoFilesFoundInZip']; - return false; - } elseif ($this->_handle->GetError(0) != 0) { - $this->_error_message = $GLOBALS['strErrorInZipFile'] . ' ' . $this->_handle->GetErrorMsg(0); + if ($GLOBALS['cfg']['ZipDump'] && @function_exists('zip_open')) { + include_once './libraries/zip_extension.lib.php'; + $result = PMA_getZipContents($this->getName()); + if (! empty($result['error'])) { + $this->_error_message = PMA_Message::rawError($result['error']); return false; } else { - $this->content_uncompressed = $this->_handle->GetData(0); + $this->content_uncompressed = $result['data']; } - // We don't need to store it further - $this->_handle = null; + unset($result); } else { $this->_error_message = sprintf($GLOBALS['strUnsupportedCompressionDetected'], $this->getCompression()); return false; @@ -737,6 +732,7 @@ class PMA_File * * @param integer $length numbers of chars/bytes to skip * @return boolean + * @todo this function is unused */ function advanceFilePointer($length) { @@ -751,7 +747,7 @@ class PMA_File /** * http://bugs.php.net/bug.php?id=29532 * bzip reads a maximum of 8192 bytes on windows systems - * + * @todo this function is unused */ function getNextChunk($max_size = null) { @@ -774,6 +770,11 @@ class PMA_File $result = gzread($this->getHandle(), $size); break; case 'application/zip': + /* + * if getNextChunk() is used some day, + * replace this code by code similar to the one + * in open() + * include_once './libraries/unzip.lib.php'; $import_handle = new SimpleUnzip(); $import_handle->ReadFile($this->getName()); @@ -787,6 +788,7 @@ class PMA_File } else { $result = $import_handle->GetData(0); } + */ break; case 'none': $result = fread($this->getHandle(), $size); diff --git a/libraries/display_import.lib.php b/libraries/display_import.lib.php index a7abb404a9..557a9a79de 100644 --- a/libraries/display_import.lib.php +++ b/libraries/display_import.lib.php @@ -114,7 +114,7 @@ if ($cfg['GZipDump'] && @function_exists('gzopen')) { if ($cfg['BZipDump'] && @function_exists('bzopen')) { $compressions .= ', bzip2'; } -if ($cfg['ZipDump'] && @function_exists('gzinflate')) { +if ($cfg['ZipDump'] && @function_exists('zip_open')) { $compressions .= ', zip'; } diff --git a/libraries/unzip.lib.php b/libraries/unzip.lib.php deleted file mode 100644 index 12ffcaf32c..0000000000 --- a/libraries/unzip.lib.php +++ /dev/null @@ -1,493 +0,0 @@ - - * @copyright Copyright © 2003, Holger Boskugel, Berlin, Germany - * @license http://opensource.org/licenses/gpl-license.php GNU Public License - * - * @history - * 2003-12-02 - HB : Patched : naming bug : Time/Size of file - * Added : ZIP file comment - * Added : Check BZIP2 support of PHP - * 2003-11-29 - HB * Initial version - */ - - /** - * Unzip class, which retrieves entries from ZIP files. - * - * Supports only the compression modes - * - 0 : Stored, - * - 8 : Deflated and - * - 12 : BZIP2 - * - * Based on :
    - *
    - * {@link http://www.pkware.com/products/enterprise/white_papers/appnote.html - * * Official ZIP file format}
    - * {@link http://msdn.microsoft.com/library/en-us/w98ddk/hh/w98ddk/storage_5l4m.asp - * * Microsoft DOS date/time format} - * - * @category phpPublic - * @package File-Formats-ZIP - * @subpackage Unzip - * @version 1.0.1 - * @author Holger Boskugel - * @uses SimpleUnzipEntry - * @example example.unzip.php Two examples - */ - class SimpleUnzip { -// 2003-12-02 - HB > - /** - * Array to store file entries - * - * @var string - * @access public - * @see ReadFile() - * @since 1.0.1 - */ - var $Comment = ''; -// 2003-12-02 - HB < - - /** - * Array to store file entries - * - * @var array - * @access public - * @see ReadFile() - * @since 1.0 - */ - var $Entries = array(); - - /** - * Name of the ZIP file - * - * @var string - * @access public - * @see ReadFile() - * @since 1.0 - */ - var $Name = ''; - - /** - * Size of the ZIP file - * - * @var integer - * @access public - * @see ReadFile() - * @since 1.0 - */ - var $Size = 0; - - /** - * Time of the ZIP file (unix timestamp) - * - * @var integer - * @access public - * @see ReadFile() - * @since 1.0 - */ - var $Time = 0; - - /** - * Contructor of the class - * - * @param string File name - * @return SimpleUnzip Instanced class - * @access public - * @uses SimpleUnzip::ReadFile() Opens file on new if specified - * @since 1.0 - */ - function SimpleUnzip($in_FileName = '') - { - if ($in_FileName !== '') { - SimpleUnzip::ReadFile($in_FileName); - } - } // end of the 'SimpleUnzip' constructor - - /** - * Counts the entries - * - * @return integer Count of ZIP entries - * @access public - * @uses $Entries - * @since 1.0 - */ - function Count() - { - return count($this->Entries); - } // end of the 'Count()' method - - /** - * Gets data of the specified ZIP entry - * - * @param integer Index of the ZIP entry - * @return mixed Data for the ZIP entry - * @uses SimpleUnzipEntry::$Data - * @access public - * @since 1.0 - */ - function GetData($in_Index) - { - return $this->Entries[$in_Index]->Data; - } // end of the 'GetData()' method - - /** - * Gets an entry of the ZIP file - * - * @param integer Index of the ZIP entry - * @return SimpleUnzipEntry Entry of the ZIP file - * @uses $Entries - * @access public - * @since 1.0 - */ - function GetEntry($in_Index) - { - return $this->Entries[$in_Index]; - } // end of the 'GetEntry()' method - - /** - * Gets error code for the specified ZIP entry - * - * @param integer Index of the ZIP entry - * @return integer Error code for the ZIP entry - * @uses SimpleUnzipEntry::$Error - * @access public - * @since 1.0 - */ - function GetError($in_Index) - { - return $this->Entries[$in_Index]->Error; - } // end of the 'GetError()' method - - /** - * Gets error message for the specified ZIP entry - * - * @param integer Index of the ZIP entry - * @return string Error message for the ZIP entry - * @uses SimpleUnzipEntry::$ErrorMsg - * @access public - * @since 1.0 - */ - function GetErrorMsg($in_Index) - { - return $this->Entries[$in_Index]->ErrorMsg; - } // end of the 'GetErrorMsg()' method - - /** - * Gets file name for the specified ZIP entry - * - * @param integer Index of the ZIP entry - * @return string File name for the ZIP entry - * @uses SimpleUnzipEntry::$Name - * @access public - * @since 1.0 - */ - function GetName($in_Index) - { - return $this->Entries[$in_Index]->Name; - } // end of the 'GetName()' method - - /** - * Gets path of the file for the specified ZIP entry - * - * @param integer Index of the ZIP entry - * @return string Path of the file for the ZIP entry - * @uses SimpleUnzipEntry::$Path - * @access public - * @since 1.0 - */ - function GetPath($in_Index) - { - return $this->Entries[$in_Index]->Path; - } // end of the 'GetPath()' method - - /** - * Gets file time for the specified ZIP entry - * - * @param integer Index of the ZIP entry - * @return integer File time for the ZIP entry (unix timestamp) - * @uses SimpleUnzipEntry::$Time - * @access public - * @since 1.0 - */ - function GetTime($in_Index) - { - return $this->Entries[$in_Index]->Time; - } // end of the 'GetTime()' method - - /** - * Reads ZIP file and extracts the entries - * - * @param string File name of the ZIP archive - * @return array ZIP entry list (see also class variable {@link $Entries $Entries}) - * @uses SimpleUnzipEntry For the entries - * @access public - * @since 1.0 - */ - function ReadFile($in_FileName) - { - $this->Entries = array(); - - // Get file parameters - $this->Name = $in_FileName; - $this->Time = filemtime($in_FileName); - $this->Size = filesize($in_FileName); - - // Read file - $oF = fopen($in_FileName, 'rb'); - $vZ = fread($oF, $this->Size); - fclose($oF); - -// 2003-12-02 - HB > - // Cut end of central directory - $aE = explode("\x50\x4b\x05\x06", $vZ); - - // Easiest way, but not sure if format changes - //$this->Comment = substr($aE[1], 18); - - // Normal way - $aP = unpack('x16/v1CL', $aE[1]); - $this->Comment = substr($aE[1], 18, $aP['CL']); - - // Translates end of line from other operating systems - $this->Comment = strtr($this->Comment, array("\r\n" => "\n", - "\r" => "\n")); -// 2003-12-02 - HB < - - // Cut the entries from the central directory - $aE = explode("\x50\x4b\x01\x02", $vZ); - // Explode to each part - $aE = explode("\x50\x4b\x03\x04", $aE[0]); - // Shift out spanning signature or empty entry - array_shift($aE); - - // Loop through the entries - foreach ($aE as $vZ) { - $aI = array(); - $aI['E'] = 0; - $aI['EM'] = ''; - // Retrieving local file header information - $aP = unpack('v1VN/v1GPF/v1CM/v1FT/v1FD/V1CRC/V1CS/V1UCS/v1FNL', $vZ); - // Check if data is encrypted - $bE = ($aP['GPF'] & 0x0001) ? TRUE : FALSE; - $nF = $aP['FNL']; - - // Special case : value block after the compressed data - if ($aP['GPF'] & 0x0008) { - $aP1 = unpack('V1CRC/V1CS/V1UCS', substr($vZ, -12)); - - $aP['CRC'] = $aP1['CRC']; - $aP['CS'] = $aP1['CS']; - $aP['UCS'] = $aP1['UCS']; - - $vZ = substr($vZ, 0, -12); - } - - // Getting stored filename - $aI['N'] = substr($vZ, 26, $nF); - - if (substr($aI['N'], -1) == '/') { - // is a directory entry - will be skipped - continue; - } - - // Truncate full filename in path and filename - $aI['P'] = dirname($aI['N']); - $aI['P'] = $aI['P'] == '.' ? '' : $aI['P']; - $aI['N'] = basename($aI['N']); - - $vZ = substr($vZ, 26 + $nF); - - if (strlen($vZ) != $aP['CS']) { - $aI['E'] = 1; - $aI['EM'] = 'Compressed size is not equal with the value in header information.'; - } else { - if ($bE) { - $aI['E'] = 5; - $aI['EM'] = 'File is encrypted, which is not supported from this class.'; - } else { - switch($aP['CM']) { - case 0: // Stored - // Here is nothing to do, the file ist flat. - break; - - case 8: // Deflated - $vZ = gzinflate($vZ); - break; - - case 12: // BZIP2 -// 2003-12-02 - HB > - if (! extension_loaded('bz2')) { - if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { - @dl('php_bz2.dll'); - } else { - @dl('bz2.so'); - } - } - - if (extension_loaded('bz2')) { -// 2003-12-02 - HB < - $vZ = bzdecompress($vZ); -// 2003-12-02 - HB > - } else { - $aI['E'] = 7; - $aI['EM'] = "PHP BZIP2 extension not available."; - } -// 2003-12-02 - HB < - - break; - - default: - $aI['E'] = 6; - $aI['EM'] = "De-/Compression method {$aP['CM']} is not supported."; - } - -// 2003-12-02 - HB > - if (! $aI['E']) { -// 2003-12-02 - HB < - if ($vZ === FALSE) { - $aI['E'] = 2; - $aI['EM'] = 'Decompression of data failed.'; - } else { - if (strlen($vZ) != $aP['UCS']) { - $aI['E'] = 3; - $aI['EM'] = 'Uncompressed size is not equal with the value in header information.'; - } else { - if (crc32($vZ) != $aP['CRC']) { - $aI['E'] = 4; - $aI['EM'] = 'CRC32 checksum is not equal with the value in header information.'; - } - } - } -// 2003-12-02 - HB > - } -// 2003-12-02 - HB < - } - } - - $aI['D'] = $vZ; - - // DOS to UNIX timestamp - $aI['T'] = mktime(($aP['FT'] & 0xf800) >> 11, - ($aP['FT'] & 0x07e0) >> 5, - ($aP['FT'] & 0x001f) << 1, - ($aP['FD'] & 0x01e0) >> 5, - ($aP['FD'] & 0x001f), - (($aP['FD'] & 0xfe00) >> 9) + 1980); - - $this->Entries[] = &new SimpleUnzipEntry($aI); - } // end for each entries - - return $this->Entries; - } // end of the 'ReadFile()' method - } // end of the 'SimpleUnzip' class - - /** - * Entry of the ZIP file. - * - * @category phpPublic - * @package File-Formats-ZIP - * @subpackage Unzip - * @version 1.0 - * @author Holger Boskugel - * @example example.unzip.php Two examples - */ - class SimpleUnzipEntry { - /** - * Data of the file entry - * - * @var mixed - * @access public - * @see SimpleUnzipEntry() - * @since 1.0 - */ - var $Data = ''; - - /** - * Error of the file entry - * - * - 0 : No error raised.
    - * - 1 : Compressed size is not equal with the value in header information.
    - * - 2 : Decompression of data failed.
    - * - 3 : Uncompressed size is not equal with the value in header information.
    - * - 4 : CRC32 checksum is not equal with the value in header information.
    - * - 5 : File is encrypted, which is not supported from this class.
    - * - 6 : De-/Compression method ... is not supported.
    - * - 7 : PHP BZIP2 extension not available. - * - * @var integer - * @access public - * @see SimpleUnzipEntry() - * @since 1.0 - */ - var $Error = 0; - - /** - * Error message of the file entry - * - * @var string - * @access public - * @see SimpleUnzipEntry() - * @since 1.0 - */ - var $ErrorMsg = ''; - - /** - * File name of the file entry - * - * @var string - * @access public - * @see SimpleUnzipEntry() - * @since 1.0 - */ - var $Name = ''; - - /** - * File path of the file entry - * - * @var string - * @access public - * @see SimpleUnzipEntry() - * @since 1.0 - */ - var $Path = ''; - - /** - * File time of the file entry (unix timestamp) - * - * @var integer - * @access public - * @see SimpleUnzipEntry() - * @since 1.0 - */ - var $Time = 0; - - /** - * Contructor of the class - * - * @param array Entry datas - * @return SimpleUnzipEntry Instanced class - * @access public - * @since 1.0 - */ - function SimpleUnzipEntry($in_Entry) - { - $this->Data = $in_Entry['D']; - $this->Error = $in_Entry['E']; - $this->ErrorMsg = $in_Entry['EM']; - $this->Name = $in_Entry['N']; - $this->Path = $in_Entry['P']; - $this->Time = $in_Entry['T']; - } // end of the 'SimpleUnzipEntry' constructor - } // end of the 'SimpleUnzipEntry' class -?> diff --git a/libraries/zip_extension.lib.php b/libraries/zip_extension.lib.php new file mode 100644 index 0000000000..a079016ba9 --- /dev/null +++ b/libraries/zip_extension.lib.php @@ -0,0 +1,69 @@ + $error_message, 'data' => $file_data)); +} + + +/** + * Gets zip error message + * + * @param integer error code + * @return string error message + * @author lem9 + */ +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; +} +?> -- 2.11.4.GIT