* Rolled back browser detection in matchcondition class.
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_matchcondition.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2004 Kasper Skaarhoj (kasper@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 <kasper@typo3.com>
34 */
35 /**
36 * [CLASS/FUNCTION INDEX of SCRIPT]
37 *
38 *
39 *
40 * 77: class t3lib_matchCondition
41 * 91: function match($string)
42 * 303: function testNumber($test,$value)
43 * 325: function matchWild($haystack,$needle)
44 * 355: function whichDevice($useragent)
45 * 405: function browserInfo($useragent)
46 * 503: function browserInfo_version($tmp)
47 * 515: function getGlobal($var,$inArr='')
48 * 540: 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 <kasper@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
93 if ($this->matchAll) return true;
94 if (count($this->matchAlternative)) {
95 return in_array($string,$this->matchAlternative);
96 }
97
98 if (!$this->browserInfoArray) {
99 $this->browserInfoArray = $this->browserInfo(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
100 }
101 $browserInfo = $this->browserInfoArray;
102 $string = trim($string);
103 $string = substr($string,1,strlen($string)-2);
104 $parts = explode('][',$string);
105 reset($parts);
106 while(list(,$val)=each($parts)) {
107 $pcs = explode('=',$val,2);
108 $switchKey = trim($pcs[0]);
109 switch($switchKey) {
110 case 'browser':
111 $values = explode(',',$pcs[1]);
112 while(list(,$test)=each($values)) {
113 if (strstr($browserInfo['browser'].$browserInfo['version'],trim($test))) {
114 return true;
115 }
116 }
117 break;
118 case 'version':
119 $values = explode(',',$pcs[1]);
120 while(list(,$test)=each($values)) {
121 $test = trim($test);
122 if ($test) {
123 if (strcspn($test,'=<>')==0) {
124 switch(substr($test,0,1)) {
125 case '=':
126 if (doubleval(substr($test,1))==$browserInfo['version']) return true;
127 break;
128 case '<':
129 if (doubleval(substr($test,1))>$browserInfo['version']) return true;
130 break;
131 case '>':
132 if (doubleval(substr($test,1))<$browserInfo['version']) return true;
133 break;
134 }
135 } else {
136 if (strpos(' '.$browserInfo['version'],$test)==1) {return true;}
137 }
138 }
139 }
140 break;
141 case 'system':
142 $values = explode(',',$pcs[1]);
143 while(list(,$test)=each($values)) {
144 $test = trim($test);
145 if ($test) {
146 if (strpos(' '.$browserInfo['system'],$test)==1) {return true;}
147 }
148 }
149 break;
150 case 'device':
151 $values = explode(',',$pcs[1]);
152 if (!isset($this->deviceInfo)) {
153 $this->deviceInfo = $this->whichDevice(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
154 }
155 while(list(,$test)=each($values)) {
156 $test = trim($test);
157 if ($test) {
158 if ($this->deviceInfo==$test) {return true;}
159 }
160 }
161 break;
162 case 'useragent':
163 $test = trim($pcs[1]);
164 if ($test) {
165 return $this->matchWild($browserInfo['useragent'],$test);
166 }
167 break;
168 case 'language':
169 $values = explode(',',$pcs[1]);
170 while(list(,$test)=each($values)) {
171 $test = trim($test);
172 if ($test) {
173 if (t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE') == $test) {return true;}
174 }
175 }
176 break;
177 case 'IP':
178 if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1])) {return true;}
179 break;
180 case 'hostname':
181 if (t3lib_div::cmpFQDN(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1])) {return true;}
182 break;
183 // hour, minute, dayofweek, dayofmonth, month
184 case 'hour':
185 case 'minute':
186 case 'dayofweek':
187 case 'dayofmonth':
188 case 'month':
189 $theEvalTime = $GLOBALS['SIM_EXEC_TIME']; // In order to simulate time properly in templates.
190 switch($switchKey) {
191 case 'hour': $theTestValue = date('H',$theEvalTime); break;
192 case 'minute': $theTestValue = date('i',$theEvalTime); break;
193 case 'dayofweek': $theTestValue = date('w',$theEvalTime); break;
194 case 'dayofmonth': $theTestValue = date('d',$theEvalTime); break;
195 case 'month': $theTestValue = date('m',$theEvalTime); break;
196 }
197 $theTestValue = intval($theTestValue);
198 // comp
199 $values = explode(',',$pcs[1]);
200 reset($values);
201 while(list(,$test)=each($values)) {
202 $test = trim($test);
203 if (t3lib_div::testInt($test)) {$test='='.$test;}
204 if ($test) {
205 if ($this->testNumber($test,$theTestValue)) {return true;}
206 }
207 }
208 break;
209 case 'usergroup':
210 if ($GLOBALS['TSFE']->gr_list!='0,-1') { // '0,-1' is the default usergroups when not logged in!
211 $values = explode(',',$pcs[1]);
212 while(list(,$test)=each($values)) {
213 $test = trim($test);
214 if ($test) {
215 if ($test=='*' || t3lib_div::inList($GLOBALS['TSFE']->gr_list,$test)) {return true;}
216 }
217 }
218 }
219 break;
220 case 'loginUser':
221 if ($GLOBALS['TSFE']->loginUser) {
222 $values = explode(',',$pcs[1]);
223 while(list(,$test)=each($values)) {
224 $test = trim($test);
225 if ($test) {
226 if ($test=='*' || !strcmp($GLOBALS['TSFE']->fe_user->user['uid'],$test)) {return true;}
227 }
228 }
229 }
230 break;
231 case 'globalVar':
232 $values = explode(',',$pcs[1]);
233 while(list(,$test)=each($values)) {
234 $test = trim($test);
235 if ($test) {
236 $point = strcspn($test,'=<>');
237 $theVarName = substr($test,0,$point);
238 $nv = $this->getGP_ENV_TSFE(trim($theVarName));
239 if ($this->testNumber(substr($test,$point) ,$nv)) {return true;}
240 }
241 }
242 break;
243 case 'globalString':
244 $values = explode(',',$pcs[1]);
245 while(list(,$test)=each($values)) {
246 $test = trim($test);
247 if ($test) {
248 $point = strcspn($test,'=');
249 $theVarName = substr($test,0,$point);
250 $nv = $this->getGP_ENV_TSFE(trim($theVarName));
251 if ($this->matchWild($nv,trim(substr($test,$point+1)))) {return true;}
252 }
253 }
254 break;
255 case 'treeLevel':
256 $values = explode(',',$pcs[1]);
257 $theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
258 $theRLC = count($theRootLine)-1;
259 while(list(,$test)=each($values)) {
260 $test = trim($test);
261 if ($test==$theRLC) { return true; }
262 }
263 break;
264 case 'PIDupinRootline':
265 case 'PIDinRootline':
266 $values = explode(',',$pcs[1]);
267 if (($switchKey=='PIDinRootline') || (!in_array($GLOBALS['TSFE']->id,$values))) {
268 $theRootLine = is_array($GLOBALS['TSFE']->tmpl->rootLine) ? $GLOBALS['TSFE']->tmpl->rootLine : $this->altRootLine;
269 reset($values);
270 while(list(,$test)=each($values)) {
271 $test = trim($test);
272 reset($theRootLine);
273 while(list($rl_key,$rl_dat)=each($theRootLine)) {
274 if ($rl_dat['uid']==$test) { return true; }
275 }
276 }
277 }
278 break;
279 case 'userFunc':
280 $values = split('\(|\)',$pcs[1]);
281 $funcName=trim($values[0]);
282 $funcValue = t3lib_div::trimExplode(',',$values[1]);
283 $pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix'];
284 if ($pre &&
285 !t3lib_div::isFirstPartOfStr(trim($funcName),$pre) &&
286 !t3lib_div::isFirstPartOfStr(trim($funcName),'tx_')
287 ) {
288 if (is_object($GLOBALS['TT'])) $GLOBALS['TT']->setTSlogMessage('Match condition: Function "'.$funcName.'" was not prepended with "'.$pre.'"',3);
289 return false;
290 }
291 if (function_exists($funcName) && call_user_func($funcName, $funcValue[0])) {
292 return true;
293 }
294 break;
295 }
296 }
297 }
298
299 /**
300 * Will evaluate a $value based on an operator: "<", ">" or "=" (default)
301 *
302 * @param string The value to compare with on the form [operator][number]. Eg. "< 123"
303 * @param integer The number
304 * @return boolean If $value is "50" and $test is "< 123" then it will return true.
305 */
306 function testNumber($test,$value) {
307 $test = trim($test);
308 switch(substr($test,0,1)) {
309 case '<':
310 if (doubleval(substr($test,1))>$value) return true;
311 break;
312 case '>':
313 if (doubleval(substr($test,1))<$value) return true;
314 break;
315 default:
316 if (trim(substr($test,1))==$value) return true;
317 break;
318 }
319 }
320
321 /**
322 * Matching two strings against each other, supporting a "*" wildcard in either end of the $needle
323 *
324 * @param string The string in which to find $needle.
325 * @param string The string to find in $haystack
326 * @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.
327 */
328 function matchWild($haystack,$needle) {
329 if ($needle && $haystack) {
330 if (substr($needle,0,1)=='*') {$mode.='before';}
331 if (substr($needle,-1,1)=='*') {$mode.='after';}
332 switch($mode) {
333 case 'before':
334 $matchStr = substr($needle,1);
335 if (substr($haystack,-strlen($matchStr))==$matchStr) return true;
336 break;
337 case 'after':
338 if (strpos(' '.$haystack,substr($needle,0,-1))==1) return true;
339 break;
340 case 'beforeafter':
341 if (strstr($haystack,substr($needle,1,-1))) return true;
342 break;
343 default:
344 if ($needle==$haystack) return true;
345 break;
346 }
347 }
348 }
349
350 /**
351 * Returns a code for a browsing device based on the input useragent string
352 *
353 * @param string User agent string from browser, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
354 * @return string A code. See link.
355 * @access private
356 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=296&cHash=a8ae66c7d6
357 */
358 function whichDevice($useragent) {
359 $agent=strtolower(trim($useragent));
360 // pda
361 if( strstr($agent, 'avantgo')) {
362 return 'pda';
363 }
364
365 // wap
366 $browser=substr($agent,0,4);
367 $wapviwer=substr(stristr($agent,'wap'),0,3);
368 if( $wapviwer=='wap' ||
369 $browser=='noki' ||
370 $browser== 'eric' ||
371 $browser== 'r380' ||
372 $browser== 'up.b' ||
373 $browser== 'winw' ||
374 $browser== 'wapa') {
375 return 'wap';
376 }
377
378 // grabber
379 if( strstr($agent, 'g.r.a.b.') ||
380 strstr($agent, 'utilmind httpget') ||
381 strstr($agent, 'webcapture') ||
382 strstr($agent, 'teleport') ||
383 strstr($agent, 'webcopier')) {
384 return 'grabber';
385 }
386
387 // robots
388 if( strstr($agent, 'crawler') ||
389 strstr($agent, 'spider') ||
390 strstr($agent, 'googlebot') ||
391 strstr($agent, 'searchbot') ||
392 strstr($agent, 'infoseek') ||
393 strstr($agent, 'altavista') ||
394 strstr($agent, 'diibot')) {
395 return 'robot';
396 }
397 }
398
399 /**
400 * Generates an array with abstracted browser information
401 * In the function match() this method is called and the result stored in $this->browserInfoArray
402 *
403 * @param string The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
404 * @return array Contains keys "browser", "version", "system"
405 * @access private
406 * @see match()
407 */
408 function browserInfo($useragent) {
409 $useragent = trim($useragent);
410 $browserInfo=Array();
411 $browserInfo['useragent']=$useragent;
412 if ($useragent) {
413 // browser
414 if (strstr($useragent,'MSIE')) {
415 $browserInfo['browser']='msie';
416 } elseif(strstr($useragent,'Opera')) {
417 $browserInfo['browser']='opera';
418 } elseif(strstr($useragent,'Lynx')) {
419 $browserInfo['browser']='lynx';
420 } elseif(strstr($useragent,'PHP')) {
421 $browserInfo['browser']='php';
422 } elseif(strstr($useragent,'AvantGo')) {
423 $browserInfo['browser']='avantgo';
424 } elseif(strstr($useragent,'WebCapture')) {
425 $browserInfo['browser']='acrobat';
426 } elseif(strstr($useragent,'IBrowse')) {
427 $browserInfo['browser']='ibrowse';
428 } elseif(strstr($useragent,'Teleport')) {
429 $browserInfo['browser']='teleport';
430 } elseif(strstr($useragent,'Mozilla')) {
431 $browserInfo['browser']='netscape';
432 } else {
433 $browserInfo['browser']='unknown';
434 }
435 // version
436 switch($browserInfo['browser']) {
437 case 'netscape':
438 $browserInfo['version'] = $this->browserInfo_version(substr($useragent,8));
439 if (strstr($useragent,'Netscape6')) {$browserInfo['version']=6;}
440 break;
441 case 'msie':
442 $tmp = strstr($useragent,'MSIE');
443 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,4));
444 break;
445 case 'opera':
446 $tmp = strstr($useragent,'Opera');
447 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,5));
448 break;
449 case 'lynx':
450 $tmp = strstr($useragent,'Lynx/');
451 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,5));
452 break;
453 case 'php':
454 $tmp = strstr($useragent,'PHP/');
455 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,4));
456 break;
457 case 'avantgo':
458 $tmp = strstr($useragent,'AvantGo');
459 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,5));
460 break;
461 case 'acrobat':
462 $tmp = strstr($useragent,'WebCapture');
463 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,5));
464 break;
465 case 'ibrowse':
466 $tmp = strstr($useragent,'IBrowse/');
467 $browserInfo['version'] = $this->browserInfo_version(substr($tmp,5));
468 break;
469 }
470 // system
471 $browserInfo['system']='';
472 if (strstr($useragent,'Win')) {
473 // windows
474 if (strstr($useragent,'Win98') || strstr($useragent,'Windows 98')) {
475 $browserInfo['system']='win98';
476 } elseif (strstr($useragent,'Win95') || strstr($useragent,'Windows 95')) {
477 $browserInfo['system']='win95';
478 } elseif (strstr($useragent,'WinNT') || strstr($useragent,'Windows NT')) {
479 $browserInfo['system']='winNT';
480 } elseif (strstr($useragent,'Win16') || strstr($useragent,'Windows 311')) {
481 $browserInfo['system']='win311';
482 }
483 } elseif (strstr($useragent,'Mac')) {
484 $browserInfo['system']='mac';
485 // unixes
486 } elseif (strstr($useragent,'Linux')) {
487 $browserInfo['system']='linux';
488 } elseif (strstr($useragent,'SGI') && strstr($useragent,' IRIX ')) {
489 $browserInfo['system']='unix_sgi';
490 } elseif (strstr($useragent,' SunOS ')) {
491 $browserInfo['system']='unix_sun';
492 } elseif (strstr($useragent,' HP-UX ')) {
493 $browserInfo['system']='unix_hp';
494 }
495 }
496
497 return $browserInfo;
498 }
499
500 /**
501 * 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.
502 *
503 * @param string A string with version number, eg. "/7.32 blablabla"
504 * @return double Returns double value, eg. "7.32"
505 */
506 function browserInfo_version($tmp) {
507 return doubleval(ereg_replace('^[^0-9]*','',$tmp));
508 }
509
510 /**
511 * Return global variable where the input string $var defines array keys separated by "|"
512 *
513 * @param string Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the id GET parameter back.
514 * @param array Alternative array than $GLOBAL to get variables from.
515 * @return mixed Whatever value. If none, then blank string.
516 * @access private
517 */
518 function getGlobal($var,$inArr='') {
519 $vars = explode('|',$var);
520 $c = count($vars);
521 $k = trim($vars[0]);
522 $theVar = is_array($inArr) ? $inArr[$k] : $GLOBALS[$k];
523
524 for ($a=1;$a<$c;$a++) {
525 if (!isset($theVar)) {break;}
526 $theVar = $theVar[trim($vars[$a])];
527 }
528 if (!is_array($theVar)) {
529 return $theVar;
530 } else {
531 return '';
532 }
533 }
534
535 /**
536 * Returns GP / ENV / TSFE vars
537 *
538 * @param string Identifier
539 * @return mixed The value of the variable pointed to.
540 * @access private
541 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=311&cHash=487cbd5cdf
542 */
543 function getGP_ENV_TSFE($var) {
544 $vars = explode(':',$var,2);
545 if (count($vars)==1) {
546 $val = $this->getGlobal($var);
547 } else {
548 $splitAgain=explode('|',$vars[1],2);
549 $k=trim($splitAgain[0]);
550 if ($k) {
551 switch((string)trim($vars[0])) {
552 case 'GP':
553 $val = t3lib_div::_GP($k);
554 break;
555 case 'TSFE':
556 $val = $GLOBALS['TSFE']->$k;
557 break;
558 case 'ENV':
559 $val = getenv($k);
560 break;
561 case 'IENV':
562 $val = t3lib_div::getIndpEnv($k);
563 break;
564 case 'LIT':
565 return trim($vars[1]); // return litteral value...
566 break;
567 }
568 // If array:
569 if (count($splitAgain)>1) {
570 if (is_array($val) && trim($splitAgain[1])) {
571 $val=$this->getGlobal($splitAgain[1],$val);
572 } else {
573 $val='';
574 }
575 }
576 }
577 }
578 return $val;
579 }
580 }
581
582
583 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_matchcondition.php']) {
584 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_matchcondition.php']);
585 }
586 ?>