PageRenderTime 68ms CodeModel.GetById 6ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 2ms

/t3lib/class.t3lib_div.php

https://github.com/foxsoft/typo3v4core
PHP | 6019 lines | 3363 code | 574 blank | 2082 comment | 760 complexity | 03fd09c9e7b207cb8bc0d635e7e8b195 MD5 | raw file

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-2010 Kasper Skaarhoj (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/**
  28 * Contains the reknown class "t3lib_div" with general purpose functions
  29 *
  30 * $Id$
  31 * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
  32 * XHTML compliant
  33 * Usage counts are based on search 22/2 2003 through whole source including tslib/
  34 *
  35 * @author	Kasper Skaarhoj <kasperYYYY@typo3.com>
  36 */
  37/**
  38 * [CLASS/FUNCTION INDEX of SCRIPT]
  39 *
  40 *
  41 *
  42 *  232: class t3lib_div
  43 *
  44 *              SECTION: GET/POST Variables
  45 *  262:     function _GP($var)
  46 *  280:     function _GET($var=NULL)
  47 *  297:     function _POST($var=NULL)
  48 *  313:     function _GETset($inputGet,$key='')
  49 *  336:     function GPvar($var,$strip=0)
  50 *  353:     function GParrayMerged($var)
  51 *
  52 *              SECTION: IMAGE FUNCTIONS
  53 *  397:     function gif_compress($theFile, $type)
  54 *  425:     function png_to_gif_by_imagemagick($theFile)
  55 *  450:     function read_png_gif($theFile,$output_png=0)
  56 *
  57 *              SECTION: STRING FUNCTIONS
  58 *  499:     function fixed_lgd($string,$origChars,$preStr='...')
  59 *  524:     function fixed_lgd_pre($string,$chars)
  60 *  538:     function fixed_lgd_cs($string,$chars)
  61 *  555:     function breakTextForEmail($str,$implChar=LF,$charWidth=76)
  62 *  574:     function breakLinesForEmail($str,$implChar=LF,$charWidth=76)
  63 *  610:     function cmpIP($baseIP, $list)
  64 *  626:     function cmpIPv4($baseIP, $list)
  65 *  668:     function cmpIPv6($baseIP, $list)
  66 *  711:     function IPv6Hex2Bin ($hex)
  67 *  726:     function normalizeIPv6($address)
  68 *  782:     function validIPv6($ip)
  69 *  805:     function cmpFQDN($baseIP, $list)
  70 *  835:     function inList($list,$item)
  71 *  847:     function rmFromList($element,$list)
  72 *  863:     function expandList($list)
  73 *  894:     function intInRange($theInt,$min,$max=2000000000,$zeroValue=0)
  74 *  910:     function intval_positive($theInt)
  75 *  923:     function int_from_ver($verNumberStr)
  76 *  934:     function compat_version($verNumberStr)
  77 *  952:     function md5int($str)
  78 *  965:     function shortMD5($input, $len=10)
  79 *  978:     function uniqueList($in_list, $secondParameter=NULL)
  80 *  992:     function split_fileref($fileref)
  81 * 1030:     function dirname($path)
  82 * 1046:     function modifyHTMLColor($color,$R,$G,$B)
  83 * 1066:     function modifyHTMLColorAll($color,$all)
  84 * 1077:     function rm_endcomma($string)
  85 * 1090:     function danish_strtoupper($string)
  86 * 1105:     function convUmlauts($str)
  87 * 1118:     function testInt($var)
  88 * 1130:     function isFirstPartOfStr($str,$partStr)
  89 * 1146:     function formatSize($sizeInBytes,$labels='')
  90 * 1181:     function convertMicrotime($microtime)
  91 * 1195:     function splitCalc($string,$operators)
  92 * 1217:     function calcPriority($string)
  93 * 1258:     function calcParenthesis($string)
  94 * 1284:     function htmlspecialchars_decode($value)
  95 * 1299:     function deHSCentities($str)
  96 * 1312:     function slashJS($string,$extended=0,$char="'")
  97 * 1325:     function rawUrlEncodeJS($str)
  98 * 1337:     function rawUrlEncodeFP($str)
  99 * 1348:     function validEmail($email)
 100 * 1363:     function formatForTextarea($content)
 101 *
 102 *              SECTION: ARRAY FUNCTIONS
 103 * 1394:     function inArray($in_array,$item)
 104 * 1411:     function intExplode($delim, $string)
 105 * 1430:     function revExplode($delim, $string, $count=0)
 106 * 1450:     function trimExplode($delim, $string, $onlyNonEmptyValues=0)
 107 * 1472:     function uniqueArray($valueArray)
 108 * 1484:     function removeArrayEntryByValue($array,$cmpValue)
 109 * 1513:     function implodeArrayForUrl($name,$theArray,$str='',$skipBlank=0,$rawurlencodeParamName=0)
 110 * 1538:     function explodeUrl2Array($string,$multidim=FALSE)
 111 * 1564:     function compileSelectedGetVarsFromArray($varList,$getArray,$GPvarAlt=1)
 112 * 1587:     function addSlashesOnArray(&$theArray)
 113 * 1611:     function stripSlashesOnArray(&$theArray)
 114 * 1633:     function slashArray($arr,$cmd)
 115 * 1650:     function array_merge_recursive_overrule($arr0,$arr1,$notAddKeys=0,$includeEmtpyValues=true)
 116 * 1683:     function array_merge($arr1,$arr2)
 117 * 1696:     function csvValues($row,$delim=',',$quote='"')
 118 *
 119 *              SECTION: HTML/XML PROCESSING
 120 * 1738:     function get_tag_attributes($tag)
 121 * 1775:     function split_tag_attributes($tag)
 122 * 1809:     function implodeAttributes($arr,$xhtmlSafe=FALSE,$dontOmitBlankAttribs=FALSE)
 123 * 1836:     function implodeParams($arr,$xhtmlSafe=FALSE,$dontOmitBlankAttribs=FALSE)
 124 * 1851:     function wrapJS($string, $linebreak=TRUE)
 125 * 1882:     function xml2tree($string,$depth=999)
 126 * 1969:     function array2xml($array,$NSprefix='',$level=0,$docTag='phparray',$spaceInd=0, $options=array(),$stackData=array())
 127 * 2088:     function xml2array($string,$NSprefix='',$reportDocTag=FALSE)
 128 * 2198:     function xmlRecompileFromStructValArray($vals)
 129 * 2242:     function xmlGetHeaderAttribs($xmlData)
 130 *
 131 *              SECTION: FILES FUNCTIONS
 132 * 2275:     function getURL($url, $includeHeader=0)
 133 * 2342:     function writeFile($file,$content)
 134 * 2367:     function fixPermissions($file)
 135 * 2384:     function writeFileToTypo3tempDir($filepath,$content)
 136 * 2427:     function mkdir($theNewFolder)
 137 * 2446:     function mkdir_deep($destination,$deepDir)
 138 * 2468:     function get_dirs($path)
 139 * 2493:     function getFilesInDir($path,$extensionList='',$prependPath=0,$order='')
 140 * 2547:     function getAllFilesAndFoldersInPath($fileArr,$path,$extList='',$regDirs=0,$recursivityLevels=99)
 141 * 2570:     function removePrefixPathFromList($fileArr,$prefixToRemove)
 142 * 2586:     function fixWindowsFilePath($theFile)
 143 * 2598:     function resolveBackPath($pathStr)
 144 * 2626:     function locationHeaderUrl($path)
 145 *
 146 *              SECTION: DEBUG helper FUNCTIONS
 147 * 2666:     function debug_ordvalue($string,$characters=100)
 148 * 2683:     function view_array($array_in)
 149 * 2711:     function print_array($array_in)
 150 * 2726:     function debug($var="",$brOrHeader=0)
 151 * 2757:     function debug_trail()
 152 * 2779:     function debugRows($rows,$header='')
 153 *
 154 *              SECTION: SYSTEM INFORMATION
 155 * 2857:     function getThisUrl()
 156 * 2873:     function linkThisScript($getParams=array())
 157 * 2897:     function linkThisUrl($url,$getParams=array())
 158 * 2920:     function getIndpEnv($getEnvName)
 159 * 3113:     function milliseconds()
 160 * 3125:     function clientInfo($useragent='')
 161 *
 162 *              SECTION: TYPO3 SPECIFIC FUNCTIONS
 163 * 3212:     function getFileAbsFileName($filename,$onlyRelative=1,$relToTYPO3_mainDir=0)
 164 * 3248:     function validPathStr($theFile)
 165 * 3259:     function isAbsPath($path)
 166 * 3270:     function isAllowedAbsPath($path)
 167 * 3287:     function verifyFilenameAgainstDenyPattern($filename)
 168 * 3305:     function upload_copy_move($source,$destination)
 169 * 3331:     function upload_to_tempfile($uploadedFileName)
 170 * 3349:     function unlink_tempfile($uploadedTempFileName)
 171 * 3365:     function tempnam($filePrefix)
 172 * 3379:     function stdAuthCode($uid_or_record,$fields='',$codeLength=8)
 173 * 3410:     function cHashParams($addQueryParams)
 174 * 3433:     function hideIfNotTranslated($l18n_cfg_fieldValue)
 175 * 3448:     function readLLfile($fileRef,$langKey)
 176 * 3472:     function readLLXMLfile($fileRef,$langKey)
 177 * 3589:     function llXmlAutoFileName($fileRef,$language)
 178 * 3633:     function loadTCA($table)
 179 * 3653:     function resolveSheetDefInDS($dataStructArray,$sheet='sDEF')
 180 * 3686:     function resolveAllSheetsInDS($dataStructArray)
 181 * 3715:     function callUserFunction($funcName,&$params,&$ref,$checkPrefix='user_',$silent=0)
 182 * 3813:     function &getUserObj($classRef,$checkPrefix='user_',$silent=0)
 183 * 3871:     function &makeInstance($className)
 184 * 3883:     function makeInstanceClassName($className)
 185 * 3897:     function &makeInstanceService($serviceType, $serviceSubType='', $excludeServiceKeys=array())
 186 * 3961:     function plainMailEncoded($email,$subject,$message,$headers='',$enc='',$charset='',$dontEncodeHeader=false)
 187 * 4031:     function quoted_printable($string,$maxlen=76)
 188 * 4078:     function encodeHeader($line,$enc='',$charset='ISO-8859-1')
 189 * 4121:     function substUrlsInPlainText($message,$urlmode='76',$index_script_url='')
 190 * 4155:     function makeRedirectUrl($inUrl,$l=0,$index_script_url='')
 191 * 4182:     function freetypeDpiComp($font_size)
 192 * 4194:     function initSysLog()
 193 * 4251:     function sysLog($msg, $extKey, $severity=0)
 194 * 4334:     function devLog($msg, $extKey, $severity=0, $dataVar=FALSE)
 195 * 4355:     function arrayToLogString($arr, $valueList=array(), $valueLength=20)
 196 * 4378:     function imageMagickCommand($command, $parameters, $path='')
 197 * 4425:     function unQuoteFilenames($parameters,$unQuote=FALSE)
 198 * 4459:     function quoteJSvalue($value, $inScriptTags = false)
 199 *
 200 * TOTAL FUNCTIONS: 138
 201 * (This index is automatically created/updated by the extension "extdeveval")
 202 *
 203 */
 204
 205	// a tabulator
 206define('TAB', chr(9));
 207	// a linefeed
 208define('LF', chr(10));
 209	// a carriage return
 210define('CR', chr(13));
 211	// a CR-LF combination
 212define('CRLF', CR . LF);
 213
 214/**
 215 * The legendary "t3lib_div" class - Miscellaneous functions for general purpose.
 216 * Most of the functions does not relate specifically to TYPO3
 217 * However a section of functions requires certain TYPO3 features available
 218 * See comments in the source.
 219 * You are encouraged to use this library in your own scripts!
 220 *
 221 * USE:
 222 * The class is intended to be used without creating an instance of it.
 223 * So: Don't instantiate - call functions with "t3lib_div::" prefixed the function name.
 224 * So use t3lib_div::[method-name] to refer to the functions, eg. 't3lib_div::milliseconds()'
 225 *
 226 * @author	Kasper Skaarhoj <kasperYYYY@typo3.com>
 227 * @package TYPO3
 228 * @subpackage t3lib
 229 */
 230final class t3lib_div {
 231
 232		// Severity constants used by t3lib_div::sysLog()
 233	const SYSLOG_SEVERITY_INFO = 0;
 234	const SYSLOG_SEVERITY_NOTICE = 1;
 235	const SYSLOG_SEVERITY_WARNING = 2;
 236	const SYSLOG_SEVERITY_ERROR = 3;
 237	const SYSLOG_SEVERITY_FATAL = 4;
 238
 239
 240	/*************************
 241	 *
 242	 * GET/POST Variables
 243	 *
 244	 * Background:
 245	 * Input GET/POST variables in PHP may have their quotes escaped with "\" or not depending on configuration.
 246	 * TYPO3 has always converted quotes to BE escaped if the configuration told that they would not be so.
 247	 * But the clean solution is that quotes are never escaped and that is what the functions below offers.
 248	 * Eventually TYPO3 should provide this in the global space as well.
 249	 * In the transitional phase (or forever..?) we need to encourage EVERY to read and write GET/POST vars through the API functions below.
 250	 *
 251	 *************************/
 252
 253	/**
 254	 * Returns the 'GLOBAL' value of incoming data from POST or GET, with priority to POST (that is equalent to 'GP' order)
 255	 * Strips slashes from all output, both strings and arrays.
 256	 * This function substitutes t3lib_div::GPvar()
 257	 * To enhancement security in your scripts, please consider using t3lib_div::_GET or t3lib_div::_POST if you already know by which method your data is arriving to the scripts!
 258	 * Usage: 537
 259	 *
 260	 * @param	string		GET/POST var to return
 261	 * @return	mixed		POST var named $var and if not set, the GET var of the same name.
 262	 */
 263	public static function _GP($var)	{
 264		if(empty($var)) return;
 265		$value = isset($_POST[$var]) ? $_POST[$var] : $_GET[$var];
 266		if (isset($value))	{
 267			if (is_array($value))	{ self::stripSlashesOnArray($value); } else { $value = stripslashes($value); }
 268		}
 269		return $value;
 270	}
 271
 272	/**
 273	 * Returns the global arrays $_GET and $_POST merged with $_POST taking precedence.
 274	 *
 275	 * @param	string		Key (variable name) from GET or POST vars
 276	 * @return	array		Returns the GET vars merged recursively onto the POST vars.
 277	 */
 278	public static function _GPmerged($parameter) {
 279		$postParameter = (isset($_POST[$parameter]) && is_array($_POST[$parameter])) ? $_POST[$parameter] : array();
 280		$getParameter  = (isset($_GET[$parameter]) && is_array($_GET[$parameter])) ? $_GET[$parameter] : array();
 281
 282		$mergedParameters = self::array_merge_recursive_overrule($getParameter, $postParameter);
 283		self::stripSlashesOnArray($mergedParameters);
 284
 285		return $mergedParameters;
 286	}
 287
 288	/**
 289	 * Returns the global $_GET array (or value from) normalized to contain un-escaped values.
 290	 * ALWAYS use this API function to acquire the GET variables!
 291	 * Usage: 27
 292	 *
 293	 * @param	string		Optional pointer to value in GET array (basically name of GET var)
 294	 * @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!*
 295	 * @see _POST(), _GP(), _GETset()
 296	 */
 297	public static function _GET($var=NULL)	{
 298		$value = ($var === NULL) ? $_GET : (empty($var) ? NULL : $_GET[$var]);
 299		if (isset($value))	{	// Removes slashes since TYPO3 has added them regardless of magic_quotes setting.
 300			if (is_array($value))	{ self::stripSlashesOnArray($value); } else { $value = stripslashes($value); }
 301		}
 302		return $value;
 303	}
 304
 305	/**
 306	 * Returns the global $_POST array (or value from) normalized to contain un-escaped values.
 307	 * ALWAYS use this API function to acquire the $_POST variables!
 308	 * Usage: 41
 309	 *
 310	 * @param	string		Optional pointer to value in POST array (basically name of POST var)
 311	 * @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!*
 312	 * @see _GET(), _GP()
 313	 */
 314	public static function _POST($var=NULL)	{
 315		$value = ($var === NULL) ? $_POST : (empty($var) ? NULL : $_POST[$var]);
 316		if (isset($value))	{	// Removes slashes since TYPO3 has added them regardless of magic_quotes setting.
 317			if (is_array($value))	{ self::stripSlashesOnArray($value); } else { $value = stripslashes($value); }
 318		}
 319		return $value;
 320	}
 321
 322	/**
 323	 * Writes input value to $_GET.
 324	 * Usage: 2
 325	 *
 326	 * @param mixed $inputGet
 327	 *        array or single value to write to $_GET. Values should NOT be
 328	 *        escaped at input time (but will be escaped before writing
 329	 *        according to TYPO3 standards).
 330	 * @param string $key
 331	 *        alternative key; If set, this will not set the WHOLE GET array,
 332	 *        but only the key in it specified by this value!
 333	 *        You can specify to replace keys on deeper array levels by
 334	 *        separating the keys with a pipe.
 335	 *        Example: 'parentKey|childKey' will result in
 336	 *        array('parentKey' => array('childKey' => $inputGet))
 337	 *
 338	 * @return	void
 339	 */
 340	public static function _GETset($inputGet, $key = '') {
 341			// adds slashes since TYPO3 standard currently is that slashes
 342			// must be applied (regardless of magic_quotes setting)
 343		if (is_array($inputGet)) {
 344			self::addSlashesOnArray($inputGet);
 345		} else {
 346			$inputGet = addslashes($inputGet);
 347		}
 348
 349		if ($key != '') {
 350			if (strpos($key, '|') !== FALSE) {
 351				$pieces = explode('|', $key);
 352				$newGet = array();
 353				$pointer =& $newGet;
 354				foreach ($pieces as $piece) {
 355					$pointer =& $pointer[$piece];
 356				}
 357				$pointer = $inputGet;
 358				$mergedGet = self::array_merge_recursive_overrule(
 359					$_GET, $newGet
 360				);
 361
 362				$_GET = $mergedGet;
 363				$GLOBALS['HTTP_GET_VARS'] = $mergedGet;
 364			} else {
 365				$_GET[$key] = $inputGet;
 366				$GLOBALS['HTTP_GET_VARS'][$key] = $inputGet;
 367			}
 368		} elseif (is_array($inputGet)) {
 369			$_GET = $inputGet;
 370			$GLOBALS['HTTP_GET_VARS'] = $inputGet;
 371		}
 372	}
 373
 374	/**
 375	 * Returns the  value of incoming data from globals variable $_POST or $_GET, with priority to $_POST (that is equalent to 'GP' order).
 376	 * Strips slashes of string-outputs, but not arrays UNLESS $strip is set. If $strip is set all output will have escaped characters unescaped.
 377	 * Usage: 2
 378	 *
 379	 * @param	string		GET/POST var to return
 380	 * @param	boolean		If set, values are stripped of return values that are *arrays!* - string/integer values returned are always strip-slashed()
 381	 * @return	mixed		POST var named $var and if not set, the GET var of the same name.
 382	 * @deprecated since TYPO3 3.6 - Use t3lib_div::_GP instead (ALWAYS delivers a value with un-escaped values!)
 383	 * @see _GP()
 384	 */
 385	public static function GPvar($var,$strip=0)	{
 386		self::logDeprecatedFunction();
 387
 388		if(empty($var)) return;
 389		$value = isset($_POST[$var]) ? $_POST[$var] : $_GET[$var];
 390		if (isset($value) && is_string($value))	{ $value = stripslashes($value); }	// Originally check '&& get_magic_quotes_gpc() ' but the values of $_GET are always slashed regardless of get_magic_quotes_gpc() because HTTP_POST/GET_VARS are run through addSlashesOnArray in the very beginning of index_ts.php eg.
 391		if ($strip && isset($value) && is_array($value)) { self::stripSlashesOnArray($value); }
 392		return $value;
 393	}
 394
 395	/**
 396	 * Returns the global arrays $_GET and $_POST merged with $_POST taking precedence.
 397	 * Usage: 1
 398	 *
 399	 * @param	string		Key (variable name) from GET or POST vars
 400	 * @return	array		Returns the GET vars merged recursively onto the POST vars.
 401	 * @deprecated since TYPO3 3.7 - Use t3lib_div::_GPmerged instead
 402	 * @see _GP()
 403	 */
 404	public static function GParrayMerged($var)	{
 405		self::logDeprecatedFunction();
 406
 407		return self::_GPmerged($var);
 408	}
 409
 410	/**
 411	 * Wrapper for the RemoveXSS function.
 412	 * Removes potential XSS code from an input string.
 413	 *
 414	 * Using an external class by Travis Puderbaugh <kallahar@quickwired.com>
 415	 *
 416	 * @param	string		Input string
 417	 * @return	string		Input string with potential XSS code removed
 418	 */
 419	public static function removeXSS($string)	{
 420		require_once(PATH_typo3.'contrib/RemoveXSS/RemoveXSS.php');
 421		$string = RemoveXSS::process($string);
 422		return $string;
 423	}
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434	/*************************
 435	 *
 436	 * IMAGE FUNCTIONS
 437	 *
 438	 *************************/
 439
 440
 441	/**
 442	 * Compressing a GIF file if not already LZW compressed.
 443	 * 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)
 444	 *
 445	 * 		The function takes a file-reference, $theFile, and saves it again through GD or ImageMagick in order to compress the file
 446	 * 		GIF:
 447	 * 		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!)
 448	 * 		If $type is set to either 'IM' or 'GD' the compression is done with ImageMagick and GD respectively
 449	 * 		PNG:
 450	 * 		No changes.
 451	 *
 452	 * 		$theFile is expected to be a valid GIF-file!
 453	 * 		The function returns a code for the operation.
 454	 * Usage: 9
 455	 *
 456	 * @param	string		Filepath
 457	 * @param	string		See description of function
 458	 * @return	string		Returns "GD" if GD was used, otherwise "IM" if ImageMagick was used. If nothing done at all, it returns empty string.
 459	 */
 460	public static function gif_compress($theFile, $type)	{
 461		$gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
 462		$returnCode='';
 463		if ($gfxConf['gif_compress'] && strtolower(substr($theFile,-4,4))=='.gif')	{	// GIF...
 464			if (($type=='IM' || !$type) && $gfxConf['im'] && $gfxConf['im_path_lzw'])	{	// IM
 465				$cmd = self::imageMagickCommand('convert', '"'.$theFile.'" "'.$theFile.'"', $gfxConf['im_path_lzw']);
 466				exec($cmd);
 467
 468				$returnCode='IM';
 469			} elseif (($type=='GD' || !$type) && $gfxConf['gdlib'] && !$gfxConf['gdlib_png'])	{	// GD
 470				$tempImage = imageCreateFromGif($theFile);
 471				imageGif($tempImage, $theFile);
 472				imageDestroy($tempImage);
 473				$returnCode='GD';
 474			}
 475		}
 476		return $returnCode;
 477	}
 478
 479	/**
 480	 * Converts a png file to gif.
 481	 * This converts a png file to gif IF the FLAG $GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif'] is set true.
 482	 * Usage: 5
 483	 *
 484	 * @param	string		$theFile	the filename with path
 485	 * @return	string		new filename
 486	 */
 487	public static function png_to_gif_by_imagemagick($theFile)	{
 488		if ($GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif']
 489			&& $GLOBALS['TYPO3_CONF_VARS']['GFX']['im']
 490			&& $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']
 491			&& strtolower(substr($theFile,-4,4))=='.png'
 492			&& @is_file($theFile))	{	// IM
 493				$newFile = substr($theFile,0,-4).'.gif';
 494				$cmd = self::imageMagickCommand('convert', '"'.$theFile.'" "'.$newFile.'"', $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']);
 495				exec($cmd);
 496				$theFile = $newFile;
 497					// unlink old file?? May be bad idea bacause TYPO3 would then recreate the file every time as TYPO3 thinks the file is not generated because it's missing!! So do not unlink $theFile here!!
 498		}
 499		return $theFile;
 500	}
 501
 502	/**
 503	 * Returns filename of the png/gif version of the input file (which can be png or gif).
 504	 * If input file type does not match the wanted output type a conversion is made and temp-filename returned.
 505	 * Usage: 2
 506	 *
 507	 * @param	string		Filepath of image file
 508	 * @param	boolean		If set, then input file is converted to PNG, otherwise to GIF
 509	 * @return	string		If the new image file exists, it's filepath is returned
 510	 */
 511	public static function read_png_gif($theFile,$output_png=0)	{
 512		if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] && @is_file($theFile))	{
 513			$ext = strtolower(substr($theFile,-4,4));
 514			if (
 515					((string)$ext=='.png' && $output_png)	||
 516					((string)$ext=='.gif' && !$output_png)
 517				)	{
 518				return $theFile;
 519			} else {
 520				$newFile = PATH_site.'typo3temp/readPG_'.md5($theFile.'|'.filemtime($theFile)).($output_png?'.png':'.gif');
 521				$cmd = self::imageMagickCommand('convert', '"'.$theFile.'" "'.$newFile.'"', $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path']);
 522				exec($cmd);
 523				if (@is_file($newFile))	return $newFile;
 524			}
 525		}
 526	}
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542	/*************************
 543	 *
 544	 * STRING FUNCTIONS
 545	 *
 546	 *************************/
 547
 548	/**
 549	 * Truncates string.
 550	 * Returns a new string of max. $chars length.
 551	 * If the string is longer, it will be truncated and appended with '...'.
 552	 * Usage: 39
 553	 *
 554	 * @param	string		string to truncate
 555	 * @param	integer		must be an integer with an absolute value of at least 4. if negative the string is cropped from the right end.
 556	 * @param	string		String to append to the output if it is truncated, default is '...'
 557	 * @return	string		new string
 558	 * @deprecated since TYPO3 4.1 - Works ONLY for single-byte charsets! Use t3lib_div::fixed_lgd_cs() instead
 559	 * @see fixed_lgd_pre()
 560	 */
 561	public static function fixed_lgd($string,$origChars,$preStr='...')	{
 562		self::logDeprecatedFunction();
 563
 564		$chars = abs($origChars);
 565		if ($chars >= 4)	{
 566			if(strlen($string)>$chars)  {
 567				return $origChars < 0 ?
 568					$preStr.trim(substr($string, -($chars-3))) :
 569					trim(substr($string, 0, $chars-3)).$preStr;
 570			}
 571		}
 572		return $string;
 573	}
 574
 575	/**
 576	 * Truncates string.
 577	 * Returns a new string of max. $chars length.
 578	 * If the string is longer, it will be truncated and prepended with '...'.
 579	 * This works like fixed_lgd(), but is truncated in the start of the string instead of the end
 580	 * Usage: 6
 581	 *
 582	 * @param	string		string to truncate
 583	 * @param	integer		must be an integer of at least 4
 584	 * @return	string		new string
 585	 * @deprecated since TYPO3 4.1 - Use either fixed_lgd() or fixed_lgd_cs() (with negative input value for $chars)
 586	 * @see fixed_lgd()
 587	 */
 588	public static function fixed_lgd_pre($string,$chars)	{
 589		self::logDeprecatedFunction();
 590
 591		return strrev(self::fixed_lgd(strrev($string),$chars));
 592	}
 593
 594	/**
 595	 * Truncates a string with appended/prepended "..." and takes current character set into consideration.
 596	 * Usage: 75
 597	 *
 598	 * @param	string		string to truncate
 599	 * @param	integer		must be an integer with an absolute value of at least 4. if negative the string is cropped from the right end.
 600	 * @param	string		appendix to the truncated string
 601	 * @return	string		cropped string
 602	 */
 603	public static function fixed_lgd_cs($string, $chars, $appendString='...') {
 604		if (is_object($GLOBALS['LANG'])) {
 605			return $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet, $string, $chars, $appendString);
 606		} elseif (is_object($GLOBALS['TSFE'])) {
 607			$charSet = ($GLOBALS['TSFE']->renderCharset != '' ? $GLOBALS['TSFE']->renderCharset : $GLOBALS['TSFE']->defaultCharSet);
 608			return $GLOBALS['TSFE']->csConvObj->crop($charSet, $string, $chars, $appendString);
 609		} else {
 610				// this case should not happen
 611			$csConvObj = self::makeInstance('t3lib_cs');
 612			return $csConvObj->crop('iso-8859-1', $string, $chars, $appendString);
 613		}
 614	}
 615
 616	/**
 617	 * Breaks up the text for emails
 618	 * Usage: 1
 619	 *
 620	 * @param	string		The string to break up
 621	 * @param	string		The string to implode the broken lines with (default/typically \n)
 622	 * @param	integer		The line length
 623	 * @deprecated since TYPO3 4.1 - Use PHP function wordwrap()
 624	 * @return	string
 625	 */
 626	public static function breakTextForEmail($str,$implChar=LF,$charWidth=76)	{
 627		self::logDeprecatedFunction();
 628
 629		$lines = explode(LF,$str);
 630		$outArr=array();
 631		foreach ($lines as $lStr) {
 632			$outArr[] = self::breakLinesForEmail($lStr,$implChar,$charWidth);
 633		}
 634		return implode(LF,$outArr);
 635	}
 636
 637	/**
 638	 * Breaks up a single line of text for emails
 639	 * Usage: 5
 640	 *
 641	 * @param	string		The string to break up
 642	 * @param	string		The string to implode the broken lines with (default/typically \n)
 643	 * @param	integer		The line length
 644	 * @return	string
 645	 * @see breakTextForEmail()
 646	 */
 647	public static function breakLinesForEmail($str,$implChar=LF,$charWidth=76)	{
 648		$lines=array();
 649		$l=$charWidth;
 650		$p=0;
 651		while(strlen($str)>$p)	{
 652			$substr=substr($str,$p,$l);
 653			if (strlen($substr)==$l)	{
 654				$count = count(explode(' ',trim(strrev($substr))));
 655				if ($count>1)	{	// OK...
 656					$parts = explode(' ',strrev($substr),2);
 657					$theLine = strrev($parts[1]);
 658				} else {
 659					$afterParts = explode(' ',substr($str,$l+$p),2);
 660					$theLine = $substr.$afterParts[0];
 661				}
 662				if (!strlen($theLine))	{break; }	// Error, because this would keep us in an endless loop.
 663			} else {
 664				$theLine=$substr;
 665			}
 666
 667			$lines[]=trim($theLine);
 668			$p+=strlen($theLine);
 669			if (!trim(substr($str,$p,$l)))	break;	// added...
 670		}
 671		return implode($implChar,$lines);
 672	}
 673
 674	/**
 675	 * Match IP number with list of numbers with wildcard
 676	 * Dispatcher method for switching into specialised IPv4 and IPv6 methods.
 677	 * Usage: 10
 678	 *
 679	 * @param	string		$baseIP is the current remote IP address for instance, typ. REMOTE_ADDR
 680	 * @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.
 681	 * @return	boolean		True if an IP-mask from $list matches $baseIP
 682	 */
 683	public static function cmpIP($baseIP, $list)	{
 684		$list = trim($list);
 685		if ($list === '')	{
 686			return false;
 687		} elseif ($list === '*')	{
 688			return true;
 689		}
 690		if (strpos($baseIP, ':') !== false && self::validIPv6($baseIP))	{
 691			return self::cmpIPv6($baseIP, $list);
 692		} else {
 693			return self::cmpIPv4($baseIP, $list);
 694		}
 695	}
 696
 697	/**
 698	 * Match IPv4 number with list of numbers with wildcard
 699	 *
 700	 * @param	string		$baseIP is the current remote IP address for instance, typ. REMOTE_ADDR
 701	 * @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)
 702	 * @return	boolean		True if an IP-mask from $list matches $baseIP
 703	 */
 704	public static function cmpIPv4($baseIP, $list)	{
 705		$IPpartsReq = explode('.',$baseIP);
 706		if (count($IPpartsReq)==4)	{
 707			$values = self::trimExplode(',',$list,1);
 708
 709			foreach($values as $test)	{
 710				list($test,$mask) = explode('/',$test);
 711
 712				if(intval($mask)) {
 713						// "192.168.3.0/24"
 714					$lnet = ip2long($test);
 715					$lip = ip2long($baseIP);
 716					$binnet = str_pad( decbin($lnet),32,'0','STR_PAD_LEFT');
 717					$firstpart = substr($binnet,0,$mask);
 718					$binip = str_pad( decbin($lip),32,'0','STR_PAD_LEFT');
 719					$firstip = substr($binip,0,$mask);
 720					$yes = (strcmp($firstpart,$firstip)==0);
 721				} else {
 722						// "192.168.*.*"
 723					$IPparts = explode('.',$test);
 724					$yes = 1;
 725					foreach ($IPparts as $index => $val) {
 726						$val = trim($val);
 727						if (strcmp($val,'*') && strcmp($IPpartsReq[$index],$val))	{
 728							$yes=0;
 729						}
 730					}
 731				}
 732				if ($yes) return true;
 733			}
 734		}
 735		return false;
 736	}
 737
 738	/**
 739	 * Match IPv6 address with a list of IPv6 prefixes
 740	 *
 741	 * @param	string		$baseIP is the current remote IP address for instance
 742	 * @param	string		$list is a comma-list of IPv6 prefixes, could also contain IPv4 addresses
 743	 * @return	boolean		True if an baseIP matches any prefix
 744	 */
 745	public static function cmpIPv6($baseIP, $list)	{
 746		$success = false;	// Policy default: Deny connection
 747		$baseIP = self::normalizeIPv6($baseIP);
 748
 749		$values = self::trimExplode(',',$list,1);
 750		foreach ($values as $test)	{
 751			list($test,$mask) = explode('/',$test);
 752			if (self::validIPv6($test))	{
 753				$test = self::normalizeIPv6($test);
 754				if (intval($mask))	{
 755					switch ($mask) {	// test on /48 /64
 756						case '48':
 757							$testBin = substr(self::IPv6Hex2Bin($test), 0, 48);
 758							$baseIPBin = substr(self::IPv6Hex2Bin($baseIP), 0, 48);
 759							$success = strcmp($testBin, $baseIPBin)==0 ? true : false;
 760						break;
 761						case '64':
 762							$testBin = substr(self::IPv6Hex2Bin($test), 0, 64);
 763							$baseIPBin = substr(self::IPv6Hex2Bin($baseIP), 0, 64);
 764							$success = strcmp($testBin, $baseIPBin)==0 ? true : false;
 765						break;
 766						default:
 767							$success = false;
 768					}
 769				} else {
 770					if (self::validIPv6($test))	{	// test on full ip address 128 bits
 771						$testBin = self::IPv6Hex2Bin($test);
 772						$baseIPBin = self::IPv6Hex2Bin($baseIP);
 773						$success = strcmp($testBin, $baseIPBin)==0 ? true : false;
 774					}
 775				}
 776			}
 777			if ($success) return true;
 778		}
 779		return false;
 780	}
 781
 782	/**
 783	 * [Describe function...]
 784	 *
 785	 * @param	[type]		$hex: ...
 786	 * @return	[type]		...
 787	 */
 788	public static function IPv6Hex2Bin ($hex)	{
 789		$bin = '';
 790		$hex = str_replace(':', '', $hex);	// Replace colon to nothing
 791		for ($i=0; $i<strlen($hex); $i=$i+2)	{
 792			$bin.= chr(hexdec(substr($hex, $i, 2)));
 793		}
 794		return $bin;
 795	}
 796
 797	/**
 798	 * Normalize an IPv6 address to full length
 799	 *
 800	 * @param	string		Given IPv6 address
 801	 * @return	string		Normalized address
 802	 */
 803	public static function normalizeIPv6($address)	{
 804		$normalizedAddress = '';
 805		$stageOneAddress = '';
 806
 807		$chunks = explode('::', $address);	// Count 2 if if address has hidden zero blocks
 808		if (count($chunks)==2)	{
 809			$chunksLeft = explode(':', $chunks[0]);
 810			$chunksRight = explode(':', $chunks[1]);
 811			$left = count($chunksLeft);
 812			$right = count($chunksRight);
 813
 814				// Special case: leading zero-only blocks count to 1, should be 0
 815			if ($left==1 && strlen($chunksLeft[0])==0)	$left=0;
 816
 817			$hiddenBlocks = 8 - ($left + $right);
 818			$hiddenPart = '';
 819			while ($h<$hiddenBlocks)	{
 820				$hiddenPart .= '0000:';
 821				$h++;
 822			}
 823
 824			if ($left == 0) {
 825				$stageOneAddress = $hiddenPart . $chunks[1];
 826			} else {
 827				$stageOneAddress = $chunks[0] . ':' . $hiddenPart . $chunks[1];
 828			}
 829		} else $stageOneAddress = $address;
 830
 831			// normalize the blocks:
 832		$blocks = explode(':', $stageOneAddress);
 833		$divCounter = 0;
 834		foreach ($blocks as $block)	{
 835			$tmpBlock = '';
 836			$i = 0;
 837			$hiddenZeros = 4 - strlen($block);
 838			while ($i < $hiddenZeros)	{
 839				$tmpBlock .= '0';
 840				$i++;
 841			}
 842			$normalizedAddress .= $tmpBlock . $block;
 843			if ($divCounter < 7)	{
 844				$normalizedAddress .= ':';
 845				$divCounter++;
 846			}
 847		}
 848		return $normalizedAddress;
 849	}
 850
 851	/**
 852	 * Validate a given IP address.
 853	 *
 854	 * Possible format are IPv4 and IPv6.
 855	 *
 856	 * @param	string		IP address to be tested
 857	 * @return	boolean		True if $ip is either of IPv4 or IPv6 format.
 858	 */
 859	public static function validIP($ip) {
 860		return (filter_var($ip, FILTER_VALIDATE_IP) !== false);
 861	}
 862
 863	/**
 864	 * Validate a given IP address to the IPv4 address format.
 865	 *
 866	 * Example for possible format:  10.0.45.99
 867	 *
 868	 * @param	string		IP address to be tested
 869	 * @return	boolean		True if $ip is of IPv4 format.
 870	 */
 871	public static function validIPv4($ip) {
 872		return (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false);
 873	}
 874
 875	/**
 876	 * Validate a given IP address to the IPv6 address format.
 877	 *
 878	 * Example for possible format:  43FB::BB3F:A0A0:0 | ::1
 879	 *
 880	 * @param	string		IP address to be tested
 881	 * @return	boolean		True if $ip is of IPv6 format.
 882	 */
 883	public static function validIPv6($ip)	{
 884		return (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false);
 885	}
 886
 887	/**
 888	 * Match fully qualified domain name with list of strings with wildcard
 889	 *
 890	 * @param	string		The current remote IP address for instance, typ. REMOTE_ADDR
 891	 * @param	string		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)
 892	 * @return	boolean		True if a domain name mask from $list matches $baseIP
 893	 */
 894	public static function cmpFQDN($baseIP, $list)        {
 895		if (count(explode('.',$baseIP))==4)     {
 896			$resolvedHostName = explode('.', gethostbyaddr($baseIP));
 897			$values = self::trimExplode(',',$list,1);
 898
 899			foreach($values as $test)	{
 900				$hostNameParts = explode('.',$test);
 901				$yes = 1;
 902
 903				foreach($hostNameParts as $index => $val)	{
 904					$val = trim($val);
 905					if (strcmp($val,'*') && strcmp($resolvedHostName[$index],$val)) {
 906						$yes=0;
 907					}
 908				}
 909				if ($yes) return true;
 910			}
 911		}
 912		return false;
 913	}
 914
 915	/**
 916	 * Checks if a given URL matches the host that currently handles this HTTP request.
 917	 * Scheme, hostname and (optional) port of the given URL are compared.
 918	 *
 919	 * @param	string		$url: URL to compare with the TYPO3 request host
 920	 * @return	boolean		Whether the URL matches the TYPO3 request host
 921	 */
 922	public static function isOnCurrentHost($url) {
 923		return (stripos($url . '/', self::getIndpEnv('TYPO3_REQUEST_HOST') . '/') === 0);
 924	}
 925
 926	/**
 927	 * Check for item in list
 928	 * Check if an item exists in a comma-separated list of items.
 929	 * Usage: 163
 930	 *
 931	 * @param	string		comma-separated list of items (string)
 932	 * @param	string		item to check for
 933	 * @return	boolean		true if $item is in $list
 934	 */
 935	public static function inList($list, $item)	{
 936		return (strpos(','.$list.',', ','.$item.',')!==false ? true : false);
 937	}
 938
 939	/**
 940	 * Removes an item from a comma-separated list of items.
 941	 * Usage: 1
 942	 *
 943	 * @param	string		element to remove
 944	 * @param	string		comma-separated list of items (string)
 945	 * @return	string		new comma-separated list of items
 946	 */
 947	public static function rmFromList($element,$list)	{
 948		$items = explode(',',$list);
 949		foreach ($items as $k => $v) {
 950			if ($v==$element) {
 951				unset($items[$k]);
 952			}
 953		}
 954		return implode(',',$items);
 955	}
 956
 957	/**
 958	 * Expand a comma-separated list of integers with ranges (eg 1,3-5,7 becomes 1,3,4,5,7).
 959	 * Ranges are limited to 1000 values per range.
 960	 *
 961	 * @param	string		comma-separated list of integers with ranges (string)
 962	 * @return	string		new comma-separated list of items
 963	 * @author	Martin Kutschker <martin.kutschker@activesolution.at>
 964	 */
 965	public static function expandList($list)      {
 966		$items = explode(',',$list);
 967		$list = array();
 968		foreach ($items as $item) {
 969			$range = explode('-',$item);
 970			if (isset($range[1]))	{
 971				$runAwayBrake = 1000;
 972				for ($n=$range[0]; $n<=$range[1]; $n++)	{
 973					$list[] = $n;
 974
 975					$runAwayBrake--;
 976					if ($runAwayBrake<=0)	break;
 977				}
 978			} else {
 979				$list[] = $item;
 980			}
 981		}
 982		return implode(',',$list);
 983	}
 984
 985	/**
 986	 * Forces the integer $theInt into the boundaries of $min and $max. If the $theInt is 'false' then the $zeroValue is applied.
 987	 * Usage: 224
 988	 *
 989	 * @param	integer		Input value
 990	 * @param	integer		Lower limit
 991	 * @param	integer		Higher limit
 992	 * @param	integer		Default value if input is false.
 993	 * @return	integer		The input value forced into the boundaries of $min and $max
 994	 */
 995	public static function intInRange($theInt,$min,$max=2000000000,$zeroValue=0)	{
 996		// Returns $theInt as an integer in the integerspace from $min to $max
 997		$theInt = intval($theInt);
 998		if ($zeroValue && !$theInt)	{$theInt=$zeroValue;}	// If the input value is zero after being converted to integer, zeroValue may set another default value for it.
 999		if ($theInt<$min){$theInt=$min;}
1000		if ($theInt>$max){$theInt=$max;}
1001		return $theInt;
1002	}
1003
1004	/**
1005	 * Returns the $integer if greater than zero, otherwise returns zero.
1006	 * Usage: 1
1007	 *
1008	 * @param	integer		Integer string to process
1009	 * @return	integer
1010	 */
1011	public static function intval_positive($theInt)	{
1012		$theInt = intval($theInt);
1013		if ($theInt<0){$theInt=0;}
1014		return $theInt;
1015	}
1016
1017	/**
1018	 * Returns an integer from a three part version number, eg '4.12.3' -> 4012003
1019	 * Usage: 2
1020	 *
1021	 * @param	string		Version number on format x.x.x
1022	 * @return	integer		Integer version of version number (where each part can count to 999)
1023	 */
1024	public static function int_from_ver($verNumberStr)	{
1025		$verParts = explode('.',$verNumberStr);
1026		return intval((int)$verParts[0].str_pad((int)$verParts[1],3,'0',STR_PAD_LEFT).str_pad((int)$verParts[2],3,'0',STR_PAD_LEFT));
1027	}
1028
1029	/**
1030	 * Returns true if the current TYPO3 version (or compatibility version) is compatible to the input version
1031	 * Notice that this function compares branches, not versions (4.0.1 would be > 4.0.0 although they use the same compat_version)
1032	 *
1033	 * @param	string		Minimum branch number required (format x.y / e.g. "4.0" NOT "4.0.0"!)
1034	 * @return	boolean		Returns true if this setup is compatible with the provided version number
1035	 * @todo	Still needs a function to convert versions to branches
1036	 */
1037	public static function compat_version($verNumberStr)	{
1038		global $TYPO3_CONF_VARS;
1039		$currVersionStr = $TYPO3_CONF_VARS['SYS']['compat_version'] ? $TYPO3_CONF_VARS['SYS']['compat_version'] : TYPO3_branch;
1040
1041		if (self::int_from_ver($currVersionStr) < self::int_from_ver($verNumberStr))	{
1042			return FALSE;
1043		} else {
1044			return TRUE;
1045		}
1046	}
1047
1048	/**
1049	 * Makes a positive integer hash out of the first 7 chars from the md5 hash of the input
1050	 * Usage: 5
1051	 *
1052	 * @param	string		String to md5-hash
1053	 * @return	integer		Returns 28bit integer-hash
1054	 */
1055	public static function md5int($str)	{
1056		return hexdec(substr(md5($str),0,7));
1057	}
1058
1059	/**
1060	 * Returns the first 10 positions of the MD5-hash		(changed from 6 to 10 recently)
1061	 *
1062	 * Usage: 37
1063	 *
1064	 * @param	string		Input string to be md5-hashed
1065	 * @param	integer		The string-length of the output
1066	 * @return	string		Substring of the resulting md5-hash, being $len chars long (from beginning)
1067	 */
1068	public static function shortMD5($input, $len=10)	{
1069		return substr(md5($input),0,$len);
1070	}
1071
1072	/**
1073	 * Returns a proper HMAC on a given input string and secret TYPO3 encryption key.
1074	 *
1075	 * @param 	string		Input string to create HMAC from
1076	 * @return 	string		resulting (hexadecimal) HMAC currently with a length of 40 (HMAC-SHA-1)
1077	 */
1078	public static function hmac($input) {
1079		$hashAlgorithm = 'sha1';
1080		$hashBlocksize = 64;
1081		$hmac = '';
1082
1083		if (extension_loaded('hash') && function_exists('hash_hmac') && function_exists('hash_algos') && in_array($hashAlgorithm, hash_algos())) {
1084			$hmac = hash_hmac($hashAlgorithm, $input, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']);
1085		} else {
1086				// outer padding
1087			$opad = str_repeat(chr(0x5C), $hashBlocksize);
1088				// innner padding
1089			$ipad = str_repeat(chr(0x36), $hashBlocksize);
1090			if (strlen($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']) > $hashBlocksize) {
1091					// keys longer than blocksize are shorten
1092				$key = str_pad(pack('H*', call_user_func($hashAlgorithm, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])), $hashBlocksize, chr(0x00));
1093			} else {
1094					// keys shorter than blocksize are zero-padded
1095				$key = str_pad($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], $hashBlocksize, chr(0x00));
1096			}
1097			$hmac = call_user_func($hashAlgorithm, ($key^$opad) . pack('H*', call_user_func($hashAlgorithm, ($key^$ipad) . $input)));
1098		}
1099		return $hmac;
1100	}
1101
1102	/**
1103	 * Takes comma-separated lists and arrays and removes all duplicates
1104	 * If a value in the list is trim(empty), the value is ignored.
1105	 * Usage: 16
1106	 *
1107	 * @param	string		Accept multiple parameters wich can be comma-separated lists of values and arrays.
1108	 * @param	mixed		$secondParameter: Dummy field, which if set will show a warning!
1109	 * @return	string		Returns the list without any duplicates of values, space around values are trimmed
1110	 */
1111	public static function uniqueList($in_list, $secondParameter=NULL)	{
1112		if (is_array($in_list)) {
1113			throw new InvalidArgumentException(
1114				'TYPO3 Fatal Error: t3lib_div::uniqueList() does NOT support array arguments anymore! Only string comma lists!',
1115				1270853885
1116			);
1117		}
1118		if (isset($secondParameter)) {
1119			throw new InvalidArgumentException(
1120				'TYPO3 Fatal Error: t3lib_div::uniqueList() does NOT support more than a single argument value anymore. You have specified more than one!',
1121				1270853886
1122			);
1123		}
1124
1125		return implode(',',array_unique(self::trimExplode(',',$in_list,1)));
1126	}
1127
1128	/**
1129	 * Splits a reference to a file in 5 parts
1130	 * Usage: 43
1131	 *
1132	 * @param	string		Filename/filepath to be analysed
1133	 * @return	array		Contains keys [path], [file], [filebody], [fileext], [realFileext]
1134	 */
1135	public static function split_fileref($fileref)	{
1136		$reg = array();
1137		if (preg_match('/(.*\/)(.*)$/', $fileref, $reg)) {
1138			$info['path'] = $reg[1];
1139			$info['file'] = $reg[2];
1140		} else {
1141			$info['path'] = '';
1142			$info['file'] = $fileref;
1143		}
1144
1145		$reg = '';
1146		if (!is_dir($fileref) && preg_match('/(.*)\.([^\.]*$)/', $info['file'], $reg)) {
1147			$info['filebody'] = $reg[1];
1148			$info['fileext'] = strtolower($reg[2]);
1149			$info['realFileext'] = $reg[2];
1150		} else {
1151			$info['filebody'] = $info['file'];
1152			$info['fileext'] = '';
1153		}
1154		reset($info);
1155		return $info;
1156	}
1157
1158	/**
1159	 * Returns the directory part of a path without trailing slash
1160	 * If there is no dir-part, then an empty string is returned.
1161	 * Behaviour:
1162	 *
1163	 * '/dir1/dir2/script.php' => '/dir1/dir2'
1164	 * '/dir1/' => '/dir1'
1165	 * 'dir1/script.php' => 'dir1'
1166	 * 'd/script.php' => 'd'
1167	 * '/script.php' => ''
1168	 * '' => ''
1169	 * Usage: 5
1170	 *
1171	 * @param	string		Directory name / path
1172	 * @return	string		Processed input value. See function description.
1173	 */
1174	public static function dirname($path)	{
1175		$p = self::revExplode('/',$path,2);
1176		return count($p)==2 ? $p[0] : '';
1177	}
1178
1179	/**
1180	 * Modifies a HTML Hex color by adding/subtracting $R,$G and $B integers
1181	 * Usage: 11
1182	 *
1183	 * @param	string		A hexadecimal color code, #xxxxxx
1184	 * @param	integer		Offset value 0-255
1185	 * @param	integer		Offset value 0-255
1186	 * @param	integer		Offset value 0-255
1187	 * @return	string		A hexadecimal color code, #xxxxxx, modified according to input vars
1188	 * @see modifyHTMLColorAll()
1189	 */
1190	public static function modifyHTMLColor($color,$R,$G,$B)	{
1191		// This takes a hex-color (# included!) and adds $R, $G and $B to the HTML-color (format: #xxxxxx) and returns the new color
1192		$nR = self::intInRange(hexdec(substr($color,1,2))+$R,0,255);
1193		$nG = self::intInRange(hexdec(substr($color,3,2))+$G,0,255);
1194		$nB = self::intInRange(hexdec(substr($color,5,2))+$B,0,255);
1195		return '#'.
1196			substr('0'.dechex($nR),-2).
1197			substr('0'.dechex($nG),-2).
1198			substr('0'.dechex($nB),-2);
1199	}
1200
1201	/**
1202	 * Modifies a HTML Hex color by adding/subtracting $all integer from all R/G/B channels
1203	 * Usage: 6
1204	 *
1205	 * @param	string		A hexadecimal color code, #xxxxxx
1206	 * @param	integer		Offset value 0-255 for all three channels.
1207	 * @return	string		A hexadecimal color code, #xxxxxx, modified according to input vars
1208	 * @see modifyHTMLColor()
1209	 */
1210	public static function modifyHTMLColorAll($color,$all)	{
1211		return self::modifyHTMLColor($color,$all,$all,$all);
1212	}
1213
1214	/**
1215	 * Removes comma (if present) in the end of string
1216	 * Usage: 2
1217	 *
1218	 * @param	string		String from which the comma in the end (if any) will be removed.
1219	 * @return	string
1220	 */
1221	public static function rm_endcomma($string)	{
1222		return rtrim($string, ',');
1223	}
1224
1225	/**
1226	 * strtoupper which converts danish (and other characters) characters as well
1227	 * Usage: 0
1228	 *
1229	 * @param	string		String to process
1230	 * @return	string
1231	 * @deprecated since TYPO3 3.5 - Use t3lib_cs::conv_case() instead or for HTML output, wrap your content in <span class="uppercase">...</span>)
1232	 * @ignore
1233	 */
1234	public static function danish_strtoupper($string)	{
1235		self::logDeprecatedFunction();
1236
1237		$value = strtoupper($string);
1238		return strtr($value, 'áéúíâęűôîćřĺäöü', 'ÁÉÚÍÄËÜÖĎĆŘĹÄÖÜ');
1239	}
1240
1241	/**
1242	 * Change umlaut characters to plain ASCII with normally two character target
1243	 * Only known characters will be converted, so don't expect a result for any character.
1244	 *
1245	 * ä => ae, Ö => Oe
1246	 *
1247	 * @param	string		String to convert.
1248	 * @deprecated since TYPO3 4.1 - Works only for western europe single-byte charsets! Use t3lib_cs::specCharsToASCII() instead!
1249	 * @return	string
1250	 */
1251	public static function convUmlauts($str)	{
1252		self::logDeprecatedFunction();
1253
1254		$pat  = array (	'/ä/',	'/Ä/',	'/ö/',	'/Ö/',	'/ü/',	'/Ü/',	'/ß/',	'/ĺ/',	'/Ĺ/',	'/ř/',	'/Ř/',	'/ć/',	'/Ć/'	);
1255		$repl = array (	'ae',	'Ae',	'oe',	'Oe',	'ue',	'Ue',	'ss',	'aa',	'AA',	'oe',	'OE',	'ae',	'AE'	);
1256		return preg_replace($pat,$repl,$str);
1257	}
1258
1259	/**
1260	 * Tests if the input is an integer.
1261	 * Usage: 77
1262	 *
1263	 * @param	mixed		Any input variable to test.
1264	 * @return	boolean		Returns true if string is an integer
1265	 */
1266	public static function testInt($var)	{
1267		return !strcmp($var,intval($var));
1268	}
1269
1270	/**
1271	 * Returns true if the first part of $str matches the string $partStr
1272	 * Usage: 59
1273	 *
1274	 * @param	string		Full string to check
1275	 * @param	string		Reference string which must be found as the "first part" of the full string
1276	 * @return	boolean		True if $partStr was found to be equal to the first part of $str
1277	 */
1278	public static function isFirstPartOfStr($str,$partStr)	{
1279		// Returns true, if the first part of a $str equals $partStr and $partStr is not ''
1280		$psLen = strlen($partStr);
1281		if ($psLen)	{
1282			return substr($str,0,$psLen)==(string)$partStr;
1283		} else return false;
1284	}
1285
1286	/**
1287	 * Formats the input integer $sizeInBytes as bytes/kilobytes/megabytes (-/K/M)
1288	 * Usage: 53
1289	 *
1290	 * @param	integer		Number of bytes to format.
1291	 * @param	string		Labels for bytes, kilo, mega and giga separated by vertical bar (|) and possibly encapsulated in "". Eg: " | K| M| G" (which is the default value)
1292	 * @return	string		Formatted representation of the byte number, for output.
1293	 */
1294	public static function formatSize($sizeInBytes,$labels='')	{
1295
1296			// Set labels:
1297		if (strlen($labels) == 0) {
1298			$labels = ' | K| M| G';
1299		} else {
1300			$labels = str_replace('"','',$labels);
1301		}
1302		$labelArr = explode('|',$labels);
1303
1304			// Find size:
1305		if ($sizeInBytes>900)	{
1306			if ($sizeInBytes>900000000)	{	// GB
1307				$val = $sizeInBytes/(1024*1024*1024);
1308				return number_format($val, (($val<20)?1:0), '.', '').$labelArr[3];
1309			}
1310			elseif ($sizeInBytes>900000)	{	// MB
1311				$val = $sizeInBytes/(1024*1024);
1312				return number_format($val, (($val<20)?1:0), '.', '').$labelArr[2];
1313			} else {	// KB
1314				$val = $sizeInBytes/(1024);
1315				return number_format($val, (($val<20)?1:0), '.', '').$labelArr[1];
1316			}
1317		} else {	// Bytes
1318			return $sizeInBytes.$labelArr[0];
1319		}
1320	}
1321
1322	/**
1323	 * Returns microtime input to milliseconds
1324	 * Usage: 2
1325	 *
1326	 * @param	string		Microtime
1327	 * @return	integer		Microtime input string converted to an integer (milliseconds)
1328	 */
1329	public static function convertMicrotime($microtime)	{
1330		$parts = explode(' ',$microtime);
1331		return round(($parts[0]+$parts[1])*1000);
1332	}
1333
1334	/**
1335	 * This splits a string by the chars in $operators (typical /+-*) and returns an array with them in
1336	 * Usage: 2
1337	 *
1338	 * @param	string		Input string, eg "123 + 456 / 789 - 4"
1339	 * @param	string		Operators to split by, typically "/+-*"
1340	 * @return	array		Array with operators and operands separated.
1341	 * @see tslib_cObj::calc(), tslib_gifBuilder::calcOffset()
1342	 */
1343	public static function splitCalc($string,$operators)	{
1344		$res = Array();
1345		$sign='+';
1346		while($string)	{
1347			$valueLen=strcspn($string,$operators);
1348			$value=substr($string,0,$valueLen);
1349			$res[] = Array($sign,trim($value));
1350			$sign=substr($string,$valueLen,1);
1351			$string=substr($string,$valueLen+1);
1352		}
1353		reset($res);
1354		return $res;
1355	}
1356
1357	/**
1358	 * Calculates the input by +,-,*,/,%,^ with priority to + and -
1359	 * Usage: 1
1360	 *
1361	 * @param	string		Input string, eg "123 + 456 / 789 - 4"
1362	 * @return	integer		Calculated value. Or error string.
1363	 * @see calcParenthesis()
1364	 */
1365	public static function calcPriority($string)	{
1366		$string=preg_replace('/[[:space:]]*/','',$string);	// removing all whitespace
1367		$string='+'.$string;	// Ensuring an operator for the first entrance
1368		$qm='\*\/\+-^%';
1369		$regex = '(['.$qm.'])(['.$qm.']?[0-9\.]*)';
1370			// split the expression here:
1371		$reg = array();
1372		preg_match_all('/'.$regex.'/',$string,$reg);
1373
1374		reset($reg[2]);
1375		$number=0;
1376		$Msign='+';
1377		$err='';
1378		$buffer=doubleval(current($reg[2]));
1379		next($reg[2]);  // Advance pointer
1380
1381		while(list($k,$v)=each($reg[2])) {
1382			$v=doubleval($v);
1383			$sign = $reg[1][$k];
1384			if ($s…

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