PharStreamWrapper.php
Namespace
TYPO3\PharStreamWrapperFile
-
misc/
typo3/ phar-stream-wrapper/ src/ PharStreamWrapper.php
View source
<?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() {
stream_wrapper_restore('phar');
}
private function registerStreamWrapper() {
stream_wrapper_unregister('phar');
stream_wrapper_register('phar', get_class($this));
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
PharStreamWrapper |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.