diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php
index 5b5893abc930c0d2934ec6fa09472796f6d725ac..5711669815915dc736302d33cfd3e98f7097ea3b 100644
--- a/apps/files_sharing/appinfo/app.php
+++ b/apps/files_sharing/appinfo/app.php
@@ -5,8 +5,14 @@ OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'files_sharing/lib/share/folder.php'
 OC::$CLASSPATH['OC\Files\Storage\Shared'] = 'files_sharing/lib/sharedstorage.php';
 OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'files_sharing/lib/cache.php';
 OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'files_sharing/lib/permissions.php';
+OC::$CLASSPATH['OC\Files\Cache\Shared_Updater'] = 'files_sharing/lib/updater.php';
 OC::$CLASSPATH['OC\Files\Cache\Shared_Watcher'] = 'files_sharing/lib/watcher.php';
 OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
 OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
 OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
 OCP\Util::addScript('files_sharing', 'share');
+\OC_Hook::connect('OC_Filesystem', 'post_write', '\OC\Files\Cache\Shared_Updater', 'writeHook');
+\OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Shared_Updater', 'deleteHook');
+\OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Shared_Updater', 'renameHook');
+\OC_Hook::connect('OCP\Share', 'post_shared', '\OC\Files\Cache\Shared_Updater', 'shareHook');
+\OC_Hook::connect('OCP\Share', 'pre_unshare', '\OC\Files\Cache\Shared_Updater', 'shareHook');
\ No newline at end of file
diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php
index fb0f6c7b5a6bd3b4fb4f8cad64b4f7e900471bac..9fccd0b46f32481684e993d66b081cd4580b5cf0 100644
--- a/apps/files_sharing/lib/cache.php
+++ b/apps/files_sharing/lib/cache.php
@@ -28,10 +28,11 @@ namespace OC\Files\Cache;
  */
 class Shared_Cache extends Cache {
 
+	private $storage;
 	private $files = array();
 
 	public function __construct($storage) {
-
+		$this->storage = $storage;
 	}
 
 	/**
@@ -41,16 +42,19 @@ class Shared_Cache extends Cache {
 	 */
 	private function getSourceCache($target) {
 		$source = \OC_Share_Backend_File::getSource($target);
-		if (isset($source['path'])) {
-			$source['path'] = '/' . $source['uid_owner'] . '/' . $source['path'];
-			\OC\Files\Filesystem::initMountPoints($source['uid_owner']);
-			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source['path']);
-			if ($storage) {
-				$this->files[$target] = $internalPath;
-				$cache = $storage->getCache();
-				$this->storageId = $storage->getId();
-				$this->numericId = $cache->getNumericStorageId();
-				return $cache;
+		if (isset($source['path']) && isset($source['fileOwner'])) {
+			\OC\Files\Filesystem::initMountPoints($source['fileOwner']);
+			$mount = \OC\Files\Mount::findByNumericId($source['storage']);
+			if ($mount) {
+				$fullPath = $mount->getMountPoint().$source['path'];
+				list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath);
+				if ($storage) {
+					$this->files[$target] = $internalPath;
+					$cache = $storage->getCache();
+					$this->storageId = $storage->getId();
+					$this->numericId = $cache->getNumericStorageId();
+					return $cache;
+				}
 			}
 		}
 		return false;
@@ -64,7 +68,14 @@ class Shared_Cache extends Cache {
 	 */
 	public function get($file) {
 		if ($file == '') {
-			return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT);
+			$data = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT);
+			$etag = \OCP\Config::getUserValue(\OCP\User::getUser(), 'files_sharing', 'etag');
+			if (!isset($etag)) {
+				$etag = $this->storage->getETag('');
+				\OCP\Config::setUserValue(\OCP\User::getUser(), 'files_sharing', 'etag', $etag);
+			}
+			$data['etag'] = $etag;
+			return $data;
 		} else if (is_string($file)) {
 			if ($cache = $this->getSourceCache($file)) {
 				return $cache->get($this->files[$file]);
@@ -118,7 +129,9 @@ class Shared_Cache extends Cache {
 	 * @return int file id
 	 */
 	public function put($file, array $data) {
-		if ($cache = $this->getSourceCache($file)) {
+		if ($file === '' && isset($data['etag'])) {
+			return \OCP\Config::setUserValue(\OCP\User::getUser(), 'files_sharing', 'etag', $data['etag']);
+		} else if ($cache = $this->getSourceCache($file)) {
 			return $cache->put($this->files[$file], $data);
 		}
 		return false;
diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php
index fa43e87b49e39be3091e81c27501bbe36704b1e7..62948651806fdde14b0d28b67d64dcaa57567cc5 100644
--- a/apps/files_sharing/lib/share/file.php
+++ b/apps/files_sharing/lib/share/file.php
@@ -93,6 +93,7 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
 				$file['size'] = $item['size'];
 				$file['mtime'] = $item['mtime'];
 				$file['encrypted'] = $item['encrypted'];
+				$file['etag'] = $item['etag'];
 				$files[] = $file;
 			}
 			return $files;
diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php
index be0e59e6732dc52bbc8e0ec99fdf94200b41dde6..ffd4e5ced22bdd1264b2898b6b62bbe646f4be07 100644
--- a/apps/files_sharing/lib/sharedstorage.php
+++ b/apps/files_sharing/lib/sharedstorage.php
@@ -45,7 +45,18 @@ class Shared extends \OC\Files\Storage\Common {
 	*/
 	private function getFile($target) {
 		if (!isset($this->files[$target])) {
-			$this->files[$target] = \OC_Share_Backend_File::getSource($target);
+			// Check for partial files
+			if (pathinfo($target, PATHINFO_EXTENSION) === 'part') {
+				$source = \OC_Share_Backend_File::getSource(substr($target, 0, -5));
+				if ($source) {
+					$source['path'] .= '.part';
+					// All partial files have delete permission
+					$source['permissions'] |= \OCP\PERMISSION_DELETE;
+				}
+			} else {
+				$source = \OC_Share_Backend_File::getSource($target);
+			}
+			$this->files[$target] = $source;
 		}
 		return $this->files[$target];
 	}
@@ -280,34 +291,43 @@ class Shared extends \OC\Files\Storage\Common {
 	}
 
 	public function rename($path1, $path2) {
-		// Renaming/moving is only allowed within shared folders
-		$pos1 = strpos($path1, '/', 1);
-		$pos2 = strpos($path2, '/', 1);
-		if ($pos1 !== false && $pos2 !== false && ($oldSource = $this->getSourcePath($path1))) {
-			$newSource = $this->getSourcePath(dirname($path2)).'/'.basename($path2);
-			if (dirname($path1) == dirname($path2)) {
-				// Rename the file if UPDATE permission is granted
-				if ($this->isUpdatable($path1)) {
-					list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
-					list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
-					return $storage->rename($oldInternalPath, $newInternalPath);
-				}
-			} else {
-				// Move the file if DELETE and CREATE permissions are granted
-				if ($this->isDeletable($path1) && $this->isCreatable(dirname($path2))) {
-					// Get the root shared folder
-					$folder1 = substr($path1, 0, $pos1);
-					$folder2 = substr($path2, 0, $pos2);
-					// Copy and unlink the file if it exists in a different shared folder
-					if ($folder1 != $folder2) {
-						if ($this->copy($path1, $path2)) {
-							return $this->unlink($path1);
-						}
-					} else {
+		// Check for partial files
+		if (pathinfo($path1, PATHINFO_EXTENSION) === 'part') {
+			if ($oldSource = $this->getSourcePath($path1)) {
+				list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
+				$newInternalPath = substr($oldInternalPath, 0, -5);
+				return $storage->rename($oldInternalPath, $newInternalPath);
+			}
+		} else {
+			// Renaming/moving is only allowed within shared folders
+			$pos1 = strpos($path1, '/', 1);
+			$pos2 = strpos($path2, '/', 1);
+			if ($pos1 !== false && $pos2 !== false && ($oldSource = $this->getSourcePath($path1))) {
+				$newSource = $this->getSourcePath(dirname($path2)).'/'.basename($path2);
+				if (dirname($path1) == dirname($path2)) {
+					// Rename the file if UPDATE permission is granted
+					if ($this->isUpdatable($path1)) {
 						list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
 						list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
 						return $storage->rename($oldInternalPath, $newInternalPath);
 					}
+				} else {
+					// Move the file if DELETE and CREATE permissions are granted
+					if ($this->isDeletable($path1) && $this->isCreatable(dirname($path2))) {
+						// Get the root shared folder
+						$folder1 = substr($path1, 0, $pos1);
+						$folder2 = substr($path2, 0, $pos2);
+						// Copy and unlink the file if it exists in a different shared folder
+						if ($folder1 != $folder2) {
+							if ($this->copy($path1, $path2)) {
+								return $this->unlink($path1);
+							}
+						} else {
+							list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
+							list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
+							return $storage->rename($oldInternalPath, $newInternalPath);
+						}
+					}
 				}
 			}
 		}
@@ -371,7 +391,7 @@ class Shared extends \OC\Files\Storage\Common {
 
 	public function free_space($path) {
 		if ($path == '') {
-			return -1;
+			return \OC\Files\FREE_SPACE_UNKNOWN;
 		}
 		$source = $this->getSourcePath($path);
 		if ($source) {
diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php
new file mode 100644
index 0000000000000000000000000000000000000000..73e7808f24a08625fa50246dec64063935bd05a5
--- /dev/null
+++ b/apps/files_sharing/lib/updater.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Michael Gapczynski
+ * @copyright 2013 Michael Gapczynski mtgap@owncloud.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/>.
+ */
+
+namespace OC\Files\Cache;
+
+class Shared_Updater {
+
+	/**
+	* Correct the parent folders' ETags for all users shared the file at $target
+	*
+	* @param string $target
+	*/
+	static public function correctFolders($target) {
+		$uid = \OCP\User::getUser();
+		$uidOwner = \OC\Files\Filesystem::getOwner($target);
+		$info = \OC\Files\Filesystem::getFileInfo($target);
+		// Correct Shared folders of other users shared with
+		$users = \OCP\Share::getUsersItemShared('file', $info['fileid'], $uidOwner, true);
+		if (!empty($users)) {
+			while (!empty($users)) {
+				$reshareUsers = array();
+				foreach ($users as $user) {
+					$etag = \OC\Files\Filesystem::getETag('');
+					\OCP\Config::setUserValue($user, 'files_sharing', 'etag', $etag);
+					// Look for reshares
+					$reshareUsers = array_merge($reshareUsers, \OCP\Share::getUsersItemShared('file', $info['fileid'], $user, true));
+				}
+				$users = $reshareUsers;
+			}
+			// Correct folders of shared file owner
+			$target = substr($target, 8);
+			if ($uidOwner !== $uid && $source = \OC_Share_Backend_File::getSource($target)) {
+				\OC\Files\Filesystem::initMountPoints($uidOwner);
+				$source = '/'.$uidOwner.'/'.$source['path'];
+				\OC\Files\Cache\Updater::correctFolder($source, $info['mtime']);
+			}
+		}
+	}
+
+	/**
+	 * @param array $params
+	 */
+	static public function writeHook($params) {
+		self::correctFolders($params['path']);
+	}
+
+	/**
+	 * @param array $params
+	 */
+	static public function renameHook($params) {
+		self::correctFolders($params['oldpath']);
+		self::correctFolders($params['newpath']);
+	}
+
+	/**
+	 * @param array $params
+	 */
+	static public function deleteHook($params) {
+		self::correctFolders($params['path']);
+	}
+
+	/**
+	 * @param array $params
+	 */
+	static public function shareHook($params) {
+		if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
+			$uidOwner = \OCP\User::getUser();
+			$users = \OCP\Share::getUsersItemShared($params['itemType'], $params['fileSource'], $uidOwner, true);
+			if (!empty($users)) {
+				while (!empty($users)) {
+					$reshareUsers = array();
+					foreach ($users as $user) {
+						$etag = \OC\Files\Filesystem::getETag('');
+						\OCP\Config::setUserValue($user, 'files_sharing', 'etag', $etag);
+						// Look for reshares
+						$reshareUsers = array_merge($reshareUsers, \OCP\Share::getUsersItemShared('file', $params['fileSource'], $user, true));
+					}
+					$users = $reshareUsers;
+				}
+			}
+		}
+	}
+
+}
diff --git a/lib/public/share.php b/lib/public/share.php
index 59f41a9bfd6f59a0dbfacd9444b263a42c7d9ad0..bc404e2963f7650ca14df15f2fab6e32b04fcb76 100644
--- a/lib/public/share.php
+++ b/lib/public/share.php
@@ -198,6 +198,29 @@ class Share {
 			$parameters, -1, $includeCollections);
 	}
 
+	/**
+	* Get all users an item is shared with
+	* @param string Item type
+	* @param string Item source
+	* @param string Owner
+	* @param bool Include collections
+	* @return Return array of users
+	*/
+	public static function getUsersItemShared($itemType, $itemSource, $uidOwner, $includeCollections = false) {
+		$users = array();
+		$items = self::getItems($itemType, $itemSource, null, null, $uidOwner, self::FORMAT_NONE, null, -1, $includeCollections);
+		if ($items) {
+			foreach ($items as $item) {
+				if ((int)$item['share_type'] === self::SHARE_TYPE_USER) {
+					$users[] = $item['share_with'];
+				} else if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) {
+					$users = array_merge($users, \OC_Group::usersInGroup($item['share_with']));
+				}
+			}
+		}
+		return $users;
+	}
+
 	/**
 	* @brief Share an item with a user, group, or via private link
 	* @param string Item type
@@ -383,6 +406,7 @@ class Share {
 			\OC_Hook::emit('OCP\Share', 'pre_unshare', array(
 				'itemType' => $itemType,
 				'itemSource' => $itemSource,
+				'fileSource' => $item['file_source'],
 				'shareType' => $shareType,
 				'shareWith' => $shareWith,
 			));
@@ -1102,20 +1126,6 @@ class Share {
 				} else {
 					$fileTarget = null;
 				}
-				\OC_Hook::emit('OCP\Share', 'post_shared', array(
-					'itemType' => $itemType,
-					'itemSource' => $itemSource,
-					'itemTarget' => $itemTarget,
-					'parent' => $parent,
-					'shareType' => self::$shareTypeGroupUserUnique,
-					'shareWith' => $uid,
-					'uidOwner' => $uidOwner,
-					'permissions' => $permissions,
-					'fileSource' => $fileSource,
-					'fileTarget' => $fileTarget,
-					'id' => $parent,
-					'token' => $token
-				));
 				// Insert an extra row for the group share if the item or file target is unique for this user
 				if ($itemTarget != $groupItemTarget || (isset($fileSource) && $fileTarget != $groupFileTarget)) {
 					$query->execute(array($itemType, $itemSource, $itemTarget, $parent,
@@ -1124,6 +1134,20 @@ class Share {
 					$id = \OC_DB::insertid('*PREFIX*share');
 				}
 			}
+			\OC_Hook::emit('OCP\Share', 'post_shared', array(
+				'itemType' => $itemType,
+				'itemSource' => $itemSource,
+				'itemTarget' => $groupItemTarget,
+				'parent' => $parent,
+				'shareType' => $shareType,
+				'shareWith' => $uid,
+				'uidOwner' => $uidOwner,
+				'permissions' => $permissions,
+				'fileSource' => $fileSource,
+				'fileTarget' => $groupFileTarget,
+				'id' => $parent,
+				'token' => $token
+			));
 			if ($parentFolder === true) {
 				// Return parent folders to preserve file target paths for potential children
 				return $parentFolders;