| [ Index ] |
|
Code source de LifeType 1.2.4 |
1 <?php 2 3 /** 4 * \ingroup Cache 5 * 6 * Fast, light and safe Cache Class 7 * 8 * Cache_Lite is a fast, light and safe cache system. It's optimized 9 * for file containers. It is fast and safe (because it uses file 10 * locking and/or anti-corruption tests). 11 * 12 * There are some examples in the 'docs/examples' file 13 * Technical choices are described in the 'docs/technical' file 14 * 15 * Memory Caching is from an original idea of 16 * Mike BENOIT <ipso@snappymail.ca> 17 * 18 * Nota : A chinese documentation (thanks to RainX <china_1982@163.com>) is 19 * available at : 20 * http://rainx.phpmore.com/manual/cache_lite.html 21 * 22 * @package Cache_Lite 23 * @category Caching 24 * @version $Id: Lite.php,v 1.45 2006/06/03 08:10:33 fab Exp $ 25 * @author Fabien MARTY <fab@php.net> 26 */ 27 28 define('CACHE_LITE_ERROR_RETURN', 1); 29 define('CACHE_LITE_ERROR_DIE', 8); 30 31 class Cache_Lite 32 { 33 34 // --- Private properties --- 35 36 /** 37 * Directory where to put the cache files 38 * (make sure to add a trailing slash) 39 * 40 * @var string $_cacheDir 41 */ 42 var $_cacheDir = '/tmp/'; 43 44 /** 45 * Enable / disable caching 46 * 47 * (can be very usefull for the debug of cached scripts) 48 * 49 * @var boolean $_caching 50 */ 51 var $_caching = true; 52 53 /** 54 * Cache lifetime (in seconds) 55 * 56 * If null, the cache is valid forever. 57 * 58 * @var int $_lifeTime 59 */ 60 var $_lifeTime = 3600; 61 62 /** 63 * Enable / disable fileLocking 64 * 65 * (can avoid cache corruption under bad circumstances) 66 * 67 * @var boolean $_fileLocking 68 */ 69 var $_fileLocking = true; 70 71 /** 72 * Timestamp of the last valid cache 73 * 74 * @var int $_refreshTime 75 */ 76 var $_refreshTime; 77 78 /** 79 * File name (with path) 80 * 81 * @var string $_file 82 */ 83 var $_file; 84 85 /** 86 * File name (without path) 87 * 88 * @var string $_fileName 89 */ 90 var $_fileName; 91 92 /** 93 * Enable / disable write control (the cache is read just after writing to detect corrupt entries) 94 * 95 * Enable write control will lightly slow the cache writing but not the cache reading 96 * Write control can detect some corrupt cache files but maybe it's not a perfect control 97 * 98 * @var boolean $_writeControl 99 */ 100 var $_writeControl = true; 101 102 /** 103 * Enable / disable read control 104 * 105 * If enabled, a control key is embeded in cache file and this key is compared with the one 106 * calculated after the reading. 107 * 108 * @var boolean $_writeControl 109 */ 110 var $_readControl = true; 111 112 /** 113 * Type of read control (only if read control is enabled) 114 * 115 * Available values are : 116 * 'md5' for a md5 hash control (best but slowest) 117 * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice) 118 * 'strlen' for a length only test (fastest) 119 * 120 * @var boolean $_readControlType 121 */ 122 var $_readControlType = 'crc32'; 123 124 /** 125 * Pear error mode (when raiseError is called) 126 * 127 * (see PEAR doc) 128 * 129 * @see setToDebug() 130 * @var int $_pearErrorMode 131 */ 132 var $_pearErrorMode = CACHE_LITE_ERROR_RETURN; 133 134 /** 135 * Current cache id 136 * 137 * @var string $_id 138 */ 139 var $_id; 140 141 /** 142 * Current cache group 143 * 144 * @var string $_group 145 */ 146 var $_group; 147 148 /** 149 * Enable / Disable "Memory Caching" 150 * 151 * NB : There is no lifetime for memory caching ! 152 * 153 * @var boolean $_memoryCaching 154 */ 155 var $_memoryCaching = false; 156 157 /** 158 * Enable / Disable "Only Memory Caching" 159 * (be carefull, memory caching is "beta quality") 160 * 161 * @var boolean $_onlyMemoryCaching 162 */ 163 var $_onlyMemoryCaching = false; 164 165 /** 166 * Memory caching array 167 * 168 * @var array $_memoryCachingArray 169 */ 170 var $_memoryCachingArray = array(); 171 172 /** 173 * Memory caching counter 174 * 175 * @var int $memoryCachingCounter 176 */ 177 var $_memoryCachingCounter = 0; 178 179 /** 180 * Memory caching limit 181 * 182 * @var int $memoryCachingLimit 183 */ 184 var $_memoryCachingLimit = 1000; 185 186 /** 187 * File Name protection 188 * 189 * if set to true, you can use any cache id or group name 190 * if set to false, it can be faster but cache ids and group names 191 * will be used directly in cache file names so be carefull with 192 * special characters... 193 * 194 * @var boolean $fileNameProtection 195 */ 196 var $_fileNameProtection = true; 197 198 /** 199 * Enable / disable automatic serialization 200 * 201 * it can be used to save directly datas which aren't strings 202 * (but it's slower) 203 * 204 * @var boolean $_serialize 205 */ 206 var $_automaticSerialization = false; 207 208 /** 209 * Disable / Tune the automatic cleaning process 210 * 211 * The automatic cleaning process destroy too old (for the given life time) 212 * cache files when a new cache file is written. 213 * 0 => no automatic cache cleaning 214 * 1 => systematic cache cleaning 215 * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write 216 * 217 * @var int $_automaticCleaning 218 */ 219 var $_automaticCleaningFactor = 0; 220 221 /** 222 * Nested directory level 223 * 224 * Set the hashed directory structure level. 0 means "no hashed directory 225 * structure", 1 means "one level of directory", 2 means "two levels"... 226 * This option can speed up Cache_Lite only when you have many thousands of 227 * cache file. Only specific benchs can help you to choose the perfect value 228 * for you. Maybe, 1 or 2 is a good start. 229 * 230 * @var int $_hashedDirectoryLevel 231 */ 232 var $_hashedDirectoryLevel = 0; 233 234 /** 235 * Umask for hashed directory structure 236 * 237 * @var int $_hashedDirectoryUmask 238 */ 239 var $_hashedDirectoryUmask = 0700; 240 241 /** 242 * API break for error handling in CACHE_LITE_ERROR_RETURN mode 243 * 244 * In CACHE_LITE_ERROR_RETURN mode, error handling was not good because 245 * for example save() method always returned a boolean (a PEAR_Error object 246 * would be better in CACHE_LITE_ERROR_RETURN mode). To correct this without 247 * breaking the API, this option (false by default) can change this handling. 248 * 249 * @var boolean 250 */ 251 var $_errorHandlingAPIBreak = false; 252 253 // --- Public methods --- 254 255 /** 256 * Constructor 257 * 258 * $options is an assoc. Available options are : 259 * $options = array( 260 * 'cacheDir' => directory where to put the cache files (string), 261 * 'caching' => enable / disable caching (boolean), 262 * 'lifeTime' => cache lifetime in seconds (int), 263 * 'fileLocking' => enable / disable fileLocking (boolean), 264 * 'writeControl' => enable / disable write control (boolean), 265 * 'readControl' => enable / disable read control (boolean), 266 * 'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string), 267 * 'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int), 268 * 'memoryCaching' => enable / disable memory caching (boolean), 269 * 'onlyMemoryCaching' => enable / disable only memory caching (boolean), 270 * 'memoryCachingLimit' => max nbr of records to store into memory caching (int), 271 * 'fileNameProtection' => enable / disable automatic file name protection (boolean), 272 * 'automaticSerialization' => enable / disable automatic serialization (boolean), 273 * 'automaticCleaningFactor' => distable / tune automatic cleaning process (int), 274 * 'hashedDirectoryLevel' => level of the hashed directory system (int), 275 * 'hashedDirectoryUmask' => umask for hashed directory structure (int), 276 * 'errorHandlingAPIBreak' => API break for better error handling ? (boolean) 277 * ); 278 * 279 * @param array $options options 280 * @access public 281 */ 282 function Cache_Lite($options = array(NULL)) 283 { 284 foreach($options as $key => $value) { 285 $this->setOption($key, $value); 286 } 287 } 288 289 /** 290 * Generic way to set a Cache_Lite option 291 * 292 * see Cache_Lite constructor for available options 293 * 294 * @var string $name name of the option 295 * @var mixed $value value of the option 296 * @access public 297 */ 298 function setOption($name, $value) 299 { 300 $availableOptions = array('errorHandlingAPIBreak', 'hashedDirectoryUmask', 'hashedDirectoryLevel', 'automaticCleaningFactor', 'automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode'); 301 if (in_array($name, $availableOptions)) { 302 $property = '_'.$name; 303 $this->$property = $value; 304 } 305 } 306 307 /** 308 * Test if a cache is available and (if yes) return it 309 * 310 * @param string $id cache id 311 * @param string $group name of the cache group 312 * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested 313 * @return string data of the cache (else : false) 314 * @access public 315 */ 316 function get($id, $group = 'default', $doNotTestCacheValidity = false) 317 { 318 $this->_id = $id; 319 $this->_group = $group; 320 $data = false; 321 if ($this->_caching) { 322 $this->_setRefreshTime(); 323 $this->_setFileName($id, $group); 324 clearstatcache(); 325 if ($this->_memoryCaching) { 326 if (isset($this->_memoryCachingArray[$this->_file])) { 327 if ($this->_automaticSerialization) { 328 return unserialize($this->_memoryCachingArray[$this->_file]); 329 } 330 return $this->_memoryCachingArray[$this->_file]; 331 } 332 if ($this->_onlyMemoryCaching) { 333 return false; 334 } 335 } 336 if (($doNotTestCacheValidity) || (is_null($this->_refreshTime))) { 337 if (file_exists($this->_file)) { 338 $data = $this->_read(); 339 } 340 } else { 341 if ((file_exists($this->_file)) && (@filemtime($this->_file) > $this->_refreshTime)) { 342 $data = $this->_read(); 343 } 344 } 345 if (($data) and ($this->_memoryCaching)) { 346 $this->_memoryCacheAdd($data); 347 } 348 if (($this->_automaticSerialization) and (is_string($data))) { 349 $data = unserialize($data); 350 } 351 return $data; 352 } 353 return false; 354 } 355 356 /** 357 * Save some data in a cache file 358 * 359 * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on) 360 * @param string $id cache id 361 * @param string $group name of the cache group 362 * @return boolean true if no problem (else : false or a PEAR_Error object) 363 * @access public 364 */ 365 function save($data, $id = NULL, $group = 'default') 366 { 367 if ($this->_caching) { 368 if ($this->_automaticSerialization) { 369 $data = serialize($data); 370 } 371 if (isset($id)) { 372 $this->_setFileName($id, $group); 373 } 374 if ($this->_memoryCaching) { 375 $this->_memoryCacheAdd($data); 376 if ($this->_onlyMemoryCaching) { 377 return true; 378 } 379 } 380 if ($this->_automaticCleaningFactor>0) { 381 $rand = rand(1, $this->_automaticCleaningFactor); 382 if ($rand==1) { 383 $this->clean(false, 'old'); 384 } 385 } 386 if ($this->_writeControl) { 387 $res = $this->_writeAndControl($data); 388 if (is_bool($res)) { 389 if ($res) { 390 return true; 391 } 392 // if $res if false, we need to invalidate the cache 393 @touch($this->_file, time() - 2*abs($this->_lifeTime)); 394 return false; 395 } 396 } else { 397 $res = $this->_write($data); 398 } 399 if (is_object($res)) { 400 // $res is a PEAR_Error object 401 if (!($this->_errorHandlingAPIBreak)) { 402 return false; // we return false (old API) 403 } 404 } 405 return $res; 406 } 407 return false; 408 } 409 410 /** 411 * Remove a cache file 412 * 413 * @param string $id cache id 414 * @param string $group name of the cache group 415 * @return boolean true if no problem 416 * @access public 417 */ 418 function remove($id, $group = 'default') 419 { 420 $this->_setFileName($id, $group); 421 if ($this->_memoryCaching) { 422 if (isset($this->_memoryCachingArray[$this->_file])) { 423 unset($this->_memoryCachingArray[$this->_file]); 424 $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1; 425 } 426 if ($this->_onlyMemoryCaching) { 427 return true; 428 } 429 } 430 return $this->_unlink($this->_file); 431 } 432 433 /** 434 * Clean the cache 435 * 436 * if no group is specified all cache files will be destroyed 437 * else only cache files of the specified group will be destroyed 438 * 439 * @param string $group name of the cache group 440 * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup', 441 * 'callback_myFunction' 442 * @return boolean true if no problem 443 * @access public 444 */ 445 function clean($group = false, $mode = 'ingroup') 446 { 447 return $this->_cleanDir($this->_cacheDir, $group, $mode); 448 } 449 450 /** 451 * Set to debug mode 452 * 453 * When an error is found, the script will stop and the message will be displayed 454 * (in debug mode only). 455 * 456 * @access public 457 */ 458 function setToDebug() 459 { 460 $this->setOption('pearErrorMode', CACHE_LITE_ERROR_DIE); 461 } 462 463 /** 464 * Set a new life time 465 * 466 * @param int $newLifeTime new life time (in seconds) 467 * @access public 468 */ 469 function setLifeTime($newLifeTime) 470 { 471 $this->_lifeTime = $newLifeTime; 472 $this->_setRefreshTime(); 473 } 474 475 /** 476 * Save the state of the caching memory array into a cache file cache 477 * 478 * @param string $id cache id 479 * @param string $group name of the cache group 480 * @access public 481 */ 482 function saveMemoryCachingState($id, $group = 'default') 483 { 484 if ($this->_caching) { 485 $array = array( 486 'counter' => $this->_memoryCachingCounter, 487 'array' => $this->_memoryCachingState 488 ); 489 $data = serialize($array); 490 $this->save($data, $id, $group); 491 } 492 } 493 494 /** 495 * Load the state of the caching memory array from a given cache file cache 496 * 497 * @param string $id cache id 498 * @param string $group name of the cache group 499 * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested 500 * @access public 501 */ 502 function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false) 503 { 504 if ($this->_caching) { 505 if ($data = $this->get($id, $group, $doNotTestCacheValidity)) { 506 $array = unserialize($data); 507 $this->_memoryCachingCounter = $array['counter']; 508 $this->_memoryCachingArray = $array['array']; 509 } 510 } 511 } 512 513 /** 514 * Return the cache last modification time 515 * 516 * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY ! 517 * 518 * @return int last modification time 519 */ 520 function lastModified() 521 { 522 return @filemtime($this->_file); 523 } 524 525 /** 526 * Trigger a PEAR error 527 * 528 * To improve performances, the PEAR.php file is included dynamically. 529 * The file is so included only when an error is triggered. So, in most 530 * cases, the file isn't included and perfs are much better. 531 * 532 * @param string $msg error message 533 * @param int $code error code 534 * @access public 535 */ 536 function raiseError($msg, $code) 537 { 538 lt_include( PLOG_CLASS_PATH."class/logger/loggermanager.class.php" ); 539 $log =& LoggerManager::getLogger(); 540 $log->error($msg, LOGGER_PRIO_ERROR); 541 } 542 543 /** 544 * Extend the life of a valid cache file 545 * 546 * see http://pear.php.net/bugs/bug.php?id=6681 547 * 548 * @access public 549 */ 550 function extendLife() 551 { 552 @touch($this->_file); 553 } 554 555 // --- Private methods --- 556 557 /** 558 * Compute & set the refresh time 559 * 560 * @access private 561 */ 562 function _setRefreshTime() 563 { 564 if (is_null($this->_lifeTime)) { 565 $this->_refreshTime = null; 566 } else { 567 $this->_refreshTime = time() - $this->_lifeTime; 568 } 569 } 570 571 /** 572 * Remove a file 573 * 574 * @param string $file complete file path and name 575 * @return boolean true if no problem 576 * @access private 577 */ 578 function _unlink($file) 579 { 580 if (file_exists($file) && !@unlink($file)) { 581 return $this->raiseError('Cache_Lite : Unable to remove cache !', -3); 582 } 583 return true; 584 } 585 586 /** 587 * Recursive function for cleaning cache file in the given directory 588 * 589 * @param string $dir directory complete path (with a trailing slash) 590 * @param string $group name of the cache group 591 * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup', 592 'callback_myFunction' 593 * @return boolean true if no problem 594 * @access private 595 */ 596 function _cleanDir($dir, $group = false, $mode = 'ingroup') 597 { 598 if ($this->_fileNameProtection) { 599 $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_'; 600 } else { 601 $motif = ($group) ? 'cache_'.$group.'_' : 'cache_'; 602 } 603 if ($this->_memoryCaching) { 604 while (list($key, ) = each($this->_memoryCachingArray)) { 605 if (strpos($key, $motif, 0)) { 606 unset($this->_memoryCachingArray[$key]); 607 $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1; 608 } 609 } 610 if ($this->_onlyMemoryCaching) { 611 return true; 612 } 613 } 614 if (!($dh = opendir($dir))) { 615 return $this->raiseError('Cache_Lite : Unable to open cache directory !', -4); 616 } 617 $result = true; 618 while ($file = readdir($dh)) { 619 if (($file != '.') && ($file != '..')) { 620 if (substr($file, 0, 6)=='cache_') { 621 $file2 = $dir . $file; 622 if (is_file($file2)) { 623 switch (substr($mode, 0, 9)) { 624 case 'old': 625 // files older than lifeTime get deleted from cache 626 if (!is_null($this->_lifeTime)) { 627 if ((mktime() - @filemtime($file2)) > $this->_lifeTime) { 628 $result = ($result and ($this->_unlink($file2))); 629 } 630 } 631 break; 632 case 'notingroup': 633 if (!strpos($file2, $motif, 0)) { 634 $result = ($result and ($this->_unlink($file2))); 635 } 636 break; 637 case 'callback_': 638 $func = substr($mode, 9, strlen($mode) - 9); 639 if ($func($file2, $group)) { 640 $result = ($result and ($this->_unlink($file2))); 641 } 642 break; 643 case 'ingroup': 644 default: 645 if (strpos($file2, $motif, 0)) { 646 $result = ($result and ($this->_unlink($file2))); 647 } 648 break; 649 } 650 } 651 if ((is_dir($file2)) and ($this->_hashedDirectoryLevel>0)) { 652 $result = ($result and ($this->_cleanDir($file2 . '/', $group, $mode))); 653 } 654 } 655 } 656 } 657 return $result; 658 } 659 660 /** 661 * Add some date in the memory caching array 662 * 663 * @param string $data data to cache 664 * @access private 665 */ 666 function _memoryCacheAdd($data) 667 { 668 $this->_memoryCachingArray[$this->_file] = $data; 669 if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) { 670 list($key, ) = each($this->_memoryCachingArray); 671 unset($this->_memoryCachingArray[$key]); 672 } else { 673 $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1; 674 } 675 } 676 677 /** 678 * Make a file name (with path) 679 * 680 * @param string $id cache id 681 * @param string $group name of the group 682 * @access private 683 */ 684 function _setFileName($id, $group) 685 { 686 687 if ($this->_fileNameProtection) { 688 $suffix = 'cache_'.md5($group).'_'.md5($id); 689 } else { 690 $suffix = 'cache_'.$group.'_'.$id; 691 } 692 $root = $this->_cacheDir; 693 if ($this->_hashedDirectoryLevel>0) { 694 $hash = md5($suffix); 695 for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) { 696 $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/'; 697 } 698 } 699 $this->_fileName = $suffix; 700 $this->_file = $root.$suffix; 701 } 702 703 /** 704 * Read the cache file and return the content 705 * 706 * @return string content of the cache file (else : false or a PEAR_Error object) 707 * @access private 708 */ 709 function _read() 710 { 711 $fp = @fopen($this->_file, "rb"); 712 if ($this->_fileLocking) @flock($fp, LOCK_SH); 713 if ($fp) { 714 clearstatcache(); 715 $length = @filesize($this->_file); 716 $mqr = get_magic_quotes_runtime(); 717 set_magic_quotes_runtime(0); 718 if ($this->_readControl) { 719 $hashControl = @fread($fp, 32); 720 $length = $length - 32; 721 } 722 if ($length) { 723 $data = @fread($fp, $length); 724 } else { 725 $data = ''; 726 } 727 set_magic_quotes_runtime($mqr); 728 if ($this->_fileLocking) @flock($fp, LOCK_UN); 729 @fclose($fp); 730 if ($this->_readControl) { 731 $hashData = $this->_hash($data, $this->_readControlType); 732 if ($hashData != $hashControl) { 733 if (!(is_null($this->_lifeTime))) { 734 @touch($this->_file, time() - 2*abs($this->_lifeTime)); 735 } else { 736 @unlink($this->_file); 737 } 738 return false; 739 } 740 } 741 return $data; 742 } 743 return $this->raiseError('Cache_Lite : Unable to read cache !', -2); 744 } 745 746 /** 747 * Write the given data in the cache file 748 * 749 * @param string $data data to put in cache 750 * @return boolean true if ok (a PEAR_Error object else) 751 * @access private 752 */ 753 function _write($data) 754 { 755 if (!is_dir(dirname($this->_file)) && $this->_hashedDirectoryLevel > 0) { 756 $hash = md5($this->_fileName); 757 $root = $this->_cacheDir; 758 for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) { 759 $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/'; 760 if (!(@is_dir($root))) { 761 @mkdir($root, $this->_hashedDirectoryUmask); 762 } 763 } 764 } 765 $fp = @fopen($this->_file, "wb"); 766 if ($fp) { 767 if ($this->_fileLocking) @flock($fp, LOCK_EX); 768 if ($this->_readControl) { 769 @fwrite($fp, $this->_hash($data, $this->_readControlType), 32); 770 } 771 $len = strlen($data); 772 @fwrite($fp, $data, $len); 773 if ($this->_fileLocking) @flock($fp, LOCK_UN); 774 @fclose($fp); 775 return true; 776 } 777 return $this->raiseError('Cache_Lite : Unable to write cache file : '.$this->_file, -1); 778 } 779 780 /** 781 * Write the given data in the cache file and control it just after to avoir corrupted cache entries 782 * 783 * @param string $data data to put in cache 784 * @return boolean true if the test is ok (else : false or a PEAR_Error object) 785 * @access private 786 */ 787 function _writeAndControl($data) 788 { 789 $result = $this->_write($data); 790 if (is_object($result)) { 791 return $result; #Â We return the PEAR_Error object 792 } 793 $dataRead = $this->_read(); 794 if (is_object($dataRead)) { 795 return $result; #Â We return the PEAR_Error object 796 } 797 if ((is_bool($dataRead)) && (!$dataRead)) { 798 return false; 799 } 800 return ($dataRead==$data); 801 } 802 803 /** 804 * Make a control key with the string containing datas 805 * 806 * @param string $data data 807 * @param string $controlType type of control 'md5', 'crc32' or 'strlen' 808 * @return string control key 809 * @access private 810 */ 811 function _hash($data, $controlType) 812 { 813 switch ($controlType) { 814 case 'md5': 815 return md5($data); 816 case 'crc32': 817 return sprintf('% 32d', crc32($data)); 818 case 'strlen': 819 return sprintf('% 32d', strlen($data)); 820 default: 821 return $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5); 822 } 823 } 824 825 } 826 827 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Mon Nov 26 21:04:15 2007 | par Balluche grâce à PHPXref 0.7 |
|