diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index ec7b0c51515c0..64845f15cf541 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -77,6 +77,9 @@ */ class ShareAPIController extends OCSController { + /** Maximum length of a custom share token, matching the oc_share.token database column. */ + private const TOKEN_MAX_LENGTH = 32; + private ?Node $lockedNode = null; /** @var array $trustedServerCache */ private array $trustedServerCache = []; @@ -1363,7 +1366,7 @@ public function updateShare( throw new OCSForbiddenException($this->l->t('Custom share link tokens have been disabled by the administrator')); } if (!$this->validateToken($token)) { - throw new OCSBadRequestException($this->l->t('Tokens must contain at least 1 character and may only contain letters, numbers, or a hyphen')); + throw new OCSBadRequestException($this->l->t('Tokens must be between 1 and %s characters long and may only contain letters, numbers, or a hyphen', [self::TOKEN_MAX_LENGTH])); } $share->setToken($token); } @@ -1402,7 +1405,8 @@ public function updateShare( } private function validateToken(string $token): bool { - if (mb_strlen($token) === 0) { + $length = mb_strlen($token); + if ($length === 0 || $length > self::TOKEN_MAX_LENGTH) { return false; } if (!preg_match('/^[a-z0-9-]+$/i', $token)) { diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 55cf24d79d788..097de4fa43740 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -5604,6 +5604,23 @@ public function testWrapperStorageUnwrapped(): void { $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]); } + public static function dataValidateToken(): array { + return [ + 'empty token' => ['', false], + 'single character' => ['a', true], + 'letters numbers and hyphen' => ['abc-123', true], + 'invalid character' => ['abc_123', false], + '32 characters (oc_share.token column limit)' => [str_repeat('a', 32), true], + '32 non-ascii characters' => [str_repeat('é', 32), false], + '33 characters (exceeds oc_share.token column limit)' => [str_repeat('a', 33), false], + ]; + } + + #[DataProvider('dataValidateToken')] + public function testValidateToken(string $token, bool $expected): void { + $this->assertSame($expected, $this->invokePrivate($this->ocs, 'validateToken', [$token])); + } + /** * Helper to allow testing Talk integration even if Talk * is not available during tests.