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