Skip to content

Commit

Permalink
Merge branch 'master' into FIX-WebDav-MacOS-failed-uploads-php-fpm-an…
Browse files Browse the repository at this point in the history
…d-big-files-(-36-error)
  • Loading branch information
gonzalo authored Nov 29, 2024
2 parents 0852dac + a4c3e0c commit c428ba8
Show file tree
Hide file tree
Showing 246 changed files with 4,630 additions and 4,054 deletions.
18 changes: 15 additions & 3 deletions apps/dav/lib/Connector/Sabre/BlockLegacyClientPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,26 @@ public function beforeHandler(RequestInterface $request) {
return;
}

$minimumSupportedDesktopVersion = $this->config->getSystemValue('minimum.supported.desktop.version', '2.3.0');
$minimumSupportedDesktopVersion = $this->config->getSystemValueString('minimum.supported.desktop.version', '2.3.0');
$maximumSupportedDesktopVersion = $this->config->getSystemValueString('maximum.supported.desktop.version', '99.99.99');

// Check if the client is a desktop client
preg_match(IRequest::USER_AGENT_CLIENT_DESKTOP, $userAgent, $versionMatches);
if (isset($versionMatches[1]) &&
version_compare($versionMatches[1], $minimumSupportedDesktopVersion) === -1) {

// If the client is a desktop client and the version is too old, block it
if (isset($versionMatches[1]) && version_compare($versionMatches[1], $minimumSupportedDesktopVersion) === -1) {
$customClientDesktopLink = htmlspecialchars($this->themingDefaults->getSyncClientUrl());
$minimumSupportedDesktopVersion = htmlspecialchars($minimumSupportedDesktopVersion);

throw new \Sabre\DAV\Exception\Forbidden("This version of the client is unsupported. Upgrade to <a href=\"$customClientDesktopLink\">version $minimumSupportedDesktopVersion or later</a>.");
}

// If the client is a desktop client and the version is too new, block it
if (isset($versionMatches[1]) && version_compare($versionMatches[1], $maximumSupportedDesktopVersion) === 1) {
$customClientDesktopLink = htmlspecialchars($this->themingDefaults->getSyncClientUrl());
$maximumSupportedDesktopVersion = htmlspecialchars($maximumSupportedDesktopVersion);

throw new \Sabre\DAV\Exception\Forbidden("This version of the client is unsupported. Downgrade to <a href=\"$customClientDesktopLink\">version $maximumSupportedDesktopVersion or earlier</a>.");
}
}
}
85 changes: 58 additions & 27 deletions apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
use Sabre\HTTP\RequestInterface;
use Test\TestCase;

enum ERROR_TYPE {
case MIN_ERROR;
case MAX_ERROR;
case NONE;
}

/**
* Class BlockLegacyClientPluginTest
*
Expand All @@ -40,29 +46,41 @@ protected function setUp(): void {

public static function oldDesktopClientProvider(): array {
return [
['Mozilla/5.0 (Windows) mirall/1.5.0'],
['Mozilla/5.0 (Bogus Text) mirall/1.6.9'],
['Mozilla/5.0 (Windows) mirall/1.5.0', ERROR_TYPE::MIN_ERROR],
['Mozilla/5.0 (Bogus Text) mirall/1.6.9', ERROR_TYPE::MIN_ERROR],
['Mozilla/5.0 (Windows) mirall/2.5.0', ERROR_TYPE::MAX_ERROR],
['Mozilla/5.0 (Bogus Text) mirall/2.0.1', ERROR_TYPE::MAX_ERROR],
['Mozilla/5.0 (Windows) mirall/2.0.0', ERROR_TYPE::NONE],
['Mozilla/5.0 (Bogus Text) mirall/2.0.0', ERROR_TYPE::NONE],
];
}

/**
* @dataProvider oldDesktopClientProvider
*/
public function testBeforeHandlerException(string $userAgent): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);

public function testBeforeHandlerException(string $userAgent, ERROR_TYPE $errorType): void {
$this->themingDefaults
->expects($this->once())
->expects($this->atMost(1))
->method('getSyncClientUrl')
->willReturn('https://nextcloud.com/install/#install-clients');

$this->config
->expects($this->once())
->method('getSystemValue')
->with('minimum.supported.desktop.version', '2.3.0')
->willReturn('1.7.0');

$this->expectExceptionMessage('This version of the client is unsupported. Upgrade to <a href="https://nextcloud.com/install/#install-clients">version 1.7.0 or later</a>.');
->expects($this->exactly(2))
->method('getSystemValueString')
->willReturnCallback(function (string $key) {
if ($key === 'minimum.supported.desktop.version') {
return '1.7.0';
}
return '2.0.0';
});

if ($errorType !== ERROR_TYPE::NONE) {
$errorString = $errorType === ERROR_TYPE::MIN_ERROR
? 'This version of the client is unsupported. Upgrade to <a href="https://nextcloud.com/install/#install-clients">version 1.7.0 or later</a>.'
: 'This version of the client is unsupported. Downgrade to <a href="https://nextcloud.com/install/#install-clients">version 2.0.0 or earlier</a>.';
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->expectExceptionMessage($errorString);
}

/** @var RequestInterface|MockObject $request */
$request = $this->createMock('\Sabre\HTTP\RequestInterface');
Expand All @@ -72,29 +90,35 @@ public function testBeforeHandlerException(string $userAgent): void {
->with('User-Agent')
->willReturn($userAgent);


$this->blockLegacyClientVersionPlugin->beforeHandler($request);
}

/**
* Ensure that there is no room for XSS attack through configured URL / version
* @dataProvider oldDesktopClientProvider
*/
public function testBeforeHandlerExceptionPreventXSSAttack(string $userAgent): void {
public function testBeforeHandlerExceptionPreventXSSAttack(string $userAgent, ERROR_TYPE $errorType): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);

$this->themingDefaults
->expects($this->once())
->expects($this->atMost(1))
->method('getSyncClientUrl')
->willReturn('https://example.com"><script>alter("hacked");</script>');

$this->config
->expects($this->once())
->method('getSystemValue')
->with('minimum.supported.desktop.version', '2.3.0')
->willReturn('1.7.0 <script>alert("unsafe")</script>');

$this->expectExceptionMessage('This version of the client is unsupported. Upgrade to <a href="https://example.com&quot;&gt;&lt;script&gt;alter(&quot;hacked&quot;);&lt;/script&gt;">version 1.7.0 &lt;script&gt;alert(&quot;unsafe&quot;)&lt;/script&gt; or later</a>.');
->expects($this->exactly(2))
->method('getSystemValueString')
->willReturnCallback(function (string $key) {
if ($key === 'minimum.supported.desktop.version') {
return '1.7.0 <script>alert("unsafe")</script>';
}
return '2.0.0 <script>alert("unsafe")</script>';
});

$errorString = $errorType === ERROR_TYPE::MIN_ERROR
? 'This version of the client is unsupported. Upgrade to <a href="https://example.com&quot;&gt;&lt;script&gt;alter(&quot;hacked&quot;);&lt;/script&gt;">version 1.7.0 &lt;script&gt;alert(&quot;unsafe&quot;)&lt;/script&gt; or later</a>.'
: 'This version of the client is unsupported. Downgrade to <a href="https://example.com&quot;&gt;&lt;script&gt;alter(&quot;hacked&quot;);&lt;/script&gt;">version 2.0.0 &lt;script&gt;alert(&quot;unsafe&quot;)&lt;/script&gt; or earlier</a>.';
$this->expectExceptionMessage($errorString);

/** @var RequestInterface|MockObject $request */
$request = $this->createMock('\Sabre\HTTP\RequestInterface');
Expand All @@ -104,15 +128,17 @@ public function testBeforeHandlerExceptionPreventXSSAttack(string $userAgent): v
->with('User-Agent')
->willReturn($userAgent);


$this->blockLegacyClientVersionPlugin->beforeHandler($request);
}

public function newAndAlternateDesktopClientProvider(): array {
public static function newAndAlternateDesktopClientProvider(): array {
return [
['Mozilla/5.0 (Windows) mirall/1.7.0'],
['Mozilla/5.0 (Bogus Text) mirall/1.9.3'],
['Mozilla/5.0 (Not Our Client But Old Version) LegacySync/1.1.0'],
['Mozilla/5.0 (Windows) mirall/4.7.0'],
['Mozilla/5.0 (Bogus Text) mirall/3.9.3'],
['Mozilla/5.0 (Not Our Client But Old Version) LegacySync/45.0.0'],
];
}

Expand All @@ -129,10 +155,14 @@ public function testBeforeHandlerSuccess(string $userAgent): void {
->willReturn($userAgent);

$this->config
->expects($this->once())
->method('getSystemValue')
->with('minimum.supported.desktop.version', '2.3.0')
->willReturn('1.7.0');
->expects($this->exactly(2))
->method('getSystemValueString')
->willReturnCallback(function (string $key) {
if ($key === 'minimum.supported.desktop.version') {
return '1.7.0';
}
return '10.0.0';
});

$this->blockLegacyClientVersionPlugin->beforeHandler($request);
}
Expand All @@ -145,6 +175,7 @@ public function testBeforeHandlerNoUserAgent(): void {
->method('getHeader')
->with('User-Agent')
->willReturn(null);

$this->blockLegacyClientVersionPlugin->beforeHandler($request);
}
}
7 changes: 7 additions & 0 deletions apps/files/l10n/cs.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,13 @@ OC.L10N.register(
"Files moved successfully" : "Soubory úspěšně přesunuty",
"Conflicts resolution skipped" : "Řešení kolizí přeskočeno",
"Upload cancelled" : "Nahrávání zrušen",
"Adding the file extension \"{new}\" may render the file unreadable." : "Přidání přípony souboru „{new}“ může soubor znečitelnit.",
"Removing the file extension \"{old}\" may render the file unreadable." : "Odebrání přípony souboru „{old}“ může soubor znečitelnit.",
"Changing the file extension from \"{old}\" to \"{new}\" may render the file unreadable." : "Změna přípony souboru z „{old}“ na „{new}“ může soubor znečitelnit.",
"Change file extension" : "Změnit příponu souboru",
"Keep {oldextension}" : "Ponechat {oldextension}",
"Use {newextension}" : "Použít {newextension}",
"Remove extension" : "Odebrat příponu",
"This operation is forbidden" : "Tato operace je zakázána",
"This directory is unavailable, please check the logs or contact the administrator" : "Tento adresář není dostupný, zkontrolujte záznamy událostí nebo se obraťte na správce",
"Storage is temporarily not available" : "Úložiště je dočasně nedostupné",
Expand Down
7 changes: 7 additions & 0 deletions apps/files/l10n/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,13 @@
"Files moved successfully" : "Soubory úspěšně přesunuty",
"Conflicts resolution skipped" : "Řešení kolizí přeskočeno",
"Upload cancelled" : "Nahrávání zrušen",
"Adding the file extension \"{new}\" may render the file unreadable." : "Přidání přípony souboru „{new}“ může soubor znečitelnit.",
"Removing the file extension \"{old}\" may render the file unreadable." : "Odebrání přípony souboru „{old}“ může soubor znečitelnit.",
"Changing the file extension from \"{old}\" to \"{new}\" may render the file unreadable." : "Změna přípony souboru z „{old}“ na „{new}“ může soubor znečitelnit.",
"Change file extension" : "Změnit příponu souboru",
"Keep {oldextension}" : "Ponechat {oldextension}",
"Use {newextension}" : "Použít {newextension}",
"Remove extension" : "Odebrat příponu",
"This operation is forbidden" : "Tato operace je zakázána",
"This directory is unavailable, please check the logs or contact the administrator" : "Tento adresář není dostupný, zkontrolujte záznamy událostí nebo se obraťte na správce",
"Storage is temporarily not available" : "Úložiště je dočasně nedostupné",
Expand Down
2 changes: 1 addition & 1 deletion apps/files/l10n/gl.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "Non ten permiso para enviar ou crear ficheiros aquí.",
"Favorite" : "Favorito",
"\"{displayName}\" action executed successfully" : "A acción «{displayName}» executouse correctamente",
"\"{displayName}\" action failed" : "A acción «{displayName}» fallou",
"\"{displayName}\" action failed" : "Produciuse un fallo na acción «{displayName}»",
"Toggle selection for file \"{displayName}\"" : "Conmutar a selección para o ficheiro «{displayName}»",
"Toggle selection for folder \"{displayName}\"" : "Conmutar a selección para o cartafol «{displayName}»",
"File is loading" : "Estase a cargar o ficheiro",
Expand Down
2 changes: 1 addition & 1 deletion apps/files/l10n/gl.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"You don’t have permission to upload or create files here" : "Non ten permiso para enviar ou crear ficheiros aquí.",
"Favorite" : "Favorito",
"\"{displayName}\" action executed successfully" : "A acción «{displayName}» executouse correctamente",
"\"{displayName}\" action failed" : "A acción «{displayName}» fallou",
"\"{displayName}\" action failed" : "Produciuse un fallo na acción «{displayName}»",
"Toggle selection for file \"{displayName}\"" : "Conmutar a selección para o ficheiro «{displayName}»",
"Toggle selection for folder \"{displayName}\"" : "Conmutar a selección para o cartafol «{displayName}»",
"File is loading" : "Estase a cargar o ficheiro",
Expand Down
Loading

0 comments on commit c428ba8

Please sign in to comment.