diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php
index 8d589ea5e2e315dd433a9d955126682b8414fc36..8049e9b0ae3cbcde3564f008c351ff8087642953 100644
--- a/apps/files_sharing/appinfo/app.php
+++ b/apps/files_sharing/appinfo/app.php
@@ -6,7 +6,6 @@ OC::$CLASSPATH['OC_Share'] = "apps/files_sharing/lib_share.php";
 OC_Hook::connect("OC_Filesystem", "post_delete", "OC_Share", "deleteItem");
 OC_Hook::connect("OC_Filesystem", "post_rename", "OC_Share", "renameItem");
 OC_Hook::connect("OC_Filesystem", "post_write", "OC_Share", "updateItem");
-OC_Filesystem::registerStorageType("shared", "OC_Filestorage_Shared", array("datadir" => "string"));
 OC_Util::addScript("files_sharing", "share");
 OC_Util::addScript("3rdparty", "chosen/chosen.jquery.min");
 OC_Util::addStyle( 'files_sharing', 'sharing' );
diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index 4457dddbe15a8b5e461cf6d1f37b5fa4faee67b9..d01a07447a66c81c482f788aabf21d56adbeb4a8 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -2,6 +2,7 @@ $(document).ready(function() {
 	var shared_status = {};
 	if (typeof FileActions !== 'undefined') {
 		FileActions.register('all', 'Share', function(filename) {
+			if (scanFiles.scanning){return;}//workaround to prevent aditional http request block scanning feedback
 			var icon;
 			var file = $('#dir').val()+'/'+filename;
 			if(shared_status[file])
diff --git a/apps/files_sharing/lib_share.php b/apps/files_sharing/lib_share.php
index 0eb0e5bf85d5bb74563b9c08b8b1b288a90cbe8c..049a74278b35e8c32f2e98c0a6e2f75a61e9fdda 100644
--- a/apps/files_sharing/lib_share.php
+++ b/apps/files_sharing/lib_share.php
@@ -89,8 +89,8 @@ class OC_Share {
 				}
 				$query->execute(array($uid_owner, $uid, $source, $target, $permissions));
 				// Clear the folder size cache for the 'Shared' folder
-				$clearFolderSize = OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?");
-				$clearFolderSize->execute(array($sharedFolder));
+// 				$clearFolderSize = OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?");
+// 				$clearFolderSize->execute(array($sharedFolder));
 				// Emit post_create and post_write hooks to notify of a new file in the user's filesystem
 				OC_Hook::emit("OC_Filesystem", "post_create", array('path' => $target));
 				OC_Hook::emit("OC_Filesystem", "post_write", array('path' => $target));
diff --git a/apps/files_sharing/sharedstorage.php b/apps/files_sharing/sharedstorage.php
index b0eaeecf7235f33ae0b7704f66218a38e7e51244..4840cce4c9df4f5682a2f91c311fa88cbadb8174 100644
--- a/apps/files_sharing/sharedstorage.php
+++ b/apps/files_sharing/sharedstorage.php
@@ -22,10 +22,10 @@
 
 require_once( 'lib_share.php' );
 
-if (!OC_Filesystem::is_dir('/Shared')) {
+if (OC_Filesystem::$loaded and !OC_Filesystem::is_dir('/Shared')) {
 	OC_Filesystem::mkdir('/Shared');
 }
-OC_Filesystem::mount('shared',array('datadir'=>'/'.OC_User::getUser().'/files/Shared'),'/'.OC_User::getUser().'/files/Shared/');
+OC_Filesystem::mount('OC_Filestorage_Shared',array('datadir'=>'/'.OC_User::getUser().'/files/Shared'),'/'.OC_User::getUser().'/files/Shared/');
 
 /**
  * Convert target path to source path and pass the function call to the correct storage provider
@@ -168,19 +168,9 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 	// TODO fill in other components of array
 	public function stat($path) {
 		if ($path == "" || $path == "/") {
-			$stat["dev"] = "";
-			$stat["ino"] = "";
-			$stat["mode"] = "";
-			$stat["nlink"] = "";
-			$stat["uid"] = "";
-			$stat["gid"] = "";
-			$stat["rdev"] = "";
 			$stat["size"] = $this->filesize($path);
-			$stat["atime"] = $this->fileatime($path);
 			$stat["mtime"] = $this->filemtime($path);
 			$stat["ctime"] = $this->filectime($path);
-			$stat["blksize"] = "";
-			$stat["blocks"] = "";
 			return $stat;
 		} else {
 			$source = $this->getSource($path);
@@ -217,18 +207,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 	}
 
 	public function getFolderSize($path) {
-		// Shared folder sizes are cached separately from the source folder sizes because folders can have different names
-		$path = rtrim($path, "/");
-		$path = ltrim($path, "/");
-		$path = preg_replace('{(/)\1+}', "/", $path);
-		$dbpath = rtrim($this->datadir.$path, "/");
-		$query = OC_DB::prepare("SELECT size FROM *PREFIX*foldersize WHERE path = ?");
-		$size = $query->execute(array($dbpath))->fetchAll();
-		if (count($size) > 0) {
-			return $size[0]['size'];
-		} else {
-			return $this->calculateFolderSize($path);
-		}
+		return 0; //depricated
 	}
 	
 	private function calculateFolderSize($path) {
@@ -249,8 +228,8 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 			}
 			if ($size > 0) {
 				$dbpath = rtrim($this->datadir.$path, "/");
-				$query = OC_DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)");
-				$result = $query->execute(array($dbpath, $size));
+// 				$query = OC_DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)");
+// 				$result = $query->execute(array($dbpath, $size));
 			}
 		}
 		return $size;
@@ -263,8 +242,8 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 			$path = dirname($path);
 		}
 		$dbpath = rtrim($this->datadir.$path, "/");
-		$query = OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?");
-		$result = $query->execute(array($dbpath));
+// 		$query = OC_DB::prepare("DELETE FROM *PREFIX*/*foldersize*/ WHERE path = ?");
+// 		$result = $query->execute(array($dbpath));
 		if ($path != "/" && $path != "") {
 			$parts = explode("/", $path);
 			$part = array_pop($parts);
@@ -280,7 +259,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 		return true;
 	}
 	
-	public function is_writeable($path) {
+	public function is_writable($path) {
 		if($path == "" || $path == "/"){
 			return false;
 		}elseif (OC_Share::getPermissions($this->datadir.$path) & OC_Share::WRITE) {
@@ -320,8 +299,8 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 						$ctime = $tempctime;
 					}
 				}
-				return $ctime;
 			}
+			return $ctime;
 		} else {
 			$source = $this->getSource($path);
 			if ($source) {
@@ -341,8 +320,8 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 						$mtime = $tempmtime;
 					}
 				}
-				return $mtime;
 			}
+			return $mtime;
 		} else {
 			$source = $this->getSource($path);
 			if ($source) {
@@ -352,27 +331,6 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 		}
 	}
 	
-	public function fileatime($path) {
-		if ($path == "" || $path == "/") {
-			$atime = 0; 
-			if ($dh = $this->opendir($path)) {
-				while (($filename = readdir($dh)) !== false) {
-					$tempatime = $this->fileatime($filename);
-					if ($tempatime > $atime) {
-						$atime = $tempatime;
-					}
-				}
-				return $atime;
-			}
-		} else {
-			$source = $this->getSource($path);
-			if ($source) {
-				$storage = OC_Filesystem::getStorage($source);
-				return $storage->fileatime($this->getInternalPath($source));
-			}
-		}
-	}
-	
 	public function file_get_contents($path) {
 		$source = $this->getSource($path);
 		if ($source) {
@@ -382,7 +340,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 	}
 	
 	public function file_put_contents($path, $data) {
-		if ($this->is_writeable($path)) {
+		if ($this->is_writable($path)) {
 			$source = $this->getSource($path);
 			if ($source) {
 				$storage = OC_Filesystem::getStorage($source);
@@ -426,7 +384,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 			if ($root1 !== $root2) {
 				return false;
 			// Check if both paths have write permission
-			} else if ($this->is_writeable($path1) && $this->is_writeable($path2)) {
+			} else if ($this->is_writable($path1) && $this->is_writable($path2)) {
 				$oldSource = $this->getSource($path1);
 				$newSource = $folders['source'].substr($newTarget, strlen($folders['target']));
 				if ($oldSource) {
@@ -456,7 +414,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 		if ($path2 == "" || $path2 == "/") {
 			// TODO Construct new shared item or should this not be allowed?
 		} else {
-			if ($this->is_writeable($path2)) {
+			if ($this->is_writable($path2)) {
 				$tmpFile = $this->toTmpFile($path1);
 				$result = $this->fromTmpFile($tmpFile, $path2);
 				if ($result) {
@@ -486,7 +444,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 	}
 	
 	public function fromTmpFile($tmpFile, $path) {
-		if ($this->is_writeable($path)) {
+		if ($this->is_writable($path)) {
 			$source = $this->getSource($path);
 			if ($source) {
 				$storage = OC_Filesystem::getStorage($source);
@@ -501,23 +459,10 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 		}
 	}
 	
-	public function fromUploadedFile($tmpFile, $path) {
-		if ($this->is_writeable($path)) {
-			$source = $this->getSource($path);
-			if ($source) {
-				$storage = OC_Filesystem::getStorage($source);
-				$result = $storage->fromUploadedFile($tmpFile, $this->getInternalPath($source));
-				if ($result) {
-					$this->clearFolderSizeCache($path);
-				}
-				return $result;
-			}
-		} else {
-			return false;
-		}
-	}
-	
 	public function getMimeType($path) {
+		if ($path2 == "" || $path2 == "/") {
+			return 'httpd/unix-directory';
+		}
 		$source = $this->getSource($path);
 		if ($source) {
 			$storage = OC_Filesystem::getStorage($source);
diff --git a/apps/files_texteditor/ajax/loadfile.php b/apps/files_texteditor/ajax/loadfile.php
index 64e016be8c277551f261f97ad6608e939c8abc9f..8ece844aa29fdf2d32a8345c45b5a3c3a0b565c4 100644
--- a/apps/files_texteditor/ajax/loadfile.php
+++ b/apps/files_texteditor/ajax/loadfile.php
@@ -33,7 +33,7 @@ $filename = isset($_GET['file']) ? $_GET['file'] : '';
 if(!empty($filename))
 {	
 	$path = $dir.'/'.$filename;
-	if(OC_Filesystem::is_writeable($path))
+	if(OC_Filesystem::is_writable($path))
 	{
 		$mtime = OC_Filesystem::filemtime($path);
 		$filecontents = OC_Filesystem::file_get_contents($path);
diff --git a/apps/files_texteditor/ajax/savefile.php b/apps/files_texteditor/ajax/savefile.php
index 3d0771ea983f660e3b53ff21aa692b7436bd9485..589428d1862268bdd93e08cac52573f54d5f13e2 100644
--- a/apps/files_texteditor/ajax/savefile.php
+++ b/apps/files_texteditor/ajax/savefile.php
@@ -32,7 +32,6 @@ $filecontents = htmlspecialchars_decode($_POST['filecontents']);
 $path = isset($_POST['path']) ? $_POST['path'] : '';
 $mtime = isset($_POST['mtime']) ? $_POST['mtime'] : '';
 
-
 if($path != '' && $mtime != '')
 {
 	// Get file mtime
@@ -47,7 +46,7 @@ if($path != '' && $mtime != '')
 	{
 		// File same as when opened
 		// Save file
-		if(OC_Filesystem::is_writeable($path))	
+		if(OC_Filesystem::is_writable($path))
 		{
 			OC_Filesystem::file_put_contents($path, $filecontents);
 			// Clear statcache
diff --git a/db_structure.xml b/db_structure.xml
index ddb8c44d19dbb888a9510fe84507d7b30544e01b..8e59a59c6e51e354c16d56499fdc9219a4820458 100644
--- a/db_structure.xml
+++ b/db_structure.xml
@@ -43,10 +43,19 @@
 
  <table>
 
-  <name>*dbprefix*foldersize</name>
+  <name>*dbprefix*fscache</name>
 
   <declaration>
 
+   <field>
+	   <name>id</name>
+	   <autoincrement>1</autoincrement>
+	   <type>integer</type>
+	   <default>0</default>
+	   <notnull>true</notnull>
+	   <length>4</length>
+   </field>
+   
    <field>
     <name>path</name>
     <type>text</type>
@@ -55,6 +64,33 @@
     <length>512</length>
    </field>
 
+   <field>
+	   <name>parent</name>
+	   <type>integer</type>
+	   <default>
+	   </default>
+	   <notnull>true</notnull>
+	   <length>4</length>
+   </field>
+
+   <field>
+	   <name>name</name>
+	   <type>text</type>
+	   <default>
+	   </default>
+	   <notnull>true</notnull>
+	   <length>512</length>
+   </field>
+
+   <field>
+	   <name>user</name>
+	   <type>text</type>
+	   <default>
+	   </default>
+	   <notnull>true</notnull>
+	   <length>64</length>
+   </field>
+   
    <field>
     <name>size</name>
     <type>integer</type>
@@ -63,12 +99,93 @@
     <length>4</length>
    </field>
 
-   <index>
-    <name>path_index</name>
+   <field>
+	   <name>ctime</name>
+	   <type>integer</type>
+	   <default>
+	   </default>
+	   <notnull>true</notnull>
+	   <length>4</length>
+   </field>
+
+   <field>
+	   <name>mtime</name>
+	   <type>integer</type>
+	   <default>
+	   </default>
+	   <notnull>true</notnull>
+	   <length>4</length>
+   </field>
+
+   <field>
+	   <name>mimetype</name>
+	   <type>text</type>
+	   <default>
+	   </default>
+	   <notnull>true</notnull>
+	   <length>32</length>
+   </field>
+
+   <field>
+	   <name>mimepart</name>
+	   <type>text</type>
+	   <default>
+	   </default>
+	   <notnull>true</notnull>
+	   <length>32</length>
+   </field>
+
+   <field>
+	   <name>encrypted</name>
+	   <type>integer</type>
+	   <default>0</default>
+	   <notnull>true</notnull>
+	   <length>1</length>
+   </field>
+
+   <field>
+	   <name>versioned</name>
+	   <type>integer</type>
+	   <default>0</default>
+	   <notnull>true</notnull>
+	   <length>1</length>
+   </field>
+
+   <field>
+	   <name>writable</name>
+	   <type>integer</type>
+	   <default>0</default>
+	   <notnull>true</notnull>
+	   <length>1</length>
+   </field>
+
+   <!--<index>
+	   <name>fscache_path_index</name>
+	<unique>true</unique>
     <field>
      <name>path</name>
      <sorting>ascending</sorting>
     </field>
+   </index>-->
+
+   <index>
+	   <name>parent_index</name>
+	   <field>
+		   <name>parent</name>
+		   <sorting>ascending</sorting>
+	   </field>
+   </index>
+
+   <index>
+	   <name>parent_name_index</name>
+	   <field>
+		   <name>parent</name>
+		   <sorting>ascending</sorting>
+	   </field>
+	   <field>
+		   <name>name</name>
+		   <sorting>ascending</sorting>
+	   </field>
    </index>
 
   </declaration>
diff --git a/files/ajax/scan.php b/files/ajax/scan.php
new file mode 100644
index 0000000000000000000000000000000000000000..565275911b4e1591cefc8ff6b4f2664479c935b5
--- /dev/null
+++ b/files/ajax/scan.php
@@ -0,0 +1,37 @@
+<?php
+
+require_once '../../lib/base.php';
+
+set_time_limit(0);//scanning can take ages
+
+$force=isset($_GET['force']) and $_GET['force']=='true';
+$checkOnly=isset($_GET['checkonly']) and $_GET['checkonly']=='true';
+
+if(!$checkOnly){
+	$eventSource=new OC_EventSource();
+}
+
+
+//create the file cache if necesary
+if($force or !OC_FileCache::inCache('')){
+	if(!$checkOnly){
+		OC_DB::beginTransaction();
+		OC_FileCache::scan('',$eventSource);
+		OC_DB::commit();
+		$eventSource->send('success',true);
+	}else{
+		OC_JSON::success(array('data'=>array('done'=>true)));
+		exit;
+	}
+}else{
+	if($checkOnly){
+		OC_JSON::success(array('data'=>array('done'=>false)));
+		exit;
+	}
+	if(isset($eventSource)){
+		$eventSource->send('success',false);
+	}else{
+		exit;
+	}
+}
+$eventSource->close();
\ No newline at end of file
diff --git a/files/ajax/upload.php b/files/ajax/upload.php
index 5f0f68d9531394827bd8b30a2862f98739deab01..241edc216ff428479c073cd94ec6b91f82ed964e 100644
--- a/files/ajax/upload.php
+++ b/files/ajax/upload.php
@@ -47,7 +47,7 @@ if(strpos($dir,'..') === false){
 	$fileCount=count($files['name']);
 	for($i=0;$i<$fileCount;$i++){
 		$target=stripslashes($dir) . $files['name'][$i];
-		if(OC_Filesystem::fromUploadedFile($files['tmp_name'][$i],$target)){
+		if(is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i],$target)){
 			$result[]=array( "status" => "success", 'mime'=>OC_Filesystem::getMimeType($target),'size'=>OC_Filesystem::filesize($target),'name'=>$files['name'][$i]);
 		}
 	}
diff --git a/files/css/files.css b/files/css/files.css
index 13ed7fb33e4d117663051571aff55b413f1b37dd..512e462cb6f9f4395e6e752365231374e73af560 100644
--- a/files/css/files.css
+++ b/files/css/files.css
@@ -76,4 +76,6 @@ a.action>img{ max-height:16px; max-width:16px; }
 
 /* add breadcrumb divider to the File item in navigation panel */
 #navigation>ul>li:first-child { background:url('../../core/img/breadcrumb-start.svg') no-repeat 12.5em 0px; width:12.5em; padding-right:1em; position:fixed; }
-#navigation>ul>li:first-child+li { padding-top:2.9em; }
\ No newline at end of file
+#navigation>ul>li:first-child+li { padding-top:2.9em; }
+
+#scanning-message{ top:40%; left:40%; position:absolute; display:none }
diff --git a/files/index.php b/files/index.php
index fbf7a4901a1fe35fe5feb3f4f1be9f7ddbd3a4ec..f166790ba9c642a317c249e6d7c11322aed753fa 100644
--- a/files/index.php
+++ b/files/index.php
@@ -94,7 +94,7 @@ $tmpl = new OC_Template( "files", "index", "user" );
 $tmpl->assign( "fileList", $list->fetchPage() );
 $tmpl->assign( "breadcrumb", $breadcrumbNav->fetchPage() );
 $tmpl->assign( 'dir', $dir);
-$tmpl->assign( 'readonly', !OC_Filesystem::is_writeable($dir));
+$tmpl->assign( 'readonly', !OC_Filesystem::is_writable($dir));
 $tmpl->assign( "files", $files );
 $tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize);
 $tmpl->assign( 'uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
diff --git a/files/js/files.js b/files/js/files.js
index 7c04245c22388d0fa5444c3667852f11b1c5ead3..bebcf4e97a4da42287b1fce66e193ce1fade526a 100644
--- a/files/js/files.js
+++ b/files/js/files.js
@@ -336,8 +336,37 @@ $(document).ready(function() {
 			$('#new>a').click();
 		});
 	});
+
+	//check if we need to scan the filesystem
+	$.get(OC.filePath('files','ajax','scan.php'),{checkonly:'true'}, function(response) {
+		if(response.data.done){
+			scanFiles();
+		}
+	}, "json");
 });
 
+function scanFiles(force){
+	force=!!force; //cast to bool
+	scanFiles.scanning=true;
+	$('#scanning-message').show();
+	$('#fileList').remove();
+	var scannerEventSource=new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force});
+	scanFiles.cancel=scannerEventSource.close.bind(scannerEventSource);
+	scannerEventSource.listen('scanning',function(data){
+		$('#scan-count').text(data.count+' files scanned');
+		$('#scan-current').text(data.file+'/');
+	});
+	scannerEventSource.listen('success',function(success){
+		scanFiles.scanning=false;
+		if(success){
+			window.location.reload();
+		}else{
+			alert('error while scanning');
+		}
+	});
+}
+scanFiles.scanning=false;
+
 function boolOperationFinished(data, callback) {
 	result = jQuery.parseJSON(data.responseText);
 	if(result.status == 'success'){
diff --git a/files/templates/index.php b/files/templates/index.php
index 38a3274ff317c51f930bd23b82e96278920f250b..7e9505dec2f936435791c8eea86457c0c91bd143 100644
--- a/files/templates/index.php
+++ b/files/templates/index.php
@@ -57,3 +57,11 @@
 		<?php echo $l->t('The files you are trying to upload exceed the maximum size for file uploads on this server.');?>
 	</p>
 </div>
+<div id="scanning-message">
+	<h3>
+		<?php echo $l->t('Files are being scanned, please wait.');?> <span id='scan-count'></spann>
+	</h3>
+	<p>
+		<?php echo $l->t('Current scanning');?> <span id='scan-current'></spann>
+	</p>
+</div>
diff --git a/files/templates/part.list.php b/files/templates/part.list.php
index a364862119d177c1a3369c8910d8c15b640d43a7..b117d81a1a580b7ecbb871bbaebbd23f0313856d 100644
--- a/files/templates/part.list.php
+++ b/files/templates/part.list.php
@@ -1,5 +1,5 @@
 		<?php foreach($_['files'] as $file):
-			$write = ($file['writeable']) ? 'true' : 'false';
+			$write = ($file['writable']) ? 'true' : 'false';
 			$simple_file_size = simple_file_size($file['size']);
 			$simple_size_color = intval(200-$file['size']/(1024*1024)*2); // the bigger the file, the darker the shade of grey; megabytes*2
 			if($simple_size_color<0) $simple_size_color = 0;
@@ -10,8 +10,8 @@
 			$name = str_replace('%2F','/', $name);
 			$directory = str_replace('+','%20',urlencode($file['directory']));
 			$directory = str_replace('%2F','/', $directory); ?>
-			<tr data-file="<?php echo $name;?>" data-type="<?php echo ($file['type'] == 'dir')?'dir':'file'?>" data-mime="<?php echo $file['mime']?>" data-size='<?php echo $file['size'];?>' data-write='<?php echo $write;?>'>
-				<td class="filename svg" style="background-image:url(<?php if($file['type'] == 'dir') echo mimetype_icon('dir'); else echo mimetype_icon($file['mime']); ?>)">
+			<tr data-file="<?php echo $name;?>" data-type="<?php echo ($file['type'] == 'dir')?'dir':'file'?>" data-mime="<?php echo $file['mimetype']?>" data-size='<?php echo $file['size'];?>' data-write='<?php echo $write;?>'>
+				<td class="filename svg" style="background-image:url(<?php if($file['type'] == 'dir') echo mimetype_icon('dir'); else echo mimetype_icon($file['mimetype']); ?>)">
 					<?php if(!isset($_['readonly']) || !$_['readonly']) { ?><input type="checkbox" /><?php } ?>
 					<a class="name" href="<?php if($file['type'] == 'dir') echo $_['baseURL'].$directory.'/'.$name; else echo $_['downloadURL'].$directory.'/'.$name; ?>" title="">
 					<span class="nametext">
diff --git a/lib/base.php b/lib/base.php
index 4da17c70a572dd18de2d69f67294bfb8518046a2..5b8eeb746b186739c71f3ad046397caf0abb84ce 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -216,9 +216,6 @@ class OC{
 		OC_User::useBackend( OC_Config::getValue( "userbackend", "database" ));
 		OC_Group::setBackend( OC_Config::getValue( "groupbackend", "database" ));
 
-		// Was in required file ... put it here
-		OC_Filesystem::registerStorageType('local','OC_Filestorage_Local',array('datadir'=>'string'));
-
 		// Set up file system unless forbidden
 		global $RUNTIME_NOSETUPFS;
 		if(!$RUNTIME_NOSETUPFS ){
diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php
index 139c6b784b1625e3a7a1a93a0a64ed94207fa6a9..bb03851e39d7484db4c6a0411bdcc6b9528ef261 100644
--- a/lib/connector/sabre/directory.php
+++ b/lib/connector/sabre/directory.php
@@ -116,11 +116,11 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
 	 * @return array
 	 */
 	public function getQuotaInfo() {
-
+		$rootInfo=OC_FileCache::get('');
 		return array(
-			OC_Filesystem::filesize('/'),
+			$rootInfo['size'],
 			OC_Filesystem::free_space()
-			);
+		);
 
 	}
 
diff --git a/lib/filecache.php b/lib/filecache.php
new file mode 100644
index 0000000000000000000000000000000000000000..964099c7fcd3f561ece871d84b7f6654f7a4e465
--- /dev/null
+++ b/lib/filecache.php
@@ -0,0 +1,574 @@
+<?php
+
+/**
+* @author Robin Appelman
+* @copyright 2011 Robin Appelman icewind1991@gmail.com
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * provide caching for filesystem info in the database
+ *
+ * not used by OC_Filesystem for reading filesystem info,
+ * instread apps should use OC_FileCache::get where possible
+ *
+ * It will try to keep the data up to date but changes from outside ownCloud can invalidate the cache
+ */
+class OC_FileCache{
+	/**
+	 * get the filesystem info from the cache
+	 * @param string path
+	 * @param string root (optional)
+	 * @return array
+	 *
+	 * returns an assiciative array with the following keys:
+	 * - size
+	 * - mtime
+	 * - ctime
+	 * - mimetype
+	 * - encrypted
+	 * - versioned
+	 */
+	public static function get($path,$root=''){
+		if(self::isUpdated($path,$root)){
+			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);
+			}
+		}
+		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=?');
+		$result=$query->execute(array($path))->fetchRow();
+		if(is_array($result)){
+			return $result;
+		}else{
+			OC_Log::write('file not found in cache ('.$path.')','core',OC_Log::DEBUG);
+			return false;
+		}
+	}
+
+	/**
+	 * put filesystem info in the cache
+	 * @param string $path
+	 * @param array data
+	 * @param string root (optional)
+	 *
+	 * $data is an assiciative array in the same format as returned by get
+	 */
+	public static function put($path,$data,$root=''){
+		if(!$root){
+			$root=OC_Filesystem::getRoot();
+		}
+		if($root=='/'){
+			$root='';
+		}
+		$path=$root.$path;
+		if($path=='/'){
+			$parent=-1;
+		}else{
+			$parent=self::getFileId(dirname($path));
+		}
+		$id=self::getFileId($path);
+		if($id!=-1){
+			self::update($id,$data);
+			return;
+		}
+		if(!isset($data['encrypted'])){
+			$data['encrypted']=false;
+		}
+		if(!isset($data['versioned'])){
+			$data['versioned']=false;
+		}
+		$mimePart=dirname($data['mimetype']);
+		$user=OC_User::getUser();
+		$query=OC_DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, size, mtime, ctime, mimetype, mimepart,user,writable) VALUES(?,?,?,?,?,?,?,?,?,?)');
+		$query->execute(array($parent,basename($path),$path,$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$user,$data['writable']));
+		
+	}
+
+	/**
+	 * update filesystem info of a file
+	 * @param int $id
+	 * @param array $data
+	 */
+	private static function update($id,$data){
+		$arguments=array();
+		$queryParts=array();
+		foreach(array('size','mtime','ctime','mimetype','encrypted','versioned','writable') as $attribute){
+			if(isset($data[$attribute])){
+				$arguments[]=$data[$attribute];
+				$queryParts[]=$attribute.'=?';
+			}
+		}
+		if(isset($data['mimetype'])){
+			$arguments[]=dirname($data['mimetype']);
+			$queryParts[]='mimepart=?';
+		}
+		$arguments[]=$id;
+		$query=OC_DB::prepare('UPDATE *PREFIX*fscache SET '.implode(' , ',$queryParts).' WHERE id=?');
+		$query->execute($arguments);
+	}
+
+	/**
+	 * register a file move in the cache
+	 * @param string oldPath
+	 * @param string newPath
+	 * @param string root (optional)
+	 */
+	public static function move($oldPath,$newPath,$root=''){
+		if(!$root){
+			$root=OC_Filesystem::getRoot();
+		}
+		if($root=='/'){
+			$root='';
+		}
+		$oldPath=$root.$oldPath;
+		$newPath=$root.$newPath;
+		$newParent=self::getParentId($newPath);
+		$query=OC_DB::prepare('UPDATE *PREFIX*fscache SET parent=? ,name=?, path=? WHERE path=?');
+		$query->execute(array($newParent,basename($newPath),$newPath,$oldPath));
+	}
+
+	/**
+	 * delete info from the cache
+	 * @param string $path
+	 * @param string root (optional)
+	 */
+	public static function delete($path,$root=''){
+		if(!$root){
+			$root=OC_Filesystem::getRoot();
+		}
+		if($root=='/'){
+			$root='';
+		}
+		$path=$root.$path;
+		$query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE path=?');
+		$query->execute(array($path));
+	}
+	
+	/**
+	 * return array of filenames matching the querty
+	 * @param string $query
+	 * @param boolean $returnData
+	 * @param string root (optional)
+	 * @return array of filepaths
+	 */
+	public static function search($search,$returnData=false,$root=''){
+		if(!$root){
+			$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=?');
+		}else{
+			$query=OC_DB::prepare('SELECT * FROM *PREFIX*fscache WHERE name LIKE ? AND user=?');
+		}
+		$result=$query->execute(array("%$search%",OC_User::getUser()));
+		$names=array();
+		while($row=$result->fetchRow()){
+			if(!$returnData){
+				$names[]=substr($row['path'],$rootLen);
+			}else{
+				$row['path']=substr($row['path'],$rootLen);
+				$names[]=$row;
+			}
+		}
+		return $names;
+	}
+
+	/**
+	 * 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:
+	 * - name
+	 * - size
+	 * - mtime
+	 * - ctime
+	 * - mimetype
+	 * - encrypted
+	 * - versioned
+	 */
+	public static function getFolderContent($path,$root=''){
+		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=?');
+		$result=$query->execute(array($parent))->fetchAll();
+		if(is_array($result)){
+			return $result;
+		}else{
+			OC_Log::write('file not found in cache ('.$path.')','core',OC_Log::DEBUG);
+			return false;
+		}
+	}
+
+	/**
+	 * check if a file or folder is in the cache
+	 * @param string $path
+	 * @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;
+	}
+
+	/**
+	 * get the file id as used in the cache
+	 * @param string $path
+	 * @return int
+	 */
+	private static function getFileId($path){
+		$query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path=?');
+		$result=$query->execute(array($path))->fetchRow();
+		if(is_array($result)){
+			return $result['id'];
+		}else{
+			OC_Log::write('file not found in cache ('.$path.')','core',OC_Log::DEBUG);
+			return -1;
+		}
+	}
+
+	/**
+	 * get the file id of the parent folder, taking into account '/' has no parent
+	 * @param string $path
+	 * @return int
+	 */
+	private static function getParentId($path){
+		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);
+		//dont use self::get here, we don't want inifinte loops when a file has changed
+		$cachedSize=self::getCachedSize($path,$root);
+		$size=0;
+		if($mimetype=='httpd/unix-directory'){
+			if(self::inCache($path,$root)){
+				$parent=self::getFileId($fullPath);
+				$query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE parent=?');
+				$query->execute(array($parent));
+				while($row=$query->fetch()){
+					$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);
+	}
+
+	private static function getCachedSize($path,$root){
+		if(!$root){
+			$root=OC_Filesystem::getRoot();
+		}else{
+			if($root=='/'){
+				$root='';
+			}
+		}
+		$query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE path=?');
+		$query->execute(array($path));
+		if($row=$query->fetch()){
+			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){
+			$oldInfo=self::get($fullOldPath);
+			$oldSize=$oldInfo['size'];
+		}else{
+			return;
+		}
+		$size=OC_Filesystem::filesize($oldPath);
+		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
+	 */
+	private static function increaseSize($path,$sizeDiff){
+		if($sizeDiff==0) return;
+		while(($id=self::getFileId($path))!=-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));
+			$path=dirname($path);
+		}
+	}
+
+	/**
+	 * recursively scan the filesystem and fill the cache
+	 * @param string $path
+	 * @param OC_EventSource $enventSource (optional)
+	 * @param int count (optional)
+	 * @param string root (optionak)
+	 */
+	public static function scan($path,$eventSource=false,&$count=0,$root=''){
+		if(!$root){
+			$view=OC_Filesystem::getView();
+		}else{
+			$view=new OC_FilesystemView(($root=='/')?'':$root);
+		}
+		self::scanFile($path,$root);
+		$dh=$view->opendir($path);
+		$totalSize=0;
+		if($dh){
+			while (($filename = readdir($dh)) !== false) {
+				if($filename != '.' and $filename != '..'){
+					$file=$path.'/'.$filename;
+					if($view->is_dir($file)){
+						if($eventSource){
+							$eventSource->send('scanning',array('file'=>$file,'count'=>$count));
+						}
+						self::scan($file,$eventSource,$count,$root);
+					}else{
+						$totalSize+=self::scanFile($file,$root);
+						$count++;
+					}
+				}
+			}
+		}
+		self::increaseSize($view->getRoot().$path,$totalSize);
+	}
+
+	/**
+	 * scan a single file
+	 * @param string path
+	 * @param string root (optional)
+	 * @return int size of the scanned file
+	 */
+	public static function scanFile($path,$root=''){
+		if(!$root){
+			$view=OC_Filesystem::getView();
+		}else{
+			$view=new OC_FilesystemView(($root=='/')?'':$root);
+		}
+		if(!$view->is_readable($path)) return; //cant read, nothing we can do
+		$stat=$view->stat($path);
+		$mimetype=$view->getMimeType($path);
+		$writable=$view->is_writable($path);
+		$stat['mimetype']=$mimetype;
+		$stat['writable']=$writable;
+		if($path=='/'){
+			$path='';
+		}
+		self::put($path,$stat,$root);
+		return $stat['size'];
+	}
+
+	/**
+	 * fine files by mimetype
+	 * @param string $part1
+	 * @param string $part2 (optional)
+	 * @return array of file paths
+	 *
+	 * $part1 and $part2 together form the complete mimetype.
+	 * e.g. searchByMime('text','plain')
+	 *
+	 * seccond mimetype part can be ommited
+	 * e.g. searchByMime('audio')
+	 */
+	public static function searchByMime($part1,$part2=''){
+		if($part2){
+			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimepart=?');
+			$result=$query->execute(array($part1));
+		}else{
+			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimetype=?');
+			$result=$query->execute(array($part1.'/'.$part2));
+		}
+		$names=array();
+		while($row=$result->fetchRow()){
+			$names[]=$row['path'];
+		}
+		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);
+		}
+		$mtime=$view->filemtime($path);
+		$isDir=$view->is_dir($path);
+		$path=$root.$path;
+		$query=OC_DB::prepare('SELECT mtime FROM *PREFIX*fscache WHERE path=?');
+		$query->execute(array($path));
+		if($row=$query->fetch()){
+			$cachedMTime=$row['mtime'];
+			return ($mtime>$cachedMTime);
+		}else{//file not in cache, so it has to be updated
+			return !($isDir);//new folders are handeled sperate
+		}
+	}
+
+	/**
+	 * 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);
+						}
+					}
+				}
+			}
+		}
+
+		//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->fetch()){
+			$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);
+				}
+			}
+		}
+		//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);
+		}
+	}
+}
+
+//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');
diff --git a/lib/fileproxy.php b/lib/fileproxy.php
index 549b7015a6a11aef72b4d3fdceb0f7b310cfdd12..235fc8bf284f7707a009608147e364b86baae3e8 100644
--- a/lib/fileproxy.php
+++ b/lib/fileproxy.php
@@ -34,7 +34,7 @@
  * A post-proxy recieves 2 arguments, the filepath and the result of the operation.
  * The return calue of the post-proxy will be used as the new result of the operation
  * The operations that have a post-proxy are
- *      file_get_contents, is_file, is_dir, file_exists, stat, is_readable, is_writable, fileatime, filemtime, filectime, file_get_contents, getMimeType, hash, free_space and search
+ *      file_get_contents, is_file, is_dir, file_exists, stat, is_readable, is_writable, filemtime, filectime, file_get_contents, getMimeType, hash, free_space and search
  */
 
 class OC_FileProxy{
diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php
index f770c9cb32b6596c21f5847dc72585e36b84851c..94a49176ee6fbbe2424081fe61332bdcb1b6711f 100644
--- a/lib/fileproxy/quota.php
+++ b/lib/fileproxy/quota.php
@@ -27,8 +27,10 @@
 
 class OC_FileProxy_Quota extends OC_FileProxy{
 	private function getFreeSpace(){
-		$usedSpace=OC_Filesystem::filesize('');
+		$rootInfo=OC_FileCache::get('');
+		$usedSpace=$rootInfo['size'];
 		$totalSpace=OC_Preferences::getValue(OC_User::getUser(),'files','quota',0);
+		$totalSpace=OC_Helper::computerFileSize($totalSpace);
 		if($totalSpace==0){
 			return 0;
 		}
diff --git a/lib/files.php b/lib/files.php
index 9ae5320ad1dfbde46c5e76c26e1ded16d7f17a86..457c8ea38f2bded767dc06af3b477199aacfb4bd 100644
--- a/lib/files.php
+++ b/lib/files.php
@@ -36,44 +36,13 @@ class OC_Files {
 		if(strpos($directory,OC::$CONFIG_DATADIRECTORY)===0){
 			$directory=substr($directory,strlen(OC::$CONFIG_DATADIRECTORY));
 		}
-		$filesfound=true;
-		$content=array();
-		$dirs=array();
-		$file=array();
-		$files=array();
-		if(OC_Filesystem::is_dir($directory)) {
-			if ($dh = OC_Filesystem::opendir($directory)) {
-			while (($filename = readdir($dh)) !== false) {
-				if($filename<>'.' and $filename<>'..' and substr($filename,0,1)!='.'){
-					$file=array();
-					$filesfound=true;
-					$file['name']=$filename;
-					$file['directory']=$directory;
-					$stat=OC_Filesystem::stat($directory.'/'.$filename);
-					$file=array_merge($file,$stat);
-					$file['size']=OC_Filesystem::filesize($directory.'/'.$filename);
-					$file['mime']=OC_Files::getMimeType($directory .'/'. $filename);
-					$file['readable']=OC_Filesystem::is_readable($directory .'/'. $filename);
-					$file['writeable']=OC_Filesystem::is_writeable($directory .'/'. $filename);
-					$file['type']=OC_Filesystem::filetype($directory .'/'. $filename);
-					if($file['type']=='dir'){
-						$dirs[$file['name']]=$file;
-					}else{
-						$files[$file['name']]=$file;
-					}
-				}
-			}
-			closedir($dh);
-			}
-		}
-		uksort($dirs, "strnatcasecmp");
-		uksort($files, "strnatcasecmp");
-		$content=array_merge($dirs,$files);
-		if($filesfound){
-			return $content;
-		}else{
-			return false;
+		$files=OC_FileCache::getFolderContent($directory);
+		foreach($files as &$file){
+			$file['directory']=$directory;
+			$file['type']=($file['mimetype']=='httpd/unix-directory')?'dir':'file';
 		}
+		usort($files, "fileCmp");//TODO: remove this once ajax is merged
+		return $files;
 	}
 
 
@@ -321,3 +290,13 @@ class OC_Files {
 		return $path;
 	}
 }
+
+function fileCmp($a,$b){
+	if($a['type']=='dir' and $b['type']!='dir'){
+		return -1;
+	}elseif($a['type']!='dir' and $b['type']=='dir'){
+		return 1;
+	}else{
+		return strnatcasecmp($a['name'],$b['name']);
+	}
+}
diff --git a/lib/filestorage.php b/lib/filestorage.php
index 34fa6457fd28a4b9a9d1f52023ad2e97b22c8219..4523144f6f4230031ca805cfb3322f8a67285f3a 100644
--- a/lib/filestorage.php
+++ b/lib/filestorage.php
@@ -34,12 +34,11 @@ class OC_Filestorage{
 	public function filetype($path){}
 	public function filesize($path){}
 	public function is_readable($path){}
-	public function is_writeable($path){}
+	public function is_writable($path){}
 	public function file_exists($path){}
 	public function readfile($path){}
 	public function filectime($path){}
 	public function filemtime($path){}
-	public function fileatime($path){}
 	public function file_get_contents($path){}
 	public function file_put_contents($path,$data){}
 	public function unlink($path){}
@@ -48,7 +47,6 @@ class OC_Filestorage{
 	public function fopen($path,$mode){}
 	public function toTmpFile($path){}//copy the file to a temporary file, used for cross-storage file actions
 	public function fromTmpFile($tmpPath,$path){}//copy a file from a temporary file, used for cross-storage file actions
-	public function fromUploadedFile($tmpPath,$path){}//copy a file from a temporary file, used for cross-storage file actions
 	public function getMimeType($path){}
 	public function hash($type,$path,$raw){}
 	public function free_space($path){}
diff --git a/lib/filestorage/local.php b/lib/filestorage/local.php
index e846aa420e45c1574086790b86b8312a641fa921..2c1f650cb9f1742ca809ee0da740ca2f8d755099 100644
--- a/lib/filestorage/local.php
+++ b/lib/filestorage/local.php
@@ -13,13 +13,11 @@ class OC_Filestorage_Local extends OC_Filestorage{
 	}
 	public function mkdir($path){
 		if($return=mkdir($this->datadir.$path)){
-			$this->clearFolderSizeCache($path);
 		}
 		return $return;
 	}
 	public function rmdir($path){
 		if($return=rmdir($this->datadir.$path)){
-			$this->clearFolderSizeCache($path);
 		}
 		return $return;
 	}
@@ -52,7 +50,7 @@ class OC_Filestorage_Local extends OC_Filestorage{
 	public function is_readable($path){
 		return is_readable($this->datadir.$path);
 	}
-	public function is_writeable($path){
+	public function is_writable($path){
 		return is_writable($this->datadir.$path);
 	}
 	public function file_exists($path){
@@ -67,20 +65,15 @@ class OC_Filestorage_Local extends OC_Filestorage{
 	public function filemtime($path){
 		return filemtime($this->datadir.$path);
 	}
-	public function fileatime($path){
-		return fileatime($this->datadir.$path);
-	}
 	public function file_get_contents($path){
 		return file_get_contents($this->datadir.$path);
 	}
 	public function file_put_contents($path,$data){
 		if($return=file_put_contents($this->datadir.$path,$data)){
-			$this->clearFolderSizeCache($path);
 		}
 	}
 	public function unlink($path){
 		$return=$this->delTree($path);
-		$this->clearFolderSizeCache($path);
 		return $return;
 	}
 	public function rename($path1,$path2){
@@ -90,8 +83,6 @@ class OC_Filestorage_Local extends OC_Filestorage{
 		}
 
 		if($return=rename($this->datadir.$path1,$this->datadir.$path2)){
-			$this->clearFolderSizeCache($path1);
-			$this->clearFolderSizeCache($path2);
 		}
 		return $return;
 	}
@@ -104,7 +95,6 @@ class OC_Filestorage_Local extends OC_Filestorage{
 			$path2.=$source;
 		}
 		if($return=copy($this->datadir.$path1,$this->datadir.$path2)){
-			$this->clearFolderSizeCache($path2);
 		}
 		return $return;
 	}
@@ -117,12 +107,10 @@ class OC_Filestorage_Local extends OC_Filestorage{
 				case 'w+':
 				case 'x+':
 				case 'a+':
-					$this->clearFolderSizeCache($path);
 					break;
 				case 'w':
 				case 'x':
 				case 'a':
-					$this->clearFolderSizeCache($path);
 					break;
 			}
 		}
@@ -192,18 +180,6 @@ class OC_Filestorage_Local extends OC_Filestorage{
 		$fileStats = stat($tmpFile);
 		if(rename($tmpFile,$this->datadir.$path)){
 			touch($this->datadir.$path, $fileStats['mtime'], $fileStats['atime']);
-			$this->clearFolderSizeCache($path);
-			return true;
-		}else{
-			return false;
-		}
-	}
-
-	public function fromUploadedFile($tmpFile,$path){
-		$fileStats = stat($tmpFile);
-		if(move_uploaded_file($tmpFile,$this->datadir.$path)){
-			touch($this->datadir.$path, $fileStats['mtime'], $fileStats['atime']);
-			$this->clearFolderSizeCache($path);
 			return true;
 		}else{
 			return false;
@@ -219,7 +195,6 @@ class OC_Filestorage_Local extends OC_Filestorage{
 			if ($item == '.' || $item == '..') continue;
 			if(is_file($dir.'/'.$item)){
 				if(unlink($dir.'/'.$item)){
-					$this->clearFolderSizeCache($dir);
 				}
 			}elseif(is_dir($dir.'/'.$item)){
 				if (!$this->delTree($dirRelative. "/" . $item)){
@@ -228,7 +203,6 @@ class OC_Filestorage_Local extends OC_Filestorage{
 			}
 		}
 		if($return=rmdir($dir)){
-			$this->clearFolderSizeCache($dir);
 		}
 		return $return;
 	}
@@ -268,75 +242,6 @@ class OC_Filestorage_Local extends OC_Filestorage{
 	 * @return int size of folder and it's content
 	 */
 	public function getFolderSize($path){
-		$path=str_replace('//','/',$path);
-		if($this->is_dir($path) and substr($path,-1)!='/'){
-			$path.='/';
-		}
-		$query=OC_DB::prepare("SELECT size FROM *PREFIX*foldersize WHERE path=?");
-		$size=$query->execute(array($path))->fetchAll();
-		if(count($size)>0){// we already the size, just return it
-			return $size[0]['size'];
-		}else{//the size of the folder isn't know, calulate it
-			return $this->calculateFolderSize($path);
-		}
-	}
-
-	/**
-	 * @brief calulate the size of folder and it's content and cache it
-	 * @param string $path file path
-	 * @return int size of folder and it's content
-	 */
-	public function calculateFolderSize($path){
-		if($this->is_file($path)){
-			$path=dirname($path);
-		}
-		$path=str_replace('//','/',$path);
-		if($this->is_dir($path) and substr($path,-1)!='/'){
-			$path.='/';
-		}
-		$size=0;
-		if ($dh = $this->opendir($path)) {
-			while (($filename = readdir($dh)) !== false) {
-				if($filename!='.' and $filename!='..'){
-					$subFile=$path.'/'.$filename;
-					if($this->is_file($subFile)){
-						$size+=$this->filesize($subFile);
-					}else{
-						$size+=$this->getFolderSize($subFile);
-					}
-				}
-			}
-			if($size>0){
-				$query=OC_DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)");
-				$result=$query->execute(array($path,$size));
-			}
-		}
-		return $size;
-	}
-
-	/**
-	 * @brief clear the folder size cache of folders containing a file
-	 * @param string $path
-	 */
-	public function clearFolderSizeCache($path){
-		if($this->is_file($path)){
-			$path=dirname($path);
-		}
-		$path=str_replace('//','/',$path);
-		if($this->is_dir($path) and substr($path,-1)!='/'){
-			$path.='/';
-		}
-		$query=OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?");
-		$result=$query->execute(array($path));
-		if($path!='/' and $path!=''){
-			$parts=explode('/',$path);
-			//pop empty part
-			$part=array_pop($parts);
-			if(empty($part)){
-				array_pop($parts);
-			}
-			$parent=implode('/',$parts);
-			$this->clearFolderSizeCache($parent);
-		}
+		return 0;//depricated, use OC_FileCach instead
 	}
 }
diff --git a/lib/filestorage/remote.php b/lib/filestorage/remote.php
deleted file mode 100644
index 88bdbca481c8ad658f33e058e039cb23c23019c9..0000000000000000000000000000000000000000
--- a/lib/filestorage/remote.php
+++ /dev/null
@@ -1,350 +0,0 @@
-<?php
-
-/**
-* ownCloud
-*
-* @author Frank Karlitschek 
-* @copyright 2010 Frank Karlitschek karlitschek@kde.org 
-* 
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either 
-* version 3 of the License, or any later version.
-* 
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*  
-* You should have received a copy of the GNU Affero General Public 
-* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
-* 
-*/
-
-class OC_Filestorage_Remote extends OC_Filestorage{
-	private $url;
-	private $username;
-	private $password;
-	private $remote=false;
-	private $statCache;
-	private $statCacheDir=false;
-	private $changed=array();
-	
-	private function cacheDir($dir){
-		if($this->statCacheDir!=$dir or $this->statCacheDir===false){
-			$this->statCache=$this->remote->getFiles($dir);
-			$keys=array_keys($this->statCache);
-			$this->statCacheDir=$dir;
-		}
-	}
-	
-	public function __construct($arguments){
-		$this->url=$arguments['url'];
-		$this->username=$arguments['username'];
-		$this->password=$arguments['password'];
-	}
-	private function connect(){
-		if($this->remote===false){
-			$this->remote=OC_Connect::connect($this->url,$this->username,$this->password);
-		}
-	}
-	public function mkdir($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$return=$this->remote->newFile($parent,$name,'dir');
-		if($return){
-			$this->notifyObservers($path,OC_FILEACTION_CREATE);
-		}
-		return $return;
-	}
-	public function rmdir($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$return=$this->remote->delete($parent,$name);
-		if($return){
-			$this->notifyObservers($path,OC_FILEACTION_DELETE);
-		}
-		return $return;
-	}
-	public function opendir($path){
-		$this->connect();
-		$this->cacheDir($path);
-		$dirs=array_keys($this->statCache);
-		$id=uniqid();
-		global $FAKEDIRS;
-		$FAKEDIRS[$id]=$dirs;
-		if($return=opendir("fakedir://$id")){
-			$this->notifyObservers($path,OC_FILEACTION_READ);
-		}
-		return $return;
-	}
-	public function is_dir($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($path);
-		if($path=='' or $path=='/'){
-			return true;
-		}
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return ($this->statCache[$name]['type'=='dir']);
-	}
-	public function is_file($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return ($this->statCache[$name]['type'!='dir']);
-	}
-	public function stat($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return $false;
-		}
-		return $this->statCache[$name];
-	}
-	public function filetype($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return $this->statCache[$name]['type'];
-	}
-	public function filesize($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return $false;
-		}
-		return $this->statCache[$name]['size'];
-	}
-	public function is_readable($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return $this->statCache[$name]['readable'];
-	}
-	public function is_writeable($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return $this->statCache[$name]['writeable'];
-	}
-	public function file_exists($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		return isset($this->statCache[$name]);
-	}
-	public function readfile($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$file=$this->remote->getFile($parent,$name);
-		readfile($file);
-		unlink($file);
-	}
-	public function filectime($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return $this->statCache[$name]['ctime'];
-	}
-	public function filemtime($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return $this->statCache[$name]['mtime'];
-	}
-	public function fileatime($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return $this->statCache[$name]['atime'];
-	}
-	public function file_get_contents($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$file=$this->remote->getFile($parent,$name);
-		file_get_contents($file);
-		unlink($file);
-	}
-	public function file_put_contents($path,$data){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$file=$this->remote->getFile($parent,$name);
-		$file=tempnam(get_temp_dir(),'oc_');
-		file_put_contents($file,$data);
-		if($return=$this->remote->sendTmpFile($file,$parent,$name)){
-			$this->notifyObservers($path,OC_FILEACTION_WRITE);
-		}
-	}
-	public function unlink($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		if($return=$this->remote->delete($paren,$name)){
-			$this->notifyObservers($path,OC_FILEACTION_DELETE);
-		}
-		return $return;
-	}
-	public function rename($path1,$path2){
-		$this->connect();
-		$parent1=dirname($path1);
-		$name1=substr($path1,strlen($parent1)+1);
-		$parent2=dirname($path2);
-		$name2=substr($path2,strlen($parent2)+1);
-		if($return=$this->remote->move($parent1,$name1,$parent2,$name2)){
-			$this->notifyObservers($path1.'->'.$path2,OC_FILEACTION_RENAME);
-		}
-		return $return;
-	}
-	public function copy($path1,$path2){
-		$this->connect();
-		$parent1=dirname($path1);
-		$name1=substr($path1,strlen($parent1)+1);
-		$parent2=dirname($path2);
-		$name2=substr($path2,strlen($parent2)+1);
-		if($return=$this->copy->rename($parent1,$name1,$parent2,$name2)){
-			$this->notifyObservers($path1.'->'.$path2,OC_FILEACTION_RENAME);
-		}
-		return $return;
-	}
-	public function fopen($path,$mode){
-		$this->connect();
-		$changed=false;
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		$file=$this->remote->getFile($parent,$name);
-		if($return=fopen($file,$mode)){
-			switch($mode){
-				case 'r':
-					$this->notifyObservers($path,OC_FILEACTION_READ);
-					break;
-				case 'r+':
-				case 'w+':
-				case 'x+':
-				case 'a+':
-					$this->notifyObservers($path,OC_FILEACTION_READ | OC_FILEACTION_WRITE);
-					$this->changed[]=array('dir'=>$parent,'file'=>$name,'tmp'=>$file);
-					break;
-				case 'w':
-				case 'x':
-				case 'a':
-					$this->notifyObservers($path,OC_FILEACTION_WRITE);
-					$this->changed[]=array('dir'=>$parent,'file'=>$name,'tmp'=>$file);
-					break;
-			}
-		}
-		return $return;
-	}
-	
-	public function getMimeType($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		if(substr($name,0,1)=='/'){
-			$name=substr($name,1);
-		}
-		$this->cacheDir($parent);
-		if(!isset($this->statCache[$name])){
-			return false;
-		}
-		return $this->statCache[$name]['mime'];
-	}
-	
-	public function toTmpFile($path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		if(substr($name,0,1)=='/'){
-			$name=substr($name,1);
-		}
-		$filename=$this->remote->getFile($parent,$name);
-		if($filename){
-			$this->notifyObservers($path,OC_FILEACTION_READ);
-			return $filename;
-		}else{
-			return false;
-		}
-	}
-	
-	public function fromTmpFile($tmpFile,$path){
-		$this->connect();
-		$parent=dirname($path);
-		$name=substr($path,strlen($parent)+1);
-		if($this->remote->sendTmpFile($tmpFile,$parent,$name)){
-			$this->notifyObservers($path,OC_FILEACTION_CREATE);
-			return true;
-		}else{
-			return false;
-		}
-	}
-	
-	public function delTree($dir) {
-		$this->connect();
-		$parent=dirname($dir);
-		$name=substr($dir,strlen($parent)+1);
-		$return=$this->remote->delete($parent,$name);
-		if($return=rmdir($dir)){
-			$this->notifyObservers($dir,OC_FILEACTION_DELETE);
-		}
-		return $return;
-	}
-	
-	public function find($path){
-		return $this->getTree($path);
-	}
-	
-	public function getTree($dir) {
-		$this->connect();
-		if($return=$this->remote->getTree($dir)){
-			$this->notifyObservers($dir,OC_FILEACTION_READ);
-		}
-		return $return;
-	}
-	
-	public function __destruct(){
-		foreach($this->changed as $changed){
-			$this->remote->sendTmpFile($changed['tmp'],$changed['dir'],$changed['file']);
-		}
-	}
-}
diff --git a/lib/filestoragecommon.php b/lib/filestoragecommon.php
new file mode 100644
index 0000000000000000000000000000000000000000..f522d15c4e9ee9bbd3cdf08e28571f5ef0a3ad2a
--- /dev/null
+++ b/lib/filestoragecommon.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+* ownCloud
+*
+* @author Michael Gapczynski
+* @copyright 2012 Michael Gapczynski GapczynskiM@gmail.com
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class OC_Filestorage_Common extends OC_Filestorage {
+
+	public function __construct($parameters){}
+	public function mkdir($path){}
+	public function rmdir($path){}
+	public function opendir($path){}
+	public function is_dir($path){}
+	public function is_file($path){}
+	public function stat($path){}
+	public function filetype($path){}
+	public function filesize($path) {
+		$stat = $this->stat($path);
+		return $stat['size'];
+	}
+	public function is_readable($path){}
+	public function is_writable($path){}
+	public function file_exists($path){}
+	public function readfile($path) {
+		$handle = $this->fopen($path, "r");
+		$chunk = 1024;
+		while (!feof($handle)) {
+			echo fread($handle, $chunk);
+		}
+		return $this->filesize($path);
+	}
+	public function filectime($path) {
+		$stat = $this->stat($path);
+		return $stat['ctime'];
+	}
+	public function filemtime($path) {
+		$stat = $this->stat($path);
+		return $stat['mtime'];
+	}
+	public function fileatime($path) {
+		$stat = $this->stat($path);
+		return $stat['atime'];
+	}
+	public function file_get_contents($path) {
+		$handle = $this->fopen($path, "r");
+		return fread($handle, $this->filesize($path));
+	}
+	public function file_put_contents($path,$data) {
+		$handle = $this->fopen($path, "w");
+		return fwrite($handle, $data);
+	}
+	public function unlink($path){}
+	public function rename($path1,$path2){}
+	public function copy($path1,$path2) {
+		$data = $this->file_get_contents($path1);
+		return $this->file_put_contents($path2, $data);
+	}
+	public function fopen($path,$mode){}
+	public function toTmpFile($path){}
+	public function fromTmpFile($tmpPath,$path){}
+	public function fromUploadedFile($tmpPath,$path){}
+	public function getMimeType($path){}
+	public function hash($type,$path,$raw){}
+	public function free_space($path){}
+	public function search($query){}
+	public function getLocalFile($path){}
+}
diff --git a/lib/filesystem.php b/lib/filesystem.php
index bd953deb2107dc3188aeb0cfb12f0b6e8a521ac8..a18072ecbc2751f98348501d2aa1caf606e8023b 100644
--- a/lib/filesystem.php
+++ b/lib/filesystem.php
@@ -42,11 +42,15 @@
  *
  *   the &run parameter can be set to false to prevent the operation from occuring
  */
+
 class OC_Filesystem{
 	static private $storages=array();
 	static private $mounts=array();
-	static private $fakeRoot='';
 	static private $storageTypes=array();
+	public static $loaded=false;
+	private $fakeRoot='';
+	static private $defaultInstance;
+
 
   /**
    * classname which used for hooks handling
@@ -134,31 +138,78 @@ class OC_Filesystem{
    */
   const signal_param_run = 'run';
 
-	/**
-	* register a storage type
-	* @param  string  type
-	* @param  string  classname
-	* @param  array  arguments     an associative array in the form of name=>type (eg array('datadir'=>'string'))
+  /**
+	* get the mountpoint of the storage object for a path
+	( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account
+	*
+	* @param string path
+	* @return string
 	*/
-	static public function registerStorageType($type,$classname,$arguments){
-		self::$storageTypes[$type]=array('type'=>$type,'classname'=>$classname,'arguments'=>$arguments);
+	static public function getMountPoint($path){
+		if(!$path){
+			$path='/';
+		}
+		if(substr($path,0,1)!=='/'){
+			$path='/'.$path;
+		}
+		if(substr($path,-1)!=='/'){
+			$path=$path.'/';
+		}
+		$foundMountPoint='';
+		foreach(OC_Filesystem::$mounts as $mountpoint=>$storage){
+			if(substr($mountpoint,-1)!=='/'){
+				$mountpoint=$mountpoint.'/';
+			}
+			if($mountpoint==$path){
+				return $mountpoint;
+			}
+			if(strpos($path,$mountpoint)===0 and strlen($mountpoint)>strlen($foundMountPoint)){
+				$foundMountPoint=$mountpoint;
+			}
+		}
+		return $foundMountPoint;
 	}
-	
+
 	/**
-	* check if the filesystem supports a specific storagetype
-	* @param  string  type
+	* get the part of the path relative to the mountpoint of the storage it's stored in
+	* @param  string  path
 	* @return bool
 	*/
-	static public function hasStorageType($type){
-		return isset(self::$storageTypes[$type]);
+	static public function getInternalPath($path){
+		$mountPoint=self::getMountPoint($path);
+		$internalPath=substr($path,strlen($mountPoint));
+		return $internalPath;
 	}
-	
 	/**
-	* get the list of names of storagetypes that the filesystem supports
-	* @return array
+	* get the storage object for a path
+	* @param string path
+	* @return OC_Filestorage
 	*/
-	static public function getStorageTypeNames(){
-		return array_keys(self::$storageTypes);
+	static public function getStorage($path){
+		$mountpoint=self::getMountPoint($path);
+		if($mountpoint){
+			if(!isset(OC_Filesystem::$storages[$mountpoint])){
+				$mount=OC_Filesystem::$mounts[$mountpoint];
+				OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'],$mount['arguments']);
+			}
+			return OC_Filesystem::$storages[$mountpoint];
+		}
+	}
+	
+	static public function init($root){
+		if(self::$defaultInstance){
+			return false;
+		}
+		self::$defaultInstance=new OC_FilesystemView($root);
+		self::$loaded=true;
+	}
+
+	/**
+	 * get the default filesystem view
+	 * @return OC_FilesystemView
+	 */
+	static public function getView(){
+		return self::$defaultInstance;
 	}
 	
 	/**
@@ -177,13 +228,9 @@ class OC_Filesystem{
 	* @param  array  arguments
 	* @return OC_Filestorage
 	*/
-	static private function createStorage($type,$arguments){
-		if(!self::hasStorageType($type)){
-			return false;
-		}
-		$className=self::$storageTypes[$type]['classname'];
-		if(class_exists($className)){
-			return new $className($arguments);
+	static private function createStorage($class,$arguments){
+		if(class_exists($class)){
+			return new $class($arguments);
 		}else{
 			return false;
 		}
@@ -195,36 +242,27 @@ class OC_Filesystem{
 	* @return bool
 	*/
 	static public function chroot($fakeRoot){
-		if(!$fakeRoot==''){
-			if($fakeRoot[0]!=='/'){
-				$fakeRoot='/'.$fakeRoot;
-			}
-		}
-		self::$fakeRoot=$fakeRoot;
+		return self::$defaultInstance->chroot($path);
 	}
-	
+
 	/**
-	* get the part of the path relative to the mountpoint of the storage it's stored in
-	* @param  string  path
-	* @return bool
-	*/
-	static public function getInternalPath($path){
-		$mountPoint=self::getMountPoint($path);
-		$path=self::$fakeRoot.$path;
-		$internalPath=substr($path,strlen($mountPoint));
-		return $internalPath;
+	 * get the fake root
+	 * @return string
+	 */
+	static public function getRoot(){
+		return self::$defaultInstance->getRoot();
 	}
-	
+
 	/**
 	* mount an OC_Filestorage in our virtual filesystem
 	* @param OC_Filestorage storage
 	* @param string mountpoint
 	*/
-	static public function mount($type,$arguments,$mountpoint){
+	static public function mount($class,$arguments,$mountpoint){
 		if(substr($mountpoint,0,1)!=='/'){
 			$mountpoint='/'.$mountpoint;
 		}
-		self::$mounts[$mountpoint]=array('type'=>$type,'arguments'=>$arguments);
+		self::$mounts[$mountpoint]=array('class'=>$class,'arguments'=>$arguments);
 	}
 
 	/**
@@ -238,55 +276,6 @@ class OC_Filesystem{
 		}
 	}
 	
-	/**
-	* get the storage object for a path
-	* @param string path
-	* @return OC_Filestorage
-	*/
-	static public function getStorage($path){
-		$mountpoint=self::getMountPoint($path);
-		if($mountpoint){
-			if(!isset(self::$storages[$mountpoint])){
-				$mount=self::$mounts[$mountpoint];
-				self::$storages[$mountpoint]=self::createStorage($mount['type'],$mount['arguments']);
-			}
-			return self::$storages[$mountpoint];
-		}
-	}
-	
-	/**
-	* get the mountpoint of the storage object for a path
-	( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account
-	*
-	* @param string path
-	* @return string
-	*/
-	static public function getMountPoint($path){
-		if(!$path){
-			$path='/';
-		}
-		if(substr($path,0,1)!=='/'){
-			$path='/'.$path;
-		}
-		if(substr($path,-1)!=='/'){
-			$path=$path.'/';
-		}
-		$path=self::$fakeRoot.$path;
-		$foundMountPoint='';
-		foreach(self::$mounts as $mountpoint=>$storage){
-			if(substr($mountpoint,-1)!=='/'){
-				$mountpoint=$mountpoint.'/';
-			}
-			if($mountpoint==$path){
-				return $mountpoint;
-			}
-			if(strpos($path,$mountpoint)===0 and strlen($mountpoint)>strlen($foundMountPoint)){
-				$foundMountPoint=$mountpoint;
-			}
-		}
-		return $foundMountPoint;
-	}
-	
 	/**
 	* return the path to a local version of the file
 	* we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed
@@ -294,10 +283,7 @@ class OC_Filesystem{
 	* @return string
 	*/
 	static public function getLocalFile($path){
-		$parent=substr($path,0,strrpos($path,'/'));
-		if(self::isValidPath($parent) and $storage=self::getStorage($path)){
-			return $storage->getLocalFile(self::getInternalPath($path));
-		}
+		return self::$defaultInstance->getLocalFile($path);
 	}
 	
 	/**
@@ -314,262 +300,90 @@ class OC_Filesystem{
 		}
 		return true;
 	}
-	
+	/**
+	 * following functions are equivilent to their php buildin equivilents for arguments/return values.
+	 */
 	static public function mkdir($path){
-		return self::basicOperation('mkdir',$path,array('create','write'));
+		return self::$defaultInstance->mkdir($path);
 	}
 	static public function rmdir($path){
-		return self::basicOperation('rmdir',$path,array('delete'));
+		return self::$defaultInstance->rmdir($path);
 	}
 	static public function opendir($path){
-		return self::basicOperation('opendir',$path,array('read'));
+		return self::$defaultInstance->opendir($path);
 	}
 	static public function is_dir($path){
-		if($path=='/'){
-			return true;
-		}
-		return self::basicOperation('is_dir',$path);
+		return self::$defaultInstance->is_dir($path);
 	}
 	static public function is_file($path){
-		if($path=='/'){
-			return false;
-		}
-		return self::basicOperation('is_file',$path);
+		return self::$defaultInstance->is_file($path);
 	}
 	static public function stat($path){
-		return self::basicOperation('stat',$path);
+		return self::$defaultInstance->stat($path);
 	}
 	static public function filetype($path){
-		return self::basicOperation('filetype',$path);
+		return self::$defaultInstance->filetype($path);
 	}
 	static public function filesize($path){
-		return self::basicOperation('filesize',$path);
+		return self::$defaultInstance->filesize($path);
 	}
 	static public function readfile($path){
-		return self::basicOperation('readfile',$path,array('read'));
+		return self::$defaultInstance->readfile($path);
 	}
 	static public function is_readable($path){
-		return self::basicOperation('is_readable',$path);
+		return self::$defaultInstance->is_readable($path);
 	}
-	static public function is_writeable($path){
-		return self::basicOperation('is_writeable',$path);
+	static public function is_writable($path){
+		return self::$defaultInstance->is_writable($path);
 	}
 	static public function file_exists($path){
-		if($path=='/'){
-			return true;
-		}
-		return self::basicOperation('file_exists',$path);
+		return self::$defaultInstance->file_exists($path);
 	}
 	static public function filectime($path){
-		return self::basicOperation('filectime',$path);
+		return self::$defaultInstance->filectime($path);
 	}
 	static public function filemtime($path){
-		return self::basicOperation('filemtime',$path);
-	}
-	static public function fileatime($path){
-		return self::basicOperation('fileatime',$path);
+		return self::$defaultInstance->filemtime($path);
 	}
 	static public function file_get_contents($path){
-		return self::basicOperation('file_get_contents',$path,array('read'));
+		return self::$defaultInstance->file_get_contents($path);
 	}
 	static public function file_put_contents($path,$data){
-		return self::basicOperation('file_put_contents',$path,array('create','write'),$data);
+		return self::$defaultInstance->file_put_contents($path,$data);
 	}
 	static public function unlink($path){
-		return self::basicOperation('unlink',$path,array('delete'));
+		return self::$defaultInstance->unlink($path);
 	}
 	static public function rename($path1,$path2){
-		if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and self::is_writeable($path1) and self::isValidPath($path2)){
-			$run=true;
-      OC_Hook::emit( self::CLASSNAME, self::signal_rename, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2, self::signal_param_run => &$run));
-			if($run){
-				$mp1=self::getMountPoint($path1);
-				$mp2=self::getMountPoint($path2);
-				if($mp1==$mp2){
-					if($storage=self::getStorage($path1)){
-						$result=$storage->rename(self::getInternalPath($path1),self::getInternalPath($path2));
-					}
-				}elseif($storage1=self::getStorage($path1) and $storage2=self::getStorage($path2)){
-					$tmpFile=$storage1->toTmpFile(self::getInternalPath($path1));
-					$result=$storage2->fromTmpFile($tmpFile,self::getInternalPath($path2));
-					$storage1->unlink(self::getInternalPath($path1));
-				}
-        OC_Hook::emit( self::CLASSNAME, self::signal_post_rename, array( self::signal_param_oldpath => $path1, self::signal_param_newpath=>$path2));
-				return $result;
-			}
-		}
+		return self::$defaultInstance->rename($path1,$path2);
 	}
 	static public function copy($path1,$path2){
-		if(OC_FileProxy::runPreProxies('copy',$path1,$path2) and self::is_readable($path1) and self::isValidPath($path2)){
-			$run=true;
-      OC_Hook::emit( self::CLASSNAME, self::signal_copy, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2, self::signal_param_run => &$run));
-			$exists=self::file_exists($path2);
-			if($run and !$exists){
-        OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path2, self::signal_param_run => &$run));
-			}
-			if($run){
-        OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path2, self::signal_param_run => &$run));
-			}
-			if($run){
-				$mp1=self::getMountPoint($path1);
-				$mp2=self::getMountPoint($path2);
-				if($mp1==$mp2){
-					if($storage=self::getStorage($path1)){
-						$result=$storage->copy(self::getInternalPath($path1),self::getInternalPath($path2));
-					}
-				}elseif($storage1=self::getStorage($path1) and $storage2=self::getStorage($path2)){
-					$tmpFile=$storage1->toTmpFile(self::getInternalPath($path1));
-					$result=$storage2->fromTmpFile($tmpFile,self::getInternalPath($path2));
-				}
-        OC_Hook::emit( self::CLASSNAME, self::signal_post_copy, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2));
-				if(!$exists){
-          OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path2));
-				}
-        OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path2));
-				return $result;
-			}
-		}
+		return self::$defaultInstance->copy($path1,$path2);
 	}
 	static public function fopen($path,$mode){
-		$hooks=array();
-		switch($mode){
-			case 'r':
-				$hooks[]='read';
-				break;
-			case 'r+':
-			case 'w+':
-			case 'x+':
-			case 'a+':
-				$hooks[]='read';
-				$hooks[]='write';
-				break;
-			case 'w':
-			case 'x':
-			case 'a':
-				$hooks[]='write';
-				break;
-			default:
-				OC_Log::write('core','invalid mode ('.$mode.') for '.$path,OC_Log::ERROR);
-		}
-		
-		return self::basicOperation('fopen',$path,$hooks,$mode);
+		return self::$defaultInstance->fopen($path,$mode);
 	}
 	static public function toTmpFile($path){
-		if(OC_FileProxy::runPreProxies('toTmpFile',$path) and self::isValidPath($path) and $storage=self::getStorage($path)){
-      OC_Hook::emit( self::CLASSNAME, self::signal_read, array( self::signal_param_path => $path));
-			return $storage->toTmpFile(self::getInternalPath($path));
-		}
+		return self::$defaultInstance->toTmpFile($path);
 	}
 	static public function fromTmpFile($tmpFile,$path){
-		if(OC_FileProxy::runPreProxies('copy',$tmpFile,$path) and self::isValidPath($path) and $storage=self::getStorage($path)){
-			$run=true;
-			$exists=self::file_exists($path);
-			if(!$exists){
-        OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path, self::signal_param_run => &$run));
-			}
-			if($run){
-        OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path, self::signal_param_run => &$run));
-			}
-			if($run){
-				$result=$storage->fromTmpFile($tmpFile,self::getInternalPath($path));
-				if(!$exists){
-          OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path));
-				}
-        OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path));
-				return $result;
-			}
-		}
-	}
-	static public function fromUploadedFile($tmpFile,$path){
-		if(OC_FileProxy::runPreProxies('fromUploadedFile',$tmpFile,$path) and self::isValidPath($path) and $storage=self::getStorage($path)){
-			$run=true;
-			$exists=self::file_exists($path);
-			if(!$exists){
-        OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path, self::signal_param_run => &$run));
-			}
-			if($run){
-        OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path, self::signal_param_run => &$run));
-			}
-			if($run){
-				$result=$storage->fromUploadedFile($tmpFile,self::getInternalPath($path));
-				if(!$exists){
-          OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path));
-				}
-        OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path));
-				return $result;
-			}
-		}
+		return self::$defaultInstance->fromTmpFile($tmpFile,$path);
 	}
+
 	static public function getMimeType($path){
-		return self::basicOperation('getMimeType',$path);
+		return self::$defaultInstance->getMimeType($path);
 	}
 	static public function hash($type,$path){
-		return self::basicOperation('hash',$path,array('read'));
+		return self::$defaultInstance->hash($type,$path);
 	}
 	
 	static public function free_space($path='/'){
-		return self::basicOperation('free_space',$path);
+		return self::$defaultInstance->free_space($path);
 	}
 	
 	static public function search($query){
-		self::mountAll();
-		$files=array();
-		$fakeRoot=self::$fakeRoot;
-		$fakeRootLength=strlen($fakeRoot);
-		foreach(self::$storages as $mountpoint=>$storage){
-			$results=$storage->search($query);
-			if(is_array($results)){
-				foreach($results as $result){
-					$file=str_replace('//','/',$mountpoint.$result);
-					if(substr($file,0,$fakeRootLength)==$fakeRoot){
-						$file=substr($file,$fakeRootLength);
-						$files[]=$file;
-					}
-				}
-			}
-		}
-		return $files;
-		
-	}
-	
-	static public function update_session_file_hash($sessionname,$sessionvalue){
-		$_SESSION[$sessionname] = $sessionvalue;
-	}
-
-	/**
-	 * abstraction for running most basic operations
-	 * @param string $operation
-	 * @param string #path
-	 * @param array (optional) hooks
-	 * @param mixed (optional) $extraParam
-	 * @return mixed
-	 */
-	private static function basicOperation($operation,$path,$hooks=array(),$extraParam=null){
-		if(OC_FileProxy::runPreProxies($operation,$path, $extraParam) and self::isValidPath($path) and $storage=self::getStorage($path)){
-			$interalPath=self::getInternalPath($path);
-			$run=true;
-			foreach($hooks as $hook){
-				if($hook!='read'){
-          OC_Hook::emit( self::CLASSNAME, $hook, array( self::signal_param_path => $path, self::signal_param_run => &$run));
-				}else{
-          OC_Hook::emit( self::CLASSNAME, $hook, array( self::signal_param_path => $path));
-				}
-			}
-			if($run){
-				if($extraParam){
-					$result=$storage->$operation($interalPath,$extraParam);
-				}else{
-					$result=$storage->$operation($interalPath);
-				}
-				$result=OC_FileProxy::runPostProxies($operation,$path,$result);
-				foreach($hooks as $hook){
-					if($hook!='read'){
-            OC_Hook::emit( self::CLASSNAME, 'post_'.$hook, array( self::signal_param_path => $path));
-					}
-				}
-				return $result;
-			}
-		}
-		return null;
+		return OC_FileCache::search($query);
 	}
 }
+
+require_once('filecache.php');
diff --git a/lib/filesystemview.php b/lib/filesystemview.php
new file mode 100644
index 0000000000000000000000000000000000000000..4586507a8112b860cad82fb1c121fb4233955ba9
--- /dev/null
+++ b/lib/filesystemview.php
@@ -0,0 +1,318 @@
+<?php
+
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+class OC_FilesystemView {
+	private $fakeRoot='';
+	
+	public function __construct($root){
+		$this->fakeRoot=$root;
+	}
+	
+	public function getAbsolutePath($path){
+		if(!$path){
+			$path='/';
+		}
+		if(substr($path,0,1)!=='/'){
+			$path='/'.$path;
+		}
+		return $this->fakeRoot.$path;
+	}
+
+
+	/**
+	* change the root to a fake toor
+	* @param  string  fakeRoot
+	* @return bool
+	*/
+	public function chroot($fakeRoot){
+		if(!$fakeRoot==''){
+			if($fakeRoot[0]!=='/'){
+				$fakeRoot='/'.$fakeRoot;
+			}
+		}
+		$this->fakeRoot=$fakeRoot;
+	}
+
+	/**
+	 * get the fake root
+	 * @return string
+	 */
+	public function getRoot(){
+		return $this->fakeRoot;
+	}
+
+	/**
+	* get the part of the path relative to the mountpoint of the storage it's stored in
+	* @param  string  path
+	* @return bool
+	*/
+	public function getInternalPath($path){
+		return OC_Filesystem::getInternalPath($this->getAbsolutePath($path));
+	}
+	/**
+	* get the storage object for a path
+	* @param string path
+	* @return OC_Filestorage
+	*/
+	public function getStorage($path){
+		return OC_Filesystem::getStorage($this->getAbsolutePath($path));
+	}
+
+	/**
+	* get the mountpoint of the storage object for a path
+	( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account
+	*
+	* @param string path
+	* @return string
+	*/
+	public function getMountPoint($path){
+		return OC_Filesystem::getMountPoint($this->getAbsolutePath($path));
+	}
+
+	/**
+	* return the path to a local version of the file
+	* we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed
+	* @param string path
+	* @return string
+	*/
+	public function getLocalFile($path){
+		$parent=substr($path,0,strrpos($path,'/'));
+		if(OC_Filesystem::isValidPath($parent) and $storage=$this->getStorage($path)){
+			return $storage->getLocalFile($this->getInternalPath($path));
+		}
+	}
+
+	/**
+	 * following functions are equivilent to their php buildin equivilents for arguments/return values.
+	 */
+	public function mkdir($path){
+		return $this->basicOperation('mkdir',$path,array('create','write'));
+	}
+	public function rmdir($path){
+		return $this->basicOperation('rmdir',$path,array('delete'));
+	}
+	public function opendir($path){
+		return $this->basicOperation('opendir',$path,array('read'));
+	}
+	public function is_dir($path){
+		if($path=='/'){
+			return true;
+		}
+		return $this->basicOperation('is_dir',$path);
+	}
+	public function is_file($path){
+		if($path=='/'){
+			return false;
+		}
+		return $this->basicOperation('is_file',$path);
+	}
+	public function stat($path){
+		return $this->basicOperation('stat',$path);
+	}
+	public function filetype($path){
+		return $this->basicOperation('filetype',$path);
+	}
+	public function filesize($path){
+		return $this->basicOperation('filesize',$path);
+	}
+	public function readfile($path){
+		return $this->basicOperation('readfile',$path,array('read'));
+	}
+	public function is_readable($path){
+		return $this->basicOperation('is_readable',$path);
+	}
+	public function is_writable($path){
+		return $this->basicOperation('is_writable',$path);
+	}
+	public function file_exists($path){
+		if($path=='/'){
+			return true;
+		}
+		return $this->basicOperation('file_exists',$path);
+	}
+	public function filectime($path){
+		return $this->basicOperation('filectime',$path);
+	}
+	public function filemtime($path){
+		return $this->basicOperation('filemtime',$path);
+	}
+	public function file_get_contents($path){
+		return $this->basicOperation('file_get_contents',$path,array('read'));
+	}
+	public function file_put_contents($path,$data){
+		return $this->basicOperation('file_put_contents',$path,array('create','write'),$data);
+	}
+	public function unlink($path){
+		return $this->basicOperation('unlink',$path,array('delete'));
+	}
+	public function rename($path1,$path2){
+		if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and $this->is_writable($path1) and OC_Filesystem::isValidPath($path2)){
+			$run=true;
+			OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run));
+			if($run){
+				$mp1=$this->getMountPoint($path1);
+				$mp2=$this->getMountPoint($path2);
+				if($mp1==$mp2){
+					if($storage=$this->getStorage($path1)){
+						$result=$storage->rename($this->getInternalPath($path1),$this->getInternalPath($path2));
+					}
+				}elseif($storage1=$this->getStorage($path1) and $storage2=$this->getStorage($path2)){
+					$tmpFile=$storage1->toTmpFile($this->getInternalPath($path1));
+					$result=$storage2->fromTmpFile($tmpFile,$this->getInternalPath($path2));
+					$storage1->unlink($this->getInternalPath($path1));
+				}
+				OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_rename, array( OC_Filesystem::signal_param_oldpath => $path1, OC_Filesystem::signal_param_newpath=>$path2));
+				return $result;
+			}
+		}
+	}
+	public function copy($path1,$path2){
+		if(OC_FileProxy::runPreProxies('copy',$path1,$path2) and $this->is_readable($path1) and OC_Filesystem::isValidPath($path2)){
+			$run=true;
+			OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_copy, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run));
+			$exists=$this->file_exists($path2);
+			if($run and !$exists){
+				OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, array( OC_Filesystem::signal_param_path => $path2, OC_Filesystem::signal_param_run => &$run));
+			}
+			if($run){
+				OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, array( OC_Filesystem::signal_param_path => $path2, OC_Filesystem::signal_param_run => &$run));
+			}
+			if($run){
+				$mp1=$this->getMountPoint($path1);
+				$mp2=$this->getMountPoint($path2);
+				if($mp1==$mp2){
+					if($storage=$this->getStorage($path1)){
+						$result=$storage->copy($this->getInternalPath($path1),$this->getInternalPath($path2));
+					}
+				}elseif($storage1=$this->getStorage($path1) and $storage2=$this->getStorage($path2)){
+					$tmpFile=$storage1->toTmpFile($this->getInternalPath($path1));
+					$result=$storage2->fromTmpFile($tmpFile,$this->getInternalPath($path2));
+				}
+        OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_copy, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2));
+				if(!$exists){
+          OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, array( OC_Filesystem::signal_param_path => $path2));
+				}
+        OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path2));
+				return $result;
+			}
+		}
+	}
+	public function fopen($path,$mode){
+		$hooks=array();
+		switch($mode){
+			case 'r':
+				$hooks[]='read';
+				break;
+			case 'r+':
+			case 'w+':
+			case 'x+':
+			case 'a+':
+				$hooks[]='read';
+				$hooks[]='write';
+				break;
+			case 'w':
+			case 'x':
+			case 'a':
+				$hooks[]='write';
+				break;
+			default:
+				OC_Log::write('core','invalid mode ('.$mode.') for '.$path,OC_Log::ERROR);
+		}
+
+		return $this->basicOperation('fopen',$path,$hooks,$mode);
+	}
+	public function toTmpFile($path){
+		if(OC_FileProxy::runPreProxies('toTmpFile',$path) and OC_Filesystem::isValidPath($path) and $storage=$this->getStorage($path)){
+			OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_read, array( OC_Filesystem::signal_param_path => $path));
+			return $storage->toTmpFile($this->getInternalPath($path));
+		}
+	}
+	public function fromTmpFile($tmpFile,$path){
+		if(OC_FileProxy::runPreProxies('copy',$tmpFile,$path) and OC_Filesystem::isValidPath($path) and $storage=$this->getStorage($path)){
+			$run=true;
+			$exists=$this->file_exists($path);
+			if(!$exists){
+				OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run));
+			}
+			if($run){
+				OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run));
+			}
+			if($run){
+				$result=$storage->fromTmpFile($tmpFile,$this->getInternalPath($path));
+				if(!$exists){
+					OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, array( OC_Filesystem::signal_param_path => $path));
+				}
+				OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path));
+				return $result;
+			}
+		}
+	}
+
+	public function getMimeType($path){
+		return $this->basicOperation('getMimeType',$path);
+	}
+	public function hash($type,$path){
+		return $this->basicOperation('hash',$path,array('read'));
+	}
+
+	public function free_space($path='/'){
+		return $this->basicOperation('free_space',$path);
+	}
+
+	/**
+	 * abstraction for running most basic operations
+	 * @param string $operation
+	 * @param string #path
+	 * @param array (optional) hooks
+	 * @param mixed (optional) $extraParam
+	 * @return mixed
+	 */
+	private function basicOperation($operation,$path,$hooks=array(),$extraParam=null){
+		if(OC_FileProxy::runPreProxies($operation,$path, $extraParam) and OC_Filesystem::isValidPath($path) and $storage=$this->getStorage($path)){
+			$interalPath=$this->getInternalPath($path);
+			$run=true;
+			foreach($hooks as $hook){
+				if($hook!='read'){
+					OC_Hook::emit( OC_Filesystem::CLASSNAME, $hook, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run));
+				}else{
+					OC_Hook::emit( OC_Filesystem::CLASSNAME, $hook, array( OC_Filesystem::signal_param_path => $path));
+				}
+			}
+			if($run){
+				if($extraParam){
+					$result=$storage->$operation($interalPath,$extraParam);
+				}else{
+					$result=$storage->$operation($interalPath);
+				}
+				$result=OC_FileProxy::runPostProxies($operation,$path,$result);
+				foreach($hooks as $hook){
+					if($hook!='read'){
+						OC_Hook::emit( OC_Filesystem::CLASSNAME, 'post_'.$hook, array( OC_Filesystem::signal_param_path => $path));
+					}
+				}
+				return $result;
+			}
+		}
+		return null;
+	}
+}
diff --git a/lib/search/provider/file.php b/lib/search/provider/file.php
index 5fd35fa3e523416bba7d2eb647297b2845a185b5..c3dc2942aef43cbabc6bfddb3364191e7212b35f 100644
--- a/lib/search/provider/file.php
+++ b/lib/search/provider/file.php
@@ -2,14 +2,15 @@
 
 class OC_Search_Provider_File extends OC_Search_Provider{
 	function search($query){
-		$files=OC_Filesystem::search($query);
+		$files=OC_FileCache::search($query,true);
 		$results=array();
-		foreach($files as $file){
-			if(OC_Filesystem::is_dir($file)){
+		foreach($files as $fileData){
+			$file=$fileData['path'];
+			if($fileData['mime']=='httpd/unix-directory'){
 				$results[]=new OC_Search_Result(basename($file),'',OC_Helper::linkTo( 'files', 'index.php?dir='.$file ),'Files');
 			}else{
-				$mime=OC_Filesystem::getMimeType($file);
-				$mimeBase=substr($mime,0,strpos($mime,'/'));
+				$mime=$fileData['mime'];
+				$mimeBase=$fileData['mimepart'];
 				switch($mimeBase){
 					case 'audio':
 						break;
diff --git a/lib/util.php b/lib/util.php
index 2fba1206bffe24ea121b752cca1f3be2541f39cc..abd918044b5ef640c9645732c953340c04e43f52 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -37,7 +37,7 @@ class OC_Util {
 
 		if( $user != "" ){ //if we aren't logged in, there is no use to set up the filesystem
 			//first set up the local "root" storage
-			OC_Filesystem::mount('local',array('datadir'=>$CONFIG_DATADIRECTORY_ROOT),'/');
+			OC_Filesystem::mount('OC_Filestorage_Local',array('datadir'=>$CONFIG_DATADIRECTORY_ROOT),'/');
 
 			OC::$CONFIG_DATADIRECTORY = $CONFIG_DATADIRECTORY_ROOT."/$user/$root";
 			if( !is_dir( OC::$CONFIG_DATADIRECTORY )){
@@ -45,7 +45,7 @@ class OC_Util {
 			}
 
 			//jail the user into his "home" directory
-			OC_Filesystem::chroot("/$user/$root");
+			OC_Filesystem::init('/'.$user.'/'.$root);
 			$quotaProxy=new OC_FileProxy_Quota();
 			OC_FileProxy::register($quotaProxy);
 			self::$fsSetup=true;
@@ -62,7 +62,7 @@ class OC_Util {
 	 * @return array
 	 */
 	public static function getVersion(){
-		return array(3,00,0);
+		return array(3,00,1);
 	}
 
 	/**
@@ -226,7 +226,7 @@ class OC_Util {
 			$errors[]=array('error'=>'PHP module ctype is not installed.<br/>','hint'=>'Please ask your server administrator to install the module.');
 		}
 
-		if(file_exists(OC::$SERVERROOT."/config/config.php") and !is_writeable(OC::$SERVERROOT."/config/config.php")){
+		if(file_exists(OC::$SERVERROOT."/config/config.php") and !is_writable(OC::$SERVERROOT."/config/config.php")){
 			$errors[]=array('error'=>"Can't write into config directory 'config'",'hint'=>"You can usually fix this by giving the webserver use write access to the config directory in owncloud");
 		}
 
diff --git a/owncloud.db.filesystem b/owncloud.db.filesystem
new file mode 100644
index 0000000000000000000000000000000000000000..082977a37eff00bc5a0e6aeffa6a8fa9f57025fd
Binary files /dev/null and b/owncloud.db.filesystem differ
diff --git a/settings/ajax/setquota.php b/settings/ajax/setquota.php
index 5c07285cfcac524f2a94a604094d63f150bd8f39..d4e3c58ac113d91f19fe8dd2ba72367c404dd402 100644
--- a/settings/ajax/setquota.php
+++ b/settings/ajax/setquota.php
@@ -6,10 +6,13 @@ require_once('../../lib/base.php');
 OC_JSON::checkAdminUser();
 
 $username = $_POST["username"];
+
+//make sure the quota is in the expected format
 $quota= OC_Helper::computerFileSize($_POST["quota"]);
+$quota=OC_Helper::humanFileSize($quota);
 
 // Return Success story
 OC_Preferences::setValue($username,'files','quota',$quota);
-OC_JSON::success(array("data" => array( "username" => $username ,'quota'=>OC_Helper::humanFileSize($quota))));
+OC_JSON::success(array("data" => array( "username" => $username ,'quota'=>$quota)));
 
 ?>
diff --git a/settings/personal.php b/settings/personal.php
index 3b90827ed999905d0e8c8fe2c5adf81b278c0394..07030109de7a5e2388a70d2e56c217a4bc2bdf49 100755
--- a/settings/personal.php
+++ b/settings/personal.php
@@ -16,7 +16,8 @@ OC_Util::addStyle( '3rdparty', 'chosen' );
 OC_App::setActiveNavigationEntry( 'personal' );
 
 // calculate the disc space
-$used=OC_Filesystem::filesize('/');
+$rootInfo=OC_FileCache::get('');
+$used=$rootInfo['size'];
 $free=OC_Filesystem::free_space();
 $total=$free+$used;
 $relative=round(($used/$total)*10000)/100;
diff --git a/settings/users.php b/settings/users.php
index 686c4b6a9bf625fe0cfc0d9733f9a658e405cff1..e5dcc0494817dff3d416bd5e4936a70064d38872 100644
--- a/settings/users.php
+++ b/settings/users.php
@@ -18,7 +18,7 @@ $users = array();
 $groups = array();
 
 foreach( OC_User::getUsers() as $i ){
-	$users[] = array( "name" => $i, "groups" => join( ", ", OC_Group::getUserGroups( $i ) ),'quota'=>OC_Helper::humanFileSize(OC_Preferences::getValue($i,'files','quota',0)));
+	$users[] = array( "name" => $i, "groups" => join( ", ", OC_Group::getUserGroups( $i ) ),'quota'=>OC_Preferences::getValue($i,'files','quota',0));
 }
 
 foreach( OC_Group::getGroups() as $i ){