From 52926584b5696a4ad168b118ac304d757c3b9b1e Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Thu, 14 May 2020 10:11:55 +1000 Subject: [PATCH] Add missing sync message handling --- .../securesms/jobs/PushDecryptJob.java | 2 +- .../loki/protocol/FriendRequestProtocol.kt | 2 +- .../loki/protocol/SyncMessagesProtocol.kt | 88 +++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 5cd0aa298a..ffbce85a1c 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -344,7 +344,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get()); else if (syncMessage.getStickerPackOperations().isPresent()) handleSynchronizeStickerPackOperation(syncMessage.getStickerPackOperations().get()); else if (syncMessage.getContacts().isPresent()) SyncMessagesProtocol.handleContactSyncMessage(context, content, syncMessage.getContacts().get()); - else if (syncMessage.getGroups().isPresent()) SyncMessagesProtocol.handleGroupSyncMessage(context, content, syncMessage.getGroups().get()); + else if (syncMessage.getGroups().isPresent()) SyncMessagesProtocol.handleClosedGroupSyncMessage(context, content, syncMessage.getGroups().get()); else if (syncMessage.getOpenGroups().isPresent()) SyncMessagesProtocol.handleOpenGroupSyncMessage(context, content, syncMessage.getOpenGroups().get()); else Log.w(TAG, "Contains no known sync types..."); } else if (content.getCallMessage().isPresent()) { diff --git a/src/org/thoughtcrime/securesms/loki/protocol/FriendRequestProtocol.kt b/src/org/thoughtcrime/securesms/loki/protocol/FriendRequestProtocol.kt index 985ff815eb..e9c1ab368a 100644 --- a/src/org/thoughtcrime/securesms/loki/protocol/FriendRequestProtocol.kt +++ b/src/org/thoughtcrime/securesms/loki/protocol/FriendRequestProtocol.kt @@ -15,7 +15,7 @@ import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendReque object FriendRequestProtocol { - private fun getLastMessageID(context: Context, threadID: Long): Long? { + fun getLastMessageID(context: Context, threadID: Long): Long? { val db = DatabaseFactory.getSmsDatabase(context) val messageCount = db.getMessageCountForThread(threadID) if (messageCount == 0) { return null } diff --git a/src/org/thoughtcrime/securesms/loki/protocol/SyncMessagesProtocol.kt b/src/org/thoughtcrime/securesms/loki/protocol/SyncMessagesProtocol.kt index a36750494b..9b45332aab 100644 --- a/src/org/thoughtcrime/securesms/loki/protocol/SyncMessagesProtocol.kt +++ b/src/org/thoughtcrime/securesms/loki/protocol/SyncMessagesProtocol.kt @@ -1,16 +1,31 @@ package org.thoughtcrime.securesms.loki.protocol import android.content.Context +import android.util.Log import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData import org.thoughtcrime.securesms.contacts.ContactAccessor.NumberData import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.DatabaseFactory +import org.thoughtcrime.securesms.groups.GroupManager +import org.thoughtcrime.securesms.groups.GroupMessageProcessor import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob import org.thoughtcrime.securesms.jobs.MultiDeviceGroupUpdateJob +import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities +import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities.addGroup +import org.thoughtcrime.securesms.loki.utilities.recipient import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.util.TextSecurePreferences +import org.whispersystems.signalservice.api.messages.SignalServiceAttachment +import org.whispersystems.signalservice.api.messages.SignalServiceContent +import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage +import org.whispersystems.signalservice.api.messages.SignalServiceGroup +import org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage +import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsInputStream +import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsInputStream +import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol +import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation import java.util.* @@ -72,4 +87,77 @@ object SyncMessagesProtocol { fun shouldSyncReadReceipt(address: Address): Boolean { return !address.isGroup } + + @JvmStatic + fun handleContactSyncMessage(context: Context, content: SignalServiceContent, message: ContactsMessage) { + if (!message.contactsStream.isStream) { return } + val userPublicKey = TextSecurePreferences.getLocalNumber(context) + val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey) + if (!allUserDevices.contains(content.sender)) { return } + Log.d("Loki", "Received a contact sync message.") + val contactsInputStream = DeviceContactsInputStream(message.contactsStream.asStream().inputStream) + val contactPublicKeys = contactsInputStream.readAll().map { it.number } + for (contactPublicKey in contactPublicKeys) { + if (contactPublicKey == userPublicKey || !PublicKeyValidation.isValid(contactPublicKey)) { return } + val recipient = recipient(context, contactPublicKey) + val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient) + val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context) + val threadFRStatus = lokiThreadDB.getFriendRequestStatus(threadID) + when (threadFRStatus) { + LokiThreadFriendRequestStatus.NONE, LokiThreadFriendRequestStatus.REQUEST_EXPIRED -> { + // TODO: Send AFR to contact and their linked devices + } + LokiThreadFriendRequestStatus.REQUEST_RECEIVED -> { + FriendRequestProtocol.acceptFriendRequest(contactPublicKey) // Takes into account multi device internally + lokiThreadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS) + val lastMessageID = FriendRequestProtocol.getLastMessageID(context, threadID) + if (lastMessageID != null) { + DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(lastMessageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED) + } + } + else -> { + // Do nothing + } + } + } + } + + @JvmStatic + fun handleClosedGroupSyncMessage(context: Context, content: SignalServiceContent, message: SignalServiceAttachment) { + if (!message.isStream) { return } + val userPublicKey = TextSecurePreferences.getLocalNumber(context) + val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey) + if (!allUserDevices.contains(content.sender)) { return } + Log.d("Loki", "Received a closed group sync message.") + val closedGroupsInputStream = DeviceGroupsInputStream(message.asStream().inputStream) + val closedGroups = closedGroupsInputStream.readAll() + for (closedGroup in closedGroups) { + val signalServiceGroup = SignalServiceGroup( + SignalServiceGroup.Type.UPDATE, + closedGroup.id, + SignalServiceGroup.GroupType.SIGNAL, + closedGroup.name.orNull(), + closedGroup.members, + closedGroup.avatar.orNull(), + closedGroup.admins + ) + val signalServiceDataMessage = SignalServiceDataMessage(content.timestamp, signalServiceGroup, null, null) + // This establishes sessions internally + GroupMessageProcessor.process(context, content, signalServiceDataMessage, false) + } + } + + @JvmStatic + fun handleOpenGroupSyncMessage(context: Context, content: SignalServiceContent, openGroups: List) { + val userPublicKey = TextSecurePreferences.getLocalNumber(context) + val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey) + if (!allUserDevices.contains(content.sender)) { return } + for (openGroup in openGroups) { + val threadID: Long = GroupManager.getOpenGroupThreadID(openGroup.id, context) + if (threadID > -1) { continue } // The group exists already + val url = openGroup.server + val channel = openGroup.channel + OpenGroupUtilities.addGroup(context, url, channel) + } + } } \ No newline at end of file