PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/Documents/v4/scripts/essential.php

https://github.com/joshuawdavidson/planwatch
PHP | 741 lines | 110 code | 34 blank | 597 comment | 34 complexity | 800e334c77d8407a1f1732a032ac94be MD5 | raw file
Possible License(s): BSD-2-Clause
  1. <?php
  2. /*
  3. ESSENTIAL.PHP -- part of the planwatch library
  4. necessary functions for all pages that aren't somewhere
  5. in the standard library. also includes authentication processes
  6. and profiling.
  7. --------------------------------------------------------------------------------
  8. TODO:(v5) create installation scripts that run when you point at
  9. the dir we're in and create siteconfig.php, .htaccess, directories
  10. as appropriate.
  11. --------------------------------------------------------------------------------
  12. functions:
  13. profile()
  14. array_set_current()
  15. redirect()
  16. mail_look()
  17. planworld_node_getinfo()
  18. login() -- logs a user in, sets a cookie
  19. logout() -- logs a user out, empties a cookie
  20. profile_display()
  21. */
  22. // CATCH BOTS
  23. // stop them before anything else happens at all.
  24. if (bot_blacklist())
  25. {
  26. header("HTTP/1.1 403 Forbidden");
  27. exit;
  28. }
  29. // LOAD PROFILING
  30. //------------------------------------------------------------------------------
  31. // profile measures loops in microseconds. the first time you call it is
  32. // the beginning, the second time is the end.
  33. profile('pageload');
  34. profile('precontent');
  35. profile('essential');
  36. profile('includes','begin');
  37. profile('includes_always','begin');
  38. // ALWAYS INCLUDED FILES
  39. //------------------------------------------------------------------------------
  40. include_once('xmlrpc.inc');
  41. include_once('output.php');
  42. profile('includes_always','end');
  43. profile('includes_lib','begin');
  44. // STANDARD LIBRARY INCLUDES
  45. //------------------------------------------------------------------------------
  46. exec("ls $_SERVER[FILE_ROOT]/scripts/standard_library/*.php",$include_list);
  47. foreach($include_list as $file)
  48. include_once($file);
  49. profile('includes_lib','end');
  50. profile('includes','end');
  51. // GENERAL SETUP
  52. //------------------------------------------------------------------------------
  53. // TODO: shouldn't be reporting 200 OK here, rather when we output.
  54. // need to test this offline before changing it.
  55. header("HTTP/1.1 200 OK\n");
  56. // if you want standard php error reporting, uncomment this
  57. //error_reporting(E_ALL & ~(E_NOTICE));
  58. // the OUTPUT_MODE is used mostly to identify whether we're on
  59. // mobile or desktop, but also for non-html output formats
  60. // (Atom, RSS, soon JSON)
  61. define("OUTPUT_MODE",output_set_mode());
  62. // if we're in a subdirectory, strip it out to avoid complicating the
  63. // logic in parseurl
  64. // TODO: request cleanup should be moved to parseurl.php
  65. $_SERVER['REQUEST_URI']=str_replace($_SERVER['WEB_ROOT'],'',$_SERVER['REQUEST_URI']);
  66. //------------------------------------------------------------------------------
  67. //
  68. // AUTHENTICATION
  69. //
  70. //------------------------------------------------------------------------------
  71. // get the session id / fingerprint if it's stored in the URL
  72. // we always use the fingerprint for session ids, so we don't have to worry
  73. // about people altering settings and not having them propagated to existing
  74. // login states on other machines/browsers
  75. //
  76. // there are some fairly minor security considerations here, this could
  77. // do with a rethink for client api
  78. if (!$_POST['sid'] && !$_GET['sid']) list($trash,$sid)=explode("sid=",$_SERVER['REQUEST_URI']);
  79. elseif(isset($_POST['sid'])) $sid=$_POST['sid'];
  80. elseif(isset($_GET['sid'])) $sid=$_GET['sid'];
  81. // URL Authentication
  82. // used by people who are doing looks from different users than their
  83. // logged in users (this includes basically josh and johnnie)
  84. //-------------------------------------------------------------------
  85. $urlarray=explode('/',$_SERVER['REQUEST_URI']);
  86. $urlarray_count=count($urlarray);
  87. // if we haven't found a fingerprint so far, we check for a fingerprint in the url
  88. if (user_verify_fingerprint($urlarray[$urlarray_count-1]))
  89. {
  90. // FINGERPRINT IS LAST ITEM IN URL ARRAY
  91. }
  92. // if no valid fingerprint is found, we test the last two parts
  93. // of the url array to see if they're a valid username and password
  94. elseif (user_verify_fingerprint(user_get_fingerprint($urlarray[$urlarray_count-2],$urlarray[$urlarray_count-1])))
  95. {
  96. // USER AND PASS ARE LAST TWO ITEMS IN URL ARRAY
  97. }
  98. // If URL Authentication fails, we test for normal authentication.
  99. //-------------------------------------------------------------------
  100. // i know this seems weird, but it's really just a way to support
  101. // temporary off-user look
  102. else
  103. {
  104. if (user_verify_fingerprint($_COOKIE[$_SERVER['AUTH_COOKIE']]))
  105. {
  106. // VALID USER COOKIE FOUND
  107. if (user_is_administrator() && user_verify_fingerprint($_COOKIE['mau']))
  108. {
  109. // MASQUERADING IS ON
  110. $_SERVER['MASQUERADE']=TRUE;
  111. }
  112. else $_SERVER['MASQUERADE']=FALSE;
  113. }
  114. elseif(user_verify_fingerprint($sid))
  115. {
  116. // VALID SESSION ID FOUND
  117. $_SERVER["SESSION_ID"]=$sid;
  118. }
  119. elseif(user_verify_fingerprint($_POST[$_SERVER['AUTH_COOKIE']]))
  120. {
  121. // VALID FINGERPRINT VIA POST
  122. // this is so the write form can't expire even if the user leaves it
  123. // up past cookie expiry.
  124. }
  125. }
  126. // Cookie Updates
  127. //-------------------------------------------------------------------
  128. // if the user is not masquerading, we update the cookie expiry
  129. if (!user_verify_fingerprint($_COOKIE['mau']))
  130. {
  131. if ($_COOKIE['remember']=='remember=' && user_is_valid($user,$pass)) login($user,$pass,FALSE,FALSE);
  132. if ($_COOKIE['remember']=='remember=1' && user_is_valid($user,$pass)) login($user,$pass,1,FALSE);
  133. }
  134. // SMILEY_FUNCTIONS INCLUDE
  135. //------------------------------------------------------------------------------
  136. // Include the smileys functions if the user is reading or writing something
  137. // that could involve smileys, and they don't have the smileys-destroyer
  138. // turned on in their preferences.
  139. if ((strpos($_SERVER['REQUEST_URI'],'read') || strpos($_SERVER['REQUEST_URI'],'write') || strpos($_SERVER['REQUEST_URI'],'help'))
  140. && $_SERVER['USERINFO_ARRAY']['hatessmileys']==FALSE) { include_once('smiley_functions.php'); }
  141. // GLOBALS
  142. //------------------------------------------------------------------------------
  143. if (file_exists("$_SERVER[FILE_ROOT]/stats/plan_locations.dat")) $_SERVER['PLAN_LOCATION_ARRAY']=unserialize(file_get_contents("$_SERVER[FILE_ROOT]/stats/plan_locations.dat"));
  144. if (file_exists("$_SERVER[FILE_ROOT]/stats/plan_failures.dat")) $_SERVER['PLAN_LOCATION_FAILED_ARRAY']=unserialize(file_get_contents("$_SERVER[FILE_ROOT]/stats/plan_failures.dat"));
  145. // ERROR REPORTING
  146. //------------------------------------------------------------------------------
  147. //if (user_is_administrator()) error_reporting(E_ALL & ~(E_NOTICE));
  148. //else error_reporting(E_ERROR & E_PARSE);
  149. //error_reporting(E_ALL & ~(E_NOTICE));
  150. //if ($_SERVER['USER']=='jwdavidson') trigger_error("this is not a real error. do not be alarmed.");
  151. //if ($_SERVER['USER']=='jwdavidson') trigger_error("this is not a real error. do not be alarmed.",E_USER_WARNING);
  152. // UPDATE LAST ACTION
  153. // also updates the time reported as "last login" since we don't track login times
  154. // because most of our users are permanently logged in
  155. //------------------------------------------------------------------------------
  156. if ($_SERVER['OUTPUT_MODE']!='AJAX' && !strstr($_SERVER['REQUEST_URI'],'micro'))
  157. user_update_last_action();
  158. // TESTING VARIABLES, ETC.
  159. //------------------------------------------------------------------------------
  160. // this space intentionally left blank (for now)
  161. // STYLES
  162. //------------------------------------------------------------------------------
  163. // TODO:(v4.5) rewrite styles selection form (or at least offer advanced ver.)
  164. if ($_SERVER['USER'])
  165. {
  166. $styles_fn="$_SERVER[USER_ROOT]/styles.txt"; //reads user styles.
  167. $fonts_fn="$_SERVER[USER_ROOT]/fonts.txt"; //reads user fonts.
  168. $colors_fn="$_SERVER[USER_ROOT]/colors.txt";
  169. $skin_fn="$_SERVER[USER_ROOT]/skin.txt";
  170. }
  171. if($_SERVER['OUTPUT_MODE']=='IPHONE' || $_SERVER['OUTPUT_MODE']=='MOBILE')
  172. include('default.skin'); // reads default styles.
  173. if ($_SERVER['OUTPUT_MODE']=='HTML' || $_SERVER['OUTPUT_MODE']=='IPHONE' || $_SERVER['OUTPUT_MODE']=='MOBILE')
  174. {
  175. include_once('formatting_html.php');
  176. include('default.skin'); // reads default styles.
  177. if (file_exists($styles_fn) && !file_exists($skin_fn) && !file_exists($colors_fn))
  178. {
  179. parse_str(file_get_contents($styles_fn));
  180. if ($skin && file_exists("$_SERVER[FILE_ROOT]/resources/skins/$skin"))
  181. include($skin);
  182. if ($planlinkcolor) $navlinkcolor=$planlinkcolor;
  183. }
  184. if (file_exists($skin_fn))
  185. {
  186. parse_str(file_get_contents($skin_fn));
  187. if ($skin) include($skin);
  188. }
  189. if (file_exists($fonts_fn))
  190. {
  191. parse_str(file_get_contents($fonts_fn));
  192. }
  193. if (file_exists($colors_fn))
  194. {
  195. parse_str(file_get_contents($colors_fn));
  196. }
  197. $pfsize_css=html_size_to_css_size($pfsize);
  198. $nfsize_css=html_size_to_css_size($nfsize);
  199. $sfsize_css=html_size_to_css_size($sfsize);
  200. $hfsize_css=html_size_to_css_size($hfsize);
  201. }
  202. // TIMEZONE
  203. //-----------------------------------------------------------------------------------------
  204. if (strlen($_SERVER['USERINFO_ARRAY']['timezone'])<=3) $_SERVER['USERINFO_ARRAY']['timezone']="America/New_York";
  205. putenv("TZ={$_SERVER[USERINFO_ARRAY][timezone]}");
  206. profile('essential','end');
  207. //------------------------------------------------------------------------------
  208. // FUNCTIONS BEGIN HERE
  209. //==============================================================================
  210. if (!function_exists("stripos")) {
  211. function stripos($str,$needle,$offset=0)
  212. {
  213. return strpos(strtolower($str),strtolower($needle),$offset);
  214. }
  215. }
  216. function cache_clear($planowner)
  217. {
  218. if ($_SERVER['PLANOWNER_INFO_ARRAY']['username']!=$planowner)
  219. plan_get_owner_info($planowner);
  220. exec("rm -f $_SERVER[FILE_ROOT]/temp/*".base64_encode($planowner)."*.cache");
  221. exec("rm -f $_SERVER[FILE_ROOT]/../temp/*$planowner*.cache");
  222. exec("rm -f $_SERVER[FILE_ROOT]/temp/{$_SERVER['PLANOWNER_INFO_ARRAY']['salt']}*.cache");
  223. }
  224. // IS_MOBILE determines whether the user agent is a mobile device
  225. // based on UA testing. this is not a good way to do it, but i
  226. // haven't found a better one. anyway it's only used for picking a default mode
  227. // at the default url.
  228. function is_mobile()
  229. {
  230. $ua=strtolower($_SERVER['HTTP_USER_AGENT']);
  231. if(strstr($ua,"opera mobi")
  232. || strstr($ua,"opera mini")
  233. || strstr($ua,"iphone")
  234. || strstr($ua,"ipod")
  235. || strstr($ua,"android")
  236. || (strstr($ua,"webos") && (strstr($ua,"pre") || strstr($ua,"pixi")))
  237. || (strstr($ua,"msie") && strstr($ua,"ce"))
  238. || (strstr($ua,"safari") && strstr($ua,"tear"))
  239. || strstr($ua,"kindle")
  240. || strstr($ua,"netfront")
  241. || strstr($ua,"midp")
  242. || strstr($ua,"ucweb")
  243. ) return TRUE;
  244. else return FALSE;
  245. }
  246. function agent_is_lowfi()
  247. {
  248. if (stristr($_SERVER['HTTP_USER_AGENT'],'blackberry')) return TRUE;
  249. }
  250. function isjosh() { if (IS_JOSH) return TRUE; else return FALSE; }
  251. // prevents search engines and suspect sites from getting to plans
  252. function bot_blacklist()
  253. {
  254. $blacklist[]="irlbot";
  255. // $blacklist[]="intel mac"; // this is for testing.
  256. $blacklist[]="surveybot";
  257. $blacklist[]="googlebot";
  258. $blacklist[]="msnbot";
  259. $blacklist[]="yahoo! slurp";
  260. $blacklist[]="buildcms crawler";
  261. $blacklist[]="grub.org";
  262. $blacklist[]="65.222.176.124";
  263. $blacklist[]="66.249.85.130";
  264. $agent=strtolower($_SERVER['HTTP_USER_AGENT']);
  265. foreach($blacklist as $ban)
  266. {
  267. if (strpos($agent,$ban)) return TRUE;
  268. if (strpos($_SERVER["REMOTE_ADDR"],$ban)!==FALSE) return TRUE;
  269. }
  270. return FALSE;
  271. }
  272. // PROFILE()
  273. //
  274. // sets a point on the stopwatch so we can see how long each section takes
  275. //------------------------------------------------------------------------------
  276. function profile($key,$state=FALSE)
  277. {
  278. if ($state==FALSE)
  279. {
  280. if ($_SERVER['STOPWATCH']["{$key}_begin"]) $state = 'end';
  281. else $state = 'begin';
  282. }
  283. $_SERVER['STOPWATCH']["{$key}_$state"]=array_sum(explode(' ',microtime()));
  284. }
  285. function test($message)
  286. {
  287. if (strstr($_SERVER['USER'],'jwdavidson')) print_r($message."<br/>\n");
  288. }
  289. // ARRAY_SET_CURRENT
  290. //
  291. // this version by jari dot eskelinen at iki dot fi
  292. // from comments on http://us4.php.net/current
  293. //
  294. // sets $array's pointer to point at the entry with $key.
  295. // used in plan_read_local.
  296. //------------------------------------------------------------------------------
  297. function array_set_current(&$array, $key)
  298. {
  299. profile("array_set_current");
  300. reset($array);
  301. while (current($array)!==FALSE){
  302. if (key($array) == $key) {
  303. break;
  304. }
  305. next($array);
  306. }
  307. profile("array_set_current");
  308. return current($array);
  309. }
  310. // REDIRECT
  311. //
  312. // handles HTTP redirection, adds session info as necessary
  313. // subdir abstraction is now handled elsewhere thanks to $_SERVER[WEB_ROOT]
  314. //------------------------------------------------------------------------------
  315. function redirect($url='/')
  316. {
  317. if (!$url) $url='/';
  318. if ($url[0]=='/') $url="http://$_SERVER[HTTP_HOST]$_SERVER[WEB_ROOT]".$url;
  319. if (isset($_SERVER['SESSIONID'])) $url.="/sid=$_SERVER[SESSION_ID]";
  320. $cookie_host=$_SERVER['HTTP_HOST'];
  321. if (substr_count($cookie_host,'.') < 2) $cookie_host=".$cookie_host";
  322. $cookie_host=str_replace('www','',$cookie_host);
  323. //this way, we know we got redirected. it helps particularly on the iphone client.
  324. setcookie("redirected","1",time()+10,$_SERVER['WEB_ROOT']."/",$cookie_host);
  325. Header("Location: $url");
  326. return 1;
  327. }
  328. // MAIL_LOOK()
  329. //
  330. // emails a watched list for a registered user
  331. //------------------------------------------------------------------------------
  332. function mail_look($person)
  333. {
  334. include_once('plan_read.php');
  335. $userinfo=unserialize(file_get_contents("$_SERVER[PWUSERS_DIR]/$person/userinfo.dat"));
  336. $watchedlist=file("$_SERVER[PWUSERS_DIR]/$person/watchedlist.txt");
  337. $output.="[planwatch.org]: planwatch automailer\n\nHere's what's been updated:\n";
  338. $sortby=trim(str_replace("sort by ",'',$watchedlist[0]));
  339. if (strpos($watchedlist[0],'sort by ')!==FALSE) unset($watchedlist[0]);
  340. $output.=str_replace("&nbsp;",' ',strip_tags(list_format_html($watchedlist,$sortby,'',"\n")));
  341. $output.="\n\n\n\n";
  342. mail($userinfo['email'],"your watched list updates ".date("F jS Y"),$output,"From: watched@planwatch.org");
  343. }
  344. // planworld_node_getinfo()
  345. //
  346. // gets info for an XML-RPC planworld node
  347. // an array is returned keyed with 'port', 'server', and 'directory'
  348. //------------------------------------------------------------------------------
  349. function planworld_node_getinfo($node='note')
  350. {
  351. if (strpos($node,'@')===FALSE) $node='@'.$node;
  352. if ($node=='@note') return array("port"=>80,"server"=>"neon.note.amherst.edu","directory"=>"/planworld/backend/");
  353. elseif ($node=='@note.amherst.edu') return array("port"=>80,"server"=>"neon.note.amherst.edu","directory"=>"/planworld/backend/");
  354. elseif ($node=='@amherst.edu') return array("port"=>80,"server"=>"neon.note.amherst.edu","directory"=>"/planworld/backend/");
  355. elseif($node=='@krypton') return array("port"=>80,"server"=>"neon.note.amherst.edu","directory"=>"/planworld/backend/");
  356. elseif ($node=='@pwn') return array("port"=>80,"server"=>"planworld.net","directory"=>"/backend/");
  357. elseif ($node=='@planworld.net') return array("port"=>80,"server"=>"planworld.net","directory"=>"/backend/");
  358. elseif ($node=='@planwatch.org') return array("port"=>80,"server"=>"planwatch.org","directory"=>"/backend/");
  359. elseif ($node=='@beta.planwatch.org') return array("port"=>80,"server"=>"beta.planwatch.org","directory"=>"/backend/");
  360. elseif ($node=='@beta') return array("port"=>80,"server"=>"beta.planwatch.org","directory"=>"/backend/");
  361. elseif ($node=='@flickr') return array("port"=>80,"server"=>"www.flickr.com","directory"=>"/services/xmlrpc/");
  362. else return FALSE;
  363. }
  364. // PLANWORLD_XMLRPC_RESPONSE()
  365. //
  366. // generic xml-rpc response handler for the planworld api
  367. // designed to simplify implementation of planworld api responses for server
  368. // needs lots of testing and thinking work.
  369. //------------------------------------------------------------------------------
  370. function planworld_xmlrpc_response($method,$arguments) {
  371. global $xmlrpcerruser;
  372. global $signature;
  373. $err="";
  374. $parameter_count = $arguments->getNumParams();
  375. for($i=0;$i<$parameter_count;$i++)
  376. {
  377. $item[$i]=$arguments->getParam($i);
  378. $scalar_item[$i]=$item[$i]->scalarval();
  379. }
  380. $something = $signature[$method];
  381. // call the passed method here
  382. // if we generated an error, create an error return response
  383. if ($err) {
  384. return new xmlrpcresp(0, $xmlrpcerruser, $err);
  385. } else {
  386. // otherwise, we create the right response
  387. // with the state name
  388. return new xmlrpcresp(new xmlrpcval($plan,'base64'));
  389. }
  390. }
  391. // PLANWORLD_XMLRPC_QUERY()
  392. //
  393. // generic xml-rpc query handler for the planworld api
  394. // designed to simplify implementation of planworld api calls
  395. // needs lots of testing and thinking work.
  396. //------------------------------------------------------------------------------
  397. // TODO:(v4.1) rework xmlrpc stuff using planworld_xmlrpc_query()
  398. function planworld_xmlrpc_query($node,$message,$params,$debug=FALSE)
  399. {
  400. $nodeinfo=planworld_node_getinfo($node);
  401. $f=new xmlrpcmsg($message);
  402. // echo "<hr>";
  403. foreach($params as $param)
  404. {
  405. if (is_int($param)) $type="int";
  406. if (is_string($param)) $type="string";
  407. if (is_array($param))
  408. {
  409. $type="array";
  410. if (!isset($param[count($param)-1])) $type="struct";
  411. }
  412. if (is_bool($param)) $type=xmlrpcBoolean;
  413. $f->addParam(new xmlrpcval($param, $type));
  414. //print_r($f);
  415. //echo "$param : $type<br/>";
  416. //echo "<hr>";
  417. }
  418. $c=new xmlrpc_client($nodeinfo["directory"], $nodeinfo["server"], $nodeinfo["port"]);
  419. $c->setDebug(FALSE);
  420. $r=$c->send($f);
  421. if (!$r) { $returnval="<div class='alert'>$message to $node failed on send().</div>"; }
  422. else
  423. {
  424. $v=$r->value();
  425. if (!$r->faultCode()) {
  426. if ($v->kindOf()=='scalar') $returnval = $v->scalarval();
  427. } else {
  428. if ($debug) {
  429. $returnval="Fault: ";
  430. $returnval.="Code: " . $r->faultCode() .
  431. " Reason '" .$r->faultString()."'<br/>";
  432. }
  433. }
  434. }
  435. return $returnval;
  436. }
  437. // LOGIN()
  438. //
  439. // logs the user in by setting a cookie
  440. // the cookie data is the user's planwatch fingerprint
  441. //------------------------------------------------------------------------------
  442. function login($user,$pass,$remember=0,$prevpage='/',$newuser=FALSE)
  443. {
  444. // only go further if the user exists and has given us a valid password
  445. if (file_exists("$_SERVER[PWUSERS_DIR]/$user/userinfo.dat") && user_is_valid($user,$pass))
  446. {
  447. parse_str(user_read_info($user));
  448. // sets the expiry of the cookie to 3 hours from now, or 5 years
  449. if ($remember) $time=time()+(86400*365*5);
  450. else $time=0;
  451. $cookie_name=$_SERVER['AUTH_COOKIE'];
  452. $cookie_data=user_get_fingerprint($user,$pass);
  453. $cookie_host=$_SERVER['HTTP_HOST'];
  454. if (substr_count($cookie_host,'.') < 2) $cookie_host=".$cookie_host";
  455. $cookie_host=str_replace('www','',$cookie_host);
  456. setcookie($cookie_name,$cookie_data,$time,$_SERVER['WEB_ROOT']."/",$cookie_host);
  457. setcookie('remember',"remember=$remember",time()+86400*365*5,$_SERVER['WEB_ROOT']."/",$cookie_host);
  458. if ($prevpage===FALSE) { $prevpage='/'; }
  459. Header("Location: http://$_SERVER[HTTP_HOST]$_SERVER[WEB_ROOT]/scripts/cookie-test.php?fingerprint_v4=$cookie_data&newuser=$newuser&redirect_page=$prevpage");
  460. }
  461. else
  462. {
  463. redirect("/failed");
  464. /* echo "<div class='alert'><h1>Login failed for $user.</h1> Double check the username and password you provided, and try again. If you keep getting this message and you shouldn't, email <a href='mailto:help@planwatch.org'>help@planwatch.org</a></div>
  465. <form action='/scripts/form_shim.php' method='post' name='loginForm'>
  466. user <input id='login_username' type='text' name='user' size='10' />
  467. pass <input id='login_userpass' type='password' name='pass' size='6' />
  468. <input type='checkbox' name='remember' id='remember' value='1' />
  469. <label for='remember'>remember me</label>
  470. <input type='hidden' name='action' value='login'/>
  471. <input type='submit' name='action' value='login' onclick='document.forms.loginForm.submit();' />
  472. <input type='hidden' name='prevpage' value=''/>
  473. </form>"*/
  474. }
  475. }
  476. // LOGOUT()
  477. //
  478. // logs the user out by clearing cookie values
  479. //------------------------------------------------------------------------------
  480. function logout($message=FALSE)
  481. {
  482. $cookie_names[]=$_SERVER['AUTH_COOKIE'];
  483. $cookie_names[]="mau";
  484. $cookie_names[]="remember";
  485. $cookie_data=FALSE;
  486. $time=time()-1;
  487. $cookie_host=$_SERVER['HTTP_HOST'];
  488. if (substr_count($cookie_host,'.') < 2) $cookie_host=".$cookie_host";
  489. $cookie_host_base=str_replace('www','',$cookie_host);
  490. foreach($cookie_names as $cookie_name)
  491. {
  492. setcookie ($cookie_name,$cookie_data,$time,$_SERVER['WEB_ROOT']."/",$cookie_host);
  493. setcookie ($cookie_name,$cookie_data,$time,$_SERVER['WEB_ROOT']."/",$cookie_host_base);
  494. }
  495. if (!$message) redirect('/');
  496. else redirect("/alert/".urlencode($message));
  497. }
  498. // profile_display()
  499. //
  500. // builds a profile of how much time various functions take
  501. //------------------------------------------------------------------------------
  502. function profile_display()
  503. {
  504. $indent_level=0;
  505. $loadtime=$_SERVER['STOPWATCH']['pageload_end']-$_SERVER['STOPWATCH']['pageload_begin'];
  506. foreach($_SERVER['STOPWATCH'] as $key=>$value)
  507. {
  508. if (strpos($key,'begin'))
  509. {
  510. for($i=0;$i<$indent_level;$i++) $indent.="&nbsp;&nbsp;&nbsp;&nbsp;";
  511. $basekey=str_replace('_begin','',$key);
  512. $indent_level+=1;
  513. if (is_numeric($_SERVER['STOPWATCH'][$basekey."_end"]))
  514. {
  515. $difference=round($_SERVER['STOPWATCH'][$basekey."_end"]-$_SERVER['STOPWATCH'][$basekey."_begin"],5);
  516. $outstring="$indent $basekey: $difference";
  517. if (strpos($key,'!')===FALSE)
  518. {
  519. if ($difference >= ($loadtime*.3)) $outstring="<strong>$outstring</strong><br/>";
  520. if ($difference <= ($loadtime*.1)) $outstring="<span class='edit_links'>$outstring</span><br/>";
  521. if ($difference <= ($loadtime*.05)) $outstring="<span class='edit_links'>$outstring</span><br/>";//$outstring="";
  522. if ($difference > ($loadtime*.1) && $difference < ($loadtime*.3))
  523. { $outstring=$outstring."<br/>"; }
  524. }
  525. else { $outstring=$outstring."<br/>"; }
  526. $stopwatch_content.=$outstring;
  527. $indent="";
  528. }
  529. }
  530. if (strpos($key,'end')) $indent_level-=1;
  531. }
  532. return $stopwatch_content;
  533. }
  534. // browser_is_modern()
  535. //
  536. // makes sure the browser can take the good template
  537. //------------------------------------------------------------------------------
  538. function browser_is_modern()
  539. {
  540. $modern=FALSE;
  541. // This gets us Konqeror, Safari, Mozilla & Firefox, Camino
  542. if (stristr($_SERVER['HTTP_USER_AGENT'],'gecko')) $modern=TRUE;
  543. if (stristr($_SERVER['HTTP_USER_AGENT'],'webkit')) $modern=TRUE;
  544. // This gets us MSIE versions with non-awful CSS and JS support
  545. if (stristr($_SERVER['HTTP_USER_AGENT'],'MSIE 5')) $modern=TRUE;
  546. if (stristr($_SERVER['HTTP_USER_AGENT'],'MSIE 6')) $modern=TRUE;
  547. if (stristr($_SERVER['HTTP_USER_AGENT'],'MSIE 7')) $modern=TRUE;
  548. if (stristr($_SERVER['HTTP_USER_AGENT'],'MSIE 8')) $modern=TRUE;
  549. // This gets us Opera versions with non-awful CS and JS support
  550. if (stristr($_SERVER['HTTP_USER_AGENT'],'Opera/7')) $modern=TRUE;
  551. if (stristr($_SERVER['HTTP_USER_AGENT'],'Opera/8')) $modern=TRUE;
  552. if (stristr($_SERVER['HTTP_USER_AGENT'],'Opera/9')) $modern=TRUE;
  553. if (stristr($_SERVER['HTTP_USER_AGENT'],'Opera/10')) $modern=TRUE;
  554. if (stristr($_SERVER['HTTP_USER_AGENT'],'Opera/11')) $modern=TRUE;
  555. // if ($_SERVER['USER']=='jwdavidson') echo $_SERVER['HTTP_USER_AGENT'];
  556. return $modern;
  557. }
  558. function hyperlink($string) {
  559. // $string = preg_replace("#\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>#i","<a href='\\1'>\\1</a>",$string);
  560. $string = preg_replace("#([\s\(\)])[^'\"]*(https?|ftp|news){1}://([\w\-]+\.([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^\"\s\(\)<\[]*)?)#ie", '\'$1\'.handle_url_tag(\'$2://$3\')', $string);
  561. $string = preg_replace("#([\s\(\)])(www|ftp)\.(([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^\"\s\(\)<\[]*)?)#ie", '\'$1\'.handle_url_tag(\'$2.$3\', \'$2.$3\')', $string);
  562. return $string;
  563. }
  564. function handle_url_tag($url, $link='') {
  565. $full_url = str_replace(array(' ', '\'', '`', '"'), array('%20', '', '', ''), $url);
  566. if (strpos($url, 'www.') === 0) { $full_url = 'http://'.$full_url; }
  567. else if (strpos($url, 'ftp.') === 0) { $full_url = 'ftp://'.$full_url; }
  568. else if (!preg_match('#^([a-z0-9]{3,6})://#', $url, $bah)) { $full_url = 'http://'.$full_url; }
  569. $link = ($link == '' || $link == $url) ? ((strlen($url) > 55) ? substr($url, 0 , 39).' &hellip; '.substr($url, -10) : $url) : stripslashes($link);
  570. return '<a href="'.$full_url.'">'.$link.'</a>';
  571. }
  572. function strip_whitespace($page)
  573. {
  574. $page=str_replace(array(' =','= '),'=',$page);
  575. $page=str_replace(array(" !",", "),array("!",","),$page);
  576. $page=str_replace('{ ','{',$page);
  577. $page=str_replace(' }','}',$page);
  578. $page=preg_replace('|[\s\r]//.*|','',$page);
  579. $page=preg_replace('/[ \r\n\t]/',' ',$page);
  580. $page=preg_replace('/\s\s+/',' ',$page);
  581. $page=preg_replace('/\<![�\r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[�\r\n\t]*)\>/','',$page);
  582. return $page;
  583. }
  584. ?>