]> nmode's Git Repositories - signal-cli/commitdiff
Add RecipientStore to resolve all identifiers to SignalServiceAddress
authorAsamK <asamk@gmx.de>
Fri, 3 Apr 2020 09:56:26 +0000 (11:56 +0200)
committerAsamK <asamk@gmx.de>
Fri, 3 Apr 2020 11:22:36 +0000 (13:22 +0200)
Should fix #290

src/main/java/org/asamk/signal/manager/Manager.java
src/main/java/org/asamk/signal/manager/Utils.java
src/main/java/org/asamk/signal/storage/SignalAccount.java
src/main/java/org/asamk/signal/storage/contacts/JsonContactsStore.java
src/main/java/org/asamk/signal/storage/groups/GroupInfo.java
src/main/java/org/asamk/signal/storage/protocol/JsonSessionStore.java
src/main/java/org/asamk/signal/storage/protocol/JsonSignalProtocolStore.java
src/main/java/org/asamk/signal/storage/protocol/RecipientStore.java [new file with mode: 0644]

index ccb2fbcecef06245ac8af4577b181fe42e3a98ca..f1316d643ee78ca044ffd6de87706bd73049c109 100644 (file)
@@ -139,6 +139,7 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
@@ -1287,7 +1288,10 @@ public class Manager implements Signal {
                     }
 
                     if (groupInfo.getMembers().isPresent()) {
                     }
 
                     if (groupInfo.getMembers().isPresent()) {
-                        group.addMembers(groupInfo.getMembers().get());
+                        group.addMembers(groupInfo.getMembers().get()
+                                .stream()
+                                .map(this::resolveSignalServiceAddress)
+                                .collect(Collectors.toSet()));
                     }
 
                     account.getGroupStore().updateGroup(group);
                     }
 
                     account.getGroupStore().updateGroup(group);
@@ -1326,8 +1330,9 @@ public class Manager implements Signal {
                     break;
             }
         }
                     break;
             }
         }
+        final SignalServiceAddress conversationPartnerAddress = isSync ? destination : source;
         if (message.isEndSession()) {
         if (message.isEndSession()) {
-            handleEndSession(isSync ? destination : source);
+            handleEndSession(conversationPartnerAddress);
         }
         if (message.isExpirationUpdate() || message.getBody().isPresent()) {
             if (message.getGroupContext().isPresent() && message.getGroupContext().get().getGroupV1().isPresent()) {
         }
         if (message.isExpirationUpdate() || message.getBody().isPresent()) {
             if (message.getGroupContext().isPresent() && message.getGroupContext().get().getGroupV1().isPresent()) {
@@ -1341,9 +1346,9 @@ public class Manager implements Signal {
                     account.getGroupStore().updateGroup(group);
                 }
             } else {
                     account.getGroupStore().updateGroup(group);
                 }
             } else {
-                ContactInfo contact = account.getContactStore().getContact(isSync ? destination : source);
+                ContactInfo contact = account.getContactStore().getContact(conversationPartnerAddress);
                 if (contact == null) {
                 if (contact == null) {
-                    contact = new ContactInfo(isSync ? destination : source);
+                    contact = new ContactInfo(conversationPartnerAddress);
                 }
                 if (contact.messageExpirationTime != message.getExpiresInSeconds()) {
                     contact.messageExpirationTime = message.getExpiresInSeconds();
                 }
                 if (contact.messageExpirationTime != message.getExpiresInSeconds()) {
                     contact.messageExpirationTime = message.getExpiresInSeconds();
@@ -1607,7 +1612,10 @@ public class Manager implements Signal {
                                 if (g.getName().isPresent()) {
                                     syncGroup.name = g.getName().get();
                                 }
                                 if (g.getName().isPresent()) {
                                     syncGroup.name = g.getName().get();
                                 }
-                                syncGroup.addMembers(g.getMembers());
+                                syncGroup.addMembers(g.getMembers()
+                                        .stream()
+                                        .map(this::resolveSignalServiceAddress)
+                                        .collect(Collectors.toSet()));
                                 if (!g.isActive()) {
                                     syncGroup.removeMember(account.getSelfAddress());
                                 } else {
                                 if (!g.isActive()) {
                                     syncGroup.removeMember(account.getSelfAddress());
                                 } else {
@@ -1642,7 +1650,7 @@ public class Manager implements Signal {
                 if (syncMessage.getBlockedList().isPresent()) {
                     final BlockedListMessage blockedListMessage = syncMessage.getBlockedList().get();
                     for (SignalServiceAddress address : blockedListMessage.getAddresses()) {
                 if (syncMessage.getBlockedList().isPresent()) {
                     final BlockedListMessage blockedListMessage = syncMessage.getBlockedList().get();
                     for (SignalServiceAddress address : blockedListMessage.getAddresses()) {
-                        setContactBlocked(address, true);
+                        setContactBlocked(resolveSignalServiceAddress(address), true);
                     }
                     for (byte[] groupId : blockedListMessage.getGroupIds()) {
                         try {
                     }
                     for (byte[] groupId : blockedListMessage.getGroupIds()) {
                         try {
@@ -1667,9 +1675,10 @@ public class Manager implements Signal {
                                 if (c.getAddress().matches(account.getSelfAddress()) && c.getProfileKey().isPresent()) {
                                     account.setProfileKey(c.getProfileKey().get());
                                 }
                                 if (c.getAddress().matches(account.getSelfAddress()) && c.getProfileKey().isPresent()) {
                                     account.setProfileKey(c.getProfileKey().get());
                                 }
-                                ContactInfo contact = account.getContactStore().getContact(c.getAddress());
+                                final SignalServiceAddress address = resolveSignalServiceAddress(c.getAddress());
+                                ContactInfo contact = account.getContactStore().getContact(address);
                                 if (contact == null) {
                                 if (contact == null) {
-                                    contact = new ContactInfo(c.getAddress());
+                                    contact = new ContactInfo(address);
                                 }
                                 if (c.getName().isPresent()) {
                                     contact.name = c.getName().get();
                                 }
                                 if (c.getName().isPresent()) {
                                     contact.name = c.getName().get();
@@ -1711,7 +1720,7 @@ public class Manager implements Signal {
                 }
                 if (syncMessage.getVerified().isPresent()) {
                     final VerifiedMessage verifiedMessage = syncMessage.getVerified().get();
                 }
                 if (syncMessage.getVerified().isPresent()) {
                     final VerifiedMessage verifiedMessage = syncMessage.getVerified().get();
-                    account.getSignalProtocolStore().setIdentityTrustLevel(verifiedMessage.getDestination(), verifiedMessage.getIdentityKey(), TrustLevel.fromVerifiedState(verifiedMessage.getVerified()));
+                    account.getSignalProtocolStore().setIdentityTrustLevel(resolveSignalServiceAddress(verifiedMessage.getDestination()), verifiedMessage.getIdentityKey(), TrustLevel.fromVerifiedState(verifiedMessage.getVerified()));
                 }
                 if (syncMessage.getConfiguration().isPresent()) {
                     // TODO
                 }
                 if (syncMessage.getConfiguration().isPresent()) {
                     // TODO
@@ -2030,15 +2039,16 @@ public class Manager implements Signal {
 
     public SignalServiceAddress resolveSignalServiceAddress(String identifier) {
         SignalServiceAddress address = Util.getSignalServiceAddressFromIdentifier(identifier);
 
     public SignalServiceAddress resolveSignalServiceAddress(String identifier) {
         SignalServiceAddress address = Util.getSignalServiceAddressFromIdentifier(identifier);
+
+        return resolveSignalServiceAddress(address);
+    }
+
+    public SignalServiceAddress resolveSignalServiceAddress(SignalServiceAddress address) {
         if (address.matches(account.getSelfAddress())) {
             return account.getSelfAddress();
         }
 
         if (address.matches(account.getSelfAddress())) {
             return account.getSelfAddress();
         }
 
-        ContactInfo contactInfo = account.getContactStore().getContact(address);
-        if (contactInfo == null) {
-            return address;
-        }
-        return contactInfo.getAddress();
+        return account.getRecipientStore().resolveServiceAddress(address);
     }
 
     public interface ReceiveMessageHandler {
     }
 
     public interface ReceiveMessageHandler {
index 0b74f01d90b0d9060fd548224f7fcabd1638cf88..449681d2b8b5f8a39e68c39b8fc6e511b9a56f86 100644 (file)
@@ -252,6 +252,9 @@ class Utils {
         } else {
             // Version 1: E164 user
             version = 1;
         } else {
             // Version 1: E164 user
             version = 1;
+            if (!ownAddress.getNumber().isPresent() || !theirAddress.getNumber().isPresent()) {
+                return "INVALID ID";
+            }
             ownId = ownAddress.getNumber().get().getBytes();
             theirId = theirAddress.getNumber().get().getBytes();
         }
             ownId = ownAddress.getNumber().get().getBytes();
             theirId = theirAddress.getNumber().get().getBytes();
         }
index 73f79a48d5b1faa0adab0bebb208c102ab12fc59..f03bac3a9d0bf85edc4a347a67601fe3184c1b80 100644 (file)
@@ -14,7 +14,10 @@ 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.contacts.JsonContactsStore;
 import org.asamk.signal.storage.groups.GroupInfo;
 import org.asamk.signal.storage.groups.JsonGroupStore;
+import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
 import org.asamk.signal.storage.protocol.JsonSignalProtocolStore;
 import org.asamk.signal.storage.protocol.JsonSignalProtocolStore;
+import org.asamk.signal.storage.protocol.RecipientStore;
+import org.asamk.signal.storage.protocol.SessionInfo;
 import org.asamk.signal.storage.protocol.SignalServiceAddressResolver;
 import org.asamk.signal.storage.threads.LegacyJsonThreadStore;
 import org.asamk.signal.storage.threads.ThreadInfo;
 import org.asamk.signal.storage.protocol.SignalServiceAddressResolver;
 import org.asamk.signal.storage.threads.LegacyJsonThreadStore;
 import org.asamk.signal.storage.threads.ThreadInfo;
@@ -37,6 +40,7 @@ import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
 import java.util.Collection;
 import java.util.UUID;
 import java.nio.channels.FileLock;
 import java.util.Collection;
 import java.util.UUID;
+import java.util.stream.Collectors;
 
 public class SignalAccount {
 
 
 public class SignalAccount {
 
@@ -59,6 +63,7 @@ public class SignalAccount {
     private JsonSignalProtocolStore signalProtocolStore;
     private JsonGroupStore groupStore;
     private JsonContactsStore contactStore;
     private JsonSignalProtocolStore signalProtocolStore;
     private JsonGroupStore groupStore;
     private JsonContactsStore contactStore;
+    private RecipientStore recipientStore;
 
     private SignalAccount() {
         jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); // disable autodetect
 
     private SignalAccount() {
         jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); // disable autodetect
@@ -88,6 +93,7 @@ public class SignalAccount {
         account.signalProtocolStore = new JsonSignalProtocolStore(identityKey, registrationId);
         account.groupStore = new JsonGroupStore();
         account.contactStore = new JsonContactsStore();
         account.signalProtocolStore = new JsonSignalProtocolStore(identityKey, registrationId);
         account.groupStore = new JsonGroupStore();
         account.contactStore = new JsonContactsStore();
+        account.recipientStore = new RecipientStore();
         account.registered = false;
 
         return account;
         account.registered = false;
 
         return account;
@@ -108,6 +114,7 @@ public class SignalAccount {
         account.signalProtocolStore = new JsonSignalProtocolStore(identityKey, registrationId);
         account.groupStore = new JsonGroupStore();
         account.contactStore = new JsonContactsStore();
         account.signalProtocolStore = new JsonSignalProtocolStore(identityKey, registrationId);
         account.groupStore = new JsonGroupStore();
         account.contactStore = new JsonContactsStore();
+        account.recipientStore = new RecipientStore();
         account.registered = true;
         account.isMultiDevice = true;
 
         account.registered = true;
         account.isMultiDevice = true;
 
@@ -199,6 +206,35 @@ public class SignalAccount {
         if (contactStore == null) {
             contactStore = new JsonContactsStore();
         }
         if (contactStore == null) {
             contactStore = new JsonContactsStore();
         }
+
+        JsonNode recipientStoreNode = rootNode.get("recipientStore");
+        if (recipientStoreNode != null) {
+            recipientStore = jsonProcessor.convertValue(recipientStoreNode, RecipientStore.class);
+        }
+        if (recipientStore == null) {
+            recipientStore = new RecipientStore();
+
+            recipientStore.resolveServiceAddress(getSelfAddress());
+
+            for (ContactInfo contact : contactStore.getContacts()) {
+                recipientStore.resolveServiceAddress(contact.getAddress());
+            }
+
+            for (GroupInfo group : groupStore.getGroups()) {
+                group.members = group.members.stream()
+                        .map(m -> recipientStore.resolveServiceAddress(m))
+                        .collect(Collectors.toSet());
+            }
+
+            for (SessionInfo session : signalProtocolStore.getSessions()) {
+                session.address = recipientStore.resolveServiceAddress(session.address);
+            }
+
+            for (JsonIdentityKeyStore.Identity identity : signalProtocolStore.getIdentities()) {
+                identity.setAddress(recipientStore.resolveServiceAddress(identity.getAddress()));
+            }
+        }
+
         JsonNode threadStoreNode = rootNode.get("threadStore");
         if (threadStoreNode != null) {
             LegacyJsonThreadStore threadStore = jsonProcessor.convertValue(threadStoreNode, LegacyJsonThreadStore.class);
         JsonNode threadStoreNode = rootNode.get("threadStore");
         if (threadStoreNode != null) {
             LegacyJsonThreadStore threadStore = jsonProcessor.convertValue(threadStoreNode, LegacyJsonThreadStore.class);
@@ -244,6 +280,7 @@ public class SignalAccount {
                 .putPOJO("axolotlStore", signalProtocolStore)
                 .putPOJO("groupStore", groupStore)
                 .putPOJO("contactStore", contactStore)
                 .putPOJO("axolotlStore", signalProtocolStore)
                 .putPOJO("groupStore", groupStore)
                 .putPOJO("contactStore", contactStore)
+                .putPOJO("recipientStore", recipientStore)
         ;
         try {
             synchronized (fileChannel) {
         ;
         try {
             synchronized (fileChannel) {
@@ -302,6 +339,10 @@ public class SignalAccount {
         return contactStore;
     }
 
         return contactStore;
     }
 
+    public RecipientStore getRecipientStore() {
+        return recipientStore;
+    }
+
     public String getUsername() {
         return username;
     }
     public String getUsername() {
         return username;
     }
index 86514bc16e14aa2968a951d7f01c548f6c5ca007..bb81b0c98109388a3e279e47214781720efd5978 100644 (file)
@@ -27,6 +27,12 @@ public class JsonContactsStore {
     public ContactInfo getContact(SignalServiceAddress address) {
         for (ContactInfo contact : contacts) {
             if (contact.getAddress().matches(address)) {
     public ContactInfo getContact(SignalServiceAddress address) {
         for (ContactInfo contact : contacts) {
             if (contact.getAddress().matches(address)) {
+                if (contact.uuid == null) {
+                    contact.uuid = address.getUuid().orNull();
+                } else if (contact.number == null) {
+                    contact.number = address.getNumber().orNull();
+                }
+
                 return contact;
             }
         }
                 return contact;
             }
         }
index e3a45420450d834c3b0c0bb815296ba1f587497f..4b0adcd0a7dafa283769dc1b725734d8dd575077 100644 (file)
@@ -103,6 +103,9 @@ public class GroupInfo {
 
     public void addMembers(Collection<SignalServiceAddress> addresses) {
         for (SignalServiceAddress address : addresses) {
 
     public void addMembers(Collection<SignalServiceAddress> addresses) {
         for (SignalServiceAddress address : addresses) {
+            if (this.members.contains(address)) {
+                continue;
+            }
             removeMember(address);
             this.members.add(address);
         }
             removeMember(address);
             this.members.add(address);
         }
index 90229575e8acf6892fba555dc913b0d39059fcc7..5ce99742eedb3b019dc797b4592e253feb523d25 100644 (file)
@@ -62,6 +62,10 @@ class JsonSessionStore implements SessionStore {
         return new SessionRecord();
     }
 
         return new SessionRecord();
     }
 
+    public synchronized List<SessionInfo> getSessions() {
+        return sessions;
+    }
+
     @Override
     public synchronized List<Integer> getSubDeviceSessions(String name) {
         SignalServiceAddress serviceAddress = resolveSignalServiceAddress(name);
     @Override
     public synchronized List<Integer> getSubDeviceSessions(String name) {
         SignalServiceAddress serviceAddress = resolveSignalServiceAddress(name);
@@ -158,7 +162,7 @@ class JsonSessionStore implements SessionStore {
         }
     }
 
         }
     }
 
-    public static class JsonPreKeyStoreSerializer extends JsonSerializer<JsonSessionStore> {
+    public static class JsonSessionStoreSerializer extends JsonSerializer<JsonSessionStore> {
 
         @Override
         public void serialize(JsonSessionStore jsonSessionStore, JsonGenerator json, SerializerProvider serializerProvider) throws IOException {
 
         @Override
         public void serialize(JsonSessionStore jsonSessionStore, JsonGenerator json, SerializerProvider serializerProvider) throws IOException {
index c707907882e03a7128e425381ce85c0e6a11a854..3dc15cca256dbbf359baf8b719c0bd7baaed82c3 100644 (file)
@@ -26,7 +26,7 @@ public class JsonSignalProtocolStore implements SignalProtocolStore {
 
     @JsonProperty("sessionStore")
     @JsonDeserialize(using = JsonSessionStore.JsonSessionStoreDeserializer.class)
 
     @JsonProperty("sessionStore")
     @JsonDeserialize(using = JsonSessionStore.JsonSessionStoreDeserializer.class)
-    @JsonSerialize(using = JsonSessionStore.JsonPreKeyStoreSerializer.class)
+    @JsonSerialize(using = JsonSessionStore.JsonSessionStoreSerializer.class)
     private JsonSessionStore sessionStore;
 
     @JsonProperty("signedPreKeyStore")
     private JsonSessionStore sessionStore;
 
     @JsonProperty("signedPreKeyStore")
@@ -131,6 +131,10 @@ public class JsonSignalProtocolStore implements SignalProtocolStore {
         return sessionStore.loadSession(address);
     }
 
         return sessionStore.loadSession(address);
     }
 
+    public List<SessionInfo> getSessions() {
+        return sessionStore.getSessions();
+    }
+
     @Override
     public List<Integer> getSubDeviceSessions(String name) {
         return sessionStore.getSubDeviceSessions(name);
     @Override
     public List<Integer> getSubDeviceSessions(String name) {
         return sessionStore.getSubDeviceSessions(name);
diff --git a/src/main/java/org/asamk/signal/storage/protocol/RecipientStore.java b/src/main/java/org/asamk/signal/storage/protocol/RecipientStore.java
new file mode 100644 (file)
index 0000000..4943bd3
--- /dev/null
@@ -0,0 +1,87 @@
+package org.asamk.signal.storage.protocol;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import org.whispersystems.signalservice.api.push.SignalServiceAddress;
+import org.whispersystems.signalservice.api.util.UuidUtil;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+public class RecipientStore {
+
+    @JsonProperty("recipientStore")
+    @JsonDeserialize(using = RecipientStoreDeserializer.class)
+    @JsonSerialize(using = RecipientStoreSerializer.class)
+    private final Set<SignalServiceAddress> addresses = new HashSet<>();
+
+    public RecipientStore() {
+    }
+
+    public SignalServiceAddress resolveServiceAddress(SignalServiceAddress serviceAddress) {
+        if (addresses.contains(serviceAddress)) {
+            // If the Set already contains the exact address with UUID and Number,
+            // we can just return it here.
+            return serviceAddress;
+        }
+
+        for (SignalServiceAddress address : addresses) {
+            if (address.matches(serviceAddress)) {
+                return address;
+            }
+        }
+
+        if (serviceAddress.getNumber().isPresent() && serviceAddress.getUuid().isPresent()) {
+            addresses.add(serviceAddress);
+        }
+
+        return serviceAddress;
+    }
+
+    public static class RecipientStoreDeserializer extends JsonDeserializer<Set<SignalServiceAddress>> {
+
+        @Override
+        public Set<SignalServiceAddress> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
+            JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+            Set<SignalServiceAddress> addresses = new HashSet<>();
+
+            if (node.isArray()) {
+                for (JsonNode recipient : node) {
+                    String recipientName = recipient.get("name").asText();
+                    UUID uuid = UuidUtil.parseOrThrow(recipient.get("uuid").asText());
+                    final SignalServiceAddress serviceAddress = new SignalServiceAddress(uuid, recipientName);
+                    addresses.add(serviceAddress);
+                }
+            }
+
+            return addresses;
+        }
+    }
+
+    public static class RecipientStoreSerializer extends JsonSerializer<Set<SignalServiceAddress>> {
+
+        @Override
+        public void serialize(Set<SignalServiceAddress> addresses, JsonGenerator json, SerializerProvider serializerProvider) throws IOException {
+            json.writeStartArray();
+            for (SignalServiceAddress address : addresses) {
+                json.writeStartObject();
+                json.writeStringField("name", address.getNumber().get());
+                json.writeStringField("uuid", address.getUuid().get().toString());
+                json.writeEndObject();
+            }
+            json.writeEndArray();
+        }
+    }
+}