From b6fa0e4eefb332dc1fb9b45df50de4621ed8e6bd Mon Sep 17 00:00:00 2001
From: Bjoern Schiessle <schiessle@owncloud.com>
Date: Mon, 29 Jul 2013 17:06:05 +0200
Subject: [PATCH] working decrypt files method

---
 apps/files_encryption/hooks/hooks.php |  13 +---
 apps/files_encryption/lib/util.php    | 102 ++++++++++++++++++++++++--
 settings/ajax/decryptall.php          |  23 ++++--
 settings/js/personal.js               |  57 ++++++++++++--
 settings/personal.php                 |   5 +-
 settings/templates/personal.php       |  10 ++-
 6 files changed, 173 insertions(+), 37 deletions(-)

diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php
index b2a17f6bca..d9c3f49b73 100644
--- a/apps/files_encryption/hooks/hooks.php
+++ b/apps/files_encryption/hooks/hooks.php
@@ -62,18 +62,7 @@ class Hooks {
 			return false;
 		}
 
-		$encryptedKey = Keymanager::getPrivateKey($view, $params['uid']);
-
-		$privateKey = Crypt::decryptPrivateKey($encryptedKey, $params['password']);
-
-		if ($privateKey === false) {
-			\OCP\Util::writeLog('Encryption library', 'Private key for user "' . $params['uid']
-													  . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR);
-		}
-
-		$session = new \OCA\Encryption\Session($view);
-
-		$session->setPrivateKey($privateKey);
+		$session = $util->initEncryption($params);
 
 		// Check if first-run file migration has already been performed
 		$ready = false;
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php
index 50e823585d..03e2fae4c6 100644
--- a/apps/files_encryption/lib/util.php
+++ b/apps/files_encryption/lib/util.php
@@ -661,6 +661,69 @@ class Util {
 		}
 
 	}
+	
+	/**
+	 * @brief Decrypt all files
+	 * @return bool
+	 */
+	public function decryptAll() {
+
+		$found = $this->findEncFiles($this->userId . '/files');
+
+		if ($found) {
+
+			// Disable proxy to prevent file being encrypted twice
+			\OC_FileProxy::$enabled = false;
+
+			// Encrypt unencrypted files
+			foreach ($found['encrypted'] as $encryptedFile) {
+
+				//relative to data/<user>/file
+				$relPath = Helper::stripUserFilesPath($encryptedFile['path']);
+
+				//relative to /data
+				$rawPath = $encryptedFile['path'];
+
+				// Open enc file handle for binary reading
+				$encHandle = fopen('crypt://' . $rawPath, 'rb');
+
+				// Open plain file handle for binary writing, with same filename as original plain file
+				$plainHandle = $this->view->fopen($rawPath . '.part', 'wb');
+
+				// Move plain file to a temporary location
+				$size = stream_copy_to_stream($encHandle, $plainHandle);
+
+				fclose($encHandle);
+				fclose($plainHandle);
+
+				$fakeRoot = $this->view->getRoot();
+				$this->view->chroot('/' . $this->userId . '/files');
+
+				$this->view->rename($relPath . '.part', $relPath);
+
+				$this->view->chroot($fakeRoot);
+
+				// Add the file to the cache
+				\OC\Files\Filesystem::putFileInfo($relPath, array(
+					'encrypted' => false,
+					'size' => $size,
+					'unencrypted_size' => $size
+				));
+			}
+
+			$this->view->deleteAll($this->keyfilesPath);
+			$this->view->deleteAll($this->shareKeysPath);
+
+			\OC_FileProxy::$enabled = true;
+
+			// If files were found, return true
+			return true;
+		} else {
+
+			// If no files were found, return false
+			return false;
+		}
+	}
 
 	/**
 	 * @brief Encrypt all files in a directory
@@ -672,7 +735,9 @@ class Util {
 	 */
 	public function encryptAll($dirPath, $legacyPassphrase = null, $newPassphrase = null) {
 
-		if ($found = $this->findEncFiles($dirPath)) {
+		$found = $this->findEncFiles($dirPath);
+		
+		if ($found) {
 
 			// Disable proxy to prevent file being encrypted twice
 			\OC_FileProxy::$enabled = false;
@@ -690,12 +755,13 @@ class Util {
 				$plainHandle = $this->view->fopen($rawPath, 'rb');
 
 				// Open enc file handle for binary writing, with same filename as original plain file
-				$encHandle = fopen('crypt://' . $relPath . '.part', 'wb');
+				$encHandle = fopen('crypt://' . $rawPath . '.part', 'wb');
 
 				// Move plain file to a temporary location
 				$size = stream_copy_to_stream($plainHandle, $encHandle);
 
 				fclose($encHandle);
+				fclose($plainHandle);
 
 				$fakeRoot = $this->view->getRoot();
 				$this->view->chroot('/' . $this->userId . '/files');
@@ -706,10 +772,10 @@ class Util {
 
 				// Add the file to the cache
 				\OC\Files\Filesystem::putFileInfo($relPath, array(
-																 'encrypted' => true,
-																 'size' => $size,
-																 'unencrypted_size' => $size
-															));
+					'encrypted' => true,
+					'size' => $size,
+					'unencrypted_size' => $size
+				));
 			}
 
 			// Encrypt legacy encrypted files
@@ -1579,4 +1645,28 @@ class Util {
 		return false;
 	}
 
+	/**
+	 * @brief decrypt private key and add it to the current session
+	 * @param array $params with 'uid' and 'password'
+	 * @return mixed session or false
+	 */
+	public function initEncryption($params) {
+
+		$encryptedKey = Keymanager::getPrivateKey($this->view, $params['uid']);
+
+		$privateKey = Crypt::decryptPrivateKey($encryptedKey, $params['password']);
+
+		if ($privateKey === false) {
+			\OCP\Util::writeLog('Encryption library', 'Private key for user "' . $params['uid']
+					. '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR);
+			return false;
+		}
+
+		$session = new \OCA\Encryption\Session($this->view);
+
+		$session->setPrivateKey($privateKey);
+		
+		return $session;
+	}
+	
 }
diff --git a/settings/ajax/decryptall.php b/settings/ajax/decryptall.php
index 02a9bfe96b..7adacb9802 100644
--- a/settings/ajax/decryptall.php
+++ b/settings/ajax/decryptall.php
@@ -1,14 +1,21 @@
 <?php
+sleep(10);
+//encryption app needs to be loaded
+OC_App::loadApp('files_encryption');
 
-$status = OC_App::isEnabled('files_encryption');
-OC_App::enable('files_encryption');
+// init encryption app
+$params = array('uid' => \OCP\User::getUser(),
+				'password' => $_POST['password']);
 
-OCA\Encryption\Crypt::decryptAll();
-
-if ($status === false) {
-	OC_App::disable('files_encryption');
-}
+$view = new OC_FilesystemView('/');
+$util = new \OCA\Encryption\Util($view, \OCP\User::getUser());
 
+$result = $util->initEncryption($params);
 
-\OCP\JSON::success(array('data' => array('message' => 'looks good')));
+if ($result !== false) {
+	$util->decryptAll();
+	\OCP\JSON::success(array('data' => array('message' => 'Files decrypted successfully')));
+} else {
+	\OCP\JSON::error(array('data' => array('message' => 'Couldn\'t decrypt files, check your password and try again')));
+}
 
diff --git a/settings/js/personal.js b/settings/js/personal.js
index 97342e7653..94ef959488 100644
--- a/settings/js/personal.js
+++ b/settings/js/personal.js
@@ -112,18 +112,59 @@ $(document).ready(function(){
 	});
 
 	$('button:button[name="submitDecryptAll"]').click(function() {
-		console.log("click!");
-		$.post('ajax/decryptall.php', {}, function(data) {
-			/*
+		var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
+		OC.Encryption.decryptAll(privateKeyPassword);
+	});
+	
+	$('#decryptAll input:password[name="privateKeyPassword"]').keyup(function(event) {
+		var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
+		if (privateKeyPassword !== '' ) {
+			$('#decryptAll button:button[name="submitDecryptAll"]').removeAttr("disabled");
+			if(event.which === 13) {
+				OC.Encryption.decryptAll(privateKeyPassword);
+			}
+		} else {
+			$('#decryptAll button:button[name="submitDecryptAll"]').attr("disabled", "true");
+		}
+	});
+	
+} );
+
+OC.Encryption = {
+	decryptAll: function(password) {
+		OC.Encryption.msg.startDecrypting('#decryptAll .msg');
+		$.post('ajax/decryptall.php', {password:password}, function(data) {
 			if (data.status === "error") {
-				OC.msg.finishedSaving('#encryption .msg', data);
+				OC.Encryption.msg.finishedDecrypting('#decryptAll .msg', data);
 			} else {
-				OC.msg.finishedSaving('#encryption .msg', data);
-			}*/
+				OC.Encryption.msg.finishedDecrypting('#decryptAll .msg', data);
+			}
 		}
 		);
-	});
-} );
+	}
+}
+
+OC.Encryption.msg={
+	startDecrypting:function(selector){
+		$(selector)
+			.html( t('files_encryption', 'Decrypting files... Please wait, this can take some time.') )
+			.removeClass('success')
+			.removeClass('error')
+			.stop(true, true)
+			.show();
+	},
+	finishedDecrypting:function(selector, data){
+		if( data.status === "success" ){
+			 $(selector).html( data.data.message )
+				.addClass('success')
+				.stop(true, true)
+				.delay(3000)
+				.fadeOut(900);
+		}else{
+			$(selector).html( data.data.message ).addClass('error');
+		}
+	}
+};
 
 OC.msg={
 	startSaving:function(selector){
diff --git a/settings/personal.php b/settings/personal.php
index 79ce8e4576..f10b0afb09 100644
--- a/settings/personal.php
+++ b/settings/personal.php
@@ -27,8 +27,9 @@ $languageCodes=OC_L10N::findAvailableLanguages();
 //check if encryption was enabled in the past
 $enableDecryptAll = false;
 if (OC_App::isEnabled('files_encryption') === false) {
-	$view = new OC\Files\View('/'.OC_User::getUser());
-	if ($view->file_exists('files_encryption/keyfiles')) {
+	$view = new OC\Files\View('/'.OCP\User::getUser());
+	$remainingKeys = $view->getDirectoryContent('/files_encryption/keyfiles');
+	if (!empty($remainingKeys)) {
 		$enableDecryptAll = true;
 	}
 }
diff --git a/settings/templates/personal.php b/settings/templates/personal.php
index c0f3600a51..7e926ea42b 100644
--- a/settings/templates/personal.php
+++ b/settings/templates/personal.php
@@ -111,17 +111,25 @@ if($_['passwordChangeSupported']) {
 };?>
 
 <?php if($_['enableDecryptAll']): ?>
-<form id="encryption">
+<form id="decryptAll">
 	<fieldset class="personalblock">
 		<legend>
 			<?php p( $l->t( 'Encryption' ) ); ?>
 		</legend>
 		<?php p($l->t( "The encryption app is no longer enabled, decrypt all your file" )); ?>
 		<p>
+			<input
+				type="password"
+				name="privateKeyPassword"
+				id="privateKeyPassword" />
+			<label for="privateKeyPassword"><?php p($l->t( "Log-in password" )); ?></label>
+			<br />
 			<button
 				type="button"
+				disabled
 				name="submitDecryptAll"><?php p($l->t( "Decrypt all Files" )); ?>
 			</button>
+			<span class="msg"></span>
 		</p>
 		<br />
 	</fieldset>
-- 
GitLab