downloadAndDecryptAttachment method
Downloads (and decrypts if necessary) the attachment of this
event and returns it as a SDNFile. If this event doesn't
contain an attachment, this throws an error. Set getThumbnail
to
true to download the thumbnail instead.
Implementation
Future<SDNFile> downloadAndDecryptAttachment(
{bool getThumbnail = false,
Future<Uint8List> Function(Uri)? downloadCallback}) async {
if (![EventTypes.Message, EventTypes.Sticker].contains(type)) {
throw ("This event has the type '$type' and so it can't contain an attachment.");
}
if (status.isSending) {
final localFile = room.sendingFilePlaceholders[eventId];
if (localFile != null) return localFile;
}
final database = room.client.database;
final mxcUrl = attachmentOrThumbnailMxcUrl(getThumbnail: getThumbnail);
if (mxcUrl == null) {
throw "This event hasn't any attachment or thumbnail.";
}
getThumbnail = mxcUrl != attachmentMxcUrl;
final isEncrypted =
getThumbnail ? isThumbnailEncrypted : isAttachmentEncrypted;
if (isEncrypted && !room.client.encryptionEnabled) {
throw ('Encryption is not enabled in your Client.');
}
// Is this file storeable?
final thisInfoMap = getThumbnail ? thumbnailInfoMap : infoMap;
var storeable = database != null &&
thisInfoMap['size'] is int &&
thisInfoMap['size'] <= database.maxFileSize;
Uint8List? uint8list;
if (storeable) {
uint8list = await room.client.database?.getFile(mxcUrl);
}
// Download the file
if (uint8list == null) {
final httpClient = room.client.httpClient;
downloadCallback ??=
(Uri url) async => (await httpClient.get(url)).bodyBytes;
uint8list = await downloadCallback(mxcUrl.getDownloadLink(room.client));
storeable = database != null &&
storeable &&
uint8list.lengthInBytes < database.maxFileSize;
if (storeable) {
await database.storeFile(
mxcUrl, uint8list, DateTime.now().millisecondsSinceEpoch);
}
}
// Decrypt the file
if (isEncrypted) {
final fileMap =
getThumbnail ? infoMap['thumbnail_file'] : content['file'];
if (!fileMap['key']['key_ops'].contains('decrypt')) {
throw ("Missing 'decrypt' in 'key_ops'.");
}
final encryptedFile = EncryptedFile(
data: uint8list,
iv: fileMap['iv'],
k: fileMap['key']['k'],
sha256: fileMap['hashes']['sha256'],
);
uint8list =
await room.client.nativeImplementations.decryptFile(encryptedFile);
if (uint8list == null) {
throw ('Unable to decrypt file');
}
}
return SDNFile(bytes: uint8list, name: body);
}