8e1111c96bb79f12a964297b3eb7bc18f2aca94c
[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 intInRange
688 //////////////////////////////////
689 /**
690 * Data provider for intInRangeForcesIntegerIntoBoundaries
691 *
692 * @return array expected values, arithmetic expression
693 */
694 public function intInRangeForcesIntegerIntoDefaultBoundariesDataProvider() {
695 return array(
696 'negativeValue' => array(0, -10),
697 'normalValue' => array(30, 30),
698 'veryHighValue' => array(2000000000, 3000000001),
699 'zeroValue' => array(0, 0),
700 'anotherNormalValue' => array(12309, 12309)
701 );
702 }
703
704 /**
705 * @test
706 * @dataProvider intInRangeForcesIntegerIntoDefaultBoundariesDataProvider
707 */
708 public function intInRangeForcesIntegerIntoDefaultBoundaries($expected, $value) {
709 $this->assertEquals($expected, t3lib_div::intInRange($value, 0));
710 }
711
712 /**
713 * @test
714 */
715 public function intInRangeSetsDefaultValueIfZeroValueIsGiven() {
716 $this->assertEquals(42, t3lib_div::intInRange('', 0, 2000000000, 42));
717 }
718
719 //////////////////////////////////
720 // Tests concerning int_from_ver
721 //////////////////////////////////
722 /**
723 * Data Provider for intFromVerConvertsVersionNumbersToIntegersDataProvider
724 *
725 * return array
726 */
727 public function intFromVerConvertsVersionNumbersToIntegersDataProvider() {
728 return array(
729 array('4003003', '4.3.3'),
730 array('4012003', '4.12.3'),
731 array('5000000', '5.0.0'),
732 array('3008001', '3.8.1'),
733 array('1012', '0.1.12')
734 );
735 }
736
737 /**
738 * @test
739 * @dataProvider intFromVerConvertsVersionNumbersToIntegersDataProvider
740 */
741 public function intFromVerConvertsVersionNumbersToIntegers($expected, $version) {
742 $this->assertEquals($expected, t3lib_div::int_from_ver($version));
743 }
744
745 //////////////////////////////////
746 // Tests concerning revExplode
747 //////////////////////////////////
748
749 /**
750 * @test
751 */
752 public function revExplodeExplodesString() {
753 $testString = 'my:words:here';
754 $expectedArray = array('my:words', 'here');
755 $actualArray = t3lib_div::revExplode(':', $testString, 2);
756
757 $this->assertEquals($expectedArray, $actualArray);
758 }
759
760
761 //////////////////////////////////
762 // Tests concerning trimExplode
763 //////////////////////////////////
764
765 /**
766 * @test
767 */
768 public function checkTrimExplodeTrimsSpacesAtElementStartAndEnd() {
769 $testString = ' a , b , c ,d ,, e,f,';
770 $expectedArray = array('a', 'b', 'c', 'd', '', 'e', 'f', '');
771 $actualArray = t3lib_div::trimExplode(',', $testString);
772
773 $this->assertEquals($expectedArray, $actualArray);
774 }
775
776 /**
777 * @test
778 */
779 public function checkTrimExplodeRemovesNewLines() {
780 $testString = ' a , b , ' . LF . ' ,d ,, e,f,';
781 $expectedArray = array('a', 'b', 'd', 'e', 'f');
782 $actualArray = t3lib_div::trimExplode(',', $testString, TRUE);
783
784 $this->assertEquals($expectedArray, $actualArray);
785 }
786
787 /**
788 * @test
789 */
790 public function checkTrimExplodeRemovesEmptyElements() {
791 $testString = 'a , b , c , ,d ,, ,e,f,';
792 $expectedArray = array('a', 'b', 'c', 'd', 'e', 'f');
793 $actualArray = t3lib_div::trimExplode(',', $testString, TRUE);
794
795 $this->assertEquals($expectedArray, $actualArray);
796 }
797
798 /**
799 * @test
800 */
801 public function checkTrimExplodeKeepsRemainingResultsWithEmptyItemsAfterReachingLimitWithPositiveParameter() {
802 $testString = ' a , b , c , , d,, ,e ';
803 $expectedArray = array('a', 'b', 'c,,d,,,e');
804 // Limiting returns the rest of the string as the last element
805 $actualArray = t3lib_div::trimExplode(',', $testString, FALSE, 3);
806
807 $this->assertEquals($expectedArray, $actualArray);
808 }
809
810 /**
811 * @test
812 */
813 public function checkTrimExplodeKeepsRemainingResultsWithoutEmptyItemsAfterReachingLimitWithPositiveParameter() {
814 $testString = ' a , b , c , , d,, ,e ';
815 $expectedArray = array('a', 'b', 'c,d,e');
816 // Limiting returns the rest of the string as the last element
817 $actualArray = t3lib_div::trimExplode(',', $testString, TRUE, 3);
818
819 $this->assertEquals($expectedArray, $actualArray);
820 }
821
822 /**
823 * @test
824 */
825 public function checkTrimExplodeKeepsRamainingResultsWithEmptyItemsAfterReachingLimitWithNegativeParameter() {
826 $testString = ' a , b , c , d, ,e, f , , ';
827 $expectedArray = array('a', 'b', 'c', 'd', '', 'e');
828 // limiting returns the rest of the string as the last element
829 $actualArray = t3lib_div::trimExplode(',', $testString, FALSE, -3);
830
831 $this->assertEquals($expectedArray, $actualArray);
832 }
833
834 /**
835 * @test
836 */
837 public function checkTrimExplodeKeepsRamainingResultsWithoutEmptyItemsAfterReachingLimitWithNegativeParameter() {
838 $testString = ' a , b , c , d, ,e, f , , ';
839 $expectedArray = array('a', 'b', 'c');
840 // Limiting returns the rest of the string as the last element
841 $actualArray = t3lib_div::trimExplode(',', $testString, TRUE, -3);
842
843 $this->assertEquals($expectedArray, $actualArray);
844 }
845
846 /**
847 * @test
848 */
849 public function checkTrimExplodeReturnsExactResultsWithoutReachingLimitWithPositiveParameter() {
850 $testString = ' a , b , , c , , , ';
851 $expectedArray = array('a', 'b', 'c');
852 // Limiting returns the rest of the string as the last element
853 $actualArray = t3lib_div::trimExplode(',', $testString, TRUE, 4);
854
855 $this->assertEquals($expectedArray, $actualArray);
856 }
857
858 /**
859 * @test
860 */
861 public function checkTrimExplodeKeepsZeroAsString() {
862 $testString = 'a , b , c , ,d ,, ,e,f, 0 ,';
863 $expectedArray = array('a', 'b', 'c', 'd', 'e', 'f', '0');
864 $actualArray = t3lib_div::trimExplode(',', $testString, TRUE);
865
866 $this->assertEquals($expectedArray, $actualArray);
867 }
868
869
870 //////////////////////////////////
871 // Tests concerning removeArrayEntryByValue
872 //////////////////////////////////
873
874 /**
875 * @test
876 */
877 public function checkRemoveArrayEntryByValueRemovesEntriesFromOneDimensionalArray() {
878 $inputArray = array(
879 '0' => 'test1',
880 '1' => 'test2',
881 '2' => 'test3',
882 '3' => 'test2',
883 );
884 $compareValue = 'test2';
885 $expectedResult = array(
886 '0' => 'test1',
887 '2' => 'test3',
888 );
889 $actualResult = t3lib_div::removeArrayEntryByValue($inputArray, $compareValue);
890 $this->assertEquals($expectedResult, $actualResult);
891 }
892
893 /**
894 * @test
895 */
896 public function checkRemoveArrayEntryByValueRemovesEntriesFromMultiDimensionalArray() {
897 $inputArray = array(
898 '0' => 'foo',
899 '1' => array(
900 '10' => 'bar',
901 ),
902 '2' => 'bar',
903 );
904 $compareValue = 'bar';
905 $expectedResult = array(
906 '0' => 'foo',
907 '1' => array(),
908 );
909 $actualResult = t3lib_div::removeArrayEntryByValue($inputArray, $compareValue);
910 $this->assertEquals($expectedResult, $actualResult);
911 }
912
913 /**
914 * @test
915 */
916 public function checkRemoveArrayEntryByValueRemovesEntryWithEmptyString() {
917 $inputArray = array(
918 '0' => 'foo',
919 '1' => '',
920 '2' => 'bar',
921 );
922 $compareValue = '';
923 $expectedResult = array(
924 '0' => 'foo',
925 '2' => 'bar',
926 );
927 $actualResult = t3lib_div::removeArrayEntryByValue($inputArray, $compareValue);
928 $this->assertEquals($expectedResult, $actualResult);
929 }
930
931 //////////////////////////////////
932 // Tests concerning getBytesFromSizeMeasurement
933 //////////////////////////////////
934
935 /**
936 * Data provider for getBytesFromSizeMeasurement
937 *
938 * @return array expected value, input string
939 */
940 public function getBytesFromSizeMeasurementDataProvider() {
941 return array(
942 '100 kilo Bytes' => array('102400', '100k'),
943 '100 mega Bytes' => array('104857600', '100m'),
944 '100 giga Bytes' => array('107374182400', '100g'),
945 );
946 }
947
948 /**
949 * @test
950 * @dataProvider getBytesFromSizeMeasurementDataProvider
951 */
952 public function getBytesFromSizeMeasurementCalculatesCorrectByteValue($expected, $byteString) {
953 $this->assertEquals($expected, t3lib_div::getBytesFromSizeMeasurement($byteString));
954 }
955
956
957 //////////////////////////////////
958 // Tests concerning getIndpEnv
959 //////////////////////////////////
960
961 /**
962 * @test
963 */
964 public function getIndpEnvTypo3SitePathReturnNonEmptyString() {
965 $this->assertTrue(strlen(t3lib_div::getIndpEnv('TYPO3_SITE_PATH')) >= 1);
966 }
967
968 /**
969 * @test
970 */
971 public function getIndpEnvTypo3SitePathReturnsStringStartingWithSlash() {
972 $result = t3lib_div::getIndpEnv('TYPO3_SITE_PATH');
973 $this->assertEquals('/', $result[0]);
974 }
975
976 /**
977 * @test
978 */
979 public function getIndpEnvTypo3SitePathReturnsStringEndingWithSlash() {
980 $result = t3lib_div::getIndpEnv('TYPO3_SITE_PATH');
981 $this->assertEquals('/', $result[strlen($result) - 1]);
982 }
983
984 /**
985 * @return array
986 */
987 public static function hostnameAndPortDataProvider() {
988 return array(
989 'localhost ipv4 without port' => array('127.0.0.1', '127.0.0.1', ''),
990 'localhost ipv4 with port' => array('127.0.0.1:81', '127.0.0.1', '81'),
991 'localhost ipv6 without port' => array('[::1]', '[::1]', ''),
992 'localhost ipv6 with port' => array('[::1]:81', '[::1]', '81'),
993 'ipv6 without port' => array('[2001:DB8::1]', '[2001:DB8::1]', ''),
994 'ipv6 with port' => array('[2001:DB8::1]:81', '[2001:DB8::1]', '81'),
995 'hostname without port' => array('lolli.did.this', 'lolli.did.this', ''),
996 'hostname with port' => array('lolli.did.this:42', 'lolli.did.this', '42'),
997 );
998 }
999
1000 /**
1001 * @test
1002 * @dataProvider hostnameAndPortDataProvider
1003 */
1004 public function getIndpEnvTypo3HostOnlyParsesHostnamesAndIpAdresses($httpHost, $expectedIp) {
1005 $_SERVER['HTTP_HOST'] = $httpHost;
1006 $this->assertEquals($expectedIp, t3lib_div::getIndpEnv('TYPO3_HOST_ONLY'));
1007 }
1008
1009 /**
1010 * @test
1011 * @dataProvider hostnameAndPortDataProvider
1012 */
1013 public function getIndpEnvTypo3PortParsesHostnamesAndIpAdresses($httpHost, $dummy, $expectedPort) {
1014 $_SERVER['HTTP_HOST'] = $httpHost;
1015 $this->assertEquals($expectedPort, t3lib_div::getIndpEnv('TYPO3_PORT'));
1016 }
1017
1018
1019 //////////////////////////////////
1020 // Tests concerning underscoredToUpperCamelCase
1021 //////////////////////////////////
1022
1023 /**
1024 * Data provider for underscoredToUpperCamelCase
1025 *
1026 * @return array expected, input string
1027 */
1028 public function underscoredToUpperCamelCaseDataProvider() {
1029 return array(
1030 'single word' => array('Blogexample', 'blogexample'),
1031 'multiple words' => array('BlogExample', 'blog_example'),
1032 );
1033 }
1034
1035 /**
1036 * @test
1037 * @dataProvider underscoredToUpperCamelCaseDataProvider
1038 */
1039 public function underscoredToUpperCamelCase($expected, $inputString) {
1040 $this->assertEquals($expected, t3lib_div::underscoredToUpperCamelCase($inputString));
1041 }
1042
1043
1044 //////////////////////////////////
1045 // Tests concerning underscoredToLowerCamelCase
1046 //////////////////////////////////
1047
1048 /**
1049 * Data provider for underscoredToLowerCamelCase
1050 *
1051 * @return array expected, input string
1052 */
1053 public function underscoredToLowerCamelCaseDataProvider() {
1054 return array(
1055 'single word' => array('minimalvalue', 'minimalvalue'),
1056 'multiple words' => array('minimalValue', 'minimal_value'),
1057 );
1058 }
1059
1060 /**
1061 * @test
1062 * @dataProvider underscoredToLowerCamelCaseDataProvider
1063 */
1064 public function underscoredToLowerCamelCase($expected, $inputString) {
1065 $this->assertEquals($expected, t3lib_div::underscoredToLowerCamelCase($inputString));
1066 }
1067
1068 //////////////////////////////////
1069 // Tests concerning camelCaseToLowerCaseUnderscored
1070 //////////////////////////////////
1071
1072 /**
1073 * Data provider for camelCaseToLowerCaseUnderscored
1074 *
1075 * @return array expected, input string
1076 */
1077 public function camelCaseToLowerCaseUnderscoredDataProvider() {
1078 return array(
1079 'single word' => array('blogexample', 'blogexample'),
1080 'single word starting upper case' => array('blogexample', 'Blogexample'),
1081 'two words starting lower case' => array('minimal_value', 'minimalValue'),
1082 'two words starting upper case' => array('blog_example', 'BlogExample'),
1083 );
1084 }
1085
1086 /**
1087 * @test
1088 * @dataProvider camelCaseToLowerCaseUnderscoredDataProvider
1089 */
1090 public function camelCaseToLowerCaseUnderscored($expected, $inputString) {
1091 $this->assertEquals($expected, t3lib_div::camelCaseToLowerCaseUnderscored($inputString));
1092 }
1093
1094
1095 //////////////////////////////////
1096 // Tests concerning lcFirst
1097 //////////////////////////////////
1098
1099 /**
1100 * Data provider for lcFirst
1101 *
1102 * @return array expected, input string
1103 */
1104 public function lcfirstDataProvider() {
1105 return array(
1106 'single word' => array('blogexample', 'blogexample'),
1107 'single Word starting upper case' => array('blogexample', 'Blogexample'),
1108 'two words' => array('blogExample', 'BlogExample'),
1109 );
1110 }
1111
1112 /**
1113 * @test
1114 * @dataProvider lcfirstDataProvider
1115 */
1116 public function lcFirst($expected, $inputString) {
1117 $this->assertEquals($expected, t3lib_div::lcfirst($inputString));
1118 }
1119
1120
1121 //////////////////////////////////
1122 // Tests concerning encodeHeader
1123 //////////////////////////////////
1124
1125 /**
1126 * @test
1127 */
1128 public function encodeHeaderEncodesWhitespacesInQuotedPrintableMailHeader() {
1129 $this->assertEquals(
1130 '=?utf-8?Q?We_test_whether_the_copyright_character_=C2=A9_is_encoded_correctly?=',
1131 t3lib_div::encodeHeader(
1132 "We test whether the copyright character \xc2\xa9 is encoded correctly",
1133 'quoted-printable',
1134 'utf-8'
1135 )
1136 );
1137 }
1138
1139 /**
1140 * @test
1141 */
1142 public function encodeHeaderEncodesQuestionmarksInQuotedPrintableMailHeader() {
1143 $this->assertEquals(
1144 '=?utf-8?Q?Is_the_copyright_character_=C2=A9_really_encoded_correctly=3F_Really=3F?=',
1145 t3lib_div::encodeHeader(
1146 "Is the copyright character \xc2\xa9 really encoded correctly? Really?",
1147 'quoted-printable',
1148 'utf-8'
1149 )
1150 );
1151 }
1152
1153
1154 //////////////////////////////////
1155 // Tests concerning isValidUrl
1156 //////////////////////////////////
1157
1158 /**
1159 * Data provider for valid isValidUrl's
1160 *
1161 * @return array Valid ressource
1162 */
1163 public function validUrlValidRessourceDataProvider() {
1164 return array(
1165 'http' => array('http://www.example.org/'),
1166 'http without trailing slash' => array('http://qwe'),
1167 'http directory with trailing slash' => array('http://www.example/img/dir/'),
1168 'http directory without trailing slash' => array('http://www.example/img/dir'),
1169 'http index.html' => array('http://example.com/index.html'),
1170 'http index.php' => array('http://www.example.com/index.php'),
1171 'http test.png' => array('http://www.example/img/test.png'),
1172 'http username password querystring and ancher' => array('https://user:pw@www.example.org:80/path?arg=value#fragment'),
1173 'file' => array('file:///tmp/test.c'),
1174 'file directory' => array('file://foo/bar'),
1175 'ftp directory' => array('ftp://ftp.example.com/tmp/'),
1176 'mailto' => array('mailto:foo@bar.com'),
1177 'news' => array('news:news.php.net'),
1178 'telnet'=> array('telnet://192.0.2.16:80/'),
1179 'ldap' => array('ldap://[2001:db8::7]/c=GB?objectClass?one'),
1180 'http punycode domain name' => array('http://www.xn--bb-eka.at'),
1181 'http punicode subdomain' => array('http://xn--h-zfa.oebb.at'),
1182 'http domain-name umlauts' => array('http://www.öbb.at'),
1183 'http subdomain umlauts' => array('http://äh.oebb.at'),
1184 'http directory umlauts' => array('http://www.oebb.at/äöü/'),
1185 );
1186 }
1187
1188 /**
1189 * @test
1190 * @dataProvider validUrlValidRessourceDataProvider
1191 */
1192 public function validURLReturnsTrueForValidRessource($url) {
1193 $this->assertTrue(t3lib_div::isValidUrl($url));
1194 }
1195
1196 /**
1197 * Data provider for invalid isValidUrl's
1198 *
1199 * @return array Invalid ressource
1200 */
1201 public function isValidUrlInvalidRessourceDataProvider() {
1202 return array(
1203 'http missing colon' => array('http//www.example/wrong/url/'),
1204 'http missing slash' => array('http:/www.example'),
1205 'hostname only' => array('www.example.org/'),
1206 'file missing protocol specification' => array('/tmp/test.c'),
1207 'slash only' => array('/'),
1208 'string http://' => array('http://'),
1209 'string http:/' => array('http:/'),
1210 'string http:' => array('http:'),
1211 'string http' => array('http'),
1212 'empty string' => array(''),
1213 'string -1' => array('-1'),
1214 'string array()' => array('array()'),
1215 'random string' => array('qwe'),
1216 );
1217 }
1218
1219 /**
1220 * @test
1221 * @dataProvider isValidUrlInvalidRessourceDataProvider
1222 */
1223 public function validURLReturnsFalseForInvalidRessoure($url) {
1224 $this->assertFalse(t3lib_div::isValidUrl($url));
1225 }
1226
1227
1228 //////////////////////////////////
1229 // Tests concerning isOnCurrentHost
1230 //////////////////////////////////
1231
1232 /**
1233 * @test
1234 */
1235 public function isOnCurrentHostReturnsTrueWithCurrentHost() {
1236 $testUrl = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL');
1237 $this->assertTrue(t3lib_div::isOnCurrentHost($testUrl));
1238 }
1239
1240 /**
1241 * Data provider for invalid isOnCurrentHost's
1242 *
1243 * @return array Invalid Hosts
1244 */
1245 public function checkisOnCurrentHostInvalidHosts() {
1246 return array(
1247 'empty string' => array(''),
1248 'arbitrary string' => array('arbitrary string'),
1249 'localhost IP' => array('127.0.0.1'),
1250 'relative path' => array('./relpath/file.txt'),
1251 'absolute path' => array('/abspath/file.txt?arg=value'),
1252 'differnt host' => array(t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST') . '.example.org'),
1253 );
1254 }
1255
1256
1257 ////////////////////////////////////////
1258 // Tests concerning sanitizeLocalUrl
1259 ////////////////////////////////////////
1260
1261 /**
1262 * Data provider for valid sanitizeLocalUrl's
1263 *
1264 * @return array Valid url
1265 */
1266 public function sanitizeLocalUrlValidUrlDataProvider() {
1267 $subDirectory = t3lib_div::getIndpEnv('TYPO3_SITE_PATH');
1268 $typo3SiteUrl = t3lib_div::getIndpEnv('TYPO3_SITE_URL');
1269 $typo3RequestHost = t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST');
1270
1271 return array(
1272 'alt_intro.php' => array('alt_intro.php'),
1273 'alt_intro.php?foo=1&bar=2' => array('alt_intro.php?foo=1&bar=2'),
1274 $subDirectory . 'typo3/alt_intro.php' => array($subDirectory . 'typo3/alt_intro.php'),
1275 $subDirectory . 'index.php' => array($subDirectory . 'index.php'),
1276 '../index.php' => array('../index.php'),
1277 '../typo3/alt_intro.php' => array('../typo3/alt_intro.php'),
1278 '../~userDirectory/index.php' => array('../~userDirectory/index.php'),
1279 '../typo3/mod.php?var1=test-case&var2=~user' => array('../typo3/mod.php?var1=test-case&var2=~user'),
1280 PATH_site . 'typo3/alt_intro.php' => array(PATH_site . 'typo3/alt_intro.php'),
1281 $typo3SiteUrl . 'typo3/alt_intro.php' => array($typo3SiteUrl . 'typo3/alt_intro.php'),
1282 $typo3RequestHost . $subDirectory . '/index.php' => array($typo3RequestHost . $subDirectory . '/index.php'),
1283 );
1284 }
1285
1286 /**
1287 * @test
1288 * @dataProvider sanitizeLocalUrlValidUrlDataProvider
1289 */
1290 public function sanitizeLocalUrlAcceptsNotEncodedValidUrls($url) {
1291 $this->assertEquals($url, t3lib_div::sanitizeLocalUrl($url));
1292 }
1293
1294 /**
1295 * @test
1296 * @dataProvider sanitizeLocalUrlValidUrlDataProvider
1297 */
1298 public function sanitizeLocalUrlAcceptsEncodedValidUrls($url) {
1299 $this->assertEquals(rawurlencode($url), t3lib_div::sanitizeLocalUrl(rawurlencode($url)));
1300 }
1301
1302 /**
1303 * Data provider for invalid sanitizeLocalUrl's
1304 *
1305 * @return array Valid url
1306 */
1307 public function sanitizeLocalUrlInvalidDataProvider() {
1308 return array(
1309 'empty string' => array(''),
1310 'http domain' => array('http://www.google.de/'),
1311 'https domain' => array('https://www.google.de/'),
1312 'relative path with XSS' => array('../typo3/whatever.php?argument=javascript:alert(0)'),
1313 );
1314 }
1315
1316 /**
1317 * @test
1318 * @dataProvider sanitizeLocalUrlInvalidDataProvider
1319 */
1320 public function sanitizeLocalUrlDeniesPlainInvalidUrls($url) {
1321 $this->assertEquals('', t3lib_div::sanitizeLocalUrl($url));
1322 }
1323
1324 /**
1325 * @test
1326 * @dataProvider sanitizeLocalUrlInvalidDataProvider
1327 */
1328 public function sanitizeLocalUrlDeniesEncodedInvalidUrls($url) {
1329 $this->assertEquals('', t3lib_div::sanitizeLocalUrl(rawurlencode($url)));
1330 }
1331
1332
1333 //////////////////////////////////////
1334 // Tests concerning addSlashesOnArray
1335 //////////////////////////////////////
1336
1337 /**
1338 * @test
1339 */
1340 public function addSlashesOnArrayAddsSlashesRecursive() {
1341 $inputArray = array(
1342 'key1' => array(
1343 'key11' => "val'ue1",
1344 'key12' => 'val"ue2',
1345 ),
1346 'key2' => 'val\ue3',
1347 );
1348 $expectedResult = array(
1349 'key1' => array(
1350 'key11' => "val\'ue1",
1351 'key12' => 'val\"ue2',
1352 ),
1353 'key2' => 'val\\\\ue3',
1354 );
1355 t3lib_div::addSlashesOnArray($inputArray);
1356 $this->assertEquals(
1357 $expectedResult,
1358 $inputArray
1359 );
1360 }
1361
1362
1363 //////////////////////////////////////
1364 // Tests concerning addSlashesOnArray
1365 //////////////////////////////////////
1366
1367 /**
1368 * @test
1369 */
1370 public function stripSlashesOnArrayStripsSlashesRecursive() {
1371 $inputArray = array(
1372 'key1' => array(
1373 'key11' => "val\'ue1",
1374 'key12' => 'val\"ue2',
1375 ),
1376 'key2' => 'val\\\\ue3',
1377 );
1378 $expectedResult = array(
1379 'key1' => array(
1380 'key11' => "val'ue1",
1381 'key12' => 'val"ue2',
1382 ),
1383 'key2' => 'val\ue3',
1384 );
1385 t3lib_div::stripSlashesOnArray($inputArray);
1386 $this->assertEquals(
1387 $expectedResult,
1388 $inputArray
1389 );
1390 }
1391
1392
1393 //////////////////////////////////////
1394 // Tests concerning arrayDiffAssocRecursive
1395 //////////////////////////////////////
1396
1397 /**
1398 * @test
1399 */
1400 public function arrayDiffAssocRecursiveHandlesOneDimensionalArrays() {
1401 $array1 = array(
1402 'key1' => 'value1',
1403 'key2' => 'value2',
1404 'key3' => 'value3',
1405 );
1406 $array2 = array(
1407 'key1' => 'value1',
1408 'key3' => 'value3',
1409 );
1410 $expectedResult = array(
1411 'key2' => 'value2',
1412 );
1413 $actualResult = t3lib_div::arrayDiffAssocRecursive($array1, $array2);
1414 $this->assertEquals($expectedResult, $actualResult);
1415 }
1416
1417 /**
1418 * @test
1419 */
1420 public function arrayDiffAssocRecursiveHandlesMultiDimensionalArrays() {
1421 $array1 = array(
1422 'key1' => 'value1',
1423 'key2' => array(
1424 'key21' => 'value21',
1425 'key22' => 'value22',
1426 'key23' => array(
1427 'key231' => 'value231',
1428 'key232' => 'value232',
1429 ),
1430 ),
1431 );
1432 $array2 = array(
1433 'key1' => 'value1',
1434 'key2' => array(
1435 'key21' => 'value21',
1436 'key23' => array(
1437 'key231' => 'value231',
1438 ),
1439 ),
1440 );
1441 $expectedResult = array(
1442 'key2' => array(
1443 'key22' => 'value22',
1444 'key23' => array(
1445 'key232' => 'value232',
1446 ),
1447 ),
1448 );
1449 $actualResult = t3lib_div::arrayDiffAssocRecursive($array1, $array2);
1450 $this->assertEquals($expectedResult, $actualResult);
1451 }
1452
1453 /**
1454 * @test
1455 */
1456 public function arrayDiffAssocRecursiveHandlesMixedArrays() {
1457 $array1 = array(
1458 'key1' => array(
1459 'key11' => 'value11',
1460 'key12' => 'value12',
1461 ),
1462 'key2' => 'value2',
1463 'key3' => 'value3',
1464 );
1465 $array2 = array(
1466 'key1' => 'value1',
1467 'key2' => array(
1468 'key21' => 'value21',
1469 ),
1470 );
1471 $expectedResult = array(
1472 'key3' => 'value3',
1473 );
1474 $actualResult = t3lib_div::arrayDiffAssocRecursive($array1, $array2);
1475 $this->assertEquals($expectedResult, $actualResult);
1476 }
1477
1478
1479 //////////////////////////////////////
1480 // Tests concerning removeDotsFromTS
1481 //////////////////////////////////////
1482
1483 /**
1484 * @test
1485 */
1486 public function removeDotsFromTypoScriptSucceedsWithDottedArray() {
1487 $typoScript = array(
1488 'propertyA.' => array(
1489 'keyA.' => array(
1490 'valueA' => 1,
1491 ),
1492 'keyB' => 2,
1493 ),
1494 'propertyB' => 3,
1495 );
1496
1497 $expectedResult = array(
1498 'propertyA' => array(
1499 'keyA' => array(
1500 'valueA' => 1,
1501 ),
1502 'keyB' => 2,
1503 ),
1504 'propertyB' => 3,
1505 );
1506
1507 $this->assertEquals($expectedResult, t3lib_div::removeDotsFromTS($typoScript));
1508 }
1509
1510 /**
1511 * @test
1512 */
1513 public function removeDotsFromTypoScriptOverridesSubArray() {
1514 $typoScript = array(
1515 'propertyA.' => array(
1516 'keyA' => 'getsOverridden',
1517 'keyA.' => array(
1518 'valueA' => 1,
1519 ),
1520 'keyB' => 2,
1521 ),
1522 'propertyB' => 3,
1523 );
1524
1525 $expectedResult = array(
1526 'propertyA' => array(
1527 'keyA' => array(
1528 'valueA' => 1,
1529 ),
1530 'keyB' => 2,
1531 ),
1532 'propertyB' => 3,
1533 );
1534
1535 $this->assertEquals($expectedResult, t3lib_div::removeDotsFromTS($typoScript));
1536 }
1537
1538 /**
1539 * @test
1540 */
1541 public function removeDotsFromTypoScriptOverridesWithScalar() {
1542 $typoScript = array(
1543 'propertyA.' => array(
1544 'keyA.' => array(
1545 'valueA' => 1,
1546 ),
1547 'keyA' => 'willOverride',
1548 'keyB' => 2,
1549 ),
1550 'propertyB' => 3,
1551 );
1552
1553 $expectedResult = array(
1554 'propertyA' => array(
1555 'keyA' => 'willOverride',
1556 'keyB' => 2,
1557 ),
1558 'propertyB' => 3,
1559 );
1560
1561 $this->assertEquals($expectedResult, t3lib_div::removeDotsFromTS($typoScript));
1562 }
1563
1564 //////////////////////////////////////
1565 // Tests concerning naturalKeySortRecursive
1566 //////////////////////////////////////
1567
1568 /**
1569 * @test
1570 */
1571 public function naturalKeySortRecursiveReturnsFalseIfInputIsNotAnArray() {
1572 $testValues = array(
1573 1,
1574 'string',
1575 FALSE
1576 );
1577 foreach($testValues as $testValue) {
1578 $this->assertFalse(t3lib_div::naturalKeySortRecursive($testValue));
1579 }
1580 }
1581
1582 /**
1583 * @test
1584 */
1585 public function naturalKeySortRecursiveSortsOneDimensionalArrayByNaturalOrder() {
1586 $testArray = array(
1587 'bb' => 'bb',
1588 'ab' => 'ab',
1589 '123' => '123',
1590 'aaa' => 'aaa',
1591 'abc' => 'abc',
1592 '23' => '23',
1593 'ba' => 'ba',
1594 'bad' => 'bad',
1595 '2' => '2',
1596 'zap' => 'zap',
1597 '210' => '210'
1598 );
1599 $expectedResult = array(
1600 '2',
1601 '23',
1602 '123',
1603 '210',
1604 'aaa',
1605 'ab',
1606 'abc',
1607 'ba',
1608 'bad',
1609 'bb',
1610 'zap'
1611 );
1612 t3lib_div::naturalKeySortRecursive($testArray);
1613 $this->assertEquals($expectedResult, array_values($testArray));
1614 }
1615
1616 /**
1617 * @test
1618 */
1619 public function naturalKeySortRecursiveSortsMultiDimensionalArrayByNaturalOrder() {
1620 $testArray = array(
1621 '2' => '2',
1622 'bb' => 'bb',
1623 'ab' => 'ab',
1624 '23' => '23',
1625 'aaa' => array(
1626 'bb' => 'bb',
1627 'ab' => 'ab',
1628 '123' => '123',
1629 'aaa' => 'aaa',
1630 '2' => '2',
1631 'abc' => 'abc',
1632 'ba' => 'ba',
1633 '23' => '23',
1634 'bad' => array(
1635 'bb' => 'bb',
1636 'ab' => 'ab',
1637 '123' => '123',
1638 'aaa' => 'aaa',
1639 'abc' => 'abc',
1640 '23' => '23',
1641 'ba' => 'ba',
1642 'bad' => 'bad',
1643 '2' => '2',
1644 'zap' => 'zap',
1645 '210' => '210'
1646 ),
1647 '210' => '210',
1648 'zap' => 'zap'
1649 ),
1650 'abc' => 'abc',
1651 'ba' => 'ba',
1652 '210' => '210',
1653 'bad' => 'bad',
1654 '123' => '123',
1655 'zap' => 'zap'
1656 );
1657
1658 $expectedResult = array(
1659 '2',
1660 '23',
1661 '123',
1662 '210',
1663 'aaa',
1664 'ab',
1665 'abc',
1666 'ba',
1667 'bad',
1668 'bb',
1669 'zap'
1670 );
1671 t3lib_div::naturalKeySortRecursive($testArray);
1672
1673 $this->assertEquals($expectedResult, array_values(array_keys($testArray['aaa']['bad'])));
1674 $this->assertEquals($expectedResult, array_values(array_keys($testArray['aaa'])));
1675 $this->assertEquals($expectedResult, array_values(array_keys($testArray)));
1676 }
1677
1678 //////////////////////////////////////
1679 // Tests concerning get_dirs
1680 //////////////////////////////////////
1681
1682 /**
1683 * @test
1684 */
1685 public function getDirsReturnsArrayOfDirectoriesFromGivenDirectory() {
1686 $path = PATH_t3lib;
1687 $directories = t3lib_div::get_dirs($path);
1688
1689 $this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $directories);
1690 }
1691
1692 /**
1693 * @test
1694 */
1695 public function getDirsReturnsStringErrorOnPathFailure() {
1696 $path = 'foo';
1697 $result = t3lib_div::get_dirs($path);
1698 $expectedResult = 'error';
1699
1700 $this->assertEquals($expectedResult, $result);
1701 }
1702
1703
1704 //////////////////////////////////
1705 // Tests concerning hmac
1706 //////////////////////////////////
1707
1708 /**
1709 * @test
1710 */
1711 public function hmacReturnsHashOfProperLength() {
1712 $hmac = t3lib_div::hmac('message');
1713 $this->assertTrue(!empty($hmac) && is_string($hmac));
1714 $this->assertTrue(strlen($hmac) == 40);
1715 }
1716
1717 /**
1718 * @test
1719 */
1720 public function hmacReturnsEqualHashesForEqualInput() {
1721 $msg0 = 'message';
1722 $msg1 = 'message';
1723 $this->assertEquals(t3lib_div::hmac($msg0), t3lib_div::hmac($msg1));
1724 }
1725
1726 /**
1727 * @test
1728 */
1729 public function hmacReturnsNoEqualHashesForNonEqualInput() {
1730 $msg0 = 'message0';
1731 $msg1 = 'message1';
1732 $this->assertNotEquals(t3lib_div::hmac($msg0), t3lib_div::hmac($msg1));
1733 }
1734
1735
1736 //////////////////////////////////
1737 // Tests concerning quoteJSvalue
1738 //////////////////////////////////
1739
1740 /**
1741 * @test
1742 */
1743 public function quoteJSvalueHtmlspecialcharsDataByDefault() {
1744 $this->assertContains(
1745 '&gt;',
1746 t3lib_div::quoteJSvalue('>')
1747 );
1748 }
1749
1750 /**
1751 * @test
1752 */
1753 public function quoteJSvaluetHtmlspecialcharsDataWithinCDataSetToFalse() {
1754 $this->assertContains(
1755 '&gt;',
1756 t3lib_div::quoteJSvalue('>', FALSE)
1757 );
1758 }
1759
1760 /**
1761 * @test
1762 */
1763 public function quoteJSvaluetNotHtmlspecialcharsDataWithinCDataSetToTrue() {
1764 $this->assertContains(
1765 '>',
1766 t3lib_div::quoteJSvalue('>', TRUE)
1767 );
1768 }
1769
1770 /**
1771 * @test
1772 */
1773 public function quoteJSvalueReturnsEmptyStringQuotedInSingleQuotes() {
1774 $this->assertEquals(
1775 "''",
1776 t3lib_div::quoteJSvalue("", TRUE)
1777 );
1778 }
1779
1780 /**
1781 * @test
1782 */
1783 public function quoteJSvalueNotModifiesStringWithoutSpecialCharacters() {
1784 $this->assertEquals(
1785 "'Hello world!'",
1786 t3lib_div::quoteJSvalue("Hello world!", TRUE)
1787 );
1788 }
1789
1790 /**
1791 * @test
1792 */
1793 public function quoteJSvalueEscapesSingleQuote() {
1794 $this->assertEquals(
1795 "'\\''",
1796 t3lib_div::quoteJSvalue("'", TRUE)
1797 );
1798 }
1799
1800 /**
1801 * @test
1802 */
1803 public function quoteJSvalueEscapesDoubleQuoteWithinCDataSetToTrue() {
1804 $this->assertEquals(
1805 "'\\\"'",
1806 t3lib_div::quoteJSvalue('"', TRUE)
1807 );
1808 }
1809
1810 /**
1811 * @test
1812 */
1813 public function quoteJSvalueEscapesAndHtmlspecialcharsDoubleQuoteWithinCDataSetToFalse() {
1814 $this->assertEquals(
1815 "'\\&quot;'",
1816 t3lib_div::quoteJSvalue('"', FALSE)
1817 );
1818 }
1819
1820 /**
1821 * @test
1822 */
1823 public function quoteJSvalueEscapesTab() {
1824 $this->assertEquals(
1825 "'" . '\t' . "'",
1826 t3lib_div::quoteJSvalue(TAB)
1827 );
1828 }
1829
1830 /**
1831 * @test
1832 */
1833 public function quoteJSvalueEscapesLinefeed() {
1834 $this->assertEquals(
1835 "'" . '\n' . "'",
1836 t3lib_div::quoteJSvalue(LF)
1837 );
1838 }
1839
1840 /**
1841 * @test
1842 */
1843 public function quoteJSvalueEscapesCarriageReturn() {
1844 $this->assertEquals(
1845 "'" . '\r' . "'",
1846 t3lib_div::quoteJSvalue(CR)
1847 );
1848 }
1849
1850 /**
1851 * @test
1852 */
1853 public function quoteJSvalueEscapesBackslah() {
1854 $this->assertEquals(
1855 "'\\\\'",
1856 t3lib_div::quoteJSvalue('\\')
1857 );
1858 }
1859
1860 //////////////////////////////////
1861 // Tests concerning readLLfile
1862 //////////////////////////////////
1863
1864 /**
1865 * @test
1866 */
1867 public function readLLfileHandlesLocallangXMLOverride() {
1868 $unique = uniqid('locallangXMLOverrideTest');
1869
1870 $xml = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
1871 <T3locallang>
1872 <data type="array">
1873 <languageKey index="default" type="array">
1874 <label index="buttons.logout">EXIT</label>
1875 </languageKey>
1876 </data>
1877 </T3locallang>';
1878
1879 $file = PATH_site . 'typo3temp/' . $unique . '.xml';
1880 t3lib_div::writeFileToTypo3tempDir($file, $xml);
1881
1882 // Make sure there is no cached version of the label
1883 $GLOBALS['typo3CacheManager']->getCache('t3lib_l10n')->flush();
1884
1885 // Get default value
1886 $defaultLL = t3lib_div::readLLfile('EXT:lang/locallang_core.xml', 'default');
1887
1888 // Clear language cache again
1889 $GLOBALS['typo3CacheManager']->getCache('t3lib_l10n')->flush();
1890
1891 // Set override file
1892 $GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']['EXT:lang/locallang_core.xml'][$unique] = $file;
1893
1894 /** @var $store t3lib_l10n_Store */
1895 $store = t3lib_div::makeInstance('t3lib_l10n_Store');
1896 $store->flushData('EXT:lang/locallang_core.xml');
1897
1898 // Get override value
1899 $overrideLL = t3lib_div::readLLfile('EXT:lang/locallang_core.xml', 'default');
1900
1901 // Clean up again
1902 unlink($file);
1903
1904 $this->assertNotEquals($overrideLL['default']['buttons.logout'][0]['target'], '');
1905 $this->assertNotEquals($defaultLL['default']['buttons.logout'][0]['target'], $overrideLL['default']['buttons.logout'][0]['target']);
1906 $this->assertEquals($overrideLL['default']['buttons.logout'][0]['target'], 'EXIT');
1907 }
1908
1909
1910 ///////////////////////////////
1911 // Tests concerning _GETset()
1912 ///////////////////////////////
1913
1914 /**
1915 * @test
1916 */
1917 public function getSetWritesArrayToGetSystemVariable() {
1918 $_GET = array();
1919 $GLOBALS['HTTP_GET_VARS'] = array();
1920
1921 $getParameters = array('foo' => 'bar');
1922 t3lib_div::_GETset($getParameters);
1923 $this->assertSame($getParameters, $_GET);
1924 }
1925
1926 /**
1927 * @test
1928 */
1929 public function getSetWritesArrayToGlobalsHttpGetVars() {
1930 $_GET = array();
1931 $GLOBALS['HTTP_GET_VARS'] = array();
1932
1933 $getParameters = array('foo' => 'bar');
1934 t3lib_div::_GETset($getParameters);
1935 $this->assertSame($getParameters, $GLOBALS['HTTP_GET_VARS']);
1936 }
1937
1938 /**
1939 * @test
1940 */
1941 public function getSetForArrayDropsExistingValues() {
1942 $_GET = array();
1943 $GLOBALS['HTTP_GET_VARS'] = array();
1944
1945 t3lib_div::_GETset(array('foo' => 'bar'));
1946
1947 t3lib_div::_GETset(array('oneKey' => 'oneValue'));
1948
1949 $this->assertEquals(
1950 array('oneKey' => 'oneValue'),
1951 $GLOBALS['HTTP_GET_VARS']
1952 );
1953 }
1954
1955 /**
1956 * @test
1957 */
1958 public function getSetAssignsOneValueToOneKey() {
1959 $_GET = array();
1960 $GLOBALS['HTTP_GET_VARS'] = array();
1961
1962 t3lib_div::_GETset('oneValue', 'oneKey');
1963
1964 $this->assertEquals(
1965 'oneValue',
1966 $GLOBALS['HTTP_GET_VARS']['oneKey']
1967 );
1968 }
1969
1970 /**
1971 * @test
1972 */
1973 public function getSetForOneValueDoesNotDropUnrelatedValues() {
1974 $_GET = array();
1975 $GLOBALS['HTTP_GET_VARS'] = array();
1976
1977 t3lib_div::_GETset(array('foo' => 'bar'));
1978 t3lib_div::_GETset('oneValue', 'oneKey');
1979
1980 $this->assertEquals(
1981 array('foo' => 'bar', 'oneKey' => 'oneValue'),
1982 $GLOBALS['HTTP_GET_VARS']
1983 );
1984 }
1985
1986 /**
1987 * @test
1988 */
1989 public function getSetCanAssignsAnArrayToASpecificArrayElement() {
1990 $_GET = array();
1991 $GLOBALS['HTTP_GET_VARS'] = array();
1992
1993 t3lib_div::_GETset(array('childKey' => 'oneValue'), 'parentKey');
1994
1995 $this->assertEquals(
1996 array('parentKey' => array('childKey' => 'oneValue')),
1997 $GLOBALS['HTTP_GET_VARS']
1998 );
1999 }
2000
2001 /**
2002 * @test
2003 */
2004 public function getSetCanAssignAStringValueToASpecificArrayChildElement() {
2005 $_GET = array();
2006 $GLOBALS['HTTP_GET_VARS'] = array();
2007
2008 t3lib_div::_GETset('oneValue', 'parentKey|childKey');
2009
2010 $this->assertEquals(
2011 array('parentKey' => array('childKey' => 'oneValue')),
2012 $GLOBALS['HTTP_GET_VARS']
2013 );
2014 }
2015
2016 /**
2017 * @test
2018 */
2019 public function getSetCanAssignAnArrayToASpecificArrayChildElement() {
2020 $_GET = array();
2021 $GLOBALS['HTTP_GET_VARS'] = array();
2022
2023 t3lib_div::_GETset(
2024 array('key1' => 'value1', 'key2' => 'value2'),
2025 'parentKey|childKey'
2026 );
2027
2028 $this->assertEquals(
2029 array(
2030 'parentKey' => array(
2031 'childKey' => array('key1' => 'value1', 'key2' => 'value2')
2032 )
2033 ),
2034 $GLOBALS['HTTP_GET_VARS']
2035 );
2036 }
2037
2038
2039 ///////////////////////////
2040 // Tests concerning getUrl
2041 ///////////////////////////
2042
2043 /**
2044 * @test
2045 */
2046 public function getUrlWithAdditionalRequestHeadersProvidesHttpHeaderOnError() {
2047 $url = 'http://typo3.org/i-do-not-exist-' . time();
2048
2049 $report = array();
2050 t3lib_div::getUrl(
2051 $url,
2052 0,
2053 array(),
2054 $report
2055 );
2056 $this->assertContains(
2057 '404',
2058 $report['message']
2059 );
2060 }
2061
2062 /**
2063 * @test
2064 */
2065 public function getUrlProvidesWithoutAdditionalRequestHeadersHttpHeaderOnError() {
2066 $url = 'http://typo3.org/i-do-not-exist-' . time();
2067
2068 $report = array();
2069 t3lib_div::getUrl(
2070 $url,
2071 0,
2072 FALSE,
2073 $report
2074 );
2075 $this->assertContains(
2076 '404',
2077 $report['message'],
2078 'Did not provide the HTTP response header when requesting a failing URL.'
2079 );
2080 }
2081
2082
2083 ///////////////////////////////
2084 // Tests concerning fixPermissions
2085 ///////////////////////////////
2086
2087 /**
2088 * @test
2089 */
2090 public function fixPermissionsSetsGroup() {
2091 if (TYPO3_OS == 'WIN') {
2092 $this->markTestSkipped('fixPermissionsSetsGroup() tests not available on Windows');
2093 }
2094 if (!function_exists('posix_getegid')) {
2095 $this->markTestSkipped('Function posix_getegid() not available, fixPermissionsSetsGroup() tests skipped');
2096 }
2097 if (posix_getegid() === -1) {
2098 $this->markTestSkipped(
2099 'The fixPermissionsSetsGroup() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.'
2100 );
2101 }
2102
2103 // Create and prepare test file
2104 $filename = PATH_site . 'typo3temp/' . uniqid('test_');
2105 t3lib_div::writeFileToTypo3tempDir($filename, '42');
2106
2107 $currentGroupId = posix_getegid();
2108
2109 // Set target group and run method
2110 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $currentGroupId;
2111 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
2112
2113 clearstatcache();
2114 $resultFileGroup = filegroup($filename);
2115 unlink($filename);
2116
2117 $this->assertEquals($resultFileGroup, $currentGroupId);
2118 }
2119
2120 /**
2121 * @test
2122 */
2123 public function fixPermissionsSetsPermissionsToFile() {
2124 if (TYPO3_OS == 'WIN') {
2125 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2126 }
2127
2128 // Create and prepare test file
2129 $filename = PATH_site . 'typo3temp/' . uniqid('test_');
2130 t3lib_div::writeFileToTypo3tempDir($filename, '42');
2131 chmod($filename, 0742);
2132
2133 // Set target permissions and run method
2134 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2135 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
2136
2137 // Get actual permissions and clean up
2138 clearstatcache();
2139 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
2140 unlink($filename);
2141
2142 // Test if everything was ok
2143 $this->assertTrue($fixPermissionsResult);
2144 $this->assertEquals($resultFilePermissions, '0660');
2145 }
2146
2147 /**
2148 * @test
2149 */
2150 public function fixPermissionsSetsPermissionsToHiddenFile() {
2151 if (TYPO3_OS == 'WIN') {
2152 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2153 }
2154
2155 // Create and prepare test file
2156 $filename = PATH_site . 'typo3temp/' . uniqid('.test_');
2157 t3lib_div::writeFileToTypo3tempDir($filename, '42');
2158 chmod($filename, 0742);
2159
2160 // Set target permissions and run method
2161 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2162 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
2163
2164 // Get actual permissions and clean up
2165 clearstatcache();
2166 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
2167 unlink($filename);
2168
2169 // Test if everything was ok
2170 $this->assertTrue($fixPermissionsResult);
2171 $this->assertEquals($resultFilePermissions, '0660');
2172 }
2173
2174 /**
2175 * @test
2176 */
2177 public function fixPermissionsSetsPermissionsToDirectory() {
2178 if (TYPO3_OS == 'WIN') {
2179 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2180 }
2181
2182 // Create and prepare test directory
2183 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2184 t3lib_div::mkdir($directory);
2185 chmod($directory, 1551);
2186
2187 // Set target permissions and run method
2188 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2189 $fixPermissionsResult = t3lib_div::fixPermissions($directory);
2190
2191 // Get actual permissions and clean up
2192 clearstatcache();
2193 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2194 t3lib_div::rmdir($directory);
2195
2196 // Test if everything was ok
2197 $this->assertTrue($fixPermissionsResult);
2198 $this->assertEquals($resultDirectoryPermissions, '0770');
2199 }
2200
2201 /**
2202 * @test
2203 */
2204 public function fixPermissionsSetsPermissionsToDirectoryWithTrailingSlash() {
2205 if (TYPO3_OS == 'WIN') {
2206 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2207 }
2208
2209 // Create and prepare test directory
2210 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2211 t3lib_div::mkdir($directory);
2212 chmod($directory, 1551);
2213
2214 // Set target permissions and run method
2215 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2216 $fixPermissionsResult = t3lib_div::fixPermissions($directory . '/');
2217
2218 // Get actual permissions and clean up
2219 clearstatcache();
2220 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2221 t3lib_div::rmdir($directory);
2222
2223 // Test if everything was ok
2224 $this->assertTrue($fixPermissionsResult);
2225 $this->assertEquals($resultDirectoryPermissions, '0770');
2226 }
2227
2228 /**
2229 * @test
2230 */
2231 public function fixPermissionsSetsPermissionsToHiddenDirectory() {
2232 if (TYPO3_OS == 'WIN') {
2233 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2234 }
2235
2236 // Create and prepare test directory
2237 $directory = PATH_site . 'typo3temp/' . uniqid('.test_');
2238 t3lib_div::mkdir($directory);
2239 chmod($directory, 1551);
2240
2241 // Set target permissions and run method
2242 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2243 $fixPermissionsResult = t3lib_div::fixPermissions($directory);
2244
2245 // Get actual permissions and clean up
2246 clearstatcache();
2247 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2248 t3lib_div::rmdir($directory);
2249
2250 // Test if everything was ok
2251 $this->assertTrue($fixPermissionsResult);
2252 $this->assertEquals($resultDirectoryPermissions, '0770');
2253 }
2254
2255 /**
2256 * @test
2257 */
2258 public function fixPermissionsCorrectlySetsPermissionsRecursive() {
2259 if (TYPO3_OS == 'WIN') {
2260 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2261 }
2262
2263 // Create and prepare test directory and file structure
2264 $baseDirectory = PATH_site . 'typo3temp/' . uniqid('test_');
2265 t3lib_div::mkdir($baseDirectory);
2266 chmod($baseDirectory, 1751);
2267 t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/file', '42');
2268 chmod($baseDirectory . '/file', 0742);
2269 t3lib_div::mkdir($baseDirectory . '/foo');
2270 chmod($baseDirectory . '/foo', 1751);
2271 t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/foo/file', '42');
2272 chmod($baseDirectory . '/foo/file', 0742);
2273 t3lib_div::mkdir($baseDirectory . '/.bar');
2274 chmod($baseDirectory . '/.bar', 1751);
2275 // Use this if writeFileToTypo3tempDir is fixed to create hidden files in subdirectories
2276 // t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/.bar/.file', '42');
2277 // t3lib_div::writeFileToTypo3tempDir($baseDirectory . '/.bar/..file2', '42');
2278 touch($baseDirectory . '/.bar/.file', '42');
2279 chmod($baseDirectory . '/.bar/.file', 0742);
2280 touch($baseDirectory . '/.bar/..file2', '42');
2281 chmod($baseDirectory . '/.bar/..file2', 0742);
2282
2283 // Set target permissions and run method
2284 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2285 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2286 $fixPermissionsResult = t3lib_div::fixPermissions($baseDirectory, TRUE);
2287
2288 // Get actual permissions
2289 clearstatcache();
2290 $resultBaseDirectoryPermissions = substr(decoct(fileperms($baseDirectory)), 1);
2291 $resultBaseFilePermissions = substr(decoct(fileperms($baseDirectory . '/file')), 2);
2292 $resultFooDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/foo')), 1);
2293 $resultFooFilePermissions = substr(decoct(fileperms($baseDirectory . '/foo/file')), 2);
2294 $resultBarDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/.bar')), 1);
2295 $resultBarFilePermissions = substr(decoct(fileperms($baseDirectory . '/.bar/.file')), 2);
2296 $resultBarFile2Permissions = substr(decoct(fileperms($baseDirectory . '/.bar/..file2')), 2);
2297
2298 // Clean up
2299 unlink($baseDirectory . '/file');
2300 unlink($baseDirectory . '/foo/file');
2301 unlink($baseDirectory . '/.bar/.file');
2302 unlink($baseDirectory . '/.bar/..file2');
2303 t3lib_div::rmdir($baseDirectory . '/foo');
2304 t3lib_div::rmdir($baseDirectory . '/.bar');
2305 t3lib_div::rmdir($baseDirectory);
2306
2307 // Test if everything was ok
2308 $this->assertTrue($fixPermissionsResult);
2309 $this->assertEquals($resultBaseDirectoryPermissions, '0770');
2310 $this->assertEquals($resultBaseFilePermissions, '0660');
2311 $this->assertEquals($resultFooDirectoryPermissions, '0770');
2312 $this->assertEquals($resultFooFilePermissions, '0660');
2313 $this->assertEquals($resultBarDirectoryPermissions, '0770');
2314 $this->assertEquals($resultBarFilePermissions, '0660');
2315 $this->assertEquals($resultBarFile2Permissions, '0660');
2316 }
2317
2318 /**
2319 * @test
2320 */
2321 public function fixPermissionsDoesNotSetPermissionsToNotAllowedPath() {
2322 if (TYPO3_OS == 'WIN') {
2323 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2324 }
2325
2326 // Create and prepare test file
2327 $filename = PATH_site . 'typo3temp/../typo3temp/' . uniqid('test_');
2328 touch($filename);
2329 chmod($filename, 0742);
2330
2331 // Set target permissions and run method
2332 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2333 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
2334
2335 // Get actual permissions and clean up
2336 clearstatcache();
2337 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
2338 unlink($filename);
2339
2340 // Test if everything was ok
2341 $this->assertFalse($fixPermissionsResult);
2342 }
2343
2344 /**
2345 * @test
2346 */
2347 public function fixPermissionsSetsPermissionsWithRelativeFileReference() {
2348 if (TYPO3_OS == 'WIN') {
2349 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2350 }
2351
2352 $filename = 'typo3temp/' . uniqid('test_');
2353 t3lib_div::writeFileToTypo3tempDir(PATH_site . $filename, '42');
2354 chmod(PATH_site . $filename, 0742);
2355
2356 // Set target permissions and run method
2357 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2358 $fixPermissionsResult = t3lib_div::fixPermissions($filename);
2359
2360 // Get actual permissions and clean up
2361 clearstatcache();
2362 $resultFilePermissions = substr(decoct(fileperms(PATH_site . $filename)), 2);
2363 unlink(PATH_site . $filename);
2364
2365 // Test if everything was ok
2366 $this->assertTrue($fixPermissionsResult);
2367 $this->assertEquals($resultFilePermissions, '0660');
2368 }
2369
2370
2371 ///////////////////////////////
2372 // Tests concerning mkdir
2373 ///////////////////////////////
2374
2375 /**
2376 * @test
2377 */
2378 public function mkdirCreatesDirectory() {
2379 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2380 $mkdirResult = t3lib_div::mkdir($directory);
2381 clearstatcache();
2382 $directoryCreated = is_dir($directory);
2383 @rmdir($directory);
2384 $this->assertTrue($mkdirResult);
2385 $this->assertTrue($directoryCreated);
2386 }
2387
2388 /**
2389 * @test
2390 */
2391 public function mkdirCreatesHiddenDirectory() {
2392 $directory = PATH_site . 'typo3temp/' . uniqid('.test_');
2393 $mkdirResult = t3lib_div::mkdir($directory);
2394 clearstatcache();
2395 $directoryCreated = is_dir($directory);
2396 @rmdir($directory);
2397 $this->assertTrue($mkdirResult);
2398 $this->assertTrue($directoryCreated);
2399 }
2400
2401 /**
2402 * @test
2403 */
2404 public function mkdirCreatesDirectoryWithTrailingSlash() {
2405 $directory = PATH_site . 'typo3temp/' . uniqid('test_') . '/';
2406 $mkdirResult = t3lib_div::mkdir($directory);
2407 clearstatcache();
2408 $directoryCreated = is_dir($directory);
2409 @rmdir($directory);
2410 $this->assertTrue($mkdirResult);
2411 $this->assertTrue($directoryCreated);
2412 }
2413
2414 /**
2415 * @test
2416 */
2417 public function mkdirSetsPermissionsOfCreatedDirectory() {
2418 if (TYPO3_OS == 'WIN') {
2419 $this->markTestSkipped('mkdirSetsPermissionsOfCreatedDirectory() test not available on Windows');
2420 }
2421
2422 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2423 $oldUmask = umask(023);
2424 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0772';
2425 t3lib_div::mkdir($directory);
2426 clearstatcache();
2427 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2428 umask($oldUmask);
2429 rmdir($directory);
2430 $this->assertEquals($resultDirectoryPermissions, '0772');
2431 }
2432
2433 /**
2434 * @test
2435 */
2436 public function mkdirSetsGroupOwnershipOfCreatedDirectory() {
2437 if (!function_exists('posix_getegid')) {
2438 $this->markTestSkipped('Function posix_getegid() not available, mkdirSetsGroupOwnershipOfCreatedDirectory() tests skipped');
2439 }
2440 if (posix_getegid() === -1) {
2441 $this->markTestSkipped(
2442 'The mkdirSetsGroupOwnershipOfCreatedDirectory() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.'
2443 );
2444 }
2445 $swapGroup = $this->checkGroups(__FUNCTION__);
2446 if ($swapGroup !== FALSE) {
2447 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
2448 $directory = uniqid('mkdirtest_');
2449 t3lib_div::mkdir(PATH_site . 'typo3temp/' . $directory);
2450 clearstatcache();
2451 $resultDirectoryGroupInfo = posix_getgrgid((filegroup(PATH_site . 'typo3temp/' . $directory)));
2452 $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
2453 @rmdir(PATH_site . 'typo3temp/' . $directory);
2454 $this->assertEquals($resultDirectoryGroup, $swapGroup);
2455 }
2456 }
2457
2458 ///////////////////////////////
2459 // Helper function for filesystem ownership tests
2460 ///////////////////////////////
2461
2462 /**
2463 * Check if test on filesystem group ownership can be done in this environment
2464 * If so, return second group of webserver user
2465 * @param string calling method name
2466 * @return mixed FALSE if test cannot be run, string name of the second group of webserver user
2467 */
2468 private function checkGroups($methodName) {
2469 if (TYPO3_OS == 'WIN') {
2470 $this->markTestSkipped($methodName . '() test not available on Windows.');
2471 return FALSE;
2472 }
2473 if (!function_exists('posix_getgroups')) {
2474 $this->markTestSkipped('Function posix_getgroups() not available, ' . $methodName . '() tests skipped');
2475 }
2476
2477 $groups = posix_getgroups();
2478 if (count($groups) <= 1) {
2479 $this->markTestSkipped($methodName . '() test cannot be done when the web server user is only member of 1 group.');
2480 return FALSE;
2481 }
2482 $groupInfo = posix_getgrgid($groups[1]);
2483 return $groupInfo['name'];
2484 }
2485
2486 ///////////////////////////////
2487 // Tests concerning mkdir_deep
2488 ///////////////////////////////
2489
2490 /**
2491 * @test
2492 */
2493 public function mkdirDeepCreatesDirectory() {
2494 $directory = 'typo3temp/' . uniqid('test_');
2495 t3lib_div::mkdir_deep(PATH_site, $directory);
2496 $isDirectoryCreated = is_dir(PATH_site . $directory);
2497 rmdir(PATH_site . $directory);
2498 $this->assertTrue($isDirectoryCreated);
2499 }
2500
2501 /**
2502 * @test
2503 */
2504 public function mkdirDeepCreatesSubdirectoriesRecursive() {
2505 $directory = 'typo3temp/' . uniqid('test_');
2506 $subDirectory = $directory . '/foo';
2507 t3lib_div::mkdir_deep(PATH_site, $subDirectory);
2508 $isDirectoryCreated = is_dir(PATH_site . $subDirectory);
2509 rmdir(PATH_site . $subDirectory);
2510 rmdir(PATH_site . $directory);
2511 $this->assertTrue($isDirectoryCreated);
2512 }
2513
2514 /**
2515 * @test
2516 */
2517 public function mkdirDeepFixesPermissionsOfCreatedDirectory() {
2518 if (TYPO3_OS == 'WIN') {
2519 $this->markTestSkipped('mkdirDeepFixesPermissionsOfCreatedDirectory() test not available on Windows.');
2520 }
2521
2522 $directory = uniqid('mkdirdeeptest_');
2523 $oldUmask = umask(023);
2524 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0777';
2525 t3lib_div::mkdir_deep(PATH_site . 'typo3temp/', $directory);
2526 clearstatcache();
2527 $resultDirectoryPermissions = substr(decoct(fileperms(PATH_site . 'typo3temp/' . $directory)), -3, 3);
2528 @rmdir(PATH_site . 'typo3temp/' . $directory);
2529 umask($oldUmask);
2530 $this->assertEquals($resultDirectoryPermissions, '777');
2531 }
2532
2533 /**
2534 * @test
2535 */
2536 public function mkdirDeepFixesPermissionsOnNewParentDirectory() {
2537 if (TYPO3_OS == 'WIN') {
2538 $this->markTestSkipped('mkdirDeepFixesPermissionsOnNewParentDirectory() test not available on Windows.');
2539 }
2540
2541 $directory = uniqid('mkdirdeeptest_');
2542 $subDirectory = $directory . '/bar';
2543 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0777';
2544 $oldUmask = umask(023);
2545 t3lib_div::mkdir_deep(PATH_site . 'typo3temp/', $subDirectory);
2546 clearstatcache();
2547 $resultDirectoryPermissions = substr(decoct(fileperms(PATH_site . 'typo3temp/' . $directory)), -3, 3);
2548 @rmdir(PATH_site . 'typo3temp/' . $subDirectory);
2549 @rmdir(PATH_site . 'typo3temp/' . $directory);
2550 umask($oldUmask);
2551 $this->assertEquals($resultDirectoryPermissions, '777');
2552 }
2553
2554 /**
2555 * @test
2556 */
2557 public function mkdirDeepDoesNotChangePermissionsOfExistingSubDirectories() {
2558 if (TYPO3_OS == 'WIN') {
2559 $this->markTestSkipped('mkdirDeepDoesNotChangePermissionsOfExistingSubDirectories() test not available on Windows.');
2560 }
2561
2562 $baseDirectory = PATH_site . 'typo3temp/';
2563 $existingDirectory = uniqid('test_existing_') . '/';
2564 $newSubDirectory = uniqid('test_new_');
2565 @mkdir($baseDirectory . $existingDirectory);
2566 chmod($baseDirectory . $existingDirectory, 0742);
2567 t3lib_div::mkdir_deep($baseDirectory, $existingDirectory . $newSubDirectory);
2568 $resultExistingDirectoryPermissions = substr(decoct(fileperms($baseDirectory . $existingDirectory)), 2);
2569 @rmdir($baseDirectory, $existingDirectory . $newSubDirectory);
2570 @rmdir($baseDirectory, $existingDirectory);
2571 $this->assertEquals($resultExistingDirectoryPermissions, '0742');
2572 }
2573
2574 /**
2575 * @test
2576 */
2577 public function mkdirDeepSetsGroupOwnershipOfCreatedDirectory() {
2578 $swapGroup = $this->checkGroups(__FUNCTION__);
2579 if ($swapGroup!==FALSE) {
2580 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
2581 $directory = uniqid('mkdirdeeptest_');
2582 t3lib_div::mkdir_deep(PATH_site . 'typo3temp/', $directory);
2583 clearstatcache();
2584 $resultDirectoryGroupInfo = posix_getgrgid((filegroup(PATH_site . 'typo3temp/' . $directory)));
2585 $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
2586 @rmdir(PATH_site . 'typo3temp/' . $directory);
2587 $this->assertEquals($resultDirectoryGroup, $swapGroup);
2588 }
2589 }
2590
2591 /**
2592 * @test
2593 */
2594 public function mkdirDeepSetsGroupOwnershipOfCreatedParentDirectory() {
2595 $swapGroup = $this->checkGroups(__FUNCTION__);
2596 if ($swapGroup!==FALSE) {
2597 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
2598 $directory = uniqid('mkdirdeeptest_');
2599 $subDirectory = $directory . '/bar';
2600 t3lib_div::mkdir_deep(PATH_site . 'typo3temp/', $subDirectory);
2601 clearstatcache();
2602 $resultDirectoryGroupInfo = posix_getgrgid((filegroup(PATH_site . 'typo3temp/' . $directory)));
2603 $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
2604 @rmdir(PATH_site . 'typo3temp/' . $subDirectory);
2605 @rmdir(PATH_site . 'typo3temp/' . $directory);
2606 $this->assertEquals($resultDirectoryGroup, $swapGroup);
2607 }
2608 }
2609
2610 /**
2611 * @test
2612 */
2613 public function mkdirDeepSetsGroupOwnershipOnNewSubDirectory() {
2614 $swapGroup = $this->checkGroups(__FUNCTION__);
2615 if ($swapGroup!==FALSE) {
2616 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
2617 $directory = uniqid('mkdirdeeptest_');
2618 $subDirectory = $directory . '/bar';
2619 t3lib_div::mkdir_deep(PATH_site . 'typo3temp/', $subDirectory);
2620 clearstatcache();
2621 $resultDirectoryGroupInfo = posix_getgrgid((filegroup(PATH_site . 'typo3temp/' . $subDirectory)));
2622 $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
2623 @rmdir(PATH_site . 'typo3temp/' . $subDirectory);
2624 @rmdir(PATH_site . 'typo3temp/' . $directory);
2625 $this->assertEquals($resultDirectoryGroup, $swapGroup);
2626 }
2627 }
2628
2629 /**
2630 * @test
2631 */
2632 public function mkdirDeepCreatesDirectoryInVfsStream() {
2633 if (!class_exists('\vfsStreamWrapper')) {
2634 $this->markTestSkipped('mkdirDeepCreatesDirectoryInVfsStream() test not available with this phpunit version.');
2635 }
2636
2637 \vfsStreamWrapper::register();
2638 $baseDirectory = uniqid('test_');
2639 \vfsStreamWrapper::setRoot(new \vfsStreamDirectory($baseDirectory));
2640 t3lib_div::mkdir_deep('vfs://' . $baseDirectory . '/', 'sub');
2641 $this->assertTrue(is_dir('vfs://' . $baseDirectory . '/sub'));
2642 }
2643
2644 /**
2645 * @test
2646 * @expectedException \RuntimeException
2647 */
2648 public function mkdirDeepThrowsExceptionIfDirectoryCreationFails() {
2649 t3lib_div::mkdir_deep('http://localhost');
2650 }
2651
2652 /**
2653 * @test
2654 * @expectedException \InvalidArgumentException
2655 */
2656 public function mkdirDeepThrowsExceptionIfBaseDirectoryIsNotOfTypeString() {
2657 t3lib_div::mkdir_deep(array());
2658 }
2659
2660 /**
2661 * @test
2662 * @expectedException \InvalidArgumentException
2663 */
2664 public function mkdirDeepThrowsExceptionIfDeepDirectoryIsNotOfTypeString() {
2665 t3lib_div::mkdir_deep(PATH_site . 'typo3temp/foo', array());
2666 }
2667
2668
2669 ///////////////////////////////
2670 // Tests concerning unQuoteFilenames
2671 ///////////////////////////////
2672
2673 /**
2674 * Data provider for ImageMagick shell commands
2675 * @see explodeAndUnquoteImageMagickCommands
2676 */
2677 public function imageMagickCommandsDataProvider() {
2678 return array(
2679 // Some theoretical tests first
2680 array(
2681 'aa bb "cc" "dd"',
2682 array('aa', 'bb', '"cc"', '"dd"'),
2683 array('aa', 'bb', 'cc', 'dd'),
2684 ),
2685 array(
2686 'aa bb "cc dd"',
2687 array('aa', 'bb', '"cc dd"'),
2688 array('aa', 'bb', 'cc dd'),
2689 ),
2690 array(
2691 '\'aa bb\' "cc dd"',
2692 array('\'aa bb\'', '"cc dd"'),
2693 array('aa bb', 'cc dd'),
2694 ),
2695 array(
2696 '\'aa bb\' cc "dd"',
2697 array('\'aa bb\'', 'cc', '"dd"'),
2698 array('aa bb', 'cc', 'dd'),
2699 ),
2700 // Now test against some real world examples
2701 array(
2702 '/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"',
2703 array(
2704 '/opt/local/bin/gm.exe',
2705 'convert',
2706 '+profile',
2707 '\'*\'',
2708 '-geometry',
2709 '170x136!',
2710 '-negate',
2711 '"C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
2712 '"C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
2713 ),
2714 array(
2715 '/opt/local/bin/gm.exe',
2716 'convert',
2717 '+profile',
2718 '*',
2719 '-geometry',
2720 '170x136!',
2721 '-negate',
2722 'C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
2723 'C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
2724 ),
2725 ),
2726 array(
2727 '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"',
2728 array(
2729 'C:/opt/local/bin/gm.exe',
2730 'convert',
2731 '+profile',
2732 '\'*\'',
2733 '-geometry',
2734 '170x136!',
2735 '-negate',
2736 '"C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
2737 '"C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
2738 ),
2739 array(
2740 'C:/opt/local/bin/gm.exe',
2741 'convert',
2742 '+profile',
2743 '*',
2744 '-geometry',
2745 '170x136!',
2746 '-negate',
2747 'C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
2748 'C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
2749 ),
2750 ),
2751 array(
2752 '/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"',
2753 array(
2754 '/usr/bin/gm',
2755 'convert',
2756 '+profile',
2757 '\'*\'',
2758 '-geometry',
2759 '170x136!',
2760 '-negate',
2761 '"/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
2762 '"/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
2763 ),
2764 array(
2765 '/usr/bin/gm',
2766 'convert',
2767 '+profile',
2768 '*',
2769 '-geometry',
2770 '170x136!',
2771 '-negate',
2772 '/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
2773 '/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
2774 ),
2775 ),
2776 array(
2777 '/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"',
2778 array(
2779 '/usr/bin/gm',
2780 'convert',
2781 '+profile',
2782 '\'*\'',
2783 '-geometry',
2784 '170x136!',
2785 '-negate',
2786 '"/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
2787 '"/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
2788 ),
2789 array(
2790 '/usr/bin/gm',
2791 'convert',
2792 '+profile',
2793 '*',
2794 '-geometry',
2795 '170x136!',
2796 '-negate',
2797 '/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
2798 '/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
2799 ),
2800 ),
2801 array(
2802 '/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\'',
2803 array(
2804 '/usr/bin/gm',
2805 'convert',
2806 '+profile',
2807 '\'*\'',
2808 '-geometry',
2809 '170x136!',
2810 '-negate',
2811 '\'/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]\'',
2812 '\'/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif\''
2813 ),
2814 array(
2815 '/usr/bin/gm',
2816 'convert',
2817 '+profile',
2818 '*',
2819 '-geometry',
2820 '170x136!',
2821 '-negate',
2822 '/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
2823 '/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
2824 ),
2825 ),
2826 );
2827 }
2828
2829 /**
2830 * Tests if the commands are exploded and unquoted correctly
2831 *
2832 * @dataProvider imageMagickCommandsDataProvider
2833 * @test
2834 */
2835 public function explodeAndUnquoteImageMagickCommands($source, $expectedQuoted, $expectedUnquoted) {
2836 $actualQuoted = t3lib_div::unQuoteFilenames($source);
2837 $acutalUnquoted = t3lib_div::unQuoteFilenames($source, TRUE);
2838
2839 $this->assertEquals($expectedQuoted, $actualQuoted, 'The exploded command does not match the expected');
2840 $this->assertEquals($expectedUnquoted, $acutalUnquoted, 'The exploded and unquoted command does not match the expected');
2841 }
2842
2843
2844 ///////////////////////////////
2845 // Tests concerning split_fileref
2846 ///////////////////////////////
2847
2848 /**
2849 * @test
2850 */
2851 public function splitFileRefReturnsFileTypeNotForFolders(){
2852 $directoryName = uniqid('test_') . '.com';
2853 $directoryPath = PATH_site . 'typo3temp/';
2854 $directory = $directoryPath . $directoryName;
2855 mkdir($directory, octdec($GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask']));
2856
2857 $fileInfo = t3lib_div::split_fileref($directory);
2858
2859 $directoryCreated = is_dir($directory);
2860 rmdir($directory);
2861
2862 $this->assertTrue($directoryCreated);
2863 $this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $fileInfo);
2864 $this->assertEquals($directoryPath, $fileInfo['path']);
2865 $this->assertEquals($directoryName, $fileInfo['file']);
2866 $this->assertEquals($directoryName, $fileInfo['filebody']);
2867 $this->assertEquals('', $fileInfo['fileext']);
2868 $this->assertArrayNotHasKey('realFileext', $fileInfo);
2869 }
2870
2871 /**
2872 * @test
2873 */
2874 public function splitFileRefReturnsFileTypeForFilesWithoutPathSite() {
2875 $testFile = 'fileadmin/media/someFile.png';
2876
2877 $fileInfo = t3lib_div::split_fileref($testFile);
2878 $this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $fileInfo);
2879 $this->assertEquals('fileadmin/media/', $fileInfo['path']);
2880 $this->assertEquals('someFile.png', $fileInfo['file']);
2881 $this->assertEquals('someFile', $fileInfo['filebody']);
2882 $this->assertEquals('png', $fileInfo['fileext']);
2883 }
2884
2885
2886 /////////////////////////////
2887 // Tests concerning dirname
2888 /////////////////////////////
2889
2890 /**
2891 * @see dirnameWithDataProvider
2892 *
2893 * @return array<array>
2894 */
2895 public function dirnameDataProvider() {
2896 return array(
2897 'absolute path with multiple part and file' => array('/dir1/dir2/script.php', '/dir1/dir2'),
2898 'absolute path with one part' => array('/dir1/', '/dir1'),
2899 'absolute path to file without extension' => array('/dir1/something', '/dir1'),
2900 'relative path with one part and file' => array('dir1/script.php', 'dir1'),
2901 'relative one-character path with one part and file' => array('d/script.php', 'd'),
2902 'absolute zero-part path with file' => array('/script.php', ''),
2903 'empty string' => array('', ''),
2904 );
2905 }
2906
2907 /**
2908 * @test
2909 *
2910 * @dataProvider dirnameDataProvider
2911 *
2912 * @param string $input the input for dirname
2913 * @param string $expectedValue the expected return value expected from dirname
2914 */
2915 public function dirnameWithDataProvider($input, $expectedValue) {
2916 $this->assertEquals(
2917 $expectedValue,
2918 t3lib_div::dirname($input)
2919 );
2920 }
2921
2922
2923 /////////////////////////////////////
2924 // Tests concerning resolveBackPath
2925 /////////////////////////////////////
2926
2927 /**
2928 * @see resolveBackPathWithDataProvider
2929 *
2930 * @return array<array>
2931 */
2932 public function resolveBackPathDataProvider() {
2933 return array(
2934 'empty path' => array('', ''),
2935 'this directory' => array('./', './'),
2936 'relative directory without ..' => array('dir1/dir2/dir3/', 'dir1/dir2/dir3/'),
2937 'relative path without ..' => array('dir1/dir2/script.php', 'dir1/dir2/script.php'),
2938 'absolute directory without ..' => array('/dir1/dir2/dir3/', '/dir1/dir2/dir3/'),
2939 'absolute path without ..' => array('/dir1/dir2/script.php', '/dir1/dir2/script.php'),
2940 'only one directory upwards without trailing slash' => array('..', '..'),
2941 'only one directory upwards with trailing slash' => array('../', '../'),
2942 'one level with trailing ..' => array('dir1/..', ''),
2943 'one level with trailing ../' => array('dir1/../', ''),
2944 'two levels with trailing ..' => array('dir1/dir2/..', 'dir1'),
2945 'two levels with trailing ../' => array('dir1/dir2/../', 'dir1/'),
2946 'leading ../ without trailing /' => array('../dir1', '../dir1'),
2947 'leading ../ with trailing /' => array('../dir1/', '../dir1/'),
2948 'leading ../ and inside path' => array('../dir1/dir2/../dir3/', '../dir1/dir3/'),
2949 'one times ../ in relative directory' => array('dir1/../dir2/', 'dir2/'),
2950 'one times ../ in absolute directory' => array('/dir1/../dir2/', '/dir2/'),
2951 'one times ../ in relative path' => array('dir1/../dir2/script.php', 'dir2/script.php'),
2952 'one times ../ in absolute path' => array('/dir1/../dir2/script.php', '/dir2/script.php'),
2953 'consecutive ../' => array('dir1/dir2/dir3/../../../dir4', 'dir4'),
2954 'distrubuted ../ with trailing /' => array('dir1/../dir2/dir3/../', 'dir2/'),
2955 'distributed ../ without trailing /' => array('dir1/../dir2/dir3/..', 'dir2'),
2956 'multiple distributed and consecutive ../ together' => array('dir1/dir2/dir3/dir4/../../dir5/dir6/dir7/../dir8/', 'dir1/dir2/dir5/dir6/dir8/'),
2957 'multiple distributed and consecutive ../ together' => array('dir1/dir2/dir3/dir4/../../dir5/dir6/dir7/../dir8/', 'dir1/dir2/dir5/dir6/dir8/'),
2958 'dirname with leading ..' => array('dir1/..dir2/dir3/', 'dir1/..dir2/dir3/'),
2959 'dirname with trailing ..' => array('dir1/dir2../dir3/', 'dir1/dir2../dir3/'),
2960 'more times upwards than downwards in directory' => array('dir1/../../', '../'),
2961 'more times upwards than downwards in path' => array('dir1/../../script.php', '../script.php'),
2962 );
2963 }
2964
2965 /**
2966 * @test
2967 *
2968 * @dataProvider resolveBackPathDataProvider
2969 *
2970 * @param string $input the input for resolveBackPath
2971 * @param $expectedValue the expected return value from resolveBackPath
2972 */
2973 public function resolveBackPathWithDataProvider($input, $expectedValue) {
2974 $this->assertEquals(
2975 $expectedValue,
2976 t3lib_div::resolveBackPath($input)
2977 );
2978 }
2979
2980
2981 /////////////////////////////////////////////////////////////////////////////////////
2982 // Tests concerning makeInstance, setSingletonInstance, addInstance, purgeInstances
2983 /////////////////////////////////////////////////////////////////////////////////////
2984
2985 /**
2986 * @test
2987 * @expectedException InvalidArgumentException
2988 */
2989 public function makeInstanceWithEmptyClassNameThrowsException() {
2990 t3lib_div::makeInstance('');
2991 }
2992
2993 /**
2994 * @test
2995 * @expectedException InvalidArgumentException
2996 */
2997 public function makeInstanceWithNullClassNameThrowsException() {
2998 t3lib_div::makeInstance(NULL);
2999 }
3000
3001 /**
3002 * @test
3003 * @expectedException InvalidArgumentException
3004 */
3005 public function makeInstanceWithZeroStringClassNameThrowsException() {
3006 t3lib_div::makeInstance(0);
3007 }
3008
3009 /**
3010 * @test
3011 * @expectedException InvalidArgumentException
3012 */
3013 public function makeInstanceWithEmptyArrayThrowsException() {
3014 t3lib_div::makeInstance(array());
3015 }
3016
3017 /**
3018 * @test
3019 * @expectedException InvalidArgumentException
3020 */
3021 public function makeInstanceWithNonEmptyArrayThrowsException() {
3022 t3lib_div::makeInstance(array('foo'));
3023 }
3024
3025 /**
3026 * @test
3027 */
3028 public function makeInstanceReturnsClassInstance() {
3029 $className = get_class($this->getMock('foo'));
3030
3031 $this->assertTrue(
3032 t3lib_div::makeInstance($className) instanceof $className
3033 );
3034 }
3035
3036 /**
3037 * @test
3038 */
3039 public function makeInstancePassesParametersToConstructor() {
3040 $className = 'testingClass' . uniqid();
3041 if (!class_exists($className, FALSE)) {
3042 eval(
3043 'class ' . $className . ' {' .
3044 ' public $constructorParameter1;' .
3045 ' public $constructorParameter2;' .
3046 ' public function __construct($parameter1, $parameter2) {' .
3047 ' $this->constructorParameter1 = $parameter1;' .
3048 ' $this->constructorParameter2 = $parameter2;' .
3049 ' }' .
3050 '}'
3051 );
3052 }
3053
3054 $instance = t3lib_div::makeInstance($className, 'one parameter', 'another parameter');
3055
3056 $this->assertEquals(
3057 'one parameter',
3058 $instance->constructorParameter1,
3059 'The first constructor parameter has not been set.'
3060 );
3061 $this->assertEquals(
3062 'another parameter',
3063 $instance->constructorParameter2,
3064 'The second constructor parameter has not been set.'
3065 );
3066 }
3067
3068 /**
3069 * @test
3070 */
3071 public function makeInstanceCalledTwoTimesForNonSingletonClassReturnsDifferentInstances() {
3072 $className = get_class($this->getMock('foo'));
3073
3074 $this->assertNotSame(
3075 t3lib_div::makeInstance($className),
3076 t3lib_div::makeInstance($className)
3077 );
3078 }
3079
3080 /**
3081 * @test
3082 */
3083 public function makeInstanceCalledTwoTimesForSingletonClassReturnsSameInstance() {
3084 $className = get_class($this->getMock('t3lib_Singleton'));
3085
3086 $this->assertSame(
3087 t3lib_div::makeInstance($className),
3088 t3lib_div::makeInstance($className)
3089 );
3090 }
3091
3092 /**
3093 * @test
3094 */
3095 public function makeInstanceCalledTwoTimesForSingletonClassWithPurgeInstancesInbetweenReturnsDifferentInstances() {
3096 $className = get_class($this->getMock('t3lib_Singleton'));
3097
3098 $instance = t3lib_div::makeInstance($className);
3099 t3lib_div::purgeInstances();
3100
3101 $this->assertNotSame(
3102 $instance,
3103 t3lib_div::makeInstance($className)
3104 );
3105 }
3106
3107 /**
3108 * @test
3109 * @expectedException InvalidArgumentException
3110 */
3111 public function setSingletonInstanceForEmptyClassNameThrowsException() {
3112 $instance = $this->getMock('t3lib_Singleton');
3113
3114 t3lib_div::setSingletonInstance('', $instance);
3115 }
3116
3117 /**
3118 * @test
3119 * @expectedException InvalidArgumentException
3120 */
3121 public function setSingletonInstanceForClassThatIsNoSubclassOfProvidedClassThrowsException() {
3122 $instance = $this->getMock('t3lib_Singleton', array('foo'));
3123 $singletonClassName = get_class($this->getMock('t3lib_Singleton'));
3124
3125 t3lib_div::setSingletonInstance($singletonClassName, $instance);
3126 }
3127
3128 /**
3129 * @test
3130 */
3131 public function setSingletonInstanceMakesMakeInstanceReturnThatInstance() {
3132 $instance = $this->getMock('t3lib_Singleton');
3133 $singletonClassName = get_class($instance);
3134
3135 t3lib_div::setSingletonInstance($singletonClassName, $instance);
3136
3137 $this->assertSame(
3138 $instance,
3139 t3lib_div::makeInstance($singletonClassName)
3140 );
3141 }
3142
3143 /**
3144 * @test
3145 */
3146 public function setSingletonInstanceCalledTwoTimesMakesMakeInstanceReturnLastSetInstance() {
3147 $instance1 = $this->getMock('t3lib_Singleton');
3148 $singletonClassName = get_class($instance1);
3149 $instance2 = new $singletonClassName();
3150
3151 t3lib_div::setSingletonInstance($singletonClassName, $instance1);
3152 t3lib_div::setSingletonInstance($singletonClassName, $instance2);
3153
3154 $this->assertSame(
3155 $instance2,
3156 t3lib_div::makeInstance($singletonClassName)
3157 );
3158 }
3159
3160 /**
3161 * @test
3162 * @expectedException InvalidArgumentException
3163 */
3164 public function addInstanceForEmptyClassNameThrowsException() {
3165 $instance = $this->getMock('foo');
3166
3167 t3lib_div::addInstance('', $instance);
3168 }
3169
3170 /**
3171 * @test
3172 * @expectedException InvalidArgumentException
3173 */
3174 public function addInstanceForClassThatIsNoSubclassOfProvidedClassThrowsException() {
3175 $instance = $this->getMock('foo', array('bar'));
3176 $singletonClassName = get_class($this->getMock('foo'));
3177
3178 t3lib_div::addInstance($singletonClassName, $instance);
3179 }
3180
3181 /**
3182 * @test
3183 * @expectedException InvalidArgumentException
3184 */
3185 public function addInstanceWithSingletonInstanceThrowsException() {
3186 $instance = $this->getMock('t3lib_Singleton');
3187
3188 t3lib_div::addInstance(get_class($instance), $instance);
3189 }
3190
3191 /**
3192 * @test
3193 */
3194 public function addInstanceMakesMakeInstanceReturnThatInstance() {
3195 $instance = $this->getMock('foo');
3196 $className = get_class($instance);
3197
3198 t3lib_div::addInstance($className, $instance);
3199
3200 $this->assertSame(
3201 $instance,
3202 t3lib_div::makeInstance($className)
3203 );
3204 }
3205
3206 /**
3207 * @test
3208 */
3209 public function makeInstanceCalledTwoTimesAfterAddInstanceReturnTwoDifferentInstances() {
3210 $instance = $this->getMock('foo');
3211 $className = get_class($instance);
3212
3213 t3lib_div::addInstance($className, $instance);
3214
3215 $this->assertNotSame(
3216 t3lib_div::makeInstance($className),
3217 t3lib_div::makeInstance($className)
3218 );
3219 }
3220
3221 /**
3222 * @test
3223 */
3224 public function addInstanceCalledTwoTimesMakesMakeInstanceReturnBothInstancesInAddingOrder() {
3225 $instance1 = $this->getMock('foo');
3226 $className = get_class($instance1);
3227 t3lib_div::addInstance($className, $instance1);
3228
3229 $instance2 = new $className();
3230 t3lib_div::addInstance($className, $instance2);
3231
3232 $this->assertSame(
3233 $instance1,
3234 t3lib_div::makeInstance($className),
3235 'The first returned instance does not match the first added instance.'
3236 );
3237 $this->assertSame(
3238 $instance2,
3239 t3lib_div::makeInstance($className),
3240 'The second returned instance does not match the second added instance.'
3241 );
3242 }
3243
3244 /**
3245 * @test
3246 */
3247 public function purgeInstancesDropsAddedInstance() {
3248 $instance = $this->getMock('foo');
3249 $className = get_class($instance);
3250
3251 t3lib_div::addInstance($className, $instance);
3252 t3lib_div::purgeInstances();
3253
3254 $this->assertNotSame(
3255 $instance,
3256 t3lib_div::makeInstance($className)
3257 );
3258 }
3259
3260 /**
3261 * Data provider for validPathStrDetectsInvalidCharacters.
3262 *
3263 * @return array
3264 */
3265 public function validPathStrInvalidCharactersDataProvider() {
3266 return array(
3267 'double slash in path' => array('path//path'),
3268 'backslash in path' => array('path\\path'),
3269 'directory up in path' => array('path/../path'),
3270 'directory up at the beginning' => array('../path'),
3271 'NUL character in path' => array("path\x00path"),
3272 'BS character in path' => array("path\x08path"),
3273 );
3274 }
3275
3276 /**
3277 * Tests whether invalid characters are detected.
3278 *
3279 * @param string $path
3280 * @dataProvider validPathStrInvalidCharactersDataProvider
3281 * @test
3282 */
3283 public function validPathStrDetectsInvalidCharacters($path) {
3284 $this->assertNull(t3lib_div::validPathStr($path));
3285 }
3286
3287 /**
3288 * Tests whether Unicode characters are recognized as valid file name characters.
3289 *
3290 * @test
3291 */
3292 public function validPathStrWorksWithUnicodeFileNames() {
3293 $this->assertTrue(t3lib_div::validPathStr('fileadmin/templates/Ссылка (fce).xml'));
3294 }
3295
3296 /**
3297 * Tests whether verifyFilenameAgainstDenyPattern detects the NULL character.
3298 *
3299 * @test
3300 */
3301 public function verifyFilenameAgainstDenyPatternDetectsNullCharacter() {
3302 $this->assertFalse(t3lib_div::verifyFilenameAgainstDenyPattern("image\x00.gif"));
3303 }
3304
3305
3306 /////////////////////////////////////////////////////////////////////////////////////
3307 // Tests concerning sysLog
3308 /////////////////////////////////////////////////////////////////////////////////////
3309
3310 /**
3311 * @test
3312 */
3313 public function syslogFixesPermissionsOnFileIfUsingFileLogging() {
3314 if (TYPO3_OS == 'WIN') {
3315 $this->markTestSkipped('syslogFixesPermissionsOnFileIfUsingFileLogging() test not available on Windows.');
3316 }
3317
3318 // Fake all required settings
3319 $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLogLevel'] = 0;
3320 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogInit'] = TRUE;
3321 unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog']);
3322 $testLogFilename = PATH_site . 'typo3temp/' . uniqid('test_') . '.txt';
3323 $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLog'] = 'file,' . $testLogFilename . ',0';
3324 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
3325
3326 // Call method, get actual permissions and clean up
3327 t3lib_div::syslog('testLog', 'test', 1);
3328 clearstatcache();
3329 $resultFilePermissions = substr(decoct(fileperms($testLogFilename)), 2);
3330 t3lib_div::unlink_tempfile($testLogFilename);
3331
3332 $this->assertEquals($resultFilePermissions, '0777');
3333 }
3334
3335 /**
3336 * @test
3337 */
3338 public function deprecationLogFixesPermissionsOnLogFile() {