%PDF- %PDF-
Direktori : /www/varak.net/losik.varak.net/vendor/nette/safe-stream/src/SafeStream/ |
Current File : /www/varak.net/losik.varak.net/vendor/nette/safe-stream/src/SafeStream/SafeStream.php |
<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Utils; /** * Provides isolation for thread safe file manipulation using stream nette.safe:// * * <code> * file_put_contents('nette.safe://myfile.txt', $content); * * $content = file_get_contents('nette.safe://myfile.txt'); * * unlink('nette.safe://myfile.txt'); * </code> * @internal */ class SafeStream { /** Name of stream protocol - nette.safe:// */ public const PROTOCOL = 'nette.safe'; /** @var ?resource */ public $context; /** @var resource orignal file handle */ private $handle; /** @var string orignal file path */ private $filePath; /** @var int starting position in file (for appending) */ private $startPos = 0; /** @var bool error detected? */ private $writeError = false; /** * Registers protocol 'nette.safe://'. */ public static function register(): bool { foreach (array_intersect(stream_get_wrappers(), ['safe', self::PROTOCOL]) as $name) { stream_wrapper_unregister($name); } stream_wrapper_register('safe', self::class); // old protocol return stream_wrapper_register(self::PROTOCOL, self::class); } /** * Opens file. */ public function stream_open(string $path, string $mode, int $options): bool { $path = substr($path, strpos($path, ':') + 3); // trim protocol nette.safe:// $flag = trim($mode, 'crwax+'); // text | binary mode $resMode = rtrim($mode, 'tb'); $lock = $resMode === 'r' ? LOCK_SH : LOCK_EX; $use_path = (bool) (STREAM_USE_PATH & $options); if ($resMode[0] === 'w') { $resMode[0] = 'c'; } $handle = @fopen($path, $resMode . $flag, $use_path); // @ may fail if (!$handle || !flock($handle, $lock)) { return false; } if ($resMode === 'r') { // re-take lock if file is empty $counter = 100; while ($counter-- && !fstat($handle)['size']) { flock($handle, LOCK_UN); usleep(1); flock($handle, LOCK_SH); } } elseif ($mode[0] === 'a') { $this->startPos = fstat($handle)['size']; } elseif ($mode[0] === 'w') { ftruncate($handle, 0); } $this->handle = $handle; return true; } /** * Closes file. */ public function stream_close(): void { if ($this->writeError) { ftruncate($this->handle, $this->startPos); } flock($this->handle, LOCK_UN); fclose($this->handle); } /** * Reads up to length bytes from the file. */ public function stream_read(int $length) { return fread($this->handle, $length); } /** * Writes the string to the file. */ public function stream_write(string $data) { $len = strlen($data); $res = fwrite($this->handle, $data, $len); if ($res !== $len) { // disk full? $this->writeError = true; } return $res; } /** * Truncates a file to a given length. */ public function stream_truncate(int $size): bool { return ftruncate($this->handle, $size); } /** * Returns the position of the file. */ public function stream_tell(): int { return ftell($this->handle); } /** * Returns true if the file pointer is at end-of-file. */ public function stream_eof(): bool { return feof($this->handle); } /** * Sets the file position indicator for the file. */ public function stream_seek(int $offset, int $whence = SEEK_SET): bool { return fseek($this->handle, $offset, $whence) === 0; // ??? } /** * Gets information about a file referenced by $this->handle. */ public function stream_stat() { return fstat($this->handle); } /** * Gets information about a file referenced by filename. */ public function url_stat(string $path, int $flags) { // This is not thread safe $path = substr($path, strpos($path, ':') + 3); return ($flags & STREAM_URL_STAT_LINK) ? @lstat($path) : @stat($path); // intentionally @ } /** * Deletes a file. * On Windows unlink is not allowed till file is opened */ public function unlink(string $path): bool { $path = substr($path, strpos($path, ':') + 3); return unlink($path); } /** * Does nothing, but since PHP 7.4 needs to be implemented when using wrapper for includes */ public function stream_set_option(int $option, int $arg1, int $arg2): bool { return false; } }