cvs: pear /PHP_Archive Archive.php /PHP_Archive/Archive Creator.php
| From: | Greg Beaver | Date: | Fri, 08 Apr 2005 02:26:13 +0000 |
| Subject: | cvs: pear /PHP_Archive Archive.php /PHP_Archive/Archive Creator.php | ||
| Groups: | php.pear.cvs | ||
| Request: | Send a blank email to pear-cvs+get-31041@lists.php.net to get a copy of this message | ||
cellog Thu Apr 7 22:26:13 2005 EDT
Modified files:
/pear/PHP_Archive Archive.php
/pear/PHP_Archive/Archive Creator.php
Log:
fix
- which file we open as self
- gz compression!
- remove Archive_Tar dep (still very buggy)
http://cvs.php.net/diff.php/pear/PHP_Archive/Archive.php?r1=1.1&r2=1.2&ty=u Index: pear/PHP_Archive/Archive.php diff -u pear/PHP_Archive/Archive.php:1.1 pear/PHP_Archive/Archive.php:1.2 --- pear/PHP_Archive/Archive.php:1.1 Tue Jan 25 04:23:33 2005 +++ pear/PHP_Archive/Archive.php Thu Apr 7 22:26:12 2005 @@ -29,7 +29,7 @@ * @copyright Copyright © David Shafik and Synaptic Media 2004. All rights reserved. * @author Davey Shafik <davey@synapticmedia.net> * @link http://www.synapticmedia.net Synaptic Media - * @version $Id: Archive.php,v 1.1 2005/01/25 09:23:33 davey Exp $ + * @version $Id: Archive.php,v 1.2 2005/04/08 02:26:12 cellog Exp $ * @package PHP_Archive * @category PHP */ @@ -41,7 +41,9 @@ */ var $archive_name = null; - + var $currentStat = null; + var $currentFilename = null; + var $internalFileLength = null; /** * @var object Archive_Tar object */ @@ -68,12 +70,105 @@ function stream_start() { - require_once 'Archive/Tar.php'; - $this->archive_name = array_shift(get_included_files()); - $this->archive = new Archive_Tar($this->archive_name); + $aname = get_included_files(); + array_pop($aname); + $this->archive_name = array_pop($aname); + require_once 'PEAR.php'; +// require_once 'Archive/Tar.php'; +// $this->archive = new Archive_Tar($this->archive_name); return true; } - + + function _processFile($path) + { + if ($path == '.') { + return ''; + } + $std = str_replace("\\", "/", $path); + while ($std != ($std = preg_replace("/[^\/:?]+\/\.\.\//", "", $std))) ; + $std = str_replace("/./", "", $std); + if (strncmp($std, "./", 2) == 0) { + return substr($std, 2); + } else { + return $std; + } + } + + function _selectFile($path) + { + $std = $this->_processFile($path); + while (($error = $this->_nextFile()) === true) { + $sourceName = $this->currentFilename; + if (empty($std) || $std == $this->currentFilename || + //$std is a directory + strncmp($std.'/', $sourceName, strlen($std)+1) == 0) { + return true; + } + } + return $error; + } + + function _open() + { + $this->_file = @fopen($this->archive_name, "rb"); + if (!$this->_file) { + return PEAR::raiseError('Error: cannot open phar "' . $this->archive_name . '"'); + } + } + + function _nextFile() + { + $rawHeader = @fread($this->_file, 512); + if (strlen($rawHeader) < 512 || $rawHeader == pack("a512", "")) { + return PEAR::raiseError('Error: phar "' . $this->archive_name . '" has no tar header'); + } + + $header = unpack( + "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/". + "a8checksum/a1type/a100linkname/a6magic/a2version/". + "a32uname/a32gname/a8devmajor/a8devminor/a155path", + $rawHeader); + $this->currentStat = array( + 2 => octdec($header['mode']), + 4 => octdec($header['uid']), + 5 => octdec($header['gid']), + 7 => octdec($header['size']), + 9 => octdec($header['mtime']) + ); + + $this->internalFileLength = $this->currentStat[7]; + if ($this->internalFileLength % 512 == 0) { + $this->footerLength = 0; + } else { + $this->footerLength = 512 - $this->internalFileLength % 512; + } + + $this->currentFilename = $this->_processFile($header['path'] . $header['filename']); + $checksum = 8 * ord(" "); + for ($i = 0; $i < 148; $i++) { + $checksum += ord($rawHeader{$i}); + } + for ($i = 156; $i < 512; $i++) { + $checksum += ord($rawHeader{$i}); + } + + if (octdec($header['checksum']) != $checksum) { + return PEAR::raiseError('Error: phar "' . + $this->archive_name . '" Checksum error on entry "' . $this->currentFilename . '"'); + } + return true; + } + + function extractFile($path) + { + $this->_open(); + if ($this->_selectFile($path)) { + $actualLength = $this->internalFileLength; + $data = @fread($this->_file, $actualLength); + return $data; + } + } + /** * Open the requested file * @@ -84,14 +179,38 @@ { $path = substr($file, 7); $this->stream_start(); - $this->file = $this->archive->extractInString($path); - if (PHP_ARCHIVE_COMPRESSED) { - $this->file = gzuncompress(base64_decode($this->file)); + $this->file = $this->extractFile($path); + $compressed = $this->file ? (int) $this->file{0} : false; + $this->file ? $this->file = substr($this->file, 1) : false; + if ($compressed) { + $this->file = base64_decode($this->file); + // code borrowed from File_Archive_Reader_Gzip by Greg Beaver + $header = substr($this->file, 0, 10); + $temp = unpack("Vcrc32/Visize", substr($this->file, -8)); + $crc32 = $temp['crc32']; + $size = $temp['isize']; + + $id = @unpack("H2id1/H2id2/C1tmp/C1flags", substr($header, 0, 4)); + if ($id['id1'] != "1f" || $id['id2'] != "8b") { + trigger_error("Not valid gz file (wrong header)", E_USER_ERROR); + return false; + } + $this->file = gzinflate(substr($this->file, 10, strlen($this->file) - 8)); + + if ($size != strlen($this->file)) { + trigger_error("Not valid gz file (size error {$size} != " . + strlen($this->file) . ")", E_USER_ERROR); + return false; + } + if ($crc32 != crc32($this->file)) { + trigger_error("Not valid gz file (checksum error)", E_USER_ERROR); + return false; + } } if (!is_null($this->file) && $this->file !== false) { return true; } else { - return false; + return false; } } http://cvs.php.net/diff.php/pear/PHP_Archive/Archive/Creator.php?r1=1.1&r2=1.2&ty=u Index: pear/PHP_Archive/Archive/Creator.php diff -u pear/PHP_Archive/Archive/Creator.php:1.1 pear/PHP_Archive/Archive/Creator.php:1.2 --- pear/PHP_Archive/Archive/Creator.php:1.1 Tue Jan 25 04:23:34 2005 +++ pear/PHP_Archive/Archive/Creator.php Thu Apr 7 22:26:12 2005 @@ -26,7 +26,7 @@ * @copyright Copyright © David Shafik and Synaptic Media 2004. All rights reserved. * @author Davey Shafik <davey@synapticmedia.net> * @link http://www.synapticmedia.net Synaptic Media - * @version $Id: Creator.php,v 1.1 2005/01/25 09:23:34 davey Exp $ + * @version $Id: Creator.php,v 1.2 2005/04/08 02:26:12 cellog Exp $ * @package PHP_Archive * @category PHP * @example c:\web\php-cvs\pear\PHP_Archive\docs\examples\PHP_Archive_Creator_Example_1.php Example PHP_Archive_Creator usage @@ -103,26 +103,9 @@ stream_register_wrapper('phar', 'PHP_Archive'); PHP; - if ($compress == true) { - $unpack_code .= <<<PHP - -if (!defined('PHP_ARCHIVE_COMPRESSED')) { - define('PHP_ARCHIVE_COMPRESSED', true); -} - -PHP; - } else { - $unpack_code .= <<<PHP - -if (!defined('PHP_ARCHIVE_COMPRESSED')) { - define('PHP_ARCHIVE_COMPRESSED', false); -} - -PHP; - } - if (!$allow_direct_access) { $unpack_code .= <<<PHP + require_once 'phar://$init_file'; PHP; } else { @@ -132,6 +115,7 @@ $allow_direct_access = '.' . $allow_direct_access; } $unpack_code .= <<<PHP + require_once 'phar://{$_SERVER['PATH_INFO']}$allow_direct_access'; PHP; } @@ -172,7 +156,12 @@ $this->modified = true; $file_contents = file_get_contents($file); if ($this->compress) { - $file_contents = base64_encode(gzcompress($file_contents)); + $file_contents = '1' . base64_encode( + pack("C1C1C1C1VC1C1", 0x1f, 0x8b, 8, 0, time(), 2, 0xFF) . + gzdeflate($file_contents, 9) . + pack("VV",crc32($file_contents),strlen($file_contents))); + } else { + $file_contents = '0' . $file_contents; } return $this->tar->addString($save_path, $file_contents); }
http://cvs.php.net/diff.php/pear/PHP_Archive/Archive.php?r1=1.1&r2=1.2&ty=u Index: pear/PHP_Archive/Archive.php diff -u pear/PHP_Archive/Archive.php:1.1 pear/PHP_Archive/Archive.php:1.2 --- pear/PHP_Archive/Archive.php:1.1 Tue Jan 25 04:23:33 2005 +++ pear/PHP_Archive/Archive.php Thu Apr 7 22:26:12 2005 @@ -29,7 +29,7 @@ * @copyright Copyright © David Shafik and Synaptic Media 2004. All rights reserved. * @author Davey Shafik <davey@synapticmedia.net> * @link http://www.synapticmedia.net Synaptic Media - * @version $Id: Archive.php,v 1.1 2005/01/25 09:23:33 davey Exp $ + * @version $Id: Archive.php,v 1.2 2005/04/08 02:26:12 cellog Exp $ * @package PHP_Archive * @category PHP */ @@ -41,7 +41,9 @@ */ var $archive_name = null; - + var $currentStat = null; + var $currentFilename = null; + var $internalFileLength = null; /** * @var object Archive_Tar object */ @@ -68,12 +70,105 @@ function stream_start() { - require_once 'Archive/Tar.php'; - $this->archive_name = array_shift(get_included_files()); - $this->archive = new Archive_Tar($this->archive_name); + $aname = get_included_files(); + array_pop($aname); + $this->archive_name = array_pop($aname); + require_once 'PEAR.php'; +// require_once 'Archive/Tar.php'; +// $this->archive = new Archive_Tar($this->archive_name); return true; } - + + function _processFile($path) + { + if ($path == '.') { + return ''; + } + $std = str_replace("\\", "/", $path); + while ($std != ($std = preg_replace("/[^\/:?]+\/\.\.\//", "", $std))) ; + $std = str_replace("/./", "", $std); + if (strncmp($std, "./", 2) == 0) { + return substr($std, 2); + } else { + return $std; + } + } + + function _selectFile($path) + { + $std = $this->_processFile($path); + while (($error = $this->_nextFile()) === true) { + $sourceName = $this->currentFilename; + if (empty($std) || $std == $this->currentFilename || + //$std is a directory + strncmp($std.'/', $sourceName, strlen($std)+1) == 0) { + return true; + } + } + return $error; + } + + function _open() + { + $this->_file = @fopen($this->archive_name, "rb"); + if (!$this->_file) { + return PEAR::raiseError('Error: cannot open phar "' . $this->archive_name . '"'); + } + } + + function _nextFile() + { + $rawHeader = @fread($this->_file, 512); + if (strlen($rawHeader) < 512 || $rawHeader == pack("a512", "")) { + return PEAR::raiseError('Error: phar "' . $this->archive_name . '" has no tar header'); + } + + $header = unpack( + "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/". + "a8checksum/a1type/a100linkname/a6magic/a2version/". + "a32uname/a32gname/a8devmajor/a8devminor/a155path", + $rawHeader); + $this->currentStat = array( + 2 => octdec($header['mode']), + 4 => octdec($header['uid']), + 5 => octdec($header['gid']), + 7 => octdec($header['size']), + 9 => octdec($header['mtime']) + ); + + $this->internalFileLength = $this->currentStat[7]; + if ($this->internalFileLength % 512 == 0) { + $this->footerLength = 0; + } else { + $this->footerLength = 512 - $this->internalFileLength % 512; + } + + $this->currentFilename = $this->_processFile($header['path'] . $header['filename']); + $checksum = 8 * ord(" "); + for ($i = 0; $i < 148; $i++) { + $checksum += ord($rawHeader{$i}); + } + for ($i = 156; $i < 512; $i++) { + $checksum += ord($rawHeader{$i}); + } + + if (octdec($header['checksum']) != $checksum) { + return PEAR::raiseError('Error: phar "' . + $this->archive_name . '" Checksum error on entry "' . $this->currentFilename . '"'); + } + return true; + } + + function extractFile($path) + { + $this->_open(); + if ($this->_selectFile($path)) { + $actualLength = $this->internalFileLength; + $data = @fread($this->_file, $actualLength); + return $data; + } + } + /** * Open the requested file * @@ -84,14 +179,38 @@ { $path = substr($file, 7); $this->stream_start(); - $this->file = $this->archive->extractInString($path); - if (PHP_ARCHIVE_COMPRESSED) { - $this->file = gzuncompress(base64_decode($this->file)); + $this->file = $this->extractFile($path); + $compressed = $this->file ? (int) $this->file{0} : false; + $this->file ? $this->file = substr($this->file, 1) : false; + if ($compressed) { + $this->file = base64_decode($this->file); + // code borrowed from File_Archive_Reader_Gzip by Greg Beaver + $header = substr($this->file, 0, 10); + $temp = unpack("Vcrc32/Visize", substr($this->file, -8)); + $crc32 = $temp['crc32']; + $size = $temp['isize']; + + $id = @unpack("H2id1/H2id2/C1tmp/C1flags", substr($header, 0, 4)); + if ($id['id1'] != "1f" || $id['id2'] != "8b") { + trigger_error("Not valid gz file (wrong header)", E_USER_ERROR); + return false; + } + $this->file = gzinflate(substr($this->file, 10, strlen($this->file) - 8)); + + if ($size != strlen($this->file)) { + trigger_error("Not valid gz file (size error {$size} != " . + strlen($this->file) . ")", E_USER_ERROR); + return false; + } + if ($crc32 != crc32($this->file)) { + trigger_error("Not valid gz file (checksum error)", E_USER_ERROR); + return false; + } } if (!is_null($this->file) && $this->file !== false) { return true; } else { - return false; + return false; } } http://cvs.php.net/diff.php/pear/PHP_Archive/Archive/Creator.php?r1=1.1&r2=1.2&ty=u Index: pear/PHP_Archive/Archive/Creator.php diff -u pear/PHP_Archive/Archive/Creator.php:1.1 pear/PHP_Archive/Archive/Creator.php:1.2 --- pear/PHP_Archive/Archive/Creator.php:1.1 Tue Jan 25 04:23:34 2005 +++ pear/PHP_Archive/Archive/Creator.php Thu Apr 7 22:26:12 2005 @@ -26,7 +26,7 @@ * @copyright Copyright © David Shafik and Synaptic Media 2004. All rights reserved. * @author Davey Shafik <davey@synapticmedia.net> * @link http://www.synapticmedia.net Synaptic Media - * @version $Id: Creator.php,v 1.1 2005/01/25 09:23:34 davey Exp $ + * @version $Id: Creator.php,v 1.2 2005/04/08 02:26:12 cellog Exp $ * @package PHP_Archive * @category PHP * @example c:\web\php-cvs\pear\PHP_Archive\docs\examples\PHP_Archive_Creator_Example_1.php Example PHP_Archive_Creator usage @@ -103,26 +103,9 @@ stream_register_wrapper('phar', 'PHP_Archive'); PHP; - if ($compress == true) { - $unpack_code .= <<<PHP - -if (!defined('PHP_ARCHIVE_COMPRESSED')) { - define('PHP_ARCHIVE_COMPRESSED', true); -} - -PHP; - } else { - $unpack_code .= <<<PHP - -if (!defined('PHP_ARCHIVE_COMPRESSED')) { - define('PHP_ARCHIVE_COMPRESSED', false); -} - -PHP; - } - if (!$allow_direct_access) { $unpack_code .= <<<PHP + require_once 'phar://$init_file'; PHP; } else { @@ -132,6 +115,7 @@ $allow_direct_access = '.' . $allow_direct_access; } $unpack_code .= <<<PHP + require_once 'phar://{$_SERVER['PATH_INFO']}$allow_direct_access'; PHP; } @@ -172,7 +156,12 @@ $this->modified = true; $file_contents = file_get_contents($file); if ($this->compress) { - $file_contents = base64_encode(gzcompress($file_contents)); + $file_contents = '1' . base64_encode( + pack("C1C1C1C1VC1C1", 0x1f, 0x8b, 8, 0, time(), 2, 0xFF) . + gzdeflate($file_contents, 9) . + pack("VV",crc32($file_contents),strlen($file_contents))); + } else { + $file_contents = '0' . $file_contents; } return $this->tar->addString($save_path, $file_contents); }