feat: hacky workaround for new protobuf encryption branches !
This commit is contained in:
parent
fcb1c56edb
commit
00ad9cf39f
|
@ -82,7 +82,7 @@ Java_network_loki_messenger_libsession_1util_ConfigBase_confirmPushed(JNIEnv *en
|
|||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
JNIEXPORT jint JNICALL
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_merge___3Lkotlin_Pair_2(JNIEnv *env, jobject thiz,
|
||||
jobjectArray to_merge) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
|
@ -94,21 +94,31 @@ Java_network_loki_messenger_libsession_1util_ConfigBase_merge___3Lkotlin_Pair_2(
|
|||
auto pair = extractHashAndData(env, jElement);
|
||||
configs.push_back(pair);
|
||||
}
|
||||
return conf->merge(configs);
|
||||
auto returned = conf->merge(configs);
|
||||
auto string_stack = util::build_string_stack(env, returned);
|
||||
return string_stack;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_merge__Lkotlin_Pair_2(JNIEnv *env, jobject thiz,
|
||||
jobject to_merge) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToConfigBase(env, thiz);
|
||||
std::vector<std::pair<std::string, session::ustring>> configs = {extractHashAndData(env, to_merge)};
|
||||
return conf->merge(configs);
|
||||
auto returned = conf->merge(configs);
|
||||
auto string_stack = util::build_string_stack(env, returned);
|
||||
return string_stack;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_configNamespace(JNIEnv *env, jobject thiz) {
|
||||
auto conf = ptrToConfigBase(env, thiz);
|
||||
return (std::int16_t) conf->storage_namespace();
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jclass JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_00024Companion_kindFor(JNIEnv *env,
|
||||
jobject thiz,
|
||||
|
|
|
@ -186,6 +186,17 @@ namespace util {
|
|||
return group_member;
|
||||
}
|
||||
|
||||
jobject build_string_stack(JNIEnv* env, std::vector<std::string> to_add) {
|
||||
jclass stack_class = env->FindClass("java/util/Stack");
|
||||
jmethodID constructor = env->GetMethodID(stack_class,"<init>", "()V");
|
||||
jmethodID add = env->GetMethodID(stack_class, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
jobject our_stack = env->NewObject(stack_class, constructor);
|
||||
for (std::basic_string_view<char> string: to_add) {
|
||||
env->CallObjectMethod(our_stack, add, env->NewStringUTF(string.data()));
|
||||
}
|
||||
return our_stack;
|
||||
}
|
||||
|
||||
jobject jlongFromOptional(JNIEnv* env, std::optional<long long> optional) {
|
||||
if (!optional) {
|
||||
return nullptr;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define SESSION_ANDROID_UTIL_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <mutex>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include "session/types.hpp"
|
||||
|
@ -12,13 +11,6 @@
|
|||
#include "session/config/profile_pic.hpp"
|
||||
#include "session/config/user_groups.hpp"
|
||||
#include "session/config/expiring.hpp"
|
||||
//#include <android/log.h>
|
||||
|
||||
//#define LOG_TAG "libsession-jni"
|
||||
//#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
//#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
|
||||
//#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
//#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
namespace util {
|
||||
extern std::mutex util_mutex_;
|
||||
|
@ -37,6 +29,7 @@ namespace util {
|
|||
jstring jstringFromOptional(JNIEnv* env, std::optional<std::string_view> optional);
|
||||
jobject serialize_session_id(JNIEnv* env, std::string_view session_id);
|
||||
std::string deserialize_session_id(JNIEnv* env, jobject session_id);
|
||||
jobject build_string_stack(JNIEnv* env, std::vector<std::string> to_add);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -57,11 +57,11 @@ sealed class ConfigBase(pointer: Long): Config(pointer) {
|
|||
external fun dump(): ByteArray
|
||||
external fun encryptionDomain(): String
|
||||
external fun confirmPushed(seqNo: Long, newHash: String)
|
||||
external fun merge(toMerge: Array<Pair<String,ByteArray>>): Int
|
||||
external fun merge(toMerge: Array<Pair<String,ByteArray>>): Stack<String>
|
||||
external fun currentHashes(): List<String>
|
||||
|
||||
// Singular merge
|
||||
external fun merge(toMerge: Pair<String,ByteArray>): Int
|
||||
external fun merge(toMerge: Pair<String,ByteArray>): Stack<String>
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,8 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
|||
handleFailure(Error.NoSender, null)
|
||||
return
|
||||
}
|
||||
if (!threadRecipient.isGroupRecipient && contact?.isTrusted != true && storage.getUserPublicKey() != sender) {
|
||||
|
||||
if (!storage.shouldAutoDownloadAttachments(threadRecipient)) {
|
||||
// if we aren't receiving a group message, a message from ourselves (self-send) and the contact sending is not trusted:
|
||||
// do not continue, but do not fail
|
||||
handleFailure(Error.NoSender, null)
|
||||
|
|
|
@ -8,6 +8,7 @@ import kotlinx.coroutines.runBlocking
|
|||
import nl.komponents.kovenant.Promise
|
||||
import nl.komponents.kovenant.task
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.messages.Destination
|
||||
import org.session.libsession.messaging.messages.Message
|
||||
import org.session.libsession.messaging.messages.control.CallMessage
|
||||
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage
|
||||
|
@ -28,18 +29,19 @@ import org.session.libsession.messaging.sending_receiving.handleOpenGroupReactio
|
|||
import org.session.libsession.messaging.sending_receiving.handleUnsendRequest
|
||||
import org.session.libsession.messaging.sending_receiving.handleVisibleMessage
|
||||
import org.session.libsession.messaging.utilities.Data
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
import org.session.libsession.messaging.utilities.SodiumUtilities
|
||||
import org.session.libsession.utilities.SSKEnvironment
|
||||
import org.session.libsignal.protos.UtilProtos
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
|
||||
data class MessageReceiveParameters(
|
||||
val data: ByteArray,
|
||||
val serverHash: String? = null,
|
||||
val openGroupMessageServerID: Long? = null,
|
||||
val reactions: Map<String, OpenGroupApi.Reaction>? = null
|
||||
val reactions: Map<String, OpenGroupApi.Reaction>? = null,
|
||||
val closedGroup: Destination.ClosedGroup? = null
|
||||
)
|
||||
|
||||
class BatchMessageReceiveJob(
|
||||
|
@ -69,6 +71,7 @@ class BatchMessageReceiveJob(
|
|||
private val SERVER_HASH_KEY = "serverHash"
|
||||
private val OPEN_GROUP_MESSAGE_SERVER_ID_KEY = "openGroupMessageServerID"
|
||||
private val OPEN_GROUP_ID_KEY = "open_group_id"
|
||||
private val CLOSED_GROUP_DESTINATION_KEY = "closed_group_destination"
|
||||
}
|
||||
|
||||
private fun shouldCreateThread(parsedMessage: ParsedMessage): Boolean {
|
||||
|
@ -108,7 +111,13 @@ class BatchMessageReceiveJob(
|
|||
messages.forEach { messageParameters ->
|
||||
val (data, serverHash, openGroupMessageServerID) = messageParameters
|
||||
try {
|
||||
val (message, proto) = MessageReceiver.parse(data, openGroupMessageServerID, openGroupPublicKey = serverPublicKey, currentClosedGroups = currentClosedGroups)
|
||||
val (message, proto) = MessageReceiver.parse(
|
||||
data,
|
||||
openGroupMessageServerID,
|
||||
openGroupPublicKey = serverPublicKey,
|
||||
currentClosedGroups = currentClosedGroups,
|
||||
closedGroupSessionId = messageParameters.closedGroup?.publicKey
|
||||
)
|
||||
message.serverHash = serverHash
|
||||
val parsedParams = ParsedMessage(messageParameters, message, proto)
|
||||
val threadID = Message.getThreadId(message, openGroupID, storage, shouldCreateThread(parsedParams)) ?: NO_THREAD_MAPPING
|
||||
|
@ -262,12 +271,14 @@ class BatchMessageReceiveJob(
|
|||
.build()
|
||||
val serverHashes = messages.map { it.serverHash.orEmpty() }
|
||||
val openGroupServerIds = messages.map { it.openGroupMessageServerID ?: -1L }
|
||||
val closedGroups = messages.map { it.closedGroup?.publicKey.orEmpty() }
|
||||
return Data.Builder()
|
||||
.putInt(NUM_MESSAGES_KEY, arraySize)
|
||||
.putByteArray(DATA_KEY, dataArrays.toByteArray())
|
||||
.putString(OPEN_GROUP_ID_KEY, openGroupID)
|
||||
.putLongArray(OPEN_GROUP_MESSAGE_SERVER_ID_KEY, openGroupServerIds.toLongArray())
|
||||
.putStringArray(SERVER_HASH_KEY, serverHashes.toTypedArray())
|
||||
.putStringArray(CLOSED_GROUP_DESTINATION_KEY, closedGroups.toTypedArray())
|
||||
.build()
|
||||
}
|
||||
|
||||
|
@ -283,11 +294,22 @@ class BatchMessageReceiveJob(
|
|||
if (data.hasStringArray(SERVER_HASH_KEY)) data.getStringArray(SERVER_HASH_KEY) else arrayOf()
|
||||
val openGroupMessageServerIDs = data.getLongArray(OPEN_GROUP_MESSAGE_SERVER_ID_KEY)
|
||||
val openGroupID = data.getStringOrDefault(OPEN_GROUP_ID_KEY, null)
|
||||
val closedGroups =
|
||||
if (data.hasStringArray(CLOSED_GROUP_DESTINATION_KEY)) data.getStringArray(CLOSED_GROUP_DESTINATION_KEY)
|
||||
else arrayOf()
|
||||
|
||||
val parameters = (0 until numMessages).map { index ->
|
||||
val serverHash = serverHashes[index].let { if (it.isEmpty()) null else it }
|
||||
val serverId = openGroupMessageServerIDs[index].let { if (it == -1L) null else it }
|
||||
MessageReceiveParameters(contents[index], serverHash, serverId)
|
||||
val closedGroup = closedGroups.getOrNull(index)?.let {
|
||||
if (it.isEmpty()) null else Destination.ClosedGroup(it)
|
||||
}
|
||||
MessageReceiveParameters(
|
||||
data = contents[index],
|
||||
serverHash = serverHash,
|
||||
openGroupMessageServerID = serverId,
|
||||
closedGroup = closedGroup
|
||||
)
|
||||
}
|
||||
|
||||
return BatchMessageReceiveJob(parameters, openGroupID)
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.session.libsession.messaging.utilities.SodiumUtilities
|
|||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsignal.crypto.PushTransportDetails
|
||||
import org.session.libsignal.protos.SignalServiceProtos
|
||||
import org.session.libsignal.protos.SignalServiceProtos.Envelope
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
|
@ -53,22 +54,24 @@ object MessageReceiver {
|
|||
isOutgoing: Boolean? = null,
|
||||
otherBlindedPublicKey: String? = null,
|
||||
openGroupPublicKey: String? = null,
|
||||
currentClosedGroups: Set<String>?
|
||||
currentClosedGroups: Set<String>?,
|
||||
closedGroupSessionId: String? = null,
|
||||
): Pair<Message, SignalServiceProtos.Content> {
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val userPublicKey = storage.getUserPublicKey()
|
||||
val isOpenGroupMessage = (openGroupServerID != null)
|
||||
// Parse the envelope
|
||||
val envelope = SignalServiceProtos.Envelope.parseFrom(data)
|
||||
// Decrypt the contents
|
||||
val ciphertext = envelope.content ?: run {
|
||||
throw Error.NoData
|
||||
}
|
||||
var plaintext: ByteArray? = null
|
||||
var sender: String? = null
|
||||
var groupPublicKey: String? = null
|
||||
// Parse the envelope
|
||||
val envelope = Envelope.parseFrom(data) ?: throw Error.InvalidMessage
|
||||
// Decrypt the contents
|
||||
val envelopeContent = envelope.content ?: run {
|
||||
throw Error.NoData
|
||||
}
|
||||
|
||||
if (isOpenGroupMessage) {
|
||||
plaintext = envelope.content.toByteArray()
|
||||
plaintext = envelopeContent.toByteArray()
|
||||
sender = envelope.source
|
||||
} else {
|
||||
when (envelope.type) {
|
||||
|
@ -77,7 +80,7 @@ object MessageReceiver {
|
|||
openGroupPublicKey ?: throw Error.InvalidGroupPublicKey
|
||||
otherBlindedPublicKey ?: throw Error.DecryptionFailed
|
||||
val decryptionResult = MessageDecrypter.decryptBlinded(
|
||||
ciphertext.toByteArray(),
|
||||
envelopeContent.toByteArray(),
|
||||
isOutgoing ?: false,
|
||||
otherBlindedPublicKey,
|
||||
openGroupPublicKey
|
||||
|
@ -86,26 +89,18 @@ object MessageReceiver {
|
|||
sender = decryptionResult.second
|
||||
} else {
|
||||
val userX25519KeyPair = MessagingModuleConfiguration.shared.storage.getUserX25519KeyPair()
|
||||
val decryptionResult = MessageDecrypter.decrypt(ciphertext.toByteArray(), userX25519KeyPair)
|
||||
val decryptionResult = MessageDecrypter.decrypt(envelopeContent.toByteArray(), userX25519KeyPair)
|
||||
plaintext = decryptionResult.first
|
||||
sender = decryptionResult.second
|
||||
}
|
||||
}
|
||||
SignalServiceProtos.Envelope.Type.CLOSED_GROUP_MESSAGE -> {
|
||||
val hexEncodedGroupPublicKey = envelope.source
|
||||
val hexEncodedGroupPublicKey = closedGroupSessionId ?: envelope.source
|
||||
val sessionId = SessionId.from(hexEncodedGroupPublicKey)
|
||||
if (sessionId.prefix == IdPrefix.GROUP) {
|
||||
val configFactory = MessagingModuleConfiguration.shared.configFactory
|
||||
configFactory.getGroupKeysConfig(sessionId)?.use { config ->
|
||||
config.decrypt(ciphertext.toByteArray())?.let { (decrypted, senderSessionId) ->
|
||||
plaintext = decrypted
|
||||
sender = senderSessionId.hexString()
|
||||
groupPublicKey = envelope.source
|
||||
}
|
||||
}
|
||||
if (plaintext == null) {
|
||||
throw Error.DecryptionFailed
|
||||
}
|
||||
plaintext = envelopeContent.toByteArray()
|
||||
sender = envelope.source
|
||||
groupPublicKey = hexEncodedGroupPublicKey
|
||||
} else {
|
||||
if (!MessagingModuleConfiguration.shared.storage.isLegacyClosedGroup(hexEncodedGroupPublicKey)) {
|
||||
throw Error.InvalidGroupPublicKey
|
||||
|
@ -119,7 +114,7 @@ object MessageReceiver {
|
|||
var encryptionKeyPair = encryptionKeyPairs.removeLast()
|
||||
fun decrypt() {
|
||||
try {
|
||||
val decryptionResult = MessageDecrypter.decrypt(ciphertext.toByteArray(), encryptionKeyPair)
|
||||
val decryptionResult = MessageDecrypter.decrypt(envelopeContent.toByteArray(), encryptionKeyPair)
|
||||
plaintext = decryptionResult.first
|
||||
sender = decryptionResult.second
|
||||
} catch (e: Exception) {
|
||||
|
@ -132,7 +127,7 @@ object MessageReceiver {
|
|||
}
|
||||
}
|
||||
}
|
||||
groupPublicKey = envelope.source
|
||||
groupPublicKey = hexEncodedGroupPublicKey
|
||||
decrypt()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,25 +125,8 @@ object MessageSender {
|
|||
val proto = message.toProto() ?: throw Error.ProtoConversionFailed
|
||||
// Serialize the protobuf
|
||||
val plaintext = PushTransportDetails.getPaddedMessageBody(proto.toByteArray())
|
||||
// Encrypt the serialized protobuf
|
||||
val ciphertext = when (destination) {
|
||||
is Destination.Contact -> MessageEncrypter.encrypt(plaintext, destination.publicKey)
|
||||
is Destination.LegacyClosedGroup -> {
|
||||
val encryptionKeyPair =
|
||||
MessagingModuleConfiguration.shared.storage.getLatestClosedGroupEncryptionKeyPair(
|
||||
destination.groupPublicKey
|
||||
)!!
|
||||
MessageEncrypter.encrypt(plaintext, encryptionKeyPair.hexEncodedPublicKey)
|
||||
}
|
||||
is Destination.ClosedGroup -> {
|
||||
val groupKeys = configFactory.getGroupKeysConfig(SessionId.from(destination.publicKey)) ?: throw Error.NoKeyPair
|
||||
groupKeys.use { keys ->
|
||||
keys.encrypt(proto.toByteArray())
|
||||
}
|
||||
}
|
||||
else -> throw IllegalStateException("Destination should not be open group.")
|
||||
}
|
||||
// Wrap the result
|
||||
|
||||
// Envelope information
|
||||
val kind: SignalServiceProtos.Envelope.Type
|
||||
val senderPublicKey: String
|
||||
when (destination) {
|
||||
|
@ -161,7 +144,34 @@ object MessageSender {
|
|||
}
|
||||
else -> throw IllegalStateException("Destination should not be open group.")
|
||||
}
|
||||
val wrappedMessage = MessageWrapper.wrap(kind, message.sentTimestamp!!, senderPublicKey, ciphertext)
|
||||
|
||||
// Encrypt the serialized protobuf
|
||||
val ciphertext = when (destination) {
|
||||
is Destination.Contact -> MessageEncrypter.encrypt(plaintext, destination.publicKey)
|
||||
is Destination.LegacyClosedGroup -> {
|
||||
val encryptionKeyPair =
|
||||
MessagingModuleConfiguration.shared.storage.getLatestClosedGroupEncryptionKeyPair(
|
||||
destination.groupPublicKey
|
||||
)!!
|
||||
MessageEncrypter.encrypt(plaintext, encryptionKeyPair.hexEncodedPublicKey)
|
||||
}
|
||||
is Destination.ClosedGroup -> {
|
||||
val groupKeys = configFactory.getGroupKeysConfig(SessionId.from(destination.publicKey)) ?: throw Error.NoKeyPair
|
||||
val envelope = MessageWrapper.createEnvelope(kind, message.sentTimestamp!!, senderPublicKey, proto.toByteArray())
|
||||
groupKeys.use { keys ->
|
||||
keys.encrypt(envelope.toByteArray())
|
||||
}
|
||||
}
|
||||
else -> throw IllegalStateException("Destination should not be open group.")
|
||||
}
|
||||
// Wrap the result using envelope information
|
||||
val wrappedMessage = when (destination) {
|
||||
is Destination.ClosedGroup -> {
|
||||
// encrypted bytes from the above closed group encryption and envelope steps
|
||||
ciphertext
|
||||
}
|
||||
else -> MessageWrapper.wrap(kind, message.sentTimestamp!!, senderPublicKey, ciphertext)
|
||||
}
|
||||
val base64EncodedData = Base64.encodeBytes(wrappedMessage)
|
||||
// Send the result
|
||||
return SnodeMessage(
|
||||
|
|
|
@ -165,7 +165,7 @@ class ClosedGroupPoller(private val executor: CoroutineScope,
|
|||
keysIndex -> handleKeyPoll(response, keys, info, members)
|
||||
infoIndex -> handleInfo(response, info)
|
||||
membersIndex -> handleMembers(response, members)
|
||||
messageIndex -> handleMessages(response, snode)
|
||||
messageIndex -> handleMessages(response, snode, keys)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,11 +234,13 @@ class ClosedGroupPoller(private val executor: CoroutineScope,
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleMessages(response: RawResponse, snode: Snode) {
|
||||
private fun handleMessages(response: RawResponse, snode: Snode, keysConfig: GroupKeysConfig) {
|
||||
val body = response["body"] as RawResponse
|
||||
val messages = SnodeAPI.parseRawMessagesResponse(body, snode, closedGroupSessionId.hexString())
|
||||
val messages = SnodeAPI.parseRawMessagesResponse(body, snode, closedGroupSessionId.hexString()) {
|
||||
return@parseRawMessagesResponse keysConfig.decrypt(it)
|
||||
}
|
||||
val parameters = messages.map { (envelope, serverHash) ->
|
||||
MessageReceiveParameters(envelope.toByteArray(), serverHash = serverHash)
|
||||
MessageReceiveParameters(envelope.toByteArray(), serverHash = serverHash, closedGroup = Destination.ClosedGroup(closedGroupSessionId.hexString()))
|
||||
}
|
||||
parameters.chunked(BatchMessageReceiveJob.BATCH_DEFAULT_NUMBER).forEach { chunk ->
|
||||
val job = BatchMessageReceiveJob(chunk)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package org.session.libsession.messaging.utilities
|
||||
|
||||
import com.google.protobuf.ByteString
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.protos.SignalServiceProtos.Envelope
|
||||
import org.session.libsignal.protos.WebSocketProtos.WebSocketMessage
|
||||
import org.session.libsignal.protos.WebSocketProtos.WebSocketRequestMessage
|
||||
import org.session.libsignal.utilities.Log
|
||||
import java.security.SecureRandom
|
||||
|
||||
object MessageWrapper {
|
||||
|
@ -32,7 +32,7 @@ object MessageWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
private fun createEnvelope(type: Envelope.Type, timestamp: Long, senderPublicKey: String, content: ByteArray): Envelope {
|
||||
fun createEnvelope(type: Envelope.Type, timestamp: Long, senderPublicKey: String, content: ByteArray): Envelope {
|
||||
try {
|
||||
val builder = Envelope.newBuilder()
|
||||
builder.type = type
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.session.libsignal.utilities.Hex
|
|||
import org.session.libsignal.utilities.JsonUtil
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.Namespace
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
import org.session.libsignal.utilities.Snode
|
||||
import org.session.libsignal.utilities.ThreadUtils
|
||||
import org.session.libsignal.utilities.prettifiedDescription
|
||||
|
@ -851,14 +852,21 @@ object SnodeAPI {
|
|||
}
|
||||
}
|
||||
|
||||
fun parseRawMessagesResponse(rawResponse: RawResponse, snode: Snode, publicKey: String, namespace: Int = 0, updateLatestHash: Boolean = true, updateStoredHashes: Boolean = true): List<Pair<SignalServiceProtos.Envelope, String?>> {
|
||||
fun parseRawMessagesResponse(rawResponse: RawResponse,
|
||||
snode: Snode,
|
||||
publicKey: String,
|
||||
namespace: Int = 0,
|
||||
updateLatestHash: Boolean = true,
|
||||
updateStoredHashes: Boolean = true,
|
||||
decrypt: ((ByteArray) -> Pair<ByteArray, SessionId>?)? = null
|
||||
): List<Pair<SignalServiceProtos.Envelope, String?>> {
|
||||
val messages = rawResponse["messages"] as? List<*>
|
||||
return if (messages != null) {
|
||||
if (updateLatestHash) {
|
||||
updateLastMessageHashValueIfPossible(snode, publicKey, messages, namespace)
|
||||
}
|
||||
val newRawMessages = removeDuplicates(publicKey, messages, namespace, updateStoredHashes)
|
||||
return parseEnvelopes(newRawMessages)
|
||||
return parseEnvelopes(newRawMessages, decrypt)
|
||||
} else {
|
||||
listOf()
|
||||
}
|
||||
|
@ -895,14 +903,20 @@ object SnodeAPI {
|
|||
return result
|
||||
}
|
||||
|
||||
private fun parseEnvelopes(rawMessages: List<*>): List<Pair<SignalServiceProtos.Envelope, String?>> {
|
||||
private fun parseEnvelopes(rawMessages: List<*>, decrypt: ((ByteArray)->Pair<ByteArray, SessionId>?)?): List<Pair<SignalServiceProtos.Envelope, String?>> {
|
||||
return rawMessages.mapNotNull { rawMessage ->
|
||||
val rawMessageAsJSON = rawMessage as? Map<*, *>
|
||||
val base64EncodedData = rawMessageAsJSON?.get("data") as? String
|
||||
val data = base64EncodedData?.let { Base64.decode(it) }
|
||||
if (data != null) {
|
||||
try {
|
||||
Pair(MessageWrapper.unwrap(data), rawMessageAsJSON.get("hash") as? String)
|
||||
if (decrypt != null) {
|
||||
val (decrypted, sender) = decrypt(data)!!
|
||||
val envelope = SignalServiceProtos.Envelope.parseFrom(decrypted).toBuilder()
|
||||
envelope.source = sender.hexString()
|
||||
Pair(envelope.build(),rawMessageAsJSON.get("hash") as? String)
|
||||
}
|
||||
else Pair(MessageWrapper.unwrap(data), rawMessageAsJSON.get("hash") as? String)
|
||||
} catch (e: Exception) {
|
||||
Log.d("Loki", "Failed to unwrap data for message: ${rawMessage.prettifiedDescription()}.")
|
||||
null
|
||||
|
|
Loading…
Reference in New Issue