[ Index ] |
|
Code source de Joomla 1.0.13 |
1 <?php 2 3 /** 4 * Fast, light and safe Cache Class 5 * 6 * Cache_Lite is a fast, light and safe cache system. It's optimized 7 * for file containers. It is fast and safe (because it uses file 8 * locking and/or anti-corruption tests). 9 * 10 * There are some examples in the 'docs/examples' file 11 * Technical choices are described in the 'docs/technical' file 12 * 13 * A tutorial is available in english at this url : 14 * http://www.pearfr.org/index.php/en/article/cache_lite 15 * (big thanks to Pierre-Alain Joye for the translation) 16 * 17 * The same tutorial is also available in french at this url : 18 * http://www.pearfr.org/index.php/fr/article/cache_lite 19 * 20 * Memory Caching is from an original idea of 21 * Mike BENOIT <ipso@snappymail.ca> 22 * 23 * @package Cache_Lite 24 * @category Caching 25 * @version $Id: Lite.php 3315 2006-04-26 19:43:05Z stingrey $ 26 * @author Fabien MARTY <fab@php.net> 27 */ 28 29 define('CACHE_LITE_ERROR_RETURN', 1); 30 define('CACHE_LITE_ERROR_DIE', 8); 31 32 class Cache_Lite 33 { 34 35 // --- Private properties --- 36 37 /** 38 * Directory where to put the cache files 39 * (make sure to add a trailing slash) 40 * 41 * @var string $_cacheDir 42 */ 43 var $_cacheDir = '/tmp/'; 44 45 /** 46 * Enable / disable caching 47 * 48 * (can be very usefull for the debug of cached scripts) 49 * 50 * @var boolean $_caching 51 */ 52 var $_caching = true; 53 54 /** 55 * Cache lifetime (in seconds) 56 * 57 * @var int $_lifeTime 58 */ 59 var $_lifeTime = 3600; 60 61 /** 62 * Enable / disable fileLocking 63 * 64 * (can avoid cache corruption under bad circumstances) 65 * 66 * @var boolean $_fileLocking 67 */ 68 var $_fileLocking = true; 69 70 /** 71 * Timestamp of the last valid cache 72 * 73 * @var int $_refreshTime 74 */ 75 var $_refreshTime; 76 77 /** 78 * File name (with path) 79 * 80 * @var string $_file 81 */ 82 var $_file; 83 84 /** 85 * Enable / disable write control (the cache is read just after writing to detect corrupt entries) 86 * 87 * Enable write control will lightly slow the cache writing but not the cache reading 88 * Write control can detect some corrupt cache files but maybe it's not a perfect control 89 * 90 * @var boolean $_writeControl 91 */ 92 var $_writeControl = true; 93 94 /** 95 * Enable / disable read control 96 * 97 * If enabled, a control key is embeded in cache file and this key is compared with the one 98 * calculated after the reading. 99 * 100 * @var boolean $_writeControl 101 */ 102 var $_readControl = true; 103 104 /** 105 * Type of read control (only if read control is enabled) 106 * 107 * Available values are : 108 * 'md5' for a md5 hash control (best but slowest) 109 * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice) 110 * 'strlen' for a length only test (fastest) 111 * 112 * @var boolean $_readControlType 113 */ 114 var $_readControlType = 'crc32'; 115 116 /** 117 * Pear error mode (when raiseError is called) 118 * 119 * (see PEAR doc) 120 * 121 * @see setToDebug() 122 * @var int $_pearErrorMode 123 */ 124 var $_pearErrorMode = CACHE_LITE_ERROR_RETURN; 125 126 /** 127 * Current cache id 128 * 129 * @var string $_id 130 */ 131 var $_id; 132 133 /** 134 * Current cache group 135 * 136 * @var string $_group 137 */ 138 var $_group; 139 140 /** 141 * Enable / Disable "Memory Caching" 142 * 143 * NB : There is no lifetime for memory caching ! 144 * 145 * @var boolean $_memoryCaching 146 */ 147 var $_memoryCaching = false; 148 149 /** 150 * Enable / Disable "Only Memory Caching" 151 * (be carefull, memory caching is "beta quality") 152 * 153 * @var boolean $_onlyMemoryCaching 154 */ 155 var $_onlyMemoryCaching = false; 156 157 /** 158 * Memory caching array 159 * 160 * @var array $_memoryCachingArray 161 */ 162 var $_memoryCachingArray = array(); 163 164 /** 165 * Memory caching counter 166 * 167 * @var int $memoryCachingCounter 168 */ 169 var $_memoryCachingCounter = 0; 170 171 /** 172 * Memory caching limit 173 * 174 * @var int $memoryCachingLimit 175 */ 176 var $_memoryCachingLimit = 1000; 177 178 /** 179 * File Name protection 180 * 181 * if set to true, you can use any cache id or group name 182 * if set to false, it can be faster but cache ids and group names 183 * will be used directly in cache file names so be carefull with 184 * special characters... 185 * 186 * @var boolean $fileNameProtection 187 */ 188 var $_fileNameProtection = true; 189 190 /** 191 * Enable / disable automatic serialization 192 * 193 * it can be used to save directly datas which aren't strings 194 * (but it's slower) 195 * 196 * @var boolean $_serialize 197 */ 198 var $_automaticSerialization = false; 199 200 // --- Public methods --- 201 202 /** 203 * Constructor 204 * 205 * $options is an assoc. Available options are : 206 * $options = array( 207 * 'cacheDir' => directory where to put the cache files (string), 208 * 'caching' => enable / disable caching (boolean), 209 * 'lifeTime' => cache lifetime in seconds (int), 210 * 'fileLocking' => enable / disable fileLocking (boolean), 211 * 'writeControl' => enable / disable write control (boolean), 212 * 'readControl' => enable / disable read control (boolean), 213 * 'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string), 214 * 'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int), 215 * 'memoryCaching' => enable / disable memory caching (boolean), 216 * 'onlyMemoryCaching' => enable / disable only memory caching (boolean), 217 * 'memoryCachingLimit' => max nbr of records to store into memory caching (int), 218 * 'fileNameProtection' => enable / disable automatic file name protection (boolean), 219 * 'automaticSerialization' => enable / disable automatic serialization (boolean) 220 * ); 221 * 222 * @param array $options options 223 * @access public 224 */ 225 function Cache_Lite($options = array(NULL)) 226 { 227 $availableOptions = array('automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode'); 228 foreach($options as $key => $value) { 229 if(in_array($key, $availableOptions)) { 230 $property = '_'.$key; 231 $this->$property = $value; 232 } 233 } 234 $this->_refreshTime = time() - $this->_lifeTime; 235 } 236 237 /** 238 * Test if a cache is available and (if yes) return it 239 * 240 * @param string $id cache id 241 * @param string $group name of the cache group 242 * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested 243 * @return string data of the cache (or false if no cache available) 244 * @access public 245 */ 246 function get($id, $group = 'default', $doNotTestCacheValidity = false) 247 { 248 $this->_id = $id; 249 $this->_group = $group; 250 $data = false; 251 if ($this->_caching) { 252 $this->_setFileName($id, $group); 253 if ($this->_memoryCaching) { 254 if (isset($this->_memoryCachingArray[$this->_file])) { 255 if ($this->_automaticSerialization) { 256 return unserialize($this->_memoryCachingArray[$this->_file]); 257 } else { 258 return $this->_memoryCachingArray[$this->_file]; 259 } 260 } else { 261 if ($this->_onlyMemoryCaching) { 262 return false; 263 } 264 } 265 } 266 if ($doNotTestCacheValidity) { 267 if (file_exists($this->_file)) { 268 $data = $this->_read(); 269 } 270 } else { 271 if (@filemtime($this->_file) > $this->_refreshTime) { 272 $data = $this->_read(); 273 } 274 } 275 if (($data) and ($this->_memoryCaching)) { 276 $this->_memoryCacheAdd($this->_file, $data); 277 } 278 if (($this->_automaticSerialization) and (is_string($data))) { 279 $data = unserialize($data); 280 } 281 return $data; 282 } 283 return false; 284 } 285 286 /** 287 * Save some data in a cache file 288 * 289 * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on) 290 * @param string $id cache id 291 * @param string $group name of the cache group 292 * @return boolean true if no problem 293 * @access public 294 */ 295 function save($data, $id = NULL, $group = 'default') 296 { 297 if ($this->_caching) { 298 if ($this->_automaticSerialization) { 299 $data = serialize($data); 300 } 301 if (isset($id)) { 302 $this->_setFileName($id, $group); 303 } 304 if ($this->_memoryCaching) { 305 $this->_memoryCacheAdd($this->_file, $data); 306 if ($this->_onlyMemoryCaching) { 307 return true; 308 } 309 } 310 if ($this->_writeControl) { 311 if (!$this->_writeAndControl($data)) { 312 @touch($this->_file, time() - 2*abs($this->_lifeTime)); 313 return false; 314 } else { 315 return true; 316 } 317 } else { 318 return $this->_write($data); 319 } 320 } 321 return false; 322 } 323 324 /** 325 * Remove a cache file 326 * 327 * @param string $id cache id 328 * @param string $group name of the cache group 329 * @return boolean true if no problem 330 * @access public 331 */ 332 function remove($id, $group = 'default') 333 { 334 $this->_setFileName($id, $group); 335 if (!@unlink($this->_file)) { 336 $this->raiseError('Cache_Lite : Unable to remove cache !', -3); 337 return false; 338 } 339 return true; 340 } 341 342 /** 343 * Clean the cache 344 * 345 * if no group is specified all cache files will be destroyed 346 * else only cache files of the specified group will be destroyed 347 * 348 * @param string $group name of the cache group 349 * @return boolean true if no problem 350 * @access public 351 */ 352 function clean($group = false) 353 { 354 if ($this->_fileNameProtection) { 355 $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_'; 356 } else { 357 $motif = ($group) ? 'cache_'.$group.'_' : 'cache_'; 358 } 359 if ($this->_memoryCaching) { 360 while (list($key, $value) = each($this->_memoryCaching)) { 361 if (strpos($key, $motif, 0)) { 362 unset($this->_memoryCaching[$key]); 363 $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1; 364 } 365 } 366 if ($this->_onlyMemoryCaching) { 367 return true; 368 } 369 } 370 if (!($dh = opendir($this->_cacheDir))) { 371 $this->raiseError('Cache_Lite : Unable to open cache directory !', -4); 372 return false; 373 } 374 while ($file = readdir($dh)) { 375 if (($file != '.') && ($file != '..')) { 376 $file = $this->_cacheDir . $file; 377 if (is_file($file)) { 378 if (strpos($file, $motif, 0)) { 379 if (!@unlink($file)) { 380 $this->raiseError('Cache_Lite : Unable to remove cache !', -3); 381 return false; 382 } 383 } 384 } 385 } 386 } 387 return true; 388 } 389 390 /** 391 * Set to debug mode 392 * 393 * When an error is found, the script will stop and the message will be displayed 394 * (in debug mode only). 395 * 396 * @access public 397 */ 398 function setToDebug() 399 { 400 $this->_pearErrorMode = CACHE_LITE_ERROR_DIE; 401 } 402 403 /** 404 * Set a new life time 405 * 406 * @param int $newLifeTime new life time (in seconds) 407 * @access public 408 */ 409 function setLifeTime($newLifeTime) 410 { 411 $this->_lifeTime = $newLifeTime; 412 $this->_refreshTime = time() - $newLifeTime; 413 } 414 415 /** 416 * 417 * @access public 418 */ 419 function saveMemoryCachingState($id, $group = 'default') 420 { 421 if ($this->_caching) { 422 $array = array( 423 'counter' => $this->_memoryCachingCounter, 424 'array' => $this->_memoryCachingState 425 ); 426 $data = serialize($array); 427 $this->save($data, $id, $group); 428 } 429 } 430 431 /** 432 * 433 * @access public 434 */ 435 function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false) 436 { 437 if ($this->_caching) { 438 if ($data = $this->get($id, $group, $doNotTestCacheValidity)) { 439 $array = unserialize($data); 440 $this->_memoryCachingCounter = $array['counter']; 441 $this->_memoryCachingArray = $array['array']; 442 } 443 } 444 } 445 446 /** 447 * Return the cache last modification time 448 * 449 * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY ! 450 * 451 * @return int last modification time 452 */ 453 function lastModified() { 454 return filemtime($this->_file); 455 } 456 457 /** 458 * Trigger a PEAR error 459 * 460 * To improve performances, the PEAR.php file is included dynamically. 461 * The file is so included only when an error is triggered. So, in most 462 * cases, the file isn't included and perfs are much better. 463 * 464 * @param string $msg error message 465 * @param int $code error code 466 * @access public 467 */ 468 function raiseError($msg, $code) { 469 $path = dirname( __FILE__ ) . DIRECTORY_SEPARATOR .'includes'. DIRECTORY_SEPARATOR .'PEAR'. DIRECTORY_SEPARATOR .'PEAR.php'; 470 471 if ( file_exists( $path ) ) { 472 include_once( $path ); 473 PEAR::raiseError($msg, $code, $this->_pearErrorMode); 474 } 475 } 476 477 // --- Private methods --- 478 479 /** 480 * 481 * @access private 482 */ 483 function _memoryCacheAdd($id, $data) 484 { 485 $this->_memoryCachingArray[$this->_file] = $data; 486 if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) { 487 list($key, $value) = each($this->_memoryCachingArray); 488 unset($this->_memoryCachingArray[$key]); 489 } else { 490 $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1; 491 } 492 } 493 494 /** 495 * Make a file name (with path) 496 * 497 * @param string $id cache id 498 * @param string $group name of the group 499 * @access private 500 */ 501 function _setFileName($id, $group) 502 { 503 if ($this->_fileNameProtection) { 504 $this->_file = ($this->_cacheDir.'cache_'.md5($group).'_'.md5($id)); 505 } else { 506 $this->_file = $this->_cacheDir.'cache_'.$group.'_'.$id; 507 } 508 } 509 510 /** 511 * Read the cache file and return the content 512 * 513 * @return string content of the cache file 514 * @access private 515 */ 516 function _read() 517 { 518 $fp = @fopen($this->_file, "rb"); 519 if ($this->_fileLocking) @flock($fp, LOCK_SH); 520 if ($fp) { 521 clearstatcache(); // because the filesize can be cached by PHP itself... 522 $length = @filesize($this->_file); 523 $mqr = get_magic_quotes_runtime(); 524 set_magic_quotes_runtime(0); 525 if ($this->_readControl) { 526 $hashControl = @fread($fp, 32); 527 $length = $length - 32; 528 } 529 $data = @fread($fp, $length); 530 set_magic_quotes_runtime($mqr); 531 if ($this->_fileLocking) @flock($fp, LOCK_UN); 532 @fclose($fp); 533 if ($this->_readControl) { 534 $hashData = $this->_hash($data, $this->_readControlType); 535 if ($hashData != $hashControl) { 536 @touch($this->_file, time() - 2*abs($this->_lifeTime)); 537 return false; 538 } 539 } 540 return $data; 541 } 542 $this->raiseError('Cache_Lite : Unable to read cache !', -2); 543 return false; 544 } 545 546 /** 547 * Write the given data in the cache file 548 * 549 * @param string $data data to put in cache 550 * @return boolean true if ok 551 * @access private 552 */ 553 function _write($data) 554 { 555 $fp = @fopen($this->_file, "wb"); 556 if ($fp) { 557 if ($this->_fileLocking) @flock($fp, LOCK_EX); 558 if ($this->_readControl) { 559 @fwrite($fp, $this->_hash($data, $this->_readControlType), 32); 560 } 561 $len = strlen($data); 562 @fwrite($fp, $data, $len); 563 if ($this->_fileLocking) @flock($fp, LOCK_UN); 564 @fclose($fp); 565 return true; 566 } 567 $this->raiseError('Cache_Lite : Unable to write cache !', -1); 568 return false; 569 } 570 571 /** 572 * Write the given data in the cache file and control it just after to avoir corrupted cache entries 573 * 574 * @param string $data data to put in cache 575 * @return boolean true if the test is ok 576 * @access private 577 */ 578 function _writeAndControl($data) 579 { 580 $this->_write($data); 581 $dataRead = $this->_read($data); 582 return ($dataRead==$data); 583 } 584 585 /** 586 * Make a control key with the string containing datas 587 * 588 * @param string $data data 589 * @param string $controlType type of control 'md5', 'crc32' or 'strlen' 590 * @return string control key 591 * @access private 592 */ 593 function _hash($data, $controlType) 594 { 595 switch ($controlType) { 596 case 'md5': 597 return md5($data); 598 case 'crc32': 599 return sprintf('% 32d', crc32($data)); 600 case 'strlen': 601 return sprintf('% 32d', strlen($data)); 602 default: 603 $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5); 604 } 605 } 606 607 } 608 609 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Wed Nov 21 14:43:32 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |