PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/app/external/Cache_lite.class.php

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