diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt index a4ef41431d..72c42b03a5 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt @@ -3,8 +3,10 @@ package org.session.libsession.messaging.jobs import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.io.Input import com.esotericsoftware.kryo.io.Output +import nl.komponents.kovenant.Promise import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.file_server.FileServerAPI +import org.session.libsession.messaging.file_server.FileServerAPIV2 import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.open_groups.OpenGroupAPIV2 import org.session.libsession.messaging.sending_receiving.MessageSender @@ -15,6 +17,7 @@ import org.session.libsignal.service.api.messages.SignalServiceAttachmentStream import org.session.libsignal.service.internal.crypto.PaddingInputStream import org.session.libsignal.service.internal.push.PushAttachmentData import org.session.libsignal.service.internal.push.http.AttachmentCipherOutputStreamFactory +import org.session.libsignal.service.internal.push.http.DigestingRequestBody import org.session.libsignal.service.internal.util.Util import org.session.libsignal.service.loki.PlaintextOutputStreamFactory import org.session.libsignal.utilities.logging.Log @@ -45,27 +48,29 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess override fun execute() { try { - val attachment = MessagingModuleConfiguration.shared.messageDataProvider.getScaledSignalAttachmentStream(attachmentID) + val storage = MessagingModuleConfiguration.shared.storage + val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider + val attachment = messageDataProvider.getScaledSignalAttachmentStream(attachmentID) ?: return handleFailure(Error.NoAttachment) - val usePadding = false - val openGroupV2 = MessagingModuleConfiguration.shared.storage.getV2OpenGroup(threadID) - val openGroup = MessagingModuleConfiguration.shared.storage.getOpenGroup(threadID) - val server = openGroupV2?.server ?: openGroup?.server ?: FileServerAPI.shared.server - val shouldEncrypt = (openGroup == null && openGroupV2 == null) // Encrypt if this isn't an open group - val attachmentKey = Util.getSecretBytes(64) - val paddedLength = if (usePadding) PaddingInputStream.getPaddedSize(attachment.length) else attachment.length - val dataStream = if (usePadding) PaddingInputStream(attachment.inputStream, attachment.length) else attachment.inputStream - val ciphertextLength = if (shouldEncrypt) AttachmentCipherOutputStream.getCiphertextLength(paddedLength) else attachment.length - val outputStreamFactory = if (shouldEncrypt) AttachmentCipherOutputStreamFactory(attachmentKey) else PlaintextOutputStreamFactory() - val attachmentData = PushAttachmentData(attachment.contentType, dataStream, ciphertextLength, outputStreamFactory, attachment.listener) - val uploadResult = if (openGroupV2 != null) { - val dataBytes = attachmentData.data.readBytes() - val result = OpenGroupAPIV2.upload(dataBytes, openGroupV2.room, openGroupV2.server).get() - DotNetAPI.UploadResult(result, "${openGroupV2.server}/files/$result", byteArrayOf()) - } else { - FileServerAPI.shared.uploadAttachment(server, attachmentData) + val v2OpenGroup = storage.getV2OpenGroup(threadID) + val v1OpenGroup = storage.getOpenGroup(threadID) + if (v2OpenGroup != null) { + val keyAndResult = upload(attachment, v2OpenGroup.server, false) { + OpenGroupAPIV2.upload(it, v2OpenGroup.room, v2OpenGroup.server) + } + handleSuccess(attachment, keyAndResult.first, keyAndResult.second) + } else if (v1OpenGroup == null) { + val keyAndResult = upload(attachment, FileServerAPIV2.DEFAULT_SERVER, true) { + FileServerAPIV2.upload(it) + } + handleSuccess(attachment, keyAndResult.first, keyAndResult.second) + } else { // V1 open group + val server = v1OpenGroup.server + val pushData = PushAttachmentData(attachment.contentType, attachment.inputStream, + attachment.length, PlaintextOutputStreamFactory(), attachment.listener) + val result = FileServerAPI.shared.uploadAttachment(server, pushData) + handleSuccess(attachment, ByteArray(0), result) } - handleSuccess(attachment, attachmentKey, uploadResult) } catch (e: java.lang.Exception) { if (e == Error.NoAttachment) { this.handlePermanentFailure(e) @@ -77,6 +82,19 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess } } + private fun upload(attachment: SignalServiceAttachmentStream, server: String, encrypt: Boolean, upload: (ByteArray) -> Promise): Pair { + val key = if (encrypt) Util.getSecretBytes(64) else ByteArray(0) + val rawLength = attachment.length + val length = if (encrypt) PaddingInputStream.getPaddedSize(rawLength) else rawLength + val stream = if (encrypt) PaddingInputStream(attachment.inputStream, rawLength) else attachment.inputStream + val ciphertextLength = if (encrypt) AttachmentCipherOutputStream.getCiphertextLength(length) else rawLength + val outputStreamFactory = if (encrypt) AttachmentCipherOutputStreamFactory(key) else PlaintextOutputStreamFactory() + val pushData = PushAttachmentData(attachment.contentType, stream, ciphertextLength, outputStreamFactory, attachment.listener) + val file = DigestingRequestBody(pushData.data, outputStreamFactory, attachment.contentType, pushData.dataSize, attachment.listener) + val id = upload(pushData.data.readBytes()).get() + return Pair(key, DotNetAPI.UploadResult(id, "${server}/files/$id", file.transmittedDigest)) + } + private fun handleSuccess(attachment: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: DotNetAPI.UploadResult) { Log.d(TAG, "Attachment uploaded successfully.") delegate?.handleJobSucceeded(this) diff --git a/libsession/src/main/java/org/session/libsession/utilities/AESGCM.kt b/libsession/src/main/java/org/session/libsession/utilities/AESGCM.kt index f5a170d8bd..102ef8dc1d 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/AESGCM.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/AESGCM.kt @@ -12,16 +12,15 @@ import javax.crypto.spec.SecretKeySpec @WorkerThread internal object AESGCM { - - internal data class EncryptionResult( - internal val ciphertext: ByteArray, - internal val symmetricKey: ByteArray, - internal val ephemeralPublicKey: ByteArray - ) - internal val gcmTagSize = 128 internal val ivSize = 12 + internal data class EncryptionResult( + internal val ciphertext: ByteArray, + internal val symmetricKey: ByteArray, + internal val ephemeralPublicKey: ByteArray + ) + /** * Sync. Don't call from the main thread. */ diff --git a/libsession/src/main/java/org/session/libsession/utilities/mentions/Mention.kt b/libsession/src/main/java/org/session/libsession/utilities/mentions/Mention.kt deleted file mode 100644 index e69de29bb2..0000000000