Browse Source

added unencrypted file size to file cache

improved file size calculation and speeds
tags/v6.0.0alpha2
Florin Peter 11 years ago
parent
commit
fac288a4ad

+ 40
- 73
apps/files_encryption/lib/proxy.php View File

$size = strlen( $data ); $size = strlen( $data );
// Disable encryption proxy to prevent recursive calls // Disable encryption proxy to prevent recursive calls
\OC_FileProxy::$enabled = false;
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
// Check if there is an existing key we can reuse // Check if there is an existing key we can reuse
if ( $encKeyfile = Keymanager::getFileKey( $rootView, $userId, $filePath ) ) { if ( $encKeyfile = Keymanager::getFileKey( $rootView, $userId, $filePath ) ) {


// Fetch public keys for all users who will share the file // Fetch public keys for all users who will share the file
$publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds ); $publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds );
\OC_FileProxy::$enabled = false;
// Encrypt plain keyfile to multiple sharefiles

// Encrypt plain keyfile to multiple sharefiles
$multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys );
// Save sharekeys to user folders // Save sharekeys to user folders
\OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' );
// Re-enable proxy - our work is done // Re-enable proxy - our work is done
\OC_FileProxy::$enabled = true;
\OC_FileProxy::$enabled = $proxyStatus;
} }
} }
// TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc.
// Disable encryption proxy to prevent recursive calls // Disable encryption proxy to prevent recursive calls
\OC_FileProxy::$enabled = false;
// If data is a catfile
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;

// If data is a catfile
if ( if (
Crypt::mode() == 'server' Crypt::mode() == 'server'
&& Crypt::isCatfileContent( $data ) // TODO: Do we really need this check? Can't we assume it is properly encrypted? && Crypt::isCatfileContent( $data ) // TODO: Do we really need this check? Can't we assume it is properly encrypted?
} }
\OC_FileProxy::$enabled = true;
\OC_FileProxy::$enabled = $proxyStatus;
if ( ! isset( $plainData ) ) { if ( ! isset( $plainData ) ) {
$path = Keymanager::fixPartialFilePath( $path ); $path = Keymanager::fixPartialFilePath( $path );
// Disable encryption proxy to prevent recursive calls // Disable encryption proxy to prevent recursive calls
\OC_FileProxy::$enabled = false;
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
$view = new \OC_FilesystemView( '/' ); $view = new \OC_FilesystemView( '/' );


} }
\OC_FileProxy::$enabled = true;
\OC_FileProxy::$enabled = $proxyStatus;
// If we don't return true then file delete will fail; better // If we don't return true then file delete will fail; better
// to leave orphaned keyfiles than to disallow file deletion // to leave orphaned keyfiles than to disallow file deletion
{ {


// Disable encryption proxy to prevent recursive calls // Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false; \OC_FileProxy::$enabled = false;


$view = new \OC_FilesystemView('/'); $view = new \OC_FilesystemView('/');
// Rename keyfile so it isn't orphaned // Rename keyfile so it isn't orphaned
$result = $view->rename($oldKeyfilePath, $newKeyfilePath); $result = $view->rename($oldKeyfilePath, $newKeyfilePath);


\OC_FileProxy::$enabled = true;
\OC_FileProxy::$enabled = $proxyStatus;


return $result; return $result;


$path_f = implode( '/', array_slice( $path_split, 3 ) ); $path_f = implode( '/', array_slice( $path_split, 3 ) );
// Disable encryption proxy to prevent recursive calls // Disable encryption proxy to prevent recursive calls
\OC_FileProxy::$enabled = false;
$meta = stream_get_meta_data( $result );
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;

$meta = stream_get_meta_data( $result );
$view = new \OC_FilesystemView( '' ); $view = new \OC_FilesystemView( '' );
// NOTE: this is the case for new files saved via WebDAV // NOTE: this is the case for new files saved via WebDAV
if (
$view->file_exists( $path )
and $view->filesize( $path ) > 0
) {
$x = $view->file_get_contents( $path );
$tmp = tmpfile();
// if (
// $view->file_exists( $path )
// and $view->filesize( $path ) > 0
// ) {
// $x = $view->file_get_contents( $path );
//
// $tmp = tmpfile();
// // Make a temporary copy of the original file // // Make a temporary copy of the original file
// \OCP\Files::streamCopy( $result, $tmp ); // \OCP\Files::streamCopy( $result, $tmp );
// //
// fclose( $tmp ); // fclose( $tmp );
}
// }


$result = fopen( 'crypt://'.$path_f, $meta['mode'] ); $result = fopen( 'crypt://'.$path_f, $meta['mode'] );
} }
// Re-enable the proxy // Re-enable the proxy
\OC_FileProxy::$enabled = true;
\OC_FileProxy::$enabled = $proxyStatus;
return $result; return $result;
// if path is a folder do nothing // if path is a folder do nothing
if(is_array($data) && array_key_exists('size', $data)) { if(is_array($data) && array_key_exists('size', $data)) {
// Disable encryption proxy to prevent recursive calls // Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false; \OC_FileProxy::$enabled = false;



// get file size // get file size
$data['size'] = self::postFileSize($path, $data['size']); $data['size'] = self::postFileSize($path, $data['size']);


// Re-enable the proxy // Re-enable the proxy
\OC_FileProxy::$enabled = true;

trigger_error('postGetFileInfo '.$path.' size: '.$data['size']);
\OC_FileProxy::$enabled = $proxyStatus;
} }


return $data; return $data;
$cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); $cached = \OC\Files\Filesystem::getFileInfo( $path, '' );
$data['size'] = $cached['size'];
$data['size'] = $cached['unencrypted_size'];
} }
return $size; return $size;
} }


$path = Keymanager::fixPartialFilePath( $path );

// Reformat path for use with OC_FSV // Reformat path for use with OC_FSV
$path_split = explode('/', $path); $path_split = explode('/', $path);
$path_f = implode('/', array_slice($path_split, 3)); $path_f = implode('/', array_slice($path_split, 3));


$userId = \OCP\User::getUser();
$util = new Util( $view, $userId );


// FIXME: is there a better solution to check if file belongs to files path?
// only get file size if file is in 'files' path
if (count($path_split) >= 2 && $path_split[2] == 'files' && $util->isEncryptedPath($path)) {

// Disable encryption proxy to prevent recursive calls
\OC_FileProxy::$enabled = false;

// open stream
$result = fopen('crypt://' . $path_f, "r");

if(is_resource($result)) {
// don't trust the given size, allways get the size from filesystem
$size = $view->filesize($path);

// calculate last chunk nr
$lastChunckNr = floor($size / 8192);

// calculate last chunk position
$lastChunckPos = ($lastChunckNr * 8192);

// seek to end
fseek($result, $lastChunckPos);

// get the content of the last chunck
$lastChunkContent = fgets($result);

// calc the real file size with the size of the last chunk
$realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent));

// set the size
$size = $realSize;
}

// enable proxy
\OC_FileProxy::$enabled = true;

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'];
} else { } else {

return $size;

return $fileInfo['size'];
} }
} }
} }

+ 8
- 6
apps/files_encryption/lib/stream.php View File

private $count; private $count;
private $writeCache; private $writeCache;
public $size; public $size;
public $unencryptedSize;
private $publicKey; private $publicKey;
private $keyfile; private $keyfile;
private $encKeyfile; private $encKeyfile;
} else { } else {


// Disable fileproxies so we can get the file size and open the source file without recursive encryption // Disable fileproxies so we can get the file size and open the source file without recursive encryption
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false; \OC_FileProxy::$enabled = false;


if ( if (


// We're writing a new file so start write counter with 0 bytes // We're writing a new file so start write counter with 0 bytes
$this->size = 0; $this->size = 0;
$this->unencryptedSize = 0;


} else { } else {
$this->handle = $this->rootView->fopen( $this->rawPath, $mode ); $this->handle = $this->rootView->fopen( $this->rawPath, $mode );
\OC_FileProxy::$enabled = true;
\OC_FileProxy::$enabled = $proxyStatus;


if ( ! is_resource( $this->handle ) ) { if ( ! is_resource( $this->handle ) ) {


// automatically attempted when the file is written to disk - // automatically attempted when the file is written to disk -
// we are handling that separately here and we don't want to // we are handling that separately here and we don't want to
// get into an infinite loop // get into an infinite loop
\OC_FileProxy::$enabled = false;
//\OC_FileProxy::$enabled = false;
// Get the length of the unencrypted data that we are handling // Get the length of the unencrypted data that we are handling
$length = strlen( $data ); $length = strlen( $data );
} }
$this->size = max( $this->size, $pointer + $length ); $this->size = max( $this->size, $pointer + $length );
$this->unencryptedSize += $length;

return $length; return $length;


} }
$this->meta['mode']!='r' $this->meta['mode']!='r'
and $this->meta['mode']!='rb' and $this->meta['mode']!='rb'
) { ) {
\OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => true, 'size' => $this->size ), '' );

\OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => 1, 'size' => $this->size, 'unencrypted_size' => $this->unencryptedSize ), '' );
} }


return fclose( $this->handle ); return fclose( $this->handle );

+ 8
- 0
db_structure.xml View File

<length>4</length> <length>4</length>
</field> </field>


<field>
<name>unencrypted_size</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>8</length>
</field>

<field> <field>
<name>etag</name> <name>etag</name>
<type>text</type> <type>text</type>

+ 6
- 5
lib/files/cache/cache.php View File

$params = array($file); $params = array($file);
} }
$query = \OC_DB::prepare( $query = \OC_DB::prepare(
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag`
FROM `*PREFIX*filecache` ' . $where); FROM `*PREFIX*filecache` ' . $where);
$result = $query->execute($params); $result = $query->execute($params);
$data = $result->fetchRow(); $data = $result->fetchRow();
$data['size'] = (int)$data['size']; $data['size'] = (int)$data['size'];
$data['mtime'] = (int)$data['mtime']; $data['mtime'] = (int)$data['mtime'];
$data['encrypted'] = (bool)$data['encrypted']; $data['encrypted'] = (bool)$data['encrypted'];
$data['unencrypted_size'] = (int)$data['unencrypted_size'];
$data['storage'] = $this->storageId; $data['storage'] = $this->storageId;
$data['mimetype'] = $this->getMimetype($data['mimetype']); $data['mimetype'] = $this->getMimetype($data['mimetype']);
$data['mimepart'] = $this->getMimetype($data['mimepart']); $data['mimepart'] = $this->getMimetype($data['mimepart']);
$fileId = $this->getId($folder); $fileId = $this->getId($folder);
if ($fileId > -1) { if ($fileId > -1) {
$query = \OC_DB::prepare( $query = \OC_DB::prepare(
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag`
FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC'); FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC');
$result = $query->execute(array($fileId)); $result = $query->execute(array($fileId));
$files = $result->fetchAll(); $files = $result->fetchAll();
* @return array * @return array
*/ */
function buildParts(array $data) { function buildParts(array $data) {
$fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'etag');
$fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'unencrypted_size', 'etag');
$params = array(); $params = array();
$queryParts = array(); $queryParts = array();
foreach ($data as $name => $value) { foreach ($data as $name => $value) {
*/ */
public function search($pattern) { public function search($pattern) {
$query = \OC_DB::prepare(' $query = \OC_DB::prepare('
SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag`
FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?' FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?'
); );
$result = $query->execute(array($pattern, $this->numericId)); $result = $query->execute(array($pattern, $this->numericId));
$where = '`mimepart` = ?'; $where = '`mimepart` = ?';
} }
$query = \OC_DB::prepare(' $query = \OC_DB::prepare('
SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag`
FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?'
); );
$mimetype = $this->getMimetypeId($mimetype); $mimetype = $this->getMimetypeId($mimetype);

Loading…
Cancel
Save