Skip to content

Commit 6fee632

Browse files
authored
Merge branch 'stable26' into backport/46013/stable26
2 parents 9059def + 5c5b571 commit 6fee632

File tree

29 files changed

+496
-274
lines changed

29 files changed

+496
-274
lines changed

.git-blame-ignore-revs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# .git-blame-ignore-revs
2+
3+
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
4+
# SPDX-License-Identifier: AGPL-3.0-or-later

.github/workflows/smb-kerberos.yml

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,48 @@
11
name: Samba Kerberos SSO
22
on:
3-
push:
4-
branches:
5-
- master
6-
- stable*
7-
paths:
8-
- 'apps/files_external/**'
9-
- '.github/workflows/smb-kerberos.yml'
103
pull_request:
114
paths:
125
- 'apps/files_external/**'
136
- '.github/workflows/smb-kerberos.yml'
147

8+
concurrency:
9+
group: smb-kerberos-${{ github.head_ref || github.run_id }}
10+
cancel-in-progress: true
11+
1512
jobs:
1613
smb-kerberos-tests:
17-
runs-on: ubuntu-latest
14+
runs-on: ubuntu-22.04
1815

1916
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
2017

2118
name: smb-kerberos-sso
2219

2320
steps:
2421
- name: Checkout server
25-
uses: actions/checkout@v3
22+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
2623
with:
2724
submodules: true
25+
- name: Checkout user_saml
26+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
27+
with:
28+
repository: nextcloud/user_saml
29+
path: apps/user_saml
30+
ref: stable-5.2
2831
- name: Pull images
2932
run: |
30-
docker pull icewind1991/samba-krb-test-dc
31-
docker pull icewind1991/samba-krb-test-apache
32-
docker pull icewind1991/samba-krb-test-client
33+
docker pull ghcr.io/icewind1991/samba-krb-test-dc
34+
docker pull ghcr.io/icewind1991/samba-krb-test-apache
35+
docker pull ghcr.io/icewind1991/samba-krb-test-client
36+
docker tag ghcr.io/icewind1991/samba-krb-test-dc icewind1991/samba-krb-test-dc
37+
docker tag ghcr.io/icewind1991/samba-krb-test-apache icewind1991/samba-krb-test-apache
38+
docker tag ghcr.io/icewind1991/samba-krb-test-client icewind1991/samba-krb-test-client
3339
- name: Setup AD-DC
3440
run: |
35-
cp apps/files_external/tests/*.sh .
3641
mkdir data
3742
sudo chown -R 33 data apps config
38-
DC_IP=$(./start-dc.sh)
39-
./start-apache.sh $DC_IP $PWD
43+
DC_IP=$(apps/files_external/tests/start-dc.sh)
44+
sleep 1
45+
apps/files_external/tests/start-apache.sh $DC_IP $PWD
4046
echo "DC_IP=$DC_IP" >> $GITHUB_ENV
4147
- name: Set up Nextcloud
4248
run: |
@@ -61,14 +67,15 @@ jobs:
6167
chmod 0777 /tmp/shared/cookies
6268
6369
echo "SAML login"
64-
./client-cmd.sh ${{ env.DC_IP }} curl -c /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/index.php/apps/user_saml/saml/login
70+
apps/files_external/tests/client-cmd.sh ${{ env.DC_IP }} curl -c /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/index.php/apps/user_saml/saml/login
6571
echo "Check we are logged in"
66-
CONTENT=$(./client-cmd.sh ${{ env.DC_IP }} curl -b /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/remote.php/webdav/smb/test.txt)
72+
CONTENT=$(apps/files_external/tests/client-cmd.sh ${{ env.DC_IP }} curl -b /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/remote.php/webdav/smb/test.txt)
6773
CONTENT=$(echo $CONTENT | head -n 1 | tr -d '[:space:]')
6874
[[ $CONTENT == "testfile" ]]
6975
- name: Show logs
7076
if: failure()
7177
run: |
7278
docker exec --user 33 apache ./occ log:file
7379
FILEPATH=$(docker exec --user 33 apache ./occ log:file | grep "Log file:" | cut -d' ' -f3)
80+
echo "$FILEPATH:"
7481
docker exec --user 33 apache cat $FILEPATH

.github/workflows/static-code-analysis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
uses: shivammathur/setup-php@v2
2424
with:
2525
php-version: '8.0'
26-
extensions: apcu,ctype,curl,dom,fileinfo,ftp,gd,intl,json,ldap,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
26+
extensions: apcu,ctype,curl,dom,fileinfo,ftp,gd,imagick,intl,json,ldap,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
2727
coverage: none
2828
env:
2929
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -57,7 +57,7 @@ jobs:
5757
uses: shivammathur/setup-php@master
5858
with:
5959
php-version: '8.0'
60-
extensions: ctype,curl,dom,fileinfo,gd,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
60+
extensions: ctype,curl,dom,fileinfo,gd,imagick,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
6161
coverage: none
6262

6363
- name: Composer install
@@ -85,7 +85,7 @@ jobs:
8585
uses: shivammathur/setup-php@v2
8686
with:
8787
php-version: '8.0'
88-
extensions: ctype,curl,dom,fileinfo,gd,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
88+
extensions: ctype,curl,dom,fileinfo,gd,imagick,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
8989
coverage: none
9090
env:
9191
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

apps/dav/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@
235235
'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => $baseDir . '/../lib/Events/SubscriptionUpdatedEvent.php',
236236
'OCA\\DAV\\Exception\\ServerMaintenanceMode' => $baseDir . '/../lib/Exception/ServerMaintenanceMode.php',
237237
'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => $baseDir . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php',
238-
'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => $baseDir . '/../lib/Files/BrowserErrorPagePlugin.php',
238+
'OCA\\DAV\\Files\\ErrorPagePlugin' => $baseDir . '/../lib/Files/ErrorPagePlugin.php',
239239
'OCA\\DAV\\Files\\FileSearchBackend' => $baseDir . '/../lib/Files/FileSearchBackend.php',
240240
'OCA\\DAV\\Files\\FilesHome' => $baseDir . '/../lib/Files/FilesHome.php',
241241
'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
@@ -250,7 +250,7 @@ class ComposerStaticInitDAV
250250
'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/SubscriptionUpdatedEvent.php',
251251
'OCA\\DAV\\Exception\\ServerMaintenanceMode' => __DIR__ . '/..' . '/../lib/Exception/ServerMaintenanceMode.php',
252252
'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => __DIR__ . '/..' . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php',
253-
'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/BrowserErrorPagePlugin.php',
253+
'OCA\\DAV\\Files\\ErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/ErrorPagePlugin.php',
254254
'OCA\\DAV\\Files\\FileSearchBackend' => __DIR__ . '/..' . '/../lib/Files/FileSearchBackend.php',
255255
'OCA\\DAV\\Files\\FilesHome' => __DIR__ . '/..' . '/../lib/Files/FilesHome.php',
256256
'OCA\\DAV\\Files\\LazySearchBackend' => __DIR__ . '/..' . '/../lib/Files/LazySearchBackend.php',

apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php

Lines changed: 61 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,14 @@
3131
namespace OCA\DAV\CalDAV\WebcalCaching;
3232

3333
use Exception;
34-
use GuzzleHttp\HandlerStack;
35-
use GuzzleHttp\Middleware;
34+
use GuzzleHttp\RequestOptions;
3635
use OCA\DAV\CalDAV\CalDavBackend;
3736
use OCP\Http\Client\IClientService;
3837
use OCP\Http\Client\LocalServerException;
3938
use OCP\IConfig;
40-
use Psr\Http\Message\RequestInterface;
41-
use Psr\Http\Message\ResponseInterface;
4239
use Psr\Log\LoggerInterface;
4340
use Sabre\DAV\Exception\BadRequest;
4441
use Sabre\DAV\PropPatch;
45-
use Sabre\DAV\Xml\Property\Href;
4642
use Sabre\VObject\Component;
4743
use Sabre\VObject\DateTimeParser;
4844
use Sabre\VObject\InvalidDataException;
@@ -76,15 +72,15 @@ public function __construct(CalDavBackend $calDavBackend, IClientService $client
7672
$this->logger = $logger;
7773
}
7874

79-
public function refreshSubscription(string $principalUri, string $uri) {
75+
public function refreshSubscription(string $principalUri, string $uri): void {
8076
$subscription = $this->getSubscription($principalUri, $uri);
8177
$mutations = [];
8278
if (!$subscription) {
8379
return;
8480
}
8581

8682
$webcalData = $this->queryWebcalFeed($subscription, $mutations);
87-
if (!$webcalData) {
83+
if ($webcalData === null) {
8884
return;
8985
}
9086

@@ -127,7 +123,7 @@ public function refreshSubscription(string $principalUri, string $uri) {
127123
$calendarData = $vObject->serialize();
128124
try {
129125
$this->calDavBackend->createCalendarObject($subscription['id'], $objectUri, $calendarData, CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION);
130-
} catch (NoInstancesException | BadRequest $ex) {
126+
} catch (NoInstancesException|BadRequest $ex) {
131127
$this->logger->error('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $ex, 'subscriptionId' => $subscription['id'], 'source' => $subscription['source']]);
132128
}
133129
}
@@ -139,7 +135,7 @@ public function refreshSubscription(string $principalUri, string $uri) {
139135

140136
$this->updateSubscription($subscription, $mutations);
141137
} catch (ParseException $ex) {
142-
$this->logger->error("Subscription {subscriptionId} could not be refreshed due to a parsing error", ['exception' => $ex, 'subscriptionId' => $subscription['id']]);
138+
$this->logger->error('Subscription {subscriptionId} could not be refreshed due to a parsing error', ['exception' => $ex, 'subscriptionId' => $subscription['id']]);
143139
}
144140
}
145141

@@ -165,106 +161,81 @@ function ($sub) use ($uri) {
165161
* gets webcal feed from remote server
166162
*/
167163
private function queryWebcalFeed(array $subscription, array &$mutations): ?string {
168-
$client = $this->clientService->newClient();
169-
170-
$didBreak301Chain = false;
171-
$latestLocation = null;
172-
173-
$handlerStack = HandlerStack::create();
174-
$handlerStack->push(Middleware::mapRequest(function (RequestInterface $request) {
175-
return $request
176-
->withHeader('Accept', 'text/calendar, application/calendar+json, application/calendar+xml')
177-
->withHeader('User-Agent', 'Nextcloud Webcal Service');
178-
}));
179-
$handlerStack->push(Middleware::mapResponse(function (ResponseInterface $response) use (&$didBreak301Chain, &$latestLocation) {
180-
if (!$didBreak301Chain) {
181-
if ($response->getStatusCode() !== 301) {
182-
$didBreak301Chain = true;
183-
} else {
184-
$latestLocation = $response->getHeader('Location');
185-
}
186-
}
187-
return $response;
188-
}));
189-
190-
$allowLocalAccess = $this->config->getAppValue('dav', 'webcalAllowLocalAccess', 'no');
191164
$subscriptionId = $subscription['id'];
192165
$url = $this->cleanURL($subscription['source']);
193166
if ($url === null) {
194167
return null;
195168
}
196169

197-
try {
198-
$params = [
199-
'allow_redirects' => [
200-
'redirects' => 10
201-
],
202-
'handler' => $handlerStack,
203-
'nextcloud' => [
204-
'allow_local_address' => $allowLocalAccess === 'yes',
205-
]
206-
];
207-
208-
$user = parse_url($subscription['source'], PHP_URL_USER);
209-
$pass = parse_url($subscription['source'], PHP_URL_PASS);
210-
if ($user !== null && $pass !== null) {
211-
$params['auth'] = [$user, $pass];
212-
}
213-
214-
$response = $client->get($url, $params);
215-
$body = $response->getBody();
170+
$allowLocalAccess = $this->config->getAppValue('dav', 'webcalAllowLocalAccess', 'no');
216171

217-
if ($latestLocation) {
218-
$mutations['{http://calendarserver.org/ns/}source'] = new Href($latestLocation);
219-
}
172+
$params = [
173+
'nextcloud' => [
174+
'allow_local_address' => $allowLocalAccess === 'yes',
175+
],
176+
RequestOptions::HEADERS => [
177+
'User-Agent' => 'Nextcloud Webcal Service',
178+
'Accept' => 'text/calendar, application/calendar+json, application/calendar+xml',
179+
],
180+
];
181+
182+
$user = parse_url($subscription['source'], PHP_URL_USER);
183+
$pass = parse_url($subscription['source'], PHP_URL_PASS);
184+
if ($user !== null && $pass !== null) {
185+
$params[RequestOptions::AUTH] = [$user, $pass];
186+
}
220187

221-
$contentType = $response->getHeader('Content-Type');
222-
$contentType = explode(';', $contentType, 2)[0];
223-
switch ($contentType) {
224-
case 'application/calendar+json':
225-
try {
226-
$jCalendar = Reader::readJson($body, Reader::OPTION_FORGIVING);
227-
} catch (Exception $ex) {
228-
// In case of a parsing error return null
229-
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
230-
return null;
231-
}
232-
return $jCalendar->serialize();
233-
234-
case 'application/calendar+xml':
235-
try {
236-
$xCalendar = Reader::readXML($body);
237-
} catch (Exception $ex) {
238-
// In case of a parsing error return null
239-
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
240-
return null;
241-
}
242-
return $xCalendar->serialize();
243-
244-
case 'text/calendar':
245-
default:
246-
try {
247-
$vCalendar = Reader::read($body);
248-
} catch (Exception $ex) {
249-
// In case of a parsing error return null
250-
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
251-
return null;
252-
}
253-
return $vCalendar->serialize();
254-
}
188+
try {
189+
$client = $this->clientService->newClient();
190+
$response = $client->get($url, $params);
255191
} catch (LocalServerException $ex) {
256192
$this->logger->warning("Subscription $subscriptionId was not refreshed because it violates local access rules", [
257193
'exception' => $ex,
258194
]);
259-
260195
return null;
261196
} catch (Exception $ex) {
262197
$this->logger->warning("Subscription $subscriptionId could not be refreshed due to a network error", [
263198
'exception' => $ex,
264199
]);
265-
266200
return null;
267201
}
202+
203+
$body = $response->getBody();
204+
205+
$contentType = $response->getHeader('Content-Type');
206+
$contentType = explode(';', $contentType, 2)[0];
207+
switch ($contentType) {
208+
case 'application/calendar+json':
209+
try {
210+
$jCalendar = Reader::readJson($body, Reader::OPTION_FORGIVING);
211+
} catch (Exception $ex) {
212+
// In case of a parsing error return null
213+
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
214+
return null;
215+
}
216+
return $jCalendar->serialize();
217+
218+
case 'application/calendar+xml':
219+
try {
220+
$xCalendar = Reader::readXML($body);
221+
} catch (Exception $ex) {
222+
// In case of a parsing error return null
223+
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
224+
return null;
225+
}
226+
return $xCalendar->serialize();
227+
228+
case 'text/calendar':
229+
default:
230+
try {
231+
$vCalendar = Reader::read($body);
232+
} catch (Exception $ex) {
233+
// In case of a parsing error return null
234+
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
235+
return null;
236+
}
237+
return $vCalendar->serialize();
238+
}
268239
}
269240

270241
/**

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,27 @@ public function __construct($treeOrNode = null) {
4343
self::$exposeVersion = false;
4444
$this->enablePropfindDepthInfinity = true;
4545
}
46+
47+
// Copied from 3rdparty/sabre/dav/lib/DAV/Server.php
48+
// Should be them exact same without the exception output.
49+
public function start(): void {
50+
try {
51+
// If nginx (pre-1.2) is used as a proxy server, and SabreDAV as an
52+
// origin, we must make sure we send back HTTP/1.0 if this was
53+
// requested.
54+
// This is mainly because nginx doesn't support Chunked Transfer
55+
// Encoding, and this forces the webserver SabreDAV is running on,
56+
// to buffer entire responses to calculate Content-Length.
57+
$this->httpResponse->setHTTPVersion($this->httpRequest->getHTTPVersion());
58+
59+
// Setting the base url
60+
$this->httpRequest->setBaseUrl($this->getBaseUri());
61+
$this->invokeMethod($this->httpRequest, $this->httpResponse);
62+
} catch (\Throwable $e) {
63+
try {
64+
$this->emit('exception', [$e]);
65+
} catch (\Exception $ignore) {
66+
}
67+
}
68+
}
4669
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
use OCP\Files\Folder;
3535
use OCA\DAV\AppInfo\PluginManager;
3636
use OCA\DAV\DAV\ViewOnlyPlugin;
37-
use OCA\DAV\Files\BrowserErrorPagePlugin;
37+
use OCA\DAV\Files\ErrorPagePlugin;
3838
use OCP\Files\Mount\IMountManager;
3939
use OCP\IConfig;
4040
use OCP\IDBConnection;
@@ -120,9 +120,7 @@ public function createServer(string $baseUri,
120120
$server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin());
121121
}
122122

123-
if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
124-
$server->addPlugin(new BrowserErrorPagePlugin());
125-
}
123+
$server->addPlugin(new ErrorPagePlugin($this->request, $this->config));
126124

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

0 commit comments

Comments
 (0)