Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a3f245359b | |||
| 6d110f5059 | |||
| acf629d31c | |||
| 36614e023f | |||
| 8725a904b8 | |||
| 31861e0162 | |||
| 1405ee194c | |||
| aab803f8dc | |||
| 91540a84ba | |||
| 5e337d28e6 | |||
| 90146ee6fa | |||
| 4d08ffe5a9 | |||
| 1ee9a07912 | |||
| 1d301dd4ba | |||
| cd5c190de2 |
@@ -0,0 +1,49 @@
|
||||
localhost {
|
||||
php_server {
|
||||
worker index.php
|
||||
}
|
||||
|
||||
log {
|
||||
level ERROR
|
||||
output stderr
|
||||
}
|
||||
|
||||
encode gzip
|
||||
|
||||
redir /.well-known/carddav /remote.php/dav 301
|
||||
redir /.well-known/caldav /remote.php/dav 301
|
||||
|
||||
# Rule: Maps most RFC 8615 compliant well-known URIs to our main frontend controller (/index.php) by default
|
||||
@wellKnown {
|
||||
path "/.well-known/"
|
||||
not {
|
||||
path /.well-known/acme-challenge
|
||||
path /.well-known/pki-validation
|
||||
}
|
||||
}
|
||||
rewrite @wellKnown /index.php
|
||||
|
||||
rewrite /ocm-provider/ /index.php
|
||||
|
||||
@forbidden {
|
||||
path /.htaccess
|
||||
path /data/*
|
||||
path /config/*
|
||||
path /db_structure
|
||||
path /.xml
|
||||
path /README
|
||||
path /3rdparty/*
|
||||
path /lib/*
|
||||
path /templates/*
|
||||
path /occ
|
||||
path /build
|
||||
path /tests
|
||||
path /console.php
|
||||
path /autotest
|
||||
path /issue
|
||||
path /indi
|
||||
path /db_
|
||||
path /console
|
||||
}
|
||||
respond @forbidden 404
|
||||
}
|
||||
@@ -16,6 +16,11 @@
|
||||
<types>
|
||||
<authentication/>
|
||||
</types>
|
||||
|
||||
<commands>
|
||||
<command>OCA\Testing\Command\StaticHunt</command>
|
||||
</commands>
|
||||
|
||||
<category>monitoring</category>
|
||||
<bugs>https://github.com/nextcloud/server/issues</bugs>
|
||||
<dependencies>
|
||||
|
||||
@@ -9,6 +9,7 @@ return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'OCA\\Testing\\AlternativeHomeUserBackend' => $baseDir . '/../lib/AlternativeHomeUserBackend.php',
|
||||
'OCA\\Testing\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
|
||||
'OCA\\Testing\\Command\\StaticHunt' => $baseDir . '/../lib/Command/StaticHunt.php',
|
||||
'OCA\\Testing\\Controller\\ConfigController' => $baseDir . '/../lib/Controller/ConfigController.php',
|
||||
'OCA\\Testing\\Controller\\LockingController' => $baseDir . '/../lib/Controller/LockingController.php',
|
||||
'OCA\\Testing\\Controller\\RateLimitTestController' => $baseDir . '/../lib/Controller/RateLimitTestController.php',
|
||||
|
||||
@@ -24,6 +24,7 @@ class ComposerStaticInitTesting
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'OCA\\Testing\\AlternativeHomeUserBackend' => __DIR__ . '/..' . '/../lib/AlternativeHomeUserBackend.php',
|
||||
'OCA\\Testing\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
|
||||
'OCA\\Testing\\Command\\StaticHunt' => __DIR__ . '/..' . '/../lib/Command/StaticHunt.php',
|
||||
'OCA\\Testing\\Controller\\ConfigController' => __DIR__ . '/..' . '/../lib/Controller/ConfigController.php',
|
||||
'OCA\\Testing\\Controller\\LockingController' => __DIR__ . '/..' . '/../lib/Controller/LockingController.php',
|
||||
'OCA\\Testing\\Controller\\RateLimitTestController' => __DIR__ . '/..' . '/../lib/Controller/RateLimitTestController.php',
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Testing\Command;
|
||||
|
||||
use OCP\App\IAppManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class StaticHunt extends Command {
|
||||
private const array SKIP_REGEX = [
|
||||
'@/templates/.+.php$@',
|
||||
'@/ajax/.+.php$@',
|
||||
'@/register_command.php$@',
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
private IAppManager $appManager,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure() {
|
||||
$this
|
||||
->setName('testing:static-hunt')
|
||||
->setDescription('Hunt for static properties in classes');
|
||||
}
|
||||
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
$folders = [
|
||||
'' => __DIR__ . '/../../../../lib/private/legacy',
|
||||
'\\OC' => __DIR__ . '/../../../../lib/private',
|
||||
'\\OC\\Core' => __DIR__ . '/../../../../core',
|
||||
];
|
||||
$apps = $this->appManager->getAllAppsInAppsFolders();
|
||||
foreach ($apps as $app) {
|
||||
$info = $this->appManager->getAppInfo($app);
|
||||
if (!isset($info['namespace'])) {
|
||||
continue;
|
||||
}
|
||||
$folders['\\OCA\\' . $info['namespace']] = $this->appManager->getAppPath($app) . '/lib';
|
||||
}
|
||||
$stats = [
|
||||
'classes' => 0,
|
||||
'properties' => 0,
|
||||
];
|
||||
foreach ($folders as $namespace => $folder) {
|
||||
$this->scanFolder($folder, $namespace, $output, $stats);
|
||||
}
|
||||
|
||||
$output->writeln('<info>Found ' . $stats['properties'] . ' static properties spread among ' . $stats['classes'] . ' classes</info>');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function scanFolder(string $folder, string $namespace, OutputInterface $output, array &$stats): void {
|
||||
$folder = realpath($folder);
|
||||
$output->writeln('Folder ' . $folder, OutputInterface::VERBOSITY_VERBOSE);
|
||||
foreach ($this->recursiveGlob($folder) as $filename) {
|
||||
try {
|
||||
$filename = realpath($filename);
|
||||
if (($namespace === '\\OC') && str_contains($filename, 'lib/private/legacy')) {
|
||||
// Skip legacy in OC as it’s scanned with an empty namespace separately
|
||||
continue;
|
||||
}
|
||||
foreach (self::SKIP_REGEX as $skipRegex) {
|
||||
if (preg_match($skipRegex, $filename)) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
$classname = $namespace . substr(str_replace('/', '\\', substr($filename, strlen($folder))), 0, -4);
|
||||
$output->writeln('Class ' . $classname, OutputInterface::VERBOSITY_VERBOSE);
|
||||
if (!class_exists($classname)) {
|
||||
continue;
|
||||
}
|
||||
$rClass = new \ReflectionClass($classname);
|
||||
$staticProperties = $rClass->getStaticProperties();
|
||||
if (empty($staticProperties)) {
|
||||
continue;
|
||||
}
|
||||
$stats['classes']++;
|
||||
$output->writeln('<info># ' . str_replace(\OC::$SERVERROOT, '', $filename) . " $classname</info>");
|
||||
foreach ($staticProperties as $property => $value) {
|
||||
$propertyObject = $rClass->getProperty($property);
|
||||
$stats['properties']++;
|
||||
$output->write("$propertyObject");
|
||||
}
|
||||
$output->writeln('');
|
||||
} catch (\Throwable $t) {
|
||||
$output->writeln("$t");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function recursiveGlob(string $path, int $depth = 1): \Generator {
|
||||
$pattern = $path . str_repeat('/*', $depth);
|
||||
yield from glob($pattern . '.php');
|
||||
if (!empty(glob($pattern, GLOB_ONLYDIR))) {
|
||||
yield from $this->recursiveGlob($path, $depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ use OCP\Security\IHasher;
|
||||
use OCP\Security\ISecureRandom;
|
||||
|
||||
class BackupCodeStorage {
|
||||
private static $CODE_LENGTH = 16;
|
||||
private const CODE_LENGTH = 16;
|
||||
|
||||
public function __construct(
|
||||
private BackupCodeMapper $mapper,
|
||||
@@ -40,7 +40,7 @@ class BackupCodeStorage {
|
||||
|
||||
$uid = $user->getUID();
|
||||
foreach (range(1, min([$number, 20])) as $i) {
|
||||
$code = $this->random->generate(self::$CODE_LENGTH, ISecureRandom::CHAR_HUMAN_READABLE);
|
||||
$code = $this->random->generate(self::CODE_LENGTH, ISecureRandom::CHAR_HUMAN_READABLE);
|
||||
|
||||
$dbCode = new BackupCode();
|
||||
$dbCode->setUserId($uid);
|
||||
|
||||
@@ -571,7 +571,7 @@ class Configuration {
|
||||
*/
|
||||
public function getConfigTranslationArray(): array {
|
||||
//TODO: merge them into one representation
|
||||
static $array = [
|
||||
return [
|
||||
'ldap_host' => 'ldapHost',
|
||||
'ldap_port' => 'ldapPort',
|
||||
'ldap_backup_host' => 'ldapBackupHost',
|
||||
@@ -644,7 +644,6 @@ class Configuration {
|
||||
'ldap_attr_anniversarydate' => 'ldapAttributeAnniversaryDate',
|
||||
'ldap_attr_pronouns' => 'ldapAttributePronouns',
|
||||
];
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,7 @@ use OCP\Util;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Wizard extends LDAPUtility {
|
||||
protected static ?IL10N $l = null;
|
||||
private IL10N $l;
|
||||
protected ?\LDAP\Connection $cr = null;
|
||||
protected WizardResult $result;
|
||||
protected LoggerInterface $logger;
|
||||
@@ -40,9 +40,7 @@ class Wizard extends LDAPUtility {
|
||||
protected Access $access,
|
||||
) {
|
||||
parent::__construct($ldap);
|
||||
if (is_null(static::$l)) {
|
||||
static::$l = Server::get(IL10NFactory::class)->get('user_ldap');
|
||||
}
|
||||
$this->l = Server::get(IL10NFactory::class)->get('user_ldap');
|
||||
$this->result = new WizardResult();
|
||||
$this->logger = Server::get(LoggerInterface::class);
|
||||
}
|
||||
@@ -94,7 +92,7 @@ class Wizard extends LDAPUtility {
|
||||
$filter = $this->configuration->ldapGroupFilter;
|
||||
|
||||
if (empty($filter)) {
|
||||
$output = self::$l->n('%n group found', '%n groups found', 0);
|
||||
$output = $this->l->n('%n group found', '%n groups found', 0);
|
||||
$this->result->addChange('ldap_group_count', $output);
|
||||
return $this->result;
|
||||
}
|
||||
@@ -110,9 +108,9 @@ class Wizard extends LDAPUtility {
|
||||
}
|
||||
|
||||
if ($groupsTotal > 1000) {
|
||||
$output = self::$l->t('> 1000 groups found');
|
||||
$output = $this->l->t('> 1000 groups found');
|
||||
} else {
|
||||
$output = self::$l->n(
|
||||
$output = $this->l->n(
|
||||
'%n group found',
|
||||
'%n groups found',
|
||||
$groupsTotal
|
||||
@@ -130,9 +128,9 @@ class Wizard extends LDAPUtility {
|
||||
|
||||
$usersTotal = $this->countEntries($filter, 'users');
|
||||
if ($usersTotal > 1000) {
|
||||
$output = self::$l->t('> 1000 users found');
|
||||
$output = $this->l->t('> 1000 users found');
|
||||
} else {
|
||||
$output = self::$l->n(
|
||||
$output = $this->l->n(
|
||||
'%n user found',
|
||||
'%n users found',
|
||||
$usersTotal
|
||||
@@ -216,7 +214,7 @@ class Wizard extends LDAPUtility {
|
||||
}
|
||||
}
|
||||
|
||||
throw new \Exception(self::$l->t('Could not detect user display name attribute. Please specify it yourself in advanced LDAP settings.'));
|
||||
throw new \Exception($this->l->t('Could not detect user display name attribute. Please specify it yourself in advanced LDAP settings.'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,7 +429,7 @@ class Wizard extends LDAPUtility {
|
||||
natsort($groupNames);
|
||||
$this->result->addOptions($dbKey, array_values($groupNames));
|
||||
} else {
|
||||
throw new \Exception(self::$l->t('Could not find the desired feature'));
|
||||
throw new \Exception($this->l->t('Could not find the desired feature'));
|
||||
}
|
||||
|
||||
$setFeatures = $this->configuration->$confKey;
|
||||
@@ -1024,7 +1022,7 @@ class Wizard extends LDAPUtility {
|
||||
$host = $this->configuration->ldapHost;
|
||||
$hostInfo = parse_url((string)$host);
|
||||
if (!is_string($host) || !$hostInfo) {
|
||||
throw new \Exception(self::$l->t('Invalid Host'));
|
||||
throw new \Exception($this->l->t('Invalid Host'));
|
||||
}
|
||||
$this->logger->debug(
|
||||
'Wiz: Attempting to connect',
|
||||
@@ -1032,7 +1030,7 @@ class Wizard extends LDAPUtility {
|
||||
);
|
||||
$cr = $this->ldap->connect($host, (string)$port);
|
||||
if (!$this->ldap->isResource($cr)) {
|
||||
throw new \Exception(self::$l->t('Invalid Host'));
|
||||
throw new \Exception($this->l->t('Invalid Host'));
|
||||
}
|
||||
/** @var \LDAP\Connection $cr */
|
||||
|
||||
@@ -1219,7 +1217,7 @@ class Wizard extends LDAPUtility {
|
||||
//sorting in the web UI. Therefore: array_values
|
||||
$this->result->addOptions($dbkey, array_values($availableFeatures));
|
||||
} else {
|
||||
throw new \Exception(self::$l->t('Could not find the desired feature'));
|
||||
throw new \Exception($this->l->t('Could not find the desired feature'));
|
||||
}
|
||||
|
||||
$setFeatures = $this->configuration->$confkey;
|
||||
@@ -1307,7 +1305,7 @@ class Wizard extends LDAPUtility {
|
||||
* @return array<array{port:int,tls:bool}>
|
||||
*/
|
||||
private function getDefaultLdapPortSettings(): array {
|
||||
static $settings = [
|
||||
return [
|
||||
['port' => 7636, 'tls' => false],
|
||||
['port' => 636, 'tls' => false],
|
||||
['port' => 7389, 'tls' => true],
|
||||
@@ -1315,7 +1313,6 @@ class Wizard extends LDAPUtility {
|
||||
['port' => 7389, 'tls' => false],
|
||||
['port' => 389, 'tls' => false],
|
||||
];
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ declare(strict_types=1);
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\WorkflowEngine\Command;
|
||||
|
||||
use OCA\WorkflowEngine\Helper\ScopeContext;
|
||||
@@ -43,11 +44,11 @@ class Index extends Command {
|
||||
}
|
||||
|
||||
protected function mappedScope(string $scope): int {
|
||||
static $scopes = [
|
||||
return match($scope) {
|
||||
'admin' => IManager::SCOPE_ADMIN,
|
||||
'user' => IManager::SCOPE_USER,
|
||||
];
|
||||
return $scopes[$scope] ?? -1;
|
||||
default => -1,
|
||||
};
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
|
||||
@@ -65,6 +65,9 @@ class Manager implements IManager {
|
||||
/** @var CappedMemoryCache<int[]> */
|
||||
protected CappedMemoryCache $operationsByScope;
|
||||
|
||||
/** @var array<class-string<IOperation>, ScopeContext[]> $scopesByOperation */
|
||||
private array $scopesByOperation = [];
|
||||
|
||||
public function __construct(
|
||||
protected readonly IDBConnection $connection,
|
||||
protected readonly ContainerInterface $container,
|
||||
@@ -128,10 +131,8 @@ class Manager implements IManager {
|
||||
* @return ScopeContext[]
|
||||
*/
|
||||
public function getAllConfiguredScopesForOperation(string $operationClass): array {
|
||||
/** @var array<class-string<IOperation>, ScopeContext[]> $scopesByOperation */
|
||||
static $scopesByOperation = [];
|
||||
if (isset($scopesByOperation[$operationClass])) {
|
||||
return $scopesByOperation[$operationClass];
|
||||
if (isset($this->scopesByOperation[$operationClass])) {
|
||||
return $this->scopesByOperation[$operationClass];
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -152,7 +153,7 @@ class Manager implements IManager {
|
||||
$query->setParameters(['operationClass' => $operationClass]);
|
||||
$result = $query->executeQuery();
|
||||
|
||||
$scopesByOperation[$operationClass] = [];
|
||||
$this->scopesByOperation[$operationClass] = [];
|
||||
while ($row = $result->fetchAssociative()) {
|
||||
$scope = new ScopeContext($row['type'], $row['value']);
|
||||
|
||||
@@ -160,10 +161,10 @@ class Manager implements IManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
$scopesByOperation[$operationClass][$scope->getHash()] = $scope;
|
||||
$this->scopesByOperation[$operationClass][$scope->getHash()] = $scope;
|
||||
}
|
||||
|
||||
return $scopesByOperation[$operationClass];
|
||||
return $this->scopesByOperation[$operationClass];
|
||||
}
|
||||
|
||||
public function getAllOperations(ScopeContext $scopeContext): array {
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Plugin\EventHandler\AfterClassLikeVisitInterface;
|
||||
use Psalm\Plugin\EventHandler\AfterStatementAnalysisInterface;
|
||||
use Psalm\Plugin\EventHandler\Event\AfterClassLikeVisitEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\AfterStatementAnalysisEvent;
|
||||
|
||||
/**
|
||||
* Complains about static property in classes and static vars in methods
|
||||
*/
|
||||
class StaticVarsChecker implements AfterClassLikeVisitInterface, AfterStatementAnalysisInterface {
|
||||
public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event): void {
|
||||
$classLike = $event->getStmt();
|
||||
$statementsSource = $event->getStatementsSource();
|
||||
|
||||
foreach ($classLike->stmts as $stmt) {
|
||||
if ($stmt instanceof Property) {
|
||||
if ($stmt->isStatic()) {
|
||||
IssueBuffer::maybeAdd(
|
||||
// ImpureStaticProperty is close enough, all static properties are impure to my eyes
|
||||
new \Psalm\Issue\ImpureStaticProperty(
|
||||
'Static property should not be used as they do not follow requests lifecycle',
|
||||
new CodeLocation($statementsSource, $stmt),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function afterStatementAnalysis(AfterStatementAnalysisEvent $event): ?bool {
|
||||
$stmt = $event->getStmt();
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\Static_) {
|
||||
IssueBuffer::maybeAdd(
|
||||
// Same logic
|
||||
new \Psalm\Issue\ImpureStaticVariable(
|
||||
'Static var should not be used as they do not follow requests lifecycle and are hard to reset',
|
||||
new CodeLocation($event->getStatementsSource(), $stmt),
|
||||
)
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
class StaticVarsTest {
|
||||
public static $forbiddenStaticProperty;
|
||||
protected static $forbiddenProtectedStaticProperty;
|
||||
private static $forbiddenPrivateStaticProperty;
|
||||
private static $forbiddenPrivateStaticPropertyWithValue = [];
|
||||
|
||||
public function normalFunction(): void {
|
||||
static $forbiddenStaticVar = false;
|
||||
}
|
||||
|
||||
public static function staticFunction(): void {
|
||||
static $forbiddenStaticVar = false;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
|
||||
class GenerateCommand extends Command implements CompletionAwareInterface {
|
||||
protected static $_templateSimple
|
||||
private const string TEMPLATE
|
||||
= '<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -197,7 +197,7 @@ class {{classname}} extends SimpleMigrationStep {
|
||||
$schemaBody,
|
||||
date('Y')
|
||||
];
|
||||
$code = str_replace($placeHolders, $replacements, self::$_templateSimple);
|
||||
$code = str_replace($placeHolders, $replacements, self::TEMPLATE);
|
||||
$dir = $ms->getMigrationsDirectory();
|
||||
|
||||
$this->ensureMigrationDirExists($dir);
|
||||
|
||||
@@ -19,90 +19,127 @@ use OCP\Server;
|
||||
use OCP\Template\ITemplateManager;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
try {
|
||||
require_once __DIR__ . '/lib/base.php';
|
||||
require_once __DIR__ . '/lib/OC.php';
|
||||
|
||||
OC::handleRequest();
|
||||
} catch (ServiceUnavailableException $ex) {
|
||||
Server::get(LoggerInterface::class)->error($ex->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex,
|
||||
]);
|
||||
\OC::boot();
|
||||
|
||||
//show the user a detailed error page
|
||||
Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, 503);
|
||||
} catch (HintException $ex) {
|
||||
function cleanupStaticCrap() {
|
||||
// FIXME needed because these use a static var
|
||||
\OC_Hook::clear();
|
||||
\OC_Util::$styles = [];
|
||||
\OC_Util::$headers = [];
|
||||
\OC_User::setIncognitoMode(false);
|
||||
\OC_User::$_setupedBackends = [];
|
||||
\OC_App::reset();
|
||||
\OC_Helper::reset();
|
||||
}
|
||||
|
||||
$handler = static function () {
|
||||
try {
|
||||
Server::get(ITemplateManager::class)->printErrorPage($ex->getMessage(), $ex->getHint(), 503);
|
||||
} catch (Exception $ex2) {
|
||||
// In worker mode, script name is empty in FrankenPHP
|
||||
if ($_SERVER['SCRIPT_NAME'] === '') {
|
||||
$_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
|
||||
}
|
||||
cleanupStaticCrap();
|
||||
OC::init();
|
||||
OC::handleRequest();
|
||||
} catch (ServiceUnavailableException $ex) {
|
||||
Server::get(LoggerInterface::class)->error($ex->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex,
|
||||
]);
|
||||
|
||||
//show the user a detailed error page
|
||||
Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, 503);
|
||||
} catch (HintException $ex) {
|
||||
try {
|
||||
Server::get(ITemplateManager::class)->printErrorPage($ex->getMessage(), $ex->getHint(), 503);
|
||||
} catch (Exception $ex2) {
|
||||
try {
|
||||
Server::get(LoggerInterface::class)->error($ex->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex,
|
||||
]);
|
||||
Server::get(LoggerInterface::class)->error($ex2->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex2,
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
// no way to log it properly - but to avoid a white page of death we try harder and ignore this one here
|
||||
}
|
||||
|
||||
//show the user a detailed error page
|
||||
Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, 500);
|
||||
}
|
||||
} catch (LoginException $ex) {
|
||||
$request = Server::get(IRequest::class);
|
||||
/**
|
||||
* Routes with the @CORS annotation and other API endpoints should
|
||||
* not return a webpage, so we only print the error page when html is accepted,
|
||||
* otherwise we reply with a JSON array like the SecurityMiddleware would do.
|
||||
*/
|
||||
if (stripos($request->getHeader('Accept'), 'html') === false) {
|
||||
http_response_code(401);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode(['message' => $ex->getMessage()]);
|
||||
exit();
|
||||
}
|
||||
Server::get(ITemplateManager::class)->printErrorPage($ex->getMessage(), $ex->getMessage(), 401);
|
||||
} catch (MaxDelayReached $ex) {
|
||||
$request = Server::get(IRequest::class);
|
||||
/**
|
||||
* Routes with the @CORS annotation and other API endpoints should
|
||||
* not return a webpage, so we only print the error page when html is accepted,
|
||||
* otherwise we reply with a JSON array like the BruteForceMiddleware would do.
|
||||
*/
|
||||
if (stripos($request->getHeader('Accept'), 'html') === false) {
|
||||
http_response_code(429);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode(['message' => $ex->getMessage()]);
|
||||
exit();
|
||||
}
|
||||
http_response_code(429);
|
||||
Server::get(ITemplateManager::class)->printGuestPage('core', '429');
|
||||
} catch (Exception $ex) {
|
||||
Server::get(LoggerInterface::class)->error($ex->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex,
|
||||
]);
|
||||
|
||||
//show the user a detailed error page
|
||||
Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, 500);
|
||||
} catch (Error $ex) {
|
||||
try {
|
||||
Server::get(LoggerInterface::class)->error($ex->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex,
|
||||
]);
|
||||
Server::get(LoggerInterface::class)->error($ex2->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex2,
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
// no way to log it properly - but to avoid a white page of death we try harder and ignore this one here
|
||||
}
|
||||
} catch (Error $e) {
|
||||
http_response_code(500);
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
print("Internal Server Error\n\n");
|
||||
print("The server encountered an internal error and was unable to complete your request.\n");
|
||||
print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
|
||||
print("More details can be found in the webserver log.\n");
|
||||
|
||||
//show the user a detailed error page
|
||||
throw $ex;
|
||||
}
|
||||
Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, 500);
|
||||
}
|
||||
} catch (LoginException $ex) {
|
||||
$request = Server::get(IRequest::class);
|
||||
/**
|
||||
* Routes with the @CORS annotation and other API endpoints should
|
||||
* not return a webpage, so we only print the error page when html is accepted,
|
||||
* otherwise we reply with a JSON array like the SecurityMiddleware would do.
|
||||
*/
|
||||
if (stripos($request->getHeader('Accept'), 'html') === false) {
|
||||
http_response_code(401);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode(['message' => $ex->getMessage()]);
|
||||
exit();
|
||||
}
|
||||
Server::get(ITemplateManager::class)->printErrorPage($ex->getMessage(), $ex->getMessage(), 401);
|
||||
} catch (MaxDelayReached $ex) {
|
||||
$request = Server::get(IRequest::class);
|
||||
/**
|
||||
* Routes with the @CORS annotation and other API endpoints should
|
||||
* not return a webpage, so we only print the error page when html is accepted,
|
||||
* otherwise we reply with a JSON array like the BruteForceMiddleware would do.
|
||||
*/
|
||||
if (stripos($request->getHeader('Accept'), 'html') === false) {
|
||||
http_response_code(429);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode(['message' => $ex->getMessage()]);
|
||||
exit();
|
||||
}
|
||||
http_response_code(429);
|
||||
Server::get(ITemplateManager::class)->printGuestPage('core', '429');
|
||||
} catch (Exception $ex) {
|
||||
Server::get(LoggerInterface::class)->error($ex->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex,
|
||||
]);
|
||||
};
|
||||
|
||||
//show the user a detailed error page
|
||||
Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, 500);
|
||||
} catch (Error $ex) {
|
||||
try {
|
||||
Server::get(LoggerInterface::class)->error($ex->getMessage(), [
|
||||
'app' => 'index',
|
||||
'exception' => $ex,
|
||||
]);
|
||||
} catch (Error $e) {
|
||||
http_response_code(500);
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
print("Internal Server Error\n\n");
|
||||
print("The server encountered an internal error and was unable to complete your request.\n");
|
||||
print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
|
||||
print("More details can be found in the webserver log.\n");
|
||||
if (function_exists('frankenphp_handle_request')) {
|
||||
$maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0);
|
||||
for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) {
|
||||
$keepRunning = \frankenphp_handle_request($handler);
|
||||
|
||||
throw $ex;
|
||||
// Call the garbage collector to reduce the chances of it being triggered in the middle of a page generation
|
||||
gc_collect_cycles();
|
||||
|
||||
if (!$keepRunning) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, 500);
|
||||
} else {
|
||||
$handler();
|
||||
}
|
||||
|
||||
+1299
File diff suppressed because it is too large
Load Diff
+4
-1281
File diff suppressed because it is too large
Load Diff
@@ -368,7 +368,7 @@ class AccountManager implements IAccountManager {
|
||||
}
|
||||
|
||||
protected function updateVerificationStatus(IAccount $updatedAccount, array $oldData): void {
|
||||
static $propertiesVerifiableByLookupServer = [
|
||||
$propertiesVerifiableByLookupServer = [
|
||||
self::PROPERTY_TWITTER,
|
||||
self::PROPERTY_FEDIVERSE,
|
||||
self::PROPERTY_WEBSITE,
|
||||
|
||||
@@ -54,6 +54,9 @@ class AppManager implements IAppManager {
|
||||
/** @var string[] $appId => $enabled */
|
||||
private array $enabledAppsCache = [];
|
||||
|
||||
/** @var array<string, array{path: string, url: string}> $appId => approot information */
|
||||
private array $appsDirCache = [];
|
||||
|
||||
/** @var string[]|null */
|
||||
private ?array $shippedApps = null;
|
||||
|
||||
@@ -743,11 +746,9 @@ class AppManager implements IAppManager {
|
||||
if ($sanitizedAppId !== $appId) {
|
||||
return false;
|
||||
}
|
||||
// FIXME replace by a property or a cache
|
||||
static $app_dir = [];
|
||||
|
||||
if (isset($app_dir[$appId]) && !$ignoreCache) {
|
||||
return $app_dir[$appId];
|
||||
if (isset($this->appsDirCache[$appId]) && !$ignoreCache) {
|
||||
return $this->appsDirCache[$appId];
|
||||
}
|
||||
|
||||
$possibleApps = [];
|
||||
@@ -761,7 +762,7 @@ class AppManager implements IAppManager {
|
||||
return false;
|
||||
} elseif (count($possibleApps) === 1) {
|
||||
$dir = array_shift($possibleApps);
|
||||
$app_dir[$appId] = $dir;
|
||||
$this->appsDirCache[$appId] = $dir;
|
||||
return $dir;
|
||||
} else {
|
||||
$versionToLoad = [];
|
||||
@@ -778,7 +779,7 @@ class AppManager implements IAppManager {
|
||||
if (!isset($versionToLoad['dir'])) {
|
||||
return false;
|
||||
}
|
||||
$app_dir[$appId] = $versionToLoad['dir'];
|
||||
$this->appsDirCache[$appId] = $versionToLoad['dir'];
|
||||
return $versionToLoad['dir'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ class PlatformRepository {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
|
||||
private const string MODIFIER_REGEX = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
|
||||
|
||||
/**
|
||||
* Normalizes a version string to be able to perform comparisons on it
|
||||
@@ -154,16 +154,16 @@ class PlatformRepository {
|
||||
return 'dev-' . substr($version, 4);
|
||||
}
|
||||
// match classical versioning
|
||||
if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?' . self::$modifierRegex . '$}i', $version, $matches)) {
|
||||
if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?' . self::MODIFIER_REGEX . '$}i', $version, $matches)) {
|
||||
$version = $matches[1]
|
||||
. (!empty($matches[2]) ? $matches[2] : '.0')
|
||||
. (!empty($matches[3]) ? $matches[3] : '.0')
|
||||
. (!empty($matches[4]) ? $matches[4] : '.0');
|
||||
$index = 5;
|
||||
} elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) { // match date-based versioning
|
||||
} elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::MODIFIER_REGEX . '$}i', $version, $matches)) { // match date-based versioning
|
||||
$version = preg_replace('{\D}', '-', $matches[1]);
|
||||
$index = 2;
|
||||
} elseif (preg_match('{^v?(\d{4,})(\.\d+)?(\.\d+)?(\.\d+)?' . self::$modifierRegex . '$}i', $version, $matches)) {
|
||||
} elseif (preg_match('{^v?(\d{4,})(\.\d+)?(\.\d+)?(\.\d+)?' . self::MODIFIER_REGEX . '$}i', $version, $matches)) {
|
||||
$version = $matches[1]
|
||||
. (!empty($matches[2]) ? $matches[2] : '.0')
|
||||
. (!empty($matches[3]) ? $matches[3] : '.0')
|
||||
|
||||
@@ -28,18 +28,12 @@ use Psr\Log\LoggerInterface;
|
||||
* @package OC\Files\Cache
|
||||
*/
|
||||
class Storage {
|
||||
private static ?StorageGlobal $globalCache = null;
|
||||
|
||||
private string $storageId;
|
||||
|
||||
private int $numericId;
|
||||
|
||||
public static function getGlobalCache(): StorageGlobal {
|
||||
if (is_null(self::$globalCache)) {
|
||||
self::$globalCache = new StorageGlobal(Server::get(IDBConnection::class));
|
||||
}
|
||||
|
||||
return self::$globalCache;
|
||||
return Server::get(StorageGlobal::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -95,6 +95,8 @@ class SetupManager implements ISetupManager {
|
||||
private const SETUP_WITH_CHILDREN = 1;
|
||||
private const SETUP_WITHOUT_CHILDREN = 0;
|
||||
|
||||
private bool $updatingProviders = false;
|
||||
|
||||
public function __construct(
|
||||
private IEventLogger $eventLogger,
|
||||
private MountProviderCollection $mountProviderCollection,
|
||||
@@ -245,11 +247,10 @@ class SetupManager implements ISetupManager {
|
||||
}
|
||||
|
||||
// prevent recursion loop from when getting mounts from providers ends up setting up the filesystem
|
||||
static $updatingProviders = false;
|
||||
if ($updatingProviders) {
|
||||
if ($this->updatingProviders) {
|
||||
return;
|
||||
}
|
||||
$updatingProviders = true;
|
||||
$this->updatingProviders = true;
|
||||
|
||||
$providers = $this->mountProviderCollection->getProviders();
|
||||
$nonAuthoritativeProviders = array_filter(
|
||||
@@ -265,7 +266,7 @@ class SetupManager implements ISetupManager {
|
||||
$this->userMountCache->registerMounts($user, $mount, $providerNames);
|
||||
|
||||
$this->usersMountsUpdated[$user->getUID()] = true;
|
||||
$updatingProviders = false;
|
||||
$this->updatingProviders = false;
|
||||
}
|
||||
|
||||
#[Override]
|
||||
|
||||
@@ -74,6 +74,8 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage,
|
||||
private ?LoggerInterface $logger = null;
|
||||
private ?IFilenameValidator $filenameValidator = null;
|
||||
|
||||
private ?CacheDependencies $cacheDependencies = null;
|
||||
|
||||
public function __construct(array $parameters) {
|
||||
}
|
||||
|
||||
@@ -304,11 +306,10 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage,
|
||||
}
|
||||
|
||||
protected function getCacheDependencies(): CacheDependencies {
|
||||
static $dependencies = null;
|
||||
if (!$dependencies) {
|
||||
$dependencies = Server::get(CacheDependencies::class);
|
||||
if ($this->cacheDependencies === null) {
|
||||
$this->cacheDependencies = Server::get(CacheDependencies::class);
|
||||
}
|
||||
return $dependencies;
|
||||
return $this->cacheDependencies;
|
||||
}
|
||||
|
||||
public function getCache(string $path = '', ?IStorage $storage = null): ICache {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
namespace OC\Memcache;
|
||||
|
||||
use OC\RedisFactory;
|
||||
use OCP\IMemcacheTTL;
|
||||
use OCP\Server;
|
||||
|
||||
@@ -37,24 +38,18 @@ class Redis extends Cache implements IMemcacheTTL {
|
||||
|
||||
private const MAX_TTL = 30 * 24 * 60 * 60; // 1 month
|
||||
|
||||
/**
|
||||
* @var \Redis|\RedisCluster $cache
|
||||
*/
|
||||
private static $cache = null;
|
||||
private \Redis|\RedisCluster $cache;
|
||||
|
||||
public function __construct($prefix = '', string $logFile = '') {
|
||||
parent::__construct($prefix);
|
||||
$this->cache = \OCP\Server::get(RedisFactory::class)->getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Redis|\RedisCluster|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getCache() {
|
||||
if (is_null(self::$cache)) {
|
||||
self::$cache = Server::get('RedisFactory')->getInstance();
|
||||
}
|
||||
return self::$cache;
|
||||
public function getCache(): \Redis|\RedisCluster {
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
public function get($key) {
|
||||
|
||||
@@ -11,7 +11,6 @@ use OCP\Server;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class NaturalSort {
|
||||
private static $instance;
|
||||
private $collator;
|
||||
private $cache = [];
|
||||
|
||||
@@ -113,10 +112,7 @@ class NaturalSort {
|
||||
* Returns a singleton
|
||||
* @return NaturalSort instance
|
||||
*/
|
||||
public static function getInstance() {
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new NaturalSort();
|
||||
}
|
||||
return self::$instance;
|
||||
public static function getInstance(): NaturalSort {
|
||||
return \OCP\Server::get(NaturalSort::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,15 +131,14 @@ class RedisFactory {
|
||||
}
|
||||
|
||||
public function getInstance(): \Redis|\RedisCluster {
|
||||
if (!$this->isAvailable()) {
|
||||
throw new \Exception('Redis support is not available');
|
||||
}
|
||||
if ($this->instance === null) {
|
||||
if (!$this->isAvailable()) {
|
||||
throw new \Exception('Redis support is not available');
|
||||
}
|
||||
$this->create();
|
||||
}
|
||||
|
||||
if ($this->instance === null) {
|
||||
throw new \Exception('Redis support is not available');
|
||||
if ($this->instance === null) {
|
||||
throw new \Exception('Redis support is not available');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->instance;
|
||||
|
||||
@@ -60,7 +60,6 @@ use OC\Files\Config\UserMountCache;
|
||||
use OC\Files\Config\UserMountCacheListener;
|
||||
use OC\Files\Conversion\ConversionManager;
|
||||
use OC\Files\FilenameValidator;
|
||||
use OC\Files\Filesystem;
|
||||
use OC\Files\Lock\LockManager;
|
||||
use OC\Files\Mount\CacheMountProvider;
|
||||
use OC\Files\Mount\LocalHomeMountProvider;
|
||||
@@ -440,12 +439,11 @@ class Server extends ServerContainer implements IServerContainer {
|
||||
});
|
||||
$this->registerAlias(IFileAccess::class, FileAccess::class);
|
||||
$this->registerService('RootFolder', function (ContainerInterface $c) {
|
||||
$manager = Filesystem::getMountManager();
|
||||
$view = new View();
|
||||
/** @var IUserSession $userSession */
|
||||
$userSession = $c->get(IUserSession::class);
|
||||
$root = new Root(
|
||||
$manager,
|
||||
$c->get(\OC\Files\Mount\Manager::class),
|
||||
$view,
|
||||
$userSession->getUser(),
|
||||
$c->get(IUserMountCache::class),
|
||||
@@ -671,10 +669,7 @@ class Server extends ServerContainer implements IServerContainer {
|
||||
});
|
||||
$this->registerAlias(ICacheFactory::class, Factory::class);
|
||||
|
||||
$this->registerService('RedisFactory', function (Server $c) {
|
||||
$systemConfig = $c->get(SystemConfig::class);
|
||||
return new RedisFactory($systemConfig, $c->get(IEventLogger::class));
|
||||
});
|
||||
$this->registerDeprecatedAlias('RedisFactory', RedisFactory::class);
|
||||
|
||||
$this->registerService(\OCP\Activity\IManager::class, function (Server $c) {
|
||||
$l10n = $this->get(IFactory::class)->get('lib');
|
||||
|
||||
@@ -72,7 +72,7 @@ class Setup {
|
||||
$this->l10n = $l10nFactory->get('lib');
|
||||
}
|
||||
|
||||
protected static array $dbSetupClasses = [
|
||||
private const array DB_SETUP_CLASSES = [
|
||||
'mysql' => MySQL::class,
|
||||
'pgsql' => PostgreSQL::class,
|
||||
'oci' => OCI::class,
|
||||
@@ -334,13 +334,13 @@ class Setup {
|
||||
$options['directory'] = \OC::$SERVERROOT . '/data';
|
||||
}
|
||||
|
||||
if (!isset(self::$dbSetupClasses[$dbType])) {
|
||||
if (!isset(self::DB_SETUP_CLASSES[$dbType])) {
|
||||
$dbType = 'sqlite';
|
||||
}
|
||||
|
||||
$dataDir = htmlspecialchars_decode($options['directory']);
|
||||
|
||||
$class = self::$dbSetupClasses[$dbType];
|
||||
$class = self::DB_SETUP_CLASSES[$dbType];
|
||||
/** @var AbstractDatabase $dbSetup */
|
||||
$dbSetup = new $class($l, $this->config, $this->logger, $this->random);
|
||||
$error = array_merge($error, $dbSetup->validate($options));
|
||||
|
||||
@@ -76,12 +76,12 @@ class Task extends Entity {
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public static array $columns = ['id', 'last_updated', 'type', 'input', 'output', 'status', 'user_id', 'app_id', 'custom_id', 'completion_expected_at', 'error_message', 'progress', 'webhook_uri', 'webhook_method', 'scheduled_at', 'started_at', 'ended_at', 'allow_cleanup', 'user_facing_error_message', 'include_watermark'];
|
||||
public const array COLUMNS = ['id', 'last_updated', 'type', 'input', 'output', 'status', 'user_id', 'app_id', 'custom_id', 'completion_expected_at', 'error_message', 'progress', 'webhook_uri', 'webhook_method', 'scheduled_at', 'started_at', 'ended_at', 'allow_cleanup', 'user_facing_error_message', 'include_watermark'];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public static array $fields = ['id', 'lastUpdated', 'type', 'input', 'output', 'status', 'userId', 'appId', 'customId', 'completionExpectedAt', 'errorMessage', 'progress', 'webhookUri', 'webhookMethod', 'scheduledAt', 'startedAt', 'endedAt', 'allowCleanup', 'userFacingErrorMessage', 'includeWatermark'];
|
||||
public const array FIELDS = ['id', 'lastUpdated', 'type', 'input', 'output', 'status', 'userId', 'appId', 'customId', 'completionExpectedAt', 'errorMessage', 'progress', 'webhookUri', 'webhookMethod', 'scheduledAt', 'startedAt', 'endedAt', 'allowCleanup', 'userFacingErrorMessage', 'includeWatermark'];
|
||||
|
||||
|
||||
public function __construct() {
|
||||
@@ -109,9 +109,9 @@ class Task extends Entity {
|
||||
}
|
||||
|
||||
public function toRow(): array {
|
||||
return array_combine(self::$columns, array_map(function ($field) {
|
||||
return array_combine(self::COLUMNS, array_map(function ($field) {
|
||||
return $this->{'get' . ucfirst($field)}();
|
||||
}, self::$fields));
|
||||
}, self::FIELDS));
|
||||
}
|
||||
|
||||
public static function fromPublicTask(OCPTask $task): self {
|
||||
|
||||
@@ -38,7 +38,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function find(int $id): Task {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
|
||||
return $this->findEntity($qb);
|
||||
@@ -53,7 +53,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findOldestScheduledByType(array $taskTypes, array $taskIdsToIgnore): Task {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('status', $qb->createPositionalParameter(\OCP\TaskProcessing\Task::STATUS_SCHEDULED, IQueryBuilder::PARAM_INT)))
|
||||
->setMaxResults(1)
|
||||
@@ -85,7 +85,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findByIdAndUser(int $id, ?string $userId): Task {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
|
||||
if ($userId === null) {
|
||||
@@ -105,7 +105,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findByUserAndTaskType(?string $userId, ?string $taskType = null, ?string $customId = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)));
|
||||
if ($taskType !== null) {
|
||||
@@ -126,7 +126,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findUserTasksByApp(?string $userId, string $appId, ?string $customId = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)))
|
||||
->andWhere($qb->expr()->eq('app_id', $qb->createPositionalParameter($appId)));
|
||||
@@ -151,7 +151,7 @@ class TaskMapper extends QBMapper {
|
||||
?string $userId, ?string $taskType = null, ?string $appId = null, ?string $customId = null,
|
||||
?int $status = null, ?int $scheduleAfter = null, ?int $endedBefore = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName);
|
||||
|
||||
// empty string: no userId filter
|
||||
@@ -205,7 +205,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function getTasksToCleanup(int $timeout, bool $force = false): \Generator {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->lt('last_updated', $qb->createPositionalParameter($this->timeFactory->getDateTime()->getTimestamp() - $timeout)));
|
||||
if (!$force) {
|
||||
@@ -243,7 +243,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findNOldestScheduledByType(array $taskTypes, array $taskIdsToIgnore, int $numberOfTasks) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('status', $qb->createPositionalParameter(\OCP\TaskProcessing\Task::STATUS_SCHEDULED, IQueryBuilder::PARAM_INT)))
|
||||
->setMaxResults($numberOfTasks)
|
||||
|
||||
@@ -46,13 +46,12 @@ class Task extends Entity {
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public static array $columns = ['id', 'last_updated', 'type', 'input', 'output', 'status', 'user_id', 'app_id', 'identifier', 'completion_expected_at'];
|
||||
public const array COLUMNS = ['id', 'last_updated', 'type', 'input', 'output', 'status', 'user_id', 'app_id', 'identifier', 'completion_expected_at'];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public static array $fields = ['id', 'lastUpdated', 'type', 'input', 'output', 'status', 'userId', 'appId', 'identifier', 'completionExpectedAt'];
|
||||
|
||||
public const array FIELDS = ['id', 'lastUpdated', 'type', 'input', 'output', 'status', 'userId', 'appId', 'identifier', 'completionExpectedAt'];
|
||||
|
||||
public function __construct() {
|
||||
// add types in constructor
|
||||
@@ -69,9 +68,9 @@ class Task extends Entity {
|
||||
}
|
||||
|
||||
public function toRow(): array {
|
||||
return array_combine(self::$columns, array_map(function ($field) {
|
||||
return array_combine(self::COLUMNS, array_map(function ($field) {
|
||||
return $this->{'get' . ucfirst($field)}();
|
||||
}, self::$fields));
|
||||
}, self::FIELDS));
|
||||
}
|
||||
|
||||
public static function fromPublicTask(OCPTask $task): Task {
|
||||
|
||||
@@ -37,7 +37,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function find(int $id): Task {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
|
||||
return $this->findEntity($qb);
|
||||
@@ -53,7 +53,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findByIdAndUser(int $id, ?string $userId): Task {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
|
||||
if ($userId === null) {
|
||||
@@ -73,7 +73,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findUserTasksByApp(string $userId, string $appId, ?string $identifier = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)))
|
||||
->andWhere($qb->expr()->eq('app_id', $qb->createPositionalParameter($appId)));
|
||||
|
||||
@@ -44,7 +44,10 @@ class Manager implements IManager {
|
||||
/** @var ?IProvider[] */
|
||||
private ?array $providers = null;
|
||||
|
||||
private static array $taskProcessingCompatibleTaskTypes = [
|
||||
/**
|
||||
* @var array<class-string, string>
|
||||
*/
|
||||
private const array COMPATIBLE_TASK_TYPES = [
|
||||
FreePromptTaskType::class => TextToText::ID,
|
||||
HeadlineTaskType::class => TextToTextHeadline::ID,
|
||||
SummaryTaskType::class => TextToTextSummary::ID,
|
||||
@@ -91,7 +94,7 @@ class Manager implements IManager {
|
||||
public function hasProviders(): bool {
|
||||
// check if task processing equivalent types are available
|
||||
$taskTaskTypes = $this->taskProcessingManager->getAvailableTaskTypes();
|
||||
foreach (self::$taskProcessingCompatibleTaskTypes as $textTaskTypeClass => $taskTaskTypeId) {
|
||||
foreach (self::COMPATIBLE_TASK_TYPES as $textTaskTypeClass => $taskTaskTypeId) {
|
||||
if (isset($taskTaskTypes[$taskTaskTypeId])) {
|
||||
return true;
|
||||
}
|
||||
@@ -115,7 +118,7 @@ class Manager implements IManager {
|
||||
|
||||
// check if task processing equivalent types are available
|
||||
$taskTaskTypes = $this->taskProcessingManager->getAvailableTaskTypes();
|
||||
foreach (self::$taskProcessingCompatibleTaskTypes as $textTaskTypeClass => $taskTaskTypeId) {
|
||||
foreach (self::COMPATIBLE_TASK_TYPES as $textTaskTypeClass => $taskTaskTypeId) {
|
||||
if (isset($taskTaskTypes[$taskTaskTypeId])) {
|
||||
$tasks[$textTaskTypeClass] = true;
|
||||
}
|
||||
@@ -134,9 +137,9 @@ class Manager implements IManager {
|
||||
public function runTask(OCPTask $task): string {
|
||||
// try to run a task processing task if possible
|
||||
$taskTypeClass = $task->getType();
|
||||
if (isset(self::$taskProcessingCompatibleTaskTypes[$taskTypeClass]) && isset($this->taskProcessingManager->getAvailableTaskTypes()[self::$taskProcessingCompatibleTaskTypes[$taskTypeClass]])) {
|
||||
if (isset(self::COMPATIBLE_TASK_TYPES[$taskTypeClass]) && isset($this->taskProcessingManager->getAvailableTaskTypes()[self::COMPATIBLE_TASK_TYPES[$taskTypeClass]])) {
|
||||
try {
|
||||
$taskProcessingTaskTypeId = self::$taskProcessingCompatibleTaskTypes[$taskTypeClass];
|
||||
$taskProcessingTaskTypeId = self::COMPATIBLE_TASK_TYPES[$taskTypeClass];
|
||||
$taskProcessingTask = new \OCP\TaskProcessing\Task(
|
||||
$taskProcessingTaskTypeId,
|
||||
['input' => $task->getInput()],
|
||||
@@ -222,8 +225,8 @@ class Manager implements IManager {
|
||||
$task->setStatus(OCPTask::STATUS_SCHEDULED);
|
||||
$providers = $this->getPreferredProviders($task);
|
||||
$equivalentTaskProcessingTypeAvailable = (
|
||||
isset(self::$taskProcessingCompatibleTaskTypes[$task->getType()])
|
||||
&& isset($this->taskProcessingManager->getAvailableTaskTypes()[self::$taskProcessingCompatibleTaskTypes[$task->getType()]])
|
||||
isset(self::COMPATIBLE_TASK_TYPES[$task->getType()])
|
||||
&& isset($this->taskProcessingManager->getAvailableTaskTypes()[self::COMPATIBLE_TASK_TYPES[$task->getType()]])
|
||||
);
|
||||
if (count($providers) === 0 && !$equivalentTaskProcessingTypeAvailable) {
|
||||
throw new PreConditionNotMetException('No LanguageModel provider is installed that can handle this task');
|
||||
|
||||
@@ -49,12 +49,12 @@ class Task extends Entity {
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public static array $columns = ['id', 'last_updated', 'input', 'status', 'user_id', 'app_id', 'identifier', 'number_of_images', 'completion_expected_at'];
|
||||
public const array COLUMNS = ['id', 'last_updated', 'input', 'status', 'user_id', 'app_id', 'identifier', 'number_of_images', 'completion_expected_at'];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public static array $fields = ['id', 'lastUpdated', 'input', 'status', 'userId', 'appId', 'identifier', 'numberOfImages', 'completionExpectedAt'];
|
||||
public const array FIELDS = ['id', 'lastUpdated', 'input', 'status', 'userId', 'appId', 'identifier', 'numberOfImages', 'completionExpectedAt'];
|
||||
|
||||
|
||||
public function __construct() {
|
||||
@@ -71,9 +71,9 @@ class Task extends Entity {
|
||||
}
|
||||
|
||||
public function toRow(): array {
|
||||
return array_combine(self::$columns, array_map(function ($field) {
|
||||
return array_combine(self::COLUMNS, array_map(function ($field) {
|
||||
return $this->{'get' . ucfirst($field)}();
|
||||
}, self::$fields));
|
||||
}, self::FIELDS));
|
||||
}
|
||||
|
||||
public static function fromPublicTask(OCPTask $task): Task {
|
||||
|
||||
@@ -38,7 +38,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function find(int $id): Task {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
|
||||
return $this->findEntity($qb);
|
||||
@@ -54,7 +54,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findByIdAndUser(int $id, ?string $userId): Task {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('id', $qb->createPositionalParameter($id)));
|
||||
if ($userId === null) {
|
||||
@@ -74,7 +74,7 @@ class TaskMapper extends QBMapper {
|
||||
*/
|
||||
public function findUserTasksByApp(?string $userId, string $appId, ?string $identifier = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select(Task::$columns)
|
||||
$qb->select(Task::COLUMNS)
|
||||
->from($this->tableName)
|
||||
->where($qb->expr()->eq('user_id', $qb->createPositionalParameter($userId)))
|
||||
->andWhere($qb->expr()->eq('app_id', $qb->createPositionalParameter($appId)));
|
||||
|
||||
@@ -46,6 +46,14 @@ class OC_App {
|
||||
public const supportedApp = 300;
|
||||
public const officialApp = 200;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function reset(): void {
|
||||
self::$altLogin = [];
|
||||
self::$alreadyRegistered = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* clean the appId
|
||||
*
|
||||
|
||||
@@ -44,6 +44,14 @@ class OC_Helper {
|
||||
private static ?ICacheFactory $cacheFactory = null;
|
||||
private static ?bool $quotaIncludeExternalStorage = null;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function reset(): void {
|
||||
self::$cacheFactory = null;
|
||||
self::$quotaIncludeExternalStorage = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive copying of folders
|
||||
* @param string $src source folder
|
||||
|
||||
@@ -114,6 +114,7 @@ class OC_Hook {
|
||||
}
|
||||
} else {
|
||||
self::$registered = [];
|
||||
self::$thrownExceptions = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ use Psr\Log\LoggerInterface;
|
||||
* logout()
|
||||
*/
|
||||
class OC_User {
|
||||
private static $_setupedBackends = [];
|
||||
public static $_setupedBackends = [];
|
||||
|
||||
// bool, stores if a user want to access a resource anonymously, e.g if they open a public link
|
||||
private static $incognitoMode = false;
|
||||
|
||||
+1
-12
@@ -412,24 +412,13 @@ class Util {
|
||||
return \OC_Hook::emit($signalclass, $signalname, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached encrypted CSRF token. Some static unit-tests of ownCloud compare
|
||||
* multiple Template elements which invoke `callRegister`. If the value
|
||||
* would not be cached these unit-tests would fail.
|
||||
* @var string
|
||||
*/
|
||||
private static $token = '';
|
||||
|
||||
/**
|
||||
* Register an get/post call. This is important to prevent CSRF attacks
|
||||
* @since 4.5.0
|
||||
* @deprecated 32.0.0 directly use CsrfTokenManager instead
|
||||
*/
|
||||
public static function callRegister() {
|
||||
if (self::$token === '') {
|
||||
self::$token = \OCP\Server::get(CsrfTokenManager::class)->getToken()->getEncryptedValue();
|
||||
}
|
||||
return self::$token;
|
||||
return \OCP\Server::get(CsrfTokenManager::class)->getToken()->getEncryptedValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<plugin filename="build/psalm/AppFrameworkTainter.php" />
|
||||
<plugin filename="build/psalm/AttributeNamedParameters.php" />
|
||||
<plugin filename="build/psalm/LogicalOperatorChecker.php" />
|
||||
<plugin filename="build/psalm/StaticVarsChecker.php" />
|
||||
</plugins>
|
||||
<projectFiles>
|
||||
<directory name="apps/admin_audit"/>
|
||||
|
||||
Reference in New Issue
Block a user