diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index c673d5cfaf..64050b831d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -16,6 +16,7 @@ import org.session.libsession.messaging.threads.Address; import org.session.libsession.utilities.GroupUtil; import org.session.libsession.utilities.TextSecurePreferences; +import org.session.libsignal.service.internal.push.SignalServiceProtos; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; @@ -28,6 +29,7 @@ import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.session.libsignal.utilities.logging.Log; +import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2; import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; @@ -158,7 +160,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { if (filterAddress != null) targets = Collections.singletonList(Address.fromSerialized(filterAddress)); else if (!existingNetworkFailures.isEmpty()) targets = Stream.of(existingNetworkFailures).map(NetworkFailure::getAddress).toList(); - else targets = Collections.singletonList(Address.fromSerialized(message.getRecipient().getAddress().toGroupString())); + else targets = ClosedGroupsProtocolV2.getMessageDestinations(context, message.getRecipient().getAddress().toGroupString()); List results = deliver(message, targets); List networkFailures = Stream.of(results).filter(SendMessageResult::isNetworkFailure).map(result -> new NetworkFailure(Address.fromSerialized(result.getAddress().getNumber()))).toList(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt index 90d18dd0d8..12d94269aa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt @@ -65,7 +65,7 @@ object ClosedGroupsProtocolV2 { // Generate the key pair that'll be used for encryption and decryption val encryptionKeyPair = Curve.generateKeyPair() // Create the group - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val admins = setOf( userPublicKey ) val adminsAsData = admins.map { Hex.fromStringCondensed(it) } DatabaseFactory.getGroupDatabase(context).create(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), @@ -102,7 +102,7 @@ object ClosedGroupsProtocolV2 { val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() val updatedMembers = group.members.map { it.serialize() }.toSet() - userPublicKey val admins = group.admins.map { it.serialize() } @@ -133,7 +133,7 @@ object ClosedGroupsProtocolV2 { return task { val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null) { Log.d("Loki", "Can't leave nonexistent closed group.") @@ -181,7 +181,7 @@ object ClosedGroupsProtocolV2 { val userPublicKey = TextSecurePreferences.getLocalNumber(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null) { Log.d("Loki", "Can't leave nonexistent closed group.") @@ -225,7 +225,7 @@ object ClosedGroupsProtocolV2 { val deferred = deferred() ThreadUtils.queue { val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() val members = group.members.map { it.serialize() }.toSet() val admins = group.admins.map { it.serialize() } @@ -254,7 +254,7 @@ object ClosedGroupsProtocolV2 { fun leave(context: Context, groupPublicKey: String): Promise { val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null) { Log.d("Loki", "Can't leave nonexistent closed group.") @@ -278,7 +278,7 @@ object ClosedGroupsProtocolV2 { val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null) { Log.d("Loki", "Can't update nonexistent closed group.") @@ -359,7 +359,7 @@ object ClosedGroupsProtocolV2 { val userPublicKey = TextSecurePreferences.getLocalNumber(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null) { Log.d("Loki", "Can't update nonexistent closed group.") @@ -454,7 +454,7 @@ object ClosedGroupsProtocolV2 { val members = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() } val admins = closedGroupUpdate.adminsList.map { it.toByteArray().toHexString() } // Create the group - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val groupDB = DatabaseFactory.getGroupDatabase(context) val prevGroup = groupDB.getGroup(groupID).orNull() if (prevGroup != null) { @@ -486,7 +486,7 @@ object ClosedGroupsProtocolV2 { fun handleClosedGroupMembersRemoved(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) { val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null || !group.isActive) { Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") @@ -540,7 +540,7 @@ object ClosedGroupsProtocolV2 { val userPublicKey = TextSecurePreferences.getLocalNumber(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null || !group.isActive) { Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") @@ -582,7 +582,7 @@ object ClosedGroupsProtocolV2 { // Check that the sender is a member of the group (before the update) val userPublicKey = TextSecurePreferences.getLocalNumber(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null || !group.isActive) { Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") @@ -610,7 +610,7 @@ object ClosedGroupsProtocolV2 { val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null || !group.isActive) { Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") @@ -654,7 +654,7 @@ object ClosedGroupsProtocolV2 { val name = closedGroupUpdate.name val members = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() } val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null || !group.isActive) { Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") @@ -735,7 +735,7 @@ object ClosedGroupsProtocolV2 { val userKeyPair = apiDB.getUserX25519KeyPair() // Unwrap the message val groupDB = DatabaseFactory.getGroupDatabase(context) - val groupID = doubleEncodeGroupID(groupPublicKey) + val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() if (group == null) { Log.d("Loki", "Ignoring closed group encryption key pair message for nonexistent group.") @@ -791,17 +791,22 @@ object ClosedGroupsProtocolV2 { mmsDB.markAsSent(infoMessageID, true) } - // NOTE: Signal group ID handling is weird. The ID is double encoded in the database, but not in a `GroupContext`. - @JvmStatic - @Throws(IOException::class) - public fun doubleEncodeGroupID(groupPublicKey: String): String { - return GroupUtil.getEncodedClosedGroupID(GroupUtil.getEncodedClosedGroupID(Hex.fromStringCondensed(groupPublicKey)).toByteArray()) - } - - @JvmStatic - @Throws(IOException::class) - public fun doubleDecodeGroupID(groupID: String): ByteArray { - return GroupUtil.getDecodedGroupIDAsData(GroupUtil.getDecodedGroupID(groupID)) + fun getMessageDestinations(context: Context, groupID: String): List
{ + return if (GroupUtil.isOpenGroup(groupID)) { + listOf(Address.fromSerialized(groupID)) + } else { + var groupPublicKey: String? = null + try { + groupPublicKey = GroupUtil.doubleDecodeGroupID(groupID).toHexString() + } catch (exception: Exception) { + // Do nothing + } + if (groupPublicKey != null && DatabaseFactory.getLokiAPIDatabase(context).isClosedGroup(groupPublicKey)) { + listOf(Address.fromSerialized(groupPublicKey)) + } else { + DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, false).map { it.address } + } + } } } \ No newline at end of file