‪TYPO3CMS  11.5
PharStreamWrapperInterceptorTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use TYPO3\PharStreamWrapper\Exception;
21 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
22 
23 class ‪PharStreamWrapperInterceptorTest extends FunctionalTestCase
24 {
28  protected ‪$initializeDatabase = false;
29 
34  'typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_resources' => 'typo3conf/ext/test_resources',
35  'typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_resources/bundle.phar' => 'fileadmin/bundle.phar',
36  ];
37 
38  protected function ‪setUp(): void
39  {
40  parent::setUp();
41  if (!in_array('phar', stream_get_wrappers())) {
42  self::markTestSkipped('Phar stream wrapper is not registered');
43  }
44  // PharStreamWrapper is not initialized here since it relies on being
45  // properly defined in \TYPO3\CMS\Core\Core\Bootstrap - thus, it tests
46  // are expected to fail in case PharStreamWrapper is not initialized
47  }
48 
49  public function ‪directoryActionAllowsInvocationDataProvider(): array
50  {
51  $allowedPath = 'typo3conf/ext/test_resources/bundle.phar';
52 
53  return [
54  'root directory' => [
55  $allowedPath,
56  ['Classes', 'Resources'],
57  ],
58  'Classes/Domain/Model directory' => [
59  $allowedPath . '/Classes/Domain/Model',
60  ['DemoModel.php'],
61  ],
62  'Resources directory' => [
63  $allowedPath . '/Resources',
64  ['content.txt'],
65  ],
66  ];
67  }
68 
75  public function ‪directoryOpenAllowsInvocation(string $path): void
76  {
77  $path = $this->instancePath . '/' . $path;
78  $handle = opendir('phar://' . $path);
79  self::assertIsResource($handle);
80  }
81 
86  public function ‪directoryReadAllowsInvocation(string $path, array $expectation): void
87  {
88  $path = $this->instancePath . '/' . $path;
89 
90  $items = [];
91  $handle = opendir('phar://' . $path);
92  while (false !== $item = readdir($handle)) {
93  $items[] = $item;
94  }
95 
96  self::assertSame($expectation, $items);
97  }
98 
103  public function ‪directoryCloseAllowsInvocation(string $path, array $expectation): void
104  {
105  $path = $this->instancePath . '/' . $path;
106 
107  $handle = opendir('phar://' . $path);
108  closedir($handle);
109 
110  // Testing with a variable here, otherwise the suggested assertion would be assertIsNotResource
111  // which fails.
112  $isResource = is_resource($handle);
113  self::assertFalse($isResource);
114  }
115 
116  public function ‪directoryActionDeniesInvocationDataProvider(): array
117  {
118  $deniedPath = 'fileadmin/bundle.phar';
119 
120  return [
121  'root directory' => [
122  $deniedPath,
123  ['Classes', 'Resources'],
124  ],
125  'Classes/Domain/Model directory' => [
126  $deniedPath . '/Classes/Domain/Model',
127  ['DemoModel.php'],
128  ],
129  'Resources directory' => [
130  $deniedPath . '/Resources',
131  ['content.txt'],
132  ],
133  ];
134  }
135 
142  public function ‪directoryActionDeniesInvocation(string $path): void
143  {
144  $this->expectException(Exception::class);
145  $this->expectExceptionCode(1539625084);
146 
147  $path = $this->instancePath . '/' . $path;
148  opendir('phar://' . $path);
149  }
150 
154  public function ‪urlStatAllowsInvocationDataProvider(): array
155  {
156  $allowedPath = 'typo3conf/ext/test_resources/bundle.phar';
157 
158  return [
159  'filesize base file' => [
160  'filesize',
161  $allowedPath,
162  0, // Phar base file always has zero size when accessed through phar://
163  ],
164  'filesize Resources/content.txt' => [
165  'filesize',
166  $allowedPath . '/Resources/content.txt',
167  21,
168  ],
169  'is_file base file' => [
170  'is_file',
171  $allowedPath,
172  false, // Phar base file is not a file when accessed through phar://
173  ],
174  'is_file Resources/content.txt' => [
175  'is_file',
176  $allowedPath . '/Resources/content.txt',
177  true,
178  ],
179  'is_dir base file' => [
180  'is_dir',
181  $allowedPath,
182  true, // Phar base file is a directory when accessed through phar://
183  ],
184  'is_dir Resources/content.txt' => [
185  'is_dir',
186  $allowedPath . '/Resources/content.txt',
187  false,
188  ],
189  'file_exists base file' => [
190  'file_exists',
191  $allowedPath,
192  true,
193  ],
194  'file_exists Resources/content.txt' => [
195  'file_exists',
196  $allowedPath . '/Resources/content.txt',
197  true,
198  ],
199  ];
200  }
201 
210  public function ‪urlStatAllowsInvocation(string $functionName, string $path, $expectation): void
211  {
212  $path = $this->instancePath . '/' . $path;
213 
214  self::assertSame(
215  $expectation,
216  $functionName('phar://' . $path)
217  );
218  }
219 
223  public function ‪urlStatDeniesInvocationDataProvider(): array
224  {
225  $deniedPath = 'fileadmin/bundle.phar';
226 
227  return [
228  'filesize base file' => [
229  'filesize',
230  $deniedPath,
231  0, // Phar base file always has zero size when accessed through phar://
232  ],
233  'filesize Resources/content.txt' => [
234  'filesize',
235  $deniedPath . '/Resources/content.txt',
236  21,
237  ],
238  'is_file base file' => [
239  'is_file',
240  $deniedPath,
241  false, // Phar base file is not a file when accessed through phar://
242  ],
243  'is_file Resources/content.txt' => [
244  'is_file',
245  $deniedPath . '/Resources/content.txt',
246  true,
247  ],
248  'is_dir base file' => [
249  'is_dir',
250  $deniedPath,
251  true, // Phar base file is a directory when accessed through phar://
252  ],
253  'is_dir Resources/content.txt' => [
254  'is_dir',
255  $deniedPath . '/Resources/content.txt',
256  false,
257  ],
258  'file_exists base file' => [
259  'file_exists',
260  $deniedPath,
261  true,
262  ],
263  'file_exists Resources/content.txt' => [
264  'file_exists',
265  $deniedPath . '/Resources/content.txt',
266  true,
267  ],
268  ];
269  }
270 
279  public function ‪urlStatDeniesInvocation(string $functionName, string $path): void
280  {
281  $this->expectException(Exception::class);
282  $this->expectExceptionCode(1539625084);
283 
284  $path = $this->instancePath . '/' . $path;
285  $functionName('phar://' . $path);
286  }
287 
291  public function ‪streamOpenAllowsInvocationForFileOpen(): void
292  {
293  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
294  $handle = fopen('phar://' . $allowedPath . '/Resources/content.txt', 'r');
295  self::assertIsResource($handle);
296  }
297 
301  public function ‪streamOpenAllowsInvocationForFileRead(): void
302  {
303  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
304  $handle = fopen('phar://' . $allowedPath . '/Resources/content.txt', 'r');
305  $content = fread($handle, 1024);
306  self::assertSame('TYPO3 demo text file.', $content);
307  }
308 
312  public function ‪streamOpenAllowsInvocationForFileEnd(): void
313  {
314  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
315  $handle = fopen('phar://' . $allowedPath . '/Resources/content.txt', 'r');
316  fread($handle, 1024);
317  self::assertTrue(feof($handle));
318  }
319 
323  public function ‪streamOpenAllowsInvocationForFileClose(): void
324  {
325  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
326  $handle = fopen('phar://' . $allowedPath . '/Resources/content.txt', 'r');
327  fclose($handle);
328  // Testing with a variable here, otherwise the suggested assertion would be assertIsNotResource
329  // which fails.
330  $isResource = is_resource($handle);
331  self::assertFalse($isResource);
332  }
333 
338  {
339  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
340  $content = file_get_contents('phar://' . $allowedPath . '/Resources/content.txt');
341  self::assertSame('TYPO3 demo text file.', $content);
342  }
343 
347  public function ‪streamOpenAllowsInvocationForInclude(): void
348  {
349  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
350  include('phar://' . $allowedPath . '/Classes/Domain/Model/DemoModel.php');
351 
352  self::assertTrue(
353  class_exists(
354  \TYPO3Demo\Demo\Domain\Model\DemoModel::class,
355  false
356  )
357  );
358  }
359 
363  public function ‪streamOpenDeniesInvocationForFileOpen(): void
364  {
365  $this->expectException(Exception::class);
366  $this->expectExceptionCode(1539625084);
367 
368  $allowedPath = $this->instancePath . '/fileadmin/bundle.phar';
369  fopen('phar://' . $allowedPath . '/Resources/content.txt', 'r');
370  }
371 
376  {
377  $this->expectException(Exception::class);
378  $this->expectExceptionCode(1539625084);
379 
380  $allowedPath = $this->instancePath . '/fileadmin/bundle.phar';
381  file_get_contents('phar://' . $allowedPath . '/Resources/content.txt');
382  }
383 
385  {
386  return [
387  'fileadmin/bundle.phar' => ['fileadmin/bundle.phar'],
388  'EXT:test_resources/compromised.phar' => ['typo3conf/ext/test_resources/compromised.phar'],
389  ];
390  }
391 
396  public function ‪streamOpenDeniesInvocationForInclude(string $path): void
397  {
398  $this->expectException(Exception::class);
399  $this->expectExceptionCode(1539625084);
400 
401  $allowedPath = $this->instancePath . '/' . $path;
402  include('phar://' . $allowedPath . '/Classes/Domain/Model/DemoModel.php');
403  }
404 }
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenDeniesInvocationForIncludeDataProvider
‪streamOpenDeniesInvocationForIncludeDataProvider()
Definition: PharStreamWrapperInterceptorTest.php:383
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenAllowsInvocationForFileClose
‪streamOpenAllowsInvocationForFileClose()
Definition: PharStreamWrapperInterceptorTest.php:322
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\urlStatDeniesInvocation
‪urlStatDeniesInvocation(string $functionName, string $path)
Definition: PharStreamWrapperInterceptorTest.php:278
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\urlStatAllowsInvocation
‪urlStatAllowsInvocation(string $functionName, string $path, $expectation)
Definition: PharStreamWrapperInterceptorTest.php:209
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenAllowsInvocationForFileGetContents
‪streamOpenAllowsInvocationForFileGetContents()
Definition: PharStreamWrapperInterceptorTest.php:336
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenAllowsInvocationForInclude
‪streamOpenAllowsInvocationForInclude()
Definition: PharStreamWrapperInterceptorTest.php:346
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenAllowsInvocationForFileRead
‪streamOpenAllowsInvocationForFileRead()
Definition: PharStreamWrapperInterceptorTest.php:300
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenDeniesInvocationForFileOpen
‪streamOpenDeniesInvocationForFileOpen()
Definition: PharStreamWrapperInterceptorTest.php:362
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\urlStatDeniesInvocationDataProvider
‪array urlStatDeniesInvocationDataProvider()
Definition: PharStreamWrapperInterceptorTest.php:222
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest
Definition: PharStreamWrapperInterceptorTest.php:24
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\directoryReadAllowsInvocation
‪directoryReadAllowsInvocation(string $path, array $expectation)
Definition: PharStreamWrapperInterceptorTest.php:85
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenAllowsInvocationForFileOpen
‪streamOpenAllowsInvocationForFileOpen()
Definition: PharStreamWrapperInterceptorTest.php:290
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\directoryActionDeniesInvocation
‪directoryActionDeniesInvocation(string $path)
Definition: PharStreamWrapperInterceptorTest.php:141
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\$initializeDatabase
‪bool $initializeDatabase
Definition: PharStreamWrapperInterceptorTest.php:27
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\$pathsToProvideInTestInstance
‪$pathsToProvideInTestInstance
Definition: PharStreamWrapperInterceptorTest.php:32
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenAllowsInvocationForFileEnd
‪streamOpenAllowsInvocationForFileEnd()
Definition: PharStreamWrapperInterceptorTest.php:311
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenDeniesInvocationForInclude
‪streamOpenDeniesInvocationForInclude(string $path)
Definition: PharStreamWrapperInterceptorTest.php:395
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\directoryOpenAllowsInvocation
‪directoryOpenAllowsInvocation(string $path)
Definition: PharStreamWrapperInterceptorTest.php:74
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\directoryActionAllowsInvocationDataProvider
‪directoryActionAllowsInvocationDataProvider()
Definition: PharStreamWrapperInterceptorTest.php:48
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\urlStatAllowsInvocationDataProvider
‪array urlStatAllowsInvocationDataProvider()
Definition: PharStreamWrapperInterceptorTest.php:153
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\directoryActionDeniesInvocationDataProvider
‪directoryActionDeniesInvocationDataProvider()
Definition: PharStreamWrapperInterceptorTest.php:115
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\directoryCloseAllowsInvocation
‪directoryCloseAllowsInvocation(string $path, array $expectation)
Definition: PharStreamWrapperInterceptorTest.php:102
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenDeniesInvocationForFileGetContents
‪streamOpenDeniesInvocationForFileGetContents()
Definition: PharStreamWrapperInterceptorTest.php:374
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\setUp
‪setUp()
Definition: PharStreamWrapperInterceptorTest.php:37
‪TYPO3\CMS\Core\Tests\Functional\IO
Definition: PharStreamWrapperInterceptorTest.php:18