]> nmode's Git Repositories - signal-cli/blobdiff - src/main/java/org/asamk/signal/storage/SignalAccount.java
Prevent corrupting account file, when serialization fails
[signal-cli] / src / main / java / org / asamk / signal / storage / SignalAccount.java
index d9b37825b108fd114baa90139ddd44ca83bffd6a..6043d803407b82457359ed59e5044797605184e4 100644 (file)
@@ -34,6 +34,8 @@ 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;
@@ -75,7 +77,6 @@ public class SignalAccount implements Closeable {
         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);
@@ -306,11 +307,16 @@ public class SignalAccount implements Closeable {
                 .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()));