* This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ /** * handles updating the filecache according to outside changes */ class OC_FileCache_Update{ /** * check if a file or folder is updated outside owncloud * @param string path * @param string root (optional) * @param boolean folder * @return bool */ public static function hasUpdated($path, $root=false, $folder=false) { if($root===false) { $view=OC_Filesystem::getView(); }else{ $view=new OC_FilesystemView($root); } if(!$view->file_exists($path)) { return false; } $cachedData=OC_FileCache_Cached::get($path, $root); if(isset($cachedData['mtime'])) { $cachedMTime=$cachedData['mtime']; if($folder) { return $view->hasUpdated($path.'/', $cachedMTime); }else{ return $view->hasUpdated($path, $cachedMTime); } }else{//file not in cache, so it has to be updated if(($path=='/' or $path=='') and $root===false) {//dont auto update the home folder, it will be scanned return false; } return true; } } /** * delete non existing files from the cache */ public static function cleanFolder($path, $root=false) { if($root===false) { $view=OC_Filesystem::getView(); }else{ $view=new OC_FilesystemView($root); } $cachedContent=OC_FileCache_Cached::getFolderContent($path, $root); foreach($cachedContent as $fileData) { $path=$fileData['path']; $file=$view->getRelativePath($path); if(!$view->file_exists($file)) { if($root===false) {//filesystem hooks are only valid for the default root OC_Hook::emit('OC_Filesystem', 'post_delete', array('path'=>$file)); }else{ self::delete($file, $root); } } } } /** * update the cache according to changes in the folder * @param string path * @param string root (optional) */ public static function updateFolder($path, $root=false) { if($root===false) { $view=OC_Filesystem::getView(); }else{ $view=new OC_FilesystemView($root); } $dh=$view->opendir($path.'/'); if($dh) {//check for changed/new files while (($filename = readdir($dh)) !== false) { if($filename != '.' and $filename != '..' and $filename != '') { $file=$path.'/'.$filename; $isDir=$view->is_dir($file); if(self::hasUpdated($file, $root, $isDir)) { if($isDir) { self::updateFolder($file, $root); }elseif($root===false) {//filesystem hooks are only valid for the default root OC_Hook::emit('OC_Filesystem', 'post_write', array('path'=>$file)); }else{ self::update($file, $root); } } } } } self::cleanFolder($path, $root); //update the folder last, so we can calculate the size correctly if($root===false) {//filesystem hooks are only valid for the default root OC_Hook::emit('OC_Filesystem', 'post_write', array('path'=>$path)); }else{ self::update($path, $root); } } /** * called when changes are made to files * @param array $params * @param string root (optional) */ public static function fileSystemWatcherWrite($params) { $path=$params['path']; self::update($path); } /** * called when files are deleted * @param array $params * @param string root (optional) */ public static function fileSystemWatcherDelete($params) { $path=$params['path']; self::delete($path); } /** * called when files are deleted * @param array $params * @param string root (optional) */ public static function fileSystemWatcherRename($params) { $oldPath=$params['oldpath']; $newPath=$params['newpath']; self::rename($oldPath, $newPath); } /** * update the filecache according to changes to the filesystem * @param string path * @param string root (optional) */ public static function update($path, $root=false) { if($root===false) { $view=OC_Filesystem::getView(); }else{ $view=new OC_FilesystemView($root); } $mimetype=$view->getMimeType($path); $size=0; $cached=OC_FileCache_Cached::get($path, $root); $cachedSize=isset($cached['size'])?$cached['size']:0; if($view->is_dir($path.'/')) { if(OC_FileCache::inCache($path, $root)) { $cachedContent=OC_FileCache_Cached::getFolderContent($path, $root); foreach($cachedContent as $file) { $size+=$file['size']; } $mtime=$view->filemtime($path.'/'); $ctime=$view->filectime($path.'/'); $writable=$view->is_writable($path.'/'); OC_FileCache::put($path, array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype, 'writable'=>$writable)); }else{ $count=0; OC_FileCache::scan($path, null, $count, $root); return; //increaseSize is already called inside scan } }else{ $size=OC_FileCache::scanFile($path, $root); } if($path !== '' and $path !== '/') { OC_FileCache::increaseSize(dirname($path), $size-$cachedSize, $root); } } /** * update the filesystem after a delete has been detected * @param string path * @param string root (optional) */ public static function delete($path, $root=false) { $cached=OC_FileCache_Cached::get($path, $root); if(!isset($cached['size'])) { return; } $size=$cached['size']; OC_FileCache::increaseSize(dirname($path), -$size, $root); OC_FileCache::delete($path, $root); } /** * update the filesystem after a rename has been detected * @param string oldPath * @param string newPath * @param string root (optional) */ public static function rename($oldPath, $newPath, $root=false) { if(!OC_FileCache::inCache($oldPath, $root)) { return; } if($root===false) { $view=OC_Filesystem::getView(); }else{ $view=new OC_FilesystemView($root); } $cached=OC_FileCache_Cached::get($oldPath, $root); $oldSize=$cached['size']; OC_FileCache::increaseSize(dirname($oldPath), -$oldSize, $root); OC_FileCache::increaseSize(dirname($newPath), $oldSize, $root); OC_FileCache::move($oldPath, $newPath); } /** * delete files owned by user from the cache * @param string $parameters$parameters["uid"]) */ public static function deleteFromUser($parameters) { OC_FileCache::clear($parameters["uid"]); } }