Skip to content

Commit 4fad4d8

Browse files
Merge branch 'master' into fix/issue-48079-windows-time-zones
2 parents d17895e + 01b2ae4 commit 4fad4d8

File tree

120 files changed

+962
-331
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+962
-331
lines changed

.github/workflows/cypress.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ jobs:
162162

163163
- name: Create data dir archive
164164
if: failure() && matrix.containers != 'component'
165-
run: docker exec nextcloud-cypress-tests-server tar -cvjf - data > data.tar
165+
run: docker exec nextcloud-cypress-tests_server tar -cvjf - data > data.tar
166166

167167
- name: Upload data dir archive
168168
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3

.github/workflows/files-external-smb-kerberos.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ jobs:
5353
repository: nextcloud/user_saml
5454
path: apps/user_saml
5555

56+
- name: Install user_saml
57+
run: |
58+
cd apps/user_saml
59+
composer i
60+
cd ../..
61+
5662
- name: Pull images
5763
run: |
5864
docker pull ghcr.io/icewind1991/samba-krb-test-dc

apps/dav/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@
277277
'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => $baseDir . '/../lib/Events/SubscriptionUpdatedEvent.php',
278278
'OCA\\DAV\\Exception\\ServerMaintenanceMode' => $baseDir . '/../lib/Exception/ServerMaintenanceMode.php',
279279
'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => $baseDir . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php',
280-
'OCA\\DAV\\Files\\ErrorPagePlugin' => $baseDir . '/../lib/Files/ErrorPagePlugin.php',
280+
'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => $baseDir . '/../lib/Files/BrowserErrorPagePlugin.php',
281281
'OCA\\DAV\\Files\\FileSearchBackend' => $baseDir . '/../lib/Files/FileSearchBackend.php',
282282
'OCA\\DAV\\Files\\FilesHome' => $baseDir . '/../lib/Files/FilesHome.php',
283283
'OCA\\DAV\\Files\\LazySearchBackend' => $baseDir . '/../lib/Files/LazySearchBackend.php',

apps/dav/composer/composer/autoload_static.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ class ComposerStaticInitDAV
292292
'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/SubscriptionUpdatedEvent.php',
293293
'OCA\\DAV\\Exception\\ServerMaintenanceMode' => __DIR__ . '/..' . '/../lib/Exception/ServerMaintenanceMode.php',
294294
'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => __DIR__ . '/..' . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php',
295-
'OCA\\DAV\\Files\\ErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/ErrorPagePlugin.php',
295+
'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/BrowserErrorPagePlugin.php',
296296
'OCA\\DAV\\Files\\FileSearchBackend' => __DIR__ . '/..' . '/../lib/Files/FileSearchBackend.php',
297297
'OCA\\DAV\\Files\\FilesHome' => __DIR__ . '/..' . '/../lib/Files/FilesHome.php',
298298
'OCA\\DAV\\Files\\LazySearchBackend' => __DIR__ . '/..' . '/../lib/Files/LazySearchBackend.php',

apps/dav/lib/CalDAV/CalDavBackend.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3569,9 +3569,9 @@ protected function purgeCalendarInvitations(int $calendarId): void {
35693569
// delete all links that match object uid's
35703570
$cmd = $this->db->getQueryBuilder();
35713571
$cmd->delete($this->dbObjectInvitationsTable)
3572-
->where($cmd->expr()->in('uid', $cmd->createNamedParameter('uids'), IQueryBuilder::PARAM_STR_ARRAY));
3573-
foreach (array_chunk($allIds, 1000) as $chunckIds) {
3574-
$cmd->setParameter('uids', $chunckIds, IQueryBuilder::PARAM_INT_ARRAY);
3572+
->where($cmd->expr()->in('uid', $cmd->createParameter('uids'), IQueryBuilder::PARAM_STR_ARRAY));
3573+
foreach (array_chunk($allIds, 1000) as $chunkIds) {
3574+
$cmd->setParameter('uids', $chunkIds, IQueryBuilder::PARAM_STR_ARRAY);
35753575
$cmd->executeStatement();
35763576
}
35773577
}
@@ -3588,7 +3588,7 @@ protected function purgeCalendarInvitations(int $calendarId): void {
35883588
protected function purgeObjectInvitations(string $eventId): void {
35893589
$cmd = $this->db->getQueryBuilder();
35903590
$cmd->delete($this->dbObjectInvitationsTable)
3591-
->where($cmd->expr()->eq('uid', $cmd->createNamedParameter($eventId)));
3591+
->where($cmd->expr()->eq('uid', $cmd->createNamedParameter($eventId, IQueryBuilder::PARAM_STR), IQueryBuilder::PARAM_STR));
35923592
$cmd->executeStatement();
35933593
}
35943594
}

apps/dav/lib/Connector/Sabre/Server.php

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
*/
88
namespace OCA\DAV\Connector\Sabre;
99

10+
use Sabre\DAV\Exception;
11+
use Sabre\DAV\Version;
12+
1013
/**
1114
* Class \OCA\DAV\Connector\Sabre\Server
1215
*
@@ -26,9 +29,11 @@ public function __construct($treeOrNode = null) {
2629
$this->enablePropfindDepthInfinity = true;
2730
}
2831

29-
// Copied from 3rdparty/sabre/dav/lib/DAV/Server.php
30-
// Should be them exact same without the exception output.
31-
public function start(): void {
32+
/**
33+
*
34+
* @return void
35+
*/
36+
public function start() {
3237
try {
3338
// If nginx (pre-1.2) is used as a proxy server, and SabreDAV as an
3439
// origin, we must make sure we send back HTTP/1.0 if this was
@@ -42,10 +47,74 @@ public function start(): void {
4247
$this->httpRequest->setBaseUrl($this->getBaseUri());
4348
$this->invokeMethod($this->httpRequest, $this->httpResponse);
4449
} catch (\Throwable $e) {
50+
if ($e instanceof \TypeError) {
51+
/*
52+
* The TypeError includes the file path where the error occurred,
53+
* potentially revealing the installation directory.
54+
*
55+
* By re-throwing the exception, we ensure that the
56+
* default exception handler processes it.
57+
*/
58+
throw $e;
59+
}
60+
4561
try {
4662
$this->emit('exception', [$e]);
4763
} catch (\Exception $ignore) {
4864
}
65+
66+
$DOM = new \DOMDocument('1.0', 'utf-8');
67+
$DOM->formatOutput = true;
68+
69+
$error = $DOM->createElementNS('DAV:', 'd:error');
70+
$error->setAttribute('xmlns:s', self::NS_SABREDAV);
71+
$DOM->appendChild($error);
72+
73+
$h = function ($v) {
74+
return htmlspecialchars((string)$v, ENT_NOQUOTES, 'UTF-8');
75+
};
76+
77+
if (self::$exposeVersion) {
78+
$error->appendChild($DOM->createElement('s:sabredav-version', $h(Version::VERSION)));
79+
}
80+
81+
$error->appendChild($DOM->createElement('s:exception', $h(get_class($e))));
82+
$error->appendChild($DOM->createElement('s:message', $h($e->getMessage())));
83+
if ($this->debugExceptions) {
84+
$error->appendChild($DOM->createElement('s:file', $h($e->getFile())));
85+
$error->appendChild($DOM->createElement('s:line', $h($e->getLine())));
86+
$error->appendChild($DOM->createElement('s:code', $h($e->getCode())));
87+
$error->appendChild($DOM->createElement('s:stacktrace', $h($e->getTraceAsString())));
88+
}
89+
90+
if ($this->debugExceptions) {
91+
$previous = $e;
92+
while ($previous = $previous->getPrevious()) {
93+
$xPrevious = $DOM->createElement('s:previous-exception');
94+
$xPrevious->appendChild($DOM->createElement('s:exception', $h(get_class($previous))));
95+
$xPrevious->appendChild($DOM->createElement('s:message', $h($previous->getMessage())));
96+
$xPrevious->appendChild($DOM->createElement('s:file', $h($previous->getFile())));
97+
$xPrevious->appendChild($DOM->createElement('s:line', $h($previous->getLine())));
98+
$xPrevious->appendChild($DOM->createElement('s:code', $h($previous->getCode())));
99+
$xPrevious->appendChild($DOM->createElement('s:stacktrace', $h($previous->getTraceAsString())));
100+
$error->appendChild($xPrevious);
101+
}
102+
}
103+
104+
if ($e instanceof Exception) {
105+
$httpCode = $e->getHTTPCode();
106+
$e->serialize($this, $error);
107+
$headers = $e->getHTTPHeaders($this);
108+
} else {
109+
$httpCode = 500;
110+
$headers = [];
111+
}
112+
$headers['Content-Type'] = 'application/xml; charset=utf-8';
113+
114+
$this->httpResponse->setStatus($httpCode);
115+
$this->httpResponse->setHeaders($headers);
116+
$this->httpResponse->setBody($DOM->saveXML());
117+
$this->sapi->sendResponse($this->httpResponse);
49118
}
50119
}
51120
}

apps/dav/lib/Connector/Sabre/ServerFactory.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use OCA\DAV\CalDAV\DefaultCalendarValidator;
1313
use OCA\DAV\DAV\CustomPropertiesBackend;
1414
use OCA\DAV\DAV\ViewOnlyPlugin;
15-
use OCA\DAV\Files\ErrorPagePlugin;
15+
use OCA\DAV\Files\BrowserErrorPagePlugin;
1616
use OCA\Theming\ThemingDefaults;
1717
use OCP\EventDispatcher\IEventDispatcher;
1818
use OCP\Files\Folder;
@@ -90,7 +90,9 @@ public function createServer(string $baseUri,
9090
$server->addPlugin(new FakeLockerPlugin());
9191
}
9292

93-
$server->addPlugin(new ErrorPagePlugin($this->request, $this->config));
93+
if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
94+
$server->addPlugin(new BrowserErrorPagePlugin());
95+
}
9496

9597
// wait with registering these until auth is handled and the filesystem is setup
9698
$server->on('beforeMethod:*', function () use ($server, $objectTree, $viewCallBack): void {

apps/dav/lib/Files/ErrorPagePlugin.php renamed to apps/dav/lib/Files/BrowserErrorPagePlugin.php

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,17 @@
77
*/
88
namespace OCA\DAV\Files;
99

10+
use OC\AppFramework\Http\Request;
1011
use OC_Template;
1112
use OCP\AppFramework\Http\ContentSecurityPolicy;
12-
use OCP\IConfig;
1313
use OCP\IRequest;
1414
use Sabre\DAV\Exception;
1515
use Sabre\DAV\Server;
1616
use Sabre\DAV\ServerPlugin;
1717

18-
class ErrorPagePlugin extends ServerPlugin {
19-
private ?Server $server = null;
20-
21-
public function __construct(
22-
private IRequest $request,
23-
private IConfig $config,
24-
) {
25-
}
18+
class BrowserErrorPagePlugin extends ServerPlugin {
19+
/** @var Server */
20+
private $server;
2621

2722
/**
2823
* This initializes the plugin.
@@ -31,12 +26,35 @@ public function __construct(
3126
* addPlugin is called.
3227
*
3328
* This method should set up the required event subscriptions.
29+
*
30+
* @param Server $server
31+
* @return void
3432
*/
35-
public function initialize(Server $server): void {
33+
public function initialize(Server $server) {
3634
$this->server = $server;
3735
$server->on('exception', [$this, 'logException'], 1000);
3836
}
3937

38+
/**
39+
* @param IRequest $request
40+
* @return bool
41+
*/
42+
public static function isBrowserRequest(IRequest $request) {
43+
if ($request->getMethod() !== 'GET') {
44+
return false;
45+
}
46+
return $request->isUserAgent([
47+
Request::USER_AGENT_IE,
48+
Request::USER_AGENT_MS_EDGE,
49+
Request::USER_AGENT_CHROME,
50+
Request::USER_AGENT_FIREFOX,
51+
Request::USER_AGENT_SAFARI,
52+
]);
53+
}
54+
55+
/**
56+
* @param \Throwable $ex
57+
*/
4058
public function logException(\Throwable $ex): void {
4159
if ($ex instanceof Exception) {
4260
$httpCode = $ex->getHTTPCode();
@@ -47,7 +65,7 @@ public function logException(\Throwable $ex): void {
4765
}
4866
$this->server->httpResponse->addHeaders($headers);
4967
$this->server->httpResponse->setStatus($httpCode);
50-
$body = $this->generateBody($ex, $httpCode);
68+
$body = $this->generateBody($httpCode);
5169
$this->server->httpResponse->setBody($body);
5270
$csp = new ContentSecurityPolicy();
5371
$this->server->httpResponse->addHeader('Content-Security-Policy', $csp->buildPolicy());
@@ -58,32 +76,18 @@ public function logException(\Throwable $ex): void {
5876
* @codeCoverageIgnore
5977
* @return bool|string
6078
*/
61-
public function generateBody(\Throwable $ex, int $httpCode): mixed {
62-
if ($this->acceptHtml()) {
63-
$templateName = 'exception';
64-
$renderAs = 'guest';
65-
if ($httpCode === 403 || $httpCode === 404) {
66-
$templateName = (string)$httpCode;
67-
}
68-
} else {
69-
$templateName = 'xml_exception';
70-
$renderAs = null;
71-
$this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
72-
}
79+
public function generateBody(int $httpCode) {
80+
$request = \OC::$server->getRequest();
7381

74-
$debug = $this->config->getSystemValueBool('debug', false);
82+
$templateName = 'exception';
83+
if ($httpCode === 403 || $httpCode === 404) {
84+
$templateName = (string)$httpCode;
85+
}
7586

76-
$content = new OC_Template('core', $templateName, $renderAs);
87+
$content = new OC_Template('core', $templateName, 'guest');
7788
$content->assign('title', $this->server->httpResponse->getStatusText());
78-
$content->assign('remoteAddr', $this->request->getRemoteAddress());
79-
$content->assign('requestID', $this->request->getId());
80-
$content->assign('debugMode', $debug);
81-
$content->assign('errorClass', get_class($ex));
82-
$content->assign('errorMsg', $ex->getMessage());
83-
$content->assign('errorCode', $ex->getCode());
84-
$content->assign('file', $ex->getFile());
85-
$content->assign('line', $ex->getLine());
86-
$content->assign('exception', $ex);
89+
$content->assign('remoteAddr', $request->getRemoteAddress());
90+
$content->assign('requestID', $request->getId());
8791
return $content->fetchPage();
8892
}
8993

@@ -92,15 +96,6 @@ public function generateBody(\Throwable $ex, int $httpCode): mixed {
9296
*/
9397
public function sendResponse() {
9498
$this->server->sapi->sendResponse($this->server->httpResponse);
95-
}
96-
97-
private function acceptHtml(): bool {
98-
foreach (explode(',', $this->request->getHeader('Accept')) as $part) {
99-
$subparts = explode(';', $part);
100-
if (str_ends_with($subparts[0], '/html')) {
101-
return true;
102-
}
103-
}
104-
return false;
99+
exit();
105100
}
106101
}

apps/dav/lib/Server.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
use OCA\DAV\DAV\ViewOnlyPlugin;
5555
use OCA\DAV\Events\SabrePluginAddEvent;
5656
use OCA\DAV\Events\SabrePluginAuthInitEvent;
57-
use OCA\DAV\Files\ErrorPagePlugin;
57+
use OCA\DAV\Files\BrowserErrorPagePlugin;
5858
use OCA\DAV\Files\FileSearchBackend;
5959
use OCA\DAV\Files\LazySearchBackend;
6060
use OCA\DAV\Profiler\ProfilerPlugin;
@@ -244,7 +244,9 @@ public function __construct(
244244
$this->server->addPlugin(new FakeLockerPlugin());
245245
}
246246

247-
$this->server->addPlugin(new ErrorPagePlugin($this->request, \OC::$server->getConfig()));
247+
if (BrowserErrorPagePlugin::isBrowserRequest($request)) {
248+
$this->server->addPlugin(new BrowserErrorPagePlugin());
249+
}
248250

249251
$lazySearchBackend = new LazySearchBackend();
250252
$this->server->addPlugin(new SearchPlugin($lazySearchBackend));

apps/dav/tests/testsuits/caldavtest/tests/CalDAV/sync-report.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2701,7 +2701,7 @@
27012701
<callback>prepostcondition</callback>
27022702
<arg>
27032703
<name>error</name>
2704-
<value>{http://sabredav.org/ns}exception</value>
2704+
<value>{DAV:}valid-sync-token</value>
27052705
</arg>
27062706
<arg>
27072707
<name>ignoreextras</name>

0 commit comments

Comments
 (0)