|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00205 // a tabulator 00206 define('TAB', chr(9)); 00207 // a linefeed 00208 define('LF', chr(10)); 00209 // a carriage return 00210 define('CR', chr(13)); 00211 // a CR-LF combination 00212 define('CRLF', CR . LF); 00213 00230 final class t3lib_div { 00231 00232 // Severity constants used by t3lib_div::sysLog() 00233 const SYSLOG_SEVERITY_INFO = 0; 00234 const SYSLOG_SEVERITY_NOTICE = 1; 00235 const SYSLOG_SEVERITY_WARNING = 2; 00236 const SYSLOG_SEVERITY_ERROR = 3; 00237 const SYSLOG_SEVERITY_FATAL = 4; 00238 00245 protected static $singletonInstances = array(); 00246 00252 protected static $nonSingletonInstances = array(); 00253 00259 protected static $finalClassNameRegister = array(); 00260 00261 /************************* 00262 * 00263 * GET/POST Variables 00264 * 00265 * Background: 00266 * Input GET/POST variables in PHP may have their quotes escaped with "\" or not depending on configuration. 00267 * TYPO3 has always converted quotes to BE escaped if the configuration told that they would not be so. 00268 * But the clean solution is that quotes are never escaped and that is what the functions below offers. 00269 * Eventually TYPO3 should provide this in the global space as well. 00270 * In the transitional phase (or forever..?) we need to encourage EVERY to read and write GET/POST vars through the API functions below. 00271 * 00272 *************************/ 00273 00284 public static function _GP($var) { 00285 if (empty($var)) { 00286 return; 00287 } 00288 $value = isset($_POST[$var]) ? $_POST[$var] : $_GET[$var]; 00289 if (isset($value)) { 00290 if (is_array($value)) { 00291 self::stripSlashesOnArray($value); 00292 } else { 00293 $value = stripslashes($value); 00294 } 00295 } 00296 return $value; 00297 } 00298 00305 public static function _GPmerged($parameter) { 00306 $postParameter = (isset($_POST[$parameter]) && is_array($_POST[$parameter])) ? $_POST[$parameter] : array(); 00307 $getParameter = (isset($_GET[$parameter]) && is_array($_GET[$parameter])) ? $_GET[$parameter] : array(); 00308 00309 $mergedParameters = self::array_merge_recursive_overrule($getParameter, $postParameter); 00310 self::stripSlashesOnArray($mergedParameters); 00311 00312 return $mergedParameters; 00313 } 00314 00324 public static function _GET($var = NULL) { 00325 $value = ($var === NULL) ? $_GET : (empty($var) ? NULL : $_GET[$var]); 00326 if (isset($value)) { // Removes slashes since TYPO3 has added them regardless of magic_quotes setting. 00327 if (is_array($value)) { 00328 self::stripSlashesOnArray($value); 00329 } else { 00330 $value = stripslashes($value); 00331 } 00332 } 00333 return $value; 00334 } 00335 00345 public static function _POST($var = NULL) { 00346 $value = ($var === NULL) ? $_POST : (empty($var) ? NULL : $_POST[$var]); 00347 if (isset($value)) { // Removes slashes since TYPO3 has added them regardless of magic_quotes setting. 00348 if (is_array($value)) { 00349 self::stripSlashesOnArray($value); 00350 } else { 00351 $value = stripslashes($value); 00352 } 00353 } 00354 return $value; 00355 } 00356 00375 public static function _GETset($inputGet, $key = '') { 00376 // adds slashes since TYPO3 standard currently is that slashes 00377 // must be applied (regardless of magic_quotes setting) 00378 if (is_array($inputGet)) { 00379 self::addSlashesOnArray($inputGet); 00380 } else { 00381 $inputGet = addslashes($inputGet); 00382 } 00383 00384 if ($key != '') { 00385 if (strpos($key, '|') !== FALSE) { 00386 $pieces = explode('|', $key); 00387 $newGet = array(); 00388 $pointer =& $newGet; 00389 foreach ($pieces as $piece) { 00390 $pointer =& $pointer[$piece]; 00391 } 00392 $pointer = $inputGet; 00393 $mergedGet = self::array_merge_recursive_overrule( 00394 $_GET, $newGet 00395 ); 00396 00397 $_GET = $mergedGet; 00398 $GLOBALS['HTTP_GET_VARS'] = $mergedGet; 00399 } else { 00400 $_GET[$key] = $inputGet; 00401 $GLOBALS['HTTP_GET_VARS'][$key] = $inputGet; 00402 } 00403 } elseif (is_array($inputGet)) { 00404 $_GET = $inputGet; 00405 $GLOBALS['HTTP_GET_VARS'] = $inputGet; 00406 } 00407 } 00408 00420 public static function GPvar($var, $strip = 0) { 00421 self::logDeprecatedFunction(); 00422 00423 if (empty($var)) { 00424 return; 00425 } 00426 $value = isset($_POST[$var]) ? $_POST[$var] : $_GET[$var]; 00427 if (isset($value) && is_string($value)) { 00428 $value = stripslashes($value); 00429 } // 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. 00430 if ($strip && isset($value) && is_array($value)) { 00431 self::stripSlashesOnArray($value); 00432 } 00433 return $value; 00434 } 00435 00445 public static function GParrayMerged($var) { 00446 self::logDeprecatedFunction(); 00447 00448 return self::_GPmerged($var); 00449 } 00450 00460 public static function removeXSS($string) { 00461 require_once(PATH_typo3 . 'contrib/RemoveXSS/RemoveXSS.php'); 00462 $string = RemoveXSS::process($string); 00463 return $string; 00464 } 00465 00466 00467 /************************* 00468 * 00469 * IMAGE FUNCTIONS 00470 * 00471 *************************/ 00472 00473 00493 public static function gif_compress($theFile, $type) { 00494 $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX']; 00495 $returnCode = ''; 00496 if ($gfxConf['gif_compress'] && strtolower(substr($theFile, -4, 4)) == '.gif') { // GIF... 00497 if (($type == 'IM' || !$type) && $gfxConf['im'] && $gfxConf['im_path_lzw']) { // IM 00498 // use temporary file to prevent problems with read and write lock on same file on network file systems 00499 $temporaryName = dirname($theFile) . '/' . md5(uniqid()) . '.gif'; 00500 // rename could fail, if a simultaneous thread is currently working on the same thing 00501 if (@rename($theFile, $temporaryName)) { 00502 $cmd = self::imageMagickCommand('convert', '"' . $temporaryName . '" "' . $theFile . '"', $gfxConf['im_path_lzw']); 00503 t3lib_utility_Command::exec($cmd); 00504 unlink($temporaryName); 00505 } 00506 00507 $returnCode = 'IM'; 00508 if (@is_file($theFile)) { 00509 self::fixPermissions($theFile); 00510 } 00511 } elseif (($type == 'GD' || !$type) && $gfxConf['gdlib'] && !$gfxConf['gdlib_png']) { // GD 00512 $tempImage = imageCreateFromGif($theFile); 00513 imageGif($tempImage, $theFile); 00514 imageDestroy($tempImage); 00515 $returnCode = 'GD'; 00516 if (@is_file($theFile)) { 00517 self::fixPermissions($theFile); 00518 } 00519 } 00520 } 00521 return $returnCode; 00522 } 00523 00532 public static function png_to_gif_by_imagemagick($theFile) { 00533 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif'] 00534 && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] 00535 && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'] 00536 && strtolower(substr($theFile, -4, 4)) == '.png' 00537 && @is_file($theFile)) { // IM 00538 $newFile = substr($theFile, 0, -4) . '.gif'; 00539 $cmd = self::imageMagickCommand('convert', '"' . $theFile . '" "' . $newFile . '"', $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']); 00540 t3lib_utility_Command::exec($cmd); 00541 $theFile = $newFile; 00542 if (@is_file($newFile)) { 00543 self::fixPermissions($newFile); 00544 } 00545 // 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!! 00546 } 00547 return $theFile; 00548 } 00549 00559 public static function read_png_gif($theFile, $output_png = 0) { 00560 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] && @is_file($theFile)) { 00561 $ext = strtolower(substr($theFile, -4, 4)); 00562 if ( 00563 ((string) $ext == '.png' && $output_png) || 00564 ((string) $ext == '.gif' && !$output_png) 00565 ) { 00566 return $theFile; 00567 } else { 00568 $newFile = PATH_site . 'typo3temp/readPG_' . md5($theFile . '|' . filemtime($theFile)) . ($output_png ? '.png' : '.gif'); 00569 $cmd = self::imageMagickCommand('convert', '"' . $theFile . '" "' . $newFile . '"', $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path']); 00570 t3lib_utility_Command::exec($cmd); 00571 if (@is_file($newFile)) { 00572 self::fixPermissions($newFile); 00573 return $newFile; 00574 } 00575 } 00576 } 00577 } 00578 00579 00580 /************************* 00581 * 00582 * STRING FUNCTIONS 00583 * 00584 *************************/ 00585 00599 public static function fixed_lgd($string, $origChars, $preStr = '...') { 00600 self::logDeprecatedFunction(); 00601 00602 $chars = abs($origChars); 00603 if ($chars >= 4) { 00604 if (strlen($string) > $chars) { 00605 return $origChars < 0 ? 00606 $preStr . trim(substr($string, -($chars - 3))) : 00607 trim(substr($string, 0, $chars - 3)) . $preStr; 00608 } 00609 } 00610 return $string; 00611 } 00612 00626 public static function fixed_lgd_pre($string, $chars) { 00627 self::logDeprecatedFunction(); 00628 00629 return strrev(self::fixed_lgd(strrev($string), $chars)); 00630 } 00631 00641 public static function fixed_lgd_cs($string, $chars, $appendString = '...') { 00642 if (is_object($GLOBALS['LANG'])) { 00643 return $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet, $string, $chars, $appendString); 00644 } elseif (is_object($GLOBALS['TSFE'])) { 00645 $charSet = ($GLOBALS['TSFE']->renderCharset != '' ? $GLOBALS['TSFE']->renderCharset : $GLOBALS['TSFE']->defaultCharSet); 00646 return $GLOBALS['TSFE']->csConvObj->crop($charSet, $string, $chars, $appendString); 00647 } else { 00648 // this case should not happen 00649 $csConvObj = self::makeInstance('t3lib_cs'); 00650 return $csConvObj->crop('iso-8859-1', $string, $chars, $appendString); 00651 } 00652 } 00653 00664 public static function breakTextForEmail($str, $implChar = LF, $charWidth = 76) { 00665 self::logDeprecatedFunction(); 00666 00667 $lines = explode(LF, $str); 00668 $outArr = array(); 00669 foreach ($lines as $lStr) { 00670 $outArr[] = self::breakLinesForEmail($lStr, $implChar, $charWidth); 00671 } 00672 return implode(LF, $outArr); 00673 } 00674 00685 public static function breakLinesForEmail($str, $implChar = LF, $charWidth = 76) { 00686 $lines = array(); 00687 $l = $charWidth; 00688 $p = 0; 00689 while (strlen($str) > $p) { 00690 $substr = substr($str, $p, $l); 00691 if (strlen($substr) == $l) { 00692 $count = count(explode(' ', trim(strrev($substr)))); 00693 if ($count > 1) { // OK... 00694 $parts = explode(' ', strrev($substr), 2); 00695 $theLine = strrev($parts[1]); 00696 } else { 00697 $afterParts = explode(' ', substr($str, $l + $p), 2); 00698 $theLine = $substr . $afterParts[0]; 00699 } 00700 if (!strlen($theLine)) { 00701 break; 00702 } // Error, because this would keep us in an endless loop. 00703 } else { 00704 $theLine = $substr; 00705 } 00706 00707 $lines[] = trim($theLine); 00708 $p += strlen($theLine); 00709 if (!trim(substr($str, $p, $l))) { 00710 break; 00711 } // added... 00712 } 00713 return implode($implChar, $lines); 00714 } 00715 00725 public static function cmpIP($baseIP, $list) { 00726 $list = trim($list); 00727 if ($list === '') { 00728 return FALSE; 00729 } elseif ($list === '*') { 00730 return TRUE; 00731 } 00732 if (strpos($baseIP, ':') !== FALSE && self::validIPv6($baseIP)) { 00733 return self::cmpIPv6($baseIP, $list); 00734 } else { 00735 return self::cmpIPv4($baseIP, $list); 00736 } 00737 } 00738 00746 public static function cmpIPv4($baseIP, $list) { 00747 $IPpartsReq = explode('.', $baseIP); 00748 if (count($IPpartsReq) == 4) { 00749 $values = self::trimExplode(',', $list, 1); 00750 00751 foreach ($values as $test) { 00752 list($test, $mask) = explode('/', $test); 00753 00754 if (intval($mask)) { 00755 // "192.168.3.0/24" 00756 $lnet = ip2long($test); 00757 $lip = ip2long($baseIP); 00758 $binnet = str_pad(decbin($lnet), 32, '0', STR_PAD_LEFT); 00759 $firstpart = substr($binnet, 0, $mask); 00760 $binip = str_pad(decbin($lip), 32, '0', STR_PAD_LEFT); 00761 $firstip = substr($binip, 0, $mask); 00762 $yes = (strcmp($firstpart, $firstip) == 0); 00763 } else { 00764 // "192.168.*.*" 00765 $IPparts = explode('.', $test); 00766 $yes = 1; 00767 foreach ($IPparts as $index => $val) { 00768 $val = trim($val); 00769 if (strcmp($val, '*') && strcmp($IPpartsReq[$index], $val)) { 00770 $yes = 0; 00771 } 00772 } 00773 } 00774 if ($yes) { 00775 return TRUE; 00776 } 00777 } 00778 } 00779 return FALSE; 00780 } 00781 00789 public static function cmpIPv6($baseIP, $list) { 00790 $success = FALSE; // Policy default: Deny connection 00791 $baseIP = self::normalizeIPv6($baseIP); 00792 00793 $values = self::trimExplode(',', $list, 1); 00794 foreach ($values as $test) { 00795 $testList = explode('/', $test); 00796 if (count($testList) == 2) { 00797 list($test, $mask) = $testList; 00798 } else { 00799 $mask = FALSE; 00800 } 00801 00802 if (self::validIPv6($test)) { 00803 $test = self::normalizeIPv6($test); 00804 $maskInt = intval($mask) ? intval($mask) : 128; 00805 if ($mask === '0') { // special case; /0 is an allowed mask - equals a wildcard 00806 $success = TRUE; 00807 } elseif ($maskInt == 128) { 00808 $success = ($test === $baseIP); 00809 } else { 00810 $testBin = self::IPv6Hex2Bin($test); 00811 $baseIPBin = self::IPv6Hex2Bin($baseIP); 00812 $success = TRUE; 00813 00814 // modulo is 0 if this is a 8-bit-boundary 00815 $maskIntModulo = $maskInt % 8; 00816 $numFullCharactersUntilBoundary = intval($maskInt / 8); 00817 00818 if (substr($testBin, 0, $numFullCharactersUntilBoundary) !== substr($baseIPBin, 0, $numFullCharactersUntilBoundary)) { 00819 $success = FALSE; 00820 } elseif ($maskIntModulo > 0) { 00821 // if not an 8-bit-boundary, check bits of last character 00822 $testLastBits = str_pad(decbin(ord(substr($testBin, $numFullCharactersUntilBoundary, 1))), 8, '0', STR_PAD_LEFT); 00823 $baseIPLastBits = str_pad(decbin(ord(substr($baseIPBin, $numFullCharactersUntilBoundary, 1))), 8, '0', STR_PAD_LEFT); 00824 if (strncmp($testLastBits, $baseIPLastBits, $maskIntModulo) != 0) { 00825 $success = FALSE; 00826 } 00827 } 00828 } 00829 } 00830 if ($success) { 00831 return TRUE; 00832 } 00833 } 00834 return FALSE; 00835 } 00836 00844 public static function IPv6Hex2Bin($hex) { 00845 // normalized representation has 39 characters (0000:0000:0000:0000:0000:0000:0000:0000) 00846 if (strlen($hex) < 39) { 00847 $hex = self::normalizeIPv6($hex); 00848 } 00849 $hex = str_replace(':', '', $hex); // Replace colon to nothing 00850 $bin = pack("H*" , $hex); 00851 return $bin; 00852 } 00853 00860 public static function normalizeIPv6($address) { 00861 $normalizedAddress = ''; 00862 $stageOneAddress = ''; 00863 00864 $chunks = explode('::', $address); // Count 2 if if address has hidden zero blocks 00865 if (count($chunks) == 2) { 00866 $chunksLeft = explode(':', $chunks[0]); 00867 $chunksRight = explode(':', $chunks[1]); 00868 $left = count($chunksLeft); 00869 $right = count($chunksRight); 00870 00871 // Special case: leading zero-only blocks count to 1, should be 0 00872 if ($left == 1 && strlen($chunksLeft[0]) == 0) { 00873 $left = 0; 00874 } 00875 00876 $hiddenBlocks = 8 - ($left + $right); 00877 $hiddenPart = ''; 00878 $h = 0; 00879 while ($h < $hiddenBlocks) { 00880 $hiddenPart .= '0000:'; 00881 $h++; 00882 } 00883 00884 if ($left == 0) { 00885 $stageOneAddress = $hiddenPart . $chunks[1]; 00886 } else { 00887 $stageOneAddress = $chunks[0] . ':' . $hiddenPart . $chunks[1]; 00888 } 00889 } else { 00890 $stageOneAddress = $address; 00891 } 00892 00893 // normalize the blocks: 00894 $blocks = explode(':', $stageOneAddress); 00895 $divCounter = 0; 00896 foreach ($blocks as $block) { 00897 $tmpBlock = ''; 00898 $i = 0; 00899 $hiddenZeros = 4 - strlen($block); 00900 while ($i < $hiddenZeros) { 00901 $tmpBlock .= '0'; 00902 $i++; 00903 } 00904 $normalizedAddress .= $tmpBlock . $block; 00905 if ($divCounter < 7) { 00906 $normalizedAddress .= ':'; 00907 $divCounter++; 00908 } 00909 } 00910 return $normalizedAddress; 00911 } 00912 00921 public static function validIP($ip) { 00922 return (filter_var($ip, FILTER_VALIDATE_IP) !== FALSE); 00923 } 00924 00933 public static function validIPv4($ip) { 00934 return (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== FALSE); 00935 } 00936 00945 public static function validIPv6($ip) { 00946 return (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE); 00947 } 00948 00956 public static function cmpFQDN($baseHost, $list) { 00957 $baseHost = trim($baseHost); 00958 if (empty($baseHost)) { 00959 return FALSE; 00960 } 00961 if (self::validIPv4($baseHost) || self::validIPv6($baseHost)) { 00962 // resolve hostname 00963 // note: this is reverse-lookup and can be randomly set as soon as somebody is able to set 00964 // the reverse-DNS for his IP (security when for example used with REMOTE_ADDR) 00965 $baseHostName = gethostbyaddr($baseHost); 00966 if ($baseHostName === $baseHost) { 00967 // unable to resolve hostname 00968 return FALSE; 00969 } 00970 } else { 00971 $baseHostName = $baseHost; 00972 } 00973 $baseHostNameParts = explode('.', $baseHostName); 00974 00975 $values = self::trimExplode(',', $list, 1); 00976 00977 foreach ($values as $test) { 00978 $hostNameParts = explode('.', $test); 00979 00980 // to match hostNameParts can only be shorter (in case of wildcards) or equal 00981 if (count($hostNameParts) > count($baseHostNameParts)) { 00982 continue; 00983 } 00984 00985 $yes = TRUE; 00986 foreach ($hostNameParts as $index => $val) { 00987 $val = trim($val); 00988 if ($val === '*') { 00989 // wildcard valid for one or more hostname-parts 00990 00991 $wildcardStart = $index + 1; 00992 // wildcard as last/only part always matches, otherwise perform recursive checks 00993 if ($wildcardStart < count($hostNameParts)) { 00994 $wildcardMatched = FALSE; 00995 $tempHostName = implode('.', array_slice($hostNameParts, $index + 1)); 00996 while (($wildcardStart < count($baseHostNameParts)) && (!$wildcardMatched)) { 00997 $tempBaseHostName = implode('.', array_slice($baseHostNameParts, $wildcardStart)); 00998 $wildcardMatched = self::cmpFQDN($tempBaseHostName, $tempHostName); 00999 $wildcardStart++; 01000 } 01001 if ($wildcardMatched) { 01002 // match found by recursive compare 01003 return TRUE; 01004 } else { 01005 $yes = FALSE; 01006 } 01007 } 01008 } elseif ($baseHostNameParts[$index] !== $val) { 01009 // in case of no match 01010 $yes = FALSE; 01011 } 01012 } 01013 if ($yes) { 01014 return TRUE; 01015 } 01016 } 01017 return FALSE; 01018 } 01019 01027 public static function isOnCurrentHost($url) { 01028 return (stripos($url . '/', self::getIndpEnv('TYPO3_REQUEST_HOST') . '/') === 0); 01029 } 01030 01040 public static function inList($list, $item) { 01041 return (strpos(',' . $list . ',', ',' . $item . ',') !== FALSE ? TRUE : FALSE); 01042 } 01043 01052 public static function rmFromList($element, $list) { 01053 $items = explode(',', $list); 01054 foreach ($items as $k => $v) { 01055 if ($v == $element) { 01056 unset($items[$k]); 01057 } 01058 } 01059 return implode(',', $items); 01060 } 01061 01070 public static function expandList($list) { 01071 $items = explode(',', $list); 01072 $list = array(); 01073 foreach ($items as $item) { 01074 $range = explode('-', $item); 01075 if (isset($range[1])) { 01076 $runAwayBrake = 1000; 01077 for ($n = $range[0]; $n <= $range[1]; $n++) { 01078 $list[] = $n; 01079 01080 $runAwayBrake--; 01081 if ($runAwayBrake <= 0) { 01082 break; 01083 } 01084 } 01085 } else { 01086 $list[] = $item; 01087 } 01088 } 01089 return implode(',', $list); 01090 } 01091 01102 public static function intInRange($theInt, $min, $max = 2000000000, $zeroValue = 0) { 01103 // Returns $theInt as an integer in the integerspace from $min to $max 01104 $theInt = intval($theInt); 01105 if ($zeroValue && !$theInt) { 01106 $theInt = $zeroValue; 01107 } // If the input value is zero after being converted to integer, zeroValue may set another default value for it. 01108 if ($theInt < $min) { 01109 $theInt = $min; 01110 } 01111 if ($theInt > $max) { 01112 $theInt = $max; 01113 } 01114 return $theInt; 01115 } 01116 01124 public static function intval_positive($theInt) { 01125 $theInt = intval($theInt); 01126 if ($theInt < 0) { 01127 $theInt = 0; 01128 } 01129 return $theInt; 01130 } 01131 01142 public static function int_from_ver($verNumberStr) { 01143 $verParts = explode('.', $verNumberStr); 01144 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)); 01145 } 01146 01155 public static function compat_version($verNumberStr) { 01156 global $TYPO3_CONF_VARS; 01157 $currVersionStr = $TYPO3_CONF_VARS['SYS']['compat_version'] ? $TYPO3_CONF_VARS['SYS']['compat_version'] : TYPO3_branch; 01158 01159 if (self::int_from_ver($currVersionStr) < self::int_from_ver($verNumberStr)) { 01160 return FALSE; 01161 } else { 01162 return TRUE; 01163 } 01164 } 01165 01173 public static function md5int($str) { 01174 return hexdec(substr(md5($str), 0, 7)); 01175 } 01176 01186 public static function shortMD5($input, $len = 10) { 01187 return substr(md5($input), 0, $len); 01188 } 01189 01196 public static function hmac($input) { 01197 $hashAlgorithm = 'sha1'; 01198 $hashBlocksize = 64; 01199 $hmac = ''; 01200 01201 if (extension_loaded('hash') && function_exists('hash_hmac') && function_exists('hash_algos') && in_array($hashAlgorithm, hash_algos())) { 01202 $hmac = hash_hmac($hashAlgorithm, $input, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']); 01203 } else { 01204 // outer padding 01205 $opad = str_repeat(chr(0x5C), $hashBlocksize); 01206 // innner padding 01207 $ipad = str_repeat(chr(0x36), $hashBlocksize); 01208 if (strlen($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']) > $hashBlocksize) { 01209 // keys longer than blocksize are shorten 01210 $key = str_pad(pack('H*', call_user_func($hashAlgorithm, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])), $hashBlocksize, chr(0x00)); 01211 } else { 01212 // keys shorter than blocksize are zero-padded 01213 $key = str_pad($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], $hashBlocksize, chr(0x00)); 01214 } 01215 $hmac = call_user_func($hashAlgorithm, ($key ^ $opad) . pack('H*', call_user_func($hashAlgorithm, ($key ^ $ipad) . $input))); 01216 } 01217 return $hmac; 01218 } 01219 01229 public static function uniqueList($in_list, $secondParameter = NULL) { 01230 if (is_array($in_list)) { 01231 throw new InvalidArgumentException( 01232 'TYPO3 Fatal Error: t3lib_div::uniqueList() does NOT support array arguments anymore! Only string comma lists!', 01233 1270853885 01234 ); 01235 } 01236 if (isset($secondParameter)) { 01237 throw new InvalidArgumentException( 01238 'TYPO3 Fatal Error: t3lib_div::uniqueList() does NOT support more than a single argument value anymore. You have specified more than one!', 01239 1270853886 01240 ); 01241 } 01242 01243 return implode(',', array_unique(self::trimExplode(',', $in_list, 1))); 01244 } 01245 01253 public static function split_fileref($fileref) { 01254 $reg = array(); 01255 if (preg_match('/(.*\/)(.*)$/', $fileref, $reg)) { 01256 $info['path'] = $reg[1]; 01257 $info['file'] = $reg[2]; 01258 } else { 01259 $info['path'] = ''; 01260 $info['file'] = $fileref; 01261 } 01262 01263 $reg = ''; 01264 if (!is_dir($fileref) && preg_match('/(.*)\.([^\.]*$)/', $info['file'], $reg)) { 01265 $info['filebody'] = $reg[1]; 01266 $info['fileext'] = strtolower($reg[2]); 01267 $info['realFileext'] = $reg[2]; 01268 } else { 01269 $info['filebody'] = $info['file']; 01270 $info['fileext'] = ''; 01271 } 01272 reset($info); 01273 return $info; 01274 } 01275 01292 public static function dirname($path) { 01293 $p = self::revExplode('/', $path, 2); 01294 return count($p) == 2 ? $p[0] : ''; 01295 } 01296 01308 public static function modifyHTMLColor($color, $R, $G, $B) { 01309 // This takes a hex-color (# included!) and adds $R, $G and $B to the HTML-color (format: #xxxxxx) and returns the new color 01310 $nR = self::intInRange(hexdec(substr($color, 1, 2)) + $R, 0, 255); 01311 $nG = self::intInRange(hexdec(substr($color, 3, 2)) + $G, 0, 255); 01312 $nB = self::intInRange(hexdec(substr($color, 5, 2)) + $B, 0, 255); 01313 return '#' . 01314 substr('0' . dechex($nR), -2) . 01315 substr('0' . dechex($nG), -2) . 01316 substr('0' . dechex($nB), -2); 01317 } 01318 01328 public static function modifyHTMLColorAll($color, $all) { 01329 return self::modifyHTMLColor($color, $all, $all, $all); 01330 } 01331 01340 public static function rm_endcomma($string) { 01341 self::logDeprecatedFunction(); 01342 01343 return rtrim($string, ','); 01344 } 01345 01355 public static function danish_strtoupper($string) { 01356 self::logDeprecatedFunction(); 01357 01358 $value = strtoupper($string); 01359 return strtr($value, array( 01360 chr(225) => chr(193), 01361 chr(233) => chr(201), 01362 chr(250) => chr(218), 01363 chr(237) => chr(205), 01364 chr(226) => chr(196), 01365 chr(234) => chr(203), 01366 chr(251) => chr(220), 01367 chr(244) => chr(214), 01368 chr(238) => chr(207), 01369 chr(230) => chr(198), 01370 chr(248) => chr(216), 01371 chr(229) => chr(197), 01372 chr(228) => chr(196), 01373 chr(246) => chr(214), 01374 chr(252) => chr(220), 01375 )); 01376 } 01377 01388 public static function convUmlauts($str) { 01389 self::logDeprecatedFunction(); 01390 01391 $pattern = array(chr(228), chr(196), chr(246), chr(214), chr(252), chr(220), chr(223), chr(229), chr(197), chr(248), chr(216), chr(230), chr(198)); 01392 $replace = array('ae', 'Ae', 'oe', 'Oe', 'ue', 'Ue', 'ss', 'aa', 'AA', 'oe', 'OE', 'ae', 'AE'); 01393 return str_replace($pattern, $replace, $str); 01394 } 01395 01402 public static function testInt($var) { 01403 if ($var === '') { 01404 return FALSE; 01405 } 01406 return (string) intval($var) === (string) $var; 01407 } 01408 01417 public static function isFirstPartOfStr($str, $partStr) { 01418 return $partStr != '' && strpos((string) $str, (string) $partStr, 0) === 0; 01419 } 01420 01429 public static function formatSize($sizeInBytes, $labels = '') { 01430 01431 // Set labels: 01432 if (strlen($labels) == 0) { 01433 $labels = ' | K| M| G'; 01434 } else { 01435 $labels = str_replace('"', '', $labels); 01436 } 01437 $labelArr = explode('|', $labels); 01438 01439 // Find size: 01440 if ($sizeInBytes > 900) { 01441 if ($sizeInBytes > 900000000) { // GB 01442 $val = $sizeInBytes / (1024 * 1024 * 1024); 01443 return number_format($val, (($val < 20) ? 1 : 0), '.', '') . $labelArr[3]; 01444 } 01445 elseif ($sizeInBytes > 900000) { // MB 01446 $val = $sizeInBytes / (1024 * 1024); 01447 return number_format($val, (($val < 20) ? 1 : 0), '.', '') . $labelArr[2]; 01448 } else { // KB 01449 $val = $sizeInBytes / (1024); 01450 return number_format($val, (($val < 20) ? 1 : 0), '.', '') . $labelArr[1]; 01451 } 01452 } else { // Bytes 01453 return $sizeInBytes . $labelArr[0]; 01454 } 01455 } 01456 01464 public static function convertMicrotime($microtime) { 01465 $parts = explode(' ', $microtime); 01466 return round(($parts[0] + $parts[1]) * 1000); 01467 } 01468 01478 public static function splitCalc($string, $operators) { 01479 $res = Array(); 01480 $sign = '+'; 01481 while ($string) { 01482 $valueLen = strcspn($string, $operators); 01483 $value = substr($string, 0, $valueLen); 01484 $res[] = Array($sign, trim($value)); 01485 $sign = substr($string, $valueLen, 1); 01486 $string = substr($string, $valueLen + 1); 01487 } 01488 reset($res); 01489 return $res; 01490 } 01491 01500 public static function calcPriority($string) { 01501 $string = preg_replace('/[[:space:]]*/', '', $string); // removing all whitespace 01502 $string = '+' . $string; // Ensuring an operator for the first entrance 01503 $qm = '\*\/\+-^%'; 01504 $regex = '([' . $qm . '])([' . $qm . ']?[0-9\.]*)'; 01505 // split the expression here: 01506 $reg = array(); 01507 preg_match_all('/' . $regex . '/', $string, $reg); 01508 01509 reset($reg[2]); 01510 $number = 0; 01511 $Msign = '+'; 01512 $err = ''; 01513 $buffer = doubleval(current($reg[2])); 01514 next($reg[2]); // Advance pointer 01515 01516 while (list($k, $v) = each($reg[2])) { 01517 $v = doubleval($v); 01518 $sign = $reg[1][$k]; 01519 if ($sign == '+' || $sign == '-') { 01520 $number = $Msign == '-' ? $number -= $buffer : $number += $buffer; 01521 $Msign = $sign; 01522 $buffer = $v; 01523 } else { 01524 if ($sign == '/') { 01525 if ($v) { 01526 $buffer /= $v; 01527 } else { 01528 $err = 'dividing by zero'; 01529 } 01530 } 01531 if ($sign == '%') { 01532 if ($v) { 01533 $buffer %= $v; 01534 } else { 01535 $err = 'dividing by zero'; 01536 } 01537 } 01538 if ($sign == '*') { 01539 $buffer *= $v; 01540 } 01541 if ($sign == '^') { 01542 $buffer = pow($buffer, $v); 01543 } 01544 } 01545 } 01546 $number = $Msign == '-' ? $number -= $buffer : $number += $buffer; 01547 return $err ? 'ERROR: ' . $err : $number; 01548 } 01549 01558 public static function calcParenthesis($string) { 01559 $securC = 100; 01560 do { 01561 $valueLenO = strcspn($string, '('); 01562 $valueLenC = strcspn($string, ')'); 01563 if ($valueLenC == strlen($string) || $valueLenC < $valueLenO) { 01564 $value = self::calcPriority(substr($string, 0, $valueLenC)); 01565 $string = $value . substr($string, $valueLenC + 1); 01566 return $string; 01567 } else { 01568 $string = substr($string, 0, $valueLenO) . self::calcParenthesis(substr($string, $valueLenO + 1)); 01569 } 01570 // Security: 01571 $securC--; 01572 if ($securC <= 0) { 01573 break; 01574 } 01575 } while ($valueLenO < strlen($string)); 01576 return $string; 01577 } 01578 01586 public static function htmlspecialchars_decode($value) { 01587 $value = str_replace('>', '>', $value); 01588 $value = str_replace('<', '<', $value); 01589 $value = str_replace('"', '"', $value); 01590 $value = str_replace('&', '&', $value); 01591 return $value; 01592 } 01593 01601 public static function deHSCentities($str) { 01602 return preg_replace('/&([#[:alnum:]]*;)/', '&\1', $str); 01603 } 01604 01614 public static function slashJS($string, $extended = 0, $char = "'") { 01615 if ($extended) { 01616 $string = str_replace("\\", "\\\\", $string); 01617 } 01618 return str_replace($char, "\\" . $char, $string); 01619 } 01620 01629 public static function rawUrlEncodeJS($str) { 01630 return str_replace('%20', ' ', rawurlencode($str)); 01631 } 01632 01641 public static function rawUrlEncodeFP($str) { 01642 return str_replace('%2F', '/', rawurlencode($str)); 01643 } 01644 01652 public static function validEmail($email) { 01653 // enforce maximum length to prevent libpcre recursion crash bug #52929 in PHP 01654 // fixed in PHP 5.2+ later than Sept 2010; length restriction per SMTP RFC 2821 01655 if (strlen($email) > 320) { 01656 return FALSE; 01657 } 01658 return (filter_var($email, FILTER_VALIDATE_EMAIL) !== FALSE); 01659 } 01660 01673 public static function isBrokenEmailEnvironment() { 01674 return TYPO3_OS == 'WIN' || (FALSE !== strpos(ini_get('sendmail_path'), 'mini_sendmail')); 01675 } 01676 01684 public static function normalizeMailAddress($address) { 01685 if (self::isBrokenEmailEnvironment() && FALSE !== ($pos1 = strrpos($address, '<'))) { 01686 $pos2 = strpos($address, '>', $pos1); 01687 $address = substr($address, $pos1 + 1, ($pos2 ? $pos2 : strlen($address)) - $pos1 - 1); 01688 } 01689 return $address; 01690 } 01691 01701 public static function formatForTextarea($content) { 01702 return LF . htmlspecialchars($content); 01703 } 01704 01714 public static function strtoupper($str) { 01715 return strtr((string) $str, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'); 01716 } 01717 01727 public static function strtolower($str) { 01728 return strtr((string) $str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); 01729 } 01730 01739 public static function generateRandomBytes($count) { 01740 $output = ''; 01741 // /dev/urandom is available on many *nix systems and is considered 01742 // the best commonly available pseudo-random source. 01743 if (TYPO3_OS != 'WIN' && ($fh = @fopen('/dev/urandom', 'rb'))) { 01744 $output = fread($fh, $count); 01745 fclose($fh); 01746 } elseif (TYPO3_OS == 'WIN') { 01747 if (class_exists('COM')) { 01748 try { 01749 $com = new COM('CAPICOM.Utilities.1'); 01750 $output = base64_decode($com->GetRandom($count, 0)); 01751 } catch (Exception $e) { 01752 // CAPICOM not installed 01753 } 01754 } 01755 if ($output === '' && version_compare(PHP_VERSION, '5.3.0', '>=')) { 01756 if (function_exists('mcrypt_create_iv')) { 01757 $output = mcrypt_create_iv($count, MCRYPT_DEV_URANDOM); 01758 } elseif (function_exists('openssl_random_pseudo_bytes')) { 01759 $isStrong = NULL; 01760 $output = openssl_random_pseudo_bytes($count, $isStrong); 01761 // skip ssl since it wasn't using the strong algo 01762 if ($isStrong !== TRUE) { 01763 $output = ''; 01764 } 01765 } 01766 } 01767 } 01768 01769 // fallback if other random byte generation failed until now 01770 if (!isset($output{$count - 1})) { 01771 // We initialize with the somewhat random. 01772 $randomState = $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] 01773 . base_convert(memory_get_usage() % pow(10, 6), 10, 2) 01774 . microtime() . uniqid('') . getmypid(); 01775 while (!isset($output{$count - 1})) { 01776 $randomState = sha1(microtime() . mt_rand() . $randomState); 01777 $output .= sha1(mt_rand() . $randomState, TRUE); 01778 } 01779 $output = substr($output, strlen($output) - $count, $count); 01780 } 01781 return $output; 01782 } 01783 01790 public static function getRandomHexString($count) { 01791 return substr(bin2hex(self::generateRandomBytes(intval(($count + 1) / 2))), 0, $count); 01792 } 01793 01801 public static function underscoredToUpperCamelCase($string) { 01802 $upperCamelCase = str_replace(' ', '', ucwords(str_replace('_', ' ', self::strtolower($string)))); 01803 return $upperCamelCase; 01804 } 01805 01813 public static function underscoredToLowerCamelCase($string) { 01814 $upperCamelCase = str_replace(' ', '', ucwords(str_replace('_', ' ', self::strtolower($string)))); 01815 $lowerCamelCase = self::lcfirst($upperCamelCase); 01816 return $lowerCamelCase; 01817 } 01818 01826 public static function camelCaseToLowerCaseUnderscored($string) { 01827 return self::strtolower(preg_replace('/(?<=\w)([A-Z])/', '_\\1', $string)); 01828 } 01829 01837 public static function lcfirst($string) { 01838 return self::strtolower(substr($string, 0, 1)) . substr($string, 1); 01839 } 01840 01847 public static function isValidUrl($url) { 01848 return (filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED) !== FALSE); 01849 } 01850 01851 01852 /************************* 01853 * 01854 * ARRAY FUNCTIONS 01855 * 01856 *************************/ 01857 01881 public static function inArray(array $in_array, $item) { 01882 foreach ($in_array as $val) { 01883 if (!is_array($val) && !strcmp($val, $item)) { 01884 return TRUE; 01885 } 01886 } 01887 return FALSE; 01888 } 01889 01903 public static function intExplode($delimiter, $string, $onlyNonEmptyValues = FALSE, $limit = 0) { 01904 $explodedValues = self::trimExplode($delimiter, $string, $onlyNonEmptyValues, $limit); 01905 return array_map('intval', $explodedValues); 01906 } 01907 01918 public static function revExplode($delimiter, $string, $count = 0) { 01919 $explodedValues = explode($delimiter, strrev($string), $count); 01920 $explodedValues = array_map('strrev', $explodedValues); 01921 return array_reverse($explodedValues); 01922 } 01923 01940 public static function trimExplode($delim, $string, $removeEmptyValues = FALSE, $limit = 0) { 01941 $explodedValues = explode($delim, $string); 01942 01943 $result = array_map('trim', $explodedValues); 01944 01945 if ($removeEmptyValues) { 01946 $temp = array(); 01947 foreach ($result as $value) { 01948 if ($value !== '') { 01949 $temp[] = $value; 01950 } 01951 } 01952 $result = $temp; 01953 } 01954 01955 if ($limit != 0) { 01956 if ($limit < 0) { 01957 $result = array_slice($result, 0, $limit); 01958 } elseif (count($result) > $limit) { 01959 $lastElements = array_slice($result, $limit - 1); 01960 $result = array_slice($result, 0, $limit - 1); 01961 $result[] = implode($delim, $lastElements); 01962 } 01963 } 01964 01965 return $result; 01966 } 01967 01977 public static function uniqueArray(array $valueArray) { 01978 self::logDeprecatedFunction(); 01979 01980 return array_unique($valueArray); 01981 } 01982 01991 public static function removeArrayEntryByValue(array $array, $cmpValue) { 01992 foreach ($array as $k => $v) { 01993 if (is_array($v)) { 01994 $array[$k] = self::removeArrayEntryByValue($v, $cmpValue); 01995 } elseif (!strcmp($v, $cmpValue)) { 01996 unset($array[$k]); 01997 } 01998 } 01999 return $array; 02000 } 02001 02025 public static function keepItemsInArray(array $array, $keepItems, $getValueFunc = NULL) { 02026 if ($array) { 02027 // Convert strings to arrays: 02028 if (is_string($keepItems)) { 02029 $keepItems = self::trimExplode(',', $keepItems); 02030 } 02031 // create_function() returns a string: 02032 if (!is_string($getValueFunc)) { 02033 $getValueFunc = NULL; 02034 } 02035 // Do the filtering: 02036 if (is_array($keepItems) && count($keepItems)) { 02037 foreach ($array as $key => $value) { 02038 // Get the value to compare by using the callback function: 02039 $keepValue = (isset($getValueFunc) ? $getValueFunc($value) : $value); 02040 if (!in_array($keepValue, $keepItems)) { 02041 unset($array[$key]); 02042 } 02043 } 02044 } 02045 } 02046 return $array; 02047 } 02048 02061 public static function implodeArrayForUrl($name, array $theArray, $str = '', $skipBlank = FALSE, $rawurlencodeParamName = FALSE) { 02062 foreach ($theArray as $Akey => $AVal) { 02063 $thisKeyName = $name ? $name . '[' . $Akey . ']' : $Akey; 02064 if (is_array($AVal)) { 02065 $str = self::implodeArrayForUrl($thisKeyName, $AVal, $str, $skipBlank, $rawurlencodeParamName); 02066 } else { 02067 if (!$skipBlank || strcmp($AVal, '')) { 02068 $str .= '&' . ($rawurlencodeParamName ? rawurlencode($thisKeyName) : $thisKeyName) . 02069 '=' . rawurlencode($AVal); 02070 } 02071 } 02072 } 02073 return $str; 02074 } 02075 02084 public static function explodeUrl2Array($string, $multidim = FALSE) { 02085 $output = array(); 02086 if ($multidim) { 02087 parse_str($string, $output); 02088 } else { 02089 $p = explode('&', $string); 02090 foreach ($p as $v) { 02091 if (strlen($v)) { 02092 list($pK, $pV) = explode('=', $v, 2); 02093 $output[rawurldecode($pK)] = rawurldecode($pV); 02094 } 02095 } 02096 } 02097 return $output; 02098 } 02099 02110 public static function compileSelectedGetVarsFromArray($varList, array $getArray, $GPvarAlt = 1) { 02111 $keys = self::trimExplode(',', $varList, 1); 02112 $outArr = array(); 02113 foreach ($keys as $v) { 02114 if (isset($getArray[$v])) { 02115 $outArr[$v] = $getArray[$v]; 02116 } elseif ($GPvarAlt) { 02117 $outArr[$v] = self::_GP($v); 02118 } 02119 } 02120 return $outArr; 02121 } 02122 02133 public static function addSlashesOnArray(array &$theArray) { 02134 foreach ($theArray as &$value) { 02135 if (is_array($value)) { 02136 self::addSlashesOnArray($value); 02137 } else { 02138 $value = addslashes($value); 02139 } 02140 unset($value); 02141 } 02142 reset($theArray); 02143 } 02144 02155 public static function stripSlashesOnArray(array &$theArray) { 02156 foreach ($theArray as &$value) { 02157 if (is_array($value)) { 02158 self::stripSlashesOnArray($value); 02159 } else { 02160 $value = stripslashes($value); 02161 } 02162 unset($value); 02163 } 02164 reset($theArray); 02165 } 02166 02175 public static function slashArray(array $arr, $cmd) { 02176 if ($cmd == 'strip') { 02177 self::stripSlashesOnArray($arr); 02178 } 02179 if ($cmd == 'add') { 02180 self::addSlashesOnArray($arr); 02181 } 02182 return $arr; 02183 } 02184 02190 function remapArrayKeys(&$array, $mappingTable) { 02191 if (is_array($mappingTable)) { 02192 foreach ($mappingTable as $old => $new) { 02193 if ($new && isset($array[$old])) { 02194 $array[$new] = $array[$old]; 02195 unset ($array[$old]); 02196 } 02197 } 02198 } 02199 } 02200 02201 02215 public static function array_merge_recursive_overrule(array $arr0, array $arr1, $notAddKeys = 0, $includeEmtpyValues = TRUE) { 02216 foreach ($arr1 as $key => $val) { 02217 if (is_array($arr0[$key])) { 02218 if (is_array($arr1[$key])) { 02219 $arr0[$key] = self::array_merge_recursive_overrule($arr0[$key], $arr1[$key], $notAddKeys, $includeEmtpyValues); 02220 } 02221 } else { 02222 if ($notAddKeys) { 02223 if (isset($arr0[$key])) { 02224 if ($includeEmtpyValues || $val) { 02225 $arr0[$key] = $val; 02226 } 02227 } 02228 } else { 02229 if ($includeEmtpyValues || $val) { 02230 $arr0[$key] = $val; 02231 } 02232 } 02233 } 02234 } 02235 reset($arr0); 02236 return $arr0; 02237 } 02238 02247 public static function array_merge(array $arr1, array $arr2) { 02248 return $arr2 + $arr1; 02249 } 02250 02259 public static function arrayDiffAssocRecursive(array $array1, array $array2) { 02260 $differenceArray = array(); 02261 foreach ($array1 as $key => $value) { 02262 if (!array_key_exists($key, $array2)) { 02263 $differenceArray[$key] = $value; 02264 } elseif (is_array($value)) { 02265 if (is_array($array2[$key])) { 02266 $differenceArray[$key] = self::arrayDiffAssocRecursive($value, $array2[$key]); 02267 } 02268 } 02269 } 02270 02271 return $differenceArray; 02272 } 02273 02283 public static function csvValues(array $row, $delim = ',', $quote = '"') { 02284 reset($row); 02285 $out = array(); 02286 foreach ($row as $value) { 02287 $out[] = str_replace($quote, $quote . $quote, $value); 02288 } 02289 $str = $quote . implode($quote . $delim . $quote, $out) . $quote; 02290 return $str; 02291 } 02292 02301 public static function array2json(array $jsonArray) { 02302 self::logDeprecatedFunction(); 02303 02304 return json_encode($jsonArray); 02305 } 02306 02314 public static function removeDotsFromTS(array $ts) { 02315 $out = array(); 02316 foreach ($ts as $key => $value) { 02317 if (is_array($value)) { 02318 $key = rtrim($key, '.'); 02319 $out[$key] = self::removeDotsFromTS($value); 02320 } else { 02321 $out[$key] = $value; 02322 } 02323 } 02324 return $out; 02325 } 02326 02333 public static function naturalKeySortRecursive(&$array) { 02334 if (!is_array($array)) { 02335 return FALSE; 02336 } 02337 uksort($array, 'strnatcasecmp'); 02338 foreach ($array as $key => $value) { 02339 self::naturalKeySortRecursive($array[$key]); 02340 } 02341 return TRUE; 02342 } 02343 02344 02345 /************************* 02346 * 02347 * HTML/XML PROCESSING 02348 * 02349 *************************/ 02350 02360 public static function get_tag_attributes($tag) { 02361 $components = self::split_tag_attributes($tag); 02362 $name = ''; // attribute name is stored here 02363 $valuemode = FALSE; 02364 $attributes = array(); 02365 foreach ($components as $key => $val) { 02366 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 02367 if ($valuemode) { 02368 if ($name) { 02369 $attributes[$name] = $val; 02370 $name = ''; 02371 } 02372 } else { 02373 if ($key = strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $val))) { 02374 $attributes[$key] = ''; 02375 $name = $key; 02376 } 02377 } 02378 $valuemode = FALSE; 02379 } else { 02380 $valuemode = TRUE; 02381 } 02382 } 02383 return $attributes; 02384 } 02385 02394 public static function split_tag_attributes($tag) { 02395 $tag_tmp = trim(preg_replace('/^<[^[:space:]]*/', '', trim($tag))); 02396 // Removes any > in the end of the string 02397 $tag_tmp = trim(rtrim($tag_tmp, '>')); 02398 02399 $value = array(); 02400 while (strcmp($tag_tmp, '')) { // Compared with empty string instead , 030102 02401 $firstChar = substr($tag_tmp, 0, 1); 02402 if (!strcmp($firstChar, '"') || !strcmp($firstChar, "'")) { 02403 $reg = explode($firstChar, $tag_tmp, 3); 02404 $value[] = $reg[1]; 02405 $tag_tmp = trim($reg[2]); 02406 } elseif (!strcmp($firstChar, '=')) { 02407 $value[] = '='; 02408 $tag_tmp = trim(substr($tag_tmp, 1)); // Removes = chars. 02409 } else { 02410 // There are '' around the value. We look for the next ' ' or '>' 02411 $reg = preg_split('/[[:space:]=]/', $tag_tmp, 2); 02412 $value[] = trim($reg[0]); 02413 $tag_tmp = trim(substr($tag_tmp, strlen($reg[0]), 1) . $reg[1]); 02414 } 02415 } 02416 reset($value); 02417 return $value; 02418 } 02419 02429 public static function implodeAttributes(array $arr, $xhtmlSafe = FALSE, $dontOmitBlankAttribs = FALSE) { 02430 if ($xhtmlSafe) { 02431 $newArr = array(); 02432 foreach ($arr as $p => $v) { 02433 if (!isset($newArr[strtolower($p)])) { 02434 $newArr[strtolower($p)] = htmlspecialchars($v); 02435 } 02436 } 02437 $arr = $newArr; 02438 } 02439 $list = array(); 02440 foreach ($arr as $p => $v) { 02441 if (strcmp($v, '') || $dontOmitBlankAttribs) { 02442 $list[] = $p . '="' . $v . '"'; 02443 } 02444 } 02445 return implode(' ', $list); 02446 } 02447 02458 public static function implodeParams(array $arr, $xhtmlSafe = FALSE, $dontOmitBlankAttribs = FALSE) { 02459 self::logDeprecatedFunction(); 02460 02461 return self::implodeAttributes($arr, $xhtmlSafe, $dontOmitBlankAttribs); 02462 } 02463 02475 public static function wrapJS($string, $linebreak = TRUE) { 02476 if (trim($string)) { 02477 // <script wrapped in nl? 02478 $cr = $linebreak ? LF : ''; 02479 02480 // remove nl from the beginning 02481 $string = preg_replace('/^\n+/', '', $string); 02482 // re-ident to one tab using the first line as reference 02483 $match = array(); 02484 if (preg_match('/^(\t+)/', $string, $match)) { 02485 $string = str_replace($match[1], TAB, $string); 02486 } 02487 $string = $cr . '<script type="text/javascript"> 02488 /*<![CDATA[*/ 02489 ' . $string . ' 02490 /*]]>*/ 02491 </script>' . $cr; 02492 } 02493 return trim($string); 02494 } 02495 02496 02506 public static function xml2tree($string, $depth = 999) { 02507 $parser = xml_parser_create(); 02508 $vals = array(); 02509 $index = array(); 02510 02511 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 02512 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0); 02513 xml_parse_into_struct($parser, $string, $vals, $index); 02514 02515 if (xml_get_error_code($parser)) { 02516 return 'Line ' . xml_get_current_line_number($parser) . ': ' . xml_error_string(xml_get_error_code($parser)); 02517 } 02518 xml_parser_free($parser); 02519 02520 $stack = array(array()); 02521 $stacktop = 0; 02522 $startPoint = 0; 02523 02524 $tagi = array(); 02525 foreach ($vals as $key => $val) { 02526 $type = $val['type']; 02527 02528 // open tag: 02529 if ($type == 'open' || $type == 'complete') { 02530 $stack[$stacktop++] = $tagi; 02531 02532 if ($depth == $stacktop) { 02533 $startPoint = $key; 02534 } 02535 02536 $tagi = array('tag' => $val['tag']); 02537 02538 if (isset($val['attributes'])) { 02539 $tagi['attrs'] = $val['attributes']; 02540 } 02541 if (isset($val['value'])) { 02542 $tagi['values'][] = $val['value']; 02543 } 02544 } 02545 // finish tag: 02546 if ($type == 'complete' || $type == 'close') { 02547 $oldtagi = $tagi; 02548 $tagi = $stack[--$stacktop]; 02549 $oldtag = $oldtagi['tag']; 02550 unset($oldtagi['tag']); 02551 02552 if ($depth == ($stacktop + 1)) { 02553 if ($key - $startPoint > 0) { 02554 $partArray = array_slice( 02555 $vals, 02556 $startPoint + 1, 02557 $key - $startPoint - 1 02558 ); 02559 #$oldtagi=array('XMLvalue'=>self::xmlRecompileFromStructValArray($partArray)); 02560 $oldtagi['XMLvalue'] = self::xmlRecompileFromStructValArray($partArray); 02561 } else { 02562 $oldtagi['XMLvalue'] = $oldtagi['values'][0]; 02563 } 02564 } 02565 02566 $tagi['ch'][$oldtag][] = $oldtagi; 02567 unset($oldtagi); 02568 } 02569 // cdata 02570 if ($type == 'cdata') { 02571 $tagi['values'][] = $val['value']; 02572 } 02573 } 02574 return $tagi['ch']; 02575 } 02576 02587 public static function array2xml_cs(array $array, $docTag = 'phparray', array $options = array(), $charset = '') { 02588 02589 // Figure out charset if not given explicitly: 02590 if (!$charset) { 02591 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']) { // First priority: forceCharset! If set, this will be authoritative! 02592 $charset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']; 02593 } elseif (is_object($GLOBALS['LANG'])) { 02594 $charset = $GLOBALS['LANG']->charSet; // If "LANG" is around, that will hold the current charset 02595 } else { 02596 $charset = 'iso-8859-1'; // THIS is just a hopeful guess! 02597 } 02598 } 02599 02600 // Return XML: 02601 return '<?xml version="1.0" encoding="' . htmlspecialchars($charset) . '" standalone="yes" ?>' . LF . 02602 self::array2xml($array, '', 0, $docTag, 0, $options); 02603 } 02604 02628 public static function array2xml(array $array, $NSprefix = '', $level = 0, $docTag = 'phparray', $spaceInd = 0, array $options = array(), array $stackData = array()) { 02629 // 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 02630 $binaryChars = chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5) . chr(6) . chr(7) . chr(8) . 02631 chr(11) . chr(12) . chr(14) . chr(15) . chr(16) . chr(17) . chr(18) . chr(19) . 02632 chr(20) . chr(21) . chr(22) . chr(23) . chr(24) . chr(25) . chr(26) . chr(27) . chr(28) . chr(29) . 02633 chr(30) . chr(31); 02634 // Set indenting mode: 02635 $indentChar = $spaceInd ? ' ' : TAB; 02636 $indentN = $spaceInd > 0 ? $spaceInd : 1; 02637 $nl = ($spaceInd >= 0 ? LF : ''); 02638 02639 // Init output variable: 02640 $output = ''; 02641 02642 // Traverse the input array 02643 foreach ($array as $k => $v) { 02644 $attr = ''; 02645 $tagName = $k; 02646 02647 // Construct the tag name. 02648 if (isset($options['grandParentTagMap'][$stackData['grandParentTagName'] . '/' . $stackData['parentTagName']])) { // Use tag based on grand-parent + parent tag name 02649 $attr .= ' index="' . htmlspecialchars($tagName) . '"'; 02650 $tagName = (string) $options['grandParentTagMap'][$stackData['grandParentTagName'] . '/' . $stackData['parentTagName']]; 02651 } elseif (isset($options['parentTagMap'][$stackData['parentTagName'] . ':_IS_NUM']) && self::testInt($tagName)) { // Use tag based on parent tag name + if current tag is numeric 02652 $attr .= ' index="' . htmlspecialchars($tagName) . '"'; 02653 $tagName = (string) $options['parentTagMap'][$stackData['parentTagName'] . ':_IS_NUM']; 02654 } elseif (isset($options['parentTagMap'][$stackData['parentTagName'] . ':' . $tagName])) { // Use tag based on parent tag name + current tag 02655 $attr .= ' index="' . htmlspecialchars($tagName) . '"'; 02656 $tagName = (string) $options['parentTagMap'][$stackData['parentTagName'] . ':' . $tagName]; 02657 } elseif (isset($options['parentTagMap'][$stackData['parentTagName']])) { // Use tag based on parent tag name: 02658 $attr .= ' index="' . htmlspecialchars($tagName) . '"'; 02659 $tagName = (string) $options['parentTagMap'][$stackData['parentTagName']]; 02660 } elseif (!strcmp(intval($tagName), $tagName)) { // If integer...; 02661 if ($options['useNindex']) { // If numeric key, prefix "n" 02662 $tagName = 'n' . $tagName; 02663 } else { // Use special tag for num. keys: 02664 $attr .= ' index="' . $tagName . '"'; 02665 $tagName = $options['useIndexTagForNum'] ? $options['useIndexTagForNum'] : 'numIndex'; 02666 } 02667 } elseif ($options['useIndexTagForAssoc']) { // Use tag for all associative keys: 02668 $attr .= ' index="' . htmlspecialchars($tagName) . '"'; 02669 $tagName = $options['useIndexTagForAssoc']; 02670 } 02671 02672 // The tag name is cleaned up so only alphanumeric chars (plus - and _) are in there and not longer than 100 chars either. 02673 $tagName = substr(preg_replace('/[^[:alnum:]_-]/', '', $tagName), 0, 100); 02674 02675 // If the value is an array then we will call this function recursively: 02676 if (is_array($v)) { 02677 02678 // Sub elements: 02679 if ($options['alt_options'][$stackData['path'] . '/' . $tagName]) { 02680 $subOptions = $options['alt_options'][$stackData['path'] . '/' . $tagName]; 02681 $clearStackPath = $subOptions['clearStackPath']; 02682 } else { 02683 $subOptions = $options; 02684 $clearStackPath = FALSE; 02685 } 02686 02687 $content = $nl . 02688 self::array2xml( 02689 $v, 02690 $NSprefix, 02691 $level + 1, 02692 '', 02693 $spaceInd, 02694 $subOptions, 02695 array( 02696 'parentTagName' => $tagName, 02697 'grandParentTagName' => $stackData['parentTagName'], 02698 'path' => $clearStackPath ? '' : $stackData['path'] . '/' . $tagName, 02699 ) 02700 ) . 02701 ($spaceInd >= 0 ? str_pad('', ($level + 1) * $indentN, $indentChar) : ''); 02702 if ((int) $options['disableTypeAttrib'] != 2) { // Do not set "type = array". Makes prettier XML but means that empty arrays are not restored with xml2array 02703 $attr .= ' type="array"'; 02704 } 02705 } else { // Just a value: 02706 02707 // Look for binary chars: 02708 $vLen = strlen($v); // check for length, because PHP 5.2.0 may crash when first argument of strcspn is empty 02709 if ($vLen && strcspn($v, $binaryChars) != $vLen) { // Go for base64 encoding if the initial segment NOT matching any binary char has the same length as the whole string! 02710 // If the value contained binary chars then we base64-encode it an set an attribute to notify this situation: 02711 $content = $nl . chunk_split(base64_encode($v)); 02712 $attr .= ' base64="1"'; 02713 } else { 02714 // Otherwise, just htmlspecialchar the stuff: 02715 $content = htmlspecialchars($v); 02716 $dType = gettype($v); 02717 if ($dType == 'string') { 02718 if ($options['useCDATA'] && $content != $v) { 02719 $content = '<![CDATA[' . $v . ']]>'; 02720 } 02721 } elseif (!$options['disableTypeAttrib']) { 02722 $attr .= ' type="' . $dType . '"'; 02723 } 02724 } 02725 } 02726 02727 // Add the element to the output string: 02728 $output .= ($spaceInd >= 0 ? str_pad('', ($level + 1) * $indentN, $indentChar) : '') . '<' . $NSprefix . $tagName . $attr . '>' . $content . '</' . $NSprefix . $tagName . '>' . $nl; 02729 } 02730 02731 // If we are at the outer-most level, then we finally wrap it all in the document tags and return that as the value: 02732 if (!$level) { 02733 $output = 02734 '<' . $docTag . '>' . $nl . 02735 $output . 02736 '</' . $docTag . '>'; 02737 } 02738 02739 return $output; 02740 } 02741 02755 public static function xml2array($string, $NSprefix = '', $reportDocTag = FALSE) { 02756 static $firstLevelCache = array(); 02757 02758 $identifier = md5($string . $NSprefix . ($reportDocTag ? '1' : '0')); 02759 02760 // look up in first level cache 02761 if (!empty($firstLevelCache[$identifier])) { 02762 $array = $firstLevelCache[$identifier]; 02763 } else { 02764 // look up in second level cache 02765 $cacheContent = t3lib_pageSelect::getHash($identifier, 0); 02766 $array = unserialize($cacheContent); 02767 02768 if ($array === FALSE) { 02769 $array = self::xml2arrayProcess($string, $NSprefix, $reportDocTag); 02770 t3lib_pageSelect::storeHash($identifier, serialize($array), 'ident_xml2array'); 02771 } 02772 // store content in first level cache 02773 $firstLevelCache[$identifier] = $array; 02774 } 02775 return $array; 02776 } 02777 02789 protected function xml2arrayProcess($string, $NSprefix = '', $reportDocTag = FALSE) { 02790 global $TYPO3_CONF_VARS; 02791 02792 // Create parser: 02793 $parser = xml_parser_create(); 02794 $vals = array(); 02795 $index = array(); 02796 02797 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 02798 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0); 02799 02800 // default output charset is UTF-8, only ASCII, ISO-8859-1 and UTF-8 are supported!!! 02801 $match = array(); 02802 preg_match('/^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"/', substr($string, 0, 200), $match); 02803 $theCharset = $match[1] ? $match[1] : ($TYPO3_CONF_VARS['BE']['forceCharset'] ? $TYPO3_CONF_VARS['BE']['forceCharset'] : 'iso-8859-1'); 02804 xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset); // us-ascii / utf-8 / iso-8859-1 02805 02806 // Parse content: 02807 xml_parse_into_struct($parser, $string, $vals, $index); 02808 02809 // If error, return error message: 02810 if (xml_get_error_code($parser)) { 02811 return 'Line ' . xml_get_current_line_number($parser) . ': ' . xml_error_string(xml_get_error_code($parser)); 02812 } 02813 xml_parser_free($parser); 02814 02815 // Init vars: 02816 $stack = array(array()); 02817 $stacktop = 0; 02818 $current = array(); 02819 $tagName = ''; 02820 $documentTag = ''; 02821 02822 // Traverse the parsed XML structure: 02823 foreach ($vals as $key => $val) { 02824 02825 // First, process the tag-name (which is used in both cases, whether "complete" or "close") 02826 $tagName = $val['tag']; 02827 if (!$documentTag) { 02828 $documentTag = $tagName; 02829 } 02830 02831 // Test for name space: 02832 $tagName = ($NSprefix && substr($tagName, 0, strlen($NSprefix)) == $NSprefix) ? substr($tagName, strlen($NSprefix)) : $tagName; 02833 02834 // Test for numeric tag, encoded on the form "nXXX": 02835 $testNtag = substr($tagName, 1); // Closing tag. 02836 $tagName = (substr($tagName, 0, 1) == 'n' && !strcmp(intval($testNtag), $testNtag)) ? intval($testNtag) : $tagName; 02837 02838 // Test for alternative index value: 02839 if (strlen($val['attributes']['index'])) { 02840 $tagName = $val['attributes']['index']; 02841 } 02842 02843 // Setting tag-values, manage stack: 02844 switch ($val['type']) { 02845 case 'open': // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array: 02846 $current[$tagName] = array(); // Setting blank place holder 02847 $stack[$stacktop++] = $current; 02848 $current = array(); 02849 break; 02850 case 'close': // If the tag is "close" then it is an array which is closing and we decrease the stack pointer. 02851 $oldCurrent = $current; 02852 $current = $stack[--$stacktop]; 02853 end($current); // Going to the end of array to get placeholder key, key($current), and fill in array next: 02854 $current[key($current)] = $oldCurrent; 02855 unset($oldCurrent); 02856 break; 02857 case 'complete': // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it. 02858 if ($val['attributes']['base64']) { 02859 $current[$tagName] = base64_decode($val['value']); 02860 } else { 02861 $current[$tagName] = (string) $val['value']; // Had to cast it as a string - otherwise it would be evaluate false if tested with isset()!! 02862 02863 // Cast type: 02864 switch ((string) $val['attributes']['type']) { 02865 case 'integer': 02866 $current[$tagName] = (integer) $current[$tagName]; 02867 break; 02868 case 'double': 02869 $current[$tagName] = (double) $current[$tagName]; 02870 break; 02871 case 'boolean': 02872 $current[$tagName] = (bool) $current[$tagName]; 02873 break; 02874 case 'array': 02875 $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... 02876 break; 02877 } 02878 } 02879 break; 02880 } 02881 } 02882 02883 if ($reportDocTag) { 02884 $current[$tagName]['_DOCUMENT_TAG'] = $documentTag; 02885 } 02886 02887 // Finally return the content of the document tag. 02888 return $current[$tagName]; 02889 } 02890 02898 public static function xmlRecompileFromStructValArray(array $vals) { 02899 $XMLcontent = ''; 02900 02901 foreach ($vals as $val) { 02902 $type = $val['type']; 02903 02904 // open tag: 02905 if ($type == 'open' || $type == 'complete') { 02906 $XMLcontent .= '<' . $val['tag']; 02907 if (isset($val['attributes'])) { 02908 foreach ($val['attributes'] as $k => $v) { 02909 $XMLcontent .= ' ' . $k . '="' . htmlspecialchars($v) . '"'; 02910 } 02911 } 02912 if ($type == 'complete') { 02913 if (isset($val['value'])) { 02914 $XMLcontent .= '>' . htmlspecialchars($val['value']) . '</' . $val['tag'] . '>'; 02915 } else { 02916 $XMLcontent .= '/>'; 02917 } 02918 } else { 02919 $XMLcontent .= '>'; 02920 } 02921 02922 if ($type == 'open' && isset($val['value'])) { 02923 $XMLcontent .= htmlspecialchars($val['value']); 02924 } 02925 } 02926 // finish tag: 02927 if ($type == 'close') { 02928 $XMLcontent .= '</' . $val['tag'] . '>'; 02929 } 02930 // cdata 02931 if ($type == 'cdata') { 02932 $XMLcontent .= htmlspecialchars($val['value']); 02933 } 02934 } 02935 02936 return $XMLcontent; 02937 } 02938 02946 public static function xmlGetHeaderAttribs($xmlData) { 02947 $match = array(); 02948 if (preg_match('/^\s*<\?xml([^>]*)\?>/', $xmlData, $match)) { 02949 return self::get_tag_attributes($match[1]); 02950 } 02951 } 02952 02960 public static function minifyJavaScript($script, &$error = '') { 02961 require_once(PATH_typo3 . 'contrib/jsmin/jsmin.php'); 02962 try { 02963 $error = ''; 02964 $script = trim(JSMin::minify(str_replace(CR, '', $script))); 02965 } 02966 catch (JSMinException $e) { 02967 $error = 'Error while minifying JavaScript: ' . $e->getMessage(); 02968 self::devLog($error, 't3lib_div', 2, 02969 array('JavaScript' => $script, 'Stack trace' => $e->getTrace())); 02970 } 02971 return $script; 02972 } 02973 02974 02975 /************************* 02976 * 02977 * FILES FUNCTIONS 02978 * 02979 *************************/ 02980 02992 public static function getUrl($url, $includeHeader = 0, $requestHeaders = FALSE, &$report = NULL) { 02993 $content = FALSE; 02994 02995 if (isset($report)) { 02996 $report['error'] = 0; 02997 $report['message'] = ''; 02998 } 02999 03000 // use cURL for: http, https, ftp, ftps, sftp and scp 03001 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlUse'] == '1' && preg_match('/^(?:http|ftp)s?|s(?:ftp|cp):/', $url)) { 03002 if (isset($report)) { 03003 $report['lib'] = 'cURL'; 03004 } 03005 03006 // External URL without error checking. 03007 $ch = curl_init(); 03008 if (!$ch) { 03009 if (isset($report)) { 03010 $report['error'] = -1; 03011 $report['message'] = 'Couldn\'t initialize cURL.'; 03012 } 03013 return FALSE; 03014 } 03015 03016 curl_setopt($ch, CURLOPT_URL, $url); 03017 curl_setopt($ch, CURLOPT_HEADER, $includeHeader ? 1 : 0); 03018 curl_setopt($ch, CURLOPT_NOBODY, $includeHeader == 2 ? 1 : 0); 03019 curl_setopt($ch, CURLOPT_HTTPGET, $includeHeader == 2 ? 'HEAD' : 'GET'); 03020 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 03021 curl_setopt($ch, CURLOPT_FAILONERROR, 1); 03022 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, max(0, intval($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlTimeout']))); 03023 03024 // may fail (PHP 5.2.0+ and 5.1.5+) when open_basedir or safe_mode are enabled 03025 $followLocation = @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 03026 03027 if (is_array($requestHeaders)) { 03028 curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders); 03029 } 03030 03031 // (Proxy support implemented by Arco <arco@appeltaart.mine.nu>) 03032 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyServer']) { 03033 curl_setopt($ch, CURLOPT_PROXY, $GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyServer']); 03034 03035 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyTunnel']) { 03036 curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, $GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyTunnel']); 03037 } 03038 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyUserPass']) { 03039 curl_setopt($ch, CURLOPT_PROXYUSERPWD, $GLOBALS['TYPO3_CONF_VARS']['SYS']['curlProxyUserPass']); 03040 } 03041 } 03042 $content = curl_exec($ch); 03043 if (isset($report)) { 03044 if ($content === FALSE) { 03045 $report['error'] = curl_errno($ch); 03046 $report['message'] = curl_error($ch); 03047 } else { 03048 $curlInfo = curl_getinfo($ch); 03049 // We hit a redirection but we couldn't follow it 03050 if (!$followLocation && $curlInfo['status'] >= 300 && $curlInfo['status'] < 400) { 03051 $report['error'] = -1; 03052 $report['message'] = 'Couldn\'t follow location redirect (either PHP configuration option safe_mode or open_basedir is in effect).'; 03053 } elseif ($includeHeader) { 03054 // Set only for $includeHeader to work exactly like PHP variant 03055 $report['http_code'] = $curlInfo['http_code']; 03056 $report['content_type'] = $curlInfo['content_type']; 03057 } 03058 } 03059 } 03060 curl_close($ch); 03061 03062 } elseif ($includeHeader) { 03063 if (isset($report)) { 03064 $report['lib'] = 'socket'; 03065 } 03066 $parsedURL = parse_url($url); 03067 if (!preg_match('/^https?/', $parsedURL['scheme'])) { 03068 if (isset($report)) { 03069 $report['error'] = -1; 03070 $report['message'] = 'Reading headers is not allowed for this protocol.'; 03071 } 03072 return FALSE; 03073 } 03074 $port = intval($parsedURL['port']); 03075 if ($port < 1) { 03076 if ($parsedURL['scheme'] == 'http') { 03077 $port = ($port > 0 ? $port : 80); 03078 $scheme = ''; 03079 } else { 03080 $port = ($port > 0 ? $port : 443); 03081 $scheme = 'ssl://'; 03082 } 03083 } 03084 $errno = 0; 03085 // $errstr = ''; 03086 $fp = @fsockopen($scheme . $parsedURL['host'], $port, $errno, $errstr, 2.0); 03087 if (!$fp || $errno > 0) { 03088 if (isset($report)) { 03089 $report['error'] = $errno ? $errno : -1; 03090 $report['message'] = $errno ? ($errstr ? $errstr : 'Socket error.') : 'Socket initialization error.'; 03091 } 03092 return FALSE; 03093 } 03094 $method = ($includeHeader == 2) ? 'HEAD' : 'GET'; 03095 $msg = $method . ' ' . (isset($parsedURL['path']) ? $parsedURL['path'] : '/') . 03096 ($parsedURL['query'] ? '?' . $parsedURL['query'] : '') . 03097 ' HTTP/1.0' . CRLF . 'Host: ' . 03098 $parsedURL['host'] . "\r\nConnection: close\r\n"; 03099 if (is_array($requestHeaders)) { 03100 $msg .= implode(CRLF, $requestHeaders) . CRLF; 03101 } 03102 $msg .= CRLF; 03103 03104 fputs($fp, $msg); 03105 while (!feof($fp)) { 03106 $line = fgets($fp, 2048); 03107 if (isset($report)) { 03108 if (preg_match('|^HTTP/\d\.\d +(\d+)|', $line, $status)) { 03109 $report['http_code'] = $status[1]; 03110 } 03111 elseif (preg_match('/^Content-Type: *(.*)/i', $line, $type)) { 03112 $report['content_type'] = $type[1]; 03113 } 03114 } 03115 $content .= $line; 03116 if (!strlen(trim($line))) { 03117 break; // Stop at the first empty line (= end of header) 03118 } 03119 } 03120 if ($includeHeader != 2) { 03121 $content .= stream_get_contents($fp); 03122 } 03123 fclose($fp); 03124 03125 } elseif (is_array($requestHeaders)) { 03126 if (isset($report)) { 03127 $report['lib'] = 'file/context'; 03128 } 03129 $parsedURL = parse_url($url); 03130 if (!preg_match('/^https?/', $parsedURL['scheme'])) { 03131 if (isset($report)) { 03132 $report['error'] = -1; 03133 $report['message'] = 'Sending request headers is not allowed for this protocol.'; 03134 } 03135 return FALSE; 03136 } 03137 $ctx = stream_context_create(array( 03138 'http' => array( 03139 'header' => implode(CRLF, $requestHeaders) 03140 ) 03141 ) 03142 ); 03143 $content = @file_get_contents($url, FALSE, $ctx); 03144 if ($content === FALSE && isset($report)) { 03145 $phpError = error_get_last(); 03146 $report['error'] = $phpError['type']; 03147 $report['message'] = $phpError['message']; 03148 } 03149 } else { 03150 if (isset($report)) { 03151 $report['lib'] = 'file'; 03152 } 03153 $content = @file_get_contents($url); 03154 if ($content === FALSE && isset($report)) { 03155 if (function_exists('error_get_last')) { 03156 $phpError = error_get_last(); 03157 $report['error'] = $phpError['type']; 03158 $report['message'] = $phpError['message']; 03159 } else { 03160 $report['error'] = -1; 03161 $report['message'] = 'Couldn\'t get URL.'; 03162 } 03163 } 03164 } 03165 03166 return $content; 03167 } 03168 03177 public static function writeFile($file, $content) { 03178 if (!@is_file($file)) { 03179 $changePermissions = TRUE; 03180 } 03181 03182 if ($fd = fopen($file, 'wb')) { 03183 $res = fwrite($fd, $content); 03184 fclose($fd); 03185 03186 if ($res === FALSE) { 03187 return FALSE; 03188 } 03189 03190 if ($changePermissions) { // Change the permissions only if the file has just been created 03191 self::fixPermissions($file); 03192 } 03193 03194 return TRUE; 03195 } 03196 03197 return FALSE; 03198 } 03199 03207 public static function fixPermissions($path, $recursive = FALSE) { 03208 if (TYPO3_OS != 'WIN') { 03209 $result = FALSE; 03210 03211 // Make path absolute 03212 if (!self::isAbsPath($path)) { 03213 $path = self::getFileAbsFileName($path, FALSE); 03214 } 03215 03216 if (self::isAllowedAbsPath($path)) { 03217 if (@is_file($path)) { 03218 // "@" is there because file is not necessarily OWNED by the user 03219 $result = @chmod($path, octdec($GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'])); 03220 } elseif (@is_dir($path)) { 03221 $path = preg_replace('|/$|', '', $path); 03222 // "@" is there because file is not necessarily OWNED by the user 03223 $result = @chmod($path, octdec($GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'])); 03224 } 03225 03226 // Set createGroup if not empty 03227 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup']) { 03228 // "@" is there because file is not necessarily OWNED by the user 03229 $changeGroupResult = @chgrp($path, $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup']); 03230 $result = $changeGroupResult ? $result : FALSE; 03231 } 03232 03233 // Call recursive if recursive flag if set and $path is directory 03234 if ($recursive && @is_dir($path)) { 03235 $handle = opendir($path); 03236 while (($file = readdir($handle)) !== FALSE) { 03237 $recursionResult = NULL; 03238 if ($file !== '.' && $file !== '..') { 03239 if (@is_file($path . '/' . $file)) { 03240 $recursionResult = self::fixPermissions($path . '/' . $file); 03241 } elseif (@is_dir($path . '/' . $file)) { 03242 $recursionResult = self::fixPermissions($path . '/' . $file, TRUE); 03243 } 03244 if (isset($recursionResult) && !$recursionResult) { 03245 $result = FALSE; 03246 } 03247 } 03248 } 03249 closedir($handle); 03250 } 03251 } 03252 } else { 03253 $result = TRUE; 03254 } 03255 return $result; 03256 } 03257 03266 public static function writeFileToTypo3tempDir($filepath, $content) { 03267 03268 // Parse filepath into directory and basename: 03269 $fI = pathinfo($filepath); 03270 $fI['dirname'] .= '/'; 03271 03272 // Check parts: 03273 if (self::validPathStr($filepath) && $fI['basename'] && strlen($fI['basename']) < 60) { 03274 if (defined('PATH_site')) { 03275 $dirName = PATH_site . 'typo3temp/'; // Setting main temporary directory name (standard) 03276 if (@is_dir($dirName)) { 03277 if (self::isFirstPartOfStr($fI['dirname'], $dirName)) { 03278 03279 // Checking if the "subdir" is found: 03280 $subdir = substr($fI['dirname'], strlen($dirName)); 03281 if ($subdir) { 03282 if (preg_match('/^[[:alnum:]_]+\/$/', $subdir) || preg_match('/^[[:alnum:]_]+\/[[:alnum:]_]+\/$/', $subdir)) { 03283 $dirName .= $subdir; 03284 if (!@is_dir($dirName)) { 03285 self::mkdir_deep(PATH_site . 'typo3temp/', $subdir); 03286 } 03287 } else { 03288 return 'Subdir, "' . $subdir . '", was NOT on the form "[[:alnum:]_]/" or "[[:alnum:]_]/[[:alnum:]_]/"'; 03289 } 03290 } 03291 // Checking dir-name again (sub-dir might have been created): 03292 if (@is_dir($dirName)) { 03293 if ($filepath == $dirName . $fI['basename']) { 03294 self::writeFile($filepath, $content); 03295 if (!@is_file($filepath)) { 03296 return 'File not written to disk! Write permission error in filesystem?'; 03297 } 03298 } else { 03299 return 'Calculated filelocation didn\'t match input $filepath!'; 03300 } 03301 } else { 03302 return '"' . $dirName . '" is not a directory!'; 03303 } 03304 } else { 03305 return '"' . $fI['dirname'] . '" was not within directory PATH_site + "typo3temp/"'; 03306 } 03307 } else { 03308 return 'PATH_site + "typo3temp/" was not a directory!'; 03309 } 03310 } else { 03311 return 'PATH_site constant was NOT defined!'; 03312 } 03313 } else { 03314 return 'Input filepath "' . $filepath . '" was generally invalid!'; 03315 } 03316 } 03317 03326 public static function mkdir($newFolder) { 03327 $newFolder = preg_replace('|/$|', '', $newFolder); 03328 $result = @mkdir($newFolder, octdec($GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'])); 03329 if ($result) { 03330 self::fixPermissions($newFolder); 03331 } 03332 return $result; 03333 } 03334 03342 public static function mkdir_deep($destination, $deepDir) { 03343 $allParts = self::trimExplode('/', $deepDir, 1); 03344 $root = ''; 03345 foreach ($allParts as $part) { 03346 $root .= $part . '/'; 03347 if (!is_dir($destination . $root)) { 03348 self::mkdir($destination . $root); 03349 if (!@is_dir($destination . $root)) { 03350 return 'Error: The directory "' . $destination . $root . '" could not be created...'; 03351 } 03352 } 03353 } 03354 } 03355 03363 public static function rmdir($path, $removeNonEmpty = FALSE) { 03364 $OK = FALSE; 03365 $path = preg_replace('|/$|', '', $path); // Remove trailing slash 03366 03367 if (file_exists($path)) { 03368 $OK = TRUE; 03369 03370 if (is_dir($path)) { 03371 if ($removeNonEmpty == TRUE && $handle = opendir($path)) { 03372 while ($OK && FALSE !== ($file = readdir($handle))) { 03373 if ($file == '.' || $file == '..') { 03374 continue; 03375 } 03376 $OK = self::rmdir($path . '/' . $file, $removeNonEmpty); 03377 } 03378 closedir($handle); 03379 } 03380 if ($OK) { 03381 $OK = rmdir($path); 03382 } 03383 03384 } else { // If $dirname is a file, simply remove it 03385 $OK = unlink($path); 03386 } 03387 03388 clearstatcache(); 03389 } 03390 03391 return $OK; 03392 } 03393 03402 public static function get_dirs($path) { 03403 if ($path) { 03404 if (is_dir($path)) { 03405 $dir = scandir($path); 03406 $dirs = array(); 03407 foreach ($dir as $entry) { 03408 if (is_dir($path . '/' . $entry) && $entry != '..' && $entry != '.') { 03409 $dirs[] = $entry; 03410 } 03411 } 03412 } else { 03413 $dirs = 'error'; 03414 } 03415 } 03416 return $dirs; 03417 } 03418 03430 public static function getFilesInDir($path, $extensionList = '', $prependPath = 0, $order = '', $excludePattern = '') { 03431 03432 // Initialize variabels: 03433 $filearray = array(); 03434 $sortarray = array(); 03435 $path = rtrim($path, '/'); 03436 03437 // Find files+directories: 03438 if (@is_dir($path)) { 03439 $extensionList = strtolower($extensionList); 03440 $d = dir($path); 03441 if (is_object($d)) { 03442 while ($entry = $d->read()) { 03443 if (@is_file($path . '/' . $entry)) { 03444 $fI = pathinfo($entry); 03445 $key = md5($path . '/' . $entry); // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension) 03446 if ((!strlen($extensionList) || self::inList($extensionList, strtolower($fI['extension']))) && (!strlen($excludePattern) || !preg_match('/^' . $excludePattern . '$/', $entry))) { 03447 $filearray[$key] = ($prependPath ? $path . '/' : '') . $entry; 03448 if ($order == 'mtime') { 03449 $sortarray[$key] = filemtime($path . '/' . $entry); 03450 } 03451 elseif ($order) { 03452 $sortarray[$key] = $entry; 03453 } 03454 } 03455 } 03456 } 03457 $d->close(); 03458 } else { 03459 return 'error opening path: "' . $path . '"'; 03460 } 03461 } 03462 03463 // Sort them: 03464 if ($order) { 03465 asort($sortarray); 03466 $newArr = array(); 03467 foreach ($sortarray as $k => $v) { 03468 $newArr[$k] = $filearray[$k]; 03469 } 03470 $filearray = $newArr; 03471 } 03472 03473 // Return result 03474 reset($filearray); 03475 return $filearray; 03476 } 03477 03490 public static function getAllFilesAndFoldersInPath(array $fileArr, $path, $extList = '', $regDirs = 0, $recursivityLevels = 99, $excludePattern = '') { 03491 if ($regDirs) { 03492 $fileArr[] = $path; 03493 } 03494 $fileArr = array_merge($fileArr, self::getFilesInDir($path, $extList, 1, 1, $excludePattern)); 03495 03496 $dirs = self::get_dirs($path); 03497 if (is_array($dirs) && $recursivityLevels > 0) { 03498 foreach ($dirs as $subdirs) { 03499 if ((string) $subdirs != '' && (!strlen($excludePattern) || !preg_match('/^' . $excludePattern . '$/', $subdirs))) { 03500 $fileArr = self::getAllFilesAndFoldersInPath($fileArr, $path . $subdirs . '/', $extList, $regDirs, $recursivityLevels - 1, $excludePattern); 03501 } 03502 } 03503 } 03504 return $fileArr; 03505 } 03506 03515 public static function removePrefixPathFromList(array $fileArr, $prefixToRemove) { 03516 foreach ($fileArr as $k => &$absFileRef) { 03517 if (self::isFirstPartOfStr($absFileRef, $prefixToRemove)) { 03518 $absFileRef = substr($absFileRef, strlen($prefixToRemove)); 03519 } else { 03520 return 'ERROR: One or more of the files was NOT prefixed with the prefix-path!'; 03521 } 03522 } 03523 return $fileArr; 03524 } 03525 03533 public static function fixWindowsFilePath($theFile) { 03534 return str_replace('//', '/', str_replace('\\', '/', $theFile)); 03535 } 03536 03545 public static function resolveBackPath($pathStr) { 03546 $parts = explode('/', $pathStr); 03547 $output = array(); 03548 $c = 0; 03549 foreach ($parts as $pV) { 03550 if ($pV == '..') { 03551 if ($c) { 03552 array_pop($output); 03553 $c--; 03554 } else { 03555 $output[] = $pV; 03556 } 03557 } else { 03558 $c++; 03559 $output[] = $pV; 03560 } 03561 } 03562 return implode('/', $output); 03563 } 03564 03575 public static function locationHeaderUrl($path) { 03576 $uI = parse_url($path); 03577 if (substr($path, 0, 1) == '/') { // relative to HOST 03578 $path = self::getIndpEnv('TYPO3_REQUEST_HOST') . $path; 03579 } elseif (!$uI['scheme']) { // No scheme either 03580 $path = self::getIndpEnv('TYPO3_REQUEST_DIR') . $path; 03581 } 03582 return $path; 03583 } 03584 03595 public static function getMaxUploadFileSize($localLimit = 0) { 03596 // don't allow more than the global max file size at all 03597 $t3Limit = (intval($localLimit > 0 ? $localLimit : $GLOBALS['TYPO3_CONF_VARS']['BE']['maxFileSize'])); 03598 // as TYPO3 is handling the file size in KB, multiply by 1024 to get bytes 03599 $t3Limit = $t3Limit * 1024; 03600 03601 // check for PHP restrictions of the maximum size of one of the $_FILES 03602 $phpUploadLimit = self::getBytesFromSizeMeasurement(ini_get('upload_max_filesize')); 03603 // check for PHP restrictions of the maximum $_POST size 03604 $phpPostLimit = self::getBytesFromSizeMeasurement(ini_get('post_max_size')); 03605 // if the total amount of post data is smaller (!) than the upload_max_filesize directive, 03606 // then this is the real limit in PHP 03607 $phpUploadLimit = ($phpPostLimit < $phpUploadLimit ? $phpPostLimit : $phpUploadLimit); 03608 03609 // is the allowed PHP limit (upload_max_filesize) lower than the TYPO3 limit?, also: revert back to KB 03610 return floor($phpUploadLimit < $t3Limit ? $phpUploadLimit : $t3Limit) / 1024; 03611 } 03612 03619 public static function getBytesFromSizeMeasurement($measurement) { 03620 if (stripos($measurement, 'G')) { 03621 $bytes = doubleval($measurement) * 1024 * 1024 * 1024; 03622 } else { 03623 if (stripos($measurement, 'M')) { 03624 $bytes = doubleval($measurement) * 1024 * 1024; 03625 } else { 03626 if (stripos($measurement, 'K')) { 03627 $bytes = doubleval($measurement) * 1024; 03628 } else { 03629 $bytes = doubleval($measurement); 03630 } 03631 } 03632 } 03633 return $bytes; 03634 } 03635 03642 public static function getMaximumPathLength() { 03643 $maximumPathLength = 0; 03644 03645 if (version_compare(PHP_VERSION, '5.3.0', '<')) { 03646 // rough assumptions 03647 if (TYPO3_OS == 'WIN') { 03648 // WIN is usually 255, Vista 260, although NTFS can hold about 2k 03649 $maximumPathLength = 255; 03650 } else { 03651 $maximumPathLength = 2048; 03652 } 03653 } else { 03654 // precise information is available since PHP 5.3 03655 $maximumPathLength = PHP_MAXPATHLEN; 03656 } 03657 03658 return $maximumPathLength; 03659 } 03660 03661 03680 public static function createVersionNumberedFilename($file, $forceQueryString = FALSE) { 03681 $lookupFile = explode('?', $file); 03682 $path = self::resolveBackPath(self::dirname(PATH_thisScript) . '/' . $lookupFile[0]); 03683 03684 if (TYPO3_MODE == 'FE') { 03685 $mode = strtolower($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['versionNumberInFilename']); 03686 if ($mode === 'embed') { 03687 $mode = TRUE; 03688 } else { 03689 if ($mode === 'querystring') { 03690 $mode = FALSE; 03691 } else { 03692 $doNothing = TRUE; 03693 } 03694 } 03695 } else { 03696 $mode = $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['versionNumberInFilename']; 03697 } 03698 03699 if (!file_exists($path) || $doNothing) { 03700 // File not found, return filename unaltered 03701 $fullName = $file; 03702 03703 } else { 03704 if (!$mode || $forceQueryString) { 03705 // If use of .htaccess rule is not configured, 03706 // we use the default query-string method 03707 if ($lookupFile[1]) { 03708 $separator = '&'; 03709 } else { 03710 $separator = '?'; 03711 } 03712 $fullName = $file . $separator . filemtime($path); 03713 03714 } else { 03715 // Change the filename 03716 $name = explode('.', $lookupFile[0]); 03717 $extension = array_pop($name); 03718 03719 array_push($name, filemtime($path), $extension); 03720 $fullName = implode('.', $name); 03721 // append potential query string 03722 $fullName .= $lookupFile[1] ? '?' . $lookupFile[1] : ''; 03723 } 03724 } 03725 03726 return $fullName; 03727 } 03728 03729 03730 /************************* 03731 * 03732 * DEBUG helper FUNCTIONS 03733 * 03734 *************************/ 03735 03736 /* Deprecated since 4.5, use t3lib_utility_Debug */ 03737 03738 03748 public static function debug_ordvalue($string, $characters = 100) { 03749 self::logDeprecatedFunction(); 03750 return t3lib_utility_Debug::ordinalValue($string, $characters); 03751 } 03752 03763 public static function view_array($array_in) { 03764 self::logDeprecatedFunction(); 03765 return t3lib_utility_Debug::viewArray($array_in); 03766 } 03767 03777 public static function print_array($array_in) { 03778 self::logDeprecatedFunction(); 03779 t3lib_utility_Debug::printArray($array_in); 03780 } 03781 03795 public static function debug($var = '', $header = '', $group = 'Debug') { 03796 self::logDeprecatedFunction(); 03797 t3lib_utility_Debug::debug($var, $header, $group); 03798 } 03799 03806 public static function debug_trail() { 03807 self::logDeprecatedFunction(); 03808 return t3lib_utility_Debug::debugTrail(); 03809 } 03810 03820 public static function debugRows($rows, $header = '', $returnHTML = FALSE) { 03821 self::logDeprecatedFunction(); 03822 return t3lib_utility_Debug::debugRows($rows, $header, $returnHTML); 03823 } 03824 03825 03826 /************************* 03827 * 03828 * SYSTEM INFORMATION 03829 * 03830 *************************/ 03831 03838 public static function getThisUrl() { 03839 $p = parse_url(self::getIndpEnv('TYPO3_REQUEST_SCRIPT')); // Url of this script 03840 $dir = self::dirname($p['path']) . '/'; // Strip file 03841 $url = str_replace('//', '/', $p['host'] . ($p['port'] ? ':' . $p['port'] : '') . $dir); 03842 return $url; 03843 } 03844 03854 public static function linkThisScript(array $getParams = array()) { 03855 $parts = self::getIndpEnv('SCRIPT_NAME'); 03856 $params = self::_GET(); 03857 03858 foreach ($getParams as $key => $value) { 03859 if ($value !== '') { 03860 $params[$key] = $value; 03861 } else { 03862 unset($params[$key]); 03863 } 03864 } 03865 03866 $pString = self::implodeArrayForUrl('', $params); 03867 03868 return $pString ? $parts . '?' . preg_replace('/^&/', '', $pString) : $parts; 03869 } 03870 03880 public static function linkThisUrl($url, array $getParams = array()) { 03881 $parts = parse_url($url); 03882 $getP = array(); 03883 if ($parts['query']) { 03884 parse_str($parts['query'], $getP); 03885 } 03886 $getP = self::array_merge_recursive_overrule($getP, $getParams); 03887 $uP = explode('?', $url); 03888 03889 $params = self::implodeArrayForUrl('', $getP); 03890 $outurl = $uP[0] . ($params ? '?' . substr($params, 1) : ''); 03891 03892 return $outurl; 03893 } 03894 03903 public static function getIndpEnv($getEnvName) { 03904 /* 03905 Conventions: 03906 output from parse_url(): 03907 URL: http://username:password@192.168.1.4:8080/typo3/32/temp/phpcheck/index.php/arg1/arg2/arg3/?arg1,arg2,arg3&p1=parameter1&p2[key]=value#link1 03908 [scheme] => 'http' 03909 [user] => 'username' 03910 [pass] => 'password' 03911 [host] => '192.168.1.4' 03912 [port] => '8080' 03913 [path] => '/typo3/32/temp/phpcheck/index.php/arg1/arg2/arg3/' 03914 [query] => 'arg1,arg2,arg3&p1=parameter1&p2[key]=value' 03915 [fragment] => 'link1' 03916 03917 Further definition: [path_script] = '/typo3/32/temp/phpcheck/index.php' 03918 [path_dir] = '/typo3/32/temp/phpcheck/' 03919 [path_info] = '/arg1/arg2/arg3/' 03920 [path] = [path_script/path_dir][path_info] 03921 03922 03923 Keys supported: 03924 03925 URI______: 03926 REQUEST_URI = [path]?[query] = /typo3/32/temp/phpcheck/index.php/arg1/arg2/arg3/?arg1,arg2,arg3&p1=parameter1&p2[key]=value 03927 HTTP_HOST = [host][:[port]] = 192.168.1.4:8080 03928 SCRIPT_NAME = [path_script]++ = /typo3/32/temp/phpcheck/index.php // NOTICE THAT SCRIPT_NAME will return the php-script name ALSO. [path_script] may not do that (eg. '/somedir/' may result in SCRIPT_NAME '/somedir/index.php')! 03929 PATH_INFO = [path_info] = /arg1/arg2/arg3/ 03930 QUERY_STRING = [query] = arg1,arg2,arg3&p1=parameter1&p2[key]=value 03931 HTTP_REFERER = [scheme]://[host][:[port]][path] = http://192.168.1.4:8080/typo3/32/temp/phpcheck/index.php/arg1/arg2/arg3/?arg1,arg2,arg3&p1=parameter1&p2[key]=value 03932 (Notice: NO username/password + NO fragment) 03933 03934 CLIENT____: 03935 REMOTE_ADDR = (client IP) 03936 REMOTE_HOST = (client host) 03937 HTTP_USER_AGENT = (client user agent) 03938 HTTP_ACCEPT_LANGUAGE = (client accept language) 03939 03940 SERVER____: 03941 SCRIPT_FILENAME = Absolute filename of script (Differs between windows/unix). On windows 'C:\\blabla\\blabl\\' will be converted to 'C:/blabla/blabl/' 03942 03943 Special extras: 03944 TYPO3_HOST_ONLY = [host] = 192.168.1.4 03945 TYPO3_PORT = [port] = 8080 (blank if 80, taken from host value) 03946 TYPO3_REQUEST_HOST = [scheme]://[host][:[port]] 03947 TYPO3_REQUEST_URL = [scheme]://[host][:[port]][path]?[query] (scheme will by default be "http" until we can detect something different) 03948 TYPO3_REQUEST_SCRIPT = [scheme]://[host][:[port]][path_script] 03949 TYPO3_REQUEST_DIR = [scheme]://[host][:[port]][path_dir] 03950 TYPO3_SITE_URL = [scheme]://[host][:[port]][path_dir] of the TYPO3 website frontend 03951 TYPO3_SITE_PATH = [path_dir] of the TYPO3 website frontend 03952 TYPO3_SITE_SCRIPT = [script / Speaking URL] of the TYPO3 website 03953 TYPO3_DOCUMENT_ROOT = Absolute path of root of documents: TYPO3_DOCUMENT_ROOT.SCRIPT_NAME = SCRIPT_FILENAME (typically) 03954 TYPO3_SSL = Returns TRUE if this session uses SSL/TLS (https) 03955 TYPO3_PROXY = Returns TRUE if this session runs over a well known proxy 03956 03957 Notice: [fragment] is apparently NEVER available to the script! 03958 03959 03960 Testing suggestions: 03961 - Output all the values. 03962 - In the script, make a link to the script it self, maybe add some parameters and click the link a few times so HTTP_REFERER is seen 03963 - ALSO TRY the script from the ROOT of a site (like 'http://www.mytest.com/' and not 'http://www.mytest.com/test/' !!) 03964 03965 */ 03966 03967 # if ($getEnvName=='HTTP_REFERER') return ''; 03968 03969 $retVal = ''; 03970 03971 switch ((string) $getEnvName) { 03972 case 'SCRIPT_NAME': 03973 $retVal = (PHP_SAPI == 'fpm-fcgi' || PHP_SAPI == 'cgi' || PHP_SAPI == 'cgi-fcgi') && 03974 ($_SERVER['ORIG_PATH_INFO'] ? $_SERVER['ORIG_PATH_INFO'] : $_SERVER['PATH_INFO']) ? 03975 ($_SERVER['ORIG_PATH_INFO'] ? $_SERVER['ORIG_PATH_INFO'] : $_SERVER['PATH_INFO']) : 03976 ($_SERVER['ORIG_SCRIPT_NAME'] ? $_SERVER['ORIG_SCRIPT_NAME'] : $_SERVER['SCRIPT_NAME']); 03977 // add a prefix if TYPO3 is behind a proxy: ext-domain.com => int-server.com/prefix 03978 if (self::cmpIP($_SERVER['REMOTE_ADDR'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP'])) { 03979 if (self::getIndpEnv('TYPO3_SSL') && $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyPrefixSSL']) { 03980 $retVal = $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyPrefixSSL'] . $retVal; 03981 } elseif ($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyPrefix']) { 03982 $retVal = $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyPrefix'] . $retVal; 03983 } 03984 } 03985 break; 03986 case 'SCRIPT_FILENAME': 03987 $retVal = str_replace('//', '/', str_replace('\\', '/', 03988 (PHP_SAPI == 'fpm-fcgi' || PHP_SAPI == 'cgi' || PHP_SAPI == 'isapi' || PHP_SAPI == 'cgi-fcgi') && 03989 ($_SERVER['ORIG_PATH_TRANSLATED'] ? $_SERVER['ORIG_PATH_TRANSLATED'] : $_SERVER['PATH_TRANSLATED']) ? 03990 ($_SERVER['ORIG_PATH_TRANSLATED'] ? $_SERVER['ORIG_PATH_TRANSLATED'] : $_SERVER['PATH_TRANSLATED']) : 03991 ($_SERVER['ORIG_SCRIPT_FILENAME'] ? $_SERVER['ORIG_SCRIPT_FILENAME'] : $_SERVER['SCRIPT_FILENAME']))); 03992 03993 break; 03994 case 'REQUEST_URI': 03995 // Typical application of REQUEST_URI is return urls, forms submitting to itself etc. Example: returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')) 03996 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['requestURIvar']) { // This is for URL rewriters that store the original URI in a server variable (eg ISAPI_Rewriter for IIS: HTTP_X_REWRITE_URL) 03997 list($v, $n) = explode('|', $GLOBALS['TYPO3_CONF_VARS']['SYS']['requestURIvar']); 03998 $retVal = $GLOBALS[$v][$n]; 03999 } elseif (!$_SERVER['REQUEST_URI']) { // This is for ISS/CGI which does not have the REQUEST_URI available. 04000 $retVal = '/' . ltrim(self::getIndpEnv('SCRIPT_NAME'), '/') . 04001 ($_SERVER['QUERY_STRING'] ? '?' . $_SERVER['QUERY_STRING'] : ''); 04002 } else { 04003 $retVal = $_SERVER['REQUEST_URI']; 04004 } 04005 // add a prefix if TYPO3 is behind a proxy: ext-domain.com => int-server.com/prefix 04006 if (self::cmpIP($_SERVER['REMOTE_ADDR'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP'])) { 04007 if (self::getIndpEnv('TYPO3_SSL') && $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyPrefixSSL']) { 04008 $retVal = $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyPrefixSSL'] . $retVal; 04009 } elseif ($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyPrefix']) { 04010 $retVal = $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyPrefix'] . $retVal; 04011 } 04012 } 04013 break; 04014 case 'PATH_INFO': 04015 // $_SERVER['PATH_INFO']!=$_SERVER['SCRIPT_NAME'] is necessary because some servers (Windows/CGI) are seen to set PATH_INFO equal to script_name 04016 // Further, there must be at least one '/' in the path - else the PATH_INFO value does not make sense. 04017 // IF 'PATH_INFO' never works for our purpose in TYPO3 with CGI-servers, then 'PHP_SAPI=='cgi'' might be a better check. Right now strcmp($_SERVER['PATH_INFO'],t3lib_div::getIndpEnv('SCRIPT_NAME')) will always return false for CGI-versions, but that is only as long as SCRIPT_NAME is set equal to PATH_INFO because of PHP_SAPI=='cgi' (see above) 04018 // if (strcmp($_SERVER['PATH_INFO'],self::getIndpEnv('SCRIPT_NAME')) && count(explode('/',$_SERVER['PATH_INFO']))>1) { 04019 if (PHP_SAPI != 'cgi' && PHP_SAPI != 'cgi-fcgi' && PHP_SAPI != 'fpm-fcgi') { 04020 $retVal = $_SERVER['PATH_INFO']; 04021 } 04022 break; 04023 case 'TYPO3_REV_PROXY': 04024 $retVal = self::cmpIP($_SERVER['REMOTE_ADDR'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP']); 04025 break; 04026 case 'REMOTE_ADDR': 04027 $retVal = $_SERVER['REMOTE_ADDR']; 04028 if (self::cmpIP($_SERVER['REMOTE_ADDR'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP'])) { 04029 $ip = self::trimExplode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); 04030 // choose which IP in list to use 04031 if (count($ip)) { 04032 switch ($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyHeaderMultiValue']) { 04033 case 'last': 04034 $ip = array_pop($ip); 04035 break; 04036 case 'first': 04037 $ip = array_shift($ip); 04038 break; 04039 case 'none': 04040 default: 04041 $ip = ''; 04042 break; 04043 } 04044 } 04045 if (self::validIP($ip)) { 04046 $retVal = $ip; 04047 } 04048 } 04049 break; 04050 case 'HTTP_HOST': 04051 $retVal = $_SERVER['HTTP_HOST']; 04052 if (self::cmpIP($_SERVER['REMOTE_ADDR'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP'])) { 04053 $host = self::trimExplode(',', $_SERVER['HTTP_X_FORWARDED_HOST']); 04054 // choose which host in list to use 04055 if (count($host)) { 04056 switch ($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyHeaderMultiValue']) { 04057 case 'last': 04058 $host = array_pop($host); 04059 break; 04060 case 'first': 04061 $host = array_shift($host); 04062 break; 04063 case 'none': 04064 default: 04065 $host = ''; 04066 break; 04067 } 04068 } 04069 if ($host) { 04070 $retVal = $host; 04071 } 04072 } 04073 break; 04074 // These are let through without modification 04075 case 'HTTP_REFERER': 04076 case 'HTTP_USER_AGENT': 04077 case 'HTTP_ACCEPT_ENCODING': 04078 case 'HTTP_ACCEPT_LANGUAGE': 04079 case 'REMOTE_HOST': 04080 case 'QUERY_STRING': 04081 $retVal = $_SERVER[$getEnvName]; 04082 break; 04083 case 'TYPO3_DOCUMENT_ROOT': 04084 // Get the web root (it is not the root of the TYPO3 installation) 04085 // The absolute path of the script can be calculated with TYPO3_DOCUMENT_ROOT + SCRIPT_FILENAME 04086 // Some CGI-versions (LA13CGI) and mod-rewrite rules on MODULE versions will deliver a 'wrong' DOCUMENT_ROOT (according to our description). Further various aliases/mod_rewrite rules can disturb this as well. 04087 // Therefore the DOCUMENT_ROOT is now always calculated as the SCRIPT_FILENAME minus the end part shared with SCRIPT_NAME. 04088 $SFN = self::getIndpEnv('SCRIPT_FILENAME'); 04089 $SN_A = explode('/', strrev(self::getIndpEnv('SCRIPT_NAME'))); 04090 $SFN_A = explode('/', strrev($SFN)); 04091 $acc = array(); 04092 foreach ($SN_A as $kk => $vv) { 04093 if (!strcmp($SFN_A[$kk], $vv)) { 04094 $acc[] = $vv; 04095 } else { 04096 break; 04097 } 04098 } 04099 $commonEnd = strrev(implode('/', $acc)); 04100 if (strcmp($commonEnd, '')) { 04101 $DR = substr($SFN, 0, -(strlen($commonEnd) + 1)); 04102 } 04103 $retVal = $DR; 04104 break; 04105 case 'TYPO3_HOST_ONLY': 04106 $httpHost = self::getIndpEnv('HTTP_HOST'); 04107 $httpHostBracketPosition = strpos($httpHost, ']'); 04108 $retVal = ($httpHostBracketPosition !== FALSE) ? substr($httpHost, 0, ($httpHostBracketPosition + 1)) : array_shift(explode(':', $httpHost)); 04109 break; 04110 case 'TYPO3_PORT': 04111 $httpHost = self::getIndpEnv('HTTP_HOST'); 04112 $httpHostOnly = self::getIndpEnv('TYPO3_HOST_ONLY'); 04113 $retVal = (strlen($httpHost) > strlen($httpHostOnly)) ? substr($httpHost, strlen($httpHostOnly) + 1) : ''; 04114 break; 04115 case 'TYPO3_REQUEST_HOST': 04116 $retVal = (self::getIndpEnv('TYPO3_SSL') ? 'https://' : 'http://') . 04117 self::getIndpEnv('HTTP_HOST'); 04118 break; 04119 case 'TYPO3_REQUEST_URL': 04120 $retVal = self::getIndpEnv('TYPO3_REQUEST_HOST') . self::getIndpEnv('REQUEST_URI'); 04121 break; 04122 case 'TYPO3_REQUEST_SCRIPT': 04123 $retVal = self::getIndpEnv('TYPO3_REQUEST_HOST') . self::getIndpEnv('SCRIPT_NAME'); 04124 break; 04125 case 'TYPO3_REQUEST_DIR': 04126 $retVal = self::getIndpEnv('TYPO3_REQUEST_HOST') . self::dirname(self::getIndpEnv('SCRIPT_NAME')) . '/'; 04127 break; 04128 case 'TYPO3_SITE_URL': 04129 if (defined('PATH_thisScript') && defined('PATH_site')) { 04130 $lPath = substr(dirname(PATH_thisScript), strlen(PATH_site)) . '/'; 04131 $url = self::getIndpEnv('TYPO3_REQUEST_DIR'); 04132 $siteUrl = substr($url, 0, -strlen($lPath)); 04133 if (substr($siteUrl, -1) != '/') { 04134 $siteUrl .= '/'; 04135 } 04136 $retVal = $siteUrl; 04137 } 04138 break; 04139 case 'TYPO3_SITE_PATH': 04140 $retVal = substr(self::getIndpEnv('TYPO3_SITE_URL'), strlen(self::getIndpEnv('TYPO3_REQUEST_HOST'))); 04141 break; 04142 case 'TYPO3_SITE_SCRIPT': 04143 $retVal = substr(self::getIndpEnv('TYPO3_REQUEST_URL'), strlen(self::getIndpEnv('TYPO3_SITE_URL'))); 04144 break; 04145 case 'TYPO3_SSL': 04146 $proxySSL = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxySSL']); 04147 if ($proxySSL == '*') { 04148 $proxySSL = $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP']; 04149 } 04150 if (self::cmpIP($_SERVER['REMOTE_ADDR'], $proxySSL)) { 04151 $retVal = TRUE; 04152 } else { 04153 $retVal = $_SERVER['SSL_SESSION_ID'] || !strcasecmp($_SERVER['HTTPS'], 'on') || !strcmp($_SERVER['HTTPS'], '1') ? TRUE : FALSE; // see http://bugs.typo3.org/view.php?id=3909 04154 } 04155 break; 04156 case '_ARRAY': 04157 $out = array(); 04158 // Here, list ALL possible keys to this function for debug display. 04159 $envTestVars = self::trimExplode(',', ' 04160 HTTP_HOST, 04161 TYPO3_HOST_ONLY, 04162 TYPO3_PORT, 04163 PATH_INFO, 04164 QUERY_STRING, 04165 REQUEST_URI, 04166 HTTP_REFERER, 04167 TYPO3_REQUEST_HOST, 04168 TYPO3_REQUEST_URL, 04169 TYPO3_REQUEST_SCRIPT, 04170 TYPO3_REQUEST_DIR, 04171 TYPO3_SITE_URL, 04172 TYPO3_SITE_SCRIPT, 04173 TYPO3_SSL, 04174 TYPO3_REV_PROXY, 04175 SCRIPT_NAME, 04176 TYPO3_DOCUMENT_ROOT, 04177 SCRIPT_FILENAME, 04178 REMOTE_ADDR, 04179 REMOTE_HOST, 04180 HTTP_USER_AGENT, 04181 HTTP_ACCEPT_LANGUAGE', 1); 04182 foreach ($envTestVars as $v) { 04183 $out[$v] = self::getIndpEnv($v); 04184 } 04185 reset($out); 04186 $retVal = $out; 04187 break; 04188 } 04189 return $retVal; 04190 } 04191 04197 public static function milliseconds() { 04198 return round(microtime(TRUE) * 1000); 04199 } 04200 04208 public static function clientInfo($useragent = '') { 04209 if (!$useragent) { 04210 $useragent = self::getIndpEnv('HTTP_USER_AGENT'); 04211 } 04212 04213 $bInfo = array(); 04214 // Which browser? 04215 if (strpos($useragent, 'Konqueror') !== FALSE) { 04216 $bInfo['BROWSER'] = 'konqu'; 04217 } elseif (strpos($useragent, 'Opera') !== FALSE) { 04218 $bInfo['BROWSER'] = 'opera'; 04219 } elseif (strpos($useragent, 'MSIE') !== FALSE) { 04220 $bInfo['BROWSER'] = 'msie'; 04221 } elseif (strpos($useragent, 'Mozilla') !== FALSE) { 04222 $bInfo['BROWSER'] = 'net'; 04223 } elseif (strpos($useragent, 'Flash') !== FALSE) { 04224 $bInfo['BROWSER'] = 'flash'; 04225 } 04226 if ($bInfo['BROWSER']) { 04227 // Browser version 04228 switch ($bInfo['BROWSER']) { 04229 case 'net': 04230 $bInfo['VERSION'] = doubleval(substr($useragent, 8)); 04231 if (strpos($useragent, 'Netscape6/') !== FALSE) { 04232 $bInfo['VERSION'] = doubleval(substr(strstr($useragent, 'Netscape6/'), 10)); 04233 } // Will we ever know if this was a typo or intention...?! :-( 04234 if (strpos($useragent, 'Netscape/6') !== FALSE) { 04235 $bInfo['VERSION'] = doubleval(substr(strstr($useragent, 'Netscape/6'), 10)); 04236 } 04237 if (strpos($useragent, 'Netscape/7') !== FALSE) { 04238 $bInfo['VERSION'] = doubleval(substr(strstr($useragent, 'Netscape/7'), 9)); 04239 } 04240 break; 04241 case 'msie': 04242 $tmp = strstr($useragent, 'MSIE'); 04243 $bInfo['VERSION'] = doubleval(preg_replace('/^[^0-9]*/', '', substr($tmp, 4))); 04244 break; 04245 case 'opera': 04246 $tmp = strstr($useragent, 'Opera'); 04247 $bInfo['VERSION'] = doubleval(preg_replace('/^[^0-9]*/', '', substr($tmp, 5))); 04248 break; 04249 case 'konqu': 04250 $tmp = strstr($useragent, 'Konqueror/'); 04251 $bInfo['VERSION'] = doubleval(substr($tmp, 10)); 04252 break; 04253 } 04254 // Client system 04255 if (strpos($useragent, 'Win') !== FALSE) { 04256 $bInfo['SYSTEM'] = 'win'; 04257 } elseif (strpos($useragent, 'Mac') !== FALSE) { 04258 $bInfo['SYSTEM'] = 'mac'; 04259 } elseif (strpos($useragent, 'Linux') !== FALSE || strpos($useragent, 'X11') !== FALSE || strpos($useragent, 'SGI') !== FALSE || strpos($useragent, ' SunOS ') !== FALSE || strpos($useragent, ' HP-UX ') !== FALSE) { 04260 $bInfo['SYSTEM'] = 'unix'; 04261 } 04262 } 04263 // Is true if the browser supports css to format forms, especially the width 04264 $bInfo['FORMSTYLE'] = ($bInfo['BROWSER'] == 'msie' || ($bInfo['BROWSER'] == 'net' && $bInfo['VERSION'] >= 5) || $bInfo['BROWSER'] == 'opera' || $bInfo['BROWSER'] == 'konqu'); 04265 04266 return $bInfo; 04267 } 04268 04276 public static function getHostname($requestHost = TRUE) { 04277 $host = ''; 04278 // If not called from the command-line, resolve on getIndpEnv() 04279 // Note that TYPO3_REQUESTTYPE is not used here as it may not yet be defined 04280 if ($requestHost && (!defined('TYPO3_cliMode') || !TYPO3_cliMode)) { 04281 $host = self::getIndpEnv('HTTP_HOST'); 04282 } 04283 if (!$host) { 04284 // will fail for PHP 4.1 and 4.2 04285 $host = @php_uname('n'); 04286 // 'n' is ignored in broken installations 04287 if (strpos($host, ' ')) { 04288 $host = ''; 04289 } 04290 } 04291 // we have not found a FQDN yet 04292 if ($host && strpos($host, '.') === FALSE) { 04293 $ip = gethostbyname($host); 04294 // we got an IP address 04295 if ($ip != $host) { 04296 $fqdn = gethostbyaddr($ip); 04297 if ($ip != $fqdn) { 04298 $host = $fqdn; 04299 } 04300 } 04301 } 04302 if (!$host) { 04303 $host = 'localhost.localdomain'; 04304 } 04305 04306 return $host; 04307 } 04308 04309 04310 /************************* 04311 * 04312 * TYPO3 SPECIFIC FUNCTIONS 04313 * 04314 *************************/ 04315 04325 public static function getFileAbsFileName($filename, $onlyRelative = TRUE, $relToTYPO3_mainDir = FALSE) { 04326 if (!strcmp($filename, '')) { 04327 return ''; 04328 } 04329 04330 if ($relToTYPO3_mainDir) { 04331 if (!defined('PATH_typo3')) { 04332 return ''; 04333 } 04334 $relPathPrefix = PATH_typo3; 04335 } else { 04336 $relPathPrefix = PATH_site; 04337 } 04338 if (substr($filename, 0, 4) == 'EXT:') { // extension 04339 list($extKey, $local) = explode('/', substr($filename, 4), 2); 04340 $filename = ''; 04341 if (strcmp($extKey, '') && t3lib_extMgm::isLoaded($extKey) && strcmp($local, '')) { 04342 $filename = t3lib_extMgm::extPath($extKey) . $local; 04343 } 04344 } elseif (!self::isAbsPath($filename)) { // relative. Prepended with $relPathPrefix 04345 $filename = $relPathPrefix . $filename; 04346 } elseif ($onlyRelative && !self::isFirstPartOfStr($filename, $relPathPrefix)) { // absolute, but set to blank if not allowed 04347 $filename = ''; 04348 } 04349 if (strcmp($filename, '') && self::validPathStr($filename)) { // checks backpath. 04350 return $filename; 04351 } 04352 } 04353 04367 public static function validPathStr($theFile) { 04368 if (strpos($theFile, '//') === FALSE && strpos($theFile, '\\') === FALSE && !preg_match('#(?:^\.\.|/\.\./|[[:cntrl:]])#', $theFile)) { 04369 return TRUE; 04370 } 04371 } 04372 04380 public static function isAbsPath($path) { 04381 // on Windows also a path starting with a drive letter is absolute: X:/ 04382 if (TYPO3_OS === 'WIN' && substr($path, 1, 2) === ':/') { 04383 return TRUE; 04384 } 04385 04386 // path starting with a / is always absolute, on every system 04387 return (substr($path, 0, 1) === '/'); 04388 } 04389 04397 public static function isAllowedAbsPath($path) { 04398 if (self::isAbsPath($path) && 04399 self::validPathStr($path) && 04400 (self::isFirstPartOfStr($path, PATH_site) 04401 || 04402 ($GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath'] && self::isFirstPartOfStr($path, $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath'])) 04403 ) 04404 ) { 04405 return TRUE; 04406 } 04407 } 04408 04416 public static function verifyFilenameAgainstDenyPattern($filename) { 04417 // Filenames are not allowed to contain control characters 04418 if (preg_match('/[[:cntrl:]]/', $filename)) { 04419 return FALSE; 04420 } 04421 04422 if (strcmp($filename, '') && strcmp($GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'], '')) { 04423 $result = preg_match('/' . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'] . '/i', $filename); 04424 if ($result) { 04425 return FALSE; 04426 } // so if a matching filename is found, return FALSE; 04427 } 04428 return TRUE; 04429 } 04430 04440 public static function sanitizeLocalUrl($url = '') { 04441 $sanitizedUrl = ''; 04442 $decodedUrl = rawurldecode($url); 04443 04444 if (!empty($url) && self::removeXSS($decodedUrl) === $decodedUrl) { 04445 $testAbsoluteUrl = self::resolveBackPath($decodedUrl); 04446 $testRelativeUrl = self::resolveBackPath( 04447 self::dirname(self::getIndpEnv('SCRIPT_NAME')) . '/' . $decodedUrl 04448 ); 04449 04450 // Pass if URL is on the current host: 04451 if (self::isValidUrl($decodedUrl)) { 04452 if (self::isOnCurrentHost($decodedUrl) && strpos($decodedUrl, self::getIndpEnv('TYPO3_SITE_URL')) === 0) { 04453 $sanitizedUrl = $url; 04454 } 04455 // Pass if URL is an absolute file path: 04456 } elseif (self::isAbsPath($decodedUrl) && self::isAllowedAbsPath($decodedUrl)) { 04457 $sanitizedUrl = $url; 04458 // Pass if URL is absolute and below TYPO3 base directory: 04459 } elseif (strpos($testAbsoluteUrl, self::getIndpEnv('TYPO3_SITE_PATH')) === 0 && substr($decodedUrl, 0, 1) === '/') { 04460 $sanitizedUrl = $url; 04461 // Pass if URL is relative and below TYPO3 base directory: 04462 } elseif (strpos($testRelativeUrl, self::getIndpEnv('TYPO3_SITE_PATH')) === 0 && substr($decodedUrl, 0, 1) !== '/') { 04463 $sanitizedUrl = $url; 04464 } 04465 } 04466 04467 if (!empty($url) && empty($sanitizedUrl)) { 04468 self::sysLog('The URL "' . $url . '" is not considered to be local and was denied.', 'Core', self::SYSLOG_SEVERITY_NOTICE); 04469 } 04470 04471 return $sanitizedUrl; 04472 } 04473 04484 public static function upload_copy_move($source, $destination) { 04485 if (is_uploaded_file($source)) { 04486 $uploaded = TRUE; 04487 // Return the value of move_uploaded_file, and if false the temporary $source is still around so the user can use unlink to delete it: 04488 $uploadedResult = move_uploaded_file($source, $destination); 04489 } else { 04490 $uploaded = FALSE; 04491 @copy($source, $destination); 04492 } 04493 04494 self::fixPermissions($destination); // Change the permissions of the file 04495 04496 // If here the file is copied and the temporary $source is still around, so when returning false the user can try unlink to delete the $source 04497 return $uploaded ? $uploadedResult : FALSE; 04498 } 04499 04510 public static function upload_to_tempfile($uploadedFileName) { 04511 if (is_uploaded_file($uploadedFileName)) { 04512 $tempFile = self::tempnam('upload_temp_'); 04513 move_uploaded_file($uploadedFileName, $tempFile); 04514 return @is_file($tempFile) ? $tempFile : ''; 04515 } 04516 } 04517 04528 public static function unlink_tempfile($uploadedTempFileName) { 04529 if ($uploadedTempFileName && self::validPathStr($uploadedTempFileName) && self::isFirstPartOfStr($uploadedTempFileName, PATH_site . 'typo3temp/') && @is_file($uploadedTempFileName)) { 04530 if (unlink($uploadedTempFileName)) { 04531 return TRUE; 04532 } 04533 } 04534 } 04535 04546 public static function tempnam($filePrefix) { 04547 return tempnam(PATH_site . 'typo3temp/', $filePrefix); 04548 } 04549 04559 public static function stdAuthCode($uid_or_record, $fields = '', $codeLength = 8) { 04560 04561 if (is_array($uid_or_record)) { 04562 $recCopy_temp = array(); 04563 if ($fields) { 04564 $fieldArr = self::trimExplode(',', $fields, 1); 04565 foreach ($fieldArr as $k => $v) { 04566 $recCopy_temp[$k] = $uid_or_record[$v]; 04567 } 04568 } else { 04569 $recCopy_temp = $uid_or_record; 04570 } 04571 $preKey = implode('|', $recCopy_temp); 04572 } else { 04573 $preKey = $uid_or_record; 04574 } 04575 04576 $authCode = $preKey . '||' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']; 04577 $authCode = substr(md5($authCode), 0, $codeLength); 04578 return $authCode; 04579 } 04580 04589 public static function cHashParams($addQueryParams) { 04590 $params = explode('&', substr($addQueryParams, 1)); // Splitting parameters up 04591 04592 // Make array: 04593 $pA = array(); 04594 foreach ($params as $theP) { 04595 $pKV = explode('=', $theP); // Splitting single param by '=' sign 04596 if (!self::inList('id,type,no_cache,cHash,MP,ftu', $pKV[0]) && !preg_match('/TSFE_ADMIN_PANEL\[.*?\]/', $pKV[0])) { 04597 $pA[rawurldecode($pKV[0])] = (string) rawurldecode($pKV[1]); 04598 } 04599 } 04600 // Hook: Allows to manipulate the parameters which are taken to build the chash: 04601 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['cHashParamsHook'])) { 04602 $cHashParamsHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['cHashParamsHook']; 04603 if (is_array($cHashParamsHook)) { 04604 $hookParameters = array( 04605 'addQueryParams' => &$addQueryParams, 04606 'params' => &$params, 04607 'pA' => &$pA, 04608 ); 04609 $hookReference = NULL; 04610 foreach ($cHashParamsHook as $hookFunction) { 04611 self::callUserFunction($hookFunction, $hookParameters, $hookReference); 04612 } 04613 } 04614 } 04615 // Finish and sort parameters array by keys: 04616 $pA['encryptionKey'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']; 04617 ksort($pA); 04618 04619 return $pA; 04620 } 04621 04629 public static function generateCHash($addQueryParams) { 04630 $cHashParams = self::cHashParams($addQueryParams); 04631 $cHash = self::calculateCHash($cHashParams); 04632 return $cHash; 04633 } 04634 04641 public static function calculateCHash($params) { 04642 $cHash = md5(serialize($params)); 04643 return $cHash; 04644 } 04645 04652 public static function hideIfNotTranslated($l18n_cfg_fieldValue) { 04653 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['hidePagesIfNotTranslatedByDefault']) { 04654 return $l18n_cfg_fieldValue & 2 ? FALSE : TRUE; 04655 } else { 04656 return $l18n_cfg_fieldValue & 2 ? TRUE : FALSE; 04657 } 04658 } 04659 04670 public static function readLLfile($fileRef, $langKey, $charset = '', $errorMode = 0) { 04671 04672 $result = FALSE; 04673 $file = self::getFileAbsFileName($fileRef); 04674 if ($file) { 04675 $baseFile = preg_replace('/\.(php|xml)$/', '', $file); 04676 04677 if (@is_file($baseFile . '.xml')) { 04678 $LOCAL_LANG = self::readLLXMLfile($baseFile . '.xml', $langKey, $charset); 04679 } elseif (@is_file($baseFile . '.php')) { 04680 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] || $charset) { 04681 $LOCAL_LANG = self::readLLPHPfile($baseFile . '.php', $langKey, $charset); 04682 } else { 04683 include($baseFile . '.php'); 04684 if (is_array($LOCAL_LANG)) { 04685 $LOCAL_LANG = array('default' => $LOCAL_LANG['default'], $langKey => $LOCAL_LANG[$langKey]); 04686 } 04687 } 04688 } else { 04689 $errorMsg = 'File "' . $fileRef . '" not found!'; 04690 if ($errorMode == 2) { 04691 throw new t3lib_exception($errorMsg); 04692 } elseif (!$errorMode) { 04693 self::sysLog($errorMsg, 'Core', self::SYSLOG_SEVERITY_ERROR); 04694 } 04695 $fileNotFound = TRUE; 04696 } 04697 04698 04699 $overrides = array(); 04700 $fileRefWithoutExtension = preg_replace('/\.(php|xml)$/', '', $fileRef); 04701 04702 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'][$fileRefWithoutExtension . '.php'])) { 04703 $overrides = array_merge($overrides, $GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'][$fileRefWithoutExtension . '.php']); 04704 } 04705 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'][$fileRefWithoutExtension . '.xml'])) { 04706 $overrides = array_merge($overrides, $GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'][$fileRefWithoutExtension . '.xml']); 04707 } 04708 04709 if (count($overrides) > 0) { 04710 foreach ($overrides as $overrideFile) { 04711 $languageOverrideFileName = self::getFileAbsFileName($overrideFile); 04712 if (@is_file($languageOverrideFileName)) { 04713 $languageOverrideArray = self::readLLXMLfile($languageOverrideFileName, $langKey, $charset); 04714 $LOCAL_LANG = self::array_merge_recursive_overrule($LOCAL_LANG, $languageOverrideArray); 04715 } 04716 } 04717 } 04718 } 04719 if ($fileNotFound !== TRUE) { 04720 $result = is_array($LOCAL_LANG) ? $LOCAL_LANG : array(); 04721 } 04722 return $result; 04723 } 04724 04734 public static function readLLPHPfile($fileRef, $langKey, $charset = '') { 04735 04736 if (is_object($GLOBALS['LANG'])) { 04737 $csConvObj = $GLOBALS['LANG']->csConvObj; 04738 } elseif (is_object($GLOBALS['TSFE'])) { 04739 $csConvObj = $GLOBALS['TSFE']->csConvObj; 04740 } else { 04741 $csConvObj = self::makeInstance('t3lib_cs'); 04742 } 04743 04744 if (@is_file($fileRef) && $langKey) { 04745 04746 // Set charsets: 04747 $sourceCharset = $csConvObj->parse_charset($csConvObj->charSetArray[$langKey] ? $csConvObj->charSetArray[$langKey] : 'iso-8859-1'); 04748 if ($charset) { 04749 $targetCharset = $csConvObj->parse_charset($charset); 04750 } elseif ($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']) { 04751 // when forceCharset is set, we store ALL labels in this charset!!! 04752 $targetCharset = $csConvObj->parse_charset($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']); 04753 } else { 04754 $targetCharset = $csConvObj->parse_charset($csConvObj->charSetArray[$langKey] ? $csConvObj->charSetArray[$langKey] : 'iso-8859-1'); 04755 } 04756 04757 // Cache file name: 04758 $hashSource = substr($fileRef, strlen(PATH_site)) . '|' . date('d-m-Y H:i:s', filemtime($fileRef)) . '|version=2.3'; 04759 $cacheFileName = PATH_site . 'typo3temp/llxml/' . 04760 substr(basename($fileRef), 10, 15) . 04761 '_' . self::shortMD5($hashSource) . '.' . $langKey . '.' . $targetCharset . '.cache'; 04762 // Check if cache file exists... 04763 if (!@is_file($cacheFileName)) { // ... if it doesn't, create content and write it: 04764 $LOCAL_LANG = NULL; 04765 // Get PHP data 04766 include($fileRef); 04767 if (!is_array($LOCAL_LANG)) { 04768 $fileName = substr($fileRef, strlen(PATH_site)); 04769 throw new RuntimeException( 04770 'TYPO3 Fatal Error: "' . $fileName . '" is no TYPO3 language file!', 04771 1270853900 04772 ); 04773 } 04774 04775 // converting the default language (English) 04776 // this needs to be done for a few accented loan words and extension names 04777 if (is_array($LOCAL_LANG['default']) && $targetCharset != 'iso-8859-1') { 04778 foreach ($LOCAL_LANG['default'] as &$labelValue) { 04779 $labelValue = $csConvObj->conv($labelValue, 'iso-8859-1', $targetCharset); 04780 } 04781 } 04782 04783 if ($langKey != 'default' && is_array($LOCAL_LANG[$langKey]) && $sourceCharset != $targetCharset) { 04784 foreach ($LOCAL_LANG[$langKey] as &$labelValue) { 04785 $labelValue = $csConvObj->conv($labelValue, $sourceCharset, $targetCharset); 04786 } 04787 } 04788 04789 // Cache the content now: 04790 $serContent = array('origFile' => $hashSource, 'LOCAL_LANG' => array('default' => $LOCAL_LANG['default'], $langKey => $LOCAL_LANG[$langKey])); 04791 $res = self::writeFileToTypo3tempDir($cacheFileName, serialize($serContent)); 04792 if ($res) { 04793 throw new RuntimeException( 04794 'TYPO3 Fatal Error: "' . $res, 04795 1270853901 04796 ); 04797 } 04798 } else { 04799 // Get content from cache: 04800 $serContent = unserialize(self::getUrl($cacheFileName)); 04801 $LOCAL_LANG = $serContent['LOCAL_LANG']; 04802 } 04803 04804 return $LOCAL_LANG; 04805 } 04806 } 04807 04817 public static function readLLXMLfile($fileRef, $langKey, $charset = '') { 04818 04819 if (is_object($GLOBALS['LANG'])) { 04820 $csConvObj = $GLOBALS['LANG']->csConvObj; 04821 } elseif (is_object($GLOBALS['TSFE'])) { 04822 $csConvObj = $GLOBALS['TSFE']->csConvObj; 04823 } else { 04824 $csConvObj = self::makeInstance('t3lib_cs'); 04825 } 04826 04827 $LOCAL_LANG = NULL; 04828 if (@is_file($fileRef) && $langKey) { 04829 04830 // Set charset: 04831 if ($charset) { 04832 $targetCharset = $csConvObj->parse_charset($charset); 04833 } elseif ($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']) { 04834 // when forceCharset is set, we store ALL labels in this charset!!! 04835 $targetCharset = $csConvObj->parse_charset($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']); 04836 } else { 04837 $targetCharset = $csConvObj->parse_charset($csConvObj->charSetArray[$langKey] ? $csConvObj->charSetArray[$langKey] : 'iso-8859-1'); 04838 } 04839 04840 // Cache file name: 04841 $hashSource = substr($fileRef, strlen(PATH_site)) . '|' . date('d-m-Y H:i:s', filemtime($fileRef)) . '|version=2.3'; 04842 $cacheFileName = PATH_site . 'typo3temp/llxml/' . 04843 substr(basename($fileRef), 10, 15) . 04844 '_' . self::shortMD5($hashSource) . '.' . $langKey . '.' . $targetCharset . '.cache'; 04845 04846 // Check if cache file exists... 04847 if (!@is_file($cacheFileName)) { // ... if it doesn't, create content and write it: 04848 04849 // Read XML, parse it. 04850 $xmlString = self::getUrl($fileRef); 04851 $xmlContent = self::xml2array($xmlString); 04852 if (!is_array($xmlContent)) { 04853 $fileName = substr($fileRef, strlen(PATH_site)); 04854 throw new RuntimeException( 04855 'TYPO3 Fatal Error: The file "' . $fileName . '" is no TYPO3 language file!', 04856 1270853902 04857 ); 04858 } 04859 04860 // Set default LOCAL_LANG array content: 04861 $LOCAL_LANG = array(); 04862 $LOCAL_LANG['default'] = $xmlContent['data']['default']; 04863 04864 // converting the default language (English) 04865 // this needs to be done for a few accented loan words and extension names 04866 // NOTE: no conversion is done when in UTF-8 mode! 04867 if (is_array($LOCAL_LANG['default']) && $targetCharset != 'utf-8') { 04868 foreach ($LOCAL_LANG['default'] as &$labelValue) { 04869 $labelValue = $csConvObj->utf8_decode($labelValue, $targetCharset); 04870 } 04871 unset($labelValue); 04872 } 04873 04874 // converting other languages to their "native" charsets 04875 // NOTE: no conversion is done when in UTF-8 mode! 04876 if ($langKey != 'default') { 04877 04878 // If no entry is found for the language key, then force a value depending on meta-data setting. By default an automated filename will be used: 04879 $LOCAL_LANG[$langKey] = self::llXmlAutoFileName($fileRef, $langKey); 04880 $localized_file = self::getFileAbsFileName($LOCAL_LANG[$langKey]); 04881 if (!@is_file($localized_file) && isset($xmlContent['data'][$langKey])) { 04882 $LOCAL_LANG[$langKey] = $xmlContent['data'][$langKey]; 04883 } 04884 04885 // Checking if charset should be converted. 04886 if (is_array($LOCAL_LANG[$langKey]) && $targetCharset != 'utf-8') { 04887 foreach ($LOCAL_LANG[$langKey] as $labelKey => $labelValue) { 04888 $LOCAL_LANG[$langKey][$labelKey] = $csConvObj->utf8_decode($labelValue, $targetCharset); 04889 } 04890 } 04891 } 04892 04893 // Cache the content now: 04894 $serContent = array('origFile' => $hashSource, 'LOCAL_LANG' => array('default' => $LOCAL_LANG['default'], $langKey => $LOCAL_LANG[$langKey])); 04895 $res = self::writeFileToTypo3tempDir($cacheFileName, serialize($serContent)); 04896 if ($res) { 04897 throw new RuntimeException( 04898 'TYPO3 Fatal Error: ' . $res, 04899 1270853903 04900 ); 04901 } 04902 } else { 04903 // Get content from cache: 04904 $serContent = unserialize(self::getUrl($cacheFileName)); 04905 $LOCAL_LANG = $serContent['LOCAL_LANG']; 04906 } 04907 04908 // Checking for EXTERNAL file for non-default language: 04909 if ($langKey != 'default' && is_string($LOCAL_LANG[$langKey]) && strlen($LOCAL_LANG[$langKey])) { 04910 04911 // Look for localized file: 04912 $localized_file = self::getFileAbsFileName($LOCAL_LANG[$langKey]); 04913 if ($localized_file && @is_file($localized_file)) { 04914 04915 // Cache file name: 04916 $hashSource = substr($localized_file, strlen(PATH_site)) . '|' . date('d-m-Y H:i:s', filemtime($localized_file)) . '|version=2.3'; 04917 $cacheFileName = PATH_site . 'typo3temp/llxml/EXT_' . 04918 substr(basename($localized_file), 10, 15) . 04919 '_' . self::shortMD5($hashSource) . '.' . $langKey . '.' . $targetCharset . '.cache'; 04920 04921 // Check if cache file exists... 04922 if (!@is_file($cacheFileName)) { // ... if it doesn't, create content and write it: 04923 04924 // Read and parse XML content: 04925 $local_xmlString = self::getUrl($localized_file); 04926 $local_xmlContent = self::xml2array($local_xmlString); 04927 if (!is_array($local_xmlContent)) { 04928 $fileName = substr($localized_file, strlen(PATH_site)); 04929 throw new RuntimeException( 04930 'TYPO3 Fatal Error: The file "' . $fileName . '" is no TYPO3 language file!', 04931 1270853904 04932 ); 04933 } 04934 $LOCAL_LANG[$langKey] = is_array($local_xmlContent['data'][$langKey]) ? $local_xmlContent['data'][$langKey] : array(); 04935 04936 // Checking if charset should be converted. 04937 if (is_array($LOCAL_LANG[$langKey]) && $targetCharset != 'utf-8') { 04938 foreach ($LOCAL_LANG[$langKey] as $labelKey => $labelValue) { 04939 $LOCAL_LANG[$langKey][$labelKey] = $csConvObj->utf8_decode($labelValue, $targetCharset); 04940 } 04941 } 04942 04943 // Cache the content now: 04944 $serContent = array('extlang' => $langKey, 'origFile' => $hashSource, 'EXT_DATA' => $LOCAL_LANG[$langKey]); 04945 $res = self::writeFileToTypo3tempDir($cacheFileName, serialize($serContent)); 04946 if ($res) { 04947 throw new RuntimeException( 04948 'TYPO3 Fatal Error: ' . $res, 04949 1270853905 04950 ); 04951 } 04952 } else { 04953 // Get content from cache: 04954 $serContent = unserialize(self::getUrl($cacheFileName)); 04955 $LOCAL_LANG[$langKey] = $serContent['EXT_DATA']; 04956 } 04957 } else { 04958 $LOCAL_LANG[$langKey] = array(); 04959 } 04960 } 04961 04962 return $LOCAL_LANG; 04963 } 04964 } 04965 04973 public static function llXmlAutoFileName($fileRef, $language) { 04974 // Analyse file reference: 04975 $location = 'typo3conf/l10n/' . $language . '/'; // Default location of translations 04976 if (self::isFirstPartOfStr($fileRef, PATH_typo3 . 'sysext/')) { // Is system: 04977 $validatedPrefix = PATH_typo3 . 'sysext/'; 04978 #$location = 'EXT:csh_'.$language.'/'; // For system extensions translations are found in "csh_*" extensions (language packs) 04979 } elseif (self::isFirstPartOfStr($fileRef, PATH_typo3 . 'ext/')) { // Is global: 04980 $validatedPrefix = PATH_typo3 . 'ext/'; 04981 } elseif (self::isFirstPartOfStr($fileRef, PATH_typo3conf . 'ext/')) { // Is local: 04982 $validatedPrefix = PATH_typo3conf . 'ext/'; 04983 } else { 04984 $validatedPrefix = ''; 04985 } 04986 04987 if ($validatedPrefix) { 04988 04989 // Divide file reference into extension key, directory (if any) and base name: 04990 list($file_extKey, $file_extPath) = explode('/', substr($fileRef, strlen($validatedPrefix)), 2); 04991 $temp = self::revExplode('/', $file_extPath, 2); 04992 if (count($temp) == 1) { 04993 array_unshift($temp, ''); 04994 } // Add empty first-entry if not there. 04995 list($file_extPath, $file_fileName) = $temp; 04996 04997 // The filename is prefixed with "[language key]." because it prevents the llxmltranslate tool from detecting it. 04998 return $location . 04999 $file_extKey . '/' . 05000 ($file_extPath ? $file_extPath . '/' : '') . 05001 $language . '.' . $file_fileName; 05002 } else { 05003 return NULL; 05004 } 05005 } 05006 05007 05024 public static function loadTCA($table) { 05025 global $TCA; 05026 05027 if (isset($TCA[$table])) { 05028 $tca = &$TCA[$table]; 05029 if (!$tca['columns']) { 05030 $dcf = $tca['ctrl']['dynamicConfigFile']; 05031 if ($dcf) { 05032 if (!strcmp(substr($dcf, 0, 6), 'T3LIB:')) { 05033 include(PATH_t3lib . 'stddb/' . substr($dcf, 6)); 05034 } elseif (self::isAbsPath($dcf) && @is_file($dcf)) { // Absolute path... 05035 include($dcf); 05036 } else { 05037 include(PATH_typo3conf . $dcf); 05038 } 05039 } 05040 } 05041 } 05042 } 05043 05053 public static function resolveSheetDefInDS($dataStructArray, $sheet = 'sDEF') { 05054 if (!is_array($dataStructArray)) { 05055 return 'Data structure must be an array'; 05056 } 05057 05058 if (is_array($dataStructArray['sheets'])) { 05059 $singleSheet = FALSE; 05060 if (!isset($dataStructArray['sheets'][$sheet])) { 05061 $sheet = 'sDEF'; 05062 } 05063 $dataStruct = $dataStructArray['sheets'][$sheet]; 05064 05065 // If not an array, but still set, then regard it as a relative reference to a file: 05066 if ($dataStruct && !is_array($dataStruct)) { 05067 $file = self::getFileAbsFileName($dataStruct); 05068 if ($file && @is_file($file)) { 05069 $dataStruct = self::xml2array(self::getUrl($file)); 05070 } 05071 } 05072 } else { 05073 $singleSheet = TRUE; 05074 $dataStruct = $dataStructArray; 05075 if (isset($dataStruct['meta'])) { 05076 unset($dataStruct['meta']); 05077 } // Meta data should not appear there. 05078 $sheet = 'sDEF'; // Default sheet 05079 } 05080 return array($dataStruct, $sheet, $singleSheet); 05081 } 05082 05090 public static function resolveAllSheetsInDS(array $dataStructArray) { 05091 if (is_array($dataStructArray['sheets'])) { 05092 $out = array('sheets' => array()); 05093 foreach ($dataStructArray['sheets'] as $sheetId => $sDat) { 05094 list($ds, $aS) = self::resolveSheetDefInDS($dataStructArray, $sheetId); 05095 if ($sheetId == $aS) { 05096 $out['sheets'][$aS] = $ds; 05097 } 05098 } 05099 } else { 05100 list($ds) = self::resolveSheetDefInDS($dataStructArray); 05101 $out = array('sheets' => array('sDEF' => $ds)); 05102 } 05103 return $out; 05104 } 05105 05119 public static function callUserFunction($funcName, &$params, &$ref, $checkPrefix = 'user_', $errorMode = 0) { 05120 global $TYPO3_CONF_VARS; 05121 $content = FALSE; 05122 05123 // Check persistent object and if found, call directly and exit. 05124 if (is_array($GLOBALS['T3_VAR']['callUserFunction'][$funcName])) { 05125 return call_user_func_array( 05126 array(&$GLOBALS['T3_VAR']['callUserFunction'][$funcName]['obj'], 05127 $GLOBALS['T3_VAR']['callUserFunction'][$funcName]['method']), 05128 array(&$params, &$ref) 05129 ); 05130 } 05131 05132 // Check file-reference prefix; if found, require_once() the file (should be library of code) 05133 if (strpos($funcName, ':') !== FALSE) { 05134 list($file, $funcRef) = self::revExplode(':', $funcName, 2); 05135 $requireFile = self::getFileAbsFileName($file); 05136 if ($requireFile) { 05137 self::requireOnce($requireFile); 05138 } 05139 } else { 05140 $funcRef = $funcName; 05141 } 05142 05143 // Check for persistent object token, "&" 05144 if (substr($funcRef, 0, 1) == '&') { 05145 $funcRef = substr($funcRef, 1); 05146 $storePersistentObject = TRUE; 05147 } else { 05148 $storePersistentObject = FALSE; 05149 } 05150 05151 // Check prefix is valid: 05152 if ($checkPrefix && !self::hasValidClassPrefix($funcRef, array($checkPrefix))) { 05153 $errorMsg = "Function/class '$funcRef' was not prepended with '$checkPrefix'"; 05154 if ($errorMode == 2) { 05155 throw new Exception($errorMsg); 05156 } elseif (!$errorMode) { 05157 debug($errorMsg, 't3lib_div::callUserFunction'); 05158 } 05159 return FALSE; 05160 } 05161 05162 // Call function or method: 05163 $parts = explode('->', $funcRef); 05164 if (count($parts) == 2) { // Class 05165 05166 // Check if class/method exists: 05167 if (class_exists($parts[0])) { 05168 05169 // Get/Create object of class: 05170 if ($storePersistentObject) { // Get reference to current instance of class: 05171 if (!is_object($GLOBALS['T3_VAR']['callUserFunction_classPool'][$parts[0]])) { 05172 $GLOBALS['T3_VAR']['callUserFunction_classPool'][$parts[0]] = self::makeInstance($parts[0]); 05173 } 05174 $classObj = $GLOBALS['T3_VAR']['callUserFunction_classPool'][$parts[0]]; 05175 } else { // Create new object: 05176 $classObj = self::makeInstance($parts[0]); 05177 } 05178 05179 if (method_exists($classObj, $parts[1])) { 05180 05181 // If persistent object should be created, set reference: 05182 if ($storePersistentObject) { 05183 $GLOBALS['T3_VAR']['callUserFunction'][$funcName] = array( 05184 'method' => $parts[1], 05185 'obj' => &$classObj 05186 ); 05187 } 05188 // Call method: 05189 $content = call_user_func_array( 05190 array(&$classObj, $parts[1]), 05191 array(&$params, &$ref) 05192 ); 05193 } else { 05194 $errorMsg = "<strong>ERROR:</strong> No method name '" . $parts[1] . "' in class " . $parts[0]; 05195 if ($errorMode == 2) { 05196 throw new Exception($errorMsg); 05197 } elseif (!$errorMode) { 05198 debug($errorMsg, 't3lib_div::callUserFunction'); 05199 } 05200 } 05201 } else { 05202 $errorMsg = "<strong>ERROR:</strong> No class named: " . $parts[0]; 05203 if ($errorMode == 2) { 05204 throw new Exception($errorMsg); 05205 } elseif (!$errorMode) { 05206 debug($errorMsg, 't3lib_div::callUserFunction'); 05207 } 05208 } 05209 } else { // Function 05210 if (function_exists($funcRef)) { 05211 $content = call_user_func_array($funcRef, array(&$params, &$ref)); 05212 } else { 05213 $errorMsg = "<strong>ERROR:</strong> No function named: " . $funcRef; 05214 if ($errorMode == 2) { 05215 throw new Exception($errorMsg); 05216 } elseif (!$errorMode) { 05217 debug($errorMsg, 't3lib_div::callUserFunction'); 05218 } 05219 } 05220 } 05221 return $content; 05222 } 05223 05235 public static function getUserObj($classRef, $checkPrefix = 'user_', $silent = FALSE) { 05236 global $TYPO3_CONF_VARS; 05237 // Check persistent object and if found, call directly and exit. 05238 if (is_object($GLOBALS['T3_VAR']['getUserObj'][$classRef])) { 05239 return $GLOBALS['T3_VAR']['getUserObj'][$classRef]; 05240 } else { 05241 05242 // Check file-reference prefix; if found, require_once() the file (should be library of code) 05243 if (strpos($classRef, ':') !== FALSE) { 05244 list($file, $class) = self::revExplode(':', $classRef, 2); 05245 $requireFile = self::getFileAbsFileName($file); 05246 if ($requireFile) { 05247 self::requireOnce($requireFile); 05248 } 05249 } else { 05250 $class = $classRef; 05251 } 05252 05253 // Check for persistent object token, "&" 05254 if (substr($class, 0, 1) == '&') { 05255 $class = substr($class, 1); 05256 $storePersistentObject = TRUE; 05257 } else { 05258 $storePersistentObject = FALSE; 05259 } 05260 05261 // Check prefix is valid: 05262 if ($checkPrefix && !self::hasValidClassPrefix($class, array($checkPrefix))) { 05263 if (!$silent) { 05264 debug("Class '" . $class . "' was not prepended with '" . $checkPrefix . "'", 't3lib_div::getUserObj'); 05265 } 05266 return FALSE; 05267 } 05268 05269 // Check if class exists: 05270 if (class_exists($class)) { 05271 $classObj = self::makeInstance($class); 05272 05273 // If persistent object should be created, set reference: 05274 if ($storePersistentObject) { 05275 $GLOBALS['T3_VAR']['getUserObj'][$classRef] = $classObj; 05276 } 05277 05278 return $classObj; 05279 } else { 05280 if (!$silent) { 05281 debug("<strong>ERROR:</strong> No class named: " . $class, 't3lib_div::getUserObj'); 05282 } 05283 } 05284 } 05285 } 05286 05294 public static function hasValidClassPrefix($classRef, array $additionalPrefixes = array()) { 05295 $hasValidPrefix = FALSE; 05296 $validPrefixes = array('tx_', 'Tx_', $GLOBALS['TYPO3_CONF_VARS']['FE']['userFuncClassPrefix']); 05297 $classRef = trim($classRef); 05298 05299 if (count($additionalPrefixes)) { 05300 $validPrefixes = array_merge($validPrefixes, $additionalPrefixes); 05301 } 05302 05303 foreach ($validPrefixes as $prefixToCheck) { 05304 if (self::isFirstPartOfStr($classRef, $prefixToCheck)) { 05305 $hasValidPrefix = TRUE; 05306 break; 05307 } 05308 } 05309 05310 return $hasValidPrefix; 05311 } 05312 05326 public static function makeInstance($className) { 05327 if ($className === '') { 05328 throw new InvalidArgumentException('$classname must not be empty.', 1288965219); 05329 } 05330 05331 // Determine final class name which must be instantiated, this takes XCLASS handling 05332 // into account. Cache in a local array to save some cycles for consecutive calls. 05333 if (!isset(self::$finalClassNameRegister[$className])) { 05334 self::$finalClassNameRegister[$className] = self::getClassName($className); 05335 } 05336 $finalClassName = self::$finalClassNameRegister[$className]; 05337 05338 // Return singleton instance if it is already registered 05339 if (isset(self::$singletonInstances[$finalClassName])) { 05340 return self::$singletonInstances[$finalClassName]; 05341 } 05342 05343 // Return instance if it has been injected by addInstance() 05344 if (isset(self::$nonSingletonInstances[$finalClassName]) 05345 && !empty(self::$nonSingletonInstances[$finalClassName]) 05346 ) { 05347 return array_shift(self::$nonSingletonInstances[$finalClassName]); 05348 } 05349 05350 // Create new instance and call constructor with parameters 05351 if (func_num_args() > 1) { 05352 $constructorArguments = func_get_args(); 05353 array_shift($constructorArguments); 05354 05355 $reflectedClass = new ReflectionClass($finalClassName); 05356 $instance = $reflectedClass->newInstanceArgs($constructorArguments); 05357 } else { 05358 $instance = new $finalClassName; 05359 } 05360 05361 // Register new singleton instance 05362 if ($instance instanceof t3lib_Singleton) { 05363 self::$singletonInstances[$finalClassName] = $instance; 05364 } 05365 05366 return $instance; 05367 } 05368 05378 public static function makeInstanceClassName($className) { 05379 self::logDeprecatedFunction(); 05380 05381 return (class_exists($className) && class_exists('ux_' . $className, FALSE) ? self::makeInstanceClassName('ux_' . $className) : $className); 05382 } 05383 05391 protected function getClassName($className) { 05392 if (class_exists($className)) { 05393 while (class_exists('ux_' . $className, FALSE)) { 05394 $className = 'ux_' . $className; 05395 } 05396 } 05397 05398 return $className; 05399 } 05400 05416 public static function setSingletonInstance($className, t3lib_Singleton $instance) { 05417 self::checkInstanceClassName($className, $instance); 05418 self::$singletonInstances[$className] = $instance; 05419 } 05420 05438 public static function addInstance($className, $instance) { 05439 self::checkInstanceClassName($className, $instance); 05440 05441 if ($instance instanceof t3lib_Singleton) { 05442 throw new InvalidArgumentException( 05443 '$instance must not be an instance of t3lib_Singleton. ' . 05444 'For setting singletons, please use setSingletonInstance.', 05445 1288969325 05446 ); 05447 } 05448 05449 if (!isset(self::$nonSingletonInstances[$className])) { 05450 self::$nonSingletonInstances[$className] = array(); 05451 } 05452 self::$nonSingletonInstances[$className][] = $instance; 05453 } 05454 05464 protected static function checkInstanceClassName($className, $instance) { 05465 if ($className === '') { 05466 throw new InvalidArgumentException('$className must not be empty.', 1288967479); 05467 } 05468 if (!($instance instanceof $className)) { 05469 throw new InvalidArgumentException( 05470 '$instance must be an instance of ' . $className . ', but actually is an instance of ' . get_class($instance) . '.', 05471 1288967686 05472 ); 05473 } 05474 } 05475 05487 public static function purgeInstances() { 05488 self::$singletonInstances = array(); 05489 self::$nonSingletonInstances = array(); 05490 } 05491 05502 public static function makeInstanceService($serviceType, $serviceSubType = '', $excludeServiceKeys = array()) { 05503 global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS; 05504 05505 $error = FALSE; 05506 05507 if (!is_array($excludeServiceKeys)) { 05508 $excludeServiceKeys = self::trimExplode(',', $excludeServiceKeys, 1); 05509 } 05510 while ($info = t3lib_extMgm::findService($serviceType, $serviceSubType, $excludeServiceKeys)) { 05511 05512 // Check persistent object and if found, call directly and exit. 05513 if (is_object($GLOBALS['T3_VAR']['makeInstanceService'][$info['className']])) { 05514 // reset service and return object 05515 $T3_VAR['makeInstanceService'][$info['className']]->reset(); 05516 return $GLOBALS['T3_VAR']['makeInstanceService'][$info['className']]; 05517 05518 // include file and create object 05519 } else { 05520 $requireFile = self::getFileAbsFileName($info['classFile']); 05521 if (@is_file($requireFile)) { 05522 self::requireOnce($requireFile); 05523 $obj = self::makeInstance($info['className']); 05524 if (is_object($obj)) { 05525 if (!@is_callable(array($obj, 'init'))) { 05526 // use silent logging??? I don't think so. 05527 die ('Broken service:' . t3lib_utility_Debug::viewArray($info)); 05528 } 05529 $obj->info = $info; 05530 if ($obj->init()) { // service available? 05531 05532 // create persistent object 05533 $T3_VAR['makeInstanceService'][$info['className']] = $obj; 05534 05535 // needed to delete temp files 05536 register_shutdown_function(array(&$obj, '__destruct')); 05537 05538 return $obj; // object is passed as reference by function definition 05539 } 05540 $error = $obj->getLastErrorArray(); 05541 unset($obj); 05542 } 05543 } 05544 } 05545 // deactivate the service 05546 t3lib_extMgm::deactivateService($info['serviceType'], $info['serviceKey']); 05547 } 05548 return $error; 05549 } 05550 05555 public static function requireOnce($requireFile) { 05556 global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS; 05557 05558 require_once ($requireFile); 05559 } 05560 05569 public static function requireFile($requireFile) { 05570 global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS; 05571 require $requireFile; 05572 } 05573 05589 public static function plainMailEncoded($email, $subject, $message, $headers = '', $encoding = 'quoted-printable', $charset = '', $dontEncodeHeader = FALSE) { 05590 if (!$charset) { 05591 $charset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] ? $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] : 'ISO-8859-1'; 05592 } 05593 05594 $email = self::normalizeMailAddress($email); 05595 if (!$dontEncodeHeader) { 05596 // Mail headers must be ASCII, therefore we convert the whole header to either base64 or quoted_printable 05597 $newHeaders = array(); 05598 foreach (explode(LF, $headers) as $line) { // Split the header in lines and convert each line separately 05599 $parts = explode(': ', $line, 2); // Field tags must not be encoded 05600 if (count($parts) == 2) { 05601 if (0 == strcasecmp($parts[0], 'from')) { 05602 $parts[1] = self::normalizeMailAddress($parts[1]); 05603 } 05604 $parts[1] = self::encodeHeader($parts[1], $encoding, $charset); 05605 $newHeaders[] = implode(': ', $parts); 05606 } else { 05607 $newHeaders[] = $line; // Should never happen - is such a mail header valid? Anyway, just add the unchanged line... 05608 } 05609 } 05610 $headers = implode(LF, $newHeaders); 05611 unset($newHeaders); 05612 05613 $email = self::encodeHeader($email, $encoding, $charset); // Email address must not be encoded, but it could be appended by a name which should be so (e.g. "Kasper Skårhøj <kasperYYYY@typo3.com>") 05614 $subject = self::encodeHeader($subject, $encoding, $charset); 05615 } 05616 05617 switch ((string) $encoding) { 05618 case 'base64': 05619 $headers = trim($headers) . LF . 05620 'Mime-Version: 1.0' . LF . 05621 'Content-Type: text/plain; charset="' . $charset . '"' . LF . 05622 'Content-Transfer-Encoding: base64'; 05623 05624 $message = trim(chunk_split(base64_encode($message . LF))) . LF; // Adding LF because I think MS outlook 2002 wants it... may be removed later again. 05625 break; 05626 case '8bit': 05627 $headers = trim($headers) . LF . 05628 'Mime-Version: 1.0' . LF . 05629 'Content-Type: text/plain; charset=' . $charset . LF . 05630 'Content-Transfer-Encoding: 8bit'; 05631 break; 05632 case 'quoted-printable': 05633 default: 05634 $headers = trim($headers) . LF . 05635 'Mime-Version: 1.0' . LF . 05636 'Content-Type: text/plain; charset=' . $charset . LF . 05637 'Content-Transfer-Encoding: quoted-printable'; 05638 05639 $message = self::quoted_printable($message); 05640 break; 05641 } 05642 05643 // Headers must be separated by CRLF according to RFC 2822, not just LF. 05644 // But many servers (Gmail, for example) behave incorectly and want only LF. 05645 // So we stick to LF in all cases. 05646 $headers = trim(implode(LF, self::trimExplode(LF, $headers, TRUE))); // Make sure no empty lines are there. 05647 05648 05649 return t3lib_utility_Mail::mail($email, $subject, $message, $headers); 05650 } 05651 05662 public static function quoted_printable($string, $maxlen = 76) { 05663 // Make sure the string contains only Unix linebreaks 05664 $string = str_replace(CRLF, LF, $string); // Replace Windows breaks (\r\n) 05665 $string = str_replace(CR, LF, $string); // Replace Mac breaks (\r) 05666 05667 $linebreak = LF; // Default line break for Unix systems. 05668 if (TYPO3_OS == 'WIN') { 05669 $linebreak = CRLF; // Line break for Windows. This is needed because PHP on Windows systems send mails via SMTP instead of using sendmail, and thus the linebreak needs to be \r\n. 05670 } 05671 05672 $newString = ''; 05673 $theLines = explode(LF, $string); // Split lines 05674 foreach ($theLines as $val) { 05675 $newVal = ''; 05676 $theValLen = strlen($val); 05677 $len = 0; 05678 for ($index = 0; $index < $theValLen; $index++) { // Walk through each character of this line 05679 $char = substr($val, $index, 1); 05680 $ordVal = ord($char); 05681 if ($len > ($maxlen - 4) || ($len > ($maxlen - 14) && $ordVal == 32)) { 05682 $newVal .= '=' . $linebreak; // Add a line break 05683 $len = 0; // Reset the length counter 05684 } 05685 if (($ordVal >= 33 && $ordVal <= 60) || ($ordVal >= 62 && $ordVal <= 126) || $ordVal == 9 || $ordVal == 32) { 05686 $newVal .= $char; // This character is ok, add it to the message 05687 $len++; 05688 } else { 05689 $newVal .= sprintf('=%02X', $ordVal); // Special character, needs to be encoded 05690 $len += 3; 05691 } 05692 } 05693 $newVal = preg_replace('/' . chr(32) . '$/', '=20', $newVal); // Replaces a possible SPACE-character at the end of a line 05694 $newVal = preg_replace('/' . TAB . '$/', '=09', $newVal); // Replaces a possible TAB-character at the end of a line 05695 $newString .= $newVal . $linebreak; 05696 } 05697 return preg_replace('/' . $linebreak . '$/', '', $newString); // Remove last newline 05698 } 05699 05709 public static function encodeHeader($line, $enc = 'quoted-printable', $charset = 'iso-8859-1') { 05710 // Avoid problems if "###" is found in $line (would conflict with the placeholder which is used below) 05711 if (strpos($line, '###') !== FALSE) { 05712 return $line; 05713 } 05714 // Check if any non-ASCII characters are found - otherwise encoding is not needed 05715 if (!preg_match('/[^' . chr(32) . '-' . chr(127) . ']/', $line)) { 05716 return $line; 05717 } 05718 // Wrap email addresses in a special marker 05719 $line = preg_replace('/([^ ]+@[^ ]+)/', '###$1###', $line); 05720 05721 $matches = preg_split('/(.?###.+###.?|\(|\))/', $line, -1, PREG_SPLIT_NO_EMPTY); 05722 foreach ($matches as $part) { 05723 $oldPart = $part; 05724 switch ((string) $enc) { 05725 case 'base64': 05726 $part = '=?' . $charset . '?B?' . base64_encode($part) . '?='; 05727 break; 05728 case 'quoted-printable': 05729 default: 05730 $qpValue = self::quoted_printable($part, 1000); 05731 if ($part != $qpValue) { 05732 // Encoded words in the header should not contain non-encoded: 05733 // * spaces. "_" is a shortcut for "=20". See RFC 2047 for details. 05734 // * question mark. See RFC 1342 (http://tools.ietf.org/html/rfc1342) 05735 $search = array(' ', '?'); 05736 $replace = array('_', '=3F'); 05737 $qpValue = str_replace($search, $replace, $qpValue); 05738 $part = '=?' . $charset . '?Q?' . $qpValue . '?='; 05739 } 05740 break; 05741 } 05742 $line = str_replace($oldPart, $part, $line); 05743 } 05744 $line = preg_replace('/###(.+?)###/', '$1', $line); // Remove the wrappers 05745 05746 return $line; 05747 } 05748 05760 public static function substUrlsInPlainText($message, $urlmode = '76', $index_script_url = '') { 05761 // Substitute URLs with shorter links: 05762 foreach (array('http', 'https') as $protocol) { 05763 $urlSplit = explode($protocol . '://', $message); 05764 foreach ($urlSplit as $c => &$v) { 05765 if ($c) { 05766 $newParts = preg_split('/\s|[<>"{}|\\\^`()\']/', $v, 2); 05767 $newURL = $protocol . '://' . $newParts[0]; 05768 05769 switch ((string) $urlmode) { 05770 case 'all': 05771 $newURL = self::makeRedirectUrl($newURL, 0, $index_script_url); 05772 break; 05773 case '76': 05774 $newURL = self::makeRedirectUrl($newURL, 76, $index_script_url); 05775 break; 05776 } 05777 $v = $newURL . substr($v, strlen($newParts[0])); 05778 } 05779 } 05780 $message = implode('', $urlSplit); 05781 } 05782 05783 return $message; 05784 } 05785 05795 public static function makeRedirectUrl($inUrl, $l = 0, $index_script_url = '') { 05796 if (strlen($inUrl) > $l) { 05797 $md5 = substr(md5($inUrl), 0, 20); 05798 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows( 05799 '*', 05800 'cache_md5params', 05801 'md5hash=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($md5, 'cache_md5params') 05802 ); 05803 if (!$count) { 05804 $insertFields = array( 05805 'md5hash' => $md5, 05806 'tstamp' => $GLOBALS['EXEC_TIME'], 05807 'type' => 2, 05808 'params' => $inUrl 05809 ); 05810 05811 $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_md5params', $insertFields); 05812 } 05813 $inUrl = ($index_script_url ? $index_script_url : self::getIndpEnv('TYPO3_REQUEST_DIR') . 'index.php') . 05814 '?RDCT=' . $md5; 05815 } 05816 05817 return $inUrl; 05818 } 05819 05827 public static function freetypeDpiComp($font_size) { 05828 $dpi = intval($GLOBALS['TYPO3_CONF_VARS']['GFX']['TTFdpi']); 05829 if ($dpi != 72) { 05830 $font_size = $font_size / $dpi * 72; 05831 } 05832 return $font_size; 05833 } 05834 05841 public static function initSysLog() { 05842 global $TYPO3_CONF_VARS; 05843 05844 // for CLI logging name is <fqdn-hostname>:<TYPO3-path> 05845 // Note that TYPO3_REQUESTTYPE is not used here as it may not yet be defined 05846 if (defined('TYPO3_cliMode') && TYPO3_cliMode) { 05847 $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] = self::getHostname($requestHost = FALSE) . ':' . PATH_site; 05848 } 05849 // for Web logging name is <protocol>://<request-hostame>/<site-path> 05850 else { 05851 $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] = self::getIndpEnv('TYPO3_SITE_URL'); 05852 } 05853 05854 // init custom logging 05855 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'])) { 05856 $params = array('initLog' => TRUE); 05857 $fakeThis = FALSE; 05858 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'] as $hookMethod) { 05859 self::callUserFunction($hookMethod, $params, $fakeThis); 05860 } 05861 } 05862 05863 // init TYPO3 logging 05864 foreach (explode(';', $TYPO3_CONF_VARS['SYS']['systemLog'], 2) as $log) { 05865 list($type, $destination) = explode(',', $log, 3); 05866 05867 if ($type == 'syslog') { 05868 if (TYPO3_OS == 'WIN') { 05869 $facility = LOG_USER; 05870 } else { 05871 $facility = constant('LOG_' . strtoupper($destination)); 05872 } 05873 openlog($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'], LOG_ODELAY, $facility); 05874 } 05875 } 05876 05877 $TYPO3_CONF_VARS['SYS']['systemLogLevel'] = self::intInRange($TYPO3_CONF_VARS['SYS']['systemLogLevel'], 0, 4); 05878 $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogInit'] = TRUE; 05879 } 05880 05892 public static function sysLog($msg, $extKey, $severity = 0) { 05893 global $TYPO3_CONF_VARS; 05894 05895 $severity = self::intInRange($severity, 0, 4); 05896 05897 // is message worth logging? 05898 if (intval($TYPO3_CONF_VARS['SYS']['systemLogLevel']) > $severity) { 05899 return; 05900 } 05901 05902 // initialize logging 05903 if (!$TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogInit']) { 05904 self::initSysLog(); 05905 } 05906 05907 // do custom logging 05908 if (isset($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog']) && 05909 is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'])) { 05910 $params = array('msg' => $msg, 'extKey' => $extKey, 'backTrace' => debug_backtrace(), 'severity' => $severity); 05911 $fakeThis = FALSE; 05912 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'] as $hookMethod) { 05913 self::callUserFunction($hookMethod, $params, $fakeThis); 05914 } 05915 } 05916 05917 // TYPO3 logging enabled? 05918 if (!$TYPO3_CONF_VARS['SYS']['systemLog']) { 05919 return; 05920 } 05921 05922 $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']; 05923 $timeFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm']; 05924 05925 // use all configured logging options 05926 foreach (explode(';', $TYPO3_CONF_VARS['SYS']['systemLog'], 2) as $log) { 05927 list($type, $destination, $level) = explode(',', $log, 4); 05928 05929 // is message worth logging for this log type? 05930 if (intval($level) > $severity) { 05931 continue; 05932 } 05933 05934 $msgLine = ' - ' . $extKey . ': ' . $msg; 05935 05936 // write message to a file 05937 if ($type == 'file') { 05938 $file = fopen($destination, 'a'); 05939 if ($file) { 05940 flock($file, LOCK_EX); // try locking, but ignore if not available (eg. on NFS and FAT) 05941 fwrite($file, date($dateFormat . ' ' . $timeFormat) . $msgLine . LF); 05942 flock($file, LOCK_UN); // release the lock 05943 fclose($file); 05944 self::fixPermissions($destination); 05945 } 05946 } 05947 // send message per mail 05948 elseif ($type == 'mail') { 05949 list($to, $from) = explode('/', $destination); 05950 if (!t3lib_div::validEmail($from)) { 05951 $from = t3lib_utility_Mail::getSystemFrom(); 05952 } 05954 $mail = t3lib_div::makeInstance('t3lib_mail_Message'); 05955 $mail->setTo($to) 05956 ->setFrom($from) 05957 ->setSubject('Warning - error in TYPO3 installation') 05958 ->setBody('Host: ' . $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] . LF . 05959 'Extension: ' . $extKey . LF . 05960 'Severity: ' . $severity . LF . 05961 LF . $msg 05962 ); 05963 $mail->send(); 05964 } 05965 // use the PHP error log 05966 elseif ($type == 'error_log') { 05967 error_log($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] . $msgLine, 0); 05968 } 05969 // use the system log 05970 elseif ($type == 'syslog') { 05971 $priority = array(LOG_INFO, LOG_NOTICE, LOG_WARNING, LOG_ERR, LOG_CRIT); 05972 syslog($priority[(int) $severity], $msgLine); 05973 } 05974 } 05975 } 05976 05991 public static function devLog($msg, $extKey, $severity = 0, $dataVar = FALSE) { 05992 global $TYPO3_CONF_VARS; 05993 05994 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['devLog'])) { 05995 $params = array('msg' => $msg, 'extKey' => $extKey, 'severity' => $severity, 'dataVar' => $dataVar); 05996 $fakeThis = FALSE; 05997 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['devLog'] as $hookMethod) { 05998 self::callUserFunction($hookMethod, $params, $fakeThis); 05999 } 06000 } 06001 } 06002 06009 public static function deprecationLog($msg) { 06010 if (!$GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog']) { 06011 return; 06012 } 06013 06014 $log = $GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog']; 06015 $date = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'] . ': '); 06016 06017 // legacy values (no strict comparison, $log can be boolean, string or int) 06018 if ($log === TRUE || $log == '1') { 06019 $log = 'file'; 06020 } 06021 06022 if (stripos($log, 'file') !== FALSE) { 06023 // write a longer message to the deprecation log 06024 $destination = self::getDeprecationLogFileName(); 06025 $file = @fopen($destination, 'a'); 06026 if ($file) { 06027 flock($file, LOCK_EX); // try locking, but ignore if not available (eg. on NFS and FAT) 06028 @fwrite($file, $date . $msg . LF); 06029 flock($file, LOCK_UN); // release the lock 06030 @fclose($file); 06031 self::fixPermissions($destination); 06032 } 06033 } 06034 06035 if (stripos($log, 'devlog') !== FALSE) { 06036 // copy message also to the developer log 06037 self::devLog($msg, 'Core', self::SYSLOG_SEVERITY_WARNING); 06038 } 06039 06040 // do not use console in login screen 06041 if (stripos($log, 'console') !== FALSE && isset($GLOBALS['BE_USER']->user['uid'])) { 06042 t3lib_utility_Debug::debug($msg, $date, 'Deprecation Log'); 06043 } 06044 } 06045 06051 public static function getDeprecationLogFileName() { 06052 return PATH_typo3conf . 06053 'deprecation_' . 06054 self::shortMD5( 06055 PATH_site . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] 06056 ) . 06057 '.log'; 06058 } 06059 06065 public static function logDeprecatedFunction() { 06066 if (!$GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog']) { 06067 return; 06068 } 06069 06070 $trail = debug_backtrace(); 06071 06072 if ($trail[1]['type']) { 06073 $function = new ReflectionMethod($trail[1]['class'], $trail[1]['function']); 06074 } else { 06075 $function = new ReflectionFunction($trail[1]['function']); 06076 } 06077 06078 $msg = ''; 06079 if (preg_match('/@deprecated\s+(.*)/', $function->getDocComment(), $match)) { 06080 $msg = $match[1]; 06081 } 06082 06083 // trigger PHP error with a short message: <function> is deprecated (called from <source>, defined in <source>) 06084 $errorMsg = 'Function ' . $trail[1]['function']; 06085 if ($trail[1]['class']) { 06086 $errorMsg .= ' of class ' . $trail[1]['class']; 06087 } 06088 $errorMsg .= ' is deprecated (called from ' . $trail[1]['file'] . '#' . $trail[1]['line'] . ', defined in ' . $function->getFileName() . '#' . $function->getStartLine() . ')'; 06089 06090 // write a longer message to the deprecation log: <function> <annotion> - <trace> (<source>) 06091 $logMsg = $trail[1]['class'] . $trail[1]['type'] . $trail[1]['function']; 06092 $logMsg .= '() - ' . $msg.' - ' . t3lib_utility_Debug::debugTrail(); 06093 $logMsg .= ' (' . substr($function->getFileName(), strlen(PATH_site)) . '#' . $function->getStartLine() . ')'; 06094 self::deprecationLog($logMsg); 06095 } 06096 06106 public static function arrayToLogString(array $arr, $valueList = array(), $valueLength = 20) { 06107 $str = ''; 06108 if (!is_array($valueList)) { 06109 $valueList = self::trimExplode(',', $valueList, 1); 06110 } 06111 $valListCnt = count($valueList); 06112 foreach ($arr as $key => $value) { 06113 if (!$valListCnt || in_array($key, $valueList)) { 06114 $str .= (string) $key . trim(': ' . self::fixed_lgd_cs(str_replace(LF, '|', (string) $value), $valueLength)) . '; '; 06115 } 06116 } 06117 return $str; 06118 } 06119 06128 public static function imageMagickCommand($command, $parameters, $path = '') { 06129 return t3lib_utility_Command::imageMagickCommand($command, $parameters, $path); 06130 } 06131 06139 public static function unQuoteFilenames($parameters, $unQuote = FALSE) { 06140 $paramsArr = explode(' ', trim($parameters)); 06141 06142 $quoteActive = -1; // Whenever a quote character (") is found, $quoteActive is set to the element number inside of $params. A value of -1 means that there are not open quotes at the current position. 06143 foreach ($paramsArr as $k => $v) { 06144 if ($quoteActive > -1) { 06145 $paramsArr[$quoteActive] .= ' ' . $v; 06146 unset($paramsArr[$k]); 06147 if (substr($v, -1) === $paramsArr[$quoteActive][0]) { 06148 $quoteActive = -1; 06149 } 06150 } elseif (!trim($v)) { 06151 unset($paramsArr[$k]); // Remove empty elements 06152 06153 } elseif (preg_match('/^(["\'])/', $v) && substr($v, -1) !== $v[0]) { 06154 $quoteActive = $k; 06155 } 06156 } 06157 06158 if ($unQuote) { 06159 foreach ($paramsArr as $key => &$val) { 06160 $val = preg_replace('/(^"|"$)/', '', $val); 06161 $val = preg_replace('/(^\'|\'$)/', '', $val); 06162 06163 } 06164 } 06165 // return reindexed array 06166 return array_values($paramsArr); 06167 } 06168 06169 06183 static public function quoteJSvalue($value, $withinCData = FALSE) { 06184 $escapedValue = addcslashes( 06185 $value, '\'' . '"' . '\\' . TAB . LF . CR 06186 ); 06187 if (!$withinCData) { 06188 $escapedValue = htmlspecialchars($escapedValue); 06189 } 06190 return '\'' . $escapedValue . '\''; 06191 } 06192 06193 06199 public static function cleanOutputBuffers() { 06200 while (ob_end_clean()) { 06201 ; 06202 } 06203 header('Content-Encoding: None', TRUE); 06204 } 06205 06206 06212 public static function flushOutputBuffers() { 06213 $obContent = ''; 06214 06215 while ($obContent .= ob_get_clean()) { 06216 ; 06217 } 06218 06219 // if previously a "Content-Encoding: whatever" has been set, we have to unset it 06220 if (!headers_sent()) { 06221 $headersList = headers_list(); 06222 foreach ($headersList as $header) { 06223 // split it up at the : 06224 list($key, $value) = self::trimExplode(':', $header, TRUE); 06225 // check if we have a Content-Encoding other than 'None' 06226 if (strtolower($key) === 'content-encoding' && strtolower($value) !== 'none') { 06227 header('Content-Encoding: None'); 06228 break; 06229 } 06230 } 06231 } 06232 echo $obContent; 06233 } 06234 } 06235 06236 ?>