diff options
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/Activity/Manager.php (renamed from lib/private/ActivityManager.php) | 5 | ||||
-rw-r--r-- | lib/private/App/InfoParser.php | 23 | ||||
-rw-r--r-- | lib/private/AppFramework/Db/Db.php | 17 | ||||
-rw-r--r-- | lib/private/AppFramework/DependencyInjection/DIContainer.php | 4 | ||||
-rw-r--r-- | lib/private/Archive/Archive.php (renamed from lib/private/archive.php) | 12 | ||||
-rw-r--r-- | lib/private/Archive/TAR.php (renamed from lib/private/archive/tar.php) | 24 | ||||
-rw-r--r-- | lib/private/Archive/ZIP.php (renamed from lib/private/archive/zip.php) | 14 | ||||
-rw-r--r-- | lib/private/Authentication/Exceptions/InvalidTokenException.php | 29 | ||||
-rw-r--r-- | lib/private/Authentication/Token/DefaultToken.php | 90 | ||||
-rw-r--r-- | lib/private/Authentication/Token/DefaultTokenCleanupJob.php | 36 | ||||
-rw-r--r-- | lib/private/Authentication/Token/DefaultTokenMapper.php | 114 | ||||
-rw-r--r-- | lib/private/Authentication/Token/DefaultTokenProvider.php | 219 | ||||
-rw-r--r-- | lib/private/Authentication/Token/IProvider.php | 91 | ||||
-rw-r--r-- | lib/private/Authentication/Token/IToken.php | 50 | ||||
-rw-r--r-- | lib/private/BackgroundJob/JobList.php | 86 | ||||
-rw-r--r-- | lib/private/Cache/File.php | 4 | ||||
-rw-r--r-- | lib/private/Console/Application.php | 2 | ||||
-rw-r--r-- | lib/private/DB/Adapter.php | 20 | ||||
-rw-r--r-- | lib/private/DB/AdapterMySQL.php | 12 | ||||
-rw-r--r-- | lib/private/DB/AdapterSqlite.php | 12 | ||||
-rw-r--r-- | lib/private/DB/Connection.php | 38 | ||||
-rw-r--r-- | lib/private/DateTimeFormatter.php (renamed from lib/private/datetimeformatter.php) | 0 | ||||
-rw-r--r-- | lib/private/DateTimeZone.php (renamed from lib/private/datetimezone.php) | 0 | ||||
-rw-r--r-- | lib/private/Files/Cache/Wrapper/CacheJail.php | 2 | ||||
-rw-r--r-- | lib/private/Files/Config/MountProviderCollection.php | 36 | ||||
-rw-r--r-- | lib/private/Files/Filesystem.php | 106 | ||||
-rw-r--r-- | lib/private/Files/Mount/CacheMountProvider.php | 69 | ||||
-rw-r--r-- | lib/private/Files/Mount/LocalHomeMountProvider.php | 46 | ||||
-rw-r--r-- | lib/private/Files/Mount/ObjectHomeMountProvider.php | 73 | ||||
-rw-r--r-- | lib/private/Files/Storage/Wrapper/Availability.php | 4 | ||||
-rw-r--r-- | lib/private/ForbiddenException.php (renamed from lib/private/forbiddenexception.php) | 0 | ||||
-rw-r--r-- | lib/private/Group/Backend.php (renamed from lib/private/group/backend.php) | 28 | ||||
-rw-r--r-- | lib/private/Group/Database.php (renamed from lib/private/group/database.php) | 12 | ||||
-rw-r--r-- | lib/private/Group/Group.php (renamed from lib/private/group/group.php) | 12 | ||||
-rw-r--r-- | lib/private/Group/Manager.php (renamed from lib/private/group/manager.php) | 2 | ||||
-rw-r--r-- | lib/private/Group/MetaData.php (renamed from lib/private/group/metadata.php) | 0 | ||||
-rw-r--r-- | lib/private/HTTPHelper.php (renamed from lib/private/httphelper.php) | 0 | ||||
-rw-r--r-- | lib/private/HintException.php (renamed from lib/private/hintexception.php) | 0 | ||||
-rw-r--r-- | lib/private/Http/Client/Client.php | 29 | ||||
-rw-r--r-- | lib/private/Installer.php (renamed from lib/private/installer.php) | 91 | ||||
-rw-r--r-- | lib/private/L10N/Factory.php | 2 | ||||
-rw-r--r-- | lib/private/LargeFileHelper.php (renamed from lib/private/largefilehelper.php) | 0 | ||||
-rw-r--r-- | lib/private/Lock/AbstractLockingProvider.php | 7 | ||||
-rw-r--r-- | lib/private/Lock/MemcacheLockingProvider.php | 9 | ||||
-rw-r--r-- | lib/private/Log.php (renamed from lib/private/log.php) | 4 | ||||
-rw-r--r-- | lib/private/Log/ErrorHandler.php (renamed from lib/private/log/errorhandler.php) | 0 | ||||
-rw-r--r-- | lib/private/Log/Errorlog.php (renamed from lib/private/log/errorlog.php) | 4 | ||||
-rw-r--r-- | lib/private/Log/Owncloud.php (renamed from lib/private/log/owncloud.php) | 16 | ||||
-rw-r--r-- | lib/private/Log/Rotate.php (renamed from lib/private/log/rotate.php) | 0 | ||||
-rw-r--r-- | lib/private/Log/Syslog.php (renamed from lib/private/log/syslog.php) | 4 | ||||
-rw-r--r-- | lib/private/Memcache/Memcached.php | 30 | ||||
-rw-r--r-- | lib/private/Memcache/Redis.php | 31 | ||||
-rw-r--r-- | lib/private/NaturalSort.php (renamed from lib/private/naturalsort.php) | 0 | ||||
-rw-r--r-- | lib/private/NaturalSort_DefaultCollator.php (renamed from lib/private/naturalsort_defaultcollator.php) | 0 | ||||
-rw-r--r-- | lib/private/NavigationManager.php (renamed from lib/private/navigationmanager.php) | 0 | ||||
-rw-r--r-- | lib/private/NeedsUpdateException.php (renamed from lib/private/needsupdateexception.php) | 0 | ||||
-rw-r--r-- | lib/private/NotSquareException.php (renamed from lib/private/notsquareexception.php) | 0 | ||||
-rw-r--r-- | lib/private/OCS/Cloud.php (renamed from lib/private/ocs/cloud.php) | 14 | ||||
-rw-r--r-- | lib/private/OCS/Config.php (renamed from lib/private/ocs/config.php) | 8 | ||||
-rw-r--r-- | lib/private/OCS/CoreCapabilities.php (renamed from lib/private/ocs/corecapabilities.php) | 0 | ||||
-rw-r--r-- | lib/private/OCS/Exception.php (renamed from lib/private/ocs/exception.php) | 2 | ||||
-rw-r--r-- | lib/private/OCS/Person.php (renamed from lib/private/ocs/person.php) | 12 | ||||
-rw-r--r-- | lib/private/OCS/PrivateData.php (renamed from lib/private/ocs/privatedata.php) | 17 | ||||
-rw-r--r-- | lib/private/OCS/Provider.php | 96 | ||||
-rw-r--r-- | lib/private/OCS/Result.php (renamed from lib/private/ocs/result.php) | 4 | ||||
-rw-r--r-- | lib/private/OCSClient.php (renamed from lib/private/ocsclient.php) | 8 | ||||
-rw-r--r-- | lib/private/Preview.php (renamed from lib/private/preview.php) | 0 | ||||
-rw-r--r-- | lib/private/PreviewManager.php (renamed from lib/private/previewmanager.php) | 0 | ||||
-rw-r--r-- | lib/private/RedisFactory.php | 85 | ||||
-rw-r--r-- | lib/private/Repair.php (renamed from lib/private/repair.php) | 50 | ||||
-rw-r--r-- | lib/private/Repair/DropOldTables.php | 5 | ||||
-rw-r--r-- | lib/private/RepairException.php (renamed from lib/private/repairexception.php) | 0 | ||||
-rw-r--r-- | lib/private/Route/CachingRouter.php | 5 | ||||
-rw-r--r-- | lib/private/Search.php (renamed from lib/private/search.php) | 0 | ||||
-rw-r--r-- | lib/private/Server.php | 71 | ||||
-rw-r--r-- | lib/private/ServerContainer.php (renamed from lib/private/servercontainer.php) | 0 | ||||
-rw-r--r-- | lib/private/ServerNotAvailableException.php (renamed from lib/private/servernotavailableexception.php) | 0 | ||||
-rw-r--r-- | lib/private/ServiceUnavailableException.php (renamed from lib/private/serviceunavailableexception.php) | 0 | ||||
-rw-r--r-- | lib/private/Session/CryptoSessionData.php | 12 | ||||
-rw-r--r-- | lib/private/Session/Internal.php | 17 | ||||
-rw-r--r-- | lib/private/Session/Memory.php | 18 | ||||
-rw-r--r-- | lib/private/Setup.php (renamed from lib/private/setup.php) | 67 | ||||
-rw-r--r-- | lib/private/Share/Constants.php (renamed from lib/private/share/constants.php) | 0 | ||||
-rw-r--r-- | lib/private/Share/Helper.php (renamed from lib/private/share/helper.php) | 0 | ||||
-rw-r--r-- | lib/private/Share/MailNotifications.php (renamed from lib/private/share/mailnotifications.php) | 22 | ||||
-rw-r--r-- | lib/private/Share/SearchResultSorter.php (renamed from lib/private/share/searchresultsorter.php) | 0 | ||||
-rw-r--r-- | lib/private/Share/Share.php (renamed from lib/private/share/share.php) | 0 | ||||
-rw-r--r-- | lib/private/Streamer.php (renamed from lib/private/streamer.php) | 0 | ||||
-rw-r--r-- | lib/private/SubAdmin.php (renamed from lib/private/subadmin.php) | 0 | ||||
-rw-r--r-- | lib/private/SystemConfig.php (renamed from lib/private/systemconfig.php) | 0 | ||||
-rw-r--r-- | lib/private/SystemTag/ManagerFactory.php | 1 | ||||
-rw-r--r-- | lib/private/SystemTag/SystemTagManager.php | 113 | ||||
-rw-r--r-- | lib/private/TagManager.php (renamed from lib/private/tagmanager.php) | 0 | ||||
-rw-r--r-- | lib/private/Tags.php (renamed from lib/private/tags.php) | 0 | ||||
-rw-r--r-- | lib/private/TempManager.php (renamed from lib/private/tempmanager.php) | 0 | ||||
-rw-r--r-- | lib/private/Template/Base.php (renamed from lib/private/template/base.php) | 0 | ||||
-rw-r--r-- | lib/private/Template/CSSResourceLocator.php (renamed from lib/private/template/cssresourcelocator.php) | 0 | ||||
-rw-r--r-- | lib/private/Template/JSResourceLocator.php (renamed from lib/private/template/jsresourcelocator.php) | 0 | ||||
-rw-r--r-- | lib/private/Template/ResourceLocator.php (renamed from lib/private/template/resourcelocator.php) | 0 | ||||
-rw-r--r-- | lib/private/Template/ResourceNotFoundException.php (renamed from lib/private/template/resourcenotfoundexception.php) | 0 | ||||
-rw-r--r-- | lib/private/Template/TemplateFileLocator.php (renamed from lib/private/template/templatefilelocator.php) | 0 | ||||
-rw-r--r-- | lib/private/TemplateLayout.php (renamed from lib/private/templatelayout.php) | 0 | ||||
-rw-r--r-- | lib/private/URLGenerator.php (renamed from lib/private/urlgenerator.php) | 0 | ||||
-rw-r--r-- | lib/private/Updater.php (renamed from lib/private/updater.php) | 38 | ||||
-rw-r--r-- | lib/private/Updater/VersionCheck.php | 8 | ||||
-rw-r--r-- | lib/private/User/Backend.php (renamed from lib/private/user/backend.php) | 28 | ||||
-rw-r--r-- | lib/private/User/Database.php (renamed from lib/private/user/database.php) | 44 | ||||
-rw-r--r-- | lib/private/User/LoginException.php (renamed from lib/private/user/loginexception.php) | 0 | ||||
-rw-r--r-- | lib/private/User/Manager.php (renamed from lib/private/user/manager.php) | 37 | ||||
-rw-r--r-- | lib/private/User/NoUserException.php (renamed from lib/private/user/nouserexception.php) | 0 | ||||
-rw-r--r-- | lib/private/User/Session.php | 545 | ||||
-rw-r--r-- | lib/private/User/User.php (renamed from lib/private/user/user.php) | 15 | ||||
-rw-r--r-- | lib/private/legacy/api.php (renamed from lib/private/api.php) | 42 | ||||
-rw-r--r-- | lib/private/legacy/app.php (renamed from lib/private/app.php) | 59 | ||||
-rw-r--r-- | lib/private/legacy/db.php (renamed from lib/private/db.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/defaults.php (renamed from lib/private/defaults.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/eventsource.php (renamed from lib/private/eventsource.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/filechunking.php (renamed from lib/private/filechunking.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/files.php (renamed from lib/private/files.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/group.php (renamed from lib/private/group.php) | 2 | ||||
-rw-r--r-- | lib/private/legacy/group/backend.php | 59 | ||||
-rw-r--r-- | lib/private/legacy/group/database.php | 30 | ||||
-rw-r--r-- | lib/private/legacy/group/example.php (renamed from lib/private/group/example.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/group/interface.php (renamed from lib/private/group/interface.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/helper.php (renamed from lib/private/helper.php) | 31 | ||||
-rw-r--r-- | lib/private/legacy/hook.php (renamed from lib/private/hook.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/image.php (renamed from lib/private/image.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/json.php (renamed from lib/private/json.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/ocs.php (renamed from lib/private/ocs.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/ocs/cloud.php | 27 | ||||
-rw-r--r-- | lib/private/legacy/ocs/config.php | 27 | ||||
-rw-r--r-- | lib/private/legacy/ocs/person.php | 27 | ||||
-rw-r--r-- | lib/private/legacy/ocs/privatedata.php | 27 | ||||
-rw-r--r-- | lib/private/legacy/ocs/result.php | 27 | ||||
-rw-r--r-- | lib/private/legacy/response.php (renamed from lib/private/response.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/template.php (renamed from lib/private/template.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/template/functions.php (renamed from lib/private/template/functions.php) | 6 | ||||
-rw-r--r-- | lib/private/legacy/user.php (renamed from lib/private/user.php) | 70 | ||||
-rw-r--r-- | lib/private/legacy/user/backend.php | 67 | ||||
-rw-r--r-- | lib/private/legacy/user/interface.php (renamed from lib/private/user/interface.php) | 0 | ||||
-rw-r--r-- | lib/private/legacy/util.php (renamed from lib/private/util.php) | 5 | ||||
-rw-r--r-- | lib/private/user/session.php | 318 |
142 files changed, 2758 insertions, 927 deletions
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/AppFramework/Db/Db.php b/lib/private/AppFramework/Db/Db.php index 0d17d7bc225..ab06d56cfd1 100644 --- a/lib/private/AppFramework/Db/Db.php +++ b/lib/private/AppFramework/Db/Db.php @@ -29,6 +29,7 @@ namespace OC\AppFramework\Db; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDb; use OCP\IDBConnection; +use OCP\PreConditionNotMetException; /** * @deprecated use IDBConnection directly, will be removed in ownCloud 10 @@ -157,13 +158,27 @@ class Db implements IDb { * @param array $updatePreconditionValues ensure values match preconditions (column name => value) * @return int number of new rows * @throws \Doctrine\DBAL\DBALException - * @throws PreconditionNotMetException + * @throws PreConditionNotMetException */ public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) { return $this->connection->setValues($table, $keys, $values, $updatePreconditionValues); } /** + * @inheritdoc + */ + public function lockTable($tableName) { + $this->connection->lockTable($tableName); + } + + /** + * @inheritdoc + */ + public function unlockTable() { + $this->connection->unlockTable(); + } + + /** * Start a transaction */ public function beginTransaction() { diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 2951ee536d2..439b631b50f 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -148,6 +148,10 @@ class DIContainer extends SimpleContainer implements IAppContainer { return $this->getServer()->getRootFolder(); }); + $this->registerService('OCP\\Http\\Client\\IClientService', function($c) { + return $this->getServer()->getHTTPClientService(); + }); + $this->registerService('OCP\\IGroupManager', function($c) { return $this->getServer()->getGroupManager(); }); diff --git a/lib/private/archive.php b/lib/private/Archive/Archive.php index 62512d1448a..b5286968a2f 100644 --- a/lib/private/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/Authentication/Exceptions/InvalidTokenException.php b/lib/private/Authentication/Exceptions/InvalidTokenException.php new file mode 100644 index 00000000000..3e52d3b78f0 --- /dev/null +++ b/lib/private/Authentication/Exceptions/InvalidTokenException.php @@ -0,0 +1,29 @@ +<?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 OC\Authentication\Exceptions; + +use Exception; + +class InvalidTokenException extends Exception { + +} diff --git a/lib/private/Authentication/Token/DefaultToken.php b/lib/private/Authentication/Token/DefaultToken.php new file mode 100644 index 00000000000..08451a46151 --- /dev/null +++ b/lib/private/Authentication/Token/DefaultToken.php @@ -0,0 +1,90 @@ +<?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 OC\Authentication\Token; + +use OCP\AppFramework\Db\Entity; + +/** + * @method void setId(int $id) + * @method void setUid(string $uid); + * @method void setPassword(string $password) + * @method string getPassword() + * @method void setName(string $name) + * @method string getName() + * @method void setToken(string $token) + * @method string getToken() + * @method void setType(string $type) + * @method int getType() + * @method void setLastActivity(int $lastActivity) + * @method int getLastActivity() + */ +class DefaultToken extends Entity implements IToken { + + /** + * @var string user UID + */ + protected $uid; + + /** + * @var string encrypted user password + */ + protected $password; + + /** + * @var string token name (e.g. browser/OS) + */ + protected $name; + + /** + * @var string + */ + protected $token; + + /** + * @var int + */ + protected $type; + + /** + * @var int + */ + protected $lastActivity; + + public function getId() { + return $this->id; + } + + public function getUID() { + return $this->uid; + } + + /** + * Get the (encrypted) login password + * + * @return string + */ + public function getPassword() { + return parent::getPassword(); + } + +} diff --git a/lib/private/Authentication/Token/DefaultTokenCleanupJob.php b/lib/private/Authentication/Token/DefaultTokenCleanupJob.php new file mode 100644 index 00000000000..4d1290eb623 --- /dev/null +++ b/lib/private/Authentication/Token/DefaultTokenCleanupJob.php @@ -0,0 +1,36 @@ +<?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 OC\Authentication\Token; + +use OC; +use OC\BackgroundJob\Job; + +class DefaultTokenCleanupJob extends Job { + + protected function run($argument) { + /* @var $provider DefaultTokenProvider */ + $provider = OC::$server->query('OC\Authentication\Token\DefaultTokenProvider'); + $provider->invalidateOldTokens(); + } + +} diff --git a/lib/private/Authentication/Token/DefaultTokenMapper.php b/lib/private/Authentication/Token/DefaultTokenMapper.php new file mode 100644 index 00000000000..9f173571270 --- /dev/null +++ b/lib/private/Authentication/Token/DefaultTokenMapper.php @@ -0,0 +1,114 @@ +<?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 OC\Authentication\Token; + +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\Mapper; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use OCP\IUser; + +class DefaultTokenMapper extends Mapper { + + public function __construct(IDBConnection $db) { + parent::__construct($db, 'authtoken'); + } + + /** + * Invalidate (delete) a given token + * + * @param string $token + */ + public function invalidate($token) { + $qb = $this->db->getQueryBuilder(); + $qb->delete('authtoken') + ->andWhere($qb->expr()->eq('token', $qb->createParameter('token'))) + ->setParameter('token', $token) + ->execute(); + } + + /** + * @param int $olderThan + */ + public function invalidateOld($olderThan) { + /* @var $qb IQueryBuilder */ + $qb = $this->db->getQueryBuilder(); + $qb->delete('authtoken') + ->where($qb->expr()->lt('last_activity', $qb->createParameter('last_activity'))) + ->andWhere($qb->expr()->eq('type', $qb->createParameter('type'))) + ->setParameter('last_activity', $olderThan, IQueryBuilder::PARAM_INT) + ->setParameter('type', IToken::TEMPORARY_TOKEN, IQueryBuilder::PARAM_INT) + ->execute(); + } + + /** + * Get the user UID for the given token + * + * @param string $token + * @throws DoesNotExistException + * @return DefaultToken + */ + public function getToken($token) { + /* @var $qb IQueryBuilder */ + $qb = $this->db->getQueryBuilder(); + $result = $qb->select('id', 'uid', 'password', 'name', 'type', 'token', 'last_activity') + ->from('authtoken') + ->where($qb->expr()->eq('token', $qb->createParameter('token'))) + ->setParameter('token', $token) + ->execute(); + + $data = $result->fetch(); + if ($data === false) { + throw new DoesNotExistException('token does not exist'); + } + return DefaultToken::fromRow($data); + } + + /** + * Get all token of a user + * + * The provider may limit the number of result rows in case of an abuse + * where a high number of (session) tokens is generated + * + * @param IUser $user + * @return DefaultToken[] + */ + public function getTokenByUser(IUser $user) { + /* @var $qb IQueryBuilder */ + $qb = $this->db->getQueryBuilder(); + $qb->select('id', 'uid', 'password', 'name', 'type', 'token', 'last_activity') + ->from('authtoken') + ->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID()))) + ->setMaxResults(1000); + $result = $qb->execute(); + $data = $result->fetchAll(); + $result->closeCursor(); + + $entities = array_map(function ($row) { + return DefaultToken::fromRow($row); + }, $data); + + return $entities; + } + +} diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php new file mode 100644 index 00000000000..6c69d852d7b --- /dev/null +++ b/lib/private/Authentication/Token/DefaultTokenProvider.php @@ -0,0 +1,219 @@ +<?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 OC\Authentication\Token; + +use Exception; +use OC\Authentication\Exceptions\InvalidTokenException; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IConfig; +use OCP\ILogger; +use OCP\IUser; +use OCP\Security\ICrypto; + +class DefaultTokenProvider implements IProvider { + + /** @var DefaultTokenMapper */ + private $mapper; + + /** @var ICrypto */ + private $crypto; + + /** @var IConfig */ + private $config; + + /** @var ILogger $logger */ + private $logger; + + /** @var ITimeFactory $time */ + private $time; + + /** + * @param DefaultTokenMapper $mapper + * @param ICrypto $crypto + * @param IConfig $config + * @param ILogger $logger + * @param ITimeFactory $time + */ + public function __construct(DefaultTokenMapper $mapper, ICrypto $crypto, IConfig $config, ILogger $logger, ITimeFactory $time) { + $this->mapper = $mapper; + $this->crypto = $crypto; + $this->config = $config; + $this->logger = $logger; + $this->time = $time; + } + + /** + * Create and persist a new token + * + * @param string $token + * @param string $uid + * @param string $password + * @param string $name + * @param int $type token type + * @return DefaultToken + */ + public function generateToken($token, $uid, $password, $name, $type = IToken::TEMPORARY_TOKEN) { + $dbToken = new DefaultToken(); + $dbToken->setUid($uid); + $dbToken->setPassword($this->encryptPassword($password, $token)); + $dbToken->setName($name); + $dbToken->setToken($this->hashToken($token)); + $dbToken->setType($type); + $dbToken->setLastActivity($this->time->getTime()); + + $this->mapper->insert($dbToken); + + return $dbToken; + } + + /** + * Update token activity timestamp + * + * @throws InvalidTokenException + * @param IToken $token + */ + public function updateToken(IToken $token) { + if (!($token instanceof DefaultToken)) { + throw new InvalidTokenException(); + } + /** @var DefaultToken $token */ + $token->setLastActivity($this->time->getTime()); + + $this->mapper->update($token); + } + + /** + * Get all token of a user + * + * The provider may limit the number of result rows in case of an abuse + * where a high number of (session) tokens is generated + * + * @param IUser $user + * @return IToken[] + */ + public function getTokenByUser(IUser $user) { + return $this->mapper->getTokenByUser($user); + } + + /** + * Get a token by token id + * + * @param string $tokenId + * @throws InvalidTokenException + * @return DefaultToken + */ + public function getToken($tokenId) { + try { + return $this->mapper->getToken($this->hashToken($tokenId)); + } catch (DoesNotExistException $ex) { + throw new InvalidTokenException(); + } + } + + /** + * @param IToken $savedToken + * @param string $tokenId session token + * @return string + */ + public function getPassword(IToken $savedToken, $tokenId) { + return $this->decryptPassword($savedToken->getPassword(), $tokenId); + } + + /** + * Invalidate (delete) the given session token + * + * @param string $token + */ + public function invalidateToken($token) { + $this->mapper->invalidate($this->hashToken($token)); + } + + /** + * Invalidate (delete) old session tokens + */ + public function invalidateOldTokens() { + $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24); + $this->logger->info('Invalidating tokens older than ' . date('c', $olderThan)); + $this->mapper->invalidateOld($olderThan); + } + + /** + * @param string $token + * @throws InvalidTokenException + * @return DefaultToken user UID + */ + public function validateToken($token) { + try { + $dbToken = $this->mapper->getToken($this->hashToken($token)); + $this->logger->debug('valid default token for ' . $dbToken->getUID()); + return $dbToken; + } catch (DoesNotExistException $ex) { + throw new InvalidTokenException(); + } + } + + /** + * @param string $token + * @return string + */ + private function hashToken($token) { + $secret = $this->config->getSystemValue('secret'); + return hash('sha512', $token . $secret); + } + + /** + * Encrypt the given password + * + * The token is used as key + * + * @param string $password + * @param string $token + * @return string encrypted password + */ + private function encryptPassword($password, $token) { + $secret = $this->config->getSystemValue('secret'); + return $this->crypto->encrypt($password, $token . $secret); + } + + /** + * Decrypt the given password + * + * The token is used as key + * + * @param string $password + * @param string $token + * @return string the decrypted key + */ + private function decryptPassword($password, $token) { + $secret = $this->config->getSystemValue('secret'); + try { + return $this->crypto->decrypt($password, $token . $secret); + } catch (Exception $ex) { + // Delete the invalid token + $this->invalidateToken($token); + throw new InvalidTokenException(); + } + } + +} diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php new file mode 100644 index 00000000000..a5c5faa5639 --- /dev/null +++ b/lib/private/Authentication/Token/IProvider.php @@ -0,0 +1,91 @@ +<?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 OC\Authentication\Token; + +use OC\Authentication\Exceptions\InvalidTokenException; +use OCP\IUser; + +interface IProvider { + + /** + * Create and persist a new token + * + * @param string $token + * @param string $uid + * @param string $password + * @param string $name + * @param int $type token type + * @return DefaultToken + */ + public function generateToken($token, $uid, $password, $name, $type = IToken::TEMPORARY_TOKEN); + + /** + * Get a token by token id + * + * @param string $tokenId + * @throws InvalidTokenException + * @return IToken + */ + public function getToken($tokenId) ; + + /** + * @param string $token + * @throws InvalidTokenException + * @return IToken + */ + public function validateToken($token); + + /** + * Invalidate (delete) the given session token + * + * @param string $token + */ + public function invalidateToken($token); + + /** + * Update token activity timestamp + * + * @param IToken $token + */ + public function updateToken(IToken $token); + + /** + * Get all token of a user + * + * The provider may limit the number of result rows in case of an abuse + * where a high number of (session) tokens is generated + * + * @param IUser $user + * @return IToken[] + */ + public function getTokenByUser(IUser $user); + + /** + * Get the (unencrypted) password of the given token + * + * @param IToken $token + * @param string $tokenId + * @return string + */ + public function getPassword(IToken $token, $tokenId); +} diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php new file mode 100644 index 00000000000..2a01ea75ea9 --- /dev/null +++ b/lib/private/Authentication/Token/IToken.php @@ -0,0 +1,50 @@ +<?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 OC\Authentication\Token; + +interface IToken { + + const TEMPORARY_TOKEN = 0; + const PERMANENT_TOKEN = 1; + + /** + * Get the token ID + * + * @return string + */ + public function getId(); + + /** + * Get the user UID + * + * @return string + */ + public function getUID(); + + /** + * Get the (encrypted) login password + * + * @return string + */ + public function getPassword(); +} diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php index 2429b830446..c84969776c2 100644 --- a/lib/private/BackgroundJob/JobList.php +++ b/lib/private/BackgroundJob/JobList.php @@ -25,27 +25,34 @@ namespace OC\BackgroundJob; use OCP\AppFramework\QueryException; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJob; use OCP\BackgroundJob\IJobList; use OCP\AutoloadNotAllowedException; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IConfig; +use OCP\IDBConnection; class JobList implements IJobList { - /** @var \OCP\IDBConnection */ + + /** @var IDBConnection */ protected $connection; - /** - * @var \OCP\IConfig $config - */ + /**@var IConfig */ protected $config; + /**@var ITimeFactory */ + protected $timeFactory; + /** - * @param \OCP\IDBConnection $connection - * @param \OCP\IConfig $config + * @param IDBConnection $connection + * @param IConfig $config + * @param ITimeFactory $timeFactory */ - public function __construct($connection, $config) { + public function __construct(IDBConnection $connection, IConfig $config, ITimeFactory $timeFactory) { $this->connection = $connection; $this->config = $config; + $this->timeFactory = $timeFactory; } /** @@ -71,6 +78,7 @@ class JobList implements IJobList { 'class' => $query->createNamedParameter($class), 'argument' => $query->createNamedParameter($argument), 'last_run' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT), + 'last_checked' => $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT), ]); $query->execute(); } @@ -167,45 +175,40 @@ class JobList implements IJobList { * @return IJob|null */ public function getNext() { - $lastId = $this->getLastJob(); - $query = $this->connection->getQueryBuilder(); $query->select('*') ->from('jobs') - ->where($query->expr()->lt('id', $query->createNamedParameter($lastId, IQueryBuilder::PARAM_INT))) - ->orderBy('id', 'DESC') + ->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - 12 * 3600, IQueryBuilder::PARAM_INT))) + ->orderBy('last_checked', 'ASC') ->setMaxResults(1); + + $update = $this->connection->getQueryBuilder(); + $update->update('jobs') + ->set('reserved_at', $update->createNamedParameter($this->timeFactory->getTime())) + ->set('last_checked', $update->createNamedParameter($this->timeFactory->getTime())) + ->where($update->expr()->eq('id', $update->createParameter('jobid'))); + + $this->connection->lockTable('jobs'); $result = $query->execute(); $row = $result->fetch(); $result->closeCursor(); if ($row) { - $jobId = $row['id']; + $update->setParameter('jobid', $row['id']); + $update->execute(); + $this->connection->unlockTable(); + $job = $this->buildJob($row); - } else { - //begin at the start of the queue - $query = $this->connection->getQueryBuilder(); - $query->select('*') - ->from('jobs') - ->orderBy('id', 'DESC') - ->setMaxResults(1); - $result = $query->execute(); - $row = $result->fetch(); - $result->closeCursor(); - - if ($row) { - $jobId = $row['id']; - $job = $this->buildJob($row); - } else { - return null; //empty job list + + if ($job === null) { + // Background job from disabled app, try again. + return $this->getNext(); } - } - if (is_null($job)) { - $this->removeById($jobId); - return $this->getNext(); - } else { return $job; + } else { + $this->connection->unlockTable(); + return null; } } @@ -267,13 +270,30 @@ class JobList implements IJobList { * @param IJob $job */ public function setLastJob($job) { + $this->unlockJob($job); $this->config->setAppValue('backgroundjob', 'lastjob', $job->getId()); } /** + * Remove the reservation for a job + * + * @param IJob $job + */ + public function unlockJob($job) { + $query = $this->connection->getQueryBuilder(); + $query->update('jobs') + ->set('reserved_at', $query->expr()->literal(0, IQueryBuilder::PARAM_INT)) + ->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT))); + $query->execute(); + } + + /** * get the id of the last ran job * * @return int + * @deprecated 9.1.0 - The functionality behind the value is deprecated, it + * only tells you which job finished last, but since we now allow multiple + * executors to run in parallel, it's not used to calculate the next job. */ public function getLastJob() { return (int) $this->config->getAppValue('backgroundjob', 'lastjob', 0); diff --git a/lib/private/Cache/File.php b/lib/private/Cache/File.php index 989e05275b7..38f88959bd7 100644 --- a/lib/private/Cache/File.php +++ b/lib/private/Cache/File.php @@ -172,7 +172,9 @@ class File implements ICache { public function gc() { $storage = $this->getStorage(); if ($storage and $storage->is_dir('/')) { - $now = time(); + // extra hour safety, in case of stray part chunks that take longer to write, + // because touch() is only called after the chunk was finished + $now = time() - 3600; $dh = $storage->opendir('/'); if (!is_resource($dh)) { return null; diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php index 7f12db4eca6..dd5111743f1 100644 --- a/lib/private/Console/Application.php +++ b/lib/private/Console/Application.php @@ -98,7 +98,7 @@ class Application { if($appPath === false) { continue; } - \OC::$loader->addValidRoot($appPath); + \OC_App::registerAutoloading($app, $appPath); $file = $appPath . '/appinfo/register_command.php'; if (file_exists($file)) { require $file; diff --git a/lib/private/DB/Adapter.php b/lib/private/DB/Adapter.php index 9522f768c88..bcced395cb7 100644 --- a/lib/private/DB/Adapter.php +++ b/lib/private/DB/Adapter.php @@ -58,6 +58,26 @@ class Adapter { } /** + * Create an exclusive read+write lock on a table + * + * @param string $tableName + * @since 9.1.0 + */ + public function lockTable($tableName) { + $this->conn->beginTransaction(); + $this->conn->executeUpdate('LOCK TABLE `' .$tableName . '` IN EXCLUSIVE MODE'); + } + + /** + * Release a previous acquired lock again + * + * @since 9.1.0 + */ + public function unlockTable() { + $this->conn->commit(); + } + + /** * Insert a row if the matching row does not exists. * * @param string $table The table name (will replace *PREFIX* with the actual prefix) diff --git a/lib/private/DB/AdapterMySQL.php b/lib/private/DB/AdapterMySQL.php index ab87c589747..8504fc74e0f 100644 --- a/lib/private/DB/AdapterMySQL.php +++ b/lib/private/DB/AdapterMySQL.php @@ -24,6 +24,18 @@ namespace OC\DB; class AdapterMySQL extends Adapter { + + /** + * @param string $tableName + */ + public function lockTable($tableName) { + $this->conn->executeUpdate('LOCK TABLES `' .$tableName . '` WRITE'); + } + + public function unlockTable() { + $this->conn->executeUpdate('UNLOCK TABLES'); + } + public function fixupStatement($statement) { $statement = str_replace(' ILIKE ', ' COLLATE utf8_general_ci LIKE ', $statement); return $statement; diff --git a/lib/private/DB/AdapterSqlite.php b/lib/private/DB/AdapterSqlite.php index 3466e0e1aac..cefb06ffac6 100644 --- a/lib/private/DB/AdapterSqlite.php +++ b/lib/private/DB/AdapterSqlite.php @@ -27,6 +27,18 @@ namespace OC\DB; class AdapterSqlite extends Adapter { + + /** + * @param string $tableName + */ + public function lockTable($tableName) { + $this->conn->executeUpdate('BEGIN EXCLUSIVE TRANSACTION'); + } + + public function unlockTable() { + $this->conn->executeUpdate('COMMIT TRANSACTION'); + } + public function fixupStatement($statement) { $statement = preg_replace('( I?LIKE \?)', '$0 ESCAPE \'\\\'', $statement); $statement = preg_replace('/`(\w+)` ILIKE \?/', 'LOWER($1) LIKE LOWER(?)', $statement); diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index 7904fab0726..5b7026db2f3 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -25,6 +25,7 @@ */ namespace OC\DB; + use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Configuration; @@ -33,7 +34,7 @@ use Doctrine\Common\EventManager; use OC\DB\QueryBuilder\QueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; -use OCP\PreconditionNotMetException; +use OCP\PreConditionNotMetException; class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { /** @@ -46,6 +47,8 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { */ protected $adapter; + protected $lockedTable = null; + public function connect() { try { return parent::connect(); @@ -262,7 +265,7 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { * @param array $updatePreconditionValues ensure values match preconditions (column name => value) * @return int number of new rows * @throws \Doctrine\DBAL\DBALException - * @throws PreconditionNotMetException + * @throws PreConditionNotMetException */ public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) { try { @@ -281,7 +284,7 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { foreach ($values as $name => $value) { $updateQb->set($name, $updateQb->createNamedParameter($value, $this->getType($value))); } - $where = $updateQb->expr()->andx(); + $where = $updateQb->expr()->andX(); $whereValues = array_merge($keys, $updatePreconditionValues); foreach ($whereValues as $name => $value) { $where->add($updateQb->expr()->eq( @@ -294,7 +297,7 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { $affected = $updateQb->execute(); if ($affected === 0 && !empty($updatePreconditionValues)) { - throw new PreconditionNotMetException(); + throw new PreConditionNotMetException(); } return 0; @@ -302,6 +305,33 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { } /** + * Create an exclusive read+write lock on a table + * + * @param string $tableName + * @throws \BadMethodCallException When trying to acquire a second lock + * @since 9.1.0 + */ + public function lockTable($tableName) { + if ($this->lockedTable !== null) { + throw new \BadMethodCallException('Can not lock a new table until the previous lock is released.'); + } + + $tableName = $this->tablePrefix . $tableName; + $this->lockedTable = $tableName; + $this->adapter->lockTable($tableName); + } + + /** + * Release a previous acquired lock again + * + * @since 9.1.0 + */ + public function unlockTable() { + $this->adapter->unlockTable(); + $this->lockedTable = null; + } + + /** * returns the error code and message as a string for logging * works with DoctrineException * @return string diff --git a/lib/private/datetimeformatter.php b/lib/private/DateTimeFormatter.php index 5639ab1cace..5639ab1cace 100644 --- a/lib/private/datetimeformatter.php +++ b/lib/private/DateTimeFormatter.php diff --git a/lib/private/datetimezone.php b/lib/private/DateTimeZone.php index 5359cd6b391..5359cd6b391 100644 --- a/lib/private/datetimezone.php +++ b/lib/private/DateTimeZone.php diff --git a/lib/private/Files/Cache/Wrapper/CacheJail.php b/lib/private/Files/Cache/Wrapper/CacheJail.php index 3148d1412f4..d737d28fc80 100644 --- a/lib/private/Files/Cache/Wrapper/CacheJail.php +++ b/lib/private/Files/Cache/Wrapper/CacheJail.php @@ -303,6 +303,6 @@ class CacheJail extends CacheWrapper { if ($sourceCache === $this) { return $this->move($sourcePath, $targetPath); } - return $this->cache->moveFromCache($sourceCache, $sourcePath, $targetPath); + return $this->cache->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath)); } } diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php index 499fa576fbc..60c90d7a019 100644 --- a/lib/private/Files/Config/MountProviderCollection.php +++ b/lib/private/Files/Config/MountProviderCollection.php @@ -24,6 +24,7 @@ namespace OC\Files\Config; use OC\Hooks\Emitter; use OC\Hooks\EmitterTrait; +use OCP\Files\Config\IHomeMountProvider; use OCP\Files\Config\IMountProviderCollection; use OCP\Files\Config\IMountProvider; use OCP\Files\Config\IUserMountCache; @@ -35,6 +36,11 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { use EmitterTrait; /** + * @var \OCP\Files\Config\IHomeMountProvider[] + */ + private $homeProviders = []; + + /** * @var \OCP\Files\Config\IMountProvider[] */ private $providers = array(); @@ -78,6 +84,25 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { } /** + * Get the configured home mount for this user + * + * @param \OCP\IUser $user + * @return \OCP\Files\Mount\IMountPoint + * @since 9.1.0 + */ + public function getHomeMountForUser(IUser $user) { + /** @var \OCP\Files\Config\IHomeMountProvider[] $providers */ + $providers = array_reverse($this->homeProviders); // call the latest registered provider first to give apps an opportunity to overwrite builtin + foreach ($providers as $homeProvider) { + if ($mount = $homeProvider->getHomeMountForUser($user, $this->loader)) { + $mount->setMountPoint('/' . $user->getUID()); //make sure the mountpoint is what we expect + return $mount; + } + } + throw new \Exception('No home storage configured for user ' . $user); + } + + /** * Add a provider for mount points * * @param \OCP\Files\Config\IMountProvider $provider @@ -88,6 +113,17 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { } /** + * Add a provider for home mount points + * + * @param \OCP\Files\Config\IHomeMountProvider $provider + * @since 9.1.0 + */ + public function registerHomeProvider(IHomeMountProvider $provider) { + $this->homeProviders[] = $provider; + $this->emit('\OC\Files\Config', 'registerHomeMountProvider', [$provider]); + } + + /** * Cache mounts for user * * @param IUser $user diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index 7283c815c97..70236773448 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -58,6 +58,7 @@ namespace OC\Files; +use OC\Cache\CappedMemoryCache; use OC\Files\Config\MountProviderCollection; use OC\Files\Mount\MountPoint; use OC\Files\Storage\StorageFactory; @@ -81,7 +82,7 @@ class Filesystem { static private $usersSetup = array(); - static private $normalizedPathCache = array(); + static private $normalizedPathCache = null; static private $listeningForProviders = false; @@ -207,12 +208,30 @@ class Filesystem { */ private static $loader; + /** @var bool */ + private static $logWarningWhenAddingStorageWrapper = true; + + /** + * @param bool $shouldLog + * @internal + */ + public static function logWarningWhenAddingStorageWrapper($shouldLog) { + self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog; + } + /** * @param string $wrapperName * @param callable $wrapper * @param int $priority */ public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) { + if (self::$logWarningWhenAddingStorageWrapper) { + \OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [ + 'wrapper' => $wrapperName, + 'app' => 'filesystem', + ]); + } + $mounts = self::getMountManager()->getAll(); if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) { // do not re-wrap if storage with this name already existed @@ -378,7 +397,6 @@ class Filesystem { if (isset(self::$usersSetup[$user])) { return; } - $root = \OC_User::getHome($user); $userManager = \OC::$server->getUserManager(); $userObject = $userManager->get($user); @@ -390,52 +408,26 @@ class Filesystem { self::$usersSetup[$user] = true; - $homeStorage = \OC::$server->getConfig()->getSystemValue('objectstore'); - if (!empty($homeStorage)) { - // sanity checks - if (empty($homeStorage['class'])) { - \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR); - } - if (!isset($homeStorage['arguments'])) { - $homeStorage['arguments'] = array(); - } - // instantiate object store implementation - $homeStorage['arguments']['objectstore'] = new $homeStorage['class']($homeStorage['arguments']); - // mount with home object store implementation - $homeStorage['class'] = '\OC\Files\ObjectStore\HomeObjectStoreStorage'; - } else { - $homeStorage = array( - //default home storage configuration: - 'class' => '\OC\Files\Storage\Home', - 'arguments' => array() - ); - } - $homeStorage['arguments']['user'] = $userObject; - - // check for legacy home id (<= 5.0.12) - if (\OC\Files\Cache\Storage::exists('local::' . $root . '/')) { - $homeStorage['arguments']['legacy'] = true; - } + /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */ + $mountConfigManager = \OC::$server->getMountProviderCollection(); - $mount = new MountPoint($homeStorage['class'], '/' . $user, $homeStorage['arguments'], self::getLoader()); - self::getMountManager()->addMount($mount); + // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers + $homeMount = $mountConfigManager->getHomeMountForUser($userObject); - $home = \OC\Files\Filesystem::getStorage($user); + self::getMountManager()->addMount($homeMount); - self::mountCacheDir($user); + \OC\Files\Filesystem::getStorage($user); // Chance to mount for other storages - /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */ - $mountConfigManager = \OC::$server->getMountProviderCollection(); if ($userObject) { $mounts = $mountConfigManager->getMountsForUser($userObject); array_walk($mounts, array(self::$mounts, 'addMount')); - $mounts[] = $mount; + $mounts[] = $homeMount; $mountConfigManager->registerMounts($userObject, $mounts); } self::listenForNewMountProviders($mountConfigManager, $userManager); - \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', array('user' => $user, 'user_dir' => $root)); + \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', array('user' => $user)); } /** @@ -460,23 +452,6 @@ class Filesystem { } /** - * Mounts the cache directory - * - * @param string $user user name - */ - private static function mountCacheDir($user) { - $cacheBaseDir = \OC::$server->getConfig()->getSystemValue('cache_path', ''); - if ($cacheBaseDir !== '') { - $cacheDir = rtrim($cacheBaseDir, '/') . '/' . $user; - if (!file_exists($cacheDir)) { - mkdir($cacheDir, 0770, true); - } - // mount external cache dir to "/$user/cache" mount point - self::mount('\OC\Files\Storage\Local', array('datadir' => $cacheDir), '/' . $user . '/cache'); - } - } - - /** * get the default filesystem view * * @return View @@ -789,11 +764,16 @@ 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(); + } + /** * FIXME: This is a workaround for existing classes and files which call * this function with another type than a valid string. This @@ -813,19 +793,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; @@ -851,7 +825,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/Files/Mount/CacheMountProvider.php b/lib/private/Files/Mount/CacheMountProvider.php new file mode 100644 index 00000000000..c8422c4a507 --- /dev/null +++ b/lib/private/Files/Mount/CacheMountProvider.php @@ -0,0 +1,69 @@ +<?php +/** + * @author Robin Appelman <icewind@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 OC\Files\Mount; + +use OCP\Files\Config\IMountProvider; +use OCP\Files\Storage\IStorageFactory; +use OCP\IConfig; +use OCP\IUser; + +/** + * Mount provider for custom cache storages + */ +class CacheMountProvider implements IMountProvider { + /** + * @var IConfig + */ + private $config; + + /** + * ObjectStoreHomeMountProvider constructor. + * + * @param IConfig $config + */ + public function __construct(IConfig $config) { + $this->config = $config; + } + + /** + * Get the cache mount for a user + * + * @param IUser $user + * @param IStorageFactory $loader + * @return \OCP\Files\Mount\IMountPoint[] + */ + public function getMountsForUser(IUser $user, IStorageFactory $loader) { + $cacheBaseDir = $this->config->getSystemValue('cache_path', ''); + if ($cacheBaseDir !== '') { + $cacheDir = rtrim($cacheBaseDir, '/') . '/' . $user->getUID(); + if (!file_exists($cacheDir)) { + mkdir($cacheDir, 0770, true); + } + + return [ + new MountPoint('\OC\Files\Storage\Local', '/' . $user->getUID() . '/cache', ['datadir' => $cacheDir, $loader]) + ]; + } else { + return []; + } + } +} diff --git a/lib/private/Files/Mount/LocalHomeMountProvider.php b/lib/private/Files/Mount/LocalHomeMountProvider.php new file mode 100644 index 00000000000..102df59a536 --- /dev/null +++ b/lib/private/Files/Mount/LocalHomeMountProvider.php @@ -0,0 +1,46 @@ +<?php +/** + * @author Robin Appelman <icewind@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 OC\Files\Mount; + +use OCP\Files\Config\IHomeMountProvider; +use OCP\Files\Storage\IStorageFactory; +use OCP\IUser; + +/** + * Mount provider for regular posix home folders + */ +class LocalHomeMountProvider implements IHomeMountProvider { + /** + * Get the cache mount for a user + * + * @param IUser $user + * @param IStorageFactory $loader + * @return \OCP\Files\Mount\IMountPoint[] + */ + public function getHomeMountForUser(IUser $user, IStorageFactory $loader) { + $arguments = ['user' => $user]; + if (\OC\Files\Cache\Storage::exists('local::' . $user->getHome() . '/')) { + $arguments['legacy'] = true; + } + return new MountPoint('\OC\Files\Storage\Home', '/' . $user->getUID(), $arguments, $loader); + } +} diff --git a/lib/private/Files/Mount/ObjectHomeMountProvider.php b/lib/private/Files/Mount/ObjectHomeMountProvider.php new file mode 100644 index 00000000000..c910cf6bd45 --- /dev/null +++ b/lib/private/Files/Mount/ObjectHomeMountProvider.php @@ -0,0 +1,73 @@ +<?php +/** + * @author Robin Appelman <icewind@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 OC\Files\Mount; + +use OCP\Files\Config\IHomeMountProvider; +use OCP\Files\Storage\IStorageFactory; +use OCP\IConfig; +use OCP\IUser; + +/** + * Mount provider for object store home storages + */ +class ObjectHomeMountProvider implements IHomeMountProvider { + /** + * @var IConfig + */ + private $config; + + /** + * ObjectStoreHomeMountProvider constructor. + * + * @param IConfig $config + */ + public function __construct(IConfig $config) { + $this->config = $config; + } + + /** + * Get the cache mount for a user + * + * @param IUser $user + * @param IStorageFactory $loader + * @return \OCP\Files\Mount\IMountPoint[] + */ + public function getHomeMountForUser(IUser $user, IStorageFactory $loader) { + $config = $this->config->getSystemValue('objectstore'); + if (!is_array($config)) { + return null; //fall back to local home provider + } + + // sanity checks + if (empty($config['class'])) { + \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR); + } + if (!isset($config['arguments'])) { + $config['arguments'] = []; + } + $config['arguments']['user'] = $user; + // instantiate object store implementation + $config['arguments']['objectstore'] = new $config['class']($config['arguments']); + + return new MountPoint('\OC\Files\ObjectStore\HomeObjectStoreStorage', '/' . $user->getUID(), $config['arguments'], $loader); + } +} diff --git a/lib/private/Files/Storage/Wrapper/Availability.php b/lib/private/Files/Storage/Wrapper/Availability.php index 0ed31ba854a..8d6fc4b3369 100644 --- a/lib/private/Files/Storage/Wrapper/Availability.php +++ b/lib/private/Files/Storage/Wrapper/Availability.php @@ -40,9 +40,13 @@ class Availability extends Wrapper { } /** + * Only called if availability === false + * * @return bool */ private function updateAvailability() { + // reset availability to false so that multiple requests don't recheck concurrently + $this->setAvailability(false); try { $result = $this->test(); } catch (\Exception $e) { diff --git a/lib/private/forbiddenexception.php b/lib/private/ForbiddenException.php index 48be35ba316..48be35ba316 100644 --- a/lib/private/forbiddenexception.php +++ b/lib/private/ForbiddenException.php diff --git a/lib/private/group/backend.php b/lib/private/Group/Backend.php index 3d8d71b1529..6dd5bdc3507 100644 --- a/lib/private/group/backend.php +++ b/lib/private/Group/Backend.php @@ -29,32 +29,12 @@ * */ -/** - * error code for functions not provided by the group backend - * @deprecated Use \OC_Group_Backend::NOT_IMPLEMENTED instead - */ -define('OC_GROUP_BACKEND_NOT_IMPLEMENTED', -501); - -/** - * actions that user backends can define - */ -/** @deprecated Use \OC_Group_Backend::CREATE_GROUP instead */ -define('OC_GROUP_BACKEND_CREATE_GROUP', 0x00000001); -/** @deprecated Use \OC_Group_Backend::DELETE_GROUP instead */ -define('OC_GROUP_BACKEND_DELETE_GROUP', 0x00000010); -/** @deprecated Use \OC_Group_Backend::ADD_TO_GROUP instead */ -define('OC_GROUP_BACKEND_ADD_TO_GROUP', 0x00000100); -/** @deprecated Use \OC_Group_Backend::REMOVE_FROM_GOUP instead */ -define('OC_GROUP_BACKEND_REMOVE_FROM_GOUP', 0x00001000); -/** @deprecated Obsolete */ -define('OC_GROUP_BACKEND_GET_DISPLAYNAME', 0x00010000); //OBSOLETE -/** @deprecated Use \OC_Group_Backend::COUNT_USERS instead */ -define('OC_GROUP_BACKEND_COUNT_USERS', 0x00100000); +namespace OC\Group; /** * Abstract base class for user management */ -abstract class OC_Group_Backend implements \OCP\GroupInterface { +abstract class Backend implements \OCP\GroupInterface { /** * error code for functions not provided by the group backend */ @@ -83,7 +63,7 @@ abstract class OC_Group_Backend implements \OCP\GroupInterface { * @return int bitwise-or'ed actions * * Returns the supported actions as int to be - * compared with \OC_Group_Backend::CREATE_GROUP etc. + * compared with \OC\Group\Backend::CREATE_GROUP etc. */ public function getSupportedActions() { $actions = 0; @@ -102,7 +82,7 @@ abstract class OC_Group_Backend implements \OCP\GroupInterface { * @return bool * * Returns the supported actions as int to be - * compared with \OC_Group_Backend::CREATE_GROUP etc. + * compared with \OC\Group\Backend::CREATE_GROUP etc. */ public function implementsActions($actions) { return (bool)($this->getSupportedActions() & $actions); diff --git a/lib/private/group/database.php b/lib/private/Group/Database.php index 9ea0bbb8242..9fefdd77300 100644 --- a/lib/private/group/database.php +++ b/lib/private/Group/Database.php @@ -46,10 +46,12 @@ * */ +namespace OC\Group; + /** * Class for group management in a SQL Database (e.g. MySQL, SQLite) */ -class OC_Group_Database extends OC_Group_Backend { +class Database extends \OC\Group\Backend { /** @var string[] */ private $groupCache = []; @@ -58,7 +60,7 @@ class OC_Group_Database extends OC_Group_Backend { private $dbConn; /** - * OC_Group_Database constructor. + * \OC\Group\Database constructor. * * @param \OCP\IDBConnection|null $dbConn */ @@ -245,7 +247,7 @@ class OC_Group_Database extends OC_Group_Backend { $searchLike = ' WHERE LOWER(`gid`) LIKE LOWER(?)'; } - $stmt = OC_DB::prepare('SELECT `gid` FROM `*PREFIX*groups`' . $searchLike . ' ORDER BY `gid` ASC', $limit, $offset); + $stmt = \OC_DB::prepare('SELECT `gid` FROM `*PREFIX*groups`' . $searchLike . ' ORDER BY `gid` ASC', $limit, $offset); $result = $stmt->execute($parameters); $groups = array(); while ($row = $result->fetchRow()) { @@ -298,7 +300,7 @@ class OC_Group_Database extends OC_Group_Backend { $searchLike = ' AND `uid` LIKE ?'; } - $stmt = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*group_user` WHERE `gid` = ?' . $searchLike . ' ORDER BY `uid` ASC', + $stmt = \OC_DB::prepare('SELECT `uid` FROM `*PREFIX*group_user` WHERE `gid` = ?' . $searchLike . ' ORDER BY `uid` ASC', $limit, $offset); $result = $stmt->execute($parameters); @@ -324,7 +326,7 @@ class OC_Group_Database extends OC_Group_Backend { $searchLike = ' AND `uid` LIKE ?'; } - $stmt = OC_DB::prepare('SELECT COUNT(`uid`) AS `count` FROM `*PREFIX*group_user` WHERE `gid` = ?' . $searchLike); + $stmt = \OC_DB::prepare('SELECT COUNT(`uid`) AS `count` FROM `*PREFIX*group_user` WHERE `gid` = ?' . $searchLike); $result = $stmt->execute($parameters); $count = $result->fetchOne(); if($count !== false) { diff --git a/lib/private/group/group.php b/lib/private/Group/Group.php index 064b9f899e6..c42f53af9a6 100644 --- a/lib/private/group/group.php +++ b/lib/private/Group/Group.php @@ -46,7 +46,7 @@ class Group implements IGroup { private $usersLoaded; /** - * @var \OC_Group_Backend[]|\OC_Group_Database[] $backend + * @var \OC\Group\Backend[]|\OC\Group\Database[] $backend */ private $backends; @@ -62,7 +62,7 @@ class Group implements IGroup { /** * @param string $gid - * @param \OC_Group_Backend[] $backends + * @param \OC\Group\Backend[] $backends * @param \OC\User\Manager $userManager * @param \OC\Hooks\PublicEmitter $emitter */ @@ -136,7 +136,7 @@ class Group implements IGroup { $this->emitter->emit('\OC\Group', 'preAddUser', array($this, $user)); } foreach ($this->backends as $backend) { - if ($backend->implementsActions(\OC_Group_Backend::ADD_TO_GROUP)) { + if ($backend->implementsActions(\OC\Group\Backend::ADD_TO_GROUP)) { $backend->addToGroup($user->getUID(), $this->gid); if ($this->users) { $this->users[$user->getUID()] = $user; @@ -160,7 +160,7 @@ class Group implements IGroup { $this->emitter->emit('\OC\Group', 'preRemoveUser', array($this, $user)); } foreach ($this->backends as $backend) { - if ($backend->implementsActions(\OC_Group_Backend::REMOVE_FROM_GOUP) and $backend->inGroup($user->getUID(), $this->gid)) { + if ($backend->implementsActions(\OC\Group\Backend::REMOVE_FROM_GOUP) and $backend->inGroup($user->getUID(), $this->gid)) { $backend->removeFromGroup($user->getUID(), $this->gid); $result = true; } @@ -209,7 +209,7 @@ class Group implements IGroup { public function count($search = '') { $users = false; foreach ($this->backends as $backend) { - if($backend->implementsActions(\OC_Group_Backend::COUNT_USERS)) { + if($backend->implementsActions(\OC\Group\Backend::COUNT_USERS)) { if($users === false) { //we could directly add to a bool variable, but this would //be ugly @@ -257,7 +257,7 @@ class Group implements IGroup { $this->emitter->emit('\OC\Group', 'preDelete', array($this)); } foreach ($this->backends as $backend) { - if ($backend->implementsActions(\OC_Group_Backend::DELETE_GROUP)) { + if ($backend->implementsActions(\OC\Group\Backend::DELETE_GROUP)) { $result = true; $backend->deleteGroup($this->gid); } diff --git a/lib/private/group/manager.php b/lib/private/Group/Manager.php index e82a1d4f2e6..22367180edd 100644 --- a/lib/private/group/manager.php +++ b/lib/private/Group/Manager.php @@ -190,7 +190,7 @@ class Manager extends PublicEmitter implements IGroupManager { } else { $this->emit('\OC\Group', 'preCreate', array($gid)); foreach ($this->backends as $backend) { - if ($backend->implementsActions(\OC_Group_Backend::CREATE_GROUP)) { + if ($backend->implementsActions(\OC\Group\Backend::CREATE_GROUP)) { $backend->createGroup($gid); $group = $this->getGroupObject($gid); $this->emit('\OC\Group', 'postCreate', array($group)); diff --git a/lib/private/group/metadata.php b/lib/private/Group/MetaData.php index 8e0866479c1..8e0866479c1 100644 --- a/lib/private/group/metadata.php +++ b/lib/private/Group/MetaData.php diff --git a/lib/private/httphelper.php b/lib/private/HTTPHelper.php index f33d4a51745..f33d4a51745 100644 --- a/lib/private/httphelper.php +++ b/lib/private/HTTPHelper.php diff --git a/lib/private/hintexception.php b/lib/private/HintException.php index aeddea481cc..aeddea481cc 100644 --- a/lib/private/hintexception.php +++ b/lib/private/HintException.php diff --git a/lib/private/Http/Client/Client.php b/lib/private/Http/Client/Client.php index bd9e82ddae7..3f49b224d1e 100644 --- a/lib/private/Http/Client/Client.php +++ b/lib/private/Http/Client/Client.php @@ -39,6 +39,7 @@ class Client implements IClient { private $config; /** @var ICertificateManager */ private $certificateManager; + private $configured = false; /** * @param IConfig $config @@ -51,13 +52,16 @@ class Client implements IClient { $this->config = $config; $this->client = $client; $this->certificateManager = $certificateManager; - $this->setDefaultOptions(); } /** * Sets the default options to the client */ private function setDefaultOptions() { + if ($this->configured) { + return; + } + $this->configured = true; // Either use user bundle or the system bundle if nothing is specified if ($this->certificateManager->listCertificates() !== []) { $this->client->setDefaultOption('verify', $this->certificateManager->getAbsoluteBundlePath()); @@ -65,7 +69,7 @@ class Client implements IClient { // If the instance is not yet setup we need to use the static path as // $this->certificateManager->getAbsoluteBundlePath() tries to instantiiate // a view - if($this->config->getSystemValue('installed', false)) { + if ($this->config->getSystemValue('installed', false)) { $this->client->setDefaultOption('verify', $this->certificateManager->getAbsoluteBundlePath(null)); } else { $this->client->setDefaultOption('verify', \OC::$SERVERROOT . '/resources/config/ca-bundle.crt'); @@ -73,13 +77,14 @@ class Client implements IClient { } $this->client->setDefaultOption('headers/User-Agent', 'ownCloud Server Crawler'); - if($this->getProxyUri() !== '') { + if ($this->getProxyUri() !== '') { $this->client->setDefaultOption('proxy', $this->getProxyUri()); } } /** * Get the proxy URI + * * @return string */ private function getProxyUri() { @@ -87,10 +92,10 @@ class Client implements IClient { $proxyUserPwd = $this->config->getSystemValue('proxyuserpwd', null); $proxyUri = ''; - if(!is_null($proxyUserPwd)) { - $proxyUri .= $proxyUserPwd.'@'; + if (!is_null($proxyUserPwd)) { + $proxyUri .= $proxyUserPwd . '@'; } - if(!is_null($proxyHost)) { + if (!is_null($proxyHost)) { $proxyUri .= $proxyHost; } @@ -99,6 +104,7 @@ class Client implements IClient { /** * Sends a GET request + * * @param string $uri * @param array $options Array such as * 'query' => [ @@ -126,6 +132,7 @@ class Client implements IClient { * @throws \Exception If the request could not get completed */ public function get($uri, array $options = []) { + $this->setDefaultOptions(); $response = $this->client->get($uri, $options); $isStream = isset($options['stream']) && $options['stream']; return new Response($response, $isStream); @@ -133,6 +140,7 @@ class Client implements IClient { /** * Sends a HEAD request + * * @param string $uri * @param array $options Array such as * 'headers' => [ @@ -155,12 +163,14 @@ class Client implements IClient { * @throws \Exception If the request could not get completed */ public function head($uri, $options = []) { + $this->setDefaultOptions(); $response = $this->client->head($uri, $options); return new Response($response); } /** * Sends a POST request + * * @param string $uri * @param array $options Array such as * 'body' => [ @@ -188,12 +198,14 @@ class Client implements IClient { * @throws \Exception If the request could not get completed */ public function post($uri, array $options = []) { + $this->setDefaultOptions(); $response = $this->client->post($uri, $options); return new Response($response); } /** * Sends a PUT request + * * @param string $uri * @param array $options Array such as * 'body' => [ @@ -221,12 +233,14 @@ class Client implements IClient { * @throws \Exception If the request could not get completed */ public function put($uri, array $options = []) { + $this->setDefaultOptions(); $response = $this->client->put($uri, $options); return new Response($response); } /** * Sends a DELETE request + * * @param string $uri * @param array $options Array such as * 'body' => [ @@ -254,6 +268,7 @@ class Client implements IClient { * @throws \Exception If the request could not get completed */ public function delete($uri, array $options = []) { + $this->setDefaultOptions(); $response = $this->client->delete($uri, $options); return new Response($response); } @@ -261,6 +276,7 @@ class Client implements IClient { /** * Sends a options request + * * @param string $uri * @param array $options Array such as * 'body' => [ @@ -288,6 +304,7 @@ class Client implements IClient { * @throws \Exception If the request could not get completed */ public function options($uri, array $options = []) { + $this->setDefaultOptions(); $response = $this->client->options($uri, $options); return new Response($response); } diff --git a/lib/private/installer.php b/lib/private/Installer.php index 24c79b2dd8c..336fa0acef8 100644 --- a/lib/private/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'); } @@ -582,13 +564,16 @@ class OC_Installer{ } //run appinfo/install.php - \OC::$loader->addValidRoot($appPath); + \OC_App::registerAutoloading($app, $appPath); self::includeAppScript("$appPath/appinfo/install.php"); $info = OC_App::getAppInfo($app); 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/L10N/Factory.php b/lib/private/L10N/Factory.php index 8f157d9c0bb..08b92657a1b 100644 --- a/lib/private/L10N/Factory.php +++ b/lib/private/L10N/Factory.php @@ -263,7 +263,7 @@ class Factory implements IFactory { } } - if (!$this->requestLanguage) { + if ($app === null && !$this->requestLanguage) { $this->requestLanguage = 'en'; } return 'en'; // Last try: English diff --git a/lib/private/largefilehelper.php b/lib/private/LargeFileHelper.php index f5252ee01e7..f5252ee01e7 100644 --- a/lib/private/largefilehelper.php +++ b/lib/private/LargeFileHelper.php diff --git a/lib/private/Lock/AbstractLockingProvider.php b/lib/private/Lock/AbstractLockingProvider.php index f96358778c1..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]); @@ -116,4 +119,8 @@ abstract class AbstractLockingProvider implements ILockingProvider { $this->releaseLock($path, self::LOCK_EXCLUSIVE); } } + + protected function getOwnSharedLockCount($path) { + return isset($this->acquiredLocks['shared'][$path]) ? $this->acquiredLocks['shared'][$path] : 0; + } } diff --git a/lib/private/Lock/MemcacheLockingProvider.php b/lib/private/Lock/MemcacheLockingProvider.php index 536b29e2c28..56e581b2192 100644 --- a/lib/private/Lock/MemcacheLockingProvider.php +++ b/lib/private/Lock/MemcacheLockingProvider.php @@ -88,9 +88,14 @@ class MemcacheLockingProvider extends AbstractLockingProvider { */ public function releaseLock($path, $type) { if ($type === self::LOCK_SHARED) { - if (isset($this->acquiredLocks['shared'][$path]) and $this->acquiredLocks['shared'][$path] > 0) { + if ($this->getOwnSharedLockCount($path) === 1) { + $removed = $this->memcache->cad($path, 1); // if we're the only one having a shared lock we can remove it in one go + if (!$removed) { //someone else also has a shared lock, decrease only + $this->memcache->dec($path); + } + } else { + // if we own more than one lock ourselves just decrease $this->memcache->dec($path); - $this->memcache->cad($path, 0); } } else if ($type === self::LOCK_EXCLUSIVE) { $this->memcache->cad($path, 'exclusive'); 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/Memcache/Memcached.php b/lib/private/Memcache/Memcached.php index a30f9da7ed7..63ac73e9b9d 100644 --- a/lib/private/Memcache/Memcached.php +++ b/lib/private/Memcache/Memcached.php @@ -26,6 +26,7 @@ namespace OC\Memcache; +use OC\HintException; use OCP\IMemcache; class Memcached extends Cache implements IMemcache { @@ -52,6 +53,35 @@ class Memcached extends Cache implements IMemcache { } } self::$cache->addServers($servers); + + $defaultOptions = [ + \Memcached::OPT_CONNECT_TIMEOUT => 50, + \Memcached::OPT_RETRY_TIMEOUT => 50, + \Memcached::OPT_SEND_TIMEOUT => 50, + \Memcached::OPT_RECV_TIMEOUT => 50, + \Memcached::OPT_POLL_TIMEOUT => 50, + + // Enable compression + \Memcached::OPT_COMPRESSION => true, + + // Turn on consistent hashing + \Memcached::OPT_LIBKETAMA_COMPATIBLE => true, + + // Enable Binary Protocol + \Memcached::OPT_BINARY_PROTOCOL => true, + ]; + // by default enable igbinary serializer if available + if (\Memcached::HAVE_IGBINARY) { + $defaultOptions[\Memcached::OPT_SERIALIZER] = + \Memcached::SERIALIZER_IGBINARY; + } + $options = \OC::$server->getConfig()->getSystemValue('memcached_options', []); + if (is_array($options)) { + $options = $options + $defaultOptions; + self::$cache->setOptions($options); + } else { + throw new HintException("Expected 'memcached_options' config to be an array, got $options"); + } } } diff --git a/lib/private/Memcache/Redis.php b/lib/private/Memcache/Redis.php index b3444a2b4e9..5b6955823c4 100644 --- a/lib/private/Memcache/Redis.php +++ b/lib/private/Memcache/Redis.php @@ -37,33 +37,7 @@ class Redis extends Cache implements IMemcacheTTL { public function __construct($prefix = '') { parent::__construct($prefix); if (is_null(self::$cache)) { - // TODO allow configuring a RedisArray, see https://github.com/nicolasff/phpredis/blob/master/arrays.markdown#redis-arrays - self::$cache = new \Redis(); - $config = \OC::$server->getSystemConfig()->getValue('redis', array()); - if (isset($config['host'])) { - $host = $config['host']; - } else { - $host = '127.0.0.1'; - } - if (isset($config['port'])) { - $port = $config['port']; - } else { - $port = 6379; - } - if (isset($config['timeout'])) { - $timeout = $config['timeout']; - } else { - $timeout = 0.0; // unlimited - } - - self::$cache->connect($host, $port, $timeout); - if(isset($config['password']) && $config['password'] !== '') { - self::$cache->auth($config['password']); - } - - if (isset($config['dbindex'])) { - self::$cache->select($config['dbindex']); - } + self::$cache = \OC::$server->getGetRedisFactory()->getInstance(); } } @@ -201,8 +175,7 @@ class Redis extends Cache implements IMemcacheTTL { } static public function isAvailable() { - return extension_loaded('redis') - && version_compare(phpversion('redis'), '2.2.5', '>='); + return \OC::$server->getGetRedisFactory()->isAvailable(); } } diff --git a/lib/private/naturalsort.php b/lib/private/NaturalSort.php index f44e8032d36..f44e8032d36 100644 --- a/lib/private/naturalsort.php +++ b/lib/private/NaturalSort.php diff --git a/lib/private/naturalsort_defaultcollator.php b/lib/private/NaturalSort_DefaultCollator.php index 7b8400fa8e1..7b8400fa8e1 100644 --- a/lib/private/naturalsort_defaultcollator.php +++ b/lib/private/NaturalSort_DefaultCollator.php diff --git a/lib/private/navigationmanager.php b/lib/private/NavigationManager.php index 6dbb9c925e0..6dbb9c925e0 100644 --- a/lib/private/navigationmanager.php +++ b/lib/private/NavigationManager.php diff --git a/lib/private/needsupdateexception.php b/lib/private/NeedsUpdateException.php index 90c642780d8..90c642780d8 100644 --- a/lib/private/needsupdateexception.php +++ b/lib/private/NeedsUpdateException.php diff --git a/lib/private/notsquareexception.php b/lib/private/NotSquareException.php index e3494463850..e3494463850 100644 --- a/lib/private/notsquareexception.php +++ b/lib/private/NotSquareException.php diff --git a/lib/private/ocs/cloud.php b/lib/private/OCS/Cloud.php index 1d47fb208a7..9686e9bfb58 100644 --- a/lib/private/ocs/cloud.php +++ b/lib/private/OCS/Cloud.php @@ -22,7 +22,9 @@ * */ -class OC_OCS_Cloud { +namespace OC\OCS; + +class Cloud { public static function getCapabilities() { $result = array(); @@ -31,22 +33,22 @@ class OC_OCS_Cloud { 'major' => $major, 'minor' => $minor, 'micro' => $micro, - 'string' => OC_Util::getVersionString(), - 'edition' => OC_Util::getEditionString(), + 'string' => \OC_Util::getVersionString(), + 'edition' => \OC_Util::getEditionString(), ); $result['capabilities'] = \OC::$server->getCapabilitiesManager()->getCapabilities(); - return new OC_OCS_Result($result); + return new Result($result); } public static function getCurrentUser() { - $userObject = \OC::$server->getUserManager()->get(OC_User::getUser()); + $userObject = \OC::$server->getUserManager()->get(\OC_User::getUser()); $data = array( 'id' => $userObject->getUID(), 'display-name' => $userObject->getDisplayName(), 'email' => $userObject->getEMailAddress(), ); - return new OC_OCS_Result($data); + return new Result($data); } } diff --git a/lib/private/ocs/config.php b/lib/private/OCS/Config.php index db04dcbd400..5478411d6fd 100644 --- a/lib/private/ocs/config.php +++ b/lib/private/OCS/Config.php @@ -21,15 +21,17 @@ * */ -class OC_OCS_Config { +namespace OC\OCS; + +class Config { public static function apiConfig() { $xml['version'] = '1.7'; $xml['website'] = 'ownCloud'; - $xml['host'] = OCP\Util::getServerHost(); + $xml['host'] = \OCP\Util::getServerHost(); $xml['contact'] = ''; $xml['ssl'] = 'false'; - return new OC_OCS_Result($xml); + return new Result($xml); } } diff --git a/lib/private/ocs/corecapabilities.php b/lib/private/OCS/CoreCapabilities.php index 388a58791b4..388a58791b4 100644 --- a/lib/private/ocs/corecapabilities.php +++ b/lib/private/OCS/CoreCapabilities.php diff --git a/lib/private/ocs/exception.php b/lib/private/OCS/Exception.php index ca67ac5e841..33c88fcf7d3 100644 --- a/lib/private/ocs/exception.php +++ b/lib/private/OCS/Exception.php @@ -23,7 +23,7 @@ namespace OC\OCS; class Exception extends \Exception { - public function __construct(\OC_OCS_Result $result) { + public function __construct(Result $result) { $this->result = $result; } diff --git a/lib/private/ocs/person.php b/lib/private/OCS/Person.php index 7162fa5e4fb..fd33504e0a8 100644 --- a/lib/private/ocs/person.php +++ b/lib/private/OCS/Person.php @@ -21,20 +21,22 @@ * */ -class OC_OCS_Person { +namespace OC\OCS; + +class Person { public static function check() { $login = isset($_POST['login']) ? $_POST['login'] : false; $password = isset($_POST['password']) ? $_POST['password'] : false; if($login && $password) { - if(OC_User::checkPassword($login, $password)) { + if(\OC_User::checkPassword($login, $password)) { $xml['person']['personid'] = $login; - return new OC_OCS_Result($xml); + return new Result($xml); } else { - return new OC_OCS_Result(null, 102); + return new Result(null, 102); } } else { - return new OC_OCS_Result(null, 101); + return new Result(null, 101); } } diff --git a/lib/private/ocs/privatedata.php b/lib/private/OCS/PrivateData.php index e514c05a3dd..c69d8b9cc17 100644 --- a/lib/private/ocs/privatedata.php +++ b/lib/private/OCS/PrivateData.php @@ -25,8 +25,9 @@ * */ +namespace OC\OCS; -class OC_OCS_Privatedata { +class PrivateData { /** * read keys @@ -36,7 +37,7 @@ class OC_OCS_Privatedata { * @return \OC_OCS_Result */ public static function get($parameters) { - $user = OC_User::getUser(); + $user = \OC_User::getUser(); $app = addslashes(strip_tags($parameters['app'])); $key = isset($parameters['key']) ? addslashes(strip_tags($parameters['key'])) : null; @@ -57,7 +58,7 @@ class OC_OCS_Privatedata { $xml[] = $data; } - return new OC_OCS_Result($xml); + return new Result($xml); } /** @@ -67,7 +68,7 @@ class OC_OCS_Privatedata { * @return \OC_OCS_Result */ public static function set($parameters) { - $user = OC_User::getUser(); + $user = \OC_User::getUser(); $app = addslashes(strip_tags($parameters['app'])); $key = addslashes(strip_tags($parameters['key'])); $value = (string)$_POST['value']; @@ -82,7 +83,7 @@ class OC_OCS_Privatedata { $query->execute(array($user, $app, $key, $value)); } - return new OC_OCS_Result(null, 100); + return new Result(null, 100); } /** @@ -92,10 +93,10 @@ class OC_OCS_Privatedata { * @return \OC_OCS_Result */ public static function delete($parameters) { - $user = OC_User::getUser(); + $user = \OC_User::getUser(); if (!isset($parameters['app']) or !isset($parameters['key'])) { //key and app are NOT optional here - return new OC_OCS_Result(null, 101); + return new Result(null, 101); } $app = addslashes(strip_tags($parameters['app'])); @@ -105,7 +106,7 @@ class OC_OCS_Privatedata { $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*privatedata` WHERE `user` = ? AND `app` = ? AND `key` = ? '); $query->execute(array($user, $app, $key )); - return new OC_OCS_Result(null, 100); + return new Result(null, 100); } } diff --git a/lib/private/OCS/Provider.php b/lib/private/OCS/Provider.php new file mode 100644 index 00000000000..4a7caa79fa5 --- /dev/null +++ b/lib/private/OCS/Provider.php @@ -0,0 +1,96 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @copyright Copyright (c) 2015, 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 OC\OCS; + +class Provider extends \OCP\AppFramework\Controller { + /** @var \OCP\App\IAppManager */ + private $appManager; + + /** + * @param string $appName + * @param \OCP\IRequest $request + * @param \OCP\App\IAppManager $appManager + */ + public function __construct($appName, + \OCP\IRequest $request, + \OCP\App\IAppManager $appManager) { + parent::__construct($appName, $request); + $this->appManager = $appManager; + } + + /** + * @return \OCP\AppFramework\Http\JSONResponse + */ + public function buildProviderList() { + $services = [ + 'PRIVATE_DATA' => [ + 'version' => 1, + 'endpoints' => [ + 'store' => '/ocs/v2.php/privatedata/setattribute', + 'read' => '/ocs/v2.php/privatedata/getattribute', + 'delete' => '/ocs/v2.php/privatedata/deleteattribute', + ], + ], + ]; + + if($this->appManager->isEnabledForUser('files_sharing')) { + $services['SHARING'] = [ + 'version' => 1, + 'endpoints' => [ + 'share' => '/ocs/v2.php/apps/files_sharing/api/v1/shares', + ], + ]; + $services['FEDERATED_SHARING'] = [ + 'version' => 1, + 'endpoints' => [ + 'share' => '/ocs/v2.php/cloud/shares', + 'webdav' => '/public.php/webdav/', + ], + ]; + } + + if($this->appManager->isEnabledForUser('activity')) { + $services['ACTIVITY'] = [ + 'version' => 1, + 'endpoints' => [ + 'list' => '/ocs/v2.php/cloud/activity', + ], + ]; + } + + if($this->appManager->isEnabledForUser('provisioning_api')) { + $services['PROVISIONING'] = [ + 'version' => 1, + 'endpoints' => [ + 'user' => '/ocs/v2.php/cloud/users', + 'groups' => '/ocs/v2.php/cloud/groups', + 'apps' => '/ocs/v2.php/cloud/apps', + ], + ]; + } + + return new \OCP\AppFramework\Http\JSONResponse([ + 'version' => 2, + 'services' => $services, + ]); + } +} diff --git a/lib/private/ocs/result.php b/lib/private/OCS/Result.php index c342bc582fe..c2c61e2383d 100644 --- a/lib/private/ocs/result.php +++ b/lib/private/OCS/Result.php @@ -26,7 +26,9 @@ * */ -class OC_OCS_Result{ +namespace OC\OCS; + +class Result { /** @var array */ protected $data; diff --git a/lib/private/ocsclient.php b/lib/private/OCSClient.php index a783a1f8425..da2f5c61769 100644 --- a/lib/private/ocsclient.php +++ b/lib/private/OCSClient.php @@ -128,7 +128,7 @@ class OCSClient { $response = $client->get( $this->getAppStoreUrl() . '/content/categories', [ - 'timeout' => 5, + 'timeout' => 20, 'query' => [ 'version' => implode('x', $targetVersion), ], @@ -179,7 +179,7 @@ class OCSClient { $response = $client->get( $this->getAppStoreUrl() . '/content/data', [ - 'timeout' => 5, + 'timeout' => 20, 'query' => [ 'version' => implode('x', $targetVersion), 'filter' => $filter, @@ -256,7 +256,7 @@ class OCSClient { $response = $client->get( $this->getAppStoreUrl() . '/content/data/' . urlencode($id), [ - 'timeout' => 5, + 'timeout' => 20, 'query' => [ 'version' => implode('x', $targetVersion), ], @@ -321,7 +321,7 @@ class OCSClient { $response = $client->get( $url, [ - 'timeout' => 5, + 'timeout' => 20, 'query' => [ 'version' => implode('x', $targetVersion), ], diff --git a/lib/private/preview.php b/lib/private/Preview.php index 4fca56dd984..4fca56dd984 100644 --- a/lib/private/preview.php +++ b/lib/private/Preview.php diff --git a/lib/private/previewmanager.php b/lib/private/PreviewManager.php index f3c7a4de0d0..f3c7a4de0d0 100644 --- a/lib/private/previewmanager.php +++ b/lib/private/PreviewManager.php diff --git a/lib/private/RedisFactory.php b/lib/private/RedisFactory.php new file mode 100644 index 00000000000..d286c0167b2 --- /dev/null +++ b/lib/private/RedisFactory.php @@ -0,0 +1,85 @@ +<?php +/** + * @author Robin Appelman <icewind@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 OC; + +class RedisFactory { + /** @var \Redis */ + private $instance; + + /** @var SystemConfig */ + private $config; + + /** + * RedisFactory constructor. + * + * @param SystemConfig $config + */ + public function __construct(SystemConfig $config) { + $this->config = $config; + } + + private function create() { + $this->instance = new \Redis(); + // TODO allow configuring a RedisArray, see https://github.com/nicolasff/phpredis/blob/master/arrays.markdown#redis-arrays + $config = $this->config->getValue('redis', array()); + if (isset($config['host'])) { + $host = $config['host']; + } else { + $host = '127.0.0.1'; + } + if (isset($config['port'])) { + $port = $config['port']; + } else { + $port = 6379; + } + if (isset($config['timeout'])) { + $timeout = $config['timeout']; + } else { + $timeout = 0.0; // unlimited + } + + $this->instance->connect($host, $port, $timeout); + if (isset($config['password']) && $config['password'] !== '') { + $this->instance->auth($config['password']); + } + + if (isset($config['dbindex'])) { + $this->instance->select($config['dbindex']); + } + } + + public function getInstance() { + if (!$this->isAvailable()) { + throw new \Exception('Redis support is not available'); + } + if (!$this->instance instanceof \Redis) { + $this->create(); + } + + return $this->instance; + } + + public function isAvailable() { + return extension_loaded('redis') + && version_compare(phpversion('redis'), '2.2.5', '>='); + } +} diff --git a/lib/private/repair.php b/lib/private/Repair.php index 586e4e42b13..38752ee1703 100644 --- a/lib/private/repair.php +++ b/lib/private/Repair.php @@ -28,8 +28,6 @@ namespace OC; -use OC\Hooks\BasicEmitter; -use OC\Hooks\Emitter; use OC\Repair\AssetCache; use OC\Repair\CleanTags; use OC\Repair\Collation; @@ -46,16 +44,19 @@ use OC\Repair\RepairMimeTypes; use OC\Repair\SearchLuceneTables; use OC\Repair\UpdateOutdatedOcsIds; use OC\Repair\RepairInvalidShares; +use OCP\AppFramework\QueryException; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\GenericEvent; -class Repair extends BasicEmitter implements IOutput{ +class Repair implements IOutput{ /* @var IRepairStep[] */ private $repairSteps; /** @var EventDispatcher */ private $dispatcher; + /** @var string */ + private $currentStep; /** * Creates a new repair step runner @@ -72,24 +73,14 @@ class Repair extends BasicEmitter 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; } // run each repair step foreach ($this->repairSteps as $step) { - $this->emit('\OC\Repair', 'step', array($step->getName())); - - 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)); - }); - } - + $this->currentStep = $step->getName(); + $this->emit('\OC\Repair', 'step', [$this->currentStep]); $step->run($this); } } @@ -102,15 +93,20 @@ class Repair extends BasicEmitter implements IOutput{ */ public function addStep($repairStep) { if (is_string($repairStep)) { - if (class_exists($repairStep)) { - $s = new $repairStep(); - if ($s instanceof IRepairStep) { - $this->repairSteps[] = $s; + try { + $s = \OC::$server->query($repairStep); + } catch (QueryException $e) { + if (class_exists($repairStep)) { + $s = new $repairStep(); } else { - throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep"); + throw new \Exception("Repair step '$repairStep' is unknown"); } + } + + if ($s instanceof IRepairStep) { + $this->repairSteps[] = $s; } else { - throw new \Exception("Repair step '$repairStep' is unknown"); + throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep"); } } else { $this->repairSteps[] = $repairStep; @@ -178,10 +174,11 @@ class Repair extends BasicEmitter implements IOutput{ } /** - * {@inheritDoc} + * @param string $scope + * @param string $method + * @param array $arguments */ public function emit($scope, $method, array $arguments = []) { - parent::emit($scope, $method, $arguments); if (!is_null($this->dispatcher)) { $this->dispatcher->dispatch("$scope::$method", new GenericEvent("$scope::$method", $arguments)); @@ -206,15 +203,16 @@ class Repair extends BasicEmitter implements IOutput{ */ public function startProgress($max = 0) { // for now just emit as we did in the past - $this->emit('\OC\Repair', 'startProgress', [$max]); + $this->emit('\OC\Repair', 'startProgress', [$max, $this->currentStep]); } /** * @param int $step + * @param string $description */ - public function advance($step = 1) { + public function advance($step = 1, $description = '') { // for now just emit as we did in the past - $this->emit('\OC\Repair', 'advance', [$step]); + $this->emit('\OC\Repair', 'advance', [$step, $description]); } /** diff --git a/lib/private/Repair/DropOldTables.php b/lib/private/Repair/DropOldTables.php index 15d5b9a3577..b9963b50775 100644 --- a/lib/private/Repair/DropOldTables.php +++ b/lib/private/Repair/DropOldTables.php @@ -55,12 +55,15 @@ class DropOldTables implements IRepairStep { * @throws \Exception in case of failure */ public function run(IOutput $output) { + $tables = $this->oldDatabaseTables(); + $output->startProgress(count($tables)); foreach ($this->oldDatabaseTables() as $tableName) { if ($this->connection->tableExists($tableName)){ - $output->info(sprintf('Table %s has been deleted', $tableName)); $this->connection->dropTable($tableName); } + $output->advance(1, "Drop old database table: $tableName"); } + $output->finishProgress(); } /** diff --git a/lib/private/repairexception.php b/lib/private/RepairException.php index e244f2bb820..e244f2bb820 100644 --- a/lib/private/repairexception.php +++ b/lib/private/RepairException.php diff --git a/lib/private/Route/CachingRouter.php b/lib/private/Route/CachingRouter.php index d6270dcf2c7..063d389e98b 100644 --- a/lib/private/Route/CachingRouter.php +++ b/lib/private/Route/CachingRouter.php @@ -50,8 +50,9 @@ class CachingRouter extends Router { public function generate($name, $parameters = array(), $absolute = false) { asort($parameters); $key = $this->context->getHost() . '#' . $this->context->getBaseUrl() . $name . sha1(json_encode($parameters)) . intval($absolute); - if ($this->cache->hasKey($key)) { - return $this->cache->get($key); + $cachedKey = $this->cache->get($key); + if ($cachedKey) { + return $cachedKey; } else { $url = parent::generate($name, $parameters, $absolute); $this->cache->set($key, $url, 3600); diff --git a/lib/private/search.php b/lib/private/Search.php index 7d1e2734195..7d1e2734195 100644 --- a/lib/private/search.php +++ b/lib/private/Search.php diff --git a/lib/private/Server.php b/lib/private/Server.php index d37edc4f45f..0b7b8f9e403 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -5,6 +5,7 @@ * @author Bernhard Posselt <dev@bernhard-posselt.com> * @author Bernhard Reiter <ockham@raz.or.at> * @author Björn Schießle <schiessle@owncloud.com> + * @author Christoph Wurst <christoph@owncloud.com> * @author Christopher Schäpers <kondou@ts.unde.re> * @author Joas Schilling <nickvergessen@owncloud.com> * @author Jörn Friedrich Dreyer <jfd@butonic.de> @@ -47,6 +48,9 @@ use OC\Diagnostics\NullQueryLogger; use OC\Diagnostics\QueryLogger; use OC\Files\Config\UserMountCache; use OC\Files\Config\UserMountCacheListener; +use OC\Files\Mount\CacheMountProvider; +use OC\Files\Mount\LocalHomeMountProvider; +use OC\Files\Mount\ObjectHomeMountProvider; use OC\Files\Node\HookConnector; use OC\Files\Node\LazyRoot; use OC\Files\Node\Root; @@ -207,12 +211,31 @@ class Server extends ServerContainer implements IServerContainer { }); return $groupManager; }); + $this->registerService('OC\Authentication\Token\DefaultTokenMapper', function (Server $c) { + $dbConnection = $c->getDatabaseConnection(); + return new Authentication\Token\DefaultTokenMapper($dbConnection); + }); + $this->registerService('OC\Authentication\Token\DefaultTokenProvider', function (Server $c) { + $mapper = $c->query('OC\Authentication\Token\DefaultTokenMapper'); + $crypto = $c->getCrypto(); + $config = $c->getConfig(); + $logger = $c->getLogger(); + $timeFactory = new TimeFactory(); + return new \OC\Authentication\Token\DefaultTokenProvider($mapper, $crypto, $config, $logger, $timeFactory); + }); $this->registerService('UserSession', function (Server $c) { $manager = $c->getUserManager(); - $session = new \OC\Session\Memory(''); - - $userSession = new \OC\User\Session($manager, $session); + $timeFactory = new TimeFactory(); + // Token providers might require a working database. This code + // might however be called when ownCloud is not yet setup. + if (\OC::$server->getSystemConfig()->getValue('installed', false)) { + $defaultTokenProvider = $c->query('OC\Authentication\Token\DefaultTokenProvider'); + } else { + $defaultTokenProvider = null; + } + + $userSession = new \OC\User\Session($manager, $session, $timeFactory, $defaultTokenProvider); $userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) { \OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password)); }); @@ -311,8 +334,12 @@ class Server extends ServerContainer implements IServerContainer { '\\OC\\Memcache\\ArrayCache' ); }); + $this->registerService('RedisFactory', function (Server $c) { + $systemConfig = $c->getSystemConfig(); + return new RedisFactory($systemConfig); + }); $this->registerService('ActivityManager', function (Server $c) { - return new ActivityManager( + return new \OC\Activity\Manager( $c->getRequest(), $c->getUserSession(), $c->getConfig() @@ -328,14 +355,18 @@ 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); }); $this->registerService('JobList', function (Server $c) { $config = $c->getConfig(); - return new \OC\BackgroundJob\JobList($c->getDatabaseConnection(), $config); + return new \OC\BackgroundJob\JobList( + $c->getDatabaseConnection(), + $config, + new TimeFactory() + ); }); $this->registerService('Router', function (Server $c) { $cacheFactory = $c->getMemCacheFactory(); @@ -444,7 +475,16 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('MountConfigManager', function (Server $c) { $loader = \OC\Files\Filesystem::getLoader(); $mountCache = $c->query('UserMountCache'); - return new \OC\Files\Config\MountProviderCollection($loader, $mountCache); + $manager = new \OC\Files\Config\MountProviderCollection($loader, $mountCache); + + // builtin providers + + $config = $c->getConfig(); + $manager->registerProvider(new CacheMountProvider($config)); + $manager->registerHomeProvider(new LocalHomeMountProvider()); + $manager->registerHomeProvider(new ObjectHomeMountProvider($config)); + + return $manager; }); $this->registerService('IniWrapper', function ($c) { return new IniGetWrapper(); @@ -615,7 +655,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( @@ -829,8 +869,7 @@ class Server extends ServerContainer implements IServerContainer { } /** - * For internal use only - * + * @internal For internal use only * @return \OC\SystemConfig */ public function getSystemConfig() { @@ -899,6 +938,16 @@ class Server extends ServerContainer implements IServerContainer { } /** + * Returns an \OC\RedisFactory instance + * + * @return \OC\RedisFactory + */ + public function getGetRedisFactory() { + return $this->query('RedisFactory'); + } + + + /** * Returns the current session * * @return \OCP\IDBConnection @@ -1172,7 +1221,7 @@ class Server extends ServerContainer implements IServerContainer { return $this->query('MountManager'); } - /* + /** * Get the MimeTypeDetector * * @return \OCP\Files\IMimeTypeDetector diff --git a/lib/private/servercontainer.php b/lib/private/ServerContainer.php index d297c9fd39c..d297c9fd39c 100644 --- a/lib/private/servercontainer.php +++ b/lib/private/ServerContainer.php diff --git a/lib/private/servernotavailableexception.php b/lib/private/ServerNotAvailableException.php index f4b5f4f8cf3..f4b5f4f8cf3 100644 --- a/lib/private/servernotavailableexception.php +++ b/lib/private/ServerNotAvailableException.php diff --git a/lib/private/serviceunavailableexception.php b/lib/private/ServiceUnavailableException.php index fb4920b3607..fb4920b3607 100644 --- a/lib/private/serviceunavailableexception.php +++ b/lib/private/ServiceUnavailableException.php 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..d60c4663fb0 100644 --- a/lib/private/setup.php +++ b/lib/private/Setup.php @@ -364,10 +364,17 @@ class Setup { $group =\OC::$server->getGroupManager()->createGroup('admin'); $group->addUser($user); - \OC_User::login($username, $password); + + // Create a session token for the newly created user + // The token provider requires a working db, so it's not injected on setup + /* @var $userSession User\Session */ + $userSession = \OC::$server->getUserSession(); + $defaultTokenProvider = \OC::$server->query('OC\Authentication\Token\DefaultTokenProvider'); + $userSession->setTokenProvider($defaultTokenProvider); + $userSession->createSessionToken($request, $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 @@ -382,6 +389,8 @@ class Setup { $config->setSystemValue('logtimezone', date_default_timezone_get()); } + self::installBackgroundJobs(); + //and we are done $config->setSystemValue('installed', true); } @@ -389,6 +398,10 @@ class Setup { return $error; } + public static function installBackgroundJobs() { + \OC::$server->getJobList()->add('\OC\Authentication\Token\DefaultTokenCleanupJob'); + } + /** * @return string Absolute path to htaccess */ @@ -420,37 +433,47 @@ class Setup { $htaccessContent = file_get_contents($setupHelper->pathToHtaccess()); $content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n"; - if(strpos($htaccessContent, $content) === false) { - //custom 403 error page - $content.= "\nErrorDocument 403 ".$webRoot."/core/templates/403.php"; + $htaccessContent = explode($content, $htaccessContent, 2)[0]; - //custom 404 error page - $content.= "\nErrorDocument 404 ".$webRoot."/core/templates/404.php"; + //custom 403 error page + $content.= "\nErrorDocument 403 ".$webRoot."/core/templates/403.php"; - // ownCloud may be configured to live at the root folder without a - // trailing slash being specified. In this case manually set the - // rewrite base to `/` - $rewriteBase = $webRoot; - if($webRoot === '') { - $rewriteBase = '/'; - } + //custom 404 error page + $content.= "\nErrorDocument 404 ".$webRoot."/core/templates/404.php"; - // Add rewrite base + // Add rewrite rules if the RewriteBase is configured + $rewriteBase = $config->getSystemValue('htaccess.RewriteBase', ''); + if($rewriteBase !== '') { $content .= "\n<IfModule mod_rewrite.c>"; + $content .= "\n Options -MultiViews"; + $content .= "\n RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]"; + $content .= "\n RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/remote.php"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/public.php"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/cron.php"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/status.php"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/updater/"; + $content .= "\n RewriteCond %{REQUEST_FILENAME} !/ocs-provider/"; + $content .= "\n RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*"; $content .= "\n RewriteRule . index.php [PT,E=PATH_INFO:$1]"; - $content .= "\n RewriteBase ".$rewriteBase; + $content .= "\n RewriteBase " . $rewriteBase; $content .= "\n <IfModule mod_env.c>"; $content .= "\n SetEnv front_controller_active true"; $content .= "\n <IfModule mod_dir.c>"; $content .= "\n DirectorySlash off"; $content .= "\n </IfModule>"; - $content.="\n </IfModule>"; - $content.="\n</IfModule>"; + $content .= "\n </IfModule>"; + $content .= "\n</IfModule>"; + } - if ($content !== '') { - //suppress errors in case we don't have permissions for it - @file_put_contents($setupHelper->pathToHtaccess(), $content . "\n", FILE_APPEND); - } + if ($content !== '') { + //suppress errors in case we don't have permissions for it + @file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent.$content . "\n"); } } diff --git a/lib/private/share/constants.php b/lib/private/Share/Constants.php index e60eb98832b..e60eb98832b 100644 --- a/lib/private/share/constants.php +++ b/lib/private/Share/Constants.php diff --git a/lib/private/share/helper.php b/lib/private/Share/Helper.php index f9581e48e62..f9581e48e62 100644 --- a/lib/private/share/helper.php +++ b/lib/private/Share/Helper.php diff --git a/lib/private/share/mailnotifications.php b/lib/private/Share/MailNotifications.php index f71651e71fc..afecff0b97b 100644 --- a/lib/private/share/mailnotifications.php +++ b/lib/private/Share/MailNotifications.php @@ -119,27 +119,9 @@ class MailNotifications { } } - // Link to folder, or root folder if a file - - if ($itemType === 'folder') { - $args = array( - 'dir' => $filename, - ); - } else if (strpos($filename, '/')) { - $args = array( - 'dir' => '/' . dirname($filename), - 'scrollto' => basename($filename), - ); - } else { - $args = array( - 'dir' => '/', - 'scrollto' => $filename, - ); - } - $link = $this->urlGenerator->linkToRouteAbsolute( - 'files.view.index', - $args + 'files.viewcontroller.showFile', + ['fileId' => $items[0]['item_source']] ); list($htmlBody, $textBody) = $this->createMailBody($filename, $link, $expiration, 'internal'); diff --git a/lib/private/share/searchresultsorter.php b/lib/private/Share/SearchResultSorter.php index 6d5542146e7..6d5542146e7 100644 --- a/lib/private/share/searchresultsorter.php +++ b/lib/private/Share/SearchResultSorter.php diff --git a/lib/private/share/share.php b/lib/private/Share/Share.php index 5b61f418a4d..5b61f418a4d 100644 --- a/lib/private/share/share.php +++ b/lib/private/Share/Share.php diff --git a/lib/private/streamer.php b/lib/private/Streamer.php index 23c191b68da..23c191b68da 100644 --- a/lib/private/streamer.php +++ b/lib/private/Streamer.php diff --git a/lib/private/subadmin.php b/lib/private/SubAdmin.php index 34dd40c22ff..34dd40c22ff 100644 --- a/lib/private/subadmin.php +++ b/lib/private/SubAdmin.php diff --git a/lib/private/systemconfig.php b/lib/private/SystemConfig.php index 449a2dc50b2..449a2dc50b2 100644 --- a/lib/private/systemconfig.php +++ b/lib/private/SystemConfig.php diff --git a/lib/private/SystemTag/ManagerFactory.php b/lib/private/SystemTag/ManagerFactory.php index d9acf327f8a..6b238e3c428 100644 --- a/lib/private/SystemTag/ManagerFactory.php +++ b/lib/private/SystemTag/ManagerFactory.php @@ -59,6 +59,7 @@ class ManagerFactory implements ISystemTagManagerFactory { public function getManager() { return new SystemTagManager( $this->serverContainer->getDatabaseConnection(), + $this->serverContainer->getGroupManager(), $this->serverContainer->getEventDispatcher() ); } diff --git a/lib/private/SystemTag/SystemTagManager.php b/lib/private/SystemTag/SystemTagManager.php index 76a60a91328..2b0ef03e471 100644 --- a/lib/private/SystemTag/SystemTagManager.php +++ b/lib/private/SystemTag/SystemTagManager.php @@ -30,10 +30,18 @@ use OCP\SystemTag\ManagerEvent; use OCP\SystemTag\TagAlreadyExistsException; use OCP\SystemTag\TagNotFoundException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use OCP\IUserManager; +use OCP\IGroupManager; +use OCP\SystemTag\ISystemTag; +use OCP\IUser; +/** + * Manager class for system tags + */ class SystemTagManager implements ISystemTagManager { const TAG_TABLE = 'systemtag'; + const TAG_GROUP_TABLE = 'systemtag_group'; /** @var IDBConnection */ protected $connection; @@ -41,6 +49,9 @@ class SystemTagManager implements ISystemTagManager { /** @var EventDispatcherInterface */ protected $dispatcher; + /** @var IGroupManager */ + protected $groupManager; + /** * Prepared query for selecting tags directly * @@ -54,8 +65,13 @@ class SystemTagManager implements ISystemTagManager { * @param IDBConnection $connection database connection * @param EventDispatcherInterface $dispatcher */ - public function __construct(IDBConnection $connection, EventDispatcherInterface $dispatcher) { + public function __construct( + IDBConnection $connection, + IGroupManager $groupManager, + EventDispatcherInterface $dispatcher + ) { $this->connection = $connection; + $this->groupManager = $groupManager; $this->dispatcher = $dispatcher; $query = $this->connection->getQueryBuilder(); @@ -316,7 +332,102 @@ class SystemTagManager implements ISystemTagManager { } } + /** + * {@inheritdoc} + */ + public function canUserAssignTag(ISystemTag $tag, IUser $user) { + // early check to avoid unneeded group lookups + if ($tag->isUserAssignable() && $tag->isUserVisible()) { + return true; + } + + if ($this->groupManager->isAdmin($user->getUID())) { + return true; + } + + if (!$tag->isUserVisible()) { + return false; + } + + $groupIds = $this->groupManager->getUserGroupIds($user); + if (!empty($groupIds)) { + $matchingGroups = array_intersect($groupIds, $this->getTagGroups($tag)); + if (!empty($matchingGroups)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function canUserSeeTag(ISystemTag $tag, IUser $user) { + if ($tag->isUserVisible()) { + return true; + } + + if ($this->groupManager->isAdmin($user->getUID())) { + return true; + } + + return false; + } + private function createSystemTagFromRow($row) { return new SystemTag((int)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']); } + + /** + * {@inheritdoc} + */ + public function setTagGroups(ISystemTag $tag, $groupIds) { + // delete relationships first + $this->connection->beginTransaction(); + try { + $query = $this->connection->getQueryBuilder(); + $query->delete(self::TAG_GROUP_TABLE) + ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId()))) + ->execute(); + + // add each group id + $query = $this->connection->getQueryBuilder(); + $query->insert(self::TAG_GROUP_TABLE) + ->values([ + 'systemtagid' => $query->createNamedParameter($tag->getId()), + 'gid' => $query->createParameter('gid'), + ]); + foreach ($groupIds as $groupId) { + $query->setParameter('gid', $groupId); + $query->execute(); + } + + $this->connection->commit(); + } catch (\Exception $e) { + $this->connection->rollback(); + throw $e; + } + } + + /** + * {@inheritdoc} + */ + public function getTagGroups(ISystemTag $tag) { + $groupIds = []; + $query = $this->connection->getQueryBuilder(); + $query->select('gid') + ->from(self::TAG_GROUP_TABLE) + ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId()))) + ->orderBy('gid'); + + $result = $query->execute(); + while ($row = $result->fetch()) { + $groupIds[] = $row['gid']; + } + + $result->closeCursor(); + + return $groupIds; + } } diff --git a/lib/private/tagmanager.php b/lib/private/TagManager.php index a9e1cdfe076..a9e1cdfe076 100644 --- a/lib/private/tagmanager.php +++ b/lib/private/TagManager.php diff --git a/lib/private/tags.php b/lib/private/Tags.php index cf39a9a9759..cf39a9a9759 100644 --- a/lib/private/tags.php +++ b/lib/private/Tags.php diff --git a/lib/private/tempmanager.php b/lib/private/TempManager.php index dd97a36cd7f..dd97a36cd7f 100644 --- a/lib/private/tempmanager.php +++ b/lib/private/TempManager.php diff --git a/lib/private/template/base.php b/lib/private/Template/Base.php index cfe629b5fbf..cfe629b5fbf 100644 --- a/lib/private/template/base.php +++ b/lib/private/Template/Base.php diff --git a/lib/private/template/cssresourcelocator.php b/lib/private/Template/CSSResourceLocator.php index 6a547931ee3..6a547931ee3 100644 --- a/lib/private/template/cssresourcelocator.php +++ b/lib/private/Template/CSSResourceLocator.php diff --git a/lib/private/template/jsresourcelocator.php b/lib/private/Template/JSResourceLocator.php index 6ea7b6291c0..6ea7b6291c0 100644 --- a/lib/private/template/jsresourcelocator.php +++ b/lib/private/Template/JSResourceLocator.php diff --git a/lib/private/template/resourcelocator.php b/lib/private/Template/ResourceLocator.php index e64fce81afc..e64fce81afc 100644 --- a/lib/private/template/resourcelocator.php +++ b/lib/private/Template/ResourceLocator.php diff --git a/lib/private/template/resourcenotfoundexception.php b/lib/private/Template/ResourceNotFoundException.php index 8c7f1f14175..8c7f1f14175 100644 --- a/lib/private/template/resourcenotfoundexception.php +++ b/lib/private/Template/ResourceNotFoundException.php diff --git a/lib/private/template/templatefilelocator.php b/lib/private/Template/TemplateFileLocator.php index f8553156914..f8553156914 100644 --- a/lib/private/template/templatefilelocator.php +++ b/lib/private/Template/TemplateFileLocator.php diff --git a/lib/private/templatelayout.php b/lib/private/TemplateLayout.php index 88077b418a7..88077b418a7 100644 --- a/lib/private/templatelayout.php +++ b/lib/private/TemplateLayout.php diff --git a/lib/private/urlgenerator.php b/lib/private/URLGenerator.php index 327c0c32dfe..327c0c32dfe 100644 --- a/lib/private/urlgenerator.php +++ b/lib/private/URLGenerator.php diff --git a/lib/private/updater.php b/lib/private/Updater.php index 66f410b779f..dbcaccaad26 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; @@ -132,6 +131,8 @@ class Updater extends BasicEmitter { * @return bool true if the operation succeeded, false otherwise */ public function upgrade() { + $this->emitRepairEvents(); + $logLevel = $this->config->getSystemValue('loglevel', \OCP\Util::WARN); $this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]); $this->config->setSystemValue('loglevel', \OCP\Util::DEBUG); @@ -196,26 +197,6 @@ class Updater extends BasicEmitter { } /** - * Forward messages emitted by the repair routine - * - * @param Repair $repair repair routine - */ - private function emitRepairMessages(Repair $repair) { - $repair->listen('\OC\Repair', 'warning', function ($description) { - $this->emit('\OC\Updater', 'repairWarning', array($description)); - }); - $repair->listen('\OC\Repair', 'error', function ($description) { - $this->emit('\OC\Updater', 'repairError', array($description)); - }); - $repair->listen('\OC\Repair', 'info', function ($description) { - $this->emit('\OC\Updater', 'repairInfo', array($description)); - }); - $repair->listen('\OC\Repair', 'step', function ($description) { - $this->emit('\OC\Updater', 'repairStep', array($description)); - }); - } - - /** * runs the update actions in maintenance mode, does not upgrade the source files * except the main .htaccess file * @@ -235,6 +216,8 @@ class Updater extends BasicEmitter { try { Setup::updateHtaccess(); Setup::protectDataDirectory(); + // TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378 + Setup::installBackgroundJobs(); } catch (\Exception $e) { throw new \Exception($e->getMessage()); } @@ -245,8 +228,7 @@ class Updater extends BasicEmitter { file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', ''); // pre-upgrade repairs - $repair = new Repair(Repair::getBeforeUpgradeRepairSteps()); - $this->emitRepairMessages($repair); + $repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher()); $repair->run(); // simulate DB upgrade @@ -270,7 +252,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]); @@ -278,8 +260,7 @@ class Updater extends BasicEmitter { } // post-upgrade repairs - $repair = new Repair(Repair::getRepairSteps()); - $this->emitRepairMessages($repair); + $repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher()); $repair->run(); //Invalidate update feed @@ -362,7 +343,6 @@ class Updater extends BasicEmitter { * @throws NeedsUpdateException */ protected function doAppUpgrade() { - $this->emitRepairEvents(); $apps = \OC_App::getEnabledApps(); $priorityTypes = array('authentication', 'filesystem', 'logging'); $pseudoOtherType = 'other'; @@ -464,11 +444,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/Updater/VersionCheck.php b/lib/private/Updater/VersionCheck.php index e42a1e2a40c..7b330b53686 100644 --- a/lib/private/Updater/VersionCheck.php +++ b/lib/private/Updater/VersionCheck.php @@ -61,19 +61,15 @@ class VersionCheck { /** * Check if a new version is available * - * @param string $updaterUrl the url to check, i.e. 'http://apps.owncloud.com/updater.php' * @return array|bool */ - public function check($updaterUrl = null) { - + public function check() { // Look up the cache - it is invalidated all 30 minutes if (((int)$this->config->getAppValue('core', 'lastupdatedat') + 1800) > time()) { return json_decode($this->config->getAppValue('core', 'lastupdateResult'), true); } - if (is_null($updaterUrl)) { - $updaterUrl = 'https://updates.owncloud.com/server/'; - } + $updaterUrl = $this->config->getSystemValue('updater.server.url', 'https://updates.owncloud.com/server/'); $this->config->setAppValue('core', 'lastupdatedat', time()); diff --git a/lib/private/user/backend.php b/lib/private/User/Backend.php index 2bb1df4d6b3..d5f82dc9621 100644 --- a/lib/private/user/backend.php +++ b/lib/private/User/Backend.php @@ -32,37 +32,13 @@ * */ -/** - * error code for functions not provided by the user backend - * @deprecated Use \OC_User_Backend::NOT_IMPLEMENTED instead - */ -define('OC_USER_BACKEND_NOT_IMPLEMENTED', -501); - -/** - * actions that user backends can define - */ -/** @deprecated Use \OC_User_Backend::CREATE_USER instead */ -define('OC_USER_BACKEND_CREATE_USER', 1 << 0); -/** @deprecated Use \OC_User_Backend::SET_PASSWORD instead */ -define('OC_USER_BACKEND_SET_PASSWORD', 1 << 4); -/** @deprecated Use \OC_User_Backend::CHECK_PASSWORD instead */ -define('OC_USER_BACKEND_CHECK_PASSWORD', 1 << 8); -/** @deprecated Use \OC_User_Backend::GET_HOME instead */ -define('OC_USER_BACKEND_GET_HOME', 1 << 12); -/** @deprecated Use \OC_User_Backend::GET_DISPLAYNAME instead */ -define('OC_USER_BACKEND_GET_DISPLAYNAME', 1 << 16); -/** @deprecated Use \OC_User_Backend::SET_DISPLAYNAME instead */ -define('OC_USER_BACKEND_SET_DISPLAYNAME', 1 << 20); -/** @deprecated Use \OC_User_Backend::PROVIDE_AVATAR instead */ -define('OC_USER_BACKEND_PROVIDE_AVATAR', 1 << 24); -/** @deprecated Use \OC_User_Backend::COUNT_USERS instead */ -define('OC_USER_BACKEND_COUNT_USERS', 1 << 28); +namespace OC\User; /** * Abstract base class for user management. Provides methods for querying backend * capabilities. */ -abstract class OC_User_Backend implements \OCP\UserInterface { +abstract class Backend implements \OCP\UserInterface { /** * error code for functions not provided by the user backend */ diff --git a/lib/private/user/database.php b/lib/private/User/Database.php index 22a05090b96..7a4b58e6f40 100644 --- a/lib/private/user/database.php +++ b/lib/private/User/Database.php @@ -48,11 +48,23 @@ * */ +namespace OC\User; + +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(); +class Database extends \OC\User\Backend implements \OCP\IUserBackend { + /** @var CappedMemoryCache */ + private $cache; + + /** + * OC_User_Database constructor. + */ + public function __construct() { + $this->cache = new CappedMemoryCache(); + } /** * Create a new user @@ -65,7 +77,7 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { */ public function createUser($uid, $password) { if (!$this->userExists($uid)) { - $query = OC_DB::prepare('INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )'); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )'); $result = $query->execute(array($uid, \OC::$server->getHasher()->hash($password))); return $result ? true : false; @@ -83,7 +95,7 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { */ public function deleteUser($uid) { // Delete user-group-relation - $query = OC_DB::prepare('DELETE FROM `*PREFIX*users` WHERE `uid` = ?'); + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*users` WHERE `uid` = ?'); $result = $query->execute(array($uid)); if (isset($this->cache[$uid])) { @@ -103,7 +115,7 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { */ public function setPassword($uid, $password) { if ($this->userExists($uid)) { - $query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `password` = ? WHERE `uid` = ?'); + $query = \OC_DB::prepare('UPDATE `*PREFIX*users` SET `password` = ? WHERE `uid` = ?'); $result = $query->execute(array(\OC::$server->getHasher()->hash($password), $uid)); return $result ? true : false; @@ -122,7 +134,7 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { */ public function setDisplayName($uid, $displayName) { if ($this->userExists($uid)) { - $query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `displayname` = ? WHERE LOWER(`uid`) = LOWER(?)'); + $query = \OC_DB::prepare('UPDATE `*PREFIX*users` SET `displayname` = ? WHERE LOWER(`uid`) = LOWER(?)'); $query->execute(array($displayName, $uid)); $this->cache[$uid]['displayname'] = $displayName; @@ -161,7 +173,7 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { } $displayNames = array(); - $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`' + $query = \OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`' . $searchLike .' ORDER BY `uid` ASC', $limit, $offset); $result = $query->execute($parameters); while ($row = $result->fetchRow()) { @@ -181,7 +193,7 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { * returns the user id or false */ public function checkPassword($uid, $password) { - $query = OC_DB::prepare('SELECT `uid`, `password` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)'); + $query = \OC_DB::prepare('SELECT `uid`, `password` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)'); $result = $query->execute(array($uid)); $row = $result->fetchRow(); @@ -207,11 +219,11 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { */ private function loadUser($uid) { if (empty($this->cache[$uid])) { - $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)'); + $query = \OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)'); $result = $query->execute(array($uid)); if ($result === false) { - \OCP\Util::writeLog('core', OC_DB::getErrorMessage(), \OCP\Util::ERROR); + \OCP\Util::writeLog('core', \OC_DB::getErrorMessage(), \OCP\Util::ERROR); return false; } @@ -240,7 +252,7 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { $searchLike = ' WHERE LOWER(`uid`) LIKE LOWER(?)'; } - $query = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users`' . $searchLike . ' ORDER BY `uid` ASC', $limit, $offset); + $query = \OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users`' . $searchLike . ' ORDER BY `uid` ASC', $limit, $offset); $result = $query->execute($parameters); $users = array(); while ($row = $result->fetchRow()) { @@ -266,7 +278,7 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { */ public function getHome($uid) { if ($this->userExists($uid)) { - return \OC::$server->getConfig()->getSystemValue("datadirectory", OC::$SERVERROOT . "/data") . '/' . $uid; + return \OC::$server->getConfig()->getSystemValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $uid; } return false; @@ -285,10 +297,10 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { * @return int|bool */ public function countUsers() { - $query = OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users`'); + $query = \OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users`'); $result = $query->execute(); if ($result === false) { - \OCP\Util::writeLog('core', OC_DB::getErrorMessage(), \OCP\Util::ERROR); + \OCP\Util::writeLog('core', \OC_DB::getErrorMessage(), \OCP\Util::ERROR); return false; } return $result->fetchOne(); @@ -323,8 +335,8 @@ class OC_User_Database extends OC_User_Backend implements \OCP\IUserBackend { $backends = \OC::$server->getUserManager()->getBackends(); foreach ($backends as $backend) { - if ($backend instanceof \OC_User_Database) { - /** @var \OC_User_Database $backend */ + if ($backend instanceof \OC\User\Database) { + /** @var \OC\User\Database $backend */ $uid = $backend->loginName2UserName($param['uid']); if ($uid !== false) { $param['uid'] = $uid; diff --git a/lib/private/user/loginexception.php b/lib/private/User/LoginException.php index 84426f7f5da..84426f7f5da 100644 --- a/lib/private/user/loginexception.php +++ b/lib/private/User/LoginException.php diff --git a/lib/private/user/manager.php b/lib/private/User/Manager.php index 7967f877024..a9d9425e24d 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; } /** @@ -180,7 +186,7 @@ class Manager extends PublicEmitter implements IUserManager { $password = str_replace("\0", '', $password); foreach ($this->backends as $backend) { - if ($backend->implementsActions(\OC_User_Backend::CHECK_PASSWORD)) { + if ($backend->implementsActions(\OC\User\Backend::CHECK_PASSWORD)) { $uid = $backend->checkPassword($loginName, $password); if ($uid !== false) { return $this->getUserObject($uid, $backend); @@ -284,7 +290,7 @@ class Manager extends PublicEmitter implements IUserManager { $this->emit('\OC\User', 'preCreateUser', array($uid, $password)); foreach ($this->backends as $backend) { - if ($backend->implementsActions(\OC_User_Backend::CREATE_USER)) { + if ($backend->implementsActions(\OC\User\Backend::CREATE_USER)) { $backend->createUser($uid, $password); $user = $this->getUserObject($uid, $backend); $this->emit('\OC\User', 'postCreateUser', array($user, $password)); @@ -302,7 +308,7 @@ class Manager extends PublicEmitter implements IUserManager { public function countUsers() { $userCountStatistics = array(); foreach ($this->backends as $backend) { - if ($backend->implementsActions(\OC_User_Backend::COUNT_USERS)) { + if ($backend->implementsActions(\OC\User\Backend::COUNT_USERS)) { $backendUsers = $backend->countUsers(); if($backendUsers !== false) { if($backend instanceof IUserBackend) { @@ -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/private/user/nouserexception.php b/lib/private/User/NoUserException.php index afd5c729fcf..afd5c729fcf 100644 --- a/lib/private/user/nouserexception.php +++ b/lib/private/User/NoUserException.php diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php new file mode 100644 index 00000000000..7104f46fea2 --- /dev/null +++ b/lib/private/User/Session.php @@ -0,0 +1,545 @@ +<?php + +/** + * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Bernhard Posselt <dev@bernhard-posselt.com> + * @author Christoph Wurst <christoph@owncloud.com> + * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Jörn Friedrich Dreyer <jfd@butonic.de> + * @author Lukas Reschke <lukas@owncloud.com> + * @author Morris Jobke <hey@morrisjobke.de> + * @author Robin Appelman <icewind@owncloud.com> + * @author Robin McCorkell <robin@mccorkell.me.uk> + * @author Roeland Jago Douma <rullzer@owncloud.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Vincent Petry <pvince81@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 OC\User; + +use OC; +use OC\Authentication\Exceptions\InvalidTokenException; +use OC\Authentication\Token\IProvider; +use OC\Authentication\Token\IToken; +use OC\Hooks\Emitter; +use OC_User; +use OC_Util; +use OCA\DAV\Connector\Sabre\Auth; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IRequest; +use OCP\ISession; +use OCP\IUser; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\Session\Exceptions\SessionNotAvailableException; + +/** + * Class Session + * + * Hooks available in scope \OC\User: + * - preSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - postSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - preDelete(\OC\User\User $user) + * - postDelete(\OC\User\User $user) + * - preCreateUser(string $uid, string $password) + * - postCreateUser(\OC\User\User $user) + * - preLogin(string $user, string $password) + * - postLogin(\OC\User\User $user, string $password) + * - preRememberedLogin(string $uid) + * - postRememberedLogin(\OC\User\User $user) + * - logout() + * + * @package OC\User + */ +class Session implements IUserSession, Emitter { + + /** @var Manager $manager */ + private $manager; + + /** @var ISession $session */ + private $session; + + /** @var ITimeFactory */ + private $timeFacory; + + /** @var IProvider */ + private $tokenProvider; + + /** @var User $activeUser */ + protected $activeUser; + + /** + * @param IUserManager $manager + * @param ISession $session + * @param ITimeFactory $timeFacory + * @param IProvider $tokenProvider + */ + public function __construct(IUserManager $manager, ISession $session, ITimeFactory $timeFacory, $tokenProvider) { + $this->manager = $manager; + $this->session = $session; + $this->timeFacory = $timeFacory; + $this->tokenProvider = $tokenProvider; + } + + /** + * @param IProvider $provider + */ + public function setTokenProvider(IProvider $provider) { + $this->tokenProvider = $provider; + } + + /** + * @param string $scope + * @param string $method + * @param callable $callback + */ + public function listen($scope, $method, callable $callback) { + $this->manager->listen($scope, $method, $callback); + } + + /** + * @param string $scope optional + * @param string $method optional + * @param callable $callback optional + */ + public function removeListener($scope = null, $method = null, callable $callback = null) { + $this->manager->removeListener($scope, $method, $callback); + } + + /** + * get the manager object + * + * @return Manager + */ + public function getManager() { + return $this->manager; + } + + /** + * get the session object + * + * @return ISession + */ + public function getSession() { + return $this->session; + } + + /** + * set the session object + * + * @param ISession $session + */ + public function setSession(ISession $session) { + if ($this->session instanceof ISession) { + $this->session->close(); + } + $this->session = $session; + $this->activeUser = null; + } + + /** + * set the currently active user + * + * @param User|null $user + */ + public function setUser($user) { + if (is_null($user)) { + $this->session->remove('user_id'); + } else { + $this->session->set('user_id', $user->getUID()); + } + $this->activeUser = $user; + } + + /** + * get the current active user + * + * @return IUser|null Current user, otherwise null + */ + public function getUser() { + // FIXME: This is a quick'n dirty work-around for the incognito mode as + // described at https://github.com/owncloud/core/pull/12912#issuecomment-67391155 + if (OC_User::isIncognitoMode()) { + return null; + } + if (is_null($this->activeUser)) { + $uid = $this->session->get('user_id'); + if (is_null($uid)) { + return null; + } + $this->activeUser = $this->manager->get($uid); + if (is_null($this->activeUser)) { + return null; + } + $this->validateSession($this->activeUser); + } + return $this->activeUser; + } + + protected function validateSession(IUser $user) { + try { + $sessionId = $this->session->getId(); + } catch (SessionNotAvailableException $ex) { + return; + } + try { + $token = $this->tokenProvider->getToken($sessionId); + } catch (InvalidTokenException $ex) { + // Session was invalidated + $this->logout(); + return; + } + + // Check whether login credentials are still valid + // This check is performed each 5 minutes + $lastCheck = $this->session->get('last_login_check') ? : 0; + $now = $this->timeFacory->getTime(); + if ($lastCheck < ($now - 60 * 5)) { + try { + $pwd = $this->tokenProvider->getPassword($token, $sessionId); + } catch (InvalidTokenException $ex) { + // An invalid token password was used -> log user out + $this->logout(); + return; + } + + if ($this->manager->checkPassword($user->getUID(), $pwd) === false) { + // Password has changed -> log user out + $this->logout(); + return; + } + $this->session->set('last_login_check', $now); + } + + // Session is valid, so the token can be refreshed + $this->updateToken($token); + } + + /** + * Checks whether the user is logged in + * + * @return bool if logged in + */ + public function isLoggedIn() { + $user = $this->getUser(); + if (is_null($user)) { + return false; + } + + return $user->isEnabled(); + } + + /** + * set the login name + * + * @param string|null $loginName for the logged in user + */ + public function setLoginName($loginName) { + if (is_null($loginName)) { + $this->session->remove('loginname'); + } else { + $this->session->set('loginname', $loginName); + } + } + + /** + * get the login name of the current user + * + * @return string + */ + public function getLoginName() { + if ($this->activeUser) { + return $this->session->get('loginname'); + } else { + $uid = $this->session->get('user_id'); + if ($uid) { + $this->activeUser = $this->manager->get($uid); + return $this->session->get('loginname'); + } else { + return null; + } + } + } + + /** + * try to login with the provided credentials + * + * @param string $uid + * @param string $password + * @return boolean|null + * @throws LoginException + */ + public function login($uid, $password) { + $this->session->regenerateId(); + $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); + $user = $this->manager->checkPassword($uid, $password); + if ($user === false) { + if ($this->validateToken($password)) { + $user = $this->getUser(); + } + } + if ($user !== false) { + if (!is_null($user)) { + if ($user->isEnabled()) { + $this->setUser($user); + $this->setLoginName($uid); + $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); + if ($this->isLoggedIn()) { + $this->prepareUserLogin(); + return true; + } else { + // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory + $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); + throw new LoginException($message); + } + } else { + // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory + $message = \OC::$server->getL10N('lib')->t('User disabled'); + throw new LoginException($message); + } + } + } + return false; + } + + protected function prepareUserLogin() { + // TODO: mock/inject/use non-static + // Refresh the token + \OC::$server->getCsrfTokenManager()->refreshToken(); + //we need to pass the user name, which may differ from login name + $user = $this->getUser()->getUID(); + OC_Util::setupFS($user); + //trigger creation of user home and /files folder + \OC::$server->getUserFolder($user); + } + + /** + * Tries to login the user with HTTP Basic Authentication + * + * @param IRequest $request + * @return boolean if the login was successful + */ + public function tryBasicAuthLogin(IRequest $request) { + if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) { + $result = $this->login($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW']); + if ($result === true) { + /** + * Add DAV authenticated. This should in an ideal world not be + * necessary but the iOS App reads cookies from anywhere instead + * only the DAV endpoint. + * This makes sure that the cookies will be valid for the whole scope + * @see https://github.com/owncloud/core/issues/22893 + */ + $this->session->set( + Auth::DAV_AUTHENTICATED, $this->getUser()->getUID() + ); + return true; + } + } + return false; + } + + private function loginWithToken($uid) { + // TODO: $this->manager->emit('\OC\User', 'preTokenLogin', array($uid)); + $user = $this->manager->get($uid); + if (is_null($user)) { + // user does not exist + return false; + } + if (!$user->isEnabled()) { + // disabled users can not log in + return false; + } + + //login + $this->setUser($user); + // TODO: $this->manager->emit('\OC\User', 'postTokenLogin', array($user)); + return true; + } + + /** + * Create a new session token for the given user credentials + * + * @param IRequest $request + * @param string $uid user UID + * @param string $password + * @return boolean + */ + public function createSessionToken(IRequest $request, $uid, $password) { + if (is_null($this->manager->get($uid))) { + // User does not exist + return false; + } + $name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser'; + $loggedIn = $this->login($uid, $password); + if ($loggedIn) { + try { + $sessionId = $this->session->getId(); + $this->tokenProvider->generateToken($sessionId, $uid, $password, $name); + } catch (SessionNotAvailableException $ex) { + + } + } + return $loggedIn; + } + + /** + * @param string $token + * @return boolean + */ + private function validateToken($token) { + try { + $token = $this->tokenProvider->validateToken($token); + if (!is_null($token)) { + $result = $this->loginWithToken($token->getUID()); + if ($result) { + // Login success + $this->updateToken($token); + return true; + } + } + } catch (InvalidTokenException $ex) { + + } + return false; + } + + /** + * @param IToken $token + */ + private function updateToken(IToken $token) { + // To save unnecessary DB queries, this is only done once a minute + $lastTokenUpdate = $this->session->get('last_token_update') ? : 0; + $now = $this->timeFacory->getTime(); + if ($lastTokenUpdate < ($now - 60)) { + $this->tokenProvider->updateToken($token); + $this->session->set('last_token_update', $now); + } + } + + /** + * Tries to login the user with auth token header + * + * @todo check remember me cookie + * @return boolean + */ + public function tryTokenLogin(IRequest $request) { + $authHeader = $request->getHeader('Authorization'); + if (strpos($authHeader, 'token ') === false) { + // No auth header, let's try session id + try { + $sessionId = $this->session->getId(); + return $this->validateToken($sessionId); + } catch (SessionNotAvailableException $ex) { + return false; + } + } else { + $token = substr($authHeader, 6); + return $this->validateToken($token); + } + } + + /** + * perform login using the magic cookie (remember login) + * + * @param string $uid the username + * @param string $currentToken + * @return bool + */ + public function loginWithCookie($uid, $currentToken) { + $this->session->regenerateId(); + $this->manager->emit('\OC\User', 'preRememberedLogin', array($uid)); + $user = $this->manager->get($uid); + if (is_null($user)) { + // user does not exist + return false; + } + + // get stored tokens + $tokens = OC::$server->getConfig()->getUserKeys($uid, 'login_token'); + // test cookies token against stored tokens + if (!in_array($currentToken, $tokens, true)) { + return false; + } + // replace successfully used token with a new one + OC::$server->getConfig()->deleteUserValue($uid, 'login_token', $currentToken); + $newToken = OC::$server->getSecureRandom()->generate(32); + OC::$server->getConfig()->setUserValue($uid, 'login_token', $newToken, time()); + $this->setMagicInCookie($user->getUID(), $newToken); + + //login + $this->setUser($user); + $this->manager->emit('\OC\User', 'postRememberedLogin', array($user)); + return true; + } + + /** + * logout the user from the session + */ + public function logout() { + $this->manager->emit('\OC\User', 'logout'); + $user = $this->getUser(); + if (!is_null($user)) { + try { + $this->tokenProvider->invalidateToken($this->session->getId()); + } catch (SessionNotAvailableException $ex) { + + } + } + $this->setUser(null); + $this->setLoginName(null); + $this->unsetMagicInCookie(); + $this->session->clear(); + } + + /** + * Set cookie value to use in next page load + * + * @param string $username username to be set + * @param string $token + */ + public function setMagicInCookie($username, $token) { + $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https'; + $expires = time() + OC::$server->getConfig()->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); + setcookie('oc_username', $username, $expires, OC::$WEBROOT, '', $secureCookie, true); + setcookie('oc_token', $token, $expires, OC::$WEBROOT, '', $secureCookie, true); + setcookie('oc_remember_login', '1', $expires, OC::$WEBROOT, '', $secureCookie, true); + } + + /** + * Remove cookie for "remember username" + */ + public function unsetMagicInCookie() { + //TODO: DI for cookies and IRequest + $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https'; + + unset($_COOKIE['oc_username']); //TODO: DI + unset($_COOKIE['oc_token']); + unset($_COOKIE['oc_remember_login']); + setcookie('oc_username', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true); + setcookie('oc_token', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true); + setcookie('oc_remember_login', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true); + // old cookies might be stored under /webroot/ instead of /webroot + // and Firefox doesn't like it! + setcookie('oc_username', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); + setcookie('oc_token', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); + setcookie('oc_remember_login', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); + } + +} diff --git a/lib/private/user/user.php b/lib/private/User/User.php index 3199790dba0..66ecbd18534 100644 --- a/lib/private/user/user.php +++ b/lib/private/User/User.php @@ -110,7 +110,7 @@ class User implements IUser { public function getDisplayName() { if (!isset($this->displayName)) { $displayName = ''; - if ($this->backend and $this->backend->implementsActions(\OC_User_Backend::GET_DISPLAYNAME)) { + if ($this->backend and $this->backend->implementsActions(\OC\User\Backend::GET_DISPLAYNAME)) { // get display name and strip whitespace from the beginning and end of it $backendDisplayName = $this->backend->getDisplayName($this->uid); if (is_string($backendDisplayName)) { @@ -135,7 +135,7 @@ class User implements IUser { */ public function setDisplayName($displayName) { $displayName = trim($displayName); - if ($this->backend->implementsActions(\OC_User_Backend::SET_DISPLAYNAME) && !empty($displayName)) { + if ($this->backend->implementsActions(\OC\User\Backend::SET_DISPLAYNAME) && !empty($displayName)) { $result = $this->backend->setDisplayName($this->uid, $displayName); if ($result) { $this->displayName = $displayName; @@ -230,7 +230,7 @@ class User implements IUser { if ($this->emitter) { $this->emitter->emit('\OC\User', 'preSetPassword', array($this, $password, $recoveryPassword)); } - if ($this->backend->implementsActions(\OC_User_Backend::SET_PASSWORD)) { + if ($this->backend->implementsActions(\OC\User\Backend::SET_PASSWORD)) { $result = $this->backend->setPassword($this->uid, $password); if ($this->emitter) { $this->emitter->emit('\OC\User', 'postSetPassword', array($this, $password, $recoveryPassword)); @@ -248,7 +248,7 @@ class User implements IUser { */ public function getHome() { if (!$this->home) { - if ($this->backend->implementsActions(\OC_User_Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) { + if ($this->backend->implementsActions(\OC\User\Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) { $this->home = $home; } elseif ($this->config) { $this->home = $this->config->getSystemValue('datadirectory') . '/' . $this->uid; @@ -277,7 +277,7 @@ class User implements IUser { * @return bool */ public function canChangeAvatar() { - if ($this->backend->implementsActions(\OC_User_Backend::PROVIDE_AVATAR)) { + if ($this->backend->implementsActions(\OC\User\Backend::PROVIDE_AVATAR)) { return $this->backend->canChangeAvatar($this->uid); } return true; @@ -289,7 +289,7 @@ class User implements IUser { * @return bool */ public function canChangePassword() { - return $this->backend->implementsActions(\OC_User_Backend::SET_PASSWORD); + return $this->backend->implementsActions(\OC\User\Backend::SET_PASSWORD); } /** @@ -301,7 +301,7 @@ class User implements IUser { if ($this->config->getSystemValue('allow_user_to_change_display_name') === false) { return false; } - return $this->backend->implementsActions(\OC_User_Backend::SET_DISPLAYNAME); + return $this->backend->implementsActions(\OC\User\Backend::SET_DISPLAYNAME); } /** @@ -417,5 +417,4 @@ class User implements IUser { $this->emitter->emit('\OC\User', 'changeUser', array($this, $feature, $value)); } } - } diff --git a/lib/private/api.php b/lib/private/legacy/api.php index bab879c95f8..60300c88b57 100644 --- a/lib/private/api.php +++ b/lib/private/legacy/api.php @@ -337,7 +337,7 @@ class OC_API { } // reuse existing login - $loggedIn = OC_User::isLoggedIn(); + $loggedIn = \OC::$server->getUserSession()->isLoggedIn(); if ($loggedIn === true) { $ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false; if ($ocsApiRequest) { @@ -353,31 +353,25 @@ class OC_API { // basic auth - because OC_User::login will create a new session we shall only try to login // if user and pass are set - if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']) ) { - $authUser = $_SERVER['PHP_AUTH_USER']; - $authPw = $_SERVER['PHP_AUTH_PW']; - $return = OC_User::login($authUser, $authPw); - if ($return === true) { - self::$logoutRequired = true; - - // initialize the user's filesystem - \OC_Util::setUpFS(\OC_User::getUser()); - self::$isLoggedIn = true; + $userSession = \OC::$server->getUserSession(); + $request = \OC::$server->getRequest(); + try { + $loginSuccess = $userSession->tryTokenLogin($request); + if (!$loginSuccess) { + $loginSuccess = $userSession->tryBasicAuthLogin($request); + } + } catch (\OC\User\LoginException $e) { + return false; + } + + if ($loginSuccess === true) { + self::$logoutRequired = true; - /** - * Add DAV authenticated. This should in an ideal world not be - * necessary but the iOS App reads cookies from anywhere instead - * only the DAV endpoint. - * This makes sure that the cookies will be valid for the whole scope - * @see https://github.com/owncloud/core/issues/22893 - */ - \OC::$server->getSession()->set( - \OCA\DAV\Connector\Sabre\Auth::DAV_AUTHENTICATED, - \OC::$server->getUserSession()->getUser()->getUID() - ); + // initialize the user's filesystem + \OC_Util::setUpFS(\OC_User::getUser()); + self::$isLoggedIn = true; - return \OC_User::getUser(); - } + return \OC_User::getUser(); } return false; diff --git a/lib/private/app.php b/lib/private/legacy/app.php index 246bf97ee91..f558c873556 100644 --- a/lib/private/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,23 @@ class OC_App { } /** + * @internal + * @param string $app + * @param string $path + */ + public 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 +325,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 +361,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 +375,7 @@ class OC_App { return false; } - return OC_Installer::removeApp($app); + return Installer::removeApp($app); } /** @@ -369,9 +390,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 +858,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 +1104,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 +1191,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 +1219,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 +1242,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/db.php b/lib/private/legacy/db.php index 5d612312919..5d612312919 100644 --- a/lib/private/db.php +++ b/lib/private/legacy/db.php diff --git a/lib/private/defaults.php b/lib/private/legacy/defaults.php index 43e8c8082cc..43e8c8082cc 100644 --- a/lib/private/defaults.php +++ b/lib/private/legacy/defaults.php diff --git a/lib/private/eventsource.php b/lib/private/legacy/eventsource.php index f567d1e6ca5..f567d1e6ca5 100644 --- a/lib/private/eventsource.php +++ b/lib/private/legacy/eventsource.php diff --git a/lib/private/filechunking.php b/lib/private/legacy/filechunking.php index f2cef275458..f2cef275458 100644 --- a/lib/private/filechunking.php +++ b/lib/private/legacy/filechunking.php diff --git a/lib/private/files.php b/lib/private/legacy/files.php index 9b6a1a4465f..9b6a1a4465f 100644 --- a/lib/private/files.php +++ b/lib/private/legacy/files.php diff --git a/lib/private/group.php b/lib/private/legacy/group.php index f1b84069a38..ceb99389942 100644 --- a/lib/private/group.php +++ b/lib/private/legacy/group.php @@ -66,7 +66,7 @@ class OC_Group { /** * set the group backend - * @param \OC_Group_Backend $backend The backend to use for user management + * @param \OC\Group\Backend $backend The backend to use for user management * @return bool */ public static function useBackend($backend) { diff --git a/lib/private/legacy/group/backend.php b/lib/private/legacy/group/backend.php new file mode 100644 index 00000000000..a5df9c339b9 --- /dev/null +++ b/lib/private/legacy/group/backend.php @@ -0,0 +1,59 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Bart Visscher <bartv@thisnet.nl> + * @author Jakob Sack <mail@jakobsack.de> + * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Jörn Friedrich Dreyer <jfd@butonic.de> + * @author Lukas Reschke <lukas@owncloud.com> + * @author Michael Gapczynski <GapczynskiM@gmail.com> + * @author Morris Jobke <hey@morrisjobke.de> + * @author Robin Appelman <icewind@owncloud.com> + * @author Robin McCorkell <robin@mccorkell.me.uk> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @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/> + * + */ + +/** + * error code for functions not provided by the group backend + * @deprecated Use \OC_Group_Backend::NOT_IMPLEMENTED instead + */ +define('OC_GROUP_BACKEND_NOT_IMPLEMENTED', -501); + +/** + * actions that user backends can define + */ +/** @deprecated Use \OC_Group_Backend::CREATE_GROUP instead */ +define('OC_GROUP_BACKEND_CREATE_GROUP', 0x00000001); +/** @deprecated Use \OC_Group_Backend::DELETE_GROUP instead */ +define('OC_GROUP_BACKEND_DELETE_GROUP', 0x00000010); +/** @deprecated Use \OC_Group_Backend::ADD_TO_GROUP instead */ +define('OC_GROUP_BACKEND_ADD_TO_GROUP', 0x00000100); +/** @deprecated Use \OC_Group_Backend::REMOVE_FROM_GOUP instead */ +define('OC_GROUP_BACKEND_REMOVE_FROM_GOUP', 0x00001000); +/** @deprecated Obsolete */ +define('OC_GROUP_BACKEND_GET_DISPLAYNAME', 0x00010000); //OBSOLETE +/** @deprecated Use \OC_Group_Backend::COUNT_USERS instead */ +define('OC_GROUP_BACKEND_COUNT_USERS', 0x00100000); + +/** + * Abstract base class for user management + * @deprecated Since 9.1.0 use \OC\Group\Backend + */ +abstract class OC_Group_Backend extends \OC\Group\Backend { +} diff --git a/lib/private/legacy/group/database.php b/lib/private/legacy/group/database.php new file mode 100644 index 00000000000..3969b3681fe --- /dev/null +++ b/lib/private/legacy/group/database.php @@ -0,0 +1,30 @@ +<?php +/** + * @author Jakob Sack <mail@jakobsack.de> + * @author Morris Jobke <hey@morrisjobke.de> + * @author Roeland Jago Douma <rullzer@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/> + * + */ + +/** + * Class OC_Group_Database + * @deprecated Since 9.1.0 use \OC\Group\Database + */ +class OC_Group_Database extends \OC\Group\Database { + +}
\ No newline at end of file diff --git a/lib/private/group/example.php b/lib/private/legacy/group/example.php index 17fae90f2e0..17fae90f2e0 100644 --- a/lib/private/group/example.php +++ b/lib/private/legacy/group/example.php diff --git a/lib/private/group/interface.php b/lib/private/legacy/group/interface.php index bdfe5235103..bdfe5235103 100644 --- a/lib/private/group/interface.php +++ b/lib/private/legacy/group/interface.php diff --git a/lib/private/helper.php b/lib/private/legacy/helper.php index e6aaed0fd15..29ee1be76b4 100644 --- a/lib/private/helper.php +++ b/lib/private/legacy/helper.php @@ -67,21 +67,6 @@ class OC_Helper { } /** - * get path to preview of file - * @param string $path path - * @return string the url - * - * Returns the path to the preview of the file. - */ - public static function previewIcon($path) { - return \OC::$server->getURLGenerator()->linkToRoute('core_ajax_preview', ['x' => 32, 'y' => 32, 'file' => $path]); - } - - public static function publicPreviewIcon( $path, $token ) { - return \OC::$server->getURLGenerator()->linkToRoute('core_ajax_public_preview', ['x' => 32, 'y' => 32, 'file' => $path, 't' => $token]); - } - - /** * Make a human file size * @param int $bytes file size in bytes * @return string a human readable file size @@ -463,22 +448,6 @@ class OC_Helper { } /** - * Shortens str to maxlen by replacing characters in the middle with '...', eg. - * ellipsis('a very long string with lots of useless info to make a better example', 14) becomes 'a very ...example' - * - * @param string $str the string - * @param string $maxlen the maximum length of the result - * @return string with at most maxlen characters - */ - public static function ellipsis($str, $maxlen) { - if (strlen($str) > $maxlen) { - $characters = floor($maxlen / 2); - return substr($str, 0, $characters) . '...' . substr($str, -1 * $characters); - } - return $str; - } - - /** * calculates the maximum upload size respecting system settings, free space and user quota * * @param string $dir the current folder where the user currently operates diff --git a/lib/private/hook.php b/lib/private/legacy/hook.php index 76f3b657eb9..76f3b657eb9 100644 --- a/lib/private/hook.php +++ b/lib/private/legacy/hook.php diff --git a/lib/private/image.php b/lib/private/legacy/image.php index a97347df623..a97347df623 100644 --- a/lib/private/image.php +++ b/lib/private/legacy/image.php diff --git a/lib/private/json.php b/lib/private/legacy/json.php index 74aebd476fb..74aebd476fb 100644 --- a/lib/private/json.php +++ b/lib/private/legacy/json.php diff --git a/lib/private/ocs.php b/lib/private/legacy/ocs.php index f48879a98b1..f48879a98b1 100644 --- a/lib/private/ocs.php +++ b/lib/private/legacy/ocs.php diff --git a/lib/private/legacy/ocs/cloud.php b/lib/private/legacy/ocs/cloud.php new file mode 100644 index 00000000000..1430cfa94ed --- /dev/null +++ b/lib/private/legacy/ocs/cloud.php @@ -0,0 +1,27 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * @author Tom Needham <tom@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/> + * + */ + +/** + * @deprecated Since 9.1.0 use \OC\OCS\Cloud + */ +class OC_OCS_Cloud extends \OC\OCS\Cloud { +} diff --git a/lib/private/legacy/ocs/config.php b/lib/private/legacy/ocs/config.php new file mode 100644 index 00000000000..b2e473276b4 --- /dev/null +++ b/lib/private/legacy/ocs/config.php @@ -0,0 +1,27 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * @author Tom Needham <tom@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/> + * + */ + +/** + * @deprecated Since 9.1.0 use \OC\OCS\Config + */ +class OC_OCS_Config extends \OC\OCS\Config { +} diff --git a/lib/private/legacy/ocs/person.php b/lib/private/legacy/ocs/person.php new file mode 100644 index 00000000000..edf4a7ced55 --- /dev/null +++ b/lib/private/legacy/ocs/person.php @@ -0,0 +1,27 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * @author Tom Needham <tom@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/> + * + */ + +/** + * @deprecated Since 9.1.0 use \OC\OCS\Person + */ +class OC_OCS_Person extends \OC\OCS\Person { +} diff --git a/lib/private/legacy/ocs/privatedata.php b/lib/private/legacy/ocs/privatedata.php new file mode 100644 index 00000000000..3c402457366 --- /dev/null +++ b/lib/private/legacy/ocs/privatedata.php @@ -0,0 +1,27 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * @author Tom Needham <tom@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/> + * + */ + +/** + * @deprecated Since 9.1.0 use \OC\OCS\PrivateData + */ +class OC_OCS_Privatedata extends \OC\OCS\PrivateData { +} diff --git a/lib/private/legacy/ocs/result.php b/lib/private/legacy/ocs/result.php new file mode 100644 index 00000000000..b59c6404e25 --- /dev/null +++ b/lib/private/legacy/ocs/result.php @@ -0,0 +1,27 @@ +<?php +/** + * @author Christopher Schäpers <kondou@ts.unde.re> + * @author Roeland Jago Douma <rullzer@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/> + * + */ + +/** + * @deprecated Since 9.1.0 use \OC\OCS\Result + */ +class OC_OCS_Result extends \OC\OCS\Result { +} diff --git a/lib/private/response.php b/lib/private/legacy/response.php index 51e0ff75e6a..51e0ff75e6a 100644 --- a/lib/private/response.php +++ b/lib/private/legacy/response.php diff --git a/lib/private/template.php b/lib/private/legacy/template.php index 73725529702..73725529702 100644 --- a/lib/private/template.php +++ b/lib/private/legacy/template.php diff --git a/lib/private/template/functions.php b/lib/private/legacy/template/functions.php index a57b3575ba9..a0540420e29 100644 --- a/lib/private/template/functions.php +++ b/lib/private/legacy/template/functions.php @@ -184,18 +184,16 @@ function mimetype_icon( $mimetype ) { * Returns the path to the preview of the image. * @param string $path path of file * @return link to the preview - * - * For further information have a look at OC_Helper::previewIcon */ function preview_icon( $path ) { - return OC_Helper::previewIcon( $path ); + return \OC::$server->getURLGenerator()->linkToRoute('core_ajax_preview', ['x' => 32, 'y' => 32, 'file' => $path]); } /** * @param string $path */ function publicPreview_icon ( $path, $token ) { - return OC_Helper::publicPreviewIcon( $path, $token ); + return \OC::$server->getURLGenerator()->linkToRoute('core_ajax_public_preview', ['x' => 32, 'y' => 32, 'file' => $path, 't' => $token]); } /** diff --git a/lib/private/user.php b/lib/private/legacy/user.php index 11c35daa0de..499e916994a 100644 --- a/lib/private/user.php +++ b/lib/private/legacy/user.php @@ -6,6 +6,7 @@ * @author Bart Visscher <bartv@thisnet.nl> * @author Bartek Przybylski <bart.p.pl@gmail.com> * @author Björn Schießle <schiessle@owncloud.com> + * @author Christoph Wurst <christoph@owncloud.com> * @author Florian Preinstorfer <nblock@archlinux.us> * @author Georg Ehrke <georg@owncloud.com> * @author Jakob Sack <mail@jakobsack.de> @@ -63,13 +64,11 @@ class OC_User { return OC::$server->getUserSession(); } - private static $_backends = array(); - private static $_usedBackends = array(); private static $_setupedBackends = array(); - // bool, stores if a user want to access a resource anonymously, e.g if he opens a public link + // bool, stores if a user want to access a resource anonymously, e.g if they open a public link private static $incognitoMode = false; /** @@ -96,7 +95,7 @@ class OC_User { case 'mysql': case 'sqlite': \OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', \OCP\Util::DEBUG); - self::$_usedBackends[$backend] = new OC_User_Database(); + self::$_usedBackends[$backend] = new \OC\User\Database(); \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]); break; case 'dummy': @@ -105,7 +104,7 @@ class OC_User { break; default: \OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', \OCP\Util::DEBUG); - $className = 'OC_USER_' . strToUpper($backend); + $className = 'OC_USER_' . strtoupper($backend); self::$_usedBackends[$backend] = new $className(); \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]); break; @@ -150,31 +149,10 @@ class OC_User { } /** - * Try to login a user - * - * @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); - if ($result) { - // Refresh the token - \OC::$server->getCsrfTokenManager()->refreshToken(); - //we need to pass the user name, which may differ from login name - $user = self::getUserSession()->getUser()->getUID(); - OC_Util::setupFS($user); - //trigger creation of user home and /files folder - \OC::$server->getUserFolder($user); - } - return $result; - } - /** * Try to login a user using the magic cookie (remember login) * + * @deprecated use \OCP\IUserSession::loginWithCookie() * @param string $uid The username of the user to log in * @param string $token * @return bool @@ -205,10 +183,13 @@ class OC_User { self::getUserSession()->setLoginName($uid); // setup the filesystem OC_Util::setupFS($uid); + // first call the post_login hooks, the login-process needs to be + // completed before we can safely create the users folder. + // For example encryption needs to initialize the users keys first + // before we can create the user folder with the skeleton files + OC_Hook::emit("OC_User", "post_login", array("uid" => $uid, 'password' => '')); //trigger creation of user home and /files folder \OC::$server->getUserFolder($uid); - - OC_Hook::emit("OC_User", "post_login", array("uid" => $uid, 'password' => '')); } return true; } @@ -241,6 +222,8 @@ class OC_User { /** * Sets user id for session and triggers emit + * + * @param string $uid */ public static function setUserId($uid) { $userSession = \OC::$server->getUserSession(); @@ -272,38 +255,13 @@ class OC_User { } /** - * Tries to login the user with HTTP Basic Authentication - */ - public static function tryBasicAuthLogin() { - if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) { - $result = \OC_User::login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); - if($result === true) { - /** - * Add DAV authenticated. This should in an ideal world not be - * necessary but the iOS App reads cookies from anywhere instead - * only the DAV endpoint. - * This makes sure that the cookies will be valid for the whole scope - * @see https://github.com/owncloud/core/issues/22893 - */ - \OC::$server->getSession()->set( - \OCA\DAV\Connector\Sabre\Auth::DAV_AUTHENTICATED, - \OC::$server->getUserSession()->getUser()->getUID() - ); - } - } - } - - /** * Check if the user is logged in, considers also the HTTP basic credentials * + * @deprecated use \OC::$server->getUserSession()->isLoggedIn() * @return bool */ public static function isLoggedIn() { - if (\OC::$server->getSession()->get('user_id') !== null && self::$incognitoMode === false) { - return self::userExists(\OC::$server->getSession()->get('user_id')); - } - - return false; + return \OC::$server->getUserSession()->isLoggedIn(); } /** diff --git a/lib/private/legacy/user/backend.php b/lib/private/legacy/user/backend.php new file mode 100644 index 00000000000..42c7b9aa126 --- /dev/null +++ b/lib/private/legacy/user/backend.php @@ -0,0 +1,67 @@ +<?php +/** + * @author Aldo "xoen" Giambelluca <xoen@xoen.org> + * @author Bart Visscher <bartv@thisnet.nl> + * @author Björn Schießle <schiessle@owncloud.com> + * @author Dominik Schmidt <dev@dominik-schmidt.de> + * @author Georg Ehrke <georg@owncloud.com> + * @author Jakob Sack <mail@jakobsack.de> + * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Jörn Friedrich Dreyer <jfd@butonic.de> + * @author Lukas Reschke <lukas@owncloud.com> + * @author Morris Jobke <hey@morrisjobke.de> + * @author Robin Appelman <icewind@owncloud.com> + * @author Sam Tuke <mail@samtuke.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Tigran Mkrtchyan <tigran.mkrtchyan@desy.de> + * + * @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/> + * + */ + +/** + * error code for functions not provided by the user backend + * @deprecated Use \OC_User_Backend::NOT_IMPLEMENTED instead + */ +define('OC_USER_BACKEND_NOT_IMPLEMENTED', -501); + +/** + * actions that user backends can define + */ +/** @deprecated Use \OC_User_Backend::CREATE_USER instead */ +define('OC_USER_BACKEND_CREATE_USER', 1 << 0); +/** @deprecated Use \OC_User_Backend::SET_PASSWORD instead */ +define('OC_USER_BACKEND_SET_PASSWORD', 1 << 4); +/** @deprecated Use \OC_User_Backend::CHECK_PASSWORD instead */ +define('OC_USER_BACKEND_CHECK_PASSWORD', 1 << 8); +/** @deprecated Use \OC_User_Backend::GET_HOME instead */ +define('OC_USER_BACKEND_GET_HOME', 1 << 12); +/** @deprecated Use \OC_User_Backend::GET_DISPLAYNAME instead */ +define('OC_USER_BACKEND_GET_DISPLAYNAME', 1 << 16); +/** @deprecated Use \OC_User_Backend::SET_DISPLAYNAME instead */ +define('OC_USER_BACKEND_SET_DISPLAYNAME', 1 << 20); +/** @deprecated Use \OC_User_Backend::PROVIDE_AVATAR instead */ +define('OC_USER_BACKEND_PROVIDE_AVATAR', 1 << 24); +/** @deprecated Use \OC_User_Backend::COUNT_USERS instead */ +define('OC_USER_BACKEND_COUNT_USERS', 1 << 28); + +/** + * Abstract base class for user management. Provides methods for querying backend + * capabilities. + */ +abstract class OC_User_Backend extends \OC\User\Backend implements \OCP\UserInterface { + +} diff --git a/lib/private/user/interface.php b/lib/private/legacy/user/interface.php index d2868a79c2c..d2868a79c2c 100644 --- a/lib/private/user/interface.php +++ b/lib/private/legacy/user/interface.php diff --git a/lib/private/util.php b/lib/private/legacy/util.php index 7caa1efcf54..4f7a8668dfc 100644 --- a/lib/private/util.php +++ b/lib/private/legacy/util.php @@ -145,6 +145,7 @@ class OC_Util { \OC\Files\Filesystem::initMountManager(); + \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(false); \OC\Files\Filesystem::addStorageWrapper('mount_options', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) { if ($storage->instanceOfStorage('\OC\Files\Storage\Common')) { /** @var \OC\Files\Storage\Common $storage */ @@ -195,6 +196,7 @@ class OC_Util { }); OC_Hook::emit('OC_Filesystem', 'preSetup', array('user' => $user)); + \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(true); //check if we are using an object storage $objectStore = \OC::$server->getSystemConfig()->getValue('objectstore', null); @@ -955,8 +957,7 @@ class OC_Util { public static function checkLoggedIn() { // Check if we are a user if (!OC_User::isLoggedIn()) { - header('Location: ' . \OC::$server->getURLGenerator()->linkToRoute( - 'core.login.showLoginForm', + header('Location: ' . \OCP\Util::linkToAbsolute('', 'index.php', [ 'redirect_url' => \OC::$server->getRequest()->getRequestUri() ] diff --git a/lib/private/user/session.php b/lib/private/user/session.php deleted file mode 100644 index 5402c5cf74f..00000000000 --- a/lib/private/user/session.php +++ /dev/null @@ -1,318 +0,0 @@ -<?php -/** - * @author Arthur Schiwon <blizzz@owncloud.com> - * @author Bernhard Posselt <dev@bernhard-posselt.com> - * @author Joas Schilling <nickvergessen@owncloud.com> - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Lukas Reschke <lukas@owncloud.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <icewind@owncloud.com> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * @author Roeland Jago Douma <rullzer@owncloud.com> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <pvince81@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 OC\User; - -use OC\Hooks\Emitter; -use OCP\IUserSession; - -/** - * Class Session - * - * Hooks available in scope \OC\User: - * - preSetPassword(\OC\User\User $user, string $password, string $recoverPassword) - * - postSetPassword(\OC\User\User $user, string $password, string $recoverPassword) - * - preDelete(\OC\User\User $user) - * - postDelete(\OC\User\User $user) - * - preCreateUser(string $uid, string $password) - * - postCreateUser(\OC\User\User $user) - * - preLogin(string $user, string $password) - * - postLogin(\OC\User\User $user, string $password) - * - preRememberedLogin(string $uid) - * - postRememberedLogin(\OC\User\User $user) - * - logout() - * - * @package OC\User - */ -class Session implements IUserSession, Emitter { - /** - * @var \OC\User\Manager $manager - */ - private $manager; - - /** - * @var \OC\Session\Session $session - */ - private $session; - - /** - * @var \OC\User\User $activeUser - */ - protected $activeUser; - - /** - * @param \OCP\IUserManager $manager - * @param \OCP\ISession $session - */ - public function __construct(\OCP\IUserManager $manager, \OCP\ISession $session) { - $this->manager = $manager; - $this->session = $session; - } - - /** - * @param string $scope - * @param string $method - * @param callable $callback - */ - public function listen($scope, $method, callable $callback) { - $this->manager->listen($scope, $method, $callback); - } - - /** - * @param string $scope optional - * @param string $method optional - * @param callable $callback optional - */ - public function removeListener($scope = null, $method = null, callable $callback = null) { - $this->manager->removeListener($scope, $method, $callback); - } - - /** - * get the manager object - * - * @return \OC\User\Manager - */ - public function getManager() { - return $this->manager; - } - - /** - * get the session object - * - * @return \OCP\ISession - */ - public function getSession() { - return $this->session; - } - - /** - * set the session object - * - * @param \OCP\ISession $session - */ - public function setSession(\OCP\ISession $session) { - if ($this->session instanceof \OCP\ISession) { - $this->session->close(); - } - $this->session = $session; - $this->activeUser = null; - } - - /** - * set the currently active user - * - * @param \OC\User\User|null $user - */ - public function setUser($user) { - if (is_null($user)) { - $this->session->remove('user_id'); - } else { - $this->session->set('user_id', $user->getUID()); - } - $this->activeUser = $user; - } - - /** - * get the current active user - * - * @return \OCP\IUser|null Current user, otherwise null - */ - public function getUser() { - // FIXME: This is a quick'n dirty work-around for the incognito mode as - // described at https://github.com/owncloud/core/pull/12912#issuecomment-67391155 - if (\OC_User::isIncognitoMode()) { - return null; - } - if ($this->activeUser) { - return $this->activeUser; - } else { - $uid = $this->session->get('user_id'); - if ($uid !== null) { - $this->activeUser = $this->manager->get($uid); - return $this->activeUser; - } else { - return null; - } - } - } - - /** - * Checks whether the user is logged in - * - * @return bool if logged in - */ - public function isLoggedIn() { - return $this->getUser() !== null; - } - - /** - * set the login name - * - * @param string|null $loginName for the logged in user - */ - public function setLoginName($loginName) { - if (is_null($loginName)) { - $this->session->remove('loginname'); - } else { - $this->session->set('loginname', $loginName); - } - } - - /** - * get the login name of the current user - * - * @return string - */ - public function getLoginName() { - if ($this->activeUser) { - return $this->session->get('loginname'); - } else { - $uid = $this->session->get('user_id'); - if ($uid) { - $this->activeUser = $this->manager->get($uid); - return $this->session->get('loginname'); - } else { - return null; - } - } - } - - /** - * try to login with the provided credentials - * - * @param string $uid - * @param string $password - * @return boolean|null - * @throws LoginException - */ - public function login($uid, $password) { - $this->session->regenerateId(); - $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); - $user = $this->manager->checkPassword($uid, $password); - if ($user !== false) { - if (!is_null($user)) { - if ($user->isEnabled()) { - $this->setUser($user); - $this->setLoginName($uid); - $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); - if ($this->isLoggedIn()) { - return true; - } else { - throw new LoginException('Login canceled by app'); - } - } else { - return false; - } - } - } else { - return false; - } - } - - /** - * perform login using the magic cookie (remember login) - * - * @param string $uid the username - * @param string $currentToken - * @return bool - */ - public function loginWithCookie($uid, $currentToken) { - $this->session->regenerateId(); - $this->manager->emit('\OC\User', 'preRememberedLogin', array($uid)); - $user = $this->manager->get($uid); - if (is_null($user)) { - // user does not exist - return false; - } - - // get stored tokens - $tokens = \OC::$server->getConfig()->getUserKeys($uid, 'login_token'); - // test cookies token against stored tokens - if (!in_array($currentToken, $tokens, true)) { - return false; - } - // replace successfully used token with a new one - \OC::$server->getConfig()->deleteUserValue($uid, 'login_token', $currentToken); - $newToken = \OC::$server->getSecureRandom()->generate(32); - \OC::$server->getConfig()->setUserValue($uid, 'login_token', $newToken, time()); - $this->setMagicInCookie($user->getUID(), $newToken); - - //login - $this->setUser($user); - $this->manager->emit('\OC\User', 'postRememberedLogin', array($user)); - return true; - } - - /** - * logout the user from the session - */ - public function logout() { - $this->manager->emit('\OC\User', 'logout'); - $this->setUser(null); - $this->setLoginName(null); - $this->unsetMagicInCookie(); - $this->session->clear(); - } - - /** - * Set cookie value to use in next page load - * - * @param string $username username to be set - * @param string $token - */ - public function setMagicInCookie($username, $token) { - $secureCookie = \OC::$server->getRequest()->getServerProtocol() === 'https'; - $expires = time() + \OC::$server->getConfig()->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); - setcookie("oc_username", $username, $expires, \OC::$WEBROOT, '', $secureCookie, true); - setcookie("oc_token", $token, $expires, \OC::$WEBROOT, '', $secureCookie, true); - setcookie("oc_remember_login", "1", $expires, \OC::$WEBROOT, '', $secureCookie, true); - } - - /** - * Remove cookie for "remember username" - */ - public function unsetMagicInCookie() { - //TODO: DI for cookies and IRequest - $secureCookie = \OC::$server->getRequest()->getServerProtocol() === 'https'; - - unset($_COOKIE["oc_username"]); //TODO: DI - unset($_COOKIE["oc_token"]); - unset($_COOKIE["oc_remember_login"]); - setcookie('oc_username', '', time() - 3600, \OC::$WEBROOT, '',$secureCookie, true); - setcookie('oc_token', '', time() - 3600, \OC::$WEBROOT, '', $secureCookie, true); - setcookie('oc_remember_login', '', time() - 3600, \OC::$WEBROOT, '', $secureCookie, true); - // old cookies might be stored under /webroot/ instead of /webroot - // and Firefox doesn't like it! - setcookie('oc_username', '', time() - 3600, \OC::$WEBROOT . '/', '', $secureCookie, true); - setcookie('oc_token', '', time() - 3600, \OC::$WEBROOT . '/', '', $secureCookie, true); - setcookie('oc_remember_login', '', time() - 3600, \OC::$WEBROOT . '/', '', $secureCookie, true); - } -} |