7538afe25faa2fa53755fa8babf594860972e54b
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Utility / GeneralUtilityTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Utility;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2009-2011 Ingo Renner <ingo@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 /**
28 * Testcase for class \TYPO3\CMS\Core\Utility\GeneralUtility
29 *
30 * @author Ingo Renner <ingo@typo3.org>
31 * @author Oliver Klee <typo3-coding@oliverklee.de>
32 * @package TYPO3
33 * @subpackage t3lib
34 */
35 class GeneralUtilityTest extends \tx_phpunit_testcase {
36
37 /**
38 * Enable backup of global and system variables
39 *
40 * @var boolean
41 */
42 protected $backupGlobals = TRUE;
43
44 /**
45 * Exclude TYPO3_DB from backup/ restore of $GLOBALS
46 * because resource types cannot be handled during serializing
47 *
48 * @var array
49 */
50 protected $backupGlobalsBlacklist = array('TYPO3_DB');
51
52 /**
53 * @var array A backup of registered singleton instances
54 */
55 protected $singletonInstances = array();
56
57 public function setUp() {
58 $this->singletonInstances = \TYPO3\CMS\Core\Utility\GeneralUtility::getSingletonInstances();
59 }
60
61 public function tearDown() {
62 \TYPO3\CMS\Core\Utility\GeneralUtility::resetSingletonInstances($this->singletonInstances);
63 }
64
65 ///////////////////////////
66 // Tests concerning _GP
67 ///////////////////////////
68 /**
69 * @test
70 * @dataProvider gpDataProvider
71 */
72 public function canRetrieveValueWithGP($key, $get, $post, $expected) {
73 $_GET = $get;
74 $_POST = $post;
75 $this->assertSame($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::_GP($key));
76 }
77
78 /**
79 * Data provider for canRetrieveValueWithGP.
80 * All test values also check whether slashes are stripped properly.
81 *
82 * @return array
83 */
84 public function gpDataProvider() {
85 return array(
86 'No key parameter' => array(NULL, array(), array(), NULL),
87 'Key not found' => array('cake', array(), array(), NULL),
88 'Value only in GET' => array('cake', array('cake' => 'li\\e'), array(), 'lie'),
89 'Value only in POST' => array('cake', array(), array('cake' => 'l\\ie'), 'lie'),
90 'Value from POST preferred over GET' => array('cake', array('cake' => 'is a'), array('cake' => '\\lie'), 'lie'),
91 'Value can be an array' => array(
92 'cake',
93 array('cake' => array('is a' => 'l\\ie')),
94 array(),
95 array('is a' => 'lie')
96 )
97 );
98 }
99
100 ///////////////////////////
101 // Tests concerning _GPmerged
102 ///////////////////////////
103 /**
104 * @test
105 * @dataProvider gpMergedDataProvider
106 */
107 public function gpMergedWillMergeArraysFromGetAndPost($get, $post, $expected) {
108 $_POST = $post;
109 $_GET = $get;
110 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::_GPmerged('cake'));
111 }
112
113 /**
114 * Data provider for gpMergedWillMergeArraysFromGetAndPost
115 *
116 * @return array
117 */
118 public function gpMergedDataProvider() {
119 $fullDataArray = array('cake' => array('a' => 'is a', 'b' => 'lie'));
120 $postPartData = array('cake' => array('b' => 'lie'));
121 $getPartData = array('cake' => array('a' => 'is a'));
122 $getPartDataModified = array('cake' => array('a' => 'is not a'));
123 return array(
124 'Key doesn\' exist' => array(array('foo'), array('bar'), array()),
125 'No POST data' => array($fullDataArray, array(), $fullDataArray['cake']),
126 'No GET data' => array(array(), $fullDataArray, $fullDataArray['cake']),
127 'POST and GET are merged' => array($getPartData, $postPartData, $fullDataArray['cake']),
128 'POST is preferred over GET' => array($getPartDataModified, $fullDataArray, $fullDataArray['cake'])
129 );
130 }
131
132 ///////////////////////////////
133 // Tests concerning _GET / _POST
134 ///////////////////////////////
135 /**
136 * Data provider for canRetrieveGlobalInputsThroughGet
137 * and canRetrieveGlobalInputsThroughPost
138 *
139 * @return array
140 */
141 public function getAndPostDataProvider() {
142 return array(
143 'Requested input data doesn\'t exist' => array('cake', array(), NULL),
144 'No key will return entire input data' => array(NULL, array('cake' => 'l\\ie'), array('cake' => 'lie')),
145 'Can retrieve specific input' => array('cake', array('cake' => 'li\\e', 'foo'), 'lie'),
146 'Can retrieve nested input data' => array('cake', array('cake' => array('is a' => 'l\\ie')), array('is a' => 'lie'))
147 );
148 }
149
150 /**
151 * @test
152 * @dataProvider getAndPostDataProvider
153 */
154 public function canRetrieveGlobalInputsThroughGet($key, $get, $expected) {
155 $_GET = $get;
156 $this->assertSame($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::_GET($key));
157 }
158
159 /**
160 * @test
161 * @dataProvider getAndPostDataProvider
162 */
163 public function canRetrieveGlobalInputsThroughPost($key, $post, $expected) {
164 $_POST = $post;
165 $this->assertSame($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::_POST($key));
166 }
167
168 ///////////////////////////////
169 // Tests concerning _GETset
170 ///////////////////////////////
171 /**
172 * @test
173 * @dataProvider getSetDataProvider
174 */
175 public function canSetNewGetInputValues($input, $key, $expected, $getPreset = array()) {
176 $_GET = $getPreset;
177 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset($input, $key);
178 $this->assertSame($expected, $_GET);
179 }
180
181 /**
182 * Data provider for canSetNewGetInputValues
183 *
184 * @return array
185 */
186 public function getSetDataProvider() {
187 return array(
188 'No input data used without target key' => array(NULL, NULL, array()),
189 'No input data used with target key' => array(NULL, 'cake', array('cake' => '')),
190 'No target key used with string input data' => array('data', NULL, array()),
191 'No target key used with array input data' => array(array('cake' => 'lie'), NULL, array('cake' => 'lie')),
192 'Target key and string input data' => array('lie', 'cake', array('cake' => 'lie')),
193 'Replace existing GET data' => array('lie', 'cake', array('cake' => 'lie'), array('cake' => 'is a lie')),
194 'Target key pointing to sublevels and string input data' => array('lie', 'cake|is', array('cake' => array('is' => 'lie'))),
195 'Target key pointing to sublevels and array input data' => array(array('a' => 'lie'), 'cake|is', array('cake' => array('is' => array('a' => 'lie'))))
196 );
197 }
198
199 ///////////////////////////////
200 // Tests concerning gif_compress
201 ///////////////////////////////
202 /**
203 * @test
204 */
205 public function gifCompressFixesPermissionOfConvertedFileIfUsingImagemagick() {
206 if (TYPO3_OS == 'WIN') {
207 $this->markTestSkipped('gifCompressFixesPermissionOfConvertedFileIfUsingImagemagick() test not available on Windows.');
208 }
209 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] || !$GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']) {
210 $this->markTestSkipped('gifCompressFixesPermissionOfConvertedFileIfUsingImagemagick() test not available without imagemagick setup.');
211 }
212 $fixtureGifFile = __DIR__ . '/Fixtures/clear.gif';
213 $GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress'] = TRUE;
214 // Copy file to unique filename in typo3temp, set target permissions and run method
215 $testFilename = ((PATH_site . 'typo3temp/') . uniqid('test_')) . '.gif';
216 @copy($fixtureGifFile, $testFilename);
217 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
218 \TYPO3\CMS\Core\Utility\GeneralUtility::gif_compress($testFilename, 'IM');
219 // Get actual permissions and clean up
220 clearstatcache();
221 $resultFilePermissions = substr(decoct(fileperms($testFilename)), 2);
222 \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($testFilename);
223 $this->assertEquals($resultFilePermissions, '0777');
224 }
225
226 /**
227 * @test
228 */
229 public function gifCompressFixesPermissionOfConvertedFileIfUsingGd() {
230 if (TYPO3_OS == 'WIN') {
231 $this->markTestSkipped('gifCompressFixesPermissionOfConvertedFileIfUsingImagemagick() test not available on Windows.');
232 }
233 $fixtureGifFile = __DIR__ . '/Fixtures/clear.gif';
234 $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'] = TRUE;
235 $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'] = FALSE;
236 $GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress'] = TRUE;
237 // Copy file to unique filename in typo3temp, set target permissions and run method
238 $testFilename = ((PATH_site . 'typo3temp/') . uniqid('test_')) . '.gif';
239 @copy($fixtureGifFile, $testFilename);
240 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
241 \TYPO3\CMS\Core\Utility\GeneralUtility::gif_compress($testFilename, 'GD');
242 // Get actual permissions and clean up
243 clearstatcache();
244 $resultFilePermissions = substr(decoct(fileperms($testFilename)), 2);
245 \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($testFilename);
246 $this->assertEquals($resultFilePermissions, '0777');
247 }
248
249 ///////////////////////////////
250 // Tests concerning png_to_gif_by_imagemagick
251 ///////////////////////////////
252 /**
253 * @test
254 */
255 public function pngToGifByImagemagickFixesPermissionsOfConvertedFile() {
256 if (TYPO3_OS == 'WIN') {
257 $this->markTestSkipped('pngToGifByImagemagickFixesPermissionsOfConvertedFile() test not available on Windows.');
258 }
259 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] || !$GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']) {
260 $this->markTestSkipped('pngToGifByImagemagickFixesPermissionsOfConvertedFile() test not available without imagemagick setup.');
261 }
262 $fixturePngFile = __DIR__ . '/Fixtures/clear.png';
263 $GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif'] = TRUE;
264 // Copy file to unique filename in typo3temp, set target permissions and run method
265 $testFilename = ((PATH_site . 'typo3temp/') . uniqid('test_')) . '.png';
266 @copy($fixturePngFile, $testFilename);
267 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
268 $newGifFile = \TYPO3\CMS\Core\Utility\GeneralUtility::png_to_gif_by_imagemagick($testFilename);
269 // Get actual permissions and clean up
270 clearstatcache();
271 $resultFilePermissions = substr(decoct(fileperms($newGifFile)), 2);
272 \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($newGifFile);
273 $this->assertEquals($resultFilePermissions, '0777');
274 }
275
276 ///////////////////////////////
277 // Tests concerning read_png_gif
278 ///////////////////////////////
279 /**
280 * @test
281 */
282 public function readPngGifFixesPermissionsOfConvertedFile() {
283 if (TYPO3_OS == 'WIN') {
284 $this->markTestSkipped('readPngGifFixesPermissionsOfConvertedFile() test not available on Windows.');
285 }
286 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
287 $this->markTestSkipped('readPngGifFixesPermissionsOfConvertedFile() test not available without imagemagick setup.');
288 }
289 $testGifFile = __DIR__ . '/Fixtures/clear.gif';
290 // Set target permissions and run method
291 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
292 $newPngFile = \TYPO3\CMS\Core\Utility\GeneralUtility::read_png_gif($testGifFile, TRUE);
293 // Get actual permissions and clean up
294 clearstatcache();
295 $resultFilePermissions = substr(decoct(fileperms($newPngFile)), 2);
296 \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($newPngFile);
297 $this->assertEquals($resultFilePermissions, '0777');
298 }
299
300 ///////////////////////////
301 // Tests concerning cmpIPv4
302 ///////////////////////////
303 /**
304 * Data provider for cmpIPv4ReturnsTrueForMatchingAddress
305 *
306 * @return array Data sets
307 */
308 static public function cmpIPv4DataProviderMatching() {
309 return array(
310 'host with full IP address' => array('127.0.0.1', '127.0.0.1'),
311 'host with two wildcards at the end' => array('127.0.0.1', '127.0.*.*'),
312 'host with wildcard at third octet' => array('127.0.0.1', '127.0.*.1'),
313 'host with wildcard at second octet' => array('127.0.0.1', '127.*.0.1'),
314 '/8 subnet' => array('127.0.0.1', '127.1.1.1/8'),
315 '/32 subnet (match only name)' => array('127.0.0.1', '127.0.0.1/32'),
316 '/30 subnet' => array('10.10.3.1', '10.10.3.3/30'),
317 'host with wildcard in list with IPv4/IPv6 addresses' => array('192.168.1.1', '127.0.0.1, 1234:5678::/126, 192.168.*'),
318 'host in list with IPv4/IPv6 addresses' => array('192.168.1.1', '::1, 1234:5678::/126, 192.168.1.1'),
319 );
320 }
321
322 /**
323 * @test
324 * @dataProvider cmpIPv4DataProviderMatching
325 */
326 public function cmpIPv4ReturnsTrueForMatchingAddress($ip, $list) {
327 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIPv4($ip, $list));
328 }
329
330 /**
331 * Data provider for cmpIPv4ReturnsFalseForNotMatchingAddress
332 *
333 * @return array Data sets
334 */
335 static public function cmpIPv4DataProviderNotMatching() {
336 return array(
337 'single host' => array('127.0.0.1', '127.0.0.2'),
338 'single host with wildcard' => array('127.0.0.1', '127.*.1.1'),
339 'single host with /32 subnet mask' => array('127.0.0.1', '127.0.0.2/32'),
340 '/31 subnet' => array('127.0.0.1', '127.0.0.2/31'),
341 'list with IPv4/IPv6 addresses' => array('127.0.0.1', '10.0.2.3, 192.168.1.1, ::1'),
342 'list with only IPv6 addresses' => array('10.20.30.40', '::1, 1234:5678::/127')
343 );
344 }
345
346 /**
347 * @test
348 * @dataProvider cmpIPv4DataProviderNotMatching
349 */
350 public function cmpIPv4ReturnsFalseForNotMatchingAddress($ip, $list) {
351 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIPv4($ip, $list));
352 }
353
354 ///////////////////////////
355 // Tests concerning cmpIPv6
356 ///////////////////////////
357 /**
358 * Data provider for cmpIPv6ReturnsTrueForMatchingAddress
359 *
360 * @return array Data sets
361 */
362 static public function cmpIPv6DataProviderMatching() {
363 return array(
364 'empty address' => array('::', '::'),
365 'empty with netmask in list' => array('::', '::/0'),
366 'empty with netmask 0 and host-bits set in list' => array('::', '::123/0'),
367 'localhost' => array('::1', '::1'),
368 'localhost with leading zero blocks' => array('::1', '0:0::1'),
369 'host with submask /128' => array('::1', '0:0::1/128'),
370 '/16 subnet' => array('1234::1', '1234:5678::/16'),
371 '/126 subnet' => array('1234:5678::3', '1234:5678::/126'),
372 '/126 subnet with host-bits in list set' => array('1234:5678::3', '1234:5678::2/126'),
373 'list with IPv4/IPv6 addresses' => array('1234:5678::3', '::1, 127.0.0.1, 1234:5678::/126, 192.168.1.1')
374 );
375 }
376
377 /**
378 * @test
379 * @dataProvider cmpIPv6DataProviderMatching
380 */
381 public function cmpIPv6ReturnsTrueForMatchingAddress($ip, $list) {
382 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIPv6($ip, $list));
383 }
384
385 /**
386 * Data provider for cmpIPv6ReturnsFalseForNotMatchingAddress
387 *
388 * @return array Data sets
389 */
390 static public function cmpIPv6DataProviderNotMatching() {
391 return array(
392 'empty against localhost' => array('::', '::1'),
393 'empty against localhost with /128 netmask' => array('::', '::1/128'),
394 'localhost against different host' => array('::1', '::2'),
395 'localhost against host with prior bits set' => array('::1', '::1:1'),
396 'host against different /17 subnet' => array('1234::1', '1234:f678::/17'),
397 'host against different /127 subnet' => array('1234:5678::3', '1234:5678::/127'),
398 'host against IPv4 address list' => array('1234:5678::3', '127.0.0.1, 192.168.1.1'),
399 'host against mixed list with IPv6 host in different subnet' => array('1234:5678::3', '::1, 1234:5678::/127')
400 );
401 }
402
403 /**
404 * @test
405 * @dataProvider cmpIPv6DataProviderNotMatching
406 */
407 public function cmpIPv6ReturnsFalseForNotMatchingAddress($ip, $list) {
408 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIPv6($ip, $list));
409 }
410
411 ///////////////////////////////
412 // Tests concerning IPv6Hex2Bin
413 ///////////////////////////////
414 /**
415 * Data provider for IPv6Hex2BinCorrect
416 *
417 * @return array Data sets
418 */
419 static public function IPv6Hex2BinDataProviderCorrect() {
420 return array(
421 'empty 1' => array('::', str_pad('', 16, "\x00")),
422 'empty 2, already normalized' => array('0000:0000:0000:0000:0000:0000:0000:0000', str_pad('', 16, "\x00")),
423 'already normalized' => array('0102:0304:0000:0000:0000:0000:0506:0078', "\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78"),
424 'expansion in middle 1' => array('1::2', "\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02"),
425 'expansion in middle 2' => array('beef::fefa', "\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa"),
426 );
427 }
428
429 /**
430 * @test
431 * @dataProvider IPv6Hex2BinDataProviderCorrect
432 */
433 public function IPv6Hex2BinCorrectlyConvertsAddresses($hex, $binary) {
434 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::IPv6Hex2Bin($hex) === $binary);
435 }
436
437 ///////////////////////////////
438 // Tests concerning IPv6Bin2Hex
439 ///////////////////////////////
440 /**
441 * Data provider for IPv6Bin2HexCorrect
442 *
443 * @return array Data sets
444 */
445 static public function IPv6Bin2HexDataProviderCorrect() {
446 return array(
447 'empty' => array(str_pad('', 16, "\x00"), '::'),
448 'non-empty front' => array("\x01" . str_pad('', 15, "\x00"), '100::'),
449 'non-empty back' => array(str_pad('', 15, "\x00") . "\x01", '::1'),
450 'normalized' => array("\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78", '102:304::506:78'),
451 'expansion in middle 1' => array("\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02", '1::2'),
452 'expansion in middle 2' => array("\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa", 'beef::fefa'),
453 );
454 }
455
456 /**
457 * @test
458 * @dataProvider IPv6Bin2HexDataProviderCorrect
459 */
460 public function IPv6Bin2HexCorrectlyConvertsAddresses($binary, $hex) {
461 if (!class_exists('t3lib_diff')) {
462 $this->markTestSkipped('The current version of phpunit relies on t3lib_diff which is removed in 6.0 and thus this test fails. Move t3lib_diff to phpunit and reenable this test.');
463 }
464 $this->assertEquals(\TYPO3\CMS\Core\Utility\GeneralUtility::IPv6Bin2Hex($binary), $hex);
465 }
466
467 ////////////////////////////////////////////////
468 // Tests concerning normalizeIPv6 / compressIPv6
469 ////////////////////////////////////////////////
470 /**
471 * Data provider for normalizeIPv6ReturnsCorrectlyNormalizedFormat
472 *
473 * @return array Data sets
474 */
475 static public function normalizeCompressIPv6DataProviderCorrect() {
476 return array(
477 'empty' => array('::', '0000:0000:0000:0000:0000:0000:0000:0000'),
478 'localhost' => array('::1', '0000:0000:0000:0000:0000:0000:0000:0001'),
479 'some address on right side' => array('::f0f', '0000:0000:0000:0000:0000:0000:0000:0f0f'),
480 'expansion in middle 1' => array('1::2', '0001:0000:0000:0000:0000:0000:0000:0002'),
481 'expansion in middle 2' => array('1:2::3', '0001:0002:0000:0000:0000:0000:0000:0003'),
482 'expansion in middle 3' => array('1::2:3', '0001:0000:0000:0000:0000:0000:0002:0003'),
483 'expansion in middle 4' => array('1:2::3:4:5', '0001:0002:0000:0000:0000:0003:0004:0005')
484 );
485 }
486
487 /**
488 * @test
489 * @dataProvider normalizeCompressIPv6DataProviderCorrect
490 */
491 public function normalizeIPv6CorrectlyNormalizesAddresses($compressed, $normalized) {
492 $this->assertEquals(\TYPO3\CMS\Core\Utility\GeneralUtility::normalizeIPv6($compressed), $normalized);
493 }
494
495 /**
496 * @test
497 * @dataProvider normalizeCompressIPv6DataProviderCorrect
498 */
499 public function compressIPv6CorrectlyCompressesAdresses($compressed, $normalized) {
500 if (!class_exists('t3lib_diff')) {
501 $this->markTestSkipped('The current version of phpunit relies on t3lib_diff which is removed in 6.0 and thus this test fails. Move t3lib_diff to phpunit and reenable this test.');
502 }
503 $this->assertEquals(\TYPO3\CMS\Core\Utility\GeneralUtility::compressIPv6($normalized), $compressed);
504 }
505
506 ///////////////////////////////
507 // Tests concerning validIP
508 ///////////////////////////////
509 /**
510 * Data provider for checkValidIpReturnsTrueForValidIp
511 *
512 * @return array Data sets
513 */
514 static public function validIpDataProvider() {
515 return array(
516 '0.0.0.0' => array('0.0.0.0'),
517 'private IPv4 class C' => array('192.168.0.1'),
518 'private IPv4 class A' => array('10.0.13.1'),
519 'private IPv6' => array('fe80::daa2:5eff:fe8b:7dfb')
520 );
521 }
522
523 /**
524 * @test
525 * @dataProvider validIpDataProvider
526 */
527 public function validIpReturnsTrueForValidIp($ip) {
528 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::validIP($ip));
529 }
530
531 /**
532 * Data provider for checkValidIpReturnsFalseForInvalidIp
533 *
534 * @return array Data sets
535 */
536 static public function invalidIpDataProvider() {
537 return array(
538 'null' => array(NULL),
539 'zero' => array(0),
540 'string' => array('test'),
541 'string empty' => array(''),
542 'string NULL' => array('NULL'),
543 'out of bounds IPv4' => array('300.300.300.300'),
544 'dotted decimal notation with only two dots' => array('127.0.1')
545 );
546 }
547
548 /**
549 * @test
550 * @dataProvider invalidIpDataProvider
551 */
552 public function validIpReturnsFalseForInvalidIp($ip) {
553 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::validIP($ip));
554 }
555
556 ///////////////////////////////
557 // Tests concerning cmpFQDN
558 ///////////////////////////////
559 /**
560 * Data provider for cmpFqdnReturnsTrue
561 *
562 * @return array Data sets
563 */
564 static public function cmpFqdnValidDataProvider() {
565 return array(
566 'localhost should usually resolve, IPv4' => array('127.0.0.1', '*'),
567 'localhost should usually resolve, IPv6' => array('::1', '*'),
568 // other testcases with resolving not possible since it would
569 // require a working IPv4/IPv6-connectivity
570 'aaa.bbb.ccc.ddd.eee, full' => array('aaa.bbb.ccc.ddd.eee', 'aaa.bbb.ccc.ddd.eee'),
571 'aaa.bbb.ccc.ddd.eee, wildcard first' => array('aaa.bbb.ccc.ddd.eee', '*.ccc.ddd.eee'),
572 'aaa.bbb.ccc.ddd.eee, wildcard last' => array('aaa.bbb.ccc.ddd.eee', 'aaa.bbb.ccc.*'),
573 'aaa.bbb.ccc.ddd.eee, wildcard middle' => array('aaa.bbb.ccc.ddd.eee', 'aaa.*.eee'),
574 'list-matches, 1' => array('aaa.bbb.ccc.ddd.eee', 'xxx, yyy, zzz, aaa.*.eee'),
575 'list-matches, 2' => array('aaa.bbb.ccc.ddd.eee', '127:0:0:1,,aaa.*.eee,::1')
576 );
577 }
578
579 /**
580 * @test
581 * @dataProvider cmpFqdnValidDataProvider
582 */
583 public function cmpFqdnReturnsTrue($baseHost, $list) {
584 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::cmpFQDN($baseHost, $list));
585 }
586
587 /**
588 * Data provider for cmpFqdnReturnsFalse
589 *
590 * @return array Data sets
591 */
592 static public function cmpFqdnInvalidDataProvider() {
593 return array(
594 'num-parts of hostname to check can only be less or equal than hostname, 1' => array('aaa.bbb.ccc.ddd.eee', 'aaa.bbb.ccc.ddd.eee.fff'),
595 'num-parts of hostname to check can only be less or equal than hostname, 2' => array('aaa.bbb.ccc.ddd.eee', 'aaa.*.bbb.ccc.ddd.eee')
596 );
597 }
598
599 /**
600 * @test
601 * @dataProvider cmpFqdnInvalidDataProvider
602 */
603 public function cmpFqdnReturnsFalse($baseHost, $list) {
604 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::cmpFQDN($baseHost, $list));
605 }
606
607 ///////////////////////////////
608 // Tests concerning inList
609 ///////////////////////////////
610 /**
611 * @test
612 * @param string $haystack
613 * @dataProvider inListForItemContainedReturnsTrueDataProvider
614 */
615 public function inListForItemContainedReturnsTrue($haystack) {
616 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::inList($haystack, 'findme'));
617 }
618
619 /**
620 * Data provider for inListForItemContainedReturnsTrue.
621 *
622 * @return array
623 */
624 public function inListForItemContainedReturnsTrueDataProvider() {
625 return array(
626 'Element as second element of four items' => array('one,findme,three,four'),
627 'Element at beginning of list' => array('findme,one,two'),
628 'Element at end of list' => array('one,two,findme'),
629 'One item list' => array('findme')
630 );
631 }
632
633 /**
634 * @test
635 * @param string $haystack
636 * @dataProvider inListForItemNotContainedReturnsFalseDataProvider
637 */
638 public function inListForItemNotContainedReturnsFalse($haystack) {
639 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::inList($haystack, 'findme'));
640 }
641
642 /**
643 * Data provider for inListForItemNotContainedReturnsFalse.
644 *
645 * @return array
646 */
647 public function inListForItemNotContainedReturnsFalseDataProvider() {
648 return array(
649 'Four item list' => array('one,two,three,four'),
650 'One item list' => array('one'),
651 'Empty list' => array('')
652 );
653 }
654
655 ///////////////////////////////
656 // Tests concerning rmFromList
657 ///////////////////////////////
658 /**
659 * @test
660 * @param string $initialList
661 * @param string $listWithElementRemoved
662 * @dataProvider rmFromListRemovesElementsFromCommaSeparatedListDataProvider
663 */
664 public function rmFromListRemovesElementsFromCommaSeparatedList($initialList, $listWithElementRemoved) {
665 $this->assertSame($listWithElementRemoved, \TYPO3\CMS\Core\Utility\GeneralUtility::rmFromList('removeme', $initialList));
666 }
667
668 /**
669 * Data provider for rmFromListRemovesElementsFromCommaSeparatedList
670 *
671 * @return array
672 */
673 public function rmFromListRemovesElementsFromCommaSeparatedListDataProvider() {
674 return array(
675 'Element as second element of three' => array('one,removeme,two', 'one,two'),
676 'Element at beginning of list' => array('removeme,one,two', 'one,two'),
677 'Element at end of list' => array('one,two,removeme', 'one,two'),
678 'One item list' => array('removeme', ''),
679 'Element not contained in list' => array('one,two,three', 'one,two,three'),
680 'Empty list' => array('', '')
681 );
682 }
683
684 ///////////////////////////////
685 // Tests concerning expandList
686 ///////////////////////////////
687 /**
688 * @test
689 * @param string $list
690 * @param string $expectation
691 * @dataProvider expandListExpandsIntegerRangesDataProvider
692 */
693 public function expandListExpandsIntegerRanges($list, $expectation) {
694 $this->assertSame($expectation, \TYPO3\CMS\Core\Utility\GeneralUtility::expandList($list));
695 }
696
697 /**
698 * Data provider for expandListExpandsIntegerRangesDataProvider
699 *
700 * @return array
701 */
702 public function expandListExpandsIntegerRangesDataProvider() {
703 return array(
704 'Expand for the same number' => array('1,2-2,7', '1,2,7'),
705 'Small range expand with parameters reversed ignores reversed items' => array('1,5-3,7', '1,7'),
706 'Small range expand' => array('1,3-5,7', '1,3,4,5,7'),
707 'Expand at beginning' => array('3-5,1,7', '3,4,5,1,7'),
708 'Expand at end' => array('1,7,3-5', '1,7,3,4,5'),
709 'Multiple small range expands' => array('1,3-5,7-10,12', '1,3,4,5,7,8,9,10,12'),
710 'One item list' => array('1-5', '1,2,3,4,5'),
711 'Nothing to expand' => array('1,2,3,4', '1,2,3,4'),
712 'Empty list' => array('', '')
713 );
714 }
715
716 /**
717 * @test
718 */
719 public function expandListExpandsForTwoThousandElementsExpandsOnlyToThousandElementsMaximum() {
720 $list = \TYPO3\CMS\Core\Utility\GeneralUtility::expandList('1-2000');
721 $this->assertSame(1000, count(explode(',', $list)));
722 }
723
724 ///////////////////////////////
725 // Tests concerning uniqueList
726 ///////////////////////////////
727 /**
728 * @test
729 * @param string $initialList
730 * @param string $unifiedList
731 * @dataProvider uniqueListUnifiesCommaSeparatedListDataProvider
732 */
733 public function uniqueListUnifiesCommaSeparatedList($initialList, $unifiedList) {
734 $this->assertSame($unifiedList, \TYPO3\CMS\Core\Utility\GeneralUtility::uniqueList($initialList));
735 }
736
737 /**
738 * Data provider for uniqueListUnifiesCommaSeparatedList
739 *
740 * @return array
741 */
742 public function uniqueListUnifiesCommaSeparatedListDataProvider() {
743 return array(
744 'List without duplicates' => array('one,two,three', 'one,two,three'),
745 'List with two consecutive duplicates' => array('one,two,two,three,three', 'one,two,three'),
746 'List with non-consecutive duplicates' => array('one,two,three,two,three', 'one,two,three'),
747 'One item list' => array('one', 'one'),
748 'Empty list' => array('', '')
749 );
750 }
751
752 ///////////////////////////////
753 // Tests concerning isFirstPartOfStr
754 ///////////////////////////////
755 /**
756 * Data provider for isFirstPartOfStrReturnsTrueForMatchingFirstParts
757 *
758 * @return array
759 */
760 public function isFirstPartOfStrReturnsTrueForMatchingFirstPartDataProvider() {
761 return array(
762 'match first part of string' => array('hello world', 'hello'),
763 'match whole string' => array('hello', 'hello'),
764 'integer is part of string with same number' => array('24', 24),
765 'string is part of integer with same number' => array(24, '24'),
766 'integer is part of string starting with same number' => array('24 beer please', 24)
767 );
768 }
769
770 /**
771 * @test
772 * @dataProvider isFirstPartOfStrReturnsTrueForMatchingFirstPartDataProvider
773 */
774 public function isFirstPartOfStrReturnsTrueForMatchingFirstPart($string, $part) {
775 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($string, $part));
776 }
777
778 /**
779 * Data provider for checkIsFirstPartOfStrReturnsFalseForNotMatchingFirstParts
780 *
781 * @return array
782 */
783 public function isFirstPartOfStrReturnsFalseForNotMatchingFirstPartDataProvider() {
784 return array(
785 'no string match' => array('hello', 'bye'),
786 'no case sensitive string match' => array('hello world', 'Hello'),
787 'array is not part of string' => array('string', array()),
788 'string is not part of array' => array(array(), 'string'),
789 'NULL is not part of string' => array('string', NULL),
790 'string is not part of array' => array(NULL, 'string'),
791 'NULL is not part of array' => array(array(), NULL),
792 'array is not part of string' => array(NULL, array()),
793 'empty string is not part of empty string' => array('', ''),
794 'NULL is not part of empty string' => array('', NULL),
795 'false is not part of empty string' => array('', FALSE),
796 'empty string is not part of NULL' => array(NULL, ''),
797 'empty string is not part of false' => array(FALSE, ''),
798 'empty string is not part of zero integer' => array(0, ''),
799 'zero integer is not part of NULL' => array(NULL, 0),
800 'zero integer is not part of empty string' => array('', 0)
801 );
802 }
803
804 /**
805 * @test
806 * @dataProvider isFirstPartOfStrReturnsFalseForNotMatchingFirstPartDataProvider
807 */
808 public function isFirstPartOfStrReturnsFalseForNotMatchingFirstPart($string, $part) {
809 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($string, $part));
810 }
811
812 ///////////////////////////////
813 // Tests concerning formatSize
814 ///////////////////////////////
815 /**
816 * @test
817 * @dataProvider formatSizeDataProvider
818 */
819 public function formatSizeTranslatesBytesToHigherOrderRepresentation($size, $label, $expected) {
820 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::formatSize($size, $label));
821 }
822
823 /**
824 * Data provider for formatSizeTranslatesBytesToHigherOrderRepresentation
825 *
826 * @return array
827 */
828 public function formatSizeDataProvider() {
829 return array(
830 'Bytes keep beeing bytes (min)' => array(1, '', '1 '),
831 'Bytes keep beeing bytes (max)' => array(899, '', '899 '),
832 'Kilobytes are detected' => array(1024, '', '1.0 K'),
833 'Megabytes are detected' => array(1048576, '', '1.0 M'),
834 'Gigabytes are detected' => array(1073741824, '', '1.0 G'),
835 'Decimal is omitted for large kilobytes' => array(31080, '', '30 K'),
836 'Decimal is omitted for large megabytes' => array(31458000, '', '30 M'),
837 'Decimal is omitted for large gigabytes' => array(32212254720, '', '30 G'),
838 'Label for bytes can be exchanged' => array(1, ' Foo|||', '1 Foo'),
839 'Label for kilobytes can be exchanged' => array(1024, '| Foo||', '1.0 Foo'),
840 'Label for megabyes can be exchanged' => array(1048576, '|| Foo|', '1.0 Foo'),
841 'Label for gigabytes can be exchanged' => array(1073741824, '||| Foo', '1.0 Foo')
842 );
843 }
844
845 ///////////////////////////////
846 // Tests concerning splitCalc
847 ///////////////////////////////
848 /**
849 * Data provider for splitCalc
850 *
851 * @return array expected values, arithmetic expression
852 */
853 public function splitCalcDataProvider() {
854 return array(
855 'empty string returns empty array' => array(
856 array(),
857 ''
858 ),
859 'number without operator returns array with plus and number' => array(
860 array(array('+', 42)),
861 '42'
862 ),
863 'two numbers with asterisk return first number with plus and second number with asterisk' => array(
864 array(array('+', 42), array('*', 31)),
865 '42 * 31'
866 )
867 );
868 }
869
870 /**
871 * @test
872 * @dataProvider splitCalcDataProvider
873 */
874 public function splitCalcCorrectlySplitsExpression($expected, $expression) {
875 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::splitCalc($expression, '+-*/'));
876 }
877
878 ///////////////////////////////
879 // Tests concerning htmlspecialchars_decode
880 ///////////////////////////////
881 /**
882 * @test
883 */
884 public function htmlspecialcharsDecodeReturnsDecodedString() {
885 $string = '<typo3 version="6.0">&nbsp;</typo3>';
886 $encoded = htmlspecialchars($string);
887 $decoded = \TYPO3\CMS\Core\Utility\GeneralUtility::htmlspecialchars_decode($encoded);
888 $this->assertEquals($string, $decoded);
889 }
890
891 ///////////////////////////////
892 // Tests concerning deHSCentities
893 ///////////////////////////////
894 /**
895 * @test
896 * @dataProvider deHSCentitiesReturnsDecodedStringDataProvider
897 */
898 public function deHSCentitiesReturnsDecodedString($input, $expected) {
899 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::deHSCentities($input));
900 }
901
902 /**
903 * Data provider for deHSCentitiesReturnsDecodedString
904 *
905 * @return array
906 */
907 public function deHSCentitiesReturnsDecodedStringDataProvider() {
908 return array(
909 'Empty string' => array('', ''),
910 'Double encoded &' => array('&amp;amp;', '&amp;'),
911 'Double encoded numeric entity' => array('&amp;#1234;', '&#1234;'),
912 'Double encoded hexadecimal entity' => array('&amp;#x1b;', '&#x1b;'),
913 'Single encoded entities are not touched' => array('&amp; &#1234; &#x1b;', '&amp; &#1234; &#x1b;')
914 );
915 }
916
917 //////////////////////////////////
918 // Tests concerning slashJS
919 //////////////////////////////////
920 /**
921 * @test
922 * @dataProvider slashJsDataProvider
923 */
924 public function slashJsEscapesSingleQuotesAndSlashes($input, $extended, $expected) {
925 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::slashJS($input, $extended));
926 }
927
928 /**
929 * Data provider for slashJsEscapesSingleQuotesAndSlashes
930 *
931 * @return array
932 */
933 public function slashJsDataProvider() {
934 return array(
935 'Empty string is not changed' => array('', FALSE, ''),
936 'Normal string is not changed' => array('The cake is a lie √', FALSE, 'The cake is a lie √'),
937 'String with single quotes' => array('The \'cake\' is a lie', FALSE, 'The \\\'cake\\\' is a lie'),
938 'String with single quotes and backslashes - just escape single quotes' => array('The \\\'cake\\\' is a lie', FALSE, 'The \\\\\'cake\\\\\' is a lie'),
939 'String with single quotes and backslashes - escape both' => array('The \\\'cake\\\' is a lie', TRUE, 'The \\\\\\\'cake\\\\\\\' is a lie')
940 );
941 }
942
943 //////////////////////////////////
944 // Tests concerning rawUrlEncodeJS
945 //////////////////////////////////
946 /**
947 * @test
948 */
949 public function rawUrlEncodeJsPreservesWhitespaces() {
950 $input = 'Encode \'me\', but leave my spaces √';
951 $expected = 'Encode %27me%27%2C but leave my spaces %E2%88%9A';
952 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::rawUrlEncodeJS($input));
953 }
954
955 //////////////////////////////////
956 // Tests concerning rawUrlEncodeJS
957 //////////////////////////////////
958 /**
959 * @test
960 */
961 public function rawUrlEncodeFpPreservesSlashes() {
962 $input = 'Encode \'me\', but leave my / √';
963 $expected = 'Encode%20%27me%27%2C%20but%20leave%20my%20/%20%E2%88%9A';
964 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::rawUrlEncodeFP($input));
965 }
966
967 //////////////////////////////////
968 // Tests concerning strtoupper / strtolower
969 //////////////////////////////////
970 /**
971 * Data provider for strtoupper and strtolower
972 *
973 * @return array
974 */
975 public function strtouppperDataProvider() {
976 return array(
977 'Empty string' => array('', ''),
978 'String containing only latin characters' => array('the cake is a lie.', 'THE CAKE IS A LIE.'),
979 'String with umlauts and accent characters' => array('the càkê is ä lie.', 'THE CàKê IS ä LIE.')
980 );
981 }
982
983 /**
984 * @test
985 * @dataProvider strtouppperDataProvider
986 */
987 public function strtoupperConvertsOnlyLatinCharacters($input, $expected) {
988 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::strtoupper($input));
989 }
990
991 /**
992 * @test
993 * @dataProvider strtouppperDataProvider
994 */
995 public function strtolowerConvertsOnlyLatinCharacters($expected, $input) {
996 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::strtolower($input));
997 }
998
999 //////////////////////////////////
1000 // Tests concerning validEmail
1001 //////////////////////////////////
1002 /**
1003 * Data provider for valid validEmail's
1004 *
1005 * @return array Valid email addresses
1006 */
1007 public function validEmailValidDataProvider() {
1008 return array(
1009 'short mail address' => array('a@b.c'),
1010 'simple mail address' => array('test@example.com'),
1011 'uppercase characters' => array('QWERTYUIOPASDFGHJKLZXCVBNM@QWERTYUIOPASDFGHJKLZXCVBNM.NET'),
1012 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6 and 5.3.2 but fails with 5.3.0 on windows
1013 // 'equal sign in local part' => array('test=mail@example.com'),
1014 'dash in local part' => array('test-mail@example.com'),
1015 'plus in local part' => array('test+mail@example.com'),
1016 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6 and 5.3.2 but fails with 5.3.0 on windows
1017 // 'question mark in local part' => array('test?mail@example.com'),
1018 'slash in local part' => array('foo/bar@example.com'),
1019 'hash in local part' => array('foo#bar@example.com'),
1020 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6 and 5.3.2 but fails with 5.3.0 on windows
1021 // 'dot in local part' => array('firstname.lastname@employee.2something.com'),
1022 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
1023 // 'dash as local part' => array('-@foo.com'),
1024 'umlauts in local part' => array('äöüfoo@bar.com'),
1025 'umlauts in domain part' => array('foo@äöüfoo.com')
1026 );
1027 }
1028
1029 /**
1030 * @test
1031 * @dataProvider validEmailValidDataProvider
1032 */
1033 public function validEmailReturnsTrueForValidMailAddress($address) {
1034 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($address));
1035 }
1036
1037 /**
1038 * Data provider for invalid validEmail's
1039 *
1040 * @return array Invalid email addresses
1041 */
1042 public function validEmailInvalidDataProvider() {
1043 return array(
1044 '@ sign only' => array('@'),
1045 'duplicate @' => array('test@@example.com'),
1046 'duplicate @ combined with further special characters in local part' => array('test!.!@#$%^&*@example.com'),
1047 'opening parenthesis in local part' => array('foo(bar@example.com'),
1048 'closing parenthesis in local part' => array('foo)bar@example.com'),
1049 'opening square bracket in local part' => array('foo[bar@example.com'),
1050 'closing square bracket as local part' => array(']@example.com'),
1051 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
1052 // 'top level domain only' => array('test@com'),
1053 'dash as second level domain' => array('foo@-.com'),
1054 'domain part starting with dash' => array('foo@-foo.com'),
1055 'domain part ending with dash' => array('foo@foo-.com'),
1056 'number as top level domain' => array('foo@bar.123'),
1057 // Fix / change if TYPO3 php requirement changed: Address not ok with 5.2.6, but ok with 5.3.2 (?)
1058 // 'dash as top level domain' => array('foo@bar.-'),
1059 'dot at beginning of domain part' => array('test@.com'),
1060 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
1061 // 'local part ends with dot' => array('e.x.a.m.p.l.e.@example.com'),
1062 'trailing whitespace' => array('test@example.com '),
1063 'trailing carriage return' => array('test@example.com' . CR),
1064 'trailing linefeed' => array('test@example.com' . LF),
1065 'trailing carriage return linefeed' => array('test@example.com' . CRLF),
1066 'trailing tab' => array('test@example.com' . TAB)
1067 );
1068 }
1069
1070 /**
1071 * @test
1072 * @dataProvider validEmailInvalidDataProvider
1073 */
1074 public function validEmailReturnsFalseForInvalidMailAddress($address) {
1075 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($address));
1076 }
1077
1078 //////////////////////////////////
1079 // Tests concerning inArray
1080 //////////////////////////////////
1081 /**
1082 * @test
1083 * @dataProvider inArrayDataProvider
1084 */
1085 public function inArrayChecksStringExistenceWithinArray($array, $item, $expected) {
1086 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::inArray($array, $item));
1087 }
1088
1089 /**
1090 * Data provider for inArrayChecksStringExistenceWithinArray
1091 *
1092 * @return array
1093 */
1094 public function inArrayDataProvider() {
1095 return array(
1096 'Empty array' => array(array(), 'search', FALSE),
1097 'One item array no match' => array(array('one'), 'two', FALSE),
1098 'One item array match' => array(array('one'), 'one', TRUE),
1099 'Multiple items array no match' => array(array('one', 2, 'three', 4), 'four', FALSE),
1100 'Multiple items array match' => array(array('one', 2, 'three', 4), 'three', TRUE),
1101 'Integer search items can match string values' => array(array('0', '1', '2'), 1, TRUE),
1102 'Search item is not casted to integer for a match' => array(array(4), '4a', FALSE),
1103 'Empty item won\'t match - in contrast to the php-builtin ' => array(array(0, 1, 2), '', FALSE)
1104 );
1105 }
1106
1107 //////////////////////////////////
1108 // Tests concerning intExplode
1109 //////////////////////////////////
1110 /**
1111 * @test
1112 */
1113 public function intExplodeConvertsStringsToInteger() {
1114 $testString = '1,foo,2';
1115 $expectedArray = array(1, 0, 2);
1116 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $testString);
1117 $this->assertEquals($expectedArray, $actualArray);
1118 }
1119
1120 //////////////////////////////////
1121 // Tests concerning keepItemsInArray
1122 //////////////////////////////////
1123 /**
1124 * @test
1125 * @dataProvider keepItemsInArrayWorksWithOneArgumentDataProvider
1126 */
1127 public function keepItemsInArrayWorksWithOneArgument($search, $array, $expected) {
1128 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::keepItemsInArray($array, $search));
1129 }
1130
1131 /**
1132 * Data provider for keepItemsInArrayWorksWithOneArgument
1133 *
1134 * @return array
1135 */
1136 public function keepItemsInArrayWorksWithOneArgumentDataProvider() {
1137 $array = array(
1138 'one' => 'one',
1139 'two' => 'two',
1140 'three' => 'three'
1141 );
1142 return array(
1143 'Empty argument will match "all" elements' => array(NULL, $array, $array),
1144 'No match' => array('four', $array, array()),
1145 'One match' => array('two', $array, array('two' => 'two')),
1146 'Multiple matches' => array('two,one', $array, array('one' => 'one', 'two' => 'two')),
1147 'Argument can be an array' => array(array('three'), $array, array('three' => 'three'))
1148 );
1149 }
1150
1151 /**
1152 * Shows the exmaple from the doc comment where
1153 * a function is used to reduce the sub arrays to one item which
1154 * is then used for the matching.
1155 *
1156 * @test
1157 */
1158 public function keepItemsInArrayCanUseCallbackOnSearchArray() {
1159 $array = array(
1160 'aa' => array('first', 'second'),
1161 'bb' => array('third', 'fourth'),
1162 'cc' => array('fifth', 'sixth')
1163 );
1164 $expected = array('bb' => array('third', 'fourth'));
1165 $keepItems = 'third';
1166 $getValueFunc = create_function('$value', 'return $value[0];');
1167 $match = \TYPO3\CMS\Core\Utility\GeneralUtility::keepItemsInArray($array, $keepItems, $getValueFunc);
1168 $this->assertEquals($expected, $match);
1169 }
1170
1171 //////////////////////////////////
1172 // Tests concerning implodeArrayForUrl / explodeUrl2Array
1173 //////////////////////////////////
1174 /**
1175 * Data provider for implodeArrayForUrlBuildsValidParameterString and
1176 * explodeUrl2ArrayTransformsParameterStringToArray
1177 *
1178 * @return array
1179 */
1180 public function implodeArrayForUrlDataProvider() {
1181 $valueArray = array('one' => '√', 'two' => 2);
1182 return array(
1183 'Empty input' => array('foo', array(), ''),
1184 'String parameters' => array('foo', $valueArray, '&foo[one]=%E2%88%9A&foo[two]=2'),
1185 'Nested array parameters' => array('foo', array($valueArray), '&foo[0][one]=%E2%88%9A&foo[0][two]=2'),
1186 'Keep blank parameters' => array('foo', array('one' => '√', ''), '&foo[one]=%E2%88%9A&foo[0]=')
1187 );
1188 }
1189
1190 /**
1191 * @test
1192 * @dataProvider implodeArrayForUrlDataProvider
1193 */
1194 public function implodeArrayForUrlBuildsValidParameterString($name, $input, $expected) {
1195 $this->assertSame($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl($name, $input));
1196 }
1197
1198 /**
1199 * @test
1200 */
1201 public function implodeArrayForUrlCanSkipEmptyParameters() {
1202 $input = array('one' => '√', '');
1203 $expected = '&foo[one]=%E2%88%9A';
1204 $this->assertSame($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl('foo', $input, '', TRUE));
1205 }
1206
1207 /**
1208 * @test
1209 */
1210 public function implodeArrayForUrlCanUrlEncodeKeyNames() {
1211 $input = array('one' => '√', '');
1212 $expected = '&foo%5Bone%5D=%E2%88%9A&foo%5B0%5D=';
1213 $this->assertSame($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl('foo', $input, '', FALSE, TRUE));
1214 }
1215
1216 /**
1217 * @test
1218 * @dataProvider implodeArrayForUrlDataProvider
1219 */
1220 public function explodeUrl2ArrayTransformsParameterStringToNestedArray($name, $array, $input) {
1221 $expected = $array ? array($name => $array) : array();
1222 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::explodeUrl2Array($input, TRUE));
1223 }
1224
1225 /**
1226 * @test
1227 * @dataProvider explodeUrl2ArrayDataProvider
1228 */
1229 public function explodeUrl2ArrayTransformsParameterStringToFlatArray($input, $expected) {
1230 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::explodeUrl2Array($input, FALSE));
1231 }
1232
1233 /**
1234 * Data provider for explodeUrl2ArrayTransformsParameterStringToFlatArray
1235 *
1236 * @return array
1237 */
1238 public function explodeUrl2ArrayDataProvider() {
1239 return array(
1240 'Empty string' => array('', array()),
1241 'Simple parameter string' => array('&one=%E2%88%9A&two=2', array('one' => '√', 'two' => 2)),
1242 'Nested parameter string' => array('&foo[one]=%E2%88%9A&two=2', array('foo[one]' => '√', 'two' => 2))
1243 );
1244 }
1245
1246 //////////////////////////////////
1247 // Tests concerning compileSelectedGetVarsFromArray
1248 //////////////////////////////////
1249 /**
1250 * @test
1251 */
1252 public function compileSelectedGetVarsFromArrayFiltersIncomingData() {
1253 $filter = 'foo,bar';
1254 $getArray = array('foo' => 1, 'cake' => 'lie');
1255 $expected = array('foo' => 1);
1256 $result = \TYPO3\CMS\Core\Utility\GeneralUtility::compileSelectedGetVarsFromArray($filter, $getArray, FALSE);
1257 $this->assertSame($expected, $result);
1258 }
1259
1260 /**
1261 * @test
1262 */
1263 public function compileSelectedGetVarsFromArrayUsesGetPostDataFallback() {
1264 $_GET['bar'] = '2';
1265 $filter = 'foo,bar';
1266 $getArray = array('foo' => 1, 'cake' => 'lie');
1267 $expected = array('foo' => 1, 'bar' => '2');
1268 $result = \TYPO3\CMS\Core\Utility\GeneralUtility::compileSelectedGetVarsFromArray($filter, $getArray, TRUE);
1269 $this->assertSame($expected, $result);
1270 }
1271
1272 //////////////////////////////////
1273 // Tests concerning remapArrayKeys
1274 //////////////////////////////////
1275 /**
1276 * @test
1277 */
1278 public function remapArrayKeysExchangesKeysWithGivenMapping() {
1279 $array = array(
1280 'one' => 'one',
1281 'two' => 'two',
1282 'three' => 'three'
1283 );
1284 $keyMapping = array(
1285 'one' => '1',
1286 'two' => '2'
1287 );
1288 $expected = array(
1289 '1' => 'one',
1290 '2' => 'two',
1291 'three' => 'three'
1292 );
1293 \TYPO3\CMS\Core\Utility\GeneralUtility::remapArrayKeys($array, $keyMapping);
1294 $this->assertEquals($expected, $array);
1295 }
1296
1297 //////////////////////////////////
1298 // Tests concerning array_merge
1299 //////////////////////////////////
1300 /**
1301 * Test demonstrating array_merge. This is actually
1302 * a native PHP operator, therefore this test is mainly used to
1303 * show how this function can be used.
1304 *
1305 * @test
1306 */
1307 public function arrayMergeKeepsIndexesAfterMerge() {
1308 $array1 = array(10 => 'FOO', '20' => 'BAR');
1309 $array2 = array('5' => 'PLONK');
1310 $expected = array('5' => 'PLONK', 10 => 'FOO', '20' => 'BAR');
1311 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge($array1, $array2));
1312 }
1313
1314 //////////////////////////////////
1315 // Tests concerning int_from_ver
1316 //////////////////////////////////
1317 /**
1318 * Data Provider for intFromVerConvertsVersionNumbersToIntegersDataProvider
1319 *
1320 * return array
1321 */
1322 public function intFromVerConvertsVersionNumbersToIntegersDataProvider() {
1323 return array(
1324 array('4003003', '4.3.3'),
1325 array('4012003', '4.12.3'),
1326 array('5000000', '5.0.0'),
1327 array('3008001', '3.8.1'),
1328 array('1012', '0.1.12')
1329 );
1330 }
1331
1332 /**
1333 * @test
1334 * @dataProvider intFromVerConvertsVersionNumbersToIntegersDataProvider
1335 */
1336 public function intFromVerConvertsVersionNumbersToIntegers($expected, $version) {
1337 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::int_from_ver($version));
1338 }
1339
1340 //////////////////////////////////
1341 // Tests concerning revExplode
1342 //////////////////////////////////
1343 /**
1344 * @test
1345 */
1346 public function revExplodeExplodesString() {
1347 $testString = 'my:words:here';
1348 $expectedArray = array('my:words', 'here');
1349 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::revExplode(':', $testString, 2);
1350 $this->assertEquals($expectedArray, $actualArray);
1351 }
1352
1353 //////////////////////////////////
1354 // Tests concerning trimExplode
1355 //////////////////////////////////
1356 /**
1357 * @test
1358 */
1359 public function checkTrimExplodeTrimsSpacesAtElementStartAndEnd() {
1360 $testString = ' a , b , c ,d ,, e,f,';
1361 $expectedArray = array('a', 'b', 'c', 'd', '', 'e', 'f', '');
1362 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString);
1363 $this->assertEquals($expectedArray, $actualArray);
1364 }
1365
1366 /**
1367 * @test
1368 */
1369 public function checkTrimExplodeRemovesNewLines() {
1370 $testString = (' a , b , ' . LF) . ' ,d ,, e,f,';
1371 $expectedArray = array('a', 'b', 'd', 'e', 'f');
1372 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1373 $this->assertEquals($expectedArray, $actualArray);
1374 }
1375
1376 /**
1377 * @test
1378 */
1379 public function checkTrimExplodeRemovesEmptyElements() {
1380 $testString = 'a , b , c , ,d ,, ,e,f,';
1381 $expectedArray = array('a', 'b', 'c', 'd', 'e', 'f');
1382 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1383 $this->assertEquals($expectedArray, $actualArray);
1384 }
1385
1386 /**
1387 * @test
1388 */
1389 public function checkTrimExplodeKeepsRemainingResultsWithEmptyItemsAfterReachingLimitWithPositiveParameter() {
1390 $testString = ' a , b , c , , d,, ,e ';
1391 $expectedArray = array('a', 'b', 'c,,d,,,e');
1392 // Limiting returns the rest of the string as the last element
1393 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString, FALSE, 3);
1394 $this->assertEquals($expectedArray, $actualArray);
1395 }
1396
1397 /**
1398 * @test
1399 */
1400 public function checkTrimExplodeKeepsRemainingResultsWithoutEmptyItemsAfterReachingLimitWithPositiveParameter() {
1401 $testString = ' a , b , c , , d,, ,e ';
1402 $expectedArray = array('a', 'b', 'c,d,e');
1403 // Limiting returns the rest of the string as the last element
1404 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString, TRUE, 3);
1405 $this->assertEquals($expectedArray, $actualArray);
1406 }
1407
1408 /**
1409 * @test
1410 */
1411 public function checkTrimExplodeKeepsRamainingResultsWithEmptyItemsAfterReachingLimitWithNegativeParameter() {
1412 $testString = ' a , b , c , d, ,e, f , , ';
1413 $expectedArray = array('a', 'b', 'c', 'd', '', 'e');
1414 // limiting returns the rest of the string as the last element
1415 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString, FALSE, -3);
1416 $this->assertEquals($expectedArray, $actualArray);
1417 }
1418
1419 /**
1420 * @test
1421 */
1422 public function checkTrimExplodeKeepsRamainingResultsWithoutEmptyItemsAfterReachingLimitWithNegativeParameter() {
1423 $testString = ' a , b , c , d, ,e, f , , ';
1424 $expectedArray = array('a', 'b', 'c');
1425 // Limiting returns the rest of the string as the last element
1426 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString, TRUE, -3);
1427 $this->assertEquals($expectedArray, $actualArray);
1428 }
1429
1430 /**
1431 * @test
1432 */
1433 public function checkTrimExplodeReturnsExactResultsWithoutReachingLimitWithPositiveParameter() {
1434 $testString = ' a , b , , c , , , ';
1435 $expectedArray = array('a', 'b', 'c');
1436 // Limiting returns the rest of the string as the last element
1437 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString, TRUE, 4);
1438 $this->assertEquals($expectedArray, $actualArray);
1439 }
1440
1441 /**
1442 * @test
1443 */
1444 public function checkTrimExplodeKeepsZeroAsString() {
1445 $testString = 'a , b , c , ,d ,, ,e,f, 0 ,';
1446 $expectedArray = array('a', 'b', 'c', 'd', 'e', 'f', '0');
1447 $actualArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1448 $this->assertEquals($expectedArray, $actualArray);
1449 }
1450
1451 //////////////////////////////////
1452 // Tests concerning removeArrayEntryByValue
1453 //////////////////////////////////
1454 /**
1455 * @test
1456 */
1457 public function checkRemoveArrayEntryByValueRemovesEntriesFromOneDimensionalArray() {
1458 $inputArray = array(
1459 '0' => 'test1',
1460 '1' => 'test2',
1461 '2' => 'test3',
1462 '3' => 'test2'
1463 );
1464 $compareValue = 'test2';
1465 $expectedResult = array(
1466 '0' => 'test1',
1467 '2' => 'test3'
1468 );
1469 $actualResult = \TYPO3\CMS\Core\Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1470 $this->assertEquals($expectedResult, $actualResult);
1471 }
1472
1473 /**
1474 * @test
1475 */
1476 public function checkRemoveArrayEntryByValueRemovesEntriesFromMultiDimensionalArray() {
1477 $inputArray = array(
1478 '0' => 'foo',
1479 '1' => array(
1480 '10' => 'bar'
1481 ),
1482 '2' => 'bar'
1483 );
1484 $compareValue = 'bar';
1485 $expectedResult = array(
1486 '0' => 'foo',
1487 '1' => array()
1488 );
1489 $actualResult = \TYPO3\CMS\Core\Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1490 $this->assertEquals($expectedResult, $actualResult);
1491 }
1492
1493 /**
1494 * @test
1495 */
1496 public function checkRemoveArrayEntryByValueRemovesEntryWithEmptyString() {
1497 $inputArray = array(
1498 '0' => 'foo',
1499 '1' => '',
1500 '2' => 'bar'
1501 );
1502 $compareValue = '';
1503 $expectedResult = array(
1504 '0' => 'foo',
1505 '2' => 'bar'
1506 );
1507 $actualResult = \TYPO3\CMS\Core\Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1508 $this->assertEquals($expectedResult, $actualResult);
1509 }
1510
1511 //////////////////////////////////
1512 // Tests concerning getBytesFromSizeMeasurement
1513 //////////////////////////////////
1514 /**
1515 * Data provider for getBytesFromSizeMeasurement
1516 *
1517 * @return array expected value, input string
1518 */
1519 public function getBytesFromSizeMeasurementDataProvider() {
1520 return array(
1521 '100 kilo Bytes' => array('102400', '100k'),
1522 '100 mega Bytes' => array('104857600', '100m'),
1523 '100 giga Bytes' => array('107374182400', '100g')
1524 );
1525 }
1526
1527 /**
1528 * @test
1529 * @dataProvider getBytesFromSizeMeasurementDataProvider
1530 */
1531 public function getBytesFromSizeMeasurementCalculatesCorrectByteValue($expected, $byteString) {
1532 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::getBytesFromSizeMeasurement($byteString));
1533 }
1534
1535 //////////////////////////////////
1536 // Tests concerning getIndpEnv
1537 //////////////////////////////////
1538 /**
1539 * @test
1540 */
1541 public function getIndpEnvTypo3SitePathReturnNonEmptyString() {
1542 $this->assertTrue(strlen(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH')) >= 1);
1543 }
1544
1545 /**
1546 * @test
1547 */
1548 public function getIndpEnvTypo3SitePathReturnsStringStartingWithSlash() {
1549 $result = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1550 $this->assertEquals('/', $result[0]);
1551 }
1552
1553 /**
1554 * @test
1555 */
1556 public function getIndpEnvTypo3SitePathReturnsStringEndingWithSlash() {
1557 $result = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1558 $this->assertEquals('/', $result[strlen($result) - 1]);
1559 }
1560
1561 /**
1562 * @return array
1563 */
1564 static public function hostnameAndPortDataProvider() {
1565 return array(
1566 'localhost ipv4 without port' => array('127.0.0.1', '127.0.0.1', ''),
1567 'localhost ipv4 with port' => array('127.0.0.1:81', '127.0.0.1', '81'),
1568 'localhost ipv6 without port' => array('[::1]', '[::1]', ''),
1569 'localhost ipv6 with port' => array('[::1]:81', '[::1]', '81'),
1570 'ipv6 without port' => array('[2001:DB8::1]', '[2001:DB8::1]', ''),
1571 'ipv6 with port' => array('[2001:DB8::1]:81', '[2001:DB8::1]', '81'),
1572 'hostname without port' => array('lolli.did.this', 'lolli.did.this', ''),
1573 'hostname with port' => array('lolli.did.this:42', 'lolli.did.this', '42')
1574 );
1575 }
1576
1577 /**
1578 * @test
1579 * @dataProvider hostnameAndPortDataProvider
1580 */
1581 public function getIndpEnvTypo3HostOnlyParsesHostnamesAndIpAdresses($httpHost, $expectedIp) {
1582 $_SERVER['HTTP_HOST'] = $httpHost;
1583 $this->assertEquals($expectedIp, \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'));
1584 }
1585
1586 /**
1587 * @test
1588 * @dataProvider hostnameAndPortDataProvider
1589 */
1590 public function getIndpEnvTypo3PortParsesHostnamesAndIpAdresses($httpHost, $dummy, $expectedPort) {
1591 $_SERVER['HTTP_HOST'] = $httpHost;
1592 $this->assertEquals($expectedPort, \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_PORT'));
1593 }
1594
1595 //////////////////////////////////
1596 // Tests concerning underscoredToUpperCamelCase
1597 //////////////////////////////////
1598 /**
1599 * Data provider for underscoredToUpperCamelCase
1600 *
1601 * @return array expected, input string
1602 */
1603 public function underscoredToUpperCamelCaseDataProvider() {
1604 return array(
1605 'single word' => array('Blogexample', 'blogexample'),
1606 'multiple words' => array('BlogExample', 'blog_example')
1607 );
1608 }
1609
1610 /**
1611 * @test
1612 * @dataProvider underscoredToUpperCamelCaseDataProvider
1613 */
1614 public function underscoredToUpperCamelCase($expected, $inputString) {
1615 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($inputString));
1616 }
1617
1618 //////////////////////////////////
1619 // Tests concerning underscoredToLowerCamelCase
1620 //////////////////////////////////
1621 /**
1622 * Data provider for underscoredToLowerCamelCase
1623 *
1624 * @return array expected, input string
1625 */
1626 public function underscoredToLowerCamelCaseDataProvider() {
1627 return array(
1628 'single word' => array('minimalvalue', 'minimalvalue'),
1629 'multiple words' => array('minimalValue', 'minimal_value')
1630 );
1631 }
1632
1633 /**
1634 * @test
1635 * @dataProvider underscoredToLowerCamelCaseDataProvider
1636 */
1637 public function underscoredToLowerCamelCase($expected, $inputString) {
1638 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToLowerCamelCase($inputString));
1639 }
1640
1641 //////////////////////////////////
1642 // Tests concerning camelCaseToLowerCaseUnderscored
1643 //////////////////////////////////
1644 /**
1645 * Data provider for camelCaseToLowerCaseUnderscored
1646 *
1647 * @return array expected, input string
1648 */
1649 public function camelCaseToLowerCaseUnderscoredDataProvider() {
1650 return array(
1651 'single word' => array('blogexample', 'blogexample'),
1652 'single word starting upper case' => array('blogexample', 'Blogexample'),
1653 'two words starting lower case' => array('minimal_value', 'minimalValue'),
1654 'two words starting upper case' => array('blog_example', 'BlogExample')
1655 );
1656 }
1657
1658 /**
1659 * @test
1660 * @dataProvider camelCaseToLowerCaseUnderscoredDataProvider
1661 */
1662 public function camelCaseToLowerCaseUnderscored($expected, $inputString) {
1663 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($inputString));
1664 }
1665
1666 //////////////////////////////////
1667 // Tests concerning lcFirst
1668 //////////////////////////////////
1669 /**
1670 * Data provider for lcFirst
1671 *
1672 * @return array expected, input string
1673 */
1674 public function lcfirstDataProvider() {
1675 return array(
1676 'single word' => array('blogexample', 'blogexample'),
1677 'single Word starting upper case' => array('blogexample', 'Blogexample'),
1678 'two words' => array('blogExample', 'BlogExample')
1679 );
1680 }
1681
1682 /**
1683 * @test
1684 * @dataProvider lcfirstDataProvider
1685 */
1686 public function lcFirst($expected, $inputString) {
1687 $this->assertEquals($expected, \TYPO3\CMS\Core\Utility\GeneralUtility::lcfirst($inputString));
1688 }
1689
1690 //////////////////////////////////
1691 // Tests concerning encodeHeader
1692 //////////////////////////////////
1693 /**
1694 * @test
1695 */
1696 public function encodeHeaderEncodesWhitespacesInQuotedPrintableMailHeader() {
1697 $this->assertEquals('=?utf-8?Q?We_test_whether_the_copyright_character_=C2=A9_is_encoded_correctly?=', \TYPO3\CMS\Core\Utility\GeneralUtility::encodeHeader('We test whether the copyright character © is encoded correctly', 'quoted-printable', 'utf-8'));
1698 }
1699
1700 /**
1701 * @test
1702 */
1703 public function encodeHeaderEncodesQuestionmarksInQuotedPrintableMailHeader() {
1704 $this->assertEquals('=?utf-8?Q?Is_the_copyright_character_=C2=A9_really_encoded_correctly=3F_Really=3F?=', \TYPO3\CMS\Core\Utility\GeneralUtility::encodeHeader('Is the copyright character © really encoded correctly? Really?', 'quoted-printable', 'utf-8'));
1705 }
1706
1707 //////////////////////////////////
1708 // Tests concerning isValidUrl
1709 //////////////////////////////////
1710 /**
1711 * Data provider for valid isValidUrl's
1712 *
1713 * @return array Valid ressource
1714 */
1715 public function validUrlValidRessourceDataProvider() {
1716 return array(
1717 'http' => array('http://www.example.org/'),
1718 'http without trailing slash' => array('http://qwe'),
1719 'http directory with trailing slash' => array('http://www.example/img/dir/'),
1720 'http directory without trailing slash' => array('http://www.example/img/dir'),
1721 'http index.html' => array('http://example.com/index.html'),
1722 'http index.php' => array('http://www.example.com/index.php'),
1723 'http test.png' => array('http://www.example/img/test.png'),
1724 'http username password querystring and ancher' => array('https://user:pw@www.example.org:80/path?arg=value#fragment'),
1725 'file' => array('file:///tmp/test.c'),
1726 'file directory' => array('file://foo/bar'),
1727 'ftp directory' => array('ftp://ftp.example.com/tmp/'),
1728 'mailto' => array('mailto:foo@bar.com'),
1729 'news' => array('news:news.php.net'),
1730 'telnet' => array('telnet://192.0.2.16:80/'),
1731 'ldap' => array('ldap://[2001:db8::7]/c=GB?objectClass?one'),
1732 'http punycode domain name' => array('http://www.xn--bb-eka.at'),
1733 'http punicode subdomain' => array('http://xn--h-zfa.oebb.at'),
1734 'http domain-name umlauts' => array('http://www.öbb.at'),
1735 'http subdomain umlauts' => array('http://äh.oebb.at'),
1736 'http directory umlauts' => array('http://www.oebb.at/äöü/')
1737 );
1738 }
1739
1740 /**
1741 * @test
1742 * @dataProvider validUrlValidRessourceDataProvider
1743 */
1744 public function validURLReturnsTrueForValidRessource($url) {
1745 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::isValidUrl($url));
1746 }
1747
1748 /**
1749 * Data provider for invalid isValidUrl's
1750 *
1751 * @return array Invalid ressource
1752 */
1753 public function isValidUrlInvalidRessourceDataProvider() {
1754 return array(
1755 'http missing colon' => array('http//www.example/wrong/url/'),
1756 'http missing slash' => array('http:/www.example'),
1757 'hostname only' => array('www.example.org/'),
1758 'file missing protocol specification' => array('/tmp/test.c'),
1759 'slash only' => array('/'),
1760 'string http://' => array('http://'),
1761 'string http:/' => array('http:/'),
1762 'string http:' => array('http:'),
1763 'string http' => array('http'),
1764 'empty string' => array(''),
1765 'string -1' => array('-1'),
1766 'string array()' => array('array()'),
1767 'random string' => array('qwe')
1768 );
1769 }
1770
1771 /**
1772 * @test
1773 * @dataProvider isValidUrlInvalidRessourceDataProvider
1774 */
1775 public function validURLReturnsFalseForInvalidRessoure($url) {
1776 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::isValidUrl($url));
1777 }
1778
1779 //////////////////////////////////
1780 // Tests concerning isOnCurrentHost
1781 //////////////////////////////////
1782 /**
1783 * @test
1784 */
1785 public function isOnCurrentHostReturnsTrueWithCurrentHost() {
1786 $testUrl = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL');
1787 $this->assertTrue(\TYPO3\CMS\Core\Utility\GeneralUtility::isOnCurrentHost($testUrl));
1788 }
1789
1790 /**
1791 * Data provider for invalid isOnCurrentHost's
1792 *
1793 * @return array Invalid Hosts
1794 */
1795 public function checkisOnCurrentHostInvalidHosts() {
1796 return array(
1797 'empty string' => array(''),
1798 'arbitrary string' => array('arbitrary string'),
1799 'localhost IP' => array('127.0.0.1'),
1800 'relative path' => array('./relpath/file.txt'),
1801 'absolute path' => array('/abspath/file.txt?arg=value'),
1802 'differnt host' => array(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_HOST') . '.example.org')
1803 );
1804 }
1805
1806 ////////////////////////////////////////
1807 // Tests concerning sanitizeLocalUrl
1808 ////////////////////////////////////////
1809 /**
1810 * Data provider for valid sanitizeLocalUrl's
1811 *
1812 * @return array Valid url
1813 */
1814 public function sanitizeLocalUrlValidUrlDataProvider() {
1815 $subDirectory = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1816 $typo3SiteUrl = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
1817 $typo3RequestHost = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_HOST');
1818 return array(
1819 'alt_intro.php' => array('alt_intro.php'),
1820 'alt_intro.php?foo=1&bar=2' => array('alt_intro.php?foo=1&bar=2'),
1821 $subDirectory . 'typo3/alt_intro.php' => array($subDirectory . 'typo3/alt_intro.php'),
1822 $subDirectory . 'index.php' => array($subDirectory . 'index.php'),
1823 '../index.php' => array('../index.php'),
1824 '../typo3/alt_intro.php' => array('../typo3/alt_intro.php'),
1825 '../~userDirectory/index.php' => array('../~userDirectory/index.php'),
1826 '../typo3/mod.php?var1=test-case&var2=~user' => array('../typo3/mod.php?var1=test-case&var2=~user'),
1827 PATH_site . 'typo3/alt_intro.php' => array(PATH_site . 'typo3/alt_intro.php'),
1828 $typo3SiteUrl . 'typo3/alt_intro.php' => array($typo3SiteUrl . 'typo3/alt_intro.php'),
1829 ($typo3RequestHost . $subDirectory) . '/index.php' => array(($typo3RequestHost . $subDirectory) . '/index.php')
1830 );
1831 }
1832
1833 /**
1834 * @test
1835 * @dataProvider sanitizeLocalUrlValidUrlDataProvider
1836 */
1837 public function sanitizeLocalUrlAcceptsNotEncodedValidUrls($url) {
1838 $this->assertEquals($url, \TYPO3\CMS\Core\Utility\GeneralUtility::sanitizeLocalUrl($url));
1839 }
1840
1841 /**
1842 * @test
1843 * @dataProvider sanitizeLocalUrlValidUrlDataProvider
1844 */
1845 public function sanitizeLocalUrlAcceptsEncodedValidUrls($url) {
1846 $this->assertEquals(rawurlencode($url), \TYPO3\CMS\Core\Utility\GeneralUtility::sanitizeLocalUrl(rawurlencode($url)));
1847 }
1848
1849 /**
1850 * Data provider for invalid sanitizeLocalUrl's
1851 *
1852 * @return array Valid url
1853 */
1854 public function sanitizeLocalUrlInvalidDataProvider() {
1855 return array(
1856 'empty string' => array(''),
1857 'http domain' => array('http://www.google.de/'),
1858 'https domain' => array('https://www.google.de/'),
1859 'relative path with XSS' => array('../typo3/whatever.php?argument=javascript:alert(0)')
1860 );
1861 }
1862
1863 /**
1864 * @test
1865 * @dataProvider sanitizeLocalUrlInvalidDataProvider
1866 */
1867 public function sanitizeLocalUrlDeniesPlainInvalidUrls($url) {
1868 $this->assertEquals('', \TYPO3\CMS\Core\Utility\GeneralUtility::sanitizeLocalUrl($url));
1869 }
1870
1871 /**
1872 * @test
1873 * @dataProvider sanitizeLocalUrlInvalidDataProvider
1874 */
1875 public function sanitizeLocalUrlDeniesEncodedInvalidUrls($url) {
1876 $this->assertEquals('', \TYPO3\CMS\Core\Utility\GeneralUtility::sanitizeLocalUrl(rawurlencode($url)));
1877 }
1878
1879 //////////////////////////////////////
1880 // Tests concerning addSlashesOnArray
1881 //////////////////////////////////////
1882 /**
1883 * @test
1884 */
1885 public function addSlashesOnArrayAddsSlashesRecursive() {
1886 $inputArray = array(
1887 'key1' => array(
1888 'key11' => 'val\'ue1',
1889 'key12' => 'val"ue2'
1890 ),
1891 'key2' => 'val\\ue3'
1892 );
1893 $expectedResult = array(
1894 'key1' => array(
1895 'key11' => 'val\\\'ue1',
1896 'key12' => 'val\\"ue2'
1897 ),
1898 'key2' => 'val\\\\ue3'
1899 );
1900 \TYPO3\CMS\Core\Utility\GeneralUtility::addSlashesOnArray($inputArray);
1901 $this->assertEquals($expectedResult, $inputArray);
1902 }
1903
1904 //////////////////////////////////////
1905 // Tests concerning addSlashesOnArray
1906 //////////////////////////////////////
1907 /**
1908 * @test
1909 */
1910 public function stripSlashesOnArrayStripsSlashesRecursive() {
1911 $inputArray = array(
1912 'key1' => array(
1913 'key11' => 'val\\\'ue1',
1914 'key12' => 'val\\"ue2'
1915 ),
1916 'key2' => 'val\\\\ue3'
1917 );
1918 $expectedResult = array(
1919 'key1' => array(
1920 'key11' => 'val\'ue1',
1921 'key12' => 'val"ue2'
1922 ),
1923 'key2' => 'val\\ue3'
1924 );
1925 \TYPO3\CMS\Core\Utility\GeneralUtility::stripSlashesOnArray($inputArray);
1926 $this->assertEquals($expectedResult, $inputArray);
1927 }
1928
1929 //////////////////////////////////////
1930 // Tests concerning arrayDiffAssocRecursive
1931 //////////////////////////////////////
1932 /**
1933 * @test
1934 */
1935 public function arrayDiffAssocRecursiveHandlesOneDimensionalArrays() {
1936 $array1 = array(
1937 'key1' => 'value1',
1938 'key2' => 'value2',
1939 'key3' => 'value3'
1940 );
1941 $array2 = array(
1942 'key1' => 'value1',
1943 'key3' => 'value3'
1944 );
1945 $expectedResult = array(
1946 'key2' => 'value2'
1947 );
1948 $actualResult = \TYPO3\CMS\Core\Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
1949 $this->assertEquals($expectedResult, $actualResult);
1950 }
1951
1952 /**
1953 * @test
1954 */
1955 public function arrayDiffAssocRecursiveHandlesMultiDimensionalArrays() {
1956 $array1 = array(
1957 'key1' => 'value1',
1958 'key2' => array(
1959 'key21' => 'value21',
1960 'key22' => 'value22',
1961 'key23' => array(
1962 'key231' => 'value231',
1963 'key232' => 'value232'
1964 )
1965 )
1966 );
1967 $array2 = array(
1968 'key1' => 'value1',
1969 'key2' => array(
1970 'key21' => 'value21',
1971 'key23' => array(
1972 'key231' => 'value231'
1973 )
1974 )
1975 );
1976 $expectedResult = array(
1977 'key2' => array(
1978 'key22' => 'value22',
1979 'key23' => array(
1980 'key232' => 'value232'
1981 )
1982 )
1983 );
1984 $actualResult = \TYPO3\CMS\Core\Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
1985 $this->assertEquals($expectedResult, $actualResult);
1986 }
1987
1988 /**
1989 * @test
1990 */
1991 public function arrayDiffAssocRecursiveHandlesMixedArrays() {
1992 $array1 = array(
1993 'key1' => array(
1994 'key11' => 'value11',
1995 'key12' => 'value12'
1996 ),
1997 'key2' => 'value2',
1998 'key3' => 'value3'
1999 );
2000 $array2 = array(
2001 'key1' => 'value1',
2002 'key2' => array(
2003 'key21' => 'value21'
2004 )
2005 );
2006 $expectedResult = array(
2007 'key3' => 'value3'
2008 );
2009 $actualResult = \TYPO3\CMS\Core\Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
2010 $this->assertEquals($expectedResult, $actualResult);
2011 }
2012
2013 //////////////////////////////////////
2014 // Tests concerning removeDotsFromTS
2015 //////////////////////////////////////
2016 /**
2017 * @test
2018 */
2019 public function removeDotsFromTypoScriptSucceedsWithDottedArray() {
2020 $typoScript = array(
2021 'propertyA.' => array(
2022 'keyA.' => array(
2023 'valueA' => 1
2024 ),
2025 'keyB' => 2
2026 ),
2027 'propertyB' => 3
2028 );
2029 $expectedResult = array(
2030 'propertyA' => array(
2031 'keyA' => array(
2032 'valueA' => 1
2033 ),
2034 'keyB' => 2
2035 ),
2036 'propertyB' => 3
2037 );
2038 $this->assertEquals($expectedResult, \TYPO3\CMS\Core\Utility\GeneralUtility::removeDotsFromTS($typoScript));
2039 }
2040
2041 /**
2042 * @test
2043 */
2044 public function removeDotsFromTypoScriptOverridesSubArray() {
2045 $typoScript = array(
2046 'propertyA.' => array(
2047 'keyA' => 'getsOverridden',
2048 'keyA.' => array(
2049 'valueA' => 1
2050 ),
2051 'keyB' => 2
2052 ),
2053 'propertyB' => 3
2054 );
2055 $expectedResult = array(
2056 'propertyA' => array(
2057 'keyA' => array(
2058 'valueA' => 1
2059 ),
2060 'keyB' => 2
2061 ),
2062 'propertyB' => 3
2063 );
2064 $this->assertEquals($expectedResult, \TYPO3\CMS\Core\Utility\GeneralUtility::removeDotsFromTS($typoScript));
2065 }
2066
2067 /**
2068 * @test
2069 */
2070 public function removeDotsFromTypoScriptOverridesWithScalar() {
2071 $typoScript = array(
2072 'propertyA.' => array(
2073 'keyA.' => array(
2074 'valueA' => 1
2075 ),
2076 'keyA' => 'willOverride',
2077 'keyB' => 2
2078 ),
2079 'propertyB' => 3
2080 );
2081 $expectedResult = array(
2082 'propertyA' => array(
2083 'keyA' => 'willOverride',
2084 'keyB' => 2
2085 ),
2086 'propertyB' => 3
2087 );
2088 $this->assertEquals($expectedResult, \TYPO3\CMS\Core\Utility\GeneralUtility::removeDotsFromTS($typoScript));
2089 }
2090
2091 //////////////////////////////////////
2092 // Tests concerning naturalKeySortRecursive
2093 //////////////////////////////////////
2094 /**
2095 * @test
2096 */
2097 public function naturalKeySortRecursiveReturnsFalseIfInputIsNotAnArray() {
2098 $testValues = array(
2099 1,
2100 'string',
2101 FALSE
2102 );
2103 foreach ($testValues as $testValue) {
2104 $this->assertFalse(\TYPO3\CMS\Core\Utility\GeneralUtility::naturalKeySortRecursive($testValue));
2105 }
2106 }
2107
2108 /**
2109 * @test
2110 */
2111 public function naturalKeySortRecursiveSortsOneDimensionalArrayByNaturalOrder() {
2112 $testArray = array(
2113 'bb' => 'bb',
2114 'ab' => 'ab',
2115 '123' => '123',
2116 'aaa' => 'aaa',
2117 'abc' => 'abc',
2118 '23' => '23',
2119 'ba' => 'ba',
2120 'bad' => 'bad',
2121 '2' => '2',
2122 'zap' => 'zap',
2123 '210' => '210'
2124 );
2125 $expectedResult = array(
2126 '2',
2127 '23',
2128 '123',
2129 '210',
2130 'aaa',
2131 'ab',
2132 'abc',
2133 'ba',
2134 'bad',
2135 'bb',
2136 'zap'
2137 );
2138 \TYPO3\CMS\Core\Utility\GeneralUtility::naturalKeySortRecursive($testArray);
2139 $this->assertEquals($expectedResult, array_values($testArray));
2140 }
2141
2142 /**
2143 * @test
2144 */
2145 public function naturalKeySortRecursiveSortsMultiDimensionalArrayByNaturalOrder() {
2146 $testArray = array(
2147 '2' => '2',
2148 'bb' => 'bb',
2149 'ab' => 'ab',
2150 '23' => '23',
2151 'aaa' => array(
2152 'bb' => 'bb',
2153 'ab' => 'ab',
2154 '123' => '123',
2155 'aaa' => 'aaa',
2156 '2' => '2',
2157 'abc' => 'abc',
2158 'ba' => 'ba',
2159 '23' => '23',
2160 'bad' => array(
2161 'bb' => 'bb',
2162 'ab' => 'ab',
2163 '123' => '123',
2164 'aaa' => 'aaa',
2165 'abc' => 'abc',
2166 '23' => '23',
2167 'ba' => 'ba',
2168 'bad' => 'bad',
2169 '2' => '2',
2170 'zap' => 'zap',
2171 '210' => '210'
2172 ),
2173 '210' => '210',
2174 'zap' => 'zap'
2175 ),
2176 'abc' => 'abc',
2177 'ba' => 'ba',
2178 '210' => '210',
2179 'bad' => 'bad',
2180 '123' => '123',
2181 'zap' => 'zap'
2182 );
2183 $expectedResult = array(
2184 '2',
2185 '23',
2186 '123',
2187 '210',
2188 'aaa',
2189 'ab',
2190 'abc',
2191 'ba',
2192 'bad',
2193 'bb',
2194 'zap'
2195 );
2196 \TYPO3\CMS\Core\Utility\GeneralUtility::naturalKeySortRecursive($testArray);
2197 $this->assertEquals($expectedResult, array_values(array_keys($testArray['aaa']['bad'])));
2198 $this->assertEquals($expectedResult, array_values(array_keys($testArray['aaa'])));
2199 $this->assertEquals($expectedResult, array_values(array_keys($testArray)));
2200 }
2201
2202 //////////////////////////////////////
2203 // Tests concerning get_dirs
2204 //////////////////////////////////////
2205 /**
2206 * @test
2207 */
2208 public function getDirsReturnsArrayOfDirectoriesFromGivenDirectory() {
2209 $path = PATH_t3lib;
2210 $directories = \TYPO3\CMS\Core\Utility\GeneralUtility::get_dirs($path);
2211 $this->assertInternalType(\PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $directories);
2212 }
2213
2214 /**
2215 * @test
2216 */
2217 public function getDirsReturnsStringErrorOnPathFailure() {
2218 $path = 'foo';
2219 $result = \TYPO3\CMS\Core\Utility\GeneralUtility::get_dirs($path);
2220 $expectedResult = 'error';
2221 $this->assertEquals($expectedResult, $result);
2222 }
2223
2224 //////////////////////////////////
2225 // Tests concerning hmac
2226 //////////////////////////////////
2227 /**
2228 * @test
2229 */
2230 public function hmacReturnsHashOfProperLength() {
2231 $hmac = \TYPO3\CMS\Core\Utility\GeneralUtility::hmac('message');
2232 $this->assertTrue(!empty($hmac) && is_string($hmac));
2233 $this->assertTrue(strlen($hmac) == 40);
2234 }
2235
2236 /**
2237 * @test
2238 */
2239 public function hmacReturnsEqualHashesForEqualInput() {
2240 $msg0 = 'message';
2241 $msg1 = 'message';
2242 $this->assertEquals(\TYPO3\CMS\Core\Utility\GeneralUtility::hmac($msg0), \TYPO3\CMS\Core\Utility\GeneralUtility::hmac($msg1));
2243 }
2244
2245 /**
2246 * @test
2247 */
2248 public function hmacReturnsNoEqualHashesForNonEqualInput() {
2249 $msg0 = 'message0';
2250 $msg1 = 'message1';
2251 $this->assertNotEquals(\TYPO3\CMS\Core\Utility\GeneralUtility::hmac($msg0), \TYPO3\CMS\Core\Utility\GeneralUtility::hmac($msg1));
2252 }
2253
2254 //////////////////////////////////
2255 // Tests concerning quoteJSvalue
2256 //////////////////////////////////
2257 /**
2258 * Data provider for quoteJSvalueTest.
2259 *
2260 * @return array
2261 */
2262 public function quoteJsValueDataProvider() {
2263 return array(
2264 'Immune characters are returned as is' => array(
2265 '._,',
2266 '._,'
2267 ),
2268 'Alphanumerical characters are returned as is' => array(
2269 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
2270 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
2271 ),
2272 'Angel brackets and ampersand are encoded' => array(
2273 '<>&',
2274 '\\x3C\\x3E\\x26'
2275 ),
2276 'Quotes and slashes are encoded' => array(
2277 '"\'\\/',
2278 '\\x22\\x27\\x5C\\x2F'
2279 ),
2280 'Empty string stays empty' => array(
2281 '',
2282 ''
2283 ),
2284 'Exclamation mark and space are properly encoded' => array(
2285 'Hello World!',
2286 'Hello\\x20World\\x21'
2287 ),
2288 'Whitespaces are properly encoded' => array(
2289 ((TAB . LF) . CR) . ' ',
2290 '\\x09\\x0A\\x0D\\x20'
2291 ),
2292 'Null byte is properly encoded' => array(
2293 chr(0),
2294 '\\x00'
2295 ),
2296 'Umlauts are properly encoded' => array(
2297 'ÜüÖöÄä',
2298 '\\xDC\\xFC\\xD6\\xF6\\xC4\\xE4'
2299 )
2300 );
2301 }
2302
2303 /**
2304 * @test
2305 * @param string $input
2306 * @param string $expected
2307 * @dataProvider quoteJsValueDataProvider
2308 */
2309 public function quoteJsValueTest($input, $expected) {
2310 $this->assertSame(('\'' . $expected) . '\'', \TYPO3\CMS\Core\Utility\GeneralUtility::quoteJSvalue($input));
2311 }
2312
2313 //////////////////////////////////
2314 // Tests concerning readLLfile
2315 //////////////////////////////////
2316 /**
2317 * @test
2318 */
2319 public function readLLfileHandlesLocallangXMLOverride() {
2320 $unique = uniqid('locallangXMLOverrideTest');
2321 $xml = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
2322 <T3locallang>
2323 <data type="array">
2324 <languageKey index="default" type="array">
2325 <label index="buttons.logout">EXIT</label>
2326 </languageKey>
2327 </data>
2328 </T3locallang>';
2329 $file = ((PATH_site . 'typo3temp/') . $unique) . '.xml';
2330 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($file, $xml);
2331 // Make sure there is no cached version of the label
2332 $GLOBALS['typo3CacheManager']->getCache('t3lib_l10n')->flush();
2333 // Get default value
2334 $defaultLL = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile('EXT:lang/locallang_core.xml', 'default');
2335 // Clear language cache again
2336 $GLOBALS['typo3CacheManager']->getCache('t3lib_l10n')->flush();
2337 // Set override file
2338 $GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']['EXT:lang/locallang_core.xml'][$unique] = $file;
2339 /** @var $store \TYPO3\CMS\Core\Localization\LanguageStore */
2340 $store = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\LanguageStore');
2341 $store->flushData('EXT:lang/locallang_core.xml');
2342 // Get override value
2343 $overrideLL = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile('EXT:lang/locallang_core.xml', 'default');
2344 // Clean up again
2345 unlink($file);
2346 $this->assertNotEquals($overrideLL['default']['buttons.logout'][0]['target'], '');
2347 $this->assertNotEquals($defaultLL['default']['buttons.logout'][0]['target'], $overrideLL['default']['buttons.logout'][0]['target']);
2348 $this->assertEquals($overrideLL['default']['buttons.logout'][0]['target'], 'EXIT');
2349 }
2350
2351 ///////////////////////////////
2352 // Tests concerning _GETset()
2353 ///////////////////////////////
2354 /**
2355 * @test
2356 */
2357 public function getSetWritesArrayToGetSystemVariable() {
2358 $_GET = array();
2359 $GLOBALS['HTTP_GET_VARS'] = array();
2360 $getParameters = array('foo' => 'bar');
2361 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset($getParameters);
2362 $this->assertSame($getParameters, $_GET);
2363 }
2364
2365 /**
2366 * @test
2367 */
2368 public function getSetWritesArrayToGlobalsHttpGetVars() {
2369 $_GET = array();
2370 $GLOBALS['HTTP_GET_VARS'] = array();
2371 $getParameters = array('foo' => 'bar');
2372 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset($getParameters);
2373 $this->assertSame($getParameters, $GLOBALS['HTTP_GET_VARS']);
2374 }
2375
2376 /**
2377 * @test
2378 */
2379 public function getSetForArrayDropsExistingValues() {
2380 $_GET = array();
2381 $GLOBALS['HTTP_GET_VARS'] = array();
2382 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('foo' => 'bar'));
2383 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('oneKey' => 'oneValue'));
2384 $this->assertEquals(array('oneKey' => 'oneValue'), $GLOBALS['HTTP_GET_VARS']);
2385 }
2386
2387 /**
2388 * @test
2389 */
2390 public function getSetAssignsOneValueToOneKey() {
2391 $_GET = array();
2392 $GLOBALS['HTTP_GET_VARS'] = array();
2393 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset('oneValue', 'oneKey');
2394 $this->assertEquals('oneValue', $GLOBALS['HTTP_GET_VARS']['oneKey']);
2395 }
2396
2397 /**
2398 * @test
2399 */
2400 public function getSetForOneValueDoesNotDropUnrelatedValues() {
2401 $_GET = array();
2402 $GLOBALS['HTTP_GET_VARS'] = array();
2403 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('foo' => 'bar'));
2404 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset('oneValue', 'oneKey');
2405 $this->assertEquals(array('foo' => 'bar', 'oneKey' => 'oneValue'), $GLOBALS['HTTP_GET_VARS']);
2406 }
2407
2408 /**
2409 * @test
2410 */
2411 public function getSetCanAssignsAnArrayToASpecificArrayElement() {
2412 $_GET = array();
2413 $GLOBALS['HTTP_GET_VARS'] = array();
2414 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('childKey' => 'oneValue'), 'parentKey');
2415 $this->assertEquals(array('parentKey' => array('childKey' => 'oneValue')), $GLOBALS['HTTP_GET_VARS']);
2416 }
2417
2418 /**
2419 * @test
2420 */
2421 public function getSetCanAssignAStringValueToASpecificArrayChildElement() {
2422 $_GET = array();
2423 $GLOBALS['HTTP_GET_VARS'] = array();
2424 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset('oneValue', 'parentKey|childKey');
2425 $this->assertEquals(array('parentKey' => array('childKey' => 'oneValue')), $GLOBALS['HTTP_GET_VARS']);
2426 }
2427
2428 /**
2429 * @test
2430 */
2431 public function getSetCanAssignAnArrayToASpecificArrayChildElement() {
2432 $_GET = array();
2433 $GLOBALS['HTTP_GET_VARS'] = array();
2434 \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('key1' => 'value1', 'key2' => 'value2'), 'parentKey|childKey');
2435 $this->assertEquals(array(
2436 'parentKey' => array(
2437 'childKey' => array('key1' => 'value1', 'key2' => 'value2')
2438 )
2439 ), $GLOBALS['HTTP_GET_VARS']);
2440 }
2441
2442 ///////////////////////////
2443 // Tests concerning minifyJavaScript
2444 ///////////////////////////
2445 /**
2446 * @test
2447 */
2448 public function minifyJavaScriptReturnsInputStringIfNoHookIsRegistered() {
2449 unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript']);
2450 $testString = uniqid('string');
2451 $this->assertSame($testString, \TYPO3\CMS\Core\Utility\GeneralUtility::minifyJavaScript($testString));
2452 }
2453
2454 /**
2455 * Create an own hook callback class, register as hook, and check
2456 * if given string to compress is given to hook method
2457 *
2458 * @test
2459 */
2460 public function minifyJavaScriptCallsRegisteredHookWithInputString() {
2461 $hookClassName = uniqid('tx_coretest');
2462 $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2463 $functionName = ('&' . $hookClassName) . '->minify';
2464 $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2465 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2466 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2467 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2468 $minifyHookMock->expects($this->once())->method('minify')->will($this->returnCallback(array($this, 'isMinifyJavaScriptHookCalledCallback')));
2469 \TYPO3\CMS\Core\Utility\GeneralUtility::minifyJavaScript('foo');
2470 }
2471
2472 /**
2473 * Callback function used in minifyJavaScriptCallsRegisteredHookWithInputString test
2474 *
2475 * @param array $params
2476 */
2477 public function isMinifyJavaScriptHookCalledCallback(array $params) {
2478 // We can not throw an exception here, because that would be caught by the
2479 // minifyJavaScript method under test itself. Thus, we just die if the
2480 // input string is not ok.
2481 if ($params['script'] !== 'foo') {
2482 die('broken');
2483 }
2484 }
2485
2486 /**
2487 * Create a hook callback, use callback to throw an exception and check
2488 * if the exception is given as error parameter to the calling method.
2489 *
2490 * @test
2491 */
2492 public function minifyJavaScriptReturnsErrorStringOfHookException() {
2493 $hookClassName = uniqid('tx_coretest');
2494 $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2495 $functionName = ('&' . $hookClassName) . '->minify';
2496 $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2497 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2498 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2499 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2500 $minifyHookMock->expects($this->any())->method('minify')->will($this->returnCallback(array($this, 'minifyJavaScriptErroneousCallback')));
2501 $error = '';
2502 \TYPO3\CMS\Core\Utility\GeneralUtility::minifyJavaScript('string to compress', $error);
2503 $this->assertSame('Error minifying java script: foo', $error);
2504 }
2505
2506 /**
2507 * Check if the error message that is returned by the hook callback
2508 * is logged to t3lib_div::devLog.
2509 *
2510 * @test
2511 */
2512 public function minifyJavaScriptWritesExceptionMessageToDevLog() {
2513 $namespace = 'TYPO3\\CMS\\Core\\Utility';
2514 $t3libDivMock = uniqid('GeneralUtility');
2515 eval((((((((('namespace ' . $namespace . '; class ' . $t3libDivMock) . ' extends \\TYPO3\\CMS\\Core\\Utility\\GeneralUtility {') . ' public static function devLog($errorMessage) {') . ' if (!($errorMessage === \'Error minifying java script: foo\')) {') . ' throw new \\UnexpectedValue(\'broken\');') . ' }') . ' throw new \\RuntimeException();') . ' }') . '}');
2516 $t3libDivMock = $namespace . '\\' . $t3libDivMock;
2517 $hookClassName = uniqid('tx_coretest');
2518 $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2519 $functionName = ('&' . $hookClassName) . '->minify';
2520 $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2521 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2522 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2523 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2524 $minifyHookMock->expects($this->any())->method('minify')->will($this->returnCallback(array($this, 'minifyJavaScriptErroneousCallback')));
2525 $this->setExpectedException('\\RuntimeException');
2526 $t3libDivMock::minifyJavaScript('string to compress');
2527 }
2528
2529 /**
2530 * Callback function used in
2531 * minifyJavaScriptReturnsErrorStringOfHookException and
2532 * minifyJavaScriptWritesExceptionMessageToDevLog
2533 *
2534 * @throws \RuntimeException
2535 */
2536 public function minifyJavaScriptErroneousCallback() {
2537 throw new \RuntimeException('foo', 1344888548);
2538 }
2539
2540 ///////////////////////////
2541 // Tests concerning getUrl
2542 ///////////////////////////
2543 /**
2544 * @test
2545 */
2546 public function getUrlWithAdditionalRequestHeadersProvidesHttpHeaderOnError() {
2547 $url = 'http://typo3.org/i-do-not-exist-' . time();
2548 $report = array();
2549 \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($url, 0, array(), $report);
2550 $this->assertContains('404', $report['message']);
2551 }
2552
2553 /**
2554 * @test
2555 */
2556 public function getUrlProvidesWithoutAdditionalRequestHeadersHttpHeaderOnError() {
2557 $url = 'http://typo3.org/i-do-not-exist-' . time();
2558 $report = array();
2559 \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($url, 0, FALSE, $report);
2560 $this->assertContains('404', $report['message'], 'Did not provide the HTTP response header when requesting a failing URL.');
2561 }
2562
2563 ///////////////////////////////
2564 // Tests concerning fixPermissions
2565 ///////////////////////////////
2566 /**
2567 * @test
2568 */
2569 public function fixPermissionsSetsGroup() {
2570 if (TYPO3_OS == 'WIN') {
2571 $this->markTestSkipped('fixPermissionsSetsGroup() tests not available on Windows');
2572 }
2573 if (!function_exists('posix_getegid')) {
2574 $this->markTestSkipped('Function posix_getegid() not available, fixPermissionsSetsGroup() tests skipped');
2575 }
2576 if (posix_getegid() === -1) {
2577 $this->markTestSkipped('The fixPermissionsSetsGroup() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.');
2578 }
2579 // Create and prepare test file
2580 $filename = (PATH_site . 'typo3temp/') . uniqid('test_');
2581 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($filename, '42');
2582 $currentGroupId = posix_getegid();
2583 // Set target group and run method
2584 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $currentGroupId;
2585 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($filename);
2586 clearstatcache();
2587 $resultFileGroup = filegroup($filename);
2588 unlink($filename);
2589 $this->assertEquals($currentGroupId, $resultFileGroup);
2590 }
2591
2592 /**
2593 * @test
2594 */
2595 public function fixPermissionsSetsPermissionsToFile() {
2596 if (TYPO3_OS == 'WIN') {
2597 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2598 }
2599 // Create and prepare test file
2600 $filename = (PATH_site . 'typo3temp/') . uniqid('test_');
2601 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($filename, '42');
2602 chmod($filename, 482);
2603 // Set target permissions and run method
2604 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2605 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($filename);
2606 // Get actual permissions and clean up
2607 clearstatcache();
2608 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
2609 unlink($filename);
2610 // Test if everything was ok
2611 $this->assertTrue($fixPermissionsResult);
2612 $this->assertEquals($resultFilePermissions, '0660');
2613 }
2614
2615 /**
2616 * @test
2617 */
2618 public function fixPermissionsSetsPermissionsToHiddenFile() {
2619 if (TYPO3_OS == 'WIN') {
2620 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2621 }
2622 // Create and prepare test file
2623 $filename = (PATH_site . 'typo3temp/') . uniqid('.test_');
2624 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($filename, '42');
2625 chmod($filename, 482);
2626 // Set target permissions and run method
2627 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2628 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($filename);
2629 // Get actual permissions and clean up
2630 clearstatcache();
2631 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
2632 unlink($filename);
2633 // Test if everything was ok
2634 $this->assertTrue($fixPermissionsResult);
2635 $this->assertEquals($resultFilePermissions, '0660');
2636 }
2637
2638 /**
2639 * @test
2640 */
2641 public function fixPermissionsSetsPermissionsToDirectory() {
2642 if (TYPO3_OS == 'WIN') {
2643 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2644 }
2645 // Create and prepare test directory
2646 $directory = (PATH_site . 'typo3temp/') . uniqid('test_');
2647 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($directory);
2648 chmod($directory, 1551);
2649 // Set target permissions and run method
2650 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2651 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($directory);
2652 // Get actual permissions and clean up
2653 clearstatcache();
2654 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2655 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($directory);
2656 // Test if everything was ok
2657 $this->assertTrue($fixPermissionsResult);
2658 $this->assertEquals($resultDirectoryPermissions, '0770');
2659 }
2660
2661 /**
2662 * @test
2663 */
2664 public function fixPermissionsSetsPermissionsToDirectoryWithTrailingSlash() {
2665 if (TYPO3_OS == 'WIN') {
2666 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2667 }
2668 // Create and prepare test directory
2669 $directory = (PATH_site . 'typo3temp/') . uniqid('test_');
2670 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($directory);
2671 chmod($directory, 1551);
2672 // Set target permissions and run method
2673 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2674 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($directory . '/');
2675 // Get actual permissions and clean up
2676 clearstatcache();
2677 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2678 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($directory);
2679 // Test if everything was ok
2680 $this->assertTrue($fixPermissionsResult);
2681 $this->assertEquals($resultDirectoryPermissions, '0770');
2682 }
2683
2684 /**
2685 * @test
2686 */
2687 public function fixPermissionsSetsPermissionsToHiddenDirectory() {
2688 if (TYPO3_OS == 'WIN') {
2689 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2690 }
2691 // Create and prepare test directory
2692 $directory = (PATH_site . 'typo3temp/') . uniqid('.test_');
2693 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($directory);
2694 chmod($directory, 1551);
2695 // Set target permissions and run method
2696 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2697 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($directory);
2698 // Get actual permissions and clean up
2699 clearstatcache();
2700 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2701 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($directory);
2702 // Test if everything was ok
2703 $this->assertTrue($fixPermissionsResult);
2704 $this->assertEquals($resultDirectoryPermissions, '0770');
2705 }
2706
2707 /**
2708 * @test
2709 */
2710 public function fixPermissionsCorrectlySetsPermissionsRecursive() {
2711 if (TYPO3_OS == 'WIN') {
2712 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2713 }
2714 // Create and prepare test directory and file structure
2715 $baseDirectory = (PATH_site . 'typo3temp/') . uniqid('test_');
2716 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($baseDirectory);
2717 chmod($baseDirectory, 1751);
2718 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/file', '42');
2719 chmod($baseDirectory . '/file', 482);
2720 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($baseDirectory . '/foo');
2721 chmod($baseDirectory . '/foo', 1751);
2722 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/foo/file', '42');
2723 chmod($baseDirectory . '/foo/file', 482);
2724 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($baseDirectory . '/.bar');
2725 chmod($baseDirectory . '/.bar', 1751);
2726 // Use this if writeFileToTypo3tempDir is fixed to create hidden files in subdirectories
2727 // t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/.bar/.file', '42');
2728 // t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/.bar/..file2', '42');
2729 touch($baseDirectory . '/.bar/.file', '42');
2730 chmod($baseDirectory . '/.bar/.file', 482);
2731 touch($baseDirectory . '/.bar/..file2', '42');
2732 chmod($baseDirectory . '/.bar/..file2', 482);
2733 // Set target permissions and run method
2734 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2735 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2736 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($baseDirectory, TRUE);
2737 // Get actual permissions
2738 clearstatcache();
2739 $resultBaseDirectoryPermissions = substr(decoct(fileperms($baseDirectory)), 1);
2740 $resultBaseFilePermissions = substr(decoct(fileperms($baseDirectory . '/file')), 2);
2741 $resultFooDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/foo')), 1);
2742 $resultFooFilePermissions = substr(decoct(fileperms($baseDirectory . '/foo/file')), 2);
2743 $resultBarDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/.bar')), 1);
2744 $resultBarFilePermissions = substr(decoct(fileperms($baseDirectory . '/.bar/.file')), 2);
2745 $resultBarFile2Permissions = substr(decoct(fileperms($baseDirectory . '/.bar/..file2')), 2);
2746 // Clean up
2747 unlink($baseDirectory . '/file');
2748 unlink($baseDirectory . '/foo/file');
2749 unlink($baseDirectory . '/.bar/.file');
2750 unlink($baseDirectory . '/.bar/..file2');
2751 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($baseDirectory . '/foo');
2752 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($baseDirectory . '/.bar');
2753 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($baseDirectory);
2754 // Test if everything was ok
2755 $this->assertTrue($fixPermissionsResult);
2756 $this->assertEquals($resultBaseDirectoryPermissions, '0770');
2757 $this->assertEquals($resultBaseFilePermissions, '0660');
2758 $this->assertEquals($resultFooDirectoryPermissions, '0770');
2759 $this->assertEquals($resultFooFilePermissions, '0660');
2760 $this->assertEquals($resultBarDirectoryPermissions, '0770');
2761 $this->assertEquals($resultBarFilePermissions, '0660');
2762 $this->assertEquals($resultBarFile2Permissions, '0660');
2763 }
2764
2765 /**
2766 * @test
2767 */
2768 public function fixPermissionsDoesNotSetPermissionsToNotAllowedPath() {
2769 if (TYPO3_OS == 'WIN') {
2770 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2771 }
2772 // Create and prepare test file
2773 $filename = (PATH_site . 'typo3temp/../typo3temp/') . uniqid('test_');
2774 touch($filename);
2775 chmod($filename, 482);
2776 // Set target permissions and run method
2777 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2778 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($filename);
2779 // Get actual permissions and clean up
2780 clearstatcache();
2781 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
2782 unlink($filename);
2783 // Test if everything was ok
2784 $this->assertFalse($fixPermissionsResult);
2785 }
2786
2787 /**
2788 * @test
2789 */
2790 public function fixPermissionsSetsPermissionsWithRelativeFileReference() {
2791 if (TYPO3_OS == 'WIN') {
2792 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2793 }
2794 $filename = 'typo3temp/' . uniqid('test_');
2795 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir(PATH_site . $filename, '42');
2796 chmod(PATH_site . $filename, 482);
2797 // Set target permissions and run method
2798 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2799 $fixPermissionsResult = \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($filename);
2800 // Get actual permissions and clean up
2801 clearstatcache();
2802 $resultFilePermissions = substr(decoct(fileperms(PATH_site . $filename)), 2);
2803 unlink(PATH_site . $filename);
2804 // Test if everything was ok
2805 $this->assertTrue($fixPermissionsResult);
2806 $this->assertEquals($resultFilePermissions, '0660');
2807 }
2808
2809 ///////////////////////////////
2810 // Tests concerning mkdir
2811 ///////////////////////////////
2812 /**
2813 * @test
2814 */
2815 public function mkdirCreatesDirectory() {
2816 $directory = (PATH_site . 'typo3temp/') . uniqid('test_');
2817 $mkdirResult = \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($directory);
2818 clearstatcache();
2819 $directoryCreated = is_dir($directory);
2820 @rmdir($directory);
2821 $this->assertTrue($mkdirResult);
2822 $this->assertTrue($directoryCreated);
2823 }
2824
2825 /**
2826 * @test
2827 */
2828 public function mkdirCreatesHiddenDirectory() {
2829 $directory = (PATH_site . 'typo3temp/') . uniqid('.test_');
2830 $mkdirResult = \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($directory);
2831 clearstatcache();
2832 $directoryCreated = is_dir($directory);
2833 @rmdir($directory);
2834 $this->assertTrue($mkdirResult);
2835 $this->assertTrue($directoryCreated);
2836 }
2837
2838 /**
2839 * @test
2840 */
2841 public function mkdirCreatesDirectoryWithTrailingSlash() {
2842 $directory = ((PATH_site . 'typo3temp/') . uniqid('test_')) . '/';
2843 $mkdirResult = \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($directory);
2844 clearstatcache();
2845 $directoryCreated = is_dir($directory);
2846 @rmdir($directory);
2847 $this->assertTrue($mkdirResult);
2848 $this->assertTrue($directoryCreated);
2849 }
2850
2851 /**
2852 * @test
2853 */
2854 public function mkdirSetsPermissionsOfCreatedDirectory() {
2855 if (TYPO3_OS == 'WIN') {
2856 $this->markTestSkipped('mkdirSetsPermissionsOfCreatedDirectory() test not available on Windows');
2857 }
2858 $directory = (PATH_site . 'typo3temp/') . uniqid('test_');
2859 $oldUmask = umask(19);
2860 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0772';
2861 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($directory);
2862 clearstatcache();
2863 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2864 umask($oldUmask);
2865 rmdir($directory);
2866 $this->assertEquals($resultDirectoryPermissions, '0772');
2867 }
2868
2869 /**
2870 * @test
2871 */
2872 public function mkdirSetsGroupOwnershipOfCreatedDirectory() {
2873 if (!function_exists('posix_getegid')) {
2874 $this->markTestSkipped('Function posix_getegid() not available, mkdirSetsGroupOwnershipOfCreatedDirectory() tests skipped');
2875 }
2876 if (posix_getegid() === -1) {
2877 $this->markTestSkipped('The mkdirSetsGroupOwnershipOfCreatedDirectory() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.');
2878 }
2879 $swapGroup = $this->checkGroups(__FUNCTION__);
2880 if ($swapGroup !== FALSE) {
2881 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
2882 $directory = uniqid('mkdirtest_');
2883 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir((PATH_site . 'typo3temp/') . $directory);
2884 clearstatcache();
2885 $resultDirectoryGroupInfo = posix_getgrgid(filegroup((PATH_site . 'typo3temp/') . $directory));
2886 $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
2887 @rmdir(((PATH_site . 'typo3temp/') . $directory));
2888 $this->assertEquals($resultDirectoryGroup, $swapGroup);
2889 }
2890 }
2891
2892 ///////////////////////////////
2893 // Helper function for filesystem ownership tests
2894 ///////////////////////////////
2895 /**
2896 * Check if test on filesystem group ownership can be done in this environment
2897 * If so, return second group of webserver user
2898 *
2899 * @param string calling method name
2900 * @return mixed FALSE if test cannot be run, string name of the second group of webserver user
2901 */
2902 private function checkGroups($methodName) {
2903 if (TYPO3_OS == 'WIN') {
2904 $this->markTestSkipped($methodName . '() test not available on Windows.');
2905 return FALSE;
2906 }
2907 if (!function_exists('posix_getgroups')) {
2908 $this->markTestSkipped(('Function posix_getgroups() not available, ' . $methodName) . '() tests skipped');
2909 }
2910 $groups = posix_getgroups();
2911 if (count($groups) <= 1) {
2912 $this->markTestSkipped($methodName . '() test cannot be done when the web server user is only member of 1 group.');
2913 return FALSE;
2914 }
2915 $groupInfo = posix_getgrgid($groups[1]);
2916 return $groupInfo['name'];
2917 }
2918
2919 ///////////////////////////////
2920 // Tests concerning mkdir_deep
2921 ///////////////////////////////
2922 /**
2923 * @test
2924 */
2925 public function mkdirDeepCreatesDirectory() {
2926 $directory = 'typo3temp/' . uniqid('test_');
2927 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir_deep(PATH_site, $directory);
2928 $isDirectoryCreated = is_dir(PATH_site . $directory);
2929 rmdir(PATH_site . $directory);
2930 $this->assertTrue($isDirectoryCreated);
2931 }
2932
2933 /**
2934 * @test
2935 */
2936 public function mkdirDeepCreatesSubdirectoriesRecursive() {
2937 $directory = 'typo3temp/' . uniqid('test_');
2938 $subDirectory = $directory . '/foo';