1 package org
.asamk
.signal
.manager
.storage
.prekeys
;
3 import org
.asamk
.signal
.manager
.util
.IOUtils
;
4 import org
.slf4j
.Logger
;
5 import org
.slf4j
.LoggerFactory
;
6 import org
.whispersystems
.libsignal
.InvalidKeyIdException
;
7 import org
.whispersystems
.libsignal
.state
.SignedPreKeyRecord
;
10 import java
.io
.FileInputStream
;
11 import java
.io
.FileOutputStream
;
12 import java
.io
.IOException
;
13 import java
.nio
.file
.Files
;
14 import java
.util
.Arrays
;
15 import java
.util
.List
;
16 import java
.util
.regex
.Pattern
;
18 public class SignedPreKeyStore
implements org
.whispersystems
.libsignal
.state
.SignedPreKeyStore
{
20 private final static Logger logger
= LoggerFactory
.getLogger(SignedPreKeyStore
.class);
22 private final File signedPreKeysPath
;
24 public SignedPreKeyStore(final File signedPreKeysPath
) {
25 this.signedPreKeysPath
= signedPreKeysPath
;
29 public SignedPreKeyRecord
loadSignedPreKey(int signedPreKeyId
) throws InvalidKeyIdException
{
30 final var file
= getSignedPreKeyFile(signedPreKeyId
);
33 throw new InvalidKeyIdException("No such signed pre key record!");
35 return loadSignedPreKeyRecord(file
);
38 final Pattern signedPreKeyFileNamePattern
= Pattern
.compile("([0-9]+)");
41 public List
<SignedPreKeyRecord
> loadSignedPreKeys() {
42 final var files
= signedPreKeysPath
.listFiles();
46 return Arrays
.stream(files
)
47 .filter(f
-> signedPreKeyFileNamePattern
.matcher(f
.getName()).matches())
48 .map(this::loadSignedPreKeyRecord
)
53 public void storeSignedPreKey(int signedPreKeyId
, SignedPreKeyRecord
record) {
54 final var file
= getSignedPreKeyFile(signedPreKeyId
);
56 try (var outputStream
= new FileOutputStream(file
)) {
57 outputStream
.write(record.serialize());
59 } catch (IOException e
) {
60 logger
.warn("Failed to store signed pre key, trying to delete file and retry: {}", e
.getMessage());
62 Files
.delete(file
.toPath());
63 try (var outputStream
= new FileOutputStream(file
)) {
64 outputStream
.write(record.serialize());
66 } catch (IOException e2
) {
67 logger
.error("Failed to store signed pre key file {}: {}", file
, e2
.getMessage());
73 public boolean containsSignedPreKey(int signedPreKeyId
) {
74 final var file
= getSignedPreKeyFile(signedPreKeyId
);
80 public void removeSignedPreKey(int signedPreKeyId
) {
81 final var file
= getSignedPreKeyFile(signedPreKeyId
);
87 Files
.delete(file
.toPath());
88 } catch (IOException e
) {
89 logger
.error("Failed to delete signed pre key file {}: {}", file
, e
.getMessage());
93 public void removeAllSignedPreKeys() {
94 final var files
= signedPreKeysPath
.listFiles();
99 for (var file
: files
) {
101 Files
.delete(file
.toPath());
102 } catch (IOException e
) {
103 logger
.error("Failed to delete signed pre key file {}: {}", file
, e
.getMessage());
108 private File
getSignedPreKeyFile(int signedPreKeyId
) {
110 IOUtils
.createPrivateDirectories(signedPreKeysPath
);
111 } catch (IOException e
) {
112 throw new AssertionError("Failed to create signed pre keys path", e
);
114 return new File(signedPreKeysPath
, String
.valueOf(signedPreKeyId
));
117 private SignedPreKeyRecord
loadSignedPreKeyRecord(final File file
) {
118 try (var inputStream
= new FileInputStream(file
)) {
119 return new SignedPreKeyRecord(inputStream
.readAllBytes());
120 } catch (IOException e
) {
121 logger
.error("Failed to load signed pre key: {}", e
.getMessage());
122 throw new AssertionError(e
);