TYPO3 CMS  TYPO3_6-2
GeneralUtilityTest.php
Go to the documentation of this file.
1 <?php
3 
19 use \org\bovigo\vfs\vfsStream;
20 use \org\bovigo\vfs\vfsStreamDirectory;
21 use \org\bovigo\vfs\vfsStreamWrapper;
22 
30 
34  protected $testFilesToDelete = array();
35 
39  protected $singletonInstances = array();
40 
41  public function setUp() {
44  $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] = Utility\GeneralUtility::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL;
45  $this->singletonInstances = Utility\GeneralUtility::getSingletonInstances();
46  }
47 
48  public function tearDown() {
49  Utility\GeneralUtility::resetSingletonInstances($this->singletonInstances);
50  foreach ($this->testFilesToDelete as $absoluteFileName) {
51  Utility\GeneralUtility::rmdir($absoluteFileName, TRUE);
52  }
53  parent::tearDown();
54  }
55 
62  public function isConnected() {
63  $isConnected = FALSE;
64  $connected = @fsockopen('typo3.org', 80);
65  if ($connected) {
66  $isConnected = TRUE;
67  fclose($connected);
68  }
69  return $isConnected;
70  }
71 
73  // Tests concerning _GP
75 
79  public function canRetrieveValueWithGP($key, $get, $post, $expected) {
80  $_GET = $get;
81  $_POST = $post;
82  $this->assertSame($expected, Utility\GeneralUtility::_GP($key));
83  }
84 
91  public function gpDataProvider() {
92  return array(
93  'No key parameter' => array(NULL, array(), array(), NULL),
94  'Key not found' => array('cake', array(), array(), NULL),
95  'Value only in GET' => array('cake', array('cake' => 'li\\e'), array(), 'lie'),
96  'Value only in POST' => array('cake', array(), array('cake' => 'l\\ie'), 'lie'),
97  'Value from POST preferred over GET' => array('cake', array('cake' => 'is a'), array('cake' => '\\lie'), 'lie'),
98  'Value can be an array' => array(
99  'cake',
100  array('cake' => array('is a' => 'l\\ie')),
101  array(),
102  array('is a' => 'lie')
103  )
104  );
105  }
106 
108  // Tests concerning _GPmerged
110 
114  public function gpMergedWillMergeArraysFromGetAndPost($get, $post, $expected) {
115  $_POST = $post;
116  $_GET = $get;
117  $this->assertEquals($expected, Utility\GeneralUtility::_GPmerged('cake'));
118  }
119 
125  public function gpMergedDataProvider() {
126  $fullDataArray = array('cake' => array('a' => 'is a', 'b' => 'lie'));
127  $postPartData = array('cake' => array('b' => 'lie'));
128  $getPartData = array('cake' => array('a' => 'is a'));
129  $getPartDataModified = array('cake' => array('a' => 'is not a'));
130  return array(
131  'Key doesn\' exist' => array(array('foo'), array('bar'), array()),
132  'No POST data' => array($fullDataArray, array(), $fullDataArray['cake']),
133  'No GET data' => array(array(), $fullDataArray, $fullDataArray['cake']),
134  'POST and GET are merged' => array($getPartData, $postPartData, $fullDataArray['cake']),
135  'POST is preferred over GET' => array($getPartDataModified, $fullDataArray, $fullDataArray['cake'])
136  );
137  }
138 
140  // Tests concerning _GET / _POST
142 
148  public function getAndPostDataProvider() {
149  return array(
150  'Requested input data doesn\'t exist' => array('cake', array(), NULL),
151  'No key will return entire input data' => array(NULL, array('cake' => 'l\\ie'), array('cake' => 'lie')),
152  'Can retrieve specific input' => array('cake', array('cake' => 'li\\e', 'foo'), 'lie'),
153  'Can retrieve nested input data' => array('cake', array('cake' => array('is a' => 'l\\ie')), array('is a' => 'lie'))
154  );
155  }
156 
161  public function canRetrieveGlobalInputsThroughGet($key, $get, $expected) {
162  $_GET = $get;
163  $this->assertSame($expected, Utility\GeneralUtility::_GET($key));
164  }
165 
170  public function canRetrieveGlobalInputsThroughPost($key, $post, $expected) {
171  $_POST = $post;
172  $this->assertSame($expected, Utility\GeneralUtility::_POST($key));
173  }
174 
176  // Tests concerning _GETset
178 
182  public function canSetNewGetInputValues($input, $key, $expected, $getPreset = array()) {
183  $_GET = $getPreset;
184  Utility\GeneralUtility::_GETset($input, $key);
185  $this->assertSame($expected, $_GET);
186  }
187 
193  public function getSetDataProvider() {
194  return array(
195  'No input data used without target key' => array(NULL, NULL, array()),
196  'No input data used with target key' => array(NULL, 'cake', array('cake' => '')),
197  'No target key used with string input data' => array('data', NULL, array()),
198  'No target key used with array input data' => array(array('cake' => 'lie'), NULL, array('cake' => 'lie')),
199  'Target key and string input data' => array('lie', 'cake', array('cake' => 'lie')),
200  'Replace existing GET data' => array('lie', 'cake', array('cake' => 'lie'), array('cake' => 'is a lie')),
201  'Target key pointing to sublevels and string input data' => array('lie', 'cake|is', array('cake' => array('is' => 'lie'))),
202  'Target key pointing to sublevels and array input data' => array(array('a' => 'lie'), 'cake|is', array('cake' => array('is' => array('a' => 'lie'))))
203  );
204  }
205 
207  // Tests concerning cmpIPv4
209 
214  static public function cmpIPv4DataProviderMatching() {
215  return array(
216  'host with full IP address' => array('127.0.0.1', '127.0.0.1'),
217  'host with two wildcards at the end' => array('127.0.0.1', '127.0.*.*'),
218  'host with wildcard at third octet' => array('127.0.0.1', '127.0.*.1'),
219  'host with wildcard at second octet' => array('127.0.0.1', '127.*.0.1'),
220  '/8 subnet' => array('127.0.0.1', '127.1.1.1/8'),
221  '/32 subnet (match only name)' => array('127.0.0.1', '127.0.0.1/32'),
222  '/30 subnet' => array('10.10.3.1', '10.10.3.3/30'),
223  'host with wildcard in list with IPv4/IPv6 addresses' => array('192.168.1.1', '127.0.0.1, 1234:5678::/126, 192.168.*'),
224  'host in list with IPv4/IPv6 addresses' => array('192.168.1.1', '::1, 1234:5678::/126, 192.168.1.1'),
225  );
226  }
227 
232  public function cmpIPv4ReturnsTrueForMatchingAddress($ip, $list) {
233  $this->assertTrue(Utility\GeneralUtility::cmpIPv4($ip, $list));
234  }
235 
241  static public function cmpIPv4DataProviderNotMatching() {
242  return array(
243  'single host' => array('127.0.0.1', '127.0.0.2'),
244  'single host with wildcard' => array('127.0.0.1', '127.*.1.1'),
245  'single host with /32 subnet mask' => array('127.0.0.1', '127.0.0.2/32'),
246  '/31 subnet' => array('127.0.0.1', '127.0.0.2/31'),
247  'list with IPv4/IPv6 addresses' => array('127.0.0.1', '10.0.2.3, 192.168.1.1, ::1'),
248  'list with only IPv6 addresses' => array('10.20.30.40', '::1, 1234:5678::/127')
249  );
250  }
251 
256  public function cmpIPv4ReturnsFalseForNotMatchingAddress($ip, $list) {
257  $this->assertFalse(Utility\GeneralUtility::cmpIPv4($ip, $list));
258  }
259 
261  // Tests concerning cmpIPv6
263 
268  static public function cmpIPv6DataProviderMatching() {
269  return array(
270  'empty address' => array('::', '::'),
271  'empty with netmask in list' => array('::', '::/0'),
272  'empty with netmask 0 and host-bits set in list' => array('::', '::123/0'),
273  'localhost' => array('::1', '::1'),
274  'localhost with leading zero blocks' => array('::1', '0:0::1'),
275  'host with submask /128' => array('::1', '0:0::1/128'),
276  '/16 subnet' => array('1234::1', '1234:5678::/16'),
277  '/126 subnet' => array('1234:5678::3', '1234:5678::/126'),
278  '/126 subnet with host-bits in list set' => array('1234:5678::3', '1234:5678::2/126'),
279  'list with IPv4/IPv6 addresses' => array('1234:5678::3', '::1, 127.0.0.1, 1234:5678::/126, 192.168.1.1')
280  );
281  }
282 
287  public function cmpIPv6ReturnsTrueForMatchingAddress($ip, $list) {
288  $this->assertTrue(Utility\GeneralUtility::cmpIPv6($ip, $list));
289  }
290 
296  static public function cmpIPv6DataProviderNotMatching() {
297  return array(
298  'empty against localhost' => array('::', '::1'),
299  'empty against localhost with /128 netmask' => array('::', '::1/128'),
300  'localhost against different host' => array('::1', '::2'),
301  'localhost against host with prior bits set' => array('::1', '::1:1'),
302  'host against different /17 subnet' => array('1234::1', '1234:f678::/17'),
303  'host against different /127 subnet' => array('1234:5678::3', '1234:5678::/127'),
304  'host against IPv4 address list' => array('1234:5678::3', '127.0.0.1, 192.168.1.1'),
305  'host against mixed list with IPv6 host in different subnet' => array('1234:5678::3', '::1, 1234:5678::/127')
306  );
307  }
308 
313  public function cmpIPv6ReturnsFalseForNotMatchingAddress($ip, $list) {
314  $this->assertFalse(Utility\GeneralUtility::cmpIPv6($ip, $list));
315  }
316 
318  // Tests concerning IPv6Hex2Bin
320 
325  static public function IPv6Hex2BinDataProviderCorrect() {
326  return array(
327  'empty 1' => array('::', str_pad('', 16, "\x00")),
328  'empty 2, already normalized' => array('0000:0000:0000:0000:0000:0000:0000:0000', str_pad('', 16, "\x00")),
329  'already normalized' => array('0102:0304:0000:0000:0000:0000:0506:0078', "\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78"),
330  'expansion in middle 1' => array('1::2', "\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02"),
331  'expansion in middle 2' => array('beef::fefa', "\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa"),
332  );
333  }
334 
339  public function IPv6Hex2BinCorrectlyConvertsAddresses($hex, $binary) {
340  $this->assertTrue(Utility\GeneralUtility::IPv6Hex2Bin($hex) === $binary);
341  }
342 
344  // Tests concerning IPv6Bin2Hex
346 
351  static public function IPv6Bin2HexDataProviderCorrect() {
352  return array(
353  'empty' => array(str_pad('', 16, "\x00"), '::'),
354  'non-empty front' => array("\x01" . str_pad('', 15, "\x00"), '100::'),
355  'non-empty back' => array(str_pad('', 15, "\x00") . "\x01", '::1'),
356  'normalized' => array("\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78", '102:304::506:78'),
357  'expansion in middle 1' => array("\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02", '1::2'),
358  'expansion in middle 2' => array("\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa", 'beef::fefa'),
359  );
360  }
361 
366  public function IPv6Bin2HexCorrectlyConvertsAddresses($binary, $hex) {
367  $this->assertEquals(Utility\GeneralUtility::IPv6Bin2Hex($binary), $hex);
368  }
369 
371  // Tests concerning normalizeIPv6 / compressIPv6
373 
378  static public function normalizeCompressIPv6DataProviderCorrect() {
379  return array(
380  'empty' => array('::', '0000:0000:0000:0000:0000:0000:0000:0000'),
381  'localhost' => array('::1', '0000:0000:0000:0000:0000:0000:0000:0001'),
382  'expansion in middle 1' => array('1::2', '0001:0000:0000:0000:0000:0000:0000:0002'),
383  'expansion in middle 2' => array('1:2::3', '0001:0002:0000:0000:0000:0000:0000:0003'),
384  'expansion in middle 3' => array('1::2:3', '0001:0000:0000:0000:0000:0000:0002:0003'),
385  'expansion in middle 4' => array('1:2::3:4:5', '0001:0002:0000:0000:0000:0003:0004:0005')
386  );
387  }
388 
393  public function normalizeIPv6CorrectlyNormalizesAddresses($compressed, $normalized) {
394  $this->assertEquals($normalized, Utility\GeneralUtility::normalizeIPv6($compressed));
395  }
396 
401  public function compressIPv6CorrectlyCompressesAdresses($compressed, $normalized) {
402  $this->assertEquals($compressed, Utility\GeneralUtility::compressIPv6($normalized));
403  }
404 
409  if (strtolower(PHP_OS) === 'darwin') {
410  $this->markTestSkipped('This test does not work on OSX / Darwin OS.');
411  }
412  $this->assertEquals('::f0f', Utility\GeneralUtility::compressIPv6('0000:0000:0000:0000:0000:0000:0000:0f0f'));
413  }
414 
416  // Tests concerning validIP
418 
423  static public function validIpDataProvider() {
424  return array(
425  '0.0.0.0' => array('0.0.0.0'),
426  'private IPv4 class C' => array('192.168.0.1'),
427  'private IPv4 class A' => array('10.0.13.1'),
428  'private IPv6' => array('fe80::daa2:5eff:fe8b:7dfb')
429  );
430  }
431 
436  public function validIpReturnsTrueForValidIp($ip) {
437  $this->assertTrue(Utility\GeneralUtility::validIP($ip));
438  }
439 
445  static public function invalidIpDataProvider() {
446  return array(
447  'null' => array(NULL),
448  'zero' => array(0),
449  'string' => array('test'),
450  'string empty' => array(''),
451  'string NULL' => array('NULL'),
452  'out of bounds IPv4' => array('300.300.300.300'),
453  'dotted decimal notation with only two dots' => array('127.0.1')
454  );
455  }
456 
461  public function validIpReturnsFalseForInvalidIp($ip) {
462  $this->assertFalse(Utility\GeneralUtility::validIP($ip));
463  }
464 
466  // Tests concerning cmpFQDN
468 
473  static public function cmpFqdnValidDataProvider() {
474  return array(
475  'localhost should usually resolve, IPv4' => array('127.0.0.1', '*'),
476  'localhost should usually resolve, IPv6' => array('::1', '*'),
477  // other testcases with resolving not possible since it would
478  // require a working IPv4/IPv6-connectivity
479  'aaa.bbb.ccc.ddd.eee, full' => array('aaa.bbb.ccc.ddd.eee', 'aaa.bbb.ccc.ddd.eee'),
480  'aaa.bbb.ccc.ddd.eee, wildcard first' => array('aaa.bbb.ccc.ddd.eee', '*.ccc.ddd.eee'),
481  'aaa.bbb.ccc.ddd.eee, wildcard last' => array('aaa.bbb.ccc.ddd.eee', 'aaa.bbb.ccc.*'),
482  'aaa.bbb.ccc.ddd.eee, wildcard middle' => array('aaa.bbb.ccc.ddd.eee', 'aaa.*.eee'),
483  'list-matches, 1' => array('aaa.bbb.ccc.ddd.eee', 'xxx, yyy, zzz, aaa.*.eee'),
484  'list-matches, 2' => array('aaa.bbb.ccc.ddd.eee', '127:0:0:1,,aaa.*.eee,::1')
485  );
486  }
487 
492  public function cmpFqdnReturnsTrue($baseHost, $list) {
493  $this->assertTrue(Utility\GeneralUtility::cmpFQDN($baseHost, $list));
494  }
495 
501  static public function cmpFqdnInvalidDataProvider() {
502  return array(
503  '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'),
504  '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')
505  );
506  }
507 
512  public function cmpFqdnReturnsFalse($baseHost, $list) {
513  $this->assertFalse(Utility\GeneralUtility::cmpFQDN($baseHost, $list));
514  }
515 
517  // Tests concerning inList
519 
524  public function inListForItemContainedReturnsTrue($haystack) {
525  $this->assertTrue(Utility\GeneralUtility::inList($haystack, 'findme'));
526  }
527 
534  return array(
535  'Element as second element of four items' => array('one,findme,three,four'),
536  'Element at beginning of list' => array('findme,one,two'),
537  'Element at end of list' => array('one,two,findme'),
538  'One item list' => array('findme')
539  );
540  }
541 
547  public function inListForItemNotContainedReturnsFalse($haystack) {
548  $this->assertFalse(Utility\GeneralUtility::inList($haystack, 'findme'));
549  }
550 
557  return array(
558  'Four item list' => array('one,two,three,four'),
559  'One item list' => array('one'),
560  'Empty list' => array('')
561  );
562  }
563 
565  // Tests concerning rmFromList
567 
573  public function rmFromListRemovesElementsFromCommaSeparatedList($initialList, $listWithElementRemoved) {
574  $this->assertSame($listWithElementRemoved, Utility\GeneralUtility::rmFromList('removeme', $initialList));
575  }
576 
583  return array(
584  'Element as second element of three' => array('one,removeme,two', 'one,two'),
585  'Element at beginning of list' => array('removeme,one,two', 'one,two'),
586  'Element at end of list' => array('one,two,removeme', 'one,two'),
587  'One item list' => array('removeme', ''),
588  'Element not contained in list' => array('one,two,three', 'one,two,three'),
589  'Empty element survives' => array('one,,three,,removeme', 'one,,three,'),
590  'Empty element survives at start' => array(',removeme,three,removeme', ',three'),
591  'Empty element survives at end' => array('removeme,three,removeme,', 'three,'),
592  'Empty list' => array('', ''),
593  'List contains removeme multiple times' => array('removeme,notme,removeme,removeme', 'notme'),
594  'List contains removeme multiple times nothing else' => array('removeme,removeme,removeme', ''),
595  'List contains removeme multiple times nothing else 2x' => array('removeme,removeme', ''),
596  'List contains removeme multiple times nothing else 3x' => array('removeme,removeme,removeme', ''),
597  'List contains removeme multiple times nothing else 4x' => array('removeme,removeme,removeme,removeme', ''),
598  'List contains removeme multiple times nothing else 5x' => array('removeme,removeme,removeme,removeme,removeme', ''),
599  );
600  }
601 
603  // Tests concerning expandList
605 
611  public function expandListExpandsIntegerRanges($list, $expectation) {
612  $this->assertSame($expectation, Utility\GeneralUtility::expandList($list));
613  }
614 
621  return array(
622  'Expand for the same number' => array('1,2-2,7', '1,2,7'),
623  'Small range expand with parameters reversed ignores reversed items' => array('1,5-3,7', '1,7'),
624  'Small range expand' => array('1,3-5,7', '1,3,4,5,7'),
625  'Expand at beginning' => array('3-5,1,7', '3,4,5,1,7'),
626  'Expand at end' => array('1,7,3-5', '1,7,3,4,5'),
627  'Multiple small range expands' => array('1,3-5,7-10,12', '1,3,4,5,7,8,9,10,12'),
628  'One item list' => array('1-5', '1,2,3,4,5'),
629  'Nothing to expand' => array('1,2,3,4', '1,2,3,4'),
630  'Empty list' => array('', '')
631  );
632  }
633 
638  $list = Utility\GeneralUtility::expandList('1-2000');
639  $this->assertSame(1000, count(explode(',', $list)));
640  }
641 
643  // Tests concerning uniqueList
645 
651  public function uniqueListUnifiesCommaSeparatedList($initialList, $unifiedList) {
652  $this->assertSame($unifiedList, Utility\GeneralUtility::uniqueList($initialList));
653  }
654 
661  return array(
662  'List without duplicates' => array('one,two,three', 'one,two,three'),
663  'List with two consecutive duplicates' => array('one,two,two,three,three', 'one,two,three'),
664  'List with non-consecutive duplicates' => array('one,two,three,two,three', 'one,two,three'),
665  'One item list' => array('one', 'one'),
666  'Empty list' => array('', '')
667  );
668  }
669 
671  // Tests concerning isFirstPartOfStr
673 
679  return array(
680  'match first part of string' => array('hello world', 'hello'),
681  'match whole string' => array('hello', 'hello'),
682  'integer is part of string with same number' => array('24', 24),
683  'string is part of integer with same number' => array(24, '24'),
684  'integer is part of string starting with same number' => array('24 beer please', 24)
685  );
686  }
687 
692  public function isFirstPartOfStrReturnsTrueForMatchingFirstPart($string, $part) {
693  $this->assertTrue(Utility\GeneralUtility::isFirstPartOfStr($string, $part));
694  }
695 
702  return array(
703  'no string match' => array('hello', 'bye'),
704  'no case sensitive string match' => array('hello world', 'Hello'),
705  'array is not part of string' => array('string', array()),
706  'string is not part of array' => array(array(), 'string'),
707  'NULL is not part of string' => array('string', NULL),
708  'string is not part of NULL' => array(NULL, 'string'),
709  'NULL is not part of array' => array(array(), NULL),
710  'array is not part of NULL' => array(NULL, array()),
711  'empty string is not part of empty string' => array('', ''),
712  'NULL is not part of empty string' => array('', NULL),
713  'false is not part of empty string' => array('', FALSE),
714  'empty string is not part of NULL' => array(NULL, ''),
715  'empty string is not part of false' => array(FALSE, ''),
716  'empty string is not part of zero integer' => array(0, ''),
717  'zero integer is not part of NULL' => array(NULL, 0),
718  'zero integer is not part of empty string' => array('', 0)
719  );
720  }
721 
726  public function isFirstPartOfStrReturnsFalseForNotMatchingFirstPart($string, $part) {
727  $this->assertFalse(Utility\GeneralUtility::isFirstPartOfStr($string, $part));
728  }
729 
731  // Tests concerning formatSize
733 
737  public function formatSizeTranslatesBytesToHigherOrderRepresentation($size, $label, $expected) {
738  $this->assertEquals($expected, Utility\GeneralUtility::formatSize($size, $label));
739  }
740 
746  public function formatSizeDataProvider() {
747  return array(
748  'Bytes keep beeing bytes (min)' => array(1, '', '1 '),
749  'Bytes keep beeing bytes (max)' => array(899, '', '899 '),
750  'Kilobytes are detected' => array(1024, '', '1.0 K'),
751  'Megabytes are detected' => array(1048576, '', '1.0 M'),
752  'Gigabytes are detected' => array(1073741824, '', '1.0 G'),
753  'Decimal is omitted for large kilobytes' => array(31080, '', '30 K'),
754  'Decimal is omitted for large megabytes' => array(31458000, '', '30 M'),
755  'Decimal is omitted for large gigabytes' => array(32212254720, '', '30 G'),
756  'Label for bytes can be exchanged' => array(1, ' Foo|||', '1 Foo'),
757  'Label for kilobytes can be exchanged' => array(1024, '| Foo||', '1.0 Foo'),
758  'Label for megabyes can be exchanged' => array(1048576, '|| Foo|', '1.0 Foo'),
759  'Label for gigabytes can be exchanged' => array(1073741824, '||| Foo', '1.0 Foo')
760  );
761  }
762 
764  // Tests concerning splitCalc
766 
771  public function splitCalcDataProvider() {
772  return array(
773  'empty string returns empty array' => array(
774  array(),
775  ''
776  ),
777  'number without operator returns array with plus and number' => array(
778  array(array('+', 42)),
779  '42'
780  ),
781  'two numbers with asterisk return first number with plus and second number with asterisk' => array(
782  array(array('+', 42), array('*', 31)),
783  '42 * 31'
784  )
785  );
786  }
787 
792  public function splitCalcCorrectlySplitsExpression($expected, $expression) {
793  $this->assertEquals($expected, Utility\GeneralUtility::splitCalc($expression, '+-*/'));
794  }
795 
797  // Tests concerning htmlspecialchars_decode
799 
803  $string = '<typo3 version="6.0">&nbsp;</typo3>';
804  $encoded = htmlspecialchars($string);
805  $decoded = htmlspecialchars_decode($encoded);
806  $this->assertEquals($string, $decoded);
807  }
808 
810  // Tests concerning deHSCentities
812 
816  public function deHSCentitiesReturnsDecodedString($input, $expected) {
817  $this->assertEquals($expected, Utility\GeneralUtility::deHSCentities($input));
818  }
819 
826  return array(
827  'Empty string' => array('', ''),
828  'Double encoded &' => array('&amp;amp;', '&amp;'),
829  'Double encoded numeric entity' => array('&amp;#1234;', '&#1234;'),
830  'Double encoded hexadecimal entity' => array('&amp;#x1b;', '&#x1b;'),
831  'Single encoded entities are not touched' => array('&amp; &#1234; &#x1b;', '&amp; &#1234; &#x1b;')
832  );
833  }
834 
836  // Tests concerning slashJS
838 
842  public function slashJsEscapesSingleQuotesAndSlashes($input, $extended, $expected) {
843  $this->assertEquals($expected, Utility\GeneralUtility::slashJS($input, $extended));
844  }
845 
851  public function slashJsDataProvider() {
852  return array(
853  'Empty string is not changed' => array('', FALSE, ''),
854  'Normal string is not changed' => array('The cake is a lie √', FALSE, 'The cake is a lie √'),
855  'String with single quotes' => array('The \'cake\' is a lie', FALSE, 'The \\\'cake\\\' is a lie'),
856  'String with single quotes and backslashes - just escape single quotes' => array('The \\\'cake\\\' is a lie', FALSE, 'The \\\\\'cake\\\\\' is a lie'),
857  'String with single quotes and backslashes - escape both' => array('The \\\'cake\\\' is a lie', TRUE, 'The \\\\\\\'cake\\\\\\\' is a lie')
858  );
859  }
860 
862  // Tests concerning rawUrlEncodeJS
864 
868  $input = 'Encode \'me\', but leave my spaces √';
869  $expected = 'Encode %27me%27%2C but leave my spaces %E2%88%9A';
870  $this->assertEquals($expected, Utility\GeneralUtility::rawUrlEncodeJS($input));
871  }
872 
874  // Tests concerning rawUrlEncodeJS
876 
879  public function rawUrlEncodeFpPreservesSlashes() {
880  $input = 'Encode \'me\', but leave my / √';
881  $expected = 'Encode%20%27me%27%2C%20but%20leave%20my%20/%20%E2%88%9A';
882  $this->assertEquals($expected, Utility\GeneralUtility::rawUrlEncodeFP($input));
883  }
884 
886  // Tests concerning strtoupper / strtolower
888 
893  public function strtouppperDataProvider() {
894  return array(
895  'Empty string' => array('', ''),
896  'String containing only latin characters' => array('the cake is a lie.', 'THE CAKE IS A LIE.'),
897  'String with umlauts and accent characters' => array('the càkê is ä lie.', 'THE CàKê IS ä LIE.')
898  );
899  }
900 
905  public function strtoupperConvertsOnlyLatinCharacters($input, $expected) {
906  $this->assertEquals($expected, Utility\GeneralUtility::strtoupper($input));
907  }
908 
913  public function strtolowerConvertsOnlyLatinCharacters($expected, $input) {
914  $this->assertEquals($expected, Utility\GeneralUtility::strtolower($input));
915  }
916 
918  // Tests concerning validEmail
920 
925  public function validEmailValidDataProvider() {
926  return array(
927  'short mail address' => array('a@b.c'),
928  'simple mail address' => array('test@example.com'),
929  'uppercase characters' => array('QWERTYUIOPASDFGHJKLZXCVBNM@QWERTYUIOPASDFGHJKLZXCVBNM.NET'),
930  // 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
931  // 'equal sign in local part' => array('test=mail@example.com'),
932  'dash in local part' => array('test-mail@example.com'),
933  'plus in local part' => array('test+mail@example.com'),
934  // 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
935  // 'question mark in local part' => array('test?mail@example.com'),
936  'slash in local part' => array('foo/bar@example.com'),
937  'hash in local part' => array('foo#bar@example.com'),
938  // 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
939  // 'dot in local part' => array('firstname.lastname@employee.2something.com'),
940  // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
941  // 'dash as local part' => array('-@foo.com'),
942  'umlauts in domain part' => array('foo@äöüfoo.com')
943  );
944  }
945 
950  public function validEmailReturnsTrueForValidMailAddress($address) {
951  $this->assertTrue(Utility\GeneralUtility::validEmail($address));
952  }
953 
959  public function validEmailInvalidDataProvider() {
960  return array(
961  'empty string' => array(''),
962  'empty array' => array(array()),
963  'integer' => array(42),
964  'float' => array(42.23),
965  'array' => array(array('foo')),
966  'object' => array(new \stdClass()),
967  '@ sign only' => array('@'),
968  'string longer than 320 characters' => array(str_repeat('0123456789', 33)),
969  'duplicate @' => array('test@@example.com'),
970  'duplicate @ combined with further special characters in local part' => array('test!.!@#$%^&*@example.com'),
971  'opening parenthesis in local part' => array('foo(bar@example.com'),
972  'closing parenthesis in local part' => array('foo)bar@example.com'),
973  'opening square bracket in local part' => array('foo[bar@example.com'),
974  'closing square bracket as local part' => array(']@example.com'),
975  // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
976  // 'top level domain only' => array('test@com'),
977  'dash as second level domain' => array('foo@-.com'),
978  'domain part starting with dash' => array('foo@-foo.com'),
979  'domain part ending with dash' => array('foo@foo-.com'),
980  'number as top level domain' => array('foo@bar.123'),
981  // Fix / change if TYPO3 php requirement changed: Address not ok with 5.2.6, but ok with 5.3.2 (?)
982  // 'dash as top level domain' => array('foo@bar.-'),
983  'dot at beginning of domain part' => array('test@.com'),
984  // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
985  // 'local part ends with dot' => array('e.x.a.m.p.l.e.@example.com'),
986  'umlauts in local part' => array('äöüfoo@bar.com'),
987  'trailing whitespace' => array('test@example.com '),
988  'trailing carriage return' => array('test@example.com' . CR),
989  'trailing linefeed' => array('test@example.com' . LF),
990  'trailing carriage return linefeed' => array('test@example.com' . CRLF),
991  'trailing tab' => array('test@example.com' . TAB)
992  );
993  }
994 
1000  $this->assertFalse(Utility\GeneralUtility::validEmail($address));
1001  }
1002 
1004  // Tests concerning inArray
1006 
1010  public function inArrayChecksStringExistenceWithinArray($array, $item, $expected) {
1011  $this->assertEquals($expected, Utility\GeneralUtility::inArray($array, $item));
1012  }
1013 
1019  public function inArrayDataProvider() {
1020  return array(
1021  'Empty array' => array(array(), 'search', FALSE),
1022  'One item array no match' => array(array('one'), 'two', FALSE),
1023  'One item array match' => array(array('one'), 'one', TRUE),
1024  'Multiple items array no match' => array(array('one', 2, 'three', 4), 'four', FALSE),
1025  'Multiple items array match' => array(array('one', 2, 'three', 4), 'three', TRUE),
1026  'Integer search items can match string values' => array(array('0', '1', '2'), 1, TRUE),
1027  'Search item is not casted to integer for a match' => array(array(4), '4a', FALSE),
1028  'Empty item won\'t match - in contrast to the php-builtin ' => array(array(0, 1, 2), '', FALSE)
1029  );
1030  }
1031 
1033  // Tests concerning intExplode
1035 
1039  $testString = '1,foo,2';
1040  $expectedArray = array(1, 0, 2);
1041  $actualArray = Utility\GeneralUtility::intExplode(',', $testString);
1042  $this->assertEquals($expectedArray, $actualArray);
1043  }
1044 
1046  // Tests concerning keepItemsInArray
1048 
1052  public function keepItemsInArrayWorksWithOneArgument($search, $array, $expected) {
1053  $this->assertEquals($expected, Utility\GeneralUtility::keepItemsInArray($array, $search));
1054  }
1055 
1062  $array = array(
1063  'one' => 'one',
1064  'two' => 'two',
1065  'three' => 'three'
1066  );
1067  return array(
1068  'Empty argument will match "all" elements' => array(NULL, $array, $array),
1069  'No match' => array('four', $array, array()),
1070  'One match' => array('two', $array, array('two' => 'two')),
1071  'Multiple matches' => array('two,one', $array, array('one' => 'one', 'two' => 'two')),
1072  'Argument can be an array' => array(array('three'), $array, array('three' => 'three'))
1073  );
1074  }
1075 
1084  $array = array(
1085  'aa' => array('first', 'second'),
1086  'bb' => array('third', 'fourth'),
1087  'cc' => array('fifth', 'sixth')
1088  );
1089  $expected = array('bb' => array('third', 'fourth'));
1090  $keepItems = 'third';
1091  $getValueFunc = create_function('$value', 'return $value[0];');
1092  $match = Utility\GeneralUtility::keepItemsInArray($array, $keepItems, $getValueFunc);
1093  $this->assertEquals($expected, $match);
1094  }
1095 
1102  public function keepItemsInArrayCanUseClosure() {
1103  $array = array(
1104  'aa' => array('first', 'second'),
1105  'bb' => array('third', 'fourth'),
1106  'cc' => array('fifth', 'sixth')
1107  );
1108  $expected = array('bb' => array('third', 'fourth'));
1109  $keepItems = 'third';
1111  $array,
1112  $keepItems,
1113  function ($value) {
1114  return $value[0];
1115  }
1116  );
1117  $this->assertEquals($expected, $match);
1118  }
1119 
1121  // Tests concerning implodeArrayForUrl / explodeUrl2Array
1123 
1130  $valueArray = array('one' => '√', 'two' => 2);
1131  return array(
1132  'Empty input' => array('foo', array(), ''),
1133  'String parameters' => array('foo', $valueArray, '&foo[one]=%E2%88%9A&foo[two]=2'),
1134  'Nested array parameters' => array('foo', array($valueArray), '&foo[0][one]=%E2%88%9A&foo[0][two]=2'),
1135  'Keep blank parameters' => array('foo', array('one' => '√', ''), '&foo[one]=%E2%88%9A&foo[0]=')
1136  );
1137  }
1138 
1143  public function implodeArrayForUrlBuildsValidParameterString($name, $input, $expected) {
1144  $this->assertSame($expected, Utility\GeneralUtility::implodeArrayForUrl($name, $input));
1145  }
1146 
1151  $input = array('one' => '√', '');
1152  $expected = '&foo[one]=%E2%88%9A';
1153  $this->assertSame($expected, Utility\GeneralUtility::implodeArrayForUrl('foo', $input, '', TRUE));
1154  }
1155 
1160  $input = array('one' => '√', '');
1161  $expected = '&foo%5Bone%5D=%E2%88%9A&foo%5B0%5D=';
1162  $this->assertSame($expected, Utility\GeneralUtility::implodeArrayForUrl('foo', $input, '', FALSE, TRUE));
1163  }
1164 
1169  public function explodeUrl2ArrayTransformsParameterStringToNestedArray($name, $array, $input) {
1170  $expected = $array ? array($name => $array) : array();
1171  $this->assertEquals($expected, Utility\GeneralUtility::explodeUrl2Array($input, TRUE));
1172  }
1173 
1178  public function explodeUrl2ArrayTransformsParameterStringToFlatArray($input, $expected) {
1179  $this->assertEquals($expected, Utility\GeneralUtility::explodeUrl2Array($input, FALSE));
1180  }
1181 
1187  public function explodeUrl2ArrayDataProvider() {
1188  return array(
1189  'Empty string' => array('', array()),
1190  'Simple parameter string' => array('&one=%E2%88%9A&two=2', array('one' => '√', 'two' => 2)),
1191  'Nested parameter string' => array('&foo[one]=%E2%88%9A&two=2', array('foo[one]' => '√', 'two' => 2))
1192  );
1193  }
1194 
1196  // Tests concerning compileSelectedGetVarsFromArray
1198 
1202  $filter = 'foo,bar';
1203  $getArray = array('foo' => 1, 'cake' => 'lie');
1204  $expected = array('foo' => 1);
1206  $this->assertSame($expected, $result);
1207  }
1208 
1213  $_GET['bar'] = '2';
1214  $filter = 'foo,bar';
1215  $getArray = array('foo' => 1, 'cake' => 'lie');
1216  $expected = array('foo' => 1, 'bar' => '2');
1218  $this->assertSame($expected, $result);
1219  }
1220 
1222  // Tests concerning remapArrayKeys
1224 
1228  $array = array(
1229  'one' => 'one',
1230  'two' => 'two',
1231  'three' => 'three'
1232  );
1233  $keyMapping = array(
1234  'one' => '1',
1235  'two' => '2'
1236  );
1237  $expected = array(
1238  '1' => 'one',
1239  '2' => 'two',
1240  'three' => 'three'
1241  );
1242  Utility\GeneralUtility::remapArrayKeys($array, $keyMapping);
1243  $this->assertEquals($expected, $array);
1244  }
1245 
1247  // Tests concerning array_merge
1249 
1257  $array1 = array(10 => 'FOO', '20' => 'BAR');
1258  $array2 = array('5' => 'PLONK');
1259  $expected = array('5' => 'PLONK', 10 => 'FOO', '20' => 'BAR');
1260  $this->assertEquals($expected, Utility\GeneralUtility::array_merge($array1, $array2));
1261  }
1262 
1264  // Tests concerning revExplode
1266 
1270  public function revExplodeDataProvider() {
1271  return array(
1272  'limit 0 should return unexploded string' => array(
1273  ':',
1274  'my:words:here',
1275  0,
1276  array('my:words:here')
1277  ),
1278  'limit 1 should return unexploded string' => array(
1279  ':',
1280  'my:words:here',
1281  1,
1282  array('my:words:here')
1283  ),
1284  'limit 2 should return two pieces' => array(
1285  ':',
1286  'my:words:here',
1287  2,
1288  array('my:words', 'here')
1289  ),
1290  'limit 3 should return unexploded string' => array(
1291  ':',
1292  'my:words:here',
1293  3,
1294  array('my', 'words', 'here')
1295  ),
1296  'limit 0 should return unexploded string if no delimiter is contained' => array(
1297  ':',
1298  'mywordshere',
1299  0,
1300  array('mywordshere')
1301  ),
1302  'limit 1 should return unexploded string if no delimiter is contained' => array(
1303  ':',
1304  'mywordshere',
1305  1,
1306  array('mywordshere')
1307  ),
1308  'limit 2 should return unexploded string if no delimiter is contained' => array(
1309  ':',
1310  'mywordshere',
1311  2,
1312  array('mywordshere')
1313  ),
1314  'limit 3 should return unexploded string if no delimiter is contained' => array(
1315  ':',
1316  'mywordshere',
1317  3,
1318  array('mywordshere')
1319  ),
1320  'multi character delimiter is handled properly with limit 2' => array(
1321  '[]',
1322  'a[b][c][d]',
1323  2,
1324  array('a[b][c', 'd]')
1325  ),
1326  'multi character delimiter is handled properly with limit 3' => array(
1327  '[]',
1328  'a[b][c][d]',
1329  3,
1330  array('a[b', 'c', 'd]')
1331  ),
1332  );
1333  }
1334 
1339  public function revExplodeCorrectlyExplodesStringForGivenPartsCount($delimiter, $testString, $count, $expectedArray) {
1340  $actualArray = Utility\GeneralUtility::revExplode($delimiter, $testString, $count);
1341  $this->assertEquals($expectedArray, $actualArray);
1342  }
1343 
1348  $testString = 'even:more:of:my:words:here';
1349  $expectedArray = array('even:more:of:my', 'words', 'here');
1350  $actualArray = Utility\GeneralUtility::revExplode(':', $testString, 3);
1351  $this->assertEquals($expectedArray, $actualArray);
1352  }
1353 
1355  // Tests concerning trimExplode
1357 
1361  $testString = ' a , b , c ,d ,, e,f,';
1362  $expectedArray = array('a', 'b', 'c', 'd', '', 'e', 'f', '');
1363  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString);
1364  $this->assertEquals($expectedArray, $actualArray);
1365  }
1366 
1371  $testString = ' a , b , ' . LF . ' ,d ,, e,f,';
1372  $expectedArray = array('a', 'b', 'd', 'e', 'f');
1373  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1374  $this->assertEquals($expectedArray, $actualArray);
1375  }
1376 
1381  $testString = 'a , b , c , ,d ,, ,e,f,';
1382  $expectedArray = array('a', 'b', 'c', 'd', 'e', 'f');
1383  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1384  $this->assertEquals($expectedArray, $actualArray);
1385  }
1386 
1391  $testString = ' a , b , c , , d,, ,e ';
1392  $expectedArray = array('a', 'b', 'c , , d,, ,e');
1393  // Limiting returns the rest of the string as the last element
1394  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, FALSE, 3);
1395  $this->assertEquals($expectedArray, $actualArray);
1396  }
1397 
1402  $testString = ' a , b , c , , d,, ,e ';
1403  $expectedArray = array('a', 'b', 'c , d,e');
1404  // Limiting returns the rest of the string as the last element
1405  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE, 3);
1406  $this->assertEquals($expectedArray, $actualArray);
1407  }
1408 
1413  $testString = ' a , b , c , d, ,e, f , , ';
1414  $expectedArray = array('a', 'b', 'c', 'd', '', 'e');
1415  // limiting returns the rest of the string as the last element
1416  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, FALSE, -3);
1417  $this->assertEquals($expectedArray, $actualArray);
1418  }
1419 
1424  $testString = ' a , b , c , d, ,e, f , , ';
1425  $expectedArray = array('a', 'b', 'c');
1426  // Limiting returns the rest of the string as the last element
1427  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE, -3);
1428  $this->assertEquals($expectedArray, $actualArray);
1429  }
1430 
1435  $testString = ' a , b , , c , , , ';
1436  $expectedArray = array('a', 'b', 'c');
1437  // Limiting returns the rest of the string as the last element
1438  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE, 4);
1439  $this->assertEquals($expectedArray, $actualArray);
1440  }
1441 
1446  $testString = 'a , b , c , ,d ,, ,e,f, 0 ,';
1447  $expectedArray = array('a', 'b', 'c', 'd', 'e', 'f', '0');
1448  $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1449  $this->assertEquals($expectedArray, $actualArray);
1450  }
1451 
1453  // Tests concerning removeArrayEntryByValue
1455 
1459  $inputArray = array(
1460  '0' => 'test1',
1461  '1' => 'test2',
1462  '2' => 'test3',
1463  '3' => 'test2'
1464  );
1465  $compareValue = 'test2';
1466  $expectedResult = array(
1467  '0' => 'test1',
1468  '2' => 'test3'
1469  );
1470  $actualResult = Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1471  $this->assertEquals($expectedResult, $actualResult);
1472  }
1473 
1478  $inputArray = array(
1479  '0' => 'foo',
1480  '1' => array(
1481  '10' => 'bar'
1482  ),
1483  '2' => 'bar'
1484  );
1485  $compareValue = 'bar';
1486  $expectedResult = array(
1487  '0' => 'foo',
1488  '1' => array()
1489  );
1490  $actualResult = Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1491  $this->assertEquals($expectedResult, $actualResult);
1492  }
1493 
1498  $inputArray = array(
1499  '0' => 'foo',
1500  '1' => '',
1501  '2' => 'bar'
1502  );
1503  $compareValue = '';
1504  $expectedResult = array(
1505  '0' => 'foo',
1506  '2' => 'bar'
1507  );
1508  $actualResult = Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1509  $this->assertEquals($expectedResult, $actualResult);
1510  }
1511 
1513  // Tests concerning getBytesFromSizeMeasurement
1515 
1521  return array(
1522  '100 kilo Bytes' => array('102400', '100k'),
1523  '100 mega Bytes' => array('104857600', '100m'),
1524  '100 giga Bytes' => array('107374182400', '100g')
1525  );
1526  }
1527 
1532  public function getBytesFromSizeMeasurementCalculatesCorrectByteValue($expected, $byteString) {
1533  $this->assertEquals($expected, Utility\GeneralUtility::getBytesFromSizeMeasurement($byteString));
1534  }
1535 
1537  // Tests concerning getIndpEnv
1539 
1543  $this->assertTrue(strlen(Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH')) >= 1);
1544  }
1545 
1550  if (TYPO3_OS === 'WIN') {
1551  $this->markTestSkipped('Test not available on Windows OS.');
1552  }
1553  $result = Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1554  $this->assertEquals('/', $result[0]);
1555  }
1556 
1561  if (TYPO3_OS !== 'WIN') {
1562  $this->markTestSkipped('Test available only on Windows OS.');
1563  }
1564  $result = Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1565  $this->assertRegExp('/^[a-z]:\//i', $result);
1566  }
1567 
1572  $result = Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1573  $this->assertEquals('/', $result[strlen($result) - 1]);
1574  }
1575 
1579  static public function hostnameAndPortDataProvider() {
1580  return array(
1581  'localhost ipv4 without port' => array('127.0.0.1', '127.0.0.1', ''),
1582  'localhost ipv4 with port' => array('127.0.0.1:81', '127.0.0.1', '81'),
1583  'localhost ipv6 without port' => array('[::1]', '[::1]', ''),
1584  'localhost ipv6 with port' => array('[::1]:81', '[::1]', '81'),
1585  'ipv6 without port' => array('[2001:DB8::1]', '[2001:DB8::1]', ''),
1586  'ipv6 with port' => array('[2001:DB8::1]:81', '[2001:DB8::1]', '81'),
1587  'hostname without port' => array('lolli.did.this', 'lolli.did.this', ''),
1588  'hostname with port' => array('lolli.did.this:42', 'lolli.did.this', '42')
1589  );
1590  }
1591 
1596  public function getIndpEnvTypo3HostOnlyParsesHostnamesAndIpAdresses($httpHost, $expectedIp) {
1597  $_SERVER['HTTP_HOST'] = $httpHost;
1598  $this->assertEquals($expectedIp, Utility\GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'));
1599  }
1600 
1605  unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern']);
1606  $this->assertFalse(GeneralUtilityFixture::isAllowedHostHeaderValue('evil.foo.bar'));
1607  }
1608 
1613  return array(
1614  'hostname without port matching' => array('lolli.did.this', '.*\.did\.this'),
1615  'other hostname without port matching' => array('helmut.did.this', '.*\.did\.this'),
1616  'two different hostnames without port matching 1st host' => array('helmut.is.secure', '(helmut\.is\.secure|lolli\.is\.secure)'),
1617  'two different hostnames without port matching 2nd host' => array('lolli.is.secure', '(helmut\.is\.secure|lolli\.is\.secure)'),
1618  'hostname with port matching' => array('lolli.did.this:42', '.*\.did\.this:42'),
1619  'hostnames are case insensitive 1' => array('lolli.DID.this:42', '.*\.did.this:42'),
1620  'hostnames are case insensitive 2' => array('lolli.did.this:42', '.*\.DID.this:42'),
1621  );
1622  }
1623 
1628  return array(
1629  'hostname without port' => array('lolli.did.this', 'helmut\.did\.this'),
1630  'hostname with port, but port not allowed' => array('lolli.did.this:42', 'helmut\.did\.this'),
1631  'two different hostnames in pattern but host header starts with differnet value #1' => array('sub.helmut.is.secure', '(helmut\.is\.secure|lolli\.is\.secure)'),
1632  'two different hostnames in pattern but host header starts with differnet value #2' => array('sub.lolli.is.secure', '(helmut\.is\.secure|lolli\.is\.secure)'),
1633  'two different hostnames in pattern but host header ends with differnet value #1' => array('helmut.is.secure.tld', '(helmut\.is\.secure|lolli\.is\.secure)'),
1634  'two different hostnames in pattern but host header ends with differnet value #2' => array('lolli.is.secure.tld', '(helmut\.is\.secure|lolli\.is\.secure)'),
1635  );
1636  }
1637 
1644  public function isAllowedHostHeaderValueReturnsTrueIfHostValueMatches($httpHost, $hostNamePattern) {
1645  $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] = $hostNamePattern;
1646  $this->assertTrue(GeneralUtilityFixture::isAllowedHostHeaderValue($httpHost));
1647  }
1648 
1655  public function isAllowedHostHeaderValueReturnsFalseIfHostValueMatches($httpHost, $hostNamePattern) {
1656  $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] = $hostNamePattern;
1657  $this->assertFalse(GeneralUtilityFixture::isAllowedHostHeaderValue($httpHost));
1658  }
1659 
1660  public function serverNamePatternDataProvider() {
1661  return array(
1662  'host value matches server name and server port is default http' => array(
1663  'httpHost' => 'secure.web.server',
1664  'serverName' => 'secure.web.server',
1665  'isAllowed' => TRUE,
1666  'serverPort' => '80',
1667  'ssl' => 'Off',
1668  ),
1669  'host value matches server name if compared case insensitive 1' => array(
1670  'httpHost' => 'secure.web.server',
1671  'serverName' => 'secure.WEB.server',
1672  'isAllowed' => TRUE,
1673  ),
1674  'host value matches server name if compared case insensitive 2' => array(
1675  'httpHost' => 'secure.WEB.server',
1676  'serverName' => 'secure.web.server',
1677  'isAllowed' => TRUE,
1678  ),
1679  'host value matches server name and server port is default https' => array(
1680  'httpHost' => 'secure.web.server',
1681  'serverName' => 'secure.web.server',
1682  'isAllowed' => TRUE,
1683  'serverPort' => '443',
1684  'ssl' => 'On',
1685  ),
1686  'host value matches server name and server port' => array(
1687  'httpHost' => 'secure.web.server:88',
1688  'serverName' => 'secure.web.server',
1689  'isAllowed' => TRUE,
1690  'serverPort' => '88',
1691  ),
1692  'host value matches server name case insensitive 1 and server port' => array(
1693  'httpHost' => 'secure.WEB.server:88',
1694  'serverName' => 'secure.web.server',
1695  'isAllowed' => TRUE,
1696  'serverPort' => '88',
1697  ),
1698  'host value matches server name case insensitive 2 and server port' => array(
1699  'httpHost' => 'secure.web.server:88',
1700  'serverName' => 'secure.WEB.server',
1701  'isAllowed' => TRUE,
1702  'serverPort' => '88',
1703  ),
1704  'host value is ipv6 but matches server name and server port' => array(
1705  'httpHost' => '[::1]:81',
1706  'serverName' => '[::1]',
1707  'isAllowed' => TRUE,
1708  'serverPort' => '81',
1709  ),
1710  'host value does not match server name' => array(
1711  'httpHost' => 'insecure.web.server',
1712  'serverName' => 'secure.web.server',
1713  'isAllowed' => FALSE,
1714  ),
1715  'host value does not match server port' => array(
1716  'httpHost' => 'secure.web.server:88',
1717  'serverName' => 'secure.web.server',
1718  'isAllowed' => FALSE,
1719  'serverPort' => '89',
1720  ),
1721  'host value has default port that does not match server port' => array(
1722  'httpHost' => 'secure.web.server',
1723  'serverName' => 'secure.web.server',
1724  'isAllowed' => FALSE,
1725  'serverPort' => '81',
1726  'ssl' => 'Off',
1727  ),
1728  'host value has default port that does not match server ssl port' => array(
1729  'httpHost' => 'secure.web.server',
1730  'serverName' => 'secure.web.server',
1731  'isAllowed' => FALSE,
1732  'serverPort' => '444',
1733  'ssl' => 'On',
1734  ),
1735  );
1736  }
1737 
1748  public function isAllowedHostHeaderValueWorksCorrectlyWithWithServerNamePattern($httpHost, $serverName, $isAllowed, $serverPort = '80', $ssl = 'Off') {
1749  $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] = Utility\GeneralUtility::ENV_TRUSTED_HOSTS_PATTERN_SERVER_NAME;
1750  $_SERVER['SERVER_NAME'] = $serverName;
1751  $_SERVER['SERVER_PORT'] = $serverPort;
1752  $_SERVER['HTTPS'] = $ssl;
1753  $this->assertSame($isAllowed, GeneralUtilityFixture::isAllowedHostHeaderValue($httpHost));
1754  }
1755 
1760  GeneralUtilityFixture::getIndpEnv('HTTP_HOST');
1761  GeneralUtilityFixture::getIndpEnv('TYPO3_HOST_ONLY');
1762  GeneralUtilityFixture::getIndpEnv('TYPO3_REQUEST_HOST');
1763  GeneralUtilityFixture::getIndpEnv('TYPO3_REQUEST_URL');
1765  }
1766 
1775  public function getIndpEnvForHostThrowsExceptionForNotAllowedHostnameValues($httpHost, $hostNamePattern) {
1776  $_SERVER['HTTP_HOST'] = $httpHost;
1777  $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] = $hostNamePattern;
1778  GeneralUtilityFixture::getIndpEnv('HTTP_HOST');
1779  }
1780 
1787  public function getIndpEnvForHostAllowsAllHostnameValuesIfHostPatternIsSetToAllowAll($httpHost, $hostNamePattern) {
1788  $_SERVER['HTTP_HOST'] = $httpHost;
1789  $GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] = Utility\GeneralUtility::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL;
1790  $this->assertSame($httpHost, Utility\GeneralUtility::getIndpEnv('HTTP_HOST'));
1791  }
1792 
1797  public function getIndpEnvTypo3PortParsesHostnamesAndIpAdresses($httpHost, $dummy, $expectedPort) {
1798  $_SERVER['HTTP_HOST'] = $httpHost;
1799  $this->assertEquals($expectedPort, Utility\GeneralUtility::getIndpEnv('TYPO3_PORT'));
1800  }
1801 
1803  // Tests concerning underscoredToUpperCamelCase
1805 
1811  return array(
1812  'single word' => array('Blogexample', 'blogexample'),
1813  'multiple words' => array('BlogExample', 'blog_example')
1814  );
1815  }
1816 
1821  public function underscoredToUpperCamelCase($expected, $inputString) {
1822  $this->assertEquals($expected, Utility\GeneralUtility::underscoredToUpperCamelCase($inputString));
1823  }
1824 
1826  // Tests concerning underscoredToLowerCamelCase
1828 
1834  return array(
1835  'single word' => array('minimalvalue', 'minimalvalue'),
1836  'multiple words' => array('minimalValue', 'minimal_value')
1837  );
1838  }
1839 
1844  public function underscoredToLowerCamelCase($expected, $inputString) {
1845  $this->assertEquals($expected, Utility\GeneralUtility::underscoredToLowerCamelCase($inputString));
1846  }
1847 
1849  // Tests concerning camelCaseToLowerCaseUnderscored
1851 
1857  return array(
1858  'single word' => array('blogexample', 'blogexample'),
1859  'single word starting upper case' => array('blogexample', 'Blogexample'),
1860  'two words starting lower case' => array('minimal_value', 'minimalValue'),
1861  'two words starting upper case' => array('blog_example', 'BlogExample')
1862  );
1863  }
1864 
1869  public function camelCaseToLowerCaseUnderscored($expected, $inputString) {
1870  $this->assertEquals($expected, Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($inputString));
1871  }
1872 
1874  // Tests concerning lcFirst
1876 
1881  public function lcfirstDataProvider() {
1882  return array(
1883  'single word' => array('blogexample', 'blogexample'),
1884  'single Word starting upper case' => array('blogexample', 'Blogexample'),
1885  'two words' => array('blogExample', 'BlogExample')
1886  );
1887  }
1888 
1893  public function lcFirst($expected, $inputString) {
1894  $this->assertEquals($expected, Utility\GeneralUtility::lcfirst($inputString));
1895  }
1896 
1898  // Tests concerning encodeHeader
1900 
1904  $this->assertEquals('=?utf-8?Q?We_test_whether_the_copyright_character_=C2=A9_is_encoded_correctly?=', Utility\GeneralUtility::encodeHeader('We test whether the copyright character © is encoded correctly', 'quoted-printable', 'utf-8'));
1905  }
1906 
1911  $this->assertEquals('=?utf-8?Q?Is_the_copyright_character_=C2=A9_really_encoded_correctly=3F_Really=3F?=', Utility\GeneralUtility::encodeHeader('Is the copyright character © really encoded correctly? Really?', 'quoted-printable', 'utf-8'));
1912  }
1913 
1915  // Tests concerning isValidUrl
1917 
1923  return array(
1924  'http' => array('http://www.example.org/'),
1925  'http without trailing slash' => array('http://qwe'),
1926  'http directory with trailing slash' => array('http://www.example/img/dir/'),
1927  'http directory without trailing slash' => array('http://www.example/img/dir'),
1928  'http index.html' => array('http://example.com/index.html'),
1929  'http index.php' => array('http://www.example.com/index.php'),
1930  'http test.png' => array('http://www.example/img/test.png'),
1931  'http username password querystring and ancher' => array('https://user:pw@www.example.org:80/path?arg=value#fragment'),
1932  'file' => array('file:///tmp/test.c'),
1933  'file directory' => array('file://foo/bar'),
1934  'ftp directory' => array('ftp://ftp.example.com/tmp/'),
1935  'mailto' => array('mailto:foo@bar.com'),
1936  'news' => array('news:news.php.net'),
1937  'telnet' => array('telnet://192.0.2.16:80/'),
1938  'ldap' => array('ldap://[2001:db8::7]/c=GB?objectClass?one'),
1939  'http punycode domain name' => array('http://www.xn--bb-eka.at'),
1940  'http punicode subdomain' => array('http://xn--h-zfa.oebb.at'),
1941  'http domain-name umlauts' => array('http://www.öbb.at'),
1942  'http subdomain umlauts' => array('http://äh.oebb.at'),
1943  );
1944  }
1945 
1950  public function validURLReturnsTrueForValidResource($url) {
1951  $this->assertTrue(Utility\GeneralUtility::isValidUrl($url));
1952  }
1953 
1960  return array(
1961  'http missing colon' => array('http//www.example/wrong/url/'),
1962  'http missing slash' => array('http:/www.example'),
1963  'hostname only' => array('www.example.org/'),
1964  'file missing protocol specification' => array('/tmp/test.c'),
1965  'slash only' => array('/'),
1966  'string http://' => array('http://'),
1967  'string http:/' => array('http:/'),
1968  'string http:' => array('http:'),
1969  'string http' => array('http'),
1970  'empty string' => array(''),
1971  'string -1' => array('-1'),
1972  'string array()' => array('array()'),
1973  'random string' => array('qwe'),
1974  'http directory umlauts' => array('http://www.oebb.at/äöü/'),
1975  );
1976  }
1977 
1983  $this->assertFalse(Utility\GeneralUtility::isValidUrl($url));
1984  }
1985 
1987  // Tests concerning isOnCurrentHost
1989 
1993  $testUrl = Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL');
1994  $this->assertTrue(Utility\GeneralUtility::isOnCurrentHost($testUrl));
1995  }
1996 
2003  return array(
2004  'empty string' => array(''),
2005  'arbitrary string' => array('arbitrary string'),
2006  'localhost IP' => array('127.0.0.1'),
2007  'relative path' => array('./relpath/file.txt'),
2008  'absolute path' => array('/abspath/file.txt?arg=value'),
2009  'differnt host' => array(Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_HOST') . '.example.org')
2010  );
2011  }
2012 
2014  // Tests concerning sanitizeLocalUrl
2016 
2022  return array(
2023  'alt_intro.php' => array('alt_intro.php'),
2024  'alt_intro.php?foo=1&bar=2' => array('alt_intro.php?foo=1&bar=2'),
2025  '../index.php' => array('../index.php'),
2026  '../typo3/alt_intro.php' => array('../typo3/alt_intro.php'),
2027  '../~userDirectory/index.php' => array('../~userDirectory/index.php'),
2028  '../typo3/mod.php?var1=test-case&var2=~user' => array('../typo3/mod.php?var1=test-case&var2=~user'),
2029  PATH_site . 'typo3/alt_intro.php' => array(PATH_site . 'typo3/alt_intro.php'),
2030  );
2031  }
2032 
2039  $this->assertEquals($path, Utility\GeneralUtility::sanitizeLocalUrl($path));
2040  }
2041 
2048  $this->assertEquals(rawurlencode($path), Utility\GeneralUtility::sanitizeLocalUrl(rawurlencode($path)));
2049  }
2050 
2057  $host = 'localhost';
2058  $subDirectory = '/cms/';
2059 
2060  return array(
2061  $subDirectory . 'typo3/alt_intro.php' => array(
2062  $subDirectory . 'typo3/alt_intro.php',
2063  $host,
2064  $subDirectory,
2065  ),
2066  $subDirectory . 'index.php' => array(
2067  $subDirectory . 'index.php',
2068  $host,
2069  $subDirectory,
2070  ),
2071  'http://' . $host . '/typo3/alt_intro.php' => array(
2072  'http://' . $host . '/typo3/alt_intro.php',
2073  $host,
2074  '',
2075  ),
2076  'http://' . $host . $subDirectory . 'typo3/alt_intro.php' => array(
2077  'http://' . $host . $subDirectory . 'typo3/alt_intro.php',
2078  $host,
2079  $subDirectory,
2080  ),
2081  );
2082  }
2083 
2091  public function sanitizeLocalUrlAcceptsNotEncodedValidUrls($url, $host, $subDirectory) {
2092  $_SERVER['HTTP_HOST'] = $host;
2093  $_SERVER['SCRIPT_NAME'] = $subDirectory . 'typo3/index.php';
2094  $this->assertEquals($url, Utility\GeneralUtility::sanitizeLocalUrl($url));
2095  }
2096 
2104  public function sanitizeLocalUrlAcceptsEncodedValidUrls($url, $host, $subDirectory) {
2105  $_SERVER['HTTP_HOST'] = $host;
2106  $_SERVER['SCRIPT_NAME'] = $subDirectory . 'typo3/index.php';
2107  $this->assertEquals(rawurlencode($url), Utility\GeneralUtility::sanitizeLocalUrl(rawurlencode($url)));
2108  }
2109 
2116  return array(
2117  'empty string' => array(''),
2118  'http domain' => array('http://www.google.de/'),
2119  'https domain' => array('https://www.google.de/'),
2120  'relative path with XSS' => array('../typo3/whatever.php?argument=javascript:alert(0)'),
2121  'base64 encoded string' => array('data:%20text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4='),
2122  );
2123  }
2124 
2130  $this->assertEquals('', Utility\GeneralUtility::sanitizeLocalUrl($url));
2131  }
2132 
2138  $this->assertEquals('', Utility\GeneralUtility::sanitizeLocalUrl(rawurlencode($url)));
2139  }
2140 
2142  // Tests concerning unlink_tempfile
2144 
2149  $fixtureFile = __DIR__ . '/Fixtures/clear.gif';
2150  $testFilename = PATH_site . 'typo3temp/' . $this->getUniqueId('test_') . '.gif';
2151  @copy($fixtureFile, $testFilename);
2153  $fileExists = file_exists($testFilename);
2154  $this->assertFalse($fileExists);
2155  }
2156 
2161  $fixtureFile = __DIR__ . '/Fixtures/clear.gif';
2162  $testFilename = PATH_site . 'typo3temp/' . $this->getUniqueId('.test_') . '.gif';
2163  @copy($fixtureFile, $testFilename);
2165  $fileExists = file_exists($testFilename);
2166  $this->assertFalse($fileExists);
2167  }
2168 
2173  $fixtureFile = __DIR__ . '/Fixtures/clear.gif';
2174  $testFilename = PATH_site . 'typo3temp/' . $this->getUniqueId('test_') . '.gif';
2175  @copy($fixtureFile, $testFilename);
2176  $returnValue = Utility\GeneralUtility::unlink_tempfile($testFilename);
2177  $this->assertTrue($returnValue);
2178  }
2179 
2184  $returnValue = Utility\GeneralUtility::unlink_tempfile(PATH_site . 'typo3temp/' . $this->getUniqueId('i_do_not_exist'));
2185  $this->assertNull($returnValue);
2186  }
2187 
2192  $returnValue = Utility\GeneralUtility::unlink_tempfile('/tmp/typo3-unit-test-unlink_tempfile');
2193  $this->assertNull($returnValue);
2194  }
2195 
2197  // Tests concerning tempnam
2199 
2204  $filePath = Utility\GeneralUtility::tempnam('foo');
2205  $fileName = basename($filePath);
2206  $this->assertStringStartsWith('foo', $fileName);
2207  }
2208 
2213  $filePath = Utility\GeneralUtility::tempnam('foo');
2214  $this->assertNotContains('\\', $filePath);
2215  }
2216 
2221  $filePath = Utility\GeneralUtility::tempnam('foo');
2222  $this->assertStringStartsWith(PATH_site, $filePath);
2223  }
2224 
2226  // Tests concerning addSlashesOnArray
2228 
2232  $inputArray = array(
2233  'key1' => array(
2234  'key11' => 'val\'ue1',
2235  'key12' => 'val"ue2'
2236  ),
2237  'key2' => 'val\\ue3'
2238  );
2239  $expectedResult = array(
2240  'key1' => array(
2241  'key11' => 'val\\\'ue1',
2242  'key12' => 'val\\"ue2'
2243  ),
2244  'key2' => 'val\\\\ue3'
2245  );
2247  $this->assertEquals($expectedResult, $inputArray);
2248  }
2249 
2251  // Tests concerning addSlashesOnArray
2253 
2257  $inputArray = array(
2258  'key1' => array(
2259  'key11' => 'val\\\'ue1',
2260  'key12' => 'val\\"ue2'
2261  ),
2262  'key2' => 'val\\\\ue3'
2263  );
2264  $expectedResult = array(
2265  'key1' => array(
2266  'key11' => 'val\'ue1',
2267  'key12' => 'val"ue2'
2268  ),
2269  'key2' => 'val\\ue3'
2270  );
2272  $this->assertEquals($expectedResult, $inputArray);
2273  }
2274 
2276  // Tests concerning arrayDiffAssocRecursive
2278 
2282  $array1 = array(
2283  'key1' => 'value1',
2284  'key2' => 'value2',
2285  'key3' => 'value3'
2286  );
2287  $array2 = array(
2288  'key1' => 'value1',
2289  'key3' => 'value3'
2290  );
2291  $expectedResult = array(
2292  'key2' => 'value2'
2293  );
2294  $actualResult = Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
2295  $this->assertEquals($expectedResult, $actualResult);
2296  }
2297 
2302  $array1 = array(
2303  'key1' => 'value1',
2304  'key2' => array(
2305  'key21' => 'value21',
2306  'key22' => 'value22',
2307  'key23' => array(
2308  'key231' => 'value231',
2309  'key232' => 'value232'
2310  )
2311  )
2312  );
2313  $array2 = array(
2314  'key1' => 'value1',
2315  'key2' => array(
2316  'key21' => 'value21',
2317  'key23' => array(
2318  'key231' => 'value231'
2319  )
2320  )
2321  );
2322  $expectedResult = array(
2323  'key2' => array(
2324  'key22' => 'value22',
2325  'key23' => array(
2326  'key232' => 'value232'
2327  )
2328  )
2329  );
2330  $actualResult = Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
2331  $this->assertEquals($expectedResult, $actualResult);
2332  }
2333 
2338  $array1 = array(
2339  'key1' => array(
2340  'key11' => 'value11',
2341  'key12' => 'value12'
2342  ),
2343  'key2' => 'value2',
2344  'key3' => 'value3'
2345  );
2346  $array2 = array(
2347  'key1' => 'value1',
2348  'key2' => array(
2349  'key21' => 'value21'
2350  )
2351  );
2352  $expectedResult = array(
2353  'key3' => 'value3'
2354  );
2355  $actualResult = Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
2356  $this->assertEquals($expectedResult, $actualResult);
2357  }
2358 
2360  // Tests concerning removeDotsFromTS
2362 
2366  $typoScript = array(
2367  'propertyA.' => array(
2368  'keyA.' => array(
2369  'valueA' => 1
2370  ),
2371  'keyB' => 2
2372  ),
2373  'propertyB' => 3
2374  );
2375  $expectedResult = array(
2376  'propertyA' => array(
2377  'keyA' => array(
2378  'valueA' => 1
2379  ),
2380  'keyB' => 2
2381  ),
2382  'propertyB' => 3
2383  );
2384  $this->assertEquals($expectedResult, Utility\GeneralUtility::removeDotsFromTS($typoScript));
2385  }
2386 
2391  $typoScript = array(
2392  'propertyA.' => array(
2393  'keyA' => 'getsOverridden',
2394  'keyA.' => array(
2395  'valueA' => 1
2396  ),
2397  'keyB' => 2
2398  ),
2399  'propertyB' => 3
2400  );
2401  $expectedResult = array(
2402  'propertyA' => array(
2403  'keyA' => array(
2404  'valueA' => 1
2405  ),
2406  'keyB' => 2
2407  ),
2408  'propertyB' => 3
2409  );
2410  $this->assertEquals($expectedResult, Utility\GeneralUtility::removeDotsFromTS($typoScript));
2411  }
2412 
2417  $typoScript = array(
2418  'propertyA.' => array(
2419  'keyA.' => array(
2420  'valueA' => 1
2421  ),
2422  'keyA' => 'willOverride',
2423  'keyB' => 2
2424  ),
2425  'propertyB' => 3
2426  );
2427  $expectedResult = array(
2428  'propertyA' => array(
2429  'keyA' => 'willOverride',
2430  'keyB' => 2
2431  ),
2432  'propertyB' => 3
2433  );
2434  $this->assertEquals($expectedResult, Utility\GeneralUtility::removeDotsFromTS($typoScript));
2435  }
2436 
2438  // Tests concerning naturalKeySortRecursive
2440 
2444  $testValues = array(
2445  1,
2446  'string',
2447  FALSE
2448  );
2449  foreach ($testValues as $testValue) {
2450  $this->assertFalse(Utility\GeneralUtility::naturalKeySortRecursive($testValue));
2451  }
2452  }
2453 
2458  $testArray = array(
2459  'bb' => 'bb',
2460  'ab' => 'ab',
2461  '123' => '123',
2462  'aaa' => 'aaa',
2463  'abc' => 'abc',
2464  '23' => '23',
2465  'ba' => 'ba',
2466  'bad' => 'bad',
2467  '2' => '2',
2468  'zap' => 'zap',
2469  '210' => '210'
2470  );
2471  $expectedResult = array(
2472  '2',
2473  '23',
2474  '123',
2475  '210',
2476  'aaa',
2477  'ab',
2478  'abc',
2479  'ba',
2480  'bad',
2481  'bb',
2482  'zap'
2483  );
2485  $this->assertEquals($expectedResult, array_values($testArray));
2486  }
2487 
2492  $testArray = array(
2493  '2' => '2',
2494  'bb' => 'bb',
2495  'ab' => 'ab',
2496  '23' => '23',
2497  'aaa' => array(
2498  'bb' => 'bb',
2499  'ab' => 'ab',
2500  '123' => '123',
2501  'aaa' => 'aaa',
2502  '2' => '2',
2503  'abc' => 'abc',
2504  'ba' => 'ba',
2505  '23' => '23',
2506  'bad' => array(
2507  'bb' => 'bb',
2508  'ab' => 'ab',
2509  '123' => '123',
2510  'aaa' => 'aaa',
2511  'abc' => 'abc',
2512  '23' => '23',
2513  'ba' => 'ba',
2514  'bad' => 'bad',
2515  '2' => '2',
2516  'zap' => 'zap',
2517  '210' => '210'
2518  ),
2519  '210' => '210',
2520  'zap' => 'zap'
2521  ),
2522  'abc' => 'abc',
2523  'ba' => 'ba',
2524  '210' => '210',
2525  'bad' => 'bad',
2526  '123' => '123',
2527  'zap' => 'zap'
2528  );
2529  $expectedResult = array(
2530  '2',
2531  '23',
2532  '123',
2533  '210',
2534  'aaa',
2535  'ab',
2536  'abc',
2537  'ba',
2538  'bad',
2539  'bb',
2540  'zap'
2541  );
2543  $this->assertEquals($expectedResult, array_values(array_keys($testArray['aaa']['bad'])));
2544  $this->assertEquals($expectedResult, array_values(array_keys($testArray['aaa'])));
2545  $this->assertEquals($expectedResult, array_values(array_keys($testArray)));
2546  }
2547 
2549  // Tests concerning get_dirs
2551 
2555  $path = PATH_typo3conf;
2556  $directories = Utility\GeneralUtility::get_dirs($path);
2557  $this->assertInternalType(\PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $directories);
2558  }
2559 
2564  $path = 'foo';
2566  $expectedResult = 'error';
2567  $this->assertEquals($expectedResult, $result);
2568  }
2569 
2571  // Tests concerning hmac
2573 
2576  public function hmacReturnsHashOfProperLength() {
2577  $hmac = Utility\GeneralUtility::hmac('message');
2578  $this->assertTrue(!empty($hmac) && is_string($hmac));
2579  $this->assertTrue(strlen($hmac) == 40);
2580  }
2581 
2586  $msg0 = 'message';
2587  $msg1 = 'message';
2588  $this->assertEquals(Utility\GeneralUtility::hmac($msg0), Utility\GeneralUtility::hmac($msg1));
2589  }
2590 
2595  $msg0 = 'message0';
2596  $msg1 = 'message1';
2597  $this->assertNotEquals(Utility\GeneralUtility::hmac($msg0), Utility\GeneralUtility::hmac($msg1));
2598  }
2599 
2601  // Tests concerning quoteJSvalue
2603 
2608  public function quoteJsValueDataProvider() {
2609  return array(
2610  'Immune characters are returned as is' => array(
2611  '._,',
2612  '._,'
2613  ),
2614  'Alphanumerical characters are returned as is' => array(
2615  'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
2616  'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
2617  ),
2618  'Angle brackets and ampersand are encoded' => array(
2619  '<>&',
2620  '\\u003C\\u003E\\u0026'
2621  ),
2622  'Quotes and backslashes are encoded' => array(
2623  '"\'\\',
2624  '\\u0022\\u0027\\u005C'
2625  ),
2626  'Forward slashes are escaped' => array(
2627  '</script>',
2628  '\\u003C\\/script\\u003E'
2629  ),
2630  'Empty string stays empty' => array(
2631  '',
2632  ''
2633  ),
2634  'Exclamation mark and space are properly encoded' => array(
2635  'Hello World!',
2636  'Hello\\u0020World\\u0021'
2637  ),
2638  'Whitespaces are properly encoded' => array(
2639  TAB . LF . CR . ' ',
2640  '\\u0009\\u000A\\u000D\\u0020'
2641  ),
2642  'Null byte is properly encoded' => array(
2643  chr(0),
2644  '\\u0000'
2645  ),
2646  'Umlauts are properly encoded' => array(
2647  'ÜüÖöÄä',
2648  '\\u00dc\\u00fc\\u00d6\\u00f6\\u00c4\\u00e4'
2649  )
2650  );
2651  }
2652 
2659  public function quoteJsValueTest($input, $expected) {
2660  $this->assertSame('\'' . $expected . '\'', Utility\GeneralUtility::quoteJSvalue($input));
2661  }
2662 
2664  // Tests concerning _GETset()
2666 
2670  $_GET = array();
2671  $GLOBALS['HTTP_GET_VARS'] = array();
2672  $getParameters = array('foo' => 'bar');
2673  Utility\GeneralUtility::_GETset($getParameters);
2674  $this->assertSame($getParameters, $_GET);
2675  }
2676 
2681  $_GET = array();
2682  $GLOBALS['HTTP_GET_VARS'] = array();
2683  $getParameters = array('foo' => 'bar');
2684  Utility\GeneralUtility::_GETset($getParameters);
2685  $this->assertSame($getParameters, $GLOBALS['HTTP_GET_VARS']);
2686  }
2687 
2692  $_GET = array();
2693  $GLOBALS['HTTP_GET_VARS'] = array();
2694  Utility\GeneralUtility::_GETset(array('foo' => 'bar'));
2695  Utility\GeneralUtility::_GETset(array('oneKey' => 'oneValue'));
2696  $this->assertEquals(array('oneKey' => 'oneValue'), $GLOBALS['HTTP_GET_VARS']);
2697  }
2698 
2702  public function getSetAssignsOneValueToOneKey() {
2703  $_GET = array();
2704  $GLOBALS['HTTP_GET_VARS'] = array();
2705  Utility\GeneralUtility::_GETset('oneValue', 'oneKey');
2706  $this->assertEquals('oneValue', $GLOBALS['HTTP_GET_VARS']['oneKey']);
2707  }
2708 
2713  $_GET = array();
2714  $GLOBALS['HTTP_GET_VARS'] = array();
2715  Utility\GeneralUtility::_GETset(array('foo' => 'bar'));
2716  Utility\GeneralUtility::_GETset('oneValue', 'oneKey');
2717  $this->assertEquals(array('foo' => 'bar', 'oneKey' => 'oneValue'), $GLOBALS['HTTP_GET_VARS']);
2718  }
2719 
2724  $_GET = array();
2725  $GLOBALS['HTTP_GET_VARS'] = array();
2726  Utility\GeneralUtility::_GETset(array('childKey' => 'oneValue'), 'parentKey');
2727  $this->assertEquals(array('parentKey' => array('childKey' => 'oneValue')), $GLOBALS['HTTP_GET_VARS']);
2728  }
2729 
2734  $_GET = array();
2735  $GLOBALS['HTTP_GET_VARS'] = array();
2736  Utility\GeneralUtility::_GETset('oneValue', 'parentKey|childKey');
2737  $this->assertEquals(array('parentKey' => array('childKey' => 'oneValue')), $GLOBALS['HTTP_GET_VARS']);
2738  }
2739 
2744  $_GET = array();
2745  $GLOBALS['HTTP_GET_VARS'] = array();
2746  Utility\GeneralUtility::_GETset(array('key1' => 'value1', 'key2' => 'value2'), 'parentKey|childKey');
2747  $this->assertEquals(array(
2748  'parentKey' => array(
2749  'childKey' => array('key1' => 'value1', 'key2' => 'value2')
2750  )
2751  ), $GLOBALS['HTTP_GET_VARS']);
2752  }
2753 
2755  // Tests concerning minifyJavaScript
2757 
2761  unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript']);
2762  $testString = $this->getUniqueId('string');
2763  $this->assertSame($testString, Utility\GeneralUtility::minifyJavaScript($testString));
2764  }
2765 
2773  $hookClassName = $this->getUniqueId('tx_coretest');
2774  $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2775  $functionName = '&' . $hookClassName . '->minify';
2776  $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2777  $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2778  $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2779  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2780  $minifyHookMock->expects($this->once())->method('minify')->will($this->returnCallback(array($this, 'isMinifyJavaScriptHookCalledCallback')));
2782  }
2783 
2789  public function isMinifyJavaScriptHookCalledCallback(array $params) {
2790  // We can not throw an exception here, because that would be caught by the
2791  // minifyJavaScript method under test itself. Thus, we just die if the
2792  // input string is not ok.
2793  if ($params['script'] !== 'foo') {
2794  die('broken');
2795  }
2796  }
2797 
2805  $hookClassName = $this->getUniqueId('tx_coretest');
2806  $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2807  $functionName = '&' . $hookClassName . '->minify';
2808  $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2809  $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2810  $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2811  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2812  $minifyHookMock->expects($this->any())->method('minify')->will($this->returnCallback(array($this, 'minifyJavaScriptErroneousCallback')));
2813  $error = '';
2814  Utility\GeneralUtility::minifyJavaScript('string to compress', $error);
2815  $this->assertSame('Error minifying java script: foo', $error);
2816  }
2817 
2825  $t3libDivMock = $this->getUniqueId('GeneralUtility');
2826  eval('namespace ' . __NAMESPACE__ . '; class ' . $t3libDivMock . ' extends \\TYPO3\\CMS\\Core\\Utility\\GeneralUtility {' . ' public static function devLog($errorMessage) {' . ' if (!($errorMessage === \'Error minifying java script: foo\')) {' . ' throw new \\UnexpectedValue(\'broken\');' . ' }' . ' throw new \\RuntimeException();' . ' }' . '}');
2827  $t3libDivMock = __NAMESPACE__ . '\\' . $t3libDivMock;
2828  $hookClassName = $this->getUniqueId('tx_coretest');
2829  $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2830  $functionName = '&' . $hookClassName . '->minify';
2831  $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2832  $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2833  $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2834  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2835  $minifyHookMock->expects($this->any())->method('minify')->will($this->returnCallback(array($this, 'minifyJavaScriptErroneousCallback')));
2836  $this->setExpectedException('\\RuntimeException');
2837  $t3libDivMock::minifyJavaScript('string to compress');
2838  }
2839 
2848  throw new \RuntimeException('foo', 1344888548);
2849  }
2850 
2852  // Tests concerning fixPermissions
2854 
2857  public function fixPermissionsSetsGroup() {
2858  if (TYPO3_OS == 'WIN') {
2859  $this->markTestSkipped('fixPermissionsSetsGroup() tests not available on Windows');
2860  }
2861  if (!function_exists('posix_getegid')) {
2862  $this->markTestSkipped('Function posix_getegid() not available, fixPermissionsSetsGroup() tests skipped');
2863  }
2864  if (posix_getegid() === -1) {
2865  $this->markTestSkipped('The fixPermissionsSetsGroup() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.');
2866  }
2867  // Create and prepare test file
2868  $filename = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
2870  $this->testFilesToDelete[] = $filename;
2871  $currentGroupId = posix_getegid();
2872  // Set target group and run method
2873  $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $currentGroupId;
2875  clearstatcache();
2876  $this->assertEquals($currentGroupId, filegroup($filename));
2877  }
2878 
2883  if (TYPO3_OS == 'WIN') {
2884  $this->markTestSkipped('fixPermissions() tests not available on Windows');
2885  }
2886  // Create and prepare test file
2887  $filename = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
2889  $this->testFilesToDelete[] = $filename;
2890  chmod($filename, 482);
2891  // Set target permissions and run method
2892  $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2893  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
2894  clearstatcache();
2895  $this->assertTrue($fixPermissionsResult);
2896  $this->assertEquals('0660', substr(decoct(fileperms($filename)), 2));
2897  }
2898 
2903  if (TYPO3_OS == 'WIN') {
2904  $this->markTestSkipped('fixPermissions() tests not available on Windows');
2905  }
2906  // Create and prepare test file
2907  $filename = PATH_site . 'typo3temp/' . $this->getUniqueId('.test_');
2909  $this->testFilesToDelete[] = $filename;
2910  chmod($filename, 482);
2911  // Set target permissions and run method
2912  $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2913  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
2914  clearstatcache();
2915  $this->assertTrue($fixPermissionsResult);
2916  $this->assertEquals('0660', substr(decoct(fileperms($filename)), 2));
2917  }
2918 
2923  if (TYPO3_OS == 'WIN') {
2924  $this->markTestSkipped('fixPermissions() tests not available on Windows');
2925  }
2926  // Create and prepare test directory
2927  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
2928  Utility\GeneralUtility::mkdir($directory);
2929  $this->testFilesToDelete[] = $directory;
2930  chmod($directory, 1551);
2931  // Set target permissions and run method
2932  $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2933  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($directory);
2934  clearstatcache();
2935  $this->assertTrue($fixPermissionsResult);
2936  $this->assertEquals('0770', substr(decoct(fileperms($directory)), 1));
2937  }
2938 
2943  if (TYPO3_OS == 'WIN') {
2944  $this->markTestSkipped('fixPermissions() tests not available on Windows');
2945  }
2946  // Create and prepare test directory
2947  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
2948  Utility\GeneralUtility::mkdir($directory);
2949  $this->testFilesToDelete[] = $directory;
2950  chmod($directory, 1551);
2951  // Set target permissions and run method
2952  $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2953  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($directory . '/');
2954  // Get actual permissions and clean up
2955  clearstatcache();
2956  $this->assertTrue($fixPermissionsResult);
2957  $this->assertEquals('0770', substr(decoct(fileperms($directory)), 1));
2958  }
2959 
2964  if (TYPO3_OS == 'WIN') {
2965  $this->markTestSkipped('fixPermissions() tests not available on Windows');
2966  }
2967  // Create and prepare test directory
2968  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('.test_');
2969  Utility\GeneralUtility::mkdir($directory);
2970  $this->testFilesToDelete[] = $directory;
2971  chmod($directory, 1551);
2972  // Set target permissions and run method
2973  $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2974  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($directory);
2975  // Get actual permissions and clean up
2976  clearstatcache();
2977  $this->assertTrue($fixPermissionsResult);
2978  $this->assertEquals('0770', substr(decoct(fileperms($directory)), 1));
2979  }
2980 
2985  if (TYPO3_OS == 'WIN') {
2986  $this->markTestSkipped('fixPermissions() tests not available on Windows');
2987  }
2988  // Create and prepare test directory and file structure
2989  $baseDirectory = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
2990  Utility\GeneralUtility::mkdir($baseDirectory);
2991  $this->testFilesToDelete[] = $baseDirectory;
2992  chmod($baseDirectory, 1751);
2993  Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/file', '42');
2994  chmod($baseDirectory . '/file', 482);
2995  Utility\GeneralUtility::mkdir($baseDirectory . '/foo');
2996  chmod($baseDirectory . '/foo', 1751);
2997  Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/foo/file', '42');
2998  chmod($baseDirectory . '/foo/file', 482);
2999  Utility\GeneralUtility::mkdir($baseDirectory . '/.bar');
3000  chmod($baseDirectory . '/.bar', 1751);
3001  // Use this if writeFileToTypo3tempDir is fixed to create hidden files in subdirectories
3002  // \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/.bar/.file', '42');
3003  // \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/.bar/..file2', '42');
3004  touch($baseDirectory . '/.bar/.file', '42');
3005  chmod($baseDirectory . '/.bar/.file', 482);
3006  touch($baseDirectory . '/.bar/..file2', '42');
3007  chmod($baseDirectory . '/.bar/..file2', 482);
3008  // Set target permissions and run method
3009  $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
3010  $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
3011  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($baseDirectory, TRUE);
3012  // Get actual permissions
3013  clearstatcache();
3014  $resultBaseDirectoryPermissions = substr(decoct(fileperms($baseDirectory)), 1);
3015  $resultBaseFilePermissions = substr(decoct(fileperms($baseDirectory . '/file')), 2);
3016  $resultFooDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/foo')), 1);
3017  $resultFooFilePermissions = substr(decoct(fileperms($baseDirectory . '/foo/file')), 2);
3018  $resultBarDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/.bar')), 1);
3019  $resultBarFilePermissions = substr(decoct(fileperms($baseDirectory . '/.bar/.file')), 2);
3020  $resultBarFile2Permissions = substr(decoct(fileperms($baseDirectory . '/.bar/..file2')), 2);
3021  // Test if everything was ok
3022  $this->assertTrue($fixPermissionsResult);
3023  $this->assertEquals('0770', $resultBaseDirectoryPermissions);
3024  $this->assertEquals('0660', $resultBaseFilePermissions);
3025  $this->assertEquals('0770', $resultFooDirectoryPermissions);
3026  $this->assertEquals('0660', $resultFooFilePermissions);
3027  $this->assertEquals('0770', $resultBarDirectoryPermissions);
3028  $this->assertEquals('0660', $resultBarFilePermissions);
3029  $this->assertEquals('0660', $resultBarFile2Permissions);
3030  }
3031 
3036  if (TYPO3_OS == 'WIN') {
3037  $this->markTestSkipped('fixPermissions() tests not available on Windows');
3038  }
3039  // Create and prepare test file
3040  $filename = PATH_site . 'typo3temp/../typo3temp/' . $this->getUniqueId('test_');
3041  $this->testFilesToDelete[] = $filename;
3042  touch($filename);
3043  chmod($filename, 482);
3044  // Set target permissions and run method
3045  $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
3046  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
3047  clearstatcache();
3048  $this->assertFalse($fixPermissionsResult);
3049  }
3050 
3055  if (TYPO3_OS == 'WIN') {
3056  $this->markTestSkipped('fixPermissions() tests not available on Windows');
3057  }
3058  $filename = 'typo3temp/' . $this->getUniqueId('test_');
3059  Utility\GeneralUtility::writeFileToTypo3tempDir(PATH_site . $filename, '42');
3060  $this->testFilesToDelete[] = PATH_site . $filename;
3061  chmod(PATH_site . $filename, 482);
3062  // Set target permissions and run method
3063  $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
3064  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
3065  clearstatcache();
3066  $this->assertTrue($fixPermissionsResult);
3067  $this->assertEquals('0660', substr(decoct(fileperms(PATH_site . $filename)), 2));
3068  }
3069 
3074  if (TYPO3_OS == 'WIN') {
3075  $this->markTestSkipped('fixPermissions() tests not available on Windows');
3076  }
3077  $filename = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
3079  $this->testFilesToDelete[] = $filename;
3080  chmod($filename, 482);
3081  unset($GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask']);
3082  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
3083  clearstatcache();
3084  $this->assertTrue($fixPermissionsResult);
3085  $this->assertEquals('0644', substr(decoct(fileperms($filename)), 2));
3086  }
3087 
3092  if (TYPO3_OS == 'WIN') {
3093  $this->markTestSkipped('fixPermissions() tests not available on Windows');
3094  }
3095  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
3096  Utility\GeneralUtility::mkdir($directory);
3097  $this->testFilesToDelete[] = $directory;
3098  chmod($directory, 1551);
3099  unset($GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask']);
3100  $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($directory);
3101  clearstatcache();
3102  $this->assertTrue($fixPermissionsResult);
3103  $this->assertEquals('0755', substr(decoct(fileperms($directory)), 1));
3104  }
3105 
3107  // Tests concerning mkdir
3109 
3112  public function mkdirCreatesDirectory() {
3113  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
3114  $mkdirResult = Utility\GeneralUtility::mkdir($directory);
3115  $this->testFilesToDelete[] = $directory;
3116  clearstatcache();
3117  $this->assertTrue($mkdirResult);
3118  $this->assertTrue(is_dir($directory));
3119  }
3120 
3124  public function mkdirCreatesHiddenDirectory() {
3125  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('.test_');
3126  $mkdirResult = Utility\GeneralUtility::mkdir($directory);
3127  $this->testFilesToDelete[] = $directory;
3128  clearstatcache();
3129  $this->assertTrue($mkdirResult);
3130  $this->assertTrue(is_dir($directory));
3131  }
3132 
3137  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('test_') . '/';
3138  $mkdirResult = Utility\GeneralUtility::mkdir($directory);
3139  $this->testFilesToDelete[] = $directory;
3140  clearstatcache();
3141  $this->assertTrue($mkdirResult);
3142  $this->assertTrue(is_dir($directory));
3143  }
3144 
3149  if (TYPO3_OS == 'WIN') {
3150  $this->markTestSkipped('mkdirSetsPermissionsOfCreatedDirectory() test not available on Windows');
3151  }
3152  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('test_');
3153  $oldUmask = umask(19);
3154  $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0772';
3155  Utility\GeneralUtility::mkdir($directory);
3156  $this->testFilesToDelete[] = $directory;
3157  clearstatcache();
3158  $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
3159  umask($oldUmask);
3160  $this->assertEquals($resultDirectoryPermissions, '0772');
3161  }
3162 
3167  if (!function_exists('posix_getegid')) {
3168  $this->markTestSkipped('Function posix_getegid() not available, mkdirSetsGroupOwnershipOfCreatedDirectory() tests skipped');
3169  }
3170  if (posix_getegid() === -1) {
3171  $this->markTestSkipped('The mkdirSetsGroupOwnershipOfCreatedDirectory() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.');
3172  }
3173  $swapGroup = $this->checkGroups(__FUNCTION__);
3174  if ($swapGroup !== FALSE) {
3175  $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
3176  $directory = $this->getUniqueId('mkdirtest_');
3177  Utility\GeneralUtility::mkdir(PATH_site . 'typo3temp/' . $directory);
3178  $this->testFilesToDelete[] = PATH_site . 'typo3temp/' . $directory;
3179  clearstatcache();
3180  $resultDirectoryGroupInfo = posix_getgrgid(filegroup(PATH_site . 'typo3temp/' . $directory));
3181  $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
3182  $this->assertEquals($resultDirectoryGroup, $swapGroup);
3183  }
3184  }
3185 
3187  // Helper function for filesystem ownership tests
3189 
3196  private function checkGroups($methodName) {
3197  if (TYPO3_OS == 'WIN') {
3198  $this->markTestSkipped($methodName . '() test not available on Windows.');
3199  return FALSE;
3200  }
3201  if (!function_exists('posix_getgroups')) {
3202  $this->markTestSkipped('Function posix_getgroups() not available, ' . $methodName . '() tests skipped');
3203  }
3204  $groups = posix_getgroups();
3205  if (count($groups) <= 1) {
3206  $this->markTestSkipped($methodName . '() test cannot be done when the web server user is only member of 1 group.');
3207  return FALSE;
3208  }
3209  $uname = strtolower(php_uname());
3210  $groupOffset = 1;
3211  if (strpos($uname, 'darwin') !== FALSE) {
3212  // We are on OSX and it seems that the first group needs to be fetched since Mavericks
3213  $groupOffset = 0;
3214  }
3215  $groupInfo = posix_getgrgid($groups[$groupOffset]);
3216  return $groupInfo['name'];
3217  }
3218 
3220  // Tests concerning mkdir_deep
3222 
3225  public function mkdirDeepCreatesDirectory() {
3226  $directory = 'typo3temp/' . $this->getUniqueId('test_');
3227  Utility\GeneralUtility::mkdir_deep(PATH_site, $directory);
3228  $this->testFilesToDelete[] = PATH_site . $directory;
3229  $this->assertTrue(is_dir(PATH_site . $directory));
3230  }
3231 
3236  $directory = 'typo3temp/' . $this->getUniqueId('test_');
3237  $subDirectory = $directory . '/foo';
3238  Utility\GeneralUtility::mkdir_deep(PATH_site, $subDirectory);
3239  $this->testFilesToDelete[] = PATH_site . $directory;
3240  $this->assertTrue(is_dir(PATH_site . $subDirectory));
3241  }
3242 
3247  if (TYPO3_OS == 'WIN') {
3248  $this->markTestSkipped('mkdirDeepFixesPermissionsOfCreatedDirectory() test not available on Windows.');
3249  }
3250  $directory = $this->getUniqueId('mkdirdeeptest_');
3251  $oldUmask = umask(19);
3252  $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0777';
3253  Utility\GeneralUtility::mkdir_deep(PATH_site . 'typo3temp/', $directory);
3254  $this->testFilesToDelete[] = PATH_site . 'typo3temp/' . $directory;
3255  clearstatcache();
3256  umask($oldUmask);
3257  $this->assertEquals('777', substr(decoct(fileperms(PATH_site . 'typo3temp/' . $directory)), -3, 3));
3258  }
3259 
3264  if (TYPO3_OS == 'WIN') {
3265  $this->markTestSkipped('mkdirDeepFixesPermissionsOnNewParentDirectory() test not available on Windows.');
3266  }
3267  $directory = $this->getUniqueId('mkdirdeeptest_');
3268  $subDirectory = $directory . '/bar';
3269  $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0777';
3270  $oldUmask = umask(19);
3271  Utility\GeneralUtility::mkdir_deep(PATH_site . 'typo3temp/', $subDirectory);
3272  $this->testFilesToDelete[] = PATH_site . 'typo3temp/' . $directory;
3273  clearstatcache();
3274  umask($oldUmask);
3275  $this->assertEquals('777', substr(decoct(fileperms(PATH_site . 'typo3temp/' . $directory)), -3, 3));
3276  }
3277 
3282  if (TYPO3_OS == 'WIN') {
3283  $this->markTestSkipped('mkdirDeepDoesNotChangePermissionsOfExistingSubDirectories() test not available on Windows.');
3284  }
3285  $baseDirectory = PATH_site . 'typo3temp/';
3286  $existingDirectory = $this->getUniqueId('test_existing_') . '/';
3287  $newSubDirectory = $this->getUniqueId('test_new_');
3288  @mkdir(($baseDirectory . $existingDirectory));
3289  $this->testFilesToDelete[] = $baseDirectory . $existingDirectory;
3290  chmod($baseDirectory . $existingDirectory, 482);
3291  Utility\GeneralUtility::mkdir_deep($baseDirectory, $existingDirectory . $newSubDirectory);
3292  $this->assertEquals('0742', substr(decoct(fileperms($baseDirectory . $existingDirectory)), 2));
3293  }
3294 
3299  $swapGroup = $this->checkGroups(__FUNCTION__);
3300  if ($swapGroup !== FALSE) {
3301  $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
3302  $directory = $this->getUniqueId('mkdirdeeptest_');
3303  Utility\GeneralUtility::mkdir_deep(PATH_site . 'typo3temp/', $directory);
3304  $this->testFilesToDelete[] = PATH_site . 'typo3temp/' . $directory;
3305  clearstatcache();
3306  $resultDirectoryGroupInfo = posix_getgrgid(filegroup(PATH_site . 'typo3temp/' . $directory));
3307  $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
3308  $this->assertEquals($resultDirectoryGroup, $swapGroup);
3309  }
3310  }
3311 
3316  $swapGroup = $this->checkGroups(__FUNCTION__);
3317  if ($swapGroup !== FALSE) {
3318  $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
3319  $directory = $this->getUniqueId('mkdirdeeptest_');
3320  $subDirectory = $directory . '/bar';
3321  Utility\GeneralUtility::mkdir_deep(PATH_site . 'typo3temp/', $subDirectory);
3322  $this->testFilesToDelete[] = PATH_site . 'typo3temp/' . $directory;
3323  clearstatcache();
3324  $resultDirectoryGroupInfo = posix_getgrgid(filegroup(PATH_site . 'typo3temp/' . $directory));
3325  $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
3326  $this->assertEquals($resultDirectoryGroup, $swapGroup);
3327  }
3328  }
3329 
3334  $swapGroup = $this->checkGroups(__FUNCTION__);
3335  if ($swapGroup !== FALSE) {
3336  $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $swapGroup;
3337  $directory = $this->getUniqueId('mkdirdeeptest_');
3338  $subDirectory = $directory . '/bar';
3339  Utility\GeneralUtility::mkdir_deep(PATH_site . 'typo3temp/', $subDirectory);
3340  $this->testFilesToDelete[] = PATH_site . 'typo3temp/' . $directory;
3341  clearstatcache();
3342  $resultDirectoryGroupInfo = posix_getgrgid(filegroup(PATH_site . 'typo3temp/' . $subDirectory));
3343  $resultDirectoryGroup = $resultDirectoryGroupInfo['name'];
3344  $this->assertEquals($resultDirectoryGroup, $swapGroup);
3345  }
3346  }
3347 
3352  if (!class_exists('org\\bovigo\\vfs\\vfsStreamWrapper')) {
3353  $this->markTestSkipped('mkdirDeepCreatesDirectoryInVfsStream() test not available with this phpunit version.');
3354  }
3355  vfsStreamWrapper::register();
3356  $baseDirectory = $this->getUniqueId('test_');
3357  vfsStreamWrapper::setRoot(new vfsStreamDirectory($baseDirectory));
3358  Utility\GeneralUtility::mkdir_deep('vfs://' . $baseDirectory . '/', 'sub');
3359  $this->assertTrue(is_dir('vfs://' . $baseDirectory . '/sub'));
3360  }
3361 
3367  Utility\GeneralUtility::mkdir_deep('http://localhost');
3368  }
3369 
3376  }
3377 
3383  Utility\GeneralUtility::mkdir_deep(PATH_site . 'typo3temp/foo', array());
3384  }
3385 
3387  // Tests concerning rmdir
3389 
3393  public function rmdirRemovesFile() {
3394  $file = PATH_site . 'typo3temp/' . $this->getUniqueId('file_');
3395  touch($file);
3397  $this->assertFalse(file_exists($file));
3398  }
3399 
3404  $file = PATH_site . 'typo3temp/' . $this->getUniqueId('file_');
3405  touch($file);
3406  $this->assertTrue(Utility\GeneralUtility::rmdir($file));
3407  }
3408 
3413  $file = PATH_site . 'typo3temp/' . $this->getUniqueId('file_');
3414  $this->assertFalse(Utility\GeneralUtility::rmdir($file));
3415  }
3416 
3420  public function rmdirRemovesDirectory() {
3421  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('directory_');
3422  mkdir($directory);
3423  Utility\GeneralUtility::rmdir($directory);
3424  $this->assertFalse(file_exists($directory));
3425  }
3426 
3431  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('directory_') . '/';
3432  mkdir($directory);
3433  Utility\GeneralUtility::rmdir($directory);
3434  $this->assertFalse(file_exists($directory));
3435  }
3436 
3441  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('directory_') . '/';
3442  mkdir($directory);
3443  $file = $this->getUniqueId('file_');
3444  touch($directory . $file);
3445  $this->testFilesToDelete[] = $directory;
3446  $return = Utility\GeneralUtility::rmdir($directory);
3447  $this->assertTrue(file_exists($directory));
3448  $this->assertTrue(file_exists($directory . $file));
3449  $this->assertFalse($return);
3450  }
3451 
3456  $directory = PATH_site . 'typo3temp/' . $this->getUniqueId('directory_') . '/';
3457  mkdir($directory);
3458  mkdir($directory . 'sub/');
3459  touch($directory . 'sub/file');
3460  $return = Utility\GeneralUtility::rmdir($directory, TRUE);
3461  $this->assertFalse(file_exists($directory));
3462  $this->assertTrue($return);
3463  }
3464 
3468  public function rmdirRemovesLinkToDirectory() {
3469  if (TYPO3_OS === 'WIN') {
3470  $this->markTestSkipped('Test not available on Windows OS.');
3471  }
3472  $existingDirectory = PATH_site . 'typo3temp/' . $this->getUniqueId('notExists_') . '/';
3473  mkdir($existingDirectory);
3474  $this->testFilesToDelete[] = $existingDirectory;
3475  $symlinkName = PATH_site . 'typo3temp/' . $this->getUniqueId('link_');
3476  symlink($existingDirectory, $symlinkName);
3477  Utility\GeneralUtility::rmdir($symlinkName, TRUE);
3478  $this->assertFalse(is_link($symlinkName));
3479  }
3480 
3485  if (TYPO3_OS === 'WIN') {
3486  $this->markTestSkipped('Test not available on Windows OS.');
3487  }
3488  $notExistingDirectory = PATH_site . 'typo3temp/' . $this->getUniqueId('notExists_') . '/';
3489  $symlinkName = PATH_site . 'typo3temp/' . $this->getUniqueId('link_');
3490  symlink($notExistingDirectory, $symlinkName);
3491  Utility\GeneralUtility::rmdir($symlinkName, TRUE);
3492  $this->assertFalse(is_link($symlinkName));
3493  }
3494 
3498  public function rmdirRemovesDeadLinkToFile() {
3499  if (TYPO3_OS === 'WIN') {
3500  $this->markTestSkipped('Test not available on Windows OS.');
3501  }
3502  $notExistingFile = PATH_site . 'typo3temp/' . $this->getUniqueId('notExists_');
3503  $symlinkName = PATH_site . 'typo3temp/' . $this->getUniqueId('link_');
3504  symlink($notExistingFile, $symlinkName);
3505  Utility\GeneralUtility::rmdir($symlinkName, TRUE);
3506  $this->assertFalse(is_link($symlinkName));
3507  }
3508 
3510  // Tests concerning getFilesInDir
3512 
3518  protected function getFilesInDirCreateTestDirectory() {
3519  if (!class_exists('org\\bovigo\\vfs\\vfsStreamWrapper')) {
3520  $this->markTestSkipped('getFilesInDirCreateTestDirectory() helper method not available without vfsStream.');
3521  }
3522  $structure = array(
3523  'subDirectory' => array(
3524  'test.php' => 'butter',
3525  'other.php' => 'milk',
3526  'stuff.csv' => 'honey',
3527  ),
3528  'excludeMe.txt' => 'cocoa nibs',
3529  'testB.txt' => 'olive oil',
3530  'testA.txt' => 'eggs',
3531  'testC.txt' => 'carrots',
3532  'test.js' => 'oranges',
3533  'test.css' => 'apples',
3534  '.secret.txt' => 'sammon',
3535  );
3536  vfsStream::setup('test', NULL, $structure);
3537  $vfsUrl = vfsStream::url('test');
3538 
3539  if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
3540  // set random values for mtime
3541  foreach ($structure as $structureLevel1Key => $structureLevel1Content) {
3542  $newMtime = rand();
3543  if (is_array($structureLevel1Content)) {
3544  foreach ($structureLevel1Content as $structureLevel2Key => $structureLevel2Content) {
3545  touch($vfsUrl . '/' . $structureLevel1Key . '/' . $structureLevel2Key, $newMtime);
3546  }
3547  } else {
3548  touch($vfsUrl . '/' . $structureLevel1Key, $newMtime);
3549  }
3550  }
3551  }
3552  return $vfsUrl;
3553  }
3554 
3558  public function getFilesInDirFindsRegularFile() {
3559  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3560  $files = Utility\GeneralUtility::getFilesInDir($vfsStreamUrl);
3561  $this->assertContains('testA.txt', $files);
3562  }
3563 
3567  public function getFilesInDirFindsHiddenFile() {
3568  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3569  $files = Utility\GeneralUtility::getFilesInDir($vfsStreamUrl);
3570  $this->assertContains('.secret.txt', $files);
3571  }
3572 
3577  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3578  $files = Utility\GeneralUtility::getFilesInDir($vfsStreamUrl, 'txt,js');
3579  $this->assertContains('testA.txt', $files);
3580  $this->assertContains('test.js', $files);
3581  }
3582 
3587  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3588  $files = Utility\GeneralUtility::getFilesInDir($vfsStreamUrl, 'txt,js');
3589  $this->assertContains('testA.txt', $files);
3590  $this->assertContains('test.js', $files);
3591  $this->assertNotContains('test.css', $files);
3592  }
3593 
3598  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3599  $files = Utility\GeneralUtility::getFilesInDir($vfsStreamUrl, '', FALSE, '', 'excludeMe.*');
3600  $this->assertContains('test.js', $files);
3601  $this->assertNotContains('excludeMe.txt', $files);
3602  }
3603 
3607  public function getFilesInDirCanPrependPath() {
3608  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3609  $this->assertContains(
3610  $vfsStreamUrl . '/testA.txt',
3611  Utility\GeneralUtility::getFilesInDir($vfsStreamUrl, '', TRUE)
3612  );
3613  }
3614 
3619  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3620  $this->assertSame(
3621  array_values(Utility\GeneralUtility::getFilesInDir($vfsStreamUrl, '', FALSE)),
3622  array('.secret.txt', 'excludeMe.txt', 'test.css', 'test.js', 'testA.txt', 'testB.txt', 'testC.txt')
3623  );
3624  }
3625 
3629  public function getFilesInDirCanOrderByMtime() {
3630  if (version_compare(PHP_VERSION, '5.4.0', '<')) {
3631  $this->markTestSkipped('touch() does not work with vfsStream in PHP 5.3 and below.');
3632  }
3633 
3634  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3635  $files = array();
3636  $iterator = new \DirectoryIterator($vfsStreamUrl);
3637  foreach ($iterator as $fileinfo) {
3638  if ($fileinfo->isFile()) {
3639  $files[$fileinfo->getFilename()] = $fileinfo->getMTime();
3640  }
3641  }
3642  asort($files);
3643  $this->assertSame(
3644  array_values(Utility\GeneralUtility::getFilesInDir($vfsStreamUrl, '', FALSE, 'mtime')),
3645  array_keys($files)
3646  );
3647  }
3648 
3653  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3654  $this->assertArrayHasKey(
3655  md5($vfsStreamUrl . '/testA.txt'),
3656  Utility\GeneralUtility::getFilesInDir($vfsStreamUrl)
3657  );
3658  }
3659 
3664  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3665  $this->assertNotContains(
3666  'subDirectory',
3667  Utility\GeneralUtility::getFilesInDir($vfsStreamUrl)
3668  );
3669  }
3670 
3678  $vfsStreamUrl = $this->getFilesInDirCreateTestDirectory();
3679  $files = Utility\GeneralUtility::getFilesInDir($vfsStreamUrl);
3680  $this->assertNotContains('..', $files);
3681  $this->assertNotContains('.', $files);
3682  }
3683 
3685  // Tests concerning unQuoteFilenames
3687 
3693  return array(
3694  // Some theoretical tests first
3695  array(
3696  'aa bb "cc" "dd"',
3697  array('aa', 'bb', '"cc"', '"dd"'),
3698  array('aa', 'bb', 'cc', 'dd')
3699  ),
3700  array(
3701  'aa bb "cc dd"',
3702  array('aa', 'bb', '"cc dd"'),
3703  array('aa', 'bb', 'cc dd')
3704  ),
3705  array(
3706  '\'aa bb\' "cc dd"',
3707  array('\'aa bb\'', '"cc dd"'),
3708  array('aa bb', 'cc dd')
3709  ),
3710  array(
3711  '\'aa bb\' cc "dd"',
3712  array('\'aa bb\'', 'cc', '"dd"'),
3713  array('aa bb', 'cc', 'dd')
3714  ),
3715  // Now test against some real world examples
3716  array(
3717  '/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"',
3718  array(
3719  '/opt/local/bin/gm.exe',
3720  'convert',
3721  '+profile',
3722  '\'*\'',
3723  '-geometry',
3724  '170x136!',
3725  '-negate',
3726  '"C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
3727  '"C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
3728  ),
3729  array(
3730  '/opt/local/bin/gm.exe',
3731  'convert',
3732  '+profile',
3733  '*',
3734  '-geometry',
3735  '170x136!',
3736  '-negate',
3737  'C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
3738  'C:/Users/Someuser.Domain/Documents/Htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
3739  )
3740  ),
3741  array(
3742  '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"',
3743  array(
3744  'C:/opt/local/bin/gm.exe',
3745  'convert',
3746  '+profile',
3747  '\'*\'',
3748  '-geometry',
3749  '170x136!',
3750  '-negate',
3751  '"C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
3752  '"C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
3753  ),
3754  array(
3755  'C:/opt/local/bin/gm.exe',
3756  'convert',
3757  '+profile',
3758  '*',
3759  '-geometry',
3760  '170x136!',
3761  '-negate',
3762  'C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
3763  'C:/Program Files/Apache2/htdocs/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
3764  )
3765  ),
3766  array(
3767  '/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"',
3768  array(
3769  '/usr/bin/gm',
3770  'convert',
3771  '+profile',
3772  '\'*\'',
3773  '-geometry',
3774  '170x136!',
3775  '-negate',
3776  '"/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
3777  '"/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
3778  ),
3779  array(
3780  '/usr/bin/gm',
3781  'convert',
3782  '+profile',
3783  '*',
3784  '-geometry',
3785  '170x136!',
3786  '-negate',
3787  '/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
3788  '/Shared Items/Data/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
3789  )
3790  ),
3791  array(
3792  '/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"',
3793  array(
3794  '/usr/bin/gm',
3795  'convert',
3796  '+profile',
3797  '\'*\'',
3798  '-geometry',
3799  '170x136!',
3800  '-negate',
3801  '"/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]"',
3802  '"/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif"'
3803  ),
3804  array(
3805  '/usr/bin/gm',
3806  'convert',
3807  '+profile',
3808  '*',
3809  '-geometry',
3810  '170x136!',
3811  '-negate',
3812  '/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
3813  '/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
3814  )
3815  ),
3816  array(
3817  '/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\'',
3818  array(
3819  '/usr/bin/gm',
3820  'convert',
3821  '+profile',
3822  '\'*\'',
3823  '-geometry',
3824  '170x136!',
3825  '-negate',
3826  '\'/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]\'',
3827  '\'/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif\''
3828  ),
3829  array(
3830  '/usr/bin/gm',
3831  'convert',
3832  '+profile',
3833  '*',
3834  '-geometry',
3835  '170x136!',
3836  '-negate',
3837  '/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif[0]',
3838  '/Network/Servers/server01.internal/Projects/typo3temp/temp/61401f5c16c63d58e1d92e8a2449f2fe_maskNT.gif'
3839  )
3840  )
3841  );
3842  }
3843 
3850  public function explodeAndUnquoteImageMagickCommands($source, $expectedQuoted, $expectedUnquoted) {
3851  $actualQuoted = Utility\GeneralUtility::unQuoteFilenames($source);
3852  $acutalUnquoted = Utility\GeneralUtility::unQuoteFilenames($source, TRUE);
3853  $this->assertEquals($expectedQuoted, $actualQuoted, 'The exploded command does not match the expected');
3854  $this->assertEquals($expectedUnquoted, $acutalUnquoted, 'The exploded and unquoted command does not match the expected');
3855  }
3856 
3858  // Tests concerning split_fileref
3860 
3864  $directoryName = $this->getUniqueId('test_') . '.com';
3865  $directoryPath = PATH_site . 'typo3temp/';
3866  $directory = $directoryPath . $directoryName;
3867  mkdir($directory, octdec($GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask']));
3868  $fileInfo = Utility\GeneralUtility::split_fileref($directory);
3869  $directoryCreated = is_dir($directory);
3870  rmdir($directory);
3871  $this->assertTrue($directoryCreated);
3872  $this->assertInternalType(\PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $fileInfo);
3873  $this->assertEquals($directoryPath, $fileInfo['path']);
3874  $this->assertEquals($directoryName, $fileInfo['file']);
3875  $this->assertEquals($directoryName, $fileInfo['filebody']);
3876  $this->assertEquals('', $fileInfo['fileext']);
3877  $this->assertArrayNotHasKey('realFileext', $fileInfo);
3878  }
3879 
3884  $testFile = 'fileadmin/media/someFile.png';
3885  $fileInfo = Utility\GeneralUtility::split_fileref($testFile);
3886  $this->assertInternalType(\PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $fileInfo);
3887  $this->assertEquals('fileadmin/media/', $fileInfo['path']);
3888  $this->assertEquals('someFile.png', $fileInfo['file']);
3889  $this->assertEquals('someFile', $fileInfo['filebody']);
3890  $this->assertEquals('png', $fileInfo['fileext']);
3891  }
3892 
3894  // Tests concerning dirname
3896 
3900  public function dirnameDataProvider() {
3901  return array(
3902  'absolute path with multiple part and file' => array('/dir1/dir2/script.php', '/dir1/dir2'),
3903  'absolute path with one part' => array('/dir1/', '/dir1'),
3904  'absolute path to file without extension' => array('/dir1/something', '/dir1'),
3905  'relative path with one part and file' => array('dir1/script.php', 'dir1'),
3906  'relative one-character path with one part and file' => array('d/script.php', 'd'),
3907  'absolute zero-part path with file' => array('/script.php', ''),
3908  'empty string' => array('', '')
3909  );
3910  }
3911 
3918  public function dirnameWithDataProvider($input, $expectedValue) {
3919  $this->assertEquals($expectedValue, Utility\GeneralUtility::dirname($input));
3920  }
3921 
3923  // Tests concerning resolveBackPath
3925 
3929  public function resolveBackPathDataProvider() {
3930  return array(
3931  'empty path' => array('', ''),
3932  'this directory' => array('./', './'),
3933  'relative directory without ..' => array('dir1/dir2/dir3/', 'dir1/dir2/dir3/'),
3934  'relative path without ..' => array('dir1/dir2/script.php', 'dir1/dir2/script.php'),
3935  'absolute directory without ..' => array('/dir1/dir2/dir3/', '/dir1/dir2/dir3/'),
3936  'absolute path without ..' => array('/dir1/dir2/script.php', '/dir1/dir2/script.php'),
3937  'only one directory upwards without trailing slash' => array('..', '..'),
3938  'only one directory upwards with trailing slash' => array('../', '../'),
3939  'one level with trailing ..' => array('dir1/..', ''),
3940  'one level with trailing ../' => array('dir1/../', ''),
3941  'two levels with trailing ..' => array('dir1/dir2/..', 'dir1'),
3942  'two levels with trailing ../' => array('dir1/dir2/../', 'dir1/'),
3943  'leading ../ without trailing /' => array('../dir1', '../dir1'),
3944  'leading ../ with trailing /' => array('../dir1/', '../dir1/'),
3945  'leading ../ and inside path' => array('../dir1/dir2/../dir3/', '../dir1/dir3/'),
3946  'one times ../ in relative directory' => array('dir1/../dir2/', 'dir2/'),
3947  'one times ../ in absolute directory' => array('/dir1/../dir2/', '/dir2/'),
3948  'one times ../ in relative path' => array('dir1/../dir2/script.php', 'dir2/script.php'),
3949  'one times ../ in absolute path' => array('/dir1/../dir2/script.php', '/dir2/script.php'),
3950  'consecutive ../' => array('dir1/dir2/dir3/../../../dir4', 'dir4'),
3951  'distrubuted ../ with trailing /' => array('dir1/../dir2/dir3/../', 'dir2/'),
3952  'distributed ../ without trailing /' => array('dir1/../dir2/dir3/..', 'dir2'),
3953  'multiple distributed and consecutive ../ together' => array('dir1/dir2/dir3/dir4/../../dir5/dir6/dir7/../dir8/', 'dir1/dir2/dir5/dir6/dir8/'),
3954  'dirname with leading ..' => array('dir1/..dir2/dir3/', 'dir1/..dir2/dir3/'),
3955  'dirname with trailing ..' => array('dir1/dir2../dir3/', 'dir1/dir2../dir3/'),
3956  'more times upwards than downwards in directory' => array('dir1/../../', '../'),
3957  'more times upwards than downwards in path' => array('dir1/../../script.php', '../script.php')
3958  );
3959  }
3960 
3967  public function resolveBackPathWithDataProvider($input, $expectedValue) {
3968  $this->assertEquals($expectedValue, Utility\GeneralUtility::resolveBackPath($input));
3969  }
3970 
3972  // Tests concerning makeInstance, setSingletonInstance, addInstance, purgeInstances
3974 
3980  }
3981 
3988  }
3989 
3996  }
3997 
4004  }
4005 
4012  }
4013 
4018  $className = get_class($this->getMock('foo'));
4019  $this->assertTrue(Utility\GeneralUtility::makeInstance($className) instanceof $className);
4020  }
4021 
4026  $className = $this->getUniqueId('testingClass');
4027  if (!class_exists($className, FALSE)) {
4028  eval('class ' . $className . ' {' . ' public $constructorParameter1;' . ' public $constructorParameter2;' . ' public function __construct($parameter1, $parameter2) {' . ' $this->constructorParameter1 = $parameter1;' . ' $this->constructorParameter2 = $parameter2;' . ' }' . '}');
4029  }
4030  $instance = Utility\GeneralUtility::makeInstance($className, 'one parameter', 'another parameter');
4031  $this->assertEquals('one parameter', $instance->constructorParameter1, 'The first constructor parameter has not been set.');
4032  $this->assertEquals('another parameter', $instance->constructorParameter2, 'The second constructor parameter has not been set.');
4033  }
4034 
4039  $classNameOriginal = get_class($this->getMock($this->getUniqueId('foo')));
4040  $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][$classNameOriginal] = array('className' => $classNameOriginal . 'Other');
4041  eval('class ' . $classNameOriginal . 'Other extends ' . $classNameOriginal . ' {}');
4042  $this->assertInstanceOf($classNameOriginal . 'Other', Utility\GeneralUtility::makeInstance($classNameOriginal));
4043  }
4044 
4049  $classNameOriginal = get_class($this->getMock($this->getUniqueId('foo')));
4050  $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][$classNameOriginal] = array('className' => $classNameOriginal . 'Other');
4051  $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][$classNameOriginal . 'Other'] = array('className' => $classNameOriginal . 'OtherOther');
4052  eval('class ' . $classNameOriginal . 'Other extends ' . $classNameOriginal . ' {}');
4053  eval('class ' . $classNameOriginal . 'OtherOther extends ' . $classNameOriginal . 'Other {}');
4054  $this->assertInstanceOf($classNameOriginal . 'OtherOther', Utility\GeneralUtility::makeInstance($classNameOriginal));
4055  }
4056 
4061  $className = get_class($this->getMock('foo'));
4062  $this->assertNotSame(Utility\GeneralUtility::makeInstance($className), Utility\GeneralUtility::makeInstance($className));
4063  }
4064 
4069  $className = get_class($this->getMock('TYPO3\\CMS\\Core\\SingletonInterface'));
4070  $this->assertSame(Utility\GeneralUtility::makeInstance($className), Utility\GeneralUtility::makeInstance($className));
4071  }
4072 
4077  $className = get_class($this->getMock('TYPO3\\CMS\\Core\\SingletonInterface'));
4078  $instance = Utility\GeneralUtility::makeInstance($className);
4080  $this->assertNotSame($instance, Utility\GeneralUtility::makeInstance($className));
4081  }
4082 
4088  $instance = $this->getMock('TYPO3\\CMS\\Core\\SingletonInterface');
4090  }
4091 
4097  $instance = $this->getMock('TYPO3\\CMS\\Core\\SingletonInterface', array('foo'));
4098  $singletonClassName = get_class($this->getMock('TYPO3\\CMS\\Core\\SingletonInterface'));
4099  Utility\GeneralUtility::setSingletonInstance($singletonClassName, $instance);
4100  }
4101 
4106  $instance = $this->getMock('TYPO3\\CMS\\Core\\SingletonInterface');
4107  $singletonClassName = get_class($instance);
4108  Utility\GeneralUtility::setSingletonInstance($singletonClassName, $instance);
4109  $this->assertSame($instance, Utility\GeneralUtility::makeInstance($singletonClassName));
4110  }
4111 
4116  $instance1 = $this->getMock('TYPO3\\CMS\\Core\\SingletonInterface');
4117  $singletonClassName = get_class($instance1);
4118  $instance2 = new $singletonClassName();
4119  Utility\GeneralUtility::setSingletonInstance($singletonClassName, $instance1);
4120  Utility\GeneralUtility::setSingletonInstance($singletonClassName, $instance2);
4121  $this->assertSame($instance2, Utility\GeneralUtility::makeInstance($singletonClassName));
4122  }
4123 
4128  $instance = $this->getMock('TYPO3\\CMS\\Core\\SingletonInterface');
4129  $instanceClassName = get_class($instance);
4130  Utility\GeneralUtility::setSingletonInstance($instanceClassName, $instance);
4131  $registeredSingletonInstances = Utility\GeneralUtility::getSingletonInstances();
4132  $this->assertArrayHasKey($instanceClassName, $registeredSingletonInstances);
4133  $this->assertSame($registeredSingletonInstances[$instanceClassName], $instance);
4134  }
4135 
4140  $instance = $this->getMock('TYPO3\\CMS\\Core\\SingletonInterface');
4141  $instanceClassName = get_class($instance);
4142  Utility\GeneralUtility::setSingletonInstance($instanceClassName, $instance);
4144  $registeredSingletonInstances = Utility\GeneralUtility::getSingletonInstances();
4145  $this->assertArrayNotHasKey($instanceClassName, $registeredSingletonInstances);
4146  }
4147 
4152  $instance = $this->getMock('TYPO3\\CMS\\Core\\SingletonInterface');
4153  $instanceClassName = get_class($instance);
4155  array($instanceClassName => $instance)
4156  );
4157  $registeredSingletonInstances = Utility\GeneralUtility::getSingletonInstances();
4158  $this->assertArrayHasKey($instanceClassName, $registeredSingletonInstances);
4159  $this->assertSame($registeredSingletonInstances[$instanceClassName], $instance);
4160  }
4161 
4167  $instance = $this->getMock('foo');
4168  Utility\GeneralUtility::addInstance('', $instance);
4169  }
4170 
4176  $instance = $this->getMock('foo', array('bar'));
4177  $singletonClassName = get_class($this->getMock('foo'));
4178  Utility\GeneralUtility::addInstance($singletonClassName, $instance);
4179  }
4180 
4186  $instance = $this->getMock('TYPO3\\CMS\\Core\\SingletonInterface');
4187  Utility\GeneralUtility::addInstance(get_class($instance), $instance);
4188  }
4189 
4194  $instance = $this->getMock('foo');
4195  $className = get_class($instance);
4196  Utility\GeneralUtility::addInstance($className, $instance);
4197  $this->assertSame($instance, Utility\GeneralUtility::makeInstance($className));
4198  }
4199 
4204  $instance = $this->getMock('foo');
4205  $className = get_class($instance);
4206  Utility\GeneralUtility::addInstance($className, $instance);
4207  $this->assertNotSame(Utility\GeneralUtility::makeInstance($className), Utility\GeneralUtility::makeInstance($className));
4208  }
4209 
4214  $instance1 = $this->getMock('foo');
4215  $className = get_class($instance1);
4216  Utility\GeneralUtility::addInstance($className, $instance1);
4217  $instance2 = new $className();
4218  Utility\GeneralUtility::addInstance($className, $instance2);
4219  $this->assertSame($instance1, Utility\GeneralUtility::makeInstance($className), 'The first returned instance does not match the first added instance.');
4220  $this->assertSame($instance2, Utility\GeneralUtility::makeInstance($className), 'The second returned instance does not match the second added instance.');
4221  }
4222 
4227  $instance = $this->getMock('foo');
4228  $className = get_class($instance);
4229  Utility\GeneralUtility::addInstance($className, $instance);
4231  $this->assertNotSame($instance, Utility\GeneralUtility::makeInstance($className));
4232  }
4233 
4240  $data = array(
4241  'double slash in path' => array('path//path'),
4242  'backslash in path' => array('path\\path'),
4243  'directory up in path' => array('path/../path'),
4244  'directory up at the beginning' => array('../path'),
4245  'NUL character in path' => array('path' . chr(0) . 'path'),
4246  'BS character in path' => array('path' . chr(8) . 'path'),
4247  'invalid UTF-8-sequence' => array("\xc0" . 'path/path'),
4248  'Could be overlong NUL in some UTF-8 implementations, invalid in RFC3629' => array("\xc0\x80" . 'path/path'),
4249  );
4250 
4251  // Mixing with regular utf-8
4252  $utf8Characters = 'Ссылка/';
4253  foreach ($data as $key => $value) {
4254  $data[$key . ' with UTF-8 characters prepended'] = array($utf8Characters . $value[0]);
4255  $data[$key . ' with UTF-8 characters appended'] = array($value[0] . $utf8Characters);
4256  }
4257 
4258  // Encoding with UTF-16
4259  foreach ($data as $key => $value) {
4260  $data[$key . ' encoded with UTF-16'] = array(mb_convert_encoding($value[0], 'UTF-16'));
4261  }
4262 
4263  // Valid paths encoded with UTF-16
4264  $data['Valid path but UTF-16 encoded'] = array(mb_convert_encoding('fileadmin/foo.txt', 'UTF-16'));
4265  $data['UTF-8 characters with UTF-16 encoded'] = array(mb_convert_encoding('fileadmin/templates/Ссылка (fce).xml', 'UTF-16'));
4266 
4267  return $data;
4268  }
4269 
4277  public function validPathStrDetectsInvalidCharacters($path) {
4278  $this->assertFalse(Utility\GeneralUtility::validPathStr($path));
4279  }
4280 
4284  public function validPathStrDataProvider()
4285  {
4286  $data = array(
4287  'normal ascii path' => array('fileadmin/templates/myfile..xml'),
4288  'special character' => array('fileadmin/templates/Ссылка (fce).xml')
4289  );
4290 
4291  return $data;
4292  }
4293 
4301  {
4302  $this->assertTrue(Utility\GeneralUtility::validPathStr($path));
4303  }
4304 
4308  public function deniedFilesDataProvider() {
4309  return array(
4310  'Nul character in file' => array('image' . chr(0) . '.gif'),
4311  'Nul character in file with .php' => array('image.php' . chr(0) . '.gif'),
4312  'Regular .php file' => array('file.php'),
4313  'Regular .php5 file' => array('file.php5'),
4314  'Regular .php3 file' => array('file.php3'),
4315  'Regular .phpsh file' => array('file.phpsh'),
4316  'Regular .phtml file' => array('file.phtml'),
4317  'PHP file in the middle' => array('file.php.txt'),
4318  '.htaccess file' => array('.htaccess'),
4319  );
4320  }
4321 
4330  $this->assertFalse(Utility\GeneralUtility::verifyFilenameAgainstDenyPattern($deniedFile));
4331  }
4332 
4333 
4335  // Tests concerning copyDirectory
4337 
4342  $sourceDirectory = 'typo3temp/' . $this->getUniqueId('test_') . '/';
4343  $absoluteSourceDirectory = PATH_site . $sourceDirectory;
4344  $this->testFilesToDelete[] = $absoluteSourceDirectory;
4345  Utility\GeneralUtility::mkdir($absoluteSourceDirectory);
4346 
4347  $targetDirectory = 'typo3temp/' . $this->getUniqueId('test_') . '/';
4348  $absoluteTargetDirectory = PATH_site . $targetDirectory;
4349  $this->testFilesToDelete[] = $absoluteTargetDirectory;
4350  Utility\GeneralUtility::mkdir($absoluteTargetDirectory);
4351 
4352  Utility\GeneralUtility::writeFileToTypo3tempDir($absoluteSourceDirectory . 'file', '42');
4353  Utility\GeneralUtility::mkdir($absoluteSourceDirectory . 'foo');
4354  Utility\GeneralUtility::writeFileToTypo3tempDir($absoluteSourceDirectory . 'foo/file', '42');
4355 
4356  Utility\GeneralUtility::copyDirectory($sourceDirectory, $targetDirectory);
4357 
4358  $this->assertFileExists($absoluteTargetDirectory . 'file');
4359  $this->assertFileExists($absoluteTargetDirectory . 'foo/file');
4360  }
4361 
4366  $sourceDirectory = 'typo3temp/' . $this->getUniqueId('test_') . '/';
4367  $absoluteSourceDirectory = PATH_site . $sourceDirectory;
4368  $this->testFilesToDelete[] = $absoluteSourceDirectory;
4369  Utility\GeneralUtility::mkdir($absoluteSourceDirectory);
4370 
4371  $targetDirectory = 'typo3temp/' . $this->getUniqueId('test_') . '/';
4372  $absoluteTargetDirectory = PATH_site . $targetDirectory;
4373  $this->testFilesToDelete[] = $absoluteTargetDirectory;
4374  Utility\GeneralUtility::mkdir($absoluteTargetDirectory);
4375 
4376  Utility\GeneralUtility::writeFileToTypo3tempDir($absoluteSourceDirectory . 'file', '42');
4377  Utility\GeneralUtility::mkdir($absoluteSourceDirectory . 'foo');
4378  Utility\GeneralUtility::writeFileToTypo3tempDir($absoluteSourceDirectory . 'foo/file', '42');
4379 
4380  Utility\GeneralUtility::copyDirectory($absoluteSourceDirectory, $absoluteTargetDirectory);
4381 
4382  $this->assertFileExists($absoluteTargetDirectory . 'file');
4383  $this->assertFileExists($absoluteTargetDirectory . 'foo/file');
4384  }
4385 
4387  // Tests concerning sysLog
4389 
4393  if (TYPO3_OS == 'WIN') {
4394  $this->markTestSkipped('syslogFixesPermissionsOnFileIfUsingFileLogging() test not available on Windows.');
4395  }
4396  // Fake all required settings
4397  $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLogLevel'] = 0;
4398  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogInit'] = TRUE;
4399  unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog']);
4400  $testLogFilename = PATH_site . 'typo3temp/' . $this->getUniqueId('test_') . '.txt';
4401  $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLog'] = 'file,' . $testLogFilename . ',0';
4402  $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
4403  // Call method, get actual permissions and clean up
4404  Utility\GeneralUtility::syslog('testLog', 'test', Utility\GeneralUtility::SYSLOG_SEVERITY_NOTICE);
4405  $this->testFilesToDelete[] = $testLogFilename;
4406  clearstatcache();
4407  $this->assertEquals('0777', substr(decoct(fileperms($testLogFilename)), 2));
4408  }
4409 
4414  if (TYPO3_OS == 'WIN') {
4415  $this->markTestSkipped('deprecationLogFixesPermissionsOnLogFile() test not available on Windows.');
4416  }
4417  // Fake all required settings and get an unique logfilename
4418  $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = $this->getUniqueId('test_');
4419  $deprecationLogFilename = Utility\GeneralUtility::getDeprecationLogFileName();
4420  $GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog'] = TRUE;
4421  $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
4422  // Call method, get actual permissions and clean up
4424  $this->testFilesToDelete[] = $deprecationLogFilename;
4425  clearstatcache();
4426  $resultFilePermissions = substr(decoct(fileperms($deprecationLogFilename)), 2);
4427  $this->assertEquals('0777', $resultFilePermissions);
4428  }
4429 
4431  // Tests concerning callUserFunction
4433 
4439  $inputData = array('foo' => 'bar');
4440  // omit the debug() output
4441  ob_start();
4442  $result = Utility\GeneralUtility::callUserFunction($functionName, $inputData, $this, 'user_', 1);
4443  ob_end_clean();
4444  $this->assertFalse($result);
4445  }
4446 
4453  $inputData = array('foo' => 'bar');
4454  Utility\GeneralUtility::callUserFunction($functionName, $inputData, $this, 'user_', 2);
4455  }
4456 
4464  return array(
4465  'Function is not prefixed' => array('t3lib_divTest->calledUserFunction'),
4466  'Class doesn\'t exists' => array('t3lib_divTest21345->user_calledUserFunction'),
4467  'No method name' => array('t3lib_divTest'),
4468  'No class name' => array('->user_calledUserFunction'),
4469  'No function name' => array('')
4470  );
4471  }
4472 
4481  $functionName = create_function('', 'return "Worked fine";');
4482  $inputData = array('foo' => 'bar');
4483  $result = Utility\GeneralUtility::callUserFunction($functionName, $inputData, $this, '');
4484  $this->assertEquals('Worked fine', $result);
4485  }
4486 
4490  public function callUserFunctionCanCallMethod() {
4491  $inputData = array('foo' => 'bar');
4492  $result = Utility\GeneralUtility::callUserFunction('TYPO3\CMS\Core\Tests\Unit\Utility\GeneralUtilityTest->user_calledUserFunction', $inputData, $this);
4493  $this->assertEquals('Worked fine', $result);
4494  }
4495 
4499  public function user_calledUserFunction() {
4500  return 'Worked fine';
4501  }
4502 
4507  $inputData = array('foo' => 'bar');
4508  $result = Utility\GeneralUtility::callUserFunction('typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php:TYPO3\CMS\Core\Tests\Unit\Utility\GeneralUtilityTest->user_calledUserFunction', $inputData, $this);
4509  $this->assertEquals('Worked fine', $result);
4510  }
4511 
4516  $inputData = array('called' => array());
4517  Utility\GeneralUtility::callUserFunction('&TYPO3\CMS\Core\Tests\Unit\Utility\GeneralUtilityTest->user_calledUserFunctionCountCallers', $inputData, $this);
4518  Utility\GeneralUtility::callUserFunction('&TYPO3\CMS\Core\Tests\Unit\Utility\GeneralUtilityTest->user_calledUserFunctionCountCallers', $inputData, $this);
4519  $this->assertEquals(1, sizeof($inputData['called']));
4520  }
4521 
4529  public function user_calledUserFunctionCountCallers(&$params) {
4530  $params['called'][spl_object_hash($this)]++;
4531  }
4532 
4537  $inputData = array('foo' => 'bar');
4538  $closure = function ($parameters, $reference) use($inputData) {
4539  $reference->assertEquals($inputData, $parameters, 'Passed data doesn\'t match expected output');
4540  return 'Worked fine';
4541  };
4542  $this->assertEquals('Worked fine', Utility\GeneralUtility::callUserFunction($closure, $inputData, $this));
4543  }
4544 
4546  // Tests concerning generateRandomBytes
4548 
4553  public function generateRandomBytesReturnsExpectedAmountOfBytes($numberOfBytes) {
4554  $this->assertEquals(strlen(Utility\GeneralUtility::generateRandomBytes($numberOfBytes)), $numberOfBytes);
4555  }
4556 
4558  return array(
4559  array(1),
4560  array(2),
4561  array(3),
4562  array(4),
4563  array(7),
4564  array(8),
4565  array(31),
4566  array(32),
4567  array(100),
4568  array(102),
4569  array(4000),
4570  array(4095),
4571  array(4096),
4572  array(4097),
4573  array(8000)
4574  );
4575  }
4576 
4583  $results = array();
4584  $numberOfTests = 5;
4585  // generate a few random numbers
4586  for ($i = 0; $i < $numberOfTests; $i++) {
4587  $results[$i] = Utility\GeneralUtility::generateRandomBytes($numberOfBytes);
4588  }
4589  // array_unique would filter out duplicates
4590  $this->assertEquals($results, array_unique($results));
4591  }
4592 
4594  return array(
4595  array(32),
4596  array(128),
4597  array(4096)
4598  );
4599  }
4600 
4605  $array1 = array(
4606  'first' => array(
4607  'second' => 'second',
4608  'third' => 'third'
4609  ),
4610  'fifth' => array()
4611  );
4612  $array2 = array(
4613  'first' => array(
4614  'second' => 'overrule',
4615  'third' => '__UNSET',
4616  'fourth' => 'overrile'
4617  ),
4618  'fifth' => '__UNSET'
4619  );
4620  $expected = array(
4621  'first' => array(
4622  'second' => 'overrule',
4623  'fourth' => 'overrile'
4624  )
4625  );
4627  $this->assertEquals($expected, $result);
4628  }
4629 
4631  // Tests concerning substUrlsInPlainText
4633 
4637  $urlMatch = 'http://example.com/index.php\\?RDCT=[0-9a-z]{20}';
4638  return array(
4639  array('http://only-url.com', '|^' . $urlMatch . '$|'),
4640  array('https://only-secure-url.com', '|^' . $urlMatch . '$|'),
4641  array('A http://url in the sentence.', '|^A ' . $urlMatch . ' in the sentence\\.$|'),
4642  array('URL in round brackets (http://www.example.com) in the sentence.', '|^URL in round brackets \\(' . $urlMatch . '\\) in the sentence.$|'),
4643  array('URL in square brackets [http://www.example.com/a/b.php?c[d]=e] in the sentence.', '|^URL in square brackets \\[' . $urlMatch . '\\] in the sentence.$|'),
4644  array('URL in square brackets at the end of the sentence [http://www.example.com/a/b.php?c[d]=e].', '|^URL in square brackets at the end of the sentence \\[' . $urlMatch . '].$|'),
4645  array('Square brackets in the http://www.url.com?tt_news[uid]=1', '|^Square brackets in the ' . $urlMatch . '$|'),
4646  array('URL with http://dot.com.', '|^URL with ' . $urlMatch . '.$|'),
4647  array('URL in <a href="http://www.example.com/">a tag</a>', '|^URL in <a href="' . $urlMatch . '">a tag</a\\>$|'),
4648  array('URL in HTML <b>http://www.example.com</b><br />', '|^URL in HTML <b>' . $urlMatch . '</b><br />$|'),
4649  array('URL with http://username@example.com/', '|^URL with ' . $urlMatch . '$|'),
4650  array('Secret in URL http://username:secret@example.com', '|^Secret in URL ' . $urlMatch . '$|'),
4651  array('URL in quotation marks "http://example.com"', '|^URL in quotation marks "' . $urlMatch . '"$|'),
4652  array('URL with umlauts http://müller.de', '|^URL with umlauts ' . $urlMatch . '$|'),
4653  array('Multiline
4654 text with a http://url.com', '|^Multiline
4655 text with a ' . $urlMatch . '$|s'),
4656  array('http://www.shout.com!', '|^' . $urlMatch . '!$|'),
4657  array('And with two URLs http://www.two.com/abc http://urls.com/abc?x=1&y=2', '|^And with two URLs ' . $urlMatch . ' ' . $urlMatch . '$|')
4658  );
4659  }
4660 
4667  public function substUrlsInPlainText($input, $expected) {
4668  $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array(), array(), '', FALSE);
4669  $this->assertTrue(preg_match($expected, Utility\GeneralUtility::substUrlsInPlainText($input, 1, 'http://example.com/index.php')) == 1);
4670  }
4671 
4676  return array(
4677  'Extracts redirect URL from Location header' => array("HTTP/1.0 302 Redirect\r\nServer: Apache\r\nLocation: http://example.com/\r\nX-pad: avoid browser bug\r\n\r\nLocation: test\r\n", 'http://example.com/'),
4678  'Returns empty string if no Location is found in header' => array("HTTP/1.0 302 Redirect\r\nServer: Apache\r\nX-pad: avoid browser bug\r\n\r\nLocation: test\r\n", ''),
4679  );
4680  }
4681 
4688  public function getRedirectUrlReturnsRedirectUrlFromHttpResponse($httpResponse, $expected) {
4689  $this->assertEquals($expected, GeneralUtilityFixture::getRedirectUrlFromHttpHeaders($httpResponse));
4690  }
4691 
4696  return array(
4697  'Simple content' => array("HTTP/1.0 302 Redirect\r\nServer: Apache\r\nX-pad: avoid browser bug\r\n\r\nHello, world!", 'Hello, world!'),
4698  'Content with multiple returns' => array("HTTP/1.0 302 Redirect\r\nServer: Apache\r\nX-pad: avoid browser bug\r\n\r\nHello, world!\r\n\r\nAnother hello here!", "Hello, world!\r\n\r\nAnother hello here!"),
4699  );
4700  }
4701 
4708  public function stripHttpHeadersStripsHeadersFromHttpResponse($httpResponse, $expected) {
4709  $this->assertEquals($expected, GeneralUtilityFixture::stripHttpHeaders($httpResponse));
4710  }
4711 
4719  {
4720  $input = array(
4721  'el' => array()
4722  );
4723 
4724  $output = Utility\GeneralUtility::array2xml($input);
4725 
4726  $this->assertEquals('<phparray>
4727  <el type="array"></el>
4728 </phparray>', $output);
4729  }
4730 }
static stripSlashesOnArray(array &$theArray)
getRedirectUrlReturnsRedirectUrlFromHttpResponse($httpResponse, $expected)
static minifyJavaScript($script, &$error='')
static uniqueList($in_list, $secondParameter=NULL)
static setSingletonInstance($className, \TYPO3\CMS\Core\SingletonInterface $instance)
static unlink_tempfile($uploadedTempFileName)
static substUrlsInPlainText($message, $urlmode='76', $index_script_url='')
static explodeUrl2Array($string, $multidim=FALSE)
static mkdir_deep($directory, $deepDirectory='')
static addInstance($className, $instance)
$parameters
Definition: FileDumpEID.php:15
static isFirstPartOfStr($str, $partStr)
static slashJS($string, $extended=FALSE, $char='\'')
revExplodeCorrectlyExplodesStringForGivenPartsCount($delimiter, $testString, $count, $expectedArray)
static intExplode($delimiter, $string, $removeEmptyValues=FALSE, $limit=0)
static writeFileToTypo3tempDir($filepath, $content)
canSetNewGetInputValues($input, $key, $expected, $getPreset=array())
static rmdir($path, $removeNonEmpty=FALSE)
rmFromListRemovesElementsFromCommaSeparatedList($initialList, $listWithElementRemoved)
static hmac($input, $additionalSecret='')
static fixPermissions($path, $recursive=FALSE)
getIndpEnvForHostThrowsExceptionForNotAllowedHostnameValues($httpHost, $hostNamePattern)
static generateRandomBytes($bytesToReturn)
die
Definition: index.php:6
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
static verifyFilenameAgainstDenyPattern($filename)
static remapArrayKeys(&$array, $mappingTable)
static copyDirectory($source, $destination)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
static _GETset($inputGet, $key='')
static array2xml(array $array, $NSprefix='', $level=0, $docTag='phparray', $spaceInd=0, array $options=array(), array $stackData=array())
static unQuoteFilenames($parameters, $unQuote=FALSE)
static resetSingletonInstances(array $newSingletonInstances)
static split_fileref($fileNameWithPath)
static addSlashesOnArray(array &$theArray)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
static compileSelectedGetVarsFromArray($varList, array $getArray, $GPvarAlt=TRUE)
getIndpEnvTypo3PortParsesHostnamesAndIpAdresses($httpHost, $dummy, $expectedPort)
static getBytesFromSizeMeasurement($measurement)
static inArray(array $in_array, $item)
static tempnam($filePrefix, $fileSuffix='')
$host
Definition: server.php:35
getBytesFromSizeMeasurementCalculatesCorrectByteValue($expected, $byteString)
static splitCalc($string, $operators)
slashJsEscapesSingleQuotesAndSlashes($input, $extended, $expected)
static implodeArrayForUrl($name, array $theArray, $str='', $skipBlank=FALSE, $rawurlencodeParamName=FALSE)
static formatSize($sizeInBytes, $labels='')
formatSizeTranslatesBytesToHigherOrderRepresentation($size, $label, $expected)
static array_merge(array $arr1, array $arr2)
getIndpEnvForHostAllowsAllHostnameValuesIfHostPatternIsSetToAllowAll($httpHost, $hostNamePattern)
sanitizeLocalUrlAcceptsNotEncodedValidUrls($url, $host, $subDirectory)
static getFilesInDir($path, $extensionList='', $prependPath=FALSE, $order='', $excludePattern='')
static array_merge_recursive_overrule(array $arr0, array $arr1, $notAddKeys=FALSE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
explodeAndUnquoteImageMagickCommands($source, $expectedQuoted, $expectedUnquoted)
isAllowedHostHeaderValueWorksCorrectlyWithWithServerNamePattern($httpHost, $serverName, $isAllowed, $serverPort='80', $ssl='Off')
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static removeArrayEntryByValue(array $array, $cmpValue)
static revExplode($delimiter, $string, $count=0)
isAllowedHostHeaderValueReturnsTrueIfHostValueMatches($httpHost, $hostNamePattern)
isAllowedHostHeaderValueReturnsFalseIfHostValueMatches($httpHost, $hostNamePattern)
static encodeHeader($line, $enc='quoted-printable', $charset='utf-8')
static arrayDiffAssocRecursive(array $array1, array $array2)
static keepItemsInArray(array $array, $keepItems, $getValueFunc=NULL)