From 61ed347d26872bc62465be4df595da3391ea84bb Mon Sep 17 00:00:00 2001
From: Florin Peter <github@florin-peter.de>
Date: Mon, 13 May 2013 21:24:59 +0200
Subject: [PATCH] added handling for public file access via files_sharing link

---
 apps/files_encryption/lib/keymanager.php |   2 +-
 apps/files_encryption/lib/session.php    |  22 +++-
 apps/files_encryption/lib/stream.php     |  16 +--
 apps/files_encryption/lib/util.php       | 144 +++++++++++++++--------
 4 files changed, 120 insertions(+), 64 deletions(-)

diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php
index 6c2df6f840..8ee7820b16 100755
--- a/apps/files_encryption/lib/keymanager.php
+++ b/apps/files_encryption/lib/keymanager.php
@@ -455,7 +455,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/session.php b/apps/files_encryption/lib/session.php
index 5444d0215c..f02315f95d 100644
--- a/apps/files_encryption/lib/session.php
+++ b/apps/files_encryption/lib/session.php
@@ -59,9 +59,11 @@ class Session {
 		) {
 				
  			$keypair = Crypt::createKeypair();
- 			
- 			\OC_FileProxy::$enabled = false;
- 			
+
+            // Disable encryption proxy to prevent recursive calls
+            $proxyStatus = \OC_FileProxy::$enabled;
+            \OC_FileProxy::$enabled = false;
+
  			// Save public key
  
  			if (!$view->is_dir('/public-keys')) {
@@ -76,9 +78,21 @@ class Session {
  			// 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 33b3255e2a..3149b460b6 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' 
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php
index 2a64680599..213bbd1d21 100644
--- a/apps/files_encryption/lib/util.php
+++ b/apps/files_encryption/lib/util.php
@@ -110,23 +110,47 @@ class Util {
 	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->publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId');
-		$this->recoveryKeyId = \OC_Appconfig::getValue('files_encryption', 'recoveryKeyId');
+        $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() {
@@ -1069,46 +1093,54 @@ class Util {
 
         $view = new \OC\Files\View($this->userFilesDir);
 		$fileOwnerUid = $view->getOwner( $path );
-		
-		// 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;
-			
-		}
+        // handle public access
+        if($fileOwnerUid === false && $this->isPublic) {
+            $filename = $view->getPath( $GLOBALS['fileSource'] );
+            $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;
+
+            }
+        }
+
 		
 	}
 
@@ -1233,4 +1265,14 @@ class Util {
 		
 	}
 
+    public function getUserId()
+    {
+        return $this->userId;
+    }
+
+    public function getUserFilesDir()
+    {
+        return $this->userFilesDir;
+    }
+
 }
-- 
GitLab