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