TYPO3 CMS  TYPO3_6-2
AbstractConditionMatcher.php
Go to the documentation of this file.
1 <?php
3 
18 
27 abstract class AbstractConditionMatcher {
28 
34  protected $pageId;
35 
41  protected $rootline;
42 
49  protected $simulateMatchResult = FALSE;
50 
57  protected $simulateMatchConditions = array();
58 
65  public function setPageId($pageId) {
66  if (is_integer($pageId) && $pageId > 0) {
67  $this->pageId = $pageId;
68  }
69  }
70 
76  public function getPageId() {
77  return $this->pageId;
78  }
79 
86  public function setRootline(array $rootline) {
87  if (count($rootline)) {
88  $this->rootline = $rootline;
89  }
90  }
91 
97  public function getRootline() {
98  return $this->rootline;
99  }
100 
108  if (is_bool($simulateMatchResult)) {
109  $this->simulateMatchResult = $simulateMatchResult;
110  }
111  }
112 
120  $this->simulateMatchConditions = $simulateMatchConditions;
121  }
122 
131  protected function normalizeExpression($expression) {
132  $normalizedExpression = preg_replace(array(
133  '/\\]\\s*(OR|\\|\\|)?\\s*\\[/i',
134  '/\\]\\s*(AND|&&)\\s*\\[/i'
135  ), array(
136  ']||[',
137  ']&&['
138  ), trim($expression));
139  return $normalizedExpression;
140  }
141 
148  public function match($expression) {
149  // Return directly if result should be simulated:
150  if ($this->simulateMatchResult) {
152  }
153  // Return directly if matching for specific condition is simulated only:
154  if (count($this->simulateMatchConditions)) {
155  return in_array($expression, $this->simulateMatchConditions);
156  }
157  // Sets the current pageId if not defined yet:
158  if (!isset($this->pageId)) {
159  $this->pageId = $this->determinePageId();
160  }
161  // Sets the rootline if not defined yet:
162  if (!isset($this->rootline)) {
163  $this->rootline = $this->determineRootline();
164  }
165  $result = FALSE;
166  $normalizedExpression = $this->normalizeExpression($expression);
167  // First and last character must be square brackets (e.g. "[A]&&[B]":
168  if ($normalizedExpression[0] === '[' && substr($normalizedExpression, -1) === ']') {
169  $innerExpression = substr($normalizedExpression, 1, -1);
170  $orParts = explode(']||[', $innerExpression);
171  foreach ($orParts as $orPart) {
172  $andParts = explode(']&&[', $orPart);
173  foreach ($andParts as $andPart) {
174  $result = $this->evaluateCondition($andPart);
175  // If condition in AND context fails, the whole block is FALSE:
176  if ($result === FALSE) {
177  break;
178  }
179  }
180  // If condition in OR context succeeds, the whole expression is TRUE:
181  if ($result === TRUE) {
182  break;
183  }
184  }
185  }
186  return $result;
187  }
188 
196  protected function evaluateConditionCommon($key, $value) {
197  if (GeneralUtility::inList('browser,version,system,useragent', strtolower($key))) {
198  $browserInfo = $this->getBrowserInfo(GeneralUtility::getIndpEnv('HTTP_USER_AGENT'));
199  }
200  $keyParts = GeneralUtility::trimExplode('|', $key);
201  switch ($keyParts[0]) {
202  case 'applicationContext':
203  $values = GeneralUtility::trimExplode(',', $value, TRUE);
204  $currentApplicationContext = GeneralUtility::getApplicationContext();
205  foreach ($values as $applicationContext) {
206  if ($this->searchStringWildcard($currentApplicationContext, $applicationContext)) {
207  return TRUE;
208  }
209  }
210  break;
211  case 'browser':
212  $values = GeneralUtility::trimExplode(',', $value, TRUE);
213  // take all identified browsers into account, eg chrome deliver
214  // webkit=>532.5, chrome=>4.1, safari=>532.5
215  // so comparing string will be
216  // "webkit532.5 chrome4.1 safari532.5"
217  $all = '';
218  foreach ($browserInfo['all'] as $key => $value) {
219  $all .= $key . $value . ' ';
220  }
221  foreach ($values as $test) {
222  if (stripos($all, $test) !== FALSE) {
223  return TRUE;
224  }
225  }
226  break;
227  case 'version':
228  $values = GeneralUtility::trimExplode(',', $value, TRUE);
229  foreach ($values as $test) {
230  if (strcspn($test, '=<>') == 0) {
231  switch ($test[0]) {
232  case '=':
233  if (doubleval(substr($test, 1)) == $browserInfo['version']) {
234  return TRUE;
235  }
236  break;
237  case '<':
238  if (doubleval(substr($test, 1)) > $browserInfo['version']) {
239  return TRUE;
240  }
241  break;
242  case '>':
243  if (doubleval(substr($test, 1)) < $browserInfo['version']) {
244  return TRUE;
245  }
246  break;
247  }
248  } elseif (strpos(' ' . $browserInfo['version'], $test) == 1) {
249  return TRUE;
250  }
251  }
252  break;
253  case 'system':
254  $values = GeneralUtility::trimExplode(',', $value, TRUE);
255  // Take all identified systems into account, e.g. mac for iOS, Linux
256  // for android and Windows NT for Windows XP
257  $allSystems = ' ' . implode(' ', $browserInfo['all_systems']);
258  foreach ($values as $test) {
259  if (stripos($allSystems, $test) !== FALSE) {
260  return TRUE;
261  }
262  }
263  break;
264  case 'device':
265  if (!isset($this->deviceInfo)) {
266  $this->deviceInfo = $this->getDeviceType(GeneralUtility::getIndpEnv('HTTP_USER_AGENT'));
267  }
268  $values = GeneralUtility::trimExplode(',', $value, TRUE);
269  foreach ($values as $test) {
270  if ($this->deviceInfo == $test) {
271  return TRUE;
272  }
273  }
274  break;
275  case 'useragent':
276  $test = trim($value);
277  if ($test !== '') {
278  return $this->searchStringWildcard((string)$browserInfo['useragent'], $test);
279  }
280  break;
281  case 'language':
282  $values = GeneralUtility::trimExplode(',', $value, TRUE);
283  foreach ($values as $test) {
284  if (preg_match('/^\\*.+\\*$/', $test)) {
285  $allLanguages = preg_split('/[,;]/', GeneralUtility::getIndpEnv('HTTP_ACCEPT_LANGUAGE'));
286  if (in_array(substr($test, 1, -1), $allLanguages)) {
287  return TRUE;
288  }
289  } elseif (GeneralUtility::getIndpEnv('HTTP_ACCEPT_LANGUAGE') == $test) {
290  return TRUE;
291  }
292  }
293  break;
294  case 'IP':
295  if ($value === 'devIP') {
296  $value = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
297  }
298 
299  if (GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $value)) {
300  return TRUE;
301  }
302  break;
303  case 'hostname':
304  if (GeneralUtility::cmpFQDN(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $value)) {
305  return TRUE;
306  }
307  break;
308  case 'hour':
309 
310  case 'minute':
311 
312  case 'month':
313 
314  case 'year':
315 
316  case 'dayofweek':
317 
318  case 'dayofmonth':
319 
320  case 'dayofyear':
321  // In order to simulate time properly in templates.
322  $theEvalTime = $GLOBALS['SIM_EXEC_TIME'];
323  switch ($key) {
324  case 'hour':
325  $theTestValue = date('H', $theEvalTime);
326  break;
327  case 'minute':
328  $theTestValue = date('i', $theEvalTime);
329  break;
330  case 'month':
331  $theTestValue = date('m', $theEvalTime);
332  break;
333  case 'year':
334  $theTestValue = date('Y', $theEvalTime);
335  break;
336  case 'dayofweek':
337  $theTestValue = date('w', $theEvalTime);
338  break;
339  case 'dayofmonth':
340  $theTestValue = date('d', $theEvalTime);
341  break;
342  case 'dayofyear':
343  $theTestValue = date('z', $theEvalTime);
344  break;
345  }
346  $theTestValue = (int)$theTestValue;
347  // comp
348  $values = GeneralUtility::trimExplode(',', $value, TRUE);
349  foreach ($values as $test) {
350  if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($test)) {
351  $test = '=' . $test;
352  }
353  if ($this->compareNumber($test, $theTestValue)) {
354  return TRUE;
355  }
356  }
357  break;
358  case 'compatVersion':
359  return GeneralUtility::compat_version($value);
360  break;
361  case 'loginUser':
362  if ($this->isUserLoggedIn()) {
363  $values = GeneralUtility::trimExplode(',', $value, TRUE);
364  foreach ($values as $test) {
365  if ($test == '*' || (string)$this->getUserId() === (string)$test) {
366  return TRUE;
367  }
368  }
369  } elseif ($value === '') {
370  return TRUE;
371  }
372  break;
373  case 'page':
374  if ($keyParts[1]) {
375  $page = $this->getPage();
376  $property = $keyParts[1];
377  if (!empty($page) && isset($page[$property]) && (string)$page[$property] === (string)$value) {
378  return TRUE;
379  }
380  }
381  break;
382  case 'globalVar':
383  $values = GeneralUtility::trimExplode(',', $value, TRUE);
384  foreach ($values as $test) {
385  $point = strcspn($test, '!=<>');
386  $theVarName = substr($test, 0, $point);
387  $nv = $this->getVariable(trim($theVarName));
388  $testValue = substr($test, $point);
389  if ($this->compareNumber($testValue, $nv)) {
390  return TRUE;
391  }
392  }
393  break;
394  case 'globalString':
395  $values = GeneralUtility::trimExplode(',', $value, TRUE);
396  foreach ($values as $test) {
397  $point = strcspn($test, '=');
398  $theVarName = substr($test, 0, $point);
399  $nv = (string)$this->getVariable(trim($theVarName));
400  $testValue = substr($test, $point + 1);
401  if ($this->searchStringWildcard($nv, trim($testValue))) {
402  return TRUE;
403  }
404  }
405  break;
406  case 'userFunc':
407  $matches = array();
408  preg_match_all('/^\s*([^\(\s]+)\s*(?:\((.*)\))?\s*$/', $value, $matches);
409  $funcName = $matches[1][0];
410  $funcValues = trim($matches[2][0]) !== '' ? $this->parseUserFuncArguments($matches[2][0]) : array();
411  if (is_callable($funcName) && call_user_func_array($funcName, $funcValues)) {
412  return TRUE;
413  }
414  break;
415  }
416  return NULL;
417  }
418 
425  protected function parseUserFuncArguments($arguments) {
426  $result = array();
427  $arguments = trim($arguments);
428  while ($arguments !== '') {
429  if ($arguments[0] === ',') {
430  $result[] = '';
431  $arguments = substr($arguments, 1);
432  } else {
433  $pos = strcspn($arguments, ',\'"');
434  if ($pos == 0) {
435  // We hit a quote of some kind
436  $quote = $arguments[0];
437  $segment = preg_replace('/^(.*?[^\\\])' . $quote . '.*$/', '\1', substr($arguments, 1));
438  $segment = str_replace('\\' . $quote, $quote, $segment);
439  $result[] = $segment;
440  // shorten $arguments
441  $arguments = substr($arguments, strlen($segment) + 2);
442  $offset = strpos($arguments, ',');
443  if ($offset === FALSE) {
444  $offset = strlen($arguments);
445  }
446  $arguments = substr($arguments, $offset + 1);
447  } else {
448  $result[] = trim(substr($arguments, 0, $pos));
449  $arguments = substr($arguments, $pos + 1);
450  }
451  }
452  $arguments = trim($arguments);
453  };
454  return $result;
455  }
456 
463  protected function getVariableCommon(array $vars) {
464  $value = NULL;
465  if (count($vars) == 1) {
466  $value = $this->getGlobal($vars[0]);
467  } else {
468  $splitAgain = explode('|', $vars[1], 2);
469  $k = trim($splitAgain[0]);
470  if ($k) {
471  switch ((string) trim($vars[0])) {
472  case 'GP':
473  $value = GeneralUtility::_GP($k);
474  break;
475  case 'ENV':
476  $value = getenv($k);
477  break;
478  case 'IENV':
479  $value = GeneralUtility::getIndpEnv($k);
480  break;
481  case 'LIT':
482  return trim($vars[1]);
483  break;
484  default:
485  return NULL;
486  }
487  // If array:
488  if (count($splitAgain) > 1) {
489  if (is_array($value) && trim($splitAgain[1]) !== '') {
490  $value = $this->getGlobal($splitAgain[1], $value);
491  } else {
492  $value = '';
493  }
494  }
495  }
496  }
497  return $value;
498  }
499 
507  protected function compareNumber($test, $leftValue) {
508  if (preg_match('/^(!?=+|<=?|>=?)\\s*([^\\s]*)\\s*$/', $test, $matches)) {
509  $operator = $matches[1];
510  $rightValue = $matches[2];
511  switch ($operator) {
512  case '>=':
513  return $leftValue >= doubleval($rightValue);
514  break;
515  case '<=':
516  return $leftValue <= doubleval($rightValue);
517  break;
518  case '!=':
519  // multiple values may be split with '|'
520  // see if none matches ("not in list")
521  $found = FALSE;
522  $rightValueParts = GeneralUtility::trimExplode('|', $rightValue);
523  foreach ($rightValueParts as $rightValueSingle) {
524  if ($leftValue == doubleval($rightValueSingle)) {
525  $found = TRUE;
526  break;
527  }
528  }
529  return $found === FALSE;
530  break;
531  case '<':
532  return $leftValue < doubleval($rightValue);
533  break;
534  case '>':
535  return $leftValue > doubleval($rightValue);
536  break;
537  default:
538  // nothing valid found except '=', use '='
539  // multiple values may be split with '|'
540  // see if one matches ("in list")
541  $found = FALSE;
542  $rightValueParts = GeneralUtility::trimExplode('|', $rightValue);
543  foreach ($rightValueParts as $rightValueSingle) {
544  if ($leftValue == $rightValueSingle) {
545  $found = TRUE;
546  break;
547  }
548  }
549  return $found;
550  }
551  }
552  return FALSE;
553  }
554 
562  protected function searchStringWildcard($haystack, $needle) {
563  $result = FALSE;
564  if ($haystack === $needle) {
565  $result = TRUE;
566  } elseif ($needle) {
567  if (preg_match('/^\\/.+\\/$/', $needle)) {
568  // Regular expression, only "//" is allowed as delimiter
569  $regex = $needle;
570  } else {
571  $needle = str_replace(array('*', '?'), array('###MANY###', '###ONE###'), $needle);
572  $regex = '/^' . preg_quote($needle, '/') . '$/';
573  // Replace the marker with .* to match anything (wildcard)
574  $regex = str_replace(array('###MANY###', '###ONE###'), array('.*', '.'), $regex);
575  }
576  $result = (bool)preg_match($regex, $haystack);
577  }
578  return $result;
579  }
580 
587  protected function getBrowserInfo($userAgent) {
588  return \TYPO3\CMS\Core\Utility\ClientUtility::getBrowserInfo($userAgent);
589  }
590 
597  protected function getDeviceType($userAgent) {
598  return \TYPO3\CMS\Core\Utility\ClientUtility::getDeviceType($userAgent);
599  }
600 
609  protected function getGlobal($var, $source = NULL) {
610  $vars = explode('|', $var);
611  $c = count($vars);
612  $k = trim($vars[0]);
613  $theVar = isset($source) ? $source[$k] : $GLOBALS[$k];
614  for ($a = 1; $a < $c; $a++) {
615  if (!isset($theVar)) {
616  break;
617  }
618  $key = trim($vars[$a]);
619  if (is_object($theVar)) {
620  $theVar = $theVar->{$key};
621  } elseif (is_array($theVar)) {
622  $theVar = $theVar[$key];
623  } else {
624  return '';
625  }
626  }
627  if (!is_array($theVar) && !is_object($theVar)) {
628  return $theVar;
629  } else {
630  return '';
631  }
632  }
633 
641  abstract protected function evaluateCondition($string);
642 
655  abstract protected function getVariable($name);
656 
662  abstract protected function getGroupList();
663 
669  abstract protected function determinePageId();
670 
676  abstract protected function getPage();
677 
683  abstract protected function determineRootline();
684 
690  abstract protected function getUserId();
691 
697  abstract protected function isUserLoggedIn();
698 
705  abstract protected function log($message);
706 
707 }
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]