|
9 | 9 |
|
10 | 10 | namespace Nette\Utils; |
11 | 11 |
|
12 | | - |
13 | | -/** |
14 | | - * Provides isolation for thread safe file manipulation using stream nette.safe:// |
15 | | - * |
16 | | - * <code> |
17 | | - * file_put_contents('nette.safe://myfile.txt', $content); |
18 | | - * |
19 | | - * $content = file_get_contents('nette.safe://myfile.txt'); |
20 | | - * |
21 | | - * unlink('nette.safe://myfile.txt'); |
22 | | - * </code> |
23 | | - * @internal |
24 | | - */ |
25 | | -class SafeStream |
26 | | -{ |
27 | | - /** Name of stream protocol - nette.safe:// */ |
28 | | - public const Protocol = 'nette.safe'; |
29 | | - |
30 | | - /** @deprecated use SafeStream::Protocol */ |
31 | | - public const PROTOCOL = self::Protocol; |
32 | | - |
33 | | - /** @var ?resource */ |
34 | | - public $context; |
35 | | - |
36 | | - /** @var resource orignal file handle */ |
37 | | - private $handle; |
38 | | - |
39 | | - /** orignal file path */ |
40 | | - private string $filePath; |
41 | | - |
42 | | - /** starting position in file (for appending) */ |
43 | | - private int $startPos = 0; |
44 | | - |
45 | | - /** error detected? */ |
46 | | - private bool $writeError = false; |
47 | | - |
48 | | - |
49 | | - /** |
50 | | - * Registers protocol 'nette.safe://'. |
51 | | - */ |
52 | | - public static function register(): bool |
53 | | - { |
54 | | - if (in_array(self::Protocol, stream_get_wrappers(), true)) { |
55 | | - stream_wrapper_unregister(self::Protocol); |
56 | | - } |
57 | | - |
58 | | - return stream_wrapper_register(self::Protocol, self::class); |
59 | | - } |
60 | | - |
61 | | - |
62 | | - /** |
63 | | - * Opens file. |
64 | | - */ |
65 | | - public function stream_open(string $path, string $mode, int $options): bool |
66 | | - { |
67 | | - $path = substr($path, strlen(self::Protocol) + 3); // trim protocol nette.safe:// |
68 | | - $flag = trim($mode, 'crwax+'); // text | binary mode |
69 | | - $resMode = rtrim($mode, 'tb'); |
70 | | - $lock = $resMode === 'r' ? LOCK_SH : LOCK_EX; |
71 | | - $use_path = (bool) (STREAM_USE_PATH & $options); |
72 | | - if ($resMode[0] === 'w') { |
73 | | - $resMode[0] = 'c'; |
74 | | - } |
75 | | - |
76 | | - $handle = @fopen($path, $resMode . $flag, $use_path); // @ may fail |
77 | | - if (!$handle || !flock($handle, $lock)) { |
78 | | - return false; |
79 | | - } |
80 | | - |
81 | | - if ($resMode === 'r') { // re-take lock if file is empty |
82 | | - $counter = 100; |
83 | | - while ($counter-- && !fstat($handle)['size']) { |
84 | | - flock($handle, LOCK_UN); |
85 | | - usleep(1); |
86 | | - flock($handle, LOCK_SH); |
87 | | - } |
88 | | - } elseif ($mode[0] === 'a') { |
89 | | - $this->startPos = fstat($handle)['size']; |
90 | | - |
91 | | - } elseif ($mode[0] === 'w') { |
92 | | - ftruncate($handle, 0); |
93 | | - } |
94 | | - |
95 | | - $this->handle = $handle; |
96 | | - return true; |
97 | | - } |
98 | | - |
99 | | - |
100 | | - /** |
101 | | - * Closes file. |
102 | | - */ |
103 | | - public function stream_close(): void |
104 | | - { |
105 | | - if ($this->writeError) { |
106 | | - ftruncate($this->handle, $this->startPos); |
107 | | - } |
108 | | - |
109 | | - flock($this->handle, LOCK_UN); |
110 | | - fclose($this->handle); |
111 | | - } |
| 12 | +use Nette\SafeStream\Wrapper; |
112 | 13 |
|
113 | 14 |
|
114 | | - /** |
115 | | - * Reads up to length bytes from the file. |
116 | | - */ |
117 | | - public function stream_read(int $length) |
118 | | - { |
119 | | - return fread($this->handle, $length); |
120 | | - } |
121 | | - |
122 | | - |
123 | | - /** |
124 | | - * Writes the string to the file. |
125 | | - */ |
126 | | - public function stream_write(string $data) |
127 | | - { |
128 | | - $len = strlen($data); |
129 | | - $res = fwrite($this->handle, $data, $len); |
130 | | - |
131 | | - if ($res !== $len) { // disk full? |
132 | | - $this->writeError = true; |
133 | | - } |
134 | | - |
135 | | - return $res; |
136 | | - } |
137 | | - |
138 | | - |
139 | | - /** |
140 | | - * Truncates a file to a given length. |
141 | | - */ |
142 | | - public function stream_truncate(int $size): bool |
143 | | - { |
144 | | - return ftruncate($this->handle, $size); |
145 | | - } |
146 | | - |
147 | | - |
148 | | - /** |
149 | | - * Returns the position of the file. |
150 | | - */ |
151 | | - public function stream_tell(): int |
152 | | - { |
153 | | - return ftell($this->handle); |
154 | | - } |
155 | | - |
156 | | - |
157 | | - /** |
158 | | - * Returns true if the file pointer is at end-of-file. |
159 | | - */ |
160 | | - public function stream_eof(): bool |
161 | | - { |
162 | | - return feof($this->handle); |
163 | | - } |
164 | | - |
165 | | - |
166 | | - /** |
167 | | - * Sets the file position indicator for the file. |
168 | | - */ |
169 | | - public function stream_seek(int $offset, int $whence = SEEK_SET): bool |
170 | | - { |
171 | | - return fseek($this->handle, $offset, $whence) === 0; // ??? |
172 | | - } |
173 | | - |
174 | | - |
175 | | - /** |
176 | | - * Gets information about a file referenced by $this->handle. |
177 | | - */ |
178 | | - public function stream_stat() |
179 | | - { |
180 | | - return fstat($this->handle); |
181 | | - } |
182 | | - |
183 | | - |
184 | | - /** |
185 | | - * Gets information about a file referenced by filename. |
186 | | - */ |
187 | | - public function url_stat(string $path, int $flags) |
188 | | - { |
189 | | - // This is not thread safe |
190 | | - $path = substr($path, strlen(self::Protocol) + 3); |
191 | | - return ($flags & STREAM_URL_STAT_LINK) ? @lstat($path) : @stat($path); // intentionally @ |
192 | | - } |
193 | | - |
194 | | - |
195 | | - /** |
196 | | - * Deletes a file. |
197 | | - * On Windows unlink is not allowed till file is opened |
198 | | - */ |
199 | | - public function unlink(string $path): bool |
200 | | - { |
201 | | - $path = substr($path, strlen(self::Protocol) + 3); |
202 | | - return unlink($path); |
203 | | - } |
204 | | - |
205 | | - |
206 | | - /** |
207 | | - * Does nothing, but since PHP 7.4 needs to be implemented when using wrapper for includes |
208 | | - */ |
209 | | - public function stream_set_option(int $option, int $arg1, int $arg2): bool |
210 | | - { |
211 | | - return false; |
212 | | - } |
| 15 | +/** @deprecated use Nette\SafeStream\Wrapper */ |
| 16 | +class SafeStream extends Wrapper |
| 17 | +{ |
213 | 18 | } |
0 commit comments