diff --git a/apps/files_encryption/ajax/adminrecovery.php b/apps/files_encryption/ajax/adminrecovery.php
index cec0cd4ddda7560374e9f955839959b8ed2b0e76..6a056dc7b3dca32edb366d7a233b3445ab94b3d9 100644
--- a/apps/files_encryption/ajax/adminrecovery.php
+++ b/apps/files_encryption/ajax/adminrecovery.php
@@ -1,6 +1,5 @@
-setValue( $app, $key, $value )
-
 <?php
+
 /**
  * Copyright (c) 2013, Sam Tuke <samtuke@owncloud.com>
  * This file is licensed under the Affero General Public License version 3 or later.
@@ -8,69 +7,79 @@ setValue( $app, $key, $value )
  *
  * @brief Script to handle admin settings for encrypted key recovery
  */
-
 use OCA\Encryption;
 
 \OCP\JSON::checkAdminUser();
-\OCP\JSON::checkAppEnabled( 'files_encryption' );
+\OCP\JSON::checkAppEnabled('files_encryption');
 \OCP\JSON::callCheck();
 
-$return = $doSetup = false;
+$return = false;
+
+// Enable recoveryAdmin
 
-if ( 
-	isset( $_POST['adminEnableRecovery'] ) 
-	&& $_POST['adminEnableRecovery'] == 1
-	&& isset( $_POST['recoveryPassword'] ) 
-	&& ! empty ( $_POST['recoveryPassword'] )
+if (
+	isset($_POST['adminEnableRecovery'])
+	&& 1 == $_POST['adminEnableRecovery']
 ) {
 
-	// TODO: Let the admin set this themselves
-	$recoveryAdminUid = 'recoveryAdmin';
-	
-	// If desired recoveryAdmin UID is already in use
-	if ( ! \OC_User::userExists( $recoveryAdminUid ) ) {
-	
-		// Create new recoveryAdmin user
-		\OC_User::createUser( $recoveryAdminUid, $_POST['recoveryPassword'] );
-		
-		$doSetup = true;
-		
-	} else {
-	
-		// Get list of admin users
-		$admins = OC_Group::usersInGroup( 'admin' );
-		
-		// If the existing recoveryAdmin UID is an admin
-		if ( in_array( $recoveryAdminUid, $admins ) ) {
-			
-			// The desired recoveryAdmi UID pre-exists and can be used
-			$doSetup = true;
-		
-		// If the recoveryAdmin UID exists but doesn't have admin rights
-		} else {
-		
-			$return = false;
-			
-		}
-		
+	$view = new \OC\Files\View('/');
+
+	$recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId');
+
+	if ($recoveryKeyId === null) {
+		$recoveryKeyId = 'recovery_' . substr(md5(time()), 0, 8);
+		\OC_Appconfig::setValue('files_encryption', 'recoveryKeyId', $recoveryKeyId);
 	}
-	
-	// If recoveryAdmin has passed other checks
-	if ( $doSetup ) {
-		
-		$view = new \OC_FilesystemView( '/' );
-		$util = new Util( $view, $recoveryAdminUid );
-		
-		// Ensure recoveryAdmin is ready for encryption (has usable keypair etc.)
-		$util->setupServerSide( $_POST['recoveryPassword'] );
-		
-		// Store the UID in the DB
-		OC_Appconfig::setValue( 'files_encryption', 'recoveryAdminUid', $recoveryAdminUid );
-		
-		$return = true;
-		
+
+	if (!$view->is_dir('/owncloud_private_key')) {
+		$view->mkdir('/owncloud_private_key');
+	}
+
+	if (
+		(!$view->file_exists("/public-keys/" . $recoveryKeyId . ".public.key")
+		|| !$view->file_exists("/owncloud_private_key/" . $recoveryKeyId . ".private.key"))
+		&& isset($_POST['recoveryPassword'])
+		&& !empty($_POST['recoveryPassword'])
+	) {
+
+		$keypair = \OCA\Encryption\Crypt::createKeypair();
+
+		\OC_FileProxy::$enabled = false;
+
+		// Save public key
+
+		if (!$view->is_dir('/public-keys')) {
+			$view->mkdir('/public-keys');
+		}
+
+		$view->file_put_contents('/public-keys/' . $recoveryKeyId . '.public.key', $keypair['publicKey']);
+
+		// Encrypt private key empthy passphrase
+		$encryptedPrivateKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], $_POST['recoveryPassword']);
+
+		// Save private key
+		$view->file_put_contents('/owncloud_private_key/' . $recoveryKeyId . '.private.key', $encryptedPrivateKey);
+
+		\OC_FileProxy::$enabled = true;
+
 	}
-	
+
+	// Set recoveryAdmin as enabled
+	OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1);
+
+	$return = true;
+
+// Disable recoveryAdmin
+} elseif (
+	isset($_POST['adminEnableRecovery'])
+	&& 0 == $_POST['adminEnableRecovery']
+) {
+
+	// Set recoveryAdmin as enabled
+	OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 0);
+
+	$return = true;
 }
 
-($return) ? OC_JSON::success() : OC_JSON::error();
\ No newline at end of file
+// Return success or failure
+( $return ) ? \OCP\JSON::success() : \OCP\JSON::error();
\ No newline at end of file
diff --git a/apps/files_encryption/ajax/encryptall.php b/apps/files_encryption/ajax/encryptall.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce613ca44359eaa4a0cb4559cb961851e1fb8510
--- /dev/null
+++ b/apps/files_encryption/ajax/encryptall.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright (c) 2013, Sam Tuke <samtuke@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ *
+ * @brief Script to handle manual trigger of \OCA\Encryption\Util{}->encryptAll()
+ */
+
+use OCA\Encryption;
+
+\OCP\JSON::checkAppEnabled( 'files_encryption' );
+\OCP\JSON::callCheck();
+
+$return = false;
+
+if ( 
+	isset( $_POST['encryptAll'] )
+	&& ! empty( $_POST['userPassword'] )
+) {
+
+	$view = new \OC_FilesystemView( '' );
+	$userId = \OCP\User::getUser();
+	$util = new \OCA\Encryption\Util( $view, $userId );
+	$session = new \OCA\Encryption\Session( $view );
+	$publicKey = \OCA\Encryption\Keymanager::getPublicKey( $view, $userId );
+	$path = '/' . $userId . '/' . 'files';
+	
+	$util->encryptAll( $publicKey, $path, $session->getLegacyKey(), $_POST['userPassword'] );
+	
+	$return = true;
+
+} else {
+
+	$return = false;
+	
+}
+
+// Return success or failure
+( $return ) ? \OCP\JSON::success() : \OCP\JSON::error();
\ No newline at end of file
diff --git a/apps/files_encryption/ajax/userrecovery.php b/apps/files_encryption/ajax/userrecovery.php
index 56c18f7ad5b968cc0be5c3d53e124209728ce84e..85a799011d7d4733f9849e2989dd8c3ec46c4c9a 100644
--- a/apps/files_encryption/ajax/userrecovery.php
+++ b/apps/files_encryption/ajax/userrecovery.php
@@ -1,5 +1,3 @@
-setValue( $app, $key, $value )
-
 <?php
 /**
  * Copyright (c) 2013, Sam Tuke <samtuke@owncloud.com>
@@ -17,26 +15,21 @@ use OCA\Encryption;
 
 if ( 
 	isset( $_POST['userEnableRecovery'] ) 
+	&& ( 0 == $_POST['userEnableRecovery'] || 1 == $_POST['userEnableRecovery'] )
 ) {
 
-	// Ensure preference is an integer
-	$recoveryEnabled = intval( $_POST['userEnableRecovery'] );
-
 	$userId = \OCP\USER::getUser();
 	$view = new \OC_FilesystemView( '/' );
-	$util = new Util( $view, $userId );
+	$util = new \OCA\Encryption\Util( $view, $userId );
 	
 	// Save recovery preference to DB
-	$result = $util->setRecovery( $recoveryEnabled );
-	
-	if ( $result ) {
+	$return = $util->setRecoveryForUser( $_POST['userEnableRecovery'] );
 	
-		\OCP\JSON::success();
-		
-	} else {
-	
-		\OCP\JSON::error();
-		
-	}
+} else {
+
+	$return = false;
 	
-}
\ No newline at end of file
+}
+
+// Return success or failure
+( $return ) ? \OCP\JSON::success() : \OCP\JSON::error();
\ No newline at end of file
diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php
index c2de9d0b441ec01ad9952dff36a768b9f24360cc..b611eb798f30b530a8e2602705b99e39267ec89c 100644
--- a/apps/files_encryption/appinfo/app.php
+++ b/apps/files_encryption/appinfo/app.php
@@ -8,24 +8,25 @@ OC::$CLASSPATH['OCA\Encryption\Stream'] = 'files_encryption/lib/stream.php';
 OC::$CLASSPATH['OCA\Encryption\Proxy'] = 'files_encryption/lib/proxy.php';
 OC::$CLASSPATH['OCA\Encryption\Session'] = 'files_encryption/lib/session.php';
 OC::$CLASSPATH['OCA\Encryption\Capabilities'] = 'files_encryption/lib/capabilities.php';
+OC::$CLASSPATH['OCA\Encryption\Helper'] = 'files_encryption/lib/helper.php';
 
 OC_FileProxy::register( new OCA\Encryption\Proxy() );
 
-// User-related hooks
-OCP\Util::connectHook( 'OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login' );
-OCP\Util::connectHook( 'OC_User', 'pre_setPassword', 'OCA\Encryption\Hooks', 'setPassphrase' );
+// User related hooks
+OCA\Encryption\Helper::registerUserHooks();
 
-// Sharing-related hooks
-OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' );
-OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' );
-OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', 'postUnshareAll' );
+// Sharing related hooks
+OCA\Encryption\Helper::registerShareHooks();
 
-// Webdav-related hooks
-OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfileFromClient' );
+// Webdav related hooks
+OCA\Encryption\Helper::registerWebdavHooks();
+
+// Filesystem related hooks
+OCA\Encryption\Helper::registerFilesystemHooks();
 
 stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' );
 
-$view = new OC_FilesystemView( '/' );
+$view = new \OC\Files\View( '/' );
 
 $session = new OCA\Encryption\Session( $view );
 
@@ -47,5 +48,6 @@ if (
 }
 
 // Register settings scripts
-OCP\App::registerAdmin( 'files_encryption', 'settings' );
+OCP\App::registerAdmin( 'files_encryption', 'settings-admin' );
 OCP\App::registerPersonal( 'files_encryption', 'settings-personal' );
+
diff --git a/apps/files_encryption/appinfo/database.xml b/apps/files_encryption/appinfo/database.xml
index b144b6cb2a4f035e66e60d2b90e919caf1fabd83..64c9ef65fa83f3646029a3c2ae2848db4d596df3 100644
--- a/apps/files_encryption/appinfo/database.xml
+++ b/apps/files_encryption/appinfo/database.xml
@@ -27,6 +27,13 @@
 				<default>0</default>
 				<comments>Whether encryption key recovery is enabled</comments>
 			</field>
+			<field>
+				<name>migrationStatus</name>
+				<type>boolean</type>
+				<notnull>true</notnull>
+				<default>0</default>
+				<comments>Whether encryption migration has been performed</comments>
+			</field>
 		</declaration>
 	</table>
 </database>
\ No newline at end of file
diff --git a/apps/files_encryption/css/settings-personal.css b/apps/files_encryption/css/settings-personal.css
new file mode 100644
index 0000000000000000000000000000000000000000..4ee0acc9768ce52dc9262764086ecc2f66400b1d
--- /dev/null
+++ b/apps/files_encryption/css/settings-personal.css
@@ -0,0 +1,10 @@
+/* Copyright (c) 2013, Sam Tuke, <samtuke@owncloud.com>
+ This file is licensed under the Affero General Public License version 3 or later.
+ See the COPYING-README file. */
+
+#encryptAllError
+, #encryptAllSuccess
+, #recoveryEnabledError
+, #recoveryEnabledSuccess {
+	display: none;
+}
\ No newline at end of file
diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php
index 2ac74ad6c44c5b9187a129bd1027109e4603a55b..31175d1c346739cd65f7fb5b368699a066c96af5 100644
--- a/apps/files_encryption/hooks/hooks.php
+++ b/apps/files_encryption/hooks/hooks.php
@@ -23,10 +23,11 @@
 
 namespace OCA\Encryption;
 
+use OC\Files\Filesystem;
+
 /**
  * Class for hook specific logic
  */
-
 class Hooks {
 
 	// TODO: use passphrase for encrypting private key that is separate to 
@@ -46,15 +47,11 @@ class Hooks {
 		$view = new \OC_FilesystemView( '/' );
 
 		$util = new Util( $view, $params['uid'] );
-		
-		// Check files_encryption infrastructure is ready for action
-		if ( ! $util->ready() ) {
-			
-			\OC_Log::write( 'Encryption library', 'User account "' . $params['uid'] . '" is not ready for encryption; configuration started', \OC_Log::DEBUG );
-			
-			return $util->setupServerSide( $params['password'] );
 
-		}
+        // setup user, if user not ready force relogin
+		if(Helper::setupUser($util, $params['password']) === false) {
+            return false;
+        }
 	
 		\OC_FileProxy::$enabled = false;
 		
@@ -67,49 +64,89 @@ class Hooks {
 		$session = new Session( $view );
 		
 		$session->setPrivateKey( $privateKey, $params['uid'] );
-
-        //FIXME: disabled because it gets called each time a user do an operation on iPhone
-        //FIXME: we need a better place doing this and maybe only one time or by user
-		/*$view1 = new \OC_FilesystemView( '/' . $params['uid'] );
 		
-		// Set legacy encryption key if it exists, to support 
-		// depreciated encryption system
-		if ( 
-			$view1->file_exists( 'encryption.key' )
-			&& $encLegacyKey = $view1->file_get_contents( 'encryption.key' ) 
-		) {
+		// Check if first-run file migration has already been performed
+		$migrationCompleted = $util->getMigrationStatus();
 		
-			$plainLegacyKey = Crypt::legacyDecrypt( $encLegacyKey, $params['password'] );
-			
-			$session->setLegacyKey( $plainLegacyKey );
+		// If migration not yet done
+		if ( ! $migrationCompleted ) {
 		
-		}
-		
-		\OC_FileProxy::$enabled = false;
-		
-		$publicKey = Keymanager::getPublicKey( $view, $params['uid'] );
-		
-		\OC_FileProxy::$enabled = false;*/
-		
-		// Encrypt existing user files:
-		// This serves to upgrade old versions of the encryption
-		// app (see appinfo/spec.txt)
-		/*if (
-			$util->encryptAll( $publicKey,  '/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'] )
-		) {
+			$view1 = new \OC_FilesystemView( '/' . $params['uid'] );
+			
+			// Set legacy encryption key if it exists, to support 
+			// depreciated encryption system
+			if ( 
+				$view1->file_exists( 'encryption.key' )
+				&& $encLegacyKey = $view1->file_get_contents( 'encryption.key' ) 
+			) {
+			
+				$plainLegacyKey = Crypt::legacyDecrypt( $encLegacyKey, $params['password'] );
+				
+				$session->setLegacyKey( $plainLegacyKey );
 			
-			\OC_Log::write( 
-				'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" started at login'
-				, \OC_Log::INFO 
-			);
+			}
+			
+			\OC_FileProxy::$enabled = false;
+			
+			$publicKey = Keymanager::getPublicKey( $view, $params['uid'] );
+			
+			\OC_FileProxy::$enabled = false;
+			
+			// Encrypt existing user files:
+			// This serves to upgrade old versions of the encryption
+			// app (see appinfo/spec.txt)
+			if (
+				$util->encryptAll( $publicKey,  '/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'] )
+			) {
+				
+				\OC_Log::write( 
+					'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'
+					, \OC_Log::INFO 
+				);
+			
+			}
+			
+			// Register successful migration in DB
+			$util->setMigrationStatus( 1 );
 		
-		}*/
+		}
 
 		return true;
 
 	}
-	
-	/**
+
+    /**
+     * @brief setup encryption backend upon user created
+     * @note This method should never be called for users using client side encryption
+     */
+    public static function postCreateUser( $params ) {
+        $view = new \OC_FilesystemView( '/' );
+
+        $util = new Util( $view, $params['uid'] );
+
+        Helper::setupUser($util, $params['password']);
+    }
+
+    /**
+     * @brief cleanup encryption backend upon user deleted
+     * @note This method should never be called for users using client side encryption
+     */
+    public static function postDeleteUser( $params ) {
+        $view = new \OC_FilesystemView( '/' );
+
+        // cleanup public key
+        $publicKey = '/public-keys/' . $params['uid'] . '.public.key';
+
+        // Disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        $view->unlink($publicKey);
+
+        \OC_FileProxy::$enabled = $proxyStatus;
+    }
+
+    /**
 	 * @brief Change a user's encryption passphrase
 	 * @param array $params keys: uid, password
 	 */
@@ -119,8 +156,10 @@ class Hooks {
 		// is in use (client-side encryption does not have access to 
 		// the necessary keys)
 		if ( Crypt::mode() == 'server' ) {
-			
-			$session = new Session();
+
+            $view = new \OC_FilesystemView( '/' );
+
+			$session = new Session($view);
 			
 			// Get existing decrypted private key
 			$privateKey = $session->getPrivateKey();
@@ -165,7 +204,36 @@ class Hooks {
 		}
 		
 	}
-	
+
+	/*
+	 * @brief check if files can be encrypted to every user.
+	 */
+	public static function preShared($params) {
+
+		$users = array();
+		$view = new \OC\Files\View('/public-keys/');
+
+		switch ($params['shareType']) {
+			case \OCP\Share::SHARE_TYPE_USER:
+				$users[] = $params['shareWith'];
+				break;
+			case \OCP\Share::SHARE_TYPE_GROUP:
+				$users = \OC_Group::usersInGroup($params['shareWith']);
+				break;
+		}
+
+		foreach ($users as $user) {
+			if (!$view->file_exists($user . '.public.key')) {
+				// Set flag var 'run' to notify emitting
+				// script that hook execution failed
+				$params['run']->run = false;
+				// TODO: Make sure files_sharing provides user
+				// feedback on failed share
+				break;
+			}
+		}
+	}
+
 	/**
 	 * @brief 
 	 */
@@ -187,7 +255,9 @@ class Hooks {
 		// [fileTarget] => /test8
 		// [id] => 10
 		// [token] =>
+		// [run] => whether emitting script should continue to run
 		// TODO: Should other kinds of item be encrypted too?
+
 		if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
 
 			$view = new \OC_FilesystemView('/');
@@ -196,13 +266,55 @@ class Hooks {
 			$util = new Util($view, $userId);
 			$path = $util->fileIdToPath($params['itemSource']);
 
-			//check if this is a reshare action, that's true if the item source is already shared with me
-			$sharedItem = \OCP\Share::getItemSharedWithBySource($params['itemType'], $params['itemSource']);
-			if ($sharedItem) {
-				// if it is a re-share than the file is located in my Shared folder
-				$path = '/Shared'.$sharedItem['file_target'];
-			} else {
-				$path = $util->fileIdToPath($params['itemSource']);
+			//if parent is set, then this is a re-share action
+			if ($params['parent']) {
+
+				// get the parent from current share
+				$parent = $util->getShareParent($params['parent']);
+
+				// if parent is file the it is an 1:1 share
+				if ($parent['item_type'] === 'file') {
+
+					// prefix path with Shared
+					$path = '/Shared' . $parent['file_target'];
+				} else {
+
+					// NOTE: parent is folder but shared was a file!
+					// we try to rebuild the missing path
+					// some examples we face here
+					// user1 share folder1 with user2 folder1 has 
+					// the following structure 
+					// /folder1/subfolder1/subsubfolder1/somefile.txt
+					// user2 re-share subfolder2 with user3
+					// user3 re-share somefile.txt user4
+					// so our path should be 
+					// /Shared/subfolder1/subsubfolder1/somefile.txt 
+					// while user3 is sharing
+
+					if ($params['itemType'] === 'file') {
+						// get target path
+						$targetPath = $util->fileIdToPath($params['fileSource']);
+						$targetPathSplit = array_reverse(explode('/', $targetPath));
+
+						// init values
+						$path = '';
+						$sharedPart = ltrim($parent['file_target'], '/');
+
+						// rebuild path
+						foreach ($targetPathSplit as $pathPart) {
+							if ($pathPart !== $sharedPart) {
+								$path = '/' . $pathPart . $path;
+							} else {
+								break;
+							}
+						}
+						// prefix path with Shared
+						$path = '/Shared' . $parent['file_target'] . $path;
+					} else {
+						// prefix path with Shared
+						$path = '/Shared' . $parent['file_target'] . $params['fileTarget'];
+					}
+				}
 			}
 
 			$sharingEnabled = \OCP\Share::isEnabled();
@@ -216,23 +328,7 @@ class Hooks {
 
 			foreach ($allFiles as $path) {
 				$usersSharing = $util->getSharingUsersArray($sharingEnabled, $path);
-
-				$failed = array();
-
-				// Attempt to set shareKey
-				if (!$util->setSharedFileKeyfiles($session, $usersSharing, $path)) {
-
-					$failed[] = $path;
-				}
-			}
-
-			// If no attempts to set keyfiles failed
-			if (empty($failed)) {
-
-				return true;
-			} else {
-
-				return false;
+				$util->setSharedFileKeyfiles( $session, $usersSharing, $path );
 			}
 		}
 	}
@@ -241,51 +337,89 @@ class Hooks {
 	 * @brief 
 	 */
 	public static function postUnshare( $params ) {
-		
+
 		// NOTE: $params has keys:
 		// [itemType] => file
 		// [itemSource] => 13
 		// [shareType] => 0
 		// [shareWith] => test1
-	
-		if ( $params['itemType'] === 'file' ||  $params['itemType'] === 'folder' ) {
-		
+		// [itemParent] =>
+
+		if ( $params['itemType'] === 'file' || $params['itemType'] === 'folder' ) {
+
 			$view = new \OC_FilesystemView( '/' );
-			$session = new Session($view);
 			$userId = \OCP\User::getUser();
-			$util = new Util( $view, $userId );
+			$util = new Util( $view, $userId);
 			$path = $util->fileIdToPath( $params['itemSource'] );
 
+			// check if this is a re-share
+			if ( $params['itemParent'] ) {
+
+				// get the parent from current share
+				$parent = $util->getShareParent( $params['itemParent'] );
+
+				// get target path
+				$targetPath = $util->fileIdToPath( $params['itemSource'] );
+				$targetPathSplit = array_reverse( explode( '/', $targetPath ) );
+
+				// init values
+				$path = '';
+				$sharedPart = ltrim( $parent['file_target'], '/' );
+
+				// rebuild path
+				foreach ( $targetPathSplit as $pathPart ) {
+				
+					if ( $pathPart !== $sharedPart ) {
+					
+						$path = '/' . $pathPart . $path;
+						
+					} else {
+					
+						break;
+						
+					}
+					
+				}
+
+				// prefix path with Shared
+				$path = '/Shared' . $parent['file_target'] . $path;
+			}
+
 			// for group shares get a list of the group members
-			if ($params['shareType'] == \OCP\Share::SHARE_TYPE_GROUP) {
+			if ( $params['shareType'] == \OCP\Share::SHARE_TYPE_GROUP ) {
 				$userIds = \OC_Group::usersInGroup($params['shareWith']);
+			} else if ( $params['shareType'] == \OCP\Share::SHARE_TYPE_LINK ){
+				$userIds = array( $util->getPublicShareKeyId() );
 			} else {
-				$userIds = array($params['shareWith']);
+				$userIds = array( $params['shareWith'] );
 			}
 
 			// if we unshare a folder we need a list of all (sub-)files
-			if ($params['itemType'] === 'folder') {
-				$allFiles = $util->getAllFiles($path);
+			if ( $params['itemType'] === 'folder' ) {
+			
+				$allFiles = $util->getAllFiles( $path );
+				
 			} else {
-				$allFiles = array($path);
+			
+				$allFiles = array( $path );
 			}
 
-			
 			foreach ( $allFiles as $path ) {
 
 				// check if the user still has access to the file, otherwise delete share key
-				$sharingUsers = $util->getSharingUsersArray(true, $path);
+				$sharingUsers = $util->getSharingUsersArray( true, $path );
 
 				// Unshare every user who no longer has access to the file
-				$delUsers = array_diff($userIds, $sharingUsers);
-				if ( ! Keymanager::delShareKey( $view, $delUsers, $path ) ) {
+				$delUsers = array_diff( $userIds, $sharingUsers);
+				
+				if ( !Keymanager::delShareKey( $view, $delUsers, $path ) ) {
 				
 					$failed[] = $path;
-					
-				}
 				
+				}
+
 			}
-			
+
 			// If no attempts to set keyfiles failed
 			if ( empty( $failed ) ) {
 			
@@ -296,19 +430,99 @@ class Hooks {
 				return false;
 				
 			}
-
 		}
-
 	}
 	
 	/**
 	 * @brief 
 	 */
 	public static function postUnshareAll( $params ) {
-	
+
 		// NOTE: It appears that this is never called for files, so 
 		// we may not need to implement it
 		
 	}
-	
+
+
+    /**
+     * @brief after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing
+     * @param array with oldpath and newpath
+     *
+     * This function is connected to the rename signal of OC_Filesystem and adjust the name and location
+     * of the stored versions along the actual file
+     */
+    public static function postRename($params) {
+        // Disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        $view = new \OC_FilesystemView('/');
+        $session = new Session($view);
+        $userId = \OCP\User::getUser();
+        $util = new Util( $view, $userId );
+
+        // Format paths to be relative to user files dir
+        $oldKeyfilePath = \OC\Files\Filesystem::normalizePath($userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['oldpath']);
+        $newKeyfilePath = \OC\Files\Filesystem::normalizePath($userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['newpath']);
+
+        // add key ext if this is not an folder
+        if (!$view->is_dir($oldKeyfilePath)) {
+            $oldKeyfilePath .= '.key';
+            $newKeyfilePath .= '.key';
+
+            // handle share-keys
+            $localKeyPath = $view->getLocalFile($userId.'/files_encryption/share-keys/'.$params['oldpath']);
+            $matches = glob(preg_quote($localKeyPath).'*.shareKey');
+            foreach ($matches as $src) {
+                $dst = \OC\Files\Filesystem::normalizePath(str_replace($params['oldpath'], $params['newpath'], $src));
+
+                // create destination folder if not exists
+                if(!file_exists(dirname($dst))) {
+                    mkdir(dirname($dst), 0750, true);
+                }
+
+                rename($src, $dst);
+            }
+
+        } else {
+            // handle share-keys folders
+            $oldShareKeyfilePath = \OC\Files\Filesystem::normalizePath($userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['oldpath']);
+            $newShareKeyfilePath = \OC\Files\Filesystem::normalizePath($userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['newpath']);
+
+            // create destination folder if not exists
+            if(!$view->file_exists(dirname($newShareKeyfilePath))) {
+                $view->mkdir(dirname($newShareKeyfilePath), 0750, true);
+            }
+
+            $view->rename($oldShareKeyfilePath, $newShareKeyfilePath);
+        }
+
+        // Rename keyfile so it isn't orphaned
+        if($view->file_exists($oldKeyfilePath)) {
+
+            // create destination folder if not exists
+            if(!$view->file_exists(dirname($newKeyfilePath))) {
+                $view->mkdir(dirname($newKeyfilePath), 0750, true);
+            }
+
+            $view->rename($oldKeyfilePath, $newKeyfilePath);
+        }
+
+        // build the path to the file
+        $newPath = '/' . $userId . '/files' .$params['newpath'];
+        $newPathRelative = $params['newpath'];
+
+        if($util->fixFileSize($newPath)) {
+            // get sharing app state
+            $sharingEnabled = \OCP\Share::isEnabled();
+
+            // get users
+            $usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative);
+
+            // update sharing-keys
+            $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative);
+        }
+
+        \OC_FileProxy::$enabled = $proxyStatus;
+    }
 }
diff --git a/apps/files_encryption/js/settings-admin.js b/apps/files_encryption/js/settings-admin.js
new file mode 100644
index 0000000000000000000000000000000000000000..9cdb7aca68a2fc52e0e3480aa58d40c39cd3cafa
--- /dev/null
+++ b/apps/files_encryption/js/settings-admin.js
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2013, Sam Tuke <samtuke@owncloud.com>, Robin Appelman 
+ * <icewind1991@gmail.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+
+$(document).ready(function(){
+	// Trigger ajax on recoveryAdmin status change
+	$( 'input:radio[name="adminEnableRecovery"]' ).change( 
+		function() {
+			
+			var recoveryStatus = $( this ).val();
+			var recoveryPassword = $( '#recoveryPassword' ).val();
+			
+			if ( '' == recoveryPassword ) {
+				
+				// FIXME: add proper OC notification
+				alert( 'You must set a recovery account password first' );
+				
+			} else {
+			
+				$.post( 
+					OC.filePath( 'files_encryption', 'ajax', 'adminrecovery.php' )
+					, { adminEnableRecovery: recoveryStatus, recoveryPassword: recoveryPassword }
+					,  function( data ) {
+						alert( data );
+					}
+				);
+			
+			}
+		}
+	);
+	
+	function blackListChange(){
+		var blackList=$( '#encryption_blacklist' ).val().join( ',' );
+		OC.AppConfig.setValue( 'files_encryption', 'type_blacklist', blackList );
+	}
+})
\ No newline at end of file
diff --git a/apps/files_encryption/js/settings-personal.js b/apps/files_encryption/js/settings-personal.js
new file mode 100644
index 0000000000000000000000000000000000000000..3b9b00dc797046a00a42728412cee83623719064
--- /dev/null
+++ b/apps/files_encryption/js/settings-personal.js
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2013, Sam Tuke <samtuke@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+$(document).ready(function(){
+	// Trigger ajax on recoveryAdmin status change
+	$( 'input:radio[name="userEnableRecovery"]' ).change( 
+		function() {
+			
+			// Hide feedback messages in case they're already visible
+			$('#recoveryEnabledSuccess').hide();
+			$('#recoveryEnabledError').hide();
+			
+			var recoveryStatus = $( this ).val();
+			
+			$.post( 
+				OC.filePath( 'files_encryption', 'ajax', 'userrecovery.php' )
+				, { userEnableRecovery: recoveryStatus }
+				,  function( data ) {
+					if ( data.status == "success" ) {
+						$('#recoveryEnabledSuccess').show();
+					} else {
+						$('#recoveryEnabledError').show();
+					}
+				}
+			);
+			// Ensure page is not reloaded on form submit
+			return false;
+		}
+	);
+	
+	$("#encryptAll").click( 
+		function(){
+			
+			// Hide feedback messages in case they're already visible
+			$('#encryptAllSuccess').hide();
+			$('#encryptAllError').hide();
+			
+			var userPassword = $( '#userPassword' ).val();
+			var encryptAll = $( '#encryptAll' ).val();
+
+			$.post( 
+				OC.filePath( 'files_encryption', 'ajax', 'encryptall.php' )
+				, { encryptAll: encryptAll, userPassword: userPassword }
+				,  function( data ) {
+					if ( data.status == "success" ) {
+						$('#encryptAllSuccess').show();
+					} else {
+						$('#encryptAllError').show();
+					}
+				}
+			);
+			// Ensure page is not reloaded on form submit
+			return false;
+		}
+		
+	);
+})
\ No newline at end of file
diff --git a/apps/files_encryption/js/settings.js b/apps/files_encryption/js/settings.js
deleted file mode 100644
index 9a0bebf2478a8c80980455404aa33fb410b6d375..0000000000000000000000000000000000000000
--- a/apps/files_encryption/js/settings.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
- * This file is licensed under the Affero General Public License version 3 or later.
- * See the COPYING-README file.
- */
-
-
-$(document).ready(function(){
-	// Trigger ajax on filetype blacklist change
-	$('#encryption_blacklist').multiSelect({
-		oncheck:blackListChange,
-		onuncheck:blackListChange,
-		createText:'...'
-	});
-	
-	// Trigger ajax on recoveryAdmin status change
-	$( 'input:radio[name="adminEnableRecovery"]' ).change( 
-		function() {
-			
-			var foo = $( this ).val();
-			
-			$.post( 
-				OC.filePath('files_encryption', 'ajax', 'adminrecovery.php')
-				, { adminEnableRecovery: foo, recoveryPassword: 'password' }
-				,  function( data ) {
-					alert( data );
-				}
-			);
-		}
-	);
-	
-	function blackListChange(){
-		var blackList=$('#encryption_blacklist').val().join(',');
-		OC.AppConfig.setValue('files_encryption','type_blacklist',blackList);
-	}
-})
\ No newline at end of file
diff --git a/apps/files_encryption/l10n/de.php b/apps/files_encryption/l10n/de.php
index bcf0ca5ad63917d3a73fee9de9bc7e927d4fa8fe..cdcd8a40b23c87ae5c13660fd17539a8885b399e 100644
--- a/apps/files_encryption/l10n/de.php
+++ b/apps/files_encryption/l10n/de.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "Dateiverschlüsselung ist aktiviert",
 "The following file types will not be encrypted:" => "Die folgenden Dateitypen werden nicht verschlüsselt:",
 "Exclude the following file types from encryption:" => "Schließe die folgenden Dateitypen von der Verschlüsselung aus:",
-"None" => "Nichts"
+"None" => "Keine"
 );
diff --git a/apps/files_encryption/l10n/de_DE.php b/apps/files_encryption/l10n/de_DE.php
index 71fd7d96711d06e12a79c4273ca08f394761a594..4f08b98eb29fdb50d0866b4b8ead9a1e9a468e38 100644
--- a/apps/files_encryption/l10n/de_DE.php
+++ b/apps/files_encryption/l10n/de_DE.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "Datei-Verschlüsselung ist aktiviert",
 "The following file types will not be encrypted:" => "Die folgenden Dateitypen werden nicht verschlüsselt:",
 "Exclude the following file types from encryption:" => "Die folgenden Dateitypen von der Verschlüsselung ausnehmen:",
-"None" => "Nichts"
+"None" => "Keine"
 );
diff --git a/apps/files_encryption/l10n/el.php b/apps/files_encryption/l10n/el.php
index 82a4c92ec2856e27a7aff4f9b1c1db7cbdb7f8cb..0031a7319445a45b376950d0e4f1f38d379a3dc4 100644
--- a/apps/files_encryption/l10n/el.php
+++ b/apps/files_encryption/l10n/el.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "Η κρυπτογράφηση αρχείων είναι ενεργή.",
 "The following file types will not be encrypted:" => "Οι παρακάτω τύποι αρχείων δεν θα κρυπτογραφηθούν:",
 "Exclude the following file types from encryption:" => "Εξαίρεση των παρακάτω τύπων αρχείων από την κρυπτογράφηση:",
-"None" => "Τίποτα"
+"None" => "Καμία"
 );
diff --git a/apps/files_encryption/l10n/eu.php b/apps/files_encryption/l10n/eu.php
index 7e3b7611ff2e49f85bbdf0501623bdc70acf750a..5a22b65728ef5d9d669b57dcd72559cda9830c60 100644
--- a/apps/files_encryption/l10n/eu.php
+++ b/apps/files_encryption/l10n/eu.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "Fitxategien enkriptazioa gaituta dago.",
 "The following file types will not be encrypted:" => "Hurrengo fitxategi motak ez dira enkriptatuko:",
 "Exclude the following file types from encryption:" => "Baztertu hurrengo fitxategi motak enkriptatzetik:",
-"None" => "Ezer"
+"None" => "Bat ere ez"
 );
diff --git a/apps/files_encryption/l10n/it.php b/apps/files_encryption/l10n/it.php
index c71713452695ab9048e9c8e608c243a6d81cee04..9ab9bc492a0fb599349802711ac6ada4df5a7237 100644
--- a/apps/files_encryption/l10n/it.php
+++ b/apps/files_encryption/l10n/it.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "La cifratura dei file è abilitata.",
 "The following file types will not be encrypted:" => "I seguenti tipi di file non saranno cifrati:",
 "Exclude the following file types from encryption:" => "Escludi i seguenti tipi di file dalla cifratura:",
-"None" => "Nessuno"
+"None" => "Nessuna"
 );
diff --git a/apps/files_encryption/l10n/pl.php b/apps/files_encryption/l10n/pl.php
index 836f545359633a970a4dce81b8979f5eb53908ac..2fa86f454f9bfbc1bbf6a361e3c44bc9b9f68739 100644
--- a/apps/files_encryption/l10n/pl.php
+++ b/apps/files_encryption/l10n/pl.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "Szyfrowanie plików jest włączone",
 "The following file types will not be encrypted:" => "Poniższe typy plików nie będą szyfrowane:",
 "Exclude the following file types from encryption:" => "Wyłącz poniższe typy plików z szyfrowania:",
-"None" => "Nic"
+"None" => "Brak"
 );
diff --git a/apps/files_encryption/l10n/pt_BR.php b/apps/files_encryption/l10n/pt_BR.php
index b41c6ed3153ae4afab3b292ff4bcbe3992367d75..28807db72ce820c067840756b9e19ef6a3cf6d2a 100644
--- a/apps/files_encryption/l10n/pt_BR.php
+++ b/apps/files_encryption/l10n/pt_BR.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "A criptografia de arquivos está ativada.",
 "The following file types will not be encrypted:" => "Os seguintes tipos de arquivo não serão criptografados:",
 "Exclude the following file types from encryption:" => "Excluir os seguintes tipos de arquivo da criptografia:",
-"None" => "Nada"
+"None" => "Nenhuma"
 );
diff --git a/apps/files_encryption/l10n/ru.php b/apps/files_encryption/l10n/ru.php
index f07dec621d78e75d93f11fd30df7ac4aed1f1327..22c1e3da3747c957863a007ce8bc54708eebe2cf 100644
--- a/apps/files_encryption/l10n/ru.php
+++ b/apps/files_encryption/l10n/ru.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "Шифрование файла включено.",
 "The following file types will not be encrypted:" => "Следующие типы файлов не будут зашифрованы:",
 "Exclude the following file types from encryption:" => "Исключить следующие типы файлов из шифрованных:",
-"None" => "Нет новостей"
+"None" => "Ничего"
 );
diff --git a/apps/files_encryption/l10n/sk_SK.php b/apps/files_encryption/l10n/sk_SK.php
index aaea9da21b4c87dad882049dbd3748efa4b6b2c1..bebb6234710dc2146021ca6a95dcc86a77a658cd 100644
--- a/apps/files_encryption/l10n/sk_SK.php
+++ b/apps/files_encryption/l10n/sk_SK.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "Šifrovanie súborov nastavené.",
 "The following file types will not be encrypted:" => "Uvedené typy súborov nebudú šifrované:",
 "Exclude the following file types from encryption:" => "Nešifrovať uvedené typy súborov",
-"None" => "Žiadny"
+"None" => "Žiadne"
 );
diff --git a/apps/files_encryption/l10n/th_TH.php b/apps/files_encryption/l10n/th_TH.php
index 30c0324a9884b8f194f076d996e69b27436d4114..e46d249118606f7f97352d974cd6054385262726 100644
--- a/apps/files_encryption/l10n/th_TH.php
+++ b/apps/files_encryption/l10n/th_TH.php
@@ -1,4 +1,4 @@
 <?php $TRANSLATIONS = array(
 "Encryption" => "การเข้ารหัส",
-"None" => "ไม่มี"
+"None" => "ไม่ต้อง"
 );
diff --git a/apps/files_encryption/l10n/vi.php b/apps/files_encryption/l10n/vi.php
index 40d4b1d0fec3757d7854462c60757d3a361d8635..0a88d1b2db60b09f23e67d9ed317e9e4aa771cc7 100644
--- a/apps/files_encryption/l10n/vi.php
+++ b/apps/files_encryption/l10n/vi.php
@@ -3,5 +3,5 @@
 "File encryption is enabled." => "Mã hóa file đã mở",
 "The following file types will not be encrypted:" => "Loại file sau sẽ không được mã hóa",
 "Exclude the following file types from encryption:" => "Việc mã hóa không bao gồm loại file sau",
-"None" => "Không gì cả"
+"None" => "Không có gì hết"
 );
diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php
new file mode 100755
index 0000000000000000000000000000000000000000..783cebeee5b9a85e424e20f2bd2bf9e1fa1df88f
--- /dev/null
+++ b/apps/files_encryption/lib/helper.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @author Florin Peter
+ * @copyright 2013 Florin Peter <owncloud@florin-peter.de>
+ *
+ * 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 OCA\Encryption;
+
+/**
+ * @brief Class to manage registration of hooks an various helper methods
+ */
+class Helper {
+		
+	/**
+	 * @brief register share related hooks
+	 * 
+	 */
+	public static function registerShareHooks() {
+
+        \OCP\Util::connectHook( 'OCP\Share', 'pre_shared', 'OCA\Encryption\Hooks', 'preShared' );
+		\OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' );
+        \OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' );
+        \OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', 'postUnshareAll' );
+	}
+
+    /**
+     * @brief register user related hooks
+     *
+     */
+    public static function registerUserHooks() {
+
+        \OCP\Util::connectHook( 'OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login' );
+        \OCP\Util::connectHook( 'OC_User', 'pre_setPassword', 'OCA\Encryption\Hooks', 'setPassphrase' );
+        \OCP\Util::connectHook( 'OC_User', 'post_createUser', 'OCA\Encryption\Hooks', 'postCreateUser' );
+        \OCP\Util::connectHook( 'OC_User', 'post_deleteUser', 'OCA\Encryption\Hooks', 'postDeleteUser' );
+    }
+
+    /**
+     * @brief register webdav related hooks
+     *
+     */
+    public static function registerWebdavHooks() {
+
+        \OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfileFromClient' );
+    }
+
+    /**
+     * @brief register filesystem related hooks
+     *
+     */
+    public static function registerFilesystemHooks() {
+
+        \OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename');
+    }
+
+    /**
+     * @brief setup user for files_encryption
+     *
+     * @param Util $util
+     * @param string $password
+     * @return bool
+     */
+    public static function setupUser($util, $password) {
+        // Check files_encryption infrastructure is ready for action
+        if ( ! $util->ready() ) {
+
+            \OC_Log::write( 'Encryption library', 'User account "' . $util->getUserId() . '" is not ready for encryption; configuration started', \OC_Log::DEBUG );
+
+            if(!$util->setupServerSide( $password )) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php
index cfc13ee132d65cdf7ab9bcd479542f13d03e10cc..74462a0d1ed479279126bf657b4ef7ab129740ea 100755
--- a/apps/files_encryption/lib/keymanager.php
+++ b/apps/files_encryption/lib/keymanager.php
@@ -32,15 +32,20 @@ class Keymanager {
 	/**
 	 * @brief retrieve the ENCRYPTED private key from a user
 	 * 
-	 * @return string private key or false
+	 * @return string private key or false (hopefully)
 	 * @note the key returned by this method must be decrypted before use
 	 */
 	public static function getPrivateKey( \OC_FilesystemView $view, $user ) {
 	
 		$path =  '/' . $user . '/' . 'files_encryption' . '/' . $user.'.private.key';
-		
+
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
 		$key = $view->file_get_contents( $path );
-		
+
+        \OC_FileProxy::$enabled = $proxyStatus;
+        
 		return $key;
 	}
 
@@ -113,8 +118,8 @@ class Keymanager {
 		\OC_FileProxy::$enabled = false;
 
 		//here we need the currently logged in user, while userId can be a different user
-		$util = new Util($view, \OCP\User::getUser());
-		list($owner, $filename) = $util->getUidAndFilename($path);
+		$util = new Util( $view, \OCP\User::getUser() );
+		list( $owner, $filename ) = $util->getUidAndFilename( $path );
 
 		$basePath = '/' . $owner . '/files_encryption/keyfiles';
 		
@@ -123,22 +128,74 @@ class Keymanager {
 		if ( !$view->is_dir( $basePath . '/' . $targetPath ) ) {
 
 			// create all parent folders
-			$info=pathinfo($basePath . '/' . $targetPath);
-			$keyfileFolderName=$view->getLocalFolder($info['dirname']);
-			if(!file_exists($keyfileFolderName)) {
-				mkdir($keyfileFolderName, 0750, true);
+			$info = pathinfo( $basePath . '/' . $targetPath );
+			$keyfileFolderName = $view->getLocalFolder( $info['dirname'] );
+			
+			if ( ! file_exists( $keyfileFolderName ) ) {
+				
+				mkdir( $keyfileFolderName, 0750, true );
+			
 			}
 		}
+
+		// try reusing key file if part file
+		if ( self::isPartialFilePath( $targetPath ) ) {
 		
-		$result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile );
+			$result = $view->file_put_contents( $basePath . '/' . self::fixPartialFilePath( $targetPath ) . '.key', $catfile );
+			
+		} else {
 		
+			$result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile );
+			
+		}
 		
 		\OC_FileProxy::$enabled = $proxyStatus;
 		
 		return $result;
 		
 	}
+
+	/**
+	 * @brief Remove .path extension from a file path
+	 * @param string $path Path that may identify a .part file
+	 * @return string File path without .part extension
+	 * @note this is needed for reusing keys
+	 */
+	public static function fixPartialFilePath( $path ) {
 	
+		if (preg_match('/\.part$/', $path)) {
+
+			$newLength = strlen($path) - 5;
+			$fPath = substr($path, 0, $newLength);
+
+			return $fPath;
+			
+		} else {
+
+			return $path;
+
+		}
+
+	}
+
+	/**
+	 * @brief Check if a path is a .part file
+	 * @param string $path Path that may identify a .part file
+	 * @return bool
+	 */
+	public static function isPartialFilePath( $path ) {
+		
+		if ( preg_match('/\.part$/', $path ) ) {
+		
+			return true;
+		
+		} else {
+			
+			return false;
+		
+		}
+
+	}
 	/**
 	 * @brief retrieve keyfile for an encrypted file
 	 * @param \OC_FilesystemView $view
@@ -150,14 +207,27 @@ class Keymanager {
 	 * of the keyfile must be performed by client code
 	 */
 	public static function getFileKey( \OC_FilesystemView $view, $userId, $filePath ) {
+
+		// try reusing key file if part file
+		if ( self::isPartialFilePath( $filePath ) ) {
+		
+			$result = self::getFileKey( $view, $userId, self::fixPartialFilePath( $filePath ) );
 		
+			if ( $result ) {
+			
+				return $result;
+				
+			}
+	
+		}
+
 		$util = new Util($view, \OCP\User::getUser());
 		list($owner, $filename) = $util->getUidAndFilename($filePath);
 		$filePath_f = ltrim( $filename, '/' );
-		
+
 		$keyfilePath = '/' . $owner . '/files_encryption/keyfiles/' . $filePath_f . '.key';
 
-        $proxyStatus = \OC_FileProxy::$enabled;
+		$proxyStatus = \OC_FileProxy::$enabled;
 		\OC_FileProxy::$enabled = false;
 		
 		if ( $view->file_exists( $keyfilePath ) ) {
@@ -226,7 +296,7 @@ class Keymanager {
 		
 		$view = new \OC_FilesystemView( '/' . $user . '/files_encryption' );
 
-        $proxyStatus = \OC_FileProxy::$enabled;
+		$proxyStatus = \OC_FileProxy::$enabled;
 		\OC_FileProxy::$enabled = false;
 		
 		if ( !$view->file_exists( '' ) ) $view->mkdir( '' );
@@ -235,7 +305,8 @@ class Keymanager {
 		
 		\OC_FileProxy::$enabled = $proxyStatus;
 
-        return $result;
+		return $result;
+		
 	}
 	
 	/**
@@ -261,7 +332,7 @@ class Keymanager {
 		
 		$view = new \OC_FilesystemView( '/public-keys' );
 
-        $proxyStatus = \OC_FileProxy::$enabled;
+		$proxyStatus = \OC_FileProxy::$enabled;
 		\OC_FileProxy::$enabled = false;
 		
 		if ( !$view->file_exists( '' ) ) $view->mkdir( '' );
@@ -270,7 +341,7 @@ class Keymanager {
 		
 		\OC_FileProxy::$enabled = $proxyStatus;
 
-        return $result;
+		return $result;
 		
 	}
 	
@@ -287,23 +358,32 @@ class Keymanager {
 	 */
 	public static function setShareKey( \OC_FilesystemView $view, $path, $userId, $shareKey ) {
 
-		//here we need the currently logged in user, while userId can be a different user
+		// Here we need the currently logged in user, while userId can be a different user
 		$util = new Util( $view, \OCP\User::getUser() );
 
-		list($owner, $filename) = $util->getUidAndFilename($path);
+		list( $owner, $filename ) = $util->getUidAndFilename( $path );
 
 		$basePath = '/' . $owner . '/files_encryption/share-keys';
 		
 		$shareKeyPath = self::keySetPreparation( $view, $filename, $basePath, $owner );
+
+		// try reusing key file if part file
+		if(self::isPartialFilePath($shareKeyPath)) {
+		
+			$writePath = $basePath . '/' . self::fixPartialFilePath($shareKeyPath) . '.' . $userId . '.shareKey';
+			
+		} else {
 		
-		$writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey';
+			$writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey';
+			
+		}
 
-        $proxyStatus = \OC_FileProxy::$enabled;
+		$proxyStatus = \OC_FileProxy::$enabled;
 		\OC_FileProxy::$enabled = false;
 
 		$result = $view->file_put_contents( $writePath, $shareKey );
 
-        \OC_FileProxy::$enabled = $proxyStatus;
+		\OC_FileProxy::$enabled = $proxyStatus;
 
 		if ( 
 			is_int( $result ) 
@@ -359,7 +439,20 @@ class Keymanager {
 	 */
 	public static function getShareKey( \OC_FilesystemView $view, $userId, $filePath ) {
 
-        $proxyStatus = \OC_FileProxy::$enabled;
+		// try reusing key file if part file
+		if(self::isPartialFilePath($filePath)) {
+		
+			$result = self::getShareKey($view, $userId, self::fixPartialFilePath($filePath));
+			
+			if($result) {
+			
+				return $result;
+				
+			}
+			
+		}
+
+		$proxyStatus = \OC_FileProxy::$enabled;
 		\OC_FileProxy::$enabled = false;
 
 		//here we need the currently logged in user, while userId can be a different user
@@ -367,7 +460,7 @@ class Keymanager {
 
 		list($owner, $filename) = $util->getUidAndFilename($filePath);
 
-		$shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey';
+		$shareKeyPath = \OC\Files\Filesystem::normalizePath('/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey');
 		if ( $view->file_exists( $shareKeyPath ) ) {
 			
 			$result = $view->file_get_contents( $shareKeyPath );
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
index 73f72a9e23eff70bc3fb9917f1f709aefb491f9d..36d05d7e0fee0f24d310d887f9c5a42300abe40a 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -93,29 +93,29 @@ class Proxy extends \OC_FileProxy {
 	
 	public function preFile_put_contents( $path, &$data ) {
 
-        if ( self::shouldEncrypt( $path ) ) {
+		if ( self::shouldEncrypt( $path ) ) {
 
-        	// Stream put contents should have been converted to fopen
+			// Stream put contents should have been converted to fopen
 			if ( !is_resource( $data ) ) {
 
-                $userId = \OCP\USER::getUser();
-				$rootView = new \OC_FilesystemView( '/' );
-				$util = new Util( $rootView, $userId );
-				$session = new Session( $rootView );
+				$userId = \OCP\USER::getUser();
+				$view = new \OC_FilesystemView( '/' );
+				$util = new Util( $view, $userId );
+				$session = new Session( $view );
 				$privateKey = $session->getPrivateKey();
 				$filePath = $util->stripUserFilesPath( $path );
 				// Set the filesize for userland, before encrypting
 				$size = strlen( $data );
-				
+					
 				// Disable encryption proxy to prevent recursive calls
-                $proxyStatus = \OC_FileProxy::$enabled;
-                \OC_FileProxy::$enabled = false;
-				
+				$proxyStatus = \OC_FileProxy::$enabled;
+				\OC_FileProxy::$enabled = false;
+					
 				// Check if there is an existing key we can reuse
-				if ( $encKeyfile = Keymanager::getFileKey( $rootView, $userId, $filePath ) ) {
+				if ( $encKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ) ) {
 					
 					// Fetch shareKey
-					$shareKey = Keymanager::getShareKey( $rootView, $userId, $filePath );
+					$shareKey = Keymanager::getShareKey( $view, $userId, $filePath );
 					
 					// Decrypt the keyfile
 					$plainKey = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
@@ -124,7 +124,7 @@ class Proxy extends \OC_FileProxy {
 				
 					// Make a new key
 					$plainKey = Crypt::generateKey();
-				
+					
 				}
 				
 				// Encrypt data
@@ -134,36 +134,37 @@ class Proxy extends \OC_FileProxy {
 				
 				$uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $filePath, $userId );
 
-                // Fetch public keys for all users who will share the file
-				$publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds );
+				// Fetch public keys for all users who will share the file
+				$publicKeys = Keymanager::getPublicKeys( $view, $uniqueUserIds );
 
-                // Encrypt plain keyfile to multiple sharefiles
+				// Encrypt plain keyfile to multiple sharefiles
 				$multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys );
 				
 				// Save sharekeys to user folders
-				Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
+				Keymanager::setShareKeys( $view, $filePath, $multiEncrypted['keys'] );
 				
 				// Set encrypted keyfile as common varname
 				$encKey = $multiEncrypted['data'];
 				
 				// Save keyfile for newly encrypted file in parallel directory tree
-				Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey );
+				Keymanager::setFileKey( $view, $filePath, $userId, $encKey );
 
 				// Replace plain content with encrypted content by reference
 				$data = $encData;
-				
+					
 				// Update the file cache with file info
-				\OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' );
-				
+				\OC\Files\Filesystem::putFileInfo( $filePath, array( 'encrypted'=>true, 'size' => strlen($size), 'unencrypted_size' => $size), '' );
+
 				// Re-enable proxy - our work is done
 				\OC_FileProxy::$enabled = $proxyStatus;
 				
 			}
 		}
 
-        return true;
+		return true;
+		
 	}
-	
+		
 	/**
 	 * @param string $path Path of file from which has been read
 	 * @param string $data Data that has been read from file
@@ -273,136 +274,22 @@ class Proxy extends \OC_FileProxy {
 	}
 
 	/**
-	 * @brief When a file is renamed, rename its keyfile also
-	 * @return bool Result of rename()
-	 * @note This is pre rather than post because using post didn't work
-	 */
-	public function preRename( $oldPath, $newPath )
-    {
-
-        // Disable encryption proxy to prevent recursive calls
-        $proxyStatus = \OC_FileProxy::$enabled;
-        \OC_FileProxy::$enabled = false;
-
-        $view = new \OC_FilesystemView('/');
-
-        $userId = \OCP\USER::getUser();
-
-        // Format paths to be relative to user files dir
-        $oldTrimmed = ltrim($oldPath, '/');
-        $oldSplit = explode('/', $oldTrimmed);
-        $oldSliced = array_slice($oldSplit, 2);
-        $oldRelPath = implode('/', $oldSliced);
-        $oldKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $oldRelPath;
-
-        $newTrimmed = ltrim($newPath, '/');
-        $newSplit = explode('/', $newTrimmed);
-        $newSliced = array_slice($newSplit, 2);
-        $newRelPath = implode('/', $newSliced);
-        $newKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $newRelPath;
-
-        // add key ext if this is not an folder
-        if (!$view->is_dir($oldKeyfilePath)) {
-            $oldKeyfilePath .= '.key';
-            $newKeyfilePath .= '.key';
-
-            // handle share-keys
-            $localKeyPath = $view->getLocalFile($userId.'/files_encryption/share-keys/'.$oldRelPath);
-            $matches = glob(preg_quote($localKeyPath).'*.shareKey');
-            foreach ($matches as $src) {
-                $dst = str_replace($oldRelPath, $newRelPath, $src);
-                rename($src, $dst);
-            }
-
-        } else {
-            // handle share-keys folders
-            $oldShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $oldRelPath;
-            $newShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $newRelPath;
-            $view->rename($oldShareKeyfilePath, $newShareKeyfilePath);
-        }
-
-        // Rename keyfile so it isn't orphaned
-        $result = $view->rename($oldKeyfilePath, $newKeyfilePath);
-
-        \OC_FileProxy::$enabled = $proxyStatus;
-
-        return $result;
-
-    }
-
-    /**
      * @brief When a file is renamed, rename its keyfile also
      * @return bool Result of rename()
      * @note This is pre rather than post because using post didn't work
      */
-    public function postRename( $oldPath, $newPath )
+    public function postWrite( $path )
     {
+        $this->handleFile($path);
 
-        // Disable encryption proxy to prevent recursive calls
-        $proxyStatus = \OC_FileProxy::$enabled;
-        \OC_FileProxy::$enabled = false;
-
-        $view = new \OC_FilesystemView('/');
-        $session = new Session($view);
-        $userId = \OCP\User::getUser();
-        $util = new Util( $view, $userId );
-
-        // Reformat path for use with OC_FSV
-        $newPathSplit = explode( '/', $newPath );
-        $newPathRelative = implode( '/', array_slice( $newPathSplit, 3 ) );
-
-        // get file info from database/cache
-        //$newFileInfo = \OC\Files\Filesystem::getFileInfo($newPathRelative);
-
-        if ($util->isEncryptedPath($newPath)) {
-            $cached = $view->getFileInfo($newPath);
-            $cached['encrypted'] = 1;
-
-            // get the size from filesystem
-            $size = $view->filesize($newPath);
-
-            // calculate last chunk nr
-            $lastChunckNr = floor($size / 8192);
-
-            // open stream
-            $result = fopen('crypt://' . $newPathRelative, "r");
-
-            if(is_resource($result)) {
-                // calculate last chunk position
-                $lastChunckPos = ($lastChunckNr * 8192);
-
-                // seek to end
-                fseek($result, $lastChunckPos);
-
-                // get the content of the last chunck
-                $lastChunkContent = fread($result, 8192);
-
-                // calc the real file size with the size of the last chunk
-                $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent));
-
-                // set the size
-                $cached['unencrypted_size'] = $realSize;
-            }
-
-            $view->putFileInfo( $newPath, $cached );
-
-            // get sharing app state
-            $sharingEnabled = \OCP\Share::isEnabled();
-
-            // get users
-            $usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative);
-
-            // update sharing-keys
-            $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative);
-        }
-
-
-
+        return true;
+    }
 
-        \OC_FileProxy::$enabled = $proxyStatus;
+    public function postTouch( $path )
+    {
+        $this->handleFile($path);
 
         return true;
-
     }
 
     public function postFopen( $path, &$result ){
@@ -518,25 +405,28 @@ class Proxy extends \OC_FileProxy {
         return $data;
     }
 
-	public function postStat( $path, $data ) {
+    public function postStat($path, $data)
+    {
+        // check if file is encrypted
+        if (Crypt::isCatfileContent($path)) {
+
+            // get file info from cache
+            $cached = \OC\Files\Filesystem::getFileInfo($path, '');
 
-        if ( Crypt::isCatfileContent( $path ) ) {
-		
-			$cached = \OC\Files\Filesystem::getFileInfo( $path, '' );
-			
-			$data['size'] = $cached['unencrypted_size'];
-			
-		}
-		
-		return $data;
-	}
+            // set the real file size
+            $data['size'] = $cached['unencrypted_size'];
+        }
 
-	public function postFileSize( $path, $size ) {
+        return $data;
+    }
 
-        $view = new \OC_FilesystemView( '/' );
+    public function postFileSize($path, $size)
+    {
+
+        $view = new \OC_FilesystemView('/');
 
         // if path is a folder do nothing
-        if($view->is_dir($path)) {
+        if ($view->is_dir($path)) {
             return $size;
         }
 
@@ -544,14 +434,65 @@ class Proxy extends \OC_FileProxy {
         $path_split = explode('/', $path);
         $path_f = implode('/', array_slice($path_split, 3));
 
+        // if path is empty we cannot resolve anything
+        if(empty($path_f)) {
+            return $size;
+        }
+
         // get file info from database/cache
         $fileInfo = \OC\Files\Filesystem::getFileInfo($path_f);
 
         // if file is encrypted return real file size
-        if(is_array($fileInfo) && $fileInfo['encrypted'] == 1) {
-            return $fileInfo['unencrypted_size'];
+        if (is_array($fileInfo) && $fileInfo['encrypted'] === true) {
+            $size = $fileInfo['unencrypted_size'];
         } else {
-            return $size;
+            // self healing if file was removed from file cache
+            if(is_array($fileInfo)) {
+                $userId = \OCP\User::getUser();
+                $util = new Util( $view, $userId );
+                $fixSize = $util->getFileSize($path);
+                if($fixSize > 0) {
+                    $size = $fixSize;
+
+                    $fileInfo['encrypted'] = true;
+                    $fileInfo['unencrypted_size'] = $size;
+
+                    // put file info
+                    $view->putFileInfo( $path_f, $fileInfo );
+                }
+            }
         }
-	}
-}
+        return $size;
+    }
+
+    public function handleFile($path) {
+
+        // Disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        $view = new \OC_FilesystemView('/');
+        $session = new Session($view);
+        $userId = \OCP\User::getUser();
+        $util = new Util( $view, $userId );
+
+        // Reformat path for use with OC_FSV
+        $path_split = explode( '/', $path );
+        $path_f = implode( '/', array_slice( $path_split, 3 ) );
+
+        // only if file is on 'files' folder fix file size and sharing
+        if($path_split[2] == 'files' && $util->fixFileSize($path)) {
+
+            // get sharing app state
+            $sharingEnabled = \OCP\Share::isEnabled();
+
+            // get users
+            $usersSharing = $util->getSharingUsersArray($sharingEnabled, $path_f);
+
+            // update sharing-keys
+            $util->setSharedFileKeyfiles($session, $usersSharing, $path_f);
+        }
+
+        \OC_FileProxy::$enabled = $proxyStatus;
+    }
+ }
diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php
index 0c6a7131fd9b6fa0d205a70a1f2af1785d03fcc5..f02315f95dfa2115765298c0c09274b9002aa535 100644
--- a/apps/files_encryption/lib/session.php
+++ b/apps/files_encryption/lib/session.php
@@ -35,43 +35,64 @@ class Session {
 	 * 
 	 * The ownCloud key pair is used to allow public link sharing even if encryption is enabled
 	 */
-	public function __construct( \OC_FilesystemView $view ) {
+	public function __construct( $view ) {
 		
 		$this->view = $view;
 
 
 		if ( ! $this->view->is_dir( 'owncloud_private_key' ) ) {
 		
-			$this->view->mkdir('owncloud_private_key');
+			$this->view->mkdir( 'owncloud_private_key' );
+			
+		}
+
+		$publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId');
+
+		if ($publicShareKeyId === null) {
+			$publicShareKeyId = 'pubShare_'.substr(md5(time()),0,8);
+			\OC_Appconfig::setValue('files_encryption', 'publicShareKeyId', $publicShareKeyId);
 		}
-		
 		
 		if ( 
-			! $this->view->file_exists("/public-keys/owncloud.public.key") 
-			|| ! $this->view->file_exists("/owncloud_private_key/owncloud.private.key" ) 
+			! $this->view->file_exists( "/public-keys/".$publicShareKeyId.".public.key" )
+			|| ! $this->view->file_exists( "/owncloud_private_key/".$publicShareKeyId.".private.key" )
 		) {
+				
+ 			$keypair = Crypt::createKeypair();
 
-			$keypair = Crypt::createKeypair();
-			
-			\OC_FileProxy::$enabled = false;
-			
-			// Save public key
+            // Disable encryption proxy to prevent recursive calls
+            $proxyStatus = \OC_FileProxy::$enabled;
+            \OC_FileProxy::$enabled = false;
 
-			if (!$view->is_dir('/public-keys')) {
-				$view->mkdir('/public-keys');
-			}
-
-			$this->view->file_put_contents( '/public-keys/owncloud.public.key', $keypair['publicKey'] );
-			
-			// Encrypt private key empthy passphrase
-			$encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' );
-			
-			// Save private key
-			$this->view->file_put_contents( '/owncloud_private_key/owncloud.private.key', $encryptedPrivateKey );
+ 			// Save public key
+ 
+ 			if (!$view->is_dir('/public-keys')) {
+ 				$view->mkdir('/public-keys');
+ 			}
+ 
+ 			$this->view->file_put_contents( '/public-keys/'.$publicShareKeyId.'.public.key', $keypair['publicKey'] );
+ 			
+ 			// Encrypt private key empthy passphrase
+ 			$encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' );
+ 			
+ 			// Save private key
+ 			$this->view->file_put_contents( '/owncloud_private_key/'.$publicShareKeyId.'.private.key', $encryptedPrivateKey );
 			
-			\OC_FileProxy::$enabled = true;
+			\OC_FileProxy::$enabled = $proxyStatus;
 			
 		}
+
+        if(\OCP\USER::getUser() === false) {
+            // Disable encryption proxy to prevent recursive calls
+            $proxyStatus = \OC_FileProxy::$enabled;
+            \OC_FileProxy::$enabled = false;
+
+            $encryptedKey = $this->view->file_get_contents( '/owncloud_private_key/'.$publicShareKeyId.'.private.key' );
+            $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, '' );
+            $this->setPrivateKey($privateKey);
+
+            \OC_FileProxy::$enabled = $proxyStatus;
+        }
 	}
 
 	/**
diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php
index 411bcdac92d7200c3ed44b93fd951fbea2d98693..ab967835082203b5a0845ecc36d4c0f05d0da674 100644
--- a/apps/files_encryption/lib/stream.php
+++ b/apps/files_encryption/lib/stream.php
@@ -72,20 +72,20 @@ class Stream {
 	private $rootView; // a fsview object set to '/'
 
 	public function stream_open( $path, $mode, $options, &$opened_path ) {
-		
-		$this->userId = \OCP\User::getUser();
-		
-		if ( ! isset( $this->rootView ) ) {
 
+		if ( ! isset( $this->rootView ) ) {
 			$this->rootView = new \OC_FilesystemView( '/' );
-
 		}
 
-		// Strip identifier text from path, this gives us the path relative to data/<user>/files
-		$this->relPath = str_replace( 'crypt://', '', $path );
+        $util = new Util( $this->rootView, \OCP\USER::getUser());
+
+        $this->userId = $util->getUserId();
+
+        // Strip identifier text from path, this gives us the path relative to data/<user>/files
+		$this->relPath = \OC\Files\Filesystem::normalizePath(str_replace( 'crypt://', '', $path ));
 		
 		// rawPath is relative to the data directory
-		$this->rawPath = $this->userId . '/files/' . $this->relPath;
+		$this->rawPath = $util->getUserFilesDir() . $this->relPath;
 		
 		if (
 		dirname( $this->rawPath ) == 'streams' 
@@ -298,7 +298,8 @@ class Stream {
 		// automatically attempted when the file is written to disk - 
 		// we are handling that separately here and we don't want to 
 		// get into an infinite loop
-		//\OC_FileProxy::$enabled = false;
+        $proxyStatus = \OC_FileProxy::$enabled;
+		\OC_FileProxy::$enabled = false;
 		
 		// Get the length of the unencrypted data that we are handling
 		$length = strlen( $data );
@@ -322,30 +323,7 @@ class Stream {
 			
 		}
 		
-		// Fetch user's public key
-		$this->publicKey = Keymanager::getPublicKey( $this->rootView, $this->userId );
-		
-		// Check if OC sharing api is enabled
-		$sharingEnabled = \OCP\Share::isEnabled();
-		
-		$util = new Util( $this->rootView, $this->userId );
-		
-		// Get all users sharing the file includes current user
-		$uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath, $this->userId);
-
-        // Fetch public keys for all sharing users
-		$publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds );
 
-        // Encrypt enc key for all sharing users
-		$this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys );
-		
-		$view = new \OC_FilesystemView( '/' );
-		
-		// Save the new encrypted file key
-		Keymanager::setFileKey( $this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data'] );
-		
-		// Save the sharekeys
-		Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] );
 		
 		// If extra data is left over from the last round, make sure it 
 		// is integrated into the next 6126 / 8192 block
@@ -437,6 +415,8 @@ class Stream {
 		$this->size = max( $this->size, $pointer + $length );
         $this->unencryptedSize += $length;
 
+        \OC_FileProxy::$enabled = $proxyStatus;
+
 		return $length;
 
 	}
@@ -492,14 +472,59 @@ class Stream {
 	}
 
 	public function stream_close() {
-	
-		$this->flush();
+
+        $this->flush();
 		
 		if ( 
 		$this->meta['mode']!='r' 
-		and $this->meta['mode']!='rb' 
+		and $this->meta['mode']!='rb'
+        and $this->size > 0
 		) {
-			\OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => 1, 'size' => $this->size, 'unencrypted_size' => $this->unencryptedSize ), '' );
+            // Disable encryption proxy to prevent recursive calls
+            $proxyStatus = \OC_FileProxy::$enabled;
+            \OC_FileProxy::$enabled = false;
+
+            // Fetch user's public key
+            $this->publicKey = Keymanager::getPublicKey( $this->rootView, $this->userId );
+
+            // Check if OC sharing api is enabled
+            $sharingEnabled = \OCP\Share::isEnabled();
+
+            $util = new Util( $this->rootView, $this->userId );
+
+            // Get all users sharing the file includes current user
+            $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath, $this->userId);
+
+            // Fetch public keys for all sharing users
+            $publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds );
+
+            // Encrypt enc key for all sharing users
+            $this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys );
+
+            $view = new \OC_FilesystemView( '/' );
+
+            // Save the new encrypted file key
+            Keymanager::setFileKey( $this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data'] );
+
+            // Save the sharekeys
+            Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] );
+
+            // get file info
+            $fileInfo = $view->getFileInfo($this->rawPath);
+            if(!is_array($fileInfo)) {
+                $fileInfo = array();
+            }
+
+            // Re-enable proxy - our work is done
+            \OC_FileProxy::$enabled = $proxyStatus;
+
+            // set encryption data
+            $fileInfo['encrypted'] = true;
+            $fileInfo['size'] = $this->size;
+            $fileInfo['unencrypted_size'] = $this->unencryptedSize;
+
+            // set fileinfo
+            $view->putFileInfo( $this->rawPath, $fileInfo);
 		}
 
 		return fclose( $this->handle );
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php
index 2198963ce14ef2bb0abc87fc17fece24d495f44d..19c9cd72a19b567345e590e8d75d73ef0a4bccf3 100644
--- a/apps/files_encryption/lib/util.php
+++ b/apps/files_encryption/lib/util.php
@@ -3,8 +3,8 @@
  * ownCloud
  *
  * @author Sam Tuke, Frank Karlitschek
- * @copyright 2012 Sam Tuke samtuke@owncloud.com, 
- * Frank Karlitschek frank@owncloud.org
+ * @copyright 2012 Sam Tuke <samtuke@owncloud.com>, 
+ * Frank Karlitschek <frank@owncloud.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@@ -24,11 +24,8 @@
 # Bugs
 # ----
 # Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer
-# Timeouts on first login due to encryption of very large files (fix in progress, as a result streaming is currently broken)
 # Sharing all files to admin for recovery purposes still in progress
 # Possibly public links are broken (not tested since last merge of master)
-# encryptAll during login mangles paths: /files/files/
-# encryptAll is accessing files via encryption proxy - perhaps proxies should be disabled?
 
 
 # Missing features
@@ -91,20 +88,13 @@ class Util {
 	
 	//// TODO: add support for optional recovery in case of lost passphrase / keys
 	//// TODO: add admin optional required long passphrase for users
-	//// TODO: add UI buttons for encrypt / decrypt everything
 	//// TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc.
 	
 	
-	// Sharing:
-	
-	//// TODO: add support for encrypting to multiple public keys
-	//// TODO: add support for decrypting to multiple private keys
-	
-	
 	// Integration testing:
 	
 	//// TODO: test new encryption with versioning
-	//// TODO: test new encryption with sharing
+	//// DONE: test new encryption with sharing
 	//// TODO: test new encryption with proxies
 	
 	
@@ -118,38 +108,65 @@ class Util {
 	private $shareKeysPath; // Dir containing env keys for shared files
 	private $publicKeyPath; // Path to user's public key
 	private $privateKeyPath; // Path to user's private key
+	private $publicShareKeyId;
+	private $recoveryKeyId;
+    private $isPublic;
 
 	public function __construct( \OC_FilesystemView $view, $userId, $client = false ) {
-	
+
 		$this->view = $view;
 		$this->userId = $userId;
 		$this->client = $client;
-		$this->userDir =  '/' . $this->userId;
-		$this->fileFolderName = 'files';
-		$this->userFilesDir =  '/' . $this->userId . '/' . $this->fileFolderName; // TODO: Does this need to be user configurable?
-		$this->publicKeyDir =  '/' . 'public-keys';
-		$this->encryptionDir =  '/' . $this->userId . '/' . 'files_encryption';
-		$this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
-		$this->shareKeysPath = $this->encryptionDir . '/' . 'share-keys';
-		$this->publicKeyPath = $this->publicKeyDir . '/' . $this->userId . '.public.key'; // e.g. data/public-keys/admin.public.key
-		$this->privateKeyPath = $this->encryptionDir . '/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key
-		
+        $this->isPublic = false;
+
+        $this->publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId');
+        $this->recoveryKeyId = \OC_Appconfig::getValue('files_encryption', 'recoveryKeyId');
+
+        // if we are anonymous/public
+        if($this->userId === false) {
+            $this->userId = $this->publicShareKeyId;
+
+            // only handle for files_sharing app
+            if($GLOBALS['app'] === 'files_sharing') {
+                $this->userDir =  '/' . $GLOBALS['fileOwner'];
+                $this->fileFolderName = 'files';
+                $this->userFilesDir =  '/' . $GLOBALS['fileOwner'] . '/' . $this->fileFolderName; // TODO: Does this need to be user configurable?
+                $this->publicKeyDir =  '/' . 'public-keys';
+                $this->encryptionDir =  '/' . $GLOBALS['fileOwner'] . '/' . 'files_encryption';
+                $this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
+                $this->shareKeysPath = $this->encryptionDir . '/' . 'share-keys';
+                $this->publicKeyPath = $this->publicKeyDir . '/' . $this->userId . '.public.key'; // e.g. data/public-keys/admin.public.key
+                $this->privateKeyPath = '/owncloud_private_key/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key
+                $this->isPublic = true;
+            }
+
+        } else {
+            $this->userDir =  '/' . $this->userId;
+            $this->fileFolderName = 'files';
+            $this->userFilesDir =  '/' . $this->userId . '/' . $this->fileFolderName; // TODO: Does this need to be user configurable?
+            $this->publicKeyDir =  '/' . 'public-keys';
+            $this->encryptionDir =  '/' . $this->userId . '/' . 'files_encryption';
+            $this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
+            $this->shareKeysPath = $this->encryptionDir . '/' . 'share-keys';
+            $this->publicKeyPath = $this->publicKeyDir . '/' . $this->userId . '.public.key'; // e.g. data/public-keys/admin.public.key
+            $this->privateKeyPath = $this->encryptionDir . '/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key
+        }
 	}
 	
 	public function ready() {
 		
 		if( 
-		!$this->view->file_exists( $this->encryptionDir )
-		or !$this->view->file_exists( $this->keyfilesPath )
-		or !$this->view->file_exists( $this->shareKeysPath )
-		or !$this->view->file_exists( $this->publicKeyPath )
-		or !$this->view->file_exists( $this->privateKeyPath ) 
+		! $this->view->file_exists( $this->encryptionDir )
+		or ! $this->view->file_exists( $this->keyfilesPath )
+		or ! $this->view->file_exists( $this->shareKeysPath )
+		or ! $this->view->file_exists( $this->publicKeyPath )
+		or ! $this->view->file_exists( $this->privateKeyPath ) 
 		) {
 		
 			return false;
 			
 		} else {
-		
+			
 			return true;
 			
 		}
@@ -207,17 +224,32 @@ class Util {
 			
 		}
 		
+		// If there's no record for this user's encryption preferences
+		if ( false === $this->recoveryEnabledForUser() ) {
+		
+			// create database configuration
+			$sql = 'INSERT INTO `*PREFIX*encryption` (`uid`,`mode`,`recovery`) VALUES (?,?,?)';
+			$args = array( $this->userId, 'server-side', 0);
+			$query = \OCP\DB::prepare( $sql );
+			$query->execute( $args );
+		
+		}
+		
 		return true;
 	
 	}
+
+	public function getPublicShareKeyId() {
+		return $this->publicShareKeyId;
+	}
 	
 	/**
 	 * @brief Check whether pwd recovery is enabled for a given user
-	 * @return bool
+	 * @return 1 = yes, 0 = no, false = no record
 	 * @note If records are not being returned, check for a hidden space 
 	 *       at the start of the uid in db
 	 */
-	public function recoveryEnabled() {
+	public function recoveryEnabledForUser() {
 	
 		$sql = 'SELECT 
 				recovery 
@@ -232,16 +264,25 @@ class Util {
 		
 		$result = $query->execute( $args );
 		
-		// Set default in case no records found
-		$recoveryEnabled = 0;
+		$recoveryEnabled = array();
 		
 		while( $row = $result->fetchRow() ) {
 		
-			$recoveryEnabled = $row['recovery'];
+			$recoveryEnabled[] = $row['recovery'];
 			
 		}
 		
-		return $recoveryEnabled;
+		// If no record is found
+		if ( empty( $recoveryEnabled ) ) {
+		
+			return false;
+		
+		// If a record is found
+		} else {
+		
+			return $recoveryEnabled[0];
+			
+		}
 	
 	}
 	
@@ -250,20 +291,33 @@ class Util {
 	 * @param bool $enabled Whether to enable or disable recovery
 	 * @return bool
 	 */
-	public function setRecovery( $enabled ) {
+	public function setRecoveryForUser( $enabled ) {
 	
-		$sql = 'UPDATE 
-				*PREFIX*encryption 
-			SET 
-				recovery = ? 
-			WHERE 
-				uid = ?';
+		$recoveryStatus = $this->recoveryEnabledForUser();
+	
+		// If a record for this user already exists, update it
+		if ( false === $recoveryStatus ) {
 		
-		// Ensure value is an integer
-		$enabled = intval( $enabled );
+			$sql = 'INSERT INTO `*PREFIX*encryption` 
+					(`uid`,`mode`,`recovery`) 
+				VALUES (?,?,?)';
+				
+			$args = array( $this->userId, 'server-side', $enabled );
 		
-		$args = array( $enabled, $this->userId );
-
+		// Create a new record instead
+		} else {
+		
+			$sql = 'UPDATE 
+					*PREFIX*encryption 
+				SET 
+					recovery = ? 
+				WHERE 
+					uid = ?';
+			
+			$args = array( $enabled, $this->userId );
+		
+		}
+	
 		$query = \OCP\DB::prepare( $sql );
 		
 		if ( $query->execute( $args ) ) {
@@ -282,7 +336,6 @@ class Util {
 	 * @brief Find all files and their encryption status within a directory
 	 * @param string $directory The path of the parent directory to search
 	 * @return mixed false if 0 found, array on success. Keys: name, path
-	 
 	 * @note $directory needs to be a path relative to OC data dir. e.g.
 	 *       /admin/files NOT /backup OR /home/www/oc/data/admin/files
 	 */
@@ -421,26 +474,123 @@ class Util {
 		return $text;
 	}
 	
-        /**
-         * @brief Check if a given path identifies an encrypted file
-         * @return true / false
-         */
+	/**
+	* @brief Check if a given path identifies an encrypted file
+	* @return true / false
+	*/
 	public function isEncryptedPath( $path ) {
 	
-		// Disable encryption proxy so data retreived is in its 
+		// Disable encryption proxy so data retrieved is in its
 		// original form
+        $proxyStatus = \OC_FileProxy::$enabled;
 		\OC_FileProxy::$enabled = false;
-	
-		$data = $this->view->file_get_contents( $path );
-		
-		\OC_FileProxy::$enabled = true;
+
+        // we only need 24 byte from the last chunk
+        $data = '';
+		$handle = $this->view->fopen( $path, 'r' );
+        if(!fseek($handle, -24, SEEK_END)) {
+            $data = fgets($handle);
+        }
+
+        // re-enable proxy
+		\OC_FileProxy::$enabled = $proxyStatus;
 		
 		return Crypt::isCatfileContent( $data );
 	
 	}
+
+	/**
+	* @brief get the file size of the unencrypted file
+	* @param $path absolute path
+	* @return bool
+	*/
+
+	public function getFileSize( $path ) {
+	
+		$result = 0;
+
+		// Disable encryption proxy to prevent recursive calls
+		$proxyStatus = \OC_FileProxy::$enabled;
+		\OC_FileProxy::$enabled = false;
+
+		// Reformat path for use with OC_FSV
+		$pathSplit = explode( '/', $path );
+		$pathRelative = implode( '/', array_slice( $pathSplit, 3 ) );
+
+		if ($pathSplit[2] == 'files' && $this->view->file_exists($path) && $this->isEncryptedPath($path)) {
+
+			// get the size from filesystem
+			$fullPath = $this->view->getLocalFile($path);
+			$size = filesize($fullPath);
+
+			// calculate last chunk nr
+			$lastChunckNr = floor($size / 8192);
+
+			// open stream
+			$stream = fopen('crypt://' . $pathRelative, "r");
+
+			if(is_resource($stream)) {
+				// calculate last chunk position
+				$lastChunckPos = ($lastChunckNr * 8192);
+
+				// seek to end
+				fseek($stream, $lastChunckPos);
+
+				// get the content of the last chunk
+				$lastChunkContent = fread($stream, 8192);
+
+				// calc the real file size with the size of the last chunk
+				$realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent));
+
+				// store file size
+				$result = $realSize;
+			}
+		}
+
+		\OC_FileProxy::$enabled = $proxyStatus;
+
+		return $result;
+	}
+    
+	/**
+	 * @brief fix the file size of the encrypted file
+	 * @param $path absolute path
+	 * @return true / false if file is encrypted
+	 */
+
+	public function fixFileSize( $path ) {
 	
+		$result = false;
+
+		// Disable encryption proxy to prevent recursive calls
+		$proxyStatus = \OC_FileProxy::$enabled;
+		\OC_FileProxy::$enabled = false;
+
+		$realSize = $this->getFileSize( $path );
+		
+		if ( $realSize > 0 ) {
+		
+			$cached = $this->view->getFileInfo( $path );
+			$cached['encrypted'] = true;
+
+			// set the size
+			$cached['unencrypted_size'] = $realSize;
+
+			// put file info
+			$this->view->putFileInfo( $path, $cached );
+
+			$result = true;
+			
+		}
+
+		\OC_FileProxy::$enabled = $proxyStatus;
+
+		return $result;
+	}
+
 	/**
 	 * @brief Format a path to be relative to the /user/files/ directory
+	 * @note e.g. turns '/admin/files/test.txt' into 'test.txt'
 	 */
 	public function stripUserFilesPath( $path ) {
 	
@@ -453,6 +603,21 @@ class Util {
 	
 	}
 	
+	/**
+	 * @brief Format a path to be relative to the /user directory
+	 * @note e.g. turns '/admin/files/test.txt' into 'files/test.txt'
+	 */
+	public function stripFilesPath( $path ) {
+	
+		$trimmed = ltrim( $path, '/' );
+		$split = explode( '/', $trimmed );
+		$sliced = array_slice( $split, 1 );
+		$relPath = implode( '/', $sliced );
+		
+		return $relPath;
+	
+	}
+	
 	/**
 	 * @brief Format a shared path to be relative to the /user/files/ directory
 	 * @note Expects a path like /uid/files/Shared/filepath
@@ -517,7 +682,7 @@ class Util {
 				stream_copy_to_stream( $plainHandle1, $plainHandle2 );
 				
 				// Close access to original file
-// 				$this->view->fclose( $plainHandle1 ); // not implemented in view{}
+				// $this->view->fclose( $plainHandle1 ); // not implemented in view{}
 				
 				// Delete original plain file so we can rename enc file later
 				$this->view->unlink( $rawPath );
@@ -653,7 +818,7 @@ class Util {
 	 * @return multi-dimensional array. keys: ready, unready
 	 */
 	public function filterShareReadyUsers( $unfilteredUsers ) {
-	
+		
 		// This array will collect the filtered IDs
 		$readyIds = $unreadyIds = array();
 	
@@ -665,8 +830,9 @@ class Util {
 			// Check that the user is encryption capable, or is the
 			// public system user 'ownCloud' (for public shares)
 			if ( 
-				$util->ready() 
-				or $user == 'owncloud'
+				$user == $this->publicShareKeyId
+				or $user == $this->recoveryKeyId
+				or $util->ready() 
 			) {
 			
 				// Construct array of ready UIDs for Keymanager{}
@@ -738,25 +904,27 @@ class Util {
 	 * @brief Encrypt keyfile to multiple users
 	 * @param array $users list of users which should be able to access the file
 	 * @param string $filePath path of the file to be shared
+	 * @return bool 
 	 */
 	public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) {
-	
+		
 		// Make sure users are capable of sharing
 		$filteredUids = $this->filterShareReadyUsers( $users );
 		
-// 		trigger_error( print_r($filteredUids, 1) );
-		
+		// If we're attempting to share to unready users
 		if ( ! empty( $filteredUids['unready'] ) ) {
-		
-			// Notify user of unready userDir
-			// TODO: Move this out of here; it belongs somewhere else
-			\OCP\JSON::error();
+			
+			\OC_Log::write( 'Encryption library', 'Sharing to these user(s) failed as they are unready for encryption:"'.print_r( $filteredUids['unready'], 1 ), \OC_Log::WARN );
+			
+			return false;
 			
 		}
 		
 		// Get public keys for each user, ready for generating sharekeys
 		$userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids['ready'] );
-
+		
+		// Note proxy status then disable it
+		$proxyStatus = \OC_FileProxy::$enabled;
 		\OC_FileProxy::$enabled = false;
 
 		// Get the current users's private key for decrypting existing keyfile
@@ -772,21 +940,19 @@ class Util {
 		
 		// Save the recrypted key to it's owner's keyfiles directory
 		// Save new sharekeys to all necessary user directory
-		// TODO: Reuse the keyfile, it it exists, instead of making a new one
 		if ( 
 			! Keymanager::setFileKey( $this->view, $filePath, $fileOwner, $multiEncKey['data'] )
 			|| ! Keymanager::setShareKeys( $this->view, $filePath, $multiEncKey['keys'] ) 
 		) {
 
-			trigger_error( "SET Share keys failed" );
+			\OC_Log::write( 'Encryption library', 'Keyfiles could not be saved for users sharing ' . $filePath, \OC_Log::ERROR );
+			
+			return false;
 
 		}
-
-		// Delete existing keyfile
-		// Do this last to ensure file is recoverable in case of error
-		// Keymanager::deleteFileKey( $this->view, $this->userId, $params['fileTarget'] );
-	
-		\OC_FileProxy::$enabled = true;
+		
+		// Return proxy to original status
+		\OC_FileProxy::$enabled = $proxyStatus;
 
 		return true;
 	}
@@ -798,33 +964,51 @@ class Util {
 	public function getSharingUsersArray( $sharingEnabled, $filePath, $currentUserId = false ) {
 
 		// Check if key recovery is enabled
-		$recoveryEnabled = $this->recoveryEnabled();
+		if (
+			\OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' )
+			&& $this->recoveryEnabledForUser()
+		) {
+		
+			$recoveryEnabled = true;
+			
+		} else {
+		
+			$recoveryEnabled = false;
+			
+		}
 		
 		// Make sure that a share key is generated for the owner too
-		list($owner, $ownerPath) = $this->getUidAndFilename($filePath);
+		list( $owner, $ownerPath ) = $this->getUidAndFilename( $filePath );
 
 		if ( $sharingEnabled ) {
 		
 			// Find out who, if anyone, is sharing the file
-			$userIds = \OCP\Share::getUsersSharingFile( $ownerPath, $owner,true, true, true );
+			$result = \OCP\Share::getUsersSharingFile( $ownerPath, $owner,true, true, true );
+			$userIds = $result['users'];
+			if ( $result['public'] ) {
+				$userIds[] = $this->publicShareKeyId;
+			}
 		
 		}
 		
 		// If recovery is enabled, add the 
 		// Admin UID to list of users to share to
 		if ( $recoveryEnabled ) {
-		
-			// FIXME: Create a separate admin user purely for recovery, and create method in util for fetching this id from DB?
-			$adminUid = 'recoveryAdmin';
-		
-			$userIds[] = $adminUid;
+			
+			// Find recoveryAdmin user ID
+			$recoveryKeyId = \OC_Appconfig::getValue( 'files_encryption', 'recoveryKeyId' );
+			
+			// Add recoveryAdmin to list of users sharing
+			$userIds[] = $recoveryKeyId;
 			
 		}
 
-        // add current user if given
-        if($currentUserId != false) {
-            $userIds[] = $currentUserId;
-        }
+		// add current user if given
+		if ( $currentUserId != false ) {
+		
+			$userIds[] = $currentUserId;
+		
+		}
 
 		// Remove duplicate UIDs
 		$uniqueUserIds = array_unique ( $userIds );
@@ -832,57 +1016,138 @@ class Util {
 		return $uniqueUserIds;
 
 	}
-		
+	
 	/**
-	 * @brief get uid of the owners of the file and the path to the file
-	 * @param $path Path of the file to check
-	 * @note $shareFilePath must be relative to data/UID/files. Files 
-	 *       relative to /Shared are also acceptable
-	 * @return array
+	 * @brief Set file migration status for user
+	 * @return bool
 	 */
-	public function getUidAndFilename( $path ) {
-
-		$fileOwnerUid = \OC\Files\Filesystem::getOwner( $path );
+	public function setMigrationStatus( $status ) {
+	
+		$sql = 'UPDATE 
+				*PREFIX*encryption 
+			SET 
+				migrationStatus = ? 
+			WHERE 
+				uid = ?';
 		
-		// Check that UID is valid
-		if ( ! \OCP\User::userExists( $fileOwnerUid ) ) {
+		$args = array( $status, $this->userId );
 		
-			throw new \Exception( 'Could not find owner (UID = "' . var_export( $fileOwnerUid, 1 ) . '") of file "' . $path . '"' );
-			
-		}
-
-		// NOTE: Bah, this dependency should be elsewhere
-		\OC\Files\Filesystem::initMountPoints( $fileOwnerUid );
+		$query = \OCP\DB::prepare( $sql );
 		
-		// If the file owner is the currently logged in user
-		if ( $fileOwnerUid == $this->userId ) {
+		if ( $query->execute( $args ) ) {
 		
-			// Assume the path supplied is correct
-			$filename = $path;
+			return true;
 			
 		} else {
 		
-			$info = \OC\Files\Filesystem::getFileInfo( $path );
-			$ownerView = new \OC\Files\View( '/' . $fileOwnerUid . '/files' );
+			return false;
 			
-			// Fetch real file path from DB
-			$filename = $ownerView->getPath( $info['fileid'] ); // TODO: Check that this returns a path without including the user data dir
-		
 		}
+	
+	}
+	
+	/**
+	 * @brief Check whether pwd recovery is enabled for a given user
+	 * @return 1 = yes, 0 = no, false = no record
+	 * @note If records are not being returned, check for a hidden space 
+	 *       at the start of the uid in db
+	 */
+	public function getMigrationStatus() {
+	
+		$sql = 'SELECT 
+				migrationStatus 
+			FROM 
+				`*PREFIX*encryption` 
+			WHERE 
+				uid = ?';
+				
+		$args = array( $this->userId );
+
+		$query = \OCP\DB::prepare( $sql );
 		
-		// Make path relative for use by $view
-		$relpath = $fileOwnerUid . '/' . $this->fileFolderName . '/' . $filename;
+		$result = $query->execute( $args );
 		
-		// Check that the filename we're using is working
-		if ( $this->view->file_exists( $relpath ) ) {
+		$migrationStatus = array();
 		
-			return array ( $fileOwnerUid, $filename );
+		while( $row = $result->fetchRow() ) {
+		
+			$migrationStatus[] = $row['migrationStatus'];
 			
-		} else {
+		}
+		
+		// If no record is found
+		if ( empty( $migrationStatus ) ) {
 		
 			return false;
+		
+		// If a record is found
+		} else {
+		
+			return $migrationStatus[0];
 			
 		}
+	
+	}
+		
+	/**
+	 * @brief get uid of the owners of the file and the path to the file
+	 * @param $path Path of the file to check
+	 * @note $shareFilePath must be relative to data/UID/files. Files 
+	 *       relative to /Shared are also acceptable
+	 * @return array
+	 */
+	public function getUidAndFilename( $path ) {
+
+        $view = new \OC\Files\View($this->userFilesDir);
+		$fileOwnerUid = $view->getOwner( $path );
+
+        // handle public access
+        if($fileOwnerUid === false && $this->isPublic) {
+            $filename = $path;
+            $fileOwnerUid = $GLOBALS['fileOwner'];
+
+            return array ( $fileOwnerUid, $filename );
+        } else {
+
+            // Check that UID is valid
+            if ( ! \OCP\User::userExists( $fileOwnerUid ) ) {
+                throw new \Exception( 'Could not find owner (UID = "' . var_export( $fileOwnerUid, 1 ) . '") of file "' . $path . '"' );
+            }
+
+            // NOTE: Bah, this dependency should be elsewhere
+            \OC\Files\Filesystem::initMountPoints( $fileOwnerUid );
+
+            // If the file owner is the currently logged in user
+            if ( $fileOwnerUid == $this->userId ) {
+
+                // Assume the path supplied is correct
+                $filename = $path;
+
+            } else {
+
+                $info = $view->getFileInfo( $path );
+                $ownerView = new \OC\Files\View( '/' . $fileOwnerUid . '/files' );
+
+                // Fetch real file path from DB
+                $filename = $ownerView->getPath( $info['fileid'] ); // TODO: Check that this returns a path without including the user data dir
+
+            }
+
+            // Make path relative for use by $view
+            $relpath = \OC\Files\Filesystem::normalizePath($fileOwnerUid . '/' . $this->fileFolderName . '/' . $filename);
+
+            // Check that the filename we're using is working
+            if ( $this->view->file_exists( $relpath ) ) {
+
+                return array ( $fileOwnerUid, $filename );
+
+            } else {
+
+                return false;
+
+            }
+        }
+
 		
 	}
 
@@ -891,19 +1156,130 @@ class Util {
 	 * @param type $dir relative to the users files folder
 	 * @return array with list of files relative to the users files folder
 	 */
-	public function getAllFiles($dir) {
+	public function getAllFiles( $dir ) {
+	
 		$result = array();
+
+		$content = $this->view->getDirectoryContent( $this->userFilesDir . $dir );
+
+		// handling for re shared folders
+		$path_split = explode( '/', $dir );
+		$shared = '';
+		
+		if( $path_split[1] === 'Shared' ) {
 		
-		$content = $this->view->getDirectoryContent($this->userFilesDir.$dir);
+			$shared = '/Shared';
+			
+		}
+
+		foreach ( $content as $c ) {
+		
+			$sharedPart = $path_split[sizeof( $path_split )-1];
+			$targetPathSplit = array_reverse( explode( '/', $c['path'] ) );
+
+			$path = '';
+
+			// rebuild path
+			foreach ( $targetPathSplit as $pathPart ) {
+			
+				if ( $pathPart !== $sharedPart ) {
+				
+					$path = '/' . $pathPart . $path;
+				
+				} else {
+				
+					break;
+				
+				}
+				
+			}
+
+			$path = $dir.$path;
 
-		foreach ($content as $c) {
 			if ($c['type'] === "dir" ) {
-				$result = array_merge($result, $this->getAllFiles(substr($c['path'],5)));
+				
+				$result = array_merge( $result, $this->getAllFiles( $path ) );
+			
 			} else {
-				$result[] = substr($c['path'], 5);
+			
+				$result[] = $path;
+			
 			}
 		}
+		
 		return $result;
+	
 	}
 
+	/**
+	 * @brief get shares parent.
+	 * @param int $id of the current share
+	 * @return array of the parent
+	 */
+	public static function getShareParent( $id ) {
+
+		$query = \OC_DB::prepare( 'SELECT `file_target`, `item_type`'
+		.' FROM `*PREFIX*share`'
+		.' WHERE `id` = ?' );
+
+		$result = $query->execute( array( $id ) );
+
+		$row = $result->fetchRow();
+
+		return $row;
+
+	}
+
+	/**
+	 * @brief get owner of the shared files.
+	 * @param int $Id of a share
+	 * @return owner
+	 */
+	public function getOwnerFromSharedFile( $id ) {
+	
+		$query = \OC_DB::prepare( 'SELECT `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `id` = ?', 1 );
+		$source = $query->execute( array( $id ) )->fetchRow();
+
+		if ( isset($source['parent'] ) ) {
+		
+			$parent = $source['parent'];
+			
+			while ( isset( $parent ) ) {
+			
+				$query = \OC_DB::prepare( 'SELECT `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `id` = ?', 1 );
+				$item = $query->execute( array( $parent ) )->fetchRow();
+				
+				if ( isset( $item['parent'] ) ) {
+				
+					$parent = $item['parent'];
+				
+				} else {
+				
+					$fileOwner = $item['uid_owner'];
+					
+					break;
+				
+				}
+			}
+			
+		} else {
+			
+			$fileOwner = $source['uid_owner'];
+			
+		}
+
+		return $fileOwner;
+		
+	}
+
+    public function getUserId()
+    {
+        return $this->userId;
+    }
+
+    public function getUserFilesDir()
+    {
+        return $this->userFilesDir;
+    }
+
 }
diff --git a/apps/files_encryption/settings.php b/apps/files_encryption/settings-admin.php
similarity index 61%
rename from apps/files_encryption/settings.php
rename to apps/files_encryption/settings-admin.php
index 71d47f061afa78de426c5d831fd01870df52fe70..ae9a85643effc640158494c803d3cd01689cffbb 100644
--- a/apps/files_encryption/settings.php
+++ b/apps/files_encryption/settings-admin.php
@@ -8,20 +8,22 @@
 
 \OC_Util::checkAdminUser();
 
-$tmpl = new OCP\Template( 'files_encryption', 'settings' );
+$tmpl = new OCP\Template( 'files_encryption', 'settings-admin' );
 
 $blackList = explode( ',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', '' ) );
 
 // Check if an adminRecovery account is enabled for recovering files after lost pwd
 $view = new OC_FilesystemView( '' );
-$util = new \OCA\Encryption\Util( $view, \OCP\USER::getUser() );
-$recoveryEnabled = $util->recoveryEnabled();
+
+$recoveryAdminEnabled = OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' );
+$recoveryAdminUid = OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminUid' );
 
 $tmpl->assign( 'blacklist', $blackList );
 $tmpl->assign( 'encryption_mode', \OC_Appconfig::getValue( 'files_encryption', 'mode', 'none' ) );
-$tmpl->assign( 'recoveryEnabled', $recoveryEnabled );
+$tmpl->assign( 'recoveryEnabled', $recoveryAdminEnabled );
+$tmpl->assign( 'recoveryAdminUid', $recoveryAdminUid );
 
-\OCP\Util::addscript( 'files_encryption', 'settings' );
+\OCP\Util::addscript( 'files_encryption', 'settings-admin' );
 \OCP\Util::addscript( 'core', 'multiselect' );
 
 return $tmpl->fetchPage();
diff --git a/apps/files_encryption/settings-personal.php b/apps/files_encryption/settings-personal.php
index c001bb0d72522a97b25f25a4ea346ee1b8f54580..46efb61b0298eb6a0d62d1bd4f0c9139d2256600 100644
--- a/apps/files_encryption/settings-personal.php
+++ b/apps/files_encryption/settings-personal.php
@@ -6,10 +6,35 @@
  * See the COPYING-README file.
  */
 
+// Add CSS stylesheet
+\OC_Util::addStyle( 'files_encryption', 'settings-personal' );
+ 
 $tmpl = new OCP\Template( 'files_encryption', 'settings-personal');
 
 $blackList = explode( ',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', '' ) );
 
+// Add human readable message in case nothing is blacklisted
+if ( 
+	1 == count( $blackList )
+	&& $blackList[0] == ''
+) {
+	
+	// FIXME: Make this string translatable
+	$blackList[0] = "(None - all filetypes will be encrypted)";
+
+}
+
+$user = \OCP\USER::getUser();
+$view = new \OC_FilesystemView( '/' );
+$util = new \OCA\Encryption\Util( $view, $user );
+
+$recoveryAdminEnabled = OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' );
+$recoveryEnabledForUser = $util->recoveryEnabledForUser();
+
+\OCP\Util::addscript( 'files_encryption', 'settings-personal' );
+
+$tmpl->assign( 'recoveryEnabled', $recoveryAdminEnabled );
+$tmpl->assign( 'recoveryEnabledForUser', $recoveryEnabledForUser );
 $tmpl->assign( 'blacklist', $blackList );
 
 return $tmpl->fetchPage();
diff --git a/apps/files_encryption/templates/settings.php b/apps/files_encryption/templates/settings-admin.php
similarity index 54%
rename from apps/files_encryption/templates/settings.php
rename to apps/files_encryption/templates/settings-admin.php
index 6499d0c8e80657d9a3ec32bbae4758cec9efd453..be7beecf6966cef4017af166f6eb5bad1e7f97e4 100644
--- a/apps/files_encryption/templates/settings.php
+++ b/apps/files_encryption/templates/settings-admin.php
@@ -4,22 +4,16 @@
 		<p>
 			<strong><?php p($l->t( 'Encryption' )); ?></strong>
 			<br />
-			
-			<?php p($l->t( "Exclude the following file types from encryption:" )); ?>
-			<br />
-			
-			<select 
-			id='encryption_blacklist' 
-			title="<?php p($l->t( 'None' ))?>" 
-			multiple="multiple">
-			<?php foreach($_["blacklist"] as $type): ?>
-				<option selected="selected" value="<?php p($type); ?>"> <?php p($type); ?> </option>
-			<?php endforeach;?>
-			</select>
 		</p>
 		<p>
-			<?php p($l->t( "Enable encryption passwords recovery account (allow sharing to recovery account):" )); ?>
+			<?php p($l->t( "Enable encryption passwords recovery key (allow sharing to recovery key):" )); ?>
+			<br />
 			<br />
+			<?php if ( empty( $_['recoveryAdminUid'] ) ): ?>
+				<input type="password" name="recoveryPassword" id="recoveryPassword" />
+				<label for="recoveryPassword">Recovery account password</label>
+				<br />
+			<?php endif; ?>
 			<input 
 			type='radio'
 			name='adminEnableRecovery'
diff --git a/apps/files_encryption/templates/settings-personal.php b/apps/files_encryption/templates/settings-personal.php
index 5f0accaed5fd960c3c6a2a08b3493f483148b841..00f567ecb2665c085453e2ebe5f520675b7691f4 100644
--- a/apps/files_encryption/templates/settings-personal.php
+++ b/apps/files_encryption/templates/settings-personal.php
@@ -1,15 +1,19 @@
 <form id="encryption">
 	<fieldset class="personalblock">
 		<legend>
-			<?php p($l->t( 'Encryption' )); ?>
+			<?php p( $l->t( 'Encryption' ) ); ?>
 		</legend>
+		
 		<p>
-			<?php p($l->t( 'File encryption is enabled.' )); ?>
+<!-- 			<?php p( $l->t( 'File encryption is enabled.' ) ); ?> -->
 		</p>
 		<?php if ( ! empty( $_["blacklist"] ) ): ?>
 		<p>
-			<?php p($l->t( 'The following file types will not be encrypted:' )); ?>
+			<strong>File types</strong>
+			<br />
+			<?php p( $l->t( 'The following file types will not be encrypted:' ) ); ?>
 		</p>
+		
 		<ul>
 			<?php foreach( $_["blacklist"] as $type ): ?>
 			<li>
@@ -18,5 +22,43 @@
 			<?php endforeach; ?>
 		</ul>
 		<?php endif; ?>
+		<br />
+		<?php if ( $_["recoveryEnabled"] ): ?>
+			<p>
+				<label for="userEnableRecovery"><?php p( $l->t( "Enable password recovery by sharing all files with administrator:" ) ); ?></label>
+				<br />
+				<em><?php p( $l->t( "Enabling this option will allow you to reobtain access to your encrypted files if your password is lost" ) ); ?></em>
+				<br />
+				<input 
+				type='radio'
+				name='userEnableRecovery'
+				value='1'
+				<?php echo ( $_["recoveryEnabledForUser"] == 1 ? 'checked="checked"' : '' ); ?> />
+				<?php p( $l->t( "Enabled" ) ); ?>
+				<br />
+				
+				<input 
+				type='radio'
+				name='userEnableRecovery'
+				value='0'
+				<?php echo ( $_["recoveryEnabledForUser"] == 0 ? 'checked="checked"' : '' ); ?> />
+				<?php p( $l->t( "Disabled" ) ); ?>
+				<div id="recoveryEnabledSuccess"><?php p( $l->t( 'File recovery settings updated' ) ); ?></div>
+				<div id="recoveryEnabledError"><?php p( $l->t( 'Could not update file recovery' ) ); ?></div>
+			</p>
+		<?php endif; ?>
+		<br />
+		<p>
+				<label for="encryptAll"><?php p( $l->t( "Scan for unencrypted files and encrypt them" ) ); ?></label>
+				<br />
+				<em><?php p( $l->t( "Use this if you suspect that you still have files which are unencrypted, or encrypted using ownCloud 4 or older." ) ); ?></em>
+				<br />
+				<input type="submit" id="encryptAll" name="encryptAll" value="<?php p( $l->t( 'Scan and encrypt files' ) ); ?>" />
+				<input type="password" name="userPassword" id="userPassword" />
+				<label for="encryptAll"><?php p( $l->t( "Account password" ) ); ?></label>
+				<div id="encryptAllSuccess"><?php p( $l->t( 'Scan complete' ) );?></div>
+				<div id="encryptAllError"><?php p( $l->t( 'Unable to scan and encrypt files' ) );?></div>
+		</p>
+		
 	</fieldset>
 </form>
diff --git a/apps/files_encryption/test/binary b/apps/files_encryption/tests/binary
similarity index 100%
rename from apps/files_encryption/test/binary
rename to apps/files_encryption/tests/binary
diff --git a/apps/files_encryption/test/crypt.php b/apps/files_encryption/tests/crypt.php
similarity index 75%
rename from apps/files_encryption/test/crypt.php
rename to apps/files_encryption/tests/crypt.php
index b02e63b2ffc667af9a055ec09cee428792c9e143..de7ae38b173e26e138c482cf11163587645c8ef0 100755
--- a/apps/files_encryption/test/crypt.php
+++ b/apps/files_encryption/tests/crypt.php
@@ -15,13 +15,13 @@ require_once realpath( dirname(__FILE__).'/../lib/keymanager.php' );
 require_once realpath( dirname(__FILE__).'/../lib/proxy.php' );
 require_once realpath( dirname(__FILE__).'/../lib/stream.php' );
 require_once realpath( dirname(__FILE__).'/../lib/util.php' );
+require_once realpath( dirname(__FILE__).'/../lib/helper.php' );
 require_once realpath( dirname(__FILE__).'/../appinfo/app.php' );
 
 use OCA\Encryption;
 
 // This has to go here because otherwise session errors arise, and the private 
 // encryption key needs to be saved in the session
-\OC_User::login( 'admin', 'admin' );
 
 /**
  * @note It would be better to use Mockery here for mocking out the session 
@@ -34,8 +34,11 @@ use OCA\Encryption;
 class Test_Crypt extends \PHPUnit_Framework_TestCase {
 	
 	function setUp() {
-		
-		// set content for encrypting / decrypting in tests
+        // reset backend
+        \OC_User::clearBackends();
+        \OC_User::useBackend('database');
+
+        // set content for encrypting / decrypting in tests
 		$this->dataLong = file_get_contents( realpath( dirname(__FILE__).'/../lib/crypt.php' ) );
 		$this->dataShort = 'hats';
 		$this->dataUrl = realpath( dirname(__FILE__).'/../lib/crypt.php' );
@@ -52,17 +55,32 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
 		\OC_User::setUserId( 'admin' );
 		$this->userId = 'admin';
 		$this->pass = 'admin';
-		
-		\OC_Filesystem::init( '/' );
-		\OC_Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => \OC_User::getHome($this->userId)), '/' );
-		
+
+        $userHome = \OC_User::getHome($this->userId);
+        $this->dataDir = str_replace('/'.$this->userId, '', $userHome);
+
+        // Filesystem related hooks
+        \OCA\Encryption\Helper::registerFilesystemHooks();
+
+        \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+        \OC_Util::tearDownFS();
+        \OC_User::setUserId('');
+        \OC\Files\Filesystem::setView(false);
+        \OC_Util::setupFS($this->userId);
+        \OC_User::setUserId($this->userId);
+
+        $params['uid'] = $this->userId;
+        $params['password'] = $this->pass;
+        OCA\Encryption\Hooks::login($params);
+
 	}
 	
 	function tearDown() {
-	
-	}
 
-	function testGenerateKey() {
+    }
+
+    function testGenerateKey() {
 	
 		# TODO: use more accurate (larger) string length for test confirmation
 		
@@ -220,40 +238,53 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
 // 		
 // 	}
 	
-	function testSymmetricStreamEncryptShortFileContent() { 
-		
-		$filename = 'tmp-'.time();
+	function testSymmetricStreamEncryptShortFileContent() {
 		
+		$filename = 'tmp-'.time().'.test';
+
 		$cryptedFile = file_put_contents( 'crypt://' . $filename, $this->dataShort );
 		
 		// Test that data was successfully written
 		$this->assertTrue( is_int( $cryptedFile ) );
-		
-		
-		// Get file contents without using any wrapper to get it's actual contents on disk
-		$retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename );
-		
+
+        // Disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        // Get file contents without using any wrapper to get it's actual contents on disk
+        $retreivedCryptedFile = $this->view->file_get_contents($this->userId . '/files/' . $filename);
+
+        // Re-enable proxy - our work is done
+        \OC_FileProxy::$enabled = $proxyStatus;
+
 		// Check that the file was encrypted before being written to disk
 		$this->assertNotEquals( $this->dataShort, $retreivedCryptedFile );
-		
-		// Get private key
-		$encryptedPrivateKey = Encryption\Keymanager::getPrivateKey( $this->view, $this->userId );
-		
-		$decryptedPrivateKey = Encryption\Crypt::symmetricDecryptFileContent( $encryptedPrivateKey, $this->pass );
-		
-		
-		// Get keyfile
-		$encryptedKeyfile = Encryption\Keymanager::getFileKey( $this->view, $this->userId, $filename );
-		
-		$decryptedKeyfile = Encryption\Crypt::keyDecrypt( $encryptedKeyfile, $decryptedPrivateKey );
-		
-		
-		// Manually decrypt
-		$manualDecrypt = Encryption\Crypt::symmetricBlockDecryptFileContent( $retreivedCryptedFile, $decryptedKeyfile );
-		
+
+        // Get the encrypted keyfile
+        $encKeyfile = Encryption\Keymanager::getFileKey( $this->view, $this->userId, $filename );
+
+        // Attempt to fetch the user's shareKey
+        $shareKey = Encryption\Keymanager::getShareKey( $this->view, $this->userId, $filename );
+
+        // get session
+        $session = new Encryption\Session( $this->view );
+
+        // get private key
+        $privateKey = $session->getPrivateKey( $this->userId );
+
+        // Decrypt keyfile with shareKey
+        $plainKeyfile = Encryption\Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
+
+        // Manually decrypt
+        $manualDecrypt = Encryption\Crypt::symmetricDecryptFileContent( $retreivedCryptedFile, $plainKeyfile );
+
 		// Check that decrypted data matches
 		$this->assertEquals( $this->dataShort, $manualDecrypt );
-		
+
+        // Teardown
+        $this->view->unlink( $this->userId . '/files/' . $filename );
+
+        Encryption\Keymanager::deleteFileKey( $this->view, $this->userId, $filename );
 	}
 	
 	/**
@@ -265,7 +296,7 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
 	function testSymmetricStreamEncryptLongFileContent() {
 		
 		// Generate a a random filename
-		$filename = 'tmp-'.time();
+		$filename = 'tmp-'.time().'.test';
 		
 		// Save long data as encrypted file using stream wrapper
 		$cryptedFile = file_put_contents( 'crypt://' . $filename, $this->dataLong.$this->dataLong );
@@ -273,12 +304,18 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
 		// Test that data was successfully written
 		$this->assertTrue( is_int( $cryptedFile ) );
 		
-		// Get file contents without using any wrapper to get it's actual contents on disk
-		$retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename );
-		
-// 		echo "\n\n\$retreivedCryptedFile = $retreivedCryptedFile\n\n";
-		
-		// Check that the file was encrypted before being written to disk
+		// Disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        // Get file contents without using any wrapper to get it's actual contents on disk
+        $retreivedCryptedFile = $this->view->file_get_contents($this->userId . '/files/' . $filename);
+
+        // Re-enable proxy - our work is done
+        \OC_FileProxy::$enabled = $proxyStatus;
+
+
+        // Check that the file was encrypted before being written to disk
 		$this->assertNotEquals( $this->dataLong.$this->dataLong, $retreivedCryptedFile );
 		
 		// Manuallly split saved file into separate IVs and encrypted chunks
@@ -290,46 +327,42 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
 		$e = array( $r[0].$r[1], $r[2].$r[3], $r[4].$r[5], $r[6].$r[7], $r[8].$r[9], $r[10].$r[11], $r[12].$r[13] );//.$r[11], $r[12].$r[13], $r[14] );
 		
 		//print_r($e);
-		
-		
-		// Get private key
-		$encryptedPrivateKey = Encryption\Keymanager::getPrivateKey( $this->view, $this->userId );
-		
-		$decryptedPrivateKey = Encryption\Crypt::symmetricDecryptFileContent( $encryptedPrivateKey, $this->pass );
-		
-		
-		// Get keyfile
-		$encryptedKeyfile = Encryption\Keymanager::getFileKey( $this->view, $this->userId, $filename );
-		
-		$decryptedKeyfile = Encryption\Crypt::keyDecrypt( $encryptedKeyfile, $decryptedPrivateKey );
-		
-		
+
+        // Get the encrypted keyfile
+        $encKeyfile = Encryption\Keymanager::getFileKey( $this->view, $this->userId, $filename );
+
+        // Attempt to fetch the user's shareKey
+        $shareKey = Encryption\Keymanager::getShareKey( $this->view, $this->userId, $filename );
+
+        // get session
+        $session = new Encryption\Session( $this->view );
+
+        // get private key
+        $privateKey = $session->getPrivateKey( $this->userId );
+
+        // Decrypt keyfile with shareKey
+        $plainKeyfile = Encryption\Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
+
 		// Set var for reassembling decrypted content
 		$decrypt = '';
 		
 		// Manually decrypt chunk
 		foreach ($e as $e) {
-		
-// 			echo "\n\$e = $e";
 			
-			$chunkDecrypt = Encryption\Crypt::symmetricDecryptFileContent( $e, $decryptedKeyfile );
+			$chunkDecrypt = Encryption\Crypt::symmetricDecryptFileContent( $e, $plainKeyfile );
 			
 			// Assemble decrypted chunks
 			$decrypt .= $chunkDecrypt;
 			
-// 			echo "\n\$chunkDecrypt = $chunkDecrypt";
-			
 		}
 		
-// 		echo "\n\$decrypt = $decrypt";
-		
 		$this->assertEquals( $this->dataLong.$this->dataLong, $decrypt );
 		
 		// Teardown
 		
-		$this->view->unlink( $filename );
+		$this->view->unlink( $this->userId . '/files/' . $filename );
 		
-		Encryption\Keymanager::deleteFileKey( $filename );
+		Encryption\Keymanager::deleteFileKey( $this->view, $this->userId, $filename );
 		
 	}
 	
@@ -345,15 +378,14 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
 		
 		// Test that data was successfully written
 		$this->assertTrue( is_int( $cryptedFile ) );
-		
-		
-		// Get file contents without using any wrapper to get it's actual contents on disk
-		$retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename );
-		
-		$decrypt = file_get_contents( 'crypt://' . $filename );
+
+        // Get file decrypted contents
+        $decrypt = file_get_contents( 'crypt://' . $filename );
 		
 		$this->assertEquals( $this->dataShort, $decrypt );
-		
+
+        // tear down
+        $this->view->unlink( $this->userId . '/files/' . $filename );
 	}
 	
 	function testSymmetricStreamDecryptLongFileContent() {
@@ -365,15 +397,14 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
 		
 		// Test that data was successfully written
 		$this->assertTrue( is_int( $cryptedFile ) );
-		
-		
-		// Get file contents without using any wrapper to get it's actual contents on disk
-		$retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename );
-		
+
+        // Get file decrypted contents
 		$decrypt = file_get_contents( 'crypt://' . $filename );
-		
+
 		$this->assertEquals( $this->dataLong, $decrypt );
-		
+
+        // tear down
+        $this->view->unlink( $this->userId . '/files/' . $filename );
 	}
 	
 	// Is this test still necessary?
@@ -600,6 +631,65 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
 		
 	}
 
+    function testRenameFile() {
+
+        $filename = 'tmp-'.time();
+
+        // Save long data as encrypted file using stream wrapper
+        $cryptedFile = file_put_contents( 'crypt://' . $filename, $this->dataLong );
+
+        // Test that data was successfully written
+        $this->assertTrue( is_int( $cryptedFile ) );
+
+        // Get file decrypted contents
+        $decrypt = file_get_contents( 'crypt://' . $filename );
+
+        $this->assertEquals( $this->dataLong, $decrypt );
+
+        $newFilename = 'tmp-new-'.time();
+        $view = new \OC\Files\View('/' . $this->userId . '/files');
+        $view->rename( $filename, $newFilename );
+
+        // Get file decrypted contents
+        $newDecrypt = file_get_contents( 'crypt://' . $newFilename );
+
+        $this->assertEquals( $this->dataLong, $newDecrypt );
+
+        // tear down
+        $view->unlink( $newFilename );
+    }
+
+    function testMoveFileIntoFolder() {
+
+        $filename = 'tmp-'.time();
+
+        // Save long data as encrypted file using stream wrapper
+        $cryptedFile = file_put_contents( 'crypt://' . $filename, $this->dataLong );
+
+        // Test that data was successfully written
+        $this->assertTrue( is_int( $cryptedFile ) );
+
+        // Get file decrypted contents
+        $decrypt = file_get_contents( 'crypt://' . $filename );
+
+        $this->assertEquals( $this->dataLong, $decrypt );
+
+        $newFolder = '/newfolder1';
+        $newFilename = 'tmp-new-'.time();
+        $view = new \OC\Files\View('/' . $this->userId . '/files');
+        $view->mkdir($newFolder);
+        $view->rename( $filename, $newFolder . '/' . $newFilename );
+
+        // Get file decrypted contents
+        $newDecrypt = file_get_contents( 'crypt://' . $newFolder . '/' . $newFilename );
+
+        $this->assertEquals( $this->dataLong, $newDecrypt );
+
+        // tear down
+        $view->unlink( $newFolder . '/' . $newFilename );
+        $view->unlink( $newFolder );
+    }
+
 // 	function testEncryption(){
 // 	
 // 		$key=uniqid();
diff --git a/apps/files_encryption/test/keymanager.php b/apps/files_encryption/tests/keymanager.php
similarity index 61%
rename from apps/files_encryption/test/keymanager.php
rename to apps/files_encryption/tests/keymanager.php
index bf453fe3163b8455136fc5b501beb451ba54c251..d24dcaa0360d7c3644605c8efb7378e9830cfbae 100644
--- a/apps/files_encryption/test/keymanager.php
+++ b/apps/files_encryption/tests/keymanager.php
@@ -13,18 +13,22 @@ require_once realpath( dirname(__FILE__).'/../lib/keymanager.php' );
 require_once realpath( dirname(__FILE__).'/../lib/proxy.php' );
 require_once realpath( dirname(__FILE__).'/../lib/stream.php' );
 require_once realpath( dirname(__FILE__).'/../lib/util.php' );
+require_once realpath( dirname(__FILE__).'/../lib/helper.php' );
 require_once realpath( dirname(__FILE__).'/../appinfo/app.php' );
 
 use OCA\Encryption;
 
 // This has to go here because otherwise session errors arise, and the private 
 // encryption key needs to be saved in the session
-\OC_User::login( 'admin', 'admin' );
+//\OC_User::login( 'admin', 'admin' );
 
 class Test_Keymanager extends \PHPUnit_Framework_TestCase {
 	
 	function setUp() {
-		
+        // reset backend
+        \OC_User::clearBackends();
+        \OC_User::useBackend('database');
+
 		\OC_FileProxy::$enabled = false;
 		
 		// set content for encrypting / decrypting in tests
@@ -38,16 +42,30 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase {
 		$keypair = Encryption\Crypt::createKeypair();
 		$this->genPublicKey =  $keypair['publicKey'];
 		$this->genPrivateKey = $keypair['privateKey'];
-		
-		$this->view = new \OC_FilesystemView( '/' );
-		
-		\OC_User::setUserId( 'admin' );
-		$this->userId = 'admin';
-		$this->pass = 'admin';
-		
-		\OC_Filesystem::init( '/' );
-		\OC_Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => \OC_User::getHome($this->userId)), '/' );
-	
+
+        $this->view = new \OC_FilesystemView( '/' );
+
+        \OC_User::setUserId( 'admin' );
+        $this->userId = 'admin';
+        $this->pass = 'admin';
+
+        $userHome = \OC_User::getHome($this->userId);
+        $this->dataDir = str_replace('/'.$this->userId, '', $userHome);
+
+        // Filesystem related hooks
+        \OCA\Encryption\Helper::registerFilesystemHooks();
+
+        \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+        \OC_Util::tearDownFS();
+        \OC_User::setUserId('');
+        \OC\Files\Filesystem::setView(false);
+        \OC_Util::setupFS($this->userId);
+        \OC_User::setUserId($this->userId);
+
+        $params['uid'] = $this->userId;
+        $params['password'] = $this->pass;
+        OCA\Encryption\Hooks::login($params);
 	}
 	
 	function tearDown(){
@@ -59,9 +77,13 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase {
 	function testGetPrivateKey() {
 	
 		$key = Encryption\Keymanager::getPrivateKey( $this->view, $this->userId );
-		 
+
+        $privateKey = Encryption\Crypt::symmetricDecryptFileContent( $key, $this->pass);
+
 		// Will this length vary? Perhaps we should use a range instead
-		$this->assertEquals( 2296, strlen( $key ) );
+		$this->assertGreaterThan( 27, strlen( $privateKey ) );
+
+        $this->assertEquals( '-----BEGIN PRIVATE KEY-----', substr( $privateKey, 0, 27 ) );
 	
 	}
 	
@@ -69,7 +91,7 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase {
 
 		$key = Encryption\Keymanager::getPublicKey( $this->view, $this->userId );
 		
-		$this->assertEquals( 451, strlen( $key ) );
+		$this->assertGreaterThan( 26, strlen( $key ) );
 		
 		$this->assertEquals( '-----BEGIN PUBLIC KEY-----', substr( $key, 0, 26 ) );
 	}
@@ -81,11 +103,19 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase {
 	
 		$key = Encryption\Crypt::symmetricEncryptFileContentKeyfile( $this->randomKey, 'hat' );
 		
-		$path = 'unittest-'.time().'txt';
-		
+		$file = 'unittest-'.time().'.txt';
+
+        // Disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        $this->view->file_put_contents($this->userId . '/files/' . $file, $key['encrypted']);
+
+        // Re-enable proxy - our work is done
+        \OC_FileProxy::$enabled = $proxyStatus;
+
 		//$view = new \OC_FilesystemView( '/' . $this->userId . '/files_encryption/keyfiles' );
-		
-		Encryption\Keymanager::setFileKey( $this->view, $path, $this->userId, $key['key'] );
+		Encryption\Keymanager::setFileKey( $this->view, $file, $this->userId, $key['key'] );
 	
 	}
 	
@@ -109,9 +139,15 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase {
 	
 		$keys = Encryption\Keymanager::getUserKeys( $this->view, $this->userId );
 		
-		$this->assertEquals( 451, strlen( $keys['publicKey'] ) );
+		$this->assertGreaterThan( 26, strlen( $keys['publicKey'] ) );
+
 		$this->assertEquals( '-----BEGIN PUBLIC KEY-----', substr( $keys['publicKey'], 0, 26 ) );
-		$this->assertEquals( 2296, strlen( $keys['privateKey'] ) );
+
+        $privateKey = Encryption\Crypt::symmetricDecryptFileContent( $keys['privateKey'], $this->pass);
+
+        $this->assertGreaterThan( 27, strlen( $keys['privateKey'] ) );
+
+        $this->assertEquals( '-----BEGIN PRIVATE KEY-----', substr( $privateKey, 0, 27 ) );
 	
 	}
 	
diff --git a/apps/files_encryption/test/legacy-encrypted-text.txt b/apps/files_encryption/tests/legacy-encrypted-text.txt
similarity index 100%
rename from apps/files_encryption/test/legacy-encrypted-text.txt
rename to apps/files_encryption/tests/legacy-encrypted-text.txt
diff --git a/apps/files_encryption/test/proxy.php b/apps/files_encryption/tests/proxy.php
similarity index 100%
rename from apps/files_encryption/test/proxy.php
rename to apps/files_encryption/tests/proxy.php
diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php
new file mode 100755
index 0000000000000000000000000000000000000000..e2e26aa75b53499c50309403b79526f62073461c
--- /dev/null
+++ b/apps/files_encryption/tests/share.php
@@ -0,0 +1,473 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Florin Peter
+ * @copyright 2013 Florin Peter <owncloud@florin-peter.de>
+ *
+ * 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/>.
+ *
+ */
+
+require_once realpath(dirname(__FILE__) . '/../../../3rdparty/Crypt_Blowfish/Blowfish.php');
+require_once realpath(dirname(__FILE__) . '/../../../lib/base.php');
+require_once realpath(dirname(__FILE__) . '/../lib/crypt.php');
+require_once realpath(dirname(__FILE__) . '/../lib/keymanager.php');
+require_once realpath(dirname(__FILE__) . '/../lib/proxy.php');
+require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
+require_once realpath(dirname(__FILE__) . '/../lib/util.php');
+require_once realpath(dirname(__FILE__) . '/../lib/helper.php');
+require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
+
+use OCA\Encryption;
+
+class Test_Encryption_Share extends \PHPUnit_Framework_TestCase
+{
+
+    function setUp()
+    {
+        // reset backend
+        \OC_User::clearBackends();
+        \OC_User::useBackend('database');
+
+        $this->dataShort = 'hats';
+        $this->view = new \OC_FilesystemView('/');
+
+        $userHome = \OC_User::getHome('admin');
+        $this->dataDir = str_replace('/admin', '', $userHome);
+
+        $this->folder1 = '/folder1';
+        $this->subfolder = '/subfolder1';
+        $this->subsubfolder = '/subsubfolder1';
+
+        $this->filename = 'share-tmp.test';
+
+        // enable resharing
+        \OC_Appconfig::setValue('core', 'shareapi_allow_resharing', 'yes');
+
+        // clear share hooks
+        \OC_Hook::clear('OCP\\Share');
+        \OC::registerShareHooks();
+        \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
+
+        // Sharing related hooks
+        \OCA\Encryption\Helper::registerShareHooks();
+
+        // Filesystem related hooks
+        \OCA\Encryption\Helper::registerFilesystemHooks();
+
+        \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+        // remember files_trashbin state
+        $this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
+
+        // we don't want to tests with app files_trashbin enabled
+        \OC_App::disable('files_trashbin');
+
+        // create users
+        $this->loginHelper('user1', true);
+        $this->loginHelper('user2', true);
+        $this->loginHelper('user3', true);
+    }
+
+    function tearDown()
+    {
+        // reset app files_trashbin
+        if ($this->stateFilesTrashbin) {
+            OC_App::enable('files_trashbin');
+        } else {
+            OC_App::disable('files_trashbin');
+        }
+
+        // cleanup users
+        \OC_User::deleteUser('user1');
+        \OC_User::deleteUser('user2');
+        \OC_User::deleteUser('user3');
+    }
+
+    function testShareFile($withTeardown = true)
+    {
+        // login as admin
+        $this->loginHelper('admin');
+
+        // save file with content
+        $cryptedFile = file_put_contents('crypt://' . $this->filename, $this->dataShort);
+
+        // test that data was successfully written
+        $this->assertTrue(is_int($cryptedFile));
+
+        // disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        // get the file info from previous created file
+        $fileInfo = $this->view->getFileInfo('/admin/files/' . $this->filename);
+
+        // check if we have a valid file info
+        $this->assertTrue(is_array($fileInfo));
+
+        // check if the unencrypted file size is stored
+        $this->assertGreaterThan(0, $fileInfo['unencrypted_size']);
+
+        // re-enable the file proxy
+        \OC_FileProxy::$enabled = $proxyStatus;
+
+        // share the file
+        \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user1', OCP\PERMISSION_ALL);
+
+        // login as admin
+        $this->loginHelper('admin');
+
+        // check if share key for user1 exists
+        $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.user1.shareKey'));
+
+        // login as user1
+        $this->loginHelper('user1');
+
+        // get file contents
+        $retrievedCryptedFile = $this->view->file_get_contents('/user1/files/Shared/' . $this->filename);
+
+        // check if data is the same as we previously written
+        $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+        // cleanup
+        if ($withTeardown) {
+
+            // login as admin
+            $this->loginHelper('admin');
+
+            // unshare the file
+            \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user1');
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.user1.shareKey'));
+
+            // cleanup
+            $this->view->unlink('/admin/files/' . $this->filename);
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.admin.shareKey'));
+        }
+    }
+
+    function testReShareFile($withTeardown = true)
+    {
+        $this->testShareFile(false);
+
+        // login as user1
+        $this->loginHelper('user1');
+
+        // get the file info
+        $fileInfo = $this->view->getFileInfo('/user1/files/Shared/' . $this->filename);
+
+        // share the file with user2
+        \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user2', OCP\PERMISSION_ALL);
+
+        // login as admin
+        $this->loginHelper('admin');
+
+        // check if share key for user2 exists
+        $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.user2.shareKey'));
+
+        // login as user2
+        $this->loginHelper('user2');
+
+        // get file contents
+        $retrievedCryptedFile = $this->view->file_get_contents('/user2/files/Shared/' . $this->filename);
+
+        // check if data is the same as previously written
+        $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+        // cleanup
+        if ($withTeardown) {
+
+            // login as user1
+            $this->loginHelper('user1');
+
+            // unshare the file with user2
+            \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user2');
+
+            // login as admin
+            $this->loginHelper('admin');
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.user2.shareKey'));
+
+            // unshare the file with user1
+            \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user1');
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.user1.shareKey'));
+
+            // cleanup
+            $this->view->unlink('/admin/files/' . $this->filename);
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.admin.shareKey'));
+        }
+    }
+
+    function testShareFolder($withTeardown = true)
+    {
+        // login as admin
+        $this->loginHelper('admin');
+
+        // create folder structure
+        $this->view->mkdir('/admin/files' . $this->folder1);
+        $this->view->mkdir('/admin/files' . $this->folder1 . $this->subfolder);
+        $this->view->mkdir('/admin/files' . $this->folder1 . $this->subfolder . $this->subsubfolder);
+
+        // save file with content
+        $cryptedFile = file_put_contents('crypt://' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename, $this->dataShort);
+
+        // test that data was successfully written
+        $this->assertTrue(is_int($cryptedFile));
+
+        // disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        // get the file info from previous created folder
+        $fileInfo = $this->view->getFileInfo('/admin/files' . $this->folder1);
+
+        // check if we have a valid file info
+        $this->assertTrue(is_array($fileInfo));
+
+        // re-enable the file proxy
+        \OC_FileProxy::$enabled = $proxyStatus;
+
+        // share the folder with user1
+        \OCP\Share::shareItem('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user1', OCP\PERMISSION_ALL);
+
+        // login as admin
+        $this->loginHelper('admin');
+
+        // check if share key for user1 exists
+        $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.user1.shareKey'));
+
+        // login as user1
+        $this->loginHelper('user1');
+
+        // get file contents
+        $retrievedCryptedFile = $this->view->file_get_contents('/user1/files/Shared' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
+
+        // check if data is the same
+        $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+        // cleanup
+        if ($withTeardown) {
+
+            // login as admin
+            $this->loginHelper('admin');
+
+            // unshare the folder with user1
+            \OCP\Share::unshare('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user1');
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.user1.shareKey'));
+
+            // cleanup
+            $this->view->unlink('/admin/files' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.admin.shareKey'));
+        }
+
+        return $fileInfo;
+    }
+
+    function testReShareFolder($withTeardown = true)
+    {
+        $fileInfoFolder1 = $this->testShareFolder(false);
+
+        // login as user1
+        $this->loginHelper('user1');
+
+        // disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        // get the file info from previous created folder
+        $fileInfoSubFolder = $this->view->getFileInfo('/user1/files/Shared' . $this->folder1 . $this->subfolder);
+
+        // check if we have a valid file info
+        $this->assertTrue(is_array($fileInfoSubFolder));
+
+        // re-enable the file proxy
+        \OC_FileProxy::$enabled = $proxyStatus;
+
+        // share the file with user2
+        \OCP\Share::shareItem('folder', $fileInfoSubFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user2', OCP\PERMISSION_ALL);
+
+        // login as admin
+        $this->loginHelper('admin');
+
+        // check if share key for user2 exists
+        $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.user2.shareKey'));
+
+        // login as user2
+        $this->loginHelper('user2');
+
+        // get file contents
+        $retrievedCryptedFile = $this->view->file_get_contents('/user2/files/Shared' . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
+
+        // check if data is the same
+        $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+        // get the file info
+        $fileInfo = $this->view->getFileInfo('/user2/files/Shared' . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
+
+        // check if we have fileInfos
+        $this->assertTrue(is_array($fileInfo));
+
+        // share the file with user3
+        \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user3', OCP\PERMISSION_ALL);
+
+        // login as admin
+        $this->loginHelper('admin');
+
+        // check if share key for user3 exists
+        $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.user3.shareKey'));
+
+        // login as user3
+        $this->loginHelper('user3');
+
+        // get file contents
+        $retrievedCryptedFile = $this->view->file_get_contents('/user3/files/Shared/' . $this->filename);
+
+        // check if data is the same
+        $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+        // cleanup
+        if ($withTeardown) {
+
+            // login as user2
+            $this->loginHelper('user2');
+
+            // unshare the file with user3
+            \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user3');
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.user3.shareKey'));
+
+            // login as user1
+            $this->loginHelper('user1');
+
+            // unshare the folder with user2
+            \OCP\Share::unshare('folder', $fileInfoSubFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user2');
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.user2.shareKey'));
+
+            // login as admin
+            $this->loginHelper('admin');
+
+            // unshare the folder1 with user1
+            \OCP\Share::unshare('folder', $fileInfoFolder1['fileid'], \OCP\Share::SHARE_TYPE_USER, 'user1');
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.user1.shareKey'));
+
+            // cleanup
+            $this->view->unlink('/admin/files' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
+
+            // check if share key not exists
+            $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.admin.shareKey'));
+        }
+    }
+
+    function testPublicShareFile()
+    {
+        // login as admin
+        $this->loginHelper('admin');
+
+        // save file with content
+        $cryptedFile = file_put_contents('crypt://' . $this->filename, $this->dataShort);
+
+        // test that data was successfully written
+        $this->assertTrue(is_int($cryptedFile));
+
+        // disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        // get the file info from previous created file
+        $fileInfo = $this->view->getFileInfo('/admin/files/' . $this->filename);
+
+        // check if we have a valid file info
+        $this->assertTrue(is_array($fileInfo));
+
+        // check if the unencrypted file size is stored
+        $this->assertGreaterThan(0, $fileInfo['unencrypted_size']);
+
+        // re-enable the file proxy
+        \OC_FileProxy::$enabled = $proxyStatus;
+
+        // share the file
+        \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null, false);
+
+        // login as admin
+        $this->loginHelper('admin');
+
+        $publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId');
+
+        // check if share key for public exists
+        $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.' . $publicShareKeyId . '.shareKey'));
+
+        // some hacking to simulate public link
+        $GLOBALS['app'] = 'files_sharing';
+        $GLOBALS['fileOwner'] = 'admin';
+        \OC_User::setUserId('');
+
+        // get file contents
+        $retrievedCryptedFile = file_get_contents('crypt://' . $this->filename);
+
+        // check if data is the same as we previously written
+        $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+        // tear down
+
+        // login as admin
+        $this->loginHelper('admin');
+
+        // unshare the file
+        \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null);
+
+        // check if share key not exists
+        $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.' . $publicShareKeyId . '.shareKey'));
+
+        // cleanup
+        $this->view->unlink('/admin/files/' . $this->filename);
+
+        // check if share key not exists
+        $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.admin.shareKey'));
+    }
+
+    function loginHelper($user, $create = false)
+    {
+        if ($create) {
+            \OC_User::createUser($user, $user);
+        }
+
+        \OC_Util::tearDownFS();
+        \OC_User::setUserId('');
+        \OC\Files\Filesystem::setView(false);
+        \OC_Util::setupFS($user);
+        \OC_User::setUserId($user);
+
+        $params['uid'] = $user;
+        $params['password'] = $user;
+        OCA\Encryption\Hooks::login($params);
+    }
+}
diff --git a/apps/files_encryption/test/stream.php b/apps/files_encryption/tests/stream.php
similarity index 99%
rename from apps/files_encryption/test/stream.php
rename to apps/files_encryption/tests/stream.php
index ba82ac80eabb17dc16d01dce0d61d0f042c8a1b0..633cc9e4fce726d7f65a851b1b3fbce1378ba3b0 100644
--- a/apps/files_encryption/test/stream.php
+++ b/apps/files_encryption/tests/stream.php
@@ -1,4 +1,4 @@
-// <?php
+<?php
 // /**
 //  * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
 //  * This file is licensed under the Affero General Public License version 3 or
diff --git a/apps/files_encryption/test/util.php b/apps/files_encryption/tests/util.php
similarity index 74%
rename from apps/files_encryption/test/util.php
rename to apps/files_encryption/tests/util.php
index 3ebc484809b430176a4da5f3d052ee8ad132375e..2abf4096902810944d902f38718092d4f640af04 100755
--- a/apps/files_encryption/test/util.php
+++ b/apps/files_encryption/tests/util.php
@@ -24,24 +24,23 @@ $loader->register();
 use \Mockery as m;
 use OCA\Encryption;
 
-\OC_User::login( 'admin', 'admin' );
-
 class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
 	
 	function setUp() {
-	
-		\OC_Filesystem::mount( 'OC_Filestorage_Local', array(), '/' );
-		
-		// set content for encrypting / decrypting in tests
+        // reset backend
+        \OC_User::useBackend('database');
+
+        \OC_User::setUserId( 'admin' );
+        $this->userId = 'admin';
+        $this->pass = 'admin';
+
+        // set content for encrypting / decrypting in tests
 		$this->dataUrl = realpath( dirname(__FILE__).'/../lib/crypt.php' );
 		$this->dataShort = 'hats';
 		$this->dataLong = file_get_contents( realpath( dirname(__FILE__).'/../lib/crypt.php' ) );
 		$this->legacyData = realpath( dirname(__FILE__).'/legacy-text.txt' );
 		$this->legacyEncryptedData = realpath( dirname(__FILE__).'/legacy-encrypted-text.txt' );
-		
-		$this->userId = 'admin';
-		$this->pass = 'admin';
-		
+
 		$keypair = Encryption\Crypt::createKeypair();
 		
 		$this->genPublicKey =  $keypair['publicKey'];
@@ -52,11 +51,29 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
 		$this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
 		$this->publicKeyPath = $this->publicKeyDir . '/' . $this->userId . '.public.key'; // e.g. data/public-keys/admin.public.key
 		$this->privateKeyPath = $this->encryptionDir . '/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key
-		
-		$this->view = new \OC_FilesystemView( '/' );
-		
-		$this->mockView = m::mock('OC_FilesystemView');
-		$this->util = new Encryption\Util( $this->mockView, $this->userId );
+
+        $this->view = new \OC_FilesystemView( '/' );
+
+        $userHome = \OC_User::getHome($this->userId);
+        $this->dataDir = str_replace('/'.$this->userId, '', $userHome);
+
+        // Filesystem related hooks
+        \OCA\Encryption\Helper::registerFilesystemHooks();
+
+        \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+        \OC_Util::tearDownFS();
+        \OC_User::setUserId('');
+        \OC\Files\Filesystem::setView(false);
+        \OC_Util::setupFS($this->userId);
+        \OC_User::setUserId($this->userId);
+
+        $params['uid'] = $this->userId;
+        $params['password'] = $this->pass;
+        OCA\Encryption\Hooks::login($params);
+
+		$mockView = m::mock('OC_FilesystemView');
+		$this->util = new Encryption\Util( $mockView, $this->userId );
 	
 	}
 	
@@ -68,6 +85,9 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
 	
 	/**
 	 * @brief test that paths set during User construction are correct
+     *
+     *
+     *
 	 */
 	function testKeyPaths() {
 	
@@ -90,8 +110,8 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
 	
 		$mockView = m::mock('OC_FilesystemView');
 		
-		$mockView->shouldReceive( 'file_exists' )->times(5)->andReturn( false );
-		$mockView->shouldReceive( 'mkdir' )->times(4)->andReturn( true );
+		$mockView->shouldReceive( 'file_exists' )->times(7)->andReturn( false );
+		$mockView->shouldReceive( 'mkdir' )->times(6)->andReturn( true );
 		$mockView->shouldReceive( 'file_put_contents' )->withAnyArgs();
 		
 		$util = new Encryption\Util( $mockView, $this->userId );
@@ -107,7 +127,7 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
 	
 		$mockView = m::mock('OC_FilesystemView');
 		
-		$mockView->shouldReceive( 'file_exists' )->times(6)->andReturn( true );
+		$mockView->shouldReceive( 'file_exists' )->times(8)->andReturn( true );
 		$mockView->shouldReceive( 'file_put_contents' )->withAnyArgs();
 		
 		$util = new Encryption\Util( $mockView, $this->userId );
@@ -141,7 +161,7 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
 	
 		$mockView = m::mock('OC_FilesystemView');
 		
-		$mockView->shouldReceive( 'file_exists' )->times(3)->andReturn( true );
+		$mockView->shouldReceive( 'file_exists' )->times(5)->andReturn( true );
 		
 		$util = new Encryption\Util( $mockView, $this->userId );
 		
@@ -158,43 +178,57 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
 
 		$util = new Encryption\Util( $this->view, $this->userId );
 		
-		$files = $util->findEncFiles( '/', 'encrypted' );
+		$files = $util->findEncFiles( '/'.$this->userId.'/');
 		
-		var_dump( $files );
+		//var_dump( $files );
 		
 		# TODO: Add more tests here to check that if any of the dirs are 
 		# then false will be returned. Use strict ordering?
 		
 	}
 	
-	function testRecoveryEnabled() {
+	function testRecoveryEnabledForUser() {
 		
 		$util = new Encryption\Util( $this->view, $this->userId );
 		
 		// Record the value so we can return it to it's original state later
-		$enabled = $util->recoveryEnabled();
+		$enabled = $util->recoveryEnabledForUser();
 		
-		$this->assertTrue( $util->setRecovery( 1 ) );
+		$this->assertTrue( $util->setRecoveryForUser( 1 ) );
 		
-		$this->assertEquals( 1, $util->recoveryEnabled() );
+		$this->assertEquals( 1, $util->recoveryEnabledForUser() );
 		
-		$this->assertTrue( $util->setRecovery( 0 ) );
+		$this->assertTrue( $util->setRecoveryForUser( 0 ) );
 		
-		$this->assertEquals( 0, $util->recoveryEnabled() );
+		$this->assertEquals( 0, $util->recoveryEnabledForUser() );
 		
 		// Return the setting to it's previous state
-		$this->assertTrue( $util->setRecovery( $enabled ) );
+		$this->assertTrue( $util->setRecoveryForUser( $enabled ) );
 		
 	}
 	
 	function testGetUidAndFilename() {
 	
 		\OC_User::setUserId( 'admin' );
-		
-		$this->util->getUidAndFilename( 'test1.txt' );
-		
-		
-	
+
+        $filename = 'tmp-'.time().'.test';
+
+        // Disable encryption proxy to prevent recursive calls
+        $proxyStatus = \OC_FileProxy::$enabled;
+        \OC_FileProxy::$enabled = false;
+
+        $this->view->file_put_contents($this->userId . '/files/' . $filename, $this->dataShort);
+
+        // Re-enable proxy - our work is done
+        \OC_FileProxy::$enabled = $proxyStatus;
+
+        $util = new Encryption\Util( $this->view, $this->userId );
+
+        list($fileOwnerUid, $file) = $util->getUidAndFilename( $filename );
+
+        $this->assertEquals('admin', $fileOwnerUid);
+
+        $this->assertEquals($file, $filename);
 	}
 
 // 	/**
diff --git a/apps/files_encryption/test/zeros b/apps/files_encryption/tests/zeros
similarity index 100%
rename from apps/files_encryption/test/zeros
rename to apps/files_encryption/tests/zeros
diff --git a/apps/files_trashbin/l10n/bg_BG.php b/apps/files_trashbin/l10n/bg_BG.php
index 288518e1a41320914d5abee9cae4a70af6460318..31c5dcb4ef19470bb49004af6e990cac3ccb0e69 100644
--- a/apps/files_trashbin/l10n/bg_BG.php
+++ b/apps/files_trashbin/l10n/bg_BG.php
@@ -13,6 +13,5 @@
 "{count} files" => "{count} файла",
 "Nothing in here. Your trash bin is empty!" => "Няма нищо. Кофата е празна!",
 "Restore" => "Възтановяване",
-"Delete" => "Изтриване",
-"Deleted Files" => "Изтрити файлове"
+"Delete" => "Изтриване"
 );
diff --git a/apps/files_trashbin/l10n/id.php b/apps/files_trashbin/l10n/id.php
index 62a63d515a3749ac279aa642c8132f22d0a1da05..e06c66784f24d3820d532363813db331986d9da2 100644
--- a/apps/files_trashbin/l10n/id.php
+++ b/apps/files_trashbin/l10n/id.php
@@ -2,13 +2,13 @@
 "Couldn't delete %s permanently" => "Tidak dapat menghapus permanen %s",
 "Couldn't restore %s" => "Tidak dapat memulihkan %s",
 "perform restore operation" => "jalankan operasi pemulihan",
-"Error" => "Galat",
+"Error" => "kesalahan",
 "delete file permanently" => "hapus berkas secara permanen",
-"Delete permanently" => "Hapus secara permanen",
+"Delete permanently" => "hapus secara permanen",
 "Name" => "Nama",
 "Deleted" => "Dihapus",
-"1 folder" => "1 folder",
-"{count} folders" => "{count} folder",
+"1 folder" => "1 map",
+"{count} folders" => "{count} map",
 "1 file" => "1 berkas",
 "{count} files" => "{count} berkas",
 "Nothing in here. Your trash bin is empty!" => "Tempat sampah anda kosong!",
diff --git a/apps/files_trashbin/l10n/nn_NO.php b/apps/files_trashbin/l10n/nn_NO.php
index 8166a024e58de6b593dc849c70ad736f466fee7b..14345ddcc4d49bedbb37d3f547197fd7b8e048ed 100644
--- a/apps/files_trashbin/l10n/nn_NO.php
+++ b/apps/files_trashbin/l10n/nn_NO.php
@@ -1,10 +1,5 @@
 <?php $TRANSLATIONS = array(
 "Error" => "Feil",
-"Delete permanently" => "Slett for godt",
 "Name" => "Namn",
-"1 folder" => "1 mappe",
-"{count} folders" => "{count} mapper",
-"1 file" => "1 fil",
-"{count} files" => "{count} filer",
 "Delete" => "Slett"
 );
diff --git a/apps/files_trashbin/l10n/pl.php b/apps/files_trashbin/l10n/pl.php
index 5c9f558f11fd610ed79046a6cd880493f05e0a6d..7fd1ab21ecd61a9aef32bac14a90e076d52f5a64 100644
--- a/apps/files_trashbin/l10n/pl.php
+++ b/apps/files_trashbin/l10n/pl.php
@@ -8,9 +8,9 @@
 "Name" => "Nazwa",
 "Deleted" => "Usunięte",
 "1 folder" => "1 folder",
-"{count} folders" => "Ilość folderów: {count}",
+"{count} folders" => "{count} foldery",
 "1 file" => "1 plik",
-"{count} files" => "Ilość plików: {count}",
+"{count} files" => "{count} pliki",
 "Nothing in here. Your trash bin is empty!" => "Nic tu nie ma. Twój kosz jest pusty!",
 "Restore" => "Przywróć",
 "Delete" => "Usuń",
diff --git a/apps/files_trashbin/l10n/pt_PT.php b/apps/files_trashbin/l10n/pt_PT.php
index ba85158b70e1a4c3a098232f3e5595b5454409e5..7dfe610466b0db2e0c0c93e9ede41dacd655c8ab 100644
--- a/apps/files_trashbin/l10n/pt_PT.php
+++ b/apps/files_trashbin/l10n/pt_PT.php
@@ -13,6 +13,6 @@
 "{count} files" => "{count} ficheiros",
 "Nothing in here. Your trash bin is empty!" => "Não hà ficheiros. O lixo está vazio!",
 "Restore" => "Restaurar",
-"Delete" => "Eliminar",
+"Delete" => "Apagar",
 "Deleted Files" => "Ficheiros Apagados"
 );
diff --git a/apps/files_trashbin/l10n/ro.php b/apps/files_trashbin/l10n/ro.php
index 3af21b7e3f367ab670c38fa81358d1db4835668e..c03ef600f35ec122d787838f6c6491722b86381f 100644
--- a/apps/files_trashbin/l10n/ro.php
+++ b/apps/files_trashbin/l10n/ro.php
@@ -1,6 +1,5 @@
 <?php $TRANSLATIONS = array(
 "Error" => "Eroare",
-"Delete permanently" => "Stergere permanenta",
 "Name" => "Nume",
 "1 folder" => "1 folder",
 "{count} folders" => "{count} foldare",
diff --git a/apps/files_trashbin/l10n/sk_SK.php b/apps/files_trashbin/l10n/sk_SK.php
index 7cef36ef1c0805436aed68f7816bc32542f19f33..7203f4c75fcda5d8ec19f6af27c6d79955e4c1d5 100644
--- a/apps/files_trashbin/l10n/sk_SK.php
+++ b/apps/files_trashbin/l10n/sk_SK.php
@@ -5,7 +5,7 @@
 "Error" => "Chyba",
 "delete file permanently" => "trvalo zmazať súbor",
 "Delete permanently" => "Zmazať  trvalo",
-"Name" => "Názov",
+"Name" => "Meno",
 "Deleted" => "Zmazané",
 "1 folder" => "1 priečinok",
 "{count} folders" => "{count} priečinkov",
diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php
index 7fda855d0c2c2765192a73f71c85e6052da388b7..70df9e2426abbd220b70713372fda1471e65cc99 100644
--- a/apps/files_trashbin/lib/trash.php
+++ b/apps/files_trashbin/lib/trash.php
@@ -29,6 +29,17 @@ class Trashbin {
 	// unit: percentage; 50% of available disk space/quota
 	const DEFAULTMAXSIZE=50;
 
+	public static function getUidAndFilename($filename) {
+		$uid = \OC\Files\Filesystem::getOwner($filename);
+		\OC\Files\Filesystem::initMountPoints($uid);
+		if ( $uid != \OCP\User::getUser() ) {
+			$info = \OC\Files\Filesystem::getFileInfo($filename);
+			$ownerView = new \OC\Files\View('/'.$uid.'/files');
+			$filename = $ownerView->getPath($info['fileid']);
+		}
+		return array($uid, $filename);
+	}
+
 	/**
 	 * move file to the trash bin
 	 *
@@ -62,8 +73,12 @@ class Trashbin {
 		if ( $trashbinSize === false || $trashbinSize < 0 ) {
 			$trashbinSize = self::calculateSize(new \OC\Files\View('/'. $user.'/files_trashbin'));
 		}
-		
+
+		// disable proxy to prevent recursive calls
+		$proxyStatus = \OC_FileProxy::$enabled;
+		\OC_FileProxy::$enabled = false;
 		$sizeOfAddedFiles = self::copy_recursive($file_path, 'files_trashbin/files/'.$filename.'.d'.$timestamp, $view);
+		\OC_FileProxy::$enabled = $proxyStatus;
 
 		if ( $view->file_exists('files_trashbin/files/'.$filename.'.d'.$timestamp) ) {
 			$trashbinSize += $sizeOfAddedFiles;
@@ -110,13 +125,17 @@ class Trashbin {
             \OC_FileProxy::$enabled = false;
 
             $user = \OCP\User::getUser();
-			if ($view->is_dir('files_versions/' . $file_path)) {
-                $size += self::calculateSize(new \OC\Files\View('/' . $user . '/files_versions/' . $file_path));
-                $view->rename('files_versions/' . $file_path, 'files_trashbin/versions/' . $filename . '.d' . $timestamp);
-			} else if ($versions = \OCA\Files_Versions\Storage::getVersions($user, $file_path)) {
+			$rootView = new \OC\Files\View('/');
+
+			list($owner, $ownerPath) = self::getUidAndFilename($file_path);
+
+			if ($rootView->is_dir($owner.'/files_versions/' . $ownerPath)) {
+                $size += self::calculateSize(new \OC\Files\View('/' . $owner . '/files_versions/' . $ownerPath));
+                $rootView->rename($owner.'/files_versions/' . $ownerPath, $user.'/files_trashbin/versions/' . $filename . '.d' . $timestamp);
+			} else if ($versions = \OCA\Files_Versions\Storage::getVersions($owner, $ownerPath)) {
                 foreach ($versions as $v) {
-					$size += $view->filesize('files_versions' . $v['path'] . '.v' . $v['version']);
-                	$view->rename('files_versions' . $v['path'] . '.v' . $v['version'], 'files_trashbin/versions/' . $filename . '.v' . $v['version'] . '.d' . $timestamp);
+					$size += $rootView->filesize($owner.'/files_versions' . $v['path'] . '.v' . $v['version']);
+                	$rootView->rename($owner.'/files_versions' . $v['path'] . '.v' . $v['version'], $user.'/files_trashbin/versions/' . $filename . '.v' . $v['version'] . '.d' . $timestamp);
 				}
 			}
 
@@ -143,35 +162,38 @@ class Trashbin {
 		if (\OCP\App::isEnabled('files_encryption')) {
 
 			$user = \OCP\User::getUser();
+			$rootView = new \OC\Files\View('/');
+
+			list($owner, $ownerPath) = self::getUidAndFilename($file_path);
+
 
             // disable proxy to prevent recursive calls
             $proxyStatus = \OC_FileProxy::$enabled;
             \OC_FileProxy::$enabled = false;
 
             // retain key files
-			$keyfile = \OC\Files\Filesystem::normalizePath('files_encryption/keyfiles/' . $file_path);
+			$keyfile = \OC\Files\Filesystem::normalizePath($owner.'/files_encryption/keyfiles/' . $ownerPath);
 
-            if ($view->is_dir($keyfile) || $view->file_exists($keyfile . '.key')) {
-            	$user = \OCP\User::getUser();
+            if ($rootView->is_dir($keyfile) || $rootView->file_exists($keyfile . '.key')) {
                 // move keyfiles
-			    if ($view->is_dir($keyfile)) {
-                    $size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . $keyfile));
-					$view->rename($keyfile, 'files_trashbin/keyfiles/' . $filename . '.d' . $timestamp);
+			    if ($rootView->is_dir($keyfile)) {
+                    $size += self::calculateSize(new \OC\Files\View($keyfile));
+					$rootView->rename($keyfile, $user.'/files_trashbin/keyfiles/' . $filename . '.d' . $timestamp);
 				} else {
-					$size += $view->filesize($keyfile . '.key');
-            		$view->rename($keyfile . '.key', 'files_trashbin/keyfiles/' . $filename . '.key.d' . $timestamp);
+					$size += $rootView->filesize($keyfile . '.key');
+            		$rootView->rename($keyfile . '.key', $user.'/files_trashbin/keyfiles/' . $filename . '.key.d' . $timestamp);
 				}
 			}
 
             // retain share keys
-			$sharekeys = \OC\Files\Filesystem::normalizePath('files_encryption/share-keys/' . $file_path);
+			$sharekeys = \OC\Files\Filesystem::normalizePath($owner.'/files_encryption/share-keys/' . $ownerPath);
 
-			if ($view->is_dir($sharekeys)) {
-				$size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . $sharekeys));
-				$view->rename($sharekeys, 'files_trashbin/share-keys/' . $filename . '.d' . $timestamp);
+			if ($rootView->is_dir($sharekeys)) {
+				$size += self::calculateSize(new \OC\Files\View($sharekeys));
+				$rootView->rename($sharekeys, $user.'/files_trashbin/share-keys/' . $filename . '.d' . $timestamp);
 			} else {
                 // get local path to share-keys
-                $localShareKeysPath = $view->getLocalFile($sharekeys);
+                $localShareKeysPath = $rootView->getLocalFile($sharekeys);
 
                 // handle share-keys
                 $matches = glob(preg_quote($localShareKeysPath).'*.shareKey');
@@ -186,10 +208,10 @@ class Trashbin {
                     if($pathinfo['basename'] == $ownerShareKey) {
 
                         // calculate size
-                        $size += $view->filesize($sharekeys. '.' . $user. '.shareKey');
+                        $size += $rootView->filesize($sharekeys. '.' . $user. '.shareKey');
 
                         // move file
-                        $view->rename($sharekeys. '.' . $user. '.shareKey', 'files_trashbin/share-keys/' . $ownerShareKey . '.d' . $timestamp);
+                        $rootView->rename($sharekeys. '.' . $user. '.shareKey', $user.'/files_trashbin/share-keys/' . $ownerShareKey . '.d' . $timestamp);
                     } else {
 
                         // calculate size
@@ -321,6 +343,12 @@ class Trashbin {
             \OC_FileProxy::$enabled = false;
 
             $user = \OCP\User::getUser();
+			$rootView = new \OC\Files\View('/');
+
+			$target = \OC\Files\Filesystem::normalizePath('/'.$location.'/'.$filename.$ext);
+
+			list($owner, $ownerPath) = self::getUidAndFilename($target);
+
 			if ($timestamp) {
 				$versionedFile = $filename;
 			} else {
@@ -329,15 +357,15 @@ class Trashbin {
 
             if ($view->is_dir('/files_trashbin/versions/'.$file)) {
 				$size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . 'files_trashbin/versions/' . $file));
-            	$view->rename(\OC\Files\Filesystem::normalizePath('files_trashbin/versions/' . $file), \OC\Files\Filesystem::normalizePath('files_versions/' . $location . '/' . $filename . $ext));
+            	$rootView->rename(\OC\Files\Filesystem::normalizePath($user.'/files_trashbin/versions/' . $file), \OC\Files\Filesystem::normalizePath($owner.'/files_versions/' . $ownerPath));
 			} else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp)) {
                 foreach ($versions as $v) {
             		if ($timestamp) {
             			$size += $view->filesize('files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp);
-                        $view->rename('files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, 'files_versions/' . $location . '/' . $filename . $ext . '.v' . $v);
+                        $rootView->rename($user.'/files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, $owner.'/files_versions/' . $ownerPath . '.v' . $v);
 					} else {
             			$size += $view->filesize('files_trashbin/versions/' . $versionedFile . '.v' . $v);
-						$view->rename('files_trashbin/versions/' . $versionedFile . '.v' . $v, 'files_versions/' . $location . '/' . $filename . $ext . '.v' . $v);
+						$rootView->rename($user.'/files_trashbin/versions/' . $versionedFile . '.v' . $v, $owner.'/files_versions/' . $ownerPath . '.v' . $v);
 					}
 				}
 			}
@@ -356,7 +384,7 @@ class Trashbin {
      * @param $file complete path to file
      * @param $filename name of file
      * @param $ext file extension in case a file with the same $filename already exists
-     * @param $location location if file
+     * @param $location location of file
      * @param $timestamp deleteion time
      *
      * @return size of restored encrypted file
@@ -366,20 +394,25 @@ class Trashbin {
 		$size = 0;
 		if (\OCP\App::isEnabled('files_encryption')) {
 			$user = \OCP\User::getUser();
+			$rootView = new \OC\Files\View('/');
+
+			$target = \OC\Files\Filesystem::normalizePath('/'.$location.'/'.$filename.$ext);
+
+			list($owner, $ownerPath) = self::getUidAndFilename($target);
 
             $path_parts = pathinfo($file);
             $source_location = $path_parts['dirname'];
 
             if ($view->is_dir('/files_trashbin/keyfiles/'.$file)) {
                 if($source_location != '.') {
-                    $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/' . $source_location . '/' . $filename);
-                    $sharekey = \OC\Files\Filesystem::normalizePath('files_trashbin/share-keys/' . $source_location . '/' . $filename);
+                    $keyfile = \OC\Files\Filesystem::normalizePath($user.'/files_trashbin/keyfiles/' . $source_location . '/' . $filename);
+                    $sharekey = \OC\Files\Filesystem::normalizePath($user.'/files_trashbin/share-keys/' . $source_location . '/' . $filename);
                 } else {
-                    $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/' . $filename);
-                    $sharekey = \OC\Files\Filesystem::normalizePath('files_trashbin/share-keys/' . $filename);
+                    $keyfile = \OC\Files\Filesystem::normalizePath($user.'/files_trashbin/keyfiles/' . $filename);
+                    $sharekey = \OC\Files\Filesystem::normalizePath($user.'/files_trashbin/share-keys/' . $filename);
                 }
             } else {
-                $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/' . $source_location . '/' . $filename . '.key');
+                $keyfile = \OC\Files\Filesystem::normalizePath($user.'/files_trashbin/keyfiles/' . $source_location . '/' . $filename . '.key');
             }
 
             if ($timestamp) {
@@ -390,35 +423,36 @@ class Trashbin {
             $proxyStatus = \OC_FileProxy::$enabled;
             \OC_FileProxy::$enabled = false;
 
-            if ($view->file_exists($keyfile)) {
+            if ($rootView->file_exists($keyfile)) {
                 // handle directory
-            	if ($view->is_dir($keyfile)) {
+            	if ($rootView->is_dir($keyfile)) {
 
                     // handle keyfiles
-                    $size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . $keyfile));
-            		$view->rename($keyfile, 'files_encryption/keyfiles/' . $location . '/' . $filename . $ext);
+                    $size += self::calculateSize(new \OC\Files\View($keyfile));
+            		$rootView->rename($keyfile, $owner.'/files_encryption/keyfiles/' . $ownerPath);
 
                     // handle share-keys
                     if ($timestamp) {
                         $sharekey .= '.d' . $timestamp;
                     }
-                    $view->rename($sharekey, 'files_encryption/share-keys/' . $location . '/' . $filename . $ext);
+					$size += self::calculateSize(new \OC\Files\View($sharekey));
+                    $rootView->rename($sharekey, $owner.'/files_encryption/share-keys/' . $ownerPath);
 
 				} else {
                     // handle keyfiles
-					$size += $view->filesize($keyfile);
-            		$view->rename($keyfile, 'files_encryption/keyfiles/' . $location . '/' . $filename . $ext . '.key');
+					$size += $rootView->filesize($keyfile);
+            		$rootView->rename($keyfile, $owner.'/files_encryption/keyfiles/' . $ownerPath . '.key');
 
                     // handle share-keys
-                    $ownerShareKey = \OC\Files\Filesystem::normalizePath('files_trashbin/share-keys/' . $source_location . '/' . $filename . '.' . $user. '.shareKey');
+                    $ownerShareKey = \OC\Files\Filesystem::normalizePath($user.'/files_trashbin/share-keys/' . $source_location . '/' . $filename . '.' . $user. '.shareKey');
                     if ($timestamp) {
                         $ownerShareKey .= '.d' . $timestamp;
                     }
 
-                    $size += $view->filesize($ownerShareKey);
+                    $size += $rootView->filesize($ownerShareKey);
 
                     // move only owners key
-                    $view->rename($ownerShareKey, 'files_encryption/share-keys/' . $location . '/' . $filename . $ext . '.' . $user. '.shareKey');
+                    $rootView->rename($ownerShareKey, $owner.'/files_encryption/share-keys/' . $ownerPath . '.' . $user. '.shareKey');
 
                     // try to re-share if file is shared
                     $filesystemView = new \OC_FilesystemView('/');
@@ -426,7 +460,7 @@ class Trashbin {
                     $util = new \OCA\Encryption\Util($filesystemView, $user);
 
                     // fix the file size
-                    $absolutePath = \OC\Files\Filesystem::normalizePath('/' . $user . '/files/'. $location. '/' .$filename);
+                    $absolutePath = \OC\Files\Filesystem::normalizePath('/' . $owner . '/files/'. $ownerPath);
                     $util->fixFileSize($absolutePath);
 
                     // get current sharing state
@@ -475,7 +509,25 @@ class Trashbin {
 			$file = $filename;
 		}
 
+		$size += self::deleteVersions($view, $file, $filename, $timestamp);
+		$size += self::deleteEncryptionKeys($view, $file, $filename, $timestamp);
+	
+		if ($view->is_dir('/files_trashbin/files/'.$file)) {
+			$size += self::calculateSize(new \OC\Files\View('/'.$user.'/files_trashbin/files/'.$file));
+		} else {
+			$size += $view->filesize('/files_trashbin/files/'.$file);
+		}
+		$view->unlink('/files_trashbin/files/'.$file);
+		$trashbinSize -= $size;
+		self::setTrashbinSize($user, $trashbinSize);
+		
+		return $size;
+	}
+
+	private static function deleteVersions($view, $file, $filename, $timestamp) {
+		$size = 0;
 		if ( \OCP\App::isEnabled('files_versions') ) {
+			$user = \OCP\User::getUser();
 			if ($view->is_dir('files_trashbin/versions/'.$file)) {
 				$size += self::calculateSize(new \OC\Files\view('/'.$user.'/files_trashbin/versions/'.$file));
 				$view->unlink('files_trashbin/versions/'.$file);
@@ -491,35 +543,37 @@ class Trashbin {
 				}
 			}
 		}
-		
-		// Take care of encryption keys
-		$parts = pathinfo($file);
-		if ( $view->is_dir('/files_trashbin/files/'.$file) ) {
-			$keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/'.$filename);
-		} else {
-			$keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/'.$filename.'.key');
-		}
-		if ($timestamp) {
-			$keyfile .= '.d'.$timestamp;
-		}
-		if ( \OCP\App::isEnabled('files_encryption') && $view->file_exists($keyfile) ) {
-			if ( $view->is_dir($keyfile) ) {
-				$size += self::calculateSize(new \OC\Files\View('/'.$user.'/'.$keyfile));
+		return $size;
+	}
+
+	private static function deleteEncryptionKeys($view, $file, $filename, $timestamp) {
+		$size = 0;
+		if (\OCP\App::isEnabled('files_encryption')) {
+			$user = \OCP\User::getUser();
+
+			if ($view->is_dir('/files_trashbin/files/' . $file)) {
+				$keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/' . $filename);
+				$sharekeys =  \OC\Files\Filesystem::normalizePath('files_trashbin/share-keys/' . $filename);
 			} else {
-				$size += $view->filesize($keyfile);
+				$keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/' . $filename . '.key');
+				$sharekeys =  \OC\Files\Filesystem::normalizePath('files_trashbin/share-keys/' . $filename . '.' . $user . '.shareKey');
+			}
+			if ($timestamp) {
+				$keyfile .= '.d' . $timestamp;
+				$sharekeys .= '.d' . $timestamp;
+			}
+			if ($view->file_exists($keyfile)) {
+				if ($view->is_dir($keyfile)) {
+					$size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . $keyfile));
+					$size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . $sharekeys));
+				} else {
+					$size += $view->filesize($keyfile);
+					$size += $view->filesize($sharekeys);
+				}
+				$view->unlink($keyfile);
+				$view->unlink($sharekeys);
 			}
-			$view->unlink($keyfile);
-		}
-	
-		if ($view->is_dir('/files_trashbin/files/'.$file)) {
-			$size += self::calculateSize(new \OC\Files\View('/'.$user.'/files_trashbin/files/'.$file));
-		} else {
-			$size += $view->filesize('/files_trashbin/files/'.$file);
 		}
-		$view->unlink('/files_trashbin/files/'.$file);
-		$trashbinSize -= $size;
-		self::setTrashbinSize($user, $trashbinSize);
-		
 		return $size;
 	}
 
diff --git a/tests/enable_all.php b/tests/enable_all.php
index 44af0115650dff1e6f52f756c96ae49b3bfc6067..111ed0e13572770ecbd170cf67bb498c973d4b33 100644
--- a/tests/enable_all.php
+++ b/tests/enable_all.php
@@ -8,6 +8,7 @@
 
 require_once __DIR__.'/../lib/base.php';
 
+OC_App::enable('files_encryption');
 OC_App::enable('calendar');
 OC_App::enable('contacts');
 OC_App::enable('apptemplateadvanced');