Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions Caddyfile
Original file line number Diff line number Diff line change
@@ -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
}
5 changes: 5 additions & 0 deletions apps/testing/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions apps/testing/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
'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',
Expand Down
1 change: 1 addition & 0 deletions apps/testing/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
110 changes: 110 additions & 0 deletions apps/testing/lib/Command/StaticHunt.php
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use OCP\Security\ISecureRandom;

class BackupCodeStorage {
private static $CODE_LENGTH = 16;
private const CODE_LENGTH = 16;

public function __construct(
private BackupCodeMapper $mapper,
Expand All @@ -40,7 +40,7 @@ public function createCodes(IUser $user, int $number = 10): array {

$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);
Expand Down
3 changes: 1 addition & 2 deletions apps/user_ldap/lib/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ public function getDefaults(): array {
*/
public function getConfigTranslationArray(): array {
//TODO: merge them into one representation
static $array = [
return [
'ldap_host' => 'ldapHost',
'ldap_port' => 'ldapPort',
'ldap_backup_host' => 'ldapBackupHost',
Expand Down Expand Up @@ -644,7 +644,6 @@ public function getConfigTranslationArray(): array {
'ldap_attr_anniversarydate' => 'ldapAttributeAnniversaryDate',
'ldap_attr_pronouns' => 'ldapAttributePronouns',
];
return $array;
}

/**
Expand Down
29 changes: 13 additions & 16 deletions apps/user_ldap/lib/Wizard.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
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;
Expand All @@ -40,9 +40,7 @@ public function __construct(
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);
}
Expand Down Expand Up @@ -94,7 +92,7 @@ public function countGroups() {
$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;
}
Expand All @@ -110,9 +108,9 @@ public function countGroups() {
}

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
Expand All @@ -130,9 +128,9 @@ public function countUsers(): WizardResult {

$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
Expand Down Expand Up @@ -216,7 +214,7 @@ public function detectUserDisplayNameAttribute() {
}
}

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.'));
}

/**
Expand Down Expand Up @@ -431,7 +429,7 @@ public function fetchGroups(string $dbKey, string $confKey): array {
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;
Expand Down Expand Up @@ -1024,15 +1022,15 @@ private function connectAndBind(int $port, bool $tls): bool {
$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',
['app' => 'user_ldap']
);
$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 */

Expand Down Expand Up @@ -1219,7 +1217,7 @@ private function determineFeature(array $objectclasses, string $attr, string $db
//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;
Expand Down Expand Up @@ -1307,15 +1305,14 @@ private function getConnection(): \LDAP\Connection|false {
* @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],
['port' => 389, 'tls' => true],
['port' => 7389, 'tls' => false],
['port' => 389, 'tls' => false],
];
return $settings;
}

/**
Expand Down
7 changes: 4 additions & 3 deletions apps/workflowengine/lib/Command/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* 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;
Expand Down Expand Up @@ -43,11 +44,11 @@ protected function configure() {
}

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 {
Expand Down
Loading
Loading