diff --git a/src/org/thoughtcrime/securesms/GroupCreateActivity.java b/src/org/thoughtcrime/securesms/GroupCreateActivity.java index 9408b45bd2..b35d8f77b9 100644 --- a/src/org/thoughtcrime/securesms/GroupCreateActivity.java +++ b/src/org/thoughtcrime/securesms/GroupCreateActivity.java @@ -72,6 +72,7 @@ import org.whispersystems.signalservice.api.util.InvalidNumberException; import java.io.File; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -246,7 +247,8 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity return; } if (isSignalGroup()) { - new CreateSignalGroupTask(this, avatarBmp, getGroupName(), getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + Recipient local = Recipient.from(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)), false); + new CreateSignalGroupTask(this, avatarBmp, getGroupName(), getAdapter().getRecipients(), Collections.singleton(local)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { new CreateMmsGroupTask(this, getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -254,7 +256,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity private void handleGroupUpdate() { new UpdateSignalGroupTask(this, groupToUpdate.get().id, avatarBmp, - getGroupName(), getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + getGroupName(), getAdapter().getRecipients(), groupToUpdate.get().admins).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } private void handleOpenConversation(long threadId, Recipient recipient) { @@ -344,9 +346,10 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity for (Recipient recipient : members) { memberAddresses.add(recipient.getAddress()); } - memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(activity))); + Address local = Address.fromSerialized(TextSecurePreferences.getLocalNumber(activity)); + memberAddresses.add(local); - String groupId = DatabaseFactory.getGroupDatabase(activity).getOrCreateGroupForMembers(memberAddresses, true); + String groupId = DatabaseFactory.getGroupDatabase(activity).getOrCreateGroupForMembers(memberAddresses, true, Collections.singletonList(local)); Recipient groupRecipient = Recipient.from(activity, Address.fromSerialized(groupId), true); long threadId = DatabaseFactory.getThreadDatabase(activity).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.DEFAULT); @@ -370,16 +373,19 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity protected Bitmap avatar; protected Set members; protected String name; + protected Set admins; public SignalGroupTask(GroupCreateActivity activity, Bitmap avatar, String name, - Set members) + Set members, + Set admins) { this.activity = activity; this.avatar = avatar; this.name = name; this.members = members; + this.admins = admins; } @Override @@ -403,13 +409,13 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity } private static class CreateSignalGroupTask extends SignalGroupTask { - public CreateSignalGroupTask(GroupCreateActivity activity, Bitmap avatar, String name, Set members) { - super(activity, avatar, name, members); + public CreateSignalGroupTask(GroupCreateActivity activity, Bitmap avatar, String name, Set members, Set admins) { + super(activity, avatar, name, members, admins); } @Override protected Optional doInBackground(Void... aVoid) { - return Optional.of(GroupManager.createGroup(activity, members, avatar, name, false)); + return Optional.of(GroupManager.createGroup(activity, members, avatar, name, false, admins)); } @Override @@ -430,16 +436,16 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity private String groupId; public UpdateSignalGroupTask(GroupCreateActivity activity, String groupId, - Bitmap avatar, String name, Set members) + Bitmap avatar, String name, Set members, Set admins) { - super(activity, avatar, name, members); + super(activity, avatar, name, members, admins); this.groupId = groupId; } @Override protected Optional doInBackground(Void... aVoid) { try { - return Optional.of(GroupManager.updateGroup(activity, groupId, members, avatar, name)); + return Optional.of(GroupManager.updateGroup(activity, groupId, members, avatar, name, admins)); } catch (InvalidNumberException e) { return Optional.absent(); } @@ -537,11 +543,17 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity existingContacts.addAll(recipients); if (group.isPresent()) { + List
adminList = group.get().getAdmins(); + final Set admins = new HashSet<>(adminList.size()); + for (Address admin : adminList) { + admins.add(Recipient.from(getContext(), admin, false)); + } return Optional.of(new GroupData(groupIds[0], existingContacts, BitmapUtil.fromByteArray(group.get().getAvatar()), group.get().getAvatar(), - group.get().getTitle())); + group.get().getTitle(), + admins)); } else { return Optional.absent(); } @@ -582,13 +594,15 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity Bitmap avatarBmp; byte[] avatarBytes; String name; + Set admins; - public GroupData(String id, Set recipients, Bitmap avatarBmp, byte[] avatarBytes, String name) { + public GroupData(String id, Set recipients, Bitmap avatarBmp, byte[] avatarBytes, String name, Set admins) { this.id = id; this.recipients = recipients; this.avatarBmp = avatarBmp; this.avatarBytes = avatarBytes; this.name = name; + this.admins = admins; } } } diff --git a/src/org/thoughtcrime/securesms/database/GroupDatabase.java b/src/org/thoughtcrime/securesms/database/GroupDatabase.java index 9d2a815cb7..19108e703e 100644 --- a/src/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/src/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -24,7 +24,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPoin import java.io.Closeable; import java.io.IOException; -import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Collections; import java.util.LinkedList; @@ -52,6 +51,7 @@ public class GroupDatabase extends Database { // Loki private static final String AVATAR_URL = "avatar_url"; + private static final String ADMINS = "admins"; public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + @@ -68,6 +68,7 @@ public class GroupDatabase extends Database { ACTIVE + " INTEGER DEFAULT 1, " + AVATAR_DIGEST + " BLOB, " + AVATAR_URL + " TEXT, " + + ADMINS + "TEXT, " + MMS + " INTEGER DEFAULT 0);"; public static final String[] CREATE_INDEXS = { @@ -76,7 +77,7 @@ public class GroupDatabase extends Database { private static final String[] GROUP_PROJECTION = { GROUP_ID, TITLE, MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST, - TIMESTAMP, ACTIVE, MMS, AVATAR_URL + TIMESTAMP, ACTIVE, MMS, AVATAR_URL, ADMINS }; static final List TYPED_GROUP_PROJECTION = Stream.of(GROUP_PROJECTION).map(columnName -> TABLE_NAME + "." + columnName).toList(); @@ -116,8 +117,9 @@ public class GroupDatabase extends Database { return new Reader(cursor); } - public String getOrCreateGroupForMembers(List
members, boolean mms) { + public String getOrCreateGroupForMembers(List
members, boolean mms, List
admins) { Collections.sort(members); + Collections.sort(admins); Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {GROUP_ID}, MEMBERS + " = ? AND " + MMS + " = ?", @@ -128,7 +130,7 @@ public class GroupDatabase extends Database { return cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID)); } else { String groupId = GroupUtil.getEncodedId(allocateGroupId(), mms); - create(groupId, null, members, null, null); + create(groupId, null, members, null, null, admins); return groupId; } } finally { @@ -157,7 +159,7 @@ public class GroupDatabase extends Database { } public void create(@NonNull String groupId, @Nullable String title, @NonNull List
members, - @Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay) + @Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable List
admins) { Collections.sort(members); @@ -179,6 +181,10 @@ public class GroupDatabase extends Database { contentValues.put(ACTIVE, 1); contentValues.put(MMS, GroupUtil.isMmsGroup(groupId)); + if (admins != null) { + contentValues.put(ADMINS, Address.toSerializedList(admins, ',')); + } + databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues); Recipient.applyCached(Address.fromSerialized(groupId), recipient -> { @@ -260,6 +266,17 @@ public class GroupDatabase extends Database { }); } + public void updateAdmins(String groupId, List
admins) { + Collections.sort(admins); + + ContentValues contents = new ContentValues(); + contents.put(ADMINS, Address.toSerializedList(admins, ',')); + contents.put(ACTIVE, 1); + + databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?", + new String[] {groupId}); + } + public void remove(String groupId, Address source) { List
currentMembers = getCurrentMembers(groupId); currentMembers.remove(source); @@ -351,7 +368,8 @@ public class GroupDatabase extends Database { cursor.getInt(cursor.getColumnIndexOrThrow(ACTIVE)) == 1, cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_DIGEST)), cursor.getInt(cursor.getColumnIndexOrThrow(MMS)) == 1, - cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_URL))); + cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_URL)), + cursor.getString(cursor.getColumnIndexOrThrow(ADMINS))); } @Override @@ -375,10 +393,11 @@ public class GroupDatabase extends Database { private final boolean active; private final boolean mms; private final String url; + private final List
admins; public GroupRecord(String id, String title, String members, byte[] avatar, long avatarId, byte[] avatarKey, String avatarContentType, - String relay, boolean active, byte[] avatarDigest, boolean mms, String url) + String relay, boolean active, byte[] avatarDigest, boolean mms, String url, String admins) { this.id = id; this.title = title; @@ -394,6 +413,9 @@ public class GroupDatabase extends Database { if (!TextUtils.isEmpty(members)) this.members = Address.fromSerializedList(members, ','); else this.members = new LinkedList<>(); + + if (!TextUtils.isEmpty(admins)) this.admins = Address.fromSerializedList(admins, ','); + else this.admins = new LinkedList<>(); } public byte[] getId() { @@ -453,5 +475,7 @@ public class GroupDatabase extends Database { public boolean isRSSFeed() { return Address.fromSerialized(id).isRSSFeed(); } public String getUrl() { return url; } + + public List
getAdmins() { return admins; } } } diff --git a/src/org/thoughtcrime/securesms/database/SmsMigrator.java b/src/org/thoughtcrime/securesms/database/SmsMigrator.java index 071714e1f1..f73acd496f 100644 --- a/src/org/thoughtcrime/securesms/database/SmsMigrator.java +++ b/src/org/thoughtcrime/securesms/database/SmsMigrator.java @@ -220,7 +220,7 @@ public class SmsMigrator { memberAddresses.add(recipient.getAddress()); } - String ourGroupId = DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(memberAddresses, true); + String ourGroupId = DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(memberAddresses, true, null); Recipient ourGroupRecipient = Recipient.from(context, Address.fromSerialized(ourGroupId), true); long ourThreadId = threadDatabase.getThreadIdFor(ourGroupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); diff --git a/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index d0b12cdd42..eab904116e 100644 --- a/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -35,16 +35,19 @@ import org.thoughtcrime.securesms.database.StickerDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob; import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.loki.*; +import org.thoughtcrime.securesms.loki.LokiAPIDatabase; +import org.thoughtcrime.securesms.loki.LokiMessageDatabase; +import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase; +import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase; +import org.thoughtcrime.securesms.loki.LokiThreadDatabase; +import org.thoughtcrime.securesms.loki.LokiUserDatabase; import org.thoughtcrime.securesms.notifications.NotificationChannels; -import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.loki.api.LokiPublicChat; import java.io.File; -import java.security.acl.Group; public class SQLCipherOpenHelper extends SQLiteOpenHelper { @@ -547,6 +550,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { groupUpdate.put("group_id", newId); db.update("groups", groupUpdate,"group_id = ?", new String[] { oldId }); } + + // Add admin field in groups + db.execSQL("ALTER TABLE groups ADD COLUMN admins TEXT"); } db.setTransactionSuccessful(); diff --git a/src/org/thoughtcrime/securesms/groups/GroupManager.java b/src/org/thoughtcrime/securesms/groups/GroupManager.java index 8f5004fbe3..80034d3d80 100644 --- a/src/org/thoughtcrime/securesms/groups/GroupManager.java +++ b/src/org/thoughtcrime/securesms/groups/GroupManager.java @@ -55,11 +55,12 @@ public class GroupManager { @NonNull Set members, @Nullable Bitmap avatar, @Nullable String name, - boolean mms) + boolean mms, + @NonNull Set admins) { GroupDatabase database = DatabaseFactory.getGroupDatabase(context); String id = GroupUtil.getEncodedId(database.allocateGroupId(), mms); - return createGroup(id, context, members, avatar, name, mms); + return createGroup(id, context, members, avatar, name, mms, admins); } public static @NonNull GroupActionResult createGroup(@NonNull String id, @@ -67,21 +68,23 @@ public class GroupManager { @NonNull Set members, @Nullable Bitmap avatar, @Nullable String name, - boolean mms) + boolean mms, + @NonNull Set admins) { final byte[] avatarBytes = BitmapUtil.toByteArray(avatar); final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); final String groupId = GroupUtil.getEncodedId(id.getBytes(), mms); final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false); final Set
memberAddresses = getMemberAddresses(members); + final Set
adminAddresses = getMemberAddresses(admins); memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context))); - groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null); + groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(adminAddresses)); if (!mms) { groupDatabase.updateAvatar(groupId, avatarBytes); DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient, true); - return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes); + return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses); } else { long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); return new GroupActionResult(groupRecipient, threadId); @@ -117,7 +120,7 @@ public class GroupManager { final Set
memberAddresses = new HashSet<>(); memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context))); - groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null); + groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>()); groupDatabase.updateAvatar(groupId, avatarBytes); @@ -129,20 +132,23 @@ public class GroupManager { @NonNull String groupId, @NonNull Set members, @Nullable Bitmap avatar, - @Nullable String name) + @Nullable String name, + @NonNull Set admins) throws InvalidNumberException { final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); final Set
memberAddresses = getMemberAddresses(members); + final Set
adminAddresses = getMemberAddresses(admins); final byte[] avatarBytes = BitmapUtil.toByteArray(avatar); memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context))); groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses)); + groupDatabase.updateAdmins(groupId, new LinkedList<>(adminAddresses)); groupDatabase.updateTitle(groupId, name); groupDatabase.updateAvatar(groupId, avatarBytes); if (!GroupUtil.isMmsGroup(groupId)) { - return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes); + return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses); } else { Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), true); long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); @@ -154,7 +160,8 @@ public class GroupManager { @NonNull String groupId, @NonNull Set
members, @Nullable String groupName, - @Nullable byte[] avatar) + @Nullable byte[] avatar, + @NonNull Set
admins) { try { Attachment avatarAttachment = null; @@ -162,15 +169,20 @@ public class GroupManager { Recipient groupRecipient = Recipient.from(context, groupAddress, false); List numbers = new LinkedList<>(); - for (Address member : members) { numbers.add(member.serialize()); } + List adminNumbers = new LinkedList<>(); + for (Address admin : admins) { + adminNumbers.add(admin.serialize()); + } + GroupContext.Builder groupContextBuilder = GroupContext.newBuilder() .setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId))) .setType(GroupContext.Type.UPDATE) - .addAllMembers(numbers); + .addAllMembers(numbers) + .addAllAdmins(adminNumbers); if (groupName != null) groupContextBuilder.setName(groupName); GroupContext groupContext = groupContextBuilder.build(); diff --git a/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java b/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java index f184231a72..1ff6467a36 100644 --- a/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java +++ b/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java @@ -25,12 +25,15 @@ import org.thoughtcrime.securesms.sms.IncomingGroupMessage; import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.GroupUtil; +import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.libsignal.util.guava.Optional; 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.SignalServiceGroup.Type; +import org.whispersystems.signalservice.loki.api.LokiStorageAPI; +import org.whispersystems.signalservice.loki.utilities.PromiseUtil; import java.util.Collections; import java.util.HashSet; @@ -87,6 +90,7 @@ public class GroupMessageProcessor { SignalServiceAttachment avatar = group.getAvatar().orNull(); List
members = group.getMembers().isPresent() ? new LinkedList
() : null; + List
admins = group.getAdmins().isPresent() ? new LinkedList<>() : null; if (group.getMembers().isPresent()) { for (String member : group.getMembers().get()) { @@ -94,8 +98,22 @@ public class GroupMessageProcessor { } } + // We should only create the group if we are part of the member list + String masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context); + String hexEncodedPublicKey = masterHexEncodedPublicKey != null ? masterHexEncodedPublicKey : TextSecurePreferences.getLocalNumber(context); + if (members == null || !members.contains(Address.fromSerialized(hexEncodedPublicKey))) { + Log.d("Loki - Group Message", "Received a group create message which doesn't include us in the member list. Ignoring."); + return null; + } + + if (group.getAdmins().isPresent()) { + for (String admin : group.getAdmins().get()) { + admins.add(Address.fromExternal(context, admin)); + } + } + database.create(id, group.getName().orNull(), members, - avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null); + avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null, admins); return storeMessage(context, content, group, builder.build(), outgoing); } @@ -110,6 +128,21 @@ public class GroupMessageProcessor { GroupDatabase database = DatabaseFactory.getGroupDatabase(context); String id = GroupUtil.getEncodedId(group); + // Only update group if admin sent the message + if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) { + String sender = content.getSender(); + String hexEncodedPublicKey = sender; + try { + String primaryDevice = PromiseUtil.timeout(LokiStorageAPI.shared.getPrimaryDevicePublicKey(sender), 5000).get(); + if (primaryDevice != null) { hexEncodedPublicKey = primaryDevice; } + } catch (Exception e) { } + + if (!groupRecord.getAdmins().contains(Address.fromSerialized(hexEncodedPublicKey))) { + Log.d("Loki - Group Message", "Received a group update message from a non-admin user for " + id +". Ignoring."); + return null; + } + } + Set
recordMembers = new HashSet<>(groupRecord.getMembers()); Set
messageMembers = new HashSet<>(); @@ -262,6 +295,10 @@ public class GroupMessageProcessor { builder.addAllMembers(group.getMembers().get()); } + if (group.getAdmins().isPresent()) { + builder.addAllAdmins(group.getAdmins().get()); + } + return builder; } diff --git a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java index ac6e206930..47411c08f0 100644 --- a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java @@ -244,7 +244,7 @@ public class MmsDownloadJob extends BaseJob { } if (members.size() > 2) { - group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), true))); + group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), true, new LinkedList<>()))); } IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false, false); diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index 37b4c3ad8f..abe6dd862c 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -267,7 +267,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { GroupContext groupContext = groupMessage.getGroupContext(); SignalServiceAttachment avatar = attachmentPointers.isEmpty() ? null : attachmentPointers.get(0); SignalServiceGroup.Type type = groupMessage.isGroupQuit() ? SignalServiceGroup.Type.QUIT : SignalServiceGroup.Type.UPDATE; - SignalServiceGroup group = new SignalServiceGroup(type, GroupUtil.getDecodedId(groupId), groupType, groupContext.getName(), groupContext.getMembersList(), avatar); + SignalServiceGroup group = new SignalServiceGroup(type, GroupUtil.getDecodedId(groupId), groupType, groupContext.getName(), groupContext.getMembersList(), avatar, groupContext.getAdminsList()); SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder() .withTimestamp(message.getSentTimeMillis()) .withExpiration(message.getRecipient().getExpireMessages()) diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java index d35dd2925f..460b028932 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java @@ -97,15 +97,20 @@ public class PushGroupUpdateJob extends BaseJob implements InjectableType { } List members = new LinkedList<>(); - for (Address member : record.get().getMembers()) { members.add(member.serialize()); } + List admins = new LinkedList<>(); + for (Address admin : record.get().getAdmins()) { + admins.add(admin.serialize()); + } + SignalServiceGroup groupContext = SignalServiceGroup.newBuilder(Type.UPDATE) .withAvatar(avatar) .withId(groupId, SignalServiceGroup.GroupType.SIGNAL) .withMembers(members) + .withAdmins(admins) .withName(record.get().getTitle()) .build(); diff --git a/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt b/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt index 2667838ad8..d2456d86b4 100644 --- a/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt +++ b/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt @@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.DatabaseFactory -import org.thoughtcrime.securesms.database.RecipientDatabase import org.thoughtcrime.securesms.jobs.PushDecryptJob import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob import org.thoughtcrime.securesms.recipients.Recipient @@ -112,7 +111,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki // region Polling private fun getDataMessage(message: LokiPublicChatMessage): SignalServiceDataMessage { val id = group.id.toByteArray() - val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.PUBLIC_CHAT, null, null, null) + val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.PUBLIC_CHAT, null, null, null, null) val quote = if (message.quote != null) { SignalServiceDataMessage.Quote(message.quote!!.quotedMessageTimestamp, SignalServiceAddress(message.quote!!.quoteeHexEncodedPublicKey), message.quote!!.quotedMessageBody, listOf()) } else { diff --git a/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt b/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt index 30d3b7c269..c56f2a224d 100644 --- a/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt +++ b/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt @@ -64,7 +64,7 @@ class LokiRSSFeedPoller(private val context: Context, private val feed: LokiRSSF bodyAsHTML = matcher.replaceAll("$2 ($1)") val body = Html.fromHtml(bodyAsHTML).toString().trim() val id = feed.id.toByteArray() - val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null) + val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null, null) val x2 = SignalServiceDataMessage(timestamp, x1, null, body) val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false) PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.absent())