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