Merge branch 'master' into remove_unused_vars

Conflicts:
	apps/files_encryption/lib/util.php
This commit is contained in:
Florin Peter 2013-05-27 17:26:35 +02:00
commit 690bf9b8c4
3 changed files with 402 additions and 310 deletions

View File

@ -49,14 +49,13 @@ namespace OCA\Encryption;
/** /**
* @brief Class for utilities relating to encrypted file storage system * @brief Class for utilities relating to encrypted file storage system
* @param OC_FilesystemView $view expected to have OC '/' as root path * @param \OC_FilesystemView $view expected to have OC '/' as root path
* @param string $userId ID of the logged in user * @param string $userId ID of the logged in user
* @param int $client indicating status of client side encryption. Currently * @param int $client indicating status of client side encryption. Currently
* unused, likely to become obsolete shortly * unused, likely to become obsolete shortly
*/ */
class Util class Util {
{
// Web UI: // Web UI:
@ -128,9 +127,8 @@ class Util
$this->recoveryKeyId = \OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); $this->recoveryKeyId = \OC_Appconfig::getValue('files_encryption', 'recoveryKeyId');
// if we are anonymous/public // if we are anonymous/public
if ( $this->userId === false || if ($this->userId === false
( isset( $_GET['service'] ) && $_GET['service'] == 'files' && || (isset($_GET['service']) && $_GET['service'] == 'files' && isset($_GET['t']))
isset( $_GET['t'] ) )
) { ) {
$this->userId = $this->publicShareKeyId; $this->userId = $this->publicShareKeyId;
@ -138,26 +136,32 @@ class Util
if ($GLOBALS['app'] === 'files_sharing') { if ($GLOBALS['app'] === 'files_sharing') {
$this->userDir = '/' . $GLOBALS['fileOwner']; $this->userDir = '/' . $GLOBALS['fileOwner'];
$this->fileFolderName = 'files'; $this->fileFolderName = 'files';
$this->userFilesDir = '/' . $GLOBALS['fileOwner'] . '/' . $this->fileFolderName; // TODO: Does this need to be user configurable? $this->userFilesDir = '/' . $GLOBALS['fileOwner'] . '/'
. $this->fileFolderName; // TODO: Does this need to be user configurable?
$this->publicKeyDir = '/' . 'public-keys'; $this->publicKeyDir = '/' . 'public-keys';
$this->encryptionDir = '/' . $GLOBALS['fileOwner'] . '/' . 'files_encryption'; $this->encryptionDir = '/' . $GLOBALS['fileOwner'] . '/' . 'files_encryption';
$this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles'; $this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
$this->shareKeysPath = $this->encryptionDir . '/' . 'share-keys'; $this->shareKeysPath = $this->encryptionDir . '/' . 'share-keys';
$this->publicKeyPath = $this->publicKeyDir . '/' . $this->userId . '.public.key'; // e.g. data/public-keys/admin.public.key $this->publicKeyPath =
$this->privateKeyPath = '/owncloud_private_key/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key $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; $this->isPublic = true;
} }
} else { } else {
$this->userDir = '/' . $this->userId; $this->userDir = '/' . $this->userId;
$this->fileFolderName = 'files'; $this->fileFolderName = 'files';
$this->userFilesDir = '/' . $this->userId . '/' . $this->fileFolderName; // TODO: Does this need to be user configurable? $this->userFilesDir =
'/' . $this->userId . '/' . $this->fileFolderName; // TODO: Does this need to be user configurable?
$this->publicKeyDir = '/' . 'public-keys'; $this->publicKeyDir = '/' . 'public-keys';
$this->encryptionDir = '/' . $this->userId . '/' . 'files_encryption'; $this->encryptionDir = '/' . $this->userId . '/' . 'files_encryption';
$this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles'; $this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
$this->shareKeysPath = $this->encryptionDir . '/' . 'share-keys'; $this->shareKeysPath = $this->encryptionDir . '/' . 'share-keys';
$this->publicKeyPath = $this->publicKeyDir . '/' . $this->userId . '.public.key'; // e.g. data/public-keys/admin.public.key $this->publicKeyPath =
$this->privateKeyPath = $this->encryptionDir . '/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key $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
} }
} }
@ -192,12 +196,12 @@ class Util
// Set directories to check / create // Set directories to check / create
$setUpDirs = array( $setUpDirs = array(
$this->userDir $this->userDir,
, $this->userFilesDir $this->userFilesDir,
, $this->publicKeyDir $this->publicKeyDir,
, $this->encryptionDir $this->encryptionDir,
, $this->keyfilesPath $this->keyfilesPath,
, $this->shareKeysPath $this->shareKeysPath
); );
// Check / create all necessary dirs // Check / create all necessary dirs
@ -237,20 +241,29 @@ class Util
} else { } else {
// check if public-key exists but private-key is missing // check if public-key exists but private-key is missing
if ($this->view->file_exists($this->publicKeyPath) && !$this->view->file_exists($this->privateKeyPath)) { if ($this->view->file_exists($this->publicKeyPath) && !$this->view->file_exists($this->privateKeyPath)) {
\OC_Log::write( 'Encryption library', 'public key exists but private key is missing for "' . $this->userId . '"', \OC_Log::FATAL ); \OCP\Util::writeLog('Encryption library',
'public key exists but private key is missing for "' . $this->userId . '"', \OCP\Util::FATAL);
return false; return false;
} else if ( !$this->view->file_exists( $this->publicKeyPath ) && $this->view->file_exists( $this->privateKeyPath ) ) { } else {
\OC_Log::write( 'Encryption library', 'private key exists but public key is missing for "' . $this->userId . '"', \OC_Log::FATAL ); if (!$this->view->file_exists($this->publicKeyPath) && $this->view->file_exists($this->privateKeyPath)
) {
\OCP\Util::writeLog('Encryption library',
'private key exists but public key is missing for "' . $this->userId . '"', \OCP\Util::FATAL);
return false; return false;
} }
} }
}
// If there's no record for this user's encryption preferences // If there's no record for this user's encryption preferences
if (false === $this->recoveryEnabledForUser()) { if (false === $this->recoveryEnabledForUser()) {
// create database configuration // create database configuration
$sql = 'INSERT INTO `*PREFIX*encryption` (`uid`,`mode`,`recovery_enabled`) VALUES (?,?,?)'; $sql = 'INSERT INTO `*PREFIX*encryption` (`uid`,`mode`,`recovery_enabled`) VALUES (?,?,?)';
$args = array( $this->userId, 'server-side', 0 ); $args = array(
$this->userId,
'server-side',
0
);
$query = \OCP\DB::prepare($sql); $query = \OCP\DB::prepare($sql);
$query->execute($args); $query->execute($args);
@ -276,12 +289,7 @@ class Util
*/ */
public function recoveryEnabledForUser() { public function recoveryEnabledForUser() {
$sql = 'SELECT $sql = 'SELECT `recovery_enabled` FROM `*PREFIX*encryption` WHERE uid = ?';
recovery_enabled
FROM
`*PREFIX*encryption`
WHERE
uid = ?';
$args = array($this->userId); $args = array($this->userId);
@ -291,10 +299,15 @@ class Util
$recoveryEnabled = array(); $recoveryEnabled = array();
while ( $row = $result->fetchRow() ) { if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if($result->numRows() > 0) {
$row = $result->fetchRow();
if (isset($row['recovery_enabled'])) {
$recoveryEnabled[] = $row['recovery_enabled']; $recoveryEnabled[] = $row['recovery_enabled'];
}
}
} }
// If no record is found // If no record is found
@ -323,23 +336,23 @@ class Util
// If a record for this user already exists, update it // If a record for this user already exists, update it
if (false === $recoveryStatus) { if (false === $recoveryStatus) {
$sql = 'INSERT INTO `*PREFIX*encryption` $sql = 'INSERT INTO `*PREFIX*encryption` (`uid`,`mode`,`recovery_enabled`) VALUES (?,?,?)';
(`uid`,`mode`,`recovery_enabled`)
VALUES (?,?,?)';
$args = array( $this->userId, 'server-side', $enabled ); $args = array(
$this->userId,
'server-side',
$enabled
);
// Create a new record instead // Create a new record instead
} else { } else {
$sql = 'UPDATE $sql = 'UPDATE `*PREFIX*encryption` SET recovery_enabled = ? WHERE uid = ?';
*PREFIX*encryption
SET
recovery_enabled = ?
WHERE
uid = ?';
$args = array( $enabled, $this->userId ); $args = array(
$enabled,
$this->userId
);
} }
@ -360,6 +373,7 @@ class Util
/** /**
* @brief Find all files and their encryption status within a directory * @brief Find all files and their encryption status within a directory
* @param string $directory The path of the parent directory to search * @param string $directory The path of the parent directory to search
* @param bool $found the founded files if called again
* @return mixed false if 0 found, array on success. Keys: name, path * @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. * @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 * /admin/files NOT /backup OR /home/www/oc/data/admin/files
@ -371,7 +385,11 @@ class Util
\OC_FileProxy::$enabled = false; \OC_FileProxy::$enabled = false;
if ($found == false) { if ($found == false) {
$found = array( 'plain' => array(), 'encrypted' => array(), 'legacy' => array() ); $found = array(
'plain' => array(),
'encrypted' => array(),
'legacy' => array()
);
} }
if ( if (
@ -417,18 +435,27 @@ class Util
&& Crypt::isCatfileContent($data) && Crypt::isCatfileContent($data)
) { ) {
$found['encrypted'][] = array( 'name' => $file, 'path' => $filePath ); $found['encrypted'][] = array(
'name' => $file,
'path' => $filePath
);
// If the file uses old // If the file uses old
// encryption system // encryption system
} elseif ( Crypt::isLegacyEncryptedContent( $data, $relPath ) ) { } elseif ( Crypt::isLegacyEncryptedContent( $data, $relPath ) ) {
$found['legacy'][] = array( 'name' => $file, 'path' => $filePath ); $found['legacy'][] = array(
'name' => $file,
'path' => $filePath
);
// If the file is not encrypted // If the file is not encrypted
} else { } else {
$found['plain'][] = array( 'name' => $file, 'path' => $relPath ); $found['plain'][] = array(
'name' => $file,
'path' => $relPath
);
} }
@ -581,8 +608,8 @@ class Util
/** /**
* @brief fix the file size of the encrypted file * @brief fix the file size of the encrypted file
* @param $path absolute path * @param string $path absolute path
* @return true / false if file is encrypted * @return boolean true / false if file is encrypted
*/ */
public function fixFileSize($path) { public function fixFileSize($path) {
@ -737,7 +764,10 @@ class Util
$size = strlen($recrypted['data']); $size = strlen($recrypted['data']);
// Add the file to the cache // Add the file to the cache
\OC\Files\Filesystem::putFileInfo( $rawPath, array( 'encrypted' => true, 'size' => $size ), '' ); \OC\Files\Filesystem::putFileInfo($rawPath, array(
'encrypted' => true,
'size' => $size
), '');
} }
} }
@ -803,22 +833,30 @@ class Util
*/ */
public static function fileIdToPath($fileId) { public static function fileIdToPath($fileId) {
$query = \OC_DB::prepare( 'SELECT `path`' $sql = 'SELECT `path` FROM `*PREFIX*filecache` WHERE `fileid` = ?';
. ' FROM `*PREFIX*filecache`'
. ' WHERE `fileid` = ?' ); $query = \OCP\DB::prepare($sql);
$result = $query->execute(array($fileId)); $result = $query->execute(array($fileId));
$path = false;
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if($result->numRows() > 0) {
$row = $result->fetchRow(); $row = $result->fetchRow();
$path = substr($row['path'], strlen('files'));
}
}
return substr( $row['path'], 5 ); return $path;
} }
/** /**
* @brief Filter an array of UIDs to return only ones ready for sharing * @brief Filter an array of UIDs to return only ones ready for sharing
* @param array $unfilteredUsers users to be checked for sharing readiness * @param array $unfilteredUsers users to be checked for sharing readiness
* @return multi-dimensional array. keys: ready, unready * @return array as multi-dimensional array. keys: ready, unready
*/ */
public function filterShareReadyUsers($unfilteredUsers) { public function filterShareReadyUsers($unfilteredUsers) {
@ -848,7 +886,8 @@ class Util
// Log warning; we can't do necessary setup here // Log warning; we can't do necessary setup here
// because we don't have the user passphrase // because we don't have the user passphrase
\OC_Log::write( 'Encryption library', '"' . $user . '" is not setup for encryption', \OC_Log::WARN ); \OCP\Util::writeLog('Encryption library',
'"' . $user . '" is not setup for encryption', \OCP\Util::WARN);
} }
@ -918,7 +957,9 @@ class Util
// If we're attempting to share to unready users // If we're attempting to share to unready users
if (!empty($filteredUids['unready'])) { if (!empty($filteredUids['unready'])) {
\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 ); \OCP\Util::writeLog('Encryption library',
'Sharing to these user(s) failed as they are unready for encryption:"'
. print_r($filteredUids['unready'], 1), \OCP\Util::WARN);
return false; return false;
@ -949,7 +990,8 @@ class Util
|| !Keymanager::setShareKeys($this->view, $filePath, $multiEncKey['keys']) || !Keymanager::setShareKeys($this->view, $filePath, $multiEncKey['keys'])
) { ) {
\OC_Log::write( 'Encryption library', 'Keyfiles could not be saved for users sharing ' . $filePath, \OC_Log::ERROR ); \OCP\Util::writeLog('Encryption library',
'Keyfiles could not be saved for users sharing ' . $filePath, \OCP\Util::ERROR);
return false; return false;
@ -1029,14 +1071,12 @@ class Util
*/ */
public function setMigrationStatus($status) { public function setMigrationStatus($status) {
$sql = 'UPDATE $sql = 'UPDATE `*PREFIX*encryption` SET migration_status = ? WHERE uid = ?';
*PREFIX*encryption
SET
migration_status = ?
WHERE
uid = ?';
$args = array( $status, $this->userId ); $args = array(
$status,
$this->userId
);
$query = \OCP\DB::prepare($sql); $query = \OCP\DB::prepare($sql);
@ -1060,12 +1100,7 @@ class Util
*/ */
public function getMigrationStatus() { public function getMigrationStatus() {
$sql = 'SELECT $sql = 'SELECT `migration_status` FROM `*PREFIX*encryption` WHERE uid = ?';
migration_status
FROM
`*PREFIX*encryption`
WHERE
uid = ?';
$args = array($this->userId); $args = array($this->userId);
@ -1075,10 +1110,16 @@ class Util
$migrationStatus = array(); $migrationStatus = array();
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if($result->numRows() > 0) {
$row = $result->fetchRow(); $row = $result->fetchRow();
if($row) { if (isset($row['migration_status'])) {
$migrationStatus[] = $row['migration_status']; $migrationStatus[] = $row['migration_status'];
} }
}
}
// If no record is found // If no record is found
if (empty($migrationStatus)) { if (empty($migrationStatus)) {
@ -1111,12 +1152,16 @@ class Util
$filename = $path; $filename = $path;
$fileOwnerUid = $GLOBALS['fileOwner']; $fileOwnerUid = $GLOBALS['fileOwner'];
return array( $fileOwnerUid, $filename ); return array(
$fileOwnerUid,
$filename
);
} else { } else {
// Check that UID is valid // Check that UID is valid
if (!\OCP\User::userExists($fileOwnerUid)) { if (!\OCP\User::userExists($fileOwnerUid)) {
throw new \Exception( 'Could not find owner (UID = "' . var_export( $fileOwnerUid, 1 ) . '") of file "' . $path . '"' ); throw new \Exception(
'Could not find owner (UID = "' . var_export($fileOwnerUid, 1) . '") of file "' . $path . '"');
} }
// NOTE: Bah, this dependency should be elsewhere // NOTE: Bah, this dependency should be elsewhere
@ -1138,7 +1183,10 @@ class Util
} }
return array( $fileOwnerUid, $filename ); return array(
$fileOwnerUid,
$filename
);
} }
@ -1204,13 +1252,20 @@ class Util
*/ */
public static function getShareParent($id) { public static function getShareParent($id) {
$query = \OC_DB::prepare( 'SELECT `file_target`, `item_type`' $sql = 'SELECT `file_target`, `item_type` FROM `*PREFIX*share` WHERE `id` = ?';
. ' FROM `*PREFIX*share`'
. ' WHERE `id` = ?' ); $query = \OCP\DB::prepare($sql);
$result = $query->execute(array($id)); $result = $query->execute(array($id));
$row = array();
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if($result->numRows() > 0) {
$row = $result->fetchRow(); $row = $result->fetchRow();
}
}
return $row; return $row;
@ -1223,13 +1278,20 @@ class Util
*/ */
public static function getParentFromShare($id) { public static function getParentFromShare($id) {
$query = \OC_DB::prepare( 'SELECT `parent`' $sql = 'SELECT `parent` FROM `*PREFIX*share` WHERE `id` = ?';
. ' FROM `*PREFIX*share`'
. ' WHERE `id` = ?' ); $query = \OCP\DB::prepare($sql);
$result = $query->execute(array($id)); $result = $query->execute(array($id));
$row = array();
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if($result->numRows() > 0) {
$row = $result->fetchRow(); $row = $result->fetchRow();
}
}
return $row; return $row;
@ -1243,8 +1305,18 @@ class Util
*/ */
public function getOwnerFromSharedFile($id) { public function getOwnerFromSharedFile($id) {
$query = \OC_DB::prepare( 'SELECT `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `id` = ?', 1 ); $query = \OCP\DB::prepare('SELECT `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `id` = ?', 1);
$source = $query->execute( array( $id ) )->fetchRow();
$result = $query->execute(array($id));
$source = array();
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if($result->numRows() > 0) {
$source = $result->fetchRow();
}
}
$fileOwner = false; $fileOwner = false;
@ -1254,8 +1326,18 @@ class Util
while (isset($parent)) { while (isset($parent)) {
$query = \OC_DB::prepare( 'SELECT `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `id` = ?', 1 ); $query = \OCP\DB::prepare('SELECT `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `id` = ?', 1);
$item = $query->execute( array( $parent ) )->fetchRow();
$result = $query->execute(array($parent));
$item = array();
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if($result->numRows() > 0) {
$item = $result->fetchRow();
}
}
if (isset($item['parent'])) { if (isset($item['parent'])) {
@ -1384,7 +1466,10 @@ class Util
$userIds[] = $this->publicShareKeyId; $userIds[] = $this->publicShareKeyId;
} }
} else { } else {
$userIds = array( $this->userId, $this->recoveryKeyId ); $userIds = array(
$this->userId,
$this->recoveryKeyId
);
} }
$filteredUids = $this->filterShareReadyUsers($userIds); $filteredUids = $this->filterShareReadyUsers($userIds);
@ -1393,7 +1478,8 @@ class Util
//decrypt file key //decrypt file key
$encKeyfile = $this->view->file_get_contents($this->keyfilesPath . $file . ".key"); $encKeyfile = $this->view->file_get_contents($this->keyfilesPath . $file . ".key");
$shareKey = $this->view->file_get_contents( $this->shareKeysPath . $file . "." . $this->recoveryKeyId . ".shareKey" ); $shareKey = $this->view->file_get_contents(
$this->shareKeysPath . $file . "." . $this->recoveryKeyId . ".shareKey");
$plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey); $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey);
// encrypt file key again to all users, this time with the new public key for the recovered use // encrypt file key again to all users, this time with the new public key for the recovered use
$userPubKeys = Keymanager::getPublicKeys($this->view, $filteredUids['ready']); $userPubKeys = Keymanager::getPublicKeys($this->view, $filteredUids['ready']);
@ -1438,7 +1524,8 @@ class Util
$proxyStatus = \OC_FileProxy::$enabled; $proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false; \OC_FileProxy::$enabled = false;
$encryptedKey = $this->view->file_get_contents( '/owncloud_private_key/' . $this->recoveryKeyId . '.private.key' ); $encryptedKey = $this->view->file_get_contents(
'/owncloud_private_key/' . $this->recoveryKeyId . '.private.key');
$privateKey = Crypt::symmetricDecryptFileContent($encryptedKey, $recoveryPassword); $privateKey = Crypt::symmetricDecryptFileContent($encryptedKey, $recoveryPassword);
\OC_FileProxy::$enabled = $proxyStatus; \OC_FileProxy::$enabled = $proxyStatus;

View File

@ -93,6 +93,7 @@ $(document).ready(function() {
}); });
$('.undelete').click('click',function(event) { $('.undelete').click('click',function(event) {
event.preventDefault();
var spinner = '<img class="move2trash" title="'+t('files_trashbin', 'perform restore operation')+'" src="'+ OC.imagePath('core', 'loader.gif') +'"></a>'; var spinner = '<img class="move2trash" title="'+t('files_trashbin', 'perform restore operation')+'" src="'+ OC.imagePath('core', 'loader.gif') +'"></a>';
var files=getSelectedFiles('file'); var files=getSelectedFiles('file');
var fileslist = JSON.stringify(files); var fileslist = JSON.stringify(files);
@ -117,6 +118,7 @@ $(document).ready(function() {
}); });
$('.delete').click('click',function(event) { $('.delete').click('click',function(event) {
event.preventDefault();
console.log("delete selected"); console.log("delete selected");
var spinner = '<img class="move2trash" title="'+t('files_trashbin', 'Delete permanently')+'" src="'+ OC.imagePath('core', 'loading.gif') +'"></a>'; var spinner = '<img class="move2trash" title="'+t('files_trashbin', 'Delete permanently')+'" src="'+ OC.imagePath('core', 'loading.gif') +'"></a>';
var files=getSelectedFiles('file'); var files=getSelectedFiles('file');

View File

@ -123,8 +123,11 @@ class OC_Files {
header('Content-Length: ' . filesize($filename)); header('Content-Length: ' . filesize($filename));
self::addSendfileHeader($filename); self::addSendfileHeader($filename);
}else{ }else{
$filesize = \OC\Files\Filesystem::filesize($filename);
header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename)); header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename));
header("Content-Length: ".\OC\Files\Filesystem::filesize($filename)); if ($filesize > -1) {
header("Content-Length: ".$filesize);
}
list($storage) = \OC\Files\Filesystem::resolvePath($filename); list($storage) = \OC\Files\Filesystem::resolvePath($filename);
if ($storage instanceof \OC\Files\Storage\Local) { if ($storage instanceof \OC\Files\Storage\Local) {
self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename)); self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename));