PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/nube/lib/filecache.php

https://bitbucket.org/iestprpp/sistemaweb
PHP | 742 lines | 525 code | 33 blank | 184 comment | 93 complexity | e2bc189b3885aae8382c85f1caf3ceb1 MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-2.1, MPL-2.0-no-copyleft-exception, AGPL-3.0, AGPL-1.0, BSD-2-Clause
  1. <?php
  2. /**
  3. * @author Robin Appelman
  4. * @copyright 2011 Robin Appelman icewind1991@gmail.com
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public
  17. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. /**
  21. * provide caching for filesystem info in the database
  22. *
  23. * not used by OC_Filesystem for reading filesystem info,
  24. * instread apps should use OC_FileCache::get where possible
  25. *
  26. * It will try to keep the data up to date but changes from outside ownCloud can invalidate the cache
  27. */
  28. class OC_FileCache{
  29. private static $savedData=array();
  30. /**
  31. * get the filesystem info from the cache
  32. * @param string path
  33. * @param string root (optional)
  34. * @return array
  35. *
  36. * returns an assiciative array with the following keys:
  37. * - size
  38. * - mtime
  39. * - ctime
  40. * - mimetype
  41. * - encrypted
  42. * - versioned
  43. */
  44. public static function get($path,$root=''){
  45. if(self::isUpdated($path,$root)){
  46. if(!$root){//filesystem hooks are only valid for the default root
  47. OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path));
  48. }else{
  49. self::fileSystemWatcherWrite(array('path'=>$path),$root);
  50. }
  51. }
  52. if(!$root){
  53. $root=OC_Filesystem::getRoot();
  54. }
  55. if($root=='/'){
  56. $root='';
  57. }
  58. $path=$root.$path;
  59. $query=OC_DB::prepare('SELECT ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path_hash=?');
  60. $result=$query->execute(array(md5($path)))->fetchRow();
  61. if(is_array($result)){
  62. return $result;
  63. }else{
  64. OC_Log::write('files','get(): file not found in cache ('.$path.')',OC_Log::DEBUG);
  65. return false;
  66. }
  67. }
  68. /**
  69. * put filesystem info in the cache
  70. * @param string $path
  71. * @param array data
  72. * @param string root (optional)
  73. *
  74. * $data is an assiciative array in the same format as returned by get
  75. */
  76. public static function put($path,$data,$root=''){
  77. if(!$root){
  78. $root=OC_Filesystem::getRoot();
  79. }
  80. if($root=='/'){
  81. $root='';
  82. }
  83. $path=$root.$path;
  84. $parent=self::getParentId($path);
  85. $id=self::getFileId($path);
  86. if(isset(OC_FileCache::$savedData[$path])){
  87. $data=array_merge(OC_FileCache::$savedData[$path],$data);
  88. unset(OC_FileCache::$savedData[$path]);
  89. }
  90. if($id!=-1){
  91. self::update($id,$data);
  92. return;
  93. }
  94. if(!isset($data['size']) or !isset($data['mtime'])){//save incomplete data for the next time we write it
  95. self::$savedData[$path]=$data;
  96. return;
  97. }
  98. if(!isset($data['encrypted'])){
  99. $data['encrypted']=false;
  100. }
  101. if(!isset($data['versioned'])){
  102. $data['versioned']=false;
  103. }
  104. $mimePart=dirname($data['mimetype']);
  105. $data['size']=(int)$data['size'];
  106. $data['ctime']=(int)$data['mtime'];
  107. $data['writable']=(int)$data['writable'];
  108. $data['encrypted']=(int)$data['encrypted'];
  109. $data['versioned']=(int)$data['versioned'];
  110. $user=OC_User::getUser();
  111. $query=OC_DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, path_hash, size, mtime, ctime, mimetype, mimepart,`user`,writable,encrypted,versioned) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)');
  112. $result=$query->execute(array($parent,basename($path),$path,md5($path),$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$user,$data['writable'],$data['encrypted'],$data['versioned']));
  113. if(OC_DB::isError($result)){
  114. OC_Log::write('files','error while writing file('.$path.') to cache',OC_Log::ERROR);
  115. }
  116. }
  117. /**
  118. * update filesystem info of a file
  119. * @param int $id
  120. * @param array $data
  121. */
  122. private static function update($id,$data){
  123. $arguments=array();
  124. $queryParts=array();
  125. foreach(array('size','mtime','ctime','mimetype','encrypted','versioned','writable') as $attribute){
  126. if(isset($data[$attribute])){
  127. //Convert to int it args are false
  128. if($data[$attribute] === false){
  129. $arguments[] = 0;
  130. }else{
  131. $arguments[] = $data[$attribute];
  132. }
  133. $queryParts[]=$attribute.'=?';
  134. }
  135. }
  136. if(isset($data['mimetype'])){
  137. $arguments[]=dirname($data['mimetype']);
  138. $queryParts[]='mimepart=?';
  139. }
  140. $arguments[]=$id;
  141. $sql = 'UPDATE *PREFIX*fscache SET '.implode(' , ',$queryParts).' WHERE id=?';
  142. $query=OC_DB::prepare($sql);
  143. $result=$query->execute($arguments);
  144. if(OC_DB::isError($result)){
  145. OC_Log::write('files','error while updating file('.$path.') in cache',OC_Log::ERROR);
  146. }
  147. }
  148. /**
  149. * register a file move in the cache
  150. * @param string oldPath
  151. * @param string newPath
  152. * @param string root (optional)
  153. */
  154. public static function move($oldPath,$newPath,$root=''){
  155. if(!$root){
  156. $root=OC_Filesystem::getRoot();
  157. }
  158. if($root=='/'){
  159. $root='';
  160. }
  161. $oldPath=$root.$oldPath;
  162. $newPath=$root.$newPath;
  163. $newParent=self::getParentId($newPath);
  164. $query=OC_DB::prepare('UPDATE *PREFIX*fscache SET parent=? ,name=?, path=?, path_hash=? WHERE path_hash=?');
  165. $query->execute(array($newParent,basename($newPath),$newPath,md5($newPath),md5($oldPath)));
  166. $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE path LIKE ?');
  167. $oldLength=strlen($oldPath);
  168. $updateQuery=OC_DB::prepare('UPDATE *PREFIX*fscache SET path=?, path_hash=? WHERE path_hash=?');
  169. while($row= $query->execute(array($oldPath.'/%'))->fetchRow()){
  170. $old=$row['path'];
  171. $new=$newPath.substr($old,$oldLength);
  172. $updateQuery->execute(array($new,md5($new),md5($old)));
  173. }
  174. }
  175. /**
  176. * delete info from the cache
  177. * @param string/int $file
  178. * @param string root (optional)
  179. */
  180. public static function delete($file,$root=''){
  181. if(!is_numeric($file)){
  182. if(!$root){
  183. $root=OC_Filesystem::getRoot();
  184. }
  185. if($root=='/'){
  186. $root='';
  187. }
  188. $path=$root.$file;
  189. self::delete(self::getFileId($path));
  190. }elseif($file!=-1){
  191. $query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE parent=?');
  192. $result=$query->execute(array($file));
  193. while($child=$result->fetchRow()){
  194. self::delete(intval($child['id']));
  195. }
  196. $query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE id=?');
  197. $query->execute(array($file));
  198. }
  199. }
  200. /**
  201. * return array of filenames matching the querty
  202. * @param string $query
  203. * @param boolean $returnData
  204. * @param string root (optional)
  205. * @return array of filepaths
  206. */
  207. public static function search($search,$returnData=false,$root=''){
  208. if(!$root){
  209. $root=OC_Filesystem::getRoot();
  210. }
  211. if($root=='/'){
  212. $root='';
  213. }
  214. $rootLen=strlen($root);
  215. if(!$returnData){
  216. $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE name LIKE ? AND `user`=?');
  217. }else{
  218. $query=OC_DB::prepare('SELECT * FROM *PREFIX*fscache WHERE name LIKE ? AND `user`=?');
  219. }
  220. $result=$query->execute(array("%$search%",OC_User::getUser()));
  221. $names=array();
  222. while($row=$result->fetchRow()){
  223. if(!$returnData){
  224. $names[]=substr($row['path'],$rootLen);
  225. }else{
  226. $row['path']=substr($row['path'],$rootLen);
  227. $names[]=$row;
  228. }
  229. }
  230. return $names;
  231. }
  232. /**
  233. * get all files and folders in a folder
  234. * @param string path
  235. * @param string root (optional)
  236. * @return array
  237. *
  238. * returns an array of assiciative arrays with the following keys:
  239. * - name
  240. * - size
  241. * - mtime
  242. * - ctime
  243. * - mimetype
  244. * - encrypted
  245. * - versioned
  246. */
  247. public static function getFolderContent($path,$root='',$mimetype_filter=''){
  248. if(self::isUpdated($path,$root,true)){
  249. self::updateFolder($path,$root);
  250. }
  251. if(!$root){
  252. $root=OC_Filesystem::getRoot();
  253. }
  254. if($root=='/'){
  255. $root='';
  256. }
  257. $path=$root.$path;
  258. $parent=self::getFileId($path);
  259. if($parent==-1){
  260. return array();
  261. }
  262. $query=OC_DB::prepare('SELECT name,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE parent=? AND (mimetype LIKE ? OR mimetype = ?)');
  263. $result=$query->execute(array($parent, $mimetype_filter.'%', 'httpd/unix-directory'))->fetchAll();
  264. if(is_array($result)){
  265. return $result;
  266. }else{
  267. OC_Log::write('files','getFolderContent(): file not found in cache ('.$path.')',OC_Log::DEBUG);
  268. return false;
  269. }
  270. }
  271. /**
  272. * check if a file or folder is in the cache
  273. * @param string $path
  274. * @param string root (optional)
  275. * @return bool
  276. */
  277. public static function inCache($path,$root=''){
  278. if(!$root){
  279. $root=OC_Filesystem::getRoot();
  280. }
  281. if($root=='/'){
  282. $root='';
  283. }
  284. $path=$root.$path;
  285. return self::getFileId($path)!=-1;
  286. }
  287. /**
  288. * get the file id as used in the cache
  289. * unlike the public getId, full paths are used here (/usename/files/foo instead of /foo)
  290. * @param string $path
  291. * @return int
  292. */
  293. private static function getFileId($path){
  294. $query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path_hash=?');
  295. if(OC_DB::isError($query)){
  296. OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR);
  297. return -1;
  298. }
  299. $result=$query->execute(array(md5($path)));
  300. if(OC_DB::isError($result)){
  301. OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR);
  302. return -1;
  303. }
  304. $result=$result->fetchRow();
  305. if(is_array($result)){
  306. return $result['id'];
  307. }else{
  308. OC_Log::write('files','getFileId(): file not found in cache ('.$path.')',OC_Log::DEBUG);
  309. return -1;
  310. }
  311. }
  312. /**
  313. * get the file id as used in the cache
  314. * @param string path
  315. * @param string root (optional)
  316. * @return int
  317. */
  318. public static function getId($path,$root=''){
  319. if(!$root){
  320. $root=OC_Filesystem::getRoot();
  321. }
  322. if($root=='/'){
  323. $root='';
  324. }
  325. $path=$root.$path;
  326. return self::getFileId($path);
  327. }
  328. /**
  329. * get the file path from the id, relative to the home folder of the user
  330. * @param int id
  331. * @param string user (optional)
  332. * @return string
  333. */
  334. public static function getPath($id,$user=''){
  335. if(!$user){
  336. $user=OC_User::getUser();
  337. }
  338. $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE id=? AND `user`=?');
  339. $result=$query->execute(array($id,$user));
  340. $row=$result->fetchRow();
  341. $path=$row['path'];
  342. $root='/'.$user.'/files';
  343. if(substr($path,0,strlen($root))!=$root){
  344. return false;
  345. }
  346. return substr($path,strlen($root));
  347. }
  348. /**
  349. * get the file id of the parent folder, taking into account '/' has no parent
  350. * @param string $path
  351. * @return int
  352. */
  353. private static function getParentId($path){
  354. if($path=='/'){
  355. return -1;
  356. }else{
  357. return self::getFileId(dirname($path));
  358. }
  359. }
  360. /**
  361. * called when changes are made to files
  362. * @param array $params
  363. * @param string root (optional)
  364. */
  365. public static function fileSystemWatcherWrite($params,$root=''){
  366. if(!$root){
  367. $view=OC_Filesystem::getView();
  368. }else{
  369. $view=new OC_FilesystemView(($root=='/')?'':$root);
  370. }
  371. $path=$params['path'];
  372. $fullPath=$view->getRoot().$path;
  373. $mimetype=$view->getMimeType($path);
  374. $dir=$view->is_dir($path.'/');
  375. //dont use self::get here, we don't want inifinte loops when a file has changed
  376. $cachedSize=self::getCachedSize($path,$root);
  377. $size=0;
  378. if($dir){
  379. if(self::inCache($path,$root) && $path != '/Shared'){
  380. $parent=self::getFileId($fullPath);
  381. $query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE parent=?');
  382. $result=$query->execute(array($parent));
  383. while($row=$result->fetchRow()){
  384. $size+=$row['size'];
  385. }
  386. $mtime=$view->filemtime($path);
  387. $ctime=$view->filectime($path);
  388. $writable=$view->is_writable($path);
  389. self::put($path,array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype,'writable'=>$writable));
  390. }else{
  391. $count=0;
  392. self::scan($path,null,$count,$root);
  393. }
  394. }else{
  395. $size=self::scanFile($path,$root);
  396. }
  397. self::increaseSize(dirname($fullPath),$size-$cachedSize);
  398. }
  399. public static function getCached($path,$root=''){
  400. if(!$root){
  401. $root=OC_Filesystem::getRoot();
  402. }else{
  403. if($root=='/'){
  404. $root='';
  405. }
  406. }
  407. $path=$root.$path;
  408. $query=OC_DB::prepare('SELECT ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path_hash=?');
  409. $result=$query->execute(array(md5($path)))->fetchRow();
  410. if(is_array($result)){
  411. if(isset(self::$savedData[$path])){
  412. $result=array_merge($result,self::$savedData[$path]);
  413. }
  414. return $result;
  415. }else{
  416. OC_Log::write('files','getChached(): file not found in cache ('.$path.')',OC_Log::DEBUG);
  417. if(isset(self::$savedData[$path])){
  418. return self::$savedData[$path];
  419. }else{
  420. return array();
  421. }
  422. }
  423. }
  424. private static function getCachedSize($path,$root){
  425. if(!$root){
  426. $root=OC_Filesystem::getRoot();
  427. }else{
  428. if($root=='/'){
  429. $root='';
  430. }
  431. }
  432. $path=$root.$path;
  433. $query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE path_hash=?');
  434. $result=$query->execute(array(md5($path)));
  435. if($row=$result->fetchRow()){
  436. return $row['size'];
  437. }else{//file not in cache
  438. return 0;
  439. }
  440. }
  441. /**
  442. * called when files are deleted
  443. * @param array $params
  444. * @param string root (optional)
  445. */
  446. public static function fileSystemWatcherDelete($params,$root=''){
  447. if(!$root){
  448. $root=OC_Filesystem::getRoot();
  449. }
  450. if($root=='/'){
  451. $root='';
  452. }
  453. $path=$params['path'];
  454. $fullPath=$root.$path;
  455. if(self::getFileId($fullPath)==-1){
  456. return;
  457. }
  458. $size=self::getCachedSize($path,$root);
  459. self::increaseSize(dirname($fullPath),-$size);
  460. self::delete($path);
  461. }
  462. /**
  463. * called when files are deleted
  464. * @param array $params
  465. * @param string root (optional)
  466. */
  467. public static function fileSystemWatcherRename($params,$root=''){
  468. if(!$root){
  469. $root=OC_Filesystem::getRoot();
  470. }
  471. if($root=='/'){
  472. $root='';
  473. }
  474. $oldPath=$params['oldpath'];
  475. $newPath=$params['newpath'];
  476. $fullOldPath=$root.$oldPath;
  477. $fullNewPath=$root.$newPath;
  478. if(($id=self::getFileId($fullOldPath))!=-1){
  479. $oldSize=self::getCachedSize($oldPath,$root);
  480. }else{
  481. return;
  482. }
  483. $size=OC_Filesystem::filesize($newPath);
  484. self::increaseSize(dirname($fullOldPath),-$oldSize);
  485. self::increaseSize(dirname($fullNewPath),$oldSize);
  486. self::move($oldPath,$newPath);
  487. }
  488. /**
  489. * adjust the size of the parent folders
  490. * @param string $path
  491. * @param int $sizeDiff
  492. */
  493. private static function increaseSize($path,$sizeDiff){
  494. if($sizeDiff==0) return;
  495. while(($id=self::getFileId($path))!=-1){//walk up the filetree increasing the size of all parent folders
  496. $query=OC_DB::prepare('UPDATE *PREFIX*fscache SET size=size+? WHERE id=?');
  497. $query->execute(array($sizeDiff,$id));
  498. $path=dirname($path);
  499. }
  500. }
  501. /**
  502. * recursively scan the filesystem and fill the cache
  503. * @param string $path
  504. * @param OC_EventSource $enventSource (optional)
  505. * @param int count (optional)
  506. * @param string root (optionak)
  507. */
  508. public static function scan($path,$eventSource=false,&$count=0,$root=''){
  509. if($eventSource){
  510. $eventSource->send('scanning',array('file'=>$path,'count'=>$count));
  511. }
  512. $lastSend=$count;
  513. if(!$root){
  514. $view=OC_Filesystem::getView();
  515. }else{
  516. $view=new OC_FilesystemView(($root=='/')?'':$root);
  517. }
  518. self::scanFile($path,$root);
  519. $dh=$view->opendir($path.'/');
  520. $totalSize=0;
  521. if($dh){
  522. while (($filename = readdir($dh)) !== false) {
  523. if($filename != '.' and $filename != '..'){
  524. $file=$path.'/'.$filename;
  525. if($view->is_dir($file.'/')){
  526. self::scan($file,$eventSource,$count,$root);
  527. }else{
  528. $totalSize+=self::scanFile($file,$root);
  529. $count++;
  530. if($count>$lastSend+25 and $eventSource){
  531. $lastSend=$count;
  532. $eventSource->send('scanning',array('file'=>$path,'count'=>$count));
  533. }
  534. }
  535. }
  536. }
  537. }
  538. self::cleanFolder($path,$root);
  539. self::increaseSize($view->getRoot().$path,$totalSize);
  540. }
  541. /**
  542. * scan a single file
  543. * @param string path
  544. * @param string root (optional)
  545. * @return int size of the scanned file
  546. */
  547. public static function scanFile($path,$root=''){
  548. if(!$root){
  549. $view=OC_Filesystem::getView();
  550. }else{
  551. $view=new OC_FilesystemView(($root=='/')?'':$root);
  552. }
  553. if(!$view->is_readable($path)) return; //cant read, nothing we can do
  554. clearstatcache();
  555. $mimetype=$view->getMimeType($path);
  556. $stat=$view->stat($path);
  557. if($mimetype=='httpd/unix-directory'){
  558. $writable=$view->is_writable($path.'/');
  559. }else{
  560. $writable=$view->is_writable($path);
  561. }
  562. $stat['mimetype']=$mimetype;
  563. $stat['writable']=$writable;
  564. if($path=='/'){
  565. $path='';
  566. }
  567. self::put($path,$stat,$root);
  568. return $stat['size'];
  569. }
  570. /**
  571. * find files by mimetype
  572. * @param string $part1
  573. * @param string $part2 (optional)
  574. * @param string root (optional)
  575. * @return array of file paths
  576. *
  577. * $part1 and $part2 together form the complete mimetype.
  578. * e.g. searchByMime('text','plain')
  579. *
  580. * seccond mimetype part can be ommited
  581. * e.g. searchByMime('audio')
  582. */
  583. public static function searchByMime($part1,$part2=null,$root=null){
  584. if(!$root){
  585. $root=OC_Filesystem::getRoot();
  586. }elseif($root=='/'){
  587. $root='';
  588. }
  589. $rootLen=strlen($root);
  590. $root .= '%';
  591. $user=OC_User::getUser();
  592. if(!$part2){
  593. $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimepart=? AND `user`=? AND path LIKE ?');
  594. $result=$query->execute(array($part1,$user, $root));
  595. }else{
  596. $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimetype=? AND `user`=? AND path LIKE ? ');
  597. $result=$query->execute(array($part1.'/'.$part2,$user, $root));
  598. }
  599. $names=array();
  600. while($row=$result->fetchRow()){
  601. $names[]=substr($row['path'],$rootLen);
  602. }
  603. return $names;
  604. }
  605. /**
  606. * check if a file or folder is updated outside owncloud
  607. * @param string path
  608. * @param string root (optional)
  609. * @param bool folder (optional)
  610. * @return bool
  611. */
  612. public static function isUpdated($path,$root='',$folder=false){
  613. if(!$root){
  614. $root=OC_Filesystem::getRoot();
  615. $view=OC_Filesystem::getView();
  616. }else{
  617. if($root=='/'){
  618. $root='';
  619. }
  620. $view=new OC_FilesystemView($root);
  621. }
  622. if(!$view->file_exists($path)){
  623. return false;
  624. }
  625. $mtime=$view->filemtime($path.(($folder)?'/':''));
  626. $isDir=$view->is_dir($path);
  627. $fullPath=$root.$path;
  628. $query=OC_DB::prepare('SELECT mtime FROM *PREFIX*fscache WHERE path_hash=?');
  629. $result=$query->execute(array(md5($fullPath)));
  630. if($row=$result->fetchRow()){
  631. $cachedMTime=$row['mtime'];
  632. return ($mtime>$cachedMTime);
  633. }else{//file not in cache, so it has to be updated
  634. if($path=='/' or $path==''){//dont auto update the root folder, it will be scanned
  635. return false;
  636. }
  637. return true;
  638. }
  639. }
  640. /**
  641. * update the cache according to changes in the folder
  642. * @param string path
  643. * @param string root (optional)
  644. */
  645. private static function updateFolder($path,$root=''){
  646. if(!$root){
  647. $view=OC_Filesystem::getView();
  648. }else{
  649. $view=new OC_FilesystemView(($root=='/')?'':$root);
  650. }
  651. $dh=$view->opendir($path.'/');
  652. if($dh){//check for changed/new files
  653. while (($filename = readdir($dh)) !== false) {
  654. if($filename != '.' and $filename != '..'){
  655. $file=$path.'/'.$filename;
  656. if(self::isUpdated($file,$root)){
  657. if(!$root){//filesystem hooks are only valid for the default root
  658. OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$file));
  659. }else{
  660. self::fileSystemWatcherWrite(array('path'=>$file),$root);
  661. }
  662. }
  663. }
  664. }
  665. }
  666. self::cleanFolder($path,$root);
  667. //update the folder last, so we can calculate the size correctly
  668. if(!$root){//filesystem hooks are only valid for the default root
  669. OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path));
  670. }else{
  671. self::fileSystemWatcherWrite(array('path'=>$path),$root);
  672. }
  673. }
  674. /**
  675. * delete non existing files from the cache
  676. */
  677. private static function cleanFolder($path,$root=''){
  678. if(!$root){
  679. $view=OC_Filesystem::getView();
  680. }else{
  681. $view=new OC_FilesystemView(($root=='/')?'':$root);
  682. }
  683. //check for removed files, not using getFolderContent to prevent loops
  684. $parent=self::getFileId($view->getRoot().$path);
  685. $query=OC_DB::prepare('SELECT name FROM *PREFIX*fscache WHERE parent=?');
  686. $result=$query->execute(array($parent));
  687. while($row=$result->fetchRow()){
  688. $file=$path.'/'.$row['name'];
  689. if(!$view->file_exists($file)){
  690. if(!$root){//filesystem hooks are only valid for the default root
  691. OC_Hook::emit('OC_Filesystem','post_delete',array('path'=>$file));
  692. }else{
  693. self::fileSystemWatcherDelete(array('path'=>$file),$root);
  694. }
  695. }
  696. }
  697. }
  698. /**
  699. * clean old pre-path_hash entries
  700. */
  701. public static function clean(){
  702. $query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE LENGTH(path_hash)<30');
  703. $query->execute();
  704. }
  705. }
  706. //watch for changes and try to keep the cache up to date
  707. OC_Hook::connect('OC_Filesystem','post_write','OC_FileCache','fileSystemWatcherWrite');
  708. OC_Hook::connect('OC_Filesystem','post_delete','OC_FileCache','fileSystemWatcherDelete');
  709. OC_Hook::connect('OC_Filesystem','post_rename','OC_FileCache','fileSystemWatcherRename');