[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/typo3/phar-stream-wrapper/src/ -> PharStreamWrapper.php (source)

   1  <?php
   2  declare(strict_types=1);
   3  namespace TYPO3\PharStreamWrapper;
   4  
   5  /*
   6   * This file is part of the TYPO3 project.
   7   *
   8   * It is free software; you can redistribute it and/or modify it under the terms
   9   * of the MIT License (MIT). For the full copyright and license information,
  10   * please read the LICENSE file that was distributed with this source code.
  11   *
  12   * The TYPO3 project - inspiring people to share!
  13   */
  14  
  15  use TYPO3\PharStreamWrapper\Resolver\PharInvocation;
  16  
  17  class PharStreamWrapper
  18  {
  19      /**
  20       * Internal stream constants that are not exposed to PHP, but used...
  21       * @see https://github.com/php/php-src/blob/e17fc0d73c611ad0207cac8a4a01ded38251a7dc/main/php_streams.h
  22       */
  23      const STREAM_OPEN_FOR_INCLUDE = 128;
  24  
  25      /**
  26       * @var resource
  27       */
  28      public $context;
  29  
  30      /**
  31       * @var resource
  32       */
  33      protected $internalResource;
  34  
  35      /**
  36       * @var PharInvocation
  37       */
  38      protected $invocation;
  39  
  40      /**
  41       * @return bool
  42       */
  43      public function dir_closedir(): bool
  44      {
  45          if (!is_resource($this->internalResource)) {
  46              return false;
  47          }
  48  
  49          $this->invokeInternalStreamWrapper(
  50              'closedir',
  51              $this->internalResource
  52          );
  53          return !is_resource($this->internalResource);
  54      }
  55  
  56      /**
  57       * @param string $path
  58       * @param int $options
  59       * @return bool
  60       */
  61      public function dir_opendir(string $path, int $options): bool
  62      {
  63          $this->assert($path, Behavior::COMMAND_DIR_OPENDIR);
  64          $this->internalResource = $this->invokeInternalStreamWrapper(
  65              'opendir',
  66              $path,
  67              $this->context
  68          );
  69          return is_resource($this->internalResource);
  70      }
  71  
  72      /**
  73       * @return string|false
  74       */
  75      public function dir_readdir()
  76      {
  77          return $this->invokeInternalStreamWrapper(
  78              'readdir',
  79              $this->internalResource
  80          );
  81      }
  82  
  83      /**
  84       * @return bool
  85       */
  86      public function dir_rewinddir(): bool
  87      {
  88          if (!is_resource($this->internalResource)) {
  89              return false;
  90          }
  91  
  92          $this->invokeInternalStreamWrapper(
  93              'rewinddir',
  94              $this->internalResource
  95          );
  96          return is_resource($this->internalResource);
  97      }
  98  
  99      /**
 100       * @param string $path
 101       * @param int $mode
 102       * @param int $options
 103       * @return bool
 104       */
 105      public function mkdir(string $path, int $mode, int $options): bool
 106      {
 107          $this->assert($path, Behavior::COMMAND_MKDIR);
 108          return $this->invokeInternalStreamWrapper(
 109              'mkdir',
 110              $path,
 111              $mode,
 112              (bool) ($options & STREAM_MKDIR_RECURSIVE),
 113              $this->context
 114          );
 115      }
 116  
 117      /**
 118       * @param string $path_from
 119       * @param string $path_to
 120       * @return bool
 121       */
 122      public function rename(string $path_from, string $path_to): bool
 123      {
 124          $this->assert($path_from, Behavior::COMMAND_RENAME);
 125          $this->assert($path_to, Behavior::COMMAND_RENAME);
 126          return $this->invokeInternalStreamWrapper(
 127              'rename',
 128              $path_from,
 129              $path_to,
 130              $this->context
 131          );
 132      }
 133  
 134      /**
 135       * @param string $path
 136       * @param int $options
 137       * @return bool
 138       */
 139      public function rmdir(string $path, int $options): bool
 140      {
 141          $this->assert($path, Behavior::COMMAND_RMDIR);
 142          return $this->invokeInternalStreamWrapper(
 143              'rmdir',
 144              $path,
 145              $this->context
 146          );
 147      }
 148  
 149      /**
 150       * @param int $cast_as
 151       */
 152      public function stream_cast(int $cast_as)
 153      {
 154          throw new Exception(
 155              'Method stream_select() cannot be used',
 156              1530103999
 157          );
 158      }
 159  
 160      public function stream_close()
 161      {
 162          $this->invokeInternalStreamWrapper(
 163              'fclose',
 164              $this->internalResource
 165          );
 166      }
 167  
 168      /**
 169       * @return bool
 170       */
 171      public function stream_eof(): bool
 172      {
 173          return $this->invokeInternalStreamWrapper(
 174              'feof',
 175              $this->internalResource
 176          );
 177      }
 178  
 179      /**
 180       * @return bool
 181       */
 182      public function stream_flush(): bool
 183      {
 184          return $this->invokeInternalStreamWrapper(
 185              'fflush',
 186              $this->internalResource
 187          );
 188      }
 189  
 190      /**
 191       * @param int $operation
 192       * @return bool
 193       */
 194      public function stream_lock(int $operation): bool
 195      {
 196          return $this->invokeInternalStreamWrapper(
 197              'flock',
 198              $this->internalResource,
 199              $operation
 200          );
 201      }
 202  
 203      /**
 204       * @param string $path
 205       * @param int $option
 206       * @param string|int $value
 207       * @return bool
 208       */
 209      public function stream_metadata(string $path, int $option, $value): bool
 210      {
 211          $this->assert($path, Behavior::COMMAND_STEAM_METADATA);
 212          if ($option === STREAM_META_TOUCH) {
 213              return $this->invokeInternalStreamWrapper(
 214                  'touch',
 215                  $path,
 216                  ...$value
 217              );
 218          }
 219          if ($option === STREAM_META_OWNER_NAME || $option === STREAM_META_OWNER) {
 220              return $this->invokeInternalStreamWrapper(
 221                  'chown',
 222                  $path,
 223                  $value
 224              );
 225          }
 226          if ($option === STREAM_META_GROUP_NAME || $option === STREAM_META_GROUP) {
 227              return $this->invokeInternalStreamWrapper(
 228                  'chgrp',
 229                  $path,
 230                  $value
 231              );
 232          }
 233          if ($option === STREAM_META_ACCESS) {
 234              return $this->invokeInternalStreamWrapper(
 235                  'chmod',
 236                  $path,
 237                  $value
 238              );
 239          }
 240          return false;
 241      }
 242  
 243      /**
 244       * @param string $path
 245       * @param string $mode
 246       * @param int $options
 247       * @param string|null $opened_path
 248       * @return bool
 249       */
 250      public function stream_open(
 251          string $path,
 252          string $mode,
 253          int $options,
 254          string &$opened_path = null
 255      ): bool {
 256          $this->assert($path, Behavior::COMMAND_STREAM_OPEN);
 257          $arguments = [$path, $mode, (bool) ($options & STREAM_USE_PATH)];
 258          // only add stream context for non include/require calls
 259          if (!($options & static::STREAM_OPEN_FOR_INCLUDE)) {
 260              $arguments[] = $this->context;
 261          // work around https://bugs.php.net/bug.php?id=66569
 262          // for including files from Phar stream with OPcache enabled
 263          } else {
 264              Helper::resetOpCache();
 265          }
 266          $this->internalResource = $this->invokeInternalStreamWrapper(
 267              'fopen',
 268              ...$arguments
 269          );
 270          if (!is_resource($this->internalResource)) {
 271              return false;
 272          }
 273          if ($opened_path !== null) {
 274              $metaData = stream_get_meta_data($this->internalResource);
 275              $opened_path = $metaData['uri'];
 276          }
 277          return true;
 278      }
 279  
 280      /**
 281       * @param int $count
 282       * @return string
 283       */
 284      public function stream_read(int $count): string
 285      {
 286          return $this->invokeInternalStreamWrapper(
 287              'fread',
 288              $this->internalResource,
 289              $count
 290          );
 291      }
 292  
 293      /**
 294       * @param int $offset
 295       * @param int $whence
 296       * @return bool
 297       */
 298      public function stream_seek(int $offset, int $whence = SEEK_SET): bool
 299      {
 300          return $this->invokeInternalStreamWrapper(
 301              'fseek',
 302              $this->internalResource,
 303              $offset,
 304              $whence
 305          ) !== -1;
 306      }
 307  
 308      /**
 309       * @param int $option
 310       * @param int $arg1
 311       * @param int $arg2
 312       * @return bool
 313       */
 314      public function stream_set_option(int $option, int $arg1, int $arg2): bool
 315      {
 316          if ($option === STREAM_OPTION_BLOCKING) {
 317              return $this->invokeInternalStreamWrapper(
 318                  'stream_set_blocking',
 319                  $this->internalResource,
 320                  $arg1
 321              );
 322          }
 323          if ($option === STREAM_OPTION_READ_TIMEOUT) {
 324              return $this->invokeInternalStreamWrapper(
 325                  'stream_set_timeout',
 326                  $this->internalResource,
 327                  $arg1,
 328                  $arg2
 329              );
 330          }
 331          if ($option === STREAM_OPTION_WRITE_BUFFER) {
 332              return $this->invokeInternalStreamWrapper(
 333                  'stream_set_write_buffer',
 334                  $this->internalResource,
 335                  $arg2
 336              ) === 0;
 337          }
 338          return false;
 339      }
 340  
 341      /**
 342       * @return array
 343       */
 344      public function stream_stat(): array
 345      {
 346          return $this->invokeInternalStreamWrapper(
 347              'fstat',
 348              $this->internalResource
 349          );
 350      }
 351  
 352      /**
 353       * @return int
 354       */
 355      public function stream_tell(): int
 356      {
 357          return $this->invokeInternalStreamWrapper(
 358              'ftell',
 359              $this->internalResource
 360          );
 361      }
 362  
 363      /**
 364       * @param int $new_size
 365       * @return bool
 366       */
 367      public function stream_truncate(int $new_size): bool
 368      {
 369          return $this->invokeInternalStreamWrapper(
 370              'ftruncate',
 371              $this->internalResource,
 372              $new_size
 373          );
 374      }
 375  
 376      /**
 377       * @param string $data
 378       * @return int
 379       */
 380      public function stream_write(string $data): int
 381      {
 382          return $this->invokeInternalStreamWrapper(
 383              'fwrite',
 384              $this->internalResource,
 385              $data
 386          );
 387      }
 388  
 389      /**
 390       * @param string $path
 391       * @return bool
 392       */
 393      public function unlink(string $path): bool
 394      {
 395          $this->assert($path, Behavior::COMMAND_UNLINK);
 396          return $this->invokeInternalStreamWrapper(
 397              'unlink',
 398              $path,
 399              $this->context
 400          );
 401      }
 402  
 403      /**
 404       * @param string $path
 405       * @param int $flags
 406       * @return array|false
 407       */
 408      public function url_stat(string $path, int $flags)
 409      {
 410          $this->assert($path, Behavior::COMMAND_URL_STAT);
 411          $functionName = $flags & STREAM_URL_STAT_QUIET ? '@stat' : 'stat';
 412          return $this->invokeInternalStreamWrapper($functionName, $path);
 413      }
 414  
 415      /**
 416       * @param string $path
 417       * @param string $command
 418       */
 419      protected function assert(string $path, string $command)
 420      {
 421          if (Manager::instance()->assert($path, $command) === true) {
 422              $this->collectInvocation($path);
 423              return;
 424          }
 425  
 426          throw new Exception(
 427              sprintf(
 428                  'Denied invocation of "%s" for command "%s"',
 429                  $path,
 430                  $command
 431              ),
 432              1535189880
 433          );
 434      }
 435  
 436      /**
 437       * @param string $path
 438       */
 439      protected function collectInvocation(string $path)
 440      {
 441          if (isset($this->invocation)) {
 442              return;
 443          }
 444  
 445          $manager = Manager::instance();
 446          $this->invocation = $manager->resolve($path);
 447          if ($this->invocation === null) {
 448              throw new Exception(
 449                  'Expected invocation could not be resolved',
 450                  1556389591
 451              );
 452          }
 453          // confirm, previous interceptor(s) validated invocation
 454          $this->invocation->confirm();
 455          $collection = $manager->getCollection();
 456          if (!$collection->has($this->invocation)) {
 457              $collection->collect($this->invocation);
 458          }
 459      }
 460  
 461      /**
 462       * @return Manager|Assertable
 463       * @deprecated Use Manager::instance() directly
 464       */
 465      protected function resolveAssertable(): Assertable
 466      {
 467          return Manager::instance();
 468      }
 469  
 470      /**
 471       * Invokes commands on the native PHP Phar stream wrapper.
 472       *
 473       * @param string $functionName
 474       * @param mixed ...$arguments
 475       * @return mixed
 476       */
 477      private function invokeInternalStreamWrapper(string $functionName, ...$arguments)
 478      {
 479          $silentExecution = $functionName[0] === '@';
 480          $functionName = ltrim($functionName, '@');
 481          $this->restoreInternalSteamWrapper();
 482  
 483          try {
 484              if ($silentExecution) {
 485                  $result = @call_user_func_array($functionName, $arguments);
 486              } else {
 487                  $result = call_user_func_array($functionName, $arguments);
 488              }
 489          } finally {
 490              $this->registerStreamWrapper();
 491          }
 492  
 493          return $result;
 494      }
 495  
 496      private function restoreInternalSteamWrapper()
 497      {
 498          if (PHP_VERSION_ID < 70324
 499              || PHP_VERSION_ID >= 70400 && PHP_VERSION_ID < 70412) {
 500              stream_wrapper_restore('phar');
 501          } else {
 502              // with https://github.com/php/php-src/pull/6183 (PHP #76943) the
 503              // behavior of `stream_wrapper_restore()` did change for
 504              // PHP 8.0-RC1, 7.4.12 and 7.3.24
 505              @stream_wrapper_restore('phar');
 506          }
 507      }
 508  
 509      private function registerStreamWrapper()
 510      {
 511          stream_wrapper_unregister('phar');
 512          stream_wrapper_register('phar', static::class);
 513      }
 514  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer