[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |