Fix infinite export loop and improve general error handling.

This commit is contained in:
Cody Henthorne
2022-10-18 16:06:37 -04:00
committed by GitHub
parent 0d715d2c18
commit 7fccbd44c0
18 changed files with 155 additions and 30 deletions

View File

@@ -65,6 +65,7 @@ import org.thoughtcrime.securesms.video.EncryptedMediaDataSource;
import org.whispersystems.signalservice.internal.util.JsonUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -204,7 +205,13 @@ public class AttachmentDatabase extends Database {
public @NonNull InputStream getAttachmentStream(AttachmentId attachmentId, long offset)
throws IOException
{
InputStream dataStream = getDataStream(attachmentId, DATA, offset);
InputStream dataStream;
try {
dataStream = getDataStream(attachmentId, DATA, offset);
} catch (FileNotFoundException e) {
throw new IOException("No stream for: " + attachmentId, e);
}
if (dataStream == null) throw new IOException("No stream for: " + attachmentId);
else return dataStream;
@@ -1019,8 +1026,8 @@ public class AttachmentDatabase extends Database {
}
@SuppressWarnings("WeakerAccess")
@VisibleForTesting
protected @Nullable InputStream getDataStream(AttachmentId attachmentId, String dataType, long offset)
private @Nullable InputStream getDataStream(AttachmentId attachmentId, String dataType, long offset)
throws FileNotFoundException
{
DataInfo dataInfo = getAttachmentDataFileInfo(attachmentId, dataType);
@@ -1042,6 +1049,9 @@ public class AttachmentDatabase extends Database {
return stream;
}
} catch (FileNotFoundException e) {
Log.w(TAG, e);
throw e;
} catch (IOException e) {
Log.w(TAG, e);
return null;

View File

@@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.database.documents.Document;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.database.model.MessageExportStatus;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.ParentStoryId;
@@ -398,7 +399,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
}
public int getUnexportedInsecureMessagesCount(long threadId) {
try (Cursor cursor = getWritableDatabase().query(getTableName(), SqlUtil.COUNT, getInsecureMessageClause(threadId) + " AND NOT " + EXPORTED, null, null, null, null)) {
try (Cursor cursor = getWritableDatabase().query(getTableName(), SqlUtil.COUNT, getInsecureMessageClause(threadId) + " AND " + EXPORTED + " < ?", SqlUtil.buildArgs(MessageExportStatus.EXPORTED), null, null, null)) {
if (cursor.moveToFirst()) {
return cursor.getInt(0);
}
@@ -407,6 +408,19 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
return 0;
}
/**
* Reset the exported status (not state) to the default for clearing errors.
*/
public void clearInsecureMessageExportedErrorStatus() {
ContentValues values = new ContentValues(1);
values.put(EXPORTED, MessageExportStatus.UNEXPORTED.getCode());
SQLiteDatabaseExtensionsKt.update(getWritableDatabase(), getTableName())
.values(values)
.where(EXPORTED + " < ?", MessageExportStatus.UNEXPORTED.getCode())
.run();
}
public void setReactionsSeen(long threadId, long sinceTimestamp) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
ContentValues values = new ContentValues();

View File

@@ -52,6 +52,7 @@ import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.database.documents.NetworkFailureSet;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.Mention;
import org.thoughtcrime.securesms.database.model.MessageExportStatus;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
@@ -205,7 +206,8 @@ public class MmsDatabase extends MessageDatabase {
"CREATE INDEX IF NOT EXISTS mms_is_story_index ON " + TABLE_NAME + " (" + STORY_TYPE + ");",
"CREATE INDEX IF NOT EXISTS mms_parent_story_id_index ON " + TABLE_NAME + " (" + PARENT_STORY_ID + ");",
"CREATE INDEX IF NOT EXISTS mms_thread_story_parent_story_index ON " + TABLE_NAME + " (" + THREAD_ID + ", " + DATE_RECEIVED + "," + STORY_TYPE + "," + PARENT_STORY_ID + ");",
"CREATE INDEX IF NOT EXISTS mms_quote_id_quote_author_index ON " + TABLE_NAME + "(" + QUOTE_ID + ", " + QUOTE_AUTHOR + ");"
"CREATE INDEX IF NOT EXISTS mms_quote_id_quote_author_index ON " + TABLE_NAME + "(" + QUOTE_ID + ", " + QUOTE_AUTHOR + ");",
"CREATE INDEX IF NOT EXISTS mms_exported_index ON " + TABLE_NAME + " (" + EXPORTED + ");"
};
private static final String[] MMS_PROJECTION = new String[] {
@@ -2466,13 +2468,13 @@ public class MmsDatabase extends MessageDatabase {
beginTransaction();
try {
List<Long> threadsToUpdate = new LinkedList<>();
try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, THREAD_ID_PROJECTION, EXPORTED + " = ?", SqlUtil.buildArgs(1), THREAD_ID, null, null, null)) {
try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, THREAD_ID_PROJECTION, EXPORTED + " = ?", SqlUtil.buildArgs(MessageExportStatus.EXPORTED), THREAD_ID, null, null, null)) {
while (cursor.moveToNext()) {
threadsToUpdate.add(CursorUtil.requireLong(cursor, THREAD_ID));
}
}
getWritableDatabase().delete(TABLE_NAME, EXPORTED + " = ?", SqlUtil.buildArgs(1));
getWritableDatabase().delete(TABLE_NAME, EXPORTED + " = ?", SqlUtil.buildArgs(MessageExportStatus.EXPORTED));
for (final long threadId : threadsToUpdate) {
SignalDatabase.threads().update(threadId, false);

View File

@@ -35,6 +35,7 @@ import org.signal.core.util.logging.Log;
import org.signal.libsignal.protocol.util.Pair;
import org.thoughtcrime.securesms.database.MessageDatabase.MessageUpdate;
import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.model.MessageExportStatus;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExportState;
@@ -671,7 +672,16 @@ public class MmsSmsDatabase extends Database {
String table = messageId.isMms() ? MmsDatabase.TABLE_NAME : SmsDatabase.TABLE_NAME;
ContentValues contentValues = new ContentValues(1);
contentValues.put(MmsSmsColumns.EXPORTED, 1);
contentValues.put(MmsSmsColumns.EXPORTED, MessageExportStatus.EXPORTED.getCode());
getWritableDatabase().update(table, contentValues, ID_WHERE, SqlUtil.buildArgs(messageId.getId()));
}
public void markMessageExportFailed(@NonNull MessageId messageId) {
String table = messageId.isMms() ? MmsDatabase.TABLE_NAME : SmsDatabase.TABLE_NAME;
ContentValues contentValues = new ContentValues(1);
contentValues.put(MmsSmsColumns.EXPORTED, MessageExportStatus.ERROR.getCode());
getWritableDatabase().update(table, contentValues, ID_WHERE, SqlUtil.buildArgs(messageId.getId()));
}

View File

@@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.database.model.GroupCallUpdateDetailsUtil;
import org.thoughtcrime.securesms.database.model.MessageExportStatus;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.ParentStoryId;
@@ -146,7 +147,8 @@ public class SmsDatabase extends MessageDatabase {
"CREATE INDEX IF NOT EXISTS sms_date_sent_index ON " + TABLE_NAME + " (" + DATE_SENT + ", " + RECIPIENT_ID + ", " + THREAD_ID + ");",
"CREATE INDEX IF NOT EXISTS sms_date_server_index ON " + TABLE_NAME + " (" + DATE_SERVER + ");",
"CREATE INDEX IF NOT EXISTS sms_thread_date_index ON " + TABLE_NAME + " (" + THREAD_ID + ", " + DATE_RECEIVED + ");",
"CREATE INDEX IF NOT EXISTS sms_reactions_unread_index ON " + TABLE_NAME + " (" + REACTIONS_UNREAD + ");"
"CREATE INDEX IF NOT EXISTS sms_reactions_unread_index ON " + TABLE_NAME + " (" + REACTIONS_UNREAD + ");",
"CREATE INDEX IF NOT EXISTS sms_exported_index ON " + TABLE_NAME + " (" + EXPORTED + ");"
};
private static final String[] MESSAGE_PROJECTION = new String[] {
@@ -924,13 +926,13 @@ public class SmsDatabase extends MessageDatabase {
beginTransaction();
try {
List<Long> threadsToUpdate = new LinkedList<>();
try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, THREAD_ID_PROJECTION, EXPORTED + " = ?", SqlUtil.buildArgs(1), THREAD_ID, null, null, null)) {
try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, THREAD_ID_PROJECTION, EXPORTED + " = ?", SqlUtil.buildArgs(MessageExportStatus.EXPORTED), THREAD_ID, null, null, null)) {
while (cursor.moveToNext()) {
threadsToUpdate.add(CursorUtil.requireLong(cursor, THREAD_ID));
}
}
getWritableDatabase().delete(TABLE_NAME, EXPORTED + " = ?", SqlUtil.buildArgs(1));
getWritableDatabase().delete(TABLE_NAME, EXPORTED + " = ?", SqlUtil.buildArgs(MessageExportStatus.EXPORTED));
for (final long threadId : threadsToUpdate) {
SignalDatabase.threads().update(threadId, false);

View File

@@ -14,13 +14,14 @@ import org.thoughtcrime.securesms.database.helpers.migration.V156_RecipientUnreg
import org.thoughtcrime.securesms.database.helpers.migration.V157_RecipeintHiddenMigration
import org.thoughtcrime.securesms.database.helpers.migration.V158_GroupsLastForceUpdateTimestampMigration
import org.thoughtcrime.securesms.database.helpers.migration.V159_ThreadUnreadSelfMentionCount
import org.thoughtcrime.securesms.database.helpers.migration.V160_SmsMmsExportedIndexMigration
/**
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
*/
object SignalDatabaseMigrations {
const val DATABASE_VERSION = 159
const val DATABASE_VERSION = 160
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@@ -67,6 +68,10 @@ object SignalDatabaseMigrations {
if (oldVersion < 159) {
V159_ThreadUnreadSelfMentionCount.migrate(context, db, oldVersion, newVersion)
}
if (oldVersion < 160) {
V160_SmsMmsExportedIndexMigration.migrate(context, db, oldVersion, newVersion)
}
}
@JvmStatic

View File

@@ -0,0 +1,11 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
object V160_SmsMmsExportedIndexMigration : SignalDatabaseMigration {
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("CREATE INDEX IF NOT EXISTS sms_exported_index ON sms (exported)")
db.execSQL("CREATE INDEX IF NOT EXISTS mms_exported_index ON mms (exported)")
}
}

View File

@@ -0,0 +1,32 @@
package org.thoughtcrime.securesms.database.model
import org.signal.core.util.DatabaseId
import org.signal.core.util.IntSerializer
/**
* Export status for a message.
*/
enum class MessageExportStatus(val code: Int) : DatabaseId {
UNEXPORTED(0),
EXPORTED(1),
ERROR(-1);
override fun serialize(): String {
return Serializer.serialize(this).toString()
}
companion object Serializer : IntSerializer<MessageExportStatus> {
override fun serialize(data: MessageExportStatus): Int {
return data.code
}
override fun deserialize(data: Int): MessageExportStatus {
return when (data) {
UNEXPORTED.code -> UNEXPORTED
EXPORTED.code -> EXPORTED
ERROR.code -> ERROR
else -> throw AssertionError("Unknown message export status: $data")
}
}
}
}