diff options
Diffstat (limited to 'lib')
24 files changed, 430 insertions, 65 deletions
diff --git a/lib/l10n/ca.js b/lib/l10n/ca.js index 3a7f21787ec..d84d7284275 100644 --- a/lib/l10n/ca.js +++ b/lib/l10n/ca.js @@ -18,6 +18,7 @@ OC.L10N.register( "_%n hour ago_::_%n hours ago_" : ["fa %n hora","fa %n hores"], "_%n minute ago_::_%n minutes ago_" : ["fa %n minut","fa %n minuts"], "seconds ago" : "segons enrere", + "File name contains at least one invalid character" : "El nom del fitxer conté al menys un caràcter invàlid", "App directory already exists" : "La carpeta de l'aplicació ja existeix", "Can't create app folder. Please fix permissions. %s" : "No es pot crear la carpeta de l'aplicació. Arregleu els permisos. %s", "No source specified when installing app" : "No heu especificat la font en instal·lar l'aplicació", @@ -43,6 +44,7 @@ OC.L10N.register( "For the best results, please consider using a GNU/Linux server instead." : "Per millors resultats, millor considereu utilitzar un servidor GNU/Linux.", "Set an admin username." : "Establiu un nom d'usuari per l'administrador.", "Set an admin password." : "Establiu una contrasenya per l'administrador.", + "Invalid Federated Cloud ID" : "ID de núvol federat invàlid", "%s shared »%s« with you" : "%s ha compartit »%s« amb tu", "Sharing %s failed, because the file does not exist" : "Ha fallat en compartir %s, perquè el fitxer no existeix", "You are not allowed to share %s" : "No se us permet compartir %s", @@ -53,6 +55,8 @@ OC.L10N.register( "Sharing %s failed, because %s is not a member of the group %s" : "Ha fallat en compartir %s, perquè %s no és membre del grup %s", "You need to provide a password to create a public link, only protected links are allowed" : "Heu de proporcionar una contrasenya per crear un enllaç públic. Només es permeten enllaços segurs.", "Sharing %s failed, because sharing with links is not allowed" : "Ha fallat en compartir %s, perquè no es permet compartir amb enllaços", + "Not allowed to create a federated share with the same user" : "No està permés crear una compartició federada amb el mateix usuari", + "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "La compartició de %s ha fallat, no es pot trobar %s, potser el servidor està actualment innacessible.", "Share type %s is not valid for %s" : "La compartició tipus %s no és vàlida per %s", "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Ha fallat en establir els permisos per %s perquè aquests excedeixen els permesos per a %s", "Setting permissions for %s failed, because the item was not found" : "Ha fallat en establir els permisos per %s, perquè no s'ha trobat l'element", diff --git a/lib/l10n/ca.json b/lib/l10n/ca.json index 255f5abbe38..ac6dd35ea1d 100644 --- a/lib/l10n/ca.json +++ b/lib/l10n/ca.json @@ -16,6 +16,7 @@ "_%n hour ago_::_%n hours ago_" : ["fa %n hora","fa %n hores"], "_%n minute ago_::_%n minutes ago_" : ["fa %n minut","fa %n minuts"], "seconds ago" : "segons enrere", + "File name contains at least one invalid character" : "El nom del fitxer conté al menys un caràcter invàlid", "App directory already exists" : "La carpeta de l'aplicació ja existeix", "Can't create app folder. Please fix permissions. %s" : "No es pot crear la carpeta de l'aplicació. Arregleu els permisos. %s", "No source specified when installing app" : "No heu especificat la font en instal·lar l'aplicació", @@ -41,6 +42,7 @@ "For the best results, please consider using a GNU/Linux server instead." : "Per millors resultats, millor considereu utilitzar un servidor GNU/Linux.", "Set an admin username." : "Establiu un nom d'usuari per l'administrador.", "Set an admin password." : "Establiu una contrasenya per l'administrador.", + "Invalid Federated Cloud ID" : "ID de núvol federat invàlid", "%s shared »%s« with you" : "%s ha compartit »%s« amb tu", "Sharing %s failed, because the file does not exist" : "Ha fallat en compartir %s, perquè el fitxer no existeix", "You are not allowed to share %s" : "No se us permet compartir %s", @@ -51,6 +53,8 @@ "Sharing %s failed, because %s is not a member of the group %s" : "Ha fallat en compartir %s, perquè %s no és membre del grup %s", "You need to provide a password to create a public link, only protected links are allowed" : "Heu de proporcionar una contrasenya per crear un enllaç públic. Només es permeten enllaços segurs.", "Sharing %s failed, because sharing with links is not allowed" : "Ha fallat en compartir %s, perquè no es permet compartir amb enllaços", + "Not allowed to create a federated share with the same user" : "No està permés crear una compartició federada amb el mateix usuari", + "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "La compartició de %s ha fallat, no es pot trobar %s, potser el servidor està actualment innacessible.", "Share type %s is not valid for %s" : "La compartició tipus %s no és vàlida per %s", "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Ha fallat en establir els permisos per %s perquè aquests excedeixen els permesos per a %s", "Setting permissions for %s failed, because the item was not found" : "Ha fallat en establir els permisos per %s, perquè no s'ha trobat l'element", diff --git a/lib/l10n/he.js b/lib/l10n/he.js index 35d2593ffef..bad99d5c638 100644 --- a/lib/l10n/he.js +++ b/lib/l10n/he.js @@ -9,6 +9,7 @@ OC.L10N.register( "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "התגלה שדוגמת התצורה הועתקה. דבר זה עלול לשבור את ההתקנה ולא נתמך.יש לקרוא את מסמכי התיעוד לפני שמבצעים שינויים ב- config.php", "PHP %s or higher is required." : "נדרש PHP בגרסת %s ומעלה.", "PHP with a version lower than %s is required." : "נדרש PHP בגרסה נמוכה מ- %s.", + "%sbit or higher PHP required." : "נדרש PHP בגרסת %s ומעלה.", "Following databases are supported: %s" : "מסדי הנתונים הבאים נתמכים: %s", "The command line tool %s could not be found" : "כלי שורת הפקודה %s לא אותר", "The library %s is not available." : "הספריה %s אינה זמינה.", @@ -98,6 +99,8 @@ OC.L10N.register( "Sharing %s failed, because the sharing backend for %s could not find its source" : "השיתוף %s נכשל, כיוון שבצד אחורי לשיתוף עבור %s לא ניתן היה לאתר את מקורו", "Sharing %s failed, because the file could not be found in the file cache" : "השיתוף %s נכשל, כייון שלא ניתן היה למצוא את הקובץ בזכרון המטמון", "Cannot increase permissions of %s" : "לא ניתן להגדיל את ההיתרים של %s", + "Files can't be shared with delete permissions" : "קובץ לא ניתן לשיתוף בפעולת מחיקת הרשאות", + "Files can't be shared with create permissions" : "קובץ לא ניתן לשיתוף בפעולת יצירת הרשאות", "Expiration date is in the past" : "תאריך תפוגה הנו בעבר", "Cannot set expiration date more than %s days in the future" : "לא ניתן להגדיר את תאריך התפוגה מעל %s ימים בעתיד", "Could not find category \"%s\"" : "לא ניתן למצוא את הקטגוריה „%s“", @@ -107,12 +110,14 @@ OC.L10N.register( "Username contains whitespace at the beginning or at the end" : "שם המשתמש מכיל רווח בתחילתו או בסופו", "A valid password must be provided" : "יש לספק ססמה תקנית", "The username is already being used" : "השם משתמש כבר בשימוש", + "Login canceled by app" : "התחברות בוטלה על ידי יישום", "User disabled" : "משתמש מנוטרל", "Help" : "עזרה", "Personal" : "אישי", "Users" : "משתמשים", "Admin" : "מנהל", "Recommended" : "מומלץ", + "App \"%s\" cannot be installed because appinfo file cannot be read." : "יישום \"%s\" לא ניתן להתקנה כיוון שקובץ appinfo לא ניתן לקריאה.", "App \"%s\" cannot be installed because it is not compatible with this version of ownCloud." : "היישום \"%s\" לא ניתן להתקנה כיוון שאינו תואם לגרסה זו של ownCloud.", "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "היישום \"%s\" לא ניתן להתקנה כיוון שיחסי התלות הבאים אינם מתקיימים: %s", "No app name specified" : "לא הוגדר שם יישום", diff --git a/lib/l10n/he.json b/lib/l10n/he.json index d60e0486572..73481766e09 100644 --- a/lib/l10n/he.json +++ b/lib/l10n/he.json @@ -7,6 +7,7 @@ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "התגלה שדוגמת התצורה הועתקה. דבר זה עלול לשבור את ההתקנה ולא נתמך.יש לקרוא את מסמכי התיעוד לפני שמבצעים שינויים ב- config.php", "PHP %s or higher is required." : "נדרש PHP בגרסת %s ומעלה.", "PHP with a version lower than %s is required." : "נדרש PHP בגרסה נמוכה מ- %s.", + "%sbit or higher PHP required." : "נדרש PHP בגרסת %s ומעלה.", "Following databases are supported: %s" : "מסדי הנתונים הבאים נתמכים: %s", "The command line tool %s could not be found" : "כלי שורת הפקודה %s לא אותר", "The library %s is not available." : "הספריה %s אינה זמינה.", @@ -96,6 +97,8 @@ "Sharing %s failed, because the sharing backend for %s could not find its source" : "השיתוף %s נכשל, כיוון שבצד אחורי לשיתוף עבור %s לא ניתן היה לאתר את מקורו", "Sharing %s failed, because the file could not be found in the file cache" : "השיתוף %s נכשל, כייון שלא ניתן היה למצוא את הקובץ בזכרון המטמון", "Cannot increase permissions of %s" : "לא ניתן להגדיל את ההיתרים של %s", + "Files can't be shared with delete permissions" : "קובץ לא ניתן לשיתוף בפעולת מחיקת הרשאות", + "Files can't be shared with create permissions" : "קובץ לא ניתן לשיתוף בפעולת יצירת הרשאות", "Expiration date is in the past" : "תאריך תפוגה הנו בעבר", "Cannot set expiration date more than %s days in the future" : "לא ניתן להגדיר את תאריך התפוגה מעל %s ימים בעתיד", "Could not find category \"%s\"" : "לא ניתן למצוא את הקטגוריה „%s“", @@ -105,12 +108,14 @@ "Username contains whitespace at the beginning or at the end" : "שם המשתמש מכיל רווח בתחילתו או בסופו", "A valid password must be provided" : "יש לספק ססמה תקנית", "The username is already being used" : "השם משתמש כבר בשימוש", + "Login canceled by app" : "התחברות בוטלה על ידי יישום", "User disabled" : "משתמש מנוטרל", "Help" : "עזרה", "Personal" : "אישי", "Users" : "משתמשים", "Admin" : "מנהל", "Recommended" : "מומלץ", + "App \"%s\" cannot be installed because appinfo file cannot be read." : "יישום \"%s\" לא ניתן להתקנה כיוון שקובץ appinfo לא ניתן לקריאה.", "App \"%s\" cannot be installed because it is not compatible with this version of ownCloud." : "היישום \"%s\" לא ניתן להתקנה כיוון שאינו תואם לגרסה זו של ownCloud.", "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "היישום \"%s\" לא ניתן להתקנה כיוון שיחסי התלות הבאים אינם מתקיימים: %s", "No app name specified" : "לא הוגדר שם יישום", diff --git a/lib/l10n/sl.js b/lib/l10n/sl.js index e8e861af3c4..5e0e1fbcdbd 100644 --- a/lib/l10n/sl.js +++ b/lib/l10n/sl.js @@ -157,7 +157,7 @@ OC.L10N.register( "Please check that the data directory contains a file \".ocdata\" in its root." : "Preverite, ali je v korenu podatkovne mape datoteka \".ocdata\".", "Could not obtain lock type %d on \"%s\"." : "Ni mogoče pridobiti zaklepa %d na \"%s\".", "Storage unauthorized. %s" : "Dostop do shrambe ni overjen. %s", - "Storage incomplete configuration. %s" : "Nepopolna konfiguracija shrambe. %s", + "Storage incomplete configuration. %s" : "Nepopolna nastavitev shrambe. %s", "Storage connection error. %s" : "Napaka povezave do shrambe. %s", "Storage not available" : "Shramba ni na voljo", "Storage connection timeout. %s" : "Povezava do shrambe je časovno potekla. %s" diff --git a/lib/l10n/sl.json b/lib/l10n/sl.json index a05d62b1c39..48c9f69a86d 100644 --- a/lib/l10n/sl.json +++ b/lib/l10n/sl.json @@ -155,7 +155,7 @@ "Please check that the data directory contains a file \".ocdata\" in its root." : "Preverite, ali je v korenu podatkovne mape datoteka \".ocdata\".", "Could not obtain lock type %d on \"%s\"." : "Ni mogoče pridobiti zaklepa %d na \"%s\".", "Storage unauthorized. %s" : "Dostop do shrambe ni overjen. %s", - "Storage incomplete configuration. %s" : "Nepopolna konfiguracija shrambe. %s", + "Storage incomplete configuration. %s" : "Nepopolna nastavitev shrambe. %s", "Storage connection error. %s" : "Napaka povezave do shrambe. %s", "Storage not available" : "Shramba ni na voljo", "Storage connection timeout. %s" : "Povezava do shrambe je časovno potekla. %s" diff --git a/lib/l10n/zh_CN.js b/lib/l10n/zh_CN.js index 8951d48b5c3..a29b4adaa1e 100644 --- a/lib/l10n/zh_CN.js +++ b/lib/l10n/zh_CN.js @@ -2,8 +2,12 @@ OC.L10N.register( "lib", { "Cannot write into \"config\" directory!" : "无法写入“config”目录!", + "This can usually be fixed by giving the webserver write access to the config directory" : "给 WEB 服务器 Config 目录设置写权限可以修复这个问题。", "See %s" : "查看 %s", + "Sample configuration detected" : "示例配置检测", "PHP %s or higher is required." : "要求 PHP 版本 %s 或者更高。", + "The command line tool %s could not be found" : "命令行工具 %s 未找到", + "The library %s is not available." : "库文件 %s 不可用", "Unknown filetype" : "未知的文件类型", "Invalid image" : "无效的图像", "today" : "今天", diff --git a/lib/l10n/zh_CN.json b/lib/l10n/zh_CN.json index c502c21ad8a..9b5f0af0742 100644 --- a/lib/l10n/zh_CN.json +++ b/lib/l10n/zh_CN.json @@ -1,7 +1,11 @@ { "translations": { "Cannot write into \"config\" directory!" : "无法写入“config”目录!", + "This can usually be fixed by giving the webserver write access to the config directory" : "给 WEB 服务器 Config 目录设置写权限可以修复这个问题。", "See %s" : "查看 %s", + "Sample configuration detected" : "示例配置检测", "PHP %s or higher is required." : "要求 PHP 版本 %s 或者更高。", + "The command line tool %s could not be found" : "命令行工具 %s 未找到", + "The library %s is not available." : "库文件 %s 不可用", "Unknown filetype" : "未知的文件类型", "Invalid image" : "无效的图像", "today" : "今天", diff --git a/lib/private/AllConfig.php b/lib/private/AllConfig.php index e082cea3305..c8b2009fcc7 100644 --- a/lib/private/AllConfig.php +++ b/lib/private/AllConfig.php @@ -27,6 +27,7 @@ */ namespace OC; +use OC\Cache\CappedMemoryCache; use OCP\IDBConnection; use OCP\PreConditionNotMetException; @@ -58,14 +59,15 @@ class AllConfig implements \OCP\IConfig { * - deleteAllUserValues * - deleteAppFromAllUsers * - * @var array $userCache + * @var CappedMemoryCache $userCache */ - private $userCache = array(); + private $userCache; /** * @param SystemConfig $systemConfig */ function __construct(SystemConfig $systemConfig) { + $this->userCache = new CappedMemoryCache(); $this->systemConfig = $systemConfig; } diff --git a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php index d84e9963436..32a507623e3 100644 --- a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php @@ -26,6 +26,7 @@ namespace OC\AppFramework\Middleware\Security; use OC\AppFramework\Middleware\Security\Exceptions\SecurityException; use OC\AppFramework\Utility\ControllerMethodReflector; +use OC\Authentication\Exceptions\PasswordLoginForbiddenException; use OC\User\Session; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; @@ -89,8 +90,12 @@ class CORSMiddleware extends Middleware { $pass = $this->request->server['PHP_AUTH_PW']; $this->session->logout(); - if(!$this->session->logClientIn($user, $pass)) { - throw new SecurityException('CORS requires basic auth', Http::STATUS_UNAUTHORIZED); + try { + if (!$this->session->logClientIn($user, $pass, $this->request)) { + throw new SecurityException('CORS requires basic auth', Http::STATUS_UNAUTHORIZED); + } + } catch (PasswordLoginForbiddenException $ex) { + throw new SecurityException('Password login forbidden, use token instead', Http::STATUS_UNAUTHORIZED); } } } diff --git a/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php b/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php new file mode 100644 index 00000000000..2e9f9534dbd --- /dev/null +++ b/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.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 PasswordLoginForbiddenException extends Exception { + +} diff --git a/lib/private/Authentication/Token/DefaultTokenMapper.php b/lib/private/Authentication/Token/DefaultTokenMapper.php index c56a513b94c..9450ed6b9f3 100644 --- a/lib/private/Authentication/Token/DefaultTokenMapper.php +++ b/lib/private/Authentication/Token/DefaultTokenMapper.php @@ -77,6 +77,7 @@ class DefaultTokenMapper extends Mapper { ->execute(); $data = $result->fetch(); + $result->closeCursor(); if ($data === false) { throw new DoesNotExistException('token does not exist'); } diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php index 805735bd1b8..6ca4fd065a6 100644 --- a/lib/private/Authentication/TwoFactorAuth/Manager.php +++ b/lib/private/Authentication/TwoFactorAuth/Manager.php @@ -24,6 +24,7 @@ namespace OC\Authentication\TwoFactorAuth; use Exception; use OC; use OC\App\AppManager; +use OC_App; use OCP\AppFramework\QueryException; use OCP\Authentication\TwoFactorAuth\IProvider; use OCP\IConfig; @@ -110,6 +111,7 @@ class Manager { $providerClasses = $info['two-factor-providers']; foreach ($providerClasses as $class) { try { + $this->loadTwoFactorApp($appId); $provider = OC::$server->query($class); $providers[$provider->getId()] = $provider; } catch (QueryException $exc) { @@ -126,6 +128,17 @@ class Manager { } /** + * Load an app by ID if it has not been loaded yet + * + * @param string $appId + */ + protected function loadTwoFactorApp($appId) { + if (!OC_App::isAppLoaded($appId)) { + OC_App::loadApp($appId); + } + } + + /** * Verify the given challenge * * @param string $providerId diff --git a/lib/private/Files/Cache/Updater.php b/lib/private/Files/Cache/Updater.php index 4e17c4d778d..361db4b3f85 100644 --- a/lib/private/Files/Cache/Updater.php +++ b/lib/private/Files/Cache/Updater.php @@ -25,6 +25,8 @@ */ namespace OC\Files\Cache; + +use OCP\Files\Cache\ICacheEntry; use OCP\Files\Cache\IUpdater; use OCP\Files\Storage\IStorage; @@ -150,12 +152,20 @@ class Updater implements IUpdater { $parent = ''; } + $entry = $this->cache->get($path); + $this->cache->remove($path); - if ($this->cache instanceof Cache) { - $this->cache->correctFolderSize($parent); - } + $this->correctParentStorageMtime($path); - $this->propagator->propagateChange($path, time()); + if ($entry instanceof ICacheEntry) { + $this->propagator->propagateChange($path, time(), -$entry->getSize()); + } else { + $this->propagator->propagateChange($path, time()); + if ($this->cache instanceof Cache) { + $this->cache->correctFolderSize($parent); + } + } + } /** diff --git a/lib/private/Files/Config/LazyStorageMountInfo.php b/lib/private/Files/Config/LazyStorageMountInfo.php index 654c5b2b23e..5df04c4b78e 100644 --- a/lib/private/Files/Config/LazyStorageMountInfo.php +++ b/lib/private/Files/Config/LazyStorageMountInfo.php @@ -28,7 +28,7 @@ use OCP\Files\Node; use OCP\IUser; class LazyStorageMountInfo extends CachedMountInfo { - /** @var IMountPoint */ + /** @var IMountPoint */ private $mount; /** @@ -47,7 +47,11 @@ class LazyStorageMountInfo extends CachedMountInfo { */ public function getStorageId() { if (!$this->storageId) { - $this->storageId = $this->mount->getStorage()->getStorageCache()->getNumericId(); + $storage = $this->mount->getStorage(); + if (!$storage) { + return -1; + } + $this->storageId = $storage->getStorageCache()->getNumericId(); } return parent::getStorageId(); } diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php index edb1525b276..bc6ad1b34f0 100644 --- a/lib/private/Files/Config/UserMountCache.php +++ b/lib/private/Files/Config/UserMountCache.php @@ -36,6 +36,7 @@ use OCP\IDBConnection; use OCP\ILogger; use OCP\IUser; use OCP\IUserManager; +use OC\Cache\CappedMemoryCache; /** * Cache mounts points per user in the cache so we can easilly look them up @@ -51,15 +52,23 @@ class UserMountCache implements IUserMountCache { */ private $userManager; - /** @var ICachedMountInfo[][] [$userId => [$cachedMountInfo, ....], ...] */ - private $mountsForUsers = []; + /** + * Cached mount info. + * Map of $userId to ICachedMountInfo. + * + * @var ICache + **/ + private $mountsForUsers; /** * @var ILogger */ private $logger; - private $cacheInfoCache = []; + /** + * @var ICache + */ + private $cacheInfoCache; /** * UserMountCache constructor. @@ -72,6 +81,8 @@ class UserMountCache implements IUserMountCache { $this->connection = $connection; $this->userManager = $userManager; $this->logger = $logger; + $this->cacheInfoCache = new CappedMemoryCache(); + $this->mountsForUsers = new CappedMemoryCache(); } public function registerMounts(IUser $user, array $mounts) { @@ -124,12 +135,16 @@ class UserMountCache implements IUserMountCache { } private function addToCache(ICachedMountInfo $mount) { - $this->connection->insertIfNotExist('*PREFIX*mounts', [ - 'storage_id' => $mount->getStorageId(), - 'root_id' => $mount->getRootId(), - 'user_id' => $mount->getUser()->getUID(), - 'mount_point' => $mount->getMountPoint() - ], ['root_id', 'user_id']); + if ($mount->getStorageId() !== -1) { + $this->connection->insertIfNotExist('*PREFIX*mounts', [ + 'storage_id' => $mount->getStorageId(), + 'root_id' => $mount->getRootId(), + 'user_id' => $mount->getUser()->getUID(), + 'mount_point' => $mount->getMountPoint() + ], ['root_id', 'user_id']); + } else { + $this->logger->error('Error getting storage info for mount at ' . $mount->getMountPoint()); + } } private function setMountPoint(ICachedMountInfo $mount) { diff --git a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php index 1f31e849446..5c72bfaa57c 100644 --- a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php +++ b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php @@ -39,6 +39,7 @@ class ExcludeFileByNameFilterIterator extends \RecursiveFilterIterator { '.DS_Store', // Mac OS X 'Thumbs.db', // Microsoft Windows '.directory', // Dolphin (KDE) + '.webapp', // Gentoo/Funtoo & derivatives use a tool known as webapp-config to manager wep-apps. ]; /** diff --git a/lib/private/Preview.php b/lib/private/Preview.php index f5e2f6b57e1..8bc262d7047 100644 --- a/lib/private/Preview.php +++ b/lib/private/Preview.php @@ -136,9 +136,9 @@ class Preview { //check if there are preview backends if (!\OC::$server->getPreviewManager() - ->hasProviders() + ->hasProviders() && \OC::$server->getConfig() - ->getSystemValue('enable_previews', true) + ->getSystemValue('enable_previews', true) ) { \OCP\Util::writeLog('core', 'No preview providers exist', \OCP\Util::ERROR); throw new \Exception('No preview providers'); @@ -410,6 +410,10 @@ class Preview { * Deletes all previews of a file */ public function deleteAllPreviews() { + $thumbnailMount = $this->userView->getMount($this->getThumbnailsFolder()); + $propagator = $thumbnailMount->getStorage()->getPropagator(); + $propagator->beginBatch(); + $toDelete = $this->getChildren(); $toDelete[] = $this->getFileInfo(); @@ -422,11 +426,12 @@ class Preview { // .ocTransferId*.part file from chunked file upload. if (!empty($fileId)) { $previewPath = $this->getPreviewPath($fileId); - $this->userView->deleteAll($previewPath); $this->userView->rmdir($previewPath); } } } + + $propagator->commitBatch(); } /** @@ -573,8 +578,8 @@ class Preview { * @return integer[] */ private function applyAspectRatio($askedWidth, $askedHeight, $originalWidth = 0, $originalHeight = 0) { - if(!$originalWidth){ - $originalWidth= $this->maxPreviewWidth; + if (!$originalWidth) { + $originalWidth = $this->maxPreviewWidth; } if (!$originalHeight) { $originalHeight = $this->maxPreviewHeight; @@ -1113,7 +1118,7 @@ class Preview { $preview = null; $previewProviders = \OC::$server->getPreviewManager() - ->getProviders(); + ->getProviders(); foreach ($previewProviders as $supportedMimeType => $providers) { if (!preg_match($supportedMimeType, $this->mimeType)) { continue; @@ -1127,7 +1132,7 @@ class Preview { \OCP\Util::writeLog( 'core', 'Generating preview for "' . $file . '" with "' . get_class($provider) - . '"', \OCP\Util::DEBUG + . '"', \OCP\Util::DEBUG ); /** @var $provider Provider */ @@ -1261,7 +1266,7 @@ class Preview { $absPath = Files\Filesystem::normalizePath($view->getAbsolutePath($path)); $fileInfo = $view->getFileInfo($path); - if($fileInfo === false) { + if ($fileInfo === false) { return; } self::addPathToDeleteFileMapper($absPath, $fileInfo); diff --git a/lib/private/Repair.php b/lib/private/Repair.php index bb2967d7e6e..2b33dc413b4 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -36,6 +36,7 @@ use OC\Repair\DropOldJobs; use OC\Repair\OldGroupMembershipShares; use OC\Repair\RemoveGetETagEntries; use OC\Repair\RemoveOldShares; +use OC\Repair\RemoveRootShares; use OC\Repair\SharePropagation; use OC\Repair\SqliteAutoincrement; use OC\Repair\DropOldTables; @@ -127,7 +128,7 @@ class Repair implements IOutput{ new RepairLegacyStorages(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()), new AssetCache(), new FillETags(\OC::$server->getDatabaseConnection()), - new CleanTags(\OC::$server->getDatabaseConnection()), + new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()), new DropOldTables(\OC::$server->getDatabaseConnection()), new DropOldJobs(\OC::$server->getJobList()), new RemoveGetETagEntries(\OC::$server->getDatabaseConnection()), @@ -136,6 +137,7 @@ class Repair implements IOutput{ new SharePropagation(\OC::$server->getConfig()), new RemoveOldShares(\OC::$server->getDatabaseConnection()), new AvatarPermissions(\OC::$server->getDatabaseConnection()), + new RemoveRootShares(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager(), \OC::$server->getLazyRootFolder()), ]; } diff --git a/lib/private/Repair/CleanTags.php b/lib/private/Repair/CleanTags.php index 60ddeff08f3..4241fa6da3a 100644 --- a/lib/private/Repair/CleanTags.php +++ b/lib/private/Repair/CleanTags.php @@ -25,6 +25,7 @@ namespace OC\Repair; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; +use OCP\IUserManager; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; @@ -38,11 +39,18 @@ class CleanTags implements IRepairStep { /** @var IDBConnection */ protected $connection; + /** @var IUserManager */ + protected $userManager; + + protected $deletedTags = 0; + /** * @param IDBConnection $connection + * @param IUserManager $userManager */ - public function __construct(IDBConnection $connection) { + public function __construct(IDBConnection $connection, IUserManager $userManager) { $this->connection = $connection; + $this->userManager = $userManager; } /** @@ -56,12 +64,59 @@ class CleanTags implements IRepairStep { * Updates the configuration after running an update */ public function run(IOutput $output) { + $this->deleteOrphanTags($output); $this->deleteOrphanFileEntries($output); $this->deleteOrphanTagEntries($output); $this->deleteOrphanCategoryEntries($output); } /** + * Delete tags for deleted users + */ + protected function deleteOrphanTags(IOutput $output) { + $offset = 0; + while ($this->checkTags($offset)) { + $offset += 50; + } + + $output->info(sprintf('%d tags of deleted users have been removed.', $this->deletedTags)); + } + + protected function checkTags($offset) { + $query = $this->connection->getQueryBuilder(); + $query->select('uid') + ->from('vcategory') + ->groupBy('uid') + ->orderBy('uid') + ->setMaxResults(50) + ->setFirstResult($offset); + $result = $query->execute(); + + $users = []; + $hadResults = false; + while ($row = $result->fetch()) { + $hadResults = true; + if (!$this->userManager->userExists($row['uid'])) { + $users[] = $row['uid']; + } + } + $result->closeCursor(); + + if (!$hadResults) { + // No more tags, stop looping + return false; + } + + if (!empty($users)) { + $query = $this->connection->getQueryBuilder(); + $query->delete('vcategory') + ->where($query->expr()->in('uid', $query->createNamedParameter($users, IQueryBuilder::PARAM_STR_ARRAY))); + $this->deletedTags += $query->execute(); + } + return true; + } + + /** * Delete tag entries for deleted files */ protected function deleteOrphanFileEntries(IOutput $output) { diff --git a/lib/private/Repair/RemoveRootShares.php b/lib/private/Repair/RemoveRootShares.php new file mode 100644 index 00000000000..89f797e3ef0 --- /dev/null +++ b/lib/private/Repair/RemoveRootShares.php @@ -0,0 +1,157 @@ +<?php +/** + * @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/> + * + */ +namespace OC\Repair; + +use OCP\Files\IRootFolder; +use OCP\IDBConnection; +use OCP\IUser; +use OCP\IUserManager; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +/** + * Class RemoveRootShares + * + * @package OC\Repair + */ +class RemoveRootShares implements IRepairStep { + + /** @var IDBConnection */ + protected $connection; + + /** @var IUserManager */ + protected $userManager; + + /** @var IRootFolder */ + protected $rootFolder; + + /** + * RemoveRootShares constructor. + * + * @param IDBConnection $connection + * @param IUserManager $userManager + * @param IRootFolder $rootFolder + */ + public function __construct(IDBConnection $connection, + IUserManager $userManager, + IRootFolder $rootFolder) { + $this->connection = $connection; + $this->userManager = $userManager; + $this->rootFolder = $rootFolder; + } + + /** + * @return string + */ + public function getName() { + return 'Remove shares of a users root folder'; + } + + /** + * @param IOutput $output + */ + public function run(IOutput $output) { + if ($this->rootSharesExist()) { + $this->removeRootShares($output); + } + } + + /** + * @param IOutput $output + */ + private function removeRootShares(IOutput $output) { + $function = function(IUser $user) use ($output) { + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $fileId = $userFolder->getId(); + + $qb = $this->connection->getQueryBuilder(); + $qb->delete('share') + ->where($qb->expr()->eq('file_source', $qb->createNamedParameter($fileId))) + ->andWhere($qb->expr()->orX( + $qb->expr()->eq('item_type', $qb->expr()->literal('file')), + $qb->expr()->eq('item_type', $qb->expr()->literal('folder')) + )); + + $qb->execute(); + + $output->advance(); + }; + + $userCount = $this->countUsers(); + $output->startProgress($userCount); + + $this->userManager->callForAllUsers($function); + + $output->finishProgress(); + } + + /** + * Count all the users + * + * @return int + */ + private function countUsers() { + $allCount = $this->userManager->countUsers(); + + $totalCount = 0; + foreach ($allCount as $backend => $count) { + $totalCount += $count; + } + + return $totalCount; + } + + /** + * Verify if this repair steps is required + * It *should* not be necessary in most cases and it can be very + * costly. + * + * @return bool + */ + private function rootSharesExist() { + $qb = $this->connection->getQueryBuilder(); + $qb2 = $this->connection->getQueryBuilder(); + + $qb->select('fileid') + ->from('filecache') + ->where($qb->expr()->eq('path', $qb->expr()->literal('files'))); + + $qb2->select('id') + ->from('share') + ->where($qb2->expr()->in('file_source', $qb2->createFunction($qb->getSQL()))) + ->andWhere($qb2->expr()->orX( + $qb2->expr()->eq('item_type', $qb->expr()->literal('file')), + $qb2->expr()->eq('item_type', $qb->expr()->literal('folder')) + )) + ->setMaxResults(1); + + $cursor = $qb2->execute(); + $data = $cursor->fetch(); + $cursor->closeCursor(); + + if ($data === false) { + return false; + } + + return true; + } +} + diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 5921bbc44c8..2857a394e1e 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -24,25 +24,24 @@ namespace OC\Share20; +use OC\Cache\CappedMemoryCache; use OC\Files\Mount\MoveableMount; +use OCP\Files\File; +use OCP\Files\Folder; use OCP\Files\IRootFolder; +use OCP\Files\Mount\IMountManager; use OCP\Files\NotFoundException; -use OCP\IUserManager; -use OCP\Share\IManager; -use OCP\Share\IProviderFactory; -use OC\Share20\Exception\BackendError; use OCP\IConfig; +use OCP\IGroupManager; use OCP\IL10N; use OCP\ILogger; -use OCP\Security\ISecureRandom; +use OCP\IUserManager; use OCP\Security\IHasher; -use OCP\Files\Mount\IMountManager; -use OCP\IGroupManager; -use OCP\Files\File; -use OCP\Files\Folder; - -use OCP\Share\Exceptions\ShareNotFound; +use OCP\Security\ISecureRandom; use OCP\Share\Exceptions\GenericShareException; +use OCP\Share\Exceptions\ShareNotFound; +use OCP\Share\IManager; +use OCP\Share\IProviderFactory; /** * This class is the communication hub for all sharing related operations. @@ -69,6 +68,9 @@ class Manager implements IManager { private $userManager; /** @var IRootFolder */ private $rootFolder; + /** @var CappedMemoryCache */ + private $sharingDisabledForUsersCache; + /** * Manager constructor. @@ -106,6 +108,7 @@ class Manager implements IManager { $this->factory = $factory; $this->userManager = $userManager; $this->rootFolder = $rootFolder; + $this->sharingDisabledForUsersCache = new CappedMemoryCache(); } /** @@ -1212,6 +1215,14 @@ class Manager implements IManager { * @return bool */ public function sharingDisabledForUser($userId) { + if ($userId === null) { + return false; + } + + if (isset($this->sharingDisabledForUsersCache[$userId])) { + return $this->sharingDisabledForUsersCache[$userId]; + } + if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') { $groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', ''); $excludedGroups = json_decode($groupsList); @@ -1227,10 +1238,13 @@ class Manager implements IManager { // if the user is only in groups which are disabled for sharing then // sharing is also disabled for the user if (empty($remainingGroups)) { + $this->sharingDisabledForUsersCache[$userId] = true; return true; } } } + + $this->sharingDisabledForUsersCache[$userId] = false; return false; } diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index f560bb4bfc0..4e9c827448d 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -33,6 +33,7 @@ namespace OC\User; use OC; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; +use OC\Authentication\Exceptions\PasswordLoginForbiddenException; use OC\Authentication\Token\IProvider; use OC\Authentication\Token\IToken; use OC\Hooks\Emitter; @@ -348,18 +349,18 @@ class Session implements IUserSession, Emitter { * * @param string $user * @param string $password + * @param IRequest $request * @throws LoginException + * @throws PasswordLoginForbiddenException * @return boolean */ - public function logClientIn($user, $password) { + public function logClientIn($user, $password, IRequest $request) { $isTokenPassword = $this->isTokenPassword($password); if (!$isTokenPassword && $this->isTokenAuthEnforced()) { - // TODO: throw LoginException instead (https://github.com/owncloud/core/pull/24616) - return false; + throw new PasswordLoginForbiddenException(); } if (!$isTokenPassword && $this->isTwoFactorEnforced($user)) { - // TODO: throw LoginException instead (https://github.com/owncloud/core/pull/24616) - return false; + throw new PasswordLoginForbiddenException(); } if (!$this->login($user, $password) ) { $users = $this->manager->getByEmail($user); @@ -368,9 +369,22 @@ class Session implements IUserSession, Emitter { } return false; } + + if ($this->supportsCookies($request)) { + $this->createSessionToken($request, $this->getUser()->getUID(), $user, $password); + } + return true; } + protected function supportsCookies(IRequest $request) { + if (!is_null($request->getCookie('cookie_test'))) { + return true; + } + setcookie('cookie_test', 'test', $this->timeFacory->getTime() + 3600); + return false; + } + private function isTokenAuthEnforced() { return $this->config->getSystemValue('token_auth_enforced', false); } @@ -428,19 +442,22 @@ class Session implements IUserSession, Emitter { */ public function tryBasicAuthLogin(IRequest $request) { if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) { - $result = $this->logClientIn($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; + try { + if ($this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request)) { + /** + * 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; + } + } catch (PasswordLoginForbiddenException $ex) { + // Nothing to do } } return false; diff --git a/lib/public/Util.php b/lib/public/Util.php index eb573168e10..687f4e78f69 100644 --- a/lib/public/Util.php +++ b/lib/public/Util.php @@ -63,6 +63,9 @@ class Util { const ERROR=3; const FATAL=4; + /** \OCP\Share\IManager */ + private static $shareManager; + /** * get the current installed version of ownCloud * @return array @@ -171,13 +174,19 @@ class Util { * * @return boolean * @since 7.0.0 + * @deprecated 9.1.0 Use \OC::$server->getShareManager()->sharingDisabledForUser */ public static function isSharingDisabledForUser() { - return \OC_Util::isSharingDisabledForUser( - \OC::$server->getConfig(), - \OC::$server->getGroupManager(), - \OC::$server->getUserSession()->getUser() - ); + if (self::$shareManager === null) { + self::$shareManager = \OC::$server->getShareManager(); + } + + $user = \OC::$server->getUserSession()->getUser(); + if ($user !== null) { + $user = $user->getUID(); + } + + return self::$shareManager->sharingDisabledForUser($user); } /** |