[ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements the Hit class. 4 * 5 * This file is part of the evoCore framework - {@link http://evocore.net/} 6 * See also {@link http://sourceforge.net/projects/evocms/}. 7 * 8 * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/} 9 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}. 10 * 11 * {@internal License choice 12 * - If you have received this file as part of a package, please find the license.txt file in 13 * the same folder or the closest folder above for complete license terms. 14 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/) 15 * then you must choose one of the following licenses before using the file: 16 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php 17 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php 18 * }} 19 * 20 * {@internal Open Source relicensing agreement: 21 * Daniel HAHLER grants Francois PLANQUE the right to license 22 * Daniel HAHLER's contributions to this file and the b2evolution project 23 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 24 * }} 25 * 26 * @package evocore 27 * 28 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 29 * @author blueyed: Daniel HAHLER. 30 * @author fplanque: Francois PLANQUE. 31 * 32 * @version $Id: _hit.class.php,v 1.3 2007/09/18 00:00:59 fplanque Exp $ 33 * 34 */ 35 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 36 37 38 /** 39 * A hit to a blog. 40 * 41 * NOTE: The internal function double_check_referer() uses the class Net_IDNA_php4 from /blogs/lib/_idna_convert.class.php. 42 * It's required() only, when needed. 43 * @package evocore 44 */ 45 class Hit 46 { 47 /** 48 * ID in DB, gets set when {@link log()} was called and the hit was logged. 49 */ 50 var $ID; 51 52 /** 53 * Is the hit already logged? 54 * @var boolean 55 */ 56 var $logged = false; 57 58 /** 59 * The referer/referrer. 60 * 61 * @var string 62 */ 63 var $referer; 64 65 /** 66 * The type of referer. 67 * 68 * Note: "spam" referers do not get logged. 69 * 'search'|'blacklist'|'referer'|'direct'|'spam' 70 * 71 * @var string 72 */ 73 var $referer_type; 74 75 /** 76 * The ID of the referer's base domain in T_basedomains 77 * 78 * @var integer 79 */ 80 var $referer_domain_ID; 81 82 /** 83 * Is this a reload? 84 * This gets lazy-filled by {@link is_new_view()}. 85 * @var boolean 86 * @access protected 87 */ 88 var $_is_new_view; 89 90 /** 91 * Ignore this hit? 92 * @var boolean 93 */ 94 var $ignore = false; 95 96 /** 97 * Remote address (IP). 98 * @var string 99 */ 100 var $IP; 101 102 /** 103 * The user agent. 104 * @var string 105 */ 106 var $user_agent; 107 108 /** 109 * The user agent name, eg "safari" 110 * @var string 111 */ 112 var $agent_name; 113 114 /** 115 * The user agent platform, eg "mac" 116 * @var string 117 */ 118 var $agent_platform; 119 120 /**#@+ 121 * Detected browser. 122 * 123 * @var integer 124 */ 125 var $is_lynx = false; 126 var $is_firefox = false; 127 var $is_gecko = false; 128 var $is_winIE = false; 129 var $is_macIE = false; 130 var $is_safari = false; 131 var $is_opera = false; 132 var $is_NS4 = false; 133 /**#@-*/ 134 135 136 /** 137 * The user's remote host. 138 * Use {@link get_remote_host()} to access it (lazy filled). 139 * @var string 140 * @access protected 141 */ 142 var $_remoteHost; 143 144 /** 145 * The user agent type. 146 * 147 * The default setting ('unknown') is taken for new entries (into T_useragents), 148 * that are not detected as 'rss', 'robot' or 'browser'. 149 * 'rss'|'robot'|'browser'|'unknown' 150 * 151 * @var string 152 */ 153 var $agent_type = 'unknown'; 154 155 /** 156 * The ID of the user agent entry in T_useragents. 157 * @var integer 158 */ 159 var $agent_ID; 160 161 162 163 164 /** 165 * Constructor 166 */ 167 function Hit() 168 { 169 global $Debuglog, $DB; 170 global $comments_allowed_uri_scheme; 171 172 // Get the first IP in the list of REMOTE_ADDR and HTTP_X_FORWARDED_FOR 173 $this->IP = get_ip_list( true ); 174 175 // Check the referer and determine referer_type: 176 $this->detect_referer(); 177 178 // Check if we know the base domain: 179 $this->referer_basedomain = get_base_domain($this->referer); 180 if( $this->referer_basedomain ) 181 { // This referer has a base domain 182 // Check if we have met it before: 183 $hit_basedomain = $DB->get_row( ' 184 SELECT dom_ID 185 FROM T_basedomains 186 WHERE dom_name = '.$DB->quote($this->referer_basedomain) ); 187 if( !empty( $hit_basedomain->dom_ID ) ) 188 { // This basedomain has visited before: 189 $this->referer_domain_ID = $hit_basedomain->dom_ID; 190 // fp> The blacklist handling that was here made no sense. 191 } 192 else 193 { // This is the first time this base domain visits: 194 195 // The INSERT below can fail, probably if we get two simultaneous hits (seen in the demo logfiles) 196 $old_hold_on_error = $DB->halt_on_error; 197 $old_show_errors = $DB->show_errors; 198 $DB->halt_on_error = false; 199 $DB->show_errors = false; 200 201 if( $DB->query( ' 202 INSERT INTO T_basedomains( dom_name ) 203 VALUES( '.$DB->quote($this->referer_basedomain).' )' ) ) 204 { // INSERTed ok: 205 $this->referer_domain_ID = $DB->insert_id; 206 } 207 else 208 { // INSERT failed: see, try to select again (may become/stay NULL) 209 $this->referer_domain_ID = $DB->get_var( ' 210 SELECT dom_ID 211 FROM T_basedomains 212 WHERE dom_name = '.$DB->quote($this->referer_basedomain) ); 213 } 214 215 $DB->halt_on_error = $old_hold_on_error; 216 $DB->show_errors = $old_show_errors; 217 } 218 } 219 220 $this->detect_useragent(); 221 222 223 $Debuglog->add( 'IP: '.$this->IP, 'hit' ); 224 $Debuglog->add( 'UserAgent: '.$this->user_agent, 'hit' ); 225 $Debuglog->add( 'Referer: '.var_export($this->referer, true).'; type='.$this->referer_type, 'hit' ); 226 $Debuglog->add( 'Remote Host: '.$this->get_remote_host( false ), 'hit' ); 227 } 228 229 230 /** 231 * Detect admin page 232 */ 233 function detect_admin_page() 234 { 235 global $Debuglog; 236 237 if( is_admin_page() ) 238 { // We are inside of admin, this supersedes 'direct' access 239 // NOTE: this is not really a referer type but more a hit type 240 $Debuglog->add( 'Referer is admin page.', 'hit' ); 241 $this->referer_type = 'admin'; 242 return true; 243 } 244 return false; 245 } 246 247 248 /** 249 * Detect Referer (sic!). 250 * Due to potential non-thread safety with getenv() (fallback), we'd better do this early. 251 * 252 * referer_type: enum('search', 'blacklist', 'referer', 'direct'); 'spam' gets used internally 253 */ 254 function detect_referer() 255 { 256 global $HTTP_REFERER; // might be set by PHP (give highest priority) 257 global $Debuglog; 258 global $comments_allowed_uri_scheme; // used to validate the Referer 259 global $self_referer_list, $blackList, $search_engines; // used to detect $referer_type 260 global $skins_path; 261 global $Settings; 262 263 if( isset( $HTTP_REFERER ) ) 264 { // Referer provided by PHP: 265 $this->referer = $HTTP_REFERER; 266 } 267 else 268 { 269 if( isset($_SERVER['HTTP_REFERER']) ) 270 { 271 $this->referer = $_SERVER['HTTP_REFERER']; 272 } 273 else 274 { // Fallback method (not thread safe :[[ ) - this function does not work in ISAPI mode. 275 $this->referer = getenv('HTTP_REFERER'); 276 } 277 } 278 279 if( empty($this->referer) ) 280 { // NO referer 281 // This type may be superseeded and set to 'admin' 282 if( ! $this->detect_admin_page() ) 283 { // Not an admin page: 284 $this->referer_type = 'direct'; 285 } 286 return; 287 } 288 289 290 // ANALYZE referer... 291 292 293 // Check self referer list, see {@link $self_referer_list} 294 // fplanque: we log these (again), because if we didn't we woudln't detect 295 // reloads on these... and that would be a problem! 296 foreach( $self_referer_list as $self_referer ) 297 { 298 if( strpos( $this->referer, $self_referer ) !== false ) 299 { 300 // This type may be superseeded by admin page 301 if( ! $this->detect_admin_page() ) 302 { // Not an admin page: 303 $Debuglog->add( 'detect_referer(): self referer ('.$self_referer.')', 'hit' ); 304 $this->referer_type = 'self'; 305 } 306 return; 307 } 308 } 309 310 311 // Check blacklist, see {@link $blackList} 312 // NOTE: This is NOT the antispam!! 313 // fplanque: we log these (again), because if we didn't we woudln't detect 314 // reloads on these... and that would be a problem! 315 foreach( $blackList as $lBlacklist ) 316 { 317 if( strpos( $this->referer, $lBlacklist ) !== false ) 318 { 319 // This type may be superseeded by admin page 320 if( ! $this->detect_admin_page() ) 321 { // Not an admin page: 322 $Debuglog->add( 'detect_referer(): blacklist ('.$lBlacklist.')', 'hit' ); 323 $this->referer_type = 'blacklist'; 324 } 325 return; 326 } 327 } 328 329 330 // Check if the referer is valid and does not match the antispam blacklist: 331 // NOTE: requests to admin pages should not arrive here, because they should be matched above through $self_referer_list! 332 if( $error = validate_url( $this->referer, $comments_allowed_uri_scheme ) ) 333 { // This is most probably referer spam!! 334 $Debuglog->add( 'detect_referer(): '.$error.' (SPAM)', 'hit'); 335 $this->referer_type = 'spam'; 336 337 if( $Settings->get('antispam_block_spam_referers') ) 338 { // In order to preserve server resources, we're going to stop processing immediatly (no logging)!! 339 require $skins_path.'_403_referer_spam.main.php'; // error & exit 340 exit(); // just in case. 341 // THIS IS THE END!! 342 } 343 344 return; // type "spam" 345 } 346 347 348 // Is the referer a search engine? 349 foreach( $search_engines as $lSearchEngine ) 350 { 351 if( stristr($this->referer, $lSearchEngine) ) 352 { 353 $Debuglog->add( 'detect_referer(): search engine ('.$lSearchEngine.')', 'hit' ); 354 $this->referer_type = 'search'; 355 return; 356 } 357 } 358 359 $this->referer_type = 'referer'; 360 } 361 362 363 /** 364 * Set {@link $user_agent} and detect the browser. 365 * This function also handles the relations with T_useragents and sets {@link $agent_type}. 366 */ 367 function detect_useragent() 368 { 369 global $HTTP_USER_AGENT; // might be set by PHP, give highest priority 370 global $DB, $Debuglog; 371 global $user_agents; 372 global $skin; // to detect agent_type (gets set in /xmlsrv/atom.php for example) 373 374 375 if( isset($HTTP_USER_AGENT) ) 376 { 377 $this->user_agent = $HTTP_USER_AGENT; 378 } 379 elseif( isset($_SERVER['HTTP_USER_AGENT']) ) 380 { 381 $this->user_agent = $_SERVER['HTTP_USER_AGENT']; 382 } 383 384 if( !empty($this->user_agent) ) 385 { // detect browser 386 if(strpos($this->user_agent, 'Lynx') !== false) 387 { 388 $this->is_lynx = 1; 389 $this->agent_name = 'lynx'; 390 $this->agent_type = 'browser'; 391 } 392 elseif(strpos($this->user_agent, 'Firefox/') !== false) 393 { 394 $this->is_firefox = 1; 395 $this->agent_name = 'firefox'; 396 $this->agent_type = 'browser'; 397 } 398 elseif(strpos($this->user_agent, 'Gecko/') !== false) // We don't want to see Safari as Gecko 399 { 400 $this->is_gecko = 1; 401 $this->agent_name = 'gecko'; 402 $this->agent_type = 'browser'; 403 } 404 elseif(strpos($this->user_agent, 'MSIE') !== false && strpos($this->user_agent, 'Win') !== false) 405 { 406 $this->is_winIE = 1; 407 $this->agent_name = 'msie'; 408 $this->agent_type = 'browser'; 409 } 410 elseif(strpos($this->user_agent, 'MSIE') !== false && strpos($this->user_agent, 'Mac') !== false) 411 { 412 $this->is_macIE = 1; 413 $this->agent_name = 'msie'; 414 $this->agent_type = 'browser'; 415 } 416 elseif(strpos($this->user_agent, 'Safari/') !== false) 417 { 418 $this->is_safari = true; 419 $this->agent_name = 'safari'; 420 $this->agent_type = 'browser'; 421 } 422 elseif(strpos($this->user_agent, 'Opera') !== false) 423 { 424 $this->is_opera = 1; 425 $this->agent_name = 'opera'; 426 $this->agent_type = 'browser'; 427 } 428 elseif(strpos($this->user_agent, 'Nav') !== false || preg_match('/Mozilla\/4\./', $this->user_agent)) 429 { 430 $this->is_NS4 = 1; 431 $this->agent_name = 'nav4'; 432 $this->agent_type = 'browser'; 433 } 434 435 if( strpos($this->user_agent, 'Win') !== false) 436 { 437 $this->agent_platform = 'win'; 438 } 439 elseif( strpos($this->user_agent, 'Mac') !== false) 440 { 441 $this->agent_platform = 'mac'; 442 } 443 444 445 if( $this->user_agent != strip_tags($this->user_agent) ) 446 { // then they have tried something funky, putting HTML or PHP into the user agent 447 $Debuglog->add( 'detect_useragent(): '.T_('bad char in User Agent'), 'hit'); 448 $this->agent_name = ''; 449 $this->agent_platform = ''; 450 $this->user_agent = ''; 451 } 452 } 453 $this->is_IE = (($this->is_macIE) || ($this->is_winIE)); 454 455 $Debuglog->add( 'Agent name: '.$this->agent_name, 'hit' ); 456 $Debuglog->add( 'Agent platform: '.$this->agent_platform, 'hit' ); 457 458 459 /* 460 * Detect requests for XML feeds by $skin / $tempskin param. 461 * fp> TODO: this is WEAK! Do we really need to know before going into the skin? 462 * dh> not necessary, but only where ->agent_type gets used (logging). 463 * Use $skin, if not empty (may be set in /xmlsrv/atom.php for example), otherwise $tempskin. 464 */ 465 $used_skin = empty( $skin ) ? param( 'tempskin', 'string', '', true ) : $skin; 466 if( in_array( $used_skin, array( '_atom', '_rdf', '_rss', '_rss2' ) ) ) 467 { 468 $Debuglog->add( 'detect_useragent(): RSS', 'hit' ); 469 $this->agent_type = 'rss'; 470 } 471 else 472 { // Lookup robots 473 foreach( $user_agents as $lUserAgent ) 474 { 475 if( ($lUserAgent[0] == 'robot') && (strstr($this->user_agent, $lUserAgent[1])) ) 476 { 477 $Debuglog->add( 'detect_useragent(): robot', 'hit' ); 478 $this->agent_type = 'robot'; 479 } 480 } 481 } 482 483 484 if( $agnt_data = $DB->get_row( " 485 SELECT agnt_ID FROM T_useragents 486 WHERE agnt_signature = '".$DB->escape( $this->user_agent )."' 487 AND agnt_type = '".$this->agent_type."'" ) ) 488 { // this agent (with that type) hit us once before, re-use ID 489 $this->agent_ID = $agnt_data->agnt_ID; 490 } 491 else 492 { // create new user agent entry 493 $DB->query( " 494 INSERT INTO T_useragents ( agnt_signature, agnt_type ) 495 VALUES ( '".$DB->escape( $this->user_agent )."', '".$this->agent_type."' )" ); 496 497 $this->agent_ID = $DB->insert_id; 498 } 499 } 500 501 502 /** 503 * Log a hit on a blog page / rss feed. 504 * 505 * This function should be called at the end of the page, otherwise if the page 506 * is displaying previous hits, it may display the current one too. 507 * 508 * The hit will not be logged in special occasions, see {@link $ignore} and {@link is_good_hit()}. 509 * 510 * It will call {@link Hitlist::dbprune()} to do the automatic pruning of old hits in case 511 * of auto_prune_stats_mode == "page". 512 * 513 * @return boolean true if the hit gets logged; false if not 514 */ 515 function log() 516 { 517 global $Settings, $Plugins, $Debuglog, $is_admin_page; 518 519 if( $this->logged ) 520 { // Already logged 521 return false; 522 } 523 524 // Remember we have already attempted to log: 525 $this->logged = true; 526 527 // Auto pruning: 528 // We need to do this now because even if we don't log anything, we stil need to prune old sessions. 529 530 if( $Settings->get( 'auto_prune_stats_mode' ) == 'page' ) 531 { // Autopruning is requested 532 load_class('sessions/model/_hitlist.class.php'); 533 Hitlist::dbprune(); // will prune once per day, according to Settings 534 } 535 536 // Real logging: 537 538 if( $is_admin_page && ! $Settings->get('log_admin_hits') ) 539 { // We don't want to log admin hits: 540 return false; 541 } 542 543 if( ! $is_admin_page && ! $Settings->get('log_public_hits') ) 544 { // We don't want to log public hits: 545 return false; 546 } 547 548 if( $this->ignore || ! $this->is_good_hit() ) 549 { // We don't want to log this hit! 550 $hit_info = 'referer_type: '.var_export($this->referer_type, true) 551 .', agent_type: '.var_export($this->agent_type, true) 552 #.', is'.( $this->is_new_view() ? '' : ' NOT' ).' a new view' 553 .', is'.( $this->ignore ? '' : ' NOT' ).' ignored' 554 .', is'.( $this->is_good_hit() ? '' : ' NOT' ).' a good hit'; 555 $Debuglog->add( 'log(): Hit NOT logged, ('.$hit_info.')', 'hit' ); 556 return false; 557 } 558 559 if( ! $Plugins->trigger_event_first_true('AppendHitLog', array( 'Hit' => &$this ) ) // No plugin wants to handle recording 560 && $this->is_good_hit() // A plugin might have changed the referer_type 561 ) 562 { // Record it here: 563 $this->record_the_hit(); 564 } 565 566 return true; 567 } 568 569 570 /** 571 * This records the hit. You should not call this directly, but {@link Hit::log()} instead! 572 * 573 * However, if a Plugin registers the {@link Plugin::AppendHitLog() AppendHitLog event}, it 574 * could be necessary to call this as a shutdown function. 575 */ 576 function record_the_hit() 577 { 578 global $DB, $Session, $ReqURI, $Blog, $localtimenow, $Debuglog; 579 580 $Debuglog->add( 'log(): Recording the hit.', 'hit' ); 581 582 $blog_ID = isset($Blog) ? $Blog->ID : NULL; 583 584 $hit_uri = substr($ReqURI, 0, 250); // VARCHAR(250) and likely to be longer 585 $hit_referer = substr($this->referer, 0, 250); // VARCHAR(250) and likely to be longer 586 587 // insert hit into DB table: 588 $sql = " 589 INSERT INTO T_hitlog( 590 hit_sess_ID, hit_datetime, hit_uri, hit_referer_type, 591 hit_referer, hit_referer_dom_ID, hit_blog_ID, hit_remote_addr, hit_agnt_ID ) 592 VALUES( '".$Session->ID."', FROM_UNIXTIME(".$localtimenow."), '".$DB->escape($hit_uri)."', '".$this->referer_type 593 ."', '".$DB->escape($hit_referer)."', ".$DB->null($this->referer_domain_ID).', '.$DB->null($blog_ID).", '".$DB->escape( $this->IP )."', ".$this->agent_ID.' 594 )'; 595 596 $DB->query( $sql, 'Record the hit' ); 597 $this->ID = $DB->insert_id; 598 } 599 600 601 /** 602 * Get the User agent's signature. 603 * 604 * @return string 605 */ 606 function get_user_agent() 607 { 608 return $this->user_agent; 609 } 610 611 612 /** 613 * Get the remote hostname. 614 * 615 * @return string 616 */ 617 function get_remote_host( $allow_nslookup = false ) 618 { 619 global $Timer; 620 621 $Timer->start( 'Hit::get_remote_host' ); 622 623 if( is_null($this->_remoteHost) ) 624 { 625 if( isset( $_SERVER['REMOTE_HOST'] ) ) 626 { 627 $this->_remoteHost = $_SERVER['REMOTE_HOST']; 628 } 629 elseif( $allow_nslookup ) 630 { // We allowed reverse DNS lookup: 631 // This can be terribly time consuming (4/5 seconds!) when there is no reverse dns available! 632 // This is the case on many intranets and many users' first time installs!!! 633 // Some people end up considering evocore is very slow just because of this line! 634 // This cannot be enabled by default. 635 $this->_remoteHost = @gethostbyaddr($this->IP); 636 } 637 else 638 { 639 $this->_remoteHost = ''; 640 } 641 } 642 643 $Timer->pause( 'Hit::get_remote_host' ); 644 645 return $this->_remoteHost; 646 } 647 648 649 /** 650 * Determine if a hit is a new view (not reloaded, (internally) ignored or from a robot). 651 * 652 * 'Reloaded' means: visited before from the same user (in a session) or from same IP/user_agent in the 653 * last {@link $Settings reloadpage_timeout} seconds. 654 * 655 * This gets queried by the Item objects before incrementing its view count (if the Item gets viewed 656 * in total ({@link $dispmore})). 657 * 658 * @todo fplanque>> if this is only useful to display who's online or view counts, provide option to disable all those resource consuming gadgets. (Those gadgets should be plugins actually, and they should enable this query only if needed) 659 * blueyed>> Move functionality to Plugin (with a hook in Item::content())?! 660 * @return boolean 661 */ 662 function is_new_view() 663 { 664 if( $this->ignore || $this->agent_type == 'robot' ) 665 { 666 return false; 667 } 668 669 if( ! isset($this->_is_new_view) ) 670 { 671 global $current_User; 672 global $DB, $Debuglog, $Settings, $ReqURI, $localtimenow; 673 674 // Restrict to current user if logged in: 675 if( ! empty($current_User->ID) ) 676 { // select by user ID: one user counts really just once. May be even faster than the anonymous query below..!? 677 $sql = " 678 SELECT hit_ID FROM T_hitlog INNER JOIN T_sessions ON hit_sess_ID = sess_ID 679 WHERE sess_user_ID = ".$current_User->ID." 680 AND hit_uri = '".$DB->escape( substr($ReqURI, 0, 250) )."' 681 LIMIT 1"; 682 } 683 else 684 { // select by remote_addr/agnt_signature: 685 $sql = " 686 SELECT hit_ID 687 FROM T_hitlog INNER JOIN T_useragents 688 ON hit_agnt_ID = agnt_ID 689 WHERE hit_datetime > '".date( 'Y-m-d H:i:s', $localtimenow - $Settings->get('reloadpage_timeout') )."' 690 AND hit_remote_addr = ".$DB->quote( $this->IP )." 691 AND hit_uri = '".$DB->escape( substr($ReqURI, 0, 250) )."' 692 AND agnt_signature = ".$DB->quote($this->user_agent)." 693 LIMIT 1"; 694 } 695 if( $DB->get_var( $sql, 0, 0, 'Hit: Check for reload' ) ) 696 { 697 $Debuglog->add( 'No new view!', 'hit' ); 698 $this->_is_new_view = false; // We don't want to log this hit again 699 } 700 else 701 { 702 $this->_is_new_view = true; 703 } 704 } 705 706 return $this->_is_new_view; 707 } 708 709 710 /** 711 * Is this a good hit? This means "no spam". 712 * 713 * @return boolean 714 */ 715 function is_good_hit() 716 { 717 return ( $this->referer_type != 'spam' ); 718 } 719 720 721 /** 722 * Is this a browser reload (F5)? 723 * 724 * @return boolean true on reload, false if not. 725 */ 726 function is_browser_reload() 727 { 728 if( ( isset( $_SERVER['HTTP_CACHE_CONTROL'] ) && strpos( $_SERVER['HTTP_CACHE_CONTROL'], 'max-age=0' ) !== false ) 729 || ( isset( $_SERVER['HTTP_PRAGMA'] ) && $_SERVER['HTTP_PRAGMA'] == 'no-cache' ) ) 730 { // Reload 731 return true; 732 } 733 734 return false; 735 } 736 737 } 738 739 /* 740 * $Log: _hit.class.php,v $ 741 * Revision 1.3 2007/09/18 00:00:59 fplanque 742 * firefox mac specific forms 743 * 744 * Revision 1.2 2007/09/17 02:36:25 fplanque 745 * CSS improvements 746 * 747 * Revision 1.1 2007/06/25 11:00:57 fplanque 748 * MODULES (refactored MVC) 749 * 750 * Revision 1.49 2007/04/27 09:11:37 fplanque 751 * saving "spam" referers again (instead of buggy empty referers) 752 * 753 * Revision 1.48 2007/04/26 00:11:11 fplanque 754 * (c) 2007 755 * 756 * Revision 1.47 2007/03/25 15:07:38 fplanque 757 * multiblog fixes 758 * 759 * Revision 1.46 2007/02/19 13:15:34 waltercruz 760 * Changing double quotes to single quotes in queries 761 * 762 * Revision 1.45 2007/02/06 13:44:05 waltercruz 763 * Changing double quotes to single quotes 764 * 765 * Revision 1.44 2007/02/06 00:03:38 waltercruz 766 * Changing double quotes to single quotes 767 * 768 * Revision 1.43 2006/12/07 23:13:11 fplanque 769 * @var needs to have only one argument: the variable type 770 * Otherwise, I can't code! 771 * 772 * Revision 1.42 2006/11/24 18:27:24 blueyed 773 * Fixed link to b2evo CVS browsing interface in file docblocks 774 * 775 * Revision 1.41 2006/10/07 20:45:11 blueyed 776 * Handle logging with referers longer than 250 chars 777 * 778 * Revision 1.40 2006/10/06 21:54:16 blueyed 779 * Fixed hit_uri handling, especially in strict mode 780 */ 781 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |