PageRenderTime 104ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/typo3/class.t3lib_div.php

https://bitbucket.org/ngmares/moodle
PHP | 5843 lines | 3472 code | 473 blank | 1898 comment | 791 complexity | 3f2669a1f22e07ab859a6341fccd16e5 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, MPL-2.0-no-copyleft-exception, GPL-3.0, Apache-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
  6. * All rights reserved
  7. *
  8. * This script is part of the TYPO3 project. The TYPO3 project is
  9. * free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * The GNU General Public License can be found at
  15. * http://www.gnu.org/copyleft/gpl.html.
  16. * A copy is found in the textfile GPL.txt and important notices to the license
  17. * from the author is found in LICENSE.txt distributed with these scripts.
  18. *
  19. *
  20. * This script is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * This copyright notice MUST APPEAR in all copies of the script!
  26. ***************************************************************/
  27. // a tabulator
  28. define('TAB', chr(9));
  29. // a linefeed
  30. define('LF', chr(10));
  31. // a carriage return
  32. define('CR', chr(13));
  33. // a CR-LF combination
  34. define('CRLF', CR . LF);
  35. /**
  36. * The legendary "t3lib_div" class - Miscellaneous functions for general purpose.
  37. * Most of the functions do not relate specifically to TYPO3
  38. * However a section of functions requires certain TYPO3 features available
  39. * See comments in the source.
  40. * You are encouraged to use this library in your own scripts!
  41. *
  42. * USE:
  43. * The class is intended to be used without creating an instance of it.
  44. * So: Don't instantiate - call functions with "t3lib_div::" prefixed the function name.
  45. * So use t3lib_div::[method-name] to refer to the functions, eg. 't3lib_div::milliseconds()'
  46. *
  47. * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  48. * @package TYPO3
  49. * @subpackage t3lib
  50. */
  51. final class t3lib_div {
  52. // Severity constants used by t3lib_div::sysLog()
  53. const SYSLOG_SEVERITY_INFO = 0;
  54. const SYSLOG_SEVERITY_NOTICE = 1;
  55. const SYSLOG_SEVERITY_WARNING = 2;
  56. const SYSLOG_SEVERITY_ERROR = 3;
  57. const SYSLOG_SEVERITY_FATAL = 4;
  58. /**
  59. * Singleton instances returned by makeInstance, using the class names as
  60. * array keys
  61. *
  62. * @var array<t3lib_Singleton>
  63. */
  64. protected static $singletonInstances = array();
  65. /**
  66. * Instances returned by makeInstance, using the class names as array keys
  67. *
  68. * @var array<array><object>
  69. */
  70. protected static $nonSingletonInstances = array();
  71. /**
  72. * Register for makeInstance with given class name and final class names to reduce number of class_exists() calls
  73. *
  74. * @var array Given class name => final class name
  75. */
  76. protected static $finalClassNameRegister = array();
  77. /*************************
  78. *
  79. * GET/POST Variables
  80. *
  81. * Background:
  82. * Input GET/POST variables in PHP may have their quotes escaped with "\" or not depending on configuration.
  83. * TYPO3 has always converted quotes to BE escaped if the configuration told that they would not be so.
  84. * But the clean solution is that quotes are never escaped and that is what the functions below offers.
  85. * Eventually TYPO3 should provide this in the global space as well.
  86. * In the transitional phase (or forever..?) we need to encourage EVERY to read and write GET/POST vars through the API functions below.
  87. *
  88. *************************/
  89. /**
  90. * Returns the 'GLOBAL' value of incoming data from POST or GET, with priority to POST (that is equalent to 'GP' order)
  91. * Strips slashes from all output, both strings and arrays.
  92. * To enhancement security in your scripts, please consider using t3lib_div::_GET or t3lib_div::_POST if you already
  93. * know by which method your data is arriving to the scripts!
  94. *
  95. * @param string $var GET/POST var to return
  96. * @return mixed POST var named $var and if not set, the GET var of the same name.
  97. */
  98. public static function _GP($var) {
  99. if (empty($var)) {
  100. return;
  101. }
  102. $value = isset($_POST[$var]) ? $_POST[$var] : $_GET[$var];
  103. if (isset($value)) {
  104. if (is_array($value)) {
  105. self::stripSlashesOnArray($value);
  106. } else {
  107. $value = stripslashes($value);
  108. }
  109. }
  110. return $value;
  111. }
  112. /**
  113. * Returns the global arrays $_GET and $_POST merged with $_POST taking precedence.
  114. *
  115. * @param string $parameter Key (variable name) from GET or POST vars
  116. * @return array Returns the GET vars merged recursively onto the POST vars.
  117. */
  118. public static function _GPmerged($parameter) {
  119. $postParameter = (isset($_POST[$parameter]) && is_array($_POST[$parameter])) ? $_POST[$parameter] : array();
  120. $getParameter = (isset($_GET[$parameter]) && is_array($_GET[$parameter])) ? $_GET[$parameter] : array();
  121. $mergedParameters = self::array_merge_recursive_overrule($getParameter, $postParameter);
  122. self::stripSlashesOnArray($mergedParameters);
  123. return $mergedParameters;
  124. }
  125. /**
  126. * Returns the global $_GET array (or value from) normalized to contain un-escaped values.
  127. * ALWAYS use this API function to acquire the GET variables!
  128. *
  129. * @param string $var Optional pointer to value in GET array (basically name of GET var)
  130. * @return mixed If $var is set it returns the value of $_GET[$var]. If $var is NULL (default), returns $_GET itself. In any case *slashes are stipped from the output!*
  131. * @see _POST(), _GP(), _GETset()
  132. */
  133. public static function _GET($var = NULL) {
  134. $value = ($var === NULL) ? $_GET : (empty($var) ? NULL : $_GET[$var]);
  135. if (isset($value)) { // Removes slashes since TYPO3 has added them regardless of magic_quotes setting.
  136. if (is_array($value)) {
  137. self::stripSlashesOnArray($value);
  138. } else {
  139. $value = stripslashes($value);
  140. }
  141. }
  142. return $value;
  143. }
  144. /**
  145. * Returns the global $_POST array (or value from) normalized to contain un-escaped values.
  146. * ALWAYS use this API function to acquire the $_POST variables!
  147. *
  148. * @param string $var Optional pointer to value in POST array (basically name of POST var)
  149. * @return mixed If $var is set it returns the value of $_POST[$var]. If $var is NULL (default), returns $_POST itself. In any case *slashes are stipped from the output!*
  150. * @see _GET(), _GP()
  151. */
  152. public static function _POST($var = NULL) {
  153. $value = ($var === NULL) ? $_POST : (empty($var) ? NULL : $_POST[$var]);
  154. if (isset($value)) { // Removes slashes since TYPO3 has added them regardless of magic_quotes setting.
  155. if (is_array($value)) {
  156. self::stripSlashesOnArray($value);
  157. } else {
  158. $value = stripslashes($value);
  159. }
  160. }
  161. return $value;
  162. }
  163. /**
  164. * Writes input value to $_GET.
  165. *
  166. * @param mixed $inputGet
  167. * array or single value to write to $_GET. Values should NOT be
  168. * escaped at input time (but will be escaped before writing
  169. * according to TYPO3 standards).
  170. * @param string $key
  171. * alternative key; If set, this will not set the WHOLE GET array,
  172. * but only the key in it specified by this value!
  173. * You can specify to replace keys on deeper array levels by
  174. * separating the keys with a pipe.
  175. * Example: 'parentKey|childKey' will result in
  176. * array('parentKey' => array('childKey' => $inputGet))
  177. *
  178. * @return void
  179. */
  180. public static function _GETset($inputGet, $key = '') {
  181. // adds slashes since TYPO3 standard currently is that slashes
  182. // must be applied (regardless of magic_quotes setting)
  183. if (is_array($inputGet)) {
  184. self::addSlashesOnArray($inputGet);
  185. } else {
  186. $inputGet = addslashes($inputGet);
  187. }
  188. if ($key != '') {
  189. if (strpos($key, '|') !== FALSE) {
  190. $pieces = explode('|', $key);
  191. $newGet = array();
  192. $pointer =& $newGet;
  193. foreach ($pieces as $piece) {
  194. $pointer =& $pointer[$piece];
  195. }
  196. $pointer = $inputGet;
  197. $mergedGet = self::array_merge_recursive_overrule(
  198. $_GET, $newGet
  199. );
  200. $_GET = $mergedGet;
  201. $GLOBALS['HTTP_GET_VARS'] = $mergedGet;
  202. } else {
  203. $_GET[$key] = $inputGet;
  204. $GLOBALS['HTTP_GET_VARS'][$key] = $inputGet;
  205. }
  206. } elseif (is_array($inputGet)) {
  207. $_GET = $inputGet;
  208. $GLOBALS['HTTP_GET_VARS'] = $inputGet;
  209. }
  210. }
  211. /**
  212. * Wrapper for the RemoveXSS function.
  213. * Removes potential XSS code from an input string.
  214. *
  215. * Using an external class by Travis Puderbaugh <kallahar@quickwired.com>
  216. *
  217. * @param string $string Input string
  218. * @return string Input string with potential XSS code removed
  219. */
  220. public static function removeXSS($string) {
  221. require_once(PATH_typo3 . 'contrib/RemoveXSS/RemoveXSS.php');
  222. $string = RemoveXSS::process($string);
  223. return $string;
  224. }
  225. /*************************
  226. *
  227. * IMAGE FUNCTIONS
  228. *
  229. *************************/
  230. /**
  231. * Compressing a GIF file if not already LZW compressed.
  232. * This function is a workaround for the fact that ImageMagick and/or GD does not compress GIF-files to their minimun size (that is RLE or no compression used)
  233. *
  234. * The function takes a file-reference, $theFile, and saves it again through GD or ImageMagick in order to compress the file
  235. * GIF:
  236. * If $type is not set, the compression is done with ImageMagick (provided that $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'] is pointing to the path of a lzw-enabled version of 'convert') else with GD (should be RLE-enabled!)
  237. * If $type is set to either 'IM' or 'GD' the compression is done with ImageMagick and GD respectively
  238. * PNG:
  239. * No changes.
  240. *
  241. * $theFile is expected to be a valid GIF-file!
  242. * The function returns a code for the operation.
  243. *
  244. * @param string $theFile Filepath
  245. * @param string $type See description of function
  246. * @return string Returns "GD" if GD was used, otherwise "IM" if ImageMagick was used. If nothing done at all, it returns empty string.
  247. */
  248. public static function gif_compress($theFile, $type) {
  249. $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
  250. $returnCode = '';
  251. if ($gfxConf['gif_compress'] && strtolower(substr($theFile, -4, 4)) == '.gif') { // GIF...
  252. if (($type == 'IM' || !$type) && $gfxConf['im'] && $gfxConf['im_path_lzw']) { // IM
  253. // use temporary file to prevent problems with read and write lock on same file on network file systems
  254. $temporaryName = dirname($theFile) . '/' . md5(uniqid()) . '.gif';
  255. // rename could fail, if a simultaneous thread is currently working on the same thing
  256. if (@rename($theFile, $temporaryName)) {
  257. $cmd = self::imageMagickCommand('convert', '"' . $temporaryName . '" "' . $theFile . '"', $gfxConf['im_path_lzw']);
  258. t3lib_utility_Command::exec($cmd);
  259. unlink($temporaryName);
  260. }
  261. $returnCode = 'IM';
  262. if (@is_file($theFile)) {
  263. self::fixPermissions($theFile);
  264. }
  265. } elseif (($type == 'GD' || !$type) && $gfxConf['gdlib'] && !$gfxConf['gdlib_png']) { // GD
  266. $tempImage = imageCreateFromGif($theFile);
  267. imageGif($tempImage, $theFile);
  268. imageDestroy($tempImage);
  269. $returnCode = 'GD';
  270. if (@is_file($theFile)) {
  271. self::fixPermissions($theFile);
  272. }
  273. }
  274. }
  275. return $returnCode;
  276. }
  277. /**
  278. * Converts a png file to gif.
  279. * This converts a png file to gif IF the FLAG $GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif'] is set TRUE.
  280. *
  281. * @param string $theFile the filename with path
  282. * @return string new filename
  283. */
  284. public static function png_to_gif_by_imagemagick($theFile) {
  285. if ($GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif']
  286. && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im']
  287. && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']
  288. && strtolower(substr($theFile, -4, 4)) == '.png'
  289. && @is_file($theFile)) { // IM
  290. $newFile = substr($theFile, 0, -4) . '.gif';
  291. $cmd = self::imageMagickCommand('convert', '"' . $theFile . '" "' . $newFile . '"', $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']);
  292. t3lib_utility_Command::exec($cmd);
  293. $theFile = $newFile;
  294. if (@is_file($newFile)) {
  295. self::fixPermissions($newFile);
  296. }
  297. // unlink old file?? May be bad idea because TYPO3 would then recreate the file every time as
  298. // TYPO3 thinks the file is not generated because it's missing!! So do not unlink $theFile here!!
  299. }
  300. return $theFile;
  301. }
  302. /**
  303. * Returns filename of the png/gif version of the input file (which can be png or gif).
  304. * If input file type does not match the wanted output type a conversion is made and temp-filename returned.
  305. *
  306. * @param string $theFile Filepath of image file
  307. * @param boolean $output_png If set, then input file is converted to PNG, otherwise to GIF
  308. * @return string If the new image file exists, its filepath is returned
  309. */
  310. public static function read_png_gif($theFile, $output_png = FALSE) {
  311. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] && @is_file($theFile)) {
  312. $ext = strtolower(substr($theFile, -4, 4));
  313. if (
  314. ((string) $ext == '.png' && $output_png) ||
  315. ((string) $ext == '.gif' && !$output_png)
  316. ) {
  317. return $theFile;
  318. } else {
  319. $newFile = PATH_site . 'typo3temp/readPG_' . md5($theFile . '|' . filemtime($theFile)) . ($output_png ? '.png' : '.gif');
  320. $cmd = self::imageMagickCommand('convert', '"' . $theFile . '" "' . $newFile . '"', $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path']);
  321. t3lib_utility_Command::exec($cmd);
  322. if (@is_file($newFile)) {
  323. self::fixPermissions($newFile);
  324. return $newFile;
  325. }
  326. }
  327. }
  328. }
  329. /*************************
  330. *
  331. * STRING FUNCTIONS
  332. *
  333. *************************/
  334. /**
  335. * Truncates a string with appended/prepended "..." and takes current character set into consideration.
  336. *
  337. * @param string $string string to truncate
  338. * @param integer $chars must be an integer with an absolute value of at least 4. if negative the string is cropped from the right end.
  339. * @param string $appendString appendix to the truncated string
  340. * @return string cropped string
  341. */
  342. public static function fixed_lgd_cs($string, $chars, $appendString = '...') {
  343. if (is_object($GLOBALS['LANG'])) {
  344. return $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet, $string, $chars, $appendString);
  345. } elseif (is_object($GLOBALS['TSFE'])) {
  346. $charSet = ($GLOBALS['TSFE']->renderCharset != '' ? $GLOBALS['TSFE']->renderCharset : $GLOBALS['TSFE']->defaultCharSet);
  347. return $GLOBALS['TSFE']->csConvObj->crop($charSet, $string, $chars, $appendString);
  348. } else {
  349. // this case should not happen
  350. $csConvObj = self::makeInstance('t3lib_cs');
  351. return $csConvObj->crop('iso-8859-1', $string, $chars, $appendString);
  352. }
  353. }
  354. /**
  355. * Breaks up a single line of text for emails
  356. *
  357. * @param string $str The string to break up
  358. * @param string $newlineChar The string to implode the broken lines with (default/typically \n)
  359. * @param integer $lineWidth The line width
  360. * @return string reformatted text
  361. * @deprecated since TYPO3 4.6, will be removed in TYPO3 4.8 - Use t3lib_utility_Mail::breakLinesForEmail()
  362. */
  363. public static function breakLinesForEmail($str, $newlineChar = LF, $lineWidth = 76) {
  364. self::logDeprecatedFunction();
  365. return t3lib_utility_Mail::breakLinesForEmail($str, $newlineChar, $lineWidth);
  366. }
  367. /**
  368. * Match IP number with list of numbers with wildcard
  369. * Dispatcher method for switching into specialised IPv4 and IPv6 methods.
  370. *
  371. * @param string $baseIP is the current remote IP address for instance, typ. REMOTE_ADDR
  372. * @param string $list is a comma-list of IP-addresses to match with. *-wildcard allowed instead of number, plus leaving out parts in the IP number is accepted as wildcard (eg. 192.168.*.* equals 192.168). If list is "*" no check is done and the function returns TRUE immediately. An empty list always returns FALSE.
  373. * @return boolean TRUE if an IP-mask from $list matches $baseIP
  374. */
  375. public static function cmpIP($baseIP, $list) {
  376. $list = trim($list);
  377. if ($list === '') {
  378. return FALSE;
  379. } elseif ($list === '*') {
  380. return TRUE;
  381. }
  382. if (strpos($baseIP, ':') !== FALSE && self::validIPv6($baseIP)) {
  383. return self::cmpIPv6($baseIP, $list);
  384. } else {
  385. return self::cmpIPv4($baseIP, $list);
  386. }
  387. }
  388. /**
  389. * Match IPv4 number with list of numbers with wildcard
  390. *
  391. * @param string $baseIP is the current remote IP address for instance, typ. REMOTE_ADDR
  392. * @param string $list is a comma-list of IP-addresses to match with. *-wildcard allowed instead of number, plus leaving out parts in the IP number is accepted as wildcard (eg. 192.168.*.* equals 192.168), could also contain IPv6 addresses
  393. * @return boolean TRUE if an IP-mask from $list matches $baseIP
  394. */
  395. public static function cmpIPv4($baseIP, $list) {
  396. $IPpartsReq = explode('.', $baseIP);
  397. if (count($IPpartsReq) == 4) {
  398. $values = self::trimExplode(',', $list, 1);
  399. foreach ($values as $test) {
  400. $testList = explode('/', $test);
  401. if (count($testList) == 2) {
  402. list($test, $mask) = $testList;
  403. } else {
  404. $mask = FALSE;
  405. }
  406. if (intval($mask)) {
  407. // "192.168.3.0/24"
  408. $lnet = ip2long($test);
  409. $lip = ip2long($baseIP);
  410. $binnet = str_pad(decbin($lnet), 32, '0', STR_PAD_LEFT);
  411. $firstpart = substr($binnet, 0, $mask);
  412. $binip = str_pad(decbin($lip), 32, '0', STR_PAD_LEFT);
  413. $firstip = substr($binip, 0, $mask);
  414. $yes = (strcmp($firstpart, $firstip) == 0);
  415. } else {
  416. // "192.168.*.*"
  417. $IPparts = explode('.', $test);
  418. $yes = 1;
  419. foreach ($IPparts as $index => $val) {
  420. $val = trim($val);
  421. if (($val !== '*') && ($IPpartsReq[$index] !== $val)) {
  422. $yes = 0;
  423. }
  424. }
  425. }
  426. if ($yes) {
  427. return TRUE;
  428. }
  429. }
  430. }
  431. return FALSE;
  432. }
  433. /**
  434. * Match IPv6 address with a list of IPv6 prefixes
  435. *
  436. * @param string $baseIP is the current remote IP address for instance
  437. * @param string $list is a comma-list of IPv6 prefixes, could also contain IPv4 addresses
  438. * @return boolean TRUE if an baseIP matches any prefix
  439. */
  440. public static function cmpIPv6($baseIP, $list) {
  441. $success = FALSE; // Policy default: Deny connection
  442. $baseIP = self::normalizeIPv6($baseIP);
  443. $values = self::trimExplode(',', $list, 1);
  444. foreach ($values as $test) {
  445. $testList = explode('/', $test);
  446. if (count($testList) == 2) {
  447. list($test, $mask) = $testList;
  448. } else {
  449. $mask = FALSE;
  450. }
  451. if (self::validIPv6($test)) {
  452. $test = self::normalizeIPv6($test);
  453. $maskInt = intval($mask) ? intval($mask) : 128;
  454. if ($mask === '0') { // special case; /0 is an allowed mask - equals a wildcard
  455. $success = TRUE;
  456. } elseif ($maskInt == 128) {
  457. $success = ($test === $baseIP);
  458. } else {
  459. $testBin = self::IPv6Hex2Bin($test);
  460. $baseIPBin = self::IPv6Hex2Bin($baseIP);
  461. $success = TRUE;
  462. // modulo is 0 if this is a 8-bit-boundary
  463. $maskIntModulo = $maskInt % 8;
  464. $numFullCharactersUntilBoundary = intval($maskInt / 8);
  465. if (substr($testBin, 0, $numFullCharactersUntilBoundary) !== substr($baseIPBin, 0, $numFullCharactersUntilBoundary)) {
  466. $success = FALSE;
  467. } elseif ($maskIntModulo > 0) {
  468. // if not an 8-bit-boundary, check bits of last character
  469. $testLastBits = str_pad(decbin(ord(substr($testBin, $numFullCharactersUntilBoundary, 1))), 8, '0', STR_PAD_LEFT);
  470. $baseIPLastBits = str_pad(decbin(ord(substr($baseIPBin, $numFullCharactersUntilBoundary, 1))), 8, '0', STR_PAD_LEFT);
  471. if (strncmp($testLastBits, $baseIPLastBits, $maskIntModulo) != 0) {
  472. $success = FALSE;
  473. }
  474. }
  475. }
  476. }
  477. if ($success) {
  478. return TRUE;
  479. }
  480. }
  481. return FALSE;
  482. }
  483. /**
  484. * Transform a regular IPv6 address from hex-representation into binary
  485. *
  486. * @param string $hex IPv6 address in hex-presentation
  487. * @return string Binary representation (16 characters, 128 characters)
  488. * @see IPv6Bin2Hex()
  489. */
  490. public static function IPv6Hex2Bin($hex) {
  491. // use PHP-function if PHP was compiled with IPv6-support
  492. if (defined('AF_INET6')) {
  493. $bin = inet_pton($hex);
  494. } else {
  495. $hex = self::normalizeIPv6($hex);
  496. $hex = str_replace(':', '', $hex); // Replace colon to nothing
  497. $bin = pack("H*" , $hex);
  498. }
  499. return $bin;
  500. }
  501. /**
  502. * Transform an IPv6 address from binary to hex-representation
  503. *
  504. * @param string $bin IPv6 address in hex-presentation
  505. * @return string Binary representation (16 characters, 128 characters)
  506. * @see IPv6Hex2Bin()
  507. */
  508. public static function IPv6Bin2Hex($bin) {
  509. // use PHP-function if PHP was compiled with IPv6-support
  510. if (defined('AF_INET6')) {
  511. $hex = inet_ntop($bin);
  512. } else {
  513. $hex = unpack("H*" , $bin);
  514. $hex = chunk_split($hex[1], 4, ':');
  515. // strip last colon (from chunk_split)
  516. $hex = substr($hex, 0, -1);
  517. // IPv6 is now in normalized form
  518. // compress it for easier handling and to match result from inet_ntop()
  519. $hex = self::compressIPv6($hex);
  520. }
  521. return $hex;
  522. }
  523. /**
  524. * Normalize an IPv6 address to full length
  525. *
  526. * @param string $address Given IPv6 address
  527. * @return string Normalized address
  528. * @see compressIPv6()
  529. */
  530. public static function normalizeIPv6($address) {
  531. $normalizedAddress = '';
  532. $stageOneAddress = '';
  533. // according to RFC lowercase-representation is recommended
  534. $address = strtolower($address);
  535. // normalized representation has 39 characters (0000:0000:0000:0000:0000:0000:0000:0000)
  536. if (strlen($address) == 39) {
  537. // already in full expanded form
  538. return $address;
  539. }
  540. $chunks = explode('::', $address); // Count 2 if if address has hidden zero blocks
  541. if (count($chunks) == 2) {
  542. $chunksLeft = explode(':', $chunks[0]);
  543. $chunksRight = explode(':', $chunks[1]);
  544. $left = count($chunksLeft);
  545. $right = count($chunksRight);
  546. // Special case: leading zero-only blocks count to 1, should be 0
  547. if ($left == 1 && strlen($chunksLeft[0]) == 0) {
  548. $left = 0;
  549. }
  550. $hiddenBlocks = 8 - ($left + $right);
  551. $hiddenPart = '';
  552. $h = 0;
  553. while ($h < $hiddenBlocks) {
  554. $hiddenPart .= '0000:';
  555. $h++;
  556. }
  557. if ($left == 0) {
  558. $stageOneAddress = $hiddenPart . $chunks[1];
  559. } else {
  560. $stageOneAddress = $chunks[0] . ':' . $hiddenPart . $chunks[1];
  561. }
  562. } else {
  563. $stageOneAddress = $address;
  564. }
  565. // normalize the blocks:
  566. $blocks = explode(':', $stageOneAddress);
  567. $divCounter = 0;
  568. foreach ($blocks as $block) {
  569. $tmpBlock = '';
  570. $i = 0;
  571. $hiddenZeros = 4 - strlen($block);
  572. while ($i < $hiddenZeros) {
  573. $tmpBlock .= '0';
  574. $i++;
  575. }
  576. $normalizedAddress .= $tmpBlock . $block;
  577. if ($divCounter < 7) {
  578. $normalizedAddress .= ':';
  579. $divCounter++;
  580. }
  581. }
  582. return $normalizedAddress;
  583. }
  584. /**
  585. * Compress an IPv6 address to the shortest notation
  586. *
  587. * @param string $address Given IPv6 address
  588. * @return string Compressed address
  589. * @see normalizeIPv6()
  590. */
  591. public static function compressIPv6($address) {
  592. // use PHP-function if PHP was compiled with IPv6-support
  593. if (defined('AF_INET6')) {
  594. $bin = inet_pton($address);
  595. $address = inet_ntop($bin);
  596. } else {
  597. $address = self::normalizeIPv6($address);
  598. // append one colon for easier handling
  599. // will be removed later
  600. $address .= ':';
  601. // according to IPv6-notation the longest match
  602. // of a package of '0000:' may be replaced with ':'
  603. // (resulting in something like '1234::abcd')
  604. for ($counter = 8; $counter > 1; $counter--) {
  605. $search = str_repeat('0000:', $counter);
  606. if (($pos = strpos($address, $search)) !== FALSE) {
  607. $address = substr($address, 0, $pos) . ':' . substr($address, $pos + ($counter*5));
  608. break;
  609. }
  610. }
  611. // up to 3 zeros in the first part may be removed
  612. $address = preg_replace('/^0{1,3}/', '', $address);
  613. // up to 3 zeros at the beginning of other parts may be removed
  614. $address = preg_replace('/:0{1,3}/', ':', $address);
  615. // strip last colon (from chunk_split)
  616. $address = substr($address, 0, -1);
  617. }
  618. return $address;
  619. }
  620. /**
  621. * Validate a given IP address.
  622. *
  623. * Possible format are IPv4 and IPv6.
  624. *
  625. * @param string $ip IP address to be tested
  626. * @return boolean TRUE if $ip is either of IPv4 or IPv6 format.
  627. */
  628. public static function validIP($ip) {
  629. return (filter_var($ip, FILTER_VALIDATE_IP) !== FALSE);
  630. }
  631. /**
  632. * Validate a given IP address to the IPv4 address format.
  633. *
  634. * Example for possible format: 10.0.45.99
  635. *
  636. * @param string $ip IP address to be tested
  637. * @return boolean TRUE if $ip is of IPv4 format.
  638. */
  639. public static function validIPv4($ip) {
  640. return (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== FALSE);
  641. }
  642. /**
  643. * Validate a given IP address to the IPv6 address format.
  644. *
  645. * Example for possible format: 43FB::BB3F:A0A0:0 | ::1
  646. *
  647. * @param string $ip IP address to be tested
  648. * @return boolean TRUE if $ip is of IPv6 format.
  649. */
  650. public static function validIPv6($ip) {
  651. return (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE);
  652. }
  653. /**
  654. * Match fully qualified domain name with list of strings with wildcard
  655. *
  656. * @param string $baseHost A hostname or an IPv4/IPv6-address (will by reverse-resolved; typically REMOTE_ADDR)
  657. * @param string $list A comma-list of domain names to match with. *-wildcard allowed but cannot be part of a string, so it must match the full host name (eg. myhost.*.com => correct, myhost.*domain.com => wrong)
  658. * @return boolean TRUE if a domain name mask from $list matches $baseIP
  659. */
  660. public static function cmpFQDN($baseHost, $list) {
  661. $baseHost = trim($baseHost);
  662. if (empty($baseHost)) {
  663. return FALSE;
  664. }
  665. if (self::validIPv4($baseHost) || self::validIPv6($baseHost)) {
  666. // resolve hostname
  667. // note: this is reverse-lookup and can be randomly set as soon as somebody is able to set
  668. // the reverse-DNS for his IP (security when for example used with REMOTE_ADDR)
  669. $baseHostName = gethostbyaddr($baseHost);
  670. if ($baseHostName === $baseHost) {
  671. // unable to resolve hostname
  672. return FALSE;
  673. }
  674. } else {
  675. $baseHostName = $baseHost;
  676. }
  677. $baseHostNameParts = explode('.', $baseHostName);
  678. $values = self::trimExplode(',', $list, 1);
  679. foreach ($values as $test) {
  680. $hostNameParts = explode('.', $test);
  681. // to match hostNameParts can only be shorter (in case of wildcards) or equal
  682. if (count($hostNameParts) > count($baseHostNameParts)) {
  683. continue;
  684. }
  685. $yes = TRUE;
  686. foreach ($hostNameParts as $index => $val) {
  687. $val = trim($val);
  688. if ($val === '*') {
  689. // wildcard valid for one or more hostname-parts
  690. $wildcardStart = $index + 1;
  691. // wildcard as last/only part always matches, otherwise perform recursive checks
  692. if ($wildcardStart < count($hostNameParts)) {
  693. $wildcardMatched = FALSE;
  694. $tempHostName = implode('.', array_slice($hostNameParts, $index + 1));
  695. while (($wildcardStart < count($baseHostNameParts)) && (!$wildcardMatched)) {
  696. $tempBaseHostName = implode('.', array_slice($baseHostNameParts, $wildcardStart));
  697. $wildcardMatched = self::cmpFQDN($tempBaseHostName, $tempHostName);
  698. $wildcardStart++;
  699. }
  700. if ($wildcardMatched) {
  701. // match found by recursive compare
  702. return TRUE;
  703. } else {
  704. $yes = FALSE;
  705. }
  706. }
  707. } elseif ($baseHostNameParts[$index] !== $val) {
  708. // in case of no match
  709. $yes = FALSE;
  710. }
  711. }
  712. if ($yes) {
  713. return TRUE;
  714. }
  715. }
  716. return FALSE;
  717. }
  718. /**
  719. * Checks if a given URL matches the host that currently handles this HTTP request.
  720. * Scheme, hostname and (optional) port of the given URL are compared.
  721. *
  722. * @param string $url: URL to compare with the TYPO3 request host
  723. * @return boolean Whether the URL matches the TYPO3 request host
  724. */
  725. public static function isOnCurrentHost($url) {
  726. return (stripos($url . '/', self::getIndpEnv('TYPO3_REQUEST_HOST') . '/') === 0);
  727. }
  728. /**
  729. * Check for item in list
  730. * Check if an item exists in a comma-separated list of items.
  731. *
  732. * @param string $list comma-separated list of items (string)
  733. * @param string $item item to check for
  734. * @return boolean TRUE if $item is in $list
  735. */
  736. public static function inList($list, $item) {
  737. return (strpos(',' . $list . ',', ',' . $item . ',') !== FALSE ? TRUE : FALSE);
  738. }
  739. /**
  740. * Removes an item from a comma-separated list of items.
  741. *
  742. * @param string $element element to remove
  743. * @param string $list comma-separated list of items (string)
  744. * @return string new comma-separated list of items
  745. */
  746. public static function rmFromList($element, $list) {
  747. $items = explode(',', $list);
  748. foreach ($items as $k => $v) {
  749. if ($v == $element) {
  750. unset($items[$k]);
  751. }
  752. }
  753. return implode(',', $items);
  754. }
  755. /**
  756. * Expand a comma-separated list of integers with ranges (eg 1,3-5,7 becomes 1,3,4,5,7).
  757. * Ranges are limited to 1000 values per range.
  758. *
  759. * @param string $list comma-separated list of integers with ranges (string)
  760. * @return string new comma-separated list of items
  761. */
  762. public static function expandList($list) {
  763. $items = explode(',', $list);
  764. $list = array();
  765. foreach ($items as $item) {
  766. $range = explode('-', $item);
  767. if (isset($range[1])) {
  768. $runAwayBrake = 1000;
  769. for ($n = $range[0]; $n <= $range[1]; $n++) {
  770. $list[] = $n;
  771. $runAwayBrake--;
  772. if ($runAwayBrake <= 0) {
  773. break;
  774. }
  775. }
  776. } else {
  777. $list[] = $item;
  778. }
  779. }
  780. return implode(',', $list);
  781. }
  782. /**
  783. * Forces the integer $theInt into the boundaries of $min and $max. If the $theInt is 'FALSE' then the $zeroValue is applied.
  784. *
  785. * @param integer $theInt Input value
  786. * @param integer $min Lower limit
  787. * @param integer $max Higher limit
  788. * @param integer $zeroValue Default value if input is FALSE.
  789. * @return integer The input value forced into the boundaries of $min and $max
  790. * @deprecated since TYPO3 4.6, will be removed in TYPO3 4.8 - Use t3lib_utility_Math::forceIntegerInRange() instead
  791. */
  792. public static function intInRange($theInt, $min, $max = 2000000000, $zeroValue = 0) {
  793. self::logDeprecatedFunction();
  794. return t3lib_utility_Math::forceIntegerInRange($theInt, $min, $max, $zeroValue);
  795. }
  796. /**
  797. * Returns the $integer if greater than zero, otherwise returns zero.
  798. *
  799. * @param integer $theInt Integer string to process
  800. * @return integer
  801. * @deprecated since TYPO3 4.6, will be removed in TYPO3 4.8 - Use t3lib_utility_Math::convertToPositiveInteger() instead
  802. */
  803. public static function intval_positive($theInt) {
  804. self::logDeprecatedFunction();
  805. return t3lib_utility_Math::convertToPositiveInteger($theInt);
  806. }
  807. /**
  808. * Returns an integer from a three part version number, eg '4.12.3' -> 4012003
  809. *
  810. * @param string $verNumberStr Version number on format x.x.x
  811. * @return integer Integer version of version number (where each part can count to 999)
  812. * @deprecated since TYPO3 4.6, will be removed in TYPO3 4.9 - Use t3lib_utility_VersionNumber::convertVersionNumberToInteger() instead
  813. */
  814. public static function int_from_ver($verNumberStr) {
  815. // Deprecation log is activated only for TYPO3 4.7 and above
  816. if (t3lib_utility_VersionNumber::convertVersionNumberToInteger(TYPO3_version) >= 4007000) {
  817. self::logDeprecatedFunction();
  818. }
  819. return t3lib_utility_VersionNumber::convertVersionNumberToInteger($verNumberStr);
  820. }
  821. /**
  822. * Returns TRUE if the current TYPO3 version (or compatibility version) is compatible to the input version
  823. * Notice that this function compares branches, not versions (4.0.1 would be > 4.0.0 although they use the same compat_version)
  824. *
  825. * @param string $verNumberStr Minimum branch number required (format x.y / e.g. "4.0" NOT "4.0.0"!)
  826. * @return boolean Returns TRUE if this setup is compatible with the provided version number
  827. * @todo Still needs a function to convert versions to branches
  828. */
  829. public static function compat_version($verNumberStr) {
  830. $currVersionStr = $GLOBALS['TYPO3_CONF_VARS']['SYS']['compat_version'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['compat_version'] : TYPO3_branch;
  831. if (t3lib_utility_VersionNumber::convertVersionNumberToInteger($currVersionStr) < t3lib_utility_VersionNumber::convertVersionNumberToInteger($verNumberStr)) {
  832. return FALSE;
  833. } else {
  834. return TRUE;
  835. }
  836. }
  837. /**
  838. * Makes a positive integer hash out of the first 7 chars from the md5 hash of the input
  839. *
  840. * @param string $str String to md5-hash
  841. * @return integer Returns 28bit integer-hash
  842. */
  843. public static function md5int($str) {
  844. return hexdec(substr(md5($str), 0, 7));
  845. }
  846. /**
  847. * Returns the first 10 positions of the MD5-hash (changed from 6 to 10 recently)
  848. *
  849. * @param string $input Input string to be md5-hashed
  850. * @param integer $len The string-length of the output
  851. * @return string Substring of the resulting md5-hash, being $len chars long (from beginning)
  852. */
  853. public static function shortMD5($input, $len = 10) {
  854. return substr(md5($input), 0, $len);
  855. }
  856. /**
  857. * Returns a proper HMAC on a given input string and secret TYPO3 encryption key.
  858. *
  859. * @param string $input Input string to create HMAC from
  860. * @return string resulting (hexadecimal) HMAC currently with a length of 40 (HMAC-SHA-1)
  861. */
  862. public static function hmac($input) {
  863. $hashAlgorithm = 'sha1';
  864. $hashBlocksize = 64;
  865. $hmac = '';
  866. if (extension_loaded('hash') && function_exists('hash_hmac') && function_exists('hash_algos') && in_array($hashAlgorithm, hash_algos())) {
  867. $hmac = hash_hmac($hashAlgorithm, $input, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']);
  868. } else {
  869. // outer padding
  870. $opad = str_repeat(chr(0x5C), $hashBlocksize);
  871. // inner padding
  872. $ipad = str_repeat(chr(0x36), $hashBlocksize);
  873. if (strlen($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']) > $hashBlocksize) {
  874. // keys longer than block size are shorten
  875. $key = str_pad(pack('H*', call_user_func($hashAlgorithm, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])), $hashBlocksize, chr(0x00));
  876. } else {
  877. // keys shorter than block size are zero-padded
  878. $key = str_pad($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], $hashBlocksize, chr(0x00));
  879. }
  880. $hmac = call_user_func($hashAlgorithm, ($key ^ $opad) . pack('H*', call_user_func($hashAlgorithm, ($key ^ $ipad) . $input)));
  881. }
  882. return $hmac;
  883. }
  884. /**
  885. * Takes comma-separated lists and arrays and removes all duplicates
  886. * If a value in the list is trim(empty), the value is ignored.
  887. *
  888. * @param string $in_list Accept multiple parameters which can be comma-separated lists of values and arrays.
  889. * @param mixed $secondParameter: Dummy field, which if set will show a warning!
  890. * @return string Returns the list without any duplicates of values, space around values are trimmed
  891. */
  892. public static function uniqueList($in_list, $secondParameter = NULL) {
  893. if (is_array($in_list)) {
  894. throw new InvalidArgumentException(
  895. 'TYPO3 Fatal Error: t3lib_div::uniqueList() does NOT support array arguments anymore! Only string comma lists!',
  896. 1270853885
  897. );
  898. }
  899. if (isset($secondParameter)) {
  900. throw new InvalidArgumentException(
  901. 'TYPO3 Fatal Error: t3lib_div::uniqueList() does NOT support more than a single argument value anymore. You have specified more than one!',
  902. 1270853886
  903. );
  904. }
  905. return implode(',', array_unique(self::trimExplode(',', $in_list, 1)));
  906. }
  907. /**
  908. * Splits a reference to a file in 5 parts
  909. *
  910. * @param string $fileref Filename/filepath to be analysed
  911. * @return array Contains keys [path], [file], [filebody], [fileext], [realFileext]
  912. */
  913. public static function split_fileref($fileref) {
  914. $reg = array();
  915. if (preg_match('/(.*\/)(.*)$/', $fileref, $reg)) {
  916. $info['path'] = $reg[1];
  917. $info['file'] = $reg[2];
  918. } else {
  919. $info['path'] = '';
  920. $info['file'] = $fileref;
  921. }
  922. $reg = '';
  923. if (!is_dir($fileref) && preg_match('/(.*)\.([^\.]*$)/', $info['file'], $reg)) {
  924. $info['filebody'] = $reg[1];
  925. $info['fileext'] = strtolower($reg[2]);
  926. $info['realFileext'] = $reg[2];
  927. } else {
  928. $info['filebody'] = $info['file'];
  929. $info['fileext'] = '';
  930. }
  931. reset($info);
  932. return $info;
  933. }
  934. /**
  935. * Returns the directory part of a path without trailing slash
  936. * If there is no dir-part, then an empty string is returned.
  937. * Behaviour:
  938. *
  939. * '/dir1/dir2/script.php' => '/dir1/dir2'
  940. * '/dir1/' => '/dir1'
  941. * 'dir1/script.php' => 'dir1'
  942. * 'd/script.php' => 'd'
  943. * '/script.php' => ''
  944. * '' => ''
  945. *
  946. * @param string $path Directory name / path
  947. * @return string Processed input value. See function description.
  948. */
  949. public static function dirname($path) {
  950. $p = self::revExplode('/', $path, 2);
  951. return count($p) == 2 ? $p[0] : '';
  952. }
  953. /**
  954. * Modifies a HTML Hex color by adding/subtracting $R,$G and $B integers
  955. *
  956. * @param string $color A hexadecimal color code, #xxxxxx
  957. * @param integer $R Offset value 0-255
  958. * @param integer $G Offset value 0-255
  959. * @param integer $B Offset value 0-255
  960. * @return string A hexadecimal color code, #xxxxxx, modified according to input vars
  961. * @see modifyHTMLColorAll()
  962. */
  963. public static function modifyHTMLColor($color, $R, $G, $B) {
  964. // This takes a hex-color (# included!) and adds $R, $G and $B to the HTML-color (format: #xxxxxx) and returns the new color
  965. $nR = t3lib_utility_Math::forceIntegerInRange(hexdec(substr($color, 1, 2)) + $R, 0, 255);
  966. $nG = t3lib_utility_Math::forceIntegerInRange(hexdec(substr($color, 3, 2)) + $G, 0, 255);
  967. $nB = t3lib_utility_Math::forceIntegerInRange(hexdec(substr($color, 5, 2)) + $B, 0, 255);
  968. return '#' .
  969. substr('0' . dechex($nR), -2) .
  970. substr('0' . dechex($nG), -2) .
  971. substr('0' . dechex($nB), -2);
  972. }
  973. /**
  974. * Modifies a HTML Hex color by adding/subtracting $all integer from all R/G/B channels
  975. *
  976. * @param string $color A hexadecimal color code, #xxxxxx
  977. * @param integer $all Offset value 0-255 for all three channels.
  978. * @return string A hexadecimal color code, #xxxxxx, modified according to input vars
  979. * @see modifyHTMLColor()
  980. */
  981. public static function modifyHTMLColorAll($color, $all) {
  982. return self::modifyHTMLColor($color, $all, $all, $all);
  983. }
  984. /**
  985. * Removes comma (if present) in the end of string
  986. *
  987. * @param string $string String from which the comma in the end (if any) will be removed.
  988. * @return string
  989. * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7 - Use rtrim() directly
  990. */
  991. public static function rm_endcomma($string) {
  992. self::logDeprecatedFunction();
  993. return rtrim($string, ',');
  994. }
  995. /**
  996. * Tests if the input can be interpreted as integer.
  997. *
  998. * @param mixed $var Any input variable to test
  999. * @return boolean Returns TRUE if string is an integer
  1000. * @deprecated since TYPO3 4.6, will be removed in TYPO3 4.8 - Use t3lib_utility_Math::canBeInterpretedAsInteger() instead
  1001. */
  1002. public static function testInt($var) {
  1003. self::logDeprecatedFunction();
  1004. return t3lib_utility_Math::canBeInterpretedAsInteger($var);
  1005. }
  1006. /**
  1007. * Returns TRUE if the first part of $str matches the string $partStr
  1008. *
  1009. * @param string $str Full string to check
  1010. * @param string $partStr Reference string which must be found as the "first part" of the full string
  1011. * @return boolean TRUE if $partStr was found to be equal to the first part of $str
  1012. */
  1013. public static function isFirstPartOfStr($str, $partStr) {
  1014. return $partStr != '' && strpos((string) $str, (string) $partStr, 0) === 0;
  1015. }
  1016. /**
  1017. * Formats the input integer $sizeInBytes as bytes/kilobytes/megabytes (-/K/M)
  1018. *
  1019. * @param integer $sizeInBytes Number of bytes to format.
  1020. * @param string $labels Labels for bytes, kilo, mega and giga separated by vertical bar (|) and possibly encapsulated in "". Eg: " | K| M| G" (which is the default value)
  1021. * @return string Formatted representation of the byte number, for output.
  1022. */
  1023. public static function formatSize($sizeInBytes, $labels = '') {
  1024. // Set labels:
  1025. if (strlen($labels) == 0) {
  1026. $labels = ' | K| M| G';
  1027. } else {
  1028. $labels = str_replace('"', '', $labels);
  1029. }
  1030. $labelArr = explode('|', $labels);
  1031. // Find size:
  1032. if ($sizeInBytes > 900) {
  1033. if ($sizeInBytes > 900000000) { // GB
  1034. $val = $sizeInBytes / (1024 * 1024 * 1024);
  1035. return number_format($val, (($val < 20) ? 1 : 0), '.', '') . $labelArr[3];
  1036. }
  1037. elseif ($sizeInBytes > 900000) { // MB
  1038. $val = $sizeInBytes / (1024 * 1024);
  1039. return number_format($val, (($val < 20) ? 1 : 0), '.', '') . $labelArr[2];
  1040. } else { // KB
  1041. $val = $sizeInBytes / (1024);
  1042. return number_format($val, (($val < 20) ? 1 : 0), '.', '') . $labelArr[1];
  1043. }
  1044. } else { // Bytes
  1045. return $sizeInBytes . $labelArr[0];
  1046. }
  1047. }
  1048. /**
  1049. * Returns microtime input to milliseconds
  1050. *
  1051. * @param string $microtime Microtime
  1052. * @return integer Microtime input string converted to an integer (milliseconds)
  1053. */
  1054. public static function convertMicrotime($microtime) {
  1055. $parts = explode(' ', $microtime);
  1056. return round(($parts[0] + $parts[1]) * 1000);
  1057. }
  1058. /**
  1059. * This splits a string by the chars in $operators (typical /+-*) and returns an array with them in
  1060. *
  1061. * @param string $string Input string, eg "123 + 456 / 789 - 4"
  1062. * @param string $operators Operators to split by, typically "/+-*"
  1063. * @return array Array with operators and operands separated.
  1064. * @see tslib_cObj::calc(), tslib_gifBuilder::calcOffset()
  1065. */
  1066. public static function splitCalc($string, $operators) {
  1067. $res = Array();
  1068. $sign = '+';
  1069. while ($string) {
  1070. $valueLen = strcspn($string, $operators);
  1071. $value = substr($string, 0, $valueLen);
  1072. $res[] = Array($sign, trim($value));
  1073. $sign = substr($string, $valueLen, 1);
  1074. $string = substr($string, $valueLen + 1);
  1075. }
  1076. reset($res);
  1077. return $res;
  1078. }
  1079. /**
  1080. * Calculates the input by +,-,*,/,%,^ with priority to + and -
  1081. *
  1082. * @param string $string Input string, eg "123 + 456 / 789 - 4"
  1083. * @return integer Calculated value. Or error string.
  1084. * @see calcParenthesis()
  1085. * @deprecated since TYPO3 4.6, will be removed in TYPO3 4.8 - Use t3lib_utility_Math::calculateWithPriorityToAdditionAndSubtraction() instead
  1086. */
  1087. public static function calcPriority($string) {
  1088. self::logDeprecatedFunction();
  1089. return t3lib_utility_Math::calculateWithPriorityToAdditionAndSubtraction($string);
  1090. }
  1091. /**
  1092. * Calculates the input with parenthesis levels
  1093. *
  1094. * @param string $string Input string, eg "(123 + 456) / 789 - 4"
  1095. * @return integer Calculated value. Or error string.
  1096. * @see calcPriority(), tslib_cObj::stdWrap()
  1097. * @deprecated since TYPO3 4.6, will be removed in TYPO3 4.8 - Use t3lib_utility_Math::calculateWithParentheses() instead
  1098. */
  1099. public static function calcParenthesis($string) {
  1100. self::logDeprecatedFunction();
  1101. return t3lib_utility_Math::calculateWithParentheses($string);
  1102. }
  1103. /**
  1104. * Inverse version of htmlspecialchars()
  1105. *
  1106. * @param string $value Value where &gt;, &lt;, &quot; and &amp; should be converted to regular chars.
  1107. * @return string Converted result.
  1108. */
  1109. public static function htmlspecialchars_decode($value) {
  1110. $value = str_replace('&gt;', '>', $value);
  1111. $value = str_replace('&lt;', '<', $value);
  1112. $value = str_replace('&quot;', '"', $value);
  1113. $value = str_replace('&amp;', '&', $value);
  1114. return $value;
  1115. }
  1116. /**
  1117. * Re-converts HTML entities if they have been converted by htmlspecialchars()
  1118. *
  1119. * @param string $str String which contains eg. "&amp;amp;" which should stay "&amp;". Or "&amp;#1234;" to "&#1234;". Or "&amp;#x1b;" to "&#x1b;"
  1120. * @return string Converted result.
  1121. */
  1122. public static function deHSCentities($str) {
  1123. return preg_replace('/&amp;([#[:alnum:]]*;)/', '&\1', $str);
  1124. }
  1125. /**
  1126. * This function is used to escape any ' -characters when transferring text to JavaScript!
  1127. *
  1128. * @param string $string String to escape
  1129. * @param boolean $extended If set, also backslashes are escaped.
  1130. * @param string $char The character to escape, default is ' (single-quote)
  1131. * @return string Processed input string
  1132. */
  1133. public static function slashJS($string, $extended = FALSE, $char = "'") {
  1134. if ($extended) {
  1135. $string = str_replace("\\", "\\\\", $string);
  1136. }
  1137. return str_replace($char, "\\" . $char, $string);
  1138. }
  1139. /**
  1140. * Version of rawurlencode() where all spaces (%20) are re-converted to space-characters.
  1141. * Useful when passing text to JavaScript where you simply url-encode it to get around problems with syntax-errors, linebreaks etc.
  1142. *
  1143. * @param string $str String to raw-url-encode with spaces preserved
  1144. * @return string Rawurlencoded result of input string, but with all %20 (space chars) converted to real spaces.
  1145. */
  1146. public static function rawUrlEncodeJS($str) {
  1147. return str_replace('%20', ' ', rawurlencode($str));
  1148. }
  1149. /**
  1150. * rawurlencode which preserves "/" chars
  1151. * Useful when file paths should keep the "/" chars, but have all other special chars encoded.
  1152. *
  1153. * @param string $str Input string
  1154. * @return string Output string
  1155. */
  1156. public static function rawUrlEncodeFP($str) {
  1157. return str_replace('%2F', '/', rawurlencode($str));
  1158. }
  1159. /**
  1160. * Checking syntax of input email address
  1161. *
  1162. * @param string $email Input string to evaluate
  1163. * @return boolean Returns TRUE if the $email address (input string) is valid
  1164. */
  1165. public static function validEmail($email) {
  1166. // enforce maximum length to prevent libpcre recursion crash bug #52929 in PHP
  1167. // fixed in PHP 5.3.4; length restriction per SMTP RFC 2821
  1168. if (strlen($email) > 320) {
  1169. return FALSE;
  1170. }
  1171. return (filter_var($email, FILTER_VALIDATE_EMAIL) !== FALSE);
  1172. }
  1173. /**
  1174. * Checks if current e-mail sending method does not accept recipient/sender name
  1175. * in a call to PHP mail() function. Windows version of mail() and mini_sendmail
  1176. * program are known not to process such input correctly and they cause SMTP
  1177. * errors. This function will return TRUE if current mail sending method has
  1178. * problem with recipient name in recipient/sender argument for mail().
  1179. *
  1180. * TODO: 4.3 should have additional configuration variable, which is combined
  1181. * by || with the rest in this function.
  1182. *
  1183. * @return boolean TRUE if mail() does not accept recipient name
  1184. */
  1185. public static function isBrokenEmailEnvironment() {
  1186. return TYPO3_OS == 'WIN' || (FALSE !== strpos(ini_get('sendmail_path'), 'mini_sendmail'));
  1187. }
  1188. /**
  1189. * Changes from/to arguments for mail() function to work in any environment.
  1190. *
  1191. * @param string $address Address to adjust
  1192. * @return string Adjusted address
  1193. * @see t3lib_::isBrokenEmailEnvironment()
  1194. */
  1195. public static function normalizeMailAddress($address) {
  1196. if (self::isBrokenEmailEnvironment() && FALSE !== ($pos1 = strrpos($address, '<'))) {
  1197. $pos2 = strpos($address, '>', $pos1);
  1198. $address = substr($address, $pos1 + 1, ($pos2 ? $pos2 : strlen($address)) - $pos1 - 1);
  1199. }
  1200. return $address;
  1201. }
  1202. /**
  1203. * Formats a string for output between <textarea>-tags
  1204. * All content outputted in a textarea form should be passed through this function
  1205. * Not only is the content htmlspecialchar'ed on output but there is also a single newline added in the top. The newline is necessary because browsers will ignore the first newline after <textarea> if that is the first character. Therefore better set it!
  1206. *
  1207. * @param string $content Input string to be formatted.
  1208. * @return string Formatted for <textarea>-tags
  1209. */
  1210. public static function formatForTextarea($content) {
  1211. return LF . htmlspecialchars($content);
  1212. }
  1213. /**
  1214. * Converts string to uppercase
  1215. * The function converts all Latin characters (a-z, but no accents, etc) to
  1216. * uppercase. It is safe for all supported character sets (incl. utf-8).
  1217. * Unlike strtoupper() it does not honour the locale.
  1218. *
  1219. * @param string $str Input string
  1220. * @return string Uppercase String
  1221. */
  1222. public static function strtoupper($str) {
  1223. return strtr((string) $str, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
  1224. }
  1225. /**
  1226. * Converts string to lowercase
  1227. * The function converts all Latin characters (A-Z, but no accents, etc) to
  1228. * lowercase. It is safe for all supported character sets (incl. utf-8).
  1229. * Unlike strtolower() it does not honour the locale.
  1230. *
  1231. * @param string $str Input string
  1232. * @return string Lowercase String
  1233. */
  1234. public static function strtolower($str) {
  1235. return strtr((string) $str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
  1236. }
  1237. /**
  1238. * Returns a string of highly randomized bytes (over the full 8-bit range).
  1239. *
  1240. * Note: Returned values are not guaranteed to be crypto-safe,
  1241. * most likely they are not, depending on the used retrieval method.
  1242. *
  1243. * @param integer $bytesToReturn Number of characters (bytes) to return
  1244. * @return string Random Bytes
  1245. * @see http://bugs.php.net/bug.php?id=52523
  1246. * @see http://www.php-security.org/2010/05/09/mops-submission-04-generating-unpredictable-session-ids-and-hashes/index.html
  1247. */
  1248. public static function generateRandomBytes($bytesToReturn) {
  1249. // Cache 4k of the generated bytestream.
  1250. static $bytes = '';
  1251. $bytesToGenerate = max(4096, $bytesToReturn);
  1252. // if we have not enough random bytes cached, we generate new ones
  1253. if (!isset($bytes{$bytesToReturn - 1})) {
  1254. if (TYPO3_OS === 'WIN') {
  1255. // Openssl seems to be deadly slow on Windows, so try to use mcrypt
  1256. // Windows PHP versions have a bug when using urandom source (see #24410)
  1257. $bytes .= self::generateRandomBytesMcrypt($bytesToGenerate, MCRYPT_RAND);
  1258. } else {
  1259. // Try to use native PHP functions first, precedence has openssl
  1260. $bytes .= self::generateRandomBytesOpenSsl($bytesToGenerate);
  1261. if (!isset($bytes{$bytesToReturn - 1})) {
  1262. $bytes .= self::generateRandomBytesMcrypt($bytesToGenerate, MCRYPT_DEV_URANDOM);
  1263. }
  1264. // If openssl and mcrypt failed, try /dev/urandom
  1265. if (!isset($bytes{$bytesToReturn - 1})) {
  1266. $bytes .= self::generateRandomBytesUrandom($bytesToGenerate);
  1267. }
  1268. }
  1269. // Fall back if other random byte generation failed until now
  1270. if (!isset($bytes{$bytesToReturn - 1})) {
  1271. $bytes .= self::generateRandomBytesFallback($bytesToReturn);
  1272. }
  1273. }
  1274. // get first $bytesToReturn and remove it from the byte cache
  1275. $output = substr($bytes, 0, $bytesToReturn);
  1276. $bytes = substr($bytes, $bytesToReturn);
  1277. return $output;
  1278. }
  1279. /**
  1280. * Generate random bytes using openssl if available
  1281. *
  1282. * @param string $bytesToGenerate
  1283. * @return string
  1284. */
  1285. protected static function generateRandomBytesOpenSsl(

Large files files are truncated, but you can click here to view the full file