|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2009-2011 Oliver Hader <oliver@typo3.org> 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 ***************************************************************/ 00027 /** 00028 * Matching TypoScript conditions 00029 * 00030 * $Id: class.t3lib_matchcondition_abstract.php 10220 2011-01-21 18:08:15Z baschny $ 00031 * 00032 * Used with the TypoScript parser. 00033 * Matches browserinfo, IPnumbers for use with templates 00034 * 00035 * @author Oliver Hader <oliver@typo3.org> 00036 * @package TYPO3 00037 * @subpackage t3lib 00038 */ 00039 abstract class t3lib_matchCondition_abstract { 00040 /** 00041 * Id of the current page. 00042 * @var integer 00043 */ 00044 protected $pageId; 00045 /** 00046 * The rootline for the current page. 00047 * @var array 00048 */ 00049 protected $rootline; 00050 00051 /** 00052 * Whether to simulate the behaviour and match all conditions 00053 * (used in TypoScript object browser). 00054 * @var boolean 00055 */ 00056 protected $simulateMatchResult = FALSE; 00057 /** 00058 * Whether to simulat the behaviour and match specific conditions 00059 * (used in TypoScript object browser). 00060 * @var array 00061 */ 00062 protected $simulateMatchConditions = array(); 00063 00064 /** 00065 * Sets the id of the page to evaluate conditions for. 00066 * 00067 * @param integer $pageId: Id of the page (must be positive) 00068 * @return void 00069 */ 00070 public function setPageId($pageId) { 00071 if (is_integer($pageId) && $pageId > 0) { 00072 $this->pageId = $pageId; 00073 } 00074 } 00075 00076 /** 00077 * Gets the id of the page to evaluate conditions for. 00078 * 00079 * @return integer Id of the page 00080 */ 00081 public function getPageId() { 00082 return $this->pageId; 00083 } 00084 00085 /** 00086 * Sets the rootline. 00087 * 00088 * @param array $rootline: The rootline to be used for matching (must have elements) 00089 * @return void 00090 */ 00091 public function setRootline(array $rootline) { 00092 if (count($rootline)) { 00093 $this->rootline = $rootline; 00094 } 00095 } 00096 00097 /** 00098 * Gets the rootline. 00099 * 00100 * @return array The rootline to be used for matching 00101 */ 00102 public function getRootline() { 00103 return $this->rootline; 00104 } 00105 00106 /** 00107 * Sets whether to simulate the behaviour and match all conditions. 00108 * 00109 * @param boolean $simulateMatchResult: Whether to simulate positive matches 00110 * @return void 00111 */ 00112 public function setSimulateMatchResult($simulateMatchResult) { 00113 if (is_bool($simulateMatchResult)) { 00114 $this->simulateMatchResult = $simulateMatchResult; 00115 } 00116 } 00117 00118 /** 00119 * Sets whether to simulate the behaviour and match specific conditions. 00120 * 00121 * @param array $simulateMatchConditions: Conditions to simulate a match for 00122 * @return void 00123 */ 00124 public function setSimulateMatchConditions(array $simulateMatchConditions) { 00125 $this->simulateMatchConditions = $simulateMatchConditions; 00126 } 00127 00128 /** 00129 * Normalizes an expression and removes the first and last square bracket. 00130 * + OR normalization: "...]OR[...", "...]||[...", "...][..." --> "...]||[..." 00131 * + AND normalization: "...]AND[...", "...]&&[..." --> "...]&&[..." 00132 * 00133 * @param string $expression: The expression to be normalized (e.g. "[A] && [B] OR [C]") 00134 * @return string The normalized expression (e.g. "[A]&&[B]||[C]") 00135 */ 00136 protected function normalizeExpression($expression) { 00137 $normalizedExpression = preg_replace( 00138 array( 00139 '/\]\s*(OR|\|\|)?\s*\[/i', 00140 '/\]\s*(AND|&&)\s*\[/i', 00141 ), 00142 array( 00143 ']||[', 00144 ']&&[', 00145 ), 00146 trim($expression) 00147 ); 00148 00149 return $normalizedExpression; 00150 } 00151 00152 /** 00153 * Matches a TypoScript condition expression. 00154 * 00155 * @param string $expression: The expression to match 00156 * @return boolean Whether the expression matched 00157 */ 00158 public function match($expression) { 00159 // Return directly if result should be simulated: 00160 if ($this->simulateMatchResult) { 00161 return $this->simulateMatchResult; 00162 } 00163 // Return directly if matching for specific condition is simulated only: 00164 if (count($this->simulateMatchConditions)) { 00165 return in_array($expression, $this->simulateMatchConditions); 00166 } 00167 // Sets the current pageId if not defined yet: 00168 if (!isset($this->pageId)) { 00169 $this->pageId = $this->determinePageId(); 00170 } 00171 // Sets the rootline if not defined yet: 00172 if (!isset($this->rootline)) { 00173 $this->rootline = $this->determineRootline(); 00174 } 00175 00176 $result = FALSE; 00177 $normalizedExpression = $this->normalizeExpression($expression); 00178 00179 // First and last character must be square brackets (e.g. "[A]&&[B]": 00180 if (substr($normalizedExpression, 0, 1) === '[' && substr($normalizedExpression, -1) === ']') { 00181 $innerExpression = substr($normalizedExpression, 1, -1); 00182 00183 $orParts = explode(']||[', $innerExpression); 00184 foreach ($orParts as $orPart) { 00185 $andParts = explode(']&&[', $orPart); 00186 foreach ($andParts as $andPart) { 00187 $result = $this->evaluateCondition($andPart); 00188 // If condition in AND context fails, the whole block is false: 00189 if ($result === FALSE) { 00190 break; 00191 } 00192 } 00193 // If condition in OR context succeeds, the whole expression is true: 00194 if ($result === TRUE) { 00195 break; 00196 } 00197 } 00198 } 00199 00200 return $result; 00201 } 00202 00203 /** 00204 * Evaluates a TypoScript condition given as input, eg. "[browser=net][...(other conditions)...]" 00205 * 00206 * @param string The condition to match against its criterias. 00207 * @return mixed Returns true or false based on the evaluation 00208 */ 00209 protected function evaluateConditionCommon($key, $value) { 00210 if (t3lib_div::inList('browser,version,system,useragent', strtolower($key))) { 00211 $browserInfo = $this->getBrowserInfo(t3lib_div::getIndpEnv('HTTP_USER_AGENT')); 00212 } 00213 $keyParts = t3lib_div::trimExplode('|', $key); 00214 00215 switch ($keyParts[0]) { 00216 case 'browser': 00217 $values = t3lib_div::trimExplode(',', $value, TRUE); 00218 // take all identified browsers into account, eg chrome deliver 00219 // webkit=>532.5, chrome=>4.1, safari=>532.5 00220 // so comparing string will be 00221 // "webkit532.5 chrome4.1 safari532.5" 00222 $all = ''; 00223 foreach ($browserInfo['all'] as $key => $value) { 00224 $all .= $key . $value . ' '; 00225 } 00226 foreach ($values as $test) { 00227 if (stripos($all, $test) !== FALSE) { 00228 return TRUE; 00229 } 00230 } 00231 break; 00232 case 'version': 00233 $values = t3lib_div::trimExplode(',', $value, TRUE); 00234 foreach ($values as $test) { 00235 if (strcspn($test, '=<>') == 0) { 00236 switch (substr($test, 0, 1)) { 00237 case '=': 00238 if (doubleval(substr($test, 1)) == $browserInfo['version']) { 00239 return TRUE; 00240 } 00241 break; 00242 case '<': 00243 if (doubleval(substr($test, 1)) > $browserInfo['version']) { 00244 return TRUE; 00245 } 00246 break; 00247 case '>': 00248 if (doubleval(substr($test, 1)) < $browserInfo['version']) { 00249 return TRUE; 00250 } 00251 break; 00252 } 00253 } elseif (strpos(' ' . $browserInfo['version'], $test) == 1) { 00254 return TRUE; 00255 } 00256 } 00257 break; 00258 case 'system': 00259 $values = t3lib_div::trimExplode(',', $value, TRUE); 00260 // Take all identified systems into account, e.g. mac for iOS, Linux 00261 // for android and Windows NT for Windows XP 00262 $allSystems .= ' ' . implode(' ', $browserInfo['all_systems']); 00263 foreach ($values as $test) { 00264 if (stripos($allSystems, $test) !== FALSE) { 00265 return TRUE; 00266 } 00267 } 00268 break; 00269 case 'device': 00270 if (!isset($this->deviceInfo)) { 00271 $this->deviceInfo = $this->getDeviceType(t3lib_div::getIndpEnv('HTTP_USER_AGENT')); 00272 } 00273 $values = t3lib_div::trimExplode(',', $value, TRUE); 00274 foreach ($values as $test) { 00275 if ($this->deviceInfo == $test) { 00276 return TRUE; 00277 } 00278 } 00279 break; 00280 case 'useragent': 00281 $test = trim($value); 00282 if (strlen($test)) { 00283 return $this->searchStringWildcard($browserInfo['useragent'], $test); 00284 } 00285 break; 00286 case 'language': 00287 $values = t3lib_div::trimExplode(',', $value, TRUE); 00288 foreach ($values as $test) { 00289 if (preg_match('/^\*.+\*$/', $test)) { 00290 $allLanguages = preg_split('/[,;]/', t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE')); 00291 if (in_array(substr($test, 1, -1), $allLanguages)) { 00292 return TRUE; 00293 } 00294 } elseif (t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE') == $test) { 00295 return TRUE; 00296 } 00297 } 00298 break; 00299 case 'IP': 00300 if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $value)) { 00301 return TRUE; 00302 } 00303 break; 00304 case 'hostname': 00305 if (t3lib_div::cmpFQDN(t3lib_div::getIndpEnv('REMOTE_ADDR'), $value)) { 00306 return TRUE; 00307 } 00308 break; 00309 // hour, minute, dayofweek, dayofmonth, month, year, julianday 00310 case 'hour': 00311 case 'minute': 00312 case 'month': 00313 case 'year': 00314 case 'dayofweek': 00315 case 'dayofmonth': 00316 case 'dayofyear': 00317 $theEvalTime = $GLOBALS['SIM_EXEC_TIME']; // In order to simulate time properly in templates. 00318 switch ($key) { 00319 case 'hour': 00320 $theTestValue = date('H', $theEvalTime); 00321 break; 00322 case 'minute': 00323 $theTestValue = date('i', $theEvalTime); 00324 break; 00325 case 'month': 00326 $theTestValue = date('m', $theEvalTime); 00327 break; 00328 case 'year': 00329 $theTestValue = date('Y', $theEvalTime); 00330 break; 00331 case 'dayofweek': 00332 $theTestValue = date('w', $theEvalTime); 00333 break; 00334 case 'dayofmonth': 00335 $theTestValue = date('d', $theEvalTime); 00336 break; 00337 case 'dayofyear': 00338 $theTestValue = date('z', $theEvalTime); 00339 break; 00340 } 00341 $theTestValue = intval($theTestValue); 00342 // comp 00343 $values = t3lib_div::trimExplode(',', $value, TRUE); 00344 foreach ($values as $test) { 00345 if (t3lib_div::testInt($test)) { 00346 $test = '=' . $test; 00347 } 00348 if ($this->compareNumber($test, $theTestValue)) { 00349 return TRUE; 00350 } 00351 } 00352 break; 00353 case 'compatVersion': 00354 return t3lib_div::compat_version($value); 00355 break; 00356 case 'loginUser': 00357 if ($this->isUserLoggedIn()) { 00358 $values = t3lib_div::trimExplode(',', $value, TRUE); 00359 foreach ($values as $test) { 00360 if ($test == '*' || !strcmp($this->getUserId(), $test)) { 00361 return TRUE; 00362 } 00363 } 00364 } elseif ($value === '') { 00365 return TRUE; 00366 } 00367 break; 00368 case 'page': 00369 if ($keyParts[1]) { 00370 $page = $this->getPage(); 00371 $property = $keyParts[1]; 00372 if (!empty($page) && isset($page[$property])) { 00373 if (strcmp($page[$property], $value) === 0) { 00374 return TRUE; 00375 } 00376 } 00377 } 00378 break; 00379 case 'globalVar': 00380 $values = t3lib_div::trimExplode(',', $value, TRUE); 00381 foreach ($values as $test) { 00382 $point = strcspn($test, '!=<>'); 00383 $theVarName = substr($test, 0, $point); 00384 $nv = $this->getVariable(trim($theVarName)); 00385 $testValue = substr($test, $point); 00386 00387 if ($this->compareNumber($testValue, $nv)) { 00388 return TRUE; 00389 } 00390 } 00391 break; 00392 case 'globalString': 00393 $values = t3lib_div::trimExplode(',', $value, TRUE); 00394 foreach ($values as $test) { 00395 $point = strcspn($test, '='); 00396 $theVarName = substr($test, 0, $point); 00397 $nv = $this->getVariable(trim($theVarName)); 00398 $testValue = substr($test, $point + 1); 00399 00400 if ($this->searchStringWildcard($nv, trim($testValue))) { 00401 return TRUE; 00402 } 00403 } 00404 break; 00405 case 'userFunc': 00406 $values = preg_split('/\(|\)/', $value); 00407 $funcName = trim($values[0]); 00408 $funcValue = t3lib_div::trimExplode(',', $values[1]); 00409 $prefix = $this->getUserFuncClassPrefix(); 00410 if ($prefix && 00411 !t3lib_div::isFirstPartOfStr(trim($funcName), $prefix) && 00412 !t3lib_div::isFirstPartOfStr(trim($funcName), 'tx_') 00413 ) { 00414 $this->log('Match condition: Function "' . $funcName . '" was not prepended with "' . $prefix . '"'); 00415 return FALSE; 00416 } 00417 if (function_exists($funcName) && call_user_func($funcName, $funcValue[0])) { 00418 return TRUE; 00419 } 00420 break; 00421 } 00422 00423 return NULL; 00424 } 00425 00426 protected function getVariableCommon(array $vars) { 00427 $value = NULL; 00428 00429 if (count($vars) == 1) { 00430 $value = $this->getGlobal($vars[0]); 00431 } else { 00432 $splitAgain = explode('|', $vars[1], 2); 00433 $k = trim($splitAgain[0]); 00434 00435 if ($k) { 00436 switch ((string) trim($vars[0])) { 00437 case 'GP': 00438 $value = t3lib_div::_GP($k); 00439 break; 00440 case 'ENV': 00441 $value = getenv($k); 00442 break; 00443 case 'IENV': 00444 $value = t3lib_div::getIndpEnv($k); 00445 break; 00446 // return litteral value: 00447 case 'LIT': 00448 return trim($vars[1]); 00449 break; 00450 default: 00451 return NULL; 00452 } 00453 // If array: 00454 if (count($splitAgain) > 1) { 00455 if (is_array($value) && trim($splitAgain[1])) { 00456 $value = $this->getGlobal($splitAgain[1], $value); 00457 } else { 00458 $value = ''; 00459 } 00460 } 00461 } 00462 } 00463 00464 return $value; 00465 } 00466 00467 /** 00468 * Evaluates a $leftValue based on an operator: "<", ">", "<=", ">=", "!=" or "=" 00469 * 00470 * @param string $test: The value to compare with on the form [operator][number]. Eg. "< 123" 00471 * @param integer $leftValue: The value on the left side 00472 * @return boolean If $value is "50" and $test is "< 123" then it will return true. 00473 */ 00474 protected function compareNumber($test, $leftValue) { 00475 if (preg_match('/^(!?=+|<=?|>=?)\s*([^\s]*)\s*$/', $test, $matches)) { 00476 $operator = $matches[1]; 00477 $rightValue = $matches[2]; 00478 00479 switch ($operator) { 00480 case '>=': 00481 return ($leftValue >= doubleval($rightValue)); 00482 break; 00483 case '<=': 00484 return ($leftValue <= doubleval($rightValue)); 00485 break; 00486 case '!=': 00487 return ($leftValue != doubleval($rightValue)); 00488 break; 00489 case '<': 00490 return ($leftValue < doubleval($rightValue)); 00491 break; 00492 case '>': 00493 return ($leftValue > doubleval($rightValue)); 00494 break; 00495 default: 00496 // nothing valid found except '=', use '=' 00497 return ($leftValue == trim($rightValue)); 00498 break; 00499 } 00500 } 00501 00502 return FALSE; 00503 } 00504 00505 /** 00506 * Matching two strings against each other, supporting a "*" wildcard or (if wrapped in "/") PCRE regular expressions 00507 * 00508 * @param string The string in which to find $needle. 00509 * @param string The string to find in $haystack 00510 * @return boolean Returns true if $needle matches or is found in (according to wildcards) in $haystack. Eg. if $haystack is "Netscape 6.5" and $needle is "Net*" or "Net*ape" then it returns true. 00511 */ 00512 protected function searchStringWildcard($haystack, $needle) { 00513 $result = FALSE; 00514 00515 if ($needle) { 00516 if (preg_match('/^\/.+\/$/', $needle)) { 00517 // Regular expression, only "//" is allowed as delimiter 00518 $regex = $needle; 00519 } else { 00520 $needle = str_replace(array('*', '?'), array('###MANY###', '###ONE###'), $needle); 00521 $regex = '/^' . preg_quote($needle, '/') . '$/'; 00522 // Replace the marker with .* to match anything (wildcard) 00523 $regex = str_replace(array('###MANY###', '###ONE###'), array('.*', '.'), $regex); 00524 } 00525 00526 $result = (boolean) preg_match($regex, (string) $haystack); 00527 } 00528 00529 return $result; 00530 } 00531 00532 /** 00533 * Generates an array with abstracted browser information 00534 * 00535 * @param string $userAgent: The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT') 00536 * @return array Contains keys "browser", "version", "system" 00537 */ 00538 protected function getBrowserInfo($userAgent) { 00539 return t3lib_utility_Client::getBrowserInfo($userAgent); 00540 } 00541 00542 /** 00543 * Gets a code for a browsing device based on the input useragent string. 00544 * 00545 * @param string $userAgent: The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT') 00546 * @return string Code for the specific device type 00547 */ 00548 protected function getDeviceType($userAgent) { 00549 return t3lib_utility_Client::getDeviceType($userAgent); 00550 } 00551 00552 /** 00553 * Return global variable where the input string $var defines array keys separated by "|" 00554 * Example: $var = "HTTP_SERVER_VARS | something" will return the value $GLOBALS['HTTP_SERVER_VARS']['something'] value 00555 * 00556 * @param string Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the GET parameter "id" back. 00557 * @param array Alternative array than $GLOBAL to get variables from. 00558 * @return mixed Whatever value. If none, then blank string. 00559 */ 00560 protected function getGlobal($var, $source = NULL) { 00561 $vars = explode('|', $var); 00562 $c = count($vars); 00563 $k = trim($vars[0]); 00564 $theVar = isset($source) ? $source[$k] : $GLOBALS[$k]; 00565 00566 for ($a = 1; $a < $c; $a++) { 00567 if (!isset($theVar)) { 00568 break; 00569 } 00570 00571 $key = trim($vars[$a]); 00572 if (is_object($theVar)) { 00573 $theVar = $theVar->$key; 00574 } elseif (is_array($theVar)) { 00575 $theVar = $theVar[$key]; 00576 } else { 00577 return ''; 00578 } 00579 } 00580 00581 if (!is_array($theVar) && !is_object($theVar)) { 00582 return $theVar; 00583 } else { 00584 return ''; 00585 } 00586 } 00587 00588 00589 /** 00590 * Evaluates a TypoScript condition given as input, eg. "[browser=net][...(other conditions)...]" 00591 * 00592 * @param string $string: The condition to match against its criterias. 00593 * @return boolean Whether the condition matched 00594 * @see t3lib_tsparser::parse() 00595 */ 00596 abstract protected function evaluateCondition($string); 00597 00598 /** 00599 * Gets the value of a variable. 00600 * 00601 * Examples of names: 00602 * + TSFE:id 00603 * + GP:firstLevel|secondLevel 00604 * + _GET|firstLevel|secondLevel 00605 * + LIT:someLiteralValue 00606 * 00607 * @param string $name: The name of the variable to fetch the value from 00608 * @return mixed The value of the given variable (string) or NULL if variable did not exist 00609 */ 00610 abstract protected function getVariable($name); 00611 00612 /** 00613 * Gets the usergroup list of the current user. 00614 * 00615 * @return string The usergroup list of the current user 00616 */ 00617 abstract protected function getGroupList(); 00618 00619 /** 00620 * Determines the current page Id. 00621 * 00622 * @return integer The current page Id 00623 */ 00624 abstract protected function determinePageId(); 00625 00626 /** 00627 * Gets the properties for the current page. 00628 * 00629 * @return array The properties for the current page. 00630 */ 00631 abstract protected function getPage(); 00632 00633 /** 00634 * Determines the rootline for the current page. 00635 * 00636 * @return array The rootline for the current page. 00637 */ 00638 abstract protected function determineRootline(); 00639 00640 /** 00641 * Gets prefix for user functions (normally 'user_'). 00642 * 00643 * @return string The prefix for user functions (normally 'user_'). 00644 */ 00645 abstract protected function getUserFuncClassPrefix(); 00646 00647 /** 00648 * Gets the id of the current user. 00649 * 00650 * @return integer The id of the current user 00651 */ 00652 abstract protected function getUserId(); 00653 00654 /** 00655 * Determines if a user is logged in. 00656 * 00657 * @return boolean Determines if a user is logged in 00658 */ 00659 abstract protected function isUserLoggedIn(); 00660 00661 /** 00662 * Sets a log message. 00663 * 00664 * @param string $message: The log message to set/write 00665 * @return void 00666 */ 00667 abstract protected function log($message); 00668 } 00669 00670 ?>
1.8.0