diff options
Diffstat (limited to 'lib')
49 files changed, 814 insertions, 353 deletions
diff --git a/lib/autoloader.php b/lib/autoloader.php index 23285f61e73..41a040b3f54 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -27,6 +27,8 @@ namespace OC; +use \OCP\AutoloadNotAllowedException; + class Autoloader { private $useGlobalClassPath = true; @@ -34,13 +36,34 @@ class Autoloader { private $classPaths = array(); + private $validRoots = []; + /** * Optional low-latency memory cache for class to path mapping. + * * @var \OC\Memcache\Cache */ protected $memoryCache; /** + * Autoloader constructor. + * + * @param string[] $validRoots + */ + public function __construct(array $validRoots) { + $this->validRoots = $validRoots; + } + + /** + * Add a path to the list of valid php roots for auto loading + * + * @param string $root + */ + public function addValidRoot($root) { + $this->validRoots[] = stream_resolve_include_path($root); + } + + /** * disable the usage of the global classpath \OC::$CLASSPATH */ public function disableGlobalClassPath() { @@ -102,6 +125,15 @@ class Autoloader { return $paths; } + protected function isValidPath($fullPath) { + foreach ($this->validRoots as $root) { + if (substr($fullPath, 0, strlen($root) + 1) === $root . '/') { + return true; + } + } + throw new AutoloadNotAllowedException($fullPath); + } + /** * Load the specified class * @@ -119,7 +151,7 @@ class Autoloader { $pathsToRequire = array(); foreach ($this->findClass($class) as $path) { $fullPath = stream_resolve_include_path($path); - if ($fullPath) { + if ($fullPath && $this->isValidPath($fullPath)) { $pathsToRequire[] = $fullPath; } } @@ -138,6 +170,7 @@ class Autoloader { /** * Sets the optional low-latency cache for class to path mapping. + * * @param \OC\Memcache\Cache $memoryCache Instance of memory cache. */ public function setMemoryCache(\OC\Memcache\Cache $memoryCache = null) { diff --git a/lib/base.php b/lib/base.php index aceac2e53c3..a4b5e9e01bf 100644 --- a/lib/base.php +++ b/lib/base.php @@ -115,9 +115,6 @@ class OC { * the app path list is empty or contains an invalid path */ public static function initPaths() { - // calculate the root directories - OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4)); - // ensure we can find OC_Config set_include_path( OC::$SERVERROOT . '/lib' . PATH_SEPARATOR . @@ -519,10 +516,20 @@ class OC { } public static function init() { + // calculate the root directories + OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4)); + // register autoloader $loaderStart = microtime(true); require_once __DIR__ . '/autoloader.php'; - self::$loader = new \OC\Autoloader(); + self::$loader = new \OC\Autoloader([ + OC::$SERVERROOT . '/lib', + OC::$SERVERROOT . '/core', + OC::$SERVERROOT . '/settings', + OC::$SERVERROOT . '/ocs', + OC::$SERVERROOT . '/ocs-provider', + OC::$SERVERROOT . '/3rdparty' + ]); spl_autoload_register(array(self::$loader, 'load')); $loaderEnd = microtime(true); @@ -533,7 +540,7 @@ class OC { // setup 3rdparty autoloader $vendorAutoLoad = OC::$THIRDPARTYROOT . '/3rdparty/autoload.php'; if (!file_exists($vendorAutoLoad)) { - throw new \RuntimeException('Composer autoloader not found, unable to continue. Check the folder "3rdparty".'); + throw new \RuntimeException('Composer autoloader not found, unable to continue. Check the folder "3rdparty". Running "git submodule update --init" will initialize the git submodule that handles the subfolder "3rdparty".'); } require_once $vendorAutoLoad; @@ -663,7 +670,7 @@ class OC { self::registerCacheHooks(); self::registerFilesystemHooks(); - if (\OC::$server->getSystemConfig()->getValue('enable_previews', true)) { + if ($systemConfig->getValue('enable_previews', true)) { self::registerPreviewHooks(); } self::registerShareHooks(); diff --git a/lib/l10n/cs_CZ.js b/lib/l10n/cs_CZ.js index 8885ecd6e10..715b834d2bf 100644 --- a/lib/l10n/cs_CZ.js +++ b/lib/l10n/cs_CZ.js @@ -49,6 +49,7 @@ OC.L10N.register( "Can't read file" : "Nelze přečíst soubor", "App directory already exists" : "Adresář aplikace již existuje", "Can't create app folder. Please fix permissions. %s" : "Nelze vytvořit složku aplikace. Opravte práva souborů. %s", + "Archive does not contain a directory named %s" : "Archiv neobsahuje adresář pojmenovaný %s", "No source specified when installing app" : "Nebyl zadán zdroj při instalaci aplikace", "No href specified when installing app from http" : "Nebyl zadán odkaz pro instalaci aplikace z HTTP", "No path specified when installing app from local file" : "Nebyla zadána cesta pro instalaci aplikace z místního souboru", diff --git a/lib/l10n/cs_CZ.json b/lib/l10n/cs_CZ.json index c5f50a73848..891b30850ab 100644 --- a/lib/l10n/cs_CZ.json +++ b/lib/l10n/cs_CZ.json @@ -47,6 +47,7 @@ "Can't read file" : "Nelze přečíst soubor", "App directory already exists" : "Adresář aplikace již existuje", "Can't create app folder. Please fix permissions. %s" : "Nelze vytvořit složku aplikace. Opravte práva souborů. %s", + "Archive does not contain a directory named %s" : "Archiv neobsahuje adresář pojmenovaný %s", "No source specified when installing app" : "Nebyl zadán zdroj při instalaci aplikace", "No href specified when installing app from http" : "Nebyl zadán odkaz pro instalaci aplikace z HTTP", "No path specified when installing app from local file" : "Nebyla zadána cesta pro instalaci aplikace z místního souboru", diff --git a/lib/l10n/da.js b/lib/l10n/da.js index 42f367d21c2..d644d7d3426 100644 --- a/lib/l10n/da.js +++ b/lib/l10n/da.js @@ -91,6 +91,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s does not exist" : "Der skete en fejl ved deling af %s, brugeren %s eksistere ikke", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Der skete en fejl ved deling af %s, brugeren %s er ikke medlem af nogle grupper som %s er medlem af", "Sharing %s failed, because this item is already shared with %s" : "Der skete en fejl ved deling af %s, objektet er allerede delt med %s", + "Sharing %s failed, because this item is already shared with user %s" : "Deling af %s mislykkedes, fordi dette element allerede er delt med brugeren %s", "Sharing %s failed, because the group %s does not exist" : "Der skete en fejl ved deling af %s, gruppen %s eksistere ikke", "Sharing %s failed, because %s is not a member of the group %s" : "Der skete en fejl ved deling af %s, fordi %s ikke er medlem af gruppen %s", "You need to provide a password to create a public link, only protected links are allowed" : "Du skal angive et kodeord for at oprette et offentligt link - kun beskyttede links er tilladt", diff --git a/lib/l10n/da.json b/lib/l10n/da.json index 0e20adc31bf..d57ea2a92ae 100644 --- a/lib/l10n/da.json +++ b/lib/l10n/da.json @@ -89,6 +89,7 @@ "Sharing %s failed, because the user %s does not exist" : "Der skete en fejl ved deling af %s, brugeren %s eksistere ikke", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Der skete en fejl ved deling af %s, brugeren %s er ikke medlem af nogle grupper som %s er medlem af", "Sharing %s failed, because this item is already shared with %s" : "Der skete en fejl ved deling af %s, objektet er allerede delt med %s", + "Sharing %s failed, because this item is already shared with user %s" : "Deling af %s mislykkedes, fordi dette element allerede er delt med brugeren %s", "Sharing %s failed, because the group %s does not exist" : "Der skete en fejl ved deling af %s, gruppen %s eksistere ikke", "Sharing %s failed, because %s is not a member of the group %s" : "Der skete en fejl ved deling af %s, fordi %s ikke er medlem af gruppen %s", "You need to provide a password to create a public link, only protected links are allowed" : "Du skal angive et kodeord for at oprette et offentligt link - kun beskyttede links er tilladt", diff --git a/lib/l10n/el.js b/lib/l10n/el.js index b47cc7e36d2..ee9ad8efd42 100644 --- a/lib/l10n/el.js +++ b/lib/l10n/el.js @@ -88,6 +88,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s does not exist" : "Ο διαμοιρασμός του %s απέτυχε, γιατί ο χρήστης %s δεν υπάρχει", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Ο διαμοιρασμός του %s απέτυχε, γιατί ο χρήστης %s δεν είναι μέλος καμίας ομάδας στην οποία ο χρήστης %s είναι μέλος", "Sharing %s failed, because this item is already shared with %s" : "Ο διαμοιρασμός του %s απέτυχε, γιατί το αντικείμενο είναι διαμοιρασμένο ήδη με τον χρήστη %s", + "Sharing %s failed, because this item is already shared with user %s" : "Αποτυχία διαμοιρασμού με %s, διότι αυτό το αντικείμενο διαμοιράζεται ήδη με τον χρήστη %s", "Sharing %s failed, because the group %s does not exist" : "Ο διαμοιρασμός του %s απέτυχε, γιατί η ομάδα χρηστών %s δεν υπάρχει", "Sharing %s failed, because %s is not a member of the group %s" : "Ο διαμοιρασμός του %s απέτυχε, γιατί ο χρήστης %s δεν είναι μέλος της ομάδας %s", "You need to provide a password to create a public link, only protected links are allowed" : "Πρέπει να εισάγετε έναν κωδικό για να δημιουργήσετε έναν δημόσιο σύνδεσμο. Μόνο προστατευμένοι σύνδεσμοι επιτρέπονται", diff --git a/lib/l10n/el.json b/lib/l10n/el.json index d82aec00129..d0235598f7e 100644 --- a/lib/l10n/el.json +++ b/lib/l10n/el.json @@ -86,6 +86,7 @@ "Sharing %s failed, because the user %s does not exist" : "Ο διαμοιρασμός του %s απέτυχε, γιατί ο χρήστης %s δεν υπάρχει", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Ο διαμοιρασμός του %s απέτυχε, γιατί ο χρήστης %s δεν είναι μέλος καμίας ομάδας στην οποία ο χρήστης %s είναι μέλος", "Sharing %s failed, because this item is already shared with %s" : "Ο διαμοιρασμός του %s απέτυχε, γιατί το αντικείμενο είναι διαμοιρασμένο ήδη με τον χρήστη %s", + "Sharing %s failed, because this item is already shared with user %s" : "Αποτυχία διαμοιρασμού με %s, διότι αυτό το αντικείμενο διαμοιράζεται ήδη με τον χρήστη %s", "Sharing %s failed, because the group %s does not exist" : "Ο διαμοιρασμός του %s απέτυχε, γιατί η ομάδα χρηστών %s δεν υπάρχει", "Sharing %s failed, because %s is not a member of the group %s" : "Ο διαμοιρασμός του %s απέτυχε, γιατί ο χρήστης %s δεν είναι μέλος της ομάδας %s", "You need to provide a password to create a public link, only protected links are allowed" : "Πρέπει να εισάγετε έναν κωδικό για να δημιουργήσετε έναν δημόσιο σύνδεσμο. Μόνο προστατευμένοι σύνδεσμοι επιτρέπονται", diff --git a/lib/l10n/es.js b/lib/l10n/es.js index e08ed66f1b5..3f1d751fc1e 100644 --- a/lib/l10n/es.js +++ b/lib/l10n/es.js @@ -91,6 +91,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s does not exist" : "Se ha fallado al compartir %s, ya que el usuario %s no existe", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Se ha fallado al compartir %s, ya que el usuario %s no es miembro de ningún grupo del que %s sea miembro", "Sharing %s failed, because this item is already shared with %s" : "Se falló al compartir %s, ya que este elemento ya está compartido con %s", + "Sharing %s failed, because this item is already shared with user %s" : "Compartiendo %s falló, porque este objeto ya se comparte con el usuario %s", "Sharing %s failed, because the group %s does not exist" : "Se falló al compartir %s, ya que el grupo %s no existe", "Sharing %s failed, because %s is not a member of the group %s" : "Se falló al compartir %s, ya que %s no es miembro del grupo %s", "You need to provide a password to create a public link, only protected links are allowed" : "Es necesario definir una contraseña para crear un enlace publico. Solo los enlaces protegidos están permitidos", diff --git a/lib/l10n/es.json b/lib/l10n/es.json index f9bca103231..75b8060b819 100644 --- a/lib/l10n/es.json +++ b/lib/l10n/es.json @@ -89,6 +89,7 @@ "Sharing %s failed, because the user %s does not exist" : "Se ha fallado al compartir %s, ya que el usuario %s no existe", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Se ha fallado al compartir %s, ya que el usuario %s no es miembro de ningún grupo del que %s sea miembro", "Sharing %s failed, because this item is already shared with %s" : "Se falló al compartir %s, ya que este elemento ya está compartido con %s", + "Sharing %s failed, because this item is already shared with user %s" : "Compartiendo %s falló, porque este objeto ya se comparte con el usuario %s", "Sharing %s failed, because the group %s does not exist" : "Se falló al compartir %s, ya que el grupo %s no existe", "Sharing %s failed, because %s is not a member of the group %s" : "Se falló al compartir %s, ya que %s no es miembro del grupo %s", "You need to provide a password to create a public link, only protected links are allowed" : "Es necesario definir una contraseña para crear un enlace publico. Solo los enlaces protegidos están permitidos", diff --git a/lib/l10n/fi_FI.js b/lib/l10n/fi_FI.js index d82d26645db..6960162e0ab 100644 --- a/lib/l10n/fi_FI.js +++ b/lib/l10n/fi_FI.js @@ -82,6 +82,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s is the item owner" : "Kohteen %s jakaminen epäonnistui, koska käyttäjä %s on kohteen omistaja", "Sharing %s failed, because the user %s does not exist" : "Kohteen %s jakaminen epäonnistui, koska käyttäjää %s ei ole olemassa", "Sharing %s failed, because this item is already shared with %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", + "Sharing %s failed, because this item is already shared with user %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", "Sharing %s failed, because the group %s does not exist" : "Kohteen %s jakaminen epäonnistui, koska ryhmää %s ei ole olemassa", "Sharing %s failed, because %s is not a member of the group %s" : "Kohteen %s jakaminen epäonnistui, koska käyttäjä %s ei ole ryhmän %s jäsen", "You need to provide a password to create a public link, only protected links are allowed" : "Anna salasana luodaksesi julkisen linkin. Vain suojatut linkit ovat sallittuja", diff --git a/lib/l10n/fi_FI.json b/lib/l10n/fi_FI.json index de6d474e467..7d23189b358 100644 --- a/lib/l10n/fi_FI.json +++ b/lib/l10n/fi_FI.json @@ -80,6 +80,7 @@ "Sharing %s failed, because the user %s is the item owner" : "Kohteen %s jakaminen epäonnistui, koska käyttäjä %s on kohteen omistaja", "Sharing %s failed, because the user %s does not exist" : "Kohteen %s jakaminen epäonnistui, koska käyttäjää %s ei ole olemassa", "Sharing %s failed, because this item is already shared with %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", + "Sharing %s failed, because this item is already shared with user %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", "Sharing %s failed, because the group %s does not exist" : "Kohteen %s jakaminen epäonnistui, koska ryhmää %s ei ole olemassa", "Sharing %s failed, because %s is not a member of the group %s" : "Kohteen %s jakaminen epäonnistui, koska käyttäjä %s ei ole ryhmän %s jäsen", "You need to provide a password to create a public link, only protected links are allowed" : "Anna salasana luodaksesi julkisen linkin. Vain suojatut linkit ovat sallittuja", diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js index 873abd44ad0..d0abd693e0c 100644 --- a/lib/l10n/fr.js +++ b/lib/l10n/fr.js @@ -90,6 +90,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s does not exist" : "Le partage de %s a échoué car l'utilisateur %s n'existe pas", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Le partage de %s a échoué car l'utilisateur %s n'est membre d'aucun groupe auquel %s appartient", "Sharing %s failed, because this item is already shared with %s" : "Le partage de %s a échoué car cet objet est déjà partagé avec %s", + "Sharing %s failed, because this item is already shared with user %s" : "Le partage de %s a échoué car cet élément est déjà partagé avec l'utilisateur %s", "Sharing %s failed, because the group %s does not exist" : "Le partage de %s a échoué car le groupe %s n'existe pas", "Sharing %s failed, because %s is not a member of the group %s" : "Le partage de %s a échoué car %s n'est pas membre du groupe %s", "You need to provide a password to create a public link, only protected links are allowed" : "Vous devez fournir un mot de passe pour créer un lien public, seuls les liens protégés sont autorisées.", diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json index 440f2ddd84d..d0a90797df9 100644 --- a/lib/l10n/fr.json +++ b/lib/l10n/fr.json @@ -88,6 +88,7 @@ "Sharing %s failed, because the user %s does not exist" : "Le partage de %s a échoué car l'utilisateur %s n'existe pas", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Le partage de %s a échoué car l'utilisateur %s n'est membre d'aucun groupe auquel %s appartient", "Sharing %s failed, because this item is already shared with %s" : "Le partage de %s a échoué car cet objet est déjà partagé avec %s", + "Sharing %s failed, because this item is already shared with user %s" : "Le partage de %s a échoué car cet élément est déjà partagé avec l'utilisateur %s", "Sharing %s failed, because the group %s does not exist" : "Le partage de %s a échoué car le groupe %s n'existe pas", "Sharing %s failed, because %s is not a member of the group %s" : "Le partage de %s a échoué car %s n'est pas membre du groupe %s", "You need to provide a password to create a public link, only protected links are allowed" : "Vous devez fournir un mot de passe pour créer un lien public, seuls les liens protégés sont autorisées.", diff --git a/lib/l10n/id.js b/lib/l10n/id.js index 432ea5c0192..2114b34eddd 100644 --- a/lib/l10n/id.js +++ b/lib/l10n/id.js @@ -49,6 +49,7 @@ OC.L10N.register( "Can't read file" : "Tidak dapat membaca berkas", "App directory already exists" : "Direktori Apl sudah ada", "Can't create app folder. Please fix permissions. %s" : "Tidak dapat membuat folder apl. Silakan perbaiki perizinan. %s", + "Archive does not contain a directory named %s" : "Arsip tidak berisi direktori yang bernama %s", "No source specified when installing app" : "Tidak ada sumber yang ditentukan saat menginstal apl", "No href specified when installing app from http" : "Href tidak ditentukan saat menginstal apl dari http", "No path specified when installing app from local file" : "Lokasi tidak ditentukan saat menginstal apl dari berkas lokal", diff --git a/lib/l10n/id.json b/lib/l10n/id.json index 6aeffa363da..cdc17b6ce8e 100644 --- a/lib/l10n/id.json +++ b/lib/l10n/id.json @@ -47,6 +47,7 @@ "Can't read file" : "Tidak dapat membaca berkas", "App directory already exists" : "Direktori Apl sudah ada", "Can't create app folder. Please fix permissions. %s" : "Tidak dapat membuat folder apl. Silakan perbaiki perizinan. %s", + "Archive does not contain a directory named %s" : "Arsip tidak berisi direktori yang bernama %s", "No source specified when installing app" : "Tidak ada sumber yang ditentukan saat menginstal apl", "No href specified when installing app from http" : "Href tidak ditentukan saat menginstal apl dari http", "No path specified when installing app from local file" : "Lokasi tidak ditentukan saat menginstal apl dari berkas lokal", diff --git a/lib/l10n/it.js b/lib/l10n/it.js index d0c0022fd06..d0cf725013b 100644 --- a/lib/l10n/it.js +++ b/lib/l10n/it.js @@ -91,6 +91,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s does not exist" : "Condivisione di %s non riuscita, poiché l'utente %s non esiste", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Condivisione di %s non riuscita, poiché l'utente %s non appartiene ad alcun gruppo di cui %s è membro", "Sharing %s failed, because this item is already shared with %s" : "Condivisione di %s non riuscita, poiché l'oggetto è già condiviso con %s", + "Sharing %s failed, because this item is already shared with user %s" : "Condivisione di %s non riuscita, poiché l'oggetto è già condiviso con l'utente %s", "Sharing %s failed, because the group %s does not exist" : "Condivisione di %s non riuscita, poiché il gruppo %s non esiste", "Sharing %s failed, because %s is not a member of the group %s" : "Condivisione di %s non riuscita, poiché %s non appartiene al gruppo %s", "You need to provide a password to create a public link, only protected links are allowed" : "Devi fornire una password per creare un collegamento pubblico, sono consentiti solo i collegamenti protetti", diff --git a/lib/l10n/it.json b/lib/l10n/it.json index 1183b588eb2..81038c0e425 100644 --- a/lib/l10n/it.json +++ b/lib/l10n/it.json @@ -89,6 +89,7 @@ "Sharing %s failed, because the user %s does not exist" : "Condivisione di %s non riuscita, poiché l'utente %s non esiste", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Condivisione di %s non riuscita, poiché l'utente %s non appartiene ad alcun gruppo di cui %s è membro", "Sharing %s failed, because this item is already shared with %s" : "Condivisione di %s non riuscita, poiché l'oggetto è già condiviso con %s", + "Sharing %s failed, because this item is already shared with user %s" : "Condivisione di %s non riuscita, poiché l'oggetto è già condiviso con l'utente %s", "Sharing %s failed, because the group %s does not exist" : "Condivisione di %s non riuscita, poiché il gruppo %s non esiste", "Sharing %s failed, because %s is not a member of the group %s" : "Condivisione di %s non riuscita, poiché %s non appartiene al gruppo %s", "You need to provide a password to create a public link, only protected links are allowed" : "Devi fornire una password per creare un collegamento pubblico, sono consentiti solo i collegamenti protetti", diff --git a/lib/l10n/nl.js b/lib/l10n/nl.js index d08e8294dfb..5abae786d34 100644 --- a/lib/l10n/nl.js +++ b/lib/l10n/nl.js @@ -91,6 +91,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s does not exist" : "Delen van %s is mislukt, omdat gebruiker %s niet bestaat", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Delen van %s is mislukt, omdat gebruiker %s geen lid is van een groep waar %s lid van is", "Sharing %s failed, because this item is already shared with %s" : "Delen van %s is mislukt, omdat het object al wordt gedeeld met %s", + "Sharing %s failed, because this item is already shared with user %s" : "Delen van %s is mislukt, omdat het object al wordt gedeeld met gebruiker %s", "Sharing %s failed, because the group %s does not exist" : "Delen van %s is mislukt, omdat groep %s niet bestaat", "Sharing %s failed, because %s is not a member of the group %s" : "Delen van %s is mislukt, omdat %s geen lid is van groep %s", "You need to provide a password to create a public link, only protected links are allowed" : "U moet een wachtwoord verstrekken om een openbare koppeling te maken, alleen beschermde links zijn toegestaan", diff --git a/lib/l10n/nl.json b/lib/l10n/nl.json index 8d0b5dc7169..4e4eaf8b52a 100644 --- a/lib/l10n/nl.json +++ b/lib/l10n/nl.json @@ -89,6 +89,7 @@ "Sharing %s failed, because the user %s does not exist" : "Delen van %s is mislukt, omdat gebruiker %s niet bestaat", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Delen van %s is mislukt, omdat gebruiker %s geen lid is van een groep waar %s lid van is", "Sharing %s failed, because this item is already shared with %s" : "Delen van %s is mislukt, omdat het object al wordt gedeeld met %s", + "Sharing %s failed, because this item is already shared with user %s" : "Delen van %s is mislukt, omdat het object al wordt gedeeld met gebruiker %s", "Sharing %s failed, because the group %s does not exist" : "Delen van %s is mislukt, omdat groep %s niet bestaat", "Sharing %s failed, because %s is not a member of the group %s" : "Delen van %s is mislukt, omdat %s geen lid is van groep %s", "You need to provide a password to create a public link, only protected links are allowed" : "U moet een wachtwoord verstrekken om een openbare koppeling te maken, alleen beschermde links zijn toegestaan", diff --git a/lib/l10n/pt_BR.js b/lib/l10n/pt_BR.js index a53e5f01a16..402a7cbc51a 100644 --- a/lib/l10n/pt_BR.js +++ b/lib/l10n/pt_BR.js @@ -91,6 +91,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s does not exist" : "Compartilhamento %s falhou, porque o usuário %s não existe", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Compartilhamento %s falhou, porque o usuário %s não é membro de nenhum grupo que o usuário %s pertença", "Sharing %s failed, because this item is already shared with %s" : "Compartilhamento %s falhou, porque este ítem já está compartilhado com %s", + "Sharing %s failed, because this item is already shared with user %s" : "Compartilhamento de %s falhou, porque esse item já é compartilhada com o usuário %s", "Sharing %s failed, because the group %s does not exist" : "Compartilhamento %s falhou, porque o grupo %s não existe", "Sharing %s failed, because %s is not a member of the group %s" : "Compartilhamento %s falhou, porque %s não é membro do grupo %s", "You need to provide a password to create a public link, only protected links are allowed" : "Você precisa fornecer uma senha para criar um link público, apenas links protegidos são permitidos", diff --git a/lib/l10n/pt_BR.json b/lib/l10n/pt_BR.json index cef167c2098..255272b8cb8 100644 --- a/lib/l10n/pt_BR.json +++ b/lib/l10n/pt_BR.json @@ -89,6 +89,7 @@ "Sharing %s failed, because the user %s does not exist" : "Compartilhamento %s falhou, porque o usuário %s não existe", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Compartilhamento %s falhou, porque o usuário %s não é membro de nenhum grupo que o usuário %s pertença", "Sharing %s failed, because this item is already shared with %s" : "Compartilhamento %s falhou, porque este ítem já está compartilhado com %s", + "Sharing %s failed, because this item is already shared with user %s" : "Compartilhamento de %s falhou, porque esse item já é compartilhada com o usuário %s", "Sharing %s failed, because the group %s does not exist" : "Compartilhamento %s falhou, porque o grupo %s não existe", "Sharing %s failed, because %s is not a member of the group %s" : "Compartilhamento %s falhou, porque %s não é membro do grupo %s", "You need to provide a password to create a public link, only protected links are allowed" : "Você precisa fornecer uma senha para criar um link público, apenas links protegidos são permitidos", diff --git a/lib/l10n/th_TH.js b/lib/l10n/th_TH.js index 2ff86f599e9..6092f348cb5 100644 --- a/lib/l10n/th_TH.js +++ b/lib/l10n/th_TH.js @@ -91,6 +91,7 @@ OC.L10N.register( "Sharing %s failed, because the user %s does not exist" : "การแชร์ %s ล้มเหลวเนื่องจากไม่ได้มีผู้ใช้ %s อยู่", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "การแชร์ %s ล้มเหลวเนื่องจากผู้ใช้ %s ไม่ได้เป็นสมาชิกของกลุ่มใดๆ %s เป็นสมาชิกของ", "Sharing %s failed, because this item is already shared with %s" : "การแชร์ %s ล้มเหลวเพราะรายการนี้ถูกแชร์กับ %s", + "Sharing %s failed, because this item is already shared with user %s" : "%s ที่กำลังแชร์ล้มเหลว เพราะรายการนี้ได้ถูกแชร์กับผู้ใช้ %s", "Sharing %s failed, because the group %s does not exist" : "การแชร์ %s ล้มเหลวเพราะไม่มีกลุ่ม %s อยู่", "Sharing %s failed, because %s is not a member of the group %s" : "การแชร์ %s ล้มเหลวเพราะ %s ไม่ได้เป็นสมาชิกของกลุ่ม %s", "You need to provide a password to create a public link, only protected links are allowed" : "คุณจำเป็นต้องระบุรหัสผ่านเพื่อสร้างลิงค์สาธารณะ, ลิงค์ที่มีการป้องกันเท่านั้นที่ได้รับอนุญาต", diff --git a/lib/l10n/th_TH.json b/lib/l10n/th_TH.json index a215b67a180..a872236a70d 100644 --- a/lib/l10n/th_TH.json +++ b/lib/l10n/th_TH.json @@ -89,6 +89,7 @@ "Sharing %s failed, because the user %s does not exist" : "การแชร์ %s ล้มเหลวเนื่องจากไม่ได้มีผู้ใช้ %s อยู่", "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "การแชร์ %s ล้มเหลวเนื่องจากผู้ใช้ %s ไม่ได้เป็นสมาชิกของกลุ่มใดๆ %s เป็นสมาชิกของ", "Sharing %s failed, because this item is already shared with %s" : "การแชร์ %s ล้มเหลวเพราะรายการนี้ถูกแชร์กับ %s", + "Sharing %s failed, because this item is already shared with user %s" : "%s ที่กำลังแชร์ล้มเหลว เพราะรายการนี้ได้ถูกแชร์กับผู้ใช้ %s", "Sharing %s failed, because the group %s does not exist" : "การแชร์ %s ล้มเหลวเพราะไม่มีกลุ่ม %s อยู่", "Sharing %s failed, because %s is not a member of the group %s" : "การแชร์ %s ล้มเหลวเพราะ %s ไม่ได้เป็นสมาชิกของกลุ่ม %s", "You need to provide a password to create a public link, only protected links are allowed" : "คุณจำเป็นต้องระบุรหัสผ่านเพื่อสร้างลิงค์สาธารณะ, ลิงค์ที่มีการป้องกันเท่านั้นที่ได้รับอนุญาต", diff --git a/lib/private/activitymanager.php b/lib/private/activitymanager.php index a973db7206f..fc250173536 100644 --- a/lib/private/activitymanager.php +++ b/lib/private/activitymanager.php @@ -244,15 +244,27 @@ class ActivityManager implements IManager { * @return array */ public function getNotificationTypes($languageCode) { + $filesNotificationTypes = []; + $sharingNotificationTypes = []; + $notificationTypes = array(); foreach ($this->getExtensions() as $c) { $result = $c->getNotificationTypes($languageCode); if (is_array($result)) { + if (class_exists('\OCA\Files\Activity') && $c instanceof \OCA\Files\Activity) { + $filesNotificationTypes = $result; + continue; + } + if (class_exists('\OCA\Files_Sharing\Activity') && $c instanceof \OCA\Files_Sharing\Activity) { + $sharingNotificationTypes = $result; + continue; + } + $notificationTypes = array_merge($notificationTypes, $result); } } - return $notificationTypes; + return array_merge($filesNotificationTypes, $sharingNotificationTypes, $notificationTypes); } /** diff --git a/lib/private/app.php b/lib/private/app.php index f1a1d27ae66..f6a81f9945f 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -105,7 +105,6 @@ class OC_App { ob_start(); foreach ($apps as $app) { if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) { - self::$loadedApps[] = $app; self::loadApp($app); } } @@ -122,6 +121,8 @@ class OC_App { * @throws \OC\NeedsUpdateException */ public static function loadApp($app, $checkUpgrade = true) { + self::$loadedApps[] = $app; + \OC::$loader->addValidRoot(self::getAppPath($app)); if (is_file(self::getAppPath($app) . '/appinfo/app.php')) { \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app); if ($checkUpgrade and self::shouldUpgrade($app)) { diff --git a/lib/private/appconfig.php b/lib/private/appconfig.php index b88df10dddd..7ee64980fd0 100644 --- a/lib/private/appconfig.php +++ b/lib/private/appconfig.php @@ -28,23 +28,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/> * */ -/* - * - * The following SQL statement is just a help for developers and will not be - * executed! - * - * CREATE TABLE `appconfig` ( - * `appid` VARCHAR( 255 ) NOT NULL , - * `configkey` VARCHAR( 255 ) NOT NULL , - * `configvalue` VARCHAR( 255 ) NOT NULL - * ) - * - */ namespace OC; -use OC\DB\Connection; use OCP\IAppConfig; +use OCP\IDBConnection; /** * This class provides an easy way for apps to store config values in the @@ -52,54 +40,32 @@ use OCP\IAppConfig; */ class AppConfig implements IAppConfig { /** - * @var \OC\DB\Connection $conn + * @var \OCP\IDBConnection $conn */ protected $conn; private $cache = array(); - private $appsLoaded = array(); - - /** - * @var string[] - */ - private $apps = null; - /** - * @param Connection $conn + * @param IDBConnection $conn */ - public function __construct(Connection $conn) { + public function __construct(IDBConnection $conn) { $this->conn = $conn; + $this->configLoaded = false; } /** * @param string $app - * @return string[] - */ - private function getAppCache($app) { - if (!isset($this->cache[$app])) { - $this->cache[$app] = array(); - } - return $this->cache[$app]; - } - - /** - * @param string $app - * @return \string[] + * @return array */ private function getAppValues($app) { - $appCache = $this->getAppCache($app); - if (array_search($app, $this->appsLoaded) === false) { - $query = 'SELECT `configvalue`, `configkey` FROM `*PREFIX*appconfig`' - . ' WHERE `appid` = ?'; - $result = $this->conn->executeQuery($query, array($app)); - while ($row = $result->fetch()) { - $appCache[$row['configkey']] = $row['configvalue']; - } - $this->appsLoaded[] = $app; + $this->loadConfigValues(); + + if (isset($this->cache[$app])) { + return $this->cache[$app]; } - $this->cache[$app] = $appCache; - return $appCache; + + return []; } /** @@ -111,18 +77,9 @@ class AppConfig implements IAppConfig { * entry in the appconfig table. */ public function getApps() { - if (is_array($this->apps)) { - return $this->apps; - } - $query = 'SELECT DISTINCT `appid` FROM `*PREFIX*appconfig` ORDER BY `appid`'; - $result = $this->conn->executeQuery($query); + $this->loadConfigValues(); - $apps = array(); - while ($appid = $result->fetchColumn()) { - $apps[] = $appid; - } - $this->apps = $apps; - return $apps; + return $this->getSortedKeys($this->cache); } /** @@ -135,8 +92,17 @@ class AppConfig implements IAppConfig { * not returned. */ public function getKeys($app) { - $values = $this->getAppValues($app); - $keys = array_keys($values); + $this->loadConfigValues(); + + if (isset($this->cache[$app])) { + return $this->getSortedKeys($this->cache[$app]); + } + + return []; + } + + public function getSortedKeys($data) { + $keys = array_keys($data); sort($keys); return $keys; } @@ -153,12 +119,13 @@ class AppConfig implements IAppConfig { * not exist the default value will be returned */ public function getValue($app, $key, $default = null) { - $values = $this->getAppValues($app); - if (isset($values[$key])) { - return $values[$key]; - } else { - return $default; + $this->loadConfigValues(); + + if ($this->hasKey($app, $key)) { + return $this->cache[$app][$key]; } + + return $default; } /** @@ -169,8 +136,9 @@ class AppConfig implements IAppConfig { * @return bool */ public function hasKey($app, $key) { - $values = $this->getAppValues($app); - return array_key_exists($key, $values); + $this->loadConfigValues(); + + return isset($this->cache[$app][$key]); } /** @@ -179,11 +147,9 @@ class AppConfig implements IAppConfig { * @param string $app app * @param string $key key * @param string $value value - * @return void + * @return bool True if the value was inserted or updated, false if the value was the same */ public function setValue($app, $key, $value) { - $inserted = false; - // Does the key exist? no: insert, yes: update. if (!$this->hasKey($app, $key)) { $inserted = (bool) $this->conn->insertIfNotExist('*PREFIX*appconfig', [ 'appid' => $app, @@ -193,29 +159,32 @@ class AppConfig implements IAppConfig { 'appid', 'configkey', ]); - } - if (!$inserted) { - $oldValue = $this->getValue($app, $key); - if($oldValue === strval($value)) { - return; + if ($inserted) { + if (!isset($this->cache[$app])) { + $this->cache[$app] = []; + } + + $this->cache[$app][$key] = $value; + return true; } - $data = array( - 'configvalue' => $value, - ); - $where = array( - 'appid' => $app, - 'configkey' => $key, - ); - $this->conn->update('*PREFIX*appconfig', $data, $where); - } - if (!isset($this->cache[$app])) { - $this->cache[$app] = array(); - } - if (is_array($this->apps) and array_search($app, $this->apps) === false) { - $this->apps[$app] = $app; } + + $sql = $this->conn->getQueryBuilder(); + $sql->update('appconfig') + ->set('configvalue', $sql->createParameter('configvalue')) + ->where($sql->expr()->eq('appid', $sql->createParameter('app'))) + ->andWhere($sql->expr()->eq('configkey', $sql->createParameter('configkey'))) + ->andWhere($sql->expr()->neq('configvalue', $sql->createParameter('configvalue'))) + ->setParameter('configvalue', $value) + ->setParameter('app', $app) + ->setParameter('configkey', $key) + ->setParameter('configvalue', $value); + $changedRow = (bool) $sql->execute(); + $this->cache[$app][$key] = $value; + + return $changedRow; } /** @@ -226,14 +195,17 @@ class AppConfig implements IAppConfig { * @return boolean|null */ public function deleteKey($app, $key) { - $where = array( - 'appid' => $app, - 'configkey' => $key, - ); - $this->conn->delete('*PREFIX*appconfig', $where); - if (isset($this->cache[$app]) and isset($this->cache[$app][$key])) { - unset($this->cache[$app][$key]); - } + $this->loadConfigValues(); + + $sql = $this->conn->getQueryBuilder(); + $sql->delete('appconfig') + ->where($sql->expr()->eq('appid', $sql->createParameter('app'))) + ->andWhere($sql->expr()->eq('configkey', $sql->createParameter('configkey'))) + ->setParameter('app', $app) + ->setParameter('configkey', $key); + $sql->execute(); + + unset($this->cache[$app][$key]); } /** @@ -245,38 +217,65 @@ class AppConfig implements IAppConfig { * Removes all keys in appconfig belonging to the app. */ public function deleteApp($app) { - $where = array( - 'appid' => $app, - ); - $this->conn->delete('*PREFIX*appconfig', $where); + $this->loadConfigValues(); + + $sql = $this->conn->getQueryBuilder(); + $sql->delete('appconfig') + ->where($sql->expr()->eq('appid', $sql->createParameter('app'))) + ->setParameter('app', $app); + $sql->execute(); + unset($this->cache[$app]); - unset($this->apps[$app]); } /** - * get multiply values, either the app or key can be used as wildcard by setting it to false + * get multiple values, either the app or key can be used as wildcard by setting it to false * * @param string|false $app * @param string|false $key * @return array|false */ public function getValues($app, $key) { - if (($app !== false) == ($key !== false)) { + if (($app !== false) === ($key !== false)) { return false; } - if ($app !== false) { + if ($key === false) { return $this->getAppValues($app); } else { - $query = 'SELECT `configvalue`, `appid` FROM `*PREFIX*appconfig` WHERE `configkey` = ?'; - $result = $this->conn->executeQuery($query, array($key)); + $configs = []; + foreach ($this->getApps() as $appId) { + if ($this->hasKey($appId, $key)) { + $configs[$appId] = $this->getValue($appId, $key); + } + } + + return $configs; + } + } - $values = array(); - while ($row = $result->fetch((\PDO::FETCH_ASSOC))) { - $values[$row['appid']] = $row['configvalue']; + /** + * Load all the app config values + */ + protected function loadConfigValues() { + if ($this->configLoaded) return; + + $this->cache = []; + + $sql = $this->conn->getQueryBuilder(); + $sql->select('*') + ->from('appconfig'); + $result = $sql->execute(); + + while ($row = $result->fetch()) { + if (!isset($this->cache[$row['appid']])) { + $this->cache[$row['appid']] = []; } - return $values; + $this->cache[$row['appid']][$row['configkey']] = $row['configvalue']; } + $result->closeCursor(); + + $this->configLoaded = true; } } diff --git a/lib/private/appframework/http.php b/lib/private/appframework/http.php index e7b0d1e2cab..dee9818f4bc 100644 --- a/lib/private/appframework/http.php +++ b/lib/private/appframework/http.php @@ -121,7 +121,7 @@ class Http extends BaseHttp { // if etag or lastmodified have not changed, return a not modified if ((isset($this->server['HTTP_IF_NONE_MATCH']) - && trim($this->server['HTTP_IF_NONE_MATCH']) === $ETag) + && trim(trim($this->server['HTTP_IF_NONE_MATCH']), '"') === (string)$ETag) || diff --git a/lib/private/appframework/http/request.php b/lib/private/appframework/http/request.php index a2109439177..b430673f9a9 100644 --- a/lib/private/appframework/http/request.php +++ b/lib/private/appframework/http/request.php @@ -9,6 +9,7 @@ * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Thomas Tanghus <thomas@tanghus.net> * @author Vincent Petry <pvince81@owncloud.com> + * @author Robin McCorkell <rmccorkell@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 @@ -71,6 +72,9 @@ class Request implements \ArrayAccess, \Countable, IRequest { /** @var ICrypto */ protected $crypto; + /** @var bool */ + protected $contentDecoded = false; + /** * @param array $vars An associative array with the following optional values: * - array 'urlParams' the parameters which were matched from the URL @@ -109,27 +113,6 @@ class Request implements \ArrayAccess, \Countable, IRequest { : array(); } - // 'application/json' must be decoded manually. - if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) { - $params = json_decode(file_get_contents($this->inputStream), true); - if(count($params) > 0) { - $this->items['params'] = $params; - if($vars['method'] === 'POST') { - $this->items['post'] = $params; - } - } - // Handle application/x-www-form-urlencoded for methods other than GET - // or post correctly - } elseif($vars['method'] !== 'GET' - && $vars['method'] !== 'POST' - && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) { - - parse_str(file_get_contents($this->inputStream), $params); - if(is_array($params)) { - $this->items['params'] = $params; - } - } - $this->items['parameters'] = array_merge( $this->items['get'], $this->items['post'], @@ -237,24 +220,19 @@ class Request implements \ArrayAccess, \Countable, IRequest { if($this->method !== strtoupper($name)) { throw new \LogicException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method)); } + return $this->getContent(); case 'files': case 'server': case 'env': case 'cookies': - case 'parameters': - case 'params': case 'urlParams': - if(in_array($name, array('put', 'patch'))) { - return $this->getContent(); - } else { - return isset($this->items[$name]) - ? $this->items[$name] - : null; - } - break; case 'method': - return $this->items['method']; - break; + return isset($this->items[$name]) + ? $this->items[$name] + : null; + case 'parameters': + case 'params': + return $this->getContent(); default; return isset($this[$name]) ? $this[$name] @@ -396,11 +374,48 @@ class Request implements \ArrayAccess, \Countable, IRequest { $this->content = false; return fopen($this->inputStream, 'rb'); } else { - return $this->parameters; + $this->decodeContent(); + return $this->items['parameters']; } } /** + * Attempt to decode the content and populate parameters + */ + protected function decodeContent() { + if ($this->contentDecoded) { + return; + } + $params = []; + + // 'application/json' must be decoded manually. + if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) { + $params = json_decode(file_get_contents($this->inputStream), true); + if(count($params) > 0) { + $this->items['params'] = $params; + if($this->method === 'POST') { + $this->items['post'] = $params; + } + } + + // Handle application/x-www-form-urlencoded for methods other than GET + // or post correctly + } elseif($this->method !== 'GET' + && $this->method !== 'POST' + && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) { + + parse_str(file_get_contents($this->inputStream), $params); + if(is_array($params)) { + $this->items['params'] = $params; + } + } + + $this->items['parameters'] = array_merge($this->items['parameters'], $params); + $this->contentDecoded = true; + } + + + /** * Checks if the CSRF check was correct * @return bool true if CSRF check passed * @see OC_Util::callRegister() diff --git a/lib/private/backgroundjob/joblist.php b/lib/private/backgroundjob/joblist.php index f297bccbc7d..deadadfb77e 100644 --- a/lib/private/backgroundjob/joblist.php +++ b/lib/private/backgroundjob/joblist.php @@ -26,6 +26,7 @@ namespace OC\BackgroundJob; use OCP\BackgroundJob\IJobList; +use OCP\AutoloadNotAllowedException; class JobList implements IJobList { /** @@ -185,15 +186,20 @@ class JobList implements IJobList { /** * @var Job $job */ - if (!class_exists($class)) { - // job from disabled app or old version of an app, no need to do anything - return null; + try { + if (!class_exists($class)) { + // job from disabled app or old version of an app, no need to do anything + return null; + } + $job = new $class(); + $job->setId($row['id']); + $job->setLastRun($row['last_run']); + $job->setArgument(json_decode($row['argument'], true)); + return $job; + } catch (AutoloadNotAllowedException $e) { + // job is from a disabled app, ignore } - $job = new $class(); - $job->setId($row['id']); - $job->setLastRun($row['last_run']); - $job->setArgument(json_decode($row['argument'], true)); - return $job; + return null; } /** diff --git a/lib/private/encryption/keys/storage.php b/lib/private/encryption/keys/storage.php index b754462d9b0..d0c094538b0 100644 --- a/lib/private/encryption/keys/storage.php +++ b/lib/private/encryption/keys/storage.php @@ -27,11 +27,13 @@ namespace OC\Encryption\Keys; use OC\Encryption\Util; use OC\Files\Filesystem; use OC\Files\View; -use OCP\Encryption\Exceptions\GenericEncryptionException; use OCP\Encryption\Keys\IStorage; class Storage implements IStorage { + // hidden file which indicate that the folder is a valid key storage + const KEY_STORAGE_MARKER = '.oc_key_storage'; + /** @var View */ private $view; @@ -42,6 +44,10 @@ class Storage implements IStorage { /** @var string */ private $keys_base_dir; + // root of the key storage default is empty which means that we use the data folder + /** @var string */ + private $root_dir; + /** @var string */ private $encryption_base_dir; @@ -58,6 +64,7 @@ class Storage implements IStorage { $this->encryption_base_dir = '/files_encryption'; $this->keys_base_dir = $this->encryption_base_dir .'/keys'; + $this->root_dir = $this->util->getKeyStorageRoot(); } /** @@ -162,13 +169,13 @@ class Storage implements IStorage { protected function constructUserKeyPath($encryptionModuleId, $keyId, $uid) { if ($uid === null) { - $path = $this->encryption_base_dir . '/' . $encryptionModuleId . '/' . $keyId; + $path = $this->root_dir . '/' . $this->encryption_base_dir . '/' . $encryptionModuleId . '/' . $keyId; } else { - $path = '/' . $uid . $this->encryption_base_dir . '/' + $path = $this->root_dir . '/' . $uid . $this->encryption_base_dir . '/' . $encryptionModuleId . '/' . $uid . '.' . $keyId; } - return $path; + return \OC\Files\Filesystem::normalizePath($path); } /** @@ -227,9 +234,9 @@ class Storage implements IStorage { // in case of system wide mount points the keys are stored directly in the data directory if ($this->util->isSystemWideMountPoint($filename, $owner)) { - $keyPath = $this->keys_base_dir . $filename . '/'; + $keyPath = $this->root_dir . '/' . $this->keys_base_dir . $filename . '/'; } else { - $keyPath = '/' . $owner . $this->keys_base_dir . $filename . '/'; + $keyPath = $this->root_dir . '/' . $owner . $this->keys_base_dir . $filename . '/'; } return Filesystem::normalizePath($keyPath . $encryptionModuleId . '/', false); @@ -290,12 +297,12 @@ class Storage implements IStorage { $systemWideMountPoint = $this->util->isSystemWideMountPoint($relativePath, $owner); if ($systemWideMountPoint) { - $systemPath = $this->keys_base_dir . $relativePath . '/'; + $systemPath = $this->root_dir . '/' . $this->keys_base_dir . $relativePath . '/'; } else { - $systemPath = '/' . $owner . $this->keys_base_dir . $relativePath . '/'; + $systemPath = $this->root_dir . '/' . $owner . $this->keys_base_dir . $relativePath . '/'; } - return $systemPath; + return Filesystem::normalizePath($systemPath, false); } /** diff --git a/lib/private/encryption/manager.php b/lib/private/encryption/manager.php index 1e0a065e25a..c004dfda0d9 100644 --- a/lib/private/encryption/manager.php +++ b/lib/private/encryption/manager.php @@ -25,14 +25,12 @@ namespace OC\Encryption; +use OC\Encryption\Keys\Storage; use OC\Files\Filesystem; -use OC\Files\Storage\Shared; -use OC\Files\Storage\Wrapper\Encryption; use OC\Files\View; -use OC\Search\Provider\File; +use OC\ServiceUnavailableException; use OCP\Encryption\IEncryptionModule; use OCP\Encryption\IManager; -use OCP\Files\Mount\IMountPoint; use OCP\IConfig; use OCP\IL10N; use OCP\ILogger; @@ -51,16 +49,26 @@ class Manager implements IManager { /** @var Il10n */ protected $l; + /** @var View */ + protected $rootView; + + /** @var Util */ + protected $util; + /** * @param IConfig $config * @param ILogger $logger * @param IL10N $l10n + * @param View $rootView + * @param Util $util */ - public function __construct(IConfig $config, ILogger $logger, IL10N $l10n) { + public function __construct(IConfig $config, ILogger $logger, IL10N $l10n, View $rootView, Util $util) { $this->encryptionModules = array(); $this->config = $config; $this->logger = $logger; $this->l = $l10n; + $this->rootView = $rootView; + $this->util = $util; } /** @@ -82,7 +90,8 @@ class Manager implements IManager { /** * check if new encryption is ready * - * @return boolean + * @return bool + * @throws ServiceUnavailableException */ public function isReady() { // check if we are still in transit between the old and the new encryption @@ -94,6 +103,11 @@ class Manager implements IManager { $this->logger->warning($warning); return false; } + + if ($this->isKeyStorageReady() === false) { + throw new ServiceUnavailableException('Key Storage is not ready'); + } + return true; } @@ -221,6 +235,31 @@ class Manager implements IManager { \OC::$server->getGroupManager(), \OC::$server->getConfig() ); - \OC\Files\Filesystem::addStorageWrapper('oc_encryption', array($util, 'wrapStorage'), 2); + Filesystem::addStorageWrapper('oc_encryption', array($util, 'wrapStorage'), 2); } + + + /** + * check if key storage is ready + * + * @return bool + */ + protected function isKeyStorageReady() { + + $rootDir = $this->util->getKeyStorageRoot(); + + // the default root is always valid + if ($rootDir === '') { + return true; + } + + // check if key storage is mounted correctly + if ($this->rootView->file_exists($rootDir . '/' . Storage::KEY_STORAGE_MARKER)) { + return true; + } + + return false; + } + + } diff --git a/lib/private/encryption/util.php b/lib/private/encryption/util.php index d0733941a35..90ae8259972 100644 --- a/lib/private/encryption/util.php +++ b/lib/private/encryption/util.php @@ -59,7 +59,7 @@ class Util { protected $blockSize = 8192; /** @var View */ - protected $view; + protected $rootView; /** @var array */ protected $ocHeaderKeys; @@ -78,13 +78,13 @@ class Util { /** * - * @param \OC\Files\View $view + * @param View $rootView * @param \OC\User\Manager $userManager * @param \OC\Group\Manager $groupManager * @param IConfig $config */ public function __construct( - \OC\Files\View $view, + View $rootView, \OC\User\Manager $userManager, \OC\Group\Manager $groupManager, IConfig $config) { @@ -93,7 +93,7 @@ class Util { self::HEADER_ENCRYPTION_MODULE_KEY ]; - $this->view = $view; + $this->rootView = $rootView; $this->userManager = $userManager; $this->groupManager = $groupManager; $this->config = $config; @@ -167,7 +167,7 @@ class Util { while ($dirList) { $dir = array_pop($dirList); - $content = $this->view->getDirectoryContent($dir); + $content = $this->rootView->getDirectoryContent($dir); foreach ($content as $c) { if ($c->getType() === 'dir') { @@ -332,10 +332,22 @@ class Util { * @return boolean */ public function isExcluded($path) { - $normalizedPath = \OC\Files\Filesystem::normalizePath($path); + $normalizedPath = Filesystem::normalizePath($path); $root = explode('/', $normalizedPath, 4); if (count($root) > 1) { + // detect alternative key storage root + $rootDir = $this->getKeyStorageRoot(); + if ($rootDir !== '' && + 0 === strpos( + Filesystem::normalizePath($path), + Filesystem::normalizePath($rootDir) + ) + ) { + return true; + } + + //detect system wide folders if (in_array($root[1], $this->excludedPaths)) { return true; @@ -364,6 +376,24 @@ class Util { } /** + * set new key storage root + * + * @param string $root new key store root relative to the data folder + */ + public function setKeyStorageRoot($root) { + $this->config->setAppValue('core', 'encryption_key_storage_root', $root); + } + + /** + * get key storage root + * + * @return string key storage root + */ + public function getKeyStorageRoot() { + return $this->config->getAppValue('core', 'encryption_key_storage_root', ''); + } + + /** * Wraps the given storage when it is not a shared storage * * @param string $mountPoint diff --git a/lib/private/files.php b/lib/private/files.php index 6268bf8a129..0172f1ca6af 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -86,15 +86,6 @@ class OC_Files { */ public static function get($dir, $files, $only_header = false) { $view = \OC\Files\Filesystem::getView(); - $xsendfile = false; - if (\OC::$server->getLockingProvider() instanceof NoopLockingProvider) { - if (isset($_SERVER['MOD_X_SENDFILE_ENABLED']) || - isset($_SERVER['MOD_X_SENDFILE2_ENABLED']) || - isset($_SERVER['MOD_X_ACCEL_REDIRECT_ENABLED']) - ) { - $xsendfile = true; - } - } if (is_array($files) && count($files) === 1) { $files = $files[0]; @@ -129,9 +120,6 @@ class OC_Files { if ($get_type === self::FILE) { $zip = false; - if ($xsendfile && \OC::$server->getEncryptionManager()->isEnabled()) { - $xsendfile = false; - } } else { $zip = new ZipStreamer(false); } @@ -176,17 +164,7 @@ class OC_Files { $zip->finalize(); set_time_limit($executionTime); } else { - if ($xsendfile) { - /** @var $storage \OC\Files\Storage\Storage */ - list($storage) = $view->resolvePath($filename); - if ($storage->isLocal()) { - self::addSendfileHeader($filename); - } else { - \OC\Files\Filesystem::readfile($filename); - } - } else { - \OC\Files\Filesystem::readfile($filename); - } + \OC\Files\Filesystem::readfile($filename); } if ($get_type === self::FILE) { $view->unlockFile($filename, ILockingProvider::LOCK_SHARED); @@ -203,40 +181,6 @@ class OC_Files { } /** - * @param false|string $filename - */ - private static function addSendfileHeader($filename) { - if (isset($_SERVER['MOD_X_SENDFILE_ENABLED'])) { - $filename = \OC\Files\Filesystem::getLocalFile($filename); - header("X-Sendfile: " . $filename); - } - if (isset($_SERVER['MOD_X_SENDFILE2_ENABLED'])) { - $filename = \OC\Files\Filesystem::getLocalFile($filename); - if (isset($_SERVER['HTTP_RANGE']) && - preg_match("/^bytes=([0-9]+)-([0-9]*)$/", $_SERVER['HTTP_RANGE'], $range)) { - $filelength = filesize($filename); - if ($range[2] === "") { - $range[2] = $filelength - 1; - } - header("Content-Range: bytes $range[1]-$range[2]/" . $filelength); - header("HTTP/1.1 206 Partial content"); - header("X-Sendfile2: " . str_replace(",", "%2c", rawurlencode($filename)) . " $range[1]-$range[2]"); - } else { - header("X-Sendfile: " . $filename); - } - } - - if (isset($_SERVER['MOD_X_ACCEL_REDIRECT_ENABLED'])) { - if (isset($_SERVER['MOD_X_ACCEL_REDIRECT_PREFIX'])) { - $filename = $_SERVER['MOD_X_ACCEL_REDIRECT_PREFIX'] . \OC\Files\Filesystem::getLocalFile($filename); - } else { - $filename = \OC::$WEBROOT . '/data' . \OC\Files\Filesystem::getRoot() . $filename; - } - header("X-Accel-Redirect: " . $filename); - } - } - - /** * @param string $dir * @param ZipStreamer $zip * @param string $internalDir diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index 8cf097421d4..5c04da1f0d5 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -35,6 +35,8 @@ namespace OC\Files\Cache; +use \OCP\Files\IMimeTypeLoader; + /** * Metadata cache for a storage * @@ -66,8 +68,8 @@ class Cache { */ protected $storageCache; - protected static $mimetypeIds = array(); - protected static $mimetypes = array(); + /** @var IMimeTypeLoader */ + protected $mimetypeLoader; /** * @param \OC\Files\Storage\Storage|string $storage @@ -83,6 +85,7 @@ class Cache { } $this->storageCache = new Storage($storage); + $this->mimetypeLoader = \OC::$server->getMimeTypeLoader(); } /** @@ -95,72 +98,6 @@ class Cache { } /** - * Get the numeric id for a mimetype - * - * Mimetypes are stored as integers in the cache to prevent duplicated data of the (usually) fairly limited amount of unique mimetypes - * If the supplied mimetype does not yet have a numeric id a new one will be generated - * - * @param string $mime - * @return int - */ - public function getMimetypeId($mime) { - if (empty($mime)) { - // Can not insert empty string into Oracle NOT NULL column. - $mime = 'application/octet-stream'; - } - if (empty(self::$mimetypeIds)) { - $this->loadMimetypes(); - } - - if (!isset(self::$mimetypeIds[$mime])) { - try { - $connection = \OC_DB::getConnection(); - $connection->insertIfNotExist('*PREFIX*mimetypes', [ - 'mimetype' => $mime, - ]); - $this->loadMimetypes(); - } catch (\Doctrine\DBAL\DBALException $e) { - \OCP\Util::writeLog('core', 'Exception during mimetype insertion: ' . $e->getmessage(), \OCP\Util::DEBUG); - return -1; - } - } - - return self::$mimetypeIds[$mime]; - } - - - /** - * Get the mimetype (as string) from a mimetype id - * - * @param int $id - * @return string | null the mimetype for the id or null if the id is not known - */ - public function getMimetype($id) { - if (empty(self::$mimetypes)) { - $this->loadMimetypes(); - } - - return isset(self::$mimetypes[$id]) ? self::$mimetypes[$id] : null; - } - - /** - * Load all known mimetypes and mimetype ids from the database - * - * @throws \OC\DatabaseException - */ - public function loadMimetypes() { - self::$mimetypeIds = self::$mimetypes = array(); - - $result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array()); - if ($result) { - while ($row = $result->fetchRow()) { - self::$mimetypeIds[$row['mimetype']] = $row['id']; - self::$mimetypes[$row['id']] = $row['mimetype']; - } - } - } - - /** * get the stored metadata of a file or folder * * the returned cache entry contains at least the following values: @@ -222,8 +159,8 @@ class Cache { $data['storage_mtime'] = (int)$data['storage_mtime']; $data['encrypted'] = (bool)$data['encrypted']; $data['storage'] = $this->storageId; - $data['mimetype'] = $this->getMimetype($data['mimetype']); - $data['mimepart'] = $this->getMimetype($data['mimepart']); + $data['mimetype'] = $this->mimetypeLoader->getMimetypeById($data['mimetype']); + $data['mimepart'] = $this->mimetypeLoader->getMimetypeById($data['mimepart']); if ($data['storage_mtime'] == 0) { $data['storage_mtime'] = $data['mtime']; } @@ -258,8 +195,8 @@ class Cache { $result = \OC_DB::executeAudited($sql, array($fileId)); $files = $result->fetchAll(); foreach ($files as &$file) { - $file['mimetype'] = $this->getMimetype($file['mimetype']); - $file['mimepart'] = $this->getMimetype($file['mimepart']); + $file['mimetype'] = $this->mimetypeLoader->getMimetypeById($file['mimetype']); + $file['mimepart'] = $this->mimetypeLoader->getMimetypeById($file['mimepart']); if ($file['storage_mtime'] == 0) { $file['storage_mtime'] = $file['mtime']; } @@ -385,9 +322,9 @@ class Cache { $params[] = md5($value); $queryParts[] = '`path_hash`'; } elseif ($name === 'mimetype') { - $params[] = $this->getMimetypeId(substr($value, 0, strpos($value, '/'))); + $params[] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/'))); $queryParts[] = '`mimepart`'; - $value = $this->getMimetypeId($value); + $value = $this->mimetypeLoader->getId($value); } elseif ($name === 'storage_mtime') { if (!isset($data['mtime'])) { $params[] = $value; @@ -613,7 +550,6 @@ class Cache { * @return array an array of cache entries where the name matches the search pattern */ public function search($pattern) { - // normalize pattern $pattern = $this->normalize($pattern); @@ -630,8 +566,8 @@ class Cache { $files = array(); while ($row = $result->fetchRow()) { - $row['mimetype'] = $this->getMimetype($row['mimetype']); - $row['mimepart'] = $this->getMimetype($row['mimepart']); + $row['mimetype'] = $this->mimetypeLoader->getMimetypeById($row['mimetype']); + $row['mimepart'] = $this->mimetypeLoader->getMimetypeById($row['mimepart']); $files[] = $row; } return $files; @@ -652,12 +588,12 @@ class Cache { } $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`, `permissions` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?'; - $mimetype = $this->getMimetypeId($mimetype); + $mimetype = $this->mimetypeLoader->getId($mimetype); $result = \OC_DB::executeAudited($sql, array($mimetype, $this->getNumericStorageId())); $files = array(); while ($row = $result->fetchRow()) { - $row['mimetype'] = $this->getMimetype($row['mimetype']); - $row['mimepart'] = $this->getMimetype($row['mimepart']); + $row['mimetype'] = $this->mimetypeLoader->getMimetypeById($row['mimetype']); + $row['mimepart'] = $this->mimetypeLoader->getMimetypeById($row['mimepart']); $files[] = $row; } return $files; diff --git a/lib/private/files/storage/storagefactory.php b/lib/private/files/storage/storagefactory.php index 62b393c845c..e8df5090f09 100644 --- a/lib/private/files/storage/storagefactory.php +++ b/lib/private/files/storage/storagefactory.php @@ -99,6 +99,9 @@ class StorageFactory implements IStorageFactory { }, $wrappers); foreach ($wrappers as $wrapper) { $storage = $wrapper($mountPoint->getMountPoint(), $storage, $mountPoint); + if (!($storage instanceof \OCP\Files\Storage)) { + throw new \Exception('Invalid result from storage wrapper'); + } } return $storage; } diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php index ba286637df3..3dc3975fb2a 100644 --- a/lib/private/files/type/detection.php +++ b/lib/private/files/type/detection.php @@ -6,6 +6,7 @@ * @author Robin Appelman <icewind@owncloud.com> * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Thomas Tanghus <thomas@tanghus.net> + * @author Robin McCorkell <rmccorkell@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 @@ -101,16 +102,23 @@ class Detection implements IMimeTypeDetector { return; } - $file = file_get_contents($this->configDir . '/mimetypealiases.dist.json'); - $this->mimeTypeAlias = get_object_vars(json_decode($file)); + $this->mimeTypeAlias = json_decode(file_get_contents($this->configDir . '/mimetypealiases.dist.json'), true); if (file_exists($this->configDir . '/mimetypealiases.json')) { - $custom = get_object_vars(json_decode(file_get_contents($this->configDir . '/mimetypealiases.json'))); + $custom = json_decode(file_get_contents($this->configDir . '/mimetypealiases.json'), true); $this->mimeTypeAlias = array_merge($this->mimeTypeAlias, $custom); } } /** + * @return array + */ + public function getAllAliases() { + $this->loadAliases(); + return $this->mimeTypeAlias; + } + + /** * Add mimetype mappings if they are not yet present */ private function loadMappings() { @@ -118,20 +126,26 @@ class Detection implements IMimeTypeDetector { return; } - $dist = file_get_contents($this->configDir . '/mimetypemapping.dist.json'); - $mimetypemapping = get_object_vars(json_decode($dist)); + $mimetypemapping = json_decode(file_get_contents($this->configDir . '/mimetypemapping.dist.json'), true); //Check if need to load custom mappings if (file_exists($this->configDir . '/mimetypemapping.json')) { - $custom = file_get_contents($this->configDir . '/mimetypemapping.json'); - $custom_mapping = get_object_vars(json_decode($custom)); - $mimetypemapping = array_merge($mimetypemapping, $custom_mapping); + $custom = json_decode(file_get_contents($this->configDir . '/mimetypemapping.json'), true); + $mimetypemapping = array_merge($mimetypemapping, $custom); } $this->registerTypeArray($mimetypemapping); } /** + * @return array + */ + public function getAllMappings() { + $this->loadMappings(); + return $this->mimetypes; + } + + /** * detect mimetype only based on filename, content of file is not used * * @param string $path diff --git a/lib/private/files/type/loader.php b/lib/private/files/type/loader.php new file mode 100644 index 00000000000..df893306615 --- /dev/null +++ b/lib/private/files/type/loader.php @@ -0,0 +1,165 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@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\Files\Type; + +use OCP\Files\IMimeTypeLoader; +use OCP\IDBConnection; + +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; + +/** + * Mimetype database loader + * + * @package OC\Files\Type + */ +class Loader implements IMimeTypeLoader { + + /** @var IDBConnection */ + private $dbConnection; + + /** @var array [id => mimetype] */ + protected $mimetypes; + + /** @var array [mimetype => id] */ + protected $mimetypeIds; + + /** + * @param IDBConnection $dbConnection + */ + public function __construct(IDBConnection $dbConnection) { + $this->dbConnection = $dbConnection; + $this->mimetypes = []; + $this->mimetypeIds = []; + } + + /** + * Get a mimetype from its ID + * + * @param int $id + * @return string|null + */ + public function getMimetypeById($id) { + if (!$this->mimetypes) { + $this->loadMimetypes(); + } + if (isset($this->mimetypes[$id])) { + return $this->mimetypes[$id]; + } + return null; + } + + /** + * Get a mimetype ID, adding the mimetype to the DB if it does not exist + * + * @param string $mimetype + * @return int + */ + public function getId($mimetype) { + if (!$this->mimetypeIds) { + $this->loadMimetypes(); + } + if (isset($this->mimetypeIds[$mimetype])) { + return $this->mimetypeIds[$mimetype]; + } + return $this->store($mimetype); + } + + /** + * Test if a mimetype exists in the database + * + * @param string $mimetype + * @return bool + */ + public function exists($mimetype) { + if (!$this->mimetypeIds) { + $this->loadMimetypes(); + } + return isset($this->mimetypeIds[$mimetype]); + } + + /** + * Store a mimetype in the DB + * + * @param string $mimetype + * @param int inserted ID + */ + protected function store($mimetype) { + try { + $qb = $this->dbConnection->getQueryBuilder(); + $qb->insert('mimetypes') + ->values([ + 'mimetype' => $qb->createNamedParameter($mimetype) + ]); + $qb->execute(); + } catch (UniqueConstraintViolationException $e) { + // something inserted it before us + } + + $fetch = $this->dbConnection->getQueryBuilder(); + $fetch->select('id') + ->from('mimetypes') + ->where( + $fetch->expr()->eq('mimetype', $fetch->createNamedParameter($mimetype) + )); + $row = $fetch->execute()->fetch(); + + $this->mimetypes[$row['id']] = $mimetype; + $this->mimetypeIds[$mimetype] = $row['id']; + return $row['id']; + } + + /** + * Load all mimetypes from DB + */ + private function loadMimetypes() { + $qb = $this->dbConnection->getQueryBuilder(); + $qb->select('id', 'mimetype') + ->from('mimetypes'); + $results = $qb->execute()->fetchAll(); + + foreach ($results as $row) { + $this->mimetypes[$row['id']] = $row['mimetype']; + $this->mimetypeIds[$row['mimetype']] = $row['id']; + } + } + + /** + * Update filecache mimetype based on file extension + * + * @param string $ext file extension + * @param int $mimetypeId + * @return int number of changed rows + */ + public function updateFilecache($ext, $mimetypeId) { + $update = $this->dbConnection->getQueryBuilder(); + $update->update('filecache') + ->set('mimetype', $update->createNamedParameter($mimetypeId)) + ->where($update->expr()->neq( + 'mimetype', $update->createNamedParameter($mimetypeId) + )) + ->andWhere($update->expr()->like( + $update->createFunction('LOWER(`name`)'), $update->createNamedParameter($ext) + )); + return $update->execute(); + } + +} diff --git a/lib/private/json.php b/lib/private/json.php index e32e937c01a..ac72f02f609 100644 --- a/lib/private/json.php +++ b/lib/private/json.php @@ -167,6 +167,6 @@ class OC_JSON{ if (is_array($data)) { array_walk_recursive($data, array('OC_JSON', 'to_string')); } - return json_encode($data); + return json_encode($data, JSON_HEX_TAG); } } diff --git a/lib/private/preview.php b/lib/private/preview.php index 5dcab476a4f..978da1161c2 100644 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -38,6 +38,9 @@ class Preview { //the thumbnail folder const THUMBNAILS_FOLDER = 'thumbnails'; + const MODE_FILL = 'fill'; + const MODE_COVER = 'cover'; + //config private $maxScaleFactor; /** @var int maximum width allowed for a preview */ @@ -56,6 +59,7 @@ class Preview { private $scalingUp; private $mimeType; private $keepAspect = false; + private $mode = self::MODE_FILL; //used to calculate the size of the preview to generate /** @var int $maxPreviewWidth max width a preview can have */ @@ -332,6 +336,19 @@ class Preview { } /** + * Set whether to cover or fill the specified dimensions + * + * @param string $mode + * + * @return \OC\Preview + */ + public function setMode($mode) { + $this->mode = $mode; + + return $this; + } + + /** * Sets whether we need to generate a preview which keeps the aspect ratio of the original file * * @param bool $keepAspect @@ -531,14 +548,22 @@ class Preview { * @param int $askedWidth * @param int $askedHeight * + * @param int $originalWidth + * @param int $originalHeight * @return \int[] */ - private function applyAspectRatio($askedWidth, $askedHeight) { - $originalRatio = $this->maxPreviewWidth / $this->maxPreviewHeight; + private function applyAspectRatio($askedWidth, $askedHeight, $originalWidth = 0, $originalHeight = 0) { + if(!$originalWidth){ + $originalWidth= $this->maxPreviewWidth; + } + if (!$originalHeight) { + $originalHeight = $this->maxPreviewHeight; + } + $originalRatio = $originalWidth / $originalHeight; // Defines the box in which the preview has to fit $scaleFactor = $this->scalingUp ? $this->maxScaleFactor : 1; - $askedWidth = min($askedWidth, $this->maxPreviewWidth * $scaleFactor); - $askedHeight = min($askedHeight, $this->maxPreviewHeight * $scaleFactor); + $askedWidth = min($askedWidth, $originalWidth * $scaleFactor); + $askedHeight = min($askedHeight, $originalHeight * $scaleFactor); if ($askedWidth / $originalRatio < $askedHeight) { // width restricted @@ -551,6 +576,32 @@ class Preview { } /** + * Resizes the boundaries to cover the area + * + * @param int $askedWidth + * @param int $askedHeight + * @param int $previewWidth + * @param int $previewHeight + * @return \int[] + */ + private function applyCover($askedWidth, $askedHeight, $previewWidth, $previewHeight) { + $originalRatio = $previewWidth / $previewHeight; + // Defines the box in which the preview has to fit + $scaleFactor = $this->scalingUp ? $this->maxScaleFactor : 1; + $askedWidth = min($askedWidth, $previewWidth * $scaleFactor); + $askedHeight = min($askedHeight, $previewHeight * $scaleFactor); + + if ($askedWidth / $originalRatio > $askedHeight) { + // height restricted + $askedHeight = round($askedWidth / $originalRatio); + } else { + $askedWidth = round($askedHeight * $originalRatio); + } + + return [(int)$askedWidth, (int)$askedHeight]; + } + + /** * Makes sure an upscaled preview doesn't end up larger than the max dimensions defined in the * config * @@ -791,7 +842,15 @@ class Preview { */ if ($this->keepAspect) { list($askedWidth, $askedHeight) = - $this->applyAspectRatio($askedWidth, $askedHeight); + $this->applyAspectRatio($askedWidth, $askedHeight, $previewWidth, $previewHeight); + } + + if ($this->mode === self::MODE_COVER) { + list($scaleWidth, $scaleHeight) = + $this->applyCover($askedWidth, $askedHeight, $previewWidth, $previewHeight); + } else { + $scaleWidth = $askedWidth; + $scaleHeight = $askedHeight; } /** @@ -799,7 +858,7 @@ class Preview { * Takes the scaling ratio into consideration */ list($newPreviewWidth, $newPreviewHeight) = $this->scale( - $image, $askedWidth, $askedHeight, $previewWidth, $previewHeight + $image, $scaleWidth, $scaleHeight, $previewWidth, $previewHeight ); // The preview has been resized and should now have the asked dimensions @@ -1000,6 +1059,9 @@ class Preview { if ($this->keepAspect && !$isMaxPreview) { $previewPath .= '-with-aspect'; } + if ($this->mode === self::MODE_COVER) { + $previewPath .= '-cover'; + } $previewPath .= '.png'; return $previewPath; diff --git a/lib/private/route/router.php b/lib/private/route/router.php index 33669452f2d..7b7849a6da0 100644 --- a/lib/private/route/router.php +++ b/lib/private/route/router.php @@ -169,8 +169,9 @@ class Router implements IRouter { $this->useCollection('root'); require_once 'settings/routes.php'; require_once 'core/routes.php'; - - // include ocs routes + } + if ($this->loaded) { + // include ocs routes, must be loaded last for /ocs prefix require_once 'ocs/routes.php'; $collection = $this->getCollection('ocs'); $collection->addPrefix('/ocs'); diff --git a/lib/private/security/certificatemanager.php b/lib/private/security/certificatemanager.php index d61c7f29327..4d470f69a66 100644 --- a/lib/private/security/certificatemanager.php +++ b/lib/private/security/certificatemanager.php @@ -27,6 +27,7 @@ namespace OC\Security; use OC\Files\Filesystem; use OCP\ICertificateManager; +use OCP\IConfig; /** * Manage trusted certificates for users @@ -43,12 +44,19 @@ class CertificateManager implements ICertificateManager { protected $view; /** + * @var IConfig + */ + protected $config; + + /** * @param string $uid * @param \OC\Files\View $view relative zu data/ + * @param IConfig $config */ - public function __construct($uid, \OC\Files\View $view) { + public function __construct($uid, \OC\Files\View $view, IConfig $config) { $this->uid = $uid; $this->view = $view; + $this->config = $config; } /** @@ -57,6 +65,11 @@ class CertificateManager implements ICertificateManager { * @return \OCP\ICertificate[] */ public function listCertificates() { + + if (!$this->config->getSystemValue('installed', false)) { + return array(); + } + $path = $this->getPathToCertificates() . 'uploads/'; if (!$this->view->is_dir($path)) { return array(); diff --git a/lib/private/server.php b/lib/private/server.php index a47fa2e43f9..393c1840973 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -91,12 +91,25 @@ class Server extends SimpleContainer implements IServerContainer { }); $this->registerService('EncryptionManager', function (Server $c) { - return new Encryption\Manager($c->getConfig(), $c->getLogger(), $c->getL10N('core')); + $view = new View(); + $util = new Encryption\Util( + $view, + $c->getUserManager(), + $c->getGroupManager(), + $c->getConfig() + ); + return new Encryption\Manager( + $c->getConfig(), + $c->getLogger(), + $c->getL10N('core'), + new View(), + $util + ); }); $this->registerService('EncryptionFileHelper', function (Server $c) { - $util = new \OC\Encryption\Util( - new \OC\Files\View(), + $util = new Encryption\Util( + new View(), $c->getUserManager(), $c->getGroupManager(), $c->getConfig() @@ -105,8 +118,8 @@ class Server extends SimpleContainer implements IServerContainer { }); $this->registerService('EncryptionKeyStorage', function (Server $c) { - $view = new \OC\Files\View(); - $util = new \OC\Encryption\Util( + $view = new View(); + $util = new Encryption\Util( $view, $c->getUserManager(), $c->getGroupManager(), @@ -326,7 +339,7 @@ class Server extends SimpleContainer implements IServerContainer { $uid = $user ? $user : null; return new ClientService( $c->getConfig(), - new \OC\Security\CertificateManager($uid, new \OC\Files\View()) + new \OC\Security\CertificateManager($uid, new View(), $c->getConfig()) ); }); $this->registerService('EventLogger', function (Server $c) { @@ -438,13 +451,13 @@ class Server extends SimpleContainer implements IServerContainer { ); }); $this->registerService('LockingProvider', function (Server $c) { - if ($c->getConfig()->getSystemValue('filelocking.enabled', false) or (defined('PHPUNIT_RUN') && PHPUNIT_RUN)) { + if ($c->getConfig()->getSystemValue('filelocking.enabled', true) or (defined('PHPUNIT_RUN') && PHPUNIT_RUN)) { /** @var \OC\Memcache\Factory $memcacheFactory */ $memcacheFactory = $c->getMemCacheFactory(); $memcache = $memcacheFactory->createLocking('lock'); -// if (!($memcache instanceof \OC\Memcache\NullCache)) { -// return new MemcacheLockingProvider($memcache); -// } + if (!($memcache instanceof \OC\Memcache\NullCache)) { + return new MemcacheLockingProvider($memcache); + } return new DBLockingProvider($c->getDatabaseConnection(), $c->getLogger()); } return new NoopLockingProvider(); @@ -457,6 +470,11 @@ class Server extends SimpleContainer implements IServerContainer { $c->getURLGenerator(), \OC::$configDir); }); + $this->registerService('MimeTypeLoader', function(Server $c) { + return new \OC\Files\Type\Loader( + $c->getDatabaseConnection() + ); + }); $this->registerService('CapabilitiesManager', function (Server $c) { $manager = new \OC\CapabilitiesManager(); $manager->registerCapability(function() use ($c) { @@ -839,7 +857,7 @@ class Server extends SimpleContainer implements IServerContainer { } $userId = $user->getUID(); } - return new CertificateManager($userId, new \OC\Files\View()); + return new CertificateManager($userId, new View(), $this->getConfig()); } /** @@ -998,6 +1016,15 @@ class Server extends SimpleContainer implements IServerContainer { } /** + * Get the MimeTypeLoader + * + * @return \OCP\Files\IMimeTypeLoader + */ + public function getMimeTypeLoader() { + return $this->query('MimeTypeLoader'); + } + + /** * Get the manager of all the capabilities * * @return \OC\CapabilitiesManager diff --git a/lib/private/share/share.php b/lib/private/share/share.php index d0c69badb46..6ad36d60fe8 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -37,6 +37,7 @@ namespace OC\Share; +use OC\Files\Filesystem; use OCP\IUserSession; use OCP\IDBConnection; use OCP\IConfig; @@ -120,6 +121,7 @@ class Share extends Constants { */ public static function getUsersSharingFile($path, $ownerUser, $includeOwner = false, $returnUserPaths = false) { + Filesystem::initMountPoints($ownerUser); $shares = $sharePaths = $fileTargets = array(); $publicShare = false; $remoteShare = false; @@ -701,6 +703,18 @@ class Share extends Constants { throw new \Exception($message_t); } } + if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_USER, + $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) { + // Only allow the same share to occur again if it is the same + // owner and is not a user share, this use case is for increasing + // permissions for a specific user + if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) { + $message = 'Sharing %s failed, because this item is already shared with user %s'; + $message_t = $l->t('Sharing %s failed, because this item is already shared with user %s', array($itemSourceName, $shareWith)); + \OC_Log::write('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OC_Log::ERROR); + throw new \Exception($message_t); + } + } } else if ($shareType === self::SHARE_TYPE_GROUP) { if (!\OC_Group::groupExists($shareWith)) { $message = 'Sharing %s failed, because the group %s does not exist'; @@ -751,7 +765,7 @@ class Share extends Constants { } // Generate hash of password - same method as user passwords - if (!empty($shareWith)) { + if (is_string($shareWith) && $shareWith !== '') { self::verifyPassword($shareWith); $shareWith = \OC::$server->getHasher()->hash($shareWith); } else { diff --git a/lib/private/util.php b/lib/private/util.php index 47e42d8b7d3..eb1de5be5a4 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -1054,6 +1054,7 @@ class OC_Util { return $id; } + protected static $encryptedToken; /** * Register an get/post call. Important to prevent CSRF attacks. * @@ -1066,6 +1067,11 @@ class OC_Util { * @see OC_Util::isCallRegistered() */ public static function callRegister() { + // Use existing token if function has already been called + if(isset(self::$encryptedToken)) { + return self::$encryptedToken; + } + // Check if a token exists if (!\OC::$server->getSession()->exists('requesttoken')) { // No valid token found, generate a new one. @@ -1078,7 +1084,8 @@ class OC_Util { // Encrypt the token to mitigate breach-like attacks $sharedSecret = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(10); - return \OC::$server->getCrypto()->encrypt($requestToken, $sharedSecret) . ':' . $sharedSecret; + self::$encryptedToken = \OC::$server->getCrypto()->encrypt($requestToken, $sharedSecret) . ':' . $sharedSecret; + return self::$encryptedToken; } /** @@ -1145,6 +1152,7 @@ class OC_Util { * @throws \OC\HintException If the test file can't get written. */ public function isHtaccessWorking(\OCP\IConfig $config) { + if (\OC::$CLI || !$config->getSystemValue('check_for_working_htaccess', true)) { return true; } diff --git a/lib/public/appframework/http/jsonresponse.php b/lib/public/appframework/http/jsonresponse.php index 456a5616d4d..1a509200dd7 100644 --- a/lib/public/appframework/http/jsonresponse.php +++ b/lib/public/appframework/http/jsonresponse.php @@ -64,7 +64,7 @@ class JSONResponse extends Response { * @throws \Exception If data could not get encoded */ public function render() { - $response = json_encode($this->data); + $response = json_encode($this->data, JSON_HEX_TAG); if($response === false) { throw new \Exception(sprintf('Could not json_encode due to invalid ' . 'non UTF-8 characters in the array: %s', var_export($this->data, true))); diff --git a/lib/public/autoloadnotallowedexception.php b/lib/public/autoloadnotallowedexception.php new file mode 100644 index 00000000000..edb7121c065 --- /dev/null +++ b/lib/public/autoloadnotallowedexception.php @@ -0,0 +1,36 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@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 OCP; + +/** + * Exception for when a not allowed path is attempted to be autoloaded + * @since 8.2.0 + */ +class AutoloadNotAllowedException extends \DomainException { + /** + * @param string $path + * @since 8.2.0 + */ + public function __construct($path) { + parent::__construct('Autoload path not allowed: '.$path); + } +} + diff --git a/lib/public/files/imimetypeloader.php b/lib/public/files/imimetypeloader.php new file mode 100644 index 00000000000..24937ea9b86 --- /dev/null +++ b/lib/public/files/imimetypeloader.php @@ -0,0 +1,59 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@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 OCP\Files; + +/** + * Interface IMimeTypeLoader + * @package OCP\Files + * @since 8.2.0 + * + * Interface to load mimetypes + **/ +interface IMimeTypeLoader { + + /** + * Get a mimetype from its ID + * + * @param int $id + * @return string|null + * @since 8.2.0 + */ + public function getMimetypeById($id); + + /** + * Get a mimetype ID, adding the mimetype to the DB if it does not exist + * + * @param string $mimetype + * @return int + * @since 8.2.0 + */ + public function getId($mimetype); + + /** + * Test if a mimetype exists in the database + * + * @param string $mimetype + * @return bool + * @since 8.2.0 + */ + public function exists($mimetype); +} diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index a6d83156de3..81724cb4967 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -440,6 +440,14 @@ interface IServerContainer { */ public function getMimeTypeDetector(); + /** + * Get the MimeTypeLoader + * + * @return \OCP\Files\IMimeTypeLoader + * @since 8.2.0 + */ + public function getMimeTypeLoader(); + /** * Get the EventDispatcher |