PageRenderTime 47ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/bitrix/modules/main/classes/general/cache_files_cleaner.php

https://gitlab.com/neuser/bitrix-core
PHP | 324 lines | 286 code | 26 blank | 12 comment | 42 complexity | 521f2e52c36ea68c068db79943c31b93 MD5 | raw file
  1. <?
  2. class CFileCacheCleaner
  3. {
  4. private $_CacheType;
  5. private $_arPath;
  6. private $_CurrentBase;
  7. private $_CurrentPath;
  8. private $_obFileTree;
  9. function __construct($CacheType)
  10. {
  11. global $DB;
  12. $this->_CacheType = $CacheType;
  13. switch($this->_CacheType)
  14. {
  15. case "menu":
  16. $this->_arPath = array(
  17. BX_PERSONAL_ROOT.'/managed_cache/'.$DB->type.'/menu/',
  18. );
  19. break;
  20. case "managed":
  21. $this->_arPath = array(
  22. BX_PERSONAL_ROOT.'/managed_cache/',
  23. BX_PERSONAL_ROOT.'/stack_cache/',
  24. );
  25. break;
  26. case "html":
  27. $this->_arPath = array(
  28. BX_PERSONAL_ROOT.'/html_pages/',
  29. );
  30. break;
  31. case "expired":
  32. $this->_arPath = array(
  33. BX_PERSONAL_ROOT.'/cache/',
  34. BX_PERSONAL_ROOT.'/managed_cache/',
  35. BX_PERSONAL_ROOT.'/stack_cache/',
  36. );
  37. break;
  38. default:
  39. $this->_arPath = array(
  40. BX_PERSONAL_ROOT.'/cache/',
  41. BX_PERSONAL_ROOT.'/managed_cache/',
  42. BX_PERSONAL_ROOT.'/stack_cache/',
  43. BX_PERSONAL_ROOT.'/html_pages/',
  44. );
  45. break;
  46. }
  47. }
  48. function InitPath($PathToCheck)
  49. {
  50. if($PathToCheck <> '')
  51. {
  52. $PathToCheck = preg_replace("#[\\\\\\/]+#", "/", "/".$PathToCheck);
  53. //Check if path does not contain any injection
  54. if(preg_match('#/\\.\\.#', $PathToCheck) || preg_match('#\\.\\./#', $PathToCheck))
  55. return false;
  56. $base = "";
  57. foreach($this->_arPath as $path)
  58. {
  59. if(preg_match('#^'.$path.'#', $PathToCheck))
  60. {
  61. $base = $path;
  62. break;
  63. }
  64. }
  65. if($base <> '')
  66. {
  67. $this->_CurrentBase = $base;
  68. $this->_CurrentPath = mb_substr($PathToCheck, mb_strlen($base));
  69. return true;
  70. }
  71. else
  72. {
  73. return false;
  74. }
  75. }
  76. else
  77. {
  78. $this->_CurrentBase = $this->_arPath[0];
  79. $this->_CurrentPath = "";
  80. return true;
  81. }
  82. }
  83. function Start()
  84. {
  85. if($this->_CurrentBase)
  86. {
  87. $this->_obFileTree = new _CFileTree($_SERVER["DOCUMENT_ROOT"].$this->_CurrentBase);
  88. $this->_obFileTree->Start($this->_CurrentPath);
  89. }
  90. }
  91. function GetNextFile()
  92. {
  93. if(is_object($this->_obFileTree))
  94. {
  95. $file = $this->_obFileTree->GetNextFile();
  96. //Check if current cache subdirectory cleaned
  97. if($file === false)
  98. {
  99. //Skip all checked bases
  100. $arPath = $this->_arPath;
  101. while(count($arPath) > 0)
  102. {
  103. $CurBase = array_shift($arPath);
  104. if($CurBase == $this->_CurrentBase)
  105. break;
  106. }
  107. //There is at least one cache directory not checked yet
  108. //so try to find a file inside
  109. while(count($arPath) > 0)
  110. {
  111. $this->_CurrentBase = array_shift($arPath);
  112. $this->_CurrentPath = "";
  113. $this->_obFileTree = new _CFileTree($_SERVER["DOCUMENT_ROOT"].$this->_CurrentBase);
  114. $this->_obFileTree->Start($this->_CurrentPath);
  115. $file = $this->_obFileTree->GetNextFile();
  116. if($file !== false)
  117. return $file;
  118. }
  119. return false;
  120. }
  121. return $file;
  122. }
  123. else
  124. {
  125. return false;
  126. }
  127. }
  128. function GetFileExpiration($FileName)
  129. {
  130. if(preg_match('#^'.$_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT.'/html_pages/.*\\.html$#', $FileName))
  131. {
  132. return 1;//like an very old file
  133. }
  134. elseif(preg_match('#\\.~\\d+/#', $FileName)) //delayed delete files
  135. {
  136. return 1;//like an very old file
  137. }
  138. elseif(mb_substr($FileName, -4) == ".php")
  139. {
  140. $fd = fopen($FileName, "rb");
  141. if($fd)
  142. {
  143. $header = fread($fd, 150);
  144. fclose($fd);
  145. if(preg_match("/dateexpire\s*=\s*'([\d]+)'/im", $header, $match))
  146. return doubleval($match[1]);
  147. }
  148. }
  149. elseif(mb_substr($FileName, -5) == ".html")
  150. {
  151. $fd = fopen($FileName, "rb");
  152. if($fd)
  153. {
  154. $header = fread($fd, 26);
  155. fclose($fd);
  156. if(mb_substr($header, 0, 2) == "BX")
  157. return doubleval(mb_substr($header, 14, 12));
  158. }
  159. }
  160. return false;
  161. }
  162. }
  163. class _CFileTree
  164. {
  165. var $_in_path = '/';
  166. var $_path = '';
  167. var $_dir = false;
  168. function __construct($in_path="/")
  169. {
  170. $this->_in_path = preg_replace("#[\\\\\\/]+#", "/", $in_path);
  171. }
  172. function Start($path="/")
  173. {
  174. $this->_path = preg_replace("#[\\\\\\/]+#", "/", $this->_in_path.trim($path, "/"));
  175. if(!$this->FileExists($this->_path) || is_file($this->_path))
  176. {
  177. $last = self::ExtractFileFromPath($this->_path);
  178. $this->_dir = $this->ReadDir($this->_path);
  179. if(is_array($this->_dir))
  180. {
  181. while(count($this->_dir))
  182. {
  183. if(strcmp($this->_dir[0], $last) > 0)
  184. break;
  185. array_shift($this->_dir);
  186. }
  187. }
  188. }
  189. }
  190. function FileExists($file)
  191. {
  192. if(function_exists('accelerator_reset'))
  193. {
  194. if(is_dir($file))
  195. return true;
  196. $fd = @fopen($file, "rb");
  197. if($fd)
  198. {
  199. fclose($fd);
  200. return true;
  201. }
  202. else
  203. {
  204. return false;
  205. }
  206. }
  207. else
  208. {
  209. return file_exists($file);
  210. }
  211. }
  212. function GetNextFile()
  213. {
  214. if(!is_array($this->_dir))
  215. {
  216. $this->_dir = $this->ReadDir($this->_path);
  217. if(!is_array($this->_dir))
  218. return false;
  219. }
  220. $next = current($this->_dir);
  221. next($this->_dir);
  222. if($next === false)
  223. {
  224. //try to go up dir tree
  225. if($this->GoUp())
  226. return $this->GetNextFile();
  227. else
  228. return false;
  229. }
  230. elseif(is_file($next))
  231. {
  232. //it's our target
  233. return $next;
  234. }
  235. else
  236. {
  237. //it's dir or link try to go deeper
  238. $this->_path = $next;
  239. $this->_dir = false;
  240. return true;
  241. }
  242. }
  243. public static function ExtractFileFromPath(&$path)
  244. {
  245. $arPath = explode("/", $path);
  246. $last = array_pop($arPath);
  247. $path = implode("/", $arPath);
  248. return $path."/".$last;
  249. }
  250. function GoUp()
  251. {
  252. $last_dir = self::ExtractFileFromPath($this->_path);
  253. //We are not going to go up any more
  254. if(mb_strlen($this->_path."/") < mb_strlen($this->_in_path))
  255. return false;
  256. $this->_dir = $this->ReadDir($this->_path);
  257. //This should't be happen so try to goup one more level
  258. if(!is_array($this->_dir))
  259. return $this->GoUp();
  260. //Skip all dirs till current
  261. while(count($this->_dir))
  262. {
  263. if(strcmp($this->_dir[0], $last_dir) > 0)
  264. break;
  265. array_shift($this->_dir);
  266. }
  267. if(count($this->_dir))
  268. return true; //there is more work to do
  269. else
  270. return $this->GoUp(); // try to go upper
  271. }
  272. function ReadDir($dir)
  273. {
  274. $dir = rtrim($dir, "/");
  275. if(is_dir($dir))
  276. {
  277. $dh = opendir($dir);
  278. if($dh)
  279. {
  280. $result = array();
  281. while(($f = readdir($dh)) !== false)
  282. {
  283. if($f == "." || $f == "..")
  284. continue;
  285. $result[] = $dir."/".$f;
  286. }
  287. closedir($dh);
  288. sort($result);
  289. //try to delete an empty directory
  290. if(count($result) == 0)
  291. @rmdir($dir);
  292. return $result;
  293. }
  294. }
  295. return false;
  296. }
  297. }
  298. ?>