711ceab67a3aa03c1f020bb970d12cecf9048687
[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 // Get override value
1744 $overrideLL = t3lib_div::readLLfile('EXT:lang/locallang_core.xml', 'default');
1745
1746 // Clean up again
1747 unlink($file);
1748
1749 $this->assertNotEquals($overrideLL['default']['buttons.logout'], '');
1750 $this->assertNotEquals($defaultLL['default']['buttons.logout'], $overrideLL['default']['buttons.logout']);
1751 $this->assertEquals($overrideLL['default']['buttons.logout'], 'EXIT');
1752 }
1753
1754
1755 ///////////////////////////////
1756 // Tests concerning _GETset()
1757 ///////////////////////////////
1758
1759 /**
1760 * @test
1761 */
1762 public function getSetWritesArrayToGetSystemVariable() {
1763 $_GET = array();
1764 $GLOBALS['HTTP_GET_VARS'] = array();
1765
1766 $getParameters = array('foo' => 'bar');
1767 t3lib_div::_GETset($getParameters);
1768 $this->assertSame($getParameters, $_GET);
1769 }
1770
1771 /**
1772 * @test
1773 */
1774 public function getSetWritesArrayToGlobalsHttpGetVars() {
1775 $_GET = array();
1776 $GLOBALS['HTTP_GET_VARS'] = array();
1777
1778 $getParameters = array('foo' => 'bar');
1779 t3lib_div::_GETset($getParameters);
1780 $this->assertSame($getParameters, $GLOBALS['HTTP_GET_VARS']);
1781 }
1782
1783 /**
1784 * @test
1785 */
1786 public function getSetForArrayDropsExistingValues() {
1787 $_GET = array();
1788 $GLOBALS['HTTP_GET_VARS'] = array();
1789
1790 t3lib_div::_GETset(array('foo' => 'bar'));
1791
1792 t3lib_div::_GETset(array('oneKey' => 'oneValue'));
1793
1794 $this->assertEquals(
1795 array('oneKey' => 'oneValue'),
1796 $GLOBALS['HTTP_GET_VARS']
1797 );
1798 }
1799
1800 /**
1801 * @test
1802 */
1803 public function getSetAssignsOneValueToOneKey() {
1804 $_GET = array();
1805 $GLOBALS['HTTP_GET_VARS'] = array();
1806
1807 t3lib_div::_GETset('oneValue', 'oneKey');
1808
1809 $this->assertEquals(
1810 'oneValue',
1811 $GLOBALS['HTTP_GET_VARS']['oneKey']
1812 );
1813 }
1814
1815 /**
1816 * @test
1817 */
1818 public function getSetForOneValueDoesNotDropUnrelatedValues() {
1819 $_GET = array();
1820 $GLOBALS['HTTP_GET_VARS'] = array();
1821
1822 t3lib_div::_GETset(array('foo' => 'bar'));
1823 t3lib_div::_GETset('oneValue', 'oneKey');
1824
1825 $this->assertEquals(
1826 array('foo' => 'bar', 'oneKey' => 'oneValue'),
1827 $GLOBALS['HTTP_GET_VARS']
1828 );
1829 }
1830
1831 /**
1832 * @test
1833 */
1834 public function getSetCanAssignsAnArrayToASpecificArrayElement() {
1835 $_GET = array();
1836 $GLOBALS['HTTP_GET_VARS'] = array();
1837
1838 t3lib_div::_GETset(array('childKey' => 'oneValue'), 'parentKey');
1839
1840 $this->assertEquals(
1841 array('parentKey' => array('childKey' => 'oneValue')),
1842 $GLOBALS['HTTP_GET_VARS']
1843 );
1844 }
1845
1846 /**
1847 * @test
1848 */
1849 public function getSetCanAssignAStringValueToASpecificArrayChildElement() {
1850 $_GET = array();
1851 $GLOBALS['HTTP_GET_VARS'] = array();
1852
1853 t3lib_div::_GETset('oneValue', 'parentKey|childKey');
1854
1855 $this->assertEquals(
1856 array('parentKey' => array('childKey' => 'oneValue')),
1857 $GLOBALS['HTTP_GET_VARS']
1858 );
1859 }
1860
1861 /**
1862 * @test
1863 */
1864 public function getSetCanAssignAnArrayToASpecificArrayChildElement() {
1865 $_GET = array();
1866 $GLOBALS['HTTP_GET_VARS'] = array();
1867
1868 t3lib_div::_GETset(
1869 array('key1' => 'value1', 'key2' => 'value2'),
1870 'parentKey|childKey'
1871 );
1872
1873 $this->assertEquals(
1874 array(
1875 'parentKey' => array(
1876 'childKey' => array('key1' => 'value1', 'key2' => 'value2')
1877 )
1878 ),
1879 $GLOBALS['HTTP_GET_VARS']
1880 );
1881 }
1882
1883
1884 ///////////////////////////////
1885 // Tests concerning fixPermissions
1886 ///////////////////////////////
1887
1888 /**
1889 * @test
1890 */
1891 public function fixPermissionsSetsGroup() {
1892 if (TYPO3_OS == 'WIN') {
1893 $this->markTestSkipped('fixPermissionsSetsGroup() tests not available on Windows');
1894 }
1895 if (!function_exists('posix_getegid')) {
1896 $this->markTestSkipped('Function posix_getegid() not available, fixPermissionsSetsGroup() tests skipped');
1897 }
1898 if (posix_getegid() === -1) {
1899 $this->markTestSkipped(
1900 'The fixPermissionsSetsGroup() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.'
1901 );
1902 }
1903
1904 // Create and prepare test file
1905 $filename = PATH_site . 'typo3temp/' . uniqid('test_');
1906 t3lib_div::writeFileToTypo3tempDir($filename, '42');
1907
1908 $currentGroupId = posix_getegid();
1909
1910 // Set target group and run method
1911 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $currentGroupId;
1912 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
1913
1914 clearstatcache();
1915 $resultFileGroup = filegroup($filename);
1916 unlink($filename);
1917
1918 $this->assertEquals($resultFileGroup, $currentGroupId);
1919 }
1920
1921 /**
1922 * @test
1923 */
1924 public function fixPermissionsSetsPermissionsToFile() {
1925 if (TYPO3_OS == 'WIN') {
1926 $this->markTestSkipped('fixPermissions() tests not available on Windows');
1927 }
1928
1929 // Create and prepare test file
1930 $filename = PATH_site . 'typo3temp/' . uniqid('test_');
1931 t3lib_div::writeFileToTypo3tempDir($filename, '42');
1932 chmod($filename, 0742);
1933
1934 // Set target permissions and run method
1935 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
1936 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
1937
1938 // Get actual permissions and clean up
1939 clearstatcache();
1940 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
1941 unlink($filename);
1942
1943 // Test if everything was ok
1944 $this->assertTrue($fixPermissionsResult);
1945 $this->assertEquals($resultFilePermissions, '0660');
1946 }
1947
1948 /**
1949 * @test
1950 */
1951 public function fixPermissionsSetsPermissionsToHiddenFile() {
1952 if (TYPO3_OS == 'WIN') {
1953 $this->markTestSkipped('fixPermissions() tests not available on Windows');
1954 }
1955
1956 // Create and prepare test file
1957 $filename = PATH_site . 'typo3temp/' . uniqid('.test_');
1958 t3lib_div::writeFileToTypo3tempDir($filename, '42');
1959 chmod($filename, 0742);
1960
1961 // Set target permissions and run method
1962 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
1963 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
1964
1965 // Get actual permissions and clean up
1966 clearstatcache();
1967 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
1968 unlink($filename);
1969
1970 // Test if everything was ok
1971 $this->assertTrue($fixPermissionsResult);
1972 $this->assertEquals($resultFilePermissions, '0660');
1973 }
1974
1975 /**
1976 * @test
1977 */
1978 public function fixPermissionsSetsPermissionsToDirectory() {
1979 if (TYPO3_OS == 'WIN') {
1980 $this->markTestSkipped('fixPermissions() tests not available on Windows');
1981 }
1982
1983 // Create and prepare test directory
1984 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
1985 t3lib_div::mkdir($directory);
1986 chmod($directory, 1551);
1987
1988 // Set target permissions and run method
1989 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
1990 $fixPermissionsResult = t3lib_div::fixPermissions($directory);
1991
1992 // Get actual permissions and clean up
1993 clearstatcache();
1994 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
1995 t3lib_div::rmdir($directory);
1996
1997 // Test if everything was ok
1998 $this->assertTrue($fixPermissionsResult);
1999 $this->assertEquals($resultDirectoryPermissions, '0770');
2000 }
2001
2002 /**
2003 * @test
2004 */
2005 public function fixPermissionsSetsPermissionsToDirectoryWithTrailingSlash() {
2006 if (TYPO3_OS == 'WIN') {
2007 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2008 }
2009
2010 // Create and prepare test directory
2011 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2012 t3lib_div::mkdir($directory);
2013 chmod($directory, 1551);
2014
2015 // Set target permissions and run method
2016 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2017 $fixPermissionsResult = t3lib_div::fixPermissions($directory . '/');
2018
2019 // Get actual permissions and clean up
2020 clearstatcache();
2021 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2022 t3lib_div::rmdir($directory);
2023
2024 // Test if everything was ok
2025 $this->assertTrue($fixPermissionsResult);
2026 $this->assertEquals($resultDirectoryPermissions, '0770');
2027 }
2028
2029 /**
2030 * @test
2031 */
2032 public function fixPermissionsSetsPermissionsToHiddenDirectory() {
2033 if (TYPO3_OS == 'WIN') {
2034 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2035 }
2036
2037 // Create and prepare test directory
2038 $directory = PATH_site . 'typo3temp/' . uniqid('.test_');
2039 t3lib_div::mkdir($directory);
2040 chmod($directory, 1551);
2041
2042 // Set target permissions and run method
2043 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2044 $fixPermissionsResult = t3lib_div::fixPermissions($directory);
2045
2046 // Get actual permissions and clean up
2047 clearstatcache();
2048 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2049 t3lib_div::rmdir($directory);
2050
2051 // Test if everything was ok
2052 $this->assertTrue($fixPermissionsResult);
2053 $this->assertEquals($resultDirectoryPermissions, '0770');
2054 }
2055
2056 /**
2057 * @test
2058 */
2059 public function fixPermissionsCorrectlySetsPermissionsRecursive() {
2060 if (TYPO3_OS == 'WIN') {
2061 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2062 }
2063
2064 // Create and prepare test directory and file structure
2065 $baseDirectory = PATH_site . 'typo3temp/' . uniqid('test_');
2066 t3lib_div::mkdir($baseDirectory);
2067 chmod($baseDirectory, 1751);
2068 t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/file', '42');
2069 chmod($baseDirectory . '/file', 0742);
2070 t3lib_div::mkdir($baseDirectory . '/foo');
2071 chmod($baseDirectory . '/foo', 1751);
2072 t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/foo/file', '42');
2073 chmod($baseDirectory . '/foo/file', 0742);
2074 t3lib_div::mkdir($baseDirectory . '/.bar');
2075 chmod($baseDirectory . '/.bar', 1751);
2076 // Use this if writeFileToTypo3tempDir is fixed to create hidden files in subdirectories
2077 // t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/.bar/.file', '42');
2078 // t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/.bar/..file2', '42');
2079 touch($baseDirectory . '/.bar/.file', '42');
2080 chmod($baseDirectory . '/.bar/.file', 0742);
2081 touch($baseDirectory . '/.bar/..file2', '42');
2082 chmod($baseDirectory . '/.bar/..file2', 0742);
2083
2084 // Set target permissions and run method
2085 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2086 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2087 $fixPermissionsResult = t3lib_div::fixPermissions($baseDirectory, TRUE);
2088
2089 // Get actual permissions
2090 clearstatcache();
2091 $resultBaseDirectoryPermissions = substr(decoct(fileperms($baseDirectory)), 1);
2092 $resultBaseFilePermissions = substr(decoct(fileperms($baseDirectory . '/file')), 2);
2093 $resultFooDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/foo')), 1);
2094 $resultFooFilePermissions = substr(decoct(fileperms($baseDirectory . '/foo/file')), 2);
2095 $resultBarDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/.bar')), 1);
2096 $resultBarFilePermissions = substr(decoct(fileperms($baseDirectory . '/.bar/.file')), 2);
2097 $resultBarFile2Permissions = substr(decoct(fileperms($baseDirectory . '/.bar/..file2')), 2);
2098
2099 // Clean up
2100 unlink($baseDirectory . '/file');
2101 unlink($baseDirectory . '/foo/file');
2102 unlink($baseDirectory . '/.bar/.file');
2103 unlink($baseDirectory . '/.bar/..file2');
2104 t3lib_div::rmdir($baseDirectory . '/foo');
2105 t3lib_div::rmdir($baseDirectory . '/.bar');
2106 t3lib_div::rmdir($baseDirectory);
2107
2108 // Test if everything was ok
2109 $this->assertTrue($fixPermissionsResult);
2110 $this->assertEquals($resultBaseDirectoryPermissions, '0770');
2111 $this->assertEquals($resultBaseFilePermissions, '0660');
2112 $this->assertEquals($resultFooDirectoryPermissions, '0770');
2113 $this->assertEquals($resultFooFilePermissions, '0660');
2114 $this->assertEquals($resultBarDirectoryPermissions, '0770');
2115 $this->assertEquals($resultBarFilePermissions, '0660');
2116 $this->assertEquals($resultBarFile2Permissions, '0660');
2117 }
2118
2119 /**
2120 * @test
2121 */
2122 public function fixPermissionsDoesNotSetPermissionsToNotAllowedPath() {
2123 if (TYPO3_OS == 'WIN') {
2124 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2125 }
2126
2127 // Create and prepare test file
2128 $filename = PATH_site . 'typo3temp/../typo3temp/' . uniqid('test_');
2129 touch($filename);
2130 chmod($filename, 0742);
2131
2132 // Set target permissions and run method
2133 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2134 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
2135
2136 // Get actual permissions and clean up
2137 clearstatcache();
2138 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
2139 unlink($filename);
2140
2141 // Test if everything was ok
2142 $this->assertFalse($fixPermissionsResult);
2143 }
2144
2145 /**
2146 * @test
2147 */
2148 public function fixPermissionsSetsPermissionsWithRelativeFileReference() {
2149 if (TYPO3_OS == 'WIN') {
2150 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2151 }
2152
2153 $filename = 'typo3temp/' . uniqid('test_');
2154 t3lib_div::writeFileToTypo3tempDir(PATH_site . $filename, '42');
2155 chmod(PATH_site . $filename, 0742);
2156
2157 // Set target permissions and run method
2158 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2159 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
2160
2161 // Get actual permissions and clean up
2162 clearstatcache();
2163 $resultFilePermissions = substr(decoct(fileperms(PATH_site . $filename)), 2);
2164 unlink(PATH_site . $filename);
2165
2166 // Test if everything was ok
2167 $this->assertTrue($fixPermissionsResult);
2168 $this->assertEquals($resultFilePermissions, '0660');
2169 }
2170
2171
2172 ///////////////////////////////
2173 // Tests concerning mkdir
2174 ///////////////////////////////
2175
2176 /**
2177 * @test
2178 */
2179 public function mkdirCreatesDirectory() {
2180 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2181 $mkdirResult = t3lib_div::mkdir($directory);
2182 clearstatcache();
2183 $directoryCreated = is_dir($directory);
2184 @rmdir($directory);
2185 $this->assertTrue($mkdirResult);
2186 $this->assertTrue($directoryCreated);
2187 }
2188
2189 /**
2190 * @test
2191 */
2192 public function mkdirCreatesHiddenDirectory() {
2193 $directory = PATH_site . 'typo3temp/' . uniqid('.test_');
2194 $mkdirResult = t3lib_div::mkdir($directory);
2195 clearstatcache();
2196 $directoryCreated = is_dir($directory);
2197 @rmdir($directory);
2198 $this->assertTrue($mkdirResult);
2199 $this->assertTrue($directoryCreated);
2200 }
2201
2202 /**
2203 * @test
2204 */
2205 public function mkdirCreatesDirectoryWithTrailingSlash() {
2206 $directory = PATH_site . 'typo3temp/' . uniqid('test_') . '/';
2207 $mkdirResult = t3lib_div::mkdir($directory);
2208 clearstatcache();
2209 $directoryCreated = is_dir($directory);
2210 @rmdir($directory);
2211 $this->assertTrue($mkdirResult);
2212 $this->assertTrue($directoryCreated);
2213 }
2214
2215 /**
2216 * @test
2217 */
2218 public function mkdirSetsPermissionsOfCreatedDirectory() {
2219 if (TYPO3_OS == 'WIN') {
2220 $this->markTestSkipped('mkdirSetsPermissionsOfCreatedDirectory() test not available on Windows');
2221 }
2222
2223 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2224 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2225 t3lib_div::mkdir($directory);
2226 clearstatcache();
2227 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2228 rmdir($directory);
2229 $this->assertEquals($resultDirectoryPermissions, '0770');
2230 }
2231
2232
2233 ///////////////////////////////
2234 // Tests concerning mkdir_deep
2235 ///////////////////////////////
2236
2237 /**
2238 * @test
2239 */
2240 public function mkdirDeepCreatesDirectory() {
2241 $directory = 'typo3temp/' . uniqid('test_');
2242 t3lib_div::mkdir_deep(PATH_site, $directory);
2243 $isDirectoryCreated = is_dir(PATH_site . $directory);
2244 rmdir(PATH_site . $directory);
2245 $this->assertTrue($isDirectoryCreated);
2246 }
2247
2248 /**
2249 * @test
2250 */
2251 public function mkdirDeepCreatesSubdirectoriesRecursive() {
2252 $directory = 'typo3temp/' . uniqid('test_');
2253 $subDirectory = $directory . '/foo';
2254 t3lib_div::mkdir_deep(PATH_site, $subDirectory);
2255 $isDirectoryCreated = is_dir(PATH_site . $subDirectory);
2256 rmdir(PATH_site . $subDirectory);
2257 rmdir(PATH_site . $directory);
2258 $this->assertTrue($isDirectoryCreated);
2259 }
2260
2261 /**
2262 * @test
2263 */
2264 public function mkdirDeepFixesPermissionsOnNewDirectory() {
2265 if (TYPO3_OS == 'WIN') {
2266 $this->markTestSkipped('mkdirDeepFixesPermissionsOnNewDirectory() test not available on Windows.');
2267 }
2268
2269 $directory = uniqid('mkdirdeeptest_');
2270 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0750';
2271 t3lib_div::mkdir_deep(PATH_site . 'typo3temp/', $directory);
2272 clearstatcache();
2273 $resultDirectoryPermissions = substr(decoct(fileperms(PATH_site . 'typo3temp/' . $directory)), -3, 3);
2274 @rmdir(PATH_site . 'typo3temp/' . $directory);
2275 $this->assertEquals($resultDirectoryPermissions, '750');
2276 }
2277
2278 /**
2279 * @test
2280 */
2281 public function mkdirDeepDoesNotChangePermissionsOfExistingSubDirectories() {
2282 if (TYPO3_OS == 'WIN') {
2283 $this->markTestSkipped('mkdirDeepDoesNotChangePermissionsOfExistingSubDirectories() test not available on Windows.');
2284 }
2285
2286 $baseDirectory = PATH_site . 'typo3temp/';
2287 $existingDirectory = uniqid('test_existing_') . '/';
2288 $newSubDirectory = uniqid('test_new_');
2289 @mkdir($baseDirectory . $existingDirectory);
2290 chmod($baseDirectory . $existingDirectory, 0742);
2291 t3lib_div::mkdir_deep($baseDirectory, $existingDirectory . $newSubDirectory);
2292 $resultExistingDirectoryPermissions = substr(decoct(fileperms($baseDirectory . $existingDirectory)), 2);
2293 @rmdir($baseDirectory, $existingDirectory . $newSubDirectory);
2294 @rmdir($baseDirectory, $existingDirectory);
2295 $this->assertEquals($resultExistingDirectoryPermissions, '0742');
2296 }
2297
2298 /**
2299 * @test
2300 */
2301 public function mkdirDeepCreatesDirectoryInVfsStream() {
2302 if (!class_exists('\vfsStreamWrapper')) {
2303 $this->markTestSkipped('mkdirDeepCreatesDirectoryInVfsStream() test not available with this phpunit version.');
2304 }
2305
2306 \vfsStreamWrapper::register();
2307 $baseDirectory = uniqid('test_');
2308 \vfsStreamWrapper::setRoot(new \vfsStreamDirectory($baseDirectory));
2309 t3lib_div::mkdir_deep('vfs://' . $baseDirectory . '/', 'sub');
2310 $this->assertTrue(is_dir('vfs://' . $baseDirectory . '/sub'));
2311 }
2312
2313 /**
2314 * @test
2315 * @expectedException \RuntimeException
2316 */
2317 public function mkdirDeepThrowsExceptionIfDirectoryCreationFails() {
2318 t3lib_div::mkdir_deep('http://localhost');
2319 }
2320
2321 /**
2322 * @test
2323 * @expectedException \InvalidArgumentException
2324 */
2325 public function mkdirDeepThrowsExceptionIfBaseDirectoryIsNotOfTypeString() {
2326 t3lib_div::mkdir_deep(array());
2327 }
2328
2329 /**
2330 * @test
2331 * @expectedException \InvalidArgumentException
2332 */
2333 public function mkdirDeepThrowsExceptionIfDeepDirectoryIsNotOfTypeString() {
2334 t3lib_div::mkdir_deep(PATH_site . 'typo3temp/foo', array());
2335 }
2336
2337
2338 ///////////////////////////////
2339 // Tests concerning unQuoteFilenames
2340 ///////////////////////////////
2341
2342 /**
2343 * Data provider for ImageMagick shell commands
2344 * @see explodeAndUnquoteImageMagickCommands
2345 */
2346 public function imageMagickCommandsDataProvider() {
2347 return array(
2348 // Some theoretical tests first
2349 array(
2350 'aa bb "cc" "dd"',
2351 array('aa', 'bb', '"cc"', '"dd"'),
2352 array('aa', 'bb', 'cc', 'dd'),
2353 ),
2354 array(
2355 'aa bb "cc dd"',
2356 array('aa', 'bb', '"cc dd"'),
2357 array('aa', 'bb', 'cc dd'),
2358 ),
2359 array(
2360 '\'aa bb\' "cc dd"',
2361 array('\'aa bb\'', '"cc dd"'),
2362 array('aa bb', 'cc dd'),
2363 ),
2364 array(
2365 '\'aa bb\' cc "dd"',
2366 array('\'aa bb\'', 'cc', '"dd"'),
2367 array('aa bb', 'cc', 'dd'),
2368 ),
2369 // Now test against some real world examples
2370 array(
2371 '/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"',
2372 array(
2373 '/opt/local/bin/gm.exe',
2374 'convert',
2375 '+profile',
2376 '\'*\'',
2377 '-geometry',
2378 '170x136!',
2379 '-negate',
2380 '"C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
2381 '"C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
2382 ),
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 ),
2395 array(
2396 '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"',
2397 array(
2398 'C:/opt/local/bin/gm.exe',
2399 'convert',
2400 '+profile',
2401 '\'*\'',
2402 '-geometry',
2403 '170x136!',
2404 '-negate',
2405 '"C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
2406 '"C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
2407 ),
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 ),
2420 array(
2421 '/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"',
2422 array(
2423 '/usr/bin/gm',
2424 'convert',
2425 '+profile',
2426 '\'*\'',
2427 '-geometry',
2428 '170x136!',
2429 '-negate',
2430 '"/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
2431 '"/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
2432 ),
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 ),
2445 array(
2446 '/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"',
2447 array(
2448 '/usr/bin/gm',
2449 'convert',
2450 '+profile',
2451 '\'*\'',
2452 '-geometry',
2453 '170x136!',
2454 '-negate',
2455 '"/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
2456 '"/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
2457 ),
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 ),
2470 array(
2471 '/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\'',
2472 array(
2473 '/usr/bin/gm',
2474 'convert',
2475 '+profile',
2476 '\'*\'',
2477 '-geometry',
2478 '170x136!',
2479 '-negate',
2480 '\'/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]\'',
2481 '\'/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif\''
2482 ),
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 ),
2495 );
2496 }
2497
2498 /**
2499 * Tests if the commands are exploded and unquoted correctly
2500 *
2501 * @dataProvider imageMagickCommandsDataProvider
2502 * @test
2503 */
2504 public function explodeAndUnquoteImageMagickCommands($source, $expectedQuoted, $expectedUnquoted) {
2505 $actualQuoted = t3lib_div::unQuoteFilenames($source);
2506 $acutalUnquoted = t3lib_div::unQuoteFilenames($source, TRUE);
2507
2508 $this->assertEquals($expectedQuoted, $actualQuoted, 'The exploded command does not match the expected');
2509 $this->assertEquals($expectedUnquoted, $acutalUnquoted, 'The exploded and unquoted command does not match the expected');
2510 }
2511
2512
2513 ///////////////////////////////
2514 // Tests concerning split_fileref
2515 ///////////////////////////////
2516
2517 /**
2518 * @test
2519 */
2520 public function splitFileRefReturnsFileTypeNotForFolders(){
2521 $directoryName = uniqid('test_') . '.com';
2522 $directoryPath = PATH_site . 'typo3temp/';
2523 $directory = $directoryPath . $directoryName;
2524 mkdir($directory, octdec($GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask']));
2525
2526 $fileInfo = t3lib_div::split_fileref($directory);
2527
2528 $directoryCreated = is_dir($directory);
2529 rmdir($directory);
2530
2531 $this->assertTrue($directoryCreated);
2532 $this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $fileInfo);
2533 $this->assertEquals($directoryPath, $fileInfo['path']);
2534 $this->assertEquals($directoryName, $fileInfo['file']);
2535 $this->assertEquals($directoryName, $fileInfo['filebody']);
2536 $this->assertEquals('', $fileInfo['fileext']);
2537 $this->assertArrayNotHasKey('realFileext', $fileInfo);
2538 }
2539
2540 /**
2541 * @test
2542 */
2543 public function splitFileRefReturnsFileTypeForFilesWithoutPathSite() {
2544 $testFile = 'fileadmin/media/someFile.png';
2545
2546 $fileInfo = t3lib_div::split_fileref($testFile);
2547 $this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $fileInfo);
2548 $this->assertEquals('fileadmin/media/', $fileInfo['path']);
2549 $this->assertEquals('someFile.png', $fileInfo['file']);
2550 $this->assertEquals('someFile', $fileInfo['filebody']);
2551 $this->assertEquals('png', $fileInfo['fileext']);
2552 }
2553
2554
2555 /////////////////////////////
2556 // Tests concerning dirname
2557 /////////////////////////////
2558
2559 /**
2560 * @see dirnameWithDataProvider
2561 *
2562 * @return array<array>
2563 */
2564 public function dirnameDataProvider() {
2565 return array(
2566 'absolute path with multiple part and file' => array('/dir1/dir2/script.php', '/dir1/dir2'),
2567 'absolute path with one part' => array('/dir1/', '/dir1'),
2568 'absolute path to file without extension' => array('/dir1/something', '/dir1'),
2569 'relative path with one part and file' => array('dir1/script.php', 'dir1'),
2570 'relative one-character path with one part and file' => array('d/script.php', 'd'),
2571 'absolute zero-part path with file' => array('/script.php', ''),
2572 'empty string' => array('', ''),
2573 );
2574 }
2575
2576 /**
2577 * @test
2578 *
2579 * @dataProvider dirnameDataProvider
2580 *
2581 * @param string $input the input for dirname
2582 * @param string $expectedValue the expected return value expected from dirname
2583 */
2584 public function dirnameWithDataProvider($input, $expectedValue) {
2585 $this->assertEquals(
2586 $expectedValue,
2587 t3lib_div::dirname($input)
2588 );
2589 }
2590
2591
2592 /////////////////////////////////////
2593 // Tests concerning resolveBackPath
2594 /////////////////////////////////////
2595
2596 /**
2597 * @see resolveBackPathWithDataProvider
2598 *
2599 * @return array<array>
2600 */
2601 public function resolveBackPathDataProvider() {
2602 return array(
2603 'empty path' => array('', ''),
2604 'this directory' => array('./', './'),
2605 'relative directory without ..' => array('dir1/dir2/dir3/', 'dir1/dir2/dir3/'),
2606 'relative path without ..' => array('dir1/dir2/script.php', 'dir1/dir2/script.php'),
2607 'absolute directory without ..' => array('/dir1/dir2/dir3/', '/dir1/dir2/dir3/'),
2608 'absolute path without ..' => array('/dir1/dir2/script.php', '/dir1/dir2/script.php'),
2609 'only one directory upwards without trailing slash' => array('..', '..'),
2610 'only one directory upwards with trailing slash' => array('../', '../'),
2611 'one level with trailing ..' => array('dir1/..', ''),
2612 'one level with trailing ../' => array('dir1/../', ''),
2613 'two levels with trailing ..' => array('dir1/dir2/..', 'dir1'),
2614 'two levels with trailing ../' => array('dir1/dir2/../', 'dir1/'),
2615 'leading ../ without trailing /' => array('../dir1', '../dir1'),
2616 'leading ../ with trailing /' => array('../dir1/', '../dir1/'),
2617 'leading ../ and inside path' => array('../dir1/dir2/../dir3/', '../dir1/dir3/'),
2618 'one times ../ in relative directory' => array('dir1/../dir2/', 'dir2/'),
2619 'one times ../ in absolute directory' => array('/dir1/../dir2/', '/dir2/'),
2620 'one times ../ in relative path' => array('dir1/../dir2/script.php', 'dir2/script.php'),
2621 'one times ../ in absolute path' => array('/dir1/../dir2/script.php', '/dir2/script.php'),
2622 'consecutive ../' => array('dir1/dir2/dir3/../../../dir4', 'dir4'),
2623 'distrubuted ../ with trailing /' => array('dir1/../dir2/dir3/../', 'dir2/'),
2624 'distributed ../ without trailing /' => array('dir1/../dir2/dir3/..', 'dir2'),
2625 'multiple distributed and consecutive ../ together' => array('dir1/dir2/dir3/dir4/../../dir5/dir6/dir7/../dir8/', 'dir1/dir2/dir5/dir6/dir8/'),
2626 'multiple distributed and consecutive ../ together' => array('dir1/dir2/dir3/dir4/../../dir5/dir6/dir7/../dir8/', 'dir1/dir2/dir5/dir6/dir8/'),
2627 'dirname with leading ..' => array('dir1/..dir2/dir3/', 'dir1/..dir2/dir3/'),
2628 'dirname with trailing ..' => array('dir1/dir2../dir3/', 'dir1/dir2../dir3/'),
2629 'more times upwards than downwards in directory' => array('dir1/../../', '../'),
2630 'more times upwards than downwards in path' => array('dir1/../../script.php', '../script.php'),
2631 );
2632 }
2633
2634 /**
2635 * @test
2636 *
2637 * @dataProvider resolveBackPathDataProvider
2638 *
2639 * @param string $input the input for resolveBackPath
2640 * @param $expectedValue the expected return value from resolveBackPath
2641 */
2642 public function resolveBackPathWithDataProvider($input, $expectedValue) {
2643 $this->assertEquals(
2644 $expectedValue,
2645 t3lib_div::resolveBackPath($input)
2646 );
2647 }
2648
2649
2650 /////////////////////////////////////////////////////////////////////////////////////
2651 // Tests concerning makeInstance, setSingletonInstance, addInstance, purgeInstances
2652 /////////////////////////////////////////////////////////////////////////////////////
2653
2654 /**
2655 * @test
2656 *
2657 * @expectedException InvalidArgumentException
2658 */
2659 public function makeInstanceWithEmptyClassNameThrowsException() {
2660 t3lib_div::makeInstance('');
2661 }
2662
2663 /**
2664 * @test
2665 */
2666 public function makeInstanceReturnsClassInstance() {
2667 $className = get_class($this->getMock('foo'));
2668
2669 $this->assertTrue(
2670 t3lib_div::makeInstance($className) instanceof $className
2671 );
2672 }
2673
2674 /**
2675 * @test
2676 */
2677 public function makeInstancePassesParametersToConstructor() {
2678 $className = 'testingClass' . uniqid();
2679 if (!class_exists($className, FALSE)) {
2680 eval(
2681 'class ' . $className . ' {' .
2682 ' public $constructorParameter1;' .
2683 ' public $constructorParameter2;' .
2684 ' public function __construct($parameter1, $parameter2) {' .
2685 ' $this->constructorParameter1 = $parameter1;' .
2686 ' $this->constructorParameter2 = $parameter2;' .
2687 ' }' .
2688 '}'
2689 );
2690 }
2691
2692 $instance = t3lib_div::makeInstance($className, 'one parameter', 'another parameter');
2693
2694 $this->assertEquals(
2695 'one parameter',
2696 $instance->constructorParameter1,
2697 'The first constructor parameter has not been set.'
2698 );
2699 $this->assertEquals(
2700 'another parameter',
2701 $instance->constructorParameter2,
2702 'The second constructor parameter has not been set.'
2703 );
2704 }
2705
2706 /**
2707 * @test
2708 */
2709 public function makeInstanceCalledTwoTimesForNonSingletonClassReturnsDifferentInstances() {
2710 $className = get_class($this->getMock('foo'));
2711
2712 $this->assertNotSame(
2713 t3lib_div::makeInstance($className),
2714 t3lib_div::makeInstance($className)
2715 );
2716 }
2717
2718 /**
2719 * @test
2720 */
2721 public function makeInstanceCalledTwoTimesForSingletonClassReturnsSameInstance() {
2722 $className = get_class($this->getMock('t3lib_Singleton'));
2723
2724 $this->assertSame(
2725 t3lib_div::makeInstance($className),
2726 t3lib_div::makeInstance($className)
2727 );
2728 }
2729
2730 /**
2731 * @test
2732 */
2733 public function makeInstanceCalledTwoTimesForSingletonClassWithPurgeInstancesInbetweenReturnsDifferentInstances() {
2734 $className = get_class($this->getMock('t3lib_Singleton'));
2735
2736 $instance = t3lib_div::makeInstance($className);
2737 t3lib_div::purgeInstances();
2738
2739 $this->assertNotSame(
2740 $instance,
2741 t3lib_div::makeInstance($className)
2742 );
2743 }
2744
2745 /**
2746 * @test
2747 * @expectedException InvalidArgumentException
2748 */
2749 public function setSingletonInstanceForEmptyClassNameThrowsException() {
2750 $instance = $this->getMock('t3lib_Singleton');
2751
2752 t3lib_div::setSingletonInstance('', $instance);
2753 }
2754
2755 /**
2756 * @test
2757 * @expectedException InvalidArgumentException
2758 */
2759 public function setSingletonInstanceForClassThatIsNoSubclassOfProvidedClassThrowsException() {
2760 $instance = $this->getMock('t3lib_Singleton', array('foo'));
2761 $singletonClassName = get_class($this->getMock('t3lib_Singleton'));
2762
2763 t3lib_div::setSingletonInstance($singletonClassName, $instance);
2764 }
2765
2766 /**
2767 * @test
2768 */
2769 public function setSingletonInstanceMakesMakeInstanceReturnThatInstance() {
2770 $instance = $this->getMock('t3lib_Singleton');
2771 $singletonClassName = get_class($instance);
2772
2773 t3lib_div::setSingletonInstance($singletonClassName, $instance);
2774
2775 $this->assertSame(
2776 $instance,
2777 t3lib_div::makeInstance($singletonClassName)
2778 );
2779 }
2780
2781 /**
2782 * @test
2783 */
2784 public function setSingletonInstanceCalledTwoTimesMakesMakeInstanceReturnLastSetInstance() {
2785 $instance1 = $this->getMock('t3lib_Singleton');
2786 $singletonClassName = get_class($instance1);
2787 $instance2 = new $singletonClassName();
2788
2789 t3lib_div::setSingletonInstance($singletonClassName, $instance1);
2790 t3lib_div::setSingletonInstance($singletonClassName, $instance2);
2791
2792 $this->assertSame(
2793 $instance2,
2794 t3lib_div::makeInstance($singletonClassName)
2795 );
2796 }
2797
2798 /**
2799 * @test
2800 * @expectedException InvalidArgumentException
2801 */
2802 public function addInstanceForEmptyClassNameThrowsException() {
2803 $instance = $this->getMock('foo');
2804
2805 t3lib_div::addInstance('', $instance);
2806 }
2807
2808 /**
2809 * @test
2810 * @expectedException InvalidArgumentException
2811 */
2812 public function addInstanceForClassThatIsNoSubclassOfProvidedClassThrowsException() {
2813 $instance = $this->getMock('foo', array('bar'));
2814 $singletonClassName = get_class($this->getMock('foo'));
2815
2816 t3lib_div::addInstance($singletonClassName, $instance);
2817 }
2818
2819 /**
2820 * @test
2821 * @expectedException InvalidArgumentException
2822 */
2823 public function addInstanceWithSingletonInstanceThrowsException() {
2824 $instance = $this->getMock('t3lib_Singleton');
2825
2826 t3lib_div::addInstance(get_class($instance), $instance);
2827 }
2828
2829 /**
2830 * @test
2831 */
2832 public function addInstanceMakesMakeInstanceReturnThatInstance() {
2833 $instance = $this->getMock('foo');
2834 $className = get_class($instance);
2835
2836 t3lib_div::addInstance($className, $instance);
2837
2838 $this->assertSame(
2839 $instance,
2840 t3lib_div::makeInstance($className)
2841 );
2842 }
2843
2844 /**
2845 * @test
2846 */
2847 public function makeInstanceCalledTwoTimesAfterAddInstanceReturnTwoDifferentInstances() {
2848 $instance = $this->getMock('foo');
2849 $className = get_class($instance);
2850
2851 t3lib_div::addInstance($className, $instance);
2852
2853 $this->assertNotSame(
2854 t3lib_div::makeInstance($className),
2855 t3lib_div::makeInstance($className)
2856 );
2857 }
2858
2859 /**
2860 * @test
2861 */
2862 public function addInstanceCalledTwoTimesMakesMakeInstanceReturnBothInstancesInAddingOrder() {
2863 $instance1 = $this->getMock('foo');
2864 $className = get_class($instance1);
2865 t3lib_div::addInstance($className, $instance1);
2866
2867 $instance2 = new $className();
2868 t3lib_div::addInstance($className, $instance2);
2869
2870 $this->assertSame(
2871 $instance1,
2872 t3lib_div::makeInstance($className),
2873 'The first returned instance does not match the first added instance.'
2874 );
2875 $this->assertSame(
2876 $instance2,
2877 t3lib_div::makeInstance($className),
2878 'The second returned instance does not match the second added instance.'
2879 );
2880 }
2881
2882 /**
2883 * @test
2884 */
2885 public function purgeInstancesDropsAddedInstance() {
2886 $instance = $this->getMock('foo');
2887 $className = get_class($instance);
2888
2889 t3lib_div::addInstance($className, $instance);
2890 t3lib_div::purgeInstances();
2891
2892 $this->assertNotSame(
2893 $instance,
2894 t3lib_div::makeInstance($className)
2895 );
2896 }
2897
2898 /**
2899 * Data provider for validPathStrDetectsInvalidCharacters.
2900 *
2901 * @return array
2902 */
2903 public function validPathStrInvalidCharactersDataProvider() {
2904 return array(
2905 'double slash in path' => array('path//path'),
2906 'backslash in path' => array('path\\path'),
2907 'directory up in path' => array('path/../path'),
2908 'directory up at the beginning' => array('../path'),
2909 'NUL character in path' => array("path\x00path"),
2910 'BS character in path' => array("path\x08path"),
2911 );
2912 }
2913
2914 /**
2915 * Tests whether invalid characters are detected.
2916 *
2917 * @param string $path
2918 * @dataProvider validPathStrInvalidCharactersDataProvider
2919 * @test
2920 */
2921 public function validPathStrDetectsInvalidCharacters($path) {
2922 $this->assertNull(t3lib_div::validPathStr($path));
2923 }
2924
2925 /**
2926 * Tests whether verifyFilenameAgainstDenyPattern detects the NULL character.
2927 *
2928 * @test
2929 */
2930 public function verifyFilenameAgainstDenyPatternDetectsNullCharacter() {
2931 $this->assertFalse(t3lib_div::verifyFilenameAgainstDenyPattern("image\x00.gif"));
2932 }
2933
2934
2935 /////////////////////////////////////////////////////////////////////////////////////
2936 // Tests concerning sysLog
2937 /////////////////////////////////////////////////////////////////////////////////////
2938
2939 /**
2940 * @test
2941 */
2942 public function syslogFixesPermissionsOnFileIfUsingFileLogging() {
2943 if (TYPO3_OS == 'WIN') {
2944 $this->markTestSkipped('syslogFixesPermissionsOnFileIfUsingFileLogging() test not available on Windows.');
2945 }
2946
2947 // Fake all required settings
2948 $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLogLevel'] = 0;
2949 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogInit'] = TRUE;
2950 unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog']);
2951 $testLogFilename = PATH_site . 'typo3temp/' . uniqid('test_') . '.txt';
2952 $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLog'] = 'file,' . $testLogFilename . ',0';
2953 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
2954
2955 // Call method, get actual permissions and clean up
2956 t3lib_div::syslog('testLog', 'test', 1);
2957 clearstatcache();
2958 $resultFilePermissions = substr(decoct(fileperms($testLogFilename)), 2);
2959 t3lib_div::unlink_tempfile($testLogFilename);
2960
2961 $this->assertEquals($resultFilePermissions, '0777');
2962 }
2963
2964 /**
2965 * @test
2966 */
2967 public function deprecationLogFixesPermissionsOnLogFile() {
2968 if (TYPO3_OS == 'WIN') {
2969 $this->markTestSkipped('deprecationLogFixesPermissionsOnLogFile() test not available on Windows.');
2970 }
2971
2972 // Fake all required settings and get an unique logfilename
2973 $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = uniqid('test_');
2974 $deprecationLogFilename = t3lib_div::getDeprecationLogFileName();
2975 $GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog'] = TRUE;
2976 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
2977
2978 // Call method, get actual permissions and clean up
2979 t3lib_div::deprecationLog('foo');
2980 clearstatcache();
2981 $resultFilePermissions = substr(decoct(fileperms($deprecationLogFilename)), 2);
2982 @unlink($deprecationLogFilename);
2983
2984 $this->assertEquals($resultFilePermissions, '0777');
2985 }
2986
2987 ///////////////////////////////////////////////////
2988 // Tests concerning hasValidClassPrefix
2989 ///////////////////////////////////////////////////
2990
2991 /**
2992 * @return array
2993 */
2994 public function validClassPrefixDataProvider() {
2995 return array(
2996 array('tx_foo'),
2997 array('tx_foo_bar'),
2998 array('Tx_foo'),
2999 array($GLOBALS['TYPO3_CONF_VARS']['FE']['userFuncClassPrefix'] . 'foo'),
3000 );
3001 }
3002
3003 /**
3004 * @test
3005 * @dataProvider validClassPrefixDataProvider
3006 * @param string $className Class name to test
3007 */
3008 public function hasValidClassPrefixAcceptsValidPrefixes($className) {
3009 $this->assertTrue(
3010 t3lib_div::hasValidClassPrefix($className)
3011 );
3012 }
3013
3014 /**
3015 * @return array
3016 */
3017 public function invalidClassPrefixDataProvider() {
3018 return array(
3019 array(''),
3020 array('ab_c'),
3021 array('txfoo'),
3022 array('Txfoo'),
3023 array('userfoo'),
3024 array('User_foo'),
3025 );
3026 }
3027
3028 /**
3029 * @test
3030 * @dataProvider invalidClassPrefixDataProvider
3031 * @param string $className Class name to test
3032 */
3033 public function hasValidClassPrefixRefusesInvalidPrefixes($className) {
3034 $this->assertFalse(
3035 t3lib_div::hasValidClassPrefix($className)
3036 );
3037 }
3038
3039 /**
3040 * @test
3041 */
3042 public function hasValidClassPrefixAcceptsAdditionalPrefixes() {
3043 $this->assertTrue(
3044 t3lib_div::hasValidClassPrefix('customPrefix_foo', array('customPrefix_'))
3045 );
3046 }
3047 }
3048 ?>