fix: crash for join open group dialog and v4 file upload in FS and open group

This commit is contained in:
jubb 2022-08-11 15:39:37 +10:00
parent 2f80fac57e
commit 6c07121d7a
5 changed files with 43 additions and 22 deletions

View File

@ -5,6 +5,7 @@ import android.text.Spannable
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.style.StyleSpan import android.text.style.StyleSpan
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import network.loki.messenger.R import network.loki.messenger.R
@ -37,9 +38,13 @@ class JoinOpenGroupDialog(private val name: String, private val url: String) : B
val openGroup = OpenGroupUrlParser.parseUrl(url) val openGroup = OpenGroupUrlParser.parseUrl(url)
val activity = requireContext() as AppCompatActivity val activity = requireContext() as AppCompatActivity
ThreadUtils.queue { ThreadUtils.queue {
OpenGroupManager.add(openGroup.server, openGroup.room, openGroup.serverPublicKey, activity) try {
MessagingModuleConfiguration.shared.storage.onOpenGroupAdded(url) OpenGroupManager.add(openGroup.server, openGroup.room, openGroup.serverPublicKey, activity)
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(activity) MessagingModuleConfiguration.shared.storage.onOpenGroupAdded(url)
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(activity)
} catch (e: Exception) {
Toast.makeText(activity, R.string.activity_join_public_chat_error, Toast.LENGTH_SHORT).show()
}
} }
dismiss() dismiss()
} }

View File

@ -7,7 +7,6 @@ import okhttp3.HttpUrl
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.RequestBody import okhttp3.RequestBody
import org.session.libsession.snode.OnionRequestAPI import org.session.libsession.snode.OnionRequestAPI
import org.session.libsignal.utilities.Base64
import org.session.libsignal.utilities.HTTP import org.session.libsignal.utilities.HTTP
import org.session.libsignal.utilities.JsonUtil import org.session.libsignal.utilities.JsonUtil
import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Log
@ -38,6 +37,7 @@ object FileServerApi {
val queryParameters: Map<String, String> = mapOf(), val queryParameters: Map<String, String> = mapOf(),
val parameters: Any? = null, val parameters: Any? = null,
val headers: Map<String, String> = mapOf(), val headers: Map<String, String> = mapOf(),
val body: ByteArray? = null,
/** /**
* Always `true` under normal circumstances. You might want to disable * Always `true` under normal circumstances. You might want to disable
* this when running over Lokinet. * this when running over Lokinet.
@ -45,7 +45,8 @@ object FileServerApi {
val useOnionRouting: Boolean = true val useOnionRouting: Boolean = true
) )
private fun createBody(parameters: Any?): RequestBody? { private fun createBody(body: ByteArray?, parameters: Any?): RequestBody? {
if (body != null) return RequestBody.create(MediaType.get("application/octet-stream"), body)
if (parameters == null) return null if (parameters == null) return null
val parametersAsJSON = JsonUtil.toJson(parameters) val parametersAsJSON = JsonUtil.toJson(parameters)
return RequestBody.create(MediaType.get("application/json"), parametersAsJSON) return RequestBody.create(MediaType.get("application/json"), parametersAsJSON)
@ -68,9 +69,9 @@ object FileServerApi {
.headers(Headers.of(request.headers)) .headers(Headers.of(request.headers))
when (request.verb) { when (request.verb) {
HTTP.Verb.GET -> requestBuilder.get() HTTP.Verb.GET -> requestBuilder.get()
HTTP.Verb.PUT -> requestBuilder.put(createBody(request.parameters)!!) HTTP.Verb.PUT -> requestBuilder.put(createBody(request.body, request.parameters)!!)
HTTP.Verb.POST -> requestBuilder.post(createBody(request.parameters)!!) HTTP.Verb.POST -> requestBuilder.post(createBody(request.body, request.parameters)!!)
HTTP.Verb.DELETE -> requestBuilder.delete(createBody(request.parameters)) HTTP.Verb.DELETE -> requestBuilder.delete(createBody(request.body, request.parameters))
} }
return if (request.useOnionRouting) { return if (request.useOnionRouting) {
OnionRequestAPI.sendOnionRequest(requestBuilder.build(), server, serverPublicKey).map { OnionRequestAPI.sendOnionRequest(requestBuilder.build(), server, serverPublicKey).map {
@ -84,12 +85,10 @@ object FileServerApi {
} }
fun upload(file: ByteArray): Promise<Long, Exception> { fun upload(file: ByteArray): Promise<Long, Exception> {
val base64EncodedFile = Base64.encodeBytes(file)
val parameters = mapOf( "file" to base64EncodedFile )
val request = Request( val request = Request(
verb = HTTP.Verb.POST, verb = HTTP.Verb.POST,
endpoint = "file", endpoint = "file",
parameters = parameters, body = file,
headers = mapOf( headers = mapOf(
"Content-Disposition" to "attachment", "Content-Disposition" to "attachment",
"Content-Type" to "application/octet-stream" "Content-Type" to "application/octet-stream"
@ -97,7 +96,7 @@ object FileServerApi {
) )
return send(request).map { response -> return send(request).map { response ->
val json = JsonUtil.fromJson(response, Map::class.java) val json = JsonUtil.fromJson(response, Map::class.java)
json["result"] as? Long ?: throw Error.ParsingFailed (json["id"] as? String)?.toLong() ?: throw Error.ParsingFailed
} }
} }

View File

@ -212,6 +212,7 @@ object OpenGroupApi {
val parameters: Any? = null, val parameters: Any? = null,
val headers: Map<String, String> = mapOf(), val headers: Map<String, String> = mapOf(),
val isAuthRequired: Boolean = true, val isAuthRequired: Boolean = true,
val body: ByteArray? = null,
/** /**
* Always `true` under normal circumstances. You might want to disable * Always `true` under normal circumstances. You might want to disable
* this when running over Lokinet. * this when running over Lokinet.
@ -219,7 +220,8 @@ object OpenGroupApi {
val useOnionRouting: Boolean = true val useOnionRouting: Boolean = true
) )
private fun createBody(parameters: Any?): RequestBody? { private fun createBody(body: ByteArray?, parameters: Any?): RequestBody? {
if (body != null) return RequestBody.create(MediaType.get("application/octet-stream"), body)
if (parameters == null) return null if (parameters == null) return null
val parametersAsJSON = JsonUtil.toJson(parameters) val parametersAsJSON = JsonUtil.toJson(parameters)
return RequestBody.create(MediaType.get("application/json"), parametersAsJSON) return RequestBody.create(MediaType.get("application/json"), parametersAsJSON)
@ -276,6 +278,17 @@ object OpenGroupApi {
) { ) {
bodyHash = parameterHash bodyHash = parameterHash
} }
} else if (request.body != null) {
val byteHash = ByteArray(GenericHash.BYTES_MAX)
if (sodium.cryptoGenericHash(
byteHash,
byteHash.size,
request.body,
request.body.size.toLong()
)
) {
bodyHash = byteHash
}
} }
val messageBytes = Hex.fromStringCondensed(publicKey) val messageBytes = Hex.fromStringCondensed(publicKey)
.plus(nonce) .plus(nonce)
@ -320,9 +333,9 @@ object OpenGroupApi {
.headers(Headers.of(headers)) .headers(Headers.of(headers))
when (request.verb) { when (request.verb) {
GET -> requestBuilder.get() GET -> requestBuilder.get()
PUT -> requestBuilder.put(createBody(request.parameters)!!) PUT -> requestBuilder.put(createBody(request.body, request.parameters)!!)
POST -> requestBuilder.post(createBody(request.parameters)!!) POST -> requestBuilder.post(createBody(request.body, request.parameters)!!)
DELETE -> requestBuilder.delete(createBody(request.parameters)) DELETE -> requestBuilder.delete(createBody(request.body, request.parameters))
} }
if (!request.room.isNullOrEmpty()) { if (!request.room.isNullOrEmpty()) {
requestBuilder.header("Room", request.room) requestBuilder.header("Room", request.room)
@ -354,13 +367,16 @@ object OpenGroupApi {
// region Upload/Download // region Upload/Download
fun upload(file: ByteArray, room: String, server: String): Promise<Long, Exception> { fun upload(file: ByteArray, room: String, server: String): Promise<Long, Exception> {
val parameters = mapOf("file" to file)
val request = Request( val request = Request(
verb = POST, verb = POST,
room = room, room = room,
server = server, server = server,
endpoint = Endpoint.RoomFile(room), endpoint = Endpoint.RoomFile(room),
parameters = parameters body = file,
headers = mapOf(
"Content-Disposition" to "attachment",
"Content-Type" to "application/octet-stream"
)
) )
return getResponseBodyJson(request).map { json -> return getResponseBodyJson(request).map { json ->
(json["id"] as? Number)?.toLong() ?: throw Error.ParsingFailed (json["id"] as? Number)?.toLong() ?: throw Error.ParsingFailed

View File

@ -483,7 +483,7 @@ object OnionRequestAPI {
val prefixData = "l${requestData.size}:".toByteArray(Charsets.US_ASCII) val prefixData = "l${requestData.size}:".toByteArray(Charsets.US_ASCII)
val suffixData = "e".toByteArray(Charsets.US_ASCII) val suffixData = "e".toByteArray(Charsets.US_ASCII)
if (request.body() != null) { if (request.body() != null) {
val bodyData = body.toString().toByteArray() val bodyData = if (body is ByteArray) body else body.toString().toByteArray()
val bodyLengthData = "${bodyData.size}:".toByteArray(Charsets.US_ASCII) val bodyLengthData = "${bodyData.size}:".toByteArray(Charsets.US_ASCII)
prefixData + requestData + bodyLengthData + bodyData + suffixData prefixData + requestData + bodyLengthData + bodyData + suffixData
} else { } else {

View File

@ -3,10 +3,9 @@ package org.session.libsession.utilities
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.Request import okhttp3.Request
import okio.Buffer import okio.Buffer
import java.io.IOException
import java.util.*
import org.session.libsignal.utilities.Base64 import org.session.libsignal.utilities.Base64
import java.io.IOException
import java.util.Locale
internal fun Request.getHeadersForOnionRequest(): Map<String, Any> { internal fun Request.getHeadersForOnionRequest(): Map<String, Any> {
val result = mutableMapOf<String, Any>() val result = mutableMapOf<String, Any>()
@ -40,6 +39,8 @@ internal fun Request.getBodyForOnionRequest(): Any? {
if (body is MultipartBody) { if (body is MultipartBody) {
val base64EncodedBody: String = Base64.encodeBytes(bodyAsData) val base64EncodedBody: String = Base64.encodeBytes(bodyAsData)
return mapOf( "fileUpload" to base64EncodedBody ) return mapOf( "fileUpload" to base64EncodedBody )
} else if (body.contentType()?.toString() == "application/octet-stream") {
return bodyAsData
} else { } else {
val charset = body.contentType()?.charset() ?: Charsets.UTF_8 val charset = body.contentType()?.charset() ?: Charsets.UTF_8
return bodyAsData?.toString(charset) return bodyAsData?.toString(charset)