From e0c2f58e8d25e5cb3c4b3e88f897f2c49e327be7 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 22 Oct 2022 20:32:11 +0200 Subject: [PATCH] Store attachments with a file extension Taken from the filename if present, otherwise guessed from the contentType --- .../asamk/signal/manager/AttachmentStore.java | 43 +++++++++++++++---- .../signal/manager/api/MessageEnvelope.java | 9 ++-- .../manager/helper/AttachmentHelper.java | 10 ++--- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java b/lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java index f983a90b..949e2862 100644 --- a/lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java @@ -1,12 +1,15 @@ package org.asamk.signal.manager; import org.asamk.signal.manager.util.IOUtils; +import org.asamk.signal.manager.util.MimeUtils; +import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.Optional; public class AttachmentStore { @@ -17,15 +20,23 @@ public class AttachmentStore { } public void storeAttachmentPreview( - final SignalServiceAttachmentRemoteId attachmentId, final AttachmentStorer storer + final SignalServiceAttachmentPointer pointer, final AttachmentStorer storer ) throws IOException { - storeAttachment(getAttachmentPreviewFile(attachmentId), storer); + storeAttachment(getAttachmentPreviewFile(pointer.getRemoteId(), + pointer.getFileName(), + Optional.ofNullable(pointer.getContentType())), storer); } public void storeAttachment( - final SignalServiceAttachmentRemoteId attachmentId, final AttachmentStorer storer + final SignalServiceAttachmentPointer pointer, final AttachmentStorer storer ) throws IOException { - storeAttachment(getAttachmentFile(attachmentId), storer); + storeAttachment(getAttachmentFile(pointer), storer); + } + + public File getAttachmentFile(final SignalServiceAttachmentPointer pointer) { + return getAttachmentFile(pointer.getRemoteId(), + pointer.getFileName(), + Optional.ofNullable(pointer.getContentType())); } private void storeAttachment(final File attachmentFile, final AttachmentStorer storer) throws IOException { @@ -35,12 +46,28 @@ public class AttachmentStore { } } - private File getAttachmentPreviewFile(SignalServiceAttachmentRemoteId attachmentId) { - return new File(attachmentsPath, attachmentId.toString() + ".preview"); + private File getAttachmentPreviewFile( + SignalServiceAttachmentRemoteId attachmentId, Optional filename, Optional contentType + ) { + final var extension = getAttachmentExtension(filename, contentType); + return new File(attachmentsPath, attachmentId.toString() + extension + ".preview"); + } + + private File getAttachmentFile( + SignalServiceAttachmentRemoteId attachmentId, Optional filename, Optional contentType + ) { + final var extension = getAttachmentExtension(filename, contentType); + return new File(attachmentsPath, attachmentId.toString() + extension); } - public File getAttachmentFile(SignalServiceAttachmentRemoteId attachmentId) { - return new File(attachmentsPath, attachmentId.toString()); + private static String getAttachmentExtension( + final Optional filename, final Optional contentType + ) { + return filename.filter(f -> f.contains(".")) + .map(f -> f.substring(f.lastIndexOf(".") + 1)) + .or(() -> contentType.flatMap(MimeUtils::guessExtensionFromMimeType)) + .map(ext -> "." + ext) + .orElse(""); } private void createAttachmentsDir() throws IOException { diff --git a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java index 2eb0546a..9b6a476e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java @@ -6,7 +6,7 @@ import org.asamk.signal.manager.helper.RecipientAddressResolver; import org.asamk.signal.manager.storage.recipients.RecipientResolver; import org.signal.libsignal.metadata.ProtocolException; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId; +import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; @@ -281,8 +281,9 @@ public record MessageEnvelope( static Attachment from(SignalServiceAttachment attachment, AttachmentFileProvider fileProvider) { if (attachment.isPointer()) { final var a = attachment.asPointer(); - return new Attachment(Optional.of(a.getRemoteId().toString()), - Optional.of(fileProvider.getFile(a.getRemoteId())), + final var attachmentFile = fileProvider.getFile(a); + return new Attachment(Optional.of(attachmentFile.getName()), + Optional.of(attachmentFile), a.getFileName(), a.getContentType(), a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()), @@ -918,6 +919,6 @@ public record MessageEnvelope( public interface AttachmentFileProvider { - File getFile(SignalServiceAttachmentRemoteId attachmentRemoteId); + File getFile(SignalServiceAttachmentPointer pointer); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java index 0d560e14..ea5739b3 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java @@ -11,7 +11,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream; import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException; @@ -35,8 +34,8 @@ public class AttachmentHelper { this.attachmentStore = context.getAttachmentStore(); } - public File getAttachmentFile(SignalServiceAttachmentRemoteId attachmentId) { - return attachmentStore.getAttachmentFile(attachmentId); + public File getAttachmentFile(SignalServiceAttachmentPointer pointer) { + return attachmentStore.getAttachmentFile(pointer); } public List uploadAttachments(final List attachments) throws AttachmentInvalidException, IOException { @@ -69,7 +68,7 @@ public class AttachmentHelper { if (pointer.getPreview().isPresent()) { final var preview = pointer.getPreview().get(); try { - attachmentStore.storeAttachmentPreview(pointer.getRemoteId(), + attachmentStore.storeAttachmentPreview(pointer, outputStream -> outputStream.write(preview, 0, preview.length)); } catch (IOException e) { logger.warn("Failed to download attachment preview, ignoring: {}", e.getMessage()); @@ -77,8 +76,7 @@ public class AttachmentHelper { } try { - attachmentStore.storeAttachment(pointer.getRemoteId(), - outputStream -> this.retrieveAttachment(pointer, outputStream)); + attachmentStore.storeAttachment(pointer, outputStream -> this.retrieveAttachment(pointer, outputStream)); } catch (IOException e) { logger.warn("Failed to download attachment ({}), ignoring: {}", pointer.getRemoteId(), e.getMessage()); } -- 2.50.1