add utils

This commit is contained in:
Ryan ZHAO 2020-12-10 15:29:19 +11:00
parent 52d0a36ae5
commit fea965e37f
8 changed files with 1476 additions and 4 deletions

View File

@ -0,0 +1,34 @@
package org.session.libsession.messaging
import android.content.Context
import org.session.libsession.database.MessageDataProvider
import org.session.libsignal.libsignal.loki.SessionResetProtocol
import org.session.libsignal.libsignal.state.*
import org.session.libsignal.metadata.certificate.CertificateValidator
import org.session.libsignal.service.loki.protocol.closedgroups.SharedSenderKeysDatabaseProtocol
class MessagingConfiguration(
val context: Context,
val storage: StorageProtocol,
val signalStorage: SignalProtocolStore,
val sskDatabase: SharedSenderKeysDatabaseProtocol,
val messageDataProvider: MessageDataProvider,
val sessionResetImp: SessionResetProtocol,
val certificateValidator: CertificateValidator)
{
companion object {
lateinit var shared: MessagingConfiguration
fun configure(context: Context,
storage: StorageProtocol,
signalStorage: SignalProtocolStore,
sskDatabase: SharedSenderKeysDatabaseProtocol,
messageDataProvider: MessageDataProvider,
sessionResetImp: SessionResetProtocol,
certificateValidator: CertificateValidator
) {
if (Companion::shared.isInitialized) { return }
shared = MessagingConfiguration(context, storage, signalStorage, sskDatabase, messageDataProvider, sessionResetImp, certificateValidator)
}
}
}

View File

@ -3,7 +3,7 @@ package org.session.libsession.messaging.utilities
import com.goterl.lazycode.lazysodium.LazySodiumAndroid import com.goterl.lazycode.lazysodium.LazySodiumAndroid
import com.goterl.lazycode.lazysodium.SodiumAndroid import com.goterl.lazycode.lazysodium.SodiumAndroid
import org.session.libsession.messaging.Configuration import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsignal.libsignal.logging.Log import org.session.libsignal.libsignal.logging.Log
import org.session.libsignal.metadata.SignalProtos import org.session.libsignal.metadata.SignalProtos
@ -37,12 +37,12 @@ object UnidentifiedAccessUtil {
} }
private fun getTargetUnidentifiedAccessKey(recipientPublicKey: String): ByteArray? { private fun getTargetUnidentifiedAccessKey(recipientPublicKey: String): ByteArray? {
val theirProfileKey = Configuration.shared.storage.getProfileKeyForRecipient(recipientPublicKey) ?: return sodium.randomBytesBuf(16) val theirProfileKey = MessagingConfiguration.shared.storage.getProfileKeyForRecipient(recipientPublicKey) ?: return sodium.randomBytesBuf(16)
return UnidentifiedAccess.deriveAccessKeyFrom(theirProfileKey) return UnidentifiedAccess.deriveAccessKeyFrom(theirProfileKey)
} }
private fun getSelfUnidentifiedAccessKey(): ByteArray? { private fun getSelfUnidentifiedAccessKey(): ByteArray? {
val userPublicKey = Configuration.shared.storage.getUserPublicKey() val userPublicKey = MessagingConfiguration.shared.storage.getUserPublicKey()
if (userPublicKey != null) { if (userPublicKey != null) {
return sodium.randomBytesBuf(16) return sodium.randomBytesBuf(16)
} }
@ -50,7 +50,7 @@ object UnidentifiedAccessUtil {
} }
private fun getUnidentifiedAccessCertificate(): ByteArray? { private fun getUnidentifiedAccessCertificate(): ByteArray? {
val userPublicKey = Configuration.shared.storage.getUserPublicKey() val userPublicKey = MessagingConfiguration.shared.storage.getUserPublicKey()
if (userPublicKey != null) { if (userPublicKey != null) {
val certificate = SignalProtos.SenderCertificate.newBuilder().setSender(userPublicKey).setSenderDevice(1).build() val certificate = SignalProtos.SenderCertificate.newBuilder().setSender(userPublicKey).setSenderDevice(1).build()
return certificate.toByteArray() return certificate.toByteArray()

View File

@ -0,0 +1,18 @@
package org.session.libsession.utilities
import java.util.regex.Pattern
object DelimiterUtil {
fun escape(value: String, delimiter: Char): String {
return value.replace("" + delimiter, "\\" + delimiter)
}
fun unescape(value: String, delimiter: Char): String {
return value.replace("\\" + delimiter, "" + delimiter)
}
fun split(value: String, delimiter: Char): Array<String> {
val regex = "(?<!\\\\)" + Pattern.quote(delimiter.toString() + "")
return value.split(regex).toTypedArray()
}
}

View File

@ -0,0 +1,63 @@
package org.session.libsession.utilities
object GroupUtil {
const val CLOSED_GROUP_PREFIX = "__textsecure_group__!"
const val MMS_GROUP_PREFIX = "__signal_mms_group__!"
const val OPEN_GROUP_PREFIX = "__loki_public_chat_group__!"
fun getEncodedOpenGroupID(groupID: String): String {
return OPEN_GROUP_PREFIX + groupID
}
fun getEncodedOpenGroupIDAsData(groupID: String): ByteArray {
return (OPEN_GROUP_PREFIX + groupID).toByteArray()
}
fun getEncodedClosedGroupID(groupID: String): String {
return CLOSED_GROUP_PREFIX + groupID
}
fun getEncodedClosedGroupIDAsData(groupID: String): ByteArray {
return (CLOSED_GROUP_PREFIX + groupID).toByteArray()
}
fun getEncodedMMSGroupID(groupID: String): String {
return MMS_GROUP_PREFIX + groupID
}
fun getEncodedMMSGroupIDAsData(groupID: String): ByteArray {
return (MMS_GROUP_PREFIX + groupID).toByteArray()
}
fun getEncodedGroupID(groupID: ByteArray): String {
return groupID.toString()
}
fun getDecodedGroupID(groupID: ByteArray): String {
val encodedGroupID = groupID.toString()
if (encodedGroupID.split("!").count() > 1) {
return encodedGroupID.split("!")[1]
}
return encodedGroupID.split("!")[0]
}
fun getDecodedGroupIDAsData(groupID: ByteArray): ByteArray {
return getDecodedGroupID(groupID).toByteArray()
}
fun isEncodedGroup(groupId: String): Boolean {
return groupId.startsWith(CLOSED_GROUP_PREFIX) || groupId.startsWith(MMS_GROUP_PREFIX) || groupId.startsWith(OPEN_GROUP_PREFIX)
}
fun isMmsGroup(groupId: String): Boolean {
return groupId.startsWith(MMS_GROUP_PREFIX)
}
fun isOpenGroup(groupId: String): Boolean {
return groupId.startsWith(OPEN_GROUP_PREFIX)
}
fun isClosedGroup(groupId: String): Boolean {
return groupId.startsWith(CLOSED_GROUP_PREFIX)
}
}

View File

@ -0,0 +1,19 @@
package org.session.libsession.utilities
import android.telephony.PhoneNumberUtils
import android.util.Patterns
object NumberUtil {
private val emailPattern = Patterns.EMAIL_ADDRESS
@JvmStatic
fun isValidEmail(number: String): Boolean {
val matcher = emailPattern.matcher(number)
return matcher.matches()
}
fun isValidSmsOrEmail(number: String): Boolean {
return PhoneNumberUtils.isWellFormedSmsAddress(number) || isValidEmail(number)
}
}

View File

@ -0,0 +1,35 @@
@file:JvmName("PromiseUtilities")
package org.session.libsession.utilities
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.deferred
import org.session.libsignal.libsignal.logging.Log
import java.util.concurrent.TimeoutException
fun <V, E> Promise<V, E>.successBackground(callback: (value: V) -> Unit): Promise<V, E> {
Thread {
try {
callback(get())
} catch (e: Exception) {
Log.d("Loki", "Failed to execute task in background: ${e.message}.")
}
}.start()
return this
}
fun <V> Promise<V, Exception>.timeout(millis: Long): Promise<V, Exception> {
if (this.isDone()) { return this; }
val deferred = deferred<V, Exception>()
Thread {
Thread.sleep(millis)
if (!deferred.promise.isDone()) {
deferred.reject(TimeoutException("Promise timed out."))
}
}.start()
this.success {
if (!deferred.promise.isDone()) { deferred.resolve(it) }
}.fail {
if (!deferred.promise.isDone()) { deferred.reject(it) }
}
return deferred.promise
}

View File

@ -0,0 +1,13 @@
package org.session.libsession.utilities
object Util {
fun join(list: Collection<String?>, delimiter: String?): String {
val result = StringBuilder()
var i = 0
for (item in list) {
result.append(item)
if (++i < list.size) result.append(delimiter)
}
return result.toString()
}
}