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

/lib/typo3/class.t3lib_div.php

https://bitbucket.org/moodle/moodle
PHP | 5839 lines | 3481 code | 478 blank | 1880 comment | 802 complexity | e8ddd127c69953ca521eed2bc1738094 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0

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

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