1 package org
.asamk
.signal
.manager
;
3 import org
.asamk
.signal
.manager
.util
.IOUtils
;
4 import org
.asamk
.signal
.manager
.util
.MimeUtils
;
5 import org
.asamk
.signal
.manager
.util
.Utils
;
6 import org
.whispersystems
.signalservice
.api
.messages
.SignalServiceAttachmentPointer
;
7 import org
.whispersystems
.signalservice
.api
.messages
.SignalServiceAttachmentRemoteId
;
8 import org
.whispersystems
.signalservice
.api
.util
.StreamDetails
;
11 import java
.io
.FileOutputStream
;
12 import java
.io
.IOException
;
13 import java
.io
.OutputStream
;
14 import java
.util
.Optional
;
16 public class AttachmentStore
{
18 private final File attachmentsPath
;
20 public AttachmentStore(final File attachmentsPath
) {
21 this.attachmentsPath
= attachmentsPath
;
24 public void storeAttachmentPreview(
25 final SignalServiceAttachmentPointer pointer
, final AttachmentStorer storer
26 ) throws IOException
{
27 storeAttachment(getAttachmentPreviewFile(pointer
.getRemoteId(),
28 pointer
.getFileName(),
29 Optional
.ofNullable(pointer
.getContentType())), storer
);
32 public void storeAttachment(
33 final SignalServiceAttachmentPointer pointer
, final AttachmentStorer storer
34 ) throws IOException
{
35 storeAttachment(getAttachmentFile(pointer
), storer
);
38 public File
getAttachmentFile(final SignalServiceAttachmentPointer pointer
) {
39 return getAttachmentFile(pointer
.getRemoteId(),
40 pointer
.getFileName(),
41 Optional
.ofNullable(pointer
.getContentType()));
44 public StreamDetails
retrieveAttachment(final String id
) throws IOException
{
45 final var attachmentFile
= new File(attachmentsPath
, id
);
46 if (!attachmentFile
.exists()) {
49 return Utils
.createStreamDetailsFromFile(attachmentFile
);
52 private void storeAttachment(final File attachmentFile
, final AttachmentStorer storer
) throws IOException
{
53 createAttachmentsDir();
54 try (OutputStream output
= new FileOutputStream(attachmentFile
)) {
59 private File
getAttachmentPreviewFile(
60 SignalServiceAttachmentRemoteId attachmentId
, Optional
<String
> filename
, Optional
<String
> contentType
62 final var extension
= getAttachmentExtension(filename
, contentType
);
63 return new File(attachmentsPath
, attachmentId
.toString() + extension
+ ".preview");
66 private File
getAttachmentFile(
67 SignalServiceAttachmentRemoteId attachmentId
, Optional
<String
> filename
, Optional
<String
> contentType
69 final var extension
= getAttachmentExtension(filename
, contentType
);
70 return new File(attachmentsPath
, attachmentId
.toString() + extension
);
73 private static String
getAttachmentExtension(
74 final Optional
<String
> filename
, final Optional
<String
> contentType
76 return filename
.filter(f
-> f
.contains("."))
77 .map(f
-> f
.substring(f
.lastIndexOf(".") + 1))
78 .or(() -> contentType
.flatMap(MimeUtils
::guessExtensionFromMimeType
))
79 .map(ext
-> "." + ext
)
83 private void createAttachmentsDir() throws IOException
{
84 IOUtils
.createPrivateDirectories(attachmentsPath
);
88 public interface AttachmentStorer
{
90 void store(OutputStream outputStream
) throws IOException
;