summaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/App/DependencyAnalyzer.php6
-rw-r--r--lib/private/AppFramework/Db/Db.php11
-rw-r--r--lib/private/AppFramework/DependencyInjection/DIContainer.php4
-rw-r--r--lib/private/AppFramework/Http/Request.php2
-rw-r--r--lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php18
-rw-r--r--lib/private/Avatar.php2
-rw-r--r--lib/private/Comments/Comment.php37
-rw-r--r--lib/private/Comments/Manager.php47
-rw-r--r--lib/private/Console/Application.php63
-rw-r--r--lib/private/DB/Connection.php11
-rw-r--r--lib/private/Encryption/DecryptAll.php2
-rw-r--r--lib/private/Encryption/EncryptionWrapper.php2
-rw-r--r--lib/private/Files/Node/Folder.php12
-rw-r--r--lib/private/Files/Storage/Common.php4
-rw-r--r--lib/private/Files/Storage/Local.php14
-rw-r--r--lib/private/Files/Storage/Wrapper/PermissionsMask.php8
-rw-r--r--lib/private/Files/Storage/Wrapper/Wrapper.php4
-rw-r--r--lib/private/Files/Stream/OC.php154
-rw-r--r--lib/private/Files/View.php10
-rw-r--r--lib/private/LargeFileHelper.php30
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php82
-rw-r--r--lib/private/Security/CSRF/CsrfToken.php10
-rw-r--r--lib/private/Security/CSRF/CsrfTokenManager.php13
-rw-r--r--lib/private/Server.php14
-rw-r--r--lib/private/Share/MailNotifications.php80
-rw-r--r--lib/private/Share/Share.php4
-rw-r--r--lib/private/Template/JSConfigHelper.php243
-rw-r--r--lib/private/TemplateLayout.php18
-rw-r--r--lib/private/User/Session.php3
-rw-r--r--lib/private/legacy/app.php39
-rw-r--r--lib/private/legacy/helper.php16
-rw-r--r--lib/private/legacy/image.php27
-rw-r--r--lib/private/legacy/response.php3
-rw-r--r--lib/private/legacy/template.php8
-rw-r--r--lib/private/legacy/util.php23
35 files changed, 677 insertions, 347 deletions
diff --git a/lib/private/App/DependencyAnalyzer.php b/lib/private/App/DependencyAnalyzer.php
index 7adb5d1c574..67268981e99 100644
--- a/lib/private/App/DependencyAnalyzer.php
+++ b/lib/private/App/DependencyAnalyzer.php
@@ -197,6 +197,9 @@ class DependencyAnalyzer {
if (!is_array($commands)) {
$commands = array($commands);
}
+ if (isset($commands['@value'])) {
+ $commands = [$commands];
+ }
$os = $this->platform->getOS();
foreach ($commands as $command) {
if (isset($command['@attributes']['os']) && $command['@attributes']['os'] !== $os) {
@@ -224,6 +227,9 @@ class DependencyAnalyzer {
if (!is_array($libs)) {
$libs = array($libs);
}
+ if (isset($libs['@value'])) {
+ $libs = [$libs];
+ }
foreach ($libs as $lib) {
$libName = $this->getValue($lib);
$libVersion = $this->platform->getLibraryVersion($libName);
diff --git a/lib/private/AppFramework/Db/Db.php b/lib/private/AppFramework/Db/Db.php
index 5fea09747af..450549ffdbb 100644
--- a/lib/private/AppFramework/Db/Db.php
+++ b/lib/private/AppFramework/Db/Db.php
@@ -31,6 +31,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDb;
use OCP\IDBConnection;
use OCP\PreConditionNotMetException;
+use Doctrine\DBAL\Platforms\MySqlPlatform;
/**
* @deprecated use IDBConnection directly, will be removed in ownCloud 10
@@ -300,4 +301,14 @@ class Db implements IDb {
public function escapeLikeParameter($param) {
return $this->connection->escapeLikeParameter($param);
}
+
+ /**
+ * Check whether or not the current database support 4byte wide unicode
+ *
+ * @return bool
+ * @since 9.2.0
+ */
+ public function supports4ByteText() {
+ return $this->connection->supports4ByteText();
+ }
}
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index b2fdf86d9c2..671093ff08b 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -385,7 +385,9 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$c['AppName'],
$app->isLoggedIn(),
$app->isAdminUser(),
- $app->getServer()->getContentSecurityPolicyManager()
+ $app->getServer()->getContentSecurityPolicyManager(),
+ $app->getServer()->getCsrfTokenManager(),
+ $app->getServer()->getContentSecurityPolicyNonceManager()
);
});
diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php
index ba8a48381bd..c7a3be163fe 100644
--- a/lib/private/AppFramework/Http/Request.php
+++ b/lib/private/AppFramework/Http/Request.php
@@ -61,7 +61,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
// Firefox User Agent from https://developer.mozilla.org/en-US/docs/Web/HTTP/Gecko_user_agent_string_reference
const USER_AGENT_FIREFOX = '/^Mozilla\/5\.0 \([^)]+\) Gecko\/[0-9.]+ Firefox\/[0-9.]+$/';
// Chrome User Agent from https://developer.chrome.com/multidevice/user-agent
- const USER_AGENT_CHROME = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+$/';
+ const USER_AGENT_CHROME = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)( Ubuntu Chromium\/[0-9.]+|) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+$/';
// Safari User Agent from http://www.useragentstring.com/pages/Safari/
const USER_AGENT_SAFARI = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Version\/[0-9.]+ Safari\/[0-9.A-Z]+$/';
// Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent
diff --git a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
index 5e253d0954a..183e55740ea 100644
--- a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
@@ -36,6 +36,8 @@ use OC\AppFramework\Middleware\Security\Exceptions\NotLoggedInException;
use OC\AppFramework\Middleware\Security\Exceptions\StrictCookieMissingException;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\Security\CSP\ContentSecurityPolicyManager;
+use OC\Security\CSP\ContentSecurityPolicyNonceManager;
+use OC\Security\CSRF\CsrfTokenManager;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\EmptyContentSecurityPolicy;
use OCP\AppFramework\Http\RedirectResponse;
@@ -77,6 +79,10 @@ class SecurityMiddleware extends Middleware {
private $isAdminUser;
/** @var ContentSecurityPolicyManager */
private $contentSecurityPolicyManager;
+ /** @var CsrfTokenManager */
+ private $csrfTokenManager;
+ /** @var ContentSecurityPolicyNonceManager */
+ private $cspNonceManager;
/**
* @param IRequest $request
@@ -88,6 +94,8 @@ class SecurityMiddleware extends Middleware {
* @param bool $isLoggedIn
* @param bool $isAdminUser
* @param ContentSecurityPolicyManager $contentSecurityPolicyManager
+ * @param CSRFTokenManager $csrfTokenManager
+ * @param ContentSecurityPolicyNonceManager $cspNonceManager
*/
public function __construct(IRequest $request,
ControllerMethodReflector $reflector,
@@ -97,7 +105,9 @@ class SecurityMiddleware extends Middleware {
$appName,
$isLoggedIn,
$isAdminUser,
- ContentSecurityPolicyManager $contentSecurityPolicyManager) {
+ ContentSecurityPolicyManager $contentSecurityPolicyManager,
+ CsrfTokenManager $csrfTokenManager,
+ ContentSecurityPolicyNonceManager $cspNonceManager) {
$this->navigationManager = $navigationManager;
$this->request = $request;
$this->reflector = $reflector;
@@ -107,6 +117,8 @@ class SecurityMiddleware extends Middleware {
$this->isLoggedIn = $isLoggedIn;
$this->isAdminUser = $isAdminUser;
$this->contentSecurityPolicyManager = $contentSecurityPolicyManager;
+ $this->csrfTokenManager = $csrfTokenManager;
+ $this->cspNonceManager = $cspNonceManager;
}
@@ -190,6 +202,10 @@ class SecurityMiddleware extends Middleware {
$defaultPolicy = $this->contentSecurityPolicyManager->getDefaultPolicy();
$defaultPolicy = $this->contentSecurityPolicyManager->mergePolicies($defaultPolicy, $policy);
+ if($this->cspNonceManager->browserSupportsCspV3()) {
+ $defaultPolicy->useJsNonce($this->csrfTokenManager->getToken()->getEncryptedValue());
+ }
+
$response->setContentSecurityPolicy($defaultPolicy);
return $response;
diff --git a/lib/private/Avatar.php b/lib/private/Avatar.php
index c3a068701df..fc1909c3bda 100644
--- a/lib/private/Avatar.php
+++ b/lib/private/Avatar.php
@@ -131,7 +131,7 @@ class Avatar implements IAvatar {
}
if (!($img->height() === $img->width())) {
- throw new NotSquareException();
+ throw new NotSquareException($this->l->t("Avatar image is not square"));
}
$this->remove();
diff --git a/lib/private/Comments/Comment.php b/lib/private/Comments/Comment.php
index f6f0801c683..b5f063be323 100644
--- a/lib/private/Comments/Comment.php
+++ b/lib/private/Comments/Comment.php
@@ -204,6 +204,43 @@ class Comment implements IComment {
}
/**
+ * returns an array containing mentions that are included in the comment
+ *
+ * @return array each mention provides a 'type' and an 'id', see example below
+ * @since 9.2.0
+ *
+ * The return array looks like:
+ * [
+ * [
+ * 'type' => 'user',
+ * 'id' => 'citizen4'
+ * ],
+ * [
+ * 'type' => 'group',
+ * 'id' => 'media'
+ * ],
+ * …
+ * ]
+ *
+ */
+ public function getMentions() {
+ $ok = preg_match_all('/\B@[a-z0-9_\-@\.\']+/i', $this->getMessage(), $mentions);
+ if(!$ok || !isset($mentions[0]) || !is_array($mentions[0])) {
+ return [];
+ }
+ $uids = array_unique($mentions[0]);
+ $result = [];
+ foreach ($uids as $uid) {
+ // exclude author, no self-mentioning
+ if($uid === '@' . $this->getActorId()) {
+ continue;
+ }
+ $result[] = ['type' => 'user', 'id' => substr($uid, 1)];
+ }
+ return $result;
+ }
+
+ /**
* returns the verb of the comment
*
* @return string
diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php
index b3ecab731e1..001f4f9441c 100644
--- a/lib/private/Comments/Manager.php
+++ b/lib/private/Comments/Manager.php
@@ -55,6 +55,9 @@ class Manager implements ICommentsManager {
/** @var ICommentsEventHandler[] */
protected $eventHandlers = [];
+ /** @var \Closure[] */
+ protected $displayNameResolvers = [];
+
/**
* Manager constructor.
*
@@ -760,6 +763,50 @@ class Manager implements ICommentsManager {
}
/**
+ * registers a method that resolves an ID to a display name for a given type
+ *
+ * @param string $type
+ * @param \Closure $closure
+ * @throws \OutOfBoundsException
+ * @since 9.2.0
+ *
+ * Only one resolver shall be registered per type. Otherwise a
+ * \OutOfBoundsException has to thrown.
+ */
+ public function registerDisplayNameResolver($type, \Closure $closure) {
+ if(!is_string($type)) {
+ throw new \InvalidArgumentException('String expected.');
+ }
+ if(isset($this->displayNameResolvers[$type])) {
+ throw new \OutOfBoundsException('Displayname resolver for this type already registered');
+ }
+ $this->displayNameResolvers[$type] = $closure;
+ }
+
+ /**
+ * resolves a given ID of a given Type to a display name.
+ *
+ * @param string $type
+ * @param string $id
+ * @return string
+ * @throws \OutOfBoundsException
+ * @since 9.2.0
+ *
+ * If a provided type was not registered, an \OutOfBoundsException shall
+ * be thrown. It is upon the resolver discretion what to return of the
+ * provided ID is unknown. It must be ensured that a string is returned.
+ */
+ public function resolveDisplayName($type, $id) {
+ if(!is_string($type)) {
+ throw new \InvalidArgumentException('String expected.');
+ }
+ if(!isset($this->displayNameResolvers[$type])) {
+ throw new \OutOfBoundsException('No Displayname resolver for this type registered');
+ }
+ return (string)$this->displayNameResolvers[$type]($id);
+ }
+
+ /**
* returns valid, registered entities
*
* @return \OCP\Comments\ICommentsEventHandler[]
diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php
index 299b23714b6..cd76b43f095 100644
--- a/lib/private/Console/Application.php
+++ b/lib/private/Console/Application.php
@@ -26,6 +26,7 @@
*/
namespace OC\Console;
+use OC\NeedsUpdateException;
use OC_App;
use OCP\AppFramework\QueryException;
use OCP\Console\ConsoleEvent;
@@ -84,39 +85,43 @@ class Application {
if ($input->getOption('no-warnings')) {
$output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
}
- require_once __DIR__ . '/../../../core/register_command.php';
- if ($this->config->getSystemValue('installed', false)) {
- if (\OCP\Util::needUpgrade()) {
- if ($input->getArgument('command') !== '_completion') {
- $output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available");
- $output->writeln("You may use your browser or the occ upgrade command to do the upgrade");
- }
- } elseif ($this->config->getSystemValue('maintenance', false)) {
- if ($input->getArgument('command') !== '_completion') {
- $output->writeln("Nextcloud is in maintenance mode - no apps have been loaded");
- }
- } else {
- OC_App::loadApps();
- foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) {
- $appPath = \OC_App::getAppPath($app);
- if($appPath === false) {
- continue;
- }
- // load commands using info.xml
- $info = \OC_App::getAppInfo($app);
- if (isset($info['commands'])) {
- $this->loadCommandsFromInfoXml($info['commands']);
+ try {
+ require_once __DIR__ . '/../../../core/register_command.php';
+ if ($this->config->getSystemValue('installed', false)) {
+ if (\OCP\Util::needUpgrade()) {
+ throw new NeedsUpdateException();
+ } elseif ($this->config->getSystemValue('maintenance', false)) {
+ if ($input->getArgument('command') !== '_completion') {
+ $output->writeln("Nextcloud is in maintenance mode - no apps have been loaded");
}
- // load from register_command.php
- \OC_App::registerAutoloading($app, $appPath);
- $file = $appPath . '/appinfo/register_command.php';
- if (file_exists($file)) {
- require $file;
+ } else {
+ OC_App::loadApps();
+ foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) {
+ $appPath = \OC_App::getAppPath($app);
+ if ($appPath === false) {
+ continue;
+ }
+ // load commands using info.xml
+ $info = \OC_App::getAppInfo($app);
+ if (isset($info['commands'])) {
+ $this->loadCommandsFromInfoXml($info['commands']);
+ }
+ // load from register_command.php
+ \OC_App::registerAutoloading($app, $appPath);
+ $file = $appPath . '/appinfo/register_command.php';
+ if (file_exists($file)) {
+ require $file;
+ }
}
}
+ } else if ($input->getArgument('command') !== '_completion') {
+ $output->writeln("Nextcloud is not installed - only a limited number of commands are available");
+ }
+ } catch(NeedsUpdateException $e) {
+ if ($input->getArgument('command') !== '_completion') {
+ $output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available");
+ $output->writeln("You may use your browser or the occ upgrade command to do the upgrade");
}
- } else if ($input->getArgument('command') !== '_completion') {
- $output->writeln("Nextcloud is not installed - only a limited number of commands are available");
}
if ($input->getFirstArgument() !== 'check') {
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php
index 4fa25aae08d..dfe2e86b617 100644
--- a/lib/private/DB/Connection.php
+++ b/lib/private/DB/Connection.php
@@ -33,6 +33,7 @@ use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\Common\EventManager;
+use Doctrine\DBAL\Platforms\MySqlPlatform;
use OC\DB\QueryBuilder\QueryBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
@@ -402,4 +403,14 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
public function escapeLikeParameter($param) {
return addcslashes($param, '\\_%');
}
+
+ /**
+ * Check whether or not the current database support 4byte wide unicode
+ *
+ * @return bool
+ * @since 9.2.0
+ */
+ public function supports4ByteText() {
+ return ! ($this->getDatabasePlatform() instanceof MySqlPlatform && $this->getParams()['charset'] !== 'utf8mb4');
+ }
}
diff --git a/lib/private/Encryption/DecryptAll.php b/lib/private/Encryption/DecryptAll.php
index b84395b9e17..caf4237ab9c 100644
--- a/lib/private/Encryption/DecryptAll.php
+++ b/lib/private/Encryption/DecryptAll.php
@@ -211,7 +211,7 @@ class DecryptAll {
$content = $this->rootView->getDirectoryContent($root);
foreach ($content as $file) {
// only decrypt files owned by the user
- if($file->getStorage()->instanceOfStorage('OC\Files\Storage\Shared')) {
+ if($file->getStorage()->instanceOfStorage('OCA\Files_Sharing\SharedStorage')) {
continue;
}
$path = $root . '/' . $file['name'];
diff --git a/lib/private/Encryption/EncryptionWrapper.php b/lib/private/Encryption/EncryptionWrapper.php
index 233390f8739..573fe0159ea 100644
--- a/lib/private/Encryption/EncryptionWrapper.php
+++ b/lib/private/Encryption/EncryptionWrapper.php
@@ -81,7 +81,7 @@ class EncryptionWrapper {
'mount' => $mount
];
- if (!$storage->instanceOfStorage('OC\Files\Storage\Shared')
+ if (!$storage->instanceOfStorage('OCA\Files_Sharing\SharedStorage')
&& !$storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')
&& !$storage->instanceOfStorage('OC\Files\Storage\OwnCloud')) {
diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index 353b89068cb..288a02ef207 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -42,7 +42,7 @@ class Folder extends Node implements \OCP\Files\Folder {
*/
public function getFullPath($path) {
if (!$this->isValidPath($path)) {
- throw new NotPermittedException();
+ throw new NotPermittedException('Invalid path');
}
return $this->path . $this->normalizePath($path);
}
@@ -152,7 +152,7 @@ class Folder extends Node implements \OCP\Files\Folder {
$this->root->emit('\OC\Files', 'postCreate', array($node));
return $node;
} else {
- throw new NotPermittedException();
+ throw new NotPermittedException('No create permission for folder');
}
}
@@ -173,7 +173,7 @@ class Folder extends Node implements \OCP\Files\Folder {
$this->root->emit('\OC\Files', 'postCreate', array($node));
return $node;
} else {
- throw new NotPermittedException();
+ throw new NotPermittedException('No create permission for path');
}
}
@@ -321,7 +321,7 @@ class Folder extends Node implements \OCP\Files\Folder {
$this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
$this->exists = false;
} else {
- throw new NotPermittedException();
+ throw new NotPermittedException('No delete permission for path');
}
}
@@ -343,7 +343,7 @@ class Folder extends Node implements \OCP\Files\Folder {
$this->root->emit('\OC\Files', 'postWrite', array($targetNode));
return $targetNode;
} else {
- throw new NotPermittedException();
+ throw new NotPermittedException('No permission to copy to path');
}
}
@@ -366,7 +366,7 @@ class Folder extends Node implements \OCP\Files\Folder {
$this->path = $targetPath;
return $targetNode;
} else {
- throw new NotPermittedException();
+ throw new NotPermittedException('No permission to move to path');
}
}
diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php
index 63d3c004fd2..c975791295d 100644
--- a/lib/private/Files/Storage/Common.php
+++ b/lib/private/Files/Storage/Common.php
@@ -466,6 +466,10 @@ abstract class Common implements Storage, ILockingStorage {
* @return bool
*/
public function instanceOfStorage($class) {
+ if (ltrim($class, '\\') === 'OC\Files\Storage\Shared') {
+ // FIXME Temporary fix to keep existing checks working
+ $class = '\OCA\Files_Sharing\SharedStorage';
+ }
return is_a($this, $class);
}
diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php
index 0d63fd46ecc..4fe7dcafbbf 100644
--- a/lib/private/Files/Storage/Local.php
+++ b/lib/private/Files/Storage/Local.php
@@ -155,7 +155,7 @@ class Local extends \OC\Files\Storage\Common {
$fullPath = $this->getSourcePath($path);
if (PHP_INT_SIZE === 4) {
$helper = new \OC\LargeFileHelper;
- return $helper->getFilesize($fullPath);
+ return $helper->getFileSize($fullPath);
}
return filesize($fullPath);
}
@@ -173,8 +173,16 @@ class Local extends \OC\Files\Storage\Common {
}
public function filemtime($path) {
- clearstatcache($this->getSourcePath($path));
- return $this->file_exists($path) ? filemtime($this->getSourcePath($path)) : false;
+ $fullPath = $this->getSourcePath($path);
+ clearstatcache($fullPath);
+ if (!$this->file_exists($path)) {
+ return false;
+ }
+ if (PHP_INT_SIZE === 4) {
+ $helper = new \OC\LargeFileHelper();
+ return $helper->getFileMtime($fullPath);
+ }
+ return filemtime($fullPath);
}
public function touch($path, $mtime = null) {
diff --git a/lib/private/Files/Storage/Wrapper/PermissionsMask.php b/lib/private/Files/Storage/Wrapper/PermissionsMask.php
index 39375602c34..7bcb1087fef 100644
--- a/lib/private/Files/Storage/Wrapper/PermissionsMask.php
+++ b/lib/private/Files/Storage/Wrapper/PermissionsMask.php
@@ -78,6 +78,14 @@ class PermissionsMask extends Wrapper {
}
public function rename($path1, $path2) {
+ $p = strpos($path1, $path2);
+ if ($p === 0) {
+ $part = substr($path1, strlen($path2));
+ //This is a rename of the transfer file to the original file
+ if (strpos($part, '.ocTransferId') === 0) {
+ return $this->checkMask(Constants::PERMISSION_CREATE) and parent::rename($path1, $path2);
+ }
+ }
return $this->checkMask(Constants::PERMISSION_UPDATE) and parent::rename($path1, $path2);
}
diff --git a/lib/private/Files/Storage/Wrapper/Wrapper.php b/lib/private/Files/Storage/Wrapper/Wrapper.php
index c52b3394832..71b64d8c82c 100644
--- a/lib/private/Files/Storage/Wrapper/Wrapper.php
+++ b/lib/private/Files/Storage/Wrapper/Wrapper.php
@@ -483,6 +483,10 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage {
* @return bool
*/
public function instanceOfStorage($class) {
+ if (ltrim($class, '\\') === 'OC\Files\Storage\Shared') {
+ // FIXME Temporary fix to keep existing checks working
+ $class = '\OCA\Files_Sharing\SharedStorage';
+ }
return is_a($this, $class) or $this->getWrapperStorage()->instanceOfStorage($class);
}
diff --git a/lib/private/Files/Stream/OC.php b/lib/private/Files/Stream/OC.php
deleted file mode 100644
index f415bc13b15..00000000000
--- a/lib/private/Files/Stream/OC.php
+++ /dev/null
@@ -1,154 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- *
- * @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\Stream;
-
-/**
- * a stream wrappers for ownCloud's virtual filesystem
- */
-class OC {
- /**
- * @var \OC\Files\View
- */
- static private $rootView;
-
- private $path;
-
- /**
- * @var resource
- */
- private $dirSource;
-
- /**
- * @var resource
- */
- private $fileSource;
- private $meta;
-
- private function setup(){
- if (!self::$rootView) {
- self::$rootView = new \OC\Files\View('');
- }
- }
-
- public function stream_open($path, $mode, $options, &$opened_path) {
- $this->setup();
- $path = substr($path, strlen('oc://'));
- $this->path = $path;
- $this->fileSource = self::$rootView->fopen($path, $mode);
- if (is_resource($this->fileSource)) {
- $this->meta = stream_get_meta_data($this->fileSource);
- }
- return is_resource($this->fileSource);
- }
-
- public function stream_seek($offset, $whence = SEEK_SET) {
- return fseek($this->fileSource, $offset, $whence) === 0;
- }
-
- public function stream_tell() {
- return ftell($this->fileSource);
- }
-
- public function stream_read($count) {
- return fread($this->fileSource, $count);
- }
-
- public function stream_write($data) {
- return fwrite($this->fileSource, $data);
- }
-
- public function stream_set_option($option, $arg1, $arg2) {
- switch ($option) {
- case STREAM_OPTION_BLOCKING:
- stream_set_blocking($this->fileSource, $arg1);
- break;
- case STREAM_OPTION_READ_TIMEOUT:
- stream_set_timeout($this->fileSource, $arg1, $arg2);
- break;
- case STREAM_OPTION_WRITE_BUFFER:
- stream_set_write_buffer($this->fileSource, $arg1, $arg2);
- }
- }
-
- public function stream_stat() {
- return fstat($this->fileSource);
- }
-
- public function stream_lock($mode) {
- flock($this->fileSource, $mode);
- }
-
- public function stream_flush() {
- return fflush($this->fileSource);
- }
-
- public function stream_eof() {
- return feof($this->fileSource);
- }
-
- public function url_stat($path) {
- $this->setup();
- $path = substr($path, strlen('oc://'));
- if (self::$rootView->file_exists($path)) {
- return self::$rootView->stat($path);
- } else {
- return false;
- }
- }
-
- public function stream_close() {
- fclose($this->fileSource);
- }
-
- public function unlink($path) {
- $this->setup();
- $path = substr($path, strlen('oc://'));
- return self::$rootView->unlink($path);
- }
-
- public function dir_opendir($path, $options) {
- $this->setup();
- $path = substr($path, strlen('oc://'));
- $this->path = $path;
- $this->dirSource = self::$rootView->opendir($path);
- if (is_resource($this->dirSource)) {
- $this->meta = stream_get_meta_data($this->dirSource);
- }
- return is_resource($this->dirSource);
- }
-
- public function dir_readdir() {
- return readdir($this->dirSource);
- }
-
- public function dir_closedir() {
- closedir($this->dirSource);
- }
-
- public function dir_rewinddir() {
- rewinddir($this->dirSource);
- }
-}
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php
index fa6ba20c342..f36e2c2c64f 100644
--- a/lib/private/Files/View.php
+++ b/lib/private/Files/View.php
@@ -1357,7 +1357,7 @@ class View {
$subStorage = $mount->getStorage();
if ($subStorage) {
// exclude shared storage ?
- if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) {
+ if ($extOnly && $subStorage instanceof \OCA\Files_Sharing\SharedStorage) {
continue;
}
$subCache = $subStorage->getCache('');
@@ -1806,13 +1806,15 @@ class View {
throw new InvalidPathException($l10n->t('Dot files are not allowed'));
}
- // verify database - e.g. mysql only 3-byte chars
- if (preg_match('%(?:
+ if (!\OC::$server->getDatabaseConnection()->supports4ByteText()) {
+ // verify database - e.g. mysql only 3-byte chars
+ if (preg_match('%(?:
\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)%xs', $fileName)) {
- throw new InvalidPathException($l10n->t('4-byte characters are not supported in file names'));
+ throw new InvalidPathException($l10n->t('4-byte characters are not supported in file names'));
+ }
}
try {
diff --git a/lib/private/LargeFileHelper.php b/lib/private/LargeFileHelper.php
index 9d0fe864033..9f18a6acd6b 100644
--- a/lib/private/LargeFileHelper.php
+++ b/lib/private/LargeFileHelper.php
@@ -1,6 +1,7 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
*
* @author Andreas Fischer <bantu@owncloud.com>
* @author Lukas Reschke <lukas@statuscode.ch>
@@ -51,7 +52,7 @@ class LargeFileHelper {
public function __construct() {
$pow_2_53 = floatval(self::POW_2_53_MINUS_1) + 1.0;
if ($this->formatUnsignedInteger($pow_2_53) !== self::POW_2_53) {
- throw new \RunTimeException(
+ throw new \RuntimeException(
'This class assumes floats to be double precision or "better".'
);
}
@@ -98,10 +99,6 @@ class LargeFileHelper {
if (!is_null($fileSize)) {
return $fileSize;
}
- $fileSize = $this->getFileSizeViaCOM($filename);
- if (!is_null($fileSize)) {
- return $fileSize;
- }
$fileSize = $this->getFileSizeViaExec($filename);
if (!is_null($fileSize)) {
return $fileSize;
@@ -154,12 +151,6 @@ class LargeFileHelper {
$result = $this->exec("stat -c %s $arg");
} else if (strpos($os, 'bsd') !== false || strpos($os, 'darwin') !== false) {
$result = $this->exec("stat -f %z $arg");
- } else if (strpos($os, 'win') !== false) {
- $result = $this->exec("for %F in ($arg) do @echo %~zF");
- if (is_null($result)) {
- // PowerShell
- $result = $this->exec("(Get-Item $arg).length");
- }
}
return $result;
}
@@ -187,6 +178,23 @@ class LargeFileHelper {
return $result;
}
+ /**
+ * Returns the current mtime for $fullPath
+ *
+ * @param string $fullPath
+ * @return int
+ */
+ public function getFileMtime($fullPath) {
+ if (\OC_Helper::is_function_enabled('exec')) {
+ $os = strtolower(php_uname('s'));
+ if (strpos($os, 'linux') !== false) {
+ return $this->exec('stat -c %Y ' . escapeshellarg($fullPath));
+ }
+ }
+
+ return filemtime($fullPath);
+ }
+
protected function exec($cmd) {
$result = trim(exec($cmd));
return ctype_digit($result) ? 0 + $result : null;
diff --git a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
new file mode 100644
index 00000000000..284700566d6
--- /dev/null
+++ b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Security\CSP;
+
+use OC\AppFramework\Http\Request;
+use OC\Security\CSRF\CsrfTokenManager;
+use OCP\IRequest;
+
+/**
+ * @package OC\Security\CSP
+ */
+class ContentSecurityPolicyNonceManager {
+ /** @var CsrfTokenManager */
+ private $csrfTokenManager;
+ /** @var IRequest */
+ private $request;
+ /** @var string */
+ private $nonce = '';
+
+ /**
+ * @param CsrfTokenManager $csrfTokenManager
+ * @param IRequest $request
+ */
+ public function __construct(CsrfTokenManager $csrfTokenManager,
+ IRequest $request) {
+ $this->csrfTokenManager = $csrfTokenManager;
+ $this->request = $request;
+ }
+
+ /**
+ * Returns the current CSP nounce
+ *
+ * @return string
+ */
+ public function getNonce() {
+ if($this->nonce === '') {
+ $this->nonce = base64_encode($this->csrfTokenManager->getToken()->getEncryptedValue());
+ }
+
+ return $this->nonce;
+ }
+
+ /**
+ * Check if the browser supports CSP v3
+ *
+ * @return bool
+ */
+ public function browserSupportsCspV3() {
+ $browserWhitelist = [
+ Request::USER_AGENT_CHROME,
+ // Firefox 45+
+ '/^Mozilla\/5\.0 \([^)]+\) Gecko\/[0-9.]+ Firefox\/(4[5-9]|[5-9][0-9])\.[0-9.]+$/',
+ // Safari 10+
+ '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Version\/1[0-9.]+ Safari\/[0-9.A-Z]+$/',
+ ];
+
+ if($this->request->isUserAgent($browserWhitelist)) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/lib/private/Security/CSRF/CsrfToken.php b/lib/private/Security/CSRF/CsrfToken.php
index bf61e339f77..dce9a83b727 100644
--- a/lib/private/Security/CSRF/CsrfToken.php
+++ b/lib/private/Security/CSRF/CsrfToken.php
@@ -33,6 +33,8 @@ namespace OC\Security\CSRF;
class CsrfToken {
/** @var string */
private $value;
+ /** @var string */
+ private $encryptedValue = '';
/**
* @param string $value Value of the token. Can be encrypted or not encrypted.
@@ -48,8 +50,12 @@ class CsrfToken {
* @return string
*/
public function getEncryptedValue() {
- $sharedSecret = base64_encode(random_bytes(strlen($this->value)));
- return base64_encode($this->value ^ $sharedSecret) .':'.$sharedSecret;
+ if($this->encryptedValue === '') {
+ $sharedSecret = base64_encode(random_bytes(strlen($this->value)));
+ $this->encryptedValue = base64_encode($this->value ^ $sharedSecret) . ':' . $sharedSecret;
+ }
+
+ return $this->encryptedValue;
}
/**
diff --git a/lib/private/Security/CSRF/CsrfTokenManager.php b/lib/private/Security/CSRF/CsrfTokenManager.php
index d621cc2c29f..b43ca3d3679 100644
--- a/lib/private/Security/CSRF/CsrfTokenManager.php
+++ b/lib/private/Security/CSRF/CsrfTokenManager.php
@@ -34,6 +34,8 @@ class CsrfTokenManager {
private $tokenGenerator;
/** @var SessionStorage */
private $sessionStorage;
+ /** @var CsrfToken|null */
+ private $csrfToken = null;
/**
* @param CsrfTokenGenerator $tokenGenerator
@@ -51,6 +53,10 @@ class CsrfTokenManager {
* @return CsrfToken
*/
public function getToken() {
+ if(!is_null($this->csrfToken)) {
+ return $this->csrfToken;
+ }
+
if($this->sessionStorage->hasToken()) {
$value = $this->sessionStorage->getToken();
} else {
@@ -58,7 +64,8 @@ class CsrfTokenManager {
$this->sessionStorage->setToken($value);
}
- return new CsrfToken($value);
+ $this->csrfToken = new CsrfToken($value);
+ return $this->csrfToken;
}
/**
@@ -69,13 +76,15 @@ class CsrfTokenManager {
public function refreshToken() {
$value = $this->tokenGenerator->generateToken();
$this->sessionStorage->setToken($value);
- return new CsrfToken($value);
+ $this->csrfToken = new CsrfToken($value);
+ return $this->csrfToken;
}
/**
* Remove the current token from the storage.
*/
public function removeToken() {
+ $this->csrfToken = null;
$this->sessionStorage->removeToken();
}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 11558118d52..21ec311401d 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -73,6 +73,7 @@ use OC\Security\Bruteforce\Throttler;
use OC\Security\CertificateManager;
use OC\Security\CSP\ContentSecurityPolicyManager;
use OC\Security\Crypto;
+use OC\Security\CSP\ContentSecurityPolicyNonceManager;
use OC\Security\CSRF\CsrfTokenGenerator;
use OC\Security\CSRF\CsrfTokenManager;
use OC\Security\CSRF\TokenStorage\SessionStorage;
@@ -708,6 +709,12 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService('ContentSecurityPolicyManager', function (Server $c) {
return new ContentSecurityPolicyManager();
});
+ $this->registerService('ContentSecurityPolicyNonceManager', function(Server $c) {
+ return new ContentSecurityPolicyNonceManager(
+ $c->getCsrfTokenManager(),
+ $c->getRequest()
+ );
+ });
$this->registerService('ShareManager', function(Server $c) {
$config = $c->getConfig();
$factoryClass = $config->getSystemValue('sharing.managerFactory', '\OC\Share20\ProviderFactory');
@@ -1406,6 +1413,13 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
+ * @return ContentSecurityPolicyNonceManager
+ */
+ public function getContentSecurityPolicyNonceManager() {
+ return $this->query('ContentSecurityPolicyNonceManager');
+ }
+
+ /**
* Not a public API as of 8.2, wait for 9.0
*
* @return \OCA\Files_External\Service\BackendService
diff --git a/lib/private/Share/MailNotifications.php b/lib/private/Share/MailNotifications.php
index aaecd5353e5..1bbd365699c 100644
--- a/lib/private/Share/MailNotifications.php
+++ b/lib/private/Share/MailNotifications.php
@@ -89,75 +89,6 @@ class MailNotifications {
}
/**
- * inform users if a file was shared with them
- *
- * @param IUser[] $recipientList list of recipients
- * @param string $itemSource shared item source
- * @param string $itemType shared item type
- * @return array list of user to whom the mail send operation failed
- */
- public function sendInternalShareMail($recipientList, $itemSource, $itemType) {
- $noMail = [];
-
- foreach ($recipientList as $recipient) {
- $recipientDisplayName = $recipient->getDisplayName();
- $to = $recipient->getEMailAddress();
-
- if ($to === '') {
- $noMail[] = $recipientDisplayName;
- continue;
- }
-
- $items = $this->getItemSharedWithUser($itemSource, $itemType, $recipient);
- $filename = trim($items[0]['file_target'], '/');
- $subject = (string) $this->l->t('%s shared »%s« with you', array($this->senderDisplayName, $filename));
- $expiration = null;
- if (isset($items[0]['expiration'])) {
- try {
- $date = new DateTime($items[0]['expiration']);
- $expiration = $date->getTimestamp();
- } catch (\Exception $e) {
- $this->logger->error("Couldn't read date: ".$e->getMessage(), ['app' => 'sharing']);
- }
- }
-
- $link = $this->urlGenerator->linkToRouteAbsolute(
- 'files.viewcontroller.showFile',
- ['fileId' => $items[0]['item_source']]
- );
-
- list($htmlBody, $textBody) = $this->createMailBody($filename, $link, $expiration, 'internal');
-
- // send it out now
- try {
- $message = $this->mailer->createMessage();
- $message->setSubject($subject);
- $message->setTo([$to => $recipientDisplayName]);
- $message->setHtmlBody($htmlBody);
- $message->setPlainBody($textBody);
- $message->setFrom([
- Util::getDefaultEmailAddress('sharing-noreply') =>
- (string)$this->l->t('%s via %s', [
- $this->senderDisplayName,
- $this->defaults->getName()
- ]),
- ]);
- if(!is_null($this->replyTo)) {
- $message->setReplyTo([$this->replyTo]);
- }
-
- $this->mailer->send($message);
- } catch (\Exception $e) {
- $this->logger->error("Can't send mail to inform the user about an internal share: ".$e->getMessage(), ['app' => 'sharing']);
- $noMail[] = $recipientDisplayName;
- }
- }
-
- return $noMail;
-
- }
-
- /**
* inform recipient about public link share
*
* @param string $recipient recipient email address
@@ -224,15 +155,4 @@ class MailNotifications {
return [$htmlMail, $plainTextMail];
}
-
- /**
- * @param string $itemSource
- * @param string $itemType
- * @param IUser $recipient
- * @return array
- */
- protected function getItemSharedWithUser($itemSource, $itemType, $recipient) {
- return Share::getItemSharedWithUser($itemType, $itemSource, $recipient->getUID());
- }
-
}
diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php
index 9210dfd1fd1..33801cd6347 100644
--- a/lib/private/Share/Share.php
+++ b/lib/private/Share/Share.php
@@ -1059,7 +1059,7 @@ class Share extends Constants {
if (isset($groupShare['file_target'])) {
$shareTmp['fileTarget'] = $groupShare['file_target'];
}
- $listOfUnsharedItems = array_merge($listOfUnsharedItems, array($groupShare));
+ $listOfUnsharedItems = array_merge($listOfUnsharedItems, [$shareTmp]);
$itemUnshared = true;
} elseif (!$itemUnshared && isset($uniqueGroupShare)) {
$query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?');
@@ -1074,7 +1074,7 @@ class Share extends Constants {
if (isset($uniqueGroupShare['file_target'])) {
$shareTmp['fileTarget'] = $uniqueGroupShare['file_target'];
}
- $listOfUnsharedItems = array_merge($listOfUnsharedItems, array($uniqueGroupShare));
+ $listOfUnsharedItems = array_merge($listOfUnsharedItems, [$shareTmp]);
$itemUnshared = true;
}
diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php
new file mode 100644
index 00000000000..a7f8c251cee
--- /dev/null
+++ b/lib/private/Template/JSConfigHelper.php
@@ -0,0 +1,243 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OC\Template;
+
+use bantu\IniGetWrapper\IniGetWrapper;
+use OCP\App\IAppManager;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+use OCP\IUser;
+
+class JSConfigHelper {
+
+ /** @var IL10N */
+ private $l;
+
+ /** @var \OC_Defaults */
+ private $defaults;
+
+ /** @var IAppManager */
+ private $appManager;
+
+ /** @var IUser */
+ private $currentUser;
+
+ /** @var IConfig */
+ private $config;
+
+ /** @var IGroupManager */
+ private $groupManager;
+
+ /** @var IniGetWrapper */
+ private $iniWrapper;
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ /**
+ * @param IL10N $l
+ * @param \OC_Defaults $defaults
+ * @param IAppManager $appManager
+ * @param IUser|null $currentUser
+ * @param IConfig $config
+ * @param IGroupManager $groupManager
+ * @param IniGetWrapper $iniWrapper
+ * @param IURLGenerator $urlGenerator
+ */
+ public function __construct(IL10N $l,
+ \OC_Defaults $defaults,
+ IAppManager $appManager,
+ $currentUser,
+ IConfig $config,
+ IGroupManager $groupManager,
+ IniGetWrapper $iniWrapper,
+ IURLGenerator $urlGenerator) {
+ $this->l = $l;
+ $this->defaults = $defaults;
+ $this->appManager = $appManager;
+ $this->currentUser = $currentUser;
+ $this->config = $config;
+ $this->groupManager = $groupManager;
+ $this->iniWrapper = $iniWrapper;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ public function getConfig() {
+
+ if ($this->currentUser !== null) {
+ $uid = $this->currentUser->getUID();
+ } else {
+ $uid = null;
+ }
+
+ // Get the config
+ $apps_paths = [];
+
+ if ($this->currentUser === null) {
+ $apps = $this->appManager->getInstalledApps();
+ } else {
+ $apps = $this->appManager->getEnabledAppsForUser($this->currentUser);
+ }
+
+ foreach($apps as $app) {
+ $apps_paths[$app] = \OC_App::getAppWebPath($app);
+ }
+
+ $defaultExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
+ $defaultExpireDate = $enforceDefaultExpireDate = null;
+ if ($defaultExpireDateEnabled) {
+ $defaultExpireDate = (int) $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
+ $enforceDefaultExpireDate = $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
+ }
+ $outgoingServer2serverShareEnabled = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
+
+ $countOfDataLocation = 0;
+ $dataLocation = str_replace(\OC::$SERVERROOT .'/', '', $this->config->getSystemValue('datadirectory', ''), $countOfDataLocation);
+ if($countOfDataLocation !== 1 || !$this->groupManager->isAdmin($uid)) {
+ $dataLocation = false;
+ }
+
+ $array = [
+ "oc_debug" => $this->config->getSystemValue('debug', false) ? 'true' : 'false',
+ "oc_isadmin" => $this->groupManager->isAdmin($uid) ? 'true' : 'false',
+ "oc_dataURL" => is_string($dataLocation) ? "\"".$dataLocation."\"" : 'false',
+ "oc_webroot" => "\"".\OC::$WEBROOT."\"",
+ "oc_appswebroots" => str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution
+ "datepickerFormatDate" => json_encode($this->l->l('jsdate', null)),
+ "dayNames" => json_encode([
+ (string)$this->l->t('Sunday'),
+ (string)$this->l->t('Monday'),
+ (string)$this->l->t('Tuesday'),
+ (string)$this->l->t('Wednesday'),
+ (string)$this->l->t('Thursday'),
+ (string)$this->l->t('Friday'),
+ (string)$this->l->t('Saturday')
+ ]),
+ "dayNamesShort" => json_encode([
+ (string)$this->l->t('Sun.'),
+ (string)$this->l->t('Mon.'),
+ (string)$this->l->t('Tue.'),
+ (string)$this->l->t('Wed.'),
+ (string)$this->l->t('Thu.'),
+ (string)$this->l->t('Fri.'),
+ (string)$this->l->t('Sat.')
+ ]),
+ "dayNamesMin" => json_encode([
+ (string)$this->l->t('Su'),
+ (string)$this->l->t('Mo'),
+ (string)$this->l->t('Tu'),
+ (string)$this->l->t('We'),
+ (string)$this->l->t('Th'),
+ (string)$this->l->t('Fr'),
+ (string)$this->l->t('Sa')
+ ]),
+ "monthNames" => json_encode([
+ (string)$this->l->t('January'),
+ (string)$this->l->t('February'),
+ (string)$this->l->t('March'),
+ (string)$this->l->t('April'),
+ (string)$this->l->t('May'),
+ (string)$this->l->t('June'),
+ (string)$this->l->t('July'),
+ (string)$this->l->t('August'),
+ (string)$this->l->t('September'),
+ (string)$this->l->t('October'),
+ (string)$this->l->t('November'),
+ (string)$this->l->t('December')
+ ]),
+ "monthNamesShort" => json_encode([
+ (string)$this->l->t('Jan.'),
+ (string)$this->l->t('Feb.'),
+ (string)$this->l->t('Mar.'),
+ (string)$this->l->t('Apr.'),
+ (string)$this->l->t('May.'),
+ (string)$this->l->t('Jun.'),
+ (string)$this->l->t('Jul.'),
+ (string)$this->l->t('Aug.'),
+ (string)$this->l->t('Sep.'),
+ (string)$this->l->t('Oct.'),
+ (string)$this->l->t('Nov.'),
+ (string)$this->l->t('Dec.')
+ ]),
+ "firstDay" => json_encode($this->l->l('firstday', null)) ,
+ "oc_config" => json_encode([
+ 'session_lifetime' => min($this->config->getSystemValue('session_lifetime', $this->iniWrapper->getNumeric('session.gc_maxlifetime')), $this->iniWrapper->getNumeric('session.gc_maxlifetime')),
+ 'session_keepalive' => $this->config->getSystemValue('session_keepalive', true),
+ 'version' => implode('.', \OCP\Util::getVersion()),
+ 'versionstring' => \OC_Util::getVersionString(),
+ 'enable_avatars' => $this->config->getSystemValue('enable_avatars', true) === true,
+ 'lost_password_link'=> $this->config->getSystemValue('lost_password_link', null),
+ 'modRewriteWorking' => (getenv('front_controller_active') === 'true'),
+ ]),
+ "oc_appconfig" => json_encode([
+ 'core' => [
+ 'defaultExpireDateEnabled' => $defaultExpireDateEnabled,
+ 'defaultExpireDate' => $defaultExpireDate,
+ 'defaultExpireDateEnforced' => $enforceDefaultExpireDate,
+ 'enforcePasswordForPublicLink' => \OCP\Util::isPublicLinkPasswordRequired(),
+ 'sharingDisabledForUser' => \OCP\Util::isSharingDisabledForUser(),
+ 'resharingAllowed' => \OCP\Share::isResharingAllowed(),
+ 'remoteShareAllowed' => $outgoingServer2serverShareEnabled,
+ 'federatedCloudShareDoc' => $this->urlGenerator->linkToDocs('user-sharing-federated'),
+ 'allowGroupSharing' => \OC::$server->getShareManager()->allowGroupSharing()
+ ]
+ ]),
+ "oc_defaults" => json_encode([
+ 'entity' => $this->defaults->getEntity(),
+ 'name' => $this->defaults->getName(),
+ 'title' => $this->defaults->getTitle(),
+ 'baseUrl' => $this->defaults->getBaseUrl(),
+ 'syncClientUrl' => $this->defaults->getSyncClientUrl(),
+ 'docBaseUrl' => $this->defaults->getDocBaseUrl(),
+ 'docPlaceholderUrl' => $this->defaults->buildDocLinkToKey('PLACEHOLDER'),
+ 'slogan' => $this->defaults->getSlogan(),
+ 'logoClaim' => $this->defaults->getLogoClaim(),
+ 'shortFooter' => $this->defaults->getShortFooter(),
+ 'longFooter' => $this->defaults->getLongFooter(),
+ 'folder' => \OC_Util::getTheme(),
+ ]),
+ ];
+
+ if ($this->currentUser !== null) {
+ $array['oc_userconfig'] = json_encode([
+ 'avatar' => [
+ 'version' => (int)$this->config->getUserValue($uid, 'avatar', 'version', 0),
+ ]
+ ]);
+ }
+
+ // Allow hooks to modify the output values
+ \OC_Hook::emit('\OCP\Config', 'js', array('array' => &$array));
+
+ $result = '';
+
+ // Echo it
+ foreach ($array as $setting => $value) {
+ $result .= 'var '. $setting . '='. $value . ';' . PHP_EOL;
+ }
+
+ return $result;
+ }
+}
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index da845d80d04..9f89174e7f9 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -43,6 +43,7 @@ use Assetic\Filter\CssMinFilter;
use Assetic\Filter\CssRewriteFilter;
use Assetic\Filter\JSqueezeFilter;
use Assetic\Filter\SeparatorFilter;
+use OC\Template\JSConfigHelper;
class TemplateLayout extends \OC_Template {
@@ -142,7 +143,22 @@ class TemplateLayout extends \OC_Template {
$jsFiles = self::findJavascriptFiles(\OC_Util::$scripts);
$this->assign('jsfiles', array());
if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
- $this->append( 'jsfiles', \OC::$server->getURLGenerator()->linkToRoute('js_config', ['v' => self::$versionHash]));
+ if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
+ $jsConfigHelper = new JSConfigHelper(
+ \OC::$server->getL10N('core'),
+ \OC::$server->getThemingDefaults(),
+ \OC::$server->getAppManager(),
+ \OC::$server->getUserSession()->getUser(),
+ \OC::$server->getConfig(),
+ \OC::$server->getGroupManager(),
+ \OC::$server->getIniWrapper(),
+ \OC::$server->getURLGenerator()
+ );
+ $this->assign('inline_ocjs', $jsConfigHelper->getConfig());
+ $this->assign('foo', 'bar');
+ } else {
+ $this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash]));
+ }
}
foreach($jsFiles as $info) {
$web = $info[1];
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 4b56609ccfc..a213ee48c2a 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -362,6 +362,9 @@ class Session implements IUserSession, Emitter {
$user = $this->manager->get($username);
if (is_null($user)) {
$users = $this->manager->getByEmail($username);
+ if (empty($users)) {
+ return false;
+ }
if (count($users) !== 1) {
return true;
}
diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php
index 5e05884f5c0..d25534aa822 100644
--- a/lib/private/legacy/app.php
+++ b/lib/private/legacy/app.php
@@ -334,9 +334,16 @@ class OC_App {
* This function set an app as enabled in appconfig.
*/
public static function enable($app, $groups = null) {
- self::$enabledAppsCache = array(); // flush
+ self::$enabledAppsCache = []; // flush
if (!Installer::isInstalled($app)) {
$app = self::installApp($app);
+ } else {
+ // check for required dependencies
+ $config = \OC::$server->getConfig();
+ $l = \OC::$server->getL10N('core');
+ $info = self::getAppInfo($app);
+
+ self::checkAppDependencies($config, $l, $info);
}
$appManager = \OC::$server->getAppManager();
@@ -1186,16 +1193,7 @@ class OC_App {
}
// check for required dependencies
- $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
- $missing = $dependencyAnalyzer->analyze($info);
- if (!empty($missing)) {
- $missingMsg = join(PHP_EOL, $missing);
- throw new \Exception(
- $l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
- array($info['name'], $missingMsg)
- )
- );
- }
+ self::checkAppDependencies($config, $l, $info);
$config->setAppValue($app, 'enabled', 'yes');
if (isset($appData['id'])) {
@@ -1438,4 +1436,23 @@ class OC_App {
return $data;
}
+
+ /**
+ * @param $config
+ * @param $l
+ * @param $info
+ * @throws Exception
+ */
+ protected static function checkAppDependencies($config, $l, $info) {
+ $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
+ $missing = $dependencyAnalyzer->analyze($info);
+ if (!empty($missing)) {
+ $missingMsg = join(PHP_EOL, $missing);
+ throw new \Exception(
+ $l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
+ [$info['name'], $missingMsg]
+ )
+ );
+ }
+ }
}
diff --git a/lib/private/legacy/helper.php b/lib/private/legacy/helper.php
index 0b9477dacd4..9c4bc895fb9 100644
--- a/lib/private/legacy/helper.php
+++ b/lib/private/legacy/helper.php
@@ -254,16 +254,9 @@ class OC_Helper {
if ($path === false) {
$path = getenv("PATH");
}
- // check method depends on operating system
- if (!strncmp(PHP_OS, "WIN", 3)) {
- // on Windows an appropriate COM or EXE file needs to exist
- $exts = array(".exe", ".com");
- $check_fn = "file_exists";
- } else {
- // anywhere else we look for an executable file of that name
- $exts = array("");
- $check_fn = "is_executable";
- }
+ // we look for an executable file of that name
+ $exts = [""];
+ $check_fn = "is_executable";
// Default check will be done with $path directories :
$dirs = explode(PATH_SEPARATOR, $path);
// WARNING : We have to check if open_basedir is enabled :
@@ -498,7 +491,6 @@ class OC_Helper {
/**
* Try to find a program
- * Note: currently windows is not supported
*
* @param string $program
* @return null|string
@@ -557,7 +549,7 @@ class OC_Helper {
$quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
$storage = $rootInfo->getStorage();
$sourceStorage = $storage;
- if ($storage->instanceOfStorage('\OC\Files\Storage\Shared')) {
+ if ($storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
$includeExtStorage = false;
$sourceStorage = $storage->getSourceStorage();
}
diff --git a/lib/private/legacy/image.php b/lib/private/legacy/image.php
index fee1a805c40..5403cccd026 100644
--- a/lib/private/legacy/image.php
+++ b/lib/private/legacy/image.php
@@ -54,6 +54,8 @@ class OC_Image implements \OCP\IImage {
private $fileInfo;
/** @var \OCP\ILogger */
private $logger;
+ /** @var array */
+ private $exif;
/**
* Get mime type for an image file.
@@ -347,6 +349,10 @@ class OC_Image implements \OCP\IImage {
* @return int The orientation or -1 if no EXIF data is available.
*/
public function getOrientation() {
+ if ($this->exif !== null) {
+ return $this->exif['Orientation'];
+ }
+
if ($this->imageType !== IMAGETYPE_JPEG) {
$this->logger->debug('OC_Image->fixOrientation() Image is not a JPEG.', array('app' => 'core'));
return -1;
@@ -370,9 +376,30 @@ class OC_Image implements \OCP\IImage {
if (!isset($exif['Orientation'])) {
return -1;
}
+ $this->exif = $exif;
return $exif['Orientation'];
}
+ public function readExif($data) {
+ if (!is_callable('exif_read_data')) {
+ $this->logger->debug('OC_Image->fixOrientation() Exif module not enabled.', array('app' => 'core'));
+ return;
+ }
+ if (!$this->valid()) {
+ $this->logger->debug('OC_Image->fixOrientation() No image loaded.', array('app' => 'core'));
+ return;
+ }
+
+ $exif = @exif_read_data('data://image/jpeg;base64,' . base64_encode($data));
+ if (!$exif) {
+ return;
+ }
+ if (!isset($exif['Orientation'])) {
+ return;
+ }
+ $this->exif = $exif;
+ }
+
/**
* (I'm open for suggestions on better method name ;)
* Fixes orientation based on EXIF data.
diff --git a/lib/private/legacy/response.php b/lib/private/legacy/response.php
index 0ec27251ba5..69c84e2df68 100644
--- a/lib/private/legacy/response.php
+++ b/lib/private/legacy/response.php
@@ -33,6 +33,7 @@ class OC_Response {
const STATUS_NOT_MODIFIED = 304;
const STATUS_TEMPORARY_REDIRECT = 307;
const STATUS_BAD_REQUEST = 400;
+ const STATUS_FORBIDDEN = 403;
const STATUS_NOT_FOUND = 404;
const STATUS_INTERNAL_SERVER_ERROR = 500;
const STATUS_SERVICE_UNAVAILABLE = 503;
@@ -246,7 +247,7 @@ class OC_Response {
* @see \OCP\AppFramework\Http\Response::getHeaders
*/
$policy = 'default-src \'self\'; '
- . 'script-src \'self\' \'unsafe-eval\'; '
+ . 'script-src \'self\' \'unsafe-eval\' \'nonce-'.\OC::$server->getContentSecurityPolicyNonceManager()->getNonce().'\'; '
. 'style-src \'self\' \'unsafe-inline\'; '
. 'frame-src *; '
. 'img-src * data: blob:; '
diff --git a/lib/private/legacy/template.php b/lib/private/legacy/template.php
index 67a8b3ec6e1..7c0b58db0c0 100644
--- a/lib/private/legacy/template.php
+++ b/lib/private/legacy/template.php
@@ -117,7 +117,7 @@ class OC_Template extends \OC\Template\Base {
OC_Util::addStyle("fonts",null,true);
OC_Util::addStyle("icons",null,true);
OC_Util::addStyle("header",null,true);
- OC_Util::addStyle("inputs",null,true);
+ OC_Util::addStyle("inputs");
OC_Util::addStyle("styles",null,true);
// avatars
@@ -126,6 +126,10 @@ class OC_Template extends \OC\Template\Base {
\OC_Util::addScript('placeholder', null, true);
}
+ OC_Util::addVendorScript('select2/select2');
+ OC_Util::addVendorStyle('select2/select2', null, true);
+ OC_Util::addScript('select2-toggleselect');
+
OC_Util::addScript('oc-backbone', null, true);
OC_Util::addVendorScript('core', 'backbone/backbone', true);
OC_Util::addVendorScript('snapjs/dist/latest/snap', null, true);
@@ -135,6 +139,7 @@ class OC_Template extends \OC\Template\Base {
OC_Util::addScript("oc-requesttoken", null, true);
OC_Util::addScript('search', 'search', true);
OC_Util::addScript("config", null, true);
+ OC_Util::addScript("public/appconfig", null, true);
OC_Util::addScript("eventsource", null, true);
OC_Util::addScript("octemplate", null, true);
OC_Util::addTranslations("core", null, true);
@@ -143,7 +148,6 @@ class OC_Template extends \OC\Template\Base {
OC_Util::addScript("oc-dialogs", null, true);
OC_Util::addScript("jquery.ocdialog", null, true);
OC_Util::addStyle("jquery.ocdialog");
- OC_Util::addScript("compatibility", null, true);
OC_Util::addScript('files/fileinfo');
OC_Util::addScript('files/client');
diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php
index b8f3a93ba50..42fd0ba7db3 100644
--- a/lib/private/legacy/util.php
+++ b/lib/private/legacy/util.php
@@ -165,15 +165,14 @@ class OC_Util {
// install storage availability wrapper, before most other wrappers
\OC\Files\Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, $storage) {
- /** @var \OCP\Files\Storage $storage */
- if (!$storage->instanceOfStorage('\OC\Files\Storage\Shared') && !$storage->isLocal()) {
+ if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
return new \OC\Files\Storage\Wrapper\Availability(['storage' => $storage]);
}
return $storage;
});
\OC\Files\Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OC\Files\Storage\Shared') && !$storage->isLocal()) {
+ if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
return new \OC\Files\Storage\Wrapper\Encoding(['storage' => $storage]);
}
return $storage;
@@ -668,15 +667,6 @@ class OC_Util {
$webServerRestart = true;
}
- // Check if server running on Windows platform
- if(OC_Util::runningOnWindows()) {
- $errors[] = [
- 'error' => $l->t('Microsoft Windows Platform is not supported'),
- 'hint' => $l->t('Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you ' .
- 'use a Linux server in a virtual machine if you have no option for migrating the server itself.')
- ];
- }
-
// Check if config folder is writable.
if(!OC_Helper::isReadOnlyConfigEnabled()) {
if (!is_writable(OC::$configDir) or !is_readable(OC::$configDir)) {
@@ -1269,15 +1259,6 @@ class OC_Util {
}
/**
- * Checks whether the server is running on Windows
- *
- * @return bool true if running on Windows, false otherwise
- */
- public static function runningOnWindows() {
- return (substr(PHP_OS, 0, 3) === "WIN");
- }
-
- /**
* Checks whether the server is running on Mac OS X
*
* @return bool true if running on Mac OS X, false otherwise