‪TYPO3CMS  10.4
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 {
31  'typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_resources' => 'typo3conf/ext/test_resources',
32  'typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_resources/bundle.phar' => 'fileadmin/bundle.phar',
33  ];
34 
35  protected function ‪setUp(): void
36  {
37  parent::setUp();
38  if (!in_array('phar', stream_get_wrappers())) {
39  self::markTestSkipped('Phar stream wrapper is not registered');
40  }
41  // PharStreamWrapper is not initialized here since it relies on being
42  // properly defined in \TYPO3\CMS\Core\Core\Bootstrap - thus, it tests
43  // are expected to fail in case PharStreamWrapper is not initialized
44  }
45 
47  {
48  $allowedPath = 'typo3conf/ext/test_resources/bundle.phar';
49 
50  return [
51  'root directory' => [
52  $allowedPath,
53  ['Classes', 'Resources']
54  ],
55  'Classes/Domain/Model directory' => [
56  $allowedPath . '/Classes/Domain/Model',
57  ['DemoModel.php']
58  ],
59  'Resources directory' => [
60  $allowedPath . '/Resources',
61  ['content.txt']
62  ],
63  ];
64  }
65 
72  public function ‪directoryOpenAllowsInvocation(string $path)
73  {
74  $path = $this->instancePath . '/' . $path;
75  $handle = opendir('phar://' . $path);
76  self::assertIsResource($handle);
77  }
78 
86  public function ‪directoryReadAllowsInvocation(string $path, array $expectation)
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 
106  public function ‪directoryCloseAllowsInvocation(string $path, array $expectation)
107  {
108  $path = $this->instancePath . '/' . $path;
109 
110  $handle = opendir('phar://' . $path);
111  closedir($handle);
112 
113  self::assertFalse(is_resource($handle));
114  }
115 
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)
143  {
144  self::expectException(Exception::class);
145  self::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)
211  {
212  $path = $this->instancePath . '/' . $path;
213 
214  self::assertSame(
215  $expectation,
216  call_user_func($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)
280  {
281  self::expectException(Exception::class);
282  self::expectExceptionCode(1539625084);
283 
284  $path = $this->instancePath . '/' . $path;
285  call_user_func($functionName, 'phar://' . $path);
286  }
287 
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 
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 
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 
324  {
325  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
326  $handle = fopen('phar://' . $allowedPath . '/Resources/content.txt', 'r');
327  fclose($handle);
328  self::assertFalse(is_resource($handle));
329  }
330 
335  {
336  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
337  $content = file_get_contents('phar://' . $allowedPath . '/Resources/content.txt');
338  self::assertSame('TYPO3 demo text file.', $content);
339  }
340 
345  {
346  $allowedPath = $this->instancePath . '/typo3conf/ext/test_resources/bundle.phar';
347  include('phar://' . $allowedPath . '/Classes/Domain/Model/DemoModel.php');
348 
349  self::assertTrue(
350  class_exists(
351  \TYPO3Demo\Demo\Domain\Model\DemoModel::class,
352  false
353  )
354  );
355  }
356 
361  {
362  self::expectException(Exception::class);
363  self::expectExceptionCode(1539625084);
364 
365  $allowedPath = $this->instancePath . '/fileadmin/bundle.phar';
366  fopen('phar://' . $allowedPath . '/Resources/content.txt', 'r');
367  }
368 
373  {
374  self::expectException(Exception::class);
375  self::expectExceptionCode(1539625084);
376 
377  $allowedPath = $this->instancePath . '/fileadmin/bundle.phar';
378  file_get_contents('phar://' . $allowedPath . '/Resources/content.txt');
379  }
380 
382  {
383  return [
384  'fileadmin/bundle.phar' => ['fileadmin/bundle.phar'],
385  'EXT:test_resources/compromised.phar' => ['typo3conf/ext/test_resources/compromised.phar'],
386  ];
387  }
388 
393  public function ‪streamOpenDeniesInvocationForInclude(string $path)
394  {
395  self::expectException(Exception::class);
396  self::expectExceptionCode(1539625084);
397 
398  $allowedPath = $this->instancePath . '/' . $path;
399  include('phar://' . $allowedPath . '/Classes/Domain/Model/DemoModel.php');
400  }
401 }
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenDeniesInvocationForIncludeDataProvider
‪streamOpenDeniesInvocationForIncludeDataProvider()
Definition: PharStreamWrapperInterceptorTest.php:380
‪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:333
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenAllowsInvocationForInclude
‪streamOpenAllowsInvocationForInclude()
Definition: PharStreamWrapperInterceptorTest.php:343
‪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:359
‪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\$pathsToProvideInTestInstance
‪array $pathsToProvideInTestInstance
Definition: PharStreamWrapperInterceptorTest.php:29
‪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:392
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\directoryOpenAllowsInvocation
‪directoryOpenAllowsInvocation(string $path)
Definition: PharStreamWrapperInterceptorTest.php:71
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\directoryActionAllowsInvocationDataProvider
‪directoryActionAllowsInvocationDataProvider()
Definition: PharStreamWrapperInterceptorTest.php:45
‪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:105
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\streamOpenDeniesInvocationForFileGetContents
‪streamOpenDeniesInvocationForFileGetContents()
Definition: PharStreamWrapperInterceptorTest.php:371
‪TYPO3\CMS\Core\Tests\Functional\IO\PharStreamWrapperInterceptorTest\setUp
‪setUp()
Definition: PharStreamWrapperInterceptorTest.php:34
‪TYPO3\CMS\Core\Tests\Functional\IO
Definition: PharStreamWrapperInterceptorTest.php:18