diff options
71 files changed, 751 insertions, 290 deletions
diff --git a/apps/dav/appinfo/application.php b/apps/dav/appinfo/application.php index c3811a40845..328f86c877f 100644 --- a/apps/dav/appinfo/application.php +++ b/apps/dav/appinfo/application.php @@ -153,11 +153,6 @@ class Application extends App { return $this->getContainer()->query('SyncService'); } - public function setupCron() { - $jl = $this->getContainer()->getServer()->getJobList(); - $jl->add(new SyncJob()); - } - public function generateBirthdays() { try { /** @var BirthdayService $migration */ diff --git a/apps/dav/appinfo/database.xml b/apps/dav/appinfo/database.xml index 71dec639064..f79ea07ae76 100644 --- a/apps/dav/appinfo/database.xml +++ b/apps/dav/appinfo/database.xml @@ -259,11 +259,13 @@ CREATE TABLE calendarobjects ( <name>firstoccurence</name> <type>integer</type> <unsigned>true</unsigned> + <length>11</length> </field> <field> <name>lastoccurence</name> <type>integer</type> <unsigned>true</unsigned> + <length>11</length> </field> <field> <name>uid</name> diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index a8e7df6e8e2..e2688e2f923 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -5,7 +5,7 @@ <description>ownCloud WebDAV endpoint</description> <licence>AGPL</licence> <author>owncloud.org</author> - <version>0.2.3</version> + <version>0.2.4</version> <default_enable/> <types> <filesystem/> @@ -16,4 +16,7 @@ <dependencies> <owncloud min-version="9.1" max-version="9.1" /> </dependencies> + <background-jobs> + <job>OCA\DAV\CardDAV\Sync\SyncJob</job> + </background-jobs> </info> diff --git a/apps/dav/appinfo/install.php b/apps/dav/appinfo/install.php index fbd41d25f49..dbb23022b38 100644 --- a/apps/dav/appinfo/install.php +++ b/apps/dav/appinfo/install.php @@ -22,5 +22,4 @@ use OCA\Dav\AppInfo\Application; $app = new Application(); -$app->setupCron(); $app->generateBirthdays(); diff --git a/apps/dav/appinfo/update.php b/apps/dav/appinfo/update.php index fbd41d25f49..dbb23022b38 100644 --- a/apps/dav/appinfo/update.php +++ b/apps/dav/appinfo/update.php @@ -22,5 +22,4 @@ use OCA\Dav\AppInfo\Application; $app = new Application(); -$app->setupCron(); $app->generateBirthdays(); diff --git a/apps/dav/lib/connector/sabre/principal.php b/apps/dav/lib/connector/sabre/principal.php index 18f28a916f1..787bcdf469b 100644 --- a/apps/dav/lib/connector/sabre/principal.php +++ b/apps/dav/lib/connector/sabre/principal.php @@ -196,6 +196,14 @@ class Principal implements BackendInterface { * @return string */ function findByUri($uri, $principalPrefix) { + if (substr($uri, 0, 7) === 'mailto:') { + $email = substr($uri, 7); + $users = $this->userManager->getByEmail($email); + if (count($users) === 1) { + return $this->principalPrefix . '/' . $users[0]->getUID(); + } + } + return ''; } diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index 73e24c9a292..edaa7ac8552 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -84,6 +84,9 @@ class Server { // acl $acl = new DavAclPlugin(); + $acl->principalCollectionSet = [ + 'principals/users', 'principals/groups' + ]; $acl->defaultUsernamePath = 'principals/users'; $this->server->addPlugin($acl); diff --git a/apps/dav/tests/unit/caldav/caldavbackendtest.php b/apps/dav/tests/unit/caldav/caldavbackendtest.php index 440db7636e1..89be5671ca8 100644 --- a/apps/dav/tests/unit/caldav/caldavbackendtest.php +++ b/apps/dav/tests/unit/caldav/caldavbackendtest.php @@ -328,6 +328,7 @@ EOD; $events[0] = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z'); $events[1] = $this->createEvent($calendarId, '20130912T150000Z', '20130912T170000Z'); $events[2] = $this->createEvent($calendarId, '20130912T173000Z', '20130912T220000Z'); + $events[3] = $this->createEvent($calendarId, '21130912T130000Z', '22130912T130000Z'); $result = $this->backend->calendarQuery($calendarId, [ 'name' => '', @@ -351,11 +352,12 @@ EOD; public function providesCalendarQueryParameters() { return [ - 'all' => [[0, 1, 2], [], []], + 'all' => [[0, 1, 2, 3], [], []], 'only-todos' => [[], ['name' => 'VTODO'], []], - 'only-events' => [[0, 1, 2], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => null], 'prop-filters' => []]],], - 'start' => [[1, 2], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],], + 'only-events' => [[0, 1, 2, 3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => null], 'prop-filters' => []]],], + 'start' => [[1, 2, 3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],], 'end' => [[0], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC'))], 'prop-filters' => []]],], + 'future' => [[3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2099-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],], ]; } diff --git a/apps/dav/tests/unit/connector/sabre/principal.php b/apps/dav/tests/unit/connector/sabre/principal.php index 1747885240a..75076e9618b 100644 --- a/apps/dav/tests/unit/connector/sabre/principal.php +++ b/apps/dav/tests/unit/connector/sabre/principal.php @@ -255,4 +255,19 @@ class Principal extends TestCase { public function testSearchPrincipals() { $this->assertSame([], $this->connector->searchPrincipals('principals/users', [])); } + + public function testFindByUri() { + $fooUser = $this->getMockBuilder('\OC\User\User') + ->disableOriginalConstructor()->getMock(); + $fooUser + ->expects($this->exactly(1)) + ->method('getUID') + ->will($this->returnValue('foo')); + + $this->userManager->expects($this->once())->method('getByEmail')->willReturn([ + $fooUser + ]); + $ret = $this->connector->findByUri('mailto:foo@bar.net', 'principals/users'); + $this->assertSame('principals/users/foo', $ret); + } } diff --git a/apps/files/command/scan.php b/apps/files/command/scan.php index f607b3e1af1..1ae04c585bb 100644 --- a/apps/files/command/scan.php +++ b/apps/files/command/scan.php @@ -89,6 +89,15 @@ class Scan extends Base { ); } + public function checkScanWarning($fullPath, OutputInterface $output) { + $normalizedPath = basename(\OC\Files\Filesystem::normalizePath($fullPath)); + $path = basename($fullPath); + + if ($normalizedPath !== $path) { + $output->writeln("\t<error>Entry \"" . $fullPath . '" will not be accessible due to incompatible encoding</error>'); + } + } + protected function scanFiles($user, $path, $verbose, OutputInterface $output) { $scanner = new \OC\Files\Utils\Scanner($user, \OC::$server->getDatabaseConnection(), \OC::$server->getLogger()); # check on each file/folder if there was a user interrupt (ctrl-c) and throw an exception @@ -126,6 +135,12 @@ class Scan extends Base { } }); } + $scanner->listen('\OC\Files\Utils\Scanner', 'scanFile', function($path) use ($output) { + $this->checkScanWarning($path, $output); + }); + $scanner->listen('\OC\Files\Utils\Scanner', 'scanFolder', function($path) use ($output) { + $this->checkScanWarning($path, $output); + }); try { $scanner->scan($path); @@ -133,7 +148,9 @@ class Scan extends Base { $output->writeln("<error>Home storage for user $user not writable</error>"); $output->writeln("Make sure you're running the scan command only as the user the web server runs as"); } catch (\Exception $e) { - # exit the function if ctrl-c has been pressed + if ($e->getMessage() !== 'ctrl-c') { + $output->writeln('<error>Exception while scanning: ' . $e->getMessage() . "\n" . $e->getTraceAsString() . '</error>'); + } return; } } diff --git a/apps/files/l10n/nn_NO.js b/apps/files/l10n/nn_NO.js index 1e138d91b85..ee983939e7d 100644 --- a/apps/files/l10n/nn_NO.js +++ b/apps/files/l10n/nn_NO.js @@ -17,6 +17,7 @@ OC.L10N.register( "Upload failed. Could not get file info." : "Feil ved opplasting. Klarte ikkje å henta filinfo.", "Invalid directory." : "Ugyldig mappe.", "Files" : "Filer", + "All files" : "Alle filer", "Favorites" : "Favorittar", "Home" : "Heime", "Close" : "Lukk", diff --git a/apps/files/l10n/nn_NO.json b/apps/files/l10n/nn_NO.json index 5645a61b6bc..ec9b4efef11 100644 --- a/apps/files/l10n/nn_NO.json +++ b/apps/files/l10n/nn_NO.json @@ -15,6 +15,7 @@ "Upload failed. Could not get file info." : "Feil ved opplasting. Klarte ikkje å henta filinfo.", "Invalid directory." : "Ugyldig mappe.", "Files" : "Filer", + "All files" : "Alle filer", "Favorites" : "Favorittar", "Home" : "Heime", "Close" : "Lukk", diff --git a/apps/files/l10n/ru.js b/apps/files/l10n/ru.js index 183953629a2..8e20c65f548 100644 --- a/apps/files/l10n/ru.js +++ b/apps/files/l10n/ru.js @@ -105,6 +105,7 @@ OC.L10N.register( "With PHP-FPM it might take 5 minutes for changes to be applied." : "В режиме PHP-FPM применение изменений может занять до 5 минут.", "Missing permissions to edit from here." : "Отсутствуют права на удаление.", "Settings" : "Настройки", + "Show hidden files" : "Показать скрытые файлы", "WebDAV" : "WebDAV", "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">access your Files via WebDAV</a>" : "Используйте этот адрес для <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">для доступа к вашим файлам по WebDAV</a>", "Cancel upload" : "Отменить загрузку", diff --git a/apps/files/l10n/ru.json b/apps/files/l10n/ru.json index f75736df6ba..d4f8617e343 100644 --- a/apps/files/l10n/ru.json +++ b/apps/files/l10n/ru.json @@ -103,6 +103,7 @@ "With PHP-FPM it might take 5 minutes for changes to be applied." : "В режиме PHP-FPM применение изменений может занять до 5 минут.", "Missing permissions to edit from here." : "Отсутствуют права на удаление.", "Settings" : "Настройки", + "Show hidden files" : "Показать скрытые файлы", "WebDAV" : "WebDAV", "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">access your Files via WebDAV</a>" : "Используйте этот адрес для <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">для доступа к вашим файлам по WebDAV</a>", "Cancel upload" : "Отменить загрузку", diff --git a/apps/files/tests/activitytest.php b/apps/files/tests/activitytest.php index 5e73ff0b5dd..bc062dd0542 100644 --- a/apps/files/tests/activitytest.php +++ b/apps/files/tests/activitytest.php @@ -33,7 +33,7 @@ use Test\TestCase; */ class ActivityTest extends TestCase { - /** @var \OC\ActivityManager */ + /** @var \OCP\Activity\IManager */ private $activityManager; /** @var \OCP\IRequest|\PHPUnit_Framework_MockObject_MockObject */ @@ -70,7 +70,7 @@ class ActivityTest extends TestCase { ->disableOriginalConstructor() ->getMock(); - $this->activityManager = new \OC\ActivityManager( + $this->activityManager = new \OC\Activity\Manager( $this->request, $this->session, $this->config diff --git a/apps/files_external/lib/storage/smb.php b/apps/files_external/lib/storage/smb.php index 4249d13168c..868c52a63b4 100644 --- a/apps/files_external/lib/storage/smb.php +++ b/apps/files_external/lib/storage/smb.php @@ -100,7 +100,7 @@ class SMB extends \OC\Files\Storage\Common { * @return string */ protected function buildPath($path) { - return Filesystem::normalizePath($this->root . '/' . $path); + return Filesystem::normalizePath($this->root . '/' . $path, true, false, true); } /** diff --git a/apps/files_sharing/api/share20ocs.php b/apps/files_sharing/api/share20ocs.php index 68098530017..af762845326 100644 --- a/apps/files_sharing/api/share20ocs.php +++ b/apps/files_sharing/api/share20ocs.php @@ -28,11 +28,12 @@ use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUser; use OCP\Files\IRootFolder; +use OCP\Lock\LockedException; use OCP\Share; use OCP\Share\IManager; - use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\Exceptions\GenericShareException; +use OCP\Lock\ILockingProvider; /** * Class Share20OCS @@ -205,12 +206,21 @@ class Share20OCS { return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); } + try { + $share->getNode()->lock(ILockingProvider::LOCK_SHARED); + } catch (LockedException $e) { + return new \OC_OCS_Result(null, 404, 'could not delete share'); + } + if (!$this->canAccessShare($share)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Could not delete share')); } $this->shareManager->deleteShare($share); + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(); } @@ -233,12 +243,18 @@ class Share20OCS { $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); try { $path = $userFolder->get($path); - } catch (\OCP\Files\NotFoundException $e) { + } catch (NotFoundException $e) { return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); } $share->setNode($path); + try { + $share->getNode()->lock(ILockingProvider::LOCK_SHARED); + } catch (LockedException $e) { + return new \OC_OCS_Result(null, 404, 'Could not create share'); + } + // Parse permissions (if available) $permissions = $this->request->getParam('permissions', null); if ($permissions === null) { @@ -248,6 +264,7 @@ class Share20OCS { } if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, 'invalid permissions'); } @@ -275,17 +292,20 @@ class Share20OCS { if ($shareType === \OCP\Share::SHARE_TYPE_USER) { // Valid user is required to share if ($shareWith === null || !$this->userManager->userExists($shareWith)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid user')); } $share->setSharedWith($shareWith); $share->setPermissions($permissions); } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) { if (!$this->shareManager->allowGroupSharing()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Group sharing is disabled by the administrator')); } // Valid group is required to share if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid group')); } $share->setSharedWith($shareWith); @@ -293,6 +313,7 @@ class Share20OCS { } else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) { //Can we even share links? if (!$this->shareManager->shareApiAllowLinks()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Public link sharing is disabled by the administrator')); } @@ -302,6 +323,7 @@ class Share20OCS { */ $existingShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0); if (!empty($existingShares)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result($this->formatShare($existingShares[0])); } @@ -309,11 +331,13 @@ class Share20OCS { if ($publicUpload === 'true') { // Check if public upload is allowed if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); } // Public upload can only be set for folders if ($path instanceof \OCP\Files\File) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Public upload is only possible for publicly shared folders')); } @@ -341,18 +365,21 @@ class Share20OCS { $expireDate = $this->parseDate($expireDate); $share->setExpirationDate($expireDate); } catch (\Exception $e) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Invalid date, date format must be YYYY-MM-DD')); } } } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 403, $this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType])); } $share->setSharedWith($shareWith); $share->setPermissions($permissions); } else { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, $this->l->t('Unknown share type')); } @@ -363,13 +390,18 @@ class Share20OCS { $share = $this->shareManager->createShare($share); } catch (GenericShareException $e) { $code = $e->getCode() === 0 ? 403 : $e->getCode(); + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, $code, $e->getHint()); }catch (\Exception $e) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 403, $e->getMessage()); } - $share = $this->formatShare($share); - return new \OC_OCS_Result($share); + $output = $this->formatShare($share); + + $share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + return new \OC_OCS_Result($output); } /** @@ -454,17 +486,28 @@ class Share20OCS { $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); try { $path = $userFolder->get($path); + $path->lock(ILockingProvider::LOCK_SHARED); } catch (\OCP\Files\NotFoundException $e) { return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); + } catch (LockedException $e) { + return new \OC_OCS_Result(null, 404, $this->l->t('Could not lock path')); } } if ($sharedWithMe === 'true') { - return $this->getSharedWithMe($path); + $result = $this->getSharedWithMe($path); + if ($path !== null) { + $path->unlock(ILockingProvider::LOCK_SHARED); + } + return $result; } if ($subfiles === 'true') { - return $this->getSharesInDir($path); + $result = $this->getSharesInDir($path); + if ($path !== null) { + $path->unlock(ILockingProvider::LOCK_SHARED); + } + return $result; } if ($reshares === 'true') { @@ -494,6 +537,10 @@ class Share20OCS { } } + if ($path !== null) { + $path->unlock(ILockingProvider::LOCK_SHARED); + } + return new \OC_OCS_Result($formatted); } @@ -512,7 +559,10 @@ class Share20OCS { return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); } + $share->getNode()->lock(\OCP\Lock\ILockingProvider::LOCK_SHARED); + if (!$this->canAccessShare($share)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); } @@ -526,6 +576,7 @@ class Share20OCS { */ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); } @@ -543,15 +594,18 @@ class Share20OCS { if ($newPermissions !== null && $newPermissions !== \OCP\Constants::PERMISSION_READ && $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); } if ($newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); } if (!($share->getNode() instanceof \OCP\Files\Folder)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders')); } } @@ -566,6 +620,7 @@ class Share20OCS { try { $expireDate = $this->parseDate($expireDate); } catch (\Exception $e) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, $e->getMessage()); } $share->setExpirationDate($expireDate); @@ -580,6 +635,7 @@ class Share20OCS { } else { // For other shares only permissions is valid. if ($permissions === null) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, $this->l->t('Wrong or no update parameter given')); } else { $permissions = (int)$permissions; @@ -599,6 +655,7 @@ class Share20OCS { } if ($share->getPermissions() & ~$maxPermissions) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 404, $this->l->t('Cannot increase permissions')); } } @@ -608,9 +665,12 @@ class Share20OCS { try { $share = $this->shareManager->updateShare($share); } catch (\Exception $e) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); return new \OC_OCS_Result(null, 400, $e->getMessage()); } + $share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result($this->formatShare($share)); } diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index e0cbfd7f5ba..da573d11ec5 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -33,13 +33,6 @@ $l = \OC::$server->getL10N('files_sharing'); \OC::$CLASSPATH['OC_Share_Backend_File'] = 'files_sharing/lib/share/file.php'; \OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'files_sharing/lib/share/folder.php'; \OC::$CLASSPATH['OC\Files\Storage\Shared'] = 'files_sharing/lib/sharedstorage.php'; -\OC::$CLASSPATH['OC\Files\Cache\SharedScanner'] = 'files_sharing/lib/scanner.php'; -\OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'files_sharing/lib/cache.php'; -\OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'files_sharing/lib/permissions.php'; -\OC::$CLASSPATH['OC\Files\Cache\Shared_Updater'] = 'files_sharing/lib/updater.php'; -\OC::$CLASSPATH['OC\Files\Cache\Shared_Watcher'] = 'files_sharing/lib/watcher.php'; -\OC::$CLASSPATH['OCA\Files\Share\Maintainer'] = 'files_sharing/lib/maintainer.php'; -\OC::$CLASSPATH['OCA\Files\Share\Proxy'] = 'files_sharing/lib/proxy.php'; $application = new Application(); $application->registerMountProviders(); diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 4dcdaa892ad..abd75282579 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -23,7 +23,7 @@ * */ -namespace OC\Files\Cache; +namespace OCA\Files_Sharing; use OC\Files\Cache\Wrapper\CacheJail; use OCP\Files\Cache\ICacheEntry; @@ -34,7 +34,7 @@ use OCP\Files\Storage\IStorage; * * don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead */ -class Shared_Cache extends CacheJail { +class Cache extends CacheJail { /** * @var \OC\Files\Storage\Shared */ diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php index 8dad84eca49..500d82cb2d2 100644 --- a/apps/files_sharing/lib/helper.php +++ b/apps/files_sharing/lib/helper.php @@ -36,9 +36,9 @@ use OCP\User; class Helper { public static function registerHooks() { - \OCP\Util::connectHook('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Shared_Updater', 'renameHook'); + \OCP\Util::connectHook('OC_Filesystem', 'post_rename', '\OCA\Files_Sharing\Updater', 'renameHook'); \OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren'); - \OCP\Util::connectHook('OC_Appconfig', 'post_set_value', '\OCA\Files\Share\Maintainer', 'configChangeHook'); + \OCP\Util::connectHook('OC_Appconfig', 'post_set_value', '\OCA\Files_Sharing\Maintainer', 'configChangeHook'); \OCP\Util::connectHook('OC_User', 'post_deleteUser', '\OCA\Files_Sharing\Hooks', 'deleteUser'); } diff --git a/apps/files_sharing/lib/maintainer.php b/apps/files_sharing/lib/maintainer.php index a728f6bbb67..1d06a34bd0c 100644 --- a/apps/files_sharing/lib/maintainer.php +++ b/apps/files_sharing/lib/maintainer.php @@ -20,7 +20,7 @@ * */ -namespace OCA\Files\Share; +namespace OCA\Files_Sharing; /** * Maintains stuff around the sharing functionality diff --git a/apps/files_sharing/lib/scanner.php b/apps/files_sharing/lib/scanner.php index 2e951423aa2..215c0a7b6ae 100644 --- a/apps/files_sharing/lib/scanner.php +++ b/apps/files_sharing/lib/scanner.php @@ -21,15 +21,14 @@ * */ -namespace OC\Files\Cache; +namespace OCA\Files_Sharing; use OC\Files\ObjectStore\NoopScanner; -use OC\Files\Storage\Shared; /** * Scanner for SharedStorage */ -class SharedScanner extends Scanner { +class Scanner extends \OC\Files\Cache\Scanner { private $sourceScanner; /** diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 1a040364f11..ce214822aa7 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -318,14 +318,14 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { if (!$storage) { $storage = $this; } - return new \OC\Files\Cache\Shared_Cache($storage, $this->sourceStorage, $this->sourceRootInfo); + return new \OCA\Files_Sharing\Cache($storage, $this->sourceStorage, $this->sourceRootInfo); } public function getScanner($path = '', $storage = null) { if (!$storage) { $storage = $this; } - return new \OC\Files\Cache\SharedScanner($storage); + return new \OCA\Files_Sharing\Scanner($storage); } public function getPropagator($storage = null) { diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index de68e2ea0fc..02c349e94b6 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -25,9 +25,9 @@ * */ -namespace OC\Files\Cache; +namespace OCA\Files_Sharing; -class Shared_Updater { +class Updater { /** * @param array $params @@ -85,21 +85,6 @@ class Shared_Updater { } /** - * clean up oc_share table from files which are no longer exists - * - * This fixes issues from updates from files_sharing < 0.3.5.6 (ownCloud 4.5) - * It will just be called during the update of the app - */ - static public function fixBrokenSharesOnAppUpdate() { - // delete all shares where the original file no longer exists - $findAndRemoveShares = \OCP\DB::prepare('DELETE FROM `*PREFIX*share` ' . - 'WHERE `item_type` IN (\'file\', \'folder\') ' . - 'AND `file_source` NOT IN (SELECT `fileid` FROM `*PREFIX*filecache`)' - ); - $findAndRemoveShares->execute(array()); - } - - /** * rename mount point from the children if the parent was renamed * * @param string $oldPath old path relative to data/user/files diff --git a/apps/files_sharing/tests/api/share20ocstest.php b/apps/files_sharing/tests/api/share20ocstest.php index 56c350aa99a..ffb74da2af7 100644 --- a/apps/files_sharing/tests/api/share20ocstest.php +++ b/apps/files_sharing/tests/api/share20ocstest.php @@ -29,6 +29,7 @@ use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUser; use OCP\Files\IRootFolder; +use OCP\Lock\LockedException; /** * Class Share20OCSTest @@ -137,8 +138,11 @@ class Share20OCSTest extends \Test\TestCase { } public function testDeleteShare() { + $node = $this->getMock('\OCP\Files\File'); + $share = $this->newShare(); - $share->setSharedBy($this->currentUser->getUID()); + $share->setSharedBy($this->currentUser->getUID()) + ->setNode($node); $this->shareManager ->expects($this->once()) ->method('getShareById') @@ -149,10 +153,45 @@ class Share20OCSTest extends \Test\TestCase { ->method('deleteShare') ->with($share); + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $node->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $expected = new \OC_OCS_Result(); $this->assertEquals($expected, $this->ocs->deleteShare(42)); } + public function testDeleteShareLocked() { + $node = $this->getMock('\OCP\Files\File'); + + $share = $this->newShare(); + $share->setSharedBy($this->currentUser->getUID()) + ->setNode($node); + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with('ocinternal:42') + ->willReturn($share); + $this->shareManager + ->expects($this->never()) + ->method('deleteShare') + ->with($share); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED) + ->will($this->throwException(new LockedException('mypath'))); + $node->expects($this->never()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $expected = new \OC_OCS_Result(null, 404, 'could not delete share'); + $this->assertEquals($expected, $this->ocs->deleteShare(42)); + } + /* * FIXME: Enable once we have a federated Share Provider @@ -526,7 +565,7 @@ class Share20OCSTest extends \Test\TestCase { } public function testCreateShareInvalidPermissions() { - $share = $this->getMock('\OCP\Share\IShare'); + $share = $this->newShare(); $this->shareManager->method('newShare')->willReturn($share); $this->request @@ -548,6 +587,10 @@ class Share20OCSTest extends \Test\TestCase { ->with('valid-path') ->willReturn($path); + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $expected = new \OC_OCS_Result(null, 404, 'invalid permissions'); $result = $this->ocs->createShare(); @@ -557,7 +600,7 @@ class Share20OCSTest extends \Test\TestCase { } public function testCreateShareUserNoShareWith() { - $share = $this->getMock('\OCP\Share\IShare'); + $share = $this->newShare(); $this->shareManager->method('newShare')->willReturn($share); $this->request @@ -585,6 +628,10 @@ class Share20OCSTest extends \Test\TestCase { ->with('valid-path') ->willReturn($path); + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); $result = $this->ocs->createShare(); @@ -594,7 +641,7 @@ class Share20OCSTest extends \Test\TestCase { } public function testCreateShareUserNoValidShareWith() { - $share = $this->getMock('\OCP\Share\IShare'); + $share = $this->newShare(); $this->shareManager->method('newShare')->willReturn($share); $this->request @@ -625,6 +672,10 @@ class Share20OCSTest extends \Test\TestCase { $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $result = $this->ocs->createShare(); $this->assertEquals($expected->getMeta(), $result->getMeta()); @@ -632,9 +683,8 @@ class Share20OCSTest extends \Test\TestCase { } public function testCreateShareUser() { - $share = $this->getMock('\OCP\Share\IShare'); + $share = $this->newShare(); $this->shareManager->method('newShare')->willReturn($share); - $this->shareManager->method('createShare')->will($this->returnArgument(0)); $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') ->setConstructorArgs([ @@ -677,15 +727,26 @@ class Share20OCSTest extends \Test\TestCase { $this->userManager->method('userExists')->with('validUser')->willReturn(true); - $share->method('setNode')->with($path); - $share->method('setPermissions') - ->with( - \OCP\Constants::PERMISSION_ALL & - ~\OCP\Constants::PERMISSION_DELETE & - ~\OCP\Constants::PERMISSION_CREATE); - $share->method('setShareType')->with(\OCP\Share::SHARE_TYPE_USER); - $share->method('setSharedWith')->with('validUser'); - $share->method('setSharedBy')->with('currentUser'); + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $path->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('createShare') + ->with($this->callback(function (\OCP\Share\IShare $share) use ($path) { + return $share->getNode() === $path && + $share->getPermissions() === ( + \OCP\Constants::PERMISSION_ALL & + ~\OCP\Constants::PERMISSION_DELETE & + ~\OCP\Constants::PERMISSION_CREATE + ) && + $share->getShareType() === \OCP\Share::SHARE_TYPE_USER && + $share->getSharedWith() === 'validUser' && + $share->getSharedBy() === 'currentUser'; + })) + ->will($this->returnArgument(0)); $expected = new \OC_OCS_Result(); $result = $ocs->createShare(); @@ -695,7 +756,7 @@ class Share20OCSTest extends \Test\TestCase { } public function testCreateShareGroupNoValidShareWith() { - $share = $this->getMock('\OCP\Share\IShare'); + $share = $this->newShare(); $this->shareManager->method('newShare')->willReturn($share); $this->shareManager->method('createShare')->will($this->returnArgument(0)); @@ -727,6 +788,10 @@ class Share20OCSTest extends \Test\TestCase { $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $result = $this->ocs->createShare(); $this->assertEquals($expected->getMeta(), $result->getMeta()); @@ -734,9 +799,8 @@ class Share20OCSTest extends \Test\TestCase { } public function testCreateShareGroup() { - $share = $this->getMock('\OCP\Share\IShare'); + $share = $this->newShare(); $this->shareManager->method('newShare')->willReturn($share); - $this->shareManager->method('createShare')->will($this->returnArgument(0)); $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') ->setConstructorArgs([ @@ -783,11 +847,22 @@ class Share20OCSTest extends \Test\TestCase { ->method('allowGroupSharing') ->willReturn(true); - $share->method('setNode')->with($path); - $share->method('setPermissions')->with(\OCP\Constants::PERMISSION_ALL); - $share->method('setShareType')->with(\OCP\Share::SHARE_TYPE_GROUP); - $share->method('setSharedWith')->with('validGroup'); - $share->method('setSharedBy')->with('currentUser'); + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $path->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('createShare') + ->with($this->callback(function (\OCP\Share\IShare $share) use ($path) { + return $share->getNode() === $path && + $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && + $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && + $share->getSharedWith() === 'validGroup' && + $share->getSharedBy() === 'currentUser'; + })) + ->will($this->returnArgument(0)); $expected = new \OC_OCS_Result(); $result = $ocs->createShare(); @@ -797,7 +872,7 @@ class Share20OCSTest extends \Test\TestCase { } public function testCreateShareGroupNotAllowed() { - $share = $this->getMock('\OCP\Share\IShare'); + $share = $this->newShare(); $this->shareManager->method('newShare')->willReturn($share); $this->request @@ -832,9 +907,8 @@ class Share20OCSTest extends \Test\TestCase { ->method('allowGroupSharing') ->willReturn(false); - $share->method('setNode')->with($path); - $expected = new \OC_OCS_Result(null, 404, 'Group sharing is disabled by the administrator'); + $result = $this->ocs->createShare(); $this->assertEquals($expected->getMeta(), $result->getMeta()); @@ -1154,7 +1228,13 @@ class Share20OCSTest extends \Test\TestCase { } public function testUpdateShareCantAccess() { - $share = \OC::$server->getShareManager()->newShare(); + $node = $this->getMock('\OCP\Files\Folder'); + $share = $this->newShare(); + $share->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); @@ -1166,10 +1246,16 @@ class Share20OCSTest extends \Test\TestCase { } public function testUpdateNoParametersLink() { - $share = \OC::$server->getShareManager()->newShare(); + $node = $this->getMock('\OCP\Files\Folder'); + $share = $this->newShare(); $share->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK); + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); @@ -1181,10 +1267,16 @@ class Share20OCSTest extends \Test\TestCase { } public function testUpdateNoParametersOther() { - $share = \OC::$server->getShareManager()->newShare(); + $node = $this->getMock('\OCP\Files\Folder'); + $share = $this->newShare(); $share->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_GROUP); + ->setShareType(\OCP\Share::SHARE_TYPE_GROUP) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); @@ -1198,13 +1290,22 @@ class Share20OCSTest extends \Test\TestCase { public function testUpdateLinkShareClear() { $ocs = $this->mockFormatShare(); - $share = \OC::$server->getShareManager()->newShare(); + $node = $this->getMock('\OCP\Files\Folder'); + $share = $this->newShare(); $share->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setSharedBy($this->currentUser->getUID()) ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') ->setExpirationDate(new \DateTime()) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $node->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); $this->request ->method('getParam') @@ -1364,13 +1465,22 @@ class Share20OCSTest extends \Test\TestCase { $date = new \DateTime('2000-01-01'); $date->setTime(0,0,0); - $share = \OC::$server->getShareManager()->newShare(); + $node = $this->getMock('\OCP\Files\File'); + $share = $this->newShare(); $share->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setSharedBy($this->currentUser->getUID()) ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') ->setExpirationDate($date) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $node->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); $this->request ->method('getParam') @@ -1398,13 +1508,15 @@ class Share20OCSTest extends \Test\TestCase { public function testUpdateLinkShareExpireDateDoesNotChangeOther() { $ocs = $this->mockFormatShare(); - $share = \OC::$server->getShareManager()->newShare(); + $node = $this->getMock('\OCP\Files\File'); + $share = $this->newShare(); $share->setPermissions(\OCP\Constants::PERMISSION_ALL) ->setSharedBy($this->currentUser->getUID()) ->setShareType(\OCP\Share::SHARE_TYPE_LINK) ->setPassword('password') ->setExpirationDate(new \DateTime()) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); $this->request ->method('getParam') @@ -1412,6 +1524,13 @@ class Share20OCSTest extends \Test\TestCase { ['expireDate', null, '2010-12-23'], ])); + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $node->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); $this->shareManager->expects($this->once())->method('updateShare')->with( diff --git a/core/Command/Log/Manage.php b/core/Command/Log/Manage.php index 1d65d7ed0d8..aeaaca8aa0e 100644 --- a/core/Command/Log/Manage.php +++ b/core/Command/Log/Manage.php @@ -115,7 +115,7 @@ class Manage extends Command { * @throws \InvalidArgumentException */ protected function validateBackend($backend) { - if (!class_exists('OC_Log_'.$backend)) { + if (!class_exists('OC\\Log\\'.ucfirst($backend))) { throw new \InvalidArgumentException('Invalid backend'); } } diff --git a/core/l10n/ru.js b/core/l10n/ru.js index d52a9b6a4e3..fd81ae62fc3 100644 --- a/core/l10n/ru.js +++ b/core/l10n/ru.js @@ -27,6 +27,11 @@ OC.L10N.register( "Error unfavoriting" : "Ошибка удаления из избранного", "Couldn't send mail to following users: %s " : "Невозможно отправить письмо следующим пользователям: %s", "Preparing update" : "Подготовка к обновлению", + "[%d / %d]: %s" : "[%d / %d]: %s", + "Repair warning: " : "Предупреждение восстановления:", + "Repair error: " : "Ошибка восстановления:", + "Please use the command line updater because automatic updating is disabled in the config.php." : "Пожалуйста, используйте обновление через командную строку, так как автоматические обновления отключены в config.php.", + "[%d / %d]: Checking table %s" : "[%d / %d]: Проверка таблицы %s", "Turned on maintenance mode" : "Режим отладки включён", "Turned off maintenance mode" : "Режим отладки отключён", "Maintenance mode is kept active" : "Режим обслуживания оставлен включенным", @@ -38,8 +43,6 @@ OC.L10N.register( "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "Проверка возможности обновления схемы базы данных для %s (это может занять длительное время в зависимости от размера базы данных)", "Checked database schema update for apps" : "Проверено обновление схемы БД приложений", "Updated \"%s\" to %s" : "Обновлено \"%s\" до %s", - "Repair warning: " : "Предупреждение восстановления:", - "Repair error: " : "Ошибка восстановления:", "Set log level to debug" : "Установить журнал в режим отладки", "Reset log level" : "Сбросить уровень журнала", "Starting code integrity check" : "Начинается проверка целостности кода", @@ -95,6 +98,7 @@ OC.L10N.register( "Dec." : "Дек.", "<a href=\"{docUrl}\">There were problems with the code integrity check. More information…</a>" : "<a href=\"{docUrl}\"> Были обнаружены проблемы с проверкой целостности кода. Подробнее ...", "Settings" : "Настройки", + "Problem loading page, reloading in 5 seconds" : "Возникла проблема при загрузке страницы, повтор через 5 секунд", "Saving..." : "Сохранение...", "Dismiss" : "Прекратить", "seconds ago" : "несколько секунд назад", @@ -129,6 +133,7 @@ OC.L10N.register( "Your web server is not set up properly to resolve \"{url}\". Further information can be found in our <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">documentation</a>." : "Ваш веб-сервер настроен не корректно для разрешения \"{url}\". Дополнительная информация может быть найдена в нашей <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">документации</a>.", "This server has no working Internet connection. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. We suggest to enable Internet connection for this server if you want to have all features." : "Этот сервер не имеет подключения к Интернету. Это означает, что некоторые из функций, таких как внешнее хранилище, уведомления об обновлениях и установка сторонних приложений не будут работать. Доступ к файлам удаленно и отправки уведомлений по почте могут не работать. Рекомендуется разрешить данному серверу доступ в Интернет если хотите, чтобы все функции работали.", "No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">documentation</a>." : "Не настроена система кеширования. Для увеличения производительности сервера, по возможности, настройте memcache. Более подробная информация в нашей <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">документации</a>.", + "/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">documentation</a>." : "/dev/urandom не может быть прочитан из PHP, что крайне нежелательно по соображениям безопасности. Дополнительную информацию можно найти в нашей <a target=\"_blank\" href=\"{docLink}\"> документации </a>.", "Error occurred while checking server setup" : "Произошла ошибка при проверке настроек сервера", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Ваш каталог данных и ваши файлы возможно доступны из Интернета. Файл .htaccess не работает. Мы настоятельно рекомендуем Вам настроить веб сервер таким образом, чтобы каталог данных не был больше доступен или переместить каталог данных за пределы корня веб сервера.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "Заголовок HTTP \"{header}\" не настроен на значение \"{expected}\". Это потенциальная проблема безопасности и мы рекомендуем изменить эти настройки.", @@ -154,6 +159,7 @@ OC.L10N.register( "Send" : "Отправить", "Sending ..." : "Отправляется ...", "Email sent" : "Письмо отправлено", + "Send link via email" : "Отправить ссылку по email", "Shared with you and the group {group} by {owner}" : "{owner} поделился с вами и группой {group} ", "Shared with you by {owner}" : "С вами поделился {owner} ", "group" : "группа", @@ -169,11 +175,17 @@ OC.L10N.register( "Could not unshare" : "Не удается отменить доступ", "Share details could not be loaded for this item." : "Не удалось загрузить информацию об общем доступе для этого элемента.", "No users or groups found for {search}" : "Не найдено пользователей или групп по запросу {search}", + "No users found for {search}" : "Не найдено пользователей по запросу {search}", + "An error occurred. Please try again" : "Произошла ошибка. Попробуйте ещё раз", "{sharee} (group)" : "{sharee} (группа)", "{sharee} (at {server})" : "{sharee} (на {server})", "{sharee} (remote)" : "{sharee} (удалённо)", "Share" : "Поделиться", "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Поделиться с людьми на других серверах ownCloud используя формат username@example.com/owncloud", + "Share with users…" : "Поделиться с пользователями...", + "Share with users, groups or remote users…" : "Поделиться с пользователями, группами или удаленными пользователями...", + "Share with users or groups…" : "Поделиться с пользователями или группами...", + "Share with users or remote users…" : "Общий доступ с пользователями или удалеными пользователями", "Error removing share" : "Ошибка удаления общего доступа", "Warning" : "Предупреждение", "Error while sending notification" : "Ошибка при отправке уведомления", @@ -183,6 +195,7 @@ OC.L10N.register( "({scope})" : "({scope})", "Delete" : "Удалить", "Rename" : "Переименовать", + "Collaborative tags" : "Совместные теги", "The object type is not specified." : "Тип объекта не указан", "Enter new" : "Ввести новое", "Add" : "Добавить", @@ -197,6 +210,7 @@ OC.L10N.register( "new" : "новый", "_download %n file_::_download %n files_" : ["скачать %n файл","скачать %n файла","скачать %n файлов","скачать %n файлов"], "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "Идет обновление. Покидая эту страницу, вы можете прервать процесс обновления.", + "Updating to {version}" : "Обновляем до {version}", "An error occurred." : "Произошла ошибка.", "Please reload the page." : "Пожалуйста, обновите страницу.", "The update was unsuccessful. For more information <a href=\"{url}\">check our forum post</a> covering this issue." : "Обновление прошло не успешно. За дополнительной информацией по этой проблеме <a href=\"{url}\">обратитесь к нашему форуму</a>.", @@ -260,6 +274,7 @@ OC.L10N.register( "Search" : "Найти", "Server side authentication failed!" : "Ошибка аутентификации на стороне сервера!", "Please contact your administrator." : "Пожалуйста, обратитесь к администратору.", + "An internal error occurred." : "Произошла внутренняя ошибка.", "Please try again or contact your administrator." : "Пожалуйста попробуйте ещё раз или свяжитесь с вашим администратором", "Log in" : "Войти", "Wrong password. Reset it?" : "Неправильный пароль. Сбросить его?", @@ -286,6 +301,9 @@ OC.L10N.register( "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "Перед продолжением убедитесь, что вы сделали резервную копию базы данных, каталога конфигурации и каталога с данными.", "Start update" : "Запустить обновление", "To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" : "Чтобы избежать тайм-аутов в крупных установках, вместо этого можно выполнить следующую команду в каталоге установки:", + "Detailed logs" : "Подбробные логи", + "Update needed" : "Требуется обновление", + "For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Для помощи, ознакомьтесь с <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">документацией</a>.", "This %s instance is currently in maintenance mode, which may take a while." : "Этот сервер %s находится в режиме технического обслуживания, которое может занять некоторое время.", "This page will refresh itself when the %s instance is available again." : "Эта страница автоматически обновится, когда сервер %s снова станет доступен." }, diff --git a/core/l10n/ru.json b/core/l10n/ru.json index 36e5a2ab8a5..062231026d2 100644 --- a/core/l10n/ru.json +++ b/core/l10n/ru.json @@ -25,6 +25,11 @@ "Error unfavoriting" : "Ошибка удаления из избранного", "Couldn't send mail to following users: %s " : "Невозможно отправить письмо следующим пользователям: %s", "Preparing update" : "Подготовка к обновлению", + "[%d / %d]: %s" : "[%d / %d]: %s", + "Repair warning: " : "Предупреждение восстановления:", + "Repair error: " : "Ошибка восстановления:", + "Please use the command line updater because automatic updating is disabled in the config.php." : "Пожалуйста, используйте обновление через командную строку, так как автоматические обновления отключены в config.php.", + "[%d / %d]: Checking table %s" : "[%d / %d]: Проверка таблицы %s", "Turned on maintenance mode" : "Режим отладки включён", "Turned off maintenance mode" : "Режим отладки отключён", "Maintenance mode is kept active" : "Режим обслуживания оставлен включенным", @@ -36,8 +41,6 @@ "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "Проверка возможности обновления схемы базы данных для %s (это может занять длительное время в зависимости от размера базы данных)", "Checked database schema update for apps" : "Проверено обновление схемы БД приложений", "Updated \"%s\" to %s" : "Обновлено \"%s\" до %s", - "Repair warning: " : "Предупреждение восстановления:", - "Repair error: " : "Ошибка восстановления:", "Set log level to debug" : "Установить журнал в режим отладки", "Reset log level" : "Сбросить уровень журнала", "Starting code integrity check" : "Начинается проверка целостности кода", @@ -93,6 +96,7 @@ "Dec." : "Дек.", "<a href=\"{docUrl}\">There were problems with the code integrity check. More information…</a>" : "<a href=\"{docUrl}\"> Были обнаружены проблемы с проверкой целостности кода. Подробнее ...", "Settings" : "Настройки", + "Problem loading page, reloading in 5 seconds" : "Возникла проблема при загрузке страницы, повтор через 5 секунд", "Saving..." : "Сохранение...", "Dismiss" : "Прекратить", "seconds ago" : "несколько секунд назад", @@ -127,6 +131,7 @@ "Your web server is not set up properly to resolve \"{url}\". Further information can be found in our <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">documentation</a>." : "Ваш веб-сервер настроен не корректно для разрешения \"{url}\". Дополнительная информация может быть найдена в нашей <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">документации</a>.", "This server has no working Internet connection. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. We suggest to enable Internet connection for this server if you want to have all features." : "Этот сервер не имеет подключения к Интернету. Это означает, что некоторые из функций, таких как внешнее хранилище, уведомления об обновлениях и установка сторонних приложений не будут работать. Доступ к файлам удаленно и отправки уведомлений по почте могут не работать. Рекомендуется разрешить данному серверу доступ в Интернет если хотите, чтобы все функции работали.", "No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">documentation</a>." : "Не настроена система кеширования. Для увеличения производительности сервера, по возможности, настройте memcache. Более подробная информация в нашей <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">документации</a>.", + "/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">documentation</a>." : "/dev/urandom не может быть прочитан из PHP, что крайне нежелательно по соображениям безопасности. Дополнительную информацию можно найти в нашей <a target=\"_blank\" href=\"{docLink}\"> документации </a>.", "Error occurred while checking server setup" : "Произошла ошибка при проверке настроек сервера", "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Ваш каталог данных и ваши файлы возможно доступны из Интернета. Файл .htaccess не работает. Мы настоятельно рекомендуем Вам настроить веб сервер таким образом, чтобы каталог данных не был больше доступен или переместить каталог данных за пределы корня веб сервера.", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "Заголовок HTTP \"{header}\" не настроен на значение \"{expected}\". Это потенциальная проблема безопасности и мы рекомендуем изменить эти настройки.", @@ -152,6 +157,7 @@ "Send" : "Отправить", "Sending ..." : "Отправляется ...", "Email sent" : "Письмо отправлено", + "Send link via email" : "Отправить ссылку по email", "Shared with you and the group {group} by {owner}" : "{owner} поделился с вами и группой {group} ", "Shared with you by {owner}" : "С вами поделился {owner} ", "group" : "группа", @@ -167,11 +173,17 @@ "Could not unshare" : "Не удается отменить доступ", "Share details could not be loaded for this item." : "Не удалось загрузить информацию об общем доступе для этого элемента.", "No users or groups found for {search}" : "Не найдено пользователей или групп по запросу {search}", + "No users found for {search}" : "Не найдено пользователей по запросу {search}", + "An error occurred. Please try again" : "Произошла ошибка. Попробуйте ещё раз", "{sharee} (group)" : "{sharee} (группа)", "{sharee} (at {server})" : "{sharee} (на {server})", "{sharee} (remote)" : "{sharee} (удалённо)", "Share" : "Поделиться", "Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Поделиться с людьми на других серверах ownCloud используя формат username@example.com/owncloud", + "Share with users…" : "Поделиться с пользователями...", + "Share with users, groups or remote users…" : "Поделиться с пользователями, группами или удаленными пользователями...", + "Share with users or groups…" : "Поделиться с пользователями или группами...", + "Share with users or remote users…" : "Общий доступ с пользователями или удалеными пользователями", "Error removing share" : "Ошибка удаления общего доступа", "Warning" : "Предупреждение", "Error while sending notification" : "Ошибка при отправке уведомления", @@ -181,6 +193,7 @@ "({scope})" : "({scope})", "Delete" : "Удалить", "Rename" : "Переименовать", + "Collaborative tags" : "Совместные теги", "The object type is not specified." : "Тип объекта не указан", "Enter new" : "Ввести новое", "Add" : "Добавить", @@ -195,6 +208,7 @@ "new" : "новый", "_download %n file_::_download %n files_" : ["скачать %n файл","скачать %n файла","скачать %n файлов","скачать %n файлов"], "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "Идет обновление. Покидая эту страницу, вы можете прервать процесс обновления.", + "Updating to {version}" : "Обновляем до {version}", "An error occurred." : "Произошла ошибка.", "Please reload the page." : "Пожалуйста, обновите страницу.", "The update was unsuccessful. For more information <a href=\"{url}\">check our forum post</a> covering this issue." : "Обновление прошло не успешно. За дополнительной информацией по этой проблеме <a href=\"{url}\">обратитесь к нашему форуму</a>.", @@ -258,6 +272,7 @@ "Search" : "Найти", "Server side authentication failed!" : "Ошибка аутентификации на стороне сервера!", "Please contact your administrator." : "Пожалуйста, обратитесь к администратору.", + "An internal error occurred." : "Произошла внутренняя ошибка.", "Please try again or contact your administrator." : "Пожалуйста попробуйте ещё раз или свяжитесь с вашим администратором", "Log in" : "Войти", "Wrong password. Reset it?" : "Неправильный пароль. Сбросить его?", @@ -284,6 +299,9 @@ "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "Перед продолжением убедитесь, что вы сделали резервную копию базы данных, каталога конфигурации и каталога с данными.", "Start update" : "Запустить обновление", "To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" : "Чтобы избежать тайм-аутов в крупных установках, вместо этого можно выполнить следующую команду в каталоге установки:", + "Detailed logs" : "Подбробные логи", + "Update needed" : "Требуется обновление", + "For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Для помощи, ознакомьтесь с <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">документацией</a>.", "This %s instance is currently in maintenance mode, which may take a while." : "Этот сервер %s находится в режиме технического обслуживания, которое может занять некоторое время.", "This page will refresh itself when the %s instance is available again." : "Эта страница автоматически обновится, когда сервер %s снова станет доступен." },"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);" diff --git a/core/templates/login.php b/core/templates/login.php index 8405bac6890..86c186928cc 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -40,11 +40,11 @@ script('core', [ </div> <p class="grouptop"> <input type="text" name="user" id="user" - placeholder="<?php p($l->t('Username')); ?>" + placeholder="<?php p($l->t('Username or email')); ?>" value="<?php p($_['loginName']); ?>" <?php p($_['user_autofocus'] ? 'autofocus' : ''); ?> autocomplete="on" autocapitalize="off" autocorrect="off" required> - <label for="user" class="infield"><?php p($l->t('Username')); ?></label> + <label for="user" class="infield"><?php p($l->t('Username or email')); ?></label> </p> <p class="groupbottom"> diff --git a/lib/base.php b/lib/base.php index fb58177a432..badbe3cd1f8 100644 --- a/lib/base.php +++ b/lib/base.php @@ -103,6 +103,9 @@ class OC { */ public static $loader = null; + /** @var \Composer\Autoload\ClassLoader $composerAutoloader */ + public static $composerAutoloader = null; + /** * @var \OC\Server */ @@ -493,7 +496,7 @@ class OC { self::$CLI = (php_sapi_name() == 'cli'); // Add default composer PSR-4 autoloader - require_once OC::$SERVERROOT . '/lib/composer/autoload.php'; + self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php'; try { self::initPaths(); diff --git a/lib/private/ActivityManager.php b/lib/private/Activity/Manager.php index e522dca9e3b..e68802b2abb 100644 --- a/lib/private/ActivityManager.php +++ b/lib/private/Activity/Manager.php @@ -20,10 +20,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/> * */ -namespace OC; +namespace OC\Activity; -use OC\Activity\Event; use OCP\Activity\IConsumer; use OCP\Activity\IEvent; use OCP\Activity\IExtension; @@ -33,7 +32,7 @@ use OCP\IRequest; use OCP\IUser; use OCP\IUserSession; -class ActivityManager implements IManager { +class Manager implements IManager { /** @var IRequest */ protected $request; diff --git a/lib/private/App/InfoParser.php b/lib/private/App/InfoParser.php index b7540c04248..e9456550206 100644 --- a/lib/private/App/InfoParser.php +++ b/lib/private/App/InfoParser.php @@ -74,6 +74,9 @@ class InfoParser { if (!array_key_exists('repair-steps', $array)) { $array['repair-steps'] = []; } + if (!array_key_exists('install', $array['repair-steps'])) { + $array['repair-steps']['install'] = []; + } if (!array_key_exists('pre-migration', $array['repair-steps'])) { $array['repair-steps']['pre-migration'] = []; } @@ -83,6 +86,12 @@ class InfoParser { if (!array_key_exists('live-migration', $array['repair-steps'])) { $array['repair-steps']['live-migration'] = []; } + if (!array_key_exists('uninstall', $array['repair-steps'])) { + $array['repair-steps']['uninstall'] = []; + } + if (!array_key_exists('background-jobs', $array)) { + $array['background-jobs'] = []; + } if (array_key_exists('documentation', $array) && is_array($array['documentation'])) { foreach ($array['documentation'] as $key => $url) { @@ -107,6 +116,9 @@ class InfoParser { $array['types'] = []; } } + if (isset($array['repair-steps']['install']['step']) && is_array($array['repair-steps']['install']['step'])) { + $array['repair-steps']['install'] = $array['repair-steps']['install']['step']; + } if (isset($array['repair-steps']['pre-migration']['step']) && is_array($array['repair-steps']['pre-migration']['step'])) { $array['repair-steps']['pre-migration'] = $array['repair-steps']['pre-migration']['step']; } @@ -116,6 +128,12 @@ class InfoParser { if (isset($array['repair-steps']['live-migration']['step']) && is_array($array['repair-steps']['live-migration']['step'])) { $array['repair-steps']['live-migration'] = $array['repair-steps']['live-migration']['step']; } + if (isset($array['repair-steps']['uninstall']['step']) && is_array($array['repair-steps']['uninstall']['step'])) { + $array['repair-steps']['uninstall'] = $array['repair-steps']['uninstall']['step']; + } + if (isset($array['background-jobs']['job']) && is_array($array['background-jobs']['job'])) { + $array['background-jobs'] = $array['background-jobs']['job']; + } return $array; } @@ -135,10 +153,7 @@ class InfoParser { if (!isset($array[$element])) { $array[$element] = ""; } - /** - * @var \SimpleXMLElement $node - */ - + /** @var \SimpleXMLElement $node */ // Has attributes if ($attributes = $node->attributes()) { $data = [ diff --git a/lib/private/legacy/archive.php b/lib/private/Archive/Archive.php index 62512d1448a..b5286968a2f 100644 --- a/lib/private/legacy/archive.php +++ b/lib/private/Archive/Archive.php @@ -28,23 +28,25 @@ * */ -abstract class OC_Archive{ +namespace OC\Archive; + +abstract class Archive{ /** * Open any of the supported archive types * * @param string $path - * @return OC_Archive|void + * @return Archive|void */ public static function open($path) { $mime = \OC::$server->getMimeTypeDetector()->detect($path); switch($mime) { case 'application/zip': - return new OC_Archive_ZIP($path); + return new ZIP($path); case 'application/x-gzip': - return new OC_Archive_TAR($path); + return new TAR($path); case 'application/x-bzip2': - return new OC_Archive_TAR($path); + return new TAR($path); } } diff --git a/lib/private/archive/tar.php b/lib/private/Archive/TAR.php index 20e2e05f238..d783e53d40c 100644 --- a/lib/private/archive/tar.php +++ b/lib/private/Archive/TAR.php @@ -30,7 +30,9 @@ * */ -class OC_Archive_TAR extends OC_Archive { +namespace OC\Archive; + +class TAR extends Archive { const PLAIN = 0; const GZIP = 1; const BZIP = 2; @@ -39,7 +41,7 @@ class OC_Archive_TAR extends OC_Archive { private $cachedHeaders; /** - * @var Archive_Tar tar + * @var \Archive_Tar tar */ private $tar = null; private $path; @@ -50,7 +52,7 @@ class OC_Archive_TAR extends OC_Archive { function __construct($source) { $types = array(null, 'gz', 'bz2'); $this->path = $source; - $this->tar = new Archive_Tar($source, $types[self::getTarType($source)]); + $this->tar = new \Archive_Tar($source, $types[self::getTarType($source)]); } /** @@ -137,13 +139,13 @@ class OC_Archive_TAR extends OC_Archive { */ function rename($source, $dest) { //no proper way to delete, rename entire archive, rename file and remake archive - $tmp = OCP\Files::tmpFolder(); + $tmp = \OCP\Files::tmpFolder(); $this->tar->extract($tmp); rename($tmp . $source, $tmp . $dest); $this->tar = null; unlink($this->path); $types = array(null, 'gz', 'bz'); - $this->tar = new Archive_Tar($this->path, $types[self::getTarType($this->path)]); + $this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]); $this->tar->createModify(array($tmp), '', $tmp . '/'); $this->fileList = false; $this->cachedHeaders = false; @@ -256,7 +258,7 @@ class OC_Archive_TAR extends OC_Archive { * @return bool */ function extractFile($path, $dest) { - $tmp = OCP\Files::tmpFolder(); + $tmp = \OCP\Files::tmpFolder(); if (!$this->fileExists($path)) { return false; } @@ -268,7 +270,7 @@ class OC_Archive_TAR extends OC_Archive { if ($success) { rename($tmp . $path, $dest); } - OCP\Files::rmdirr($tmp); + \OCP\Files::rmdirr($tmp); return $success; } @@ -324,9 +326,9 @@ class OC_Archive_TAR extends OC_Archive { $this->fileList = false; $this->cachedHeaders = false; //no proper way to delete, extract entire archive, delete file and remake archive - $tmp = OCP\Files::tmpFolder(); + $tmp = \OCP\Files::tmpFolder(); $this->tar->extract($tmp); - OCP\Files::rmdirr($tmp . $path); + \OCP\Files::rmdirr($tmp . $path); $this->tar = null; unlink($this->path); $this->reopen(); @@ -347,7 +349,7 @@ class OC_Archive_TAR extends OC_Archive { } else { $ext = ''; } - $tmpFile = OCP\Files::tmpFile($ext); + $tmpFile = \OCP\Files::tmpFile($ext); if ($this->fileExists($path)) { $this->extractFile($path, $tmpFile); } elseif ($mode == 'r' or $mode == 'rb') { @@ -383,6 +385,6 @@ class OC_Archive_TAR extends OC_Archive { $this->tar = null; } $types = array(null, 'gz', 'bz'); - $this->tar = new Archive_Tar($this->path, $types[self::getTarType($this->path)]); + $this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]); } } diff --git a/lib/private/archive/zip.php b/lib/private/Archive/ZIP.php index 0d8d3b7ce76..2bc17507d32 100644 --- a/lib/private/archive/zip.php +++ b/lib/private/Archive/ZIP.php @@ -27,9 +27,11 @@ * */ -class OC_Archive_ZIP extends OC_Archive{ +namespace OC\Archive; + +class ZIP extends Archive{ /** - * @var ZipArchive zip + * @var \ZipArchive zip */ private $zip=null; private $path; @@ -39,10 +41,10 @@ class OC_Archive_ZIP extends OC_Archive{ */ function __construct($source) { $this->path=$source; - $this->zip=new ZipArchive(); - if($this->zip->open($source, ZipArchive::CREATE)) { + $this->zip=new \ZipArchive(); + if($this->zip->open($source, \ZipArchive::CREATE)) { }else{ - OCP\Util::writeLog('files_archive', 'Error while opening archive '.$source, OCP\Util::WARN); + \OCP\Util::writeLog('files_archive', 'Error while opening archive '.$source, \OCP\Util::WARN); } } /** @@ -193,7 +195,7 @@ class OC_Archive_ZIP extends OC_Archive{ }else{ $ext=''; } - $tmpFile=OCP\Files::tmpFile($ext); + $tmpFile=\OCP\Files::tmpFile($ext); \OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack')); if($this->fileExists($path)) { $this->extractFile($path, $tmpFile); diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index 39c5fd3ab4a..99c123ad1a1 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -789,11 +789,12 @@ class Filesystem { * Fix common problems with a file path * * @param string $path - * @param bool $stripTrailingSlash - * @param bool $isAbsolutePath + * @param bool $stripTrailingSlash whether to strip the trailing slash + * @param bool $isAbsolutePath whether the given path is absolute + * @param bool $keepUnicode true to disable unicode normalization * @return string */ - public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false) { + public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) { if (is_null(self::$normalizedPathCache)) { self::$normalizedPathCache = new CappedMemoryCache(); } @@ -817,19 +818,13 @@ class Filesystem { } //normalize unicode if possible - $path = \OC_Util::normalizeUnicode($path); + if (!$keepUnicode) { + $path = \OC_Util::normalizeUnicode($path); + } //no windows style slashes $path = str_replace('\\', '/', $path); - // When normalizing an absolute path, we need to ensure that the drive-letter - // is still at the beginning on windows - $windows_drive_letter = ''; - if ($isAbsolutePath && \OC_Util::runningOnWindows() && preg_match('#^([a-zA-Z])$#', $path[0]) && $path[1] == ':' && $path[2] == '/') { - $windows_drive_letter = substr($path, 0, 2); - $path = substr($path, 2); - } - //add leading slash if ($path[0] !== '/') { $path = '/' . $path; @@ -855,7 +850,7 @@ class Filesystem { $path = substr($path, 0, -2); } - $normalizedPath = $windows_drive_letter . $path; + $normalizedPath = $path; self::$normalizedPathCache[$cacheKey] = $normalizedPath; return $normalizedPath; diff --git a/lib/private/legacy/installer.php b/lib/private/Installer.php index 24c79b2dd8c..edc6306b8f1 100644 --- a/lib/private/legacy/installer.php +++ b/lib/private/Installer.php @@ -37,15 +37,19 @@ * */ +namespace OC; + use OC\App\CodeChecker\CodeChecker; use OC\App\CodeChecker\EmptyCheck; use OC\App\CodeChecker\PrivateCheck; -use OC\OCSClient; +use OC_App; +use OC_DB; +use OC_Helper; /** * This class provides the functionality needed to install, update and remove plugins/apps */ -class OC_Installer{ +class Installer { /** * @@ -129,21 +133,26 @@ class OC_Installer{ } } + \OC_App::setupBackgroundJobs($info['background-jobs']); + //run appinfo/install.php if((!isset($data['noinstall']) or $data['noinstall']==false)) { self::includeAppScript($basedir . '/appinfo/install.php'); } + $appData = OC_App::getAppInfo($appId); + OC_App::executeRepairSteps($appId, $appData['repair-steps']['install']); + //set the installed version - \OC::$server->getAppConfig()->setValue($info['id'], 'installed_version', OC_App::getAppVersion($info['id'])); - \OC::$server->getAppConfig()->setValue($info['id'], 'enabled', 'no'); + \OC::$server->getConfig()->setAppValue($info['id'], 'installed_version', OC_App::getAppVersion($info['id'])); + \OC::$server->getConfig()->setAppValue($info['id'], 'enabled', 'no'); - //set remote/public handelers + //set remote/public handlers foreach($info['remote'] as $name=>$path) { - OCP\CONFIG::setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path); + \OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $info['id'].'/'.$path); } foreach($info['public'] as $name=>$path) { - OCP\CONFIG::setAppValue('core', 'public_'.$name, $info['id'].'/'.$path); + \OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $info['id'].'/'.$path); } OC_App::setAppTypes($info['id']); @@ -158,15 +167,15 @@ class OC_Installer{ * * Checks whether or not an app is installed, i.e. registered in apps table. */ - public static function isInstalled( $app ) { - return (\OC::$server->getAppConfig()->getValue($app, "installed_version") !== null); + public static function isInstalled( $app ) { + return (\OC::$server->getConfig()->getAppValue($app, "installed_version", null) !== null); } /** * @brief Update an application * @param array $info * @param bool $isShipped - * @throws Exception + * @throws \Exception * @return bool * * This function could work like described below, but currently it disables and then @@ -229,7 +238,7 @@ class OC_Installer{ * * @param integer $ocsId * @return bool - * @throws Exception + * @throws \Exception */ public static function updateAppByOCSId($ocsId) { $ocsClient = new OCSClient( @@ -257,7 +266,7 @@ class OC_Installer{ /** * @param array $data * @return array - * @throws Exception + * @throws \Exception */ public static function downloadApp($data = array()) { $l = \OC::$server->getL10N('lib'); @@ -293,7 +302,7 @@ class OC_Installer{ $extractDir = \OC::$server->getTempManager()->getTemporaryFolder(); OC_Helper::rmdirr($extractDir); mkdir($extractDir); - if($archive=OC_Archive::open($path)) { + if($archive=\OC\Archive\Archive::open($path)) { $archive->extract($extractDir); } else { OC_Helper::rmdirr($extractDir); @@ -375,7 +384,7 @@ class OC_Installer{ } // check the code for not allowed calls - if(!$isShipped && !OC_Installer::checkCode($extractDir)) { + if(!$isShipped && !Installer::checkCode($extractDir)) { OC_Helper::rmdirr($extractDir); throw new \Exception($l->t("App can't be installed because of not allowed code in the App")); } @@ -457,7 +466,7 @@ class OC_Installer{ * The function will check if the app is already downloaded in the apps repository */ public static function isDownloaded( $name ) { - foreach(OC::$APPSROOTS as $dir) { + foreach(\OC::$APPSROOTS as $dir) { $dirToTest = $dir['path']; $dirToTest .= '/'; $dirToTest .= $name; @@ -474,52 +483,25 @@ class OC_Installer{ /** * Removes an app * @param string $name name of the application to remove - * @param array $options options * @return boolean * - * This function removes an app. $options is an associative array. The - * following keys are optional:ja - * - keeppreferences: boolean, if true the user preferences won't be deleted - * - keepappconfig: boolean, if true the config will be kept - * - keeptables: boolean, if true the database will be kept - * - keepfiles: boolean, if true the user files will be kept * * This function works as follows - * -# including appinfo/remove.php + * -# call uninstall repair steps * -# removing the files * * The function will not delete preferences, tables and the configuration, * this has to be done by the function oc_app_uninstall(). */ - public static function removeApp( $name, $options = array()) { - - if(isset($options['keeppreferences']) and $options['keeppreferences']==false ) { - // todo - // remove preferences - } - - if(isset($options['keepappconfig']) and $options['keepappconfig']==false ) { - // todo - // remove app config - } - - if(isset($options['keeptables']) and $options['keeptables']==false ) { - // todo - // remove app database tables - } - - if(isset($options['keepfiles']) and $options['keepfiles']==false ) { - // todo - // remove user files - } + public static function removeApp($appId) { - if(OC_Installer::isDownloaded( $name )) { - $appdir=OC_App::getInstallPath().'/'.$name; - OC_Helper::rmdirr($appdir); + if(Installer::isDownloaded( $appId )) { + $appDir=OC_App::getInstallPath() . '/' . $appId; + OC_Helper::rmdirr($appDir); return true; }else{ - \OCP\Util::writeLog('core', 'can\'t remove app '.$name.'. It is not installed.', \OCP\Util::ERROR); + \OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', \OCP\Util::ERROR); return false; } @@ -536,25 +518,25 @@ class OC_Installer{ */ public static function installShippedApps($softErrors = false) { $errors = []; - foreach(OC::$APPSROOTS as $app_dir) { + foreach(\OC::$APPSROOTS as $app_dir) { if($dir = opendir( $app_dir['path'] )) { while( false !== ( $filename = readdir( $dir ))) { if( substr( $filename, 0, 1 ) != '.' and is_dir($app_dir['path']."/$filename") ) { if( file_exists( $app_dir['path']."/$filename/appinfo/info.xml" )) { - if(!OC_Installer::isInstalled($filename)) { + if(!Installer::isInstalled($filename)) { $info=OC_App::getAppInfo($filename); $enabled = isset($info['default_enable']); if (($enabled || in_array($filename, \OC::$server->getAppManager()->getAlwaysEnabledApps())) && \OC::$server->getConfig()->getAppValue($filename, 'enabled') !== 'no') { if ($softErrors) { try { - OC_Installer::installShippedApp($filename); + Installer::installShippedApp($filename); } catch (\Doctrine\DBAL\Exception\TableExistsException $e) { $errors[$filename] = $e; continue; } } else { - OC_Installer::installShippedApp($filename); + Installer::installShippedApp($filename); } \OC::$server->getConfig()->setAppValue($filename, 'enabled', 'yes'); } @@ -589,6 +571,9 @@ class OC_Installer{ if (is_null($info)) { return false; } + \OC_App::setupBackgroundJobs($info['background-jobs']); + + OC_App::executeRepairSteps($app, $info['repair-steps']['install']); $config = \OC::$server->getConfig(); diff --git a/lib/private/Lock/AbstractLockingProvider.php b/lib/private/Lock/AbstractLockingProvider.php index 1886fbea082..ff9f99a9630 100644 --- a/lib/private/Lock/AbstractLockingProvider.php +++ b/lib/private/Lock/AbstractLockingProvider.php @@ -77,6 +77,9 @@ abstract class AbstractLockingProvider implements ILockingProvider { if ($type === self::LOCK_SHARED) { if (isset($this->acquiredLocks['shared'][$path]) and $this->acquiredLocks['shared'][$path] > 0) { $this->acquiredLocks['shared'][$path]--; + if ($this->acquiredLocks['shared'][$path] === 0) { + unset($this->acquiredLocks['shared'][$path]); + } } } else if ($type === self::LOCK_EXCLUSIVE) { unset($this->acquiredLocks['exclusive'][$path]); diff --git a/lib/private/Log.php b/lib/private/Log.php index bbdad9cf166..9248070c067 100644 --- a/lib/private/Log.php +++ b/lib/private/Log.php @@ -73,7 +73,7 @@ class Log implements ILogger { // FIXME: Add this for backwards compatibility, should be fixed at some point probably if($logger === null) { - $this->logger = 'OC_Log_'.ucfirst($this->config->getValue('log_type', 'owncloud')); + $this->logger = 'OC\\Log\\'.ucfirst($this->config->getValue('log_type', 'owncloud')); call_user_func(array($this->logger, 'init')); } else { $this->logger = $logger; @@ -284,7 +284,7 @@ class Log implements ILogger { 'File' => $exception->getFile(), 'Line' => $exception->getLine(), ); - $exception['Trace'] = preg_replace('!(login|checkPassword|updatePrivateKeyPassword)\(.*\)!', '$1(*** username and password replaced ***)', $exception['Trace']); + $exception['Trace'] = preg_replace('!(login|checkPassword|updatePrivateKeyPassword|validateUserPass)\(.*\)!', '$1(*** username and password replaced ***)', $exception['Trace']); $msg = isset($context['message']) ? $context['message'] : 'Exception'; $msg .= ': ' . json_encode($exception); $this->error($msg, $context); diff --git a/lib/private/log/errorhandler.php b/lib/private/Log/ErrorHandler.php index 8899bcfcb03..8899bcfcb03 100644 --- a/lib/private/log/errorhandler.php +++ b/lib/private/Log/ErrorHandler.php diff --git a/lib/private/log/errorlog.php b/lib/private/Log/Errorlog.php index ad3605136d0..37498c36aba 100644 --- a/lib/private/log/errorlog.php +++ b/lib/private/Log/Errorlog.php @@ -23,7 +23,9 @@ * THE SOFTWARE. */ -class OC_Log_Errorlog { +namespace OC\Log; + +class Errorlog { /** diff --git a/lib/private/log/owncloud.php b/lib/private/Log/Owncloud.php index 9c106299e4c..13997a0d552 100644 --- a/lib/private/log/owncloud.php +++ b/lib/private/Log/Owncloud.php @@ -27,13 +27,15 @@ * */ +namespace OC\Log; + /** * logging utilities * * Log is saved at data/owncloud.log (on default) */ -class OC_Log_Owncloud { +class Owncloud { static protected $logFile; /** @@ -41,7 +43,7 @@ class OC_Log_Owncloud { */ public static function init() { $systemConfig = \OC::$server->getSystemConfig(); - $defaultLogFile = $systemConfig->getValue("datadirectory", OC::$SERVERROOT.'/data').'/owncloud.log'; + $defaultLogFile = $systemConfig->getValue("datadirectory", \OC::$SERVERROOT.'/data').'/owncloud.log'; self::$logFile = $systemConfig->getValue("logfile", $defaultLogFile); /** @@ -72,13 +74,13 @@ class OC_Log_Owncloud { $format = $config->getValue('logdateformat', 'c'); $logTimeZone = $config->getValue( "logtimezone", 'UTC' ); try { - $timezone = new DateTimeZone($logTimeZone); - } catch (Exception $e) { - $timezone = new DateTimeZone('UTC'); + $timezone = new \DateTimeZone($logTimeZone); + } catch (\Exception $e) { + $timezone = new \DateTimeZone('UTC'); } - $time = DateTime::createFromFormat("U.u", number_format(microtime(true), 4, ".", "")); + $time = \DateTime::createFromFormat("U.u", number_format(microtime(true), 4, ".", "")); if ($time === false) { - $time = new DateTime(null, $timezone); + $time = new \DateTime(null, $timezone); } else { // apply timezone if $time is created from UNIX timestamp $time->setTimezone($timezone); diff --git a/lib/private/log/rotate.php b/lib/private/Log/Rotate.php index 458661c82d0..458661c82d0 100644 --- a/lib/private/log/rotate.php +++ b/lib/private/Log/Rotate.php diff --git a/lib/private/log/syslog.php b/lib/private/Log/Syslog.php index 96cf463d042..115103f26d6 100644 --- a/lib/private/log/syslog.php +++ b/lib/private/Log/Syslog.php @@ -21,7 +21,9 @@ * */ -class OC_Log_Syslog { +namespace OC\Log; + +class Syslog { static protected $levels = array( \OCP\Util::DEBUG => LOG_DEBUG, \OCP\Util::INFO => LOG_INFO, diff --git a/lib/private/Repair.php b/lib/private/Repair.php index 590b0bee721..5d10cd582f0 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -73,7 +73,6 @@ class Repair implements IOutput{ * Run a series of repair steps for common problems */ public function run() { - $self = $this; if (count($this->repairSteps) === 0) { $this->emit('\OC\Repair', 'info', array('No repair steps available')); return; @@ -82,16 +81,6 @@ class Repair implements IOutput{ foreach ($this->repairSteps as $step) { $this->currentStep = $step->getName(); $this->emit('\OC\Repair', 'step', [$this->currentStep]); - - if ($step instanceof Emitter) { - $step->listen('\OC\Repair', 'warning', function ($description) use ($self) { - $self->emit('\OC\Repair', 'warning', array($description)); - }); - $step->listen('\OC\Repair', 'info', function ($description) use ($self) { - $self->emit('\OC\Repair', 'info', array($description)); - }); - } - $step->run($this); } } diff --git a/lib/private/Server.php b/lib/private/Server.php index 11cce494418..bbe6b88876f 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -313,7 +313,7 @@ class Server extends ServerContainer implements IServerContainer { ); }); $this->registerService('ActivityManager', function (Server $c) { - return new ActivityManager( + return new \OC\Activity\Manager( $c->getRequest(), $c->getUserSession(), $c->getConfig() @@ -329,7 +329,7 @@ class Server extends ServerContainer implements IServerContainer { }); $this->registerService('Logger', function (Server $c) { $logClass = $c->query('AllConfig')->getSystemValue('log_type', 'owncloud'); - $logger = 'OC_Log_' . ucfirst($logClass); + $logger = 'OC\\Log\\' . ucfirst($logClass); call_user_func(array($logger, 'init')); return new Log($logger); @@ -623,7 +623,7 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('ShareManager', function(Server $c) { $config = $c->getConfig(); $factoryClass = $config->getSystemValue('sharing.managerFactory', '\OC\Share20\ProviderFactory'); - /** @var \OC\Share20\IProviderFactory $factory */ + /** @var \OCP\Share\IProviderFactory $factory */ $factory = new $factoryClass($this); $manager = new \OC\Share20\Manager( @@ -837,8 +837,7 @@ class Server extends ServerContainer implements IServerContainer { } /** - * For internal use only - * + * @internal For internal use only * @return \OC\SystemConfig */ public function getSystemConfig() { @@ -1180,7 +1179,7 @@ class Server extends ServerContainer implements IServerContainer { return $this->query('MountManager'); } - /* + /** * Get the MimeTypeDetector * * @return \OCP\Files\IMimeTypeDetector diff --git a/lib/private/Session/CryptoSessionData.php b/lib/private/Session/CryptoSessionData.php index f6c585c1611..629e6af5412 100644 --- a/lib/private/Session/CryptoSessionData.php +++ b/lib/private/Session/CryptoSessionData.php @@ -24,6 +24,7 @@ namespace OC\Session; use OCP\ISession; use OCP\Security\ICrypto; +use OCP\Session\Exceptions\SessionNotAvailableException; /** * Class CryptoSessionData @@ -142,6 +143,17 @@ class CryptoSessionData implements \ArrayAccess, ISession { } /** + * Wrapper around session_id + * + * @return string + * @throws SessionNotAvailableException + * @since 9.1.0 + */ + public function getId() { + return $this->session->getId(); + } + + /** * Close the session and release the lock, also writes all changed data in batch */ public function close() { diff --git a/lib/private/Session/Internal.php b/lib/private/Session/Internal.php index 09175bf1f2f..a24aec55222 100644 --- a/lib/private/Session/Internal.php +++ b/lib/private/Session/Internal.php @@ -26,6 +26,8 @@ namespace OC\Session; +use OCP\Session\Exceptions\SessionNotAvailableException; + /** * Class Internal * @@ -112,6 +114,21 @@ class Internal extends Session { } /** + * Wrapper around session_id + * + * @return string + * @throws SessionNotAvailableException + * @since 9.1.0 + */ + public function getId() { + $id = @session_id(); + if ($id === '') { + throw new SessionNotAvailableException(); + } + return $id; + } + + /** * @throws \Exception */ public function reopen() { diff --git a/lib/private/Session/Memory.php b/lib/private/Session/Memory.php index 777458a9aa5..bcb1f1d950c 100644 --- a/lib/private/Session/Memory.php +++ b/lib/private/Session/Memory.php @@ -26,6 +26,9 @@ namespace OC\Session; +use Exception; +use OCP\Session\Exceptions\SessionNotAvailableException; + /** * Class Internal * @@ -89,6 +92,17 @@ class Memory extends Session { public function regenerateId($deleteOldSession = true) {} /** + * Wrapper around session_id + * + * @return string + * @throws SessionNotAvailableException + * @since 9.1.0 + */ + public function getId() { + throw new SessionNotAvailableException('Memory session does not have an ID'); + } + + /** * Helper function for PHPUnit execution - don't use in non-test code */ public function reopen() { @@ -98,11 +112,11 @@ class Memory extends Session { /** * In case the session has already been locked an exception will be thrown * - * @throws \Exception + * @throws Exception */ private function validateSession() { if ($this->sessionClosed) { - throw new \Exception('Session has been closed - no further changes to the session are allowed'); + throw new Exception('Session has been closed - no further changes to the session are allowed'); } } } diff --git a/lib/private/Setup.php b/lib/private/Setup.php index 196ae8a8bce..23c66f98b7c 100644 --- a/lib/private/Setup.php +++ b/lib/private/Setup.php @@ -367,7 +367,7 @@ class Setup { \OC_User::login($username, $password); //guess what this does - \OC_Installer::installShippedApps(); + Installer::installShippedApps(); // create empty file in data dir, so we can later find // out that this is indeed an ownCloud data directory diff --git a/lib/private/Updater.php b/lib/private/Updater.php index 093ebebbbe4..7ca3cd09362 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -36,7 +36,6 @@ namespace OC; use OC\Hooks\BasicEmitter; use OC\IntegrityCheck\Checker; use OC_App; -use OC_Installer; use OCP\IConfig; use OC\Setup; use OCP\ILogger; @@ -251,7 +250,7 @@ class Updater extends BasicEmitter { // install new shipped apps on upgrade OC_App::loadApps('authentication'); - $errors = OC_Installer::installShippedApps(true); + $errors = Installer::installShippedApps(true); foreach ($errors as $appId => $exception) { /** @var \Exception $exception */ $this->log->logException($exception, ['app' => $appId]); @@ -443,11 +442,11 @@ class Updater extends BasicEmitter { private function upgradeAppStoreApps(array $disabledApps) { foreach($disabledApps as $app) { try { - if (OC_Installer::isUpdateAvailable($app)) { + if (Installer::isUpdateAvailable($app)) { $ocsId = \OC::$server->getConfig()->getAppValue($app, 'ocsid', ''); $this->emit('\OC\Updater', 'upgradeAppStoreApp', array($app)); - OC_Installer::updateAppByOCSId($ocsId); + Installer::updateAppByOCSId($ocsId); } } catch (\Exception $ex) { $this->log->logException($ex, ['app' => 'core']); diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index 246bf97ee91..dab4c1a70c7 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -46,6 +46,7 @@ */ use OC\App\DependencyAnalyzer; use OC\App\Platform; +use OC\Installer; use OC\OCSClient; use OC\Repair; @@ -107,7 +108,7 @@ class OC_App { foreach($apps as $app) { $path = self::getAppPath($app); if($path !== false) { - \OC::$loader->addValidRoot($path); + self::registerAutoloading($app, $path); } } @@ -136,7 +137,10 @@ class OC_App { if($appPath === false) { return; } - \OC::$loader->addValidRoot($appPath); // in case someone calls loadApp() directly + + // in case someone calls loadApp() directly + self::registerAutoloading($app, $appPath); + if (is_file($appPath . '/appinfo/app.php')) { \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app); if ($checkUpgrade and self::shouldUpgrade($app)) { @@ -155,6 +159,22 @@ class OC_App { } /** + * @param string $app + * @param string $path + */ + protected static function registerAutoloading($app, $path) { + // Register on PSR-4 composer autoloader + $appNamespace = \OC\AppFramework\App::buildAppNamespace($app); + \OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true); + if (defined('PHPUNIT_RUN')) { + \OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true); + } + + // Register on legacy autoloader + \OC::$loader->addValidRoot($path); + } + + /** * Load app.php from the given app * * @param string $app app name @@ -304,7 +324,7 @@ class OC_App { */ public static function enable($app, $groups = null) { self::$enabledAppsCache = array(); // flush - if (!OC_Installer::isInstalled($app)) { + if (!Installer::isInstalled($app)) { $app = self::installApp($app); } @@ -340,7 +360,7 @@ class OC_App { // Replace spaces in download link without encoding entire URL $download['downloadlink'] = str_replace(' ', '%20', $download['downloadlink']); $info = array('source' => 'http', 'href' => $download['downloadlink'], 'appdata' => $appData); - $app = OC_Installer::installApp($info); + $app = Installer::installApp($info); } return $app; } @@ -354,7 +374,7 @@ class OC_App { return false; } - return OC_Installer::removeApp($app); + return Installer::removeApp($app); } /** @@ -369,9 +389,19 @@ class OC_App { $app = self::getInternalAppIdByOcs($app); } - self::$enabledAppsCache = array(); // flush - // check if app is a shipped app or not. if not delete + // flush + self::$enabledAppsCache = array(); + + // run uninstall steps + $appData = OC_App::getAppInfo($app); + if (!is_null($appData)) { + OC_App::executeRepairSteps($app, $appData['repair-steps']['uninstall']); + } + + // emit disable hook - needed anymore ? \OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app)); + + // finally disable it $appManager = \OC::$server->getAppManager(); $appManager->disableApp($app); } @@ -827,7 +857,7 @@ class OC_App { $info['removable'] = true; } - $info['update'] = ($includeUpdateInfo) ? OC_Installer::isUpdateAvailable($app) : null; + $info['update'] = ($includeUpdateInfo) ? Installer::isUpdateAvailable($app) : null; $appPath = self::getAppPath($app); if($appPath !== false) { @@ -1073,7 +1103,7 @@ class OC_App { if ($appData && version_compare($shippedVersion, $appData['version'], '<')) { $app = self::downloadApp($app); } else { - $app = OC_Installer::installShippedApp($app); + $app = Installer::installShippedApp($app); } } else { // Maybe the app is already installed - compare the version in this @@ -1160,6 +1190,7 @@ class OC_App { self::loadApp($appId, false); include $appPath . '/appinfo/update.php'; } + self::setupBackgroundJobs($appData['background-jobs']); //set remote/public handlers if (array_key_exists('ocsid', $appData)) { @@ -1187,7 +1218,7 @@ class OC_App { * @param string[] $steps * @throws \OC\NeedsUpdateException */ - private static function executeRepairSteps($appId, array $steps) { + public static function executeRepairSteps($appId, array $steps) { if (empty($steps)) { return; } @@ -1210,6 +1241,13 @@ class OC_App { $r->run(); } + public static function setupBackgroundJobs(array $jobs) { + $queue = \OC::$server->getJobList(); + foreach ($jobs as $job) { + $queue->add($job); + } + } + /** * @param string $appId * @param string[] $steps diff --git a/lib/private/legacy/user.php b/lib/private/legacy/user.php index 34ce68e989f..18a4c369d5e 100644 --- a/lib/private/legacy/user.php +++ b/lib/private/legacy/user.php @@ -150,14 +150,22 @@ class OC_User { /** * Try to login a user * - * @param string $loginname The login name of the user to log in + * @param string $loginName The login name of the user to log in * @param string $password The password of the user * @return boolean|null * * Log in a user and regenerate a new session - if the password is ok */ - public static function login($loginname, $password) { - $result = self::getUserSession()->login($loginname, $password); + public static function login($loginName, $password) { + + $result = self::getUserSession()->login($loginName, $password); + if (!$result) { + $users = \OC::$server->getUserManager()->getByEmail($loginName); + // we only allow login by email if unique + if (count($users) === 1) { + $result = self::getUserSession()->login($users[0]->getUID(), $password); + } + } if ($result) { // Refresh the token \OC::$server->getCsrfTokenManager()->refreshToken(); diff --git a/lib/private/user/database.php b/lib/private/user/database.php index 22a05090b96..fd273055ae1 100644 --- a/lib/private/user/database.php +++ b/lib/private/user/database.php @@ -48,11 +48,21 @@ * */ +use OC\Cache\CappedMemoryCache; + /** * Class for user management in a SQL Database (e.g. MySQL, SQLite) */ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { - private $cache = array(); + /** @var CappedMemoryCache */ + private $cache; + + /** + * OC_User_Database constructor. + */ + public function __construct() { + $this->cache = new CappedMemoryCache(); + } /** * Create a new user diff --git a/lib/private/user/manager.php b/lib/private/user/manager.php index 7967f877024..37a3e5ba134 100644 --- a/lib/private/user/manager.php +++ b/lib/private/user/manager.php @@ -33,6 +33,7 @@ namespace OC\User; use OC\Hooks\PublicEmitter; +use OCP\IUser; use OCP\IUserBackend; use OCP\IUserManager; use OCP\IConfig; @@ -147,14 +148,19 @@ class Manager extends PublicEmitter implements IUserManager { * * @param string $uid * @param \OCP\UserInterface $backend + * @param bool $cacheUser If false the newly created user object will not be cached * @return \OC\User\User */ - protected function getUserObject($uid, $backend) { + protected function getUserObject($uid, $backend, $cacheUser = true) { if (isset($this->cachedUsers[$uid])) { return $this->cachedUsers[$uid]; } - $this->cachedUsers[$uid] = new User($uid, $backend, $this, $this->config); - return $this->cachedUsers[$uid]; + + $user = new User($uid, $backend, $this, $this->config); + if ($cacheUser) { + $this->cachedUsers[$uid] = $user; + } + return $user; } /** @@ -335,11 +341,11 @@ class Manager extends PublicEmitter implements IUserManager { $offset = 0; do { $users = $backend->getUsers($search, $limit, $offset); - foreach ($users as $user) { - $user = $this->get($user); - if (is_null($user)) { + foreach ($users as $uid) { + if (!$backend->userExists($uid)) { continue; } + $user = $this->getUserObject($uid, $backend, false); $return = $callback($user); if ($return === false) { break; @@ -349,4 +355,17 @@ class Manager extends PublicEmitter implements IUserManager { } while (count($users) >= $limit); } } + + /** + * @param string $email + * @return IUser[] + * @since 9.1.0 + */ + public function getByEmail($email) { + $userIds = $this->config->getUsersForUserValue('settings', 'email', $email); + + return array_map(function($uid) { + return $this->get($uid); + }, $userIds); + } } diff --git a/lib/public/IServerContainer.php b/lib/public/IServerContainer.php index de48daeef88..65754f993f8 100644 --- a/lib/public/IServerContainer.php +++ b/lib/public/IServerContainer.php @@ -519,4 +519,16 @@ interface IServerContainer { * @since 9.0.0 */ public function getContentSecurityPolicyManager(); + + /** + * @return \OCP\IDateTimeZone + * @since 8.0.0 + */ + public function getDateTimeZone(); + + /** + * @return \OCP\IDateTimeFormatter + * @since 8.0.0 + */ + public function getDateTimeFormatter(); } diff --git a/lib/public/Session/Exceptions/SessionNotAvailableException.php b/lib/public/Session/Exceptions/SessionNotAvailableException.php new file mode 100644 index 00000000000..d347e0df15e --- /dev/null +++ b/lib/public/Session/Exceptions/SessionNotAvailableException.php @@ -0,0 +1,32 @@ +<?php + +/** + * @author Christoph Wurst <christoph@owncloud.com> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCP\Session\Exceptions; + +use Exception; + +/** + * @since 9.1.0 + */ +class SessionNotAvailableException extends Exception { + +} diff --git a/lib/public/isession.php b/lib/public/isession.php index 25c76906d63..7bc8654a1b9 100644 --- a/lib/public/isession.php +++ b/lib/public/isession.php @@ -95,4 +95,13 @@ interface ISession { * @since 9.0.0 */ public function regenerateId($deleteOldSession = true); + + /** + * Wrapper around session_id + * + * @return string + * @throws SessionNotAvailableException + * @since 9.1.0 + */ + public function getId(); } diff --git a/lib/public/iusermanager.php b/lib/public/iusermanager.php index 6442938a99b..00c0bbc8721 100644 --- a/lib/public/iusermanager.php +++ b/lib/public/iusermanager.php @@ -142,4 +142,11 @@ interface IUserManager { * @since 9.0.0 */ public function callForAllUsers (\Closure $callback, $search = ''); + + /** + * @param string $email + * @return IUser[] + * @since 9.1.0 + */ + public function getByEmail($email); } diff --git a/remote.php b/remote.php index 991ca0d2302..f28c3a35691 100644 --- a/remote.php +++ b/remote.php @@ -166,5 +166,5 @@ try { } catch (Exception $ex) { handleException($ex); } catch (Error $e) { - handleException($ex); + handleException($e); } diff --git a/settings/Controller/LogSettingsController.php b/settings/Controller/LogSettingsController.php index c0c9ee04ca3..70a2b752359 100644 --- a/settings/Controller/LogSettingsController.php +++ b/settings/Controller/LogSettingsController.php @@ -102,7 +102,7 @@ class LogSettingsController extends Controller { * @return StreamResponse */ public function download() { - $resp = new StreamResponse(\OC_Log_Owncloud::getLogFilePath()); + $resp = new StreamResponse(\OC\Log\Owncloud::getLogFilePath()); $resp->addHeader('Content-Disposition', 'attachment; filename="owncloud.log"'); return $resp; } diff --git a/settings/ajax/updateapp.php b/settings/ajax/updateapp.php index 8521914884f..7ac32468fe4 100644 --- a/settings/ajax/updateapp.php +++ b/settings/ajax/updateapp.php @@ -50,7 +50,7 @@ $appId = OC_App::cleanAppId($appId); $config = \OC::$server->getConfig(); $config->setSystemValue('maintenance', true); try { - $result = OC_Installer::updateAppByOCSId($appId); + $result = \OC\Installer::updateAppByOCSId($appId); $config->setSystemValue('maintenance', false); } catch(Exception $ex) { $config->setSystemValue('maintenance', false); diff --git a/tests/data/app/expected-info.json b/tests/data/app/expected-info.json index 51d0c00ccef..81de5341efa 100644 --- a/tests/data/app/expected-info.json +++ b/tests/data/app/expected-info.json @@ -69,8 +69,11 @@ } }, "repair-steps": { + "install": [], "pre-migration": [], "post-migration": [], - "live-migration": [] - } + "live-migration": [], + "uninstall": [] + }, + "background-jobs": [] } diff --git a/tests/lib/installer.php b/tests/lib/InstallerTest.php index ca210ba31ef..e1c17b841a2 100644 --- a/tests/lib/installer.php +++ b/tests/lib/InstallerTest.php @@ -6,7 +6,12 @@ * See the COPYING-README file. */ -class Test_Installer extends \Test\TestCase { +namespace Test; + + +use OC\Installer; + +class InstallerTest extends TestCase { private static $appid = 'testapp'; private $appstore; @@ -17,11 +22,11 @@ class Test_Installer extends \Test\TestCase { $config = \OC::$server->getConfig(); $this->appstore = $config->setSystemValue('appstoreenabled', true); $config->setSystemValue('appstoreenabled', true); - OC_Installer::removeApp(self::$appid); + Installer::removeApp(self::$appid); } protected function tearDown() { - OC_Installer::removeApp(self::$appid); + Installer::removeApp(self::$appid); \OC::$server->getConfig()->setSystemValue('appstoreenabled', $this->appstore); parent::tearDown(); @@ -33,7 +38,7 @@ class Test_Installer extends \Test\TestCase { $pathOfTestApp .= 'testapp.zip'; $tmp = \OC::$server->getTempManager()->getTemporaryFile('.zip'); - OC_Helper::copyr($pathOfTestApp, $tmp); + \OC_Helper::copyr($pathOfTestApp, $tmp); $data = array( 'path' => $tmp, @@ -44,8 +49,8 @@ class Test_Installer extends \Test\TestCase { ] ); - OC_Installer::installApp($data); - $isInstalled = OC_Installer::isInstalled(self::$appid); + Installer::installApp($data); + $isInstalled = Installer::isInstalled(self::$appid); $this->assertTrue($isInstalled); } @@ -56,7 +61,7 @@ class Test_Installer extends \Test\TestCase { $pathOfOldTestApp .= 'testapp.zip'; $oldTmp = \OC::$server->getTempManager()->getTemporaryFile('.zip'); - OC_Helper::copyr($pathOfOldTestApp, $oldTmp); + \OC_Helper::copyr($pathOfOldTestApp, $oldTmp); $oldData = array( 'path' => $oldTmp, @@ -72,7 +77,7 @@ class Test_Installer extends \Test\TestCase { $pathOfNewTestApp .= 'testapp2.zip'; $newTmp = \OC::$server->getTempManager()->getTemporaryFile('.zip'); - OC_Helper::copyr($pathOfNewTestApp, $newTmp); + \OC_Helper::copyr($pathOfNewTestApp, $newTmp); $newData = array( 'path' => $newTmp, @@ -83,11 +88,11 @@ class Test_Installer extends \Test\TestCase { ] ); - OC_Installer::installApp($oldData); - $oldVersionNumber = OC_App::getAppVersion(self::$appid); + Installer::installApp($oldData); + $oldVersionNumber = \OC_App::getAppVersion(self::$appid); - OC_Installer::updateApp($newData); - $newVersionNumber = OC_App::getAppVersion(self::$appid); + Installer::updateApp($newData); + $newVersionNumber = \OC_App::getAppVersion(self::$appid); $this->assertNotEquals($oldVersionNumber, $newVersionNumber); } diff --git a/tests/lib/activitymanager.php b/tests/lib/activity/managertest.php index 26759d46270..cf855dd2813 100644 --- a/tests/lib/activitymanager.php +++ b/tests/lib/activity/managertest.php @@ -8,18 +8,22 @@ * */ -class Test_ActivityManager extends \Test\TestCase { +namespace Test\Activity; - /** @var \OC\ActivityManager */ +use Test\TestCase; + +class ManagerTest extends TestCase { + + /** @var \OC\Activity\Manager */ private $activityManager; - /** @var \PHPUnit_Framework_MockObject_MockObject */ + /** @var \OCP\IRequest|\PHPUnit_Framework_MockObject_MockObject */ protected $request; - /** @var \PHPUnit_Framework_MockObject_MockObject */ + /** @var \OCP\IUserSession|\PHPUnit_Framework_MockObject_MockObject */ protected $session; - /** @var \PHPUnit_Framework_MockObject_MockObject */ + /** @var \OCP\IConfig|\PHPUnit_Framework_MockObject_MockObject */ protected $config; protected function setUp() { @@ -35,7 +39,7 @@ class Test_ActivityManager extends \Test\TestCase { ->disableOriginalConstructor() ->getMock(); - $this->activityManager = new \OC\ActivityManager( + $this->activityManager = new \OC\Activity\Manager( $this->request, $this->session, $this->config @@ -71,7 +75,7 @@ class Test_ActivityManager extends \Test\TestCase { */ public function testGetConsumersInvalidConsumer() { $this->activityManager->registerConsumer(function() { - return new StdClass(); + return new \stdClass(); }); $this->invokePrivate($this->activityManager, 'getConsumers'); @@ -88,7 +92,7 @@ class Test_ActivityManager extends \Test\TestCase { */ public function testGetExtensionsInvalidExtension() { $this->activityManager->registerExtension(function() { - return new StdClass(); + return new \stdClass(); }); $this->invokePrivate($this->activityManager, 'getExtensions'); @@ -119,10 +123,10 @@ class Test_ActivityManager extends \Test\TestCase { } public function testTranslate() { - $result = $this->activityManager->translate('APP0', '', '', array(), false, false, 'en'); + $result = $this->activityManager->translate('APP0', '', array(), false, false, 'en'); $this->assertEquals('Stupid translation', $result); - $result = $this->activityManager->translate('APP1', '', '', array(), false, false, 'en'); + $result = $this->activityManager->translate('APP1', '', array(), false, false, 'en'); $this->assertFalse($result); } @@ -259,7 +263,7 @@ class Test_ActivityManager extends \Test\TestCase { } /** - * @expectedException BadMethodCallException + * @expectedException \BadMethodCallException * @expectedExceptionMessage App not set * @expectedExceptionCode 10 */ @@ -269,7 +273,7 @@ class Test_ActivityManager extends \Test\TestCase { } /** - * @expectedException BadMethodCallException + * @expectedException \BadMethodCallException * @expectedExceptionMessage Type not set * @expectedExceptionCode 11 */ @@ -280,7 +284,7 @@ class Test_ActivityManager extends \Test\TestCase { } /** - * @expectedException BadMethodCallException + * @expectedException \BadMethodCallException * @expectedExceptionMessage Affected user not set * @expectedExceptionCode 12 */ @@ -292,7 +296,7 @@ class Test_ActivityManager extends \Test\TestCase { } /** - * @expectedException BadMethodCallException + * @expectedException \BadMethodCallException * @expectedExceptionMessage Subject not set * @expectedExceptionCode 13 */ diff --git a/tests/lib/archive/tar.php b/tests/lib/archive/tar.php index 43157e2054d..2d20bb4c3b1 100644 --- a/tests/lib/archive/tar.php +++ b/tests/lib/archive/tar.php @@ -6,6 +6,8 @@ * See the COPYING-README file. */ +use OC\Archive\TAR; + class Test_Archive_TAR extends Test_Archive { protected function setUp() { parent::setUp(); @@ -17,10 +19,10 @@ class Test_Archive_TAR extends Test_Archive { protected function getExisting() { $dir = OC::$SERVERROOT . '/tests/data'; - return new OC_Archive_TAR($dir . '/data.tar.gz'); + return new TAR($dir . '/data.tar.gz'); } protected function getNew() { - return new OC_Archive_TAR(OCP\Files::tmpFile('.tar.gz')); + return new TAR(OCP\Files::tmpFile('.tar.gz')); } } diff --git a/tests/lib/archive/zip.php b/tests/lib/archive/zip.php index 09ea5d7d27c..2f4c9cace1d 100644 --- a/tests/lib/archive/zip.php +++ b/tests/lib/archive/zip.php @@ -6,6 +6,8 @@ * See the COPYING-README file. */ +use OC\Archive\ZIP; + class Test_Archive_ZIP extends Test_Archive { protected function setUp() { parent::setUp(); @@ -17,10 +19,10 @@ class Test_Archive_ZIP extends Test_Archive { protected function getExisting() { $dir = OC::$SERVERROOT . '/tests/data'; - return new OC_Archive_ZIP($dir . '/data.zip'); + return new ZIP($dir . '/data.zip'); } protected function getNew() { - return new OC_Archive_ZIP(OCP\Files::tmpFile('.zip')); + return new ZIP(OCP\Files::tmpFile('.zip')); } } diff --git a/tests/lib/log/owncloud.php b/tests/lib/log/owncloud.php index adecc49768c..e19063a83f5 100644 --- a/tests/lib/log/owncloud.php +++ b/tests/lib/log/owncloud.php @@ -15,12 +15,17 @@ * License along with this library. If not, see <http://www.gnu.org/licenses/>. */ +namespace Test\Log; + +use OC\Log\Owncloud; +use Test\TestCase; + /** - * Class Test_Log_Owncloud + * Class OwncloudTest * * @group DB */ -class Test_Log_Owncloud extends Test\TestCase +class OwncloudTest extends TestCase { private $restore_logfile; private $restore_logdateformat; @@ -32,7 +37,7 @@ class Test_Log_Owncloud extends Test\TestCase $this->restore_logdateformat = $config->getSystemValue('logdateformat'); $config->setSystemValue("logfile", $config->getSystemValue('datadirectory') . "/logtest"); - OC_Log_Owncloud::init(); + Owncloud::init(); } protected function tearDown() { $config = \OC::$server->getConfig(); @@ -46,7 +51,7 @@ class Test_Log_Owncloud extends Test\TestCase } else { $config->deleteSystemValue("restore_logdateformat"); } - OC_Log_Owncloud::init(); + Owncloud::init(); parent::tearDown(); } @@ -57,7 +62,7 @@ class Test_Log_Owncloud extends Test\TestCase # set format & write log line $config->setSystemValue('logdateformat', 'u'); - OC_Log_Owncloud::write('test', 'message', \OCP\Util::ERROR); + Owncloud::write('test', 'message', \OCP\Util::ERROR); # read log line $handle = @fopen($config->getSystemValue('logfile'), 'r'); diff --git a/tests/lib/logger.php b/tests/lib/logger.php index 9c9cd9e6728..e6a0abfbf28 100644 --- a/tests/lib/logger.php +++ b/tests/lib/logger.php @@ -107,4 +107,19 @@ class Logger extends TestCase { $this->assertContains('checkPassword(*** username and password replaced ***)', $logLine); } } + + /** + * @dataProvider userAndPasswordData + */ + public function testDetectvalidateUserPass($user, $password) { + $e = new \Exception('test'); + $this->logger->logException($e); + $logLines = $this->getLogs(); + + foreach($logLines as $logLine) { + $this->assertNotContains($user, $logLine); + $this->assertNotContains($password, $logLine); + $this->assertContains('validateUserPass(*** username and password replaced ***)', $logLine); + } + } } diff --git a/tests/lib/server.php b/tests/lib/server.php index d13f9be0c9e..fe3c6fd5ee8 100644 --- a/tests/lib/server.php +++ b/tests/lib/server.php @@ -44,7 +44,7 @@ class Server extends \Test\TestCase { public function dataTestQuery() { return [ - ['ActivityManager', '\OC\ActivityManager'], + ['ActivityManager', '\OC\Activity\Manager'], ['ActivityManager', '\OCP\Activity\IManager'], ['AllConfig', '\OC\AllConfig'], ['AllConfig', '\OCP\IConfig'], diff --git a/tests/lib/session/memory.php b/tests/lib/session/memory.php index 1ca4956c6ea..dbf2737fb3f 100644 --- a/tests/lib/session/memory.php +++ b/tests/lib/session/memory.php @@ -10,8 +10,17 @@ namespace Test\Session; class Memory extends Session { + protected function setUp() { parent::setUp(); $this->instance = new \OC\Session\Memory($this->getUniqueID()); } + + /** + * @expectedException OCP\Session\Exceptions\SessionNotAvailableException + */ + public function testThrowsExceptionOnGetId() { + $this->instance->getId(); + } + } |