Fixed bug #10735: Wrong returnUrl with clipboard actions
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_matchcondition.php
index a187033..8278e7d 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
  *
  *
  *
- *   77: class t3lib_matchCondition
- *   91:     function match($string)
- *  311:     function testNumber($test,$value)
- *  333:     function matchWild($haystack,$needle)
- *  363:     function whichDevice($useragent)
- *  413:     function browserInfo($useragent)
- *  517:     function browserInfo_version($tmp)
- *  529:     function getGlobal($var,$inArr='')
- *  554:     function getGP_ENV_TSFE($var)
+ *   80: class t3lib_matchCondition
+ *   87:     function __construct()
+ *  105:     function t3lib_matchCondition()
+ *  115:     function match($condition_line)
+ *  160:     function evalConditionStr($string)
+ *  381:     function testNumber($test,$value)
+ *  405:     function matchWild($haystack,$needle)
+ *  429:     function whichDevice($useragent)
+ *  498:     function browserInfo($useragent)
+ *  611:     function browserInfo_version($tmp)
+ *  624:     function getGlobal($var, $source=NULL)
+ *  658:     function getGP_ENV_TSFE($var)
  *
- * TOTAL FUNCTIONS: 8
+ * TOTAL FUNCTIONS: 11
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
@@ -79,6 +82,77 @@ class t3lib_matchCondition {
        var $matchAll=0;                                        // If set all is matched!
 
        var $altRootLine=array();
+       var $hookObjectsArr = array();
+
+       /**
+        * Constructor for this class
+        *
+        * @return      void
+        */
+       function __construct()  {
+               global $TYPO3_CONF_VARS;
+
+               // Usage (ext_localconf.php):
+               // $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['matchConditionClass'][] =
+               // 'EXT:my_ext/class.browserinfo.php:MyBrowserInfoClass';
+               if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['matchConditionClass'])) {
+                       foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['matchConditionClass'] as $classRef) {
+                               $this->hookObjectsArr[] = &t3lib_div::getUserObj($classRef, '');
+                       }
+               }
+       }
+
+       /**
+        * Constructor for this class
+        *
+        * @return      void
+        */
+       function t3lib_matchCondition() {
+               $this->__construct();
+       }
+
+       /**
+        * Matching TS condition
+        *
+        * @param       string          Line to match
+        * @return      boolean         True if matched
+        */
+       function match($condition_line) {
+               if ($this->matchAll) {
+                       return true;
+               }
+               if (count($this->matchAlternative))     {
+                       return in_array($condition_line, $this->matchAlternative);
+               }
+
+                       // Getting the value from inside of the wrapping square brackets of the condition line:
+               $insideSqrBrackets = substr(trim($condition_line), 1, strlen($condition_line) - 2);
+               $insideSqrBrackets = preg_replace('/\]\s*OR\s*\[/i', ']||[', $insideSqrBrackets);
+               $insideSqrBrackets = preg_replace('/\]\s*AND\s*\[/i', ']&&[', $insideSqrBrackets);
+
+                       // The "weak" operator "||" (OR) takes precedence: backwards compatible, [XYZ][ZYX] does still work as OR
+               $orParts = preg_split('/\]\s*(\|\|){0,1}\s*\[/',$insideSqrBrackets);
+
+               foreach ($orParts as $partString)       {
+                       $matches = false;
+
+                               // Splits by the "&&" (AND) operator:
+                       $andParts = preg_split('/\]\s*&&\s*\[/',$partString);
+                       foreach ($andParts as $condStr) {
+                               $matches = $this->evalConditionStr($condStr);
+                               if ($matches===false)   {
+                                       break;          // only true AND true = true, so we have to break here
+                               }
+                       }
+
+                       if ($matches===true)    {
+                               break;          // true OR false = true, so we break if we have a positive result
+                       }
+               }
+
+               return $matches;
+       }
+
 
        /**
         * Evaluates a TypoScript condition given as input, eg. "[browser=net][...(other conditions)...]"
@@ -88,271 +162,289 @@ class t3lib_matchCondition {
         * @see t3lib_tsparser::parse()
         * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=292&cHash=c6c7d43d2f
         */
-       function match($string) {
-               if ( !is_array( $this->altRootLine ) ) {
+       function evalConditionStr($string)      {
+               if (!is_array($this->altRootLine)) {
                        $this->altRootLine = array();
                }
-
-               if ($this->matchAll)    return true;
-               if (count($this->matchAlternative))     {
-                       return in_array($string,$this->matchAlternative);
+               list($key, $value) = explode('=', $string, 2);
+               $key = trim($key);
+               $value = trim($value);
+               if (t3lib_div::inList('browser,version,system,useragent', strtolower($key))) {
+                       $browserInfo = $this->browserInfo(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
                }
-
-               if (!$this->browserInfoArray)   {
-                       $this->browserInfoArray = $this->browserInfo(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
-               }
-               $browserInfo = $this->browserInfoArray;
-               $string = trim($string);
-               $string = substr($string,1,strlen($string)-2);
-               $parts = explode('][',$string);
-               reset($parts);
-               while(list(,$val)=each($parts)) {
-                       $pcs = explode('=',$val,2);
-                       $switchKey = trim($pcs[0]);
-                       switch($switchKey)      {
-                               case 'browser':
-                                       $values = explode(',',$pcs[1]);
-                                       while(list(,$test)=each($values))       {
-                                               if (strstr($browserInfo['browser'].$browserInfo['version'],trim($test)))        {
-                                                       return true;
-                                               }
+               switch ($key) {
+                       case 'browser':
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               foreach ($values as $test) {
+                                       if (strpos($browserInfo['browser'] . $browserInfo['version'], $test) !== false) {
+                                               return true;
                                        }
-                               break;
-                               case 'version':
-                                       $values = explode(',',$pcs[1]);
-                                       while(list(,$test)=each($values))       {
-                                               $test = trim($test);
-                                               if ($test)      {
-                                                       if (strcspn($test,'=<>')==0)    {
-                                                               switch(substr($test,0,1))       {
-                                                                       case '=':
-                                                                               if (doubleval(substr($test,1))==$browserInfo['version'])        return true;
-                                                                       break;
-                                                                       case '<':
-                                                                               if (doubleval(substr($test,1))>$browserInfo['version']) return true;
-                                                                       break;
-                                                                       case '>':
-                                                                               if (doubleval(substr($test,1))<$browserInfo['version']) return true;
-                                                                       break;
+                               }
+                       break;
+                       case 'version':
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               foreach ($values as $test) {
+                                       if (strcspn($test, '=<>') == 0) {
+                                               switch (substr($test, 0, 1)) {
+                                                       case '=':
+                                                               if (doubleval(substr($test, 1)) == $browserInfo['version']) {
+                                                                       return true;
                                                                }
-                                                       } else {
-                                                               if (strpos(' '.$browserInfo['version'],$test)==1)       {return true;}
-                                                       }
+                                                       break;
+                                                       case '<':
+                                                               if (doubleval(substr($test, 1)) > $browserInfo['version']) {
+                                                                       return true;
+                                                               }
+                                                       break;
+                                                       case '>':
+                                                               if (doubleval(substr($test, 1)) < $browserInfo['version']) {
+                                                                       return true;
+                                                               }
+                                                       break;
                                                }
-                                       }
-                               break;
-                               case 'system':
-                                       $values = explode(',',$pcs[1]);
-                                       while(list(,$test)=each($values))       {
-                                               $test = trim($test);
-                                               if ($test)      {
-                                                       if (strpos(' '.$browserInfo['system'],$test)==1)        {return true;}
+                                       } else {
+                                               if (strpos(' ' . $browserInfo['version'], $test) == 1) {
+                                                       return true;
                                                }
                                        }
-                               break;
-                               case 'device':
-                                       $values = explode(',',$pcs[1]);
-                                       if (!isset($this->deviceInfo))  {
-                                               $this->deviceInfo = $this->whichDevice(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
-                                       }
-                                       while(list(,$test)=each($values))       {
-                                               $test = trim($test);
-                                               if ($test)      {
-                                                       if ($this->deviceInfo==$test)   {return true;}
-                                               }
+                               }
+                       break;
+                       case 'system':
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               foreach ($values as $test) {
+                                       if (strpos(' ' . $browserInfo['system'], $test) == 1) {
+                                               return true;
                                        }
-                               break;
-                               case 'useragent':
-                                       $test = trim($pcs[1]);
-                                       if ($test)      {
-                                               return $this->matchWild($browserInfo['useragent'],$test);
+                               }
+                       break;
+                       case 'device':
+                               if (!isset($this->deviceInfo)) {
+                                       $this->deviceInfo = $this->whichDevice(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
+                               }
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               foreach ($values as $test) {
+                                       if ($this->deviceInfo == $test) {
+                                               return true;
                                        }
-                               break;
-                               case 'language':
-                                       $values = explode(',',$pcs[1]);
-                                       while(list(,$test)=each($values))       {
-                                               $test = trim($test);
-                                               if ($test)      {
-                                                       if (ereg('^\*.+\*$',$test))     {
-                                                               $allLanguages = split('[,;]',t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE'));
-                                                               if (in_array(substr($test,1,-1), $allLanguages))        {return true;}
-                                                       } else {
-                                                               if (t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE') == $test)     {return true;}
-                                                       }
+                               }
+                       break;
+                       case 'useragent':
+                               $test = trim($value);
+                               if (strlen($test)) {
+                                       return $this->matchWild($browserInfo['useragent'], $test);
+                               }
+                       break;
+                       case 'language':
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               foreach ($values as $test) {
+                                       if (preg_match('/^\*.+\*$/', $test)) {
+                                               $allLanguages = preg_split('/[,;]/', t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE'));
+                                               if (in_array(substr($test, 1, -1), $allLanguages)) {
+                                                       return true;
                                                }
+                                       } else if (t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE') == $test) {
+                                               return true;
                                        }
-                               break;
-                               case 'IP':
-                                       if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1]))    {return true;}
-                               break;
-                               case 'hostname':
-                                       if (t3lib_div::cmpFQDN(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1]))  {return true;}
-                               break;
-                                       // hour, minute, dayofweek, dayofmonth, month
-                               case 'hour':
-                               case 'minute':
-                               case 'dayofweek':
-                               case 'dayofmonth':
-                               case 'month':
-                                       $theEvalTime = $GLOBALS['SIM_EXEC_TIME'];       // In order to simulate time properly in templates.
-                                       switch($switchKey)      {
-                                               case 'hour':            $theTestValue = date('H',$theEvalTime); break;
-                                               case 'minute':          $theTestValue = date('i',$theEvalTime); break;
-                                               case 'dayofweek':       $theTestValue = date('w',$theEvalTime); break;
-                                               case 'dayofmonth':      $theTestValue = date('d',$theEvalTime); break;
-                                               case 'month':           $theTestValue = date('m',$theEvalTime); break;
+                               }
+                       break;
+                       case 'IP':
+                               if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $value)) {
+                                       return true;
+                               }
+                       break;
+                       case 'hostname':
+                               if (t3lib_div::cmpFQDN(t3lib_div::getIndpEnv('REMOTE_ADDR'), $value)) {
+                                       return true;
+                               }
+                       break;
+                               // hour, minute, dayofweek, dayofmonth, month, year, julianday
+                       case 'hour':
+                       case 'minute':
+                       case 'month':
+                       case 'year':
+                       case 'dayofweek':
+                       case 'dayofmonth':
+                       case 'dayofyear':
+                               $theEvalTime = $GLOBALS['SIM_EXEC_TIME'];       // In order to simulate time properly in templates.
+                               switch($key) {
+                                       case 'hour':            $theTestValue = date('H', $theEvalTime);        break;
+                                       case 'minute':          $theTestValue = date('i', $theEvalTime);        break;
+                                       case 'month':           $theTestValue = date('m', $theEvalTime);        break;
+                                       case 'year':            $theTestValue = date('Y', $theEvalTime);        break;
+                                       case 'dayofweek':       $theTestValue = date('w', $theEvalTime);        break;
+                                       case 'dayofmonth':      $theTestValue = date('d', $theEvalTime);        break;
+                                       case 'dayofyear':       $theTestValue = date('z', $theEvalTime);        break;
+                               }
+                               $theTestValue = intval($theTestValue);
+                                       // comp
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               foreach ($values as $test) {
+                                       if (t3lib_div::testInt($test)) {
+                                               $test = '=' . $test;
                                        }
-                                       $theTestValue = intval($theTestValue);
-                                               // comp
-                                       $values = explode(',',$pcs[1]);
-                                       reset($values);
-                                       while(list(,$test)=each($values))       {
-                                               $test = trim($test);
-                                               if (t3lib_div::testInt($test))  {$test='='.$test;}
-                                               if ($test)      {
-                                                       if ($this->testNumber($test,$theTestValue)) {return true;}
-                                               }
+                                       if ($this->testNumber($test, $theTestValue)) {
+                                               return true;
                                        }
-                               break;
-                               case 'usergroup':
-                                       if ($GLOBALS['TSFE']->gr_list!='0,-1')  {               // '0,-1' is the default usergroups when not logged in!
-                                               $values = explode(',',$pcs[1]);
-                                               while(list(,$test)=each($values))       {
-                                                       $test = trim($test);
-                                                       if ($test)      {
-                                                               if ($test=='*' || t3lib_div::inList($GLOBALS['TSFE']->gr_list,$test))   {return true;}
-                                                       }
+                               }
+                       break;
+                       case 'usergroup':
+                               if ($GLOBALS['TSFE']->gr_list != '0,-1') {              // '0,-1' is the default usergroups when not logged in!
+                                       $values = t3lib_div::trimExplode(',', $value, true);
+                                       foreach ($values as $test) {
+                                               if ($test == '*' || t3lib_div::inList($GLOBALS['TSFE']->gr_list, $test)) {
+                                                       return true;
                                                }
                                        }
-                               break;
-                               case 'loginUser':
-                                       if ($GLOBALS['TSFE']->loginUser)        {
-                                               $values = explode(',',$pcs[1]);
-                                               while(list(,$test)=each($values))       {
-                                                       $test = trim($test);
-                                                       if ($test)      {
-                                                               if ($test=='*' || !strcmp($GLOBALS['TSFE']->fe_user->user['uid'],$test))        {return true;}
-                                                       }
+                               }
+                       break;
+                       case 'loginUser':
+                               if ($GLOBALS['TSFE']->loginUser) {
+                                       $values = t3lib_div::trimExplode(',', $value, true);
+                                       foreach ($values as $test) {
+                                               if ($test == '*' || !strcmp($GLOBALS['TSFE']->fe_user->user['uid'], $test)) {
+                                                       return true;
                                                }
                                        }
-                               break;
-                               case 'globalVar':
-                                       $values = explode(',',$pcs[1]);
-                                       while(list(,$test)=each($values))       {
-                                               $test = trim($test);
-                                               if ($test)      {
-                                                       $point = strcspn($test,'=<>');
-                                                       $theVarName = substr($test,0,$point);
-                                                       $nv = $this->getGP_ENV_TSFE(trim($theVarName));
-                                                       if ($this->testNumber(substr($test,$point) ,$nv)) {return true;}
-                                               }
+                               }
+                       break;
+                       case 'globalVar':
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               foreach ($values as $test) {
+                                       $point = strcspn($test, '!=<>');
+                                       $theVarName = substr($test, 0, $point);
+                                       $nv = $this->getGP_ENV_TSFE(trim($theVarName));
+                                       $testValue = substr($test, $point);
+
+                                       if ($this->testNumber($testValue, $nv)) {
+                                               return true;
                                        }
-                               break;
-                               case 'globalString':
-                                       $values = explode(',',$pcs[1]);
-                                       while(list(,$test)=each($values))       {
-                                               $test = trim($test);
-                                               if ($test)      {
-                                                       $point = strcspn($test,'=');
-                                                       $theVarName = substr($test,0,$point);
-                                                       $nv = $this->getGP_ENV_TSFE(trim($theVarName));
-                                                       if ($this->matchWild($nv,trim(substr($test,$point+1)))) {return true;}
-                                               }
+                               }
+                       break;
+                       case 'globalString':
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               foreach ($values as $test) {
+                                       $point = strcspn($test, '=');
+                                       $theVarName = substr($test, 0, $point);
+                                       $nv = $this->getGP_ENV_TSFE(trim($theVarName));
+                                       $testValue = substr($test, $point+1);
+
+                                       if ($this->matchWild($nv, trim($testValue))) {
+                                               return true;
                                        }
-                               break;
-                               case 'treeLevel':
-                                       $values = explode(',',$pcs[1]);
-                                       $theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
-                                       $theRLC = count($theRootLine)-1;
-                                       while(list(,$test)=each($values))       {
-                                               $test = trim($test);
-                                               if ($test==$theRLC)     {       return true;    }
+                               }
+                       break;
+                       case 'treeLevel':
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               $theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
+                               $treeLevel = count($theRootLine)-1;
+                               foreach ($values as $test) {
+                                       if ($test == $treeLevel) {
+                                               return true;
                                        }
-                               break;
-                               case 'PIDupinRootline':
-                               case 'PIDinRootline':
-                                       $values = explode(',',$pcs[1]);
-                                       if (($switchKey=='PIDinRootline') || (!in_array($GLOBALS['TSFE']->id,$values))) {
-                                               $theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
-                                               reset($values);
-                                               while(list(,$test)=each($values))       {
-                                                       $test = trim($test);
-                                                       reset($theRootLine);
-                                                       while(list($rl_key,$rl_dat)=each($theRootLine)) {
-                                                               if ($rl_dat['uid']==$test)      {       return true;    }
+                               }
+                       break;
+                       case 'PIDupinRootline':
+                       case 'PIDinRootline':
+                               $values = t3lib_div::trimExplode(',', $value, true);
+                               if (($key=='PIDinRootline') || (!in_array($GLOBALS['TSFE']->id, $values))) {
+                                       $theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
+                                       foreach ($values as $test) {
+                                               foreach ($theRootLine as $rl_dat) {
+                                                       if ($rl_dat['uid'] == $test) {
+                                                               return true;
                                                        }
                                                }
                                        }
-                               break;
-                               case 'userFunc':
-                                       $values = split('\(|\)',$pcs[1]);
-                                       $funcName=trim($values[0]);
-                                       $funcValue = t3lib_div::trimExplode(',',$values[1]);
-                                       $pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix'];
-                                       if ($pre &&
-                                               !t3lib_div::isFirstPartOfStr(trim($funcName),$pre) &&
-                                               !t3lib_div::isFirstPartOfStr(trim($funcName),'tx_')
-                                               )       {
-                                               if (is_object($GLOBALS['TT']))  $GLOBALS['TT']->setTSlogMessage('Match condition: Function "'.$funcName.'" was not prepended with "'.$pre.'"',3);
-                                               return false;
-                                       }
-                                       if (function_exists($funcName) && call_user_func($funcName, $funcValue[0]))     {
-                                               return true;
-                                       }
-                               break;
-                       }
+                               }
+                       break;
+                       case 'compatVersion':
+                               return t3lib_div::compat_version($value);
+                       break;
+                       case 'userFunc':
+                               $values = preg_split('/[\(\)]/', $value);
+                               $funcName = trim($values[0]);
+                               $funcValue = t3lib_div::trimExplode(',', $values[1]);
+                               $pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix'];
+                               if ($pre &&
+                                       !t3lib_div::isFirstPartOfStr(trim($funcName),$pre) &&
+                                       !t3lib_div::isFirstPartOfStr(trim($funcName),'tx_')
+                               )       {
+                                       if (is_object($GLOBALS['TT']))  $GLOBALS['TT']->setTSlogMessage('Match condition: Function "'.$funcName.'" was not prepended with "'.$pre.'"',3);
+                                       return false;
+                               }
+                               if (function_exists($funcName) && call_user_func($funcName, $funcValue[0]))     {
+                                       return true;
+                               }
+                       break;
                }
+
+
+               return false;
        }
 
        /**
-        * Will evaluate a $value based on an operator: "<", ">" or "=" (default)
+        * Evaluates a $leftValue based on an operator: "<", ">", "<=", ">=", "!=" or "="
         *
-        * @param       string          The value to compare with on the form [operator][number]. Eg. "< 123"
-        * @param       integer         The number
+        * @param       string          $test: The value to compare with on the form [operator][number]. Eg. "< 123"
+        * @param       integer         $leftValue: The value on the left side
         * @return      boolean         If $value is "50" and $test is "< 123" then it will return true.
         */
-       function testNumber($test,$value) {
-               $test = trim($test);
-               switch(substr($test,0,1))       {
-                       case '<':
-                               if (doubleval(substr($test,1))>$value)  return true;
-                       break;
-                       case '>':
-                               if (doubleval(substr($test,1))<$value)  return true;
-                       break;
-                       default:
-                               if (trim(substr($test,1))==$value)      return true;
-                       break;
+       function testNumber($test, $leftValue) {
+               if (preg_match('/^(!?=+|<=?|>=?)\s*([^\s]*)\s*$/', $test, $matches)) {
+                       $operator = $matches[1];
+                       $rightValue = $matches[2];
+
+                       switch ($operator) {
+                               case '>=':
+                                       return ($leftValue >= doubleval($rightValue));
+                                       break;
+                               case '<=':
+                                       return ($leftValue <= doubleval($rightValue));
+                                       break;
+                               case '!=':
+                                       return ($leftValue != doubleval($rightValue));
+                                       break;
+                               case '<':
+                                       return ($leftValue < doubleval($rightValue));
+                                       break;
+                               case '>':
+                                       return ($leftValue > doubleval($rightValue));
+                                       break;
+                               default:
+                                       // nothing valid found except '=', use '='
+                                       return ($leftValue == trim($rightValue));
+                                       break;
+                       }
                }
+
+               return false;
        }
 
        /**
-        * Matching two strings against each other, supporting a "*" wildcard in either end of the $needle
+        * Matching two strings against each other, supporting a "*" wildcard or (if wrapped in "/") PCRE regular expressions
         *
         * @param       string          The string in which to find $needle.
         * @param       string          The string to find in $haystack
-        * @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 "Netscape*" then it returns true.
+        * @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.
         */
-       function matchWild($haystack,$needle)   {
-               if ($needle && $haystack)       {
-                       if (substr($needle,0,1)=='*')   {$mode.='before';}
-                       if (substr($needle,-1,1)=='*')  {$mode.='after';}
-                       switch($mode)   {
-                               case 'before':
-                                       $matchStr = substr($needle,1);
-                                       if (substr($haystack,-strlen($matchStr))==$matchStr) return true;
-                               break;
-                               case 'after':
-                                       if (strpos(' '.$haystack,substr($needle,0,-1))==1)      return true;
-                               break;
-                               case 'beforeafter':
-                                       if (strstr($haystack,substr($needle,1,-1)))     return true;
-                               break;
-                               default:
-                                       if ($needle==$haystack) return true;
-                               break;
+       function matchWild($haystack, $needle) {
+               $result = false;
+
+               if ($needle) {
+                       if (preg_match('/^\/.+\/$/', $needle)) {
+                               // Regular expression, only "//" is allowed as delimiter
+                               $regex = $needle;
+                       } else {
+                               $needle = str_replace(array('*', '?'), array('###MANY###', '###ONE###'), $needle);
+                               $regex = '/^' . preg_quote($needle, '/') . '$/';
+                               // Replace the marker with .* to match anything (wildcard)
+                               $regex = str_replace(array('###MANY###', '###ONE###'), array('.*' , '.'), $regex);
                        }
+
+                       $result = (boolean)preg_match($regex, (string)$haystack);
                }
+
+               return $result;
        }
 
        /**
@@ -364,6 +456,24 @@ class t3lib_matchCondition {
         * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=296&cHash=a8ae66c7d6
         */
        function whichDevice($useragent)        {
+               foreach($this->hookObjectsArr as $hookObj)      {
+                       if (method_exists($hookObj, 'whichDevice')) {
+                               $result = $hookObj->whichDevice($useragent);
+                               if (strlen($result)) {
+                                       return $result;
+                               }
+                       }
+               }
+
+               // deprecated, see above
+               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class']))       {
+                       foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class'] as $_classRef)       {
+                               $_procObj = &t3lib_div::getUserObj($_classRef);
+                               return $_procObj->whichDevice_ext($useragent);
+                       }
+               }
+               //
+
                $agent=strtolower(trim($useragent));
                        // pda
                if(     strstr($agent, 'avantgo'))      {
@@ -403,19 +513,11 @@ class t3lib_matchCondition {
                        return 'robot';
                }
 
-                       // Hook for extending device recognition capabilities:
-               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class']))       {
-                       foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class'] as $_classRef)       {
-                               $_procObj = &t3lib_div::getUserObj($_classRef);
-                               return $_procObj->whichDevice_ext($useragent);
-                       }
-               }
-
        }
 
        /**
         * Generates an array with abstracted browser information
-        * In the function match() this method is called and the result stored in $this->browserInfoArray
+        * This method is used in the function match() in this class
         *
         * @param       string          The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
         * @return      array           Contains keys "browser", "version", "system"
@@ -423,6 +525,15 @@ class t3lib_matchCondition {
         * @see match()
         */
        function browserInfo($useragent)        {
+               foreach($this->hookObjectsArr as $hookObj)      {
+                       if (method_exists($hookObj, 'browserInfo')) {
+                               $result = $hookObj->browserInfo($useragent);
+                               if (strlen($result)) {
+                                       return $result;
+                               }
+                       }
+               }
+
                $useragent = trim($useragent);
                $browserInfo=Array();
                $browserInfo['useragent']=$useragent;
@@ -527,28 +638,38 @@ class t3lib_matchCondition {
         * @return      double          Returns double value, eg. "7.32"
         */
        function browserInfo_version($tmp)      {
-               return doubleval(ereg_replace('^[^0-9]*','',$tmp));
+               return doubleval(preg_replace('/^[^0-9]*/','',$tmp));
        }
 
        /**
         * Return global variable where the input string $var defines array keys separated by "|"
+        * Example: $var = "HTTP_SERVER_VARS | something" will return the value $GLOBALS['HTTP_SERVER_VARS']['something'] value
         *
-        * @param       string          Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the id GET parameter back.
+        * @param       string          Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the GET parameter "id" back.
         * @param       array           Alternative array than $GLOBAL to get variables from.
         * @return      mixed           Whatever value. If none, then blank string.
         * @access private
         */
-       function getGlobal($var,$inArr='') {
+       function getGlobal($var, $source=NULL)  {
                $vars = explode('|',$var);
                $c = count($vars);
                $k = trim($vars[0]);
-               $theVar = is_array($inArr) ? $inArr[$k] : $GLOBALS[$k];
+               $theVar = isset($source) ? $source[$k] : $GLOBALS[$k];
 
-               for ($a=1;$a<$c;$a++) {
-                       if (!isset($theVar))    {break;}
-                       $theVar = $theVar[trim($vars[$a])];
+               for ($a=1;$a<$c;$a++)   {
+                       if (!isset($theVar))    { break; }
+
+                       $key = trim($vars[$a]);
+                       if (is_object($theVar)) {
+                               $theVar = $theVar->$key;
+                       } elseif (is_array($theVar))    {
+                               $theVar = $theVar[$key];
+                       } else {
+                               return '';
+                       }
                }
-               if (!is_array($theVar)) {
+
+               if (!is_array($theVar) && !is_object($theVar))  {
                        return $theVar;
                } else {
                        return '';
@@ -576,7 +697,8 @@ class t3lib_matchCondition {
                                                $val = t3lib_div::_GP($k);
                                        break;
                                        case 'TSFE':
-                                               $val = $GLOBALS['TSFE']->$k;
+                                               $val = $this->getGlobal('TSFE|'.$vars[1]);
+                                               $splitAgain=0;  // getGlobal resolves all parts of the key, so no further splitting is needed
                                        break;
                                        case 'ENV':
                                                $val = getenv($k);
@@ -585,7 +707,7 @@ class t3lib_matchCondition {
                                                $val = t3lib_div::getIndpEnv($k);
                                        break;
                                        case 'LIT':
-                                               return trim($vars[1]);  // return litteral value...
+                                               { return trim($vars[1]); }      // return litteral value...
                                        break;
                                }
                                        // If array:
@@ -606,4 +728,5 @@ class t3lib_matchCondition {
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_matchcondition.php'])   {
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_matchcondition.php']);
 }
-?>
+
+?>
\ No newline at end of file