From 4faba49f0a38427e96ef8393900f799c5a5ba6aa Mon Sep 17 00:00:00 2001
From: Vincent Petry <pvince81@owncloud.com>
Date: Thu, 9 Jan 2014 17:27:55 +0100
Subject: [PATCH] Fix calculated folder size to use unencrypted size

The encrypted size was used when calculating folder sizes.
This fix now also sums up the unencrypted size and shows that one when
available.
---
 lib/private/files/cache/cache.php | 22 +++++++++++----
 tests/lib/files/cache/cache.php   | 45 +++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php
index 8e682a96b75..1e7936ca26d 100644
--- a/lib/private/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -178,7 +178,7 @@ class Cache {
 				if ($file['storage_mtime'] == 0) {
 					$file['storage_mtime'] = $file['mtime'];
 				}
-				if ($file['encrypted']) {
+				if ($file['encrypted'] or ($file['unencrypted_size'] > 0 and $file['mimetype'] === 'httpd/unix-directory')) {
 					$file['encrypted_size'] = $file['size'];
 					$file['size'] = $file['unencrypted_size'];
 				}
@@ -511,22 +511,34 @@ class Cache {
 		$entry = $this->get($path);
 		if ($entry && $entry['mimetype'] === 'httpd/unix-directory') {
 			$id = $entry['fileid'];
-			$sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2 FROM `*PREFIX*filecache` '.
+			$sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2, ' .
+				'SUM(`unencrypted_size`) AS f3 ' .
+				'FROM `*PREFIX*filecache` ' .
 				'WHERE `parent` = ? AND `storage` = ?';
 			$result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId()));
 			if ($row = $result->fetchRow()) {
-				list($sum, $min) = array_values($row);
+				list($sum, $min, $unencryptedSum) = array_values($row);
 				$sum = (int)$sum;
 				$min = (int)$min;
+				$unencryptedSum = (int)$unencryptedSum;
 				if ($min === -1) {
 					$totalSize = $min;
 				} else {
 					$totalSize = $sum;
 				}
+				$update = array();
 				if ($entry['size'] !== $totalSize) {
-					$this->update($id, array('size' => $totalSize));
+					$update['size'] = $totalSize;
+				}
+				if ($entry['unencrypted_size'] !== $unencryptedSum) {
+					$update['unencrypted_size'] = $unencryptedSum;
+				}
+				if (count($update) > 0) {
+					$this->update($id, $update);
+				}
+				if ($totalSize !== -1 and $unencryptedSum > 0) {
+					$totalSize = $unencryptedSum;
 				}
-				
 			}
 		}
 		return $totalSize;
diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php
index 052d70dd0b4..7d9329328a3 100644
--- a/tests/lib/files/cache/cache.php
+++ b/tests/lib/files/cache/cache.php
@@ -137,6 +137,51 @@ class Cache extends \PHPUnit_Framework_TestCase {
 		$this->assertFalse($this->cache->inCache('folder/bar'));
 	}
 
+	public function testEncryptedFolder() {
+		$file1 = 'folder';
+		$file2 = 'folder/bar';
+		$file3 = 'folder/foo';
+		$data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
+		$fileData = array();
+		$fileData['bar'] = array('size' => 1000, 'unencrypted_size' => 900, 'encrypted' => 1, 'mtime' => 20, 'mimetype' => 'foo/file');
+		$fileData['foo'] = array('size' => 20, 'unencrypted_size' => 16, 'encrypted' => 1, 'mtime' => 25, 'mimetype' => 'foo/file');
+
+		$this->cache->put($file1, $data1);
+		$this->cache->put($file2, $fileData['bar']);
+		$this->cache->put($file3, $fileData['foo']);
+
+		$content = $this->cache->getFolderContents($file1);
+		$this->assertEquals(count($content), 2);
+		foreach ($content as $cachedData) {
+			$data = $fileData[$cachedData['name']];
+			// indirect retrieval swaps  unencrypted_size and size
+			$this->assertEquals($data['unencrypted_size'], $cachedData['size']);
+		}
+
+		$file4 = 'folder/unkownSize';
+		$fileData['unkownSize'] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'foo/file');
+		$this->cache->put($file4, $fileData['unkownSize']);
+
+		$this->assertEquals(-1, $this->cache->calculateFolderSize($file1));
+
+		$fileData['unkownSize'] = array('size' => 5, 'mtime' => 25, 'mimetype' => 'foo/file');
+		$this->cache->put($file4, $fileData['unkownSize']);
+
+		$this->assertEquals(916, $this->cache->calculateFolderSize($file1));
+		// direct cache entry retrieval returns the original values
+		$this->assertEquals(1025, $this->cache->get($file1)['size']);
+		$this->assertEquals(916, $this->cache->get($file1)['unencrypted_size']);
+
+		$this->cache->remove($file2);
+		$this->cache->remove($file3);
+		$this->cache->remove($file4);
+		$this->assertEquals(0, $this->cache->calculateFolderSize($file1));
+
+		$this->cache->remove('folder');
+		$this->assertFalse($this->cache->inCache('folder/foo'));
+		$this->assertFalse($this->cache->inCache('folder/bar'));
+	}
+
 	public function testRootFolderSizeForNonHomeStorage() {
 		$dir1 = 'knownsize';
 		$dir2 = 'unknownsize';
-- 
GitLab