diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt index ac342a707..967612a1c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt @@ -281,7 +281,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { private fun sendInvitation() { val intent = Intent() intent.action = Intent.ACTION_SEND - val invitation = "Hey, I've been using Session to chat with complete privacy and security. Come join me! Download it at https://getsession.org/. My Session ID is $hexEncodedPublicKey!" + val invitation = "Hey, I've been using Session to chat with complete privacy and security. Come join me! Download it at https://getsession.org/. My Session ID is $hexEncodedPublicKey" intent.putExtra(Intent.EXTRA_TEXT, invitation) intent.type = "text/plain" startActivity(intent) diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt index bd20346f9..f4cfd9202 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt @@ -34,7 +34,7 @@ class ClosedGroupControlMessage() : ControlMessage() { is Kind.New -> { !kind.publicKey.isEmpty && kind.name.isNotEmpty() && kind.encryptionKeyPair?.publicKey != null && kind.encryptionKeyPair?.privateKey != null && kind.members.isNotEmpty() && kind.admins.isNotEmpty() - && kind.expireTimer >= 0 + && kind.expirationTimer >= 0 } is Kind.EncryptionKeyPair -> true is Kind.NameChange -> kind.name.isNotEmpty() @@ -45,7 +45,7 @@ class ClosedGroupControlMessage() : ControlMessage() { } sealed class Kind { - class New(var publicKey: ByteString, var name: String, var encryptionKeyPair: ECKeyPair?, var members: List, var admins: List, var expireTimer: Int) : Kind() { + class New(var publicKey: ByteString, var name: String, var encryptionKeyPair: ECKeyPair?, var members: List, var admins: List, var expirationTimer: Int) : Kind() { internal constructor() : this(ByteString.EMPTY, "", null, listOf(), listOf(), 0) } /** An encryption key pair encrypted for each member individually. @@ -89,11 +89,11 @@ class ClosedGroupControlMessage() : ControlMessage() { val publicKey = closedGroupControlMessageProto.publicKey ?: return null val name = closedGroupControlMessageProto.name ?: return null val encryptionKeyPairAsProto = closedGroupControlMessageProto.encryptionKeyPair ?: return null - val expireTimer = closedGroupControlMessageProto.expireTimer + val expirationTimer = closedGroupControlMessageProto.expirationTimer try { val encryptionKeyPair = ECKeyPair(DjbECPublicKey(encryptionKeyPairAsProto.publicKey.toByteArray()), DjbECPrivateKey(encryptionKeyPairAsProto.privateKey.toByteArray())) - kind = Kind.New(publicKey, name, encryptionKeyPair, closedGroupControlMessageProto.membersList, closedGroupControlMessageProto.adminsList, expireTimer) + kind = Kind.New(publicKey, name, encryptionKeyPair, closedGroupControlMessageProto.membersList, closedGroupControlMessageProto.adminsList, expirationTimer) } catch (e: Exception) { Log.w(TAG, "Couldn't parse key pair from proto: $encryptionKeyPairAsProto.") return null @@ -145,7 +145,7 @@ class ClosedGroupControlMessage() : ControlMessage() { closedGroupControlMessage.encryptionKeyPair = encryptionKeyPair.build() closedGroupControlMessage.addAllMembers(kind.members) closedGroupControlMessage.addAllAdmins(kind.admins) - closedGroupControlMessage.expireTimer = kind.expireTimer + closedGroupControlMessage.expirationTimer = kind.expirationTimer } is Kind.EncryptionKeyPair -> { closedGroupControlMessage.type = DataMessage.ClosedGroupControlMessage.Type.ENCRYPTION_KEY_PAIR @@ -173,10 +173,6 @@ class ClosedGroupControlMessage() : ControlMessage() { dataMessageProto.closedGroupControlMessage = closedGroupControlMessage.build() // Group context setGroupContext(dataMessageProto) - // Expiration timer - // TODO: We * want * expiration timer updates to be explicit. But currently Android will disable the expiration timer for a conversation - // if it receives a message without the current expiration timer value attached to it... - dataMessageProto.expireTimer = Recipient.from(MessagingModuleConfiguration.shared.context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(recipient!!)), false).expireMessages contentProto.dataMessage = dataMessageProto.build() return contentProto.build() } catch (e: Exception) { diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ConfigurationMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ConfigurationMessage.kt index cc49cec65..cb355aa15 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ConfigurationMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ConfigurationMessage.kt @@ -6,6 +6,7 @@ import org.session.libsession.utilities.Address import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.ProfileKeyUtil +import org.session.libsession.utilities.recipients.Recipient import org.session.libsignal.crypto.ecc.DjbECPrivateKey import org.session.libsignal.crypto.ecc.DjbECPublicKey import org.session.libsignal.crypto.ecc.ECKeyPair @@ -19,10 +20,10 @@ class ConfigurationMessage(var closedGroups: List, var openGroups: override val isSelfSendValid: Boolean = true - class ClosedGroup(var publicKey: String, var name: String, var encryptionKeyPair: ECKeyPair?, var members: List, var admins: List) { + class ClosedGroup(var publicKey: String, var name: String, var encryptionKeyPair: ECKeyPair?, var members: List, var admins: List, var expirationTimer: Int) { val isValid: Boolean get() = members.isNotEmpty() && admins.isNotEmpty() - internal constructor() : this("", "", null, listOf(), listOf()) + internal constructor() : this("", "", null, listOf(), listOf(), 0) override fun toString(): String { return name @@ -39,7 +40,8 @@ class ConfigurationMessage(var closedGroups: List, var openGroups: DjbECPrivateKey(encryptionKeyPairAsProto.privateKey.toByteArray())) val members = proto.membersList.map { it.toByteArray().toHexString() } val admins = proto.adminsList.map { it.toByteArray().toHexString() } - return ClosedGroup(publicKey, name, encryptionKeyPair, members, admins) + val expirationTimer = proto.expirationTimer + return ClosedGroup(publicKey, name, encryptionKeyPair, members, admins, expirationTimer) } } @@ -53,6 +55,7 @@ class ConfigurationMessage(var closedGroups: List, var openGroups: result.encryptionKeyPair = encryptionKeyPairAsProto.build() result.addAllMembers(members.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) }) result.addAllAdmins(admins.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) }) + result.expirationTimer = expirationTimer return result.build() } } @@ -110,7 +113,8 @@ class ConfigurationMessage(var closedGroups: List, var openGroups: if (!group.members.contains(Address.fromSerialized(storage.getUserPublicKey()!!))) continue val groupPublicKey = GroupUtil.doubleDecodeGroupID(group.encodedId).toHexString() val encryptionKeyPair = storage.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) ?: continue - val closedGroup = ClosedGroup(groupPublicKey, group.title, encryptionKeyPair, group.members.map { it.serialize() }, group.admins.map { it.serialize() }) + val recipient = Recipient.from(context, Address.fromSerialized(group.encodedId), false) + val closedGroup = ClosedGroup(groupPublicKey, group.title, encryptionKeyPair, group.members.map { it.serialize() }, group.admins.map { it.serialize() }, recipient.expireMessages) closedGroups.add(closedGroup) } if (group.isOpenGroup) { diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index 27bd608f3..cfbd5605b 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -121,7 +121,7 @@ private fun handleConfigurationMessage(message: ConfigurationMessage) { for (closedGroup in message.closedGroups) { if (allClosedGroupPublicKeys.contains(closedGroup.publicKey)) continue handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, closedGroup.publicKey, closedGroup.name, - closedGroup.encryptionKeyPair!!, closedGroup.members, closedGroup.admins, message.sentTimestamp!!, 0) + closedGroup.encryptionKeyPair!!, closedGroup.members, closedGroup.admins, message.sentTimestamp!!, closedGroup.expirationTimer) } val allV2OpenGroups = storage.getAllV2OpenGroups().map { it.value.joinURL } for (openGroup in message.openGroups) { @@ -256,7 +256,7 @@ private fun MessageReceiver.handleNewClosedGroup(message: ClosedGroupControlMess val groupPublicKey = kind.publicKey.toByteArray().toHexString() val members = kind.members.map { it.toByteArray().toHexString() } val admins = kind.admins.map { it.toByteArray().toHexString() } - val expireTimer = kind.expireTimer + val expireTimer = kind.expirationTimer handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, groupPublicKey, kind.name, kind.encryptionKeyPair!!, members, admins, message.sentTimestamp!!, expireTimer) } diff --git a/libsignal/protobuf/SignalService.proto b/libsignal/protobuf/SignalService.proto index 7c44fce22..7ee8dc994 100644 --- a/libsignal/protobuf/SignalService.proto +++ b/libsignal/protobuf/SignalService.proto @@ -135,7 +135,7 @@ message DataMessage { repeated bytes members = 5; repeated bytes admins = 6; repeated KeyPairWrapper wrappers = 7; - optional uint32 expireTimer = 8; + optional uint32 expirationTimer = 8; } optional string body = 1; @@ -161,6 +161,7 @@ message ConfigurationMessage { optional KeyPair encryptionKeyPair = 3; repeated bytes members = 4; repeated bytes admins = 5; + optional uint32 expirationTimer = 6; } message Contact { diff --git a/libsignal/src/main/java/org/session/libsignal/protos/SignalServiceProtos.java b/libsignal/src/main/java/org/session/libsignal/protos/SignalServiceProtos.java index 8f7921dcb..0ca46d3a9 100644 --- a/libsignal/src/main/java/org/session/libsignal/protos/SignalServiceProtos.java +++ b/libsignal/src/main/java/org/session/libsignal/protos/SignalServiceProtos.java @@ -9222,15 +9222,15 @@ public final class SignalServiceProtos { org.session.libsignal.protos.SignalServiceProtos.DataMessage.ClosedGroupControlMessage.KeyPairWrapperOrBuilder getWrappersOrBuilder( int index); - // optional uint32 expireTimer = 8; + // optional uint32 expirationTimer = 8; /** - * optional uint32 expireTimer = 8; + * optional uint32 expirationTimer = 8; */ - boolean hasExpireTimer(); + boolean hasExpirationTimer(); /** - * optional uint32 expireTimer = 8; + * optional uint32 expirationTimer = 8; */ - int getExpireTimer(); + int getExpirationTimer(); } /** * Protobuf type {@code signalservice.DataMessage.ClosedGroupControlMessage} @@ -9343,7 +9343,7 @@ public final class SignalServiceProtos { } case 64: { bitField0_ |= 0x00000010; - expireTimer_ = input.readUInt32(); + expirationTimer_ = input.readUInt32(); break; } } @@ -10303,20 +10303,20 @@ public final class SignalServiceProtos { return wrappers_.get(index); } - // optional uint32 expireTimer = 8; - public static final int EXPIRETIMER_FIELD_NUMBER = 8; - private int expireTimer_; + // optional uint32 expirationTimer = 8; + public static final int EXPIRATIONTIMER_FIELD_NUMBER = 8; + private int expirationTimer_; /** - * optional uint32 expireTimer = 8; + * optional uint32 expirationTimer = 8; */ - public boolean hasExpireTimer() { + public boolean hasExpirationTimer() { return ((bitField0_ & 0x00000010) == 0x00000010); } /** - * optional uint32 expireTimer = 8; + * optional uint32 expirationTimer = 8; */ - public int getExpireTimer() { - return expireTimer_; + public int getExpirationTimer() { + return expirationTimer_; } private void initFields() { @@ -10327,7 +10327,7 @@ public final class SignalServiceProtos { members_ = java.util.Collections.emptyList(); admins_ = java.util.Collections.emptyList(); wrappers_ = java.util.Collections.emptyList(); - expireTimer_ = 0; + expirationTimer_ = 0; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -10379,7 +10379,7 @@ public final class SignalServiceProtos { output.writeMessage(7, wrappers_.get(i)); } if (((bitField0_ & 0x00000010) == 0x00000010)) { - output.writeUInt32(8, expireTimer_); + output.writeUInt32(8, expirationTimer_); } getUnknownFields().writeTo(output); } @@ -10430,7 +10430,7 @@ public final class SignalServiceProtos { } if (((bitField0_ & 0x00000010) == 0x00000010)) { size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(8, expireTimer_); + .computeUInt32Size(8, expirationTimer_); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; @@ -10572,7 +10572,7 @@ public final class SignalServiceProtos { } else { wrappersBuilder_.clear(); } - expireTimer_ = 0; + expirationTimer_ = 0; bitField0_ = (bitField0_ & ~0x00000080); return this; } @@ -10644,7 +10644,7 @@ public final class SignalServiceProtos { if (((from_bitField0_ & 0x00000080) == 0x00000080)) { to_bitField0_ |= 0x00000010; } - result.expireTimer_ = expireTimer_; + result.expirationTimer_ = expirationTimer_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -10721,8 +10721,8 @@ public final class SignalServiceProtos { } } } - if (other.hasExpireTimer()) { - setExpireTimer(other.getExpireTimer()); + if (other.hasExpirationTimer()) { + setExpirationTimer(other.getExpirationTimer()); } this.mergeUnknownFields(other.getUnknownFields()); return this; @@ -11430,35 +11430,35 @@ public final class SignalServiceProtos { return wrappersBuilder_; } - // optional uint32 expireTimer = 8; - private int expireTimer_ ; + // optional uint32 expirationTimer = 8; + private int expirationTimer_ ; /** - * optional uint32 expireTimer = 8; + * optional uint32 expirationTimer = 8; */ - public boolean hasExpireTimer() { + public boolean hasExpirationTimer() { return ((bitField0_ & 0x00000080) == 0x00000080); } /** - * optional uint32 expireTimer = 8; + * optional uint32 expirationTimer = 8; */ - public int getExpireTimer() { - return expireTimer_; + public int getExpirationTimer() { + return expirationTimer_; } /** - * optional uint32 expireTimer = 8; + * optional uint32 expirationTimer = 8; */ - public Builder setExpireTimer(int value) { + public Builder setExpirationTimer(int value) { bitField0_ |= 0x00000080; - expireTimer_ = value; + expirationTimer_ = value; onChanged(); return this; } /** - * optional uint32 expireTimer = 8; + * optional uint32 expirationTimer = 8; */ - public Builder clearExpireTimer() { + public Builder clearExpirationTimer() { bitField0_ = (bitField0_ & ~0x00000080); - expireTimer_ = 0; + expirationTimer_ = 0; onChanged(); return this; } @@ -14104,6 +14104,16 @@ public final class SignalServiceProtos { * repeated bytes admins = 5; */ com.google.protobuf.ByteString getAdmins(int index); + + // optional uint32 expirationTimer = 6; + /** + * optional uint32 expirationTimer = 6; + */ + boolean hasExpirationTimer(); + /** + * optional uint32 expirationTimer = 6; + */ + int getExpirationTimer(); } /** * Protobuf type {@code signalservice.ConfigurationMessage.ClosedGroup} @@ -14195,6 +14205,11 @@ public final class SignalServiceProtos { admins_.add(input.readBytes()); break; } + case 48: { + bitField0_ |= 0x00000008; + expirationTimer_ = input.readUInt32(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -14368,12 +14383,29 @@ public final class SignalServiceProtos { return admins_.get(index); } + // optional uint32 expirationTimer = 6; + public static final int EXPIRATIONTIMER_FIELD_NUMBER = 6; + private int expirationTimer_; + /** + * optional uint32 expirationTimer = 6; + */ + public boolean hasExpirationTimer() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional uint32 expirationTimer = 6; + */ + public int getExpirationTimer() { + return expirationTimer_; + } + private void initFields() { publicKey_ = com.google.protobuf.ByteString.EMPTY; name_ = ""; encryptionKeyPair_ = org.session.libsignal.protos.SignalServiceProtos.KeyPair.getDefaultInstance(); members_ = java.util.Collections.emptyList(); admins_ = java.util.Collections.emptyList(); + expirationTimer_ = 0; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -14408,6 +14440,9 @@ public final class SignalServiceProtos { for (int i = 0; i < admins_.size(); i++) { output.writeBytes(5, admins_.get(i)); } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + output.writeUInt32(6, expirationTimer_); + } getUnknownFields().writeTo(output); } @@ -14447,6 +14482,10 @@ public final class SignalServiceProtos { size += dataSize; size += 1 * getAdminsList().size(); } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(6, expirationTimer_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -14578,6 +14617,8 @@ public final class SignalServiceProtos { bitField0_ = (bitField0_ & ~0x00000008); admins_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000010); + expirationTimer_ = 0; + bitField0_ = (bitField0_ & ~0x00000020); return this; } @@ -14632,6 +14673,10 @@ public final class SignalServiceProtos { bitField0_ = (bitField0_ & ~0x00000010); } result.admins_ = admins_; + if (((from_bitField0_ & 0x00000020) == 0x00000020)) { + to_bitField0_ |= 0x00000008; + } + result.expirationTimer_ = expirationTimer_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -14679,6 +14724,9 @@ public final class SignalServiceProtos { } onChanged(); } + if (other.hasExpirationTimer()) { + setExpirationTimer(other.getExpirationTimer()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -15083,6 +15131,39 @@ public final class SignalServiceProtos { return this; } + // optional uint32 expirationTimer = 6; + private int expirationTimer_ ; + /** + * optional uint32 expirationTimer = 6; + */ + public boolean hasExpirationTimer() { + return ((bitField0_ & 0x00000020) == 0x00000020); + } + /** + * optional uint32 expirationTimer = 6; + */ + public int getExpirationTimer() { + return expirationTimer_; + } + /** + * optional uint32 expirationTimer = 6; + */ + public Builder setExpirationTimer(int value) { + bitField0_ |= 0x00000020; + expirationTimer_ = value; + onChanged(); + return this; + } + /** + * optional uint32 expirationTimer = 6; + */ + public Builder clearExpirationTimer() { + bitField0_ = (bitField0_ & ~0x00000020); + expirationTimer_ = 0; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:signalservice.ConfigurationMessage.ClosedGroup) } @@ -21289,7 +21370,7 @@ public final class SignalServiceProtos { "fication\022<\n\004type\030\001 \002(\0162..signalservice.D", "ataExtractionNotification.Type\022\021\n\ttimest" + "amp\030\002 \001(\004\"\'\n\004Type\022\016\n\nSCREENSHOT\020\001\022\017\n\013MED" + - "IA_SAVED\020\002\"\241\014\n\013DataMessage\022\014\n\004body\030\001 \001(\t" + + "IA_SAVED\020\002\"\245\014\n\013DataMessage\022\014\n\004body\030\001 \001(\t" + "\0225\n\013attachments\030\002 \003(\0132 .signalservice.At" + "tachmentPointer\022*\n\005group\030\003 \001(\0132\033.signals" + "ervice.GroupContext\022\r\n\005flags\030\004 \001(\r\022\023\n\013ex" + @@ -21314,7 +21395,7 @@ public final class SignalServiceProtos { "\n\005image\030\003 \001(\0132 .signalservice.Attachment" + "Pointer\032:\n\013LokiProfile\022\023\n\013displayName\030\001 " + "\001(\t\022\026\n\016profilePicture\030\002 \001(\t\0320\n\023OpenGroup" + - "Invitation\022\013\n\003url\030\001 \002(\t\022\014\n\004name\030\003 \002(\t\032\370\003" + + "Invitation\022\013\n\003url\030\001 \002(\t\022\014\n\004name\030\003 \002(\t\032\374\003" + "\n\031ClosedGroupControlMessage\022G\n\004type\030\001 \002(" + "\01629.signalservice.DataMessage.ClosedGrou", "pControlMessage.Type\022\021\n\tpublicKey\030\002 \001(\014\022" + @@ -21322,41 +21403,42 @@ public final class SignalServiceProtos { "2\026.signalservice.KeyPair\022\017\n\007members\030\005 \003(" + "\014\022\016\n\006admins\030\006 \003(\014\022U\n\010wrappers\030\007 \003(\0132C.si" + "gnalservice.DataMessage.ClosedGroupContr" + - "olMessage.KeyPairWrapper\022\023\n\013expireTimer\030" + - "\010 \001(\r\032=\n\016KeyPairWrapper\022\021\n\tpublicKey\030\001 \002" + - "(\014\022\030\n\020encryptedKeyPair\030\002 \002(\014\"r\n\004Type\022\007\n\003" + - "NEW\020\001\022\027\n\023ENCRYPTION_KEY_PAIR\020\003\022\017\n\013NAME_C" + - "HANGE\020\004\022\021\n\rMEMBERS_ADDED\020\005\022\023\n\017MEMBERS_RE", - "MOVED\020\006\022\017\n\013MEMBER_LEFT\020\007\"$\n\005Flags\022\033\n\027EXP" + - "IRATION_TIMER_UPDATE\020\002\"\316\003\n\024Configuration" + - "Message\022E\n\014closedGroups\030\001 \003(\0132/.signalse" + - "rvice.ConfigurationMessage.ClosedGroup\022\022" + - "\n\nopenGroups\030\002 \003(\t\022\023\n\013displayName\030\003 \001(\t\022" + - "\026\n\016profilePicture\030\004 \001(\t\022\022\n\nprofileKey\030\005 " + - "\001(\014\022=\n\010contacts\030\006 \003(\0132+.signalservice.Co" + - "nfigurationMessage.Contact\032\202\001\n\013ClosedGro" + - "up\022\021\n\tpublicKey\030\001 \001(\014\022\014\n\004name\030\002 \001(\t\0221\n\021e" + - "ncryptionKeyPair\030\003 \001(\0132\026.signalservice.K", - "eyPair\022\017\n\007members\030\004 \003(\014\022\016\n\006admins\030\005 \003(\014\032" + - "V\n\007Contact\022\021\n\tpublicKey\030\001 \002(\014\022\014\n\004name\030\002 " + - "\002(\t\022\026\n\016profilePicture\030\003 \001(\t\022\022\n\nprofileKe" + - "y\030\004 \001(\014\"u\n\016ReceiptMessage\0220\n\004type\030\001 \002(\0162" + - "\".signalservice.ReceiptMessage.Type\022\021\n\tt" + - "imestamp\030\002 \003(\004\"\036\n\004Type\022\014\n\010DELIVERY\020\000\022\010\n\004" + - "READ\020\001\"\354\001\n\021AttachmentPointer\022\n\n\002id\030\001 \002(\006" + - "\022\023\n\013contentType\030\002 \001(\t\022\013\n\003key\030\003 \001(\014\022\014\n\004si" + - "ze\030\004 \001(\r\022\021\n\tthumbnail\030\005 \001(\014\022\016\n\006digest\030\006 " + - "\001(\014\022\020\n\010fileName\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005", - "width\030\t \001(\r\022\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013" + - " \001(\t\022\013\n\003url\030e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_MESS" + - "AGE\020\001\"\365\001\n\014GroupContext\022\n\n\002id\030\001 \001(\014\022.\n\004ty" + - "pe\030\002 \001(\0162 .signalservice.GroupContext.Ty" + - "pe\022\014\n\004name\030\003 \001(\t\022\017\n\007members\030\004 \003(\t\0220\n\006ava" + - "tar\030\005 \001(\0132 .signalservice.AttachmentPoin" + - "ter\022\016\n\006admins\030\006 \003(\t\"H\n\004Type\022\013\n\007UNKNOWN\020\000" + - "\022\n\n\006UPDATE\020\001\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014R" + - "EQUEST_INFO\020\004B3\n\034org.session.libsignal.p" + - "rotosB\023SignalServiceProtos" + "olMessage.KeyPairWrapper\022\027\n\017expirationTi" + + "mer\030\010 \001(\r\032=\n\016KeyPairWrapper\022\021\n\tpublicKey" + + "\030\001 \002(\014\022\030\n\020encryptedKeyPair\030\002 \002(\014\"r\n\004Type" + + "\022\007\n\003NEW\020\001\022\027\n\023ENCRYPTION_KEY_PAIR\020\003\022\017\n\013NA" + + "ME_CHANGE\020\004\022\021\n\rMEMBERS_ADDED\020\005\022\023\n\017MEMBER", + "S_REMOVED\020\006\022\017\n\013MEMBER_LEFT\020\007\"$\n\005Flags\022\033\n" + + "\027EXPIRATION_TIMER_UPDATE\020\002\"\347\003\n\024Configura" + + "tionMessage\022E\n\014closedGroups\030\001 \003(\0132/.sign" + + "alservice.ConfigurationMessage.ClosedGro" + + "up\022\022\n\nopenGroups\030\002 \003(\t\022\023\n\013displayName\030\003 " + + "\001(\t\022\026\n\016profilePicture\030\004 \001(\t\022\022\n\nprofileKe" + + "y\030\005 \001(\014\022=\n\010contacts\030\006 \003(\0132+.signalservic" + + "e.ConfigurationMessage.Contact\032\233\001\n\013Close" + + "dGroup\022\021\n\tpublicKey\030\001 \001(\014\022\014\n\004name\030\002 \001(\t\022" + + "1\n\021encryptionKeyPair\030\003 \001(\0132\026.signalservi", + "ce.KeyPair\022\017\n\007members\030\004 \003(\014\022\016\n\006admins\030\005 " + + "\003(\014\022\027\n\017expirationTimer\030\006 \001(\r\032V\n\007Contact\022" + + "\021\n\tpublicKey\030\001 \002(\014\022\014\n\004name\030\002 \002(\t\022\026\n\016prof" + + "ilePicture\030\003 \001(\t\022\022\n\nprofileKey\030\004 \001(\014\"u\n\016" + + "ReceiptMessage\0220\n\004type\030\001 \002(\0162\".signalser" + + "vice.ReceiptMessage.Type\022\021\n\ttimestamp\030\002 " + + "\003(\004\"\036\n\004Type\022\014\n\010DELIVERY\020\000\022\010\n\004READ\020\001\"\354\001\n\021" + + "AttachmentPointer\022\n\n\002id\030\001 \002(\006\022\023\n\013content" + + "Type\030\002 \001(\t\022\013\n\003key\030\003 \001(\014\022\014\n\004size\030\004 \001(\r\022\021\n" + + "\tthumbnail\030\005 \001(\014\022\016\n\006digest\030\006 \001(\014\022\020\n\010file", + "Name\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005width\030\t \001(\r" + + "\022\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013 \001(\t\022\013\n\003url" + + "\030e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_MESSAGE\020\001\"\365\001\n\014G" + + "roupContext\022\n\n\002id\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 ." + + "signalservice.GroupContext.Type\022\014\n\004name\030" + + "\003 \001(\t\022\017\n\007members\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 " + + ".signalservice.AttachmentPointer\022\016\n\006admi" + + "ns\030\006 \003(\t\"H\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UPDATE\020" + + "\001\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST_INFO" + + "\020\004B3\n\034org.session.libsignal.protosB\023Sign", + "alServiceProtos" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -21434,7 +21516,7 @@ public final class SignalServiceProtos { internal_static_signalservice_DataMessage_ClosedGroupControlMessage_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_signalservice_DataMessage_ClosedGroupControlMessage_descriptor, - new java.lang.String[] { "Type", "PublicKey", "Name", "EncryptionKeyPair", "Members", "Admins", "Wrappers", "ExpireTimer", }); + new java.lang.String[] { "Type", "PublicKey", "Name", "EncryptionKeyPair", "Members", "Admins", "Wrappers", "ExpirationTimer", }); internal_static_signalservice_DataMessage_ClosedGroupControlMessage_KeyPairWrapper_descriptor = internal_static_signalservice_DataMessage_ClosedGroupControlMessage_descriptor.getNestedTypes().get(0); internal_static_signalservice_DataMessage_ClosedGroupControlMessage_KeyPairWrapper_fieldAccessorTable = new @@ -21452,7 +21534,7 @@ public final class SignalServiceProtos { internal_static_signalservice_ConfigurationMessage_ClosedGroup_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_signalservice_ConfigurationMessage_ClosedGroup_descriptor, - new java.lang.String[] { "PublicKey", "Name", "EncryptionKeyPair", "Members", "Admins", }); + new java.lang.String[] { "PublicKey", "Name", "EncryptionKeyPair", "Members", "Admins", "ExpirationTimer", }); internal_static_signalservice_ConfigurationMessage_Contact_descriptor = internal_static_signalservice_ConfigurationMessage_descriptor.getNestedTypes().get(1); internal_static_signalservice_ConfigurationMessage_Contact_fieldAccessorTable = new