X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/d520023fc76a522650b7561f2a4fc7a95fb5a04d..7334c7845076aacc59eea674703f7541133bc87e:/src/main/java/org/asamk/signal/storage/SignalAccount.java diff --git a/src/main/java/org/asamk/signal/storage/SignalAccount.java b/src/main/java/org/asamk/signal/storage/SignalAccount.java index 94935441..6043d803 100644 --- a/src/main/java/org/asamk/signal/storage/SignalAccount.java +++ b/src/main/java/org/asamk/signal/storage/SignalAccount.java @@ -14,6 +14,7 @@ import org.asamk.signal.storage.contacts.ContactInfo; import org.asamk.signal.storage.contacts.JsonContactsStore; import org.asamk.signal.storage.groups.GroupInfo; import org.asamk.signal.storage.groups.JsonGroupStore; +import org.asamk.signal.storage.profiles.ProfileStore; import org.asamk.signal.storage.protocol.JsonIdentityKeyStore; import org.asamk.signal.storage.protocol.JsonSignalProtocolStore; import org.asamk.signal.storage.protocol.RecipientStore; @@ -33,11 +34,14 @@ import org.whispersystems.libsignal.util.Pair; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.util.Base64; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.Channels; +import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.util.Collection; @@ -66,13 +70,13 @@ public class SignalAccount implements Closeable { private JsonGroupStore groupStore; private JsonContactsStore contactStore; private RecipientStore recipientStore; + private ProfileStore profileStore; private SignalAccount(final FileChannel fileChannel, final FileLock lock) { this.fileChannel = fileChannel; this.lock = lock; jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); // disable autodetect jsonProcessor.enable(SerializationFeature.INDENT_OUTPUT); // for pretty print, you can disable it. - jsonProcessor.enable(SerializationFeature.WRITE_NULL_MAP_VALUES); jsonProcessor.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); jsonProcessor.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE); jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); @@ -108,6 +112,7 @@ public class SignalAccount implements Closeable { account.groupStore = new JsonGroupStore(); account.contactStore = new JsonContactsStore(); account.recipientStore = new RecipientStore(); + account.profileStore = new ProfileStore(); account.registered = false; return account; @@ -133,6 +138,7 @@ public class SignalAccount implements Closeable { account.groupStore = new JsonGroupStore(); account.contactStore = new JsonContactsStore(); account.recipientStore = new RecipientStore(); + account.profileStore = new ProfileStore(); account.registered = true; account.isMultiDevice = true; @@ -244,6 +250,14 @@ public class SignalAccount implements Closeable { } } + JsonNode profileStoreNode = rootNode.get("profileStore"); + if (profileStoreNode != null) { + profileStore = jsonProcessor.convertValue(profileStoreNode, ProfileStore.class); + } + if (profileStore == null) { + profileStore = new ProfileStore(); + } + JsonNode threadStoreNode = rootNode.get("threadStore"); if (threadStoreNode != null) { LegacyJsonThreadStore threadStore = jsonProcessor.convertValue(threadStoreNode, LegacyJsonThreadStore.class); @@ -290,13 +304,19 @@ public class SignalAccount implements Closeable { .putPOJO("groupStore", groupStore) .putPOJO("contactStore", contactStore) .putPOJO("recipientStore", recipientStore) + .putPOJO("profileStore", profileStore) ; try { - synchronized (fileChannel) { - fileChannel.position(0); - jsonProcessor.writeValue(Channels.newOutputStream(fileChannel), rootNode); - fileChannel.truncate(fileChannel.position()); - fileChannel.force(false); + try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { + // Write to memory first to prevent corrupting the file in case of serialization errors + jsonProcessor.writeValue(output, rootNode); + ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); + synchronized (fileChannel) { + fileChannel.position(0); + input.transferTo(Channels.newOutputStream(fileChannel)); + fileChannel.truncate(fileChannel.position()); + fileChannel.force(false); + } } } catch (Exception e) { System.err.println(String.format("Error saving file: %s", e.getMessage())); @@ -346,6 +366,10 @@ public class SignalAccount implements Closeable { return recipientStore; } + public ProfileStore getProfileStore() { + return profileStore; + } + public String getUsername() { return username; } @@ -429,7 +453,10 @@ public class SignalAccount implements Closeable { @Override public void close() throws IOException { synchronized (fileChannel) { - lock.close(); + try { + lock.close(); + } catch (ClosedChannelException ignored) { + } fileChannel.close(); } }