phpcp/tarcls.php

2 lines
49 KiB
PHP

<?php
define('PEAR_ERROR_RETURN', 1); define('PEAR_ERROR_PRINT', 2); define('PEAR_ERROR_TRIGGER', 4); define('PEAR_ERROR_DIE', 8); define('PEAR_ERROR_CALLBACK', 16); define('PEAR_ERROR_EXCEPTION', 32); if (substr(PHP_OS, 0, 3) == 'WIN') { define('OS_WINDOWS', true); define('OS_UNIX', false); define('PEAR_OS', 'Windows'); } else { define('OS_WINDOWS', false); define('OS_UNIX', true); define('PEAR_OS', 'Unix'); } $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; $GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; $GLOBALS['_PEAR_destructor_object_list'] = array(); $GLOBALS['_PEAR_shutdown_funcs'] = array(); $GLOBALS['_PEAR_error_handler_stack'] = array(); @ini_set('track_errors', true); class PEAR { var $_debug = false; var $_default_error_mode = null; var $_default_error_options = null; var $_default_error_handler = ''; var $_error_class = 'PEAR_Error'; var $_expected_errors = array(); protected static $bivalentMethods = array( 'setErrorHandling' => true, 'raiseError' => true, 'throwError' => true, 'pushErrorHandling' => true, 'popErrorHandling' => true, ); function __construct($error_class = null) { $classname = strtolower(get_class($this)); if ($this->_debug) { print "PEAR constructor called, class=$classname\n"; } if ($error_class !== null) { $this->_error_class = $error_class; } while ($classname && strcasecmp($classname, "pear")) { $destructor = "_$classname"; if (method_exists($this, $destructor)) { global $_PEAR_destructor_object_list; $_PEAR_destructor_object_list[] = &$this; if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { register_shutdown_function("_PEAR_call_destructors"); $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; } break; } else { $classname = get_parent_class($classname); } } } public function PEAR($error_class = null) { $this->__construct($error_class); } function _PEAR() { if ($this->_debug) { printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); } } public function __call($method, $arguments) { if (!isset(self::$bivalentMethods[$method])) { trigger_error( 'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR ); } return call_user_func_array( array(get_class(), '_' . $method), array_merge(array($this), $arguments) ); } public static function __callStatic($method, $arguments) { if (!isset(self::$bivalentMethods[$method])) { trigger_error( 'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR ); } return call_user_func_array( array(get_class(), '_' . $method), array_merge(array(null), $arguments) ); } public static function &getStaticProperty($class, $var) { static $properties; if (!isset($properties[$class])) { $properties[$class] = array(); } if (!array_key_exists($var, $properties[$class])) { $properties[$class][$var] = null; } return $properties[$class][$var]; } public static function registerShutdownFunc($func, $args = array()) { if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { register_shutdown_function("_PEAR_call_destructors"); $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; } $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); } public static function isError($data, $code = null) { if (!is_a($data, 'PEAR_Error')) { return false; } if (is_null($code)) { return true; } elseif (is_string($code)) { return $data->getMessage() == $code; } return $data->getCode() == $code; } protected static function _setErrorHandling( $object, $mode = null, $options = null ) { if ($object !== null) { $setmode = &$object->_default_error_mode; $setoptions = &$object->_default_error_options; } else { $setmode = &$GLOBALS['_PEAR_default_error_mode']; $setoptions = &$GLOBALS['_PEAR_default_error_options']; } switch ($mode) { case PEAR_ERROR_EXCEPTION: case PEAR_ERROR_RETURN: case PEAR_ERROR_PRINT: case PEAR_ERROR_TRIGGER: case PEAR_ERROR_DIE: case null: $setmode = $mode; $setoptions = $options; break; case PEAR_ERROR_CALLBACK: $setmode = $mode; if (is_callable($options)) { $setoptions = $options; } else { trigger_error("invalid error callback", E_USER_WARNING); } break; default: trigger_error("invalid error mode", E_USER_WARNING); break; } } function expectError($code = '*') { if (is_array($code)) { array_push($this->_expected_errors, $code); } else { array_push($this->_expected_errors, array($code)); } return count($this->_expected_errors); } function popExpect() { return array_pop($this->_expected_errors); } function _checkDelExpect($error_code) { $deleted = false; foreach ($this->_expected_errors as $key => $error_array) { if (in_array($error_code, $error_array)) { unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); $deleted = true; } if (0 == count($this->_expected_errors[$key])) { unset($this->_expected_errors[$key]); } } return $deleted; } function delExpect($error_code) { $deleted = false; if ((is_array($error_code) && (0 != count($error_code)))) { foreach ($error_code as $key => $error) { $deleted = $this->_checkDelExpect($error) ? true : false; } return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); } elseif (!empty($error_code)) { if ($this->_checkDelExpect($error_code)) { return true; } return PEAR::raiseError("The expected error you submitted does not exist"); } return PEAR::raiseError("The expected error you submitted is empty"); } protected static function _raiseError($object, $message = null, $code = null, $mode = null, $options = null, $userinfo = null, $error_class = null, $skipmsg = false) { if (is_object($message)) { $code = $message->getCode(); $userinfo = $message->getUserInfo(); $error_class = $message->getType(); $message->error_message_prefix = ''; $message = $message->getMessage(); } if ( $object !== null && isset($object->_expected_errors) && count($object->_expected_errors) > 0 && count($exp = end($object->_expected_errors)) ) { if ($exp[0] == "*" || (is_int(reset($exp)) && in_array($code, $exp)) || (is_string(reset($exp)) && in_array($message, $exp)) ) { $mode = PEAR_ERROR_RETURN; } } if ($mode === null) { if ($object !== null && isset($object->_default_error_mode)) { $mode = $object->_default_error_mode; $options = $object->_default_error_options; } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { $mode = $GLOBALS['_PEAR_default_error_mode']; $options = $GLOBALS['_PEAR_default_error_options']; } } if ($error_class !== null) { $ec = $error_class; } elseif ($object !== null && isset($object->_error_class)) { $ec = $object->_error_class; } else { $ec = 'PEAR_Error'; } if ($skipmsg) { $a = new $ec($code, $mode, $options, $userinfo); } else { $a = new $ec($message, $code, $mode, $options, $userinfo); } return $a; } protected static function _throwError($object, $message = null, $code = null, $userinfo = null) { if ($object !== null) { $a = &$object->raiseError($message, $code, null, null, $userinfo); return $a; } $a = &PEAR::raiseError($message, $code, null, null, $userinfo); return $a; } public static function staticPushErrorHandling($mode, $options = null) { $stack = &$GLOBALS['_PEAR_error_handler_stack']; $def_mode = &$GLOBALS['_PEAR_default_error_mode']; $def_options = &$GLOBALS['_PEAR_default_error_options']; $stack[] = array($def_mode, $def_options); switch ($mode) { case PEAR_ERROR_EXCEPTION: case PEAR_ERROR_RETURN: case PEAR_ERROR_PRINT: case PEAR_ERROR_TRIGGER: case PEAR_ERROR_DIE: case null: $def_mode = $mode; $def_options = $options; break; case PEAR_ERROR_CALLBACK: $def_mode = $mode; if (is_callable($options)) { $def_options = $options; } else { trigger_error("invalid error callback", E_USER_WARNING); } break; default: trigger_error("invalid error mode", E_USER_WARNING); break; } $stack[] = array($mode, $options); return true; } public static function staticPopErrorHandling() { $stack = &$GLOBALS['_PEAR_error_handler_stack']; $setmode = &$GLOBALS['_PEAR_default_error_mode']; $setoptions = &$GLOBALS['_PEAR_default_error_options']; array_pop($stack); list($mode, $options) = $stack[sizeof($stack) - 1]; array_pop($stack); switch ($mode) { case PEAR_ERROR_EXCEPTION: case PEAR_ERROR_RETURN: case PEAR_ERROR_PRINT: case PEAR_ERROR_TRIGGER: case PEAR_ERROR_DIE: case null: $setmode = $mode; $setoptions = $options; break; case PEAR_ERROR_CALLBACK: $setmode = $mode; if (is_callable($options)) { $setoptions = $options; } else { trigger_error("invalid error callback", E_USER_WARNING); } break; default: trigger_error("invalid error mode", E_USER_WARNING); break; } return true; } protected static function _pushErrorHandling($object, $mode, $options = null) { $stack = &$GLOBALS['_PEAR_error_handler_stack']; if ($object !== null) { $def_mode = &$object->_default_error_mode; $def_options = &$object->_default_error_options; } else { $def_mode = &$GLOBALS['_PEAR_default_error_mode']; $def_options = &$GLOBALS['_PEAR_default_error_options']; } $stack[] = array($def_mode, $def_options); if ($object !== null) { $object->setErrorHandling($mode, $options); } else { PEAR::setErrorHandling($mode, $options); } $stack[] = array($mode, $options); return true; } protected static function _popErrorHandling($object) { $stack = &$GLOBALS['_PEAR_error_handler_stack']; array_pop($stack); list($mode, $options) = $stack[sizeof($stack) - 1]; array_pop($stack); if ($object !== null) { $object->setErrorHandling($mode, $options); } else { PEAR::setErrorHandling($mode, $options); } return true; } public static function loadExtension($ext) { if (extension_loaded($ext)) { return true; } if ( function_exists('dl') === false || ini_get('enable_dl') != 1 ) { return false; } if (OS_WINDOWS) { $suffix = '.dll'; } elseif (PHP_OS == 'HP-UX') { $suffix = '.sl'; } elseif (PHP_OS == 'AIX') { $suffix = '.a'; } elseif (PHP_OS == 'OSX') { $suffix = '.bundle'; } else { $suffix = '.so'; } return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); } } function _PEAR_call_destructors() { global $_PEAR_destructor_object_list; if (is_array($_PEAR_destructor_object_list) && sizeof($_PEAR_destructor_object_list)) { reset($_PEAR_destructor_object_list); $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo'); if ($destructLifoExists) { $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); } while (list($k, $objref) = each($_PEAR_destructor_object_list)) { $classname = get_class($objref); while ($classname) { $destructor = "_$classname"; if (method_exists($objref, $destructor)) { $objref->$destructor(); break; } else { $classname = get_parent_class($classname); } } } $_PEAR_destructor_object_list = array(); } if ( isset($GLOBALS['_PEAR_shutdown_funcs']) && is_array($GLOBALS['_PEAR_shutdown_funcs']) && !empty($GLOBALS['_PEAR_shutdown_funcs']) ) { foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { call_user_func_array($value[0], $value[1]); } } } class PEAR_Error { var $error_message_prefix = ''; var $mode = PEAR_ERROR_RETURN; var $level = E_USER_NOTICE; var $code = -1; var $message = ''; var $userinfo = ''; var $backtrace = null; function __construct($message = 'unknown error', $code = null, $mode = null, $options = null, $userinfo = null) { if ($mode === null) { $mode = PEAR_ERROR_RETURN; } $this->message = $message; $this->code = $code; $this->mode = $mode; $this->userinfo = $userinfo; $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace'); if (!$skiptrace) { $this->backtrace = debug_backtrace(); if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { unset($this->backtrace[0]['object']); } } if ($mode & PEAR_ERROR_CALLBACK) { $this->level = E_USER_NOTICE; $this->callback = $options; } else { if ($options === null) { $options = E_USER_NOTICE; } $this->level = $options; $this->callback = null; } if ($this->mode & PEAR_ERROR_PRINT) { if (is_null($options) || is_int($options)) { $format = "%s"; } else { $format = $options; } printf($format, $this->getMessage()); } if ($this->mode & PEAR_ERROR_TRIGGER) { trigger_error($this->getMessage(), $this->level); } if ($this->mode & PEAR_ERROR_DIE) { $msg = $this->getMessage(); if (is_null($options) || is_int($options)) { $format = "%s"; if (substr($msg, -1) != "\n") { $msg .= "\n"; } } else { $format = $options; } die(sprintf($format, $msg)); } if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) { call_user_func($this->callback, $this); } if ($this->mode & PEAR_ERROR_EXCEPTION) { trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); eval('$e = new Exception($this->message, $this->code);throw($e);'); } } function getMode() { return $this->mode; } function getCallback() { return $this->callback; } function getMessage() { return ($this->error_message_prefix . $this->message); } function getCode() { return $this->code; } function getType() { return get_class($this); } function getUserInfo() { return $this->userinfo; } function getDebugInfo() { return $this->getUserInfo(); } function getBacktrace($frame = null) { if (defined('PEAR_IGNORE_BACKTRACE')) { return null; } if ($frame === null) { return $this->backtrace; } return $this->backtrace[$frame]; } function addUserInfo($info) { if (empty($this->userinfo)) { $this->userinfo = $info; } else { $this->userinfo .= " ** $info"; } } function __toString() { return $this->getMessage(); } function toString() { $modes = array(); $levels = array(E_USER_NOTICE => 'notice', E_USER_WARNING => 'warning', E_USER_ERROR => 'error'); if ($this->mode & PEAR_ERROR_CALLBACK) { if (is_array($this->callback)) { $callback = (is_object($this->callback[0]) ? strtolower(get_class($this->callback[0])) : $this->callback[0]) . '::' . $this->callback[1]; } else { $callback = $this->callback; } return sprintf('[%s: message="%s" code=%d mode=callback '. 'callback=%s prefix="%s" info="%s"]', strtolower(get_class($this)), $this->message, $this->code, $callback, $this->error_message_prefix, $this->userinfo); } if ($this->mode & PEAR_ERROR_PRINT) { $modes[] = 'print'; } if ($this->mode & PEAR_ERROR_TRIGGER) { $modes[] = 'trigger'; } if ($this->mode & PEAR_ERROR_DIE) { $modes[] = 'die'; } if ($this->mode & PEAR_ERROR_RETURN) { $modes[] = 'return'; } return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. 'prefix="%s" info="%s"]', strtolower(get_class($this)), $this->message, $this->code, implode("|", $modes), $levels[$this->level], $this->error_message_prefix, $this->userinfo); } } define('ARCHIVE_TAR_ATT_SEPARATOR', 90001); define('ARCHIVE_TAR_END_BLOCK', pack("a512", '')); if (!function_exists('gzopen') && function_exists('gzopen64')) { function gzopen($filename, $mode, $use_include_path = 0) { return gzopen64($filename, $mode, $use_include_path); } } if (!function_exists('gztell') && function_exists('gztell64')) { function gztell($zp) { return gztell64($zp); } } if (!function_exists('gzseek') && function_exists('gzseek64')) { function gzseek($zp, $offset, $whence = SEEK_SET) { return gzseek64($zp, $offset, $whence); } } class Archive_Tar extends PEAR { public $_tarname = ''; public $_compress = false; public $_compress_type = 'none'; public $_separator = ' '; public $_file = 0; public $_temp_tarname = ''; public $_ignore_regexp = ''; public $error_object = null; public function __construct($p_tarname, $p_compress = null) { parent::__construct(); $this->_compress = false; $this->_compress_type = 'none'; if (($p_compress === null) || ($p_compress == '')) { if (@file_exists($p_tarname)) { if ($fp = @fopen($p_tarname, "rb")) { $data = fread($fp, 2); fclose($fp); if ($data == "\37\213") { $this->_compress = true; $this->_compress_type = 'gz'; } elseif ($data == "BZ") { $this->_compress = true; $this->_compress_type = 'bz2'; } elseif (file_get_contents($p_tarname, false, null, 1, 4) == '7zXZ') { $this->_compress = true; $this->_compress_type = 'lzma2'; } } } else { if (substr($p_tarname, -2) == 'gz') { $this->_compress = true; $this->_compress_type = 'gz'; } elseif ((substr($p_tarname, -3) == 'bz2') || (substr($p_tarname, -2) == 'bz') ) { $this->_compress = true; $this->_compress_type = 'bz2'; } else { if (substr($p_tarname, -2) == 'xz') { $this->_compress = true; $this->_compress_type = 'lzma2'; } } } } else { if (($p_compress === true) || ($p_compress == 'gz')) { $this->_compress = true; $this->_compress_type = 'gz'; } else { if ($p_compress == 'bz2') { $this->_compress = true; $this->_compress_type = 'bz2'; } else { if ($p_compress == 'lzma2') { $this->_compress = true; $this->_compress_type = 'lzma2'; } else { $this->_error( "Unsupported compression type '$p_compress'\n" . "Supported types are 'gz', 'bz2' and 'lzma2'.\n" ); return false; } } } } $this->_tarname = $p_tarname; if ($this->_compress) { if ($this->_compress_type == 'gz') { $extname = 'zlib'; } else { if ($this->_compress_type == 'bz2') { $extname = 'bz2'; } else { if ($this->_compress_type == 'lzma2') { $extname = 'xz'; } } } if (!extension_loaded($extname)) { PEAR::loadExtension($extname); } if (!extension_loaded($extname)) { $this->_error( "The extension '$extname' couldn't be found.\n" . "Please make sure your version of PHP was built " . "with '$extname' support.\n" ); return false; } } } public function __destruct() { $this->_close(); if ($this->_temp_tarname != '') { @unlink($this->_temp_tarname); } } public function create($p_filelist) { return $this->createModify($p_filelist, '', ''); } public function add($p_filelist) { return $this->addModify($p_filelist, '', ''); } public function extract($p_path = '', $p_preserve = false) { return $this->extractModify($p_path, '', $p_preserve); } public function listContent() { $v_list_detail = array(); if ($this->_openRead()) { if (!$this->_extractList('', $v_list_detail, "list", '', '')) { unset($v_list_detail); $v_list_detail = 0; } $this->_close(); } return $v_list_detail; } public function createModify($p_filelist, $p_add_dir, $p_remove_dir = '') { $v_result = true; if (!$this->_openWrite()) { return false; } if ($p_filelist != '') { if (is_array($p_filelist)) { $v_list = $p_filelist; } elseif (is_string($p_filelist)) { $v_list = explode($this->_separator, $p_filelist); } else { $this->_cleanFile(); $this->_error('Invalid file list'); return false; } $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir); } if ($v_result) { $this->_writeFooter(); $this->_close(); } else { $this->_cleanFile(); } return $v_result; } public function addModify($p_filelist, $p_add_dir, $p_remove_dir = '') { $v_result = true; if (!$this->_isArchive()) { $v_result = $this->createModify( $p_filelist, $p_add_dir, $p_remove_dir ); } else { if (is_array($p_filelist)) { $v_list = $p_filelist; } elseif (is_string($p_filelist)) { $v_list = explode($this->_separator, $p_filelist); } else { $this->_error('Invalid file list'); return false; } $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir); } return $v_result; } public function addString($p_filename, $p_string, $p_datetime = false, $p_params = array()) { $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time()); $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600; $p_type = @$p_params["type"] ? $p_params["type"] : ""; $p_uid = @$p_params["uid"] ? $p_params["uid"] : ""; $p_gid = @$p_params["gid"] ? $p_params["gid"] : ""; $v_result = true; if (!$this->_isArchive()) { if (!$this->_openWrite()) { return false; } $this->_close(); } if (!$this->_openAppend()) { return false; } $v_result = $this->_addString($p_filename, $p_string, $p_datetime, $p_params); $this->_writeFooter(); $this->_close(); return $v_result; } public function extractModify($p_path, $p_remove_path, $p_preserve = false) { $v_result = true; $v_list_detail = array(); if ($v_result = $this->_openRead()) { $v_result = $this->_extractList( $p_path, $v_list_detail, "complete", 0, $p_remove_path, $p_preserve ); $this->_close(); } return $v_result; } public function extractInString($p_filename) { if ($this->_openRead()) { $v_result = $this->_extractInString($p_filename); $this->_close(); } else { $v_result = null; } return $v_result; } public function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false) { $v_result = true; $v_list_detail = array(); if (is_array($p_filelist)) { $v_list = $p_filelist; } elseif (is_string($p_filelist)) { $v_list = explode($this->_separator, $p_filelist); } else { $this->_error('Invalid string list'); return false; } if ($v_result = $this->_openRead()) { $v_result = $this->_extractList( $p_path, $v_list_detail, "partial", $v_list, $p_remove_path, $p_preserve ); $this->_close(); } return $v_result; } public function setAttribute() { $v_result = true; if (($v_size = func_num_args()) == 0) { return true; } $v_att_list = & func_get_args(); $i = 0; while ($i < $v_size) { switch ($v_att_list[$i]) { case ARCHIVE_TAR_ATT_SEPARATOR : if (($i + 1) >= $v_size) { $this->_error( 'Invalid number of parameters for ' . 'attribute ARCHIVE_TAR_ATT_SEPARATOR' ); return false; } $this->_separator = $v_att_list[$i + 1]; $i++; break; default : $this->_error('Unknown attribute code ' . $v_att_list[$i] . ''); return false; } $i++; } return $v_result; } public function setIgnoreRegexp($regexp) { $this->_ignore_regexp = $regexp; } public function setIgnoreList($list) { $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list); $regexp = '#/' . join('$|/', $list) . '#'; $this->setIgnoreRegexp($regexp); } public function _error($p_message) { $this->error_object = $this->raiseError($p_message); } public function _warning($p_message) { $this->error_object = $this->raiseError($p_message); } public function _isArchive($p_filename = null) { if ($p_filename == null) { $p_filename = $this->_tarname; } clearstatcache(); return @is_file($p_filename) && !@is_link($p_filename); } public function _openWrite() { if ($this->_compress_type == 'gz' && function_exists('gzopen')) { $this->_file = @gzopen($this->_tarname, "wb9"); } else { if ($this->_compress_type == 'bz2' && function_exists('bzopen')) { $this->_file = @bzopen($this->_tarname, "w"); } else { if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) { $this->_file = @xzopen($this->_tarname, 'w'); } else { if ($this->_compress_type == 'none') { $this->_file = @fopen($this->_tarname, "wb"); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); return false; } } } } if ($this->_file == 0) { $this->_error( 'Unable to open in write mode \'' . $this->_tarname . '\'' ); return false; } return true; } public function _openRead() { if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') { if ($this->_temp_tarname == '') { $this->_temp_tarname = uniqid('tar') . '.tmp'; if (!$v_file_from = @fopen($this->_tarname, 'rb')) { $this->_error( 'Unable to open in read mode \'' . $this->_tarname . '\'' ); $this->_temp_tarname = ''; return false; } if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { $this->_error( 'Unable to open in write mode \'' . $this->_temp_tarname . '\'' ); $this->_temp_tarname = ''; return false; } while ($v_data = @fread($v_file_from, 1024)) { @fwrite($v_file_to, $v_data); } @fclose($v_file_from); @fclose($v_file_to); } $v_filename = $this->_temp_tarname; } else { $v_filename = $this->_tarname; } if ($this->_compress_type == 'gz' && function_exists('gzopen')) { $this->_file = @gzopen($v_filename, "rb"); } else { if ($this->_compress_type == 'bz2' && function_exists('bzopen')) { $this->_file = @bzopen($v_filename, "r"); } else { if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) { $this->_file = @xzopen($v_filename, "r"); } else { if ($this->_compress_type == 'none') { $this->_file = @fopen($v_filename, "rb"); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); return false; } } } } if ($this->_file == 0) { $this->_error('Unable to open in read mode \'' . $v_filename . '\''); return false; } return true; } public function _openReadWrite() { if ($this->_compress_type == 'gz') { $this->_file = @gzopen($this->_tarname, "r+b"); } else { if ($this->_compress_type == 'bz2') { $this->_error( 'Unable to open bz2 in read/write mode \'' . $this->_tarname . '\' (limitation of bz2 extension)' ); return false; } else { if ($this->_compress_type == 'lzma2') { $this->_error( 'Unable to open lzma2 in read/write mode \'' . $this->_tarname . '\' (limitation of lzma2 extension)' ); return false; } else { if ($this->_compress_type == 'none') { $this->_file = @fopen($this->_tarname, "r+b"); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); return false; } } } } if ($this->_file == 0) { $this->_error( 'Unable to open in read/write mode \'' . $this->_tarname . '\'' ); return false; } return true; } public function _close() { if (is_resource($this->_file)) { if ($this->_compress_type == 'gz') { @gzclose($this->_file); } else { if ($this->_compress_type == 'bz2') { @bzclose($this->_file); } else { if ($this->_compress_type == 'lzma2') { @xzclose($this->_file); } else { if ($this->_compress_type == 'none') { @fclose($this->_file); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } $this->_file = 0; } if ($this->_temp_tarname != '') { @unlink($this->_temp_tarname); $this->_temp_tarname = ''; } return true; } public function _cleanFile() { $this->_close(); if ($this->_temp_tarname != '') { @unlink($this->_temp_tarname); $this->_temp_tarname = ''; } else { @unlink($this->_tarname); } $this->_tarname = ''; return true; } public function _writeBlock($p_binary_data, $p_len = null) { if (is_resource($this->_file)) { if ($p_len === null) { if ($this->_compress_type == 'gz') { @gzputs($this->_file, $p_binary_data); } else { if ($this->_compress_type == 'bz2') { @bzwrite($this->_file, $p_binary_data); } else { if ($this->_compress_type == 'lzma2') { @xzwrite($this->_file, $p_binary_data); } else { if ($this->_compress_type == 'none') { @fputs($this->_file, $p_binary_data); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } } else { if ($this->_compress_type == 'gz') { @gzputs($this->_file, $p_binary_data, $p_len); } else { if ($this->_compress_type == 'bz2') { @bzwrite($this->_file, $p_binary_data, $p_len); } else { if ($this->_compress_type == 'lzma2') { @xzwrite($this->_file, $p_binary_data, $p_len); } else { if ($this->_compress_type == 'none') { @fputs($this->_file, $p_binary_data, $p_len); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } } } return true; } public function _readBlock() { $v_block = null; if (is_resource($this->_file)) { if ($this->_compress_type == 'gz') { $v_block = @gzread($this->_file, 512); } else { if ($this->_compress_type == 'bz2') { $v_block = @bzread($this->_file, 512); } else { if ($this->_compress_type == 'lzma2') { $v_block = @xzread($this->_file, 512); } else { if ($this->_compress_type == 'none') { $v_block = @fread($this->_file, 512); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } } return $v_block; } public function _jumpBlock($p_len = null) { if (is_resource($this->_file)) { if ($p_len === null) { $p_len = 1; } if ($this->_compress_type == 'gz') { @gzseek($this->_file, gztell($this->_file) + ($p_len * 512)); } else { if ($this->_compress_type == 'bz2') { for ($i = 0; $i < $p_len; $i++) { $this->_readBlock(); } } else { if ($this->_compress_type == 'lzma2') { for ($i = 0; $i < $p_len; $i++) { $this->_readBlock(); } } else { if ($this->_compress_type == 'none') { @fseek($this->_file, $p_len * 512, SEEK_CUR); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } } return true; } public function _writeFooter() { if (is_resource($this->_file)) { $v_binary_data = pack('a1024', ''); $this->_writeBlock($v_binary_data); } return true; } public function _addList($p_list, $p_add_dir, $p_remove_dir) { $v_result = true; $v_header = array(); $p_add_dir = $this->_translateWinPath($p_add_dir); $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); if (!$this->_file) { $this->_error('Invalid file descriptor'); return false; } if (sizeof($p_list) == 0) { return true; } foreach ($p_list as $v_filename) { if (!$v_result) { break; } if ($v_filename == $this->_tarname) { continue; } if ($v_filename == '') { continue; } if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/' . $v_filename)) { $this->_warning("File '$v_filename' ignored"); continue; } if (!file_exists($v_filename) && !is_link($v_filename)) { $this->_warning("File '$v_filename' does not exist"); continue; } if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) { return false; } if (@is_dir($v_filename) && !@is_link($v_filename)) { if (!($p_hdir = opendir($v_filename))) { $this->_warning("Directory '$v_filename' can not be read"); continue; } while (false !== ($p_hitem = readdir($p_hdir))) { if (($p_hitem != '.') && ($p_hitem != '..')) { if ($v_filename != ".") { $p_temp_list[0] = $v_filename . '/' . $p_hitem; } else { $p_temp_list[0] = $p_hitem; } $v_result = $this->_addList( $p_temp_list, $p_add_dir, $p_remove_dir ); } } unset($p_temp_list); unset($p_hdir); unset($p_hitem); } } return $v_result; } public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null) { if (!$this->_file) { $this->_error('Invalid file descriptor'); return false; } if ($p_filename == '') { $this->_error('Invalid file name'); return false; } if (is_null($v_stored_filename)) { $p_filename = $this->_translateWinPath($p_filename, false); $v_stored_filename = $p_filename; if (strcmp($p_filename, $p_remove_dir) == 0) { return true; } if ($p_remove_dir != '') { if (substr($p_remove_dir, -1) != '/') { $p_remove_dir .= '/'; } if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) { $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); } } $v_stored_filename = $this->_translateWinPath($v_stored_filename); if ($p_add_dir != '') { if (substr($p_add_dir, -1) == '/') { $v_stored_filename = $p_add_dir . $v_stored_filename; } else { $v_stored_filename = $p_add_dir . '/' . $v_stored_filename; } } $v_stored_filename = $this->_pathReduction($v_stored_filename); } if ($this->_isArchive($p_filename)) { if (($v_file = @fopen($p_filename, "rb")) == 0) { $this->_warning( "Unable to open file '" . $p_filename . "' in binary read mode" ); return true; } if (!$this->_writeHeader($p_filename, $v_stored_filename)) { return false; } while (($v_buffer = fread($v_file, 512)) != '') { $v_binary_data = pack("a512", "$v_buffer"); $this->_writeBlock($v_binary_data); } fclose($v_file); } else { if (!$this->_writeHeader($p_filename, $v_stored_filename)) { return false; } } return true; } public function _addString($p_filename, $p_string, $p_datetime = false, $p_params = array()) { $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time()); $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600; $p_type = @$p_params["type"] ? $p_params["type"] : ""; $p_uid = @$p_params["uid"] ? $p_params["uid"] : 0; $p_gid = @$p_params["gid"] ? $p_params["gid"] : 0; if (!$this->_file) { $this->_error('Invalid file descriptor'); return false; } if ($p_filename == '') { $this->_error('Invalid file name'); return false; } $p_filename = $this->_translateWinPath($p_filename, false); if ($p_datetime === false) { $p_datetime = time(); } if (!$this->_writeHeaderBlock( $p_filename, strlen($p_string), $p_stamp, $p_mode, $p_type, $p_uid, $p_gid ) ) { return false; } $i = 0; while (($v_buffer = substr($p_string, (($i++) * 512), 512)) != '') { $v_binary_data = pack("a512", $v_buffer); $this->_writeBlock($v_binary_data); } return true; } public function _writeHeader($p_filename, $p_stored_filename) { if ($p_stored_filename == '') { $p_stored_filename = $p_filename; } $v_reduce_filename = $this->_pathReduction($p_stored_filename); if (strlen($v_reduce_filename) > 99) { if (!$this->_writeLongHeader($v_reduce_filename)) { return false; } } $v_info = lstat($p_filename); $v_uid = sprintf("%07s", DecOct($v_info[4])); $v_gid = sprintf("%07s", DecOct($v_info[5])); $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777)); $v_mtime = sprintf("%011s", DecOct($v_info['mtime'])); $v_linkname = ''; if (@is_link($p_filename)) { $v_typeflag = '2'; $v_linkname = readlink($p_filename); $v_size = sprintf("%011s", DecOct(0)); } elseif (@is_dir($p_filename)) { $v_typeflag = "5"; $v_size = sprintf("%011s", DecOct(0)); } else { $v_typeflag = '0'; clearstatcache(); $v_size = sprintf("%011s", DecOct($v_info['size'])); } $v_magic = 'ustar '; $v_version = ' '; if (function_exists('posix_getpwuid')) { $userinfo = posix_getpwuid($v_info[4]); $groupinfo = posix_getgrgid($v_info[5]); $v_uname = $userinfo['name']; $v_gname = $groupinfo['name']; } else { $v_uname = ''; $v_gname = ''; } $v_devmajor = ''; $v_devminor = ''; $v_prefix = ''; $v_binary_data_first = pack( "a100a8a8a8a12a12", $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime ); $v_binary_data_last = pack( "a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '' ); $v_checksum = 0; for ($i = 0; $i < 148; $i++) { $v_checksum += ord(substr($v_binary_data_first, $i, 1)); } for ($i = 148; $i < 156; $i++) { $v_checksum += ord(' '); } for ($i = 156, $j = 0; $i < 512; $i++, $j++) { $v_checksum += ord(substr($v_binary_data_last, $j, 1)); } $this->_writeBlock($v_binary_data_first, 148); $v_checksum = sprintf("%06s ", DecOct($v_checksum)); $v_binary_data = pack("a8", $v_checksum); $this->_writeBlock($v_binary_data, 8); $this->_writeBlock($v_binary_data_last, 356); return true; } public function _writeHeaderBlock( $p_filename, $p_size, $p_mtime = 0, $p_perms = 0, $p_type = '', $p_uid = 0, $p_gid = 0 ) { $p_filename = $this->_pathReduction($p_filename); if (strlen($p_filename) > 99) { if (!$this->_writeLongHeader($p_filename)) { return false; } } if ($p_type == "5") { $v_size = sprintf("%011s", DecOct(0)); } else { $v_size = sprintf("%011s", DecOct($p_size)); } $v_uid = sprintf("%07s", DecOct($p_uid)); $v_gid = sprintf("%07s", DecOct($p_gid)); $v_perms = sprintf("%07s", DecOct($p_perms & 000777)); $v_mtime = sprintf("%11s", DecOct($p_mtime)); $v_linkname = ''; $v_magic = 'ustar '; $v_version = ' '; if (function_exists('posix_getpwuid')) { $userinfo = posix_getpwuid($p_uid); $groupinfo = posix_getgrgid($p_gid); $v_uname = $userinfo['name']; $v_gname = $groupinfo['name']; } else { $v_uname = ''; $v_gname = ''; } $v_devmajor = ''; $v_devminor = ''; $v_prefix = ''; $v_binary_data_first = pack( "a100a8a8a8a12A12", $p_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime ); $v_binary_data_last = pack( "a1a100a6a2a32a32a8a8a155a12", $p_type, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '' ); $v_checksum = 0; for ($i = 0; $i < 148; $i++) { $v_checksum += ord(substr($v_binary_data_first, $i, 1)); } for ($i = 148; $i < 156; $i++) { $v_checksum += ord(' '); } for ($i = 156, $j = 0; $i < 512; $i++, $j++) { $v_checksum += ord(substr($v_binary_data_last, $j, 1)); } $this->_writeBlock($v_binary_data_first, 148); $v_checksum = sprintf("%06s ", DecOct($v_checksum)); $v_binary_data = pack("a8", $v_checksum); $this->_writeBlock($v_binary_data, 8); $this->_writeBlock($v_binary_data_last, 356); return true; } public function _writeLongHeader($p_filename) { $v_size = sprintf("%11s ", DecOct(strlen($p_filename))); $v_typeflag = 'L'; $v_linkname = ''; $v_magic = ''; $v_version = ''; $v_uname = ''; $v_gname = ''; $v_devmajor = ''; $v_devminor = ''; $v_prefix = ''; $v_binary_data_first = pack( "a100a8a8a8a12a12", '././@LongLink', 0, 0, 0, $v_size, 0 ); $v_binary_data_last = pack( "a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '' ); $v_checksum = 0; for ($i = 0; $i < 148; $i++) { $v_checksum += ord(substr($v_binary_data_first, $i, 1)); } for ($i = 148; $i < 156; $i++) { $v_checksum += ord(' '); } for ($i = 156, $j = 0; $i < 512; $i++, $j++) { $v_checksum += ord(substr($v_binary_data_last, $j, 1)); } $this->_writeBlock($v_binary_data_first, 148); $v_checksum = sprintf("%06s ", DecOct($v_checksum)); $v_binary_data = pack("a8", $v_checksum); $this->_writeBlock($v_binary_data, 8); $this->_writeBlock($v_binary_data_last, 356); $i = 0; while (($v_buffer = substr($p_filename, (($i++) * 512), 512)) != '') { $v_binary_data = pack("a512", "$v_buffer"); $this->_writeBlock($v_binary_data); } return true; } public function _readHeader($v_binary_data, &$v_header) { if (strlen($v_binary_data) == 0) { $v_header['filename'] = ''; return true; } if (strlen($v_binary_data) != 512) { $v_header['filename'] = ''; $this->_error('Invalid block size : ' . strlen($v_binary_data)); return false; } if (!is_array($v_header)) { $v_header = array(); } $v_checksum = 0; for ($i = 0; $i < 148; $i++) { $v_checksum += ord(substr($v_binary_data, $i, 1)); } for ($i = 148; $i < 156; $i++) { $v_checksum += ord(' '); } for ($i = 156; $i < 512; $i++) { $v_checksum += ord(substr($v_binary_data, $i, 1)); } if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) { $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" . "a8checksum/a1typeflag/a100link/a6magic/a2version/" . "a32uname/a32gname/a8devmajor/a8devminor/a131prefix"; } else { $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" . "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" . "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix"; } $v_data = unpack($fmt, $v_binary_data); if (strlen($v_data["prefix"]) > 0) { $v_data["filename"] = "$v_data[prefix]/$v_data[filename]"; } $v_header['checksum'] = OctDec(trim($v_data['checksum'])); if ($v_header['checksum'] != $v_checksum) { $v_header['filename'] = ''; if (($v_checksum == 256) && ($v_header['checksum'] == 0)) { return true; } $this->_error( 'Invalid checksum for file "' . $v_data['filename'] . '" : ' . $v_checksum . ' calculated, ' . $v_header['checksum'] . ' expected' ); return false; } $v_header['filename'] = rtrim($v_data['filename'], "\0"); if ($this->_maliciousFilename($v_header['filename'])) { $this->_error( 'Malicious .tar detected, file "' . $v_header['filename'] . '" will not install in desired directory tree' ); return false; } $v_header['mode'] = OctDec(trim($v_data['mode'])); $v_header['uid'] = OctDec(trim($v_data['uid'])); $v_header['gid'] = OctDec(trim($v_data['gid'])); $v_header['size'] = OctDec(trim($v_data['size'])); $v_header['mtime'] = OctDec(trim($v_data['mtime'])); if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { $v_header['size'] = 0; } $v_header['link'] = trim($v_data['link']); return true; } private function _maliciousFilename($file) { if (strpos($file, '/../') !== false) { return true; } if (strpos($file, '../') === 0) { return true; } return false; } public function _readLongHeader(&$v_header) { $v_filename = ''; $v_filesize = $v_header['size']; $n = floor($v_header['size'] / 512); for ($i = 0; $i < $n; $i++) { $v_content = $this->_readBlock(); $v_filename .= $v_content; } if (($v_header['size'] % 512) != 0) { $v_content = $this->_readBlock(); $v_filename .= $v_content; } $v_binary_data = $this->_readBlock(); if (!$this->_readHeader($v_binary_data, $v_header)) { return false; } $v_filename = rtrim(substr($v_filename, 0, $v_filesize), "\0"); $v_header['filename'] = $v_filename; if ($this->_maliciousFilename($v_filename)) { $this->_error( 'Malicious .tar detected, file "' . $v_filename . '" will not install in desired directory tree' ); return false; } return true; } private function _extractInString($p_filename) { $v_result_str = ""; while (strlen($v_binary_data = $this->_readBlock()) != 0) { if (!$this->_readHeader($v_binary_data, $v_header)) { return null; } if ($v_header['filename'] == '') { continue; } if ($v_header['typeflag'] == 'L') { if (!$this->_readLongHeader($v_header)) { return null; } } if ($v_header['filename'] == $p_filename) { if ($v_header['typeflag'] == "5") { $this->_error( 'Unable to extract in string a directory ' . 'entry {' . $v_header['filename'] . '}' ); return null; } else { $n = floor($v_header['size'] / 512); for ($i = 0; $i < $n; $i++) { $v_result_str .= $this->_readBlock(); } if (($v_header['size'] % 512) != 0) { $v_content = $this->_readBlock(); $v_result_str .= substr( $v_content, 0, ($v_header['size'] % 512) ); } return $v_result_str; } } else { $this->_jumpBlock(ceil(($v_header['size'] / 512))); } } return null; } public function _extractList( $p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path, $p_preserve = false ) { $v_result = true; $v_nb = 0; $v_extract_all = true; $v_listing = false; $p_path = $this->_translateWinPath($p_path, false); if ($p_path == '' || (substr($p_path, 0, 1) != '/' && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':')) ) { $p_path = "./" . $p_path; } $p_remove_path = $this->_translateWinPath($p_remove_path); if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) { $p_remove_path .= '/'; } $p_remove_path_size = strlen($p_remove_path); switch ($p_mode) { case "complete" : $v_extract_all = true; $v_listing = false; break; case "partial" : $v_extract_all = false; $v_listing = false; break; case "list" : $v_extract_all = false; $v_listing = true; break; default : $this->_error('Invalid extract mode (' . $p_mode . ')'); return false; } clearstatcache(); while (strlen($v_binary_data = $this->_readBlock()) != 0) { $v_extract_file = false; $v_extraction_stopped = 0; if (!$this->_readHeader($v_binary_data, $v_header)) { return false; } if ($v_header['filename'] == '') { continue; } if ($v_header['typeflag'] == 'L') { if (!$this->_readLongHeader($v_header)) { return false; } } if ($v_header['typeflag'] == 'x' || $v_header['typeflag'] == 'g') { $this->_jumpBlock(ceil(($v_header['size'] / 512))); continue; } if ((!$v_extract_all) && (is_array($p_file_list))) { $v_extract_file = false; for ($i = 0; $i < sizeof($p_file_list); $i++) { if (substr($p_file_list[$i], -1) == '/') { if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i]) ) { $v_extract_file = true; break; } } elseif ($p_file_list[$i] == $v_header['filename']) { $v_extract_file = true; break; } } } else { $v_extract_file = true; } if (($v_extract_file) && (!$v_listing)) { if (($p_remove_path != '') && (substr($v_header['filename'] . '/', 0, $p_remove_path_size) == $p_remove_path) ) { $v_header['filename'] = substr( $v_header['filename'], $p_remove_path_size ); if ($v_header['filename'] == '') { continue; } } if (($p_path != './') && ($p_path != '/')) { while (substr($p_path, -1) == '/') { $p_path = substr($p_path, 0, strlen($p_path) - 1); } if (substr($v_header['filename'], 0, 1) == '/') { $v_header['filename'] = $p_path . $v_header['filename']; } else { $v_header['filename'] = $p_path . '/' . $v_header['filename']; } } if (file_exists($v_header['filename'])) { if ((@is_dir($v_header['filename'])) && ($v_header['typeflag'] == '') ) { $this->_error( 'File ' . $v_header['filename'] . ' already exists as a directory' ); return false; } if (($this->_isArchive($v_header['filename'])) && ($v_header['typeflag'] == "5") ) { $this->_error( 'Directory ' . $v_header['filename'] . ' already exists as a file' ); return false; } if (!is_writeable($v_header['filename'])) { $this->_error( 'File ' . $v_header['filename'] . ' already exists and is write protected' ); return false; } if (filemtime($v_header['filename']) > $v_header['mtime']) { } } elseif (($v_result = $this->_dirCheck( ($v_header['typeflag'] == "5" ? $v_header['filename'] : dirname($v_header['filename'])) )) != 1 ) { $this->_error('Unable to create path for ' . $v_header['filename']); return false; } if ($v_extract_file) { if ($v_header['typeflag'] == "5") { if (!@file_exists($v_header['filename'])) { if (!@mkdir($v_header['filename'], 0777)) { $this->_error( 'Unable to create directory {' . $v_header['filename'] . '}' ); return false; } } } elseif ($v_header['typeflag'] == "2") { if (@file_exists($v_header['filename'])) { @unlink($v_header['filename']); } if (!@symlink($v_header['link'], $v_header['filename'])) { $this->_error( 'Unable to extract symbolic link {' . $v_header['filename'] . '}' ); return false; } } else { if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { $this->_error( 'Error while opening {' . $v_header['filename'] . '} in write binary mode' ); return false; } else { $n = floor($v_header['size'] / 512); for ($i = 0; $i < $n; $i++) { $v_content = $this->_readBlock(); fwrite($v_dest_file, $v_content, 512); } if (($v_header['size'] % 512) != 0) { $v_content = $this->_readBlock(); fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); } @fclose($v_dest_file); if ($p_preserve) { @chown($v_header['filename'], $v_header['uid']); @chgrp($v_header['filename'], $v_header['gid']); } @touch($v_header['filename'], $v_header['mtime']); if ($v_header['mode'] & 0111) { $mode = fileperms($v_header['filename']) | (~umask() & 0111); @chmod($v_header['filename'], $mode); } } clearstatcache(); if (!is_file($v_header['filename'])) { $this->_error( 'Extracted file ' . $v_header['filename'] . 'does not exist. Archive may be corrupted.' ); return false; } $filesize = filesize($v_header['filename']); if ($filesize != $v_header['size']) { $this->_error( 'Extracted file ' . $v_header['filename'] . ' does not have the correct file size \'' . $filesize . '\' (' . $v_header['size'] . ' expected). Archive may be corrupted.' ); return false; } } } else { $this->_jumpBlock(ceil(($v_header['size'] / 512))); } } else { $this->_jumpBlock(ceil(($v_header['size'] / 512))); } if ($v_listing || $v_extract_file || $v_extraction_stopped) { if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename'] ) { $v_file_dir = ''; } if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) { $v_file_dir = '/'; } $p_list_detail[$v_nb++] = $v_header; if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) { return true; } } } return true; } public function _openAppend() { if (filesize($this->_tarname) == 0) { return $this->_openWrite(); } if ($this->_compress) { $this->_close(); if (!@rename($this->_tarname, $this->_tarname . ".tmp")) { $this->_error( 'Error while renaming \'' . $this->_tarname . '\' to temporary file \'' . $this->_tarname . '.tmp\'' ); return false; } if ($this->_compress_type == 'gz') { $v_temp_tar = @gzopen($this->_tarname . ".tmp", "rb"); } elseif ($this->_compress_type == 'bz2') { $v_temp_tar = @bzopen($this->_tarname . ".tmp", "r"); } elseif ($this->_compress_type == 'lzma2') { $v_temp_tar = @xzopen($this->_tarname . ".tmp", "r"); } if ($v_temp_tar == 0) { $this->_error( 'Unable to open file \'' . $this->_tarname . '.tmp\' in binary read mode' ); @rename($this->_tarname . ".tmp", $this->_tarname); return false; } if (!$this->_openWrite()) { @rename($this->_tarname . ".tmp", $this->_tarname); return false; } if ($this->_compress_type == 'gz') { $end_blocks = 0; while (!@gzeof($v_temp_tar)) { $v_buffer = @gzread($v_temp_tar, 512); if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { $end_blocks++; continue; } elseif ($end_blocks > 0) { for ($i = 0; $i < $end_blocks; $i++) { $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); } $end_blocks = 0; } $v_binary_data = pack("a512", $v_buffer); $this->_writeBlock($v_binary_data); } @gzclose($v_temp_tar); } elseif ($this->_compress_type == 'bz2') { $end_blocks = 0; while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) { if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { $end_blocks++; continue; } elseif ($end_blocks > 0) { for ($i = 0; $i < $end_blocks; $i++) { $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); } $end_blocks = 0; } $v_binary_data = pack("a512", $v_buffer); $this->_writeBlock($v_binary_data); } @bzclose($v_temp_tar); } elseif ($this->_compress_type == 'lzma2') { $end_blocks = 0; while (strlen($v_buffer = @xzread($v_temp_tar, 512)) > 0) { if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { $end_blocks++; continue; } elseif ($end_blocks > 0) { for ($i = 0; $i < $end_blocks; $i++) { $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); } $end_blocks = 0; } $v_binary_data = pack("a512", $v_buffer); $this->_writeBlock($v_binary_data); } @xzclose($v_temp_tar); } if (!@unlink($this->_tarname . ".tmp")) { $this->_error( 'Error while deleting temporary file \'' . $this->_tarname . '.tmp\'' ); } } else { if (!$this->_openReadWrite()) { return false; } clearstatcache(); $v_size = filesize($this->_tarname); fseek($this->_file, $v_size - 1024); if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { fseek($this->_file, $v_size - 1024); } elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { fseek($this->_file, $v_size - 512); } } return true; } public function _append($p_filelist, $p_add_dir = '', $p_remove_dir = '') { if (!$this->_openAppend()) { return false; } if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) { $this->_writeFooter(); } $this->_close(); return true; } public function _dirCheck($p_dir) { clearstatcache(); if ((@is_dir($p_dir)) || ($p_dir == '')) { return true; } $p_parent_dir = dirname($p_dir); if (($p_parent_dir != $p_dir) && ($p_parent_dir != '') && (!$this->_dirCheck($p_parent_dir)) ) { return false; } if (!@mkdir($p_dir, 0777)) { $this->_error("Unable to create directory '$p_dir'"); return false; } return true; } private function _pathReduction($p_dir) { $v_result = ''; if ($p_dir != '') { $v_list = explode('/', $p_dir); for ($i = sizeof($v_list) - 1; $i >= 0; $i--) { if ($v_list[$i] == ".") { } else { if ($v_list[$i] == "..") { $i--; } else { if (($v_list[$i] == '') && ($i != (sizeof($v_list) - 1)) && ($i != 0) ) { } else { $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? '/' . $v_result : ''); } } } } } if (defined('OS_WINDOWS') && OS_WINDOWS) { $v_result = strtr($v_result, '\\', '/'); } return $v_result; } public function _translateWinPath($p_path, $p_remove_disk_letter = true) { if (defined('OS_WINDOWS') && OS_WINDOWS) { if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false) ) { $p_path = substr($p_path, $v_position + 1); } if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) { $p_path = strtr($p_path, '\\', '/'); } } return $p_path; } }