]> nmode's Git Repositories - signal-cli/commitdiff
Store messages in cache by recipient id
authorAsamK <asamk@gmx.de>
Wed, 21 Apr 2021 16:06:48 +0000 (18:06 +0200)
committerAsamK <asamk@gmx.de>
Sat, 1 May 2021 06:46:00 +0000 (08:46 +0200)
lib/src/main/java/org/asamk/signal/manager/Manager.java
lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java
lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java
lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java

index a8eaa9abef96287a7cf0100f54f6bc4618a9f71b..60263dd996f40232503b24008aae011de4af1f3f 100644 (file)
@@ -1629,6 +1629,15 @@ public class Manager implements Closeable {
             try {
                 content = decryptMessage(envelope);
             } catch (org.whispersystems.libsignal.UntrustedIdentityException e) {
+                if (!envelope.hasSource()) {
+                    final var recipientId = resolveRecipient(((org.whispersystems.libsignal.UntrustedIdentityException) e)
+                            .getName());
+                    try {
+                        account.getMessageCache().replaceSender(cachedMessage, recipientId);
+                    } catch (IOException ioException) {
+                        logger.warn("Failed to move cached message to recipient folder: {}", ioException.getMessage());
+                    }
+                }
                 return;
             } catch (Exception er) {
                 // All other errors are not recoverable, so delete the cached message
@@ -1671,8 +1680,11 @@ public class Manager implements Closeable {
             final CachedMessage[] cachedMessage = {null};
             try {
                 var result = messagePipe.readOrEmpty(timeout, unit, envelope1 -> {
+                    final var recipientId = envelope1.hasSource()
+                            ? resolveRecipient(envelope1.getSourceIdentifier())
+                            : null;
                     // store message on disk, before acknowledging receipt to the server
-                    cachedMessage[0] = account.getMessageCache().cacheMessage(envelope1);
+                    cachedMessage[0] = account.getMessageCache().cacheMessage(envelope1, recipientId);
                 });
                 if (result.isPresent()) {
                     envelope = result.get();
@@ -1703,8 +1715,7 @@ public class Manager implements Closeable {
 
             if (envelope.hasSource()) {
                 // Store uuid if we don't have it already
-                var source = envelope.getSourceAddress();
-                resolveSignalServiceAddress(source);
+                resolveRecipientTrusted(envelope.getSourceAddress());
             }
             if (!envelope.isReceipt()) {
                 try {
@@ -1736,8 +1747,19 @@ public class Manager implements Closeable {
             } else {
                 handler.handleMessage(envelope, content, exception);
             }
-            if (!(exception instanceof org.whispersystems.libsignal.UntrustedIdentityException)) {
-                if (cachedMessage[0] != null) {
+            if (cachedMessage[0] != null) {
+                if (exception instanceof org.whispersystems.libsignal.UntrustedIdentityException) {
+                    if (!envelope.hasSource()) {
+                        final var recipientId = resolveRecipient(((org.whispersystems.libsignal.UntrustedIdentityException) exception)
+                                .getName());
+                        try {
+                            cachedMessage[0] = account.getMessageCache().replaceSender(cachedMessage[0], recipientId);
+                        } catch (IOException ioException) {
+                            logger.warn("Failed to move cached message to recipient folder: {}",
+                                    ioException.getMessage());
+                        }
+                    }
+                } else {
                     cachedMessage[0].delete();
                 }
             }
@@ -2461,7 +2483,12 @@ public class Manager implements Closeable {
         var canonicalizedNumber = UuidUtil.isUuid(identifier)
                 ? identifier
                 : PhoneNumberFormatter.formatNumber(identifier, account.getUsername());
-        var address = Utils.getSignalServiceAddressFromIdentifier(canonicalizedNumber);
+
+        return resolveRecipient(canonicalizedNumber);
+    }
+
+    private RecipientId resolveRecipient(final String identifier) {
+        var address = Utils.getSignalServiceAddressFromIdentifier(identifier);
 
         return resolveRecipient(address);
     }
index b1b888ccfaad2c3b1e791074349d2a86c1dc8003..9aa283a285c58b8e2f8c32a7147286f5fbe045da 100644 (file)
@@ -244,6 +244,7 @@ public class SignalAccount implements Closeable {
     private void mergeRecipients(RecipientId recipientId, RecipientId toBeMergedRecipientId) {
         sessionStore.mergeRecipients(recipientId, toBeMergedRecipientId);
         identityKeyStore.mergeRecipients(recipientId, toBeMergedRecipientId);
+        messageCache.mergeRecipients(recipientId, toBeMergedRecipientId);
     }
 
     public static File getFileName(File dataPath, String username) {
index 404153b3dbbc00ba761587bf727810733c15c8f1..941c4fa9323e7b08ec2d126dcf70f1e876b9c971 100644 (file)
@@ -19,6 +19,10 @@ public final class CachedMessage {
         this.file = file;
     }
 
+    File getFile() {
+        return file;
+    }
+
     public SignalServiceEnvelope loadEnvelope() {
         try {
             return MessageCacheUtils.loadEnvelope(file);
@@ -34,5 +38,10 @@ public final class CachedMessage {
         } catch (IOException e) {
             logger.warn("Failed to delete cached message file “{}”, ignoring: {}", file, e.getMessage());
         }
+        // Delete parent directory, if empty
+        try {
+            Files.delete(file.toPath().getParent());
+        } catch (IOException ignored) {
+        }
     }
 }
index 6d604300ca21dcc47a50f14744353266d3f84730..76e402ad2ab2e3ab493e535b7581777a35927636 100644 (file)
@@ -1,5 +1,6 @@
 package org.asamk.signal.manager.storage.messageCache;
 
+import org.asamk.signal.manager.storage.recipients.RecipientId;
 import org.asamk.signal.manager.util.IOUtils;
 import org.asamk.signal.manager.util.MessageCacheUtils;
 import org.slf4j.Logger;
@@ -49,12 +50,11 @@ public class MessageCache {
         }).map(CachedMessage::new).collect(Collectors.toList());
     }
 
-    public CachedMessage cacheMessage(SignalServiceEnvelope envelope) {
+    public CachedMessage cacheMessage(SignalServiceEnvelope envelope, RecipientId recipientId) {
         final var now = new Date().getTime();
-        final var source = envelope.hasSource() ? envelope.getSourceAddress().getLegacyIdentifier() : "";
 
         try {
-            var cacheFile = getMessageCacheFile(source, now, envelope.getTimestamp());
+            var cacheFile = getMessageCacheFile(recipientId, now, envelope.getTimestamp());
             MessageCacheUtils.storeEnvelope(envelope, cacheFile);
             return new CachedMessage(cacheFile);
         } catch (IOException e) {
@@ -63,17 +63,53 @@ public class MessageCache {
         }
     }
 
-    private File getMessageCachePath(String sender) {
-        if (sender == null || sender.isEmpty()) {
+    public CachedMessage replaceSender(CachedMessage cachedMessage, RecipientId sender) throws IOException {
+        final var cacheFile = getMessageCacheFile(sender, cachedMessage.getFile().getName());
+        if (cacheFile.equals(cachedMessage.getFile())) {
+            return cachedMessage;
+        }
+        Files.move(cachedMessage.getFile().toPath(), cacheFile.toPath());
+        return new CachedMessage(cacheFile);
+    }
+
+    private File getMessageCachePath(RecipientId recipientId) {
+        if (recipientId == null) {
             return messageCachePath;
         }
 
+        var sender = String.valueOf(recipientId.getId());
         return new File(messageCachePath, sender.replace("/", "_"));
     }
 
-    private File getMessageCacheFile(String sender, long now, long timestamp) throws IOException {
-        var cachePath = getMessageCachePath(sender);
+    private File getMessageCacheFile(RecipientId recipientId, String filename) throws IOException {
+        var cachePath = getMessageCachePath(recipientId);
+        IOUtils.createPrivateDirectories(cachePath);
+        return new File(cachePath, filename);
+    }
+
+    private File getMessageCacheFile(RecipientId recipientId, long now, long timestamp) throws IOException {
+        var cachePath = getMessageCachePath(recipientId);
         IOUtils.createPrivateDirectories(cachePath);
         return new File(cachePath, now + "_" + timestamp);
     }
+
+    public void mergeRecipients(final RecipientId recipientId, final RecipientId toBeMergedRecipientId) {
+        final var toBeMergedMessageCachePath = getMessageCachePath(toBeMergedRecipientId);
+        if (!toBeMergedMessageCachePath.exists()) {
+            return;
+        }
+
+        for (var file : Objects.requireNonNull(toBeMergedMessageCachePath.listFiles())) {
+            if (!file.isFile()) {
+                continue;
+            }
+
+            try {
+                final var cacheFile = getMessageCacheFile(recipientId, file.getName());
+                Files.move(file.toPath(), cacheFile.toPath());
+            } catch (IOException e) {
+                logger.warn("Failed to move cache file “{}”, ignoring: {}", file, e.getMessage());
+            }
+        }
+    }
 }