summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/dav/lib/CalDAV/Reminder/INotificationProvider.php3
-rw-r--r--apps/dav/lib/CalDAV/Reminder/NotificationProvider/AbstractProvider.php3
-rw-r--r--apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php14
-rw-r--r--apps/dav/lib/CalDAV/Reminder/NotificationProvider/PushProvider.php5
-rw-r--r--apps/dav/lib/CalDAV/Reminder/ReminderService.php17
-rw-r--r--apps/dav/lib/CalDAV/Schedule/Plugin.php20
-rw-r--r--apps/dav/lib/Connector/Sabre/Principal.php40
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php90
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php5
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php4
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php31
-rw-r--r--apps/settings/lib/WellKnown/SecurityTxtHandler.php2
-rw-r--r--apps/theming/l10n/zh_HK.js7
-rw-r--r--apps/theming/l10n/zh_HK.json7
-rw-r--r--apps/user_ldap/lib/ILDAPWrapper.php9
-rw-r--r--apps/user_ldap/lib/Wizard.php198
16 files changed, 330 insertions, 125 deletions
diff --git a/apps/dav/lib/CalDAV/Reminder/INotificationProvider.php b/apps/dav/lib/CalDAV/Reminder/INotificationProvider.php
index a6b439c0b4f..505960ed662 100644
--- a/apps/dav/lib/CalDAV/Reminder/INotificationProvider.php
+++ b/apps/dav/lib/CalDAV/Reminder/INotificationProvider.php
@@ -8,6 +8,7 @@ declare(strict_types=1);
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -42,10 +43,12 @@ interface INotificationProvider {
*
* @param VEvent $vevent
* @param string $calendarDisplayName
+ * @param string[] $principalEmailAddresses All email addresses associated to the principal owning the calendar object
* @param IUser[] $users
* @return void
*/
public function send(VEvent $vevent,
string $calendarDisplayName,
+ array $principalEmailAddresses,
array $users = []): void;
}
diff --git a/apps/dav/lib/CalDAV/Reminder/NotificationProvider/AbstractProvider.php b/apps/dav/lib/CalDAV/Reminder/NotificationProvider/AbstractProvider.php
index 49cf36f98ac..6986328facd 100644
--- a/apps/dav/lib/CalDAV/Reminder/NotificationProvider/AbstractProvider.php
+++ b/apps/dav/lib/CalDAV/Reminder/NotificationProvider/AbstractProvider.php
@@ -10,6 +10,7 @@ declare(strict_types=1);
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author Joas Schilling <coding@schilljs.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -82,11 +83,13 @@ abstract class AbstractProvider implements INotificationProvider {
*
* @param VEvent $vevent
* @param string $calendarDisplayName
+ * @param string[] $principalEmailAddresses
* @param IUser[] $users
* @return void
*/
abstract public function send(VEvent $vevent,
string $calendarDisplayName,
+ array $principalEmailAddresses,
array $users = []): void;
/**
diff --git a/apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php b/apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php
index d4aea6215ea..c2e68605d17 100644
--- a/apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php
+++ b/apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php
@@ -71,16 +71,28 @@ class EmailProvider extends AbstractProvider {
*
* @param VEvent $vevent
* @param string $calendarDisplayName
+ * @param string[] $principalEmailAddresses
* @param array $users
* @throws \Exception
*/
public function send(VEvent $vevent,
string $calendarDisplayName,
+ array $principalEmailAddresses,
array $users = []):void {
$fallbackLanguage = $this->getFallbackLanguage();
+ $organizerEmailAddress = null;
+ if (isset($vevent->ORGANIZER)) {
+ $organizerEmailAddress = $this->getEMailAddressOfAttendee($vevent->ORGANIZER);
+ }
+
$emailAddressesOfSharees = $this->getEMailAddressesOfAllUsersWithWriteAccessToCalendar($users);
- $emailAddressesOfAttendees = $this->getAllEMailAddressesFromEvent($vevent);
+ $emailAddressesOfAttendees = [];
+ if (count($principalEmailAddresses) === 0
+ || ($organizerEmailAddress && in_array($organizerEmailAddress, $principalEmailAddresses, true))
+ ) {
+ $emailAddressesOfAttendees = $this->getAllEMailAddressesFromEvent($vevent);
+ }
// Quote from php.net:
// If the input arrays have the same string keys, then the later value for that key will overwrite the previous one.
diff --git a/apps/dav/lib/CalDAV/Reminder/NotificationProvider/PushProvider.php b/apps/dav/lib/CalDAV/Reminder/NotificationProvider/PushProvider.php
index cb873020c38..833d74079aa 100644
--- a/apps/dav/lib/CalDAV/Reminder/NotificationProvider/PushProvider.php
+++ b/apps/dav/lib/CalDAV/Reminder/NotificationProvider/PushProvider.php
@@ -10,6 +10,7 @@ declare(strict_types=1);
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Citharel <nextcloud@tcit.fr>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -73,11 +74,13 @@ class PushProvider extends AbstractProvider {
*
* @param VEvent $vevent
* @param string $calendarDisplayName
+ * @param string[] $principalEmailAddresses
* @param IUser[] $users
* @throws \Exception
*/
public function send(VEvent $vevent,
- string $calendarDisplayName = null,
+ string $calendarDisplayName,
+ array $principalEmailAddresses,
array $users = []):void {
if ($this->config->getAppValue('dav', 'sendEventRemindersPush', 'no') !== 'yes') {
return;
diff --git a/apps/dav/lib/CalDAV/Reminder/ReminderService.php b/apps/dav/lib/CalDAV/Reminder/ReminderService.php
index 2a065469052..3fb8cf9ebe5 100644
--- a/apps/dav/lib/CalDAV/Reminder/ReminderService.php
+++ b/apps/dav/lib/CalDAV/Reminder/ReminderService.php
@@ -11,6 +11,7 @@ declare(strict_types=1);
* @author Joas Schilling <coding@schilljs.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Citharel <nextcloud@tcit.fr>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -32,6 +33,7 @@ namespace OCA\DAV\CalDAV\Reminder;
use DateTimeImmutable;
use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\Connector\Sabre\Principal;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IGroup;
@@ -76,6 +78,9 @@ class ReminderService {
/** @var LoggerInterface */
private $logger;
+ /** @var Principal */
+ private $principalConnector;
+
public const REMINDER_TYPE_EMAIL = 'EMAIL';
public const REMINDER_TYPE_DISPLAY = 'DISPLAY';
public const REMINDER_TYPE_AUDIO = 'AUDIO';
@@ -98,7 +103,8 @@ class ReminderService {
CalDavBackend $caldavBackend,
ITimeFactory $timeFactory,
IConfig $config,
- LoggerInterface $logger) {
+ LoggerInterface $logger,
+ Principal $principalConnector) {
$this->backend = $backend;
$this->notificationProviderManager = $notificationProviderManager;
$this->userManager = $userManager;
@@ -107,6 +113,7 @@ class ReminderService {
$this->timeFactory = $timeFactory;
$this->config = $config;
$this->logger = $logger;
+ $this->principalConnector = $principalConnector;
}
/**
@@ -175,12 +182,18 @@ class ReminderService {
$users[] = $user;
}
+ $userPrincipalEmailAddresses = [];
+ $userPrincipal = $this->principalConnector->getPrincipalByPath($reminder['principaluri']);
+ if ($userPrincipal) {
+ $userPrincipalEmailAddresses = $this->principalConnector->getEmailAddressesOfPrincipal($userPrincipal);
+ }
+
$this->logger->debug('Reminder {id} will be sent to {numUsers} users', [
'id' => $reminder['id'],
'numUsers' => count($users),
]);
$notificationProvider = $this->notificationProviderManager->getProvider($reminder['type']);
- $notificationProvider->send($vevent, $reminder['displayname'], $users);
+ $notificationProvider->send($vevent, $reminder['displayname'], $userPrincipalEmailAddresses, $users);
$this->deleteOrProcessNext($reminder, $vevent);
}
diff --git a/apps/dav/lib/CalDAV/Schedule/Plugin.php b/apps/dav/lib/CalDAV/Schedule/Plugin.php
index 44517541faa..ed160cac2c2 100644
--- a/apps/dav/lib/CalDAV/Schedule/Plugin.php
+++ b/apps/dav/lib/CalDAV/Schedule/Plugin.php
@@ -9,6 +9,7 @@
* @author Joas Schilling <coding@schilljs.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Citharel <nextcloud@tcit.fr>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -46,6 +47,7 @@ use Sabre\VObject\Component;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Component\VEvent;
use Sabre\VObject\DateTimeParser;
+use Sabre\VObject\Document;
use Sabre\VObject\FreeBusyGenerator;
use Sabre\VObject\ITip;
use Sabre\VObject\Parameter;
@@ -164,6 +166,14 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin {
* @inheritDoc
*/
public function scheduleLocalDelivery(ITip\Message $iTipMessage):void {
+ /** @var Component|null $vevent */
+ $vevent = $iTipMessage->message->VEVENT ?? null;
+
+ // Strip VALARMs from incoming VEVENT
+ if ($vevent && isset($vevent->VALARM)) {
+ $vevent->remove('VALARM');
+ }
+
parent::scheduleLocalDelivery($iTipMessage);
// We only care when the message was successfully delivered locally
@@ -200,18 +210,10 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin {
return;
}
- if (!isset($iTipMessage->message)) {
+ if (!$vevent) {
return;
}
- $vcalendar = $iTipMessage->message;
- if (!isset($vcalendar->VEVENT)) {
- return;
- }
-
- /** @var Component $vevent */
- $vevent = $vcalendar->VEVENT;
-
// We don't support autoresponses for recurrencing events for now
if (isset($vevent->RRULE) || isset($vevent->RDATE)) {
return;
diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php
index 75bee4e7b42..7b4b7090832 100644
--- a/apps/dav/lib/Connector/Sabre/Principal.php
+++ b/apps/dav/lib/Connector/Sabre/Principal.php
@@ -607,4 +607,44 @@ class Principal implements BackendInterface {
return [];
}
+
+ /**
+ * Get all email addresses associated to a principal.
+ *
+ * @param array $principal Data from getPrincipal*()
+ * @return string[] All email addresses without the mailto: prefix
+ */
+ public function getEmailAddressesOfPrincipal(array $principal): array {
+ $emailAddresses = [];
+
+ if (($primaryAddress = $principal['{http://sabredav.org/ns}email-address'])) {
+ $emailAddresses[] = $primaryAddress;
+ }
+
+ if (isset($principal['{DAV:}alternate-URI-set'])) {
+ foreach ($principal['{DAV:}alternate-URI-set'] as $address) {
+ if (str_starts_with($address, 'mailto:')) {
+ $emailAddresses[] = substr($address, 7);
+ }
+ }
+ }
+
+ if (isset($principal['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'])) {
+ foreach ($principal['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'] as $address) {
+ if (str_starts_with($address, 'mailto:')) {
+ $emailAddresses[] = substr($address, 7);
+ }
+ }
+ }
+
+ if (isset($principal['{http://calendarserver.org/ns/}email-address-set'])) {
+ foreach ($principal['{http://calendarserver.org/ns/}email-address-set'] as $address) {
+ if (str_starts_with($address, 'mailto:')) {
+ $emailAddresses[] = substr($address, 7);
+ }
+ }
+ }
+
+ return array_values(array_unique($emailAddresses));
+ }
}
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
index 273ad939144..9499e9e2ef1 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
@@ -65,6 +65,7 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
public function testSendWithoutAttendees():void {
[$user1, $user2, $user3, , $user5] = $users = $this->getUsers();
+ $principalEmailAddresses = [$user1->getEmailAddress()];
$enL10N = $this->createMock(IL10N::class);
$enL10N->method('t')
@@ -170,11 +171,12 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$this->setupURLGeneratorMock(2);
$vcalendar = $this->getNoAttendeeVCalendar();
- $this->provider->send($vcalendar->VEVENT, $this->calendarDisplayName, $users);
+ $this->provider->send($vcalendar->VEVENT, $this->calendarDisplayName, $principalEmailAddresses, $users);
}
- public function testSendWithAttendees(): void {
+ public function testSendWithAttendeesWhenOwnerIsOrganizer(): void {
[$user1, $user2, $user3, , $user5] = $users = $this->getUsers();
+ $principalEmailAddresses = [$user1->getEmailAddress()];
$enL10N = $this->createMock(IL10N::class);
$enL10N->method('t')
@@ -266,7 +268,81 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$this->setupURLGeneratorMock(2);
$vcalendar = $this->getAttendeeVCalendar();
- $this->provider->send($vcalendar->VEVENT, $this->calendarDisplayName, $users);
+ $this->provider->send($vcalendar->VEVENT, $this->calendarDisplayName, $principalEmailAddresses, $users);
+ }
+
+ public function testSendWithAttendeesWhenOwnerIsAttendee(): void {
+ [$user1, $user2, $user3] = $this->getUsers();
+ $users = [$user2, $user3];
+ $principalEmailAddresses = [$user2->getEmailAddress()];
+
+ $deL10N = $this->createMock(IL10N::class);
+ $deL10N->method('t')
+ ->willReturnArgument(0);
+ $deL10N->method('l')
+ ->willReturnArgument(0);
+
+ $this->l10nFactory
+ ->method('getUserLanguage')
+ ->willReturnMap([
+ [$user2, 'de'],
+ [$user3, 'de'],
+ ]);
+
+ $this->l10nFactory
+ ->method('findGenericLanguage')
+ ->willReturn('en');
+
+ $this->l10nFactory
+ ->method('languageExists')
+ ->willReturnMap([
+ ['dav', 'de', true],
+ ]);
+
+ $this->l10nFactory
+ ->method('get')
+ ->willReturnMap([
+ ['dav', 'de', null, $deL10N],
+ ]);
+
+ $template1 = $this->getTemplateMock();
+ $message12 = $this->getMessageMock('uid2@example.com', $template1);
+ $message13 = $this->getMessageMock('uid3@example.com', $template1);
+
+ $this->mailer->expects(self::once())
+ ->method('createEMailTemplate')
+ ->with('dav.calendarReminder')
+ ->willReturnOnConsecutiveCalls(
+ $template1,
+ );
+ $this->mailer->expects($this->atLeastOnce())
+ ->method('validateMailAddress')
+ ->willReturnMap([
+ ['foo1@example.org', true],
+ ['foo3@example.org', true],
+ ['foo4@example.org', true],
+ ['uid1@example.com', true],
+ ['uid2@example.com', true],
+ ['uid3@example.com', true],
+ ['invalid', false],
+ ]);
+ $this->mailer->expects($this->exactly(2))
+ ->method('createMessage')
+ ->with()
+ ->willReturnOnConsecutiveCalls(
+ $message12,
+ $message13,
+ );
+ $this->mailer->expects($this->exactly(2))
+ ->method('send')
+ ->withConsecutive(
+ [$message12],
+ [$message13],
+ )->willReturn([]);
+ $this->setupURLGeneratorMock(1);
+
+ $vcalendar = $this->getAttendeeVCalendar();
+ $this->provider->send($vcalendar->VEVENT, $this->calendarDisplayName, $principalEmailAddresses, $users);
}
/**
@@ -377,6 +453,14 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
]);
$vcalendar->VEVENT->add(
+ 'ORGANIZER',
+ 'mailto:uid1@example.com',
+ [
+ 'LANG' => 'en'
+ ]
+ );
+
+ $vcalendar->VEVENT->add(
'ATTENDEE',
'mailto:foo1@example.org',
[
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
index a62cb98a28f..64020b9dbd7 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
@@ -10,6 +10,7 @@ declare(strict_types=1);
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Citharel <nextcloud@tcit.fr>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -90,7 +91,7 @@ class PushProviderTest extends AbstractNotificationProviderTest {
$users = [$user1, $user2, $user3];
- $this->provider->send($this->vcalendar->VEVENT, $this->calendarDisplayName, $users);
+ $this->provider->send($this->vcalendar->VEVENT, $this->calendarDisplayName, [], $users);
}
public function testSend(): void {
@@ -143,7 +144,7 @@ class PushProviderTest extends AbstractNotificationProviderTest {
->method('notify')
->with($notification3);
- $this->provider->send($this->vcalendar->VEVENT, $this->calendarDisplayName, $users);
+ $this->provider->send($this->vcalendar->VEVENT, $this->calendarDisplayName, [], $users);
}
/**
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php b/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
index 6242e8d0355..79d9376650b 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
@@ -9,6 +9,7 @@ declare(strict_types=1);
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Citharel <nextcloud@tcit.fr>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -33,6 +34,7 @@ use OCA\DAV\CalDAV\Reminder\Backend;
use OCA\DAV\CalDAV\Reminder\INotificationProvider;
use OCA\DAV\CalDAV\Reminder\NotificationProviderManager;
use OCA\DAV\CalDAV\Reminder\ReminderService;
+use OCA\DAV\Connector\Sabre\Principal;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IGroupManager;
@@ -202,6 +204,7 @@ EOD;
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->config = $this->createMock(IConfig::class);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->principalConnector = $this->createMock(Principal::class);
$this->caldavBackend->method('getShares')->willReturn([]);
@@ -214,6 +217,7 @@ EOD;
$this->timeFactory,
$this->config,
$this->logger,
+ $this->principalConnector,
);
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
index 444c267b509..7cd31e3b8dd 100644
--- a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
@@ -11,6 +11,7 @@
* @author Morris Jobke <hey@morrisjobke.de>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license AGPL-3.0
*
@@ -974,4 +975,34 @@ class PrincipalTest extends TestCase {
['mailto:user3@foo.bar', 'user3@foo.bar', 'principals/users/user3'],
];
}
+
+ public function testGetEmailAddressesOfPrincipal(): void {
+ $principal = [
+ '{http://sabredav.org/ns}email-address' => 'bar@company.org',
+ '{DAV:}alternate-URI-set' => [
+ '/some/url',
+ 'mailto:foo@bar.com',
+ 'mailto:duplicate@example.com',
+ ],
+ '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set' => [
+ 'mailto:bernard@example.com',
+ 'mailto:bernard.desruisseaux@example.com',
+ ],
+ '{http://calendarserver.org/ns/}email-address-set' => [
+ 'mailto:duplicate@example.com',
+ 'mailto:user@some.org',
+ ],
+ ];
+
+ $expected = [
+ 'bar@company.org',
+ 'foo@bar.com',
+ 'duplicate@example.com',
+ 'bernard@example.com',
+ 'bernard.desruisseaux@example.com',
+ 'user@some.org',
+ ];
+ $actual = $this->connector->getEmailAddressesOfPrincipal($principal);
+ $this->assertEquals($expected, $actual);
+ }
}
diff --git a/apps/settings/lib/WellKnown/SecurityTxtHandler.php b/apps/settings/lib/WellKnown/SecurityTxtHandler.php
index e0b627dc269..665dfba0710 100644
--- a/apps/settings/lib/WellKnown/SecurityTxtHandler.php
+++ b/apps/settings/lib/WellKnown/SecurityTxtHandler.php
@@ -38,7 +38,7 @@ class SecurityTxtHandler implements IHandler {
}
$response = "Contact: https://hackerone.com/nextcloud
-Expires: 2023-04-31T23:00:00.000Z
+Expires: 2023-04-30T23:00:00.000Z
Acknowledgments: https://hackerone.com/nextcloud/thanks
Acknowledgments: https://github.com/nextcloud/security-advisories/security/advisories
Policy: https://hackerone.com/nextcloud
diff --git a/apps/theming/l10n/zh_HK.js b/apps/theming/l10n/zh_HK.js
index 8b93307b1bb..b514d241e9c 100644
--- a/apps/theming/l10n/zh_HK.js
+++ b/apps/theming/l10n/zh_HK.js
@@ -10,6 +10,7 @@ OC.L10N.register(
"The given privacy policy address is not a valid URL" : "指定的隱私權政策網址不是有效的 URL",
"The given slogan is too long" : "指定的標語太長",
"The given color is invalid" : "指定的顏色無效",
+ "Disable-user-theming should be true or false" : "Disable-user-theming 應該是 true 或 false",
"Saved" : "已儲存",
"The file was uploaded" : "檔案已上傳",
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "上傳的檔案大小超過 php.ini 當中 upload_max_filesize 選項的限制",
@@ -20,6 +21,8 @@ OC.L10N.register(
"Could not write file to disk" : "寫入硬碟失敗",
"A PHP extension stopped the file upload" : "一個 PHP 擴充功能終止檔案的上傳",
"No file uploaded" : "未上傳檔案",
+ "Cleanup old theming cache" : "清除舊主題的缓存",
+ "Failed to delete folder: \"%1$s\", error: %2$s" : "刪除資料夾失敗:「%1$s」,錯誤:%2$s",
"You are already using a custom theme. Theming app settings might be overwritten by that." : "您已經在使用自訂佈景主題。佈景主題應用程式設定可能會被覆寫。",
"Theming" : "佈景主題",
"Appearance and accessibility" : "外觀和可訪問性",
@@ -53,6 +56,7 @@ OC.L10N.register(
"Color" : "顏色",
"Logo" : "Logo",
"Upload new logo" : "上傳新的 Logo",
+ "Background and login image" : "背景與登入圖像",
"Legal notice link" : "法律聲明連結",
"Privacy policy link" : "私隱政策連結",
"Header logo" : "頁首圖示",
@@ -60,9 +64,12 @@ OC.L10N.register(
"Favicon" : "Favicon",
"Upload new favicon" : "上傳新 favicon",
"User settings" : "用戶設定",
+ "Disable user theming" : "停用用戶佈景主題",
"Keyboard shortcuts" : "鍵盤快捷鍵",
+ "In some cases keyboard shortcuts can interfere with accessibility tools. In order to allow focusing on your tool correctly you can disable all keyboard shortcuts here. This will also disable all available shortcuts in apps." : "在某些情況下,鍵盤快捷鍵可能會干擾無障礙工具。為了可以正確地將焦點置於您的工具,您可以在此處停用所有鍵盤快捷鍵。這也會停用應用程式中的所有可用的快捷鍵。",
"Disable all keyboard shortcuts" : "停用所有鍵盤快捷鍵",
"Background" : "背景",
+ "Customization has been disabled by your administrator" : "您的管理員已停用自訂",
"Set a custom background" : "設置自定義背景",
"Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {guidelines}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level." : "我們非常重視無障礙使用。我們遵循網路標準,並透過檢查來確保所有內容皆可在沒有滑鼠或輔助軟體(例如螢幕閱讀器)的情況下使用。我們目標是能達到 {guidelines} 網頁內容可及性指引{linkend} 2.1 版的 AA 等級,加上高對比度主題甚至還能到 AAA 等級。",
"If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!" : "如果您發現任何問題,請在 {issuetracker}我們的問題追蹤系統{linkend} 舉報。而如果您想參與,歡迎加入 {designteam}我們的設計團隊{linked}!",
diff --git a/apps/theming/l10n/zh_HK.json b/apps/theming/l10n/zh_HK.json
index eea54c066c6..18ccdc23667 100644
--- a/apps/theming/l10n/zh_HK.json
+++ b/apps/theming/l10n/zh_HK.json
@@ -8,6 +8,7 @@
"The given privacy policy address is not a valid URL" : "指定的隱私權政策網址不是有效的 URL",
"The given slogan is too long" : "指定的標語太長",
"The given color is invalid" : "指定的顏色無效",
+ "Disable-user-theming should be true or false" : "Disable-user-theming 應該是 true 或 false",
"Saved" : "已儲存",
"The file was uploaded" : "檔案已上傳",
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "上傳的檔案大小超過 php.ini 當中 upload_max_filesize 選項的限制",
@@ -18,6 +19,8 @@
"Could not write file to disk" : "寫入硬碟失敗",
"A PHP extension stopped the file upload" : "一個 PHP 擴充功能終止檔案的上傳",
"No file uploaded" : "未上傳檔案",
+ "Cleanup old theming cache" : "清除舊主題的缓存",
+ "Failed to delete folder: \"%1$s\", error: %2$s" : "刪除資料夾失敗:「%1$s」,錯誤:%2$s",
"You are already using a custom theme. Theming app settings might be overwritten by that." : "您已經在使用自訂佈景主題。佈景主題應用程式設定可能會被覆寫。",
"Theming" : "佈景主題",
"Appearance and accessibility" : "外觀和可訪問性",
@@ -51,6 +54,7 @@
"Color" : "顏色",
"Logo" : "Logo",
"Upload new logo" : "上傳新的 Logo",
+ "Background and login image" : "背景與登入圖像",
"Legal notice link" : "法律聲明連結",
"Privacy policy link" : "私隱政策連結",
"Header logo" : "頁首圖示",
@@ -58,9 +62,12 @@
"Favicon" : "Favicon",
"Upload new favicon" : "上傳新 favicon",
"User settings" : "用戶設定",
+ "Disable user theming" : "停用用戶佈景主題",
"Keyboard shortcuts" : "鍵盤快捷鍵",
+ "In some cases keyboard shortcuts can interfere with accessibility tools. In order to allow focusing on your tool correctly you can disable all keyboard shortcuts here. This will also disable all available shortcuts in apps." : "在某些情況下,鍵盤快捷鍵可能會干擾無障礙工具。為了可以正確地將焦點置於您的工具,您可以在此處停用所有鍵盤快捷鍵。這也會停用應用程式中的所有可用的快捷鍵。",
"Disable all keyboard shortcuts" : "停用所有鍵盤快捷鍵",
"Background" : "背景",
+ "Customization has been disabled by your administrator" : "您的管理員已停用自訂",
"Set a custom background" : "設置自定義背景",
"Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {guidelines}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level." : "我們非常重視無障礙使用。我們遵循網路標準,並透過檢查來確保所有內容皆可在沒有滑鼠或輔助軟體(例如螢幕閱讀器)的情況下使用。我們目標是能達到 {guidelines} 網頁內容可及性指引{linkend} 2.1 版的 AA 等級,加上高對比度主題甚至還能到 AAA 等級。",
"If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!" : "如果您發現任何問題,請在 {issuetracker}我們的問題追蹤系統{linkend} 舉報。而如果您想參與,歡迎加入 {designteam}我們的設計團隊{linked}!",
diff --git a/apps/user_ldap/lib/ILDAPWrapper.php b/apps/user_ldap/lib/ILDAPWrapper.php
index b5c5568348e..6ec88effa5f 100644
--- a/apps/user_ldap/lib/ILDAPWrapper.php
+++ b/apps/user_ldap/lib/ILDAPWrapper.php
@@ -30,7 +30,6 @@
namespace OCA\User_LDAP;
interface ILDAPWrapper {
-
//LDAP functions in use
/**
@@ -48,7 +47,7 @@ interface ILDAPWrapper {
* connect to an LDAP server
* @param string $host The host to connect to
* @param string $port The port to connect to
- * @return mixed a link resource on success, otherwise false
+ * @return resource|\LDAP\Connection|false a link resource on success, otherwise false
*/
public function connect($host, $port);
@@ -106,7 +105,7 @@ interface ILDAPWrapper {
* Get attributes from a search result entry
* @param resource|\LDAP\Connection $link LDAP link resource
* @param resource|\LDAP\ResultEntry $result LDAP result resource
- * @return array containing the results, false on error
+ * @return array|false containing the results, false on error
* */
public function getAttributes($link, $result);
@@ -114,7 +113,7 @@ interface ILDAPWrapper {
* Get the DN of a result entry
* @param resource|\LDAP\Connection $link LDAP link resource
* @param resource|\LDAP\ResultEntry $result LDAP result resource
- * @return string containing the DN, false on error
+ * @return string|false containing the DN, false on error
*/
public function getDN($link, $result);
@@ -122,7 +121,7 @@ interface ILDAPWrapper {
* Get all result entries
* @param resource|\LDAP\Connection $link LDAP link resource
* @param resource|\LDAP\Result $result LDAP result resource
- * @return array containing the results, false on error
+ * @return array|false containing the results, false on error
*/
public function getEntries($link, $result);
diff --git a/apps/user_ldap/lib/Wizard.php b/apps/user_ldap/lib/Wizard.php
index 19de55c091d..2ecdce610a7 100644
--- a/apps/user_ldap/lib/Wizard.php
+++ b/apps/user_ldap/lib/Wizard.php
@@ -19,6 +19,7 @@
* @author Tobias Perschon <tobias@perschon.at>
* @author Victor Dubiniuk <dubiniuk@owncloud.com>
* @author Xuanwo <xuanwo@yunify.com>
+ * @author Côme Chilliet <come.chilliet@nextcloud.com>
*
* @license AGPL-3.0
*
@@ -35,22 +36,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+
namespace OCA\User_LDAP;
use OC\ServerNotAvailableException;
+use OCP\IL10N;
+use OCP\L10N\IFactory as IL10NFactory;
use Psr\Log\LoggerInterface;
class Wizard extends LDAPUtility {
- /** @var \OCP\IL10N */
- protected static $l;
- protected $access;
+ protected static ?IL10N $l = null;
+ protected Access $access;
+ /** @var resource|\LDAP\Connection|null */
protected $cr;
- protected $configuration;
- protected $result;
- protected $resultCache = [];
-
- /** @var LoggerInterface */
- protected $logger;
+ protected Configuration $configuration;
+ protected WizardResult $result;
+ protected LoggerInterface $logger;
public const LRESULT_PROCESSED_OK = 2;
public const LRESULT_PROCESSED_INVALID = 3;
@@ -65,17 +66,15 @@ class Wizard extends LDAPUtility {
public const LDAP_NW_TIMEOUT = 4;
- /**
- * Constructor
- * @param Configuration $configuration an instance of Configuration
- * @param ILDAPWrapper $ldap an instance of ILDAPWrapper
- * @param Access $access
- */
- public function __construct(Configuration $configuration, ILDAPWrapper $ldap, Access $access) {
+ public function __construct(
+ Configuration $configuration,
+ ILDAPWrapper $ldap,
+ Access $access
+ ) {
parent::__construct($ldap);
$this->configuration = $configuration;
- if (is_null(Wizard::$l)) {
- Wizard::$l = \OC::$server->getL10N('user_ldap');
+ if (is_null(static::$l)) {
+ static::$l = \OC::$server->get(IL10NFactory::class)->get('user_ldap');
}
$this->access = $access;
$this->result = new WizardResult();
@@ -93,7 +92,6 @@ class Wizard extends LDAPUtility {
*
* @param string $filter the LDAP search filter
* @param string $type a string being either 'users' or 'groups';
- * @return int
* @throws \Exception
*/
public function countEntries(string $filter, string $type): int {
@@ -120,6 +118,9 @@ class Wizard extends LDAPUtility {
return (int)$result;
}
+ /**
+ * @return WizardResult|false
+ */
public function countGroups() {
$filter = $this->configuration->ldapGroupFilter;
@@ -153,10 +154,9 @@ class Wizard extends LDAPUtility {
}
/**
- * @return WizardResult
* @throws \Exception
*/
- public function countUsers() {
+ public function countUsers(): WizardResult {
$filter = $this->access->getFilterForUserCount();
$usersTotal = $this->countEntries($filter, 'users');
@@ -176,32 +176,26 @@ class Wizard extends LDAPUtility {
/**
* counts any objects in the currently set base dn
*
- * @return WizardResult
* @throws \Exception
*/
- public function countInBaseDN() {
+ public function countInBaseDN(): WizardResult {
// we don't need to provide a filter in this case
$total = $this->countEntries('', 'objects');
- if ($total === false) {
- throw new \Exception('invalid results received');
- }
$this->result->addChange('ldap_test_base', $total);
return $this->result;
}
/**
* counts users with a specified attribute
- * @param string $attr
- * @param bool $existsCheck
- * @return int|bool
+ * @return int|false
*/
- public function countUsersWithAttribute($attr, $existsCheck = false) {
+ public function countUsersWithAttribute(string $attr, bool $existsCheck = false) {
if (!$this->checkRequirements(['ldapHost',
'ldapPort',
'ldapBase',
'ldapUserFilter',
])) {
- return false;
+ return false;
}
$filter = $this->access->combineFilterWithAnd([
@@ -209,7 +203,7 @@ class Wizard extends LDAPUtility {
$attr . '=*'
]);
- $limit = ($existsCheck === false) ? null : 1;
+ $limit = $existsCheck ? null : 1;
return $this->access->countUsers($filter, ['dn'], $limit);
}
@@ -217,7 +211,7 @@ class Wizard extends LDAPUtility {
/**
* detects the display name attribute. If a setting is already present that
* returns at least one hit, the detection will be canceled.
- * @return WizardResult|bool
+ * @return WizardResult|false
* @throws \Exception
*/
public function detectUserDisplayNameAttribute() {
@@ -308,7 +302,7 @@ class Wizard extends LDAPUtility {
}
/**
- * @return WizardResult
+ * @return WizardResult|false
* @throws \Exception
*/
public function determineAttributes() {
@@ -317,11 +311,15 @@ class Wizard extends LDAPUtility {
'ldapBase',
'ldapUserFilter',
])) {
- return false;
+ return false;
}
$attributes = $this->getUserAttributes();
+ if (!is_array($attributes)) {
+ throw new \Exception('Failed to determine user attributes');
+ }
+
natcasesort($attributes);
$attributes = array_values($attributes);
@@ -337,7 +335,7 @@ class Wizard extends LDAPUtility {
/**
* detects the available LDAP attributes
- * @return array|false The instance's WizardResult instance
+ * @return array|false
* @throws \Exception
*/
private function getUserAttributes() {
@@ -346,7 +344,7 @@ class Wizard extends LDAPUtility {
'ldapBase',
'ldapUserFilter',
])) {
- return false;
+ return false;
}
$cr = $this->getConnection();
if (!$cr) {
@@ -359,8 +357,12 @@ class Wizard extends LDAPUtility {
if (!$this->ldap->isResource($rr)) {
return false;
}
+ /** @var resource|\LDAP\Result $rr */
$er = $this->ldap->firstEntry($cr, $rr);
$attributes = $this->ldap->getAttributes($cr, $er);
+ if ($attributes === false) {
+ return false;
+ }
$pureAttributes = [];
for ($i = 0; $i < $attributes['count']; $i++) {
$pureAttributes[] = $attributes[$i];
@@ -390,18 +392,15 @@ class Wizard extends LDAPUtility {
/**
* detects the available LDAP groups
- * @param string $dbKey
- * @param string $confKey
- * @param bool $testMemberOf
* @return WizardResult|false the instance's WizardResult instance
* @throws \Exception
*/
- private function determineGroups($dbKey, $confKey, $testMemberOf = true) {
+ private function determineGroups(string $dbKey, string $confKey, bool $testMemberOf = true) {
if (!$this->checkRequirements(['ldapHost',
'ldapPort',
'ldapBase',
])) {
- return false;
+ return false;
}
$cr = $this->getConnection();
if (!$cr) {
@@ -424,12 +423,9 @@ class Wizard extends LDAPUtility {
/**
* fetches all groups from LDAP and adds them to the result object
*
- * @param string $dbKey
- * @param string $confKey
- * @return array $groupEntries
* @throws \Exception
*/
- public function fetchGroups($dbKey, $confKey) {
+ public function fetchGroups(string $dbKey, string $confKey): array {
$obclasses = ['posixGroup', 'group', 'zimbraDistributionList', 'groupOfNames', 'groupOfUniqueNames'];
$filterParts = [];
@@ -451,7 +447,7 @@ class Wizard extends LDAPUtility {
// detection will fail later
$result = $this->access->searchGroups($filter, ['cn', 'dn'], $limit, $offset);
foreach ($result as $item) {
- if (!isset($item['cn']) && !is_array($item['cn']) && !isset($item['cn'][0])) {
+ if (!isset($item['cn']) || !is_array($item['cn']) || !isset($item['cn'][0])) {
// just in case - no issue known
continue;
}
@@ -476,12 +472,15 @@ class Wizard extends LDAPUtility {
return $groupEntries;
}
+ /**
+ * @return WizardResult|false
+ */
public function determineGroupMemberAssoc() {
if (!$this->checkRequirements(['ldapHost',
'ldapPort',
'ldapGroupFilter',
])) {
- return false;
+ return false;
}
$attribute = $this->detectGroupMemberAssoc();
if ($attribute === false) {
@@ -522,7 +521,7 @@ class Wizard extends LDAPUtility {
/**
* detects the available object classes
- * @return WizardResult
+ * @return WizardResult|false
* @throws \Exception
*/
public function determineUserObjectClasses() {
@@ -530,7 +529,7 @@ class Wizard extends LDAPUtility {
'ldapPort',
'ldapBase',
])) {
- return false;
+ return false;
}
$cr = $this->getConnection();
if (!$cr) {
@@ -602,7 +601,7 @@ class Wizard extends LDAPUtility {
}
/**
- * @return bool|WizardResult
+ * @return WizardResult|false
* @throws \Exception
*/
public function getUserLoginFilter() {
@@ -624,11 +623,10 @@ class Wizard extends LDAPUtility {
}
/**
- * @return bool|WizardResult
- * @param string $loginName
+ * @return WizardResult|false
* @throws \Exception
*/
- public function testLoginName($loginName) {
+ public function testLoginName(string $loginName) {
if (!$this->checkRequirements(['ldapHost',
'ldapPort',
'ldapBase',
@@ -641,6 +639,7 @@ class Wizard extends LDAPUtility {
if (!$this->ldap->isResource($cr)) {
throw new \Exception('connection error');
}
+ /** @var resource|\LDAP\Connection $cr */
if (mb_strpos($this->access->connection->ldapLoginFilter, '%uid', 0, 'UTF-8')
=== false) {
@@ -670,10 +669,6 @@ class Wizard extends LDAPUtility {
$this->checkHost();
$portSettings = $this->getPortSettingsToTry();
- if (!is_array($portSettings)) {
- throw new \Exception(print_r($portSettings, true));
- }
-
//proceed from the best configuration and return on first success
foreach ($portSettings as $setting) {
$p = $setting['port'];
@@ -742,7 +737,7 @@ class Wizard extends LDAPUtility {
//this did not help :(
//Let's see whether we can parse the Host URL and convert the domain to
//a base DN
- $helper = new Helper(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection());
+ $helper = \OC::$server->get(Helper::class);
$domain = $helper->getDomainFromURL($this->configuration->ldapHost);
if (!$domain) {
return false;
@@ -768,7 +763,7 @@ class Wizard extends LDAPUtility {
* @param string $value the (detected) value
*
*/
- private function applyFind($key, $value) {
+ private function applyFind(string $key, string $value): void {
$this->result->addChange($key, $value);
$this->configuration->setConfiguration([$key => $value]);
}
@@ -778,7 +773,7 @@ class Wizard extends LDAPUtility {
* field. In this case the port will be stripped off, but also stored as
* setting.
*/
- private function checkHost() {
+ private function checkHost(): void {
$host = $this->configuration->ldapHost;
$hostInfo = parse_url($host);
@@ -787,14 +782,14 @@ class Wizard extends LDAPUtility {
$port = $hostInfo['port'];
$host = str_replace(':'.$port, '', $host);
$this->applyFind('ldap_host', $host);
- $this->applyFind('ldap_port', $port);
+ $this->applyFind('ldap_port', (string)$port);
}
}
/**
* tries to detect the group member association attribute which is
* one of 'uniqueMember', 'memberUid', 'member', 'gidNumber'
- * @return string|false, string with the attribute name, false on error
+ * @return string|false string with the attribute name, false on error
* @throws \Exception
*/
private function detectGroupMemberAssoc() {
@@ -812,6 +807,7 @@ class Wizard extends LDAPUtility {
if (!$this->ldap->isResource($rr)) {
return false;
}
+ /** @var resource|\LDAP\Result $rr */
$er = $this->ldap->firstEntry($cr, $rr);
while ($this->ldap->isResource($er)) {
$this->ldap->getDN($cr, $er);
@@ -840,7 +836,7 @@ class Wizard extends LDAPUtility {
* @return bool true on success, false otherwise
* @throws \Exception
*/
- private function testBaseDN($base) {
+ private function testBaseDN(string $base): bool {
$cr = $this->getConnection();
if (!$cr) {
throw new \Exception('Could not connect to LDAP');
@@ -858,6 +854,7 @@ class Wizard extends LDAPUtility {
);
return false;
}
+ /** @var resource|\LDAP\Result $rr */
$entries = $this->ldap->countEntries($cr, $rr);
return ($entries !== false) && ($entries > 0);
}
@@ -871,7 +868,7 @@ class Wizard extends LDAPUtility {
* @return bool true if it does, false otherwise
* @throws \Exception
*/
- private function testMemberOf() {
+ private function testMemberOf(): bool {
$cr = $this->getConnection();
if (!$cr) {
throw new \Exception('Could not connect to LDAP');
@@ -885,13 +882,12 @@ class Wizard extends LDAPUtility {
/**
* creates an LDAP Filter from given configuration
- * @param integer $filterType int, for which use case the filter shall be created
+ * @param int $filterType int, for which use case the filter shall be created
* can be any of self::LFILTER_USER_LIST, self::LFILTER_LOGIN or
* self::LFILTER_GROUP_LIST
- * @return string|false string with the filter on success, false otherwise
* @throws \Exception
*/
- private function composeLdapFilter($filterType) {
+ private function composeLdapFilter(int $filterType): string {
$filter = '';
$parts = 0;
switch ($filterType) {
@@ -921,6 +917,7 @@ class Wizard extends LDAPUtility {
if (!$this->ldap->isResource($rr)) {
continue;
}
+ /** @var resource|\LDAP\Result $rr */
$er = $this->ldap->firstEntry($cr, $rr);
$attrs = $this->ldap->getAttributes($cr, $er);
$dn = $this->ldap->getDN($cr, $er);
@@ -980,6 +977,9 @@ class Wizard extends LDAPUtility {
$loginpart = '=%uid';
$filterUsername = '';
$userAttributes = $this->getUserAttributes();
+ if ($userAttributes === false) {
+ throw new \Exception('Failed to get user attributes');
+ }
$userAttributes = array_change_key_case(array_flip($userAttributes));
$parts = 0;
@@ -1044,24 +1044,24 @@ class Wizard extends LDAPUtility {
*
* @param int $port the port to connect with
* @param bool $tls whether startTLS is to be used
- * @return bool
* @throws \Exception
*/
- private function connectAndBind($port, $tls) {
+ private function connectAndBind(int $port, bool $tls): bool {
//connect, does not really trigger any server communication
$host = $this->configuration->ldapHost;
- $hostInfo = parse_url($host);
- if (!$hostInfo) {
+ $hostInfo = parse_url((string)$host);
+ if (!is_string($host) || !$hostInfo) {
throw new \Exception(self::$l->t('Invalid Host'));
}
$this->logger->debug(
'Wiz: Attempting to connect',
['app' => 'user_ldap']
);
- $cr = $this->ldap->connect($host, $port);
+ $cr = $this->ldap->connect($host, (string)$port);
if (!$this->ldap->isResource($cr)) {
throw new \Exception(self::$l->t('Invalid Host'));
}
+ /** @var resource|\LDAP\Connection $cr */
//set LDAP options
$this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
@@ -1086,7 +1086,7 @@ class Wizard extends LDAPUtility {
$this->configuration->ldapAgentPassword
);
$errNo = $this->ldap->errno($cr);
- $error = ldap_error($cr);
+ $error = $this->ldap->error($cr);
$this->ldap->unbind($cr);
} catch (ServerNotAvailableException $e) {
return false;
@@ -1110,9 +1110,9 @@ class Wizard extends LDAPUtility {
/**
* checks whether a valid combination of agent and password has been
* provided (either two values or nothing for anonymous connect)
- * @return bool, true if everything is fine, false otherwise
+ * @return bool true if everything is fine, false otherwise
*/
- private function checkAgentRequirements() {
+ private function checkAgentRequirements(): bool {
$agent = $this->configuration->ldapAgentName;
$pwd = $this->configuration->ldapAgentPassword;
@@ -1122,11 +1122,7 @@ class Wizard extends LDAPUtility {
;
}
- /**
- * @param array $reqs
- * @return bool
- */
- private function checkRequirements($reqs) {
+ private function checkRequirements(array $reqs): bool {
$this->checkAgentRequirements();
foreach ($reqs as $option) {
$value = $this->configuration->$option;
@@ -1148,7 +1144,7 @@ class Wizard extends LDAPUtility {
* yields most result entries
* @return array|false an array with the values on success, false otherwise
*/
- public function cumulativeSearchOnAttribute($filters, $attr, $dnReadLimit = 3, &$maxF = null) {
+ public function cumulativeSearchOnAttribute(array $filters, string $attr, int $dnReadLimit = 3, ?string &$maxF = null) {
$dnRead = [];
$foundItems = [];
$maxEntries = 0;
@@ -1161,6 +1157,7 @@ class Wizard extends LDAPUtility {
if (!$this->ldap->isResource($cr)) {
return false;
}
+ /** @var resource|\LDAP\Connection $cr */
$lastFilter = null;
if (isset($filters[count($filters) - 1])) {
$lastFilter = $filters[count($filters) - 1];
@@ -1175,6 +1172,7 @@ class Wizard extends LDAPUtility {
if (!$this->ldap->isResource($rr)) {
continue;
}
+ /** @var resource|\LDAP\Result $rr */
$entries = $this->ldap->countEntries($cr, $rr);
$getEntryFunc = 'firstEntry';
if (($entries !== false) && ($entries > 0)) {
@@ -1192,16 +1190,17 @@ class Wizard extends LDAPUtility {
$rr = $entry; //will be expected by nextEntry next round
$attributes = $this->ldap->getAttributes($cr, $entry);
$dn = $this->ldap->getDN($cr, $entry);
- if ($dn === false || in_array($dn, $dnRead)) {
+ if ($attributes === false || $dn === false || in_array($dn, $dnRead)) {
continue;
}
$newItems = [];
- $state = $this->getAttributeValuesFromEntry($attributes,
+ $state = $this->getAttributeValuesFromEntry(
+ $attributes,
$attr,
- $newItems);
+ $newItems
+ );
$dnReadCount++;
$foundItems = array_merge($foundItems, $newItems);
- $this->resultCache[$dn][$attr] = $newItems;
$dnRead[] = $dn;
} while (($state === self::LRESULT_PROCESSED_SKIP
|| $this->ldap->isResource($entry))
@@ -1221,10 +1220,10 @@ class Wizard extends LDAPUtility {
* Configuration class
* @param bool $po whether the objectClass with most result entries
* shall be pre-selected via the result
- * @return array|false list of found items.
+ * @return array list of found items.
* @throws \Exception
*/
- private function determineFeature($objectclasses, $attr, $dbkey, $confkey, $po = false) {
+ private function determineFeature(array $objectclasses, string $attr, string $dbkey, string $confkey, bool $po = false): array {
$cr = $this->getConnection();
if (!$cr) {
throw new \Exception('Could not connect to LDAP');
@@ -1271,12 +1270,11 @@ class Wizard extends LDAPUtility {
* @param array $result the return value from ldap_get_attributes
* @param string $attribute the attribute values to look for
* @param array &$known new values will be appended here
- * @return int, state on of the class constants LRESULT_PROCESSED_OK,
+ * @return int state on of the class constants LRESULT_PROCESSED_OK,
* LRESULT_PROCESSED_INVALID or LRESULT_PROCESSED_SKIP
*/
- private function getAttributeValuesFromEntry($result, $attribute, &$known) {
- if (!is_array($result)
- || !isset($result['count'])
+ private function getAttributeValuesFromEntry(array $result, string $attribute, array &$known): int {
+ if (!isset($result['count'])
|| !$result['count'] > 0) {
return self::LRESULT_PROCESSED_INVALID;
}
@@ -1300,7 +1298,7 @@ class Wizard extends LDAPUtility {
}
/**
- * @return bool|mixed
+ * @return resource|\LDAP\Connection|false a link resource on success, otherwise false
*/
private function getConnection() {
if (!is_null($this->cr)) {
@@ -1312,6 +1310,10 @@ class Wizard extends LDAPUtility {
$this->configuration->ldapPort
);
+ if ($cr === false) {
+ return false;
+ }
+
$this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
$this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0);
$this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT);
@@ -1330,10 +1332,7 @@ class Wizard extends LDAPUtility {
return false;
}
- /**
- * @return array
- */
- private function getDefaultLdapPortSettings() {
+ private function getDefaultLdapPortSettings(): array {
static $settings = [
['port' => 7636, 'tls' => false],
['port' => 636, 'tls' => false],
@@ -1345,10 +1344,7 @@ class Wizard extends LDAPUtility {
return $settings;
}
- /**
- * @return array
- */
- private function getPortSettingsToTry() {
+ private function getPortSettingsToTry(): array {
//389 ← LDAP / Unencrypted or StartTLS
//636 ← LDAPS / SSL
//7xxx ← UCS. need to be checked first, because both ports may be open