From fe47a6e958f17aa1c98052b960f87509185f4e78 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Thu, 1 Apr 2021 15:48:35 +1100 Subject: [PATCH] manage duplicates outgoing messages --- .../securesms/database/MmsDatabase.java | 18 +++++++++++++++++ .../securesms/database/SmsDatabase.java | 20 ++++++++++++++++++- .../securesms/jobs/PushDecryptJob.java | 2 +- .../messages/signal/OutgoingTextMessage.java | 10 ++++++++-- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java index 6e8b85a2d..3745735da 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -774,6 +774,11 @@ public class MmsDatabase extends MessagingDatabase { quoteAttachments.addAll(message.getOutgoingQuote().getAttachments()); } + if (isDuplicate(message, threadId)) { + Log.w(TAG, "Ignoring duplicate media message (" + message.getSentTimeMillis() + ")"); + return -1; + } + long messageId = insertMediaMessage(message.getBody(), message.getAttachments(), quoteAttachments, message.getSharedContacts(), message.getLinkPreviews(), contentValues, insertListener); if (message.getRecipient().getAddress().isGroup()) { @@ -945,6 +950,19 @@ public class MmsDatabase extends MessagingDatabase { } } + private boolean isDuplicate(OutgoingMediaMessage 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.getRecipient().getAddress().serialize(), String.valueOf(threadId)}, + null, null, null, "1"); + + try { + return cursor != null && cursor.moveToFirst(); + } finally { + if (cursor != null) cursor.close(); + } + } + public boolean isSent(long messageId) { SQLiteDatabase database = databaseHelper.getReadableDatabase(); try (Cursor cursor = database.query(TABLE_NAME, new String[] { MESSAGE_BOX }, ID + " = ?", new String[] { String.valueOf(messageId)}, null, null, null)) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 300a5c55f..d5c34c5c5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -456,7 +456,7 @@ public class SmsDatabase extends MessagingDatabase { contentValues.put(THREAD_ID, threadId); contentValues.put(BODY, message.getMessageBody()); contentValues.put(DATE_RECEIVED, System.currentTimeMillis()); - contentValues.put(DATE_SENT, date); + contentValues.put(DATE_SENT, message.getSentTimestampMillis()); contentValues.put(READ, 1); contentValues.put(TYPE, type); contentValues.put(SUBSCRIPTION_ID, message.getSubscriptionId()); @@ -464,6 +464,11 @@ public class SmsDatabase extends MessagingDatabase { contentValues.put(DELIVERY_RECEIPT_COUNT, Stream.of(earlyDeliveryReceipts.values()).mapToLong(Long::longValue).sum()); contentValues.put(READ_RECEIPT_COUNT, Stream.of(earlyReadReceipts.values()).mapToLong(Long::longValue).sum()); + if (isDuplicate(message, threadId)) { + Log.w(TAG, "Duplicate message (" + message.getSentTimestampMillis() + "), ignoring..."); + return -1; + } + SQLiteDatabase db = databaseHelper.getWritableDatabase(); long messageId = db.insert(TABLE_NAME, ADDRESS, contentValues); if (insertListener != null) { @@ -530,6 +535,19 @@ public class SmsDatabase extends MessagingDatabase { } } + private boolean isDuplicate(OutgoingTextMessage 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.getRecipient().getAddress().serialize(), String.valueOf(threadId)}, + null, null, null, "1"); + + try { + return cursor != null && cursor.moveToFirst(); + } finally { + if (cursor != null) cursor.close(); + } + } + /*package */void deleteThread(long threadId) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.delete(TABLE_NAME, THREAD_ID + " = ?", new String[] {threadId+""}); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 6ab83939b..ab54cc02e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -471,7 +471,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } OutgoingTextMessage tm = new OutgoingTextMessage(Recipient.from(context, targetAddress, false), - body, message.getExpiresInSeconds(), -1); + body, message.getExpiresInSeconds(), -1, message.getTimestamp()); // Ignore the message if it has no body if (tm.getMessageBody().length() == 0) { return; } diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.java b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.java index 0d3cd92aa..9ebd44891 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.java +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.java @@ -9,16 +9,18 @@ public class OutgoingTextMessage { private final String message; private final int subscriptionId; private final long expiresIn; + private final long sentTimestampMillis; - public OutgoingTextMessage(Recipient recipient, String message, long expiresIn, int subscriptionId) { + public OutgoingTextMessage(Recipient recipient, String message, long expiresIn, int subscriptionId, long sentTimestampMillis) { this.recipient = recipient; this.message = message; this.expiresIn = expiresIn; this.subscriptionId = subscriptionId; + this.sentTimestampMillis = sentTimestampMillis; } public static OutgoingTextMessage from(VisibleMessage message, Recipient recipient) { - return new OutgoingTextMessage(recipient, message.getText(), recipient.getExpireMessages() * 1000, -1); + return new OutgoingTextMessage(recipient, message.getText(), recipient.getExpireMessages() * 1000, -1, message.getSentTimestamp()); } public long getExpiresIn() { @@ -37,6 +39,10 @@ public class OutgoingTextMessage { return recipient; } + public long getSentTimestampMillis() { + return sentTimestampMillis; + } + public boolean isSecureMessage() { return true; }