[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/typo3/ -> class.t3lib_div.php (source)

   1  <?php
   2  /***************************************************************
   3  *  Copyright notice
   4  *
   5  *  (c) 1999-2005 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: class.t3lib_div.php,v 1.2 2005/10/17 15:48:29 stronk7 Exp $
  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   *  211: class t3lib_div
  43   *
  44   *              SECTION: GET/POST Variables
  45   *  241:     function _GP($var)
  46   *  259:     function _GET($var=NULL)
  47   *  276:     function _POST($var=NULL)
  48   *  292:     function _GETset($inputGet,$key='')
  49   *  315:     function GPvar($var,$strip=0)
  50   *  332:     function GParrayMerged($var)
  51   *
  52   *              SECTION: IMAGE FUNCTIONS
  53   *  376:     function gif_compress($theFile, $type)
  54   *  402:     function png_to_gif_by_imagemagick($theFile)
  55   *  426:     function read_png_gif($theFile,$output_png=0)
  56   *
  57   *              SECTION: STRING FUNCTIONS
  58   *  475:     function fixed_lgd($string,$origChars,$preStr='...')
  59   *  500:     function fixed_lgd_pre($string,$chars)
  60   *  514:     function fixed_lgd_cs($string,$chars)
  61   *  531:     function breakTextForEmail($str,$implChar="\n",$charWidth=76)
  62   *  550:     function breakLinesForEmail($str,$implChar="\n",$charWidth=76)
  63   *  585:     function cmpIP($baseIP, $list)
  64   *  627:     function cmpFQDN($baseIP, $list)
  65   *  657:     function inList($list,$item)
  66   *  669:     function rmFromList($element,$list)
  67   *  687:     function intInRange($theInt,$min,$max=2000000000,$zeroValue=0)
  68   *  703:     function intval_positive($theInt)
  69   *  716:     function int_from_ver($verNumberStr)
  70   *  728:     function md5int($str)
  71   *  741:     function shortMD5($input, $len=10)
  72   *  754:     function uniqueList($in_list, $secondParameter=NULL)
  73   *  768:     function split_fileref($fileref)
  74   *  805:     function dirname($path)
  75   *  821:     function modifyHTMLColor($color,$R,$G,$B)
  76   *  841:     function modifyHTMLColorAll($color,$all)
  77   *  852:     function rm_endcomma($string)
  78   *  865:     function danish_strtoupper($string)
  79   *  880:     function convUmlauts($str)
  80   *  893:     function testInt($var)
  81   *  905:     function isFirstPartOfStr($str,$partStr)
  82   *  921:     function formatSize($sizeInBytes,$labels='')
  83   *  956:     function convertMicrotime($microtime)
  84   *  970:     function splitCalc($string,$operators)
  85   *  992:     function calcPriority($string)
  86   * 1032:     function calcParenthesis($string)
  87   * 1058:     function htmlspecialchars_decode($value)
  88   * 1073:     function deHSCentities($str)
  89   * 1086:     function slashJS($string,$extended=0,$char="'")
  90   * 1099:     function rawUrlEncodeJS($str)
  91   * 1111:     function rawUrlEncodeFP($str)
  92   * 1122:     function validEmail($email)
  93   * 1137:     function formatForTextarea($content)
  94   *
  95   *              SECTION: ARRAY FUNCTIONS
  96   * 1168:     function inArray($in_array,$item)
  97   * 1185:     function intExplode($delim, $string)
  98   * 1204:     function revExplode($delim, $string, $count=0)
  99   * 1224:     function trimExplode($delim, $string, $onlyNonEmptyValues=0)
 100   * 1246:     function uniqueArray($valueArray)
 101   * 1258:     function removeArrayEntryByValue($array,$cmpValue)
 102   * 1286:     function implodeArrayForUrl($name,$theArray,$str='',$skipBlank=0,$rawurlencodeParamName=0)
 103   * 1313:     function compileSelectedGetVarsFromArray($varList,$getArray,$GPvarAlt=1)
 104   * 1336:     function addSlashesOnArray(&$theArray)
 105   * 1360:     function stripSlashesOnArray(&$theArray)
 106   * 1382:     function slashArray($arr,$cmd)
 107   * 1399:     function array_merge_recursive_overrule($arr0,$arr1,$notAddKeys=0,$includeEmtpyValues=true)
 108   * 1432:     function array_merge($arr1,$arr2)
 109   * 1445:     function csvValues($row,$delim=',',$quote='"')
 110   *
 111   *              SECTION: HTML/XML PROCESSING
 112   * 1487:     function get_tag_attributes($tag)
 113   * 1524:     function split_tag_attributes($tag)
 114   * 1558:     function implodeAttributes($arr,$xhtmlSafe=FALSE,$dontOmitBlankAttribs=FALSE)
 115   * 1585:     function implodeParams($arr,$xhtmlSafe=FALSE,$dontOmitBlankAttribs=FALSE)
 116   * 1600:     function wrapJS($string, $linebreak=TRUE)
 117   * 1630:     function xml2tree($string,$depth=999)
 118   * 1716:     function array2xml($array,$NSprefix='',$level=0,$docTag='phparray',$spaceInd=0, $options=array(),$stackData=array())
 119   * 1830:     function xml2array($string,$NSprefix='',$reportDocTag=FALSE)
 120   * 1940:     function xmlRecompileFromStructValArray($vals)
 121   * 1984:     function xmlGetHeaderAttribs($xmlData)
 122   *
 123   *              SECTION: FILES FUNCTIONS
 124   * 2016:     function getURL($url)
 125   * 2058:     function writeFile($file,$content)
 126   * 2075:     function fixPermissions($file)
 127   * 2092:     function writeFileToTypo3tempDir($filepath,$content)
 128   * 2135:     function mkdir($theNewFolder)
 129   * 2155:     function get_dirs($path)
 130   * 2180:     function getFilesInDir($path,$extensionList='',$prependPath=0,$order='')
 131   * 2234:     function getAllFilesAndFoldersInPath($fileArr,$path,$extList='',$regDirs=0,$recursivityLevels=99)
 132   * 2257:     function removePrefixPathFromList($fileArr,$prefixToRemove)
 133   * 2273:     function fixWindowsFilePath($theFile)
 134   * 2285:     function resolveBackPath($pathStr)
 135   * 2312:     function locationHeaderUrl($path)
 136   *
 137   *              SECTION: DEBUG helper FUNCTIONS
 138   * 2352:     function debug_ordvalue($string,$characters=100)
 139   * 2369:     function view_array($array_in)
 140   * 2397:     function print_array($array_in)
 141   * 2412:     function debug($var="",$brOrHeader=0)
 142   *
 143   *              SECTION: SYSTEM INFORMATION
 144   * 2481:     function getThisUrl()
 145   * 2497:     function linkThisScript($getParams=array())
 146   * 2521:     function linkThisUrl($url,$getParams=array())
 147   * 2546:     function getIndpEnv($getEnvName)
 148   * 2735:     function milliseconds()
 149   * 2747:     function clientInfo($useragent='')
 150   *
 151   *              SECTION: TYPO3 SPECIFIC FUNCTIONS
 152   * 2834:     function getFileAbsFileName($filename,$onlyRelative=1,$relToTYPO3_mainDir=0)
 153   * 2870:     function validPathStr($theFile)
 154   * 2881:     function isAbsPath($path)
 155   * 2892:     function isAllowedAbsPath($path)
 156   * 2909:     function verifyFilenameAgainstDenyPattern($filename)
 157   * 2927:     function upload_copy_move($source,$destination)
 158   * 2953:     function upload_to_tempfile($uploadedFileName)
 159   * 2971:     function unlink_tempfile($uploadedTempFileName)
 160   * 2987:     function tempnam($filePrefix)
 161   * 3000:     function stdAuthCode($uid_or_record,$fields='')
 162   * 3030:     function cHashParams($addQueryParams)
 163   * 3059:     function loadTCA($table)
 164   * 3079:     function resolveSheetDefInDS($dataStructArray,$sheet='sDEF')
 165   * 3109:     function resolveAllSheetsInDS($dataStructArray)
 166   * 3138:     function callUserFunction($funcName,&$params,&$ref,$checkPrefix='user_',$silent=0)
 167   * 3237:     function &getUserObj($classRef,$checkPrefix='user_',$silent=0)
 168   * 3295:     function &makeInstance($className)
 169   * 3307:     function makeInstanceClassName($className)
 170   * 3321:     function &makeInstanceService($serviceType, $serviceSubType='', $excludeServiceKeys=array())
 171   * 3382:     function plainMailEncoded($email,$subject,$message,$headers='',$enc='',$charset='ISO-8859-1',$dontEncodeSubject=0)
 172   * 3427:     function quoted_printable($string,$maxlen=76)
 173   * 3471:     function substUrlsInPlainText($message,$urlmode='76',$index_script_url='')
 174   * 3505:     function makeRedirectUrl($inUrl,$l=0,$index_script_url='')
 175   * 3532:     function freetypeDpiComp($font_size)
 176   * 3551:     function devLog($msg, $extKey, $severity=0, $dataVar=FALSE)
 177   * 3572:     function arrayToLogString($arr, $valueList=array(), $valueLength=20)
 178   *
 179   * TOTAL FUNCTIONS: 117
 180   * (This index is automatically created/updated by the extension "extdeveval")
 181   *
 182   */
 183  
 184  
 185  
 186  
 187  
 188  
 189  
 190  
 191  
 192  
 193  
 194  
 195  /**
 196   * The legendary "t3lib_div" class - Miscellaneous functions for general purpose.
 197   * Most of the functions does not relate specifically to TYPO3
 198   * However a section of functions requires certain TYPO3 features available
 199   * See comments in the source.
 200   * You are encouraged to use this library in your own scripts!
 201   *
 202   * USE:
 203   * The class is intended to be used without creating an instance of it.
 204   * So: Don't instantiate - call functions with "t3lib_div::" prefixed the function name.
 205   * So use t3lib_div::[method-name] to refer to the functions, eg. 't3lib_div::milliseconds()'
 206   *
 207   * @author    Kasper Skaarhoj <kasperYYYY@typo3.com>
 208   * @package TYPO3
 209   * @subpackage t3lib
 210   */
 211  class t3lib_div {
 212  
 213  
 214  
 215  
 216  
 217      /*************************
 218       *
 219       * GET/POST Variables
 220       *
 221       * Background:
 222       * Input GET/POST variables in PHP may have their quotes escaped with "\" or not depending on configuration.
 223       * TYPO3 has always converted quotes to BE escaped if the configuration told that they would not be so.
 224       * But the clean solution is that quotes are never escaped and that is what the functions below offers.
 225       * Eventually TYPO3 should provide this in the global space as well.
 226       * In the transitional phase (or forever..?) we need to encourage EVERY to read and write GET/POST vars through the API functions below.
 227       *
 228       *************************/
 229  
 230      /**
 231       * Returns the 'GLOBAL' value of incoming data from POST or GET, with priority to POST (that is equalent to 'GP' order)
 232       * Strips slashes from all output, both strings and arrays.
 233       * This function substitutes t3lib_div::GPvar()
 234       * 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!
 235       * Usage: 537
 236       *
 237       * @param    string        GET/POST var to return
 238       * @return    mixed        POST var named $var and if not set, the GET var of the same name.
 239       * @see GPvar()
 240       */
 241  	function _GP($var)    {
 242          if(empty($var)) return;
 243          $value = isset($_POST[$var]) ? $_POST[$var] : $_GET[$var];
 244          if (isset($value))    {
 245              if (is_array($value))    { t3lib_div::stripSlashesOnArray($value); } else { $value = stripslashes($value); }
 246          }
 247          return $value;
 248      }
 249  
 250      /**
 251       * Returns the global GET array (or value from) normalized to contain un-escaped values.
 252       * ALWAYS use this API function to acquire the GET variables!
 253       * Usage: 27
 254       *
 255       * @param    string        Optional pointer to value in GET array (basically name of GET var)
 256       * @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!*
 257       * @see _POST(), _GP(), _GETset()
 258       */
 259  	function _GET($var=NULL)    {
 260          $value = ($var === NULL) ? $_GET : (empty($var) ? NULL : $_GET[$var]);
 261          if (isset($value))    {    // Removes slashes since TYPO3 has added them regardless of magic_quotes setting.
 262              if (is_array($value))    { t3lib_div::stripSlashesOnArray($value); } else { $value = stripslashes($value); }
 263          }
 264          return $value;
 265      }
 266  
 267      /**
 268       * Returns the global POST array (or value from) normalized to contain un-escaped values.
 269       * ALWAYS use this API function to acquire the POST variables!
 270       * Usage: 41
 271       *
 272       * @param    string        Optional pointer to value in POST array (basically name of POST var)
 273       * @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!*
 274       * @see _GET(), _GP()
 275       */
 276  	function _POST($var=NULL)    {
 277          $value = ($var === NULL) ? $_POST : (empty($var) ? NULL : $_POST[$var]);
 278          if (isset($value))    {    // Removes slashes since TYPO3 has added them regardless of magic_quotes setting.
 279              if (is_array($value))    { t3lib_div::stripSlashesOnArray($value); } else { $value = stripslashes($value); }
 280          }
 281          return $value;
 282      }
 283  
 284      /**
 285       * Writes input value to $_GET
 286       * Usage: 2
 287       *
 288       * @param    array        Array to write to $_GET. Values should NOT be escaped at input time (but will be escaped before writing according to TYPO3 standards).
 289       * @param    string        Alternative key; If set, this will not set the WHOLE GET array, but only the key in it specified by this value!
 290       * @return    void
 291       */
 292  	function _GETset($inputGet,$key='')    {
 293              // ADDS slashes since TYPO3 standard currently is that slashes MUST be applied (regardless of magic_quotes setting).
 294          if (strcmp($key,''))    {
 295              if (is_array($inputGet))    { t3lib_div::addSlashesOnArray($inputGet); } else { $inputGet = addslashes($inputGet); }
 296              $GLOBALS['HTTP_GET_VARS'][$key] = $_GET[$key] = $inputGet;
 297          } elseif (is_array($inputGet)){
 298              t3lib_div::addSlashesOnArray($inputGet);
 299              $GLOBALS['HTTP_GET_VARS'] = $_GET = $inputGet;
 300          }
 301      }
 302  
 303      /**
 304       * GET/POST variable
 305       * Returns the 'GLOBAL' value of incoming data from POST or GET, with priority to POST (that is equalent to 'GP' order)
 306       * Strips slashes of string-outputs, but not arrays UNLESS $strip is set. If $strip is set all output will have escaped characters unescaped.
 307       * Usage: 2
 308       *
 309       * @param    string        GET/POST var to return
 310       * @param    boolean        If set, values are stripped of return values that are *arrays!* - string/integer values returned are always strip-slashed()
 311       * @return    mixed        POST var named $var and if not set, the GET var of the same name.
 312       * @deprecated        Use t3lib_div::_GP instead (ALWAYS delivers a value with un-escaped values!)
 313       * @see _GP()
 314       */
 315  	function GPvar($var,$strip=0)    {
 316          if(empty($var)) return;
 317          $value = isset($_POST[$var]) ? $_POST[$var] : $_GET[$var];
 318          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.
 319          if ($strip && isset($value) && is_array($value)) { t3lib_div::stripSlashesOnArray($value); }
 320          return $value;
 321      }
 322  
 323      /**
 324       * Returns the GET/POST global arrays merged with POST taking precedence.
 325       * Usage: 1
 326       *
 327       * @param    string        Key (variable name) from GET or POST vars
 328       * @return    array        Returns the GET vars merged recursively onto the POST vars.
 329       * @ignore
 330       * @deprecated
 331       */
 332  	function GParrayMerged($var)    {
 333          $postA = is_array($_POST[$var]) ? $_POST[$var] : array();
 334          $getA = is_array($_GET[$var]) ? $_GET[$var] : array();
 335          $mergedA = t3lib_div::array_merge_recursive_overrule($getA,$postA);
 336          t3lib_div::stripSlashesOnArray($mergedA);
 337          return $mergedA;
 338      }
 339  
 340  
 341  
 342  
 343  
 344  
 345  
 346  
 347  
 348  
 349      /*************************
 350       *
 351       * IMAGE FUNCTIONS
 352       *
 353       *************************/
 354  
 355  
 356      /**
 357       * Compressing a GIF file if not already LZW compressed
 358       * 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)
 359       *
 360       *         The function takes a file-reference, $theFile, and saves it again through GD or ImageMagick in order to compress the file
 361       *         GIF:
 362       *         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!)
 363       *         If $type is set to either 'IM' or 'GD' the compression is done with ImageMagick and GD respectively
 364       *         PNG:
 365       *         No changes.
 366       *
 367       *         $theFile is expected to be a valid GIF-file!
 368       *         The function returns a code for the operation.
 369       * Usage: 9
 370       *
 371       * @param    string        Filepath
 372       * @param    string        See description of function
 373       * @return    string        Returns "GD" if GD was used, otherwise "IM" if ImageMagick was used. If nothing done at all, it returns empty string.
 374       * @internal
 375       */
 376  	function gif_compress($theFile, $type)    {
 377          $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
 378          $returnCode='';
 379          if ($gfxConf['gif_compress'] && strtolower(substr($theFile,-4,4))=='.gif')    {    // GIF...
 380              if (($type=='IM' || !$type) && $gfxConf['im'] && $gfxConf['im_path_lzw'])    {    // IM
 381                  $cmd = t3lib_div::imageMagickCommand('convert', '"'.$theFile.'" "'.$theFile.'"', $gfxConf['im_path_lzw']);
 382                  exec($cmd);
 383  
 384                  $returnCode='IM';
 385              } elseif (($type=='GD' || !$type) && $gfxConf['gdlib'] && !$gfxConf['gdlib_png'])    {    // GD
 386                  $tempImage = imageCreateFromGif($theFile);
 387                  imageGif($tempImage, $theFile);
 388                  imageDestroy($tempImage);
 389                  $returnCode='GD';
 390              }
 391          }
 392          return $returnCode;
 393      }
 394  
 395      /**
 396       * Converts a png file to gif
 397       * This converts a png file to gif IF the FLAG $GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif'] is set true.
 398       * Usage: 5
 399       *
 400       * @param    string        $theFile    the filename with path
 401       * @return    string        new filename
 402       * @internal
 403       */
 404  	function png_to_gif_by_imagemagick($theFile)    {
 405          if ($GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif']
 406              && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im']
 407              && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']
 408              && strtolower(substr($theFile,-4,4))=='.png'
 409              && @is_file($theFile))    {    // IM
 410                  $newFile = substr($theFile,0,-4).'.gif';
 411                  $cmd = t3lib_div::imageMagickCommand('convert', '"'.$theFile.'" "'.$newFile.'"', $gfxConf['im_path_lzw']);
 412                  exec($cmd);
 413                  $theFile = $newFile;
 414                      // 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!!
 415          }
 416          return $theFile;
 417      }
 418  
 419      /**
 420       * Returns filename of the png/gif version of the input file (which can be png or gif).
 421       * If input file type does not match the wanted output type a conversion is made and temp-filename returned.
 422       * Usage: 2
 423       *
 424       * @param    string        Filepath of image file
 425       * @param    boolean        If set, then input file is converted to PNG, otherwise to GIF
 426       * @return    string        If the new image file exists, it's filepath is returned
 427       * @internal
 428       */
 429  	function read_png_gif($theFile,$output_png=0)    {
 430          if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] && @is_file($theFile))    {
 431              $ext = strtolower(substr($theFile,-4,4));
 432              if (
 433                      ((string)$ext=='.png' && $output_png)    ||
 434                      ((string)$ext=='.gif' && !$output_png)
 435                  )    {
 436                  return $theFile;
 437              } else {
 438                  $newFile = PATH_site.'typo3temp/readPG_'.md5($theFile.'|'.filemtime($theFile)).($output_png?'.png':'.gif');
 439                  exec($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path'].'convert "'.$theFile.'" "'.$newFile.'"');
 440                  if (@is_file($newFile))    return $newFile;
 441              }
 442          }
 443      }
 444  
 445  
 446  
 447  
 448  
 449  
 450  
 451  
 452  
 453  
 454  
 455  
 456  
 457  
 458  
 459      /*************************
 460       *
 461       * STRING FUNCTIONS
 462       *
 463       *************************/
 464  
 465      /**
 466       * Truncate string
 467       * Returns a new string of max. $chars length.
 468       * If the string is longer, it will be truncated and appended with '...'.
 469       * DEPRECIATED. Works ONLY for single-byte charsets! USE t3lib_div::fixed_lgd_cs() instead
 470       * Usage: 39
 471       *
 472       * @param    string        $string     string to truncate
 473       * @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.
 474       * @param    string        String to append to the output if it is truncated, default is '...'
 475       * @return    string        new string
 476       * @see fixed_lgd_pre()
 477       */
 478  	function fixed_lgd($string,$origChars,$preStr='...')    {
 479          $chars = abs($origChars);
 480          if ($chars >= 4)    {
 481              if(strlen($string)>$chars)  {
 482                  return $origChars < 0 ?
 483                      $preStr.trim(substr($string, -($chars-3))) :
 484                      trim(substr($string, 0, $chars-3)).$preStr;
 485              }
 486          }
 487          return $string;
 488      }
 489  
 490      /**
 491       * Truncate string
 492       * Returns a new string of max. $chars length.
 493       * If the string is longer, it will be truncated and prepended with '...'.
 494       * This works like fixed_lgd, but is truncated in the start of the string instead of the end
 495       * DEPRECIATED. Use either fixed_lgd() or fixed_lgd_cs() (with negative input value for $chars)
 496       * Usage: 6
 497       *
 498       * @param    string        $string     string to truncate
 499       * @param    integer        $chars     must be an integer of at least 4
 500       * @return    string        new string
 501       * @see fixed_lgd()
 502       */
 503  	function fixed_lgd_pre($string,$chars)    {
 504          return strrev(t3lib_div::fixed_lgd(strrev($string),$chars));
 505      }
 506  
 507      /**
 508       * Truncates a string with appended/prepended "..." and takes backend character set into consideration
 509       * Use only from backend!
 510       * Usage: 75
 511       *
 512       * @param    string        $string     string to truncate
 513       * @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.
 514       * @return    string        New string
 515       * @see fixed_lgd()
 516       */
 517  	function fixed_lgd_cs($string,$chars)    {
 518          if (is_object($GLOBALS['LANG']))    {
 519              return $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet,$string,$chars,'...');
 520          } else {
 521              return t3lib_div::fixed_lgd($string, $chars);
 522          }
 523      }
 524  
 525      /**
 526       * Breaks up the text for emails
 527       * Usage: 1
 528       *
 529       * @param    string        The string to break up
 530       * @param    string        The string to implode the broken lines with (default/typically \n)
 531       * @param    integer        The line length
 532       * @return    string
 533       */
 534  	function breakTextForEmail($str,$implChar="\n",$charWidth=76)    {
 535          $lines = explode(chr(10),$str);
 536          $outArr=array();
 537          while(list(,$lStr)=each($lines))    {
 538              $outArr = array_merge($outArr,t3lib_div::breakLinesForEmail($lStr,$implChar,$charWidth));
 539          }
 540          return implode(chr(10),$outArr);
 541      }
 542  
 543      /**
 544       * Breaks up a single line of text for emails
 545       * Usage: 5
 546       *
 547       * @param    string        The string to break up
 548       * @param    string        The string to implode the broken lines with (default/typically \n)
 549       * @param    integer        The line length
 550       * @return    string
 551       * @see breakTextForEmail()
 552       */
 553  	function breakLinesForEmail($str,$implChar="\n",$charWidth=76)    {
 554          $lines=array();
 555          $l=$charWidth;
 556          $p=0;
 557          while(strlen($str)>$p)    {
 558              $substr=substr($str,$p,$l);
 559              if (strlen($substr)==$l)    {
 560                  $count = count(explode(' ',trim(strrev($substr))));
 561                  if ($count>1)    {    // OK...
 562                      $parts = explode(' ',strrev($substr),2);
 563                      $theLine = strrev($parts[1]);
 564                  } else {
 565                      $afterParts = explode(' ',substr($str,$l+$p),2);
 566                      $theLine = $substr.$afterParts[0];
 567                  }
 568                  if (!strlen($theLine))    {break; }    // Error, because this would keep us in an endless loop.
 569              } else {
 570                  $theLine=$substr;
 571              }
 572  
 573              $lines[]=trim($theLine);
 574              $p+=strlen($theLine);
 575              if (!trim(substr($str,$p,$l)))    break;    // added...
 576          }
 577          return implode($implChar,$lines);
 578      }
 579  
 580      /**
 581       * Match IP number with list of numbers with wildcard
 582       * Usage: 10
 583       *
 584       * @param    string        $baseIP is the current remote IP address for instance, typ. REMOTE_ADDR
 585       * @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)
 586       * @return    boolean        True if an IP-mask from $list matches $baseIP
 587       */
 588  	function cmpIP($baseIP, $list)    {
 589          $IPpartsReq = explode('.',$baseIP);
 590          if (count($IPpartsReq)==4)    {
 591              $values = t3lib_div::trimExplode(',',$list,1);
 592  
 593              foreach($values as $test)    {
 594                  list($test,$mask) = explode('/',$test);
 595  
 596                  if(intval($mask)) {
 597                          // "192.168.3.0/24"
 598                      $lnet = ip2long($test);
 599                      $lip = ip2long($baseIP);
 600                      $binnet = str_pad( decbin($lnet),32,'0','STR_PAD_LEFT');
 601                      $firstpart = substr($binnet,0,$mask);
 602                      $binip = str_pad( decbin($lip),32,'0','STR_PAD_LEFT');
 603                      $firstip = substr($binip,0,$mask);
 604                      $yes = (strcmp($firstpart,$firstip)==0);
 605                  } else {
 606                          // "192.168.*.*"
 607                      $IPparts = explode('.',$test);
 608                      $yes = 1;
 609                      reset($IPparts);
 610                      while(list($index,$val)=each($IPparts))    {
 611                          $val = trim($val);
 612                          if (strcmp($val,'*') && strcmp($IPpartsReq[$index],$val))    {
 613                              $yes=0;
 614                          }
 615                      }
 616                  }
 617                  if ($yes) return true;
 618              }
 619          }
 620          return false;
 621      }
 622  
 623      /**
 624       * Match fully qualified domain name with list of strings with wildcard
 625       *
 626       * @param    string        $baseIP is the current remote IP address for instance, typ. REMOTE_ADDR
 627       * @param    string        $list is 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)
 628       * @return    boolean        True if a domain name mask from $list matches $baseIP
 629       */
 630  	function cmpFQDN($baseIP, $list)        {
 631          if (count(explode('.',$baseIP))==4)     {
 632              $resolvedHostName = explode('.', gethostbyaddr($baseIP));
 633              $values = t3lib_div::trimExplode(',',$list,1);
 634  
 635              foreach($values as $test)    {
 636                  $hostNameParts = explode('.',$test);
 637                  $yes = 1;
 638  
 639                  foreach($hostNameParts as $index => $val)    {
 640                      $val = trim($val);
 641                      if (strcmp($val,'*') && strcmp($resolvedHostName[$index],$val)) {
 642                          $yes=0;
 643                      }
 644                  }
 645                  if ($yes) return true;
 646              }
 647          }
 648          return false;
 649      }
 650  
 651      /**
 652       * Check for item in list
 653       * Check if an item exists in a comma-separated list of items.
 654       * Usage: 163
 655       *
 656       * @param    string        comma-separated list of items (string)
 657       * @param    string        item to check for
 658       * @return    boolean        true if $item is in $list
 659       */
 660  	function inList($list,$item)    {
 661          return strstr(','.$list.',', ','.$item.',') ? true : false;
 662      }
 663  
 664      /**
 665       * Removes an item from a comma-separated list of items.
 666       * Usage: 1
 667       *
 668       * @param    string        $element      element to remove
 669       * @param    string        $list     comma-separated list of items (string)
 670       * @return    string        new comma-separated list of items
 671       */
 672  	function rmFromList($element,$list)    {
 673          $items = explode(',',$list);
 674          while(list($k,$v)=each($items))    {
 675              if ($v==$element)    {unset($items[$k]);}
 676          }
 677          return implode(',',$items);
 678      }
 679  
 680      /**
 681       * Expand a comma-separated list of integers with ranges (eg 1,3-5,7 becomes 1,3,4,5,7).
 682       * Ranges are limited to 1000 values per range.
 683       *
 684       * @param    string        $list     comma-separated list of integers with ranges (string)
 685       * @return    string        new comma-separated list of items
 686       * @author    Martin Kutschker <martin.kutschker@activesolution.at>
 687       */
 688  	function expandList($list)      {
 689          $items = explode(',',$list);
 690          $list = array();
 691          while(list(,$item)=each($items))    {
 692              $range = explode('-',$item);
 693              if (isset($range[1]))    {
 694                  $runAwayBrake = 1000;
 695                  for ($n=$range[0]; $n<=$range[1]; $n++)    {
 696                      $list[] = $n;
 697  
 698                      $runAwayBrake--;
 699                      if ($runAwayBrake<=0)    break;
 700                  }
 701              } else {
 702                  $list[] = $item;
 703              }
 704          }
 705  
 706          return implode(',',$list);
 707      }
 708  
 709      /**
 710       * Forces the integer $theInt into the boundaries of $min and $max. If the $theInt is 'false' then the $zeroValue is applied.
 711       * Usage: 224
 712       *
 713       * @param    integer        Input value
 714       * @param    integer        Lower limit
 715       * @param    integer        Higher limit
 716       * @param    integer        Default value if input is false.
 717       * @return    integer        The input value forced into the boundaries of $min and $max
 718       */
 719  	function intInRange($theInt,$min,$max=2000000000,$zeroValue=0)    {
 720          // Returns $theInt as an integer in the integerspace from $min to $max
 721          $theInt = intval($theInt);
 722          if ($zeroValue && !$theInt)    {$theInt=$zeroValue;}    // If the input value is zero after being converted to integer, zeroValue may set another default value for it.
 723          if ($theInt<$min){$theInt=$min;}
 724          if ($theInt>$max){$theInt=$max;}
 725          return $theInt;
 726      }
 727  
 728      /**
 729       * Returns the $integer if greater than zero, otherwise returns zero.
 730       * Usage: 1
 731       *
 732       * @param    integer        Integer string to process
 733       * @return    integer
 734       */
 735  	function intval_positive($theInt)    {
 736          $theInt = intval($theInt);
 737          if ($theInt<0){$theInt=0;}
 738          return $theInt;
 739      }
 740  
 741      /**
 742       * Returns an integer from a three part version number, eg '4.12.3' -> 4012003
 743       * Usage: 2
 744       *
 745       * @param    string        Version number on format x.x.x
 746       * @return    integer        Integer version of version number (where each part can count to 999)
 747       */
 748  	function int_from_ver($verNumberStr)    {
 749          $verParts = explode('.',$verNumberStr);
 750          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));
 751      }
 752  
 753      /**
 754       * Makes a positive integer hash out of the first 7 chars from the md5 hash of the input
 755       * Usage: 5
 756       *
 757       * @param    string        String to md5-hash
 758       * @return    integer        Returns 28bit integer-hash
 759       */
 760  	function md5int($str)    {
 761          return hexdec(substr(md5($str),0,7));
 762      }
 763  
 764      /**
 765       * Returns the first 10 positions of the MD5-hash        (changed from 6 to 10 recently)
 766       *
 767       * Usage: 37
 768       *
 769       * @param    string        Input string to be md5-hashed
 770       * @param    integer        The string-length of the output
 771       * @return    string        Substring of the resulting md5-hash, being $len chars long (from beginning)
 772       */
 773  	function shortMD5($input, $len=10)    {
 774          return substr(md5($input),0,$len);
 775      }
 776  
 777      /**
 778       * Takes comma-separated lists and arrays and removes all duplicates
 779       * If a value in the list is trim(empty), the value is ignored.
 780       * Usage: 16
 781       *
 782       * @param    string        Accept multiple parameters wich can be comma-separated lists of values and arrays.
 783       * @param    mixed        $secondParameter: Dummy field, which is set will show a warning!
 784       * @return    string        Returns the list without any duplicates of values, space around values are trimmed
 785       */
 786  	function uniqueList($in_list, $secondParameter=NULL)    {
 787          if (is_array($in_list))    die('t3lib_div::uniqueList() does NOT support array arguments anymore! Only string comma lists!');
 788          if (isset($secondParameter))    die('t3lib_div::uniqueList() does NOT support more than a single argument value anymore. You have specified more than one.');
 789  
 790          return implode(',',array_unique(t3lib_div::trimExplode(',',$in_list,1)));
 791      }
 792  
 793      /**
 794       * Splits a reference to a file in 5 parts
 795       * Usage: 43
 796       *
 797       * @param    string        Filename/filepath to be analysed
 798       * @return    array        Contains keys [path], [file], [filebody], [fileext], [realFileext]
 799       */
 800  	function split_fileref($fileref)    {
 801          if (    ereg('(.*/)(.*)$',$fileref,$reg)    )    {
 802              $info['path'] = $reg[1];
 803              $info['file'] = $reg[2];
 804          } else {
 805              $info['path'] = '';
 806              $info['file'] = $fileref;
 807          }
 808          $reg='';
 809          if (    ereg('(.*)\.([^\.]*$)',$info['file'],$reg)    )    {
 810              $info['filebody'] = $reg[1];
 811              $info['fileext'] = strtolower($reg[2]);
 812              $info['realFileext'] = $reg[2];
 813          } else {
 814              $info['filebody'] = $info['file'];
 815              $info['fileext'] = '';
 816          }
 817          reset($info);
 818          return $info;
 819      }
 820  
 821      /**
 822       * Returns the directory part of a path without trailing slash
 823       * If there is no dir-part, then an empty string is returned.
 824       * Behaviour:
 825       *
 826       * '/dir1/dir2/script.php' => '/dir1/dir2'
 827       * '/dir1/' => '/dir1'
 828       * 'dir1/script.php' => 'dir1'
 829       * 'd/script.php' => 'd'
 830       * '/script.php' => ''
 831       * '' => ''
 832       * Usage: 5
 833       *
 834       * @param    string        Directory name / path
 835       * @return    string        Processed input value. See function description.
 836       */
 837  	function dirname($path)    {
 838          $p=t3lib_div::revExplode('/',$path,2);
 839          return count($p)==2?$p[0]:'';
 840      }
 841  
 842      /**
 843       * Modifies a HTML Hex color by adding/subtracting $R,$G and $B integers
 844       * Usage: 11
 845       *
 846       * @param    string        A hexadecimal color code, #xxxxxx
 847       * @param    integer        Offset value 0-255
 848       * @param    integer        Offset value 0-255
 849       * @param    integer        Offset value 0-255
 850       * @return    string        A hexadecimal color code, #xxxxxx, modified according to input vars
 851       * @see modifyHTMLColorAll()
 852       */
 853  	function modifyHTMLColor($color,$R,$G,$B)    {
 854          // This takes a hex-color (# included!) and adds $R, $G and $B to the HTML-color (format: #xxxxxx) and returns the new color
 855          $nR = t3lib_div::intInRange(hexdec(substr($color,1,2))+$R,0,255);
 856          $nG = t3lib_div::intInRange(hexdec(substr($color,3,2))+$G,0,255);
 857          $nB = t3lib_div::intInRange(hexdec(substr($color,5,2))+$B,0,255);
 858          return '#'.
 859              substr('0'.dechex($nR),-2).
 860              substr('0'.dechex($nG),-2).
 861              substr('0'.dechex($nB),-2);
 862      }
 863  
 864      /**
 865       * Modifies a HTML Hex color by adding/subtracting $all integer from all R/G/B channels
 866       * Usage: 6
 867       *
 868       * @param    string        A hexadecimal color code, #xxxxxx
 869       * @param    integer        Offset value 0-255 for all three channels.
 870       * @return    string        A hexadecimal color code, #xxxxxx, modified according to input vars
 871       * @see modifyHTMLColor()
 872       */
 873  	function modifyHTMLColorAll($color,$all)    {
 874          return t3lib_div::modifyHTMLColor($color,$all,$all,$all);
 875      }
 876  
 877      /**
 878       * Removes comma (if present) in the end of string
 879       * Usage: 2
 880       *
 881       * @param    string        String from which the comma in the end (if any) will be removed.
 882       * @return    string
 883       */
 884  	function rm_endcomma($string)    {
 885          return ereg_replace(',$','',$string);
 886      }
 887  
 888      /**
 889       * strtoupper which converts danish (and other characters) characters as well
 890       * (DEPRECIATED, use t3lib_cs::conv_case() instead or for HTML output, wrap your content in <span class="uppercase">...</span>)
 891       * Usage: 0
 892       *
 893       * @param    string        String to process
 894       * @return    string
 895       * @ignore
 896       */
 897  	function danish_strtoupper($string)    {
 898          $value = strtoupper($string);
 899          return strtr($value, 'áéúíâêûôîæøåäöü', 'ÁÉÚÍÄËÜÖÏÆØÅÄÖÜ');
 900      }
 901  
 902      /**
 903       * Change umlaut characters to plain ASCII with normally two character target
 904       * Only known characters will be converted, so don't expect a result for any character.
 905       * (DEPRECIATED: Works only for western europe single-byte charsets! Use t3lib_cs::specCharsToASCII() instead!)
 906       *
 907       * ä => ae, Ö => Oe
 908       *
 909       * @param    string        String to convert.
 910       * @return    string
 911       */
 912  	function convUmlauts($str)    {
 913          $pat  = array (    '/ä/',    '/Ä/',    '/ö/',    '/Ö/',    '/ü/',    '/Ü/',    '/ß/',    '/å/',    '/Å/',    '/ø/',    '/Ø/',    '/æ/',    '/Æ/'    );
 914          $repl = array (    'ae',    'Ae',    'oe',    'Oe',    'ue',    'Ue',    'ss',    'aa',    'AA',    'oe',    'OE',    'ae',    'AE'    );
 915          return preg_replace($pat,$repl,$str);
 916      }
 917  
 918      /**
 919       * Tests if the input is an integer.
 920       * Usage: 77
 921       *
 922       * @param    mixed        Any input variable to test.
 923       * @return    boolean        Returns true if string is an integer
 924       */
 925  	function testInt($var)    {
 926          return !strcmp($var,intval($var));
 927      }
 928  
 929      /**
 930       * Returns true if the first part of $str matches the string $partStr
 931       * Usage: 59
 932       *
 933       * @param    string        Full string to check
 934       * @param    string        Reference string which must be found as the "first part" of the full string
 935       * @return    boolean        True if $partStr was found to be equal to the first part of $str
 936       */
 937  	function isFirstPartOfStr($str,$partStr)    {
 938          // Returns true, if the first part of a $str equals $partStr and $partStr is not ''
 939          $psLen = strlen($partStr);
 940          if ($psLen)    {
 941              return substr($str,0,$psLen)==(string)$partStr;
 942          } else return false;
 943      }
 944  
 945      /**
 946       * Formats the input integer $sizeInBytes as bytes/kilobytes/megabytes (-/K/M)
 947       * Usage: 53
 948       *
 949       * @param    integer        Number of bytes to format.
 950       * @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)
 951       * @return    string        Formatted representation of the byte number, for output.
 952       */
 953  	function formatSize($sizeInBytes,$labels='')    {
 954  
 955              // Set labels:
 956          if (strlen($labels) == 0) {
 957              $labels = ' | K| M| G';
 958          } else {
 959              $labels = str_replace('"','',$labels);
 960          }
 961          $labelArr = explode('|',$labels);
 962  
 963              // Find size:
 964          if ($sizeInBytes>900)    {
 965              if ($sizeInBytes>900000000)    {    // GB
 966                  $val = $sizeInBytes/(1024*1024*1024);
 967                  return number_format($val, (($val<20)?1:0), '.', '').$labelArr[3];
 968              }
 969              elseif ($sizeInBytes>900000)    {    // MB
 970                  $val = $sizeInBytes/(1024*1024);
 971                  return number_format($val, (($val<20)?1:0), '.', '').$labelArr[2];
 972              } else {    // KB
 973                  $val = $sizeInBytes/(1024);
 974                  return number_format($val, (($val<20)?1:0), '.', '').$labelArr[1];
 975              }
 976          } else {    // Bytes
 977              return $sizeInBytes.$labelArr[0];
 978          }
 979      }
 980  
 981      /**
 982       * Returns microtime input to milliseconds
 983       * Usage: 2
 984       *
 985       * @param    string        Microtime
 986       * @return    integer        Microtime input string converted to an integer (milliseconds)
 987       */
 988  	function convertMicrotime($microtime)    {
 989          $parts = explode(' ',$microtime);
 990          return round(($parts[0]+$parts[1])*1000);
 991      }
 992  
 993      /**
 994       * This splits a string by the chars in $operators (typical /+-*) and returns an array with them in
 995       * Usage: 2
 996       *
 997       * @param    string        Input string, eg "123 + 456 / 789 - 4"
 998       * @param    string        Operators to split by, typically "/+-*"
 999       * @return    array        Array with operators and operands separated.
1000       * @see tslib_cObj::calc(), tslib_gifBuilder::calcOffset()
1001       */
1002  	function splitCalc($string,$operators)    {
1003          $res = Array();
1004          $sign='+';
1005          while($string)    {
1006              $valueLen=strcspn($string,$operators);
1007              $value=substr($string,0,$valueLen);
1008              $res[] = Array($sign,trim($value));
1009              $sign=substr($string,$valueLen,1);
1010              $string=substr($string,$valueLen+1);
1011          }
1012          reset($res);
1013          return $res;
1014      }
1015  
1016      /**
1017       * Calculates the input by +,-,*,/,%,^ with priority to + and -
1018       * Usage: 1
1019       *
1020       * @param    string        Input string, eg "123 + 456 / 789 - 4"
1021       * @return    integer        Calculated value. Or error string.
1022       * @see calcParenthesis()
1023       */
1024  	function calcPriority($string)    {
1025          $string=ereg_replace('[[:space:]]*','',$string);    // removing all whitespace
1026          $string='+'.$string;    // Ensuring an operator for the first entrance
1027          $qm='\*\/\+-^%';
1028          $regex = '(['.$qm.'])(['.$qm.']?[0-9\.]*)';
1029              // split the expression here:
1030          preg_match_all('/'.$regex.'/',$string,$reg);
1031  
1032          reset($reg[2]);
1033          $number=0;
1034          $Msign='+';
1035          $err='';
1036          $buffer=doubleval(current($reg[2]));
1037          next($reg[2]);    // Advance pointer
1038          while(list($k,$v)=each($reg[2]))    {
1039              $v=doubleval($v);
1040              $sign = $reg[1][$k];
1041              if ($sign=='+' || $sign=='-')    {
1042                  $number = $Msign=='-' ? $number-=$buffer : $number+=$buffer;
1043                  $Msign = $sign;
1044                  $buffer=$v;
1045              } else {
1046                  if ($sign=='/')    {if ($v) $buffer/=$v; else $err='dividing by zero';}
1047                  if ($sign=='%')    {if ($v) $buffer%=$v; else $err='dividing by zero';}
1048                  if ($sign=='*')    {$buffer*=$v;}
1049                  if ($sign=='^')    {$buffer=pow($buffer,$v);}
1050              }
1051          }
1052          $number = $Msign=='-' ? $number-=$buffer : $number+=$buffer;
1053          return $err ? 'ERROR: '.$err : $number;
1054      }
1055  
1056      /**
1057       * Calculates the input with parenthesis levels
1058       * Usage: 2
1059       *
1060       * @param    string        Input string, eg "(123 + 456) / 789 - 4"
1061       * @return    integer        Calculated value. Or error string.
1062       * @see calcPriority(), tslib_cObj::stdWrap()
1063       */
1064  	function calcParenthesis($string)    {
1065          $securC=100;
1066          do {
1067              $valueLenO=strcspn($string,'(');
1068              $valueLenC=strcspn($string,')');
1069              if ($valueLenC==strlen($string) || $valueLenC < $valueLenO)    {
1070                  $value = t3lib_div::calcPriority(substr($string,0,$valueLenC));
1071                  $string = $value.substr($string,$valueLenC+1);
1072                  return $string;
1073              } else {
1074                  $string = substr($string,0,$valueLenO).t3lib_div::calcParenthesis(substr($string,$valueLenO+1));
1075              }
1076                  // Security:
1077              $securC--;
1078              if ($securC<=0)    break;
1079          } while($valueLenO<strlen($string));
1080          return $string;
1081      }
1082  
1083      /**
1084       * Inverse version of htmlspecialchars()
1085       * Usage: 4
1086       *
1087       * @param    string        Value where &gt;, &lt;, &quot; and &amp; should be converted to regular chars.
1088       * @return    string        Converted result.
1089       */
1090  	function htmlspecialchars_decode($value)    {
1091          $value = str_replace('&gt;','>',$value);
1092          $value = str_replace('&lt;','<',$value);
1093          $value = str_replace('&quot;','"',$value);
1094          $value = str_replace('&amp;','&',$value);
1095          return $value;
1096      }
1097  
1098      /**
1099       * Re-converts HTML entities if they have been converted by htmlspecialchars()
1100       * Usage: 10
1101       *
1102       * @param    string        String which contains eg. "&amp;amp;" which should stay "&amp;". Or "&amp;#1234;" to "&#1234;". Or "&amp;#x1b;" to "&#x1b;"
1103       * @return    string        Converted result.
1104       */
1105  	function deHSCentities($str)    {
1106          return ereg_replace('&amp;([#[:alnum:]]*;)','&\1',$str);
1107      }
1108  
1109      /**
1110       * This function is used to escape any ' -characters when transferring text to JavaScript!
1111       * Usage: 3
1112       *
1113       * @param    string        String to escape
1114       * @param    boolean        If set, also backslashes are escaped.
1115       * @param    string        The character to escape, default is ' (single-quote)
1116       * @return    string        Processed input string
1117       */
1118  	function slashJS($string,$extended=0,$char="'")    {
1119          if ($extended)    {$string = str_replace ("\\", "\\\\", $string);}
1120          return str_replace ($char, "\\".$char, $string);
1121      }
1122  
1123      /**
1124       * Version of rawurlencode() where all spaces (%20) are re-converted to space-characters.
1125       * Usefull when passing text to JavaScript where you simply url-encode it to get around problems with syntax-errors, linebreaks etc.
1126       * Usage: 4
1127       *
1128       * @param    string        String to raw-url-encode with spaces preserved
1129       * @return    string        Rawurlencoded result of input string, but with all %20 (space chars) converted to real spaces.
1130       */
1131  	function rawUrlEncodeJS($str)    {
1132          return str_replace('%20',' ',rawurlencode($str));
1133      }
1134  
1135      /**
1136       * rawurlencode which preserves "/" chars
1137       * Usefull when filepaths should keep the "/" chars, but have all other special chars encoded.
1138       * Usage: 5
1139       *
1140       * @param    string        Input string
1141       * @return    string        Output string
1142       */
1143  	function rawUrlEncodeFP($str)    {
1144          return str_replace('%2F','/',rawurlencode($str));
1145      }
1146  
1147      /**
1148       * Checking syntax of input email address
1149       * Usage: 5
1150       *
1151       * @param    string        Input string to evaluate
1152       * @return    boolean        Returns true if the $email address (input string) is valid; Has a "@", domain name with at least one period and only allowed a-z characters.
1153       */
1154  	function validEmail($email)    {
1155          $email = trim ($email);
1156          if (strstr($email,' '))     return FALSE;
1157          return ereg('^[A-Za-z0-9\._-]+[@][A-Za-z0-9\._-]+[\.].[A-Za-z0-9]+$',$email) ? TRUE : FALSE;
1158      }
1159  
1160      /**
1161       * Formats a string for output between <textarea>-tags
1162       * All content outputted in a textarea form should be passed through this function
1163       * 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!
1164       * Usage: 23
1165       *
1166       * @param    string        Input string to be formatted.
1167       * @return    string        Formatted for <textarea>-tags
1168       */
1169  	function formatForTextarea($content)    {
1170          return chr(10).htmlspecialchars($content);
1171      }
1172  
1173  
1174  
1175  
1176  
1177  
1178  
1179  
1180  
1181  
1182  
1183  
1184      /*************************
1185       *
1186       * ARRAY FUNCTIONS
1187       *
1188       *************************/
1189  
1190      /**
1191       * Check if an item exists in an array
1192       * Please note that the order of parameters is reverse compared to the php4-function in_array()!!!
1193       * Usage: 3
1194       *
1195       * @param    array        $in_array        one-dimensional array of items
1196       * @param    string        $item     item to check for
1197       * @return    boolean        true if $item is in the one-dimensional array $in_array
1198       * @internal
1199       */
1200  	function inArray($in_array,$item)    {
1201          if (is_array($in_array))    {
1202              while (list(,$val)=each($in_array))    {
1203                  if (!is_array($val) && !strcmp($val,$item)) return true;
1204              }
1205          }
1206      }
1207  
1208      /**
1209       * Explodes a $string delimited by $delim and passes each item in the array through intval().
1210       * Corresponds to explode(), but with conversion to integers for all values.
1211       * Usage: 76
1212       *
1213       * @param    string        Delimiter string to explode with
1214       * @param    string        The string to explode
1215       * @return    array        Exploded values, all converted to integers
1216       */
1217  	function intExplode($delim, $string)    {
1218          $temp = explode($delim,$string);
1219          while(list($key,$val)=each($temp))    {
1220              $temp[$key]=intval($val);
1221          }
1222          reset($temp);
1223          return $temp;
1224      }
1225  
1226      /**
1227       * Reverse explode which explodes the string counting from behind.
1228       * Thus t3lib_div::revExplode(':','my:words:here',2) will return array('my:words','here')
1229       * Usage: 8
1230       *
1231       * @param    string        Delimiter string to explode with
1232       * @param    string        The string to explode
1233       * @param    integer        Number of array entries
1234       * @return    array        Exploded values
1235       */
1236  	function revExplode($delim, $string, $count=0)    {
1237          $temp = explode($delim,strrev($string),$count);
1238          while(list($key,$val)=each($temp))    {
1239              $temp[$key]=strrev($val);
1240          }
1241          $temp=array_reverse($temp);
1242          reset($temp);
1243          return $temp;
1244      }
1245  
1246      /**
1247       * Explodes a string and trims all values for whitespace in the ends.
1248       * If $onlyNonEmptyValues is set, then all blank ('') values are removed.
1249       * Usage: 256
1250       *
1251       * @param    string        Delimiter string to explode with
1252       * @param    string        The string to explode
1253       * @param    boolean        If set, all empty values (='') will NOT be set in output
1254       * @return    array        Exploded values
1255       */
1256  	function trimExplode($delim, $string, $onlyNonEmptyValues=0)    {
1257          $temp = explode($delim,$string);
1258          $newtemp=array();
1259          while(list($key,$val)=each($temp))    {
1260              if (!$onlyNonEmptyValues || strcmp('',trim($val)))    {
1261                  $newtemp[]=trim($val);
1262              }
1263          }
1264          reset($newtemp);
1265          return $newtemp;
1266      }
1267  
1268      /**
1269       * Remove duplicate values from an array
1270       * This function is deprecated, use the PHP function array_unique instead
1271       * Usage: 0
1272       *
1273       * @param    array        Array of values to make unique
1274       * @return    array
1275       * @ignore
1276       * @deprecated
1277       */
1278  	function uniqueArray($valueArray)    {
1279          return array_unique($valueArray);
1280      }
1281  
1282      /**
1283       * Removes the value $cmpValue from the $array if found there. Returns the modified array
1284       * Usage: 3
1285       *
1286       * @param    array        Array containing the values
1287       * @param    string        Value to search for and if found remove array entry where found.
1288       * @return    array        Output array with entries removed if search string is found
1289       */
1290  	function removeArrayEntryByValue($array,$cmpValue)    {
1291          if (is_array($array))    {
1292              reset($array);
1293              while(list($k,$v)=each($array))    {
1294                  if (is_array($v))    {
1295                      $array[$k] = t3lib_div::removeArrayEntryByValue($v,$cmpValue);
1296                  } else {
1297                      if (!strcmp($v,$cmpValue))    {
1298                          unset($array[$k]);
1299                      }
1300                  }
1301              }
1302          }
1303          reset($array);
1304          return $array;
1305      }
1306  
1307      /**
1308       * Implodes a multidim-array into GET-parameters (eg. &param[key][key2]=value2&param[key][key3]=value3)
1309       * Usage: 24
1310       *
1311       * @param    string        Name prefix for entries. Set to blank if you wish none.
1312       * @param    array        The (multidim) array to implode
1313       * @param    string        (keep blank)
1314       * @param    boolean        If set, parameters which were blank strings would be removed.
1315       * @param    boolean        If set, the param name itself (for example "param[key][key2]") would be rawurlencoded as well.
1316       * @return    string        Imploded result, fx. &param[key][key2]=value2&param[key][key3]=value3
1317       * @see explodeUrl2Array()
1318       */
1319  	function implodeArrayForUrl($name,$theArray,$str='',$skipBlank=0,$rawurlencodeParamName=0)    {
1320          if (is_array($theArray))    {
1321              foreach($theArray as $Akey => $AVal)    {
1322                  $thisKeyName = $name ? $name.'['.$Akey.']' : $Akey;
1323                  if (is_array($AVal))    {
1324                      $str = t3lib_div::implodeArrayForUrl($thisKeyName,$AVal,$str,$skipBlank,$rawurlencodeParamName);
1325                  } else {
1326                      if (!$skipBlank || strcmp($AVal,''))    {
1327                          $str.='&'.($rawurlencodeParamName ? rawurlencode($thisKeyName) : $thisKeyName).
1328                              '='.rawurlencode($AVal);
1329                      }
1330                  }
1331              }
1332          }
1333          return $str;
1334      }
1335  
1336      /**
1337       * Explodes a string with GETvars (eg. "&id=1&type=2&ext[mykey]=3") into an array
1338       *
1339       * @param    string        GETvars string
1340       * @param    boolean        If set, the string will be parsed into a multidimensional array if square brackets are used in variable names (using PHP function parse_str())
1341       * @return    array        Array of values. All values AND keys are rawurldecoded() as they properly should be. But this means that any implosion of the array again must rawurlencode it!
1342       * @see implodeArrayForUrl()
1343       */
1344  	function explodeUrl2Array($string,$multidim=FALSE)    {
1345          if ($multidim)    {
1346              parse_str($string,$tempGetVars);
1347              return $tempGetVars;
1348          } else {
1349              $output = array();
1350              $p = explode('&',$string);
1351              foreach($p as $v)    {
1352                  if (strlen($v))    {
1353                      list($pK,$pV) = explode('=',$v,2);
1354                      $output[rawurldecode($pK)] = rawurldecode($pV);
1355                  }
1356              }
1357              return $output;
1358          }
1359      }
1360  
1361      /**
1362       * Returns an array with selected keys from incoming data.
1363       * (Better read source code if you want to find out...)
1364       * Usage: 3
1365       *
1366       * @param    string        List of variable/key names
1367       * @param    array        Array from where to get values based on the keys in $varList
1368       * @param    boolean        If set, then t3lib_div::_GP() is used to fetch the value if not found (isset) in the $getArray
1369       * @return    array        Output array with selected variables.
1370       */
1371  	function compileSelectedGetVarsFromArray($varList,$getArray,$GPvarAlt=1)    {
1372          $keys = t3lib_div::trimExplode(',',$varList,1);
1373          $outArr=array();
1374          foreach($keys as $v)    {
1375              if (isset($getArray[$v]))    {
1376                  $outArr[$v]=$getArray[$v];
1377              } elseif ($GPvarAlt) {
1378                  $outArr[$v]=t3lib_div::_GP($v);
1379              }
1380          }
1381          return $outArr;
1382      }
1383  
1384      /**
1385       * AddSlash array
1386       * This function traverses a multidimentional array and adds slashes to the values.
1387       * NOTE that the input array is and argument by reference.!!
1388       * Twin-function to stripSlashesOnArray
1389       * Usage: 8
1390       *
1391       * @param    array        Multidimensional input array, (REFERENCE!)
1392       * @return    array
1393       */
1394  	function addSlashesOnArray(&$theArray)    {
1395          if (is_array($theArray))    {
1396              reset($theArray);
1397              while(list($Akey,$AVal)=each($theArray))    {
1398                  if (is_array($AVal))    {
1399                      t3lib_div::addSlashesOnArray($theArray[$Akey]);
1400                  } else {
1401                      $theArray[$Akey] = addslashes($AVal);
1402                  }
1403              }
1404              reset($theArray);
1405          }
1406      }
1407  
1408      /**
1409       * StripSlash array
1410       * This function traverses a multidimentional array and strips slashes to the values.
1411       * NOTE that the input array is and argument by reference.!!
1412       * Twin-function to addSlashesOnArray
1413       * Usage: 10
1414       *
1415       * @param    array        Multidimensional input array, (REFERENCE!)
1416       * @return    array
1417       */
1418  	function stripSlashesOnArray(&$theArray)    {
1419          if (is_array($theArray))    {
1420              reset($theArray);
1421              while(list($Akey,$AVal)=each($theArray))    {
1422                  if (is_array($AVal))    {
1423                      t3lib_div::stripSlashesOnArray($theArray[$Akey]);
1424                  } else {
1425                      $theArray[$Akey] = stripslashes($AVal);
1426                  }
1427              }
1428              reset($theArray);
1429          }
1430      }
1431  
1432      /**
1433       * Either slashes ($cmd=add) or strips ($cmd=strip) array $arr depending on $cmd
1434       * Usage: 0
1435       *
1436       * @param    array        Multidimensional input array
1437       * @param    string        "add" or "strip", depending on usage you wish.
1438       * @return    array
1439       */
1440  	function slashArray($arr,$cmd)    {
1441          if ($cmd=='strip')    t3lib_div::stripSlashesOnArray($arr);
1442          if ($cmd=='add')    t3lib_div::addSlashesOnArray($arr);
1443          return $arr;
1444      }
1445  
1446      /**
1447       * Merges two arrays recursively and "binary safe" (integer keys are overridden as well), overruling similar values in the first array ($arr0) with the values of the second array ($arr1)
1448       * In case of identical keys, ie. keeping the values of the second.
1449       * Usage: 0
1450       *
1451       * @param    array        First array
1452       * @param    array        Second array, overruling the first array
1453       * @param    boolean        If set, keys that are NOT found in $arr0 (first array) will not be set. Thus only existing value can/will be overruled from second array.
1454       * @param    boolean        If set, values from $arr1 will overrule if they are empty. Default: true
1455       * @return    array        Resulting array where $arr1 values has overruled $arr0 values
1456       */
1457  	function array_merge_recursive_overrule($arr0,$arr1,$notAddKeys=0,$includeEmtpyValues=true) {
1458          reset($arr1);
1459          while(list($key,$val) = each($arr1)) {
1460              if(is_array($arr0[$key])) {
1461                  if (is_array($arr1[$key]))    {
1462                      $arr0[$key] = t3lib_div::array_merge_recursive_overrule($arr0[$key],$arr1[$key],$notAddKeys);
1463                  }
1464              } else {
1465                  if ($notAddKeys) {
1466                      if (isset($arr0[$key])) {
1467                          if ($includeEmtpyValues OR $val) {
1468                              $arr0[$key] = $val;
1469                          }
1470                      }
1471                  } else {
1472                      if ($includeEmtpyValues OR $val) {
1473                          $arr0[$key] = $val;
1474                      }
1475                  }
1476              }
1477          }
1478          reset($arr0);
1479          return $arr0;
1480      }
1481  
1482      /**
1483       * An array_merge function where the keys are NOT renumbered as they happen to be with the real php-array_merge function. It is "binary safe" in the sense that integer keys are overridden as well.
1484       * Usage: 16
1485       *
1486       * @param    array        First array
1487       * @param    array        Second array
1488       * @return    array        Merged result.
1489       */
1490  	function array_merge($arr1,$arr2)    {
1491          return $arr2+$arr1;
1492      }
1493  
1494      /**
1495       * Takes a row and returns a CSV string of the values with $delim (default is ,) and $quote (default is ") as separator chars.
1496       * Usage: 5
1497       *
1498       * @param    array        Input array of values
1499       * @param    string        Delimited, default is comman
1500       * @param    string        Quote-character to wrap around the values.
1501       * @return    string        A single line of CSV
1502       */
1503  	function csvValues($row,$delim=',',$quote='"')    {
1504          reset($row);
1505          $out=array();
1506          while(list(,$value)=each($row))    {
1507              list($valPart) = explode(chr(10),$value);
1508              $valPart = trim($valPart);
1509              $out[]=str_replace($quote,$quote.$quote,$valPart);
1510          }
1511          $str = $quote.implode($quote.$delim.$quote,$out).$quote;
1512          return $str;
1513      }
1514  
1515  
1516  
1517  
1518  
1519  
1520  
1521  
1522  
1523  
1524  
1525  
1526  
1527  
1528  
1529  
1530      /*************************
1531       *
1532       * HTML/XML PROCESSING
1533       *
1534       *************************/
1535  
1536      /**
1537       * Returns an array with all attributes of the input HTML tag as key/value pairs. Attributes are only lowercase a-z
1538       * $tag is either a whole tag (eg '<TAG OPTION ATTRIB=VALUE>') or the parameterlist (ex ' OPTION ATTRIB=VALUE>')
1539       * If a attribute is empty (I call it 'an option'), then the value for the key is empty. You can check if it existed with isset()
1540       * Usage: 8
1541       *
1542       * @param    string        HTML-tag string (or attributes only)
1543       * @return    array        Array with the attribute values.
1544       */
1545  	function get_tag_attributes($tag)    {
1546          $components = t3lib_div::split_tag_attributes($tag);
1547          $name = '';     // attribute name is stored here
1548          $valuemode = '';
1549          if (is_array($components))    {
1550              while (list($key,$val) = each ($components))    {
1551                  if ($val != '=')    {    // Only if $name is set (if there is an attribute, that waits for a value), that valuemode is enabled. This ensures that the attribute is assigned it's value
1552                      if ($valuemode)    {
1553                          if ($name)    {
1554                              $attributes[$name] = $val;
1555                              $name = '';
1556                          }
1557                      } else {
1558                          if ($key = strtolower(ereg_replace('[^a-zA-Z0-9]','',$val)))    {
1559                              $attributes[$key] = '';
1560                              $name = $key;
1561                          }
1562                      }
1563                      $valuemode = '';
1564                  } else {
1565                      $valuemode = 'on';
1566                  }
1567              }
1568              if (is_array($attributes))    reset($attributes);
1569              return $attributes;
1570          }
1571      }
1572  
1573      /**
1574       * Returns an array with the 'components' from an attribute list from an HTML tag. The result is normally analyzed by get_tag_attributes
1575       * Removes tag-name if found
1576       * Usage: 2
1577       *
1578       * @param    string        HTML-tag string (or attributes only)
1579       * @return    array        Array with the attribute values.
1580       * @internal
1581       */
1582  	function split_tag_attributes($tag)    {
1583          $tag_tmp = trim(eregi_replace ('^<[^[:space:]]*','',trim($tag)));
1584              // Removes any > in the end of the string
1585          $tag_tmp = trim(eregi_replace ('>$','',$tag_tmp));
1586  
1587          while (strcmp($tag_tmp,''))    {    // Compared with empty string instead , 030102
1588              $firstChar=substr($tag_tmp,0,1);
1589              if (!strcmp($firstChar,'"') || !strcmp($firstChar,"'"))    {
1590                  $reg=explode($firstChar,$tag_tmp,3);
1591                  $value[]=$reg[1];
1592                  $tag_tmp=trim($reg[2]);
1593              } elseif (!strcmp($firstChar,'=')) {
1594                  $value[] = '=';
1595                  $tag_tmp = trim(substr($tag_tmp,1));        // Removes = chars.
1596              } else {
1597                      // There are '' around the value. We look for the next ' ' or '>'
1598                  $reg = split('[[:space:]=]',$tag_tmp,2);
1599                  $value[] = trim($reg[0]);
1600                  $tag_tmp = trim(substr($tag_tmp,strlen($reg[0]),1).$reg[1]);
1601              }
1602          }
1603          if (is_array($value))    reset($value);
1604          return $value;
1605      }
1606  
1607      /**
1608       * Implodes attributes in the array $arr for an attribute list in eg. and HTML tag (with quotes)
1609       * Usage: 14
1610       *
1611       * @param    array        Array with attribute key/value pairs, eg. "bgcolor"=>"red", "border"=>0
1612       * @param    boolean        If set the resulting attribute list will have a) all attributes in lowercase (and duplicates weeded out, first entry taking precedence) and b) all values htmlspecialchar()'ed. It is recommended to use this switch!
1613       * @param    boolean        If true, don't check if values are blank. Default is to omit attributes with blank values.
1614       * @return    string        Imploded attributes, eg. 'bgcolor="red" border="0"'
1615       */
1616  	function implodeAttributes($arr,$xhtmlSafe=FALSE,$dontOmitBlankAttribs=FALSE)    {
1617          if (is_array($arr))    {
1618              if ($xhtmlSafe)    {
1619                  $newArr=array();
1620                  foreach($arr as $p => $v)    {
1621                      if (!isset($newArr[strtolower($p)])) $newArr[strtolower($p)] = htmlspecialchars($v);
1622                  }
1623                  $arr = $newArr;
1624              }
1625              $list = array();
1626              foreach($arr as $p => $v)    {
1627                  if (strcmp($v,'') || $dontOmitBlankAttribs)    {$list[]=$p.'="'.$v.'"';}
1628              }
1629              return implode(' ',$list);
1630          }
1631      }
1632  
1633      /**
1634       * Implodes attributes in the array $arr for an attribute list in eg. and HTML tag (with quotes)
1635       *
1636       * @param    array        See implodeAttributes()
1637       * @param    boolean        See implodeAttributes()
1638       * @param    boolean        See implodeAttributes()
1639       * @return    string        See implodeAttributes()
1640       * @deprecated    Name was changed into implodeAttributes
1641       * @see implodeAttributes()
1642       */
1643  	function implodeParams($arr,$xhtmlSafe=FALSE,$dontOmitBlankAttribs=FALSE)    {
1644          return t3lib_div::implodeAttributes($arr,$xhtmlSafe,$dontOmitBlankAttribs);
1645      }
1646  
1647      /**
1648       * Wraps JavaScript code XHTML ready with <script>-tags
1649       * Automatic re-identing of the JS code is done by using the first line as ident reference.
1650       * This is nice for identing JS code with PHP code on the same level.
1651       *
1652       * @param    string        JavaScript code
1653       * @param    boolean        Wrap script element in linebreaks? Default is TRUE.
1654       * @return    string        The wrapped JS code, ready to put into a XHTML page
1655       * @author    Ingmar Schlecht <ingmars@web.de>
1656       * @author    René Fritz <r.fritz@colorcube.de>
1657       */
1658  	function wrapJS($string, $linebreak=TRUE) {
1659          if(trim($string)) {
1660                  // <script wrapped in nl?
1661              $cr = $linebreak? "\n" : '';
1662  
1663                  // remove nl from the beginning
1664              $string = preg_replace ('/^\n+/', '', $string);
1665                  // re-ident to one tab using the first line as reference
1666              if(preg_match('/^(\t+)/',$string,$match)) {
1667                  $string = str_replace($match[1],"\t", $string);
1668              }
1669              $string = $cr.'<script type="text/javascript">
1670  /*<![CDATA[*/
1671  '.$string.'
1672  /*]]>*/
1673  </script>'.$cr;
1674          }
1675          return trim($string);
1676      }
1677  
1678  
1679      /**
1680       * Parses XML input into a PHP array with associative keys
1681       * Usage: 0
1682       *
1683       * @param    string        XML data input
1684       * @param    integer        Number of element levels to resolve the XML into an array. Any further structure will be set as XML.
1685       * @return    mixed        The array with the parsed structure unless the XML parser returns with an error in which case the error message string is returned.
1686       * @author bisqwit at iki dot fi dot not dot for dot ads dot invalid / http://dk.php.net/xml_parse_into_struct + kasperYYYY@typo3.com
1687       */
1688  	function xml2tree($string,$depth=999) {
1689          $parser = xml_parser_create();
1690          $vals = array();
1691          $index = array();
1692  
1693          xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
1694          xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
1695          xml_parse_into_struct($parser, $string, $vals, $index);
1696  
1697          if (xml_get_error_code($parser))    return 'Line '.xml_get_current_line_number($parser).': '.xml_error_string(xml_get_error_code($parser));
1698          xml_parser_free($parser);
1699  
1700          $stack = array( array() );
1701          $stacktop = 0;
1702          $startPoint=0;
1703  
1704          unset($tagi);
1705          foreach($vals as $key => $val) {
1706              $type = $val['type'];
1707  
1708                  // open tag:
1709              if ($type=='open' || $type=='complete') {
1710                  $stack[$stacktop++] = $tagi;
1711  
1712                  if ($depth==$stacktop)    {
1713                      $startPoint=$key;
1714                  }
1715  
1716                  $tagi = array('tag' => $val['tag']);
1717  
1718                  if(isset($val['attributes']))  $tagi['attrs'] = $val['attributes'];
1719                  if(isset($val['value']))    $tagi['values'][] = $val['value'];
1720              }
1721                  // finish tag:
1722              if ($type=='complete' || $type=='close')    {
1723                  $oldtagi = $tagi;
1724                  $tagi = $stack[--$stacktop];
1725                  $oldtag = $oldtagi['tag'];
1726                  unset($oldtagi['tag']);
1727  
1728                  if ($depth==($stacktop+1))    {
1729                      if ($key-$startPoint > 0)    {
1730                          $partArray = array_slice(
1731                              $vals,
1732                              $startPoint+1,
1733                              $key-$startPoint-1
1734                          );
1735                          #$oldtagi=array('XMLvalue'=>t3lib_div::xmlRecompileFromStructValArray($partArray));
1736                          $oldtagi['XMLvalue']=t3lib_div::xmlRecompileFromStructValArray($partArray);
1737                      } else {
1738                          $oldtagi['XMLvalue']=$oldtagi['values'][0];
1739                      }
1740                  }
1741  
1742                  $tagi['ch'][$oldtag][] = $oldtagi;
1743                  unset($oldtagi);
1744              }
1745                  // cdata
1746              if($type=='cdata') {
1747                  $tagi['values'][] = $val['value'];
1748              }
1749          }
1750          return $tagi['ch'];
1751      }
1752  
1753      /**
1754       * Converts a PHP array into an XML string.
1755       * The XML output is optimized for readability since associative keys are used as tagnames.
1756       * This also means that only alphanumeric characters are allowed in the tag names AND only keys NOT starting with numbers (so watch your usage of keys!). However there are options you can set to avoid this problem.
1757       * Numeric keys are stored with the default tagname "numIndex" but can be overridden to other formats)
1758       * The function handles input values from the PHP array in a binary-safe way; All characters below 32 (except 9,10,13) will trigger the content to be converted to a base64-string
1759       * The PHP variable type of the data IS preserved as long as the types are strings, arrays, integers and booleans. Strings are the default type unless the "type" attribute is set.
1760       * The output XML has been tested with the PHP XML-parser and parses OK under all tested circumstances.
1761       * However using MSIE to read the XML output didn't always go well: One reason could be that the character encoding is not observed in the PHP data. The other reason may be if the tag-names are invalid in the eyes of MSIE. Also using the namespace feature will make MSIE break parsing. There might be more reasons...
1762       * Usage: 5
1763       *
1764       * @param    array        The input PHP array with any kind of data; text, binary, integers. Not objects though.
1765       * @param    string        tag-prefix, eg. a namespace prefix like "T3:"
1766       * @param    integer        Current recursion level. Don't change, stay at zero!
1767       * @param    string        Alternative document tag. Default is "phparray".
1768       * @param    integer        If set, the number of spaces corresponding to this number is used for indenting, otherwise a single chr(9) (TAB) is used
1769       * @param    array        Options for the compilation. Key "useNindex" => 0/1 (boolean: whether to use "n0, n1, n2" for num. indexes); Key "useIndexTagForNum" => "[tag for numerical indexes]"; Key "useIndexTagForAssoc" => "[tag for associative indexes"; Key "parentTagMap" => array('parentTag' => 'thisLevelTag')
1770       * @param    string        Stack data. Don't touch.
1771       * @return    string        An XML string made from the input content in the array.
1772       * @see xml2array()
1773       */
1774  	function array2xml($array,$NSprefix='',$level=0,$docTag='phparray',$spaceInd=0, $options=array(),$stackData=array())    {
1775              // The list of byte values which will trigger binary-safe storage. If any value has one of these char values in it, it will be encoded in base64
1776          $binaryChars = chr(0).chr(1).chr(2).chr(3).chr(4).chr(5).chr(6).chr(7).chr(8).
1777                          chr(11).chr(12).chr(14).chr(15).chr(16).chr(17).chr(18).chr(19).
1778                          chr(20).chr(21).chr(22).chr(23).chr(24).chr(25).chr(26).chr(27).chr(28).chr(29).
1779                          chr(30).chr(31);
1780              // Set indenting mode:
1781          $indentChar = $spaceInd ? ' ' : chr(9);
1782          $indentN = $spaceInd>0 ? $spaceInd : 1;
1783  
1784              // Init output variable:
1785          $output='';
1786  
1787              // Traverse the input array
1788          if (is_array($array))    {
1789              foreach($array as $k=>$v)    {
1790                  $attr = '';
1791                  $tagName = $k;
1792  
1793                      // Construct the tag name.
1794                  if(isset($options['grandParentTagMap'][$stackData['grandParentTagName'].'/'.$stackData['parentTagName']])) {        // Use tag based on grand-parent + parent tag name
1795                      $attr.=' index="'.htmlspecialchars($tagName).'"';
1796                      $tagName = (string)$options['grandParentTagMap'][$stackData['grandParentTagName'].'/'.$stackData['parentTagName']];
1797                  }elseif(isset($options['parentTagMap'][$stackData['parentTagName'].':'.$tagName])) {        // Use tag based on parent tag name + current tag
1798                      $attr.=' index="'.htmlspecialchars($tagName).'"';
1799                      $tagName = (string)$options['parentTagMap'][$stackData['parentTagName'].':'.$tagName];
1800                  } elseif(isset($options['parentTagMap'][$stackData['parentTagName']])) {        // Use tag based on parent tag name:
1801                      $attr.=' index="'.htmlspecialchars($tagName).'"';
1802                      $tagName = (string)$options['parentTagMap'][$stackData['parentTagName']];
1803                  } elseif (!strcmp(intval($tagName),$tagName))    {    // If integer...;
1804                      if ($options['useNindex']) {    // If numeric key, prefix "n"
1805                          $tagName = 'n'.$tagName;
1806                      } else {    // Use special tag for num. keys:
1807                          $attr.=' index="'.$tagName.'"';
1808                          $tagName = $options['useIndexTagForNum'] ? $options['useIndexTagForNum'] : 'numIndex';
1809                      }
1810                  } elseif($options['useIndexTagForAssoc']) {        // Use tag for all associative keys:
1811                      $attr.=' index="'.htmlspecialchars($tagName).'"';
1812                      $tagName = $options['useIndexTagForAssoc'];
1813                  }
1814  
1815                      // The tag name is cleaned up so only alphanumeric chars (plus - and _) are in there and not longer than 100 chars either.
1816                  $tagName = substr(ereg_replace('[^[:alnum:]_-]','',$tagName),0,100);
1817  
1818                      // If the value is an array then we will call this function recursively:
1819                  if (is_array($v))    {
1820  
1821                          // Sub elements:
1822                      if ($options['alt_options'][$stackData['path'].'/'.$tagName])    {
1823                          $subOptions = $options['alt_options'][$stackData['path'].'/'.$tagName];
1824                          $clearStackPath = $subOptions['clearStackPath'];
1825                      } else {
1826                          $subOptions = $options;
1827                          $clearStackPath = FALSE;
1828                      }
1829  
1830                      $content = chr(10).
1831                                  t3lib_div::array2xml(
1832                                      $v,
1833                                      $NSprefix,
1834                                      $level+1,
1835                                      '',
1836                                      $spaceInd,
1837                                      $subOptions,
1838                                      array(
1839                                          'parentTagName' => $tagName,
1840                                          'grandParentTagName' => $stackData['parentTagName'],
1841                                          'path' => $clearStackPath ? '' : $stackData['path'].'/'.$tagName,
1842                                      )
1843                                  ).
1844                                  str_pad('',($level+1)*$indentN,$indentChar);
1845                      $attr.=' type="array"';
1846                  } else {    // Just a value:
1847  
1848                          // Look for binary chars:
1849                      if (strcspn($v,$binaryChars) != strlen($v))    {    // Go for base64 encoding if the initial segment NOT matching any binary char has the same length as the whole string!
1850                              // If the value contained binary chars then we base64-encode it an set an attribute to notify this situation:
1851                          $content = chr(10).chunk_split(base64_encode($v));
1852                          $attr.=' base64="1"';
1853                      } else {
1854                              // Otherwise, just htmlspecialchar the stuff:
1855                          $content = htmlspecialchars($v);
1856                          $dType = gettype($v);
1857                          if ($dType!='string' && !$options['disableTypeAttrib'])    { $attr.=' type="'.$dType.'"'; }
1858                      }
1859                  }
1860  
1861                      // Add the element to the output string:
1862                  $output.=str_pad('',($level+1)*$indentN,$indentChar).'<'.$NSprefix.$tagName.$attr.'>'.$content.'</'.$NSprefix.$tagName.'>'.chr(10);
1863              }
1864          }
1865  
1866              // If we are at the outer-most level, then we finally wrap it all in the document tags and return that as the value:
1867          if (!$level)    {
1868              $output =
1869                  '<'.$docTag.'>'.chr(10).
1870                  $output.
1871                  '</'.$docTag.'>';
1872          }
1873  
1874          return $output;
1875      }
1876  
1877      /**
1878       * Converts an XML string to a PHP array.
1879       * This is the reverse function of array2xml()
1880       * Usage: 17
1881       *
1882       * @param    string        XML content to convert into an array
1883       * @param    string        The tag-prefix resolve, eg. a namespace like "T3:"
1884       * @param    boolean        If set, the document tag will be set in the key "_DOCUMENT_TAG" of the output array
1885       * @return    mixed        If the parsing had errors, a string with the error message is returned. Otherwise an array with the content.
1886       * @see array2xml()
1887       */
1888  	function xml2array($string,$NSprefix='',$reportDocTag=FALSE) {
1889          global $TYPO3_CONF_VARS;
1890  
1891              // Create parser:
1892          $parser = xml_parser_create();
1893          $vals = array();
1894          $index = array();
1895  
1896          xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
1897          xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
1898  
1899              // PHP5 fix of charset awareness:
1900              // Problem is: PHP5 apparently detects the charset of the XML file (or defaults to utf-8) and will AUTOMATICALLY convert the content to either utf-8, iso-8859-1 or us-ascii. PHP4 just passed the content through without taking action regarding the charset.
1901              // In TYPO3 we expect that the charset of XML content is NOT handled in the parser but internally in TYPO3 instead. Therefore it would be very nice if PHP5 could be configured to NOT process the charset of the files. But this is not possible for now.
1902              // What we do here fixes the problem but ONLY if the charset is utf-8, iso-8859-1 or us-ascii. That should work for most TYPO3 installations, in particular if people use utf-8 which we highly recommend.
1903          if ((double)phpversion()>=5)    {
1904              unset($ereg_result);
1905              ereg('^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"',substr($string,0,200),$ereg_result);
1906              $theCharset = $ereg_result[1] ? $ereg_result[1] : ($TYPO3_CONF_VARS['BE']['forceCharset'] ? $TYPO3_CONF_VARS['BE']['forceCharset'] : 'iso-8859-1');
1907              xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset);  // us-ascii / utf-8 / iso-8859-1
1908          }
1909  
1910              // Parse content:
1911          xml_parse_into_struct($parser, $string, $vals, $index);
1912  
1913              // If error, return error message:
1914          if (xml_get_error_code($parser))    {
1915              return 'Line '.xml_get_current_line_number($parser).': '.xml_error_string(xml_get_error_code($parser));
1916          }
1917          xml_parser_free($parser);
1918  
1919              // Init vars:
1920          $stack = array(array());
1921          $stacktop = 0;
1922          $current=array();
1923          $tagName = '';
1924          $documentTag = '';
1925  
1926              // Traverse the parsed XML structure:
1927          foreach($vals as $key => $val) {
1928  
1929                  // First, process the tag-name (which is used in both cases, whether "complete" or "close")
1930              $tagName = $val['tag'];
1931              if (!$documentTag)    $documentTag = $tagName;
1932  
1933                  // Test for name space:
1934              $tagName = ($NSprefix && substr($tagName,0,strlen($NSprefix))==$NSprefix) ? substr($tagName,strlen($NSprefix)) : $tagName;
1935  
1936                  // Test for numeric tag, encoded on the form "nXXX":
1937              $testNtag = substr($tagName,1);    // Closing tag.
1938              $tagName = (substr($tagName,0,1)=='n' && !strcmp(intval($testNtag),$testNtag)) ? intval($testNtag) : $tagName;
1939  
1940                  // Test for alternative index value:
1941              if (strlen($val['attributes']['index']))    { $tagName = $val['attributes']['index']; }
1942  
1943                  // Setting tag-values, manage stack:
1944              switch($val['type'])    {
1945                  case 'open':        // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
1946                      $current[$tagName] = array();    // Setting blank place holder
1947                      $stack[$stacktop++] = $current;
1948                      $current = array();
1949                  break;
1950                  case 'close':    // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
1951                      $oldCurrent = $current;
1952                      $current = $stack[--$stacktop];
1953                      end($current);    // Going to the end of array to get placeholder key, key($current), and fill in array next:
1954                      $current[key($current)] = $oldCurrent;
1955                      unset($oldCurrent);
1956                  break;
1957                  case 'complete':    // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
1958                      if ($val['attributes']['base64'])    {
1959                          $current[$tagName] = base64_decode($val['value']);
1960                      } else {
1961                          $current[$tagName] = (string)$val['value']; // Had to cast it as a string - otherwise it would be evaluate false if tested with isset()!!
1962  
1963                              // Cast type:
1964                          switch((string)$val['attributes']['type'])    {
1965                              case 'integer':
1966                                  $current[$tagName] = (integer)$current[$tagName];
1967                              break;
1968                              case 'double':
1969                                  $current[$tagName] = (double)$current[$tagName];
1970                              break;
1971                              case 'boolean':
1972                                  $current[$tagName] = (bool)$current[$tagName];
1973                              break;
1974                              case 'array':
1975                                  $current[$tagName] = array();    // MUST be an empty array since it is processed as a value; Empty arrays would end up here because they would have no tags inside...
1976                              break;
1977                          }
1978                      }
1979                  break;
1980              }
1981          }
1982  
1983          if ($reportDocTag)    {
1984              $current[$tagName]['_DOCUMENT_TAG'] = $documentTag;
1985          }
1986  
1987              // Finally return the content of the document tag.
1988          return $current[$tagName];
1989      }
1990  
1991      /**
1992       * This implodes an array of XML parts (made with xml_parse_into_struct()) into XML again.
1993       * Usage: 2
1994       *
1995       * @param    array        A array of XML parts, see xml2tree
1996       * @return    string        Re-compiled XML data.
1997       */
1998  	function xmlRecompileFromStructValArray($vals)    {
1999          $XMLcontent='';
2000  
2001          foreach($vals as $val) {
2002              $type = $val['type'];
2003  
2004                  // open tag:
2005              if ($type=='open' || $type=='complete') {
2006                  $XMLcontent.='<'.$val['tag'];
2007                  if(isset($val['attributes']))  {
2008                      foreach($val['attributes'] as $k => $v)    {
2009                          $XMLcontent.=' '.$k.'="'.htmlspecialchars($v).'"';
2010                      }
2011                  }
2012                  if ($type=='complete')    {
2013                      if(isset($val['value']))    {
2014                          $XMLcontent.='>'.htmlspecialchars($val['value']).'</'.$val['tag'].'>';
2015                      } else $XMLcontent.='/>';
2016                  } else $XMLcontent.='>';
2017  
2018                  if ($type=='open' && isset($val['value']))    {
2019                      $XMLcontent.=htmlspecialchars($val['value']);
2020                  }
2021              }
2022                  // finish tag:
2023              if ($type=='close')    {
2024                  $XMLcontent.='</'.$val['tag'].'>';
2025              }
2026                  // cdata
2027              if($type=='cdata') {
2028                  $XMLcontent.=htmlspecialchars($val['value']);
2029              }
2030          }
2031  
2032          return $XMLcontent;
2033      }
2034  
2035      /**
2036       * Extract the encoding scheme as found in the first line of an XML document (typically)
2037       * Usage: 1
2038       *
2039       * @param    string        XML data
2040       * @return    string        Encoding scheme (lowercase), if found.
2041       */
2042  	function xmlGetHeaderAttribs($xmlData)    {
2043          $xmlHeader = substr(trim($xmlData),0,200);
2044          $reg=array();
2045          if (eregi('^<\?xml([^>]*)\?\>',$xmlHeader,$reg))    {
2046              return t3lib_div::get_tag_attributes($reg[1]);
2047          }
2048      }
2049  
2050  
2051  
2052  
2053  
2054  
2055  
2056  
2057  
2058  
2059  
2060      /*************************
2061       *
2062       * FILES FUNCTIONS
2063       *
2064       *************************/
2065  
2066      /**
2067       * Reads the file or url $url and returns the content
2068       * If you are having trouble with proxys when reading URLs you can configure your way out of that with settings like $TYPO3_CONF_VARS['SYS']['curlUse'] etc.
2069       * Usage: 83
2070       *
2071       * @param    string        Filepath/URL to read
2072       * @return    string        The content from the resource given as input.
2073       */
2074  	function getURL($url)    {
2075          $content = '';
2076  
2077              // (Proxy support implemented by Arco <arco@appeltaart.mine.nu>)
2078          if((substr($url,0,7)=='http://') && ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlUse']=='1'))    {
2079              //external URL without error checking.
2080              $ch = curl_init();
2081              curl_setopt ($ch,CURLOPT_URL, $url);
2082              curl_setopt ($ch,CURLOPT_HEADER, 0);
2083              curl_setopt ($ch,CURLOPT_RETURNTRANSFER, 1);
2084  
2085              if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyServer']) {
2086                  curl_setopt ($ch, CURLOPT_PROXY, $GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyServer']);
2087  
2088                  // I don't know if it will be needed
2089                  if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyTunnel']) {
2090                      curl_setopt ($ch, CURLOPT_HTTPPROXYTUNNEL, $GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyTunnel'] );
2091                  }
2092                  if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyUserPass']) {
2093                      curl_setopt ($ch, CURLOPT_PROXYUSERPWD, $GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyUserPass'] );
2094                  }
2095              }
2096              $content=curl_exec ($ch);
2097              curl_close ($ch);
2098              return $content;
2099          } elseif($fd = fopen($url,'rb'))    {
2100              while (!feof($fd))    {
2101                  $content.=fread($fd, 5000);
2102              }
2103              fclose($fd);
2104              return $content;
2105          }
2106      }
2107  
2108      /**
2109       * Writes $content to the file $file
2110       * Usage: 30
2111       *
2112       * @param    string        Filepath to write to
2113       * @param    string        Content to write
2114       * @return    boolean        True if the file was successfully opened and written to.
2115       */
2116  	function writeFile($file,$content)    {
2117          if($fd = fopen($file,'wb'))    {
2118              fwrite( $fd, $content);
2119              fclose( $fd );
2120  
2121              t3lib_div::fixPermissions($file);    // Change the permissions of the file
2122  
2123              return true;
2124          }
2125      }
2126  
2127      /**
2128       * Setting file system mode & group ownership of file
2129       *
2130       * @param    string        Filepath of newly created file
2131       * @return    void
2132       */
2133  	function fixPermissions($file)    {
2134          if (@is_file($file) && TYPO3_OS!='WIN')    {
2135              @chmod($file, octdec($GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask']));        // "@" is there because file is not necessarily OWNED by the user
2136              if($GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'])    {    // skip this if createGroup is empty
2137                  @chgrp($file, $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup']);        // "@" is there because file is not necessarily OWNED by the user
2138              }
2139          }
2140      }
2141  
2142      /**
2143       * Writes $content to a filename in the typo3temp/ folder (and possibly a subfolder...)
2144       * Accepts an additional subdirectory in the file path!
2145       *
2146       * @param    string        Absolute filepath to write to inside "typo3temp/". First part of this string must match PATH_site."typo3temp/"
2147       * @param    string        Content string to write
2148       * @return    string        Returns false on success, otherwise an error string telling about the problem.
2149       */
2150  	function writeFileToTypo3tempDir($filepath,$content)    {
2151  
2152              // Parse filepath into directory and basename:
2153          $fI = pathinfo($filepath);
2154          $fI['dirname'].= '/';
2155  
2156              // Check parts:
2157          if (t3lib_div::validPathStr($filepath) && $fI['basename'] && strlen($fI['basename'])<60)    {
2158              if (defined('PATH_site'))    {
2159                  $dirName = PATH_site.'typo3temp/';    // Setting main temporary directory name (standard)
2160                  if (@is_dir($dirName))    {
2161                      if (t3lib_div::isFirstPartOfStr($fI['dirname'],$dirName))    {
2162  
2163                              // Checking if the "subdir" is found:
2164                          $subdir = substr($fI['dirname'],strlen(