Browse Source

fix(nextcloud): Fix WebDAV path construction

Signed-off-by: jld3103 <jld3103yt@gmail.com>
pull/1096/head
jld3103 1 year ago
parent
commit
8796b8c58f
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 19
      packages/nextcloud/lib/src/webdav/client.dart
  2. 14
      packages/nextcloud/lib/src/webdav/file.dart
  3. 35
      packages/nextcloud/test/webdav_test.dart

19
packages/nextcloud/lib/src/webdav/client.dart

@ -10,7 +10,7 @@ import 'package:universal_io/io.dart';
import 'package:xml/xml.dart' as xml; import 'package:xml/xml.dart' as xml;
/// Base path used on the server /// Base path used on the server
const String webdavBasePath = '/remote.php/webdav'; final webdavBase = Uri(path: '/remote.php/webdav');
/// WebDavClient class /// WebDavClient class
class WebDavClient { class WebDavClient {
@ -65,20 +65,11 @@ class WebDavClient {
@visibleForTesting @visibleForTesting
// ignore: public_member_api_docs // ignore: public_member_api_docs
static Uri constructUri(final Uri baseURL, [final Uri? path]) { static Uri constructUri(final Uri baseURL, [final Uri? path]) {
assert( final segments = baseURL.pathSegments.toList()..addAll(webdavBase.pathSegments);
path == null || path.path == '/' || !path.path.startsWith('/'), if (path != null) {
"The path should not start a '/' unless indicating the root folder.", segments.addAll(path.pathSegments);
);
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);
} }
return baseURL.replace(pathSegments: segments.where((final s) => s.isNotEmpty));
return baseURL.replace(path: pathBuffer.toString());
} }
Future<WebDavMultistatus> _parseResponse(final HttpClientResponse response) async => Future<WebDavMultistatus> _parseResponse(final HttpClientResponse response) async =>

14
packages/nextcloud/lib/src/webdav/file.dart

@ -25,8 +25,8 @@ class WebDavFile {
_response.propstats.singleWhere((final propstat) => propstat.status.contains('200')).prop; _response.propstats.singleWhere((final propstat) => propstat.status.contains('200')).prop;
/// The path of file /// The path of file
late final String path = late final Uri path =
Uri.decodeFull(_response.href!.substring(Uri.encodeFull(webdavBasePath).length, _response.href!.length)); Uri(pathSegments: Uri(path: _response.href).pathSegments.sublist(webdavBase.pathSegments.length));
/// The fileid namespaced by the instance id, globally unique /// The fileid namespaced by the instance id, globally unique
late final String? id = props.ocid; late final String? id = props.ocid;
@ -79,17 +79,11 @@ class WebDavFile {
late final bool? hasPreview = props.nchaspreview; late final bool? hasPreview = props.nchaspreview;
/// Returns the decoded name of the file / folder without the whole path /// Returns the decoded name of the file / folder without the whole path
late final String name = () { late final String name = path.pathSegments.where((final s) => s.isNotEmpty).lastOrNull ?? '';
// 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 ?? '';
}();
/// Whether the file is hidden. /// Whether the file is hidden.
late final bool isHidden = name.startsWith('.'); late final bool isHidden = name.startsWith('.');
/// Whether the file is a directory /// 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
packages/nextcloud/test/webdav_test.dart

@ -9,18 +9,25 @@ import 'package:universal_io/io.dart';
import 'helper.dart'; import 'helper.dart';
void main() { void main() {
test('constructUri', () { group('constructUri', () {
var baseURL = Uri.parse('http://cloud.example.com'); for (final values in [
expect(WebDavClient.constructUri(baseURL).toString(), '$baseURL$webdavBasePath'); ('http://cloud.example.com', 'http://cloud.example.com'),
expect(WebDavClient.constructUri(baseURL, Uri(path: '/')).toString(), '$baseURL$webdavBasePath'); ('http://cloud.example.com/', 'http://cloud.example.com'),
expect(WebDavClient.constructUri(baseURL, Uri(path: 'test')).toString(), '$baseURL$webdavBasePath/test'); ('http://cloud.example.com/subdir', 'http://cloud.example.com/subdir'),
('http://cloud.example.com/subdir/', 'http://cloud.example.com/subdir'),
baseURL = Uri.parse('http://cloud.example.com/subdir'); ]) {
expect(WebDavClient.constructUri(baseURL, Uri(path: 'test')).toString(), '$baseURL$webdavBasePath/test'); final baseURL = Uri.parse(values.$1);
final sanitizedBaseURL = Uri.parse(values.$2);
expect(() => WebDavClient.constructUri(baseURL, Uri(path: '/test')), throwsA(isA<AssertionError>()));
baseURL = Uri.parse('http://cloud.example.com/'); test('$baseURL', () {
expect(() => WebDavClient.constructUri(baseURL), throwsA(isA<AssertionError>())); 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( group(
@ -100,7 +107,7 @@ void main() {
.toWebDavFiles() .toWebDavFiles()
.single; .single;
expect(response.path, '/Nextcloud.png'); expect(response.path, Uri(path: 'Nextcloud.png'));
expect(response.id, isNotEmpty); expect(response.id, isNotEmpty);
expect(response.fileId, isNotEmpty); expect(response.fileId, isNotEmpty);
expect(response.isCollection, isFalse); expect(response.isCollection, isFalse);
@ -165,7 +172,7 @@ void main() {
.toWebDavFiles() .toWebDavFiles()
.single; .single;
expect(response.path, '/test/'); expect(response.path, Uri(path: 'test/'));
expect(response.isCollection, isTrue); expect(response.isCollection, isTrue);
expect(response.mimeType, isNull); expect(response.mimeType, isNull);
expect(response.size, data.lengthInBytes); expect(response.size, data.lengthInBytes);

Loading…
Cancel
Save