PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/saf/lib/Ext/phpsniff/phpSniff.core.php

https://github.com/lux/sitellite
PHP | 547 lines | 393 code | 31 blank | 123 comment | 57 complexity | 63935b1a5b58960efa8b8135930d74ff MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, GPL-3.0
  1. <?php
  2. /*******************************************************************************
  3. $Id: phpSniff.core.php,v 1.1.1.1 2005/04/29 04:44:35 lux Exp $
  4. phpSniff: HTTP_USER_AGENT Client Sniffer for PHP
  5. Copyright (C) 2001 Roger Raymond ~ epsilon7@users.sourceforge.net
  6. This library is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU Lesser General Public
  8. License as published by the Free Software Foundation; either
  9. version 2.1 of the License, or (at your option) any later version.
  10. This library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. Lesser General Public License for more details.
  14. You should have received a copy of the GNU Lesser General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *******************************************************************************/
  18. class phpSniff_core
  19. { // initialize some vars
  20. var $_browser_info = array(
  21. 'ua' => '',
  22. 'browser' => 'Unknown',
  23. 'version' => 0,
  24. 'maj_ver' => 0,
  25. 'min_ver' => 0,
  26. 'letter_ver' => '',
  27. 'javascript' => '0.0',
  28. 'platform' => 'Unknown',
  29. 'os' => 'Unknown',
  30. 'ip' => 'Unknown',
  31. 'cookies' => 'Unknown', // remains for backwards compatability
  32. 'ss_cookies' => 'Unknown',
  33. 'st_cookies' => 'Unknown',
  34. 'language' => '',
  35. 'long_name' => '',
  36. 'gecko' => '',
  37. 'gecko_ver' => ''
  38. );
  39. var $_feature_set = array(
  40. 'html' => true,
  41. 'images' => true,
  42. 'frames' => true,
  43. 'tables' => true,
  44. 'java' => true,
  45. 'plugins' => true,
  46. 'iframes' => false,
  47. 'css2' => false,
  48. 'css1' => false,
  49. 'xml' => false,
  50. 'dom' => false,
  51. 'wml' => false,
  52. 'hdml' => false
  53. );
  54. var $_quirks = array(
  55. 'must_cache_forms' => false,
  56. 'avoid_popup_windows' => false,
  57. 'cache_ssl_downloads' => false,
  58. 'break_disposition_header' => false,
  59. 'empty_file_input_value' => false,
  60. 'scrollbar_in_way' => false
  61. );
  62. var $_get_languages_ran_once = false;
  63. var $_browser_search_regex = '([a-z]+)([0-9]*)([0-9.]*)(up|dn|\+|\-)?';
  64. var $_language_search_regex = '([a-z-]{2,})';
  65. /**
  66. * init
  67. * this method starts the madness
  68. **/
  69. function init ()
  70. {
  71. // collect the ip
  72. $this->_get_ip();
  73. // run the cookie check routine first
  74. // [note: method only runs if allowed]
  75. $this->_test_cookies();
  76. // rip the user agent to pieces
  77. $this->_get_browser_info();
  78. // gecko build
  79. $this->_get_gecko();
  80. // look for other languages
  81. $this->_get_languages();
  82. // establish the operating platform
  83. $this->_get_os_info();
  84. // determine javascript version
  85. $this->_get_javascript();
  86. // determine current feature set
  87. $this->_get_features();
  88. // point out any quirks
  89. $this->_get_quirks();
  90. }
  91. /**
  92. * property
  93. * @param $p property to return . optional (null returns entire array)
  94. * @return array/string entire array or value of property
  95. **/
  96. function property ($p=null)
  97. { if($p==null)
  98. { return $this->_browser_info;
  99. }
  100. else
  101. { return $this->_browser_info[strtolower($p)];
  102. }
  103. }
  104. /**
  105. * get_property
  106. * alias for property
  107. **/
  108. function get_property ($p)
  109. { return $this->property($p);
  110. }
  111. /**
  112. * is
  113. * @param $s string search phrase format = l:lang;b:browser
  114. * @return bool true on success
  115. * ex: $client->is('b:OP5Up');
  116. **/
  117. function is ($s)
  118. { // perform language search
  119. if(preg_match('/l:'.$this->_language_search_regex.'/i',$s,$match))
  120. { if($match) return $this->_perform_language_search($match);
  121. }
  122. // perform browser search
  123. elseif(preg_match('/b:'.$this->_browser_search_regex.'/i',$s,$match))
  124. { if($match) return $this->_perform_browser_search($match);
  125. }
  126. return false;
  127. }
  128. /**
  129. * browser_is
  130. * @param $s string search phrase for browser
  131. * @return bool true on success
  132. * ex: $client->browser_is('OP5Up');
  133. **/
  134. function browser_is ($s)
  135. { preg_match('/'.$this->_browser_search_regex.'/i',$s,$match);
  136. if($match) return $this->_perform_browser_search($match);
  137. }
  138. /**
  139. * language_is
  140. * @param $s string search phrase for language
  141. * @return bool true on success
  142. * ex: $client->language_is('en-US');
  143. **/
  144. function language_is ($s)
  145. { preg_match('/'.$this->_language_search_regex.'/i',$s,$match);
  146. if($match) return $this->_perform_language_search($match);
  147. }
  148. /**
  149. * has_feature
  150. * @param $s string feature we're checking on
  151. * @return bool true on success
  152. * ex: $client->has_feature('html');
  153. **/
  154. function has_feature ($s)
  155. { return $this->_feature_set[$s];
  156. }
  157. /**
  158. * has_quirk
  159. * @param $s string quirk we're looking for
  160. * @return bool true on success
  161. * ex: $client->has_quirk('avoid_popup_windows');
  162. **/
  163. function has_quirk ($s)
  164. { return $this->_quirks[$s];
  165. }
  166. /**
  167. * _perform_browser_search
  168. * @param $data string what we're searching for
  169. * @return bool true on success
  170. * @private
  171. **/
  172. function _perform_browser_search ($data)
  173. { $search = array();
  174. $search['phrase'] = isset($data[0]) ? $data[0] : '';
  175. $search['name'] = isset($data[1]) ? strtolower($data[1]) : '';
  176. $search['maj_ver'] = isset($data[2]) ? $data[2] : '';
  177. $search['min_ver'] = isset($data[3]) ? $data[3] : '';
  178. $search['direction'] = isset($data[4]) ? strtolower($data[4]) : '';
  179. $looking_for = $search['maj_ver'].$search['min_ver'];
  180. if($search['name'] == 'aol' || $search['name'] == 'webtv')
  181. { return stristr($this->_browser_info['ua'],$search['name']);
  182. }
  183. elseif($this->_browser_info['browser'] == $search['name'])
  184. { $majv = $search['maj_ver'] ? $this->_browser_info['maj_ver'] : '';
  185. $minv = $search['min_ver'] ? $this->_browser_info['min_ver'] : '';
  186. $what_we_are = $majv.$minv;
  187. if(($search['direction'] == 'up' || $search['direction'] == '+')
  188. && ($what_we_are >= $looking_for))
  189. { return true;
  190. }
  191. elseif(($search['direction'] == 'dn' || $search['direction'] == '-')
  192. && ($what_we_are <= $looking_for))
  193. { return true;
  194. }
  195. elseif($what_we_are == $looking_for)
  196. { return true;
  197. }
  198. }
  199. return false;
  200. }
  201. function _perform_language_search ($data)
  202. { // if we've not grabbed the languages, then do so.
  203. $this->_get_languages();
  204. return stristr($this->_browser_info['language'],$data[1]);
  205. }
  206. function _get_languages ()
  207. { // capture available languages and insert into container
  208. if(!$this->_get_languages_ran_once)
  209. { if($languages = getenv('HTTP_ACCEPT_LANGUAGE'))
  210. { $languages = preg_replace('/(;q=[0-9]+.[0-9]+)/i','',$languages);
  211. }
  212. else
  213. { $languages = $this->_default_language;
  214. }
  215. $this->_set_browser('language',$languages);
  216. $this->_get_languages_ran_once = true;
  217. }
  218. }
  219. function _get_os_info ()
  220. { // regexes to use
  221. $regex_windows = '/([^dar]win[dows]*)[\s]?([0-9a-z]*)[\w\s]?([a-z0-9.]*)/i';
  222. $regex_mac = '/(68[k0]{1,3})|(ppc mac os x)|([p\S]{1,5}pc)|(darwin)/i';
  223. $regex_os2 = '/os\/2|ibm-webexplorer/i';
  224. $regex_sunos = '/(sun|i86)[os\s]*([0-9]*)/i';
  225. $regex_irix = '/(irix)[\s]*([0-9]*)/i';
  226. $regex_hpux = '/(hp-ux)[\s]*([0-9]*)/i';
  227. $regex_aix = '/aix([0-9]*)/i';
  228. $regex_dec = '/dec|osfl|alphaserver|ultrix|alphastation/i';
  229. $regex_vms = '/vax|openvms/i';
  230. $regex_sco = '/sco|unix_sv/i';
  231. $regex_linux = '/x11|inux/i';
  232. $regex_bsd = '/(free)?(bsd)/i';
  233. $regex_amiga = '/amiga[os]?/i';
  234. // look for Windows Box
  235. if(preg_match_all($regex_windows,$this->_browser_info['ua'],$match))
  236. { /** Windows has some of the most ridiculous HTTP_USER_AGENT strings */
  237. //$match[1][count($match[0])-1];
  238. $v = $match[2][count($match[0])-1];
  239. $v2 = $match[3][count($match[0])-1];
  240. // Establish NT 5.1 as Windows XP
  241. if(stristr($v,'NT') && $v2 == 5.1) $v = 'xp';
  242. // Establish NT 5.0 and Windows 2000 as win2k
  243. elseif($v == '2000') $v = '2k';
  244. elseif(stristr($v,'NT') && $v2 == 5.0) $v = '2k';
  245. // Establish 9x 4.90 as Windows 98
  246. elseif(stristr($v,'9x') && $v2 == 4.9) $v = '98';
  247. // See if we're running windows 3.1
  248. elseif($v.$v2 == '16bit') $v = '31';
  249. // otherwise display as is (31,95,98,NT,ME,XP)
  250. else $v .= $v2;
  251. // update browser info container array
  252. if(empty($v)) $v = 'win';
  253. $this->_set_browser('os',strtolower($v));
  254. $this->_set_browser('platform','win');
  255. }
  256. // look for amiga OS
  257. elseif(preg_match($regex_amiga,$this->_browser_info['ua'],$match))
  258. { $this->_set_browser('platform','amiga');
  259. if(stristr($this->_browser_info['ua'],'morphos')) {
  260. // checking for MorphOS
  261. $this->_set_browser('os','morphos');
  262. } elseif(stristr($this->_browser_info['ua'],'mc680x0')) {
  263. // checking for MC680x0
  264. $this->_set_browser('os','mc680x0');
  265. } elseif(stristr($this->_browser_info['ua'],'ppc')) {
  266. // checking for PPC
  267. $this->_set_browser('os','ppc');
  268. } elseif(preg_match('/(AmigaOS [\.1-9]?)/i',$this->_browser_info['ua'],$match)) {
  269. // checking for AmigaOS version string
  270. $this->_set_browser('os',$match[1]);
  271. }
  272. }
  273. // look for OS2
  274. elseif( preg_match($regex_os2,$this->_browser_info['ua']))
  275. { $this->_set_browser('os','os2');
  276. $this->_set_browser('platform','os2');
  277. }
  278. // look for mac
  279. // sets: platform = mac ; os = 68k or ppc
  280. elseif( preg_match($regex_mac,$this->_browser_info['ua'],$match) )
  281. { $this->_set_browser('platform','mac');
  282. $os = !empty($match[1]) ? '68k' : '';
  283. $os = !empty($match[2]) ? 'osx' : $os;
  284. $os = !empty($match[3]) ? 'ppc' : $os;
  285. $os = !empty($match[4]) ? 'osx' : $os;
  286. $this->_set_browser('os',$os);
  287. }
  288. // look for *nix boxes
  289. // sunos sets: platform = *nix ; os = sun|sun4|sun5|suni86
  290. elseif(preg_match($regex_sunos,$this->_browser_info['ua'],$match))
  291. { $this->_set_browser('platform','*nix');
  292. if(!stristr('sun',$match[1])) $match[1] = 'sun'.$match[1];
  293. $this->_set_browser('os',$match[1].$match[2]);
  294. }
  295. // irix sets: platform = *nix ; os = irix|irix5|irix6|...
  296. elseif(preg_match($regex_irix,$this->_browser_info['ua'],$match))
  297. { $this->_set_browser('platform','*nix');
  298. $this->_set_browser('os',$match[1].$match[2]);
  299. }
  300. // hp-ux sets: platform = *nix ; os = hpux9|hpux10|...
  301. elseif(preg_match($regex_hpux,$this->_browser_info['ua'],$match))
  302. { $this->_set_browser('platform','*nix');
  303. $match[1] = str_replace('-','',$match[1]);
  304. $match[2] = (int) $match[2];
  305. $this->_set_browser('os',$match[1].$match[2]);
  306. }
  307. // aix sets: platform = *nix ; os = aix|aix1|aix2|aix3|...
  308. elseif(preg_match($regex_aix,$this->_browser_info['ua'],$match))
  309. { $this->_set_browser('platform','*nix');
  310. $this->_set_browser('os','aix'.$match[1]);
  311. }
  312. // dec sets: platform = *nix ; os = dec
  313. elseif(preg_match($regex_dec,$this->_browser_info['ua'],$match))
  314. { $this->_set_browser('platform','*nix');
  315. $this->_set_browser('os','dec');
  316. }
  317. // vms sets: platform = *nix ; os = vms
  318. elseif(preg_match($regex_vms,$this->_browser_info['ua'],$match))
  319. { $this->_set_browser('platform','*nix');
  320. $this->_set_browser('os','vms');
  321. }
  322. // sco sets: platform = *nix ; os = sco
  323. elseif(preg_match($regex_sco,$this->_browser_info['ua'],$match))
  324. { $this->_set_browser('platform','*nix');
  325. $this->_set_browser('os','sco');
  326. }
  327. // unixware sets: platform = *nix ; os = unixware
  328. elseif(stristr($this->_browser_info['ua'],'unix_system_v'))
  329. { $this->_set_browser('platform','*nix');
  330. $this->_set_browser('os','unixware');
  331. }
  332. // mpras sets: platform = *nix ; os = mpras
  333. elseif(stristr($this->_browser_info['ua'],'ncr'))
  334. { $this->_set_browser('platform','*nix');
  335. $this->_set_browser('os','mpras');
  336. }
  337. // reliant sets: platform = *nix ; os = reliant
  338. elseif(stristr($this->_browser_info['ua'],'reliantunix'))
  339. { $this->_set_browser('platform','*nix');
  340. $this->_set_browser('os','reliant');
  341. }
  342. // sinix sets: platform = *nix ; os = sinix
  343. elseif(stristr($this->_browser_info['ua'],'sinix'))
  344. { $this->_set_browser('platform','*nix');
  345. $this->_set_browser('os','sinix');
  346. }
  347. // bsd sets: platform = *nix ; os = bsd|freebsd
  348. elseif(preg_match($regex_bsd,$this->_browser_info['ua'],$match))
  349. { $this->_set_browser('platform','*nix');
  350. $this->_set_browser('os',$match[1].$match[2]);
  351. }
  352. // last one to look for
  353. // linux sets: platform = *nix ; os = linux
  354. elseif(preg_match($regex_linux,$this->_browser_info['ua'],$match))
  355. { $this->_set_browser('platform','*nix');
  356. $this->_set_browser('os','linux');
  357. }
  358. }
  359. function _get_browser_info ()
  360. { $this->_build_regex();
  361. if(preg_match_all($this->_browser_regex,$this->_browser_info['ua'],$results))
  362. { // get the position of the last browser found
  363. $count = count($results[0])-1;
  364. // if we're allowing masquerading, revert to the next to last browser found
  365. // if possible, otherwise stay put
  366. if($this->_allow_masquerading && $count > 0) $count--;
  367. // insert findings into the container
  368. $this->_set_browser('browser',$this->_get_short_name($results[1][$count]));
  369. $this->_set_browser('long_name',$results[1][$count]);
  370. $this->_set_browser('maj_ver',$results[2][$count]);
  371. // parse the minor version string and look for alpha chars
  372. preg_match('/([.\0-9]+)?([\.a-z0-9]+)?/i',$results[3][$count],$match);
  373. if(isset($match[1])) {
  374. $this->_set_browser('min_ver',$match[1]);
  375. } else {
  376. $this->_set_browser('min_ver','.0');
  377. }
  378. if(isset($match[2])) $this->_set_browser('letter_ver',$match[2]);
  379. // insert findings into container
  380. $this->_set_browser('version',$this->_browser_info['maj_ver'].$this->property('min_ver'));
  381. }
  382. }
  383. function _get_ip ()
  384. { if(getenv('HTTP_CLIENT_IP'))
  385. { $ip = getenv('HTTP_CLIENT_IP');
  386. }
  387. else
  388. { $ip = getenv('REMOTE_ADDR');
  389. }
  390. $this->_set_browser('ip',$ip);
  391. }
  392. function _build_regex ()
  393. { $browsers = '';
  394. while(list($k,) = each($this->_browsers))
  395. { if(!empty($browsers)) $browsers .= "|";
  396. $browsers .= $k;
  397. }
  398. $version_string = "[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?";
  399. $this->_browser_regex = "/($browsers)$version_string/i";
  400. }
  401. function _get_short_name ($long_name)
  402. { return $this->_browsers[strtolower($long_name)];
  403. }
  404. // medianes :: new test cookie routine
  405. function _test_cookies()
  406. { global $HTTP_COOKIE_VARS;
  407. $cookies = array();
  408. if(isset($_COOKIE)) {
  409. $cookies = $_COOKIE;
  410. } elseif(isset($HTTP_COOKIE_VARS)) {
  411. $cookies = $HTTP_COOKIE_VARS;
  412. }
  413. if($this->_check_cookies)
  414. { $fp = @fopen($this->_temp_file_path.$this->property('ip'),'r');
  415. if(!$fp)
  416. { $fp = @fopen($this->_temp_file_path.$this->property('ip'),'a');
  417. fclose($fp);
  418. setcookie('phpSniff_session','ss',0,'/');
  419. setcookie('phpSniff_stored','st',time()+3600*24*365,'/');
  420. $QS=getenv('QUERY_STRING');
  421. $script_path=getenv('PATH_INFO')?getenv('PATH_INFO'):getenv('SCRIPT_NAME');
  422. if(is_integer($pos=strpos(strrev($script_path),"php.xedni/"))&&!$pos) {
  423. $script_path=strrev(substr(strrev($script_path),9));
  424. }
  425. $location='http://'.getenv('SERVER_NAME').$script_path.($QS==''?'':'?'.$QS);
  426. header("Location: $location");
  427. exit;
  428. }
  429. else
  430. { unlink($this->_temp_file_path.$this->property('ip'));
  431. fclose($fp);
  432. $this->_set_browser('ss_cookies',isset($cookies['phpSniff_session'])?'true':'false');
  433. $this->_set_browser('st_cookies',isset($cookies['phpSniff_stored'])?'true':'false');
  434. // delete the old cookies
  435. setcookie('phpSniff_session','',0,'/');
  436. setcookie('phpSniff_stored','',0,'/');
  437. }
  438. }
  439. }
  440. function _get_javascript()
  441. { $set=false;
  442. // see if we have any matches
  443. while(list($version,$browser) = each($this->_javascript_versions))
  444. { $browser = explode(',',$browser);
  445. while(list(,$search) = each($browser))
  446. { if($this->is('b:'.$search))
  447. { $this->_set_browser('javascript',$version);
  448. $set = true;
  449. break;
  450. }
  451. }
  452. if($set) break;
  453. }
  454. }
  455. function _get_features ()
  456. { while(list($feature,$browser) = each($this->_browser_features))
  457. { $browser = explode(',',$browser);
  458. while(list(,$search) = each($browser))
  459. { if($this->browser_is($search))
  460. { $this->_set_feature($feature);
  461. break;
  462. }
  463. }
  464. }
  465. }
  466. function _get_quirks ()
  467. { while(list($quirk,$browser) = each($this->_browser_quirks))
  468. { $browser = explode(',',$browser);
  469. while(list(,$search) = each($browser))
  470. { if($this->browser_is($search))
  471. { $this->_set_quirk($quirk);
  472. break;
  473. }
  474. }
  475. }
  476. }
  477. function _get_gecko ()
  478. { if(preg_match('/gecko\/([0-9]+)/i',$this->property('ua'),$match))
  479. { $this->_set_browser('gecko',$match[1]);
  480. if (preg_match('/rv[: ]?([0-9a-z.+]+)/i',$this->property('ua'),$mozv)) {
  481. // mozilla release
  482. $this->_set_browser('gecko_ver',$mozv[1]);
  483. } elseif (preg_match('/(m[0-9]+)/i',$this->property('ua'),$mozv)) {
  484. // mozilla milestone version
  485. $this->_set_browser('gecko_ver',$mozv[1]);
  486. }
  487. // if this is a mozilla browser, get the rv: information
  488. if($this->browser_is($this->_get_short_name('mozilla'))) {
  489. if(preg_match('/([0-9]+)([\.0-9]+)([a-z0-9+]?)/i',$mozv[1],$match)) {
  490. $this->_set_browser('version',$mozv[1]);
  491. $this->_set_browser('maj_ver',$match[1]);
  492. $this->_set_browser('min_ver',$match[2]);
  493. $this->_set_browser('letter_ver',$match[3]);
  494. }
  495. }
  496. } elseif($this->is('b:'.$this->_get_short_name('mozilla'))) {
  497. // this is probably a netscape browser or compatible
  498. $this->_set_browser('long_name','netscape');
  499. $this->_set_browser('browser',$this->_get_short_name('netscape'));
  500. }
  501. }
  502. function _set_browser ($k,$v)
  503. { $this->_browser_info[strtolower($k)] = strtolower($v);
  504. }
  505. function _set_feature ($k)
  506. { $this->_feature_set[strtolower($k)] = !$this->_feature_set[strtolower($k)];
  507. }
  508. function _set_quirk ($k)
  509. { $this->_quirks[strtolower($k)] = true;
  510. }
  511. }
  512. ?>