Skip to content

Commit

Permalink
Merge pull request #1096 from nextcloud/fix/nextcloud/webdav-path-con…
Browse files Browse the repository at this point in the history
…struction
  • Loading branch information
provokateurin authored Nov 4, 2023
2 parents 4643f1f + 8796b8c commit 00e58b5
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 38 deletions.
19 changes: 5 additions & 14 deletions packages/nextcloud/lib/src/webdav/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:universal_io/io.dart';
import 'package:xml/xml.dart' as xml;

/// Base path used on the server
const String webdavBasePath = '/remote.php/webdav';
final webdavBase = Uri(path: '/remote.php/webdav');

/// WebDavClient class
class WebDavClient {
Expand Down Expand Up @@ -65,20 +65,11 @@ class WebDavClient {
@visibleForTesting
// ignore: public_member_api_docs
static Uri constructUri(final Uri baseURL, [final Uri? path]) {
assert(
path == null || path.path == '/' || !path.path.startsWith('/'),
"The path should not start a '/' unless indicating the root folder.",
);
assert(!baseURL.path.endsWith('/'), "The baseURL should not end with a '/'.");

final pathBuffer = StringBuffer(baseURL.path)..write(webdavBasePath);
if (path != null && path.path != '/') {
pathBuffer
..write('/')
..write(path.path);
final segments = baseURL.pathSegments.toList()..addAll(webdavBase.pathSegments);
if (path != null) {
segments.addAll(path.pathSegments);
}

return baseURL.replace(path: pathBuffer.toString());
return baseURL.replace(pathSegments: segments.where((final s) => s.isNotEmpty));
}

Future<WebDavMultistatus> _parseResponse(final HttpClientResponse response) async =>
Expand Down
14 changes: 4 additions & 10 deletions packages/nextcloud/lib/src/webdav/file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class WebDavFile {
_response.propstats.singleWhere((final propstat) => propstat.status.contains('200')).prop;

/// The path of file
late final String path =
Uri.decodeFull(_response.href!.substring(Uri.encodeFull(webdavBasePath).length, _response.href!.length));
late final Uri path =
Uri(pathSegments: Uri(path: _response.href).pathSegments.sublist(webdavBase.pathSegments.length));

/// The fileid namespaced by the instance id, globally unique
late final String? id = props.ocid;
Expand Down Expand Up @@ -79,17 +79,11 @@ class WebDavFile {
late final bool? hasPreview = props.nchaspreview;

/// Returns the decoded name of the file / folder without the whole path
late final String name = () {
// normalized path (remove trailing slash)
final end = path.endsWith('/') ? path.length - 1 : path.length;
final segments = Uri.parse(path, 0, end).pathSegments;

return segments.lastOrNull ?? '';
}();
late final String name = path.pathSegments.where((final s) => s.isNotEmpty).lastOrNull ?? '';

/// Whether the file is hidden.
late final bool isHidden = name.startsWith('.');

/// Whether the file is a directory
late final bool isDirectory = (isCollection ?? false) || path.endsWith('/');
late final bool isDirectory = (isCollection ?? false) || path.pathSegments.last.isEmpty;
}
35 changes: 21 additions & 14 deletions packages/nextcloud/test/webdav_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,25 @@ import 'package:universal_io/io.dart';
import 'helper.dart';

void main() {
test('constructUri', () {
var baseURL = Uri.parse('http://cloud.example.com');
expect(WebDavClient.constructUri(baseURL).toString(), '$baseURL$webdavBasePath');
expect(WebDavClient.constructUri(baseURL, Uri(path: '/')).toString(), '$baseURL$webdavBasePath');
expect(WebDavClient.constructUri(baseURL, Uri(path: 'test')).toString(), '$baseURL$webdavBasePath/test');

baseURL = Uri.parse('http://cloud.example.com/subdir');
expect(WebDavClient.constructUri(baseURL, Uri(path: 'test')).toString(), '$baseURL$webdavBasePath/test');

expect(() => WebDavClient.constructUri(baseURL, Uri(path: '/test')), throwsA(isA<AssertionError>()));
baseURL = Uri.parse('http://cloud.example.com/');
expect(() => WebDavClient.constructUri(baseURL), throwsA(isA<AssertionError>()));
group('constructUri', () {
for (final values in [
('http://cloud.example.com', 'http://cloud.example.com'),
('http://cloud.example.com/', 'http://cloud.example.com'),
('http://cloud.example.com/subdir', 'http://cloud.example.com/subdir'),
('http://cloud.example.com/subdir/', 'http://cloud.example.com/subdir'),
]) {
final baseURL = Uri.parse(values.$1);
final sanitizedBaseURL = Uri.parse(values.$2);

test('$baseURL', () {
expect(WebDavClient.constructUri(baseURL).toString(), '$sanitizedBaseURL$webdavBase');
expect(WebDavClient.constructUri(baseURL, Uri(path: '/')).toString(), '$sanitizedBaseURL$webdavBase');
expect(WebDavClient.constructUri(baseURL, Uri(path: 'test')).toString(), '$sanitizedBaseURL$webdavBase/test');
expect(WebDavClient.constructUri(baseURL, Uri(path: 'test/')).toString(), '$sanitizedBaseURL$webdavBase/test');
expect(WebDavClient.constructUri(baseURL, Uri(path: '/test')).toString(), '$sanitizedBaseURL$webdavBase/test');
expect(WebDavClient.constructUri(baseURL, Uri(path: '/test/')).toString(), '$sanitizedBaseURL$webdavBase/test');
});
}
});

group(
Expand Down Expand Up @@ -100,7 +107,7 @@ void main() {
.toWebDavFiles()
.single;

expect(response.path, '/Nextcloud.png');
expect(response.path, Uri(path: 'Nextcloud.png'));
expect(response.id, isNotEmpty);
expect(response.fileId, isNotEmpty);
expect(response.isCollection, isFalse);
Expand Down Expand Up @@ -165,7 +172,7 @@ void main() {
.toWebDavFiles()
.single;

expect(response.path, '/test/');
expect(response.path, Uri(path: 'test/'));
expect(response.isCollection, isTrue);
expect(response.mimeType, isNull);
expect(response.size, data.lengthInBytes);
Expand Down

0 comments on commit 00e58b5

Please sign in to comment.