mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-26 05:20:16 +00:00
Add support for SN verification
// FREEBIE
This commit is contained in:
@@ -871,14 +871,11 @@ public class DatabaseFactory {
|
||||
if (oldVersion < INTRODUCED_IDENTITY_TIMESTAMP) {
|
||||
db.execSQL("ALTER TABLE identities ADD COLUMN timestamp INTEGER DEFAULT 0");
|
||||
db.execSQL("ALTER TABLE identities ADD COLUMN first_use INTEGER DEFAULT 0");
|
||||
db.execSQL("ALTER TABLE identities ADD COLUMN seen INTEGER DEFAULT 0");
|
||||
db.execSQL("ALTER TABLE identities ADD COLUMN blocking_approval INTEGER DEFAULT 0");
|
||||
db.execSQL("ALTER TABLE identities ADD COLUMN nonblocking_approval INTEGER DEFAULT 0");
|
||||
db.execSQL("ALTER TABLE identities ADD COLuMN verified INTEGER DEFAULT 0");
|
||||
|
||||
db.execSQL("DROP INDEX archived_index");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS archived_count_index ON thread (archived, message_count)");
|
||||
|
||||
db.execSQL("UPDATE identities SET blocking_approval = '1'");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
|
||||
@@ -21,9 +21,10 @@ import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
@@ -35,17 +36,14 @@ public class IdentityDatabase extends Database {
|
||||
|
||||
private static final String TAG = IdentityDatabase.class.getSimpleName();
|
||||
|
||||
private static final Uri CHANGE_URI = Uri.parse("content://textsecure/identities");
|
||||
|
||||
private static final String TABLE_NAME = "identities";
|
||||
private static final String ID = "_id";
|
||||
private static final String RECIPIENT = "recipient";
|
||||
private static final String IDENTITY_KEY = "key";
|
||||
private static final String TIMESTAMP = "timestamp";
|
||||
private static final String FIRST_USE = "first_use";
|
||||
private static final String SEEN = "seen";
|
||||
private static final String BLOCKING_APPROVAL = "blocking_approval";
|
||||
private static final String NONBLOCKING_APPROVAL = "nonblocking_approval";
|
||||
private static final String VERIFIED = "verified";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME +
|
||||
" (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
@@ -53,14 +51,41 @@ public class IdentityDatabase extends Database {
|
||||
IDENTITY_KEY + " TEXT, " +
|
||||
FIRST_USE + " INTEGER DEFAULT 0, " +
|
||||
TIMESTAMP + " INTEGER DEFAULT 0, " +
|
||||
SEEN + " INTEGER DEFAULT 0, " +
|
||||
BLOCKING_APPROVAL + " INTEGER DEFAULT 0, " +
|
||||
VERIFIED + " INTEGER DEFAULT 0, " +
|
||||
NONBLOCKING_APPROVAL + " INTEGER DEFAULT 0);";
|
||||
|
||||
public enum VerifiedStatus {
|
||||
DEFAULT, VERIFIED, UNVERIFIED;
|
||||
|
||||
public int toInt() {
|
||||
if (this == DEFAULT) return 0;
|
||||
else if (this == VERIFIED) return 1;
|
||||
else if (this == UNVERIFIED) return 2;
|
||||
else throw new AssertionError();
|
||||
}
|
||||
|
||||
public static VerifiedStatus forState(int state) {
|
||||
if (state == 0) return DEFAULT;
|
||||
else if (state == 1) return VERIFIED;
|
||||
else if (state == 2) return UNVERIFIED;
|
||||
else throw new AssertionError("No such state: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
IdentityDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
|
||||
public Cursor getIdentities() {
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
return database.query(TABLE_NAME, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public @Nullable IdentityReader readerFor(@Nullable Cursor cursor) {
|
||||
if (cursor == null) return null;
|
||||
return new IdentityReader(cursor);
|
||||
}
|
||||
|
||||
public Optional<IdentityRecord> getIdentity(long recipientId) {
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = null;
|
||||
@@ -70,15 +95,7 @@ public class IdentityDatabase extends Database {
|
||||
new String[] {recipientId + ""}, null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
String serializedIdentity = cursor.getString(cursor.getColumnIndexOrThrow(IDENTITY_KEY));
|
||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
|
||||
long seen = cursor.getLong(cursor.getColumnIndexOrThrow(SEEN));
|
||||
boolean blockingApproval = cursor.getInt(cursor.getColumnIndexOrThrow(BLOCKING_APPROVAL)) == 1;
|
||||
boolean nonblockingApproval = cursor.getInt(cursor.getColumnIndexOrThrow(NONBLOCKING_APPROVAL)) == 1;
|
||||
boolean firstUse = cursor.getInt(cursor.getColumnIndexOrThrow(FIRST_USE)) == 1;
|
||||
IdentityKey identity = new IdentityKey(Base64.decode(serializedIdentity), 0);
|
||||
|
||||
return Optional.of(new IdentityRecord(identity, firstUse, timestamp, seen, blockingApproval, nonblockingApproval));
|
||||
return Optional.of(getIdentityRecord(cursor));
|
||||
}
|
||||
} catch (InvalidKeyException | IOException e) {
|
||||
throw new AssertionError(e);
|
||||
@@ -89,8 +106,8 @@ public class IdentityDatabase extends Database {
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
public void saveIdentity(long recipientId, IdentityKey identityKey, boolean firstUse,
|
||||
long timestamp, boolean blockingApproval, boolean nonBlockingApproval)
|
||||
public void saveIdentity(long recipientId, IdentityKey identityKey, VerifiedStatus verifiedStatus,
|
||||
boolean firstUse, long timestamp, boolean nonBlockingApproval)
|
||||
{
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
String identityKeyString = Base64.encodeBytes(identityKey.serialize());
|
||||
@@ -99,60 +116,74 @@ public class IdentityDatabase extends Database {
|
||||
contentValues.put(RECIPIENT, recipientId);
|
||||
contentValues.put(IDENTITY_KEY, identityKeyString);
|
||||
contentValues.put(TIMESTAMP, timestamp);
|
||||
contentValues.put(BLOCKING_APPROVAL, blockingApproval ? 1 : 0);
|
||||
contentValues.put(VERIFIED, verifiedStatus.toInt());
|
||||
contentValues.put(NONBLOCKING_APPROVAL, nonBlockingApproval ? 1 : 0);
|
||||
contentValues.put(FIRST_USE, firstUse ? 1 : 0);
|
||||
contentValues.put(SEEN, 0);
|
||||
|
||||
database.replace(TABLE_NAME, null, contentValues);
|
||||
|
||||
context.getContentResolver().notifyChange(CHANGE_URI, null);
|
||||
EventBus.getDefault().post(new IdentityRecord(recipientId, identityKey, verifiedStatus,
|
||||
firstUse, timestamp, nonBlockingApproval));
|
||||
}
|
||||
|
||||
public void setApproval(long recipientId, boolean blockingApproval, boolean nonBlockingApproval) {
|
||||
public void setApproval(long recipientId, boolean nonBlockingApproval) {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
|
||||
ContentValues contentValues = new ContentValues(2);
|
||||
contentValues.put(BLOCKING_APPROVAL, blockingApproval);
|
||||
contentValues.put(NONBLOCKING_APPROVAL, nonBlockingApproval);
|
||||
|
||||
database.update(TABLE_NAME, contentValues, RECIPIENT + " = ?",
|
||||
new String[] {String.valueOf(recipientId)});
|
||||
|
||||
context.getContentResolver().notifyChange(CHANGE_URI, null);
|
||||
}
|
||||
|
||||
public void setSeen(long recipientId) {
|
||||
Log.w(TAG, "Setting seen to current time: " + recipientId);
|
||||
public void setVerified(long recipientId, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(SEEN, System.currentTimeMillis());
|
||||
contentValues.put(VERIFIED, verifiedStatus.toInt());
|
||||
|
||||
database.update(TABLE_NAME, contentValues, RECIPIENT + " = ? AND " + SEEN + " = 0",
|
||||
new String[] {String.valueOf(recipientId)});
|
||||
database.update(TABLE_NAME, contentValues, RECIPIENT + " = ? AND " + IDENTITY_KEY + " = ?",
|
||||
new String[] {String.valueOf(recipientId),
|
||||
Base64.encodeBytes(identityKey.serialize())});
|
||||
}
|
||||
|
||||
private IdentityRecord getIdentityRecord(@NonNull Cursor cursor) throws IOException, InvalidKeyException {
|
||||
long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(RECIPIENT));
|
||||
String serializedIdentity = cursor.getString(cursor.getColumnIndexOrThrow(IDENTITY_KEY));
|
||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
|
||||
int verifiedStatus = cursor.getInt(cursor.getColumnIndexOrThrow(VERIFIED));
|
||||
boolean nonblockingApproval = cursor.getInt(cursor.getColumnIndexOrThrow(NONBLOCKING_APPROVAL)) == 1;
|
||||
boolean firstUse = cursor.getInt(cursor.getColumnIndexOrThrow(FIRST_USE)) == 1;
|
||||
IdentityKey identity = new IdentityKey(Base64.decode(serializedIdentity), 0);
|
||||
|
||||
return new IdentityRecord(recipientId, identity, VerifiedStatus.forState(verifiedStatus), firstUse, timestamp, nonblockingApproval);
|
||||
}
|
||||
|
||||
public static class IdentityRecord {
|
||||
|
||||
private final IdentityKey identitykey;
|
||||
private final boolean firstUse;
|
||||
private final long timestamp;
|
||||
private final long seen;
|
||||
private final boolean blockingApproval;
|
||||
private final boolean nonblockingApproval;
|
||||
private final long recipientId;
|
||||
private final IdentityKey identitykey;
|
||||
private final VerifiedStatus verifiedStatus;
|
||||
private final boolean firstUse;
|
||||
private final long timestamp;
|
||||
private final boolean nonblockingApproval;
|
||||
|
||||
private IdentityRecord(IdentityKey identitykey, boolean firstUse, long timestamp,
|
||||
long seen, boolean blockingApproval, boolean nonblockingApproval)
|
||||
private IdentityRecord(long recipientId,
|
||||
IdentityKey identitykey, VerifiedStatus verifiedStatus,
|
||||
boolean firstUse, long timestamp, boolean nonblockingApproval)
|
||||
{
|
||||
this.recipientId = recipientId;
|
||||
this.identitykey = identitykey;
|
||||
this.verifiedStatus = verifiedStatus;
|
||||
this.firstUse = firstUse;
|
||||
this.timestamp = timestamp;
|
||||
this.seen = seen;
|
||||
this.blockingApproval = blockingApproval;
|
||||
this.nonblockingApproval = nonblockingApproval;
|
||||
}
|
||||
|
||||
public long getRecipientId() {
|
||||
return recipientId;
|
||||
}
|
||||
|
||||
public IdentityKey getIdentityKey() {
|
||||
return identitykey;
|
||||
}
|
||||
@@ -161,12 +192,8 @@ public class IdentityDatabase extends Database {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public long getSeen() {
|
||||
return seen;
|
||||
}
|
||||
|
||||
public boolean isApprovedBlocking() {
|
||||
return blockingApproval;
|
||||
public VerifiedStatus getVerifiedStatus() {
|
||||
return verifiedStatus;
|
||||
}
|
||||
|
||||
public boolean isApprovedNonBlocking() {
|
||||
@@ -177,6 +204,35 @@ public class IdentityDatabase extends Database {
|
||||
return firstUse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{recipientId: " + recipientId + ", identityKey: " + identitykey + ", verifiedStatus: " + verifiedStatus + ", firstUse: " + firstUse + "}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class IdentityReader {
|
||||
private final Cursor cursor;
|
||||
|
||||
public IdentityReader(@NonNull Cursor cursor) {
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
public @Nullable IdentityRecord getNext() {
|
||||
if (cursor.moveToNext()) {
|
||||
try {
|
||||
return getIdentityRecord(cursor);
|
||||
} catch (IOException | InvalidKeyException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,15 +50,15 @@ public interface MmsSmsColumns {
|
||||
protected static final long MESSAGE_FORCE_SMS_BIT = 0x40;
|
||||
|
||||
// Key Exchange Information
|
||||
protected static final long KEY_EXCHANGE_MASK = 0xFF00;
|
||||
protected static final long KEY_EXCHANGE_BIT = 0x8000;
|
||||
protected static final long KEY_EXCHANGE_STALE_BIT = 0x4000;
|
||||
protected static final long KEY_EXCHANGE_PROCESSED_BIT = 0x2000;
|
||||
protected static final long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000;
|
||||
protected static final long KEY_EXCHANGE_INVALID_VERSION_BIT = 0x800;
|
||||
protected static final long KEY_EXCHANGE_BUNDLE_BIT = 0x400;
|
||||
protected static final long KEY_EXCHANGE_IDENTITY_UPDATE_BIT = 0x200;
|
||||
protected static final long KEY_EXCHANGE_CONTENT_FORMAT = 0x100;
|
||||
protected static final long KEY_EXCHANGE_MASK = 0xFF00;
|
||||
protected static final long KEY_EXCHANGE_BIT = 0x8000;
|
||||
protected static final long KEY_EXCHANGE_IDENTITY_VERIFIED_BIT = 0x4000;
|
||||
protected static final long KEY_EXCHANGE_IDENTITY_DEFAULT_BIT = 0x2000;
|
||||
protected static final long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000;
|
||||
protected static final long KEY_EXCHANGE_INVALID_VERSION_BIT = 0x800;
|
||||
protected static final long KEY_EXCHANGE_BUNDLE_BIT = 0x400;
|
||||
protected static final long KEY_EXCHANGE_IDENTITY_UPDATE_BIT = 0x200;
|
||||
protected static final long KEY_EXCHANGE_CONTENT_FORMAT = 0x100;
|
||||
|
||||
// Secure Message Information
|
||||
protected static final long SECURE_MESSAGE_BIT = 0x800000;
|
||||
@@ -112,7 +112,7 @@ public interface MmsSmsColumns {
|
||||
public static boolean isPendingMessageType(long type) {
|
||||
return
|
||||
(type & BASE_TYPE_MASK) == BASE_OUTBOX_TYPE ||
|
||||
(type & BASE_TYPE_MASK) == BASE_SENDING_TYPE;
|
||||
(type & BASE_TYPE_MASK) == BASE_SENDING_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isPendingSmsFallbackType(long type) {
|
||||
@@ -152,12 +152,12 @@ public interface MmsSmsColumns {
|
||||
return (type & KEY_EXCHANGE_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isStaleKeyExchange(long type) {
|
||||
return (type & KEY_EXCHANGE_STALE_BIT) != 0;
|
||||
public static boolean isIdentityVerified(long type) {
|
||||
return (type & KEY_EXCHANGE_IDENTITY_VERIFIED_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isProcessedKeyExchange(long type) {
|
||||
return (type & KEY_EXCHANGE_PROCESSED_BIT) != 0;
|
||||
public static boolean isIdentityDefault(long type) {
|
||||
return (type & KEY_EXCHANGE_IDENTITY_DEFAULT_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isCorruptedKeyExchange(long type) {
|
||||
|
||||
@@ -521,6 +521,9 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
if (message.isIdentityUpdate()) type |= Types.KEY_EXCHANGE_IDENTITY_UPDATE_BIT;
|
||||
if (message.isContentPreKeyBundle()) type |= Types.KEY_EXCHANGE_CONTENT_FORMAT;
|
||||
|
||||
if (message.isIdentityVerified()) type |= Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
|
||||
else if (message.isIdentityDefault()) type |= Types.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT;
|
||||
|
||||
Recipients recipients;
|
||||
|
||||
if (message.getSender() != null) {
|
||||
@@ -540,7 +543,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
|
||||
boolean unread = (org.thoughtcrime.securesms.util.Util.isDefaultSmsProvider(context) ||
|
||||
message.isSecureMessage() || message.isGroup() || message.isPreKeyBundle()) &&
|
||||
!message.isIdentityUpdate();
|
||||
!message.isIdentityUpdate() && !message.isIdentityDefault() && !message.isIdentityVerified();
|
||||
|
||||
long threadId;
|
||||
|
||||
@@ -577,7 +580,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
|
||||
}
|
||||
|
||||
if (!message.isIdentityUpdate()) {
|
||||
if (!message.isIdentityUpdate() && !message.isIdentityVerified() && !message.isIdentityDefault()) {
|
||||
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
|
||||
}
|
||||
|
||||
@@ -605,6 +608,9 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
else if (message.isEndSession()) type |= Types.END_SESSION_BIT;
|
||||
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
|
||||
|
||||
if (message.isIdentityVerified()) type |= Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
|
||||
else if (message.isIdentityDefault()) type |= Types.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT;
|
||||
|
||||
String address = message.getRecipients().getPrimaryRecipient().getNumber();
|
||||
|
||||
ContentValues contentValues = new ContentValues(6);
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package org.thoughtcrime.securesms.database.identity;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class IdentityRecordList {
|
||||
|
||||
private static final String TAG = IdentityRecordList.class.getSimpleName();
|
||||
|
||||
private final List<IdentityRecord> identityRecords = new LinkedList<>();
|
||||
|
||||
public void add(Optional<IdentityRecord> identityRecord) {
|
||||
if (identityRecord.isPresent()) {
|
||||
identityRecords.add(identityRecord.get());
|
||||
}
|
||||
}
|
||||
|
||||
public void replaceWith(IdentityRecordList identityRecordList) {
|
||||
identityRecords.clear();
|
||||
identityRecords.addAll(identityRecordList.identityRecords);
|
||||
}
|
||||
|
||||
public boolean isVerified() {
|
||||
for (IdentityRecord identityRecord : identityRecords) {
|
||||
if (identityRecord.getVerifiedStatus() != VerifiedStatus.VERIFIED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return identityRecords.size() > 0;
|
||||
}
|
||||
|
||||
public boolean isUnverified() {
|
||||
for (IdentityRecord identityRecord : identityRecords) {
|
||||
if (identityRecord.getVerifiedStatus() == VerifiedStatus.UNVERIFIED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUntrusted() {
|
||||
for (IdentityRecord identityRecord : identityRecords) {
|
||||
if (isUntrusted(identityRecord)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<IdentityRecord> getUntrustedRecords() {
|
||||
List<IdentityRecord> results = new LinkedList<>();
|
||||
|
||||
for (IdentityRecord identityRecord : identityRecords) {
|
||||
if (isUntrusted(identityRecord)) {
|
||||
results.add(identityRecord);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<Recipient> getUntrustedRecipients(Context context) {
|
||||
List<Recipient> untrusted = new LinkedList<>();
|
||||
|
||||
for (IdentityRecord identityRecord : identityRecords) {
|
||||
if (isUntrusted(identityRecord)) {
|
||||
untrusted.add(RecipientFactory.getRecipientForId(context, identityRecord.getRecipientId(), false));
|
||||
}
|
||||
}
|
||||
|
||||
return untrusted;
|
||||
}
|
||||
|
||||
public List<IdentityRecord> getUnverifiedRecords() {
|
||||
List<IdentityRecord> results = new LinkedList<>();
|
||||
|
||||
for (IdentityRecord identityRecord : identityRecords) {
|
||||
if (identityRecord.getVerifiedStatus() == VerifiedStatus.UNVERIFIED) {
|
||||
results.add(identityRecord);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<Recipient> getUnverifiedRecipients(Context context) {
|
||||
List<Recipient> unverified = new LinkedList<>();
|
||||
|
||||
for (IdentityRecord identityRecord : identityRecords) {
|
||||
if (identityRecord.getVerifiedStatus() == VerifiedStatus.UNVERIFIED) {
|
||||
unverified.add(RecipientFactory.getRecipientForId(context, identityRecord.getRecipientId(), false));
|
||||
}
|
||||
}
|
||||
|
||||
return unverified;
|
||||
}
|
||||
|
||||
private boolean isUntrusted(IdentityRecord identityRecord) {
|
||||
return !identityRecord.isApprovedNonBlocking() &&
|
||||
System.currentTimeMillis() - identityRecord.getTimestamp() < TimeUnit.SECONDS.toMillis(5);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -70,7 +70,9 @@ public abstract class DisplayRecord {
|
||||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return MmsSmsColumns.Types.isPendingMessageType(type);
|
||||
return MmsSmsColumns.Types.isPendingMessageType(type) &&
|
||||
!MmsSmsColumns.Types.isIdentityVerified(type) &&
|
||||
!MmsSmsColumns.Types.isIdentityDefault(type);
|
||||
}
|
||||
|
||||
public boolean isOutgoing() {
|
||||
|
||||
@@ -114,6 +114,12 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
: emphasisAdded(context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, getIndividualRecipient().toShortString(), time));
|
||||
} else if (isIdentityUpdate()) {
|
||||
return emphasisAdded(context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, getIndividualRecipient().toShortString()));
|
||||
} else if (isIdentityVerified()) {
|
||||
if (isOutgoing()) return emphasisAdded(context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified, getIndividualRecipient().toShortString()));
|
||||
else return emphasisAdded(context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified_from_another_device, getIndividualRecipient().toShortString()));
|
||||
} else if (isIdentityDefault()) {
|
||||
if (isOutgoing()) return emphasisAdded(context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified, getIndividualRecipient().toShortString()));
|
||||
else return emphasisAdded(context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, getIndividualRecipient().toShortString()));
|
||||
} else if (getBody().getBody().length() > MAX_DISPLAY_LENGTH) {
|
||||
return new SpannableString(getBody().getBody().substring(0, MAX_DISPLAY_LENGTH));
|
||||
}
|
||||
@@ -140,12 +146,12 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return SmsDatabase.Types.isForcedSms(type);
|
||||
}
|
||||
|
||||
public boolean isStaleKeyExchange() {
|
||||
return SmsDatabase.Types.isStaleKeyExchange(type);
|
||||
public boolean isIdentityVerified() {
|
||||
return SmsDatabase.Types.isIdentityVerified(type);
|
||||
}
|
||||
|
||||
public boolean isProcessedKeyExchange() {
|
||||
return SmsDatabase.Types.isProcessedKeyExchange(type);
|
||||
public boolean isIdentityDefault() {
|
||||
return SmsDatabase.Types.isIdentityDefault(type);
|
||||
}
|
||||
|
||||
public boolean isIdentityMismatchFailure() {
|
||||
|
||||
@@ -64,10 +64,6 @@ public class SmsMessageRecord extends MessageRecord {
|
||||
public SpannableString getDisplayBody() {
|
||||
if (SmsDatabase.Types.isFailedDecryptType(type)) {
|
||||
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
|
||||
} else if (isProcessedKeyExchange()) {
|
||||
return new SpannableString("");
|
||||
} else if (isStaleKeyExchange()) {
|
||||
return emphasisAdded(context.getString(R.string.ConversationItem_error_received_stale_key_exchange_message));
|
||||
} else if (isCorruptedKeyExchange()) {
|
||||
return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_corrupted_key_exchange_message));
|
||||
} else if (isInvalidVersionKeyExchange()) {
|
||||
|
||||
@@ -105,6 +105,10 @@ public class ThreadRecord extends DisplayRecord {
|
||||
} else if (SmsDatabase.Types.isIdentityUpdate(type)) {
|
||||
if (getRecipients().isGroupRecipient()) return emphasisAdded(context.getString(R.string.ThreadRecord_safety_number_changed));
|
||||
else return emphasisAdded(context.getString(R.string.ThreadRecord_your_safety_number_with_s_has_changed, getRecipients().getPrimaryRecipient().toShortString()));
|
||||
} else if (SmsDatabase.Types.isIdentityVerified(type)) {
|
||||
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_verified));
|
||||
} else if (SmsDatabase.Types.isIdentityDefault(type)) {
|
||||
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_unverified));
|
||||
} else {
|
||||
if (TextUtils.isEmpty(getBody().getBody())) {
|
||||
return new SpannableString(emphasisAdded(context.getString(R.string.ThreadRecord_media_message)));
|
||||
|
||||
Reference in New Issue
Block a user