PageRenderTime 45ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/forum/web-optimizer/libs/php/cache_engine.php

https://github.com/GreyTeardrop/socionicasys-forum
PHP | 1544 lines | 1483 code | 35 blank | 26 comment | 99 complexity | 068e2c621aa3e9785b4bccdb17f627d2 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-3.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /**
  3. * File from WEBO Site SpeedUp, WEBO Software (http://www.webogroup.com/)
  4. * Classes for storing html cache
  5. * License agreement: http://www.webogroup.com/about/EULA.txt
  6. *
  7. **/
  8. /* Abstract class that defines basic methods and contains several methods for SQL caching*/
  9. class webo_cache_engine {
  10. /* Class constructor. Expects options array. */
  11. function webo_cache_engine($options)
  12. {
  13. if(strtolower(__CLASS__)=='baseclass'){
  14. trigger_error('This class is abstract!',E_USER_ERROR);
  15. exit();
  16. }
  17. }
  18. /* Adds or updates entry. Expects key string and value to cache. */
  19. function put_entry($key, $value, $time)
  20. {
  21. if(strtolower(__CLASS__)=='baseclass'){
  22. trigger_error('This class is abstract!',E_USER_ERROR);
  23. exit();
  24. }
  25. }
  26. /* Get cache entry by key. Expects key string. */
  27. function get_entry($key)
  28. {
  29. if(strtolower(__CLASS__)=='baseclass'){
  30. trigger_error('This class is abstract!',E_USER_ERROR);
  31. exit();
  32. }
  33. }
  34. /* Clear cache entries by pattern(s). Expects pattern or array of patterns. */
  35. function delete_entries($patterns)
  36. {
  37. if(strtolower(__CLASS__)=='baseclass'){
  38. trigger_error('This class is abstract!',E_USER_ERROR);
  39. exit();
  40. }
  41. }
  42. /* Gets creation time of cache entry. Expects key string. */
  43. function get_mtime($key)
  44. {
  45. if(strtolower(__CLASS__)=='baseclass'){
  46. trigger_error('This class is abstract!',E_USER_ERROR);
  47. exit();
  48. }
  49. }
  50. /* Sets creation time of cache entry. Expects key string and time to set. */
  51. function set_mtime($key, $time)
  52. {
  53. if(strtolower(__CLASS__)=='baseclass'){
  54. trigger_error('This class is abstract!',E_USER_ERROR);
  55. exit();
  56. }
  57. }
  58. function get_cache_size($mask, $number = false)
  59. {
  60. if(strtolower(__CLASS__)=='baseclass'){
  61. trigger_error('This class is abstract!',E_USER_ERROR);
  62. exit();
  63. }
  64. }
  65. /* Returns array with information about given query. */
  66. function get_query_info($sql)
  67. {
  68. $sql = ltrim($sql);
  69. $quote = 0;
  70. $slash = 0;
  71. $table_stage = false;
  72. $table_now = false;
  73. $word = false;
  74. $table = array();
  75. $change = false;
  76. $select = false;
  77. $alias_now = false;
  78. $cur_word = '';
  79. $words = explode(' ', $sql, 2);
  80. $first_word = strtolower($words[0]);
  81. if ($first_word == 'select')
  82. {
  83. $sql = $words[1];
  84. $select = true;
  85. }
  86. elseif ($first_word == 'delete')
  87. {
  88. $sql = $words[1];
  89. $sql = ltrim($sql);
  90. $words = explode(' ', $sql, 2);
  91. $second_word = strtolower($words[0]);
  92. if ($second_word == 'from')
  93. {
  94. $sql = $words[1];
  95. $change = true;
  96. $table_stage = true;
  97. }
  98. else
  99. {
  100. return array('select' => $select, 'table' => $table, 'change' => $change);
  101. }
  102. }
  103. elseif ($first_word == 'insert')
  104. {
  105. $sql = $words[1];
  106. $sql = ltrim($sql);
  107. $words = explode(' ', $sql, 2);
  108. $second_word = strtolower($words[0]);
  109. if ($second_word == 'into')
  110. {
  111. $sql = $words[1];
  112. $change = true;
  113. $table_stage = true;
  114. }
  115. else
  116. {
  117. return array('select' => $select, 'table' => $table, 'change' => $change);
  118. }
  119. }
  120. elseif ($first_word == 'update')
  121. {
  122. $sql = $words[1];
  123. $change = true;
  124. $table_stage = true;
  125. }
  126. else
  127. {
  128. return array('select' => $select, 'table' => $table, 'change' => $change);
  129. }
  130. $table_now = $change;
  131. for ($i = 0; $i < strlen($sql); $i++)
  132. {
  133. if ($table_stage == true)
  134. {
  135. if ($quote == 0)
  136. {
  137. if ($sql[$i] == '`')
  138. {
  139. $word = true;
  140. $quote = 1;
  141. }
  142. elseif ($sql[$i] == '\'')
  143. {
  144. $word = true;
  145. $quote = 2;
  146. }
  147. elseif ($sql[$i] == '"')
  148. {
  149. $word = true;
  150. $quote = 3;
  151. }
  152. elseif (($sql[$i] != ' ') && ($sql[$i] != ',') && ($sql[$i] != "\n") && ($word === false))
  153. {
  154. $word = true;
  155. $cur_word = $sql[$i];
  156. }
  157. elseif ((($sql[$i] == ' ') || ($sql[$i] == ',') || ($sql[$i] == "\n")) && ($word === true))
  158. {
  159. $cur_word = strtolower($cur_word);
  160. if (($cur_word == 'from') || ($cur_word == 'join'))
  161. {
  162. $table_now = true;
  163. }
  164. elseif (in_array($cur_word, array('where', 'group', 'having', 'order', 'limit', 'procedure', 'into')))
  165. {
  166. $i = strlen($sql);
  167. }
  168. elseif ($table_now == true)
  169. {
  170. $cur_word = str_replace($this->sql_prefix, '', $cur_word);
  171. $table[$cur_word] = true;
  172. if ($change == true)
  173. {
  174. $i = strlen($sql);
  175. }
  176. elseif ($sql[$i] == ',')
  177. {
  178. $table_now = true;
  179. }
  180. else
  181. {
  182. $alias_now = true;
  183. $table_now = false;
  184. }
  185. }
  186. elseif (($alias_now == true) && ($cur_word != 'as'))
  187. {
  188. $alias_now = false;
  189. if ($sql[$i] == ',')
  190. {
  191. $table_now = true;
  192. }
  193. }
  194. $word = false;
  195. $cur_word = '';
  196. }
  197. elseif ($word == true)
  198. {
  199. $cur_word .= $sql[$i];
  200. }
  201. }
  202. elseif ((($quote == 1) && ($sql[$i] == '`')) || (($quote == 2) && ($sql[$i] == '\'')) || (($quote == 3) && ($sql[$i] == '"')))
  203. {
  204. if ($slash == 0)
  205. {
  206. $quote = 0;
  207. }
  208. else
  209. {
  210. $cur_word .= $sql[$i];
  211. $slash = 0;
  212. }
  213. }
  214. elseif ($sql[$i] == '\\')
  215. {
  216. $slash = 1 - $slash;
  217. }
  218. else
  219. {
  220. $cur_word .= $sql[$i];
  221. }
  222. }
  223. else
  224. {
  225. if ($quote == 0)
  226. {
  227. if ($sql[$i] == '`')
  228. {
  229. $quote = 1;
  230. }
  231. elseif ($sql[$i] == '\'')
  232. {
  233. $quote = 2;
  234. }
  235. elseif ($sql[$i] == '"')
  236. {
  237. $quote = 3;
  238. }
  239. elseif (($sql[$i] != ' ') && ($sql[$i] != ',') && ($sql[$i] != "\n") && ($word === false))
  240. {
  241. $word = true;
  242. $cur_word = $sql[$i];
  243. }
  244. elseif ((($sql[$i] == ' ') || ($sql[$i] == ',') || ($sql[$i] == "\n")) && ($word === true))
  245. {
  246. if (strtolower($cur_word) == 'from')
  247. {
  248. $table_stage = true;
  249. $table_now = true;
  250. }
  251. $word = false;
  252. $cur_word = '';
  253. }
  254. elseif ($word == true)
  255. {
  256. $cur_word .= $sql[$i];
  257. }
  258. }
  259. elseif ((($quote == 1) && ($sql[$i] == '`')) || (($quote == 2) && ($sql[$i] == '\'')) || (($quote == 3) && ($sql[$i] == '"')))
  260. {
  261. if ($slash == 0)
  262. {
  263. $quote = 0;
  264. }
  265. else
  266. {
  267. $slash = 1;
  268. }
  269. }
  270. elseif ($sql[$i] == '\\')
  271. {
  272. $slash = 1 - $slash;
  273. }
  274. }
  275. }
  276. return array('select' => $select, 'table' => $table, 'change' => $change);
  277. }
  278. function start_sql_cache ($compress_options, $prefix = '')
  279. {
  280. $queries = $this->get_entry('cached_queries.sql');
  281. if ($queries)
  282. {
  283. $this->sql_cached_queries = unserialize($queries);
  284. }
  285. else
  286. {
  287. $this->sql_cached_queries = array();
  288. }
  289. $info = $this->get_entry('info.sql');
  290. if ($info)
  291. {
  292. $info = unserialize($info);
  293. $this->sql_tables = $info['tables'];
  294. $this->sql_table_queries = $info['table_queries'];
  295. $this->sql_last_ids = $info['last_ids'];
  296. }
  297. else
  298. {
  299. $this->sql_tables = array();
  300. $this->sql_table_queries = array();
  301. $this->sql_last_ids = array('table' => 0, 'query' => 0);
  302. }
  303. $this->sql_cache_time = $compress_options['sql_cache']['time'];
  304. $this->sql_exclude_tables = explode(' ', $compress_options['sql_cache']['tables_exclude']);
  305. $this->sql_cache_timeout = $compress_options['sql_cache']['timeout'];
  306. $this->sql_cache_enabled = true;
  307. $this->current_time = time();
  308. $this->sql_cached_result = false;
  309. $this->sql_cached_rows = 0;
  310. $this->sql_cache_changed = false;
  311. $this->sql_prefix = $prefix;
  312. $this->clear_expired_sql();
  313. }
  314. function save_sql_cache()
  315. {
  316. if (!empty($this->sql_cache_enabled) && ($this->sql_cache_changed))
  317. {
  318. $this->put_entry('info.sql', serialize(array('tables' => $this->sql_tables, 'table_queries' => $this->sql_table_queries, 'last_ids' => $this->sql_last_ids)), $this->current_time);
  319. $this->put_entry('cached_queries.sql', serialize($this->sql_cached_queries), $this->current_time);
  320. }
  321. }
  322. function get_query_options($sql)
  323. {
  324. $change = false;
  325. $cache_me = false;
  326. $cache_hit = false;
  327. $start = 0;
  328. $tables = array();
  329. $key = $sql;
  330. if ($this->sql_cache_timeout >= 3600)
  331. {
  332. $key = preg_replace('(/(\d\d\d\d-\d\d-\d\d \d\d:)\d\d:\d\d/', '${1}00:00', $key);
  333. }
  334. elseif ($this->sql_cache_timeout >= 600)
  335. {
  336. $key = preg_replace('/(\d\d\d\d-\d\d-\d\d \d\d:\d)\d:\d\d/', '${1}0:00', $key);
  337. }
  338. elseif ($this->sql_cache_timeout >= 60)
  339. {
  340. $key = preg_replace('/(\d\d\d\d-\d\d-\d\d \d\d:\d\d:)\d\d/', '${1}00', $key);
  341. }
  342. elseif ($this->sql_cache_timeout >= 10)
  343. {
  344. $key = preg_replace('/(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d)\d/', '${1}0', $key);
  345. }
  346. if (!empty($this->sql_cache_enabled))
  347. {
  348. $query_info = $this->get_query_info($sql);
  349. $tables = $query_info['table'];
  350. foreach ($tables as $table => $value)
  351. {
  352. if (in_array($table, $this->sql_exclude_tables))
  353. {
  354. $query_info['select'] = false;
  355. $query_info['change'] = false;
  356. }
  357. }
  358. $change = $query_info['change'];
  359. }
  360. if (!empty($this->sql_cache_enabled) && ($query_info['select']))
  361. {
  362. if (!empty($this->sql_cached_queries[$key]))
  363. {
  364. $query = $this->sql_cached_queries[$key];
  365. if (($this->current_time - $query['time'] < $this->sql_cache_timeout))
  366. {
  367. $this->sql_cached_result = $query['result'];
  368. $this->sql_cached_rows = $query['num_rows'];
  369. $cache_hit = true;
  370. }
  371. }
  372. $start = explode(' ', microtime());
  373. $start = $start[1] + $start[0];
  374. $cache_me = true;
  375. }
  376. return(array($cache_me, $change, $cache_hit, $tables, $start, $key));
  377. }
  378. function add_to_sql_cache($mysql_result, $start, $query_tables, $sql)
  379. {
  380. if (!is_resource($mysql_result) || (stripos(get_resource_type($mysql_result), 'mysql') === false))
  381. {
  382. return false;
  383. }
  384. $end = explode(' ', microtime());
  385. $end = $end[1] + $end[0];
  386. if (((($end - $start) * 1000) > $this->sql_cache_time))
  387. {
  388. $this->sql_cache_changed = true;
  389. $query_id = $this->sql_last_ids['query'];
  390. $this->sql_last_ids['query']++;
  391. foreach ($this->sql_tables as $table => $id)
  392. {
  393. if (!empty($query_tables[$table]))
  394. {
  395. unset($query_tables[$table]);
  396. $this->sql_table_queries[$id][$query_id] = true;
  397. }
  398. }
  399. foreach ($query_tables as $table => $value)
  400. {
  401. $id = $this->sql_last_ids['table'];
  402. $this->sql_tables[$table] = $id;
  403. $this->sql_table_queries[$id][$query_id] = true;
  404. $this->sql_last_ids['table']++;
  405. }
  406. $this->sql_cached_queries[$sql] = array('time' => $this->current_time, 'id' => $query_id);
  407. $result_array = array();
  408. $num_rows = 0;
  409. while ($row = mysql_fetch_assoc($mysql_result))
  410. {
  411. $num_rows++;
  412. $result_array[] = $row;
  413. }
  414. $this->sql_cached_result = $result_array;
  415. $this->sql_cached_rows = $num_rows;
  416. $this->sql_cached_queries[$sql]['result'] = $result_array;
  417. $this->sql_cached_queries[$sql]['num_rows'] = $num_rows;
  418. return true;
  419. }
  420. else
  421. {
  422. return false;
  423. }
  424. }
  425. function clear_expired_sql()
  426. {
  427. if (empty($this->sql_cached_queries) || !is_array($this->sql_cached_queries))
  428. {
  429. return;
  430. }
  431. foreach ($this->sql_cached_queries as $query => $info)
  432. {
  433. if ($this->current_time - $info['time'] > $this->sql_cache_timeout)
  434. {
  435. $this->sql_cache_changed = true;
  436. unset($this->sql_cached_queries[$query]);
  437. foreach ($this->sql_table_queries as $id => $queries)
  438. {
  439. unset($this->sql_table_queries[$id][$info['id']]);
  440. }
  441. }
  442. }
  443. }
  444. function update_sql_cache($tables)
  445. {
  446. foreach ($tables as $table => $value)
  447. {
  448. break;
  449. }
  450. if (isset($this->sql_tables[$table]))
  451. {
  452. $this->sql_cache_changed = true;
  453. $table_id = $this->sql_tables[$table];
  454. $drop_queries = $this->sql_table_queries[$table_id];
  455. $this->sql_table_queries[$table_id] = array();
  456. foreach ($this->sql_table_queries as $table_id => $queries)
  457. {
  458. if (count($this->sql_table_queries[$table_id]) != 0)
  459. {
  460. foreach ($drop_queries as $query_id => $value)
  461. {
  462. if (!empty($queries[$query_id]))
  463. {
  464. unset($this->sql_table_queries[$table_id][$query_id]);
  465. }
  466. }
  467. }
  468. }
  469. $max_id = 0;
  470. foreach ($this->sql_cached_queries as $query => $info)
  471. {
  472. foreach ($drop_queries as $query_id => $value)
  473. {
  474. if ($info['id'] == $query_id)
  475. {
  476. unset($this->sql_cached_queries[$query]);
  477. }
  478. elseif ($info['id'] > $max_id)
  479. {
  480. $max_id = $info['id'];
  481. }
  482. }
  483. }
  484. $this->sql_last_ids['query'] = $max_id + 1;
  485. }
  486. }
  487. function clear_sql_cache()
  488. {
  489. if (!$this->enabled)
  490. {
  491. $this->enabled = true;
  492. $result = $this->delete_entries(array('cached_queries.sql', 'info.sql'));
  493. $this->enabled = false;
  494. }
  495. else
  496. {
  497. $result = $this->delete_entries(array('cached_queries.sql', 'info.sql'));
  498. }
  499. return $result;
  500. }
  501. }
  502. /* Here starts the section with different implementations of cache_engine abstract class. Every class name should start with 'cache_' and use some specific name for particular engine. For example, cache_files (stores cache items on filesystem) or cache_memcached (uses memcached to store cache items).
  503. /* Default implementation that stores cache entries on filesystem */
  504. class webo_cache_files extends webo_cache_engine
  505. {
  506. /* Class constructor. Expects cache directory as option and checks if it's writable. */
  507. function webo_cache_files($options)
  508. {
  509. /**
  510. * A better "fnmatch" alternative for windows that converts a fnmatch
  511. * pattern into a preg one. It should work on PHP >= 4.0.0.
  512. * @author soywiz at php dot net
  513. * @since 17-Jul-2006 10:12
  514. */
  515. if (!function_exists('fnmatch')) {
  516. function fnmatch($pattern, $string) {
  517. return @preg_match('/^' . strtr(addcslashes($pattern, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $string);
  518. }
  519. }
  520. if(!empty($options['cache_dir']))
  521. {
  522. $this->enabled = true;
  523. $this->cache_dir = $options['cache_dir'];
  524. }
  525. else
  526. {
  527. $this->enabled = false;
  528. }
  529. $this->all_files = false;
  530. }
  531. function __get_files_list()
  532. {
  533. if ($this->all_files === false)
  534. {
  535. if (@is_file($this->cache_dir . 'wo.files.php'))
  536. {
  537. include($this->cache_dir . 'wo.files.php');
  538. if (isset($webo_cache_files_list) && is_array($webo_cache_files_list))
  539. {
  540. $this->all_files = $webo_cache_files_list;
  541. }
  542. else
  543. {
  544. $this->all_files = array();
  545. }
  546. }
  547. else
  548. {
  549. $this->all_files = array();
  550. }
  551. }
  552. }
  553. function __put_files_list()
  554. {
  555. $str = "<?php\n";
  556. foreach ($this->all_files as $k => $v)
  557. {
  558. $str .= '$webo_cache_files_list[\'' . addcslashes($k, "\0'\\") . '\'] = ' . "'$v';\n";
  559. }
  560. $str .= '?>';
  561. $length = strlen($str);
  562. $i = 0;
  563. $written = 0;
  564. while (($i < 3) && ($written != $length))
  565. {
  566. $fp = @fopen($this->cache_dir . 'wo.files.php', "a");
  567. if ($fp) {
  568. /* block file from writing */
  569. @flock($fp, LOCK_EX);
  570. /* erase content and move to the beginning */
  571. @ftruncate($fp, 0);
  572. @fseek($fp, 0);
  573. $written = @fwrite($fp, $str);
  574. @fclose($fp);
  575. }
  576. $i++;
  577. }
  578. }
  579. /* Adds or updates entry. Expects key string and value to cache. */
  580. function put_entry($key, $value, $time)
  581. {
  582. if (!$this->enabled)
  583. {
  584. return;
  585. }
  586. $path = $this->__get_path($key);
  587. $this->__get_files_list();
  588. $this->all_files[$path] = strlen($value);
  589. $this->__put_files_list();
  590. if (!@is_dir(dirname($path)))
  591. {
  592. $this->__make_path($path);
  593. }
  594. if (@function_exists('file_put_contents')) {
  595. @file_put_contents($path, $value);
  596. } else {
  597. $fp = @fopen($path, "a");
  598. if ($fp) {
  599. /* block file from writing */
  600. @flock($fp, LOCK_EX);
  601. /* erase content and move to the beginning */
  602. @ftruncate($fp, 0);
  603. @fseek($fp, 0);
  604. @fwrite($fp, $value);
  605. @fclose($fp);
  606. }
  607. }
  608. @touch($path);
  609. @chmod($path, octdec("0644"));
  610. }
  611. /* Get cache entry by key. Expects key string. */
  612. function get_entry($key)
  613. {
  614. if (!$this->enabled)
  615. {
  616. return false;
  617. }
  618. if (@is_file($this->__get_path($key)))
  619. {
  620. return @file_get_contents($this->__get_path($key));
  621. }
  622. else
  623. {
  624. return false;
  625. }
  626. }
  627. /* Clear cache entries by pattern(s). Expects pattern or array of patterns. */
  628. function delete_entries($patterns)
  629. {
  630. if (!$this->enabled)
  631. {
  632. return false;
  633. }
  634. $this->__get_files_list();
  635. if (!empty($patterns))
  636. {
  637. if (is_array($patterns))
  638. {
  639. foreach($patterns as $pattern)
  640. {
  641. $files = $this->__recurse_glob($this->__get_path($pattern));
  642. foreach($files as $file)
  643. {
  644. if (@is_file($file))
  645. {
  646. @unlink($file);
  647. }
  648. elseif (@is_dir($file))
  649. {
  650. $this->__recurse_rm($file);
  651. }
  652. }
  653. }
  654. }
  655. else
  656. {
  657. $files = $this->__recurse_glob($this->__get_path($patterns));
  658. foreach($files as $file)
  659. {
  660. if (@is_file($file))
  661. {
  662. @unlink($file);
  663. }
  664. elseif (@is_dir($file))
  665. {
  666. $this->__recurse_rm($file);
  667. }
  668. }
  669. }
  670. $this->__put_files_list();
  671. }
  672. }
  673. /* Gets creation time of cache entry. Expects key string. */
  674. function get_mtime($key)
  675. {
  676. if (!$this->enabled)
  677. {
  678. return 0;
  679. }
  680. if (@file_exists($this->__get_path($key)))
  681. {
  682. return @filemtime($this->__get_path($key));
  683. }
  684. else
  685. {
  686. return 0;
  687. }
  688. }
  689. /* Sets creation time of cache entry. Expects key string and time to set. */
  690. function set_mtime($key, $time)
  691. {
  692. if (!$this->enabled)
  693. {
  694. return false;
  695. }
  696. @touch($this->__get_path($key), $time);
  697. }
  698. /* Gets path to file from cache entry key */
  699. function __get_path($key)
  700. {
  701. $key = strtolower($_SERVER['HTTP_HOST']) . '/' . $key;
  702. return preg_replace('/\\.+\\/+/','',$this->cache_dir . str_replace(array('+',"'",'^','%','"','<','>','$'), array('/','','','','','','',''), $key));
  703. }
  704. /* Creates directory structure to store the file */
  705. function __make_path($path)
  706. {
  707. $dirs = explode('/', dirname($path));
  708. $cur_dir = '/';
  709. foreach($dirs as $dir)
  710. {
  711. if(!empty($dir))
  712. {
  713. $cur_dir .= $dir . '/';
  714. if(!@is_dir($cur_dir))
  715. {
  716. @mkdir($cur_dir, 0755);
  717. }
  718. }
  719. }
  720. }
  721. /* Internal method that returns all keys that match given pattern. Expects pattern. */
  722. function __recurse_glob($pattern, $size = false, $number = false) {
  723. $split=explode('/',str_replace('\\','/',$pattern));
  724. $mask=array_pop($split);
  725. $path=implode('/',$split);
  726. if (($dir=@opendir($path))!==false) {
  727. if ($size === false)
  728. {
  729. $glob=array();
  730. }
  731. else
  732. {
  733. if ($number === false)
  734. {
  735. $glob = $size;
  736. }
  737. else
  738. {
  739. $glob = array($size, $number);
  740. }
  741. }
  742. while(($file=@readdir($dir))!==false) {
  743. if(is_dir($path.'/'.$file) && (!in_array($file,array('.','..'))) )
  744. {
  745. if ($size === false)
  746. {
  747. $glob = array_merge($glob,$this->__recurse_glob($path.'/'.$file.'/'.$mask));
  748. }
  749. else
  750. {
  751. if ($number === false)
  752. {
  753. $glob = $this->__recurse_glob($path.'/'.$file.'/'.$mask, $glob);
  754. }
  755. else
  756. {
  757. $glob = $this->__recurse_glob($path.'/'.$file.'/'.$mask, $glob[0], $glob[1]);
  758. }
  759. }
  760. }
  761. if (fnmatch($mask,$file)) {
  762. if (!in_array($file,array('.','..')))
  763. {
  764. if ($size === false)
  765. {
  766. $glob[] = $path . '/'. $file;
  767. }
  768. else
  769. {
  770. if ($number === false)
  771. {
  772. $glob += @filesize($path . '/'. $file);
  773. }
  774. else
  775. {
  776. $glob[0] += @filesize($path . '/'. $file);
  777. $glob[1]++;
  778. }
  779. }
  780. }
  781. }
  782. }
  783. @closedir($dir);
  784. return $glob;
  785. } else {
  786. if ($size === false)
  787. {
  788. return array();
  789. }
  790. else
  791. {
  792. if ($number === false)
  793. {
  794. return $size;
  795. }
  796. else
  797. {
  798. return array($size, $number);
  799. }
  800. }
  801. }
  802. }
  803. function __recurse_rm($path)
  804. {
  805. if (is_dir($path))
  806. {
  807. if (substr($path, strlen($path) - 1) != '/')
  808. {
  809. $path .= '/';
  810. }
  811. $dh = @opendir($path);
  812. while (($file = @readdir($dh)) !== false)
  813. {
  814. if (($file == '.') || ($file == '..'))
  815. {
  816. //do nothing
  817. }
  818. elseif (is_dir($path . $file))
  819. {
  820. $this->__recurse_rm($path . $file);
  821. }
  822. else
  823. {
  824. if (isset($this->all_files[$path . $file]))
  825. {
  826. unset($this->all_files[$path . $file]);
  827. }
  828. @unlink($path . $file);
  829. }
  830. }
  831. @closedir($dh);
  832. @rmdir($path);
  833. }
  834. else
  835. {
  836. @unlink($path);
  837. }
  838. }
  839. /* Gets total size and number of cache files defined by mask */
  840. function get_cache_size($mask, $number = false)
  841. {
  842. $this->__get_files_list();
  843. if (!$this->enabled)
  844. {
  845. if ($number === false)
  846. {
  847. return 0;
  848. }
  849. else
  850. {
  851. return array(0,0);
  852. }
  853. }
  854. $mask = str_replace('.', '\\.', $mask);
  855. $mask = str_replace('*', '.*', $mask);
  856. $size = 0;
  857. $num = 0;
  858. foreach ($this->all_files as $key => $value)
  859. {
  860. if (preg_match('/' . $mask . '/', $key))
  861. {
  862. $size += $value;
  863. $num++;
  864. }
  865. }
  866. if ($number === false)
  867. {
  868. return $size;
  869. //return $this->__recurse_glob($this->__get_path($mask), 0);
  870. }
  871. else
  872. {
  873. return array($size, $num);
  874. //return $this->__recurse_glob($this->__get_path($mask), 0, 0);
  875. }
  876. }
  877. }
  878. class webo_cache_memcached extends webo_cache_engine {
  879. /* Class constructor. Expects options array. */
  880. function webo_cache_memcached($options)
  881. {
  882. $this->enabled = false;
  883. $this->cached = array();
  884. $this->prefix = 'webo_cache_'; //maybe memcached stores data from other applications
  885. if(!empty($options['server']))
  886. {
  887. $server = explode(':', $options['server']); //get server and port
  888. if(!empty($server[1]))
  889. {
  890. if (@class_exists('Memcached'))
  891. {
  892. $this->connection = new Memcached();
  893. }
  894. elseif (@class_exists('Memcache'))
  895. {
  896. $this->connection = new Memcache();
  897. }
  898. if($this->connection)
  899. {
  900. if ($this->connection->addServer($server[0], $server[1])) //add server to store files
  901. {
  902. $this->enabled = true;
  903. }
  904. }
  905. }
  906. }
  907. }
  908. /* Adds or updates entry. Expects key string and value to cache. */
  909. function put_entry($key, $value, $time)
  910. {
  911. if (!$this->enabled)
  912. {
  913. return;
  914. }
  915. $entries = $this->connection->get('webo_files_list');
  916. if(($entries === false) || !is_array($entries)) //filelist is broken or removed from server so we need to clear cache
  917. {
  918. $this->connection->flush(); //this removes all other applications data but is only way to do it
  919. $entries = array();
  920. }
  921. $this->connection->set($this->prefix . $key, array('value' => $value, 'time' => $time));
  922. $entries[$key] = 1;
  923. $this->connection->set('webo_files_list', $entries);
  924. }
  925. /* Get cache entry by key. Expects key string. */
  926. function get_entry($key)
  927. {
  928. if (!$this->enabled)
  929. {
  930. return false;
  931. }
  932. if (!empty($this->cached[$key]['value']))
  933. {
  934. return $this->cached[$key]['value'];
  935. }
  936. $item = $this->connection->get($this->prefix . $key);
  937. if(empty($item['value']))
  938. {
  939. return false;
  940. }
  941. else
  942. {
  943. $this->cached[$key] = $item;
  944. return $item['value'];
  945. }
  946. }
  947. /* Clear cache entries by pattern(s). Expects pattern or array of patterns. */
  948. function delete_entries($patterns)
  949. {
  950. if (!$this->enabled)
  951. {
  952. return false;
  953. }
  954. if (!empty($patterns))
  955. {
  956. $all_files = $this->connection->get('webo_files_list');
  957. if(($all_files === false) || !is_array($all_files))
  958. {
  959. $this->connection->flush();
  960. $this->connection->set('webo_files_list', array());
  961. return;
  962. }
  963. if (is_array($patterns))
  964. {
  965. foreach($patterns as $pattern)
  966. {
  967. foreach($all_files as $key => $value)
  968. {
  969. if(@preg_match('/^' . strtr(addcslashes($pattern, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  970. {
  971. $this->connection->delete($this->prefix . $key);
  972. unset($all_files[$key]);
  973. }
  974. }
  975. }
  976. $this->connection->set('webo_files_list', $all_files);
  977. }
  978. else
  979. {
  980. foreach($all_files as $key => $value)
  981. {
  982. if(@preg_match('/^' . strtr(addcslashes($patterns, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  983. {
  984. $this->connection->delete($this->prefix . $key);
  985. unset($all_files[$key]);
  986. }
  987. }
  988. $this->connection->set('webo_files_list', $all_files);
  989. }
  990. }
  991. }
  992. /* Gets creation time of cache entry. Expects key string. */
  993. function get_mtime($key)
  994. {
  995. if (!$this->enabled)
  996. {
  997. return 0;
  998. }
  999. if(!empty($this->cached[$key]['time']))
  1000. {
  1001. return $this->cached[$key]['time'];
  1002. }
  1003. $item = $this->connection->get($this->prefix . $key);
  1004. if (empty($item['time']))
  1005. {
  1006. return 0;
  1007. }
  1008. else
  1009. {
  1010. $this->cached[$key] = $item;
  1011. return $item['time'];
  1012. }
  1013. }
  1014. /* Sets creation time of cache entry. Expects key string and time to set. */
  1015. function set_mtime($key, $time)
  1016. {
  1017. if (!$this->enabled)
  1018. {
  1019. return false;
  1020. }
  1021. $item = $this->connection->get($this->prefix . $key);
  1022. if (empty($item['time']))
  1023. {
  1024. return false;
  1025. }
  1026. else
  1027. {
  1028. $item['time'] = $time;
  1029. $this->connection->set($this->prefix . $key, $item);
  1030. }
  1031. }
  1032. function get_cache_size($mask, $number = false)
  1033. {
  1034. if (!$this->enabled)
  1035. {
  1036. if ($number === false)
  1037. {
  1038. return 0;
  1039. }
  1040. else
  1041. {
  1042. return array(0,0);
  1043. }
  1044. }
  1045. $size = 0;
  1046. $count = 0;
  1047. $all_files = $this->connection->get('webo_files_list');
  1048. if(($all_files === false) || !is_array($all_files))
  1049. {
  1050. $this->connection->flush();
  1051. $this->connection->set('webo_files_list', array());
  1052. }
  1053. else
  1054. {
  1055. foreach($all_files as $key => $value)
  1056. {
  1057. if(@preg_match('/^' . strtr(addcslashes($mask, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  1058. {
  1059. $item = $this->connection->get($this->prefix . $key);
  1060. if ($item !== false)
  1061. {
  1062. $count++;
  1063. $size += strlen(serialize($item));
  1064. }
  1065. }
  1066. }
  1067. }
  1068. if ($number === false)
  1069. {
  1070. return $size;
  1071. }
  1072. else
  1073. {
  1074. return array($size, $count);
  1075. }
  1076. }
  1077. }
  1078. class webo_cache_apc extends webo_cache_engine {
  1079. /* Class constructor. Expects options array. */
  1080. function webo_cache_apc($options)
  1081. {
  1082. if(function_exists('apc_add'))
  1083. {
  1084. ini_set('apc.slam_defense','Off');
  1085. $this->enabled = true;
  1086. }
  1087. else
  1088. {
  1089. $this->enabled = false;
  1090. }
  1091. $this->cached = array();
  1092. $this->prefix = 'webo_cache_';
  1093. }
  1094. /* Adds or updates entry. Expects key string and value to cache. */
  1095. function put_entry($key, $value, $time)
  1096. {
  1097. if (!$this->enabled)
  1098. {
  1099. return;
  1100. }
  1101. $entries = apc_fetch('webo_files_list');
  1102. if(($entries === false) || !is_array($entries)) //filelist is broken or removed from server so we need to clear cache
  1103. {
  1104. apc_clear_cache('user');
  1105. $entries = array();
  1106. }
  1107. apc_store($this->prefix . $key, array('value' => $value, 'time' => $time));
  1108. $entries[$key] = 1;
  1109. apc_store('webo_files_list', $entries);
  1110. }
  1111. /* Get cache entry by key. Expects key string. */
  1112. function get_entry($key)
  1113. {
  1114. if (!$this->enabled)
  1115. {
  1116. return false;
  1117. }
  1118. if (!empty($this->cached[$key]['value']))
  1119. {
  1120. return $this->cached[$key]['value'];
  1121. }
  1122. $item = apc_fetch($this->prefix . $key);
  1123. if(empty($item['value']))
  1124. {
  1125. return false;
  1126. }
  1127. else
  1128. {
  1129. $this->cached[$key] = $item;
  1130. return $item['value'];
  1131. }
  1132. }
  1133. /* Clear cache entries by pattern(s). Expects pattern or array of patterns. */
  1134. function delete_entries($patterns)
  1135. {
  1136. if (!$this->enabled)
  1137. {
  1138. return false;
  1139. }
  1140. if (!empty($patterns))
  1141. {
  1142. $all_files = apc_fetch('webo_files_list');
  1143. if(($all_files === false) || !is_array($all_files))
  1144. {
  1145. apc_clear_cache('user');
  1146. apc_store('webo_files_list', array());
  1147. return;
  1148. }
  1149. if (is_array($patterns))
  1150. {
  1151. foreach($patterns as $pattern)
  1152. {
  1153. foreach($all_files as $key => $value)
  1154. {
  1155. if(@preg_match('/^' . strtr(addcslashes($pattern, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  1156. {
  1157. apc_delete($this->prefix . $key);
  1158. unset($all_files[$key]);
  1159. }
  1160. }
  1161. }
  1162. apc_store('webo_files_list', $all_files);
  1163. }
  1164. else
  1165. {
  1166. foreach($all_files as $key => $value)
  1167. {
  1168. if(@preg_match('/^' . strtr(addcslashes($patterns, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  1169. {
  1170. apc_delete($this->prefix . $key);
  1171. unset($all_files[$key]);
  1172. }
  1173. }
  1174. apc_store('webo_files_list', $all_files);
  1175. }
  1176. }
  1177. }
  1178. /* Gets creation time of cache entry. Expects key string. */
  1179. function get_mtime($key)
  1180. {
  1181. if (!$this->enabled)
  1182. {
  1183. return 0;
  1184. }
  1185. if(!empty($this->cached[$key]['time']))
  1186. {
  1187. return $this->cached[$key]['time'];
  1188. }
  1189. $item = apc_fetch($this->prefix . $key);
  1190. if (empty($item['time']))
  1191. {
  1192. return 0;
  1193. }
  1194. else
  1195. {
  1196. $this->cached[$key] = $item;
  1197. return $item['time'];
  1198. }
  1199. }
  1200. /* Sets creation time of cache entry. Expects key string and time to set. */
  1201. function set_mtime($key, $time)
  1202. {
  1203. if (!$this->enabled)
  1204. {
  1205. return false;
  1206. }
  1207. $item = apc_fetch($this->prefix . $key);
  1208. if (empty($item['time']))
  1209. {
  1210. return false;
  1211. }
  1212. else
  1213. {
  1214. $item['time'] = $time;
  1215. apc_store($key, $item);
  1216. }
  1217. }
  1218. function get_cache_size($mask, $number = false)
  1219. {
  1220. if (!$this->enabled)
  1221. {
  1222. if ($number === false)
  1223. {
  1224. return 0;
  1225. }
  1226. else
  1227. {
  1228. return array(0,0);
  1229. }
  1230. }
  1231. $size = 0;
  1232. $count = 0;
  1233. $all_files = apc_fetch('webo_files_list');
  1234. if(($all_files === false) || !is_array($all_files))
  1235. {
  1236. apc_clear_cache();
  1237. apc_store('webo_files_list', array());
  1238. }
  1239. else
  1240. {
  1241. foreach($all_files as $key => $value)
  1242. {
  1243. if(@preg_match('/^' . strtr(addcslashes($mask, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  1244. {
  1245. $item = apc_fetch($this->prefix . $key);
  1246. if ($item !== false)
  1247. {
  1248. $count++;
  1249. $size += strlen(serialize($item));
  1250. }
  1251. }
  1252. }
  1253. }
  1254. if ($number === false)
  1255. {
  1256. return $size;
  1257. }
  1258. else
  1259. {
  1260. return array($size, $count);
  1261. }
  1262. }
  1263. }
  1264. class webo_cache_xcache extends webo_cache_engine {
  1265. /* Class constructor. Expects options array. */
  1266. function webo_cache_xcache($options)
  1267. {
  1268. if(function_exists('xcache_set'))
  1269. {
  1270. $this->enabled = true;
  1271. }
  1272. else
  1273. {
  1274. $this->enabled = false;
  1275. }
  1276. $this->cached = array();
  1277. $this->prefix = 'webo_cache_';
  1278. }
  1279. /* Adds or updates entry. Expects key string and value to cache. */
  1280. function put_entry($key, $value, $time)
  1281. {
  1282. if (!$this->enabled)
  1283. {
  1284. return;
  1285. }
  1286. $entries = xcache_get('webo_files_list');
  1287. if(($entries === NULL) || !is_array($entries)) //filelist is broken or removed from server so we need to clear cache
  1288. {
  1289. xcache_unset('user');
  1290. $entries = array();
  1291. }
  1292. xcache_set($this->prefix . $key, array('value' => $value, 'time' => $time));
  1293. $entries[$key] = 1;
  1294. xcache_set('webo_files_list', $entries);
  1295. }
  1296. /* Get cache entry by key. Expects key string. */
  1297. function get_entry($key)
  1298. {
  1299. if (!$this->enabled)
  1300. {
  1301. return false;
  1302. }
  1303. if (!empty($this->cached[$key]['value']))
  1304. {
  1305. return $this->cached[$key]['value'];
  1306. }
  1307. $item = xcache_get($this->prefix . $key);
  1308. if(empty($item['value']))
  1309. {
  1310. return false;
  1311. }
  1312. else
  1313. {
  1314. $this->cached[$key] = $item;
  1315. return $item['value'];
  1316. }
  1317. }
  1318. /* Clear cache entries by pattern(s). Expects pattern or array of patterns. */
  1319. function delete_entries($patterns)
  1320. {
  1321. if (!$this->enabled)
  1322. {
  1323. return false;
  1324. }
  1325. if (!empty($patterns))
  1326. {
  1327. $all_files = xcache_get('webo_files_list');
  1328. if(($all_files === NULL) || !is_array($all_files))
  1329. {
  1330. xcache_unset('user');
  1331. xcache_set('webo_files_list', array());
  1332. return;
  1333. }
  1334. if (is_array($patterns))
  1335. {
  1336. foreach($patterns as $pattern)
  1337. {
  1338. foreach($all_files as $key => $value)
  1339. {
  1340. if(@preg_match('/^' . strtr(addcslashes($pattern, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  1341. {
  1342. xcache_unset($this->prefix . $key);
  1343. unset($all_files[$key]);
  1344. }
  1345. }
  1346. }
  1347. xcache_set('webo_files_list', $all_files);
  1348. }
  1349. else
  1350. {
  1351. foreach($all_files as $key => $value)
  1352. {
  1353. if(@preg_match('/^' . strtr(addcslashes($patterns, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  1354. {
  1355. xcache_unset($this->prefix . $key);
  1356. unset($all_files[$key]);
  1357. }
  1358. }
  1359. xcache_set('webo_files_list', $all_files);
  1360. }
  1361. }
  1362. }
  1363. /* Gets creation time of cache entry. Expects key string. */
  1364. function get_mtime($key)
  1365. {
  1366. if (!$this->enabled)
  1367. {
  1368. return 0;
  1369. }
  1370. if(!empty($this->cached[$key]['time']))
  1371. {
  1372. return $this->cached[$key]['time'];
  1373. }
  1374. $item = xcache_get($this->prefix . $key);
  1375. if (empty($item['time']))
  1376. {
  1377. return 0;
  1378. }
  1379. else
  1380. {
  1381. $this->cached[$key] = $item;
  1382. return $item['time'];
  1383. }
  1384. }
  1385. /* Sets creation time of cache entry. Expects key string and time to set. */
  1386. function set_mtime($key, $time)
  1387. {
  1388. if (!$this->enabled)
  1389. {
  1390. return false;
  1391. }
  1392. $item = xcache_get($this->prefix . $key);
  1393. if (empty($item['time']))
  1394. {
  1395. return false;
  1396. }
  1397. else
  1398. {
  1399. $item['time'] = $time;
  1400. xcache_set($key, $item);
  1401. }
  1402. }
  1403. function get_cache_size($mask, $number = false)
  1404. {
  1405. if (!$this->enabled)
  1406. {
  1407. if ($number === false)
  1408. {
  1409. return 0;
  1410. }
  1411. else
  1412. {
  1413. return array(0,0);
  1414. }
  1415. }
  1416. $size = 0;
  1417. $count = 0;
  1418. $all_files = xcache_get('webo_files_list');
  1419. if(($all_files === NULL) || !is_array($all_files))
  1420. {
  1421. xcache_clear_cache();
  1422. xcache_set('webo_files_list', array());
  1423. }
  1424. else
  1425. {
  1426. foreach($all_files as $key => $value)
  1427. {
  1428. if(@preg_match('/^' . strtr(addcslashes($mask, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $key))
  1429. {
  1430. $item = xcache_get($this->prefix . $key);
  1431. if ($item !== NULL)
  1432. {
  1433. $count++;
  1434. $size += strlen(serialize($item));
  1435. }
  1436. }
  1437. }
  1438. }
  1439. if ($number === false)
  1440. {
  1441. return $size;
  1442. }
  1443. else
  1444. {
  1445. return array($size, $count);
  1446. }
  1447. }
  1448. }
  1449. ?>