Ignore duplicate signal messages

Fixes #5579

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2017-01-22 13:52:36 -08:00
parent 47aa7979b2
commit 7e51d61c79
9 changed files with 196 additions and 103 deletions

View File

@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.LRUCache; import org.thoughtcrime.securesms.util.LRUCache;
import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.util.Collections; import java.util.Collections;
@ -78,8 +79,8 @@ public class EncryptingSmsDatabase extends SmsDatabase {
return insertMessageOutbox(threadId, message, type, forceSms, timestamp); return insertMessageOutbox(threadId, message, type, forceSms, timestamp);
} }
public Pair<Long, Long> insertMessageInbox(@NonNull MasterSecretUnion masterSecret, public Optional<InsertResult> insertMessageInbox(@NonNull MasterSecretUnion masterSecret,
@NonNull IncomingTextMessage message) @NonNull IncomingTextMessage message)
{ {
if (masterSecret.getMasterSecret().isPresent()) { if (masterSecret.getMasterSecret().isPresent()) {
return insertMessageInbox(masterSecret.getMasterSecret().get(), message); return insertMessageInbox(masterSecret.getMasterSecret().get(), message);
@ -88,8 +89,8 @@ public class EncryptingSmsDatabase extends SmsDatabase {
} }
} }
private Pair<Long, Long> insertMessageInbox(@NonNull MasterSecret masterSecret, private Optional<InsertResult> insertMessageInbox(@NonNull MasterSecret masterSecret,
@NonNull IncomingTextMessage message) @NonNull IncomingTextMessage message)
{ {
long type = Types.BASE_INBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT; long type = Types.BASE_INBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT;
@ -98,8 +99,8 @@ public class EncryptingSmsDatabase extends SmsDatabase {
return insertMessageInbox(message, type); return insertMessageInbox(message, type);
} }
private Pair<Long, Long> insertMessageInbox(@NonNull AsymmetricMasterSecret masterSecret, private Optional<InsertResult> insertMessageInbox(@NonNull AsymmetricMasterSecret masterSecret,
@NonNull IncomingTextMessage message) @NonNull IncomingTextMessage message)
{ {
long type = Types.BASE_INBOX_TYPE | Types.ENCRYPTION_ASYMMETRIC_BIT; long type = Types.BASE_INBOX_TYPE | Types.ENCRYPTION_ASYMMETRIC_BIT;

View File

@ -235,4 +235,21 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn
} }
} }
public static class InsertResult {
private final long messageId;
private final long threadId;
public InsertResult(long messageId, long threadId) {
this.messageId = messageId;
this.threadId = threadId;
}
public long getMessageId() {
return messageId;
}
public long getThreadId() {
return threadId;
}
}
} }

View File

@ -693,10 +693,10 @@ public class MmsDatabase extends MessagingDatabase {
} }
} }
private Pair<Long, Long> insertMessageInbox(MasterSecretUnion masterSecret, private Optional<InsertResult> insertMessageInbox(MasterSecretUnion masterSecret,
IncomingMediaMessage retrieved, IncomingMediaMessage retrieved,
String contentLocation, String contentLocation,
long threadId, long mailbox) long threadId, long mailbox)
throws MmsException throws MmsException
{ {
if (threadId == -1 || retrieved.isGroupMessage()) { if (threadId == -1 || retrieved.isGroupMessage()) {
@ -729,6 +729,11 @@ public class MmsDatabase extends MessagingDatabase {
contentValues.put(DATE_SENT, contentValues.getAsLong(DATE_RECEIVED)); contentValues.put(DATE_SENT, contentValues.getAsLong(DATE_RECEIVED));
} }
if (retrieved.isPushMessage() && isDuplicate(retrieved, threadId)) {
Log.w(TAG, "Ignoring duplicate media message (" + retrieved.getSentTimeMillis() + ")");
return Optional.absent();
}
long messageId = insertMediaMessage(masterSecret, retrieved.getAddresses(), long messageId = insertMediaMessage(masterSecret, retrieved.getAddresses(),
retrieved.getBody(), retrieved.getAttachments(), retrieved.getBody(), retrieved.getAttachments(),
contentValues); contentValues);
@ -741,12 +746,12 @@ public class MmsDatabase extends MessagingDatabase {
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
jobManager.add(new TrimThreadJob(context, threadId)); jobManager.add(new TrimThreadJob(context, threadId));
return new Pair<>(messageId, threadId); return Optional.of(new InsertResult(messageId, threadId));
} }
public Pair<Long, Long> insertMessageInbox(MasterSecretUnion masterSecret, public Optional<InsertResult> insertMessageInbox(MasterSecretUnion masterSecret,
IncomingMediaMessage retrieved, IncomingMediaMessage retrieved,
String contentLocation, long threadId) String contentLocation, long threadId)
throws MmsException throws MmsException
{ {
long type = Types.BASE_INBOX_TYPE; long type = Types.BASE_INBOX_TYPE;
@ -768,9 +773,9 @@ public class MmsDatabase extends MessagingDatabase {
return insertMessageInbox(masterSecret, retrieved, contentLocation, threadId, type); return insertMessageInbox(masterSecret, retrieved, contentLocation, threadId, type);
} }
public Pair<Long, Long> insertSecureDecryptedMessageInbox(MasterSecretUnion masterSecret, public Optional<InsertResult> insertSecureDecryptedMessageInbox(MasterSecretUnion masterSecret,
IncomingMediaMessage retrieved, IncomingMediaMessage retrieved,
long threadId) long threadId)
throws MmsException throws MmsException
{ {
long type = Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT; long type = Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT;
@ -990,6 +995,20 @@ public class MmsDatabase extends MessagingDatabase {
deleteThreads(singleThreadSet); deleteThreads(singleThreadSet);
} }
private boolean isDuplicate(IncomingMediaMessage message, long threadId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = database.query(TABLE_NAME, null, DATE_SENT + " = ? AND " + ADDRESS + " = ? AND " + THREAD_ID + " = ?",
new String[]{String.valueOf(message.getSentTimeMillis()), message.getAddresses().getFrom(), String.valueOf(threadId)},
null, null, null, "1");
try {
return cursor != null && cursor.moveToFirst();
} finally {
if (cursor != null) cursor.close();
}
}
/*package*/ void deleteThreads(Set<Long> threadIds) { /*package*/ void deleteThreads(Set<Long> threadIds) {
SQLiteDatabase db = databaseHelper.getWritableDatabase(); SQLiteDatabase db = databaseHelper.getWritableDatabase();
String where = ""; String where = "";

View File

@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.JsonUtils;
import org.whispersystems.jobqueue.JobManager; import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.util.InvalidNumberException; import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.IOException; import java.io.IOException;
@ -482,7 +483,7 @@ public class SmsDatabase extends MessagingDatabase {
return new Pair<>(messageId, threadId); return new Pair<>(messageId, threadId);
} }
protected Pair<Long, Long> insertMessageInbox(IncomingTextMessage message, long type) { protected Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long type) {
if (message.isJoined()) { if (message.isJoined()) {
type = (type & (Types.TOTAL_MASK - Types.BASE_TYPE_MASK)) | Types.JOINED_TYPE; type = (type & (Types.TOTAL_MASK - Types.BASE_TYPE_MASK)) | Types.JOINED_TYPE;
} else if (message.isPreKeyBundle()) { } else if (message.isPreKeyBundle()) {
@ -546,24 +547,29 @@ public class SmsDatabase extends MessagingDatabase {
values.put(TYPE, type); values.put(TYPE, type);
values.put(THREAD_ID, threadId); values.put(THREAD_ID, threadId);
SQLiteDatabase db = databaseHelper.getWritableDatabase(); if (message.isPush() && isDuplicate(message, threadId)) {
long messageId = db.insert(TABLE_NAME, null, values); Log.w(TAG, "Duplicate message (" + message.getSentTimestampMillis() + "), ignoring...");
return Optional.absent();
} else {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
long messageId = db.insert(TABLE_NAME, null, values);
if (unread) { if (unread) {
DatabaseFactory.getThreadDatabase(context).setUnread(threadId); DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
}
if (!message.isIdentityUpdate()) {
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
}
notifyConversationListeners(threadId);
jobManager.add(new TrimThreadJob(context, threadId));
return Optional.of(new InsertResult(messageId, threadId));
} }
if (!message.isIdentityUpdate()) {
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
}
notifyConversationListeners(threadId);
jobManager.add(new TrimThreadJob(context, threadId));
return new Pair<>(messageId, threadId);
} }
public Pair<Long, Long> insertMessageInbox(IncomingTextMessage message) { public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message) {
return insertMessageInbox(message, Types.BASE_INBOX_TYPE); return insertMessageInbox(message, Types.BASE_INBOX_TYPE);
} }
@ -653,6 +659,19 @@ public class SmsDatabase extends MessagingDatabase {
return threadDeleted; return threadDeleted;
} }
private boolean isDuplicate(IncomingTextMessage message, long threadId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = database.query(TABLE_NAME, null, DATE_SENT + " = ? AND " + ADDRESS + " = ? AND " + THREAD_ID + " = ?",
new String[]{String.valueOf(message.getSentTimestampMillis()), message.getSender(), String.valueOf(threadId)},
null, null, null, "1");
try {
return cursor != null && cursor.moveToFirst();
} finally {
if (cursor != null) cursor.close();
}
}
/*package */void deleteThread(long threadId) { /*package */void deleteThread(long threadId) {
SQLiteDatabase db = databaseHelper.getWritableDatabase(); SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.delete(TABLE_NAME, THREAD_ID + " = ?", new String[] {threadId+""}); db.delete(TABLE_NAME, THREAD_ID + " = ?", new String[] {threadId+""});
@ -817,4 +836,5 @@ public class SmsDatabase extends MessagingDatabase {
cursor.close(); cursor.close();
} }
} }
} }

View File

@ -5,7 +5,6 @@ import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
@ -15,6 +14,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase; import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob; import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
@ -216,10 +216,14 @@ public class GroupMessageProcessor {
IncomingTextMessage incoming = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(), envelope.getTimestamp(), body, Optional.of(group), 0); IncomingTextMessage incoming = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(), envelope.getTimestamp(), body, Optional.of(group), 0);
IncomingGroupMessage groupMessage = new IncomingGroupMessage(incoming, storage, body); IncomingGroupMessage groupMessage = new IncomingGroupMessage(incoming, storage, body);
Pair<Long, Long> messageAndThreadId = smsDatabase.insertMessageInbox(masterSecret, groupMessage); Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(masterSecret, groupMessage);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
return messageAndThreadId.second; if (insertResult.isPresent()) {
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
return insertResult.get().getThreadId();
} else {
return null;
}
} }
} catch (MmsException e) { } catch (MmsException e) {
Log.w(TAG, e); Log.w(TAG, e);

View File

@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion; import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
import org.thoughtcrime.securesms.database.AttachmentDatabase; import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.ApnUnavailableException; import org.thoughtcrime.securesms.mms.ApnUnavailableException;
@ -194,12 +195,14 @@ public class MmsDownloadJob extends MasterSecretJob {
IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false); IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false);
Optional<InsertResult> insertResult = database.insertMessageInbox(new MasterSecretUnion(masterSecret),
message, contentLocation, threadId);
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(new MasterSecretUnion(masterSecret), if (insertResult.isPresent()) {
message, contentLocation, threadId); database.delete(messageId);
database.delete(messageId); MessageNotifier.updateNotification(context, masterSecret, insertResult.get().getThreadId());
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second); }
} }
private void handleDownloadError(MasterSecret masterSecret, long messageId, long threadId, private void handleDownloadError(MasterSecret masterSecret, long messageId, long threadId,

View File

@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase; import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId; import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException; import org.thoughtcrime.securesms.database.NoSuchMessageException;
@ -196,23 +197,26 @@ public class PushDecryptJob extends ContextJob {
message.getTimestamp(), message.getTimestamp(),
"", Optional.<SignalServiceGroup>absent(), 0); "", Optional.<SignalServiceGroup>absent(), 0);
long threadId; Long threadId;
if (!smsMessageId.isPresent()) { if (!smsMessageId.isPresent()) {
IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage); IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage);
Pair<Long, Long> messageAndThreadId = smsDatabase.insertMessageInbox(masterSecret, incomingEndSessionMessage); Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(masterSecret, incomingEndSessionMessage);
threadId = messageAndThreadId.second; if (insertResult.isPresent()) threadId = insertResult.get().getThreadId();
else threadId = null;
} else { } else {
smsDatabase.markAsEndSession(smsMessageId.get()); smsDatabase.markAsEndSession(smsMessageId.get());
threadId = smsDatabase.getThreadIdForMessage(smsMessageId.get()); threadId = smsDatabase.getThreadIdForMessage(smsMessageId.get());
} }
SessionStore sessionStore = new TextSecureSessionStore(context); if (threadId != null) {
sessionStore.deleteAllSessions(envelope.getSource()); SessionStore sessionStore = new TextSecureSessionStore(context);
sessionStore.deleteAllSessions(envelope.getSource());
SecurityEvent.broadcastSecurityUpdateEvent(context); SecurityEvent.broadcastSecurityUpdateEvent(context);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), threadId); MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), threadId);
}
} }
private void handleGroupMessage(@NonNull MasterSecretUnion masterSecret, private void handleGroupMessage(@NonNull MasterSecretUnion masterSecret,
@ -363,21 +367,24 @@ public class PushDecryptJob extends ContextJob {
handleExpirationUpdate(masterSecret, envelope, message, Optional.<Long>absent()); handleExpirationUpdate(masterSecret, envelope, message, Optional.<Long>absent());
} }
Pair<Long, Long> messageAndThreadId = database.insertSecureDecryptedMessageInbox(masterSecret, mediaMessage, -1); Optional<InsertResult> insertResult = database.insertSecureDecryptedMessageInbox(masterSecret, mediaMessage, -1);
List<DatabaseAttachment> attachments = DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(messageAndThreadId.first);
for (DatabaseAttachment attachment : attachments) { if (insertResult.isPresent()) {
ApplicationContext.getInstance(context) List<DatabaseAttachment> attachments = DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(insertResult.get().getMessageId());
.getJobManager()
.add(new AttachmentDownloadJob(context, messageAndThreadId.first, for (DatabaseAttachment attachment : attachments) {
attachment.getAttachmentId())); ApplicationContext.getInstance(context)
.getJobManager()
.add(new AttachmentDownloadJob(context, insertResult.get().getMessageId(),
attachment.getAttachmentId()));
}
if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
}
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
} }
if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
}
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
} }
private long handleSynchronizeSentExpirationUpdate(@NonNull MasterSecretUnion masterSecret, private long handleSynchronizeSentExpirationUpdate(@NonNull MasterSecretUnion masterSecret,
@ -466,10 +473,10 @@ public class PushDecryptJob extends ContextJob {
handleExpirationUpdate(masterSecret, envelope, message, Optional.<Long>absent()); handleExpirationUpdate(masterSecret, envelope, message, Optional.<Long>absent());
} }
Pair<Long, Long> messageAndThreadId; Long threadId;
if (smsMessageId.isPresent() && !message.getGroupInfo().isPresent()) { if (smsMessageId.isPresent() && !message.getGroupInfo().isPresent()) {
messageAndThreadId = database.updateBundleMessageBody(masterSecret, smsMessageId.get(), body); threadId = database.updateBundleMessageBody(masterSecret, smsMessageId.get(), body).second;
} else { } else {
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(),
envelope.getSourceDevice(), envelope.getSourceDevice(),
@ -478,12 +485,17 @@ public class PushDecryptJob extends ContextJob {
message.getExpiresInSeconds() * 1000); message.getExpiresInSeconds() * 1000);
textMessage = new IncomingEncryptedMessage(textMessage, body); textMessage = new IncomingEncryptedMessage(textMessage, body);
messageAndThreadId = database.insertMessageInbox(masterSecret, textMessage); Optional<InsertResult> insertResult = database.insertMessageInbox(masterSecret, textMessage);
if (insertResult.isPresent()) threadId = insertResult.get().getThreadId();
else threadId = null;
if (smsMessageId.isPresent()) database.deleteMessage(smsMessageId.get()); if (smsMessageId.isPresent()) database.deleteMessage(smsMessageId.get());
} }
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second); if (threadId != null) {
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), threadId);
}
} }
private long handleSynchronizeSentTextMessage(@NonNull MasterSecretUnion masterSecret, private long handleSynchronizeSentTextMessage(@NonNull MasterSecretUnion masterSecret,
@ -527,9 +539,12 @@ public class PushDecryptJob extends ContextJob {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context); EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
if (!smsMessageId.isPresent()) { if (!smsMessageId.isPresent()) {
Pair<Long, Long> messageAndThreadId = insertPlaceholder(envelope); Optional<InsertResult> insertResult = insertPlaceholder(envelope);
smsDatabase.markAsInvalidVersionKeyExchange(messageAndThreadId.first);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second); if (insertResult.isPresent()) {
smsDatabase.markAsInvalidVersionKeyExchange(insertResult.get().getMessageId());
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
}
} else { } else {
smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId.get()); smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId.get());
} }
@ -542,9 +557,12 @@ public class PushDecryptJob extends ContextJob {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context); EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
if (!smsMessageId.isPresent()) { if (!smsMessageId.isPresent()) {
Pair<Long, Long> messageAndThreadId = insertPlaceholder(envelope); Optional<InsertResult> insertResult = insertPlaceholder(envelope);
smsDatabase.markAsDecryptFailed(messageAndThreadId.first);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second); if (insertResult.isPresent()) {
smsDatabase.markAsDecryptFailed(insertResult.get().getMessageId());
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
}
} else { } else {
smsDatabase.markAsDecryptFailed(smsMessageId.get()); smsDatabase.markAsDecryptFailed(smsMessageId.get());
} }
@ -557,9 +575,12 @@ public class PushDecryptJob extends ContextJob {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context); EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
if (!smsMessageId.isPresent()) { if (!smsMessageId.isPresent()) {
Pair<Long, Long> messageAndThreadId = insertPlaceholder(envelope); Optional<InsertResult> insertResult = insertPlaceholder(envelope);
smsDatabase.markAsNoSession(messageAndThreadId.first);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second); if (insertResult.isPresent()) {
smsDatabase.markAsNoSession(insertResult.get().getMessageId());
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
}
} else { } else {
smsDatabase.markAsNoSession(smsMessageId.get()); smsDatabase.markAsNoSession(smsMessageId.get());
} }
@ -572,9 +593,12 @@ public class PushDecryptJob extends ContextJob {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context); EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
if (!smsMessageId.isPresent()) { if (!smsMessageId.isPresent()) {
Pair<Long, Long> messageAndThreadId = insertPlaceholder(envelope); Optional<InsertResult> insertResult = insertPlaceholder(envelope);
smsDatabase.markAsLegacyVersion(messageAndThreadId.first);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second); if (insertResult.isPresent()) {
smsDatabase.markAsLegacyVersion(insertResult.get().getMessageId());
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
}
} else { } else {
smsDatabase.markAsLegacyVersion(smsMessageId.get()); smsDatabase.markAsLegacyVersion(smsMessageId.get());
} }
@ -613,11 +637,13 @@ public class PushDecryptJob extends ContextJob {
Optional.<SignalServiceGroup>absent(), 0); Optional.<SignalServiceGroup>absent(), 0);
if (!smsMessageId.isPresent()) { if (!smsMessageId.isPresent()) {
IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded); IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded);
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, bundleMessage); Optional<InsertResult> insertResult = database.insertMessageInbox(masterSecret, bundleMessage);
database.setMismatchedIdentity(messageAndThreadId.first, recipientId, identityKey); if (insertResult.isPresent()) {
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second); database.setMismatchedIdentity(insertResult.get().getMessageId(), recipientId, identityKey);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
}
} else { } else {
database.updateMessageBody(masterSecret, smsMessageId.get(), encoded); database.updateMessageBody(masterSecret, smsMessageId.get(), encoded);
database.markAsPreKeyBundle(smsMessageId.get()); database.markAsPreKeyBundle(smsMessageId.get());
@ -628,7 +654,7 @@ public class PushDecryptJob extends ContextJob {
} }
} }
private Pair<Long, Long> insertPlaceholder(@NonNull SignalServiceEnvelope envelope) { private Optional<InsertResult> insertPlaceholder(@NonNull SignalServiceEnvelope envelope) {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context); EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(), IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(),
envelope.getTimestamp(), "", envelope.getTimestamp(), "",

View File

@ -3,13 +3,13 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context; import android.content.Context;
import android.telephony.SmsMessage; import android.telephony.SmsMessage;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion; import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase; import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
@ -57,8 +57,11 @@ public class SmsReceiveJob extends ContextJob {
} }
if (message.isPresent() && !isBlocked(message.get())) { if (message.isPresent() && !isBlocked(message.get())) {
Pair<Long, Long> messageAndThreadId = storeMessage(masterSecretUnion, message.get()); Optional<InsertResult> insertResult = storeMessage(masterSecretUnion, message.get());
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
if (insertResult.isPresent()) {
MessageNotifier.updateNotification(context, masterSecret, insertResult.get().getThreadId());
}
} else if (message.isPresent()) { } else if (message.isPresent()) {
Log.w(TAG, "*** Received blocked SMS, ignoring..."); Log.w(TAG, "*** Received blocked SMS, ignoring...");
} }
@ -83,20 +86,18 @@ public class SmsReceiveJob extends ContextJob {
return false; return false;
} }
private Pair<Long, Long> storeMessage(MasterSecretUnion masterSecret, IncomingTextMessage message) { private Optional<InsertResult> storeMessage(MasterSecretUnion masterSecret, IncomingTextMessage message) {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context); EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
Pair<Long, Long> messageAndThreadId;
if (message.isSecureMessage()) { if (message.isSecureMessage()) {
IncomingTextMessage placeholder = new IncomingTextMessage(message, ""); IncomingTextMessage placeholder = new IncomingTextMessage(message, "");
messageAndThreadId = database.insertMessageInbox(placeholder); Optional<InsertResult> insertResult = database.insertMessageInbox(placeholder);
database.markAsLegacyVersion(messageAndThreadId.first); database.markAsLegacyVersion(insertResult.get().getMessageId());
} else {
messageAndThreadId = database.insertMessageInbox(masterSecret, message);
}
return messageAndThreadId; return insertResult;
} else {
return database.insertMessageInbox(masterSecret, message);
}
} }
private Optional<IncomingTextMessage> assembleMessageFragments(Object[] pdus, int subscriptionId) { private Optional<IncomingTextMessage> assembleMessageFragments(Object[] pdus, int subscriptionId) {

View File

@ -10,7 +10,6 @@ import android.provider.ContactsContract;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
@ -18,6 +17,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.SessionUtil; import org.thoughtcrime.securesms.crypto.SessionUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.NotInDirectoryException; import org.thoughtcrime.securesms.database.NotInDirectoryException;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.TextSecureDirectory; import org.thoughtcrime.securesms.database.TextSecureDirectory;
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
@ -223,14 +223,16 @@ public class DirectoryHelper {
for (String newUser : newUsers) { for (String newUser : newUsers) {
if (!SessionUtil.hasSession(context, masterSecret, newUser) && !Util.isOwnNumber(context, newUser)) { if (!SessionUtil.hasSession(context, masterSecret, newUser) && !Util.isOwnNumber(context, newUser)) {
IncomingJoinedMessage message = new IncomingJoinedMessage(newUser); IncomingJoinedMessage message = new IncomingJoinedMessage(newUser);
Pair<Long, Long> smsAndThreadId = DatabaseFactory.getSmsDatabase(context).insertMessageInbox(message); Optional<InsertResult> insertResult = DatabaseFactory.getSmsDatabase(context).insertMessageInbox(message);
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); if (insertResult.isPresent()) {
if (hour >= 9 && hour < 23) { int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
MessageNotifier.updateNotification(context, masterSecret, false, smsAndThreadId.second, true); if (hour >= 9 && hour < 23) {
} else { MessageNotifier.updateNotification(context, masterSecret, false, insertResult.get().getThreadId(), true);
MessageNotifier.updateNotification(context, masterSecret, false, smsAndThreadId.second, false); } else {
MessageNotifier.updateNotification(context, masterSecret, false, insertResult.get().getThreadId(), false);
}
} }
} }
} }