Store attachments with a file extension

Taken from the filename if present, otherwise guessed from the contentType
This commit is contained in:
AsamK 2022-10-22 20:32:11 +02:00
parent 0084a2e722
commit e0c2f58e8d
3 changed files with 44 additions and 18 deletions

View file

@ -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<String> filename, Optional<String> contentType
) {
final var extension = getAttachmentExtension(filename, contentType);
return new File(attachmentsPath, attachmentId.toString() + extension + ".preview");
}
public File getAttachmentFile(SignalServiceAttachmentRemoteId attachmentId) {
return new File(attachmentsPath, attachmentId.toString());
private File getAttachmentFile(
SignalServiceAttachmentRemoteId attachmentId, Optional<String> filename, Optional<String> contentType
) {
final var extension = getAttachmentExtension(filename, contentType);
return new File(attachmentsPath, attachmentId.toString() + extension);
}
private static String getAttachmentExtension(
final Optional<String> filename, final Optional<String> 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 {

View file

@ -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);
}
}

View file

@ -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<SignalServiceAttachment> uploadAttachments(final List<String> 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());
}