Skip to content

Commit

Permalink
Fix remote connection requests
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeDoctorDE committed Dec 1, 2023
1 parent 8cd97c4 commit c04f8a1
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 30 deletions.
59 changes: 40 additions & 19 deletions app/lib/api/file_system/file_system_dav.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,24 @@ class DavRemoteDocumentFileSystem extends DocumentRemoteSystem {
var response = await createRequest(path.split('/'), method: 'PROPFIND');
final fileName = remote.buildDocumentsUri(path: path.split('/'))?.path;
final rootDirectory = remote.buildDocumentsUri();
if (response == null) {
yield null;
return;
}
var content = await getBodyString(response);
if (response.statusCode == 404 && path.isEmpty) {
await createRequest([], method: 'MKCOL');
response = await createRequest(path.split('/'), method: 'PROPFIND');
}
if (response?.statusCode != 207 ||
fileName == null ||
rootDirectory == null) {
yield null;
return;
}
var content = await getBodyString(response!);
final xml = XmlDocument.parse(content);
final currentElement = xml.findAllElements('d:response').where((element) {
final current = element.getElement('d:href')?.value;
final current = element.getElement('d:href')?.innerText;
return current == fileName || current == '$fileName/';
}).first;
final resourceType = currentElement
Expand All @@ -92,10 +100,10 @@ class DavRemoteDocumentFileSystem extends DocumentRemoteSystem {
final assets = await Future.wait(xml
.findAllElements('d:response')
.where((element) =>
element.getElement('d:href')?.value?.startsWith(fileName) ??
element.getElement('d:href')?.innerText.startsWith(fileName) ??
false)
.where((element) {
final current = element.getElement('d:href')?.value;
final current = element.getElement('d:href')?.innerText;
return current != fileName && current != '$fileName/';
}).map((e) async {
final currentResourceType = e
Expand All @@ -106,11 +114,10 @@ class DavRemoteDocumentFileSystem extends DocumentRemoteSystem {
.findElements('d:resourcetype')
.first;
var path = e
.findElements('d:href')
.first
.value
?.substring(rootDirectory.path.length) ??
'';
.findElements('d:href')
.first
.innerText
.substring(rootDirectory.path.length);
if (path.endsWith('/')) {
path = path.substring(0, path.length - 1);
}
Expand All @@ -122,19 +129,29 @@ class DavRemoteDocumentFileSystem extends DocumentRemoteSystem {
return AppDocumentEntity.directory(
AssetLocation(remote: remote.identifier, path: path), const []);
} else {
final dataResponse =
await createRequest(path.split('/'), method: 'GET');
var fileContent = dataResponse == null
? const <int>[]
: await getBodyBytes(dataResponse);
return getAppDocumentFile(
AssetLocation(remote: remote.identifier, path: path), const []);
AssetLocation(remote: remote.identifier, path: path),
fileContent);
}
}).toList());
yield AppDocumentEntity.directory(
AssetLocation(remote: remote.identifier, path: path), assets);
return;
}
response = await createRequest(path.split('/'), method: 'GET');
if (response?.statusCode != 200) {
throw Exception('Failed to get asset: ${response?.statusCode}');
if (response == null) {
yield null;
return;
}
var fileContent = await getBodyBytes(response);
if (response.statusCode != 200) {
throw Exception('Failed to get asset: ${response.statusCode}');
}
var fileContent = await getBodyBytes(response!);
yield await getAppDocumentFile(
AssetLocation(remote: remote.identifier, path: path), fileContent);
}
Expand All @@ -156,7 +173,7 @@ class DavRemoteDocumentFileSystem extends DocumentRemoteSystem {
.firstOrNull
?.findElements('d:getlastmodified')
.firstOrNull
?.value;
?.innerText;
if (lastModified == null) {
return null;
}
Expand All @@ -177,8 +194,12 @@ class DavRemoteDocumentFileSystem extends DocumentRemoteSystem {
if (!forceSync && remote.hasDocumentCached(path)) {
cacheContent(path, data);
}
var last = path.lastIndexOf('/');
if (last == -1) {
last = path.length;
}
// Create directory if not exists
final directoryPath = path.substring(0, path.lastIndexOf('/'));
final directoryPath = path.substring(0, last);
if (!await hasAsset(directoryPath)) {
await createDirectory(directoryPath);
}
Expand Down Expand Up @@ -289,9 +310,9 @@ class DavRemoteTemplateFileSystem extends TemplateRemoteSystem {
clearCachedContent();
return (await Future.wait(xml
.findAllElements('d:href')
.where((element) => element.value?.endsWith('.bfly') ?? false)
.where((element) => element.innerText.endsWith('.bfly'))
.map((e) {
var path = e.value!.substring(rootDirectory.path.length);
var path = e.innerText.substring(rootDirectory.path.length);
path = Uri.decodeComponent(path);
return getTemplate(path);
})))
Expand Down Expand Up @@ -382,9 +403,9 @@ class DavRemotePackFileSystem extends PackRemoteSystem {
clearCachedContent();
return (await Future.wait(xml
.findAllElements('d:href')
.where((element) => element.value?.endsWith('.bfly') ?? false)
.where((element) => element.innerText.endsWith('.bfly'))
.map((e) {
var path = e.value!.substring(rootDirectory.path.length);
var path = e.innerText.substring(rootDirectory.path.length);
path = Uri.decodeComponent(path);
return getPack(path);
})))
Expand Down
26 changes: 16 additions & 10 deletions app/lib/api/file_system/file_system_remote.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,25 @@ mixin RemoteSystem {
String.fromCharCodes(cert.sha1) == remote.certificateSha1;
if (url == null) return null;
final request = await client.openUrl(method, url);
request.headers.add('Authorization',
'Basic ${base64Encode(utf8.encode('${remote.username}:${await remote.getRemotePassword()}'))}');
if (body != null) {
request.write(body);
final bytes = utf8.encode(body);
request.headers.add('Content-Length', bytes.length.toString());
request.add(bytes);
} else if (bodyBytes != null) {
request.headers.add('Content-Length', bodyBytes.length.toString());
request.add(bodyBytes);
}
request.headers.add('Authorization',
'Basic ${base64Encode(utf8.encode('${remote.username}:${await remote.getRemotePassword()}'))}');
return request.close();
}

Future<Uint8List> getBodyBytes(HttpClientResponse response) async {
final buffer = BytesBuilder();
await for (var data in response) {
buffer.add(data);
}
return buffer.toBytes();
return response.fold<Uint8List>(
Uint8List(0),
(Uint8List accumulator, List<int> chunk) =>
Uint8List.fromList(accumulator + chunk),
);
}

Future<String> getBodyString(HttpClientResponse response) async {
Expand All @@ -94,8 +97,11 @@ mixin RemoteSystem {

Future<String> getRemoteCacheDirectory() async {
var path = await getButterflyDirectory();
path = p.joinAll(
[...path.split('/'), 'Remotes', ...remote.identifier.split('/')]);
path = p.joinAll([
...path.split('/'),
'Remotes',
...remote.identifier.split(RegExp(r'(\/|:)'))
]);
return path;
}

Expand Down
5 changes: 4 additions & 1 deletion app/lib/settings/connections.dart
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,10 @@ class __AddRemoteDialogState extends State<_AddRemoteDialog> {
TextButton(
onPressed: () {
if (_isConnected && _isRemote) {
setState(() => _isConnected = false);
setState(() {
_isConnected = false;
_certificateSha1 = null;
});
return;
}
Navigator.of(context).pop();
Expand Down
1 change: 1 addition & 0 deletions fastlane/metadata/android/en-US/changelogs/81.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
* Add option to connect to a self-signed server ([#531](https://github.com/LinwoodDev/Butterfly/issues/531))
* Improve web loading experience
* Fix changing current tool when adding in collaboration mode
* Fix remote connection requests

View all changes in the blog: https://linwood.dev/butterfly/2.0.0-rc.0

0 comments on commit c04f8a1

Please sign in to comment.