* updated CSS styled content: integrated accessible mailforms,
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_matchcondition.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Contains class for Matching TypoScript conditions
29 *
30 * $Id$
31 * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
32 *
33 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
34 */
35 /**
36 * [CLASS/FUNCTION INDEX of SCRIPT]
37 *
38 *
39 *
40 * 77: class t3lib_matchCondition
41 * 91: function match($string)
42 * 311: function testNumber($test,$value)
43 * 333: function matchWild($haystack,$needle)
44 * 363: function whichDevice($useragent)
45 * 413: function browserInfo($useragent)
46 * 517: function browserInfo_version($tmp)
47 * 529: function getGlobal($var,$inArr='')
48 * 554: function getGP_ENV_TSFE($var)
49 *
50 * TOTAL FUNCTIONS: 8
51 * (This index is automatically created/updated by the extension "extdeveval")
52 *
53 */
54
55
56
57
58
59
60
61
62
63
64
65
66 /**
67 * Matching TypoScript conditions
68 *
69 * Used with the TypoScript parser.
70 * Matches browserinfo, IPnumbers for use with templates
71 *
72 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
73 * @package TYPO3
74 * @subpackage t3lib
75 * @see t3lib_TStemplate::matching(), t3lib_TStemplate::generateConfig()
76 */
77 class t3lib_matchCondition {
78 var $matchAlternative=array(); // If this array has elements, the matching returns true if a whole "matchline" is found in the array!
79 var $matchAll=0; // If set all is matched!
80
81 var $altRootLine=array();
82
83 /**
84 * Evaluates a TypoScript condition given as input, eg. "[browser=net][...(other conditions)...]"
85 *
86 * @param string The condition to match against its criterias.
87 * @return boolean Returns true or false based on the evaluation.
88 * @see t3lib_tsparser::parse()
89 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=292&cHash=c6c7d43d2f
90 */
91 function match($string) {
92 if ( !is_array( $this->altRootLine ) ) {
93 $this->altRootLine = array();
94 }
95
96 if ($this->matchAll) return true;
97 if (count($this->matchAlternative)) {
98 return in_array($string,$this->matchAlternative);
99 }
100
101 if (!$this->browserInfoArray) {
102 $this->browserInfoArray = $this->browserInfo(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
103 }
104 $browserInfo = $this->browserInfoArray;
105 $string = trim($string);
106 $string = substr($string,1,strlen($string)-2);
107 $parts = explode('][',$string);
108 foreach ($parts as $val) {
109 $pcs = explode('=',$val,2);
110 $switchKey = trim($pcs[0]);
111 switch($switchKey) {
112 case 'browser':
113 $values = explode(',',$pcs[1]);
114 while(list(,$test)=each($values)) {
115 if (strstr($browserInfo['browser'].$browserInfo['version'],trim($test))) {
116 return true;
117 }
118 }
119 break;
120 case 'version':
121 $values = explode(',',$pcs[1]);
122 while(list(,$test)=each($values)) {
123 $test = trim($test);
124 if ($test) {
125 if (strcspn($test,'=<>')==0) {
126 switch(substr($test,0,1)) {
127 case '=':
128 if (doubleval(substr($test,1))==$browserInfo['version']) return true;
129 break;
130 case '<':
131 if (doubleval(substr($test,1))>$browserInfo['version']) return true;
132 break;
133 case '>':
134 if (doubleval(substr($test,1))<$browserInfo['version']) return true;
135 break;
136 }
137 } else {
138 if (strpos(' '.$browserInfo['version'],$test)==1) {return true;}
139 }
140 }
141 }
142 break;
143 case 'system':
144 $values = explode(',',$pcs[1]);
145 while(list(,$test)=each($values)) {
146 $test = trim($test);
147 if ($test) {
148 if (strpos(' '.$browserInfo['system'],$test)==1) {return true;}
149 }
150 }
151 break;
152 case 'device':
153 $values = explode(',',$pcs[1]);
154 if (!isset($this->deviceInfo)) {
155 $this->deviceInfo = $this->whichDevice(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
156 }
157 while(list(,$test)=each($values)) {
158 $test = trim($test);
159 if ($test) {
160 if ($this->deviceInfo==$test) {return true;}
161 }
162 }
163 break;
164 case 'useragent':
165 $test = trim($pcs[1]);
166 if ($test) {
167 return $this->matchWild($browserInfo['useragent'],$test);
168 }
169 break;
170 case 'language':
171 $values = explode(',',$pcs[1]);
172 while(list(,$test)=each($values)) {
173 $test = trim($test);
174 if ($test) {
175 if (ereg('^\*.+\*$',$test)) {
176 $allLanguages = split('[,;]',t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE'));
177 if (in_array(substr($test,1,-1), $allLanguages)) {return true;}
178 } else {
179 if (t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE') == $test) {return true;}
180 }
181 }
182 }
183 break;
184 case 'IP':
185 if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1])) {return true;}
186 break;
187 case 'hostname':
188 if (t3lib_div::cmpFQDN(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1])) {return true;}
189 break;
190 // hour, minute, dayofweek, dayofmonth, month
191 case 'hour':
192 case 'minute':
193 case 'dayofweek':
194 case 'dayofmonth':
195 case 'month':
196 $theEvalTime = $GLOBALS['SIM_EXEC_TIME']; // In order to simulate time properly in templates.
197 switch($switchKey) {
198 case 'hour': $theTestValue = date('H',$theEvalTime); break;
199 case 'minute': $theTestValue = date('i',$theEvalTime); break;
200 case 'dayofweek': $theTestValue = date('w',$theEvalTime); break;
201 case 'dayofmonth': $theTestValue = date('d',$theEvalTime); break;
202 case 'month': $theTestValue = date('m',$theEvalTime); break;
203 }
204 $theTestValue = intval($theTestValue);
205 // comp
206 $values = explode(',',$pcs[1]);
207 reset($values);
208 while(list(,$test)=each($values)) {
209 $test = trim($test);
210 if (t3lib_div::testInt($test)) {$test='='.$test;}
211 if ($test) {
212 if ($this->testNumber($test,$theTestValue)) {return true;}
213 }
214 }
215 break;
216 case 'usergroup':
217 if ($GLOBALS['TSFE']->gr_list!='0,-1') { // '0,-1' is the default usergroups when not logged in!
218 $values = explode(',',$pcs[1]);
219 while(list(,$test)=each($values)) {
220 $test = trim($test);
221 if ($test) {
222 if ($test=='*' || t3lib_div::inList($GLOBALS['TSFE']->gr_list,$test)) {return true;}
223 }
224 }
225 }
226 break;
227 case 'loginUser':
228 if ($GLOBALS['TSFE']->loginUser) {
229 $values = explode(',',$pcs[1]);
230 while(list(,$test)=each($values)) {
231 $test = trim($test);
232 if ($test) {
233 if ($test=='*' || !strcmp($GLOBALS['TSFE']->fe_user->user['uid'],$test)) {return true;}
234 }
235 }
236 }
237 break;
238 case 'globalVar':
239 $values = explode(',',$pcs[1]);
240 while(list(,$test)=each($values)) {
241 $test = trim($test);
242 if ($test) {
243 $point = strcspn($test,'=<>');
244 $theVarName = substr($test,0,$point);
245 $nv = $this->getGP_ENV_TSFE(trim($theVarName));
246 $testValue = substr($test,$point);
247
248 if ($this->testNumber($testValue,$nv)) {return true;}
249 }
250 }
251 break;
252 case 'globalString':
253 $values = explode(',',$pcs[1]);
254 while(list(,$test)=each($values)) {
255 $test = trim($test);
256 if ($test) {
257 $point = strcspn($test,'=');
258 $theVarName = substr($test,0,$point);
259 $nv = $this->getGP_ENV_TSFE(trim($theVarName));
260 $testValue = substr($test,$point+1);
261
262 if ($this->matchWild($nv,trim($testValue))) {return true;}
263 }
264 }
265 break;
266 case 'treeLevel':
267 $values = explode(',',$pcs[1]);
268 $theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
269 $theRLC = count($theRootLine)-1;
270 while(list(,$test)=each($values)) {
271 $test = trim($test);
272 if ($test==$theRLC) { return true; }
273 }
274 break;
275 case 'PIDupinRootline':
276 case 'PIDinRootline':
277 $values = explode(',',$pcs[1]);
278 if (($switchKey=='PIDinRootline') || (!in_array($GLOBALS['TSFE']->id,$values))) {
279 $theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
280 reset($values);
281 while(list(,$test)=each($values)) {
282 $test = trim($test);
283 reset($theRootLine);
284 while(list($rl_key,$rl_dat)=each($theRootLine)) {
285 if ($rl_dat['uid']==$test) { return true; }
286 }
287 }
288 }
289 break;
290 case 'compatVersion':
291 return t3lib_div::compat_version($pcs[1]);
292 break;
293 case 'userFunc':
294 $values = split('\(|\)',$pcs[1]);
295 $funcName=trim($values[0]);
296 $funcValue = t3lib_div::trimExplode(',',$values[1]);
297 $pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix'];
298 if ($pre &&
299 !t3lib_div::isFirstPartOfStr(trim($funcName),$pre) &&
300 !t3lib_div::isFirstPartOfStr(trim($funcName),'tx_')
301 ) {
302 if (is_object($GLOBALS['TT'])) $GLOBALS['TT']->setTSlogMessage('Match condition: Function "'.$funcName.'" was not prepended with "'.$pre.'"',3);
303 return false;
304 }
305 if (function_exists($funcName) && call_user_func($funcName, $funcValue[0])) {
306 return true;
307 }
308 break;
309 }
310 }
311 }
312
313 /**
314 * Will evaluate a $value based on an operator: "<", ">" or "=" (default)
315 *
316 * @param string The value to compare with on the form [operator][number]. Eg. "< 123"
317 * @param integer The number
318 * @return boolean If $value is "50" and $test is "< 123" then it will return true.
319 */
320 function testNumber($test,$value) {
321 $test = trim($test);
322 switch(substr($test,0,1)) {
323 case '<':
324 if (doubleval(substr($test,1))>$value) return true;
325 break;
326 case '>':
327 if (doubleval(substr($test,1))<$value) return true;
328 break;
329 default:
330 if (trim(substr($test,1))==$value) return true;
331 break;
332 }
333 }
334
335 /**
336 * Matching two strings against each other, supporting a "*" wildcard
337 *
338 * @param string The string in which to find $needle.
339 * @param string The string to find in $haystack
340 * @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.
341 */
342 function matchWild($haystack,$needle) {
343 if ($needle && $haystack) {
344 $regex = '/^'.preg_quote($needle,'/').'$/';
345 $regex = str_replace('\\*', '.*', $regex); // 1st fix: Replace \* with .* because * is our wildcard
346 $regex = str_replace('\\\\.*', '\\*', $regex); // 2nd fix: Match needle if the * was escaped
347
348 if (preg_match($regex, $haystack, $res)) return true;
349 }
350 }
351
352 /**
353 * Returns a code for a browsing device based on the input useragent string
354 *
355 * @param string User agent string from browser, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
356 * @return string A code. See link.
357 * @access private
358 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=296&cHash=a8ae66c7d6
359 */
360 function whichDevice($useragent) {
361 $agent=strtolower(trim($useragent));
362 // pda
363 if( strstr($agent, 'avantgo')) {
364 return 'pda';
365 }
366
367 // wap
368 $browser=substr($agent,0,4);
369 $wapviwer=substr(stristr($agent,'wap'),0,3);
370 if( $wapviwer=='wap' ||
371 $browser=='noki' ||
372 $browser== 'eric' ||
373 $browser== 'r380' ||
374 $browser== 'up.b' ||
375 $browser== 'winw' ||
376 $browser== 'wapa') {
377 return 'wap';
378 }
379
380 // grabber
381 if( strstr($agent, 'g.r.a.b.') ||
382 strstr($agent, 'utilmind httpget') ||
383 strstr($agent, 'webcapture') ||
384 strstr($agent, 'teleport') ||
385 strstr($agent, 'webcopier')) {
386 return 'grabber';
387 }
388
389 // robots
390 if( strstr($agent, 'crawler') ||
391 strstr($agent, 'spider') ||
392 strstr($agent, 'googlebot') ||
393 strstr($agent, 'searchbot') ||
394 strstr($agent, 'infoseek') ||
395 strstr($agent, 'altavista') ||
396 strstr($agent, 'diibot')) {
397 return 'robot';
398 }
399
400 // Hook for extending device recognition capabilities:
401 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class'])) {
402 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_matchcondition.php']['devices_class'] as $_classRef) {
403 $_procObj = &t3lib_div::getUserObj($_classRef);
404 return $_procObj->whichDevice_ext($useragent);
405 }
406 }
407
408 }
409
410 /**
411 * Generates an array with abstracted browser information
412 * In the function match() this method is called and the result stored in $this->browserInfoArray
413 *
414 * @param string The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
415 * @return array Contains keys "browser", "version", "system"
416 * @access private
417 * @see match()
418 */
419 function browserInfo($useragent) {
420 $useragent = trim($useragent);
421 $browserInfo=Array();
422 $browserInfo['useragent']=$useragent;
423 if ($useragent) {
424 // browser
425 if (strstr($useragent,'MSIE')) {
426 $browserInfo['browser']='msie';
427 } elseif(strstr($useragent,'Konqueror')) {
428 $browserInfo['browser']='konqueror';
429 } elseif(strstr($useragent,'Opera')) {
430 $browserInfo['browser']='opera';
431 } elseif(strstr($useragent,'Lynx')) {
432 $browserInfo['browser']='lynx';
433 } elseif(strstr($useragent,'PHP')) {
434 $browserInfo['browser']='php';
435 } elseif(strstr($useragent,'AvantGo')) {
436 $browserInfo['browser']='avantgo';
437 } elseif(strstr($useragent,'WebCapture')) {
438 $browserInfo['browser']='acrobat';
439 } elseif(strstr($useragent,'IBrowse')) {
440 $browserInfo['browser']='ibrowse';
441 } elseif(strstr($useragent,'Teleport')) {
442 $browserInfo['browser']='teleport';
443 } elseif(strstr($useragent,'Mozilla')) {
444 $browserInfo['browser']='netscape';
445 } else {
446 $browserInfo['browser']='unknown';
447 }
448 // version
449 switch($browserInfo['browser']) {
450 case 'netscape':
451 $browserInfo['version'] = $this->browserInfo_version(substr($useragent,8));
452 if (strstr($useragent,'Netscape6')) {$browserInfo['version']=6;}
453 break;
454 case 'msie':
455 $tmp = strstr($useragent,'MSIE');
456 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,4));
457 break;
458 case 'opera':
459 $tmp = strstr($useragent,'Opera');
460 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,5));
461 break;
462 case 'lynx':
463 $tmp = strstr($useragent,'Lynx/');
464 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,5));
465 break;
466 case 'php':
467 $tmp = strstr($useragent,'PHP/');
468 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,4));
469 break;
470 case 'avantgo':
471 $tmp = strstr($useragent,'AvantGo');
472 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,7));
473 break;
474 case 'acrobat':
475 $tmp = strstr($useragent,'WebCapture');
476 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,10));
477 break;
478 case 'ibrowse':
479 $tmp = strstr($useragent,'IBrowse/');
480 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,8));
481 break;
482 case 'konqueror':
483 $tmp = strstr($useragent,'Konqueror/');
484 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,10));
485 break;
486 }
487 // system
488 $browserInfo['system']='';
489 if (strstr($useragent,'Win')) {
490 // windows
491 if (strstr($useragent,'Win98') || strstr($useragent,'Windows 98')) {
492 $browserInfo['system']='win98';
493 } elseif (strstr($useragent,'Win95') || strstr($useragent,'Windows 95')) {
494 $browserInfo['system']='win95';
495 } elseif (strstr($useragent,'WinNT') || strstr($useragent,'Windows NT')) {
496 $browserInfo['system']='winNT';
497 } elseif (strstr($useragent,'Win16') || strstr($useragent,'Windows 311')) {
498 $browserInfo['system']='win311';
499 }
500 } elseif (strstr($useragent,'Mac')) {
501 $browserInfo['system']='mac';
502 // unixes
503 } elseif (strstr($useragent,'Linux')) {
504 $browserInfo['system']='linux';
505 } elseif (strstr($useragent,'SGI') && strstr($useragent,' IRIX ')) {
506 $browserInfo['system']='unix_sgi';
507 } elseif (strstr($useragent,' SunOS ')) {
508 $browserInfo['system']='unix_sun';
509 } elseif (strstr($useragent,' HP-UX ')) {
510 $browserInfo['system']='unix_hp';
511 }
512 }
513
514 return $browserInfo;
515 }
516
517 /**
518 * Returns the version of a browser; Basically getting doubleval() of the input string, stripping of any non-numeric values in the beginning of the string first.
519 *
520 * @param string A string with version number, eg. "/7.32 blablabla"
521 * @return double Returns double value, eg. "7.32"
522 */
523 function browserInfo_version($tmp) {
524 return doubleval(ereg_replace('^[^0-9]*','',$tmp));
525 }
526
527 /**
528 * Return global variable where the input string $var defines array keys separated by "|"
529 *
530 * @param string Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the id GET parameter back.
531 * @param array Alternative array than $GLOBAL to get variables from.
532 * @return mixed Whatever value. If none, then blank string.
533 * @access private
534 */
535 function getGlobal($var,$inArr='') {
536 $vars = explode('|',$var);
537 $c = count($vars);
538 $k = trim($vars[0]);
539 $theVar = is_array($inArr) ? $inArr[$k] : $GLOBALS[$k];
540
541 for ($a=1;$a<$c;$a++) {
542 if (!isset($theVar)) {break;}
543
544 $key = trim($vars[$a]);
545 if (is_object($theVar)) {
546 $theVar = $theVar->$key;
547 } elseif (is_array($theVar)) {
548 $theVar = $theVar[$key];
549 } else {
550 return '';
551 }
552 }
553
554 if (!is_array($theVar) && !is_object($theVar)) {
555 return $theVar;
556 } else {
557 return '';
558 }
559 }
560
561 /**
562 * Returns GP / ENV / TSFE vars
563 *
564 * @param string Identifier
565 * @return mixed The value of the variable pointed to.
566 * @access private
567 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=311&cHash=487cbd5cdf
568 */
569 function getGP_ENV_TSFE($var) {
570 $vars = explode(':',$var,2);
571 if (count($vars)==1) {
572 $val = $this->getGlobal($var);
573 } else {
574 $splitAgain=explode('|',$vars[1],2);
575 $k=trim($splitAgain[0]);
576 if ($k) {
577 switch((string)trim($vars[0])) {
578 case 'GP':
579 $val = t3lib_div::_GP($k);
580 break;
581 case 'TSFE':
582 $val = $this->getGlobal('TSFE|'.$vars[1]);
583 $splitAgain=0; // getGlobal resolves all parts of the key, so no further splitting is needed
584 break;
585 case 'ENV':
586 $val = getenv($k);
587 break;
588 case 'IENV':
589 $val = t3lib_div::getIndpEnv($k);
590 break;
591 case 'LIT':
592 return trim($vars[1]); // return litteral value...
593 break;
594 }
595 // If array:
596 if (count($splitAgain)>1) {
597 if (is_array($val) && trim($splitAgain[1])) {
598 $val=$this->getGlobal($splitAgain[1],$val);
599 } else {
600 $val='';
601 }
602 }
603 }
604 }
605 return $val;
606 }
607 }
608
609
610 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_matchcondition.php']) {
611 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_matchcondition.php']);
612 }
613 ?>