| [ PHPXref.com ] | [ Generated: Sun Jul 20 18:58:57 2008 ] | [ NextBBS 0.4.4 ] |
| [ Index ] [ Variables ] [ Functions ] [ Classes ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
1 <?php // common.php 2 /* 3 The Next BBS - Forums Software 4 Copyright (C) 2006 Chris F. Ravenscroft 5 6 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 7 8 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 9 10 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 11 12 Questions? We can be reached at http://forums.sf.net 13 */ 14 15 require_once "tidbit.php"; 16 17 class Common 18 { 19 var $perf_startat; 20 var $crumbs; 21 var $pagetitle; 22 var $SID; 23 var $total_members; 24 var $total_guests; 25 var $total_bots; 26 var $newestuser_id; 27 var $newestuser_name; 28 var $total_accounts; 29 var $total_posts; 30 var $neighbours; 31 32 var $cache; 33 var $base_url; 34 var $bSkinOK; 35 var $skinOverride = -1; 36 37 var $OVERRIDE_ACLS = 1; 38 var $EDIT_POST = 2; 39 var $DELETE_POST = 4; 40 var $MOVE_TOPIC = 8; 41 var $SPLIT_TOPIC = 16; 42 var $MERGE_TOPICS = 32; 43 var $CLOSE_TOPIC = 64; 44 var $PIN_TOPIC = 128; 45 46 var $POST_NEW = 1; 47 var $POST_REPLY = 2; 48 var $POST_EDIT = 3; 49 50 var $ACTION_PM = 1; 51 var $ACTION_AIM = 2; 52 var $ACTION_MSN = 3; 53 var $ACTION_YIM = 4; 54 var $ACTION_ICQ = 5; 55 var $ACTION_WWW = 6; 56 57 var $MCGET = 1; 58 var $MCSET = 2; 59 var $MCADD = 3; 60 var $MCREP = 4; 61 var $MCDEL = 5; 62 63 function Common() 64 { 65 $this->perf_startat = $this->microtime_float(); 66 $this->total_members = $this->total_guests = $this->total_bots = 0; 67 $this->cache = array(); 68 $this->base_url = null; 69 $this->bSkinOK = null; 70 } 71 72 function microtime_float() 73 { 74 // *nix only 75 if(function_exists('getrusage')) 76 { 77 $used = getrusage(); 78 return ( 79 (($used['ru_utime.tv_usec'])+ 80 ($used['ru_stime.tv_usec']))/ 81 1000000); 82 } 83 // less accurate fallback 84 list($usec, $sec) = explode(" ", microtime()); 85 return ((float)$usec + (float)$sec); 86 } 87 88 /** 89 * Return how long it took to parse this page 90 * @return String time elapsed, formatted 91 */ 92 function howLong() 93 { 94 return sprintf("%1.2f", ($this->microtime_float() - $this->perf_startat)); 95 } 96 97 /** 98 * Return how long it took to run all database queries 99 * @return String time used, formatted 100 */ 101 function howLongDB() 102 { 103 global $DB, $CONFIG; 104 105 if($CONFIG->debuglevel>=2) 106 return sprintf(" (Queries: %1.2f)", $DB->getTotalTime()); 107 else 108 return ""; 109 } 110 111 function now() 112 { 113 return time(); 114 } 115 116 /** 117 * Display an error message and lets the user go back... 118 */ 119 function error($msg, $memorize=true) 120 { 121 global $INPUT; 122 123 $title = "Error"; 124 $subtext = '<input type="submit" name="ErrorSubmit" value="Go Back"></form>'; 125 126 $referer = &$_SERVER['HTTP_REFERER']; 127 128 $extra = '<form action="'.$referer.'" method="post">'; 129 130 if($memorize) 131 { 132 // First, let's make sure that the referer string is always right 133 $ref = array(); 134 $sides = explode('?', $referer); 135 if(count($sides)>1) 136 { 137 $blocks = explode('&', $sides[1]); 138 foreach($blocks as $block) 139 { 140 $parts = explode('=', $block); 141 if(count($parts)>1) 142 { 143 $ref[$parts[0]] = $parts[1]; 144 } 145 } 146 } 147 // 148 foreach($INPUT as $key => $value) 149 { 150 if($key=='do' || $key=='w' || $key=='act' || 0 == strncmp('submit', $key, 6) || isset($ref[$key])) 151 continue; 152 153 $extra .= '<input type="hidden" name="'.$key.'" value="'.$value.'">'; 154 } 155 } 156 157 $this->intermediate($title, $msg, $subtext, $extra); 158 exit; // Just to be sure... 159 } 160 161 /** 162 * Log hack attempt and die 163 */ 164 function hacker($msg,$logkey="unknown",$action="unknown" ) 165 { 166 global $LOG; 167 168 $this->loganddie($msg, $logkey, $action, $LOG->HACK_LEVEL); 169 } 170 171 /** 172 * Log, report and die. Baaad! 173 */ 174 function loganddie($msg, $logkey="unknown",$action="unknown",$level=-1) 175 { 176 global $LOG; 177 178 if($level==-1) $level=$LOG->PANIC_LEVEL; 179 $LOG->note($level,$logkey,$action,$msg); 180 $msg = "<div style='border:1px solid #121729;color:blue; background-color:#eeee00; padding:5; margin:5 }'>". 181 $msg. 182 "</div>"; 183 if($level==$LOG->HACK_LEVEL) 184 $msg = "<font color='red'><b>Note: A hack attempt was detected.<br /> 185 It is being logged and reported to the admin along with your IP address:<br /><br /></b>". 186 $msg. 187 "</font>"; 188 die($msg); 189 } 190 191 function dberror() 192 { 193 } 194 195 /** 196 * Do not call directly 197 */ 198 function _getSettingValue($setting_key, $uid=-1) 199 { 200 global $CONFIG, $DB; 201 202 $qry = "SELECT setting_value FROM {$CONFIG->dbprfx}settings 203 WHERE setting_server='{$CONFIG->server}' AND 204 setting_key='{$setting_key}' AND 205 setting_userid='{$uid}'"; 206 $res = $DB->query($qry); 207 if($res->numrows()==1) 208 { 209 $row = $res->fetchRow(DB_FETCHMODE_ASSOC); 210 return $row['setting_value']; 211 } 212 else 213 return null; 214 } 215 /** 216 * Return a setting stored in the database 217 */ 218 function getUserSettingValue($setting_key) 219 { 220 global $USER; 221 222 return $this->_getSettingValue($setting_key, $USER->id); 223 } 224 225 /** 226 * Return a setting stored in the database 227 */ 228 function getGlobalSettingValue($setting_key) 229 { 230 return $this->_getSettingValue($setting_key, -1); 231 } 232 233 /** 234 * Update an existing setting value 235 */ 236 function _updateSettingValue($setting_key, $setting_value, $uid=-1) 237 { 238 global $CONFIG, $DB; 239 240 $qry = "UPDATE {$CONFIG->dbprfx}settings 241 SET setting_value='{$setting_value}' 242 WHERE setting_server='{$CONFIG->server}' AND 243 setting_key='{$setting_key}' AND 244 setting_userid='{$uid}'"; 245 $DB->query($qry); 246 } 247 248 function updateUserSettingValue($setting_key, $setting_value) 249 { 250 global $USER; 251 252 $this->_updateSettingValue($setting_key, $setting_value, $USER->id); 253 } 254 255 function updateGlobalSettingValue($setting_key, $setting_value) 256 { 257 $this->_updateSettingValue($setting_key, $setting_value, -1); 258 } 259 260 /** 261 * @TODO Important: this method should be called when saving a user, not when accessing posts!! 262 */ 263 function getUserTitle($posts) 264 { 265 global $COMMON, $USER; 266 267 if($USER->title!='') 268 { 269 // User Custom Title! 270 return $USER->title; 271 } 272 273 if(!isset($this->usertitles)) 274 { 275 $this->usertitles = unserialize(base64_decode($COMMON->getGlobalSettingValue('user_titles'))); 276 if(empty($this->usertitles)) 277 $this->usertitles = array(); 278 ksort($this->usertitles); 279 } 280 281 $lasttitle = ''; 282 foreach($this->usertitles as $u_posts => $u_values) 283 { 284 if($u_posts > $posts) 285 break; 286 $lasttitle = $u_values['customtitle']; 287 } 288 return $lasttitle; 289 } 290 291 /** 292 * Return a date formatted for display; short format. 293 * @param dateValue long: time in ms 294 * @return String formatted date 295 */ 296 function formatDate($dateValue,$customFormat="M j, Y, g:i a") 297 { 298 global $CONFIG, $USER; 299 // First, adjust date 300 $offset = ($USER->timezone - $CONFIG->board->timezone) * 60; 301 $dateValue += $offset; 302 // 303 return date($customFormat, $dateValue); 304 } 305 306 /** 307 * Return a user name with a hyperlink to its info page if available 308 */ 309 function formatUserName($userid,$userName,$displayPrefix='',$displaySuffix='') 310 { 311 if($userid==-1) 312 return $userName; 313 else 314 return "<a href='?do=profile&id={$userid}'>{$displayPrefix}{$userName}{$displaySuffix}</a>"; 315 } 316 317 /** 318 * Return a properly formatted action 319 */ 320 function formatAction($action_id, $action_arg, $textInfo=null) 321 { 322 if($action_arg=='') 323 return; 324 325 switch($action_id) 326 { 327 case $this->ACTION_PM: 328 $ret = "<a href='?do=handlemsg&act=msg&MessageRecipient=".$action_arg."'>".($textInfo==null?"<img src='".$this->getSkinIncludesDirectory()."/p_pm.gif'>":$action_arg)."</a>"; 329 break; 330 case $this->ACTION_WWW: 331 $ret = "<a href='http://".$action_arg."' target='_blank'>".($textInfo==null?"<img src='".$this->getSkinIncludesDirectory()."/p_www.gif'>":$textInfo['in_www'])."</a>"; 332 break; 333 case $this->ACTION_AIM: 334 $ret = "<a href=\"javascript: openWindow('index.php?do=delegator&no2buf=true&action=messenger&type=aim&user=".$action_arg."',156,224);\">".($textInfo==null?"<img src='".$this->getSkinIncludesDirectory()."/p_aim.gif'>":$textInfo['in_aim'])."</a>"; 335 break; 336 case $this->ACTION_MSN: 337 $ret = "<a href=\"javascript: openWindow('index.php?do=delegator&no2buf=true&action=messenger&type=msn&user=".$action_arg."',156,224);\">".($textInfo==null?"<img src='".$this->getSkinIncludesDirectory()."/p_msn.gif'>":$textInfo['in_msn'])."</a>"; 338 break; 339 case $this->ACTION_YIM: 340 $ret = "<a href=\"javascript: openWindow('index.php?do=delegator&no2buf=true&action=messenger&type=yahoo&user=".$action_arg."',156,224);\">".($textInfo==null?"<img src='".$this->getSkinIncludesDirectory()."/p_yim.gif'>":$textInfo['in_yahoo'])."</a>"; 341 break; 342 case $this->ACTION_ICQ: 343 $ret = "<a href=\"javascript: openWindow('index.php?do=delegator&no2buf=true&action=messenger&type=icq&user=".$action_arg."',320,160);\">".($textInfo==null?"<img src='".$this->getSkinIncludesDirectory()."/p_icq.gif'>":$textInfo['in_icq'])."</a>"; 344 break; 345 } 346 return $ret; 347 } 348 349 /** 350 * Return a properly formatted ip address 351 */ 352 function formatIP($ip_address) 353 { 354 $ret = '<a href="http://ws.arin.net/whois?queryinput='.$ip_address.'" target="_blank">'.$ip_address.'</a>'; 355 return $ret; 356 } 357 358 /** 359 * Return a properly formatted user agent string 360 */ 361 function formatAgent($user_agent) 362 { 363 $ret = $user_agent; 364 return $ret; 365 } 366 367 /** 368 * Return URL of the script currently being executed 369 */ 370 function getURL() 371 { 372 // Assumption: no SSL 373 return "http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']; 374 } 375 376 /** 377 * Return URL of the script currently being executed and its parameters 378 */ 379 function getExtendedURL() 380 { 381 // Assumption: no SSL 382 return $this->getURL().'?'.$_SERVER['argv'][0]; 383 } 384 385 /** 386 * Return URL of the script currently being executed without the filename 387 */ 388 function getBaseURL() 389 { 390 global $CONFIG; 391 392 if($this->base_url==null) 393 { 394 $this->base_url = $this->getURL(); 395 if($CONFIG->board->rewrite=="true") 396 { 397 $p = strpos($this->base_url, "/do"); 398 if($p!==false) 399 { 400 $this->base_url = substr($this->base_url, 0, $p-1); 401 } 402 } 403 $p = strrpos($this->base_url, "/"); 404 if($p!==false) 405 $this->base_url = substr($this->base_url, 0, $p).'/'; 406 } 407 return $this->base_url; 408 } 409 410 /** 411 * Check whether an ip address belongs to a subnet 412 * @param subnet String: an IP address in that subnet - may be: 'ip' or an ip with a classless mask: 'ip/xx' 413 * @param ip String: the IP address we are curious about 414 * @return boolean true if it belongs 415 */ 416 function isSubnet($subnet, $ip) 417 { 418 // Classless (in more than one way) comparison 419 $cursubnet = explode('/', $subnet); 420 $longsubnet = ip2long($cursubnet[0]); 421 $longip = ip2long($ip); 422 423 if(count($cursubnet)<2) 424 { 425 // Compare IP itself 426 return ($longip==$longsubnet); 427 } 428 429 // IPv4 only! 430 $subnetmask = 0xffffffff << (32-$cursubnet[1]); 431 return (($longip & $subnetmask) == ($longsubnet & $subnetmask)); 432 } 433 434 435 /** 436 * Check whether the current user is a spider, such as Google's 437 */ 438 function checkSpider($ip, $agent='') 439 { 440 global $COMMON, $CONFIG, $USER; 441 442 $spiders_ranges = array( 443 '72.36.171.210' => 'Militate Spider', 444 '66.249.64.0/19' => 'Google Spider', 445 '64.124.85.0/24' => 'Become Spider', 446 '65.54.188.0/24' => 'Msn Spider', 447 '66.228.160.0/19 ' => 'Overture Spider', 448 '207.248.240.118/19' => 'Alestra Spider', 449 '69.28.242.87' => 'Stupid Spam Bot', 450 '64.193.62.232' => 'Some Bot (Skiplink)', 451 '66.246.120.114' => 'Some Bot (NAT)', 452 '65.254.35.10' => 'Some Bot (GNAX)', 453 '69.73.166.108' => 'Some Bot (Nocdirect)', 454 '148.244.150.52' => 'Some South American Bot', 455 '64.242.88.10/24' => 'Looksmart Spider', 456 '68.142.192.0/18' => 'Inktomi Spider', 457 '72.30.0.0/16' => 'Inktomi Spider', 458 '64.124.122.224/27' => 'Rufus Bot', 459 '202.108.22.78' => 'Baidu Spider', 460 '151.138.18.44' => 'Superpages Spider', 461 '65.214.44.143' => 'Ask Jeeves Spider', 462 '66.154.103.125' => 'GigaBot', 463 '210.173.180.166' => 'Ichiro Spider', 464 '64.34.145.197' => 'SiteSell Spider', 465 ); 466 467 foreach($spiders_ranges as $spider_range => $spider_name) 468 { 469 if($COMMON->isSubnet($spider_range, $ip)) 470 { 471 return $spider_name; 472 } 473 } 474 475 // Not found any? What if it's a new IP range? We could use their user agent too... 476 // Of course, it could be empty... 477 if(empty($agent)) 478 return 'Unknown bot'; 479 // NOTE: This is a *very rough* implementation 480 if($CONFIG->spiders->agent=='true') 481 { 482 require 'helpers/user_agents.php'; 483 // Extract browser string...yeah, right 484 preg_match('/([0-9a-zA-Z]+)/', $agent, $browserName); 485 if(in_array($browserName, $spiders_agents)) 486 return $browserName; 487 } 488 489 // OK OK...well, maybe it's unknown but it's user agent gave it away anyway? 490 if($agent=='Spider') 491 { 492 return 'Unknown Bot'; 493 } 494 495 return null; 496 } 497 498 /** 499 * Test if an IP address is banned 500 * @param ipaddress a string: ip address to test 501 * @return boolean true if banned 502 */ 503 function isBanned($ipaddress) 504 { 505 global $CONFIG, $USER; 506 507 if($USER->isAdmin()) 508 return false; 509 510 // Of course, we first need to ensure that you were not suspended... 511 if($USER->suspended > 0) 512 return true; 513 514 $userip = ip2long($ipaddress); 515 $banips = explode("\n", $CONFIG->ban->ips); 516 foreach ($banips as $banip) 517 { 518 if($this->isSubnet($banip, $userip)) 519 return true; 520 } 521 return false; 522 } 523 524 /** 525 * Check whether the board is offline and that is relevant to the user 526 * @return boolean true if board is offline 527 */ 528 function isBoardOffline() 529 { 530 global $CONFIG, $USER; 531 532 if($USER->isAdmin()) 533 return false; 534 535 if($CONFIG->boardonoff->onoff=='off') 536 return true; 537 } 538 539 /** 540 * Display a redirect page then send the user to wherever... 541 * @param page a string: what the software expects after '?do=' / 'null' means 'hard redirect' 542 * @param page a string: text to be displayed 543 * @param delay how many seconds shall we wait? '-1' means 'use config. default' 544 */ 545 function redirect($page, $text, $delay=-1) 546 { 547 global $TEMPLATE, $LANG, $CONFIG; 548 549 if($page==null) 550 { 551 if($CONFIG->board->rewrite=="true") 552 { 553 if(!strncmp($text, 'admin', 5)) 554 { 555 $hdr = $this->getURL().'?act='.$text; 556 } 557 else 558 { 559 $hdr = str_replace( 560 array('&', '='), 561 array('_', '_'), 562 str_replace( 563 'index.php', 564 '', 565 $this->getBaseURL()).'do='.$text); 566 } 567 } 568 else 569 { 570 $hdr = $this->getURL().'?do='.$text; 571 } 572 573 Header("Location: ".$hdr); 574 exit; 575 } 576 577 if($delay==-1) 578 $delay = $CONFIG->redirect->delay; 579 $TEMPLATE->assign("includes", $this->getSkinIncludesDirectory()); 580 $TEMPLATE->assign("glang", $LANG->globalAccessor()); 581 $TEMPLATE->assign("text", $text); 582