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