|
|
|
|
@@ -77,6 +77,11 @@ import org.thoughtcrime.securesms.crypto.AttachmentSecret
|
|
|
|
|
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream
|
|
|
|
|
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream
|
|
|
|
|
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream
|
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.COPY_PENDING
|
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.FINISHED
|
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.NONE
|
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.PERMANENT_FAILURE
|
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.UPLOAD_IN_PROGRESS
|
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentTable.Companion.DATA_FILE
|
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentTable.Companion.DATA_HASH_END
|
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentTable.Companion.PREUPLOAD_MESSAGE_ID
|
|
|
|
|
@@ -625,6 +630,12 @@ class AttachmentTable(
|
|
|
|
|
.readToSingleLong()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun getMessageDoesNotExpireWithinTimeoutClause(): String {
|
|
|
|
|
val messageHasExpiration = "${MessageTable.TABLE_NAME}.${MessageTable.EXPIRES_IN} > 0"
|
|
|
|
|
val messageExpiresInOneDayAfterViewing = "$messageHasExpiration AND ${MessageTable.TABLE_NAME}.${MessageTable.EXPIRES_IN} < ${1.days.inWholeMilliseconds}"
|
|
|
|
|
return "NOT $messageExpiresInOneDayAfterViewing"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Finds all of the attachmentIds of attachments that need to be uploaded to the archive cdn.
|
|
|
|
|
*/
|
|
|
|
|
@@ -632,7 +643,11 @@ class AttachmentTable(
|
|
|
|
|
return readableDatabase
|
|
|
|
|
.select("$TABLE_NAME.$ID")
|
|
|
|
|
.from("$TABLE_NAME LEFT JOIN ${MessageTable.TABLE_NAME} ON $TABLE_NAME.$MESSAGE_ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}")
|
|
|
|
|
.where("($ARCHIVE_TRANSFER_STATE = ? or $ARCHIVE_TRANSFER_STATE = ?) AND $DATA_FILE NOT NULL AND $TRANSFER_STATE = $TRANSFER_PROGRESS_DONE AND (${MessageTable.STORY_TYPE} = 0 OR ${MessageTable.STORY_TYPE} IS NULL)", ArchiveTransferState.NONE.value, ArchiveTransferState.TEMPORARY_FAILURE.value)
|
|
|
|
|
.where(
|
|
|
|
|
"($ARCHIVE_TRANSFER_STATE = ? or $ARCHIVE_TRANSFER_STATE = ?) AND $DATA_FILE NOT NULL AND $TRANSFER_STATE = $TRANSFER_PROGRESS_DONE AND (${MessageTable.STORY_TYPE} = 0 OR ${MessageTable.STORY_TYPE} IS NULL) AND ${getMessageDoesNotExpireWithinTimeoutClause()}",
|
|
|
|
|
ArchiveTransferState.NONE.value,
|
|
|
|
|
ArchiveTransferState.TEMPORARY_FAILURE.value
|
|
|
|
|
)
|
|
|
|
|
.orderBy("$TABLE_NAME.$ID DESC")
|
|
|
|
|
.run()
|
|
|
|
|
.readToList { AttachmentId(it.requireLong(ID)) }
|
|
|
|
|
@@ -679,7 +694,11 @@ class AttachmentTable(
|
|
|
|
|
fun doAnyAttachmentsNeedArchiveUpload(): Boolean {
|
|
|
|
|
return readableDatabase
|
|
|
|
|
.exists("$TABLE_NAME LEFT JOIN ${MessageTable.TABLE_NAME} ON $TABLE_NAME.$MESSAGE_ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}")
|
|
|
|
|
.where("($ARCHIVE_TRANSFER_STATE = ? OR $ARCHIVE_TRANSFER_STATE = ?) AND $DATA_FILE NOT NULL AND $TRANSFER_STATE = $TRANSFER_PROGRESS_DONE AND (${MessageTable.STORY_TYPE} = 0 OR ${MessageTable.STORY_TYPE} IS NULL)", ArchiveTransferState.NONE.value, ArchiveTransferState.TEMPORARY_FAILURE.value)
|
|
|
|
|
.where(
|
|
|
|
|
"($ARCHIVE_TRANSFER_STATE = ? OR $ARCHIVE_TRANSFER_STATE = ?) AND $DATA_FILE NOT NULL AND $TRANSFER_STATE = $TRANSFER_PROGRESS_DONE AND (${MessageTable.STORY_TYPE} = 0 OR ${MessageTable.STORY_TYPE} IS NULL) AND ${getMessageDoesNotExpireWithinTimeoutClause()}",
|
|
|
|
|
ArchiveTransferState.NONE.value,
|
|
|
|
|
ArchiveTransferState.TEMPORARY_FAILURE.value
|
|
|
|
|
)
|
|
|
|
|
.run()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -836,7 +855,8 @@ class AttachmentTable(
|
|
|
|
|
$DATA_HASH_END NOT NULL AND
|
|
|
|
|
$REMOTE_KEY NOT NULL AND
|
|
|
|
|
$ARCHIVE_TRANSFER_STATE NOT IN (${ArchiveTransferState.FINISHED.value}, ${ArchiveTransferState.PERMANENT_FAILURE.value}) AND
|
|
|
|
|
(${MessageTable.STORY_TYPE} = 0 OR ${MessageTable.STORY_TYPE} IS NULL)
|
|
|
|
|
(${MessageTable.STORY_TYPE} = 0 OR ${MessageTable.STORY_TYPE} IS NULL) AND
|
|
|
|
|
${getMessageDoesNotExpireWithinTimeoutClause()}
|
|
|
|
|
)
|
|
|
|
|
""".trimIndent()
|
|
|
|
|
)
|
|
|
|
|
@@ -1153,6 +1173,7 @@ class AttachmentTable(
|
|
|
|
|
ThumbnailRestoreState.IN_PROGRESS -> {
|
|
|
|
|
"($THUMBNAIL_RESTORE_STATE = ${ThumbnailRestoreState.NEEDS_RESTORE.value} OR $THUMBNAIL_RESTORE_STATE = ${ThumbnailRestoreState.IN_PROGRESS.value}) AND"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else -> ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2336,9 +2357,11 @@ class AttachmentTable(
|
|
|
|
|
hashMatch.hashStart -> {
|
|
|
|
|
Log.i(TAG, "[insertAttachmentWithData] Found that the new attachment hash matches the DATA_HASH_START of ${hashMatch.id}. Using all of it's fields. (MessageId: $messageId, ${attachment.uri})")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hashMatch.hashEnd -> {
|
|
|
|
|
Log.i(TAG, "[insertAttachmentWithData] Found that the new attachment hash matches the DATA_HASH_END of ${hashMatch.id}. Using all of it's fields. (MessageId: $messageId, ${attachment.uri})")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else -> {
|
|
|
|
|
throw IllegalStateException("Should not be possible based on query.")
|
|
|
|
|
}
|
|
|
|
|
@@ -2380,7 +2403,10 @@ class AttachmentTable(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (uploadTemplate != null) {
|
|
|
|
|
Log.i(TAG, "[insertAttachmentWithData] Found a valid template we could use to skip upload. Template: ${uploadTemplate.attachmentId}, TemplateUploadTimestamp: ${hashMatch?.uploadTimestamp}, CurrentTime: ${System.currentTimeMillis()}, InsertingAttachment: (MessageId: $messageId, ${attachment.uri})")
|
|
|
|
|
Log.i(
|
|
|
|
|
TAG,
|
|
|
|
|
"[insertAttachmentWithData] Found a valid template we could use to skip upload. Template: ${uploadTemplate.attachmentId}, TemplateUploadTimestamp: ${hashMatch?.uploadTimestamp}, CurrentTime: ${System.currentTimeMillis()}, InsertingAttachment: (MessageId: $messageId, ${attachment.uri})"
|
|
|
|
|
)
|
|
|
|
|
transformProperties = (uploadTemplate.transformProperties ?: transformProperties).copy(skipTransform = true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2647,11 +2673,19 @@ class AttachmentTable(
|
|
|
|
|
.associate { it to readableDatabase.count().from(TABLE_NAME).where("$ARCHIVE_TRANSFER_STATE = ${it.value} AND $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL").run().readToSingleLong(-1L) }
|
|
|
|
|
|
|
|
|
|
val attachmentFileCount = readableDatabase.query("SELECT COUNT(DISTINCT $DATA_FILE) FROM $TABLE_NAME WHERE $DATA_FILE NOT NULL AND $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL").readToSingleLong(-1L)
|
|
|
|
|
val finishedAttachmentFileCount = readableDatabase.query("SELECT COUNT(DISTINCT $DATA_FILE) FROM $TABLE_NAME WHERE $DATA_FILE NOT NULL AND $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $ARCHIVE_TRANSFER_STATE = ${ArchiveTransferState.FINISHED.value}").readToSingleLong(-1L)
|
|
|
|
|
val attachmentPlaintextHashAndKeyCount = readableDatabase.query("SELECT COUNT(*) FROM (SELECT DISTINCT $DATA_HASH_END, $REMOTE_KEY FROM $TABLE_NAME WHERE $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $TRANSFER_STATE in ($TRANSFER_PROGRESS_DONE, $TRANSFER_RESTORE_OFFLOADED, $TRANSFER_RESTORE_IN_PROGRESS, $TRANSFER_NEEDS_RESTORE))").readToSingleLong(-1L)
|
|
|
|
|
val finishedAttachmentDigestCount = readableDatabase.query("SELECT COUNT(*) FROM (SELECT DISTINCT $DATA_HASH_END, $REMOTE_KEY FROM $TABLE_NAME WHERE $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $ARCHIVE_TRANSFER_STATE = ${ArchiveTransferState.FINISHED.value})").readToSingleLong(-1L)
|
|
|
|
|
val finishedAttachmentFileCount =
|
|
|
|
|
readableDatabase.query("SELECT COUNT(DISTINCT $DATA_FILE) FROM $TABLE_NAME WHERE $DATA_FILE NOT NULL AND $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $ARCHIVE_TRANSFER_STATE = ${ArchiveTransferState.FINISHED.value}")
|
|
|
|
|
.readToSingleLong(-1L)
|
|
|
|
|
val attachmentPlaintextHashAndKeyCount =
|
|
|
|
|
readableDatabase.query("SELECT COUNT(*) FROM (SELECT DISTINCT $DATA_HASH_END, $REMOTE_KEY FROM $TABLE_NAME WHERE $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $TRANSFER_STATE in ($TRANSFER_PROGRESS_DONE, $TRANSFER_RESTORE_OFFLOADED, $TRANSFER_RESTORE_IN_PROGRESS, $TRANSFER_NEEDS_RESTORE))")
|
|
|
|
|
.readToSingleLong(-1L)
|
|
|
|
|
val finishedAttachmentDigestCount =
|
|
|
|
|
readableDatabase.query("SELECT COUNT(*) FROM (SELECT DISTINCT $DATA_HASH_END, $REMOTE_KEY FROM $TABLE_NAME WHERE $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND $ARCHIVE_TRANSFER_STATE = ${ArchiveTransferState.FINISHED.value})")
|
|
|
|
|
.readToSingleLong(-1L)
|
|
|
|
|
val thumbnailFileCount = readableDatabase.query("SELECT COUNT(DISTINCT $THUMBNAIL_FILE) FROM $TABLE_NAME WHERE $THUMBNAIL_FILE IS NOT NULL").readToSingleLong(-1L)
|
|
|
|
|
val estimatedThumbnailCount = readableDatabase.query("SELECT COUNT(*) FROM (SELECT DISTINCT $DATA_HASH_END, $REMOTE_KEY FROM $TABLE_NAME WHERE $ARCHIVE_TRANSFER_STATE = ${ArchiveTransferState.FINISHED.value} AND $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND ($CONTENT_TYPE LIKE 'image/%' OR $CONTENT_TYPE LIKE 'video/%'))").readToSingleLong(-1L)
|
|
|
|
|
val estimatedThumbnailCount =
|
|
|
|
|
readableDatabase.query("SELECT COUNT(*) FROM (SELECT DISTINCT $DATA_HASH_END, $REMOTE_KEY FROM $TABLE_NAME WHERE $ARCHIVE_TRANSFER_STATE = ${ArchiveTransferState.FINISHED.value} AND $DATA_HASH_END NOT NULL AND $REMOTE_KEY NOT NULL AND ($CONTENT_TYPE LIKE 'image/%' OR $CONTENT_TYPE LIKE 'video/%'))")
|
|
|
|
|
.readToSingleLong(-1L)
|
|
|
|
|
|
|
|
|
|
val pendingUploadBytes = getPendingArchiveUploadBytes()
|
|
|
|
|
val uploadedAttachmentBytes = readableDatabase
|
|
|
|
|
|