mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-18 21:10:02 +03:00
Encrypt file WIP
This commit is contained in:
parent
014d03893a
commit
0c2d3f36c3
3 changed files with 91 additions and 26 deletions
|
@ -42,7 +42,7 @@ object MXEncryptedAttachments {
|
||||||
*/
|
*/
|
||||||
data class EncryptionResult(
|
data class EncryptionResult(
|
||||||
var encryptedFileInfo: EncryptedFileInfo,
|
var encryptedFileInfo: EncryptedFileInfo,
|
||||||
var encryptedStream: InputStream
|
var encryptedByteArray: ByteArray
|
||||||
)
|
)
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -112,7 +112,7 @@ object MXEncryptedAttachments {
|
||||||
hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))!!),
|
hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))!!),
|
||||||
v = "v2"
|
v = "v2"
|
||||||
),
|
),
|
||||||
encryptedStream = ByteArrayInputStream(outStream.toByteArray())
|
encryptedByteArray = outStream.toByteArray()
|
||||||
)
|
)
|
||||||
|
|
||||||
outStream.close()
|
outStream.close()
|
||||||
|
|
|
@ -25,13 +25,17 @@ import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.toContent
|
import im.vector.matrix.android.api.session.events.model.toContent
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.message.*
|
import im.vector.matrix.android.api.session.room.model.message.*
|
||||||
|
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileInfo
|
||||||
import im.vector.matrix.android.internal.network.ProgressRequestBody
|
import im.vector.matrix.android.internal.network.ProgressRequestBody
|
||||||
import im.vector.matrix.android.internal.session.room.send.SendEventWorker
|
import im.vector.matrix.android.internal.session.room.send.SendEventWorker
|
||||||
import im.vector.matrix.android.internal.worker.SessionWorkerParams
|
import im.vector.matrix.android.internal.worker.SessionWorkerParams
|
||||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||||
import im.vector.matrix.android.internal.worker.getSessionComponent
|
import im.vector.matrix.android.internal.worker.getSessionComponent
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +46,8 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
|
||||||
override val userId: String,
|
override val userId: String,
|
||||||
val roomId: String,
|
val roomId: String,
|
||||||
val event: Event,
|
val event: Event,
|
||||||
val attachment: ContentAttachmentData
|
val attachment: ContentAttachmentData,
|
||||||
|
val isRoomEncrypted: Boolean
|
||||||
) : SessionWorkerParams
|
) : SessionWorkerParams
|
||||||
|
|
||||||
@Inject lateinit var fileUploader: FileUploader
|
@Inject lateinit var fileUploader: FileUploader
|
||||||
|
@ -58,17 +63,33 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
|
||||||
val eventId = params.event.eventId ?: return Result.success()
|
val eventId = params.event.eventId ?: return Result.success()
|
||||||
val attachment = params.attachment
|
val attachment = params.attachment
|
||||||
|
|
||||||
|
val isRoomEncrypted = params.isRoomEncrypted
|
||||||
|
|
||||||
|
|
||||||
val thumbnailData = ThumbnailExtractor.extractThumbnail(params.attachment)
|
val thumbnailData = ThumbnailExtractor.extractThumbnail(params.attachment)
|
||||||
val attachmentFile = createAttachmentFile(attachment) ?: return Result.failure()
|
val attachmentFile = createAttachmentFile(attachment) ?: return Result.failure()
|
||||||
var uploadedThumbnailUrl: String? = null
|
var uploadedThumbnailUrl: String? = null
|
||||||
|
var uploadedThumbnailEncryptedFileInfo: EncryptedFileInfo? = null
|
||||||
|
|
||||||
if (thumbnailData != null) {
|
if (thumbnailData != null) {
|
||||||
fileUploader
|
if (isRoomEncrypted) {
|
||||||
.uploadByteArray(thumbnailData.bytes, "thumb_${attachment.name}", thumbnailData.mimeType)
|
Timber.v("Encrypt thumbnail")
|
||||||
|
val encryptionResult = MXEncryptedAttachments.encryptAttachment(ByteArrayInputStream(thumbnailData.bytes), thumbnailData.mimeType)
|
||||||
|
?: return Result.failure()
|
||||||
|
|
||||||
|
uploadedThumbnailEncryptedFileInfo = encryptionResult.encryptedFileInfo
|
||||||
|
|
||||||
|
fileUploader
|
||||||
|
.uploadByteArray(encryptionResult.encryptedByteArray, "thumb_${attachment.name}", thumbnailData.mimeType)
|
||||||
|
} else {
|
||||||
|
fileUploader
|
||||||
|
.uploadByteArray(thumbnailData.bytes, "thumb_${attachment.name}", thumbnailData.mimeType)
|
||||||
|
}
|
||||||
.fold(
|
.fold(
|
||||||
{ Timber.e(it) },
|
{ Timber.e(it) },
|
||||||
{ uploadedThumbnailUrl = it.contentUri }
|
{ uploadedThumbnailUrl = it.contentUri }
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val progressListener = object : ProgressRequestBody.Listener {
|
val progressListener = object : ProgressRequestBody.Listener {
|
||||||
|
@ -76,12 +97,28 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
|
||||||
contentUploadStateTracker.setProgress(eventId, current, total)
|
contentUploadStateTracker.setProgress(eventId, current, total)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fileUploader
|
|
||||||
.uploadFile(attachmentFile, attachment.name, attachment.mimeType, progressListener)
|
var uploadedFileEncryptedFileInfo: EncryptedFileInfo? = null
|
||||||
|
|
||||||
|
return if (isRoomEncrypted) {
|
||||||
|
Timber.v("Encrypt file")
|
||||||
|
|
||||||
|
val encryptionResult = MXEncryptedAttachments.encryptAttachment(FileInputStream(attachmentFile), attachment.mimeType)
|
||||||
|
?: return Result.failure()
|
||||||
|
|
||||||
|
uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
|
||||||
|
|
||||||
|
fileUploader
|
||||||
|
.uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, attachment.mimeType, progressListener)
|
||||||
|
} else {
|
||||||
|
fileUploader
|
||||||
|
.uploadFile(attachmentFile, attachment.name, attachment.mimeType, progressListener)
|
||||||
|
}
|
||||||
.fold(
|
.fold(
|
||||||
{ handleFailure(params) },
|
{ handleFailure(params) },
|
||||||
{ handleSuccess(params, it.contentUri, uploadedThumbnailUrl) }
|
{ handleSuccess(params, it.contentUri, uploadedFileEncryptedFileInfo, uploadedThumbnailUrl, uploadedThumbnailEncryptedFileInfo) }
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createAttachmentFile(attachment: ContentAttachmentData): File? {
|
private fun createAttachmentFile(attachment: ContentAttachmentData): File? {
|
||||||
|
@ -100,39 +137,67 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
|
||||||
|
|
||||||
private fun handleSuccess(params: Params,
|
private fun handleSuccess(params: Params,
|
||||||
attachmentUrl: String,
|
attachmentUrl: String,
|
||||||
thumbnailUrl: String?): Result {
|
encryptedFileInfo: EncryptedFileInfo?,
|
||||||
|
thumbnailUrl: String?,
|
||||||
|
thumbnailEncryptedFileInfo: EncryptedFileInfo?): Result {
|
||||||
contentUploadStateTracker.setSuccess(params.event.eventId!!)
|
contentUploadStateTracker.setSuccess(params.event.eventId!!)
|
||||||
val event = updateEvent(params.event, attachmentUrl, thumbnailUrl)
|
val event = updateEvent(params.event, attachmentUrl, encryptedFileInfo, thumbnailUrl, thumbnailEncryptedFileInfo)
|
||||||
val sendParams = SendEventWorker.Params(params.userId, params.roomId, event)
|
val sendParams = SendEventWorker.Params(params.userId, params.roomId, event)
|
||||||
return Result.success(WorkerParamsFactory.toData(sendParams))
|
return Result.success(WorkerParamsFactory.toData(sendParams))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateEvent(event: Event, url: String, thumbnailUrl: String? = null): Event {
|
private fun updateEvent(event: Event,
|
||||||
|
url: String,
|
||||||
|
encryptedFileInfo: EncryptedFileInfo?,
|
||||||
|
thumbnailUrl: String? = null,
|
||||||
|
thumbnailEncryptedFileInfo: EncryptedFileInfo?): Event {
|
||||||
val messageContent: MessageContent = event.content.toModel() ?: return event
|
val messageContent: MessageContent = event.content.toModel() ?: return event
|
||||||
val updatedContent = when (messageContent) {
|
val updatedContent = when (messageContent) {
|
||||||
is MessageImageContent -> messageContent.update(url)
|
is MessageImageContent -> messageContent.update(url, encryptedFileInfo)
|
||||||
is MessageVideoContent -> messageContent.update(url, thumbnailUrl)
|
is MessageVideoContent -> messageContent.update(url, encryptedFileInfo, thumbnailUrl, thumbnailEncryptedFileInfo)
|
||||||
is MessageFileContent -> messageContent.update(url)
|
is MessageFileContent -> messageContent.update(url, encryptedFileInfo)
|
||||||
is MessageAudioContent -> messageContent.update(url)
|
is MessageAudioContent -> messageContent.update(url, encryptedFileInfo)
|
||||||
else -> messageContent
|
else -> messageContent
|
||||||
}
|
}
|
||||||
return event.copy(content = updatedContent.toContent())
|
return event.copy(content = updatedContent.toContent())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MessageImageContent.update(url: String): MessageImageContent {
|
private fun MessageImageContent.update(url: String,
|
||||||
return copy(url = url)
|
encryptedFileInfo: EncryptedFileInfo?): MessageImageContent {
|
||||||
|
return copy(
|
||||||
|
url = url,
|
||||||
|
encryptedFileInfo = encryptedFileInfo
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MessageVideoContent.update(url: String, thumbnailUrl: String?): MessageVideoContent {
|
private fun MessageVideoContent.update(url: String,
|
||||||
return copy(url = url, videoInfo = videoInfo?.copy(thumbnailUrl = thumbnailUrl))
|
encryptedFileInfo: EncryptedFileInfo?,
|
||||||
|
thumbnailUrl: String?,
|
||||||
|
thumbnailEncryptedFileInfo: EncryptedFileInfo?): MessageVideoContent {
|
||||||
|
return copy(
|
||||||
|
url = url,
|
||||||
|
encryptedFileInfo = encryptedFileInfo,
|
||||||
|
videoInfo = videoInfo?.copy(
|
||||||
|
thumbnailUrl = thumbnailUrl,
|
||||||
|
thumbnailFile = thumbnailEncryptedFileInfo
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MessageFileContent.update(url: String): MessageFileContent {
|
private fun MessageFileContent.update(url: String,
|
||||||
return copy(url = url)
|
encryptedFileInfo: EncryptedFileInfo?): MessageFileContent {
|
||||||
|
return copy(
|
||||||
|
url = url,
|
||||||
|
encryptedFileInfo = encryptedFileInfo
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MessageAudioContent.update(url: String): MessageAudioContent {
|
private fun MessageAudioContent.update(url: String,
|
||||||
return copy(url = url)
|
encryptedFileInfo: EncryptedFileInfo?): MessageAudioContent {
|
||||||
|
return copy(
|
||||||
|
url = url,
|
||||||
|
encryptedFileInfo = encryptedFileInfo
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte
|
||||||
val event = localEchoEventFactory.createMediaEvent(roomId, attachment).also {
|
val event = localEchoEventFactory.createMediaEvent(roomId, attachment).also {
|
||||||
saveLocalEcho(it)
|
saveLocalEcho(it)
|
||||||
}
|
}
|
||||||
val uploadWork = createUploadMediaWork(event, attachment)
|
val uploadWork = createUploadMediaWork(event, attachment, cryptoService.isRoomEncrypted(roomId))
|
||||||
val sendWork = createSendEventWork(event)
|
val sendWork = createSendEventWork(event)
|
||||||
|
|
||||||
WorkManager.getInstance(context)
|
WorkManager.getInstance(context)
|
||||||
|
@ -148,8 +148,8 @@ internal class DefaultSendService @Inject constructor(private val context: Conte
|
||||||
return TimelineSendEventWorkCommon.createWork<RedactEventWorker>(redactWorkData)
|
return TimelineSendEventWorkCommon.createWork<RedactEventWorker>(redactWorkData)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createUploadMediaWork(event: Event, attachment: ContentAttachmentData): OneTimeWorkRequest {
|
private fun createUploadMediaWork(event: Event, attachment: ContentAttachmentData, isRoomEncrypted: Boolean): OneTimeWorkRequest {
|
||||||
val uploadMediaWorkerParams = UploadContentWorker.Params(credentials.userId, roomId, event, attachment)
|
val uploadMediaWorkerParams = UploadContentWorker.Params(credentials.userId, roomId, event, attachment, isRoomEncrypted)
|
||||||
val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)
|
val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)
|
||||||
|
|
||||||
return OneTimeWorkRequestBuilder<UploadContentWorker>()
|
return OneTimeWorkRequestBuilder<UploadContentWorker>()
|
||||||
|
|
Loading…
Add table
Reference in a new issue