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