mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-03-25 00:14:42 +01:00
Refactor: make webdav parser more generic
This commit is contained in:
parent
313d5f3dcb
commit
4c88070a7e
3 changed files with 177 additions and 164 deletions
|
@ -62,7 +62,7 @@ class FileWebdavDataSource implements FileDataSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
final xml = XmlDocument.parse(response.body);
|
final xml = XmlDocument.parse(response.body);
|
||||||
var files = WebdavFileParser()(xml);
|
var files = WebdavResponseParser().parseFiles(xml);
|
||||||
// _log.fine("[list] Parsed files: [$files]");
|
// _log.fine("[list] Parsed files: [$files]");
|
||||||
files = files.where((element) => _validateFile(element)).map((e) {
|
files = files.where((element) => _validateFile(element)).map((e) {
|
||||||
if (e.metadata == null || e.metadata!.fileEtag == e.etag) {
|
if (e.metadata == null || e.metadata!.fileEtag == e.etag) {
|
||||||
|
|
|
@ -7,8 +7,12 @@ import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/string_extension.dart';
|
import 'package:nc_photos/string_extension.dart';
|
||||||
import 'package:xml/xml.dart';
|
import 'package:xml/xml.dart';
|
||||||
|
|
||||||
class WebdavFileParser {
|
class WebdavResponseParser {
|
||||||
List<File> call(XmlDocument xml) {
|
List<File> parseFiles(XmlDocument xml) => _parse<File>(xml, _toFile);
|
||||||
|
|
||||||
|
Map<String, String> get namespaces => _namespaces;
|
||||||
|
|
||||||
|
List<T> _parse<T>(XmlDocument xml, T Function(XmlElement) mapper) {
|
||||||
_namespaces = _parseNamespaces(xml);
|
_namespaces = _parseNamespaces(xml);
|
||||||
final body = () {
|
final body = () {
|
||||||
try {
|
try {
|
||||||
|
@ -16,28 +20,26 @@ class WebdavFileParser {
|
||||||
element.matchQualifiedName("multistatus",
|
element.matchQualifiedName("multistatus",
|
||||||
prefix: "DAV:", namespaces: _namespaces));
|
prefix: "DAV:", namespaces: _namespaces));
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
_log.shout("[call] Missing element: multistatus");
|
_log.shout("[_parse] Missing element: multistatus");
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
return body.children
|
return body.children
|
||||||
.whereType<XmlElement>()
|
.whereType<XmlElement>()
|
||||||
.where((element) => element.matchQualifiedName("response",
|
.where((e) => e.matchQualifiedName("response",
|
||||||
prefix: "DAV:", namespaces: _namespaces))
|
prefix: "DAV:", namespaces: _namespaces))
|
||||||
.map((element) {
|
.map((e) {
|
||||||
try {
|
try {
|
||||||
return _toFile(element);
|
return mapper(e);
|
||||||
} catch (e, stacktrace) {
|
} catch (e, stackTrace) {
|
||||||
_log.shout("[call] Failed parsing XML", e, stacktrace);
|
_log.shout("[_parse] Failed parsing XML", e, stackTrace);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.whereType<File>()
|
.whereType<T>()
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> get namespaces => _namespaces;
|
|
||||||
|
|
||||||
Map<String, String> _parseNamespaces(XmlDocument xml) {
|
Map<String, String> _parseNamespaces(XmlDocument xml) {
|
||||||
final namespaces = <String, String>{};
|
final namespaces = <String, String>{};
|
||||||
final xmlContent = xml.descendants.whereType<XmlElement>().firstWhere(
|
final xmlContent = xml.descendants.whereType<XmlElement>().firstWhere(
|
||||||
|
@ -91,7 +93,7 @@ class WebdavFileParser {
|
||||||
(element) => element.matchQualifiedName("prop",
|
(element) => element.matchQualifiedName("prop",
|
||||||
prefix: "DAV:", namespaces: _namespaces));
|
prefix: "DAV:", namespaces: _namespaces));
|
||||||
final propParser =
|
final propParser =
|
||||||
_PropParser(namespaces: _namespaces, logFilePath: path);
|
_FilePropParser(namespaces: _namespaces, logFilePath: path);
|
||||||
propParser.parse(prop);
|
propParser.parse(prop);
|
||||||
contentLength = propParser.contentLength;
|
contentLength = propParser.contentLength;
|
||||||
contentType = propParser.contentType;
|
contentType = propParser.contentType;
|
||||||
|
@ -149,8 +151,8 @@ class WebdavFileParser {
|
||||||
Logger("entity.webdav_response_parser.WebdavResponseParser");
|
Logger("entity.webdav_response_parser.WebdavResponseParser");
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PropParser {
|
class _FilePropParser {
|
||||||
_PropParser({
|
_FilePropParser({
|
||||||
this.namespaces = const {},
|
this.namespaces = const {},
|
||||||
this.logFilePath,
|
this.logFilePath,
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,8 +5,21 @@ import 'package:xml/xml.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group("WebdavFileParser", () {
|
group("WebdavFileParser", () {
|
||||||
test("file", () {
|
group("parseFiles", () {
|
||||||
final xml = XmlDocument.parse("""
|
test("file", _files);
|
||||||
|
test("file w/ 404 properties", _files404props);
|
||||||
|
test("file w/ metadata", _filesMetadata);
|
||||||
|
test("file w/ is-archived", _filesIsArchived);
|
||||||
|
test("file w/ override-date-time", _filesOverrideDateTime);
|
||||||
|
test("multiple files", _filesMultiple);
|
||||||
|
test("directory", _filesDir);
|
||||||
|
test("nextcloud hosted in subdir", _filesServerHostedInSubdir);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _files() {
|
||||||
|
final xml = XmlDocument.parse("""
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<d:multistatus xmlns:d="DAV:"
|
<d:multistatus xmlns:d="DAV:"
|
||||||
xmlns:s="http://sabredav.org/ns"
|
xmlns:s="http://sabredav.org/ns"
|
||||||
|
@ -29,23 +42,23 @@ void main() {
|
||||||
</d:response>
|
</d:response>
|
||||||
</d:multistatus>
|
</d:multistatus>
|
||||||
""");
|
""");
|
||||||
final results = WebdavFileParser()(xml);
|
final results = WebdavResponseParser().parseFiles(xml);
|
||||||
expect(results, [
|
expect(results, [
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Nextcloud intro.mp4",
|
path: "remote.php/dav/files/admin/Nextcloud intro.mp4",
|
||||||
contentLength: 3963036,
|
contentLength: 3963036,
|
||||||
contentType: "video/mp4",
|
contentType: "video/mp4",
|
||||||
etag: "1324f58d4d5c8d81bed6e4ed9d5ea862",
|
etag: "1324f58d4d5c8d81bed6e4ed9d5ea862",
|
||||||
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
||||||
hasPreview: false,
|
hasPreview: false,
|
||||||
fileId: 123,
|
fileId: 123,
|
||||||
isCollection: false,
|
isCollection: false,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
});
|
}
|
||||||
|
|
||||||
test("file w/ 404 properties", () {
|
void _files404props() {
|
||||||
final xml = XmlDocument.parse("""
|
final xml = XmlDocument.parse("""
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<d:multistatus xmlns:d="DAV:"
|
<d:multistatus xmlns:d="DAV:"
|
||||||
xmlns:s="http://sabredav.org/ns"
|
xmlns:s="http://sabredav.org/ns"
|
||||||
|
@ -75,23 +88,23 @@ void main() {
|
||||||
</d:response>
|
</d:response>
|
||||||
</d:multistatus>
|
</d:multistatus>
|
||||||
""");
|
""");
|
||||||
final results = WebdavFileParser()(xml);
|
final results = WebdavResponseParser().parseFiles(xml);
|
||||||
expect(results, [
|
expect(results, [
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Nextcloud intro.mp4",
|
path: "remote.php/dav/files/admin/Nextcloud intro.mp4",
|
||||||
contentLength: 3963036,
|
contentLength: 3963036,
|
||||||
contentType: "video/mp4",
|
contentType: "video/mp4",
|
||||||
etag: "1324f58d4d5c8d81bed6e4ed9d5ea862",
|
etag: "1324f58d4d5c8d81bed6e4ed9d5ea862",
|
||||||
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
||||||
hasPreview: false,
|
hasPreview: false,
|
||||||
fileId: 123,
|
fileId: 123,
|
||||||
isCollection: false,
|
isCollection: false,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
});
|
}
|
||||||
|
|
||||||
test("file w/ metadata", () {
|
void _filesMetadata() {
|
||||||
final xml = XmlDocument.parse("""
|
final xml = XmlDocument.parse("""
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<d:multistatus xmlns:d="DAV:"
|
<d:multistatus xmlns:d="DAV:"
|
||||||
xmlns:s="http://sabredav.org/ns"
|
xmlns:s="http://sabredav.org/ns"
|
||||||
|
@ -115,29 +128,29 @@ void main() {
|
||||||
</d:response>
|
</d:response>
|
||||||
</d:multistatus>
|
</d:multistatus>
|
||||||
""");
|
""");
|
||||||
final results = WebdavFileParser()(xml);
|
final results = WebdavResponseParser().parseFiles(xml);
|
||||||
expect(results, [
|
expect(results, [
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Photos/Nextcloud community.jpg",
|
path: "remote.php/dav/files/admin/Photos/Nextcloud community.jpg",
|
||||||
contentLength: 797325,
|
contentLength: 797325,
|
||||||
contentType: "image/jpeg",
|
contentType: "image/jpeg",
|
||||||
etag: "8950e39a034e369237d9285e2d815a50",
|
etag: "8950e39a034e369237d9285e2d815a50",
|
||||||
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
||||||
hasPreview: true,
|
hasPreview: true,
|
||||||
fileId: 123,
|
fileId: 123,
|
||||||
isCollection: false,
|
isCollection: false,
|
||||||
metadata: Metadata(
|
metadata: Metadata(
|
||||||
lastUpdated: DateTime.utc(2021, 1, 2, 3, 4, 5, 678),
|
lastUpdated: DateTime.utc(2021, 1, 2, 3, 4, 5, 678),
|
||||||
fileEtag: "8950e39a034e369237d9285e2d815a50",
|
fileEtag: "8950e39a034e369237d9285e2d815a50",
|
||||||
imageWidth: 3000,
|
imageWidth: 3000,
|
||||||
imageHeight: 2000,
|
imageHeight: 2000,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
});
|
}
|
||||||
|
|
||||||
test("file w/ is-archived", () {
|
void _filesIsArchived() {
|
||||||
final xml = XmlDocument.parse("""
|
final xml = XmlDocument.parse("""
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<d:multistatus xmlns:d="DAV:"
|
<d:multistatus xmlns:d="DAV:"
|
||||||
xmlns:s="http://sabredav.org/ns"
|
xmlns:s="http://sabredav.org/ns"
|
||||||
|
@ -160,23 +173,23 @@ void main() {
|
||||||
</d:response>
|
</d:response>
|
||||||
</d:multistatus>
|
</d:multistatus>
|
||||||
""");
|
""");
|
||||||
final results = WebdavFileParser()(xml);
|
final results = WebdavResponseParser().parseFiles(xml);
|
||||||
expect(results, [
|
expect(results, [
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Photos/Nextcloud community.jpg",
|
path: "remote.php/dav/files/admin/Photos/Nextcloud community.jpg",
|
||||||
contentLength: 797325,
|
contentLength: 797325,
|
||||||
contentType: "image/jpeg",
|
contentType: "image/jpeg",
|
||||||
etag: "8950e39a034e369237d9285e2d815a50",
|
etag: "8950e39a034e369237d9285e2d815a50",
|
||||||
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
||||||
hasPreview: true,
|
hasPreview: true,
|
||||||
isCollection: false,
|
isCollection: false,
|
||||||
isArchived: true,
|
isArchived: true,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
});
|
}
|
||||||
|
|
||||||
test("file w/ override-date-time", () {
|
void _filesOverrideDateTime() {
|
||||||
final xml = XmlDocument.parse("""
|
final xml = XmlDocument.parse("""
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<d:multistatus xmlns:d="DAV:"
|
<d:multistatus xmlns:d="DAV:"
|
||||||
xmlns:s="http://sabredav.org/ns"
|
xmlns:s="http://sabredav.org/ns"
|
||||||
|
@ -199,23 +212,23 @@ void main() {
|
||||||
</d:response>
|
</d:response>
|
||||||
</d:multistatus>
|
</d:multistatus>
|
||||||
""");
|
""");
|
||||||
final results = WebdavFileParser()(xml);
|
final results = WebdavResponseParser().parseFiles(xml);
|
||||||
expect(results, [
|
expect(results, [
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Photos/Nextcloud community.jpg",
|
path: "remote.php/dav/files/admin/Photos/Nextcloud community.jpg",
|
||||||
contentLength: 797325,
|
contentLength: 797325,
|
||||||
contentType: "image/jpeg",
|
contentType: "image/jpeg",
|
||||||
etag: "8950e39a034e369237d9285e2d815a50",
|
etag: "8950e39a034e369237d9285e2d815a50",
|
||||||
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
||||||
hasPreview: true,
|
hasPreview: true,
|
||||||
isCollection: false,
|
isCollection: false,
|
||||||
overrideDateTime: DateTime.utc(2021, 1, 2, 3, 4, 5),
|
overrideDateTime: DateTime.utc(2021, 1, 2, 3, 4, 5),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
});
|
}
|
||||||
|
|
||||||
test("multiple files", () {
|
void _filesMultiple() {
|
||||||
final xml = XmlDocument.parse("""
|
final xml = XmlDocument.parse("""
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<d:multistatus xmlns:d="DAV:"
|
<d:multistatus xmlns:d="DAV:"
|
||||||
xmlns:s="http://sabredav.org/ns"
|
xmlns:s="http://sabredav.org/ns"
|
||||||
|
@ -254,39 +267,39 @@ void main() {
|
||||||
</d:response>
|
</d:response>
|
||||||
</d:multistatus>
|
</d:multistatus>
|
||||||
""");
|
""");
|
||||||
final results = WebdavFileParser()(xml);
|
final results = WebdavResponseParser().parseFiles(xml);
|
||||||
expect(results, [
|
expect(results, [
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Nextcloud intro.mp4",
|
path: "remote.php/dav/files/admin/Nextcloud intro.mp4",
|
||||||
contentLength: 3963036,
|
contentLength: 3963036,
|
||||||
contentType: "video/mp4",
|
contentType: "video/mp4",
|
||||||
etag: "1324f58d4d5c8d81bed6e4ed9d5ea862",
|
etag: "1324f58d4d5c8d81bed6e4ed9d5ea862",
|
||||||
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
||||||
hasPreview: false,
|
hasPreview: false,
|
||||||
fileId: 123,
|
fileId: 123,
|
||||||
isCollection: false,
|
isCollection: false,
|
||||||
),
|
),
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Nextcloud.png",
|
path: "remote.php/dav/files/admin/Nextcloud.png",
|
||||||
contentLength: 50598,
|
contentLength: 50598,
|
||||||
contentType: "image/png",
|
contentType: "image/png",
|
||||||
etag: "48689d5b17c449d9db492ffe8f7ab8a6",
|
etag: "48689d5b17c449d9db492ffe8f7ab8a6",
|
||||||
lastModified: DateTime.utc(2021, 1, 2, 3, 4, 5),
|
lastModified: DateTime.utc(2021, 1, 2, 3, 4, 5),
|
||||||
hasPreview: true,
|
hasPreview: true,
|
||||||
fileId: 124,
|
fileId: 124,
|
||||||
isCollection: false,
|
isCollection: false,
|
||||||
metadata: Metadata(
|
metadata: Metadata(
|
||||||
fileEtag: "48689d5b17c449d9db492ffe8f7ab8a6",
|
fileEtag: "48689d5b17c449d9db492ffe8f7ab8a6",
|
||||||
imageWidth: 500,
|
imageWidth: 500,
|
||||||
imageHeight: 500,
|
imageHeight: 500,
|
||||||
lastUpdated: DateTime.utc(2021, 1, 2, 3, 4, 5, 678),
|
lastUpdated: DateTime.utc(2021, 1, 2, 3, 4, 5, 678),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
});
|
}
|
||||||
|
|
||||||
test("directory", () {
|
void _filesDir() {
|
||||||
final xml = XmlDocument.parse("""
|
final xml = XmlDocument.parse("""
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<d:multistatus xmlns:d="DAV:"
|
<d:multistatus xmlns:d="DAV:"
|
||||||
xmlns:s="http://sabredav.org/ns"
|
xmlns:s="http://sabredav.org/ns"
|
||||||
|
@ -317,21 +330,21 @@ void main() {
|
||||||
</d:response>
|
</d:response>
|
||||||
</d:multistatus>
|
</d:multistatus>
|
||||||
""");
|
""");
|
||||||
final results = WebdavFileParser()(xml);
|
final results = WebdavResponseParser().parseFiles(xml);
|
||||||
expect(results, [
|
expect(results, [
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Photos",
|
path: "remote.php/dav/files/admin/Photos",
|
||||||
etag: "123456789abcd",
|
etag: "123456789abcd",
|
||||||
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
||||||
isCollection: true,
|
isCollection: true,
|
||||||
hasPreview: false,
|
hasPreview: false,
|
||||||
fileId: 123,
|
fileId: 123,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
});
|
}
|
||||||
|
|
||||||
test("nextcloud hosed in subdir", () {
|
void _filesServerHostedInSubdir() {
|
||||||
final xml = XmlDocument.parse("""
|
final xml = XmlDocument.parse("""
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<d:multistatus xmlns:d="DAV:"
|
<d:multistatus xmlns:d="DAV:"
|
||||||
xmlns:s="http://sabredav.org/ns"
|
xmlns:s="http://sabredav.org/ns"
|
||||||
|
@ -354,19 +367,17 @@ void main() {
|
||||||
</d:response>
|
</d:response>
|
||||||
</d:multistatus>
|
</d:multistatus>
|
||||||
""");
|
""");
|
||||||
final results = WebdavFileParser()(xml);
|
final results = WebdavResponseParser().parseFiles(xml);
|
||||||
expect(results, [
|
expect(results, [
|
||||||
File(
|
File(
|
||||||
path: "remote.php/dav/files/admin/Nextcloud intro.mp4",
|
path: "remote.php/dav/files/admin/Nextcloud intro.mp4",
|
||||||
contentLength: 3963036,
|
contentLength: 3963036,
|
||||||
contentType: "video/mp4",
|
contentType: "video/mp4",
|
||||||
etag: "1324f58d4d5c8d81bed6e4ed9d5ea862",
|
etag: "1324f58d4d5c8d81bed6e4ed9d5ea862",
|
||||||
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
lastModified: DateTime.utc(2021, 1, 1, 2, 3, 4),
|
||||||
hasPreview: false,
|
hasPreview: false,
|
||||||
fileId: 123,
|
fileId: 123,
|
||||||
isCollection: false,
|
isCollection: false,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue