Файловый менеджер - Редактировать - /home/wuectly/www/03cbe/phar-stream-wrapper.zip
Назад
PK 2�!]#�C C composer.jsonnu &1i� { "name": "typo3/phar-stream-wrapper", "description": "Interceptors for PHP's native phar:// stream handling", "type": "library", "license": "MIT", "homepage": "https://typo3.org/", "keywords": ["php", "phar", "stream-wrapper", "security"], "require": { "php": "^5.3.3 || ^7.0", "ext-json": "*", "brumann/polyfill-unserialize": "^1.0 || ^2.0" }, "require-dev": { "ext-xdebug": "*", "phpunit/phpunit": "^4.8.36" }, "suggest": { "ext-fileinfo": "For PHP builtin file type guessing, otherwise uses internal processing" }, "autoload": { "psr-4": { "TYPO3\\PharStreamWrapper\\": "src/" } }, "autoload-dev": { "psr-4": { "TYPO3\\PharStreamWrapper\\Tests\\": "tests/" } } } PK 2�!]��1� src/Manager.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ use TYPO3\PharStreamWrapper\Resolver\PharInvocation; use TYPO3\PharStreamWrapper\Resolver\PharInvocationCollection; use TYPO3\PharStreamWrapper\Resolver\PharInvocationResolver; class Manager { /** * @var self */ private static $instance; /** * @var Behavior */ private $behavior; /** * @var Resolvable */ private $resolver; /** * @var Collectable */ private $collection; /** * @param Behavior $behaviour * @param Resolvable $resolver * @param Collectable $collection * @return self */ public static function initialize( Behavior $behaviour, Resolvable $resolver = null, Collectable $collection = null ) { if (self::$instance === null) { self::$instance = new self($behaviour, $resolver, $collection); return self::$instance; } throw new \LogicException( 'Manager can only be initialized once', 1535189871 ); } /** * @return self */ public static function instance() { if (self::$instance !== null) { return self::$instance; } throw new \LogicException( 'Manager needs to be initialized first', 1535189872 ); } /** * @return bool */ public static function destroy() { if (self::$instance === null) { return false; } self::$instance = null; return true; } /** * @param Behavior $behaviour * @param Resolvable $resolver * @param Collectable $collection */ private function __construct( Behavior $behaviour, Resolvable $resolver = null, Collectable $collection = null ) { if ($collection === null) { $collection = new PharInvocationCollection(); } if ($resolver === null) { $resolver = new PharInvocationResolver(); } $this->collection = $collection; $this->resolver = $resolver; $this->behavior = $behaviour; } /** * @param string $path * @param string $command * @return bool */ public function assert($path, $command) { return $this->behavior->assert($path, $command); } /** * @param string $path * @param null|int $flags * @return null|PharInvocation */ public function resolve($path, $flags = null) { return $this->resolver->resolve($path, $flags); } /** * @return Collectable */ public function getCollection() { return $this->collection; } } PK 2�!]2��2 �2 src/PharStreamWrapper.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ use TYPO3\PharStreamWrapper\Resolver\PharInvocation; class PharStreamWrapper { /** * Internal stream constants that are not exposed to PHP, but used... * @see https://github.com/php/php-src/blob/e17fc0d73c611ad0207cac8a4a01ded38251a7dc/main/php_streams.h */ const STREAM_OPEN_FOR_INCLUDE = 128; /** * @var resource */ public $context; /** * @var resource */ protected $internalResource; /** * @var PharInvocation */ protected $invocation; /** * @return bool */ public function dir_closedir() { if (!is_resource($this->internalResource)) { return false; } $this->invokeInternalStreamWrapper( 'closedir', $this->internalResource ); return !is_resource($this->internalResource); } /** * @param string $path * @param int $options * @return bool */ public function dir_opendir($path, $options) { $this->assert($path, Behavior::COMMAND_DIR_OPENDIR); $this->internalResource = $this->invokeInternalStreamWrapper( 'opendir', $path, $this->context ); return is_resource($this->internalResource); } /** * @return string|false */ public function dir_readdir() { return $this->invokeInternalStreamWrapper( 'readdir', $this->internalResource ); } /** * @return bool */ public function dir_rewinddir() { if (!is_resource($this->internalResource)) { return false; } $this->invokeInternalStreamWrapper( 'rewinddir', $this->internalResource ); return is_resource($this->internalResource); } /** * @param string $path * @param int $mode * @param int $options * @return bool */ public function mkdir($path, $mode, $options) { $this->assert($path, Behavior::COMMAND_MKDIR); return $this->invokeInternalStreamWrapper( 'mkdir', $path, $mode, (bool) ($options & STREAM_MKDIR_RECURSIVE), $this->context ); } /** * @param string $path_from * @param string $path_to * @return bool */ public function rename($path_from, $path_to) { $this->assert($path_from, Behavior::COMMAND_RENAME); $this->assert($path_to, Behavior::COMMAND_RENAME); return $this->invokeInternalStreamWrapper( 'rename', $path_from, $path_to, $this->context ); } /** * @param string $path * @param int $options * @return bool */ public function rmdir($path, $options) { $this->assert($path, Behavior::COMMAND_RMDIR); return $this->invokeInternalStreamWrapper( 'rmdir', $path, $this->context ); } /** * @param int $cast_as */ public function stream_cast($cast_as) { throw new Exception( 'Method stream_select() cannot be used', 1530103999 ); } public function stream_close() { $this->invokeInternalStreamWrapper( 'fclose', $this->internalResource ); } /** * @return bool */ public function stream_eof() { return $this->invokeInternalStreamWrapper( 'feof', $this->internalResource ); } /** * @return bool */ public function stream_flush() { return $this->invokeInternalStreamWrapper( 'fflush', $this->internalResource ); } /** * @param int $operation * @return bool */ public function stream_lock($operation) { return $this->invokeInternalStreamWrapper( 'flock', $this->internalResource, $operation ); } /** * @param string $path * @param int $option * @param string|int $value * @return bool */ public function stream_metadata($path, $option, $value) { $this->assert($path, Behavior::COMMAND_STEAM_METADATA); if ($option === STREAM_META_TOUCH) { return call_user_func_array( array($this, 'invokeInternalStreamWrapper'), array_merge(array('touch', $path), (array) $value) ); } if ($option === STREAM_META_OWNER_NAME || $option === STREAM_META_OWNER) { return $this->invokeInternalStreamWrapper( 'chown', $path, $value ); } if ($option === STREAM_META_GROUP_NAME || $option === STREAM_META_GROUP) { return $this->invokeInternalStreamWrapper( 'chgrp', $path, $value ); } if ($option === STREAM_META_ACCESS) { return $this->invokeInternalStreamWrapper( 'chmod', $path, $value ); } return false; } /** * @param string $path * @param string $mode * @param int $options * @param string|null $opened_path * @return bool */ public function stream_open( $path, $mode, $options, &$opened_path = null ) { $this->assert($path, Behavior::COMMAND_STREAM_OPEN); $arguments = array($path, $mode, (bool) ($options & STREAM_USE_PATH)); // only add stream context for non include/require calls if (!($options & static::STREAM_OPEN_FOR_INCLUDE)) { $arguments[] = $this->context; // work around https://bugs.php.net/bug.php?id=66569 // for including files from Phar stream with OPcache enabled } else { Helper::resetOpCache(); } $this->internalResource = call_user_func_array( array($this, 'invokeInternalStreamWrapper'), array_merge(array('fopen'), $arguments) ); if (!is_resource($this->internalResource)) { return false; } if ($opened_path !== null) { $metaData = stream_get_meta_data($this->internalResource); $opened_path = $metaData['uri']; } return true; } /** * @param int $count * @return string */ public function stream_read($count) { return $this->invokeInternalStreamWrapper( 'fread', $this->internalResource, $count ); } /** * @param int $offset * @param int $whence * @return bool */ public function stream_seek($offset, $whence = SEEK_SET) { return $this->invokeInternalStreamWrapper( 'fseek', $this->internalResource, $offset, $whence ) !== -1; } /** * @param int $option * @param int $arg1 * @param int $arg2 * @return bool */ public function stream_set_option($option, $arg1, $arg2) { if ($option === STREAM_OPTION_BLOCKING) { return $this->invokeInternalStreamWrapper( 'stream_set_blocking', $this->internalResource, $arg1 ); } if ($option === STREAM_OPTION_READ_TIMEOUT) { return $this->invokeInternalStreamWrapper( 'stream_set_timeout', $this->internalResource, $arg1, $arg2 ); } if ($option === STREAM_OPTION_WRITE_BUFFER) { return $this->invokeInternalStreamWrapper( 'stream_set_write_buffer', $this->internalResource, $arg2 ) === 0; } return false; } /** * @return array */ public function stream_stat() { return $this->invokeInternalStreamWrapper( 'fstat', $this->internalResource ); } /** * @return int */ public function stream_tell() { return $this->invokeInternalStreamWrapper( 'ftell', $this->internalResource ); } /** * @param int $new_size * @return bool */ public function stream_truncate($new_size) { return $this->invokeInternalStreamWrapper( 'ftruncate', $this->internalResource, $new_size ); } /** * @param string $data * @return int */ public function stream_write($data) { return $this->invokeInternalStreamWrapper( 'fwrite', $this->internalResource, $data ); } /** * @param string $path * @return bool */ public function unlink($path) { $this->assert($path, Behavior::COMMAND_UNLINK); return $this->invokeInternalStreamWrapper( 'unlink', $path, $this->context ); } /** * @param string $path * @param int $flags * @return array|false */ public function url_stat($path, $flags) { $this->assert($path, Behavior::COMMAND_URL_STAT); $functionName = $flags & STREAM_URL_STAT_QUIET ? '@stat' : 'stat'; return $this->invokeInternalStreamWrapper($functionName, $path); } /** * @param string $path * @param string $command */ protected function assert($path, $command) { if (Manager::instance()->assert($path, $command) === true) { $this->collectInvocation($path); return; } throw new Exception( sprintf( 'Denied invocation of "%s" for command "%s"', $path, $command ), 1535189880 ); } /** * @param string $path */ protected function collectInvocation($path) { if (isset($this->invocation)) { return; } $manager = Manager::instance(); $this->invocation = $manager->resolve($path); if ($this->invocation === null) { throw new Exception( 'Expected invocation could not be resolved', 1556389591 ); } // confirm, previous interceptor(s) validated invocation $this->invocation->confirm(); $collection = $manager->getCollection(); if (!$collection->has($this->invocation)) { $collection->collect($this->invocation); } } /** * @return Manager|Assertable * @deprecated Use Manager::instance() directly */ protected function resolveAssertable() { return Manager::instance(); } /** * Invokes commands on the native PHP Phar stream wrapper. * * @param string $functionName * @param mixed ...$arguments * @return mixed */ private function invokeInternalStreamWrapper($functionName) { $arguments = func_get_args(); array_shift($arguments); $silentExecution = $functionName[0] === '@'; $functionName = ltrim($functionName, '@'); $this->restoreInternalSteamWrapper(); try { if ($silentExecution) { $result = @call_user_func_array($functionName, $arguments); } else { $result = call_user_func_array($functionName, $arguments); } } catch (\Exception $exception) { $this->registerStreamWrapper(); throw $exception; } catch (\Throwable $throwable) { $this->registerStreamWrapper(); throw $throwable; } $this->registerStreamWrapper(); return $result; } private function restoreInternalSteamWrapper() { if (PHP_VERSION_ID < 70324 || PHP_VERSION_ID >= 70400 && PHP_VERSION_ID < 70412) { stream_wrapper_restore('phar'); } else { // with https://github.com/php/php-src/pull/6183 (PHP #76943) the // behavior of `stream_wrapper_restore()` did change for // PHP 8.0-RC1, 7.4.12 and 7.3.24 @stream_wrapper_restore('phar'); } } private function registerStreamWrapper() { stream_wrapper_unregister('phar'); stream_wrapper_register('phar', get_class($this)); } } PK 2�!]�� src/Helper.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ /** * Helper provides low-level tools on file name resolving. However it does not * (and should not) maintain any runtime state information. In order to resolve * Phar archive paths according resolvers have to be used. * * @see \TYPO3\PharStreamWrapper\Resolvable::resolve() */ class Helper { /* * Resets PHP's OPcache if enabled as work-around for issues in `include()` * or `require()` calls and OPcache delivering wrong results. * * @see https://bugs.php.net/bug.php?id=66569 */ public static function resetOpCache() { if (function_exists('opcache_reset') && function_exists('opcache_get_status') ) { $status = @opcache_get_status(); if (!empty($status['opcache_enabled'])) { @opcache_reset(); } } } /** * Determines base file that can be accessed using the regular file system. * For e.g. "phar:///home/user/bundle.phar/content.txt" that would result * into "/home/user/bundle.phar". * * @param string $path * @return string|null */ public static function determineBaseFile($path) { $parts = explode('/', static::normalizePath($path)); while (count($parts)) { $currentPath = implode('/', $parts); if (@is_file($currentPath) && realpath($currentPath) !== false) { return $currentPath; } array_pop($parts); } return null; } /** * @param string $path * @return bool */ public static function hasPharPrefix($path) { return stripos($path, 'phar://') === 0; } /** * @param string $path * @return string */ public static function removePharPrefix($path) { $path = trim($path); if (!static::hasPharPrefix($path)) { return $path; } return substr($path, 7); } /** * Normalizes a path, removes phar:// prefix, fixes Windows directory * separators. Result is without trailing slash. * * @param string $path * @return string */ public static function normalizePath($path) { return rtrim( static::normalizeWindowsPath( static::removePharPrefix($path) ), '/' ); } /** * Fixes a path for windows-backslashes and reduces double-slashes to single slashes * * @param string $path File path to process * @return string */ public static function normalizeWindowsPath($path) { return str_replace('\\', '/', $path); } /** * Resolves all dots, slashes and removes spaces after or before a path... * * @param string $path Input string * @return string Canonical path, always without trailing slash */ private static function getCanonicalPath($path) { $path = static::normalizeWindowsPath($path); $absolutePathPrefix = ''; if (static::isAbsolutePath($path)) { if (static::isWindows() && strpos($path, ':/') === 1) { $absolutePathPrefix = substr($path, 0, 3); $path = substr($path, 3); } else { $path = ltrim($path, '/'); $absolutePathPrefix = '/'; } } $pathParts = explode('/', $path); $pathPartsLength = count($pathParts); for ($partCount = 0; $partCount < $pathPartsLength; $partCount++) { // double-slashes in path: remove element if ($pathParts[$partCount] === '') { array_splice($pathParts, $partCount, 1); $partCount--; $pathPartsLength--; } // "." in path: remove element if ((isset($pathParts[$partCount]) ? $pathParts[$partCount] : '') === '.') { array_splice($pathParts, $partCount, 1); $partCount--; $pathPartsLength--; } // ".." in path: if ((isset($pathParts[$partCount]) ? $pathParts[$partCount] : '') === '..') { if ($partCount === 0) { array_splice($pathParts, $partCount, 1); $partCount--; $pathPartsLength--; } elseif ($partCount >= 1) { // Rremove this and previous element array_splice($pathParts, $partCount - 1, 2); $partCount -= 2; $pathPartsLength -= 2; } elseif ($absolutePathPrefix) { // can't go higher than root dir // simply remove this part and continue array_splice($pathParts, $partCount, 1); $partCount--; $pathPartsLength--; } } } return $absolutePathPrefix . implode('/', $pathParts); } /** * Checks if the $path is absolute or relative (detecting either '/' or * 'x:/' as first part of string) and returns TRUE if so. * * @param string $path File path to evaluate * @return bool */ private static function isAbsolutePath($path) { // Path starting with a / is always absolute, on every system // On Windows also a path starting with a drive letter is absolute: X:/ return (isset($path[0]) ? $path[0] : null) === '/' || static::isWindows() && ( strpos($path, ':/') === 1 || strpos($path, ':\\') === 1 ); } /** * @return bool */ private static function isWindows() { return stripos(PHP_OS, 'WIN') === 0; } } PK 2�!]H��Y� � src/Phar/Stub.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper\Phar; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ /** * @internal Experimental implementation of Phar archive internals */ class Stub { /** * @param string $content * @return self */ public static function fromContent($content) { $target = new static(); $target->content = $content; if ( stripos($content, 'Phar::mapPhar(') !== false && preg_match('#Phar\:\:mapPhar\(([^)]+)\)#', $content, $matches) ) { // remove spaces, single & double quotes // @todo `'my' . 'alias' . '.phar'` is not evaluated here $target->mappedAlias = trim($matches[1], ' \'"'); } return $target; } /** * @var string */ private $content; /** * @var string */ private $mappedAlias = ''; /** * @return string */ public function getContent() { return $this->content; } /** * @return string */ public function getMappedAlias() { return $this->mappedAlias; } } PK 2�!]��H� � % src/Phar/DeserializationException.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper\Phar; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ use TYPO3\PharStreamWrapper\Exception; class DeserializationException extends Exception { } PK 2�!]MXf�� � src/Phar/ReaderException.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper\Phar; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ use TYPO3\PharStreamWrapper\Exception; class ReaderException extends Exception { } PK 2�!]�D��J J src/Phar/Reader.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper\Phar; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ class Reader { /** * @var string */ private $fileName; /** * Mime-type in order to use zlib, bzip2 or no compression. * In case ext-fileinfo is not present only the relevant types * 'application/x-gzip' and 'application/x-bzip2' are assigned * to this class property. * * @var string */ private $fileType; /** * @param string $fileName */ public function __construct($fileName) { if (strpos($fileName, '://') !== false) { throw new ReaderException( 'File name must not contain stream prefix', 1539623708 ); } $this->fileName = $fileName; $this->fileType = $this->determineFileType(); } /** * @return Container */ public function resolveContainer() { $data = $this->extractData($this->resolveStream() . $this->fileName); if ($data['stubContent'] === null) { throw new ReaderException( 'Cannot resolve stub', 1547807881 ); } if ($data['manifestContent'] === null || $data['manifestLength'] === null) { throw new ReaderException( 'Cannot resolve manifest', 1547807882 ); } if (strlen($data['manifestContent']) < $data['manifestLength']) { throw new ReaderException( sprintf( 'Exected manifest length %d, got %d', strlen($data['manifestContent']), $data['manifestLength'] ), 1547807883 ); } return new Container( Stub::fromContent($data['stubContent']), Manifest::fromContent($data['manifestContent']) ); } /** * @param string $fileName e.g. '/path/file.phar' or 'compress.zlib:///path/file.phar' * @return array */ private function extractData($fileName) { $stubContent = null; $manifestContent = null; $manifestLength = null; $resource = fopen($fileName, 'r'); if (!is_resource($resource)) { throw new ReaderException( sprintf('Resource %s could not be opened', $fileName), 1547902055 ); } while (!feof($resource)) { $line = fgets($resource); // stop processing in case the system fails to read from a stream if ($line === false) { break; } // stop reading file when manifest can be extracted if ($manifestLength !== null && $manifestContent !== null && strlen($manifestContent) >= $manifestLength) { break; } $manifestPosition = strpos($line, '__HALT_COMPILER();'); // first line contains start of manifest if ($stubContent === null && $manifestContent === null && $manifestPosition !== false) { $stubContent = substr($line, 0, $manifestPosition - 1); $manifestContent = preg_replace('#^.*__HALT_COMPILER\(\);(?>[ \n]\?>(?>\r\n|\n)?)?#', '', $line); $manifestLength = $this->resolveManifestLength($manifestContent); // line contains start of stub } elseif ($stubContent === null) { $stubContent = $line; // line contains start of manifest } elseif ($manifestContent === null && $manifestPosition !== false) { $manifestContent = preg_replace('#^.*__HALT_COMPILER\(\);(?>[ \n]\?>(?>\r\n|\n)?)?#', '', $line); $manifestLength = $this->resolveManifestLength($manifestContent); // manifest has been started (thus is cannot be stub anymore), add content } elseif ($manifestContent !== null) { $manifestContent .= $line; $manifestLength = $this->resolveManifestLength($manifestContent); // stub has been started (thus cannot be manifest here, yet), add content } elseif ($stubContent !== null) { $stubContent .= $line; } } fclose($resource); return array( 'stubContent' => $stubContent, 'manifestContent' => $manifestContent, 'manifestLength' => $manifestLength, ); } /** * Resolves stream in order to handle compressed Phar archives. * * @return string */ private function resolveStream() { if ($this->fileType === 'application/x-gzip' || $this->fileType === 'application/gzip') { return 'compress.zlib://'; } elseif ($this->fileType === 'application/x-bzip2') { return 'compress.bzip2://'; } return ''; } /** * @return string */ private function determineFileType() { if (class_exists('\\finfo')) { $fileInfo = new \finfo(); return $fileInfo->file($this->fileName, FILEINFO_MIME_TYPE); } return $this->determineFileTypeByHeader(); } /** * In case ext-fileinfo is not present only the relevant types * 'application/x-gzip' and 'application/x-bzip2' are resolved. * * @return string */ private function determineFileTypeByHeader() { $resource = fopen($this->fileName, 'r'); if (!is_resource($resource)) { throw new ReaderException( sprintf('Resource %s could not be opened', $this->fileName), 1557753055 ); } $header = fgets($resource, 4); fclose($resource); $mimeType = ''; if (strpos($header, "\x42\x5a\x68") === 0) { $mimeType = 'application/x-bzip2'; } elseif (strpos($header, "\x1f\x8b") === 0) { $mimeType = 'application/x-gzip'; } return $mimeType; } /** * @param string $content * @return int|null */ private function resolveManifestLength($content) { if (strlen($content) < 4) { return null; } return static::resolveFourByteLittleEndian($content, 0); } /** * @param string $content * @param int $start * @return int */ public static function resolveFourByteLittleEndian($content, $start) { $payload = substr($content, $start, 4); if (!is_string($payload)) { throw new ReaderException( sprintf('Cannot resolve value at offset %d', $start), 1539614260 ); } $value = unpack('V', $payload); if (!isset($value[1])) { throw new ReaderException( sprintf('Cannot resolve value at offset %d', $start), 1539614261 ); } return $value[1]; } /** * @param string $content * @param int $start * @return int */ public static function resolveTwoByteBigEndian($content, $start) { $payload = substr($content, $start, 2); if (!is_string($payload)) { throw new ReaderException( sprintf('Cannot resolve value at offset %d', $start), 1539614263 ); } $value = unpack('n', $payload); if (!isset($value[1])) { throw new ReaderException( sprintf('Cannot resolve value at offset %d', $start), 1539614264 ); } return $value[1]; } } PK 2�!]�Q�fQ Q src/Phar/Manifest.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper\Phar; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ use Brumann\Polyfill\Unserialize; class Manifest { /** * @param string $content * @return self * @see http://php.net/manual/en/phar.fileformat.phar.php */ public static function fromContent($content) { $target = new static(); $target->manifestLength = Reader::resolveFourByteLittleEndian($content, 0); $target->amountOfFiles = Reader::resolveFourByteLittleEndian($content, 4); $target->flags = Reader::resolveFourByteLittleEndian($content, 10); $target->aliasLength = Reader::resolveFourByteLittleEndian($content, 14); $target->alias = substr($content, 18, $target->aliasLength); $target->metaDataLength = Reader::resolveFourByteLittleEndian($content, 18 + $target->aliasLength); $target->metaData = substr($content, 22 + $target->aliasLength, $target->metaDataLength); $apiVersionNibbles = Reader::resolveTwoByteBigEndian($content, 8); $target->apiVersion = implode('.', array( ($apiVersionNibbles & 0xf000) >> 12, ($apiVersionNibbles & 0x0f00) >> 8, ($apiVersionNibbles & 0x00f0) >> 4, )); return $target; } /** * @var int */ private $manifestLength; /** * @var int */ private $amountOfFiles; /** * @var string */ private $apiVersion; /** * @var int */ private $flags; /** * @var int */ private $aliasLength; /** * @var string */ private $alias; /** * @var int */ private $metaDataLength; /** * @var string */ private $metaData; /** * Avoid direct instantiation. */ private function __construct() { } /** * @return int */ public function getManifestLength() { return $this->manifestLength; } /** * @return int */ public function getAmountOfFiles() { return $this->amountOfFiles; } /** * @return string */ public function getApiVersion() { return $this->apiVersion; } /** * @return int */ public function getFlags() { return $this->flags; } /** * @return int */ public function getAliasLength() { return $this->aliasLength; } /** * @return string */ public function getAlias() { return $this->alias; } /** * @return int */ public function getMetaDataLength() { return $this->metaDataLength; } /** * @return string */ public function getMetaData() { return $this->metaData; } /** * @return mixed|null */ public function deserializeMetaData() { if (empty($this->metaData)) { return null; } $result = Unserialize::unserialize($this->metaData, array('allowed_classes' => false)); $serialized = json_encode($result); if (strpos($serialized, '__PHP_Incomplete_Class_Name') !== false) { throw new DeserializationException( 'Meta-data contains serialized object', 1539623382 ); } return $result; } } PK 2�!]/�'c c src/Phar/Container.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper\Phar; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ class Container { /** * @var Stub */ private $stub; /** * @var Manifest */ private $manifest; /** * @param Stub $stub * @param Manifest $manifest */ public function __construct(Stub $stub, Manifest $manifest) { $this->stub = $stub; $this->manifest = $manifest; } /** * @return Stub */ public function getStub() { return $this->stub; } /** * @return Manifest */ public function getManifest() { return $this->manifest; } /** * @return string */ public function getAlias() { return $this->manifest->getAlias() ?: $this->stub->getMappedAlias(); } } PK 2�!]��" " src/Assertable.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ interface Assertable { /** * @param string $path * @param string $command * @return bool */ public function assert($path, $command); } PK 2�!]��� � src/Resolver/PharInvocation.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper\Resolver; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ use TYPO3\PharStreamWrapper\Exception; class PharInvocation { /** * @var string */ private $baseName; /** * @var string */ private $alias; /** * @var bool * @see \TYPO3\PharStreamWrapper\PharStreamWrapper::collectInvocation() */ private $confirmed = false; /** * Arbitrary variables to be used by interceptors as registry * (e.g. in order to avoid duplicate processing and assertions) * * @var array */ private $variables; /** * @param string $baseName * @param string $alias */ public function __construct($baseName, $alias = '') { if ($baseName === '') { throw new Exception( 'Base-name cannot be empty', 1551283689 ); } $this->baseName = $baseName; $this->alias = $alias; } /** * @return string */ public function __toString() { return $this->baseName; } /** * @return string */ public function getBaseName() { return $this->baseName; } /** * @return null|string */ public function getAlias() { return $this->alias; } /** * @return bool */ public function isConfirmed() { return $this->confirmed; } public function confirm() { $this->confirmed = true; } /** * @param string $name * @return mixed|null */ public function getVariable($name) { if (!isset($this->variables[$name])) { return null; } return $this->variables[$name]; } /** * @param string $name * @param mixed $value */ public function setVariable($name, $value) { $this->variables[$name] = $value; } /** * @param PharInvocation $other * @return bool */ public function equals(PharInvocation $other) { return $other->baseName === $this->baseName && $other->alias === $this->alias; } }PK 2�!]W���e e ) src/Resolver/PharInvocationCollection.phpnu &1i� <?php namespace TYPO3\PharStreamWrapper\Resolver; /* * This file is part of the TYPO3 project. * * It is free software; you can redistribute it and/or modify it under the terms * of the MIT License (MIT). For the full copyright and license information, * please read the LICENSE file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! */ use TYPO3\PharStreamWrapper\Collectable; class PharInvocationCollection implements Collectable { const UNIQUE_INVOCATION = 1; const UNIQUE_BASE_NAME = 2; const DUPLICATE_ALIAS_WARNING = 32; /** * @var PharInvocation[] */ private $invocations = array(); /** * @param PharInvocation $invocation * @return bool */ public function has(PharInvocation $invocation) { return in_array($invocation, $this->invocations, true); } /** * @param PharInvocation $invocation * @param null|int $flags * @return bool */ public function collect(PharInvocation $invocation, $flags = null) { if ($flags === null) { $flags = static::UNIQUE_INVOCATION | static::DUPLICATE_ALIAS_WARNING; } if ($invocation->getBaseName() === '' || $invocation->getAlias() === '' || !$this->assertUniqueBaseName($invocation, $flags) || !$this->assertUniqueInvocation($invocation, $flags) ) { return false; } if ($flags & static::DUPLICATE_ALIAS_WARNING) { $this->triggerDuplicateAliasWarning($invocation); } $this->invocations[] = $invocation; return true; } /** * @param callable $callback * @param bool $reverse * @return null|PharInvocation */ public function findByCallback($callback, $reverse = false) { foreach ($this->getInvocations($reverse) as $invocation) { if (call_user_func($callback, $invocation) === true) { return $invocation; } } return null; } /** * Asserts that base-name is unique. This disallows having multiple invocations for * same base-name but having different alias names. * * @param PharInvocation $invocation * @param int $flags * @return bool */ private function assertUniqueBaseName(PharInvocation $invocation, $flags) { if (!($flags & static::UNIQUE_BASE_NAME)) { return true; } return $this->findByCallback( function (PharInvocation $candidate) use ($invocation) { return $candidate->getBaseName() === $invocation->getBaseName(); } ) === null; } /** * Asserts that combination of base-name and alias is unique. This allows having multiple * invocations for same base-name but having different alias names (for whatever reason). * * @param PharInvocation $invocation * @param int $flags * @return bool */ private function assertUniqueInvocation(PharInvocation $invocation, $flags) { if (!($flags & static::UNIQUE_INVOCATION)) { return true; } return $this->findByCallback( function (PharInvocation $candidate) use ($invocation) { return $candidate->equals($invocation); } ) === null; } /** * Triggers warning for invocations with same alias and same confirmation state. * * @param PharInvocation $invocation * @see \TYPO3\PharStreamWrapper\PharStreamWrapper::collectInvocation() */ private function triggerDuplicateAliasWarning(PharInvocation $invocation) { $sameAliasInvocation = $this->findByCallback( function (PharInvocation $candidate) use ($invocation) { return $candidate->isConfirmed() === $invocation->isConfirmed() && $candidate->getAlias() === $invocation->getAlias(); }, true ); if ($sameAliasInvocation === null) { return; } trigger_error( sprintf( 'Alias %s cannot be used by %s, already used by %s', $invocation->getAlias(), $invocation->getBaseName(), $sameAliasInvocation->getBaseName() ), E_USER_WARNING ); } /** * @param bool $reverse * @return PharInvocation[] */ private function getInvocations($reverse = false) { if ($reverse) { return array_reverse($this->invocations); } return $this->invocations; } }PK 2�!]���ܿ � '