diff options
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/files.php | 27 | ||||
-rw-r--r-- | lib/private/files/cache/scanner.php | 5 | ||||
-rw-r--r-- | lib/private/files/filesystem.php | 3 | ||||
-rw-r--r-- | lib/private/files/storage/wrapper/encryption.php | 8 | ||||
-rw-r--r-- | lib/private/files/view.php | 80 | ||||
-rw-r--r-- | lib/private/mimetypes.list.php | 4 | ||||
-rw-r--r-- | lib/private/setup.php | 18 | ||||
-rw-r--r-- | lib/private/share/share.php | 17 | ||||
-rw-r--r-- | lib/private/updater.php | 12 |
9 files changed, 129 insertions, 45 deletions
diff --git a/lib/private/files.php b/lib/private/files.php index 5a3e1029199..d08cb3f9de0 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -43,6 +43,9 @@ // TODO: get rid of this using proper composer packages require_once 'mcnetic/phpzipstreamer/ZipStreamer.php'; +use OC\Lock\NoopLockingProvider; +use OCP\Lock\ILockingProvider; + /** * Class for file server access * @@ -82,11 +85,15 @@ class OC_Files { * @param boolean $only_header ; boolean to only send header of the request */ public static function get($dir, $files, $only_header = false) { + $view = \OC\Files\Filesystem::getView(); $xsendfile = false; - if (isset($_SERVER['MOD_X_SENDFILE_ENABLED']) || - isset($_SERVER['MOD_X_SENDFILE2_ENABLED']) || - isset($_SERVER['MOD_X_ACCEL_REDIRECT_ENABLED'])) { - $xsendfile = true; + if (\OC::$server->getLockingProvider() instanceof NoopLockingProvider) { + if (isset($_SERVER['MOD_X_SENDFILE_ENABLED']) || + isset($_SERVER['MOD_X_SENDFILE2_ENABLED']) || + isset($_SERVER['MOD_X_ACCEL_REDIRECT_ENABLED']) + ) { + $xsendfile = true; + } } if (is_array($files) && count($files) === 1) { @@ -131,7 +138,9 @@ class OC_Files { OC_Util::obEnd(); try { - + if ($get_type === self::FILE) { + $view->lockFile($filename, ILockingProvider::LOCK_SHARED); + } if ($zip or \OC\Files\Filesystem::isReadable($filename)) { self::sendHeaders($filename, $name, $zip); } elseif (!\OC\Files\Filesystem::file_exists($filename)) { @@ -168,7 +177,6 @@ class OC_Files { set_time_limit($executionTime); } else { if ($xsendfile) { - $view = \OC\Files\Filesystem::getView(); /** @var $storage \OC\Files\Storage\Storage */ list($storage) = $view->resolvePath($filename); if ($storage->isLocal()) { @@ -180,6 +188,13 @@ class OC_Files { \OC\Files\Filesystem::readfile($filename); } } + if ($get_type === self::FILE) { + $view->unlockFile($filename, ILockingProvider::LOCK_SHARED); + } + } catch (\OCP\Lock\LockedException $ex) { + $l = \OC::$server->getL10N('core'); + $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; + \OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint); } catch (\Exception $ex) { $l = \OC::$server->getL10N('core'); $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; diff --git a/lib/private/files/cache/scanner.php b/lib/private/files/cache/scanner.php index 12aa05277a1..50609e1e20e 100644 --- a/lib/private/files/cache/scanner.php +++ b/lib/private/files/cache/scanner.php @@ -357,6 +357,11 @@ class Scanner extends BasicEmitter { // log and ignore \OC_Log::write('core', 'Exception while scanning file "' . $child . '": ' . $ex->getMessage(), \OC_Log::DEBUG); $exceptionOccurred = true; + } catch (\OCP\Lock\LockedException $e) { + if ($this->useTransactions) { + \OC_DB::rollback(); + } + throw $e; } } $removedChildren = \array_diff(array_keys($existingChildren), $newChildren); diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php index 212deb24b7a..4d991e5d11d 100644 --- a/lib/private/files/filesystem.php +++ b/lib/private/files/filesystem.php @@ -365,6 +365,7 @@ class Filesystem { * Initialize system and personal mount points for a user * * @param string $user + * @throws \OC\User\NoUserException if the user is not available */ public static function initMountPoints($user = '') { if ($user == '') { @@ -382,7 +383,7 @@ class Filesystem { if (is_null($userObject)) { \OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, \OCP\Util::ERROR); - throw new \OC\User\NoUserException(); + throw new \OC\User\NoUserException('Backends provided no user object for ' . $user); } $homeStorage = \OC_Config::getValue('objectstore'); diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php index 056f823c18b..8d1f80c53c0 100644 --- a/lib/private/files/storage/wrapper/encryption.php +++ b/lib/private/files/storage/wrapper/encryption.php @@ -349,7 +349,8 @@ class Encryption extends Wrapper { if ($this->util->isExcluded($fullPath) === false) { $size = $unencryptedSize = 0; - $targetExists = $this->file_exists($path); + $realFile = $this->util->stripPartialFileExtension($path); + $targetExists = $this->file_exists($realFile); $targetIsEncrypted = false; if ($targetExists) { // in case the file exists we require the explicit module as @@ -605,8 +606,9 @@ class Encryption extends Wrapper { */ protected function getHeader($path) { $header = ''; - if ($this->storage->file_exists($path)) { - $handle = $this->storage->fopen($path, 'r'); + $realFile = $this->util->stripPartialFileExtension($path); + if ($this->storage->file_exists($realFile)) { + $handle = $this->storage->fopen($realFile, 'r'); $firstBlock = fread($handle, $this->util->getHeaderSize()); fclose($handle); if (substr($firstBlock, 0, strlen(Util::HEADER_START)) === Util::HEADER_START) { diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 73daf8a141f..61adc6246fb 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -628,8 +628,8 @@ class View { return false; } - $this->lockFile($path1, ILockingProvider::LOCK_SHARED); - $this->lockFile($path2, ILockingProvider::LOCK_SHARED); + $this->lockFile($path1, ILockingProvider::LOCK_SHARED, true); + $this->lockFile($path2, ILockingProvider::LOCK_SHARED, true); $run = true; if ($this->shouldEmitHooks() && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2))) { @@ -656,8 +656,8 @@ class View { $internalPath1 = $mount1->getInternalPath($absolutePath1); $internalPath2 = $mount2->getInternalPath($absolutePath2); - $this->changeLock($path1, ILockingProvider::LOCK_EXCLUSIVE); - $this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE); + $this->changeLock($path1, ILockingProvider::LOCK_EXCLUSIVE, true); + $this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE, true); if ($internalPath1 === '' and $mount1 instanceof MoveableMount) { if ($this->isTargetAllowed($absolutePath2)) { @@ -670,12 +670,14 @@ class View { } else { $result = false; } + // moving a file/folder within the same mount point } elseif ($storage1 == $storage2) { if ($storage1) { $result = $storage1->rename($internalPath1, $internalPath2); } else { $result = false; } + // moving a file/folder between storages (from $storage1 to $storage2) } else { $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2); } @@ -693,13 +695,8 @@ class View { } } - $this->unlockFile($path1, ILockingProvider::LOCK_EXCLUSIVE); - $this->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE); - - if ($internalPath1 === '' and $mount1 instanceof MoveableMount) { - // since $path2 now points to a different storage we need to unlock the path on the old storage separately - $storage2->releaseLock($internalPath2, ILockingProvider::LOCK_EXCLUSIVE, $this->lockingProvider); - } + $this->unlockFile($path1, ILockingProvider::LOCK_EXCLUSIVE, true); + $this->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE, true); if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) { if ($this->shouldEmitHooks()) { @@ -719,8 +716,8 @@ class View { } return $result; } else { - $this->unlockFile($path1, ILockingProvider::LOCK_SHARED); - $this->unlockFile($path2, ILockingProvider::LOCK_SHARED); + $this->unlockFile($path1, ILockingProvider::LOCK_SHARED, true); + $this->unlockFile($path2, ILockingProvider::LOCK_SHARED, true); return false; } } else { @@ -1700,21 +1697,50 @@ class View { } /** + * Returns the mount point for which to lock + * + * @param string $absolutePath absolute path + * @param bool $useParentMount true to return parent mount instead of whatever + * is mounted directly on the given path, false otherwise + * @return \OC\Files\Mount\MountPoint mount point for which to apply locks + */ + private function getMountForLock($absolutePath, $useParentMount = false) { + $results = []; + $mount = Filesystem::getMountManager()->find($absolutePath); + if (!$mount) { + return $results; + } + + if ($useParentMount) { + // find out if something is mounted directly on the path + $internalPath = $mount->getInternalPath($absolutePath); + if ($internalPath === '') { + // resolve the parent mount instead + $mount = Filesystem::getMountManager()->find(dirname($absolutePath)); + } + } + + return $mount; + } + + /** * Lock the given path * * @param string $path the path of the file to lock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage + * * @return bool False if the path is excluded from locking, true otherwise * @throws \OCP\Lock\LockedException if the path is already locked */ - private function lockPath($path, $type) { + private function lockPath($path, $type, $lockMountPoint = false) { $absolutePath = $this->getAbsolutePath($path); $absolutePath = Filesystem::normalizePath($absolutePath); if (!$this->shouldLockFile($absolutePath)) { return false; } - $mount = $this->getMount($path); + $mount = $this->getMountForLock($absolutePath, $lockMountPoint); if ($mount) { try { $mount->getStorage()->acquireLock( @@ -1739,10 +1765,12 @@ class View { * * @param string $path the path of the file to lock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage + * * @return bool False if the path is excluded from locking, true otherwise * @throws \OCP\Lock\LockedException if the path is already locked */ - public function changeLock($path, $type) { + public function changeLock($path, $type, $lockMountPoint = false) { $path = Filesystem::normalizePath($path); $absolutePath = $this->getAbsolutePath($path); $absolutePath = Filesystem::normalizePath($absolutePath); @@ -1750,7 +1778,7 @@ class View { return false; } - $mount = $this->getMount($path); + $mount = $this->getMountForLock($absolutePath, $lockMountPoint); if ($mount) { try { $mount->getStorage()->changeLock( @@ -1775,16 +1803,18 @@ class View { * * @param string $path the path of the file to unlock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage + * * @return bool False if the path is excluded from locking, true otherwise */ - private function unlockPath($path, $type) { + private function unlockPath($path, $type, $lockMountPoint = false) { $absolutePath = $this->getAbsolutePath($path); $absolutePath = Filesystem::normalizePath($absolutePath); if (!$this->shouldLockFile($absolutePath)) { return false; } - $mount = $this->getMount($path); + $mount = $this->getMountForLock($absolutePath, $lockMountPoint); if ($mount) { $mount->getStorage()->releaseLock( $mount->getInternalPath($absolutePath), @@ -1801,16 +1831,18 @@ class View { * * @param string $path the path of the file to lock relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage + * * @return bool False if the path is excluded from locking, true otherwise */ - public function lockFile($path, $type) { + public function lockFile($path, $type, $lockMountPoint = false) { $absolutePath = $this->getAbsolutePath($path); $absolutePath = Filesystem::normalizePath($absolutePath); if (!$this->shouldLockFile($absolutePath)) { return false; } - $this->lockPath($path, $type); + $this->lockPath($path, $type, $lockMountPoint); $parents = $this->getParents($path); foreach ($parents as $parent) { @@ -1825,16 +1857,18 @@ class View { * * @param string $path the path of the file to lock relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage + * * @return bool False if the path is excluded from locking, true otherwise */ - public function unlockFile($path, $type) { + public function unlockFile($path, $type, $lockMountPoint = false) { $absolutePath = $this->getAbsolutePath($path); $absolutePath = Filesystem::normalizePath($absolutePath); if (!$this->shouldLockFile($absolutePath)) { return false; } - $this->unlockPath($path, $type); + $this->unlockPath($path, $type, $lockMountPoint); $parents = $this->getParents($path); foreach ($parents as $parent) { diff --git a/lib/private/mimetypes.list.php b/lib/private/mimetypes.list.php index e2b82b256e5..5f222cbd835 100644 --- a/lib/private/mimetypes.list.php +++ b/lib/private/mimetypes.list.php @@ -117,6 +117,8 @@ return array( 'mpg' => array('video/mpeg', null), 'mpo' => array('image/jpeg', null), 'msi' => array('application/x-msi', null), + 'mts' => ['video/MP2T', null], + 'mt2s' => ['video/MP2T', null], 'nef' => array('image/x-dcraw', null), 'numbers' => array('application/x-iwork-numbers-sffnumbers', null), 'odf' => array('application/vnd.oasis.opendocument.formula', null), @@ -176,7 +178,7 @@ return array( 'wav' => array('audio/wav', null), 'webm' => array('video/webm', null), 'woff' => array('application/font-woff', null), - 'wmv' => array('video/x-ms-asf', null), + 'wmv' => array('video/x-ms-wmv', null), 'xcf' => array('application/x-gimp', null), 'xla' => array('application/vnd.ms-excel', null), 'xlam' => array('application/vnd.ms-excel.addin.macroEnabled.12', null), diff --git a/lib/private/setup.php b/lib/private/setup.php index 7ca30e172ec..1ffe074dc34 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -402,10 +402,20 @@ class Setup { throw new \OC\HintException('.htaccess file has the wrong version. Please upload the correct version. Maybe you forgot to replace it after updating?'); } - $content = "\n"; - $content.= "ErrorDocument 403 ".\OC::$WEBROOT."/core/templates/403.php\n";//custom 403 error page - $content.= "ErrorDocument 404 ".\OC::$WEBROOT."/core/templates/404.php";//custom 404 error page - @file_put_contents($setupHelper->pathToHtaccess(), $content, FILE_APPEND); //suppress errors in case we don't have permissions for it + $htaccessContent = file_get_contents($setupHelper->pathToHtaccess()); + $content = ''; + if (strpos($htaccessContent, 'ErrorDocument 403') === false) { + //custom 403 error page + $content.= "\nErrorDocument 403 ".\OC::$WEBROOT."/core/templates/403.php"; + } + if (strpos($htaccessContent, 'ErrorDocument 404') === false) { + //custom 404 error page + $content.= "\nErrorDocument 404 ".\OC::$WEBROOT."/core/templates/404.php"; + } + if ($content !== '') { + //suppress errors in case we don't have permissions for it + @file_put_contents($setupHelper->pathToHtaccess(), $content . "\n", FILE_APPEND); + } } public static function protectDataDirectory() { diff --git a/lib/private/share/share.php b/lib/private/share/share.php index d8c09bb0883..fd24fc686b1 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -1222,7 +1222,7 @@ class Share extends Constants { $qb->update('`*PREFIX*share`') ->set('`share_with`', ':pass') ->where('`id` = :shareId') - ->setParameter(':pass', is_null($password) ? 'NULL' : \OC::$server->getHasher()->hash($password)) + ->setParameter(':pass', is_null($password) ? null : \OC::$server->getHasher()->hash($password)) ->setParameter(':shareId', $shareId); $qb->execute(); @@ -1705,11 +1705,20 @@ class Share extends Constants { $row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE; } // Add display names to result + $row['share_with_displayname'] = $row['share_with']; if ( isset($row['share_with']) && $row['share_with'] != '' && - isset($row['share_with']) && $row['share_type'] === self::SHARE_TYPE_USER) { + $row['share_type'] === self::SHARE_TYPE_USER) { $row['share_with_displayname'] = \OCP\User::getDisplayName($row['share_with']); - } else { - $row['share_with_displayname'] = $row['share_with']; + } else if(isset($row['share_with']) && $row['share_with'] != '' && + $row['share_type'] === self::SHARE_TYPE_REMOTE) { + $addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']); + foreach ($addressBookEntries as $entry) { + foreach ($entry['CLOUD'] as $cloudID) { + if ($cloudID === $row['share_with']) { + $row['share_with_displayname'] = $entry['FN']; + } + } + } } if ( isset($row['uid_owner']) && $row['uid_owner'] != '') { $row['displayname_owner'] = \OCP\User::getDisplayName($row['uid_owner']); diff --git a/lib/private/updater.php b/lib/private/updater.php index 7f1a493d2a0..00c6569a52f 100644 --- a/lib/private/updater.php +++ b/lib/private/updater.php @@ -189,20 +189,25 @@ class Updater extends BasicEmitter { $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core')); } + $success = true; try { $this->doUpgrade($currentVersion, $installedVersion); } catch (\Exception $exception) { - $this->emit('\OC\Updater', 'failure', array($exception->getMessage())); + \OCP\Util::logException('update', $exception); + $this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage())); + $success = false; } - $this->emit('\OC\Updater', 'updateEnd'); + $this->emit('\OC\Updater', 'updateEnd', array($success)); - if(!$wasMaintenanceModeEnabled) { + if(!$wasMaintenanceModeEnabled && $success) { $this->config->setSystemValue('maintenance', false); $this->emit('\OC\Updater', 'maintenanceDisabled'); } else { $this->emit('\OC\Updater', 'maintenanceActive'); } + + return $success; } /** @@ -386,6 +391,7 @@ class Updater extends BasicEmitter { foreach ($stacks as $type => $stack) { foreach ($stack as $appId) { if (\OC_App::shouldUpgrade($appId)) { + $this->emit('\OC\Updater', 'appUpgradeStarted', array($appId, \OC_App::getAppVersion($appId))); \OC_App::updateApp($appId); $this->emit('\OC\Updater', 'appUpgrade', array($appId, \OC_App::getAppVersion($appId))); } |