diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php
index d6c799af32c76e8069edea19d3dfaa863eebde22..b779924cfb4f92fdc33f6600a61159e7adf2bee7 100644
--- a/apps/files/ajax/upload.php
+++ b/apps/files/ajax/upload.php
@@ -48,7 +48,7 @@ if(strpos($dir,'..') === false){
 	for($i=0;$i<$fileCount;$i++){
         $target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]);
 		if(is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i],$target)){
-			$meta=OC_FileCache::getCached($target);
+			$meta=OC_FileCache_Cached::get($target);
 			$result[]=array( "status" => "success", 'mime'=>$meta['mimetype'],'size'=>$meta['size'],'name'=>basename($target));
 		}
 	}
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
index 9fd57c0f02bd6d8e6ee65082b6f28008476d1eef..ad9bcf55f2b0506948aafb1a9c77d8fe914e6f25 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -59,7 +59,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
 	 * @return bool
 	 */
 	private static function isEncrypted($path){
-		$metadata=OC_FileCache::getCached($path,'');
+		$metadata=OC_FileCache_Cached::get($path,'');
 		return isset($metadata['encrypted']) and (bool)$metadata['encrypted'];
 	}
 	
diff --git a/lib/filecache.php b/lib/filecache.php
index 3fb8e4113cba2d85660fe5ddb0d74852fedc4f41..7c9c4dc41ffeb49cf16dd57108195cfa652e7d47 100644
--- a/lib/filecache.php
+++ b/lib/filecache.php
@@ -28,8 +28,6 @@
  * It will try to keep the data up to date but changes from outside ownCloud can invalidate the cache
  */
 class OC_FileCache{
-	private static $savedData=array();
-	
 	/**
 	 * get the filesystem info from the cache
 	 * @param string path
@@ -44,29 +42,15 @@ class OC_FileCache{
 	 * - encrypted
 	 * - versioned
 	 */
-	public static function get($path,$root=''){
-		if(self::isUpdated($path,$root)){
-			if(!$root){//filesystem hooks are only valid for the default root
+	public static function get($path,$root=false){
+		if(OC_FileCache_Update::hasUpdated($path,$root)){
+			if($root===false){//filesystem hooks are only valid for the default root
 				OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path));
 			}else{
-				self::fileSystemWatcherWrite(array('path'=>$path),$root);
+				OC_FileCache_Update::update($path,$root);
 			}
 		}
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-		}
-		if($root=='/'){
-			$root='';
-		}
-		$path=$root.$path;
-		$query=OC_DB::prepare('SELECT ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path_hash=?');
-		$result=$query->execute(array(md5($path)))->fetchRow();
-		if(is_array($result)){
-			return $result;
-		}else{
-			OC_Log::write('files','get(): file not found in cache ('.$path.')',OC_Log::DEBUG);
-			return false;
-		}
+		return OC_FileCache_Cached::get($path,$root);
 	}
 
 	/**
@@ -77,30 +61,23 @@ class OC_FileCache{
 	 *
 	 * $data is an assiciative array in the same format as returned by get
 	 */
-	public static function put($path,$data,$root=''){
-		if(!$root){
+	public static function put($path,$data,$root=false){
+		if($root===false){
 			$root=OC_Filesystem::getRoot();
 		}
-		if($root=='/'){
-			$root='';
-		}
 		$path=$root.$path;
-		if($path=='/'){
-			$parent=-1;
-		}else{
-			$parent=self::getFileId(dirname($path));
-		}
-		$id=self::getFileId($path);
+		$parent=self::getParentId($path);
+		$id=self::getId($path,'');
 		if($id!=-1){
 			self::update($id,$data);
 			return;
 		}
-		if(isset(self::$savedData[$path])){
-			$data=array_merge($data,self::$savedData[$path]);
-			unset(self::$savedData[$path]);
+		if(isset(OC_FileCache_Cached::$savedData[$path])){
+			$data=array_merge($data,OC_FileCache_Cached::$savedData[$path]);
+			unset(OC_FileCache_Cached::$savedData[$path]);
 		}
 		if(!isset($data['size']) or !isset($data['mtime'])){//save incomplete data for the next time we write it
-			self::$savedData[$path]=$data;
+			OC_FileCache_Cached::$savedData[$path]=$data;
 			return;
 		}
 		if(!isset($data['encrypted'])){
@@ -157,13 +134,10 @@ class OC_FileCache{
 	 * @param string newPath
 	 * @param string root (optional)
 	 */
-	public static function move($oldPath,$newPath,$root=''){
-		if(!$root){
+	public static function move($oldPath,$newPath,$root=false){
+		if($root===false){
 			$root=OC_Filesystem::getRoot();
 		}
-		if($root=='/'){
-			$root='';
-		}
 		$oldPath=$root.$oldPath;
 		$newPath=$root.$newPath;
 		$newParent=self::getParentId($newPath);
@@ -182,28 +156,19 @@ class OC_FileCache{
 
 	/**
 	 * delete info from the cache
-	 * @param string/int $file
+	 * @param string path
 	 * @param string root (optional)
 	 */
-	public static function delete($file,$root=''){
-		if(!is_numeric($file)){
-			if(!$root){
-				$root=OC_Filesystem::getRoot();
-			}
-			if($root=='/'){
-				$root='';
-			}
-			$path=$root.$file;
-			self::delete(self::getFileId($path));
-		}elseif($file!=-1){
-			$query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE parent=?');
-			$result=$query->execute(array($file));
-			while($child=$result->fetchRow()){
-				self::delete(intval($child['id']));
-			}
-			$query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE id=?');
-			$query->execute(array($file));
+	public static function delete($path,$root=false){
+		if($root===false){
+			$root=OC_Filesystem::getRoot();
 		}
+		$query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE path_hash=?');
+		$query->execute(array(md5($root.$path)));
+		
+		//delete everything inside the folder
+		$query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE path LIKE ?');
+		$query->execute(array($root.$path.'/%'));
 	}
 	
 	/**
@@ -213,13 +178,10 @@ class OC_FileCache{
 	 * @param string root (optional)
 	 * @return array of filepaths
 	 */
-	public static function search($search,$returnData=false,$root=''){
-		if(!$root){
+	public static function search($search,$returnData=false,$root=false){
+		if($root===false){
 			$root=OC_Filesystem::getRoot();
 		}
-		if($root=='/'){
-			$root='';
-		}
 		$rootLen=strlen($root);
 		if(!$returnData){
 			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE name LIKE ? AND `user`=?');
@@ -254,26 +216,11 @@ class OC_FileCache{
 	 * - encrypted
 	 * - versioned
 	 */
-  public static function getFolderContent($path,$root='',$mimetype_filter=''){
-		if(self::isUpdated($path,$root)){
-			self::updateFolder($path,$root);
-		}
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-		}
-		if($root=='/'){
-			$root='';
-		}
-		$path=$root.$path;
-		$parent=self::getFileId($path);
-    $query=OC_DB::prepare('SELECT name,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE parent=? AND (mimetype LIKE ? OR mimetype = ?)');
-    $result=$query->execute(array($parent, $mimetype_filter.'%', 'httpd/unix-directory'))->fetchAll();
-		if(is_array($result)){
-			return $result;
-		}else{
-			OC_Log::write('files','getFolderContent(): file not found in cache ('.$path.')',OC_Log::DEBUG);
-			return false;
+	public static function getFolderContent($path,$root=false,$mimetype_filter=''){
+		if(OC_FileCache_Update::hasUpdated($path,$root)){
+			OC_FileCache_Update::updateFolder($path,$root);
 		}
+		return OC_FileCache_Cached::getFolderContent($path,$root,$mimetype_filter);
 	}
 
 	/**
@@ -282,60 +229,36 @@ class OC_FileCache{
 	 * @param string root (optional)
 	 * @return bool
 	 */
-	public static function inCache($path,$root=''){
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-		}
-		if($root=='/'){
-			$root='';
-		}
-		$path=$root.$path;
-		return self::getFileId($path)!=-1;
+	public static function inCache($path,$root=false){
+		return self::getId($path,$root)!=-1;
 	}
 
 	/**
 	 * get the file id as used in the cache
-	 * unlike the public getId, full paths are used here (/usename/files/foo instead of /foo)
-	 * @param string $path
+	 * @param string path
+	 * @param string root (optional)
 	 * @return int
 	 */
-	private static function getFileId($path){
-		$query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path_hash=?');
-		if(OC_DB::isError($query)){
-			OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR);
-			return -1;
+	public static function getId($path,$root=false){
+		if($root===false){
+			$root=OC_Filesystem::getRoot();
 		}
-		$result=$query->execute(array(md5($path)));
+		
+		$query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path_hash=?');
+		$result=$query->execute(array(md5($root.$path)));
 		if(OC_DB::isError($result)){
 			OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR);
 			return -1;
 		}
+		
 		$result=$result->fetchRow();
 		if(is_array($result)){
 			return $result['id'];
 		}else{
-			OC_Log::write('files','getFileId(): file not found in cache ('.$path.')',OC_Log::DEBUG);
 			return -1;
 		}
 	}
 	
-	/**
-	 * get the file id as used in the cache
-	 * @param string path
-	 * @param string root (optional)
-	 * @return int
-	 */
-	public static function getId($path,$root=''){
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-		}
-		if($root=='/'){
-			$root='';
-		}
-		$path=$root.$path;
-		return self::getFileId($path);
-	}
-	
 	/**
 	 * get the file path from the id, relative to the home folder of the user
 	 * @param int id
@@ -366,154 +289,23 @@ class OC_FileCache{
 		if($path=='/'){
 			return -1;
 		}else{
-			return self::getFileId(dirname($path));
-		}
-	}
-
-	/**
-	 * called when changes are made to files
-	 * @param array $params
-	 * @param string root (optional)
-	 */
-	public static function fileSystemWatcherWrite($params,$root=''){
-		if(!$root){
-			$view=OC_Filesystem::getView();
-		}else{
-			$view=new OC_FilesystemView(($root=='/')?'':$root);
-		}
-		
-		$path=$params['path'];
-		$fullPath=$view->getRoot().$path;
-		$mimetype=$view->getMimeType($path);
-		$dir=$view->is_dir($path.'/');
-		//dont use self::get here, we don't want inifinte loops when a file has changed
-		$cachedSize=self::getCachedSize($path,$root);
-		$size=0;
-		if($dir){
-			if(self::inCache($path,$root)){
-				$parent=self::getFileId($fullPath);
-				$query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE parent=?');
-				$result=$query->execute(array($parent));
-				while($row=$result->fetchRow()){
-					$size+=$row['size'];
-				}
-				$mtime=$view->filemtime($path);
-				$ctime=$view->filectime($path);
-				$writable=$view->is_writable($path);
-				self::put($path,array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype,'writable'=>$writable));
-			}else{
-				$count=0;
-				self::scan($path,null,$count,$root);
-			}
-		}else{
-			$size=self::scanFile($path,$root);
-		}
-		self::increaseSize(dirname($fullPath),$size-$cachedSize);
-	}
-	
-	public static function getCached($path,$root=''){
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-		}else{
-			if($root=='/'){
-				$root='';
-			}
-		}
-		$path=$root.$path;
-		$query=OC_DB::prepare('SELECT ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path_hash=?');
-		$result=$query->execute(array(md5($path)))->fetchRow();
-		if(is_array($result)){
-			if(isset(self::$savedData[$path])){
-				$result=array_merge($result,self::$savedData[$path]);
-			}
-			return $result;
-		}else{
-			OC_Log::write('files','getCached(): file not found in cache ('.$path.')',OC_Log::DEBUG);
-			if(isset(self::$savedData[$path])){
-				return self::$savedData[$path];
-			}else{
-				return array();
-			}
+			return self::getId(dirname($path),'');
 		}
 	}
 	
-	private static function getCachedSize($path,$root){
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-		}else{
-			if($root=='/'){
-				$root='';
-			}
-		}
-		$path=$root.$path;
-		$query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE path_hash=?');
-		$result=$query->execute(array(md5($path)));
-		if($row=$result->fetchRow()){
-			return $row['size'];
-		}else{//file not in cache
-			return 0;
-		}
-	}
-
-	/**
-	 * called when files are deleted
-	 * @param array $params
-	 * @param string root (optional)
-	 */
-	public static function fileSystemWatcherDelete($params,$root=''){
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-		}
-		if($root=='/'){
-			$root='';
-		}
-		$path=$params['path'];
-		$fullPath=$root.$path;
-		if(self::getFileId($fullPath)==-1){
-			return;
-		}
-		$size=self::getCachedSize($path,$root);
-		self::increaseSize(dirname($fullPath),-$size);
-		self::delete($path);
-	}
-
-	/**
-	 * called when files are deleted
-	 * @param array $params
-	 * @param string root (optional)
-	 */
-	public static function fileSystemWatcherRename($params,$root=''){
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-		}
-		if($root=='/'){
-			$root='';
-		}
-		$oldPath=$params['oldpath'];
-		$newPath=$params['newpath'];
-		$fullOldPath=$root.$oldPath;
-		$fullNewPath=$root.$newPath;
-		if(($id=self::getFileId($fullOldPath))!=-1){
-			$oldSize=self::getCachedSize($oldPath,$root);
-		}else{
-			return;
-		}
-		$size=OC_Filesystem::filesize($newPath);
-		self::increaseSize(dirname($fullOldPath),-$oldSize);
-		self::increaseSize(dirname($fullNewPath),$oldSize);
-		self::move($oldPath,$newPath);
-	}
-
 	/**
 	 * adjust the size of the parent folders
 	 * @param string $path
 	 * @param int $sizeDiff
+	 * @param string root (optinal)
 	 */
-	private static function increaseSize($path,$sizeDiff){
+	public static function increaseSize($path,$sizeDiff, $root=false){
 		if($sizeDiff==0) return;
-		while(($id=self::getFileId($path))!=-1){//walk up the filetree increasing the size of all parent folders
+		$id=self::getId($path,'');
+		while($id!=-1){//walk up the filetree increasing the size of all parent folders
 			$query=OC_DB::prepare('UPDATE *PREFIX*fscache SET size=size+? WHERE id=?');
 			$query->execute(array($sizeDiff,$id));
+			$id=self::getParentId($path);
 			$path=dirname($path);
 		}
 	}
@@ -525,15 +317,15 @@ class OC_FileCache{
 	 * @param int count (optional)
 	 * @param string root (optionak)
 	 */
-	public static function scan($path,$eventSource=false,&$count=0,$root=''){
+	public static function scan($path,$eventSource=false,&$count=0,$root=false){
 		if($eventSource){
 			$eventSource->send('scanning',array('file'=>$path,'count'=>$count));
 		}
 		$lastSend=$count;
-		if(!$root){
+		if($root===false){
 			$view=OC_Filesystem::getView();
 		}else{
-			$view=new OC_FilesystemView(($root=='/')?'':$root);
+			$view=new OC_FilesystemView($root);
 		}
 		self::scanFile($path,$root);
 		$dh=$view->opendir($path.'/');
@@ -555,8 +347,9 @@ class OC_FileCache{
 				}
 			}
 		}
-		self::cleanFolder($path,$root);
-		self::increaseSize($view->getRoot().$path,$totalSize);
+		
+		OC_FileCache_Update::cleanFolder($path,$root);
+		self::increaseSize($path,$totalSize,$root);
 	}
 
 	/**
@@ -565,11 +358,11 @@ class OC_FileCache{
 	 * @param string root (optional)
 	 * @return int size of the scanned file
 	 */
-	public static function scanFile($path,$root=''){
-		if(!$root){
+	public static function scanFile($path,$root=false){
+		if($root===false){
 			$view=OC_Filesystem::getView();
 		}else{
-			$view=new OC_FilesystemView(($root=='/')?'':$root);
+			$view=new OC_FilesystemView($root);
 		}
 		if(!$view->is_readable($path)) return; //cant read, nothing we can do
 		clearstatcache();
@@ -602,11 +395,9 @@ class OC_FileCache{
 	 * seccond mimetype part can be ommited
 	 * e.g. searchByMime('audio')
 	 */
-	public static function searchByMime($part1,$part2=null,$root=null){
-		if(!$root){
+	public static function searchByMime($part1,$part2=null,$root=false){
+		if($root===false){
 			$root=OC_Filesystem::getRoot();
-		}elseif($root=='/'){
-			$root='';
 		}
 		$rootLen=strlen($root);
 		$root .= '%';
@@ -625,103 +416,6 @@ class OC_FileCache{
 		return $names;
 	}
 
-	/**
-	 * check if a file or folder is updated outside owncloud
-	 * @param string path
-	 * @param string root (optional)
-	 * @return bool
-	 */
-	public static function isUpdated($path,$root=''){
-		if(!$root){
-			$root=OC_Filesystem::getRoot();
-			$view=OC_Filesystem::getView();
-		}else{
-			if($root=='/'){
-				$root='';
-			}
-			$view=new OC_FilesystemView($root);
-		}
-		if(!$view->file_exists($path)){
-			return false;
-		}
-		$mtime=$view->filemtime($path);
-		$isDir=$view->is_dir($path);
-		$fullPath=$root.$path;
-		$query=OC_DB::prepare('SELECT mtime FROM *PREFIX*fscache WHERE path_hash=?');
-		$result=$query->execute(array(md5($fullPath)));
-		if($row=$result->fetchRow()){
-			$cachedMTime=$row['mtime'];
-			return ($mtime>$cachedMTime);
-		}else{//file not in cache, so it has to be updated
-			if($path=='/' or $path==''){//dont auto update the root folder, it will be scanned
-				return false;
-			}
-			return true;
-		}
-	}
-
-	/**
-	 * update the cache according to changes in the folder
-	 * @param string path
-	 * @param string root (optional)
-	 */
-	private static function updateFolder($path,$root=''){
-		if(!$root){
-			$view=OC_Filesystem::getView();
-		}else{
-			$view=new OC_FilesystemView(($root=='/')?'':$root);
-		}
-		$dh=$view->opendir($path.'/');
-		if($dh){//check for changed/new files
-			while (($filename = readdir($dh)) !== false) {
-				if($filename != '.' and $filename != '..'){
-					$file=$path.'/'.$filename;
-					if(self::isUpdated($file,$root)){
-						if(!$root){//filesystem hooks are only valid for the default root
-							OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$file));
-						}else{
-							self::fileSystemWatcherWrite(array('path'=>$file),$root);
-						}
-					}
-				}
-			}
-		}
-		
-		self::cleanFolder($path,$root);
-		
-		//update the folder last, so we can calculate the size correctly
-		if(!$root){//filesystem hooks are only valid for the default root
-			OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path));
-		}else{
-			self::fileSystemWatcherWrite(array('path'=>$path),$root);
-		}
-	}
-
-	/**
-	 * delete non existing files from the cache
-	 */
-	private static function cleanFolder($path,$root=''){
-		if(!$root){
-			$view=OC_Filesystem::getView();
-		}else{
-			$view=new OC_FilesystemView(($root=='/')?'':$root);
-		}
-		//check for removed files, not using getFolderContent to prevent loops
-		$parent=self::getFileId($view->getRoot().$path);
-		$query=OC_DB::prepare('SELECT name FROM *PREFIX*fscache WHERE parent=?');
-		$result=$query->execute(array($parent));
-		while($row=$result->fetchRow()){
-			$file=$path.'/'.$row['name'];
-			if(!$view->file_exists($file)){
-				if(!$root){//filesystem hooks are only valid for the default root
-					OC_Hook::emit('OC_Filesystem','post_delete',array('path'=>$file));
-				}else{
-					self::fileSystemWatcherDelete(array('path'=>$file),$root);
-				}
-			}
-		}
-	}
-
 	/**
 	 * clean old pre-path_hash entries
 	 */
@@ -732,6 +426,6 @@ class OC_FileCache{
 }
 
 //watch for changes and try to keep the cache up to date
-OC_Hook::connect('OC_Filesystem','post_write','OC_FileCache','fileSystemWatcherWrite');
-OC_Hook::connect('OC_Filesystem','post_delete','OC_FileCache','fileSystemWatcherDelete');
-OC_Hook::connect('OC_Filesystem','post_rename','OC_FileCache','fileSystemWatcherRename');
+OC_Hook::connect('OC_Filesystem','post_write','OC_FileCache_Update','fileSystemWatcherWrite');
+OC_Hook::connect('OC_Filesystem','post_delete','OC_FileCache_Update','fileSystemWatcherDelete');
+OC_Hook::connect('OC_Filesystem','post_rename','OC_FileCache_Update','fileSystemWatcherRename');
diff --git a/lib/filecache/cached.php b/lib/filecache/cached.php
new file mode 100644
index 0000000000000000000000000000000000000000..a22adad4528f044d1dc79370fb6596cd4594aa03
--- /dev/null
+++ b/lib/filecache/cached.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+
+/**
+ * get data from the filecache without checking for updates
+ */
+class OC_FileCache_Cached{
+	public static $savedData=array();
+	
+	public static function get($path,$root=false){
+		if($root===false){
+			$root=OC_Filesystem::getRoot();
+		}
+		$path=$root.$path;
+		$query=OC_DB::prepare('SELECT path,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path_hash=?');
+		$result=$query->execute(array(md5($path)))->fetchRow();
+		if(is_array($result)){
+			if(isset(self::$savedData[$path])){
+				$result=array_merge($result,self::$savedData[$path]);
+			}
+			return $result;
+		}else{
+			if(isset(self::$savedData[$path])){
+				return self::$savedData[$path];
+			}else{
+				return array();
+			}
+		}
+	}
+
+	/**
+	 * get all files and folders in a folder
+	 * @param string path
+	 * @param string root (optional)
+	 * @return array
+	 *
+	 * returns an array of assiciative arrays with the following keys:
+	 * - path
+	 * - name
+	 * - size
+	 * - mtime
+	 * - ctime
+	 * - mimetype
+	 * - encrypted
+	 * - versioned
+	 */
+	public static function getFolderContent($path,$root=false,$mimetype_filter=''){
+		if($root===false){
+			$root=OC_Filesystem::getRoot();
+		}
+		$parent=OC_FileCache::getId($path,$root);
+		$query=OC_DB::prepare('SELECT path,name,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE parent=? AND (mimetype LIKE ? OR mimetype = ?)');
+		$result=$query->execute(array($parent, $mimetype_filter.'%', 'httpd/unix-directory'))->fetchAll();
+		if(is_array($result)){
+			return $result;
+		}else{
+			OC_Log::write('files','getFolderContent(): file not found in cache ('.$path.')',OC_Log::DEBUG);
+			return false;
+		}
+	}
+}
\ No newline at end of file
diff --git a/lib/filecache/update.php b/lib/filecache/update.php
new file mode 100644
index 0000000000000000000000000000000000000000..9e23c6dfe7bc3746eb4bb590740c5adef16d289c
--- /dev/null
+++ b/lib/filecache/update.php
@@ -0,0 +1,210 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * 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)
+	 * @return bool
+	 */
+	public static function hasUpdated($path,$root=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'];
+			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 != '..'){
+					$file=$path.'/'.$filename;
+					if(self::hasUpdated($file,$root)){
+						if($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 fileysystem
+	 * @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($mimetype=='httpd/unix-directory'){
+			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);
+		}
+		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'];
+		$size=$view->filesize($newPath);
+		OC_FileCache::increaseSize(dirname($oldPath),-$oldSize,$root);
+		OC_FileCache::increaseSize(dirname($newPath),$oldSize,$root);
+		OC_FileCache::move($oldPath,$newPath);
+	}
+}
\ No newline at end of file
diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php
index 9e4c2d0643e46201985d9341cddc2ec51e1683f9..f061d48219be6729b081b821bf374d32f5dd6afa 100644
--- a/lib/fileproxy/quota.php
+++ b/lib/fileproxy/quota.php
@@ -54,8 +54,8 @@ class OC_FileProxy_Quota extends OC_FileProxy{
 	 * @return int
 	 */
 	private function getFreeSpace(){
-		$rootInfo=OC_FileCache::get('');
-		$usedSpace=$rootInfo['size'];
+		$rootInfo=OC_FileCache_Cached::get('');
+		$usedSpace=isset($rootInfo['size'])?$rootInfo['size']:0;
 		$totalSpace=$this->getQuota();
 		if($totalSpace==0){
 			return 0;
diff --git a/lib/files.php b/lib/files.php
index 705b7a6ca66fefa2ad212ce8ed95faab8e5bb170..3ecf08739b02f4f28a321339cb0f13279dabf58c 100644
--- a/lib/files.php
+++ b/lib/files.php
@@ -36,7 +36,7 @@ class OC_Files {
 		if(strpos($directory,OC::$CONFIG_DATADIRECTORY)===0){
 			$directory=substr($directory,strlen(OC::$CONFIG_DATADIRECTORY));
 		}
-		$files=OC_FileCache::getFolderContent($directory, '', $mimetype_filter);
+		$files=OC_FileCache::getFolderContent($directory, false, $mimetype_filter);
 		foreach($files as &$file){
 			$file['directory']=$directory;
 			$file['type']=($file['mimetype']=='httpd/unix-directory')?'dir':'file';