mirror of
https://github.com/oxen-io/session-android.git
synced 2023-12-14 02:53:01 +01:00
Merge fbe29a558a
into 300c3a6605
This commit is contained in:
commit
663ced292b
17 changed files with 93 additions and 51 deletions
|
@ -25,6 +25,7 @@ import androidx.core.view.isVisible
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding
|
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||||
|
@ -284,7 +285,7 @@ class VisibleMessageContentView : ConstraintLayout {
|
||||||
|
|
||||||
// replace URLSpans with ModalURLSpans
|
// replace URLSpans with ModalURLSpans
|
||||||
body.getSpans<URLSpan>(0, body.length).toList().forEach { urlSpan ->
|
body.getSpans<URLSpan>(0, body.length).toList().forEach { urlSpan ->
|
||||||
val updatedUrl = urlSpan.url.let { HttpUrl.parse(it).toString() }
|
val updatedUrl = urlSpan.url.let { it.toHttpUrlOrNull().toString() }
|
||||||
val replacementSpan = ModalURLSpan(updatedUrl) { url ->
|
val replacementSpan = ModalURLSpan(updatedUrl) { url ->
|
||||||
val activity = context as AppCompatActivity
|
val activity = context as AppCompatActivity
|
||||||
ModalUrlBottomSheet(url).show(activity.supportFragmentManager, "Open URL Dialog")
|
ModalUrlBottomSheet(url).show(activity.supportFragmentManager, "Open URL Dialog")
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.groups
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.open_groups.GroupMemberRole
|
import org.session.libsession.messaging.open_groups.GroupMemberRole
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||||
|
@ -133,9 +134,9 @@ object OpenGroupManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addOpenGroup(urlAsString: String, context: Context): OpenGroupApi.RoomInfo? {
|
fun addOpenGroup(urlAsString: String, context: Context): OpenGroupApi.RoomInfo? {
|
||||||
val url = HttpUrl.parse(urlAsString) ?: return null
|
val url = urlAsString.toHttpUrlOrNull() ?: return null
|
||||||
val server = OpenGroup.getServer(urlAsString)
|
val server = OpenGroup.getServer(urlAsString)
|
||||||
val room = url.pathSegments().firstOrNull() ?: return null
|
val room = url.pathSegments.firstOrNull() ?: return null
|
||||||
val publicKey = url.queryParameter("public_key") ?: return null
|
val publicKey = url.queryParameter("public_key") ?: return null
|
||||||
|
|
||||||
return add(server.toString().removeSuffix("/"), room, publicKey, context) // assume migrated from calling function
|
return add(server.toString().removeSuffix("/"), room, publicKey, context) // assume migrated from calling function
|
||||||
|
|
|
@ -4,8 +4,10 @@ import android.content.Context
|
||||||
import nl.komponents.kovenant.Promise
|
import nl.komponents.kovenant.Promise
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI
|
import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI
|
||||||
import org.session.libsession.snode.OnionRequestAPI
|
import org.session.libsession.snode.OnionRequestAPI
|
||||||
import org.session.libsession.snode.Version
|
import org.session.libsession.snode.Version
|
||||||
|
@ -42,7 +44,7 @@ object LokiPushNotificationManager {
|
||||||
fun unregister(token: String, context: Context) {
|
fun unregister(token: String, context: Context) {
|
||||||
val parameters = mapOf( "token" to token )
|
val parameters = mapOf( "token" to token )
|
||||||
val url = "$server/unregister"
|
val url = "$server/unregister"
|
||||||
val body = RequestBody.create(MediaType.get("application/json"), JsonUtil.toJson(parameters))
|
val body = RequestBody.create("application/json".toMediaType(), JsonUtil.toJson(parameters))
|
||||||
val request = Request.Builder().url(url).post(body)
|
val request = Request.Builder().url(url).post(body)
|
||||||
retryIfNeeded(maxRetryCount) {
|
retryIfNeeded(maxRetryCount) {
|
||||||
getResponseBody(request.build()).map { json ->
|
getResponseBody(request.build()).map { json ->
|
||||||
|
@ -71,7 +73,7 @@ object LokiPushNotificationManager {
|
||||||
if (!force && token == oldToken && System.currentTimeMillis() - lastUploadDate < tokenExpirationInterval) { return }
|
if (!force && token == oldToken && System.currentTimeMillis() - lastUploadDate < tokenExpirationInterval) { return }
|
||||||
val parameters = mapOf( "token" to token, "pubKey" to publicKey )
|
val parameters = mapOf( "token" to token, "pubKey" to publicKey )
|
||||||
val url = "$server/register"
|
val url = "$server/register"
|
||||||
val body = RequestBody.create(MediaType.get("application/json"), JsonUtil.toJson(parameters))
|
val body = JsonUtil.toJson(parameters).toRequestBody("application/json".toMediaType())
|
||||||
val request = Request.Builder().url(url).post(body)
|
val request = Request.Builder().url(url).post(body)
|
||||||
retryIfNeeded(maxRetryCount) {
|
retryIfNeeded(maxRetryCount) {
|
||||||
getResponseBody(request.build()).map { json ->
|
getResponseBody(request.build()).map { json ->
|
||||||
|
@ -99,7 +101,7 @@ object LokiPushNotificationManager {
|
||||||
if (!TextSecurePreferences.isUsingFCM(context)) { return }
|
if (!TextSecurePreferences.isUsingFCM(context)) { return }
|
||||||
val parameters = mapOf( "closedGroupPublicKey" to closedGroupPublicKey, "pubKey" to publicKey )
|
val parameters = mapOf( "closedGroupPublicKey" to closedGroupPublicKey, "pubKey" to publicKey )
|
||||||
val url = "$server/${operation.rawValue}"
|
val url = "$server/${operation.rawValue}"
|
||||||
val body = RequestBody.create(MediaType.get("application/json"), JsonUtil.toJson(parameters))
|
val body = RequestBody.create("application/json".toMediaType(), JsonUtil.toJson(parameters))
|
||||||
val request = Request.Builder().url(url).post(body)
|
val request = Request.Builder().url(url).post(body)
|
||||||
retryIfNeeded(maxRetryCount) {
|
retryIfNeeded(maxRetryCount) {
|
||||||
getResponseBody(request.build()).map { json ->
|
getResponseBody(request.build()).map { json ->
|
||||||
|
|
|
@ -13,7 +13,7 @@ glideVersion=4.11.0
|
||||||
kovenantVersion=3.3.0
|
kovenantVersion=3.3.0
|
||||||
curve25519Version=0.6.0
|
curve25519Version=0.6.0
|
||||||
protobufVersion=2.5.0
|
protobufVersion=2.5.0
|
||||||
okhttpVersion=3.12.1
|
okhttpVersion=4.11.0
|
||||||
jacksonDatabindVersion=2.9.8
|
jacksonDatabindVersion=2.9.8
|
||||||
appcompatVersion=1.5.1
|
appcompatVersion=1.5.1
|
||||||
materialVersion=1.7.0
|
materialVersion=1.7.0
|
||||||
|
|
|
@ -3,8 +3,11 @@ package org.session.libsession.messaging.file_server
|
||||||
import nl.komponents.kovenant.Promise
|
import nl.komponents.kovenant.Promise
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
|
import okhttp3.Headers.Companion.toHeaders
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import org.session.libsession.snode.OnionRequestAPI
|
import org.session.libsession.snode.OnionRequestAPI
|
||||||
import org.session.libsignal.utilities.HTTP
|
import org.session.libsignal.utilities.HTTP
|
||||||
|
@ -37,18 +40,18 @@ object FileServerApi {
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun createBody(body: ByteArray?, parameters: Any?): RequestBody? {
|
private fun createBody(body: ByteArray?, parameters: Any?): RequestBody? {
|
||||||
if (body != null) return RequestBody.create(MediaType.get("application/octet-stream"), body)
|
if (body != null) return RequestBody.create("application/octet-stream".toMediaType(), 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("application/json".toMediaType(), parametersAsJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun send(request: Request): Promise<ByteArray, Exception> {
|
private fun send(request: Request): Promise<ByteArray, Exception> {
|
||||||
val url = HttpUrl.parse(server) ?: return Promise.ofFail(Error.InvalidURL)
|
val url = server.toHttpUrlOrNull() ?: return Promise.ofFail(Error.InvalidURL)
|
||||||
val urlBuilder = HttpUrl.Builder()
|
val urlBuilder = HttpUrl.Builder()
|
||||||
.scheme(url.scheme())
|
.scheme(url.scheme)
|
||||||
.host(url.host())
|
.host(url.host)
|
||||||
.port(url.port())
|
.port(url.port)
|
||||||
.addPathSegments(request.endpoint)
|
.addPathSegments(request.endpoint)
|
||||||
if (request.verb == HTTP.Verb.GET) {
|
if (request.verb == HTTP.Verb.GET) {
|
||||||
for ((key, value) in request.queryParameters) {
|
for ((key, value) in request.queryParameters) {
|
||||||
|
@ -57,7 +60,7 @@ object FileServerApi {
|
||||||
}
|
}
|
||||||
val requestBuilder = okhttp3.Request.Builder()
|
val requestBuilder = okhttp3.Request.Builder()
|
||||||
.url(urlBuilder.build())
|
.url(urlBuilder.build())
|
||||||
.headers(Headers.of(request.headers))
|
.headers(request.headers.toHeaders())
|
||||||
when (request.verb) {
|
when (request.verb) {
|
||||||
HTTP.Verb.GET -> requestBuilder.get()
|
HTTP.Verb.GET -> requestBuilder.get()
|
||||||
HTTP.Verb.PUT -> requestBuilder.put(createBody(request.body, request.parameters)!!)
|
HTTP.Verb.PUT -> requestBuilder.put(createBody(request.body, request.parameters)!!)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.session.libsession.messaging.jobs
|
package org.session.libsession.messaging.jobs
|
||||||
|
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupApi
|
import org.session.libsession.messaging.open_groups.OpenGroupApi
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
||||||
|
@ -121,8 +122,8 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
||||||
DownloadUtilities.downloadFile(tempFile, attachment.url)
|
DownloadUtilities.downloadFile(tempFile, attachment.url)
|
||||||
} else {
|
} else {
|
||||||
Log.d("AttachmentDownloadJob", "downloading open group attachment")
|
Log.d("AttachmentDownloadJob", "downloading open group attachment")
|
||||||
val url = HttpUrl.parse(attachment.url)!!
|
val url = attachment.url.toHttpUrlOrNull()!!
|
||||||
val fileID = url.pathSegments().last()
|
val fileID = url.pathSegments.last()
|
||||||
OpenGroupApi.download(fileID, openGroup.room, openGroup.server).get().let {
|
OpenGroupApi.download(fileID, openGroup.room, openGroup.server).get().let {
|
||||||
tempFile.writeBytes(it)
|
tempFile.writeBytes(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.session.libsession.messaging.jobs
|
package org.session.libsession.messaging.jobs
|
||||||
|
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupApi
|
import org.session.libsession.messaging.open_groups.OpenGroupApi
|
||||||
|
@ -23,9 +24,9 @@ class BackgroundGroupAddJob(val joinUrl: String): Job {
|
||||||
override val maxFailureCount: Int = 1
|
override val maxFailureCount: Int = 1
|
||||||
|
|
||||||
val openGroupId: String? get() {
|
val openGroupId: String? get() {
|
||||||
val url = HttpUrl.parse(joinUrl) ?: return null
|
val url = joinUrl.toHttpUrlOrNull() ?: return null
|
||||||
val server = OpenGroup.getServer(joinUrl)?.toString()?.removeSuffix("/") ?: return null
|
val server = OpenGroup.getServer(joinUrl)?.toString()?.removeSuffix("/") ?: return null
|
||||||
val room = url.pathSegments().firstOrNull() ?: return null
|
val room = url.pathSegments.firstOrNull() ?: return null
|
||||||
return "$server.$room"
|
return "$server.$room"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.esotericsoftware.kryo.io.Input
|
||||||
import com.esotericsoftware.kryo.io.Output
|
import com.esotericsoftware.kryo.io.Output
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import org.session.libsession.messaging.jobs.Job.Companion.MAX_BUFFER_SIZE
|
import org.session.libsession.messaging.jobs.Job.Companion.MAX_BUFFER_SIZE
|
||||||
|
@ -36,7 +37,7 @@ class NotifyPNServerJob(val message: SnodeMessage) : Job {
|
||||||
val server = PushNotificationAPI.server
|
val server = PushNotificationAPI.server
|
||||||
val parameters = mapOf( "data" to message.data, "send_to" to message.recipient )
|
val parameters = mapOf( "data" to message.data, "send_to" to message.recipient )
|
||||||
val url = "${server}/notify"
|
val url = "${server}/notify"
|
||||||
val body = RequestBody.create(MediaType.get("application/json"), JsonUtil.toJson(parameters))
|
val body = RequestBody.create("application/json".toMediaType(), JsonUtil.toJson(parameters))
|
||||||
val request = Request.Builder().url(url).post(body)
|
val request = Request.Builder().url(url).post(body)
|
||||||
retryIfNeeded(4) {
|
retryIfNeeded(4) {
|
||||||
OnionRequestAPI.sendOnionRequest(request.build(), server, PushNotificationAPI.serverPublicKey, Version.V2).map { response ->
|
OnionRequestAPI.sendOnionRequest(request.build(), server, PushNotificationAPI.serverPublicKey, Version.V2).map { response ->
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.session.libsession.messaging.open_groups
|
package org.session.libsession.messaging.open_groups
|
||||||
|
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.session.libsignal.utilities.JsonUtil
|
import org.session.libsignal.utilities.JsonUtil
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
@ -47,11 +48,11 @@ data class OpenGroup(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getServer(urlAsString: String): HttpUrl? {
|
fun getServer(urlAsString: String): HttpUrl? {
|
||||||
val url = HttpUrl.parse(urlAsString) ?: return null
|
val url = urlAsString.toHttpUrlOrNull() ?: return null
|
||||||
val builder = HttpUrl.Builder().scheme(url.scheme()).host(url.host())
|
val builder = HttpUrl.Builder().scheme(url.scheme).host(url.host)
|
||||||
if (url.port() != 80 || url.port() != 443) {
|
if (url.port != 80 || url.port != 443) {
|
||||||
// Non-standard port; add to server
|
// Non-standard port; add to server
|
||||||
builder.port(url.port())
|
builder.port(url.port)
|
||||||
}
|
}
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,11 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import nl.komponents.kovenant.Promise
|
import nl.komponents.kovenant.Promise
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
|
import okhttp3.Headers.Companion.toHeaders
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPoller.Companion.maxInactivityPeriod
|
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPoller.Companion.maxInactivityPeriod
|
||||||
|
@ -283,10 +286,10 @@ object OpenGroupApi {
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun createBody(body: ByteArray?, parameters: Any?): RequestBody? {
|
private fun createBody(body: ByteArray?, parameters: Any?): RequestBody? {
|
||||||
if (body != null) return RequestBody.create(MediaType.get("application/octet-stream"), body)
|
if (body != null) return RequestBody.create("application/octet-stream".toMediaType(), 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("application/json".toMediaType(), parametersAsJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getResponseBody(request: Request): Promise<ByteArray, Exception> {
|
private fun getResponseBody(request: Request): Promise<ByteArray, Exception> {
|
||||||
|
@ -302,7 +305,7 @@ object OpenGroupApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun send(request: Request): Promise<OnionResponse, Exception> {
|
private fun send(request: Request): Promise<OnionResponse, Exception> {
|
||||||
HttpUrl.parse(request.server) ?: return Promise.ofFail(Error.InvalidURL)
|
request.server.toHttpUrlOrNull() ?: return Promise.ofFail(Error.InvalidURL)
|
||||||
val urlBuilder = StringBuilder("${request.server}/${request.endpoint.value}")
|
val urlBuilder = StringBuilder("${request.server}/${request.endpoint.value}")
|
||||||
if (request.verb == GET && request.queryParameters.isNotEmpty()) {
|
if (request.verb == GET && request.queryParameters.isNotEmpty()) {
|
||||||
urlBuilder.append("?")
|
urlBuilder.append("?")
|
||||||
|
@ -389,7 +392,7 @@ object OpenGroupApi {
|
||||||
|
|
||||||
val requestBuilder = okhttp3.Request.Builder()
|
val requestBuilder = okhttp3.Request.Builder()
|
||||||
.url(urlRequest)
|
.url(urlRequest)
|
||||||
.headers(Headers.of(headers))
|
.headers(headers.toHeaders())
|
||||||
when (request.verb) {
|
when (request.verb) {
|
||||||
GET -> requestBuilder.get()
|
GET -> requestBuilder.get()
|
||||||
PUT -> requestBuilder.put(createBody(request.body, request.parameters)!!)
|
PUT -> requestBuilder.put(createBody(request.body, request.parameters)!!)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.session.libsession.messaging.sending_receiving.notifications
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
|
@ -36,7 +37,7 @@ object PushNotificationAPI {
|
||||||
fun unregister(token: String) {
|
fun unregister(token: String) {
|
||||||
val parameters = mapOf( "token" to token )
|
val parameters = mapOf( "token" to token )
|
||||||
val url = "$server/unregister"
|
val url = "$server/unregister"
|
||||||
val body = RequestBody.create(MediaType.get("application/json"), JsonUtil.toJson(parameters))
|
val body = RequestBody.create("application/json".toMediaType(), JsonUtil.toJson(parameters))
|
||||||
val request = Request.Builder().url(url).post(body)
|
val request = Request.Builder().url(url).post(body)
|
||||||
retryIfNeeded(maxRetryCount) {
|
retryIfNeeded(maxRetryCount) {
|
||||||
OnionRequestAPI.sendOnionRequest(request.build(), server, serverPublicKey, Version.V2).map { response ->
|
OnionRequestAPI.sendOnionRequest(request.build(), server, serverPublicKey, Version.V2).map { response ->
|
||||||
|
@ -64,7 +65,7 @@ object PushNotificationAPI {
|
||||||
if (!force && token == oldToken && System.currentTimeMillis() - lastUploadDate < tokenExpirationInterval) { return }
|
if (!force && token == oldToken && System.currentTimeMillis() - lastUploadDate < tokenExpirationInterval) { return }
|
||||||
val parameters = mapOf( "token" to token, "pubKey" to publicKey )
|
val parameters = mapOf( "token" to token, "pubKey" to publicKey )
|
||||||
val url = "$server/register"
|
val url = "$server/register"
|
||||||
val body = RequestBody.create(MediaType.get("application/json"), JsonUtil.toJson(parameters))
|
val body = RequestBody.create("application/json".toMediaType(), JsonUtil.toJson(parameters))
|
||||||
val request = Request.Builder().url(url).post(body)
|
val request = Request.Builder().url(url).post(body)
|
||||||
retryIfNeeded(maxRetryCount) {
|
retryIfNeeded(maxRetryCount) {
|
||||||
OnionRequestAPI.sendOnionRequest(request.build(), server, serverPublicKey, Version.V2).map { response ->
|
OnionRequestAPI.sendOnionRequest(request.build(), server, serverPublicKey, Version.V2).map { response ->
|
||||||
|
@ -91,7 +92,7 @@ object PushNotificationAPI {
|
||||||
if (!TextSecurePreferences.isUsingFCM(context)) { return }
|
if (!TextSecurePreferences.isUsingFCM(context)) { return }
|
||||||
val parameters = mapOf( "closedGroupPublicKey" to closedGroupPublicKey, "pubKey" to publicKey )
|
val parameters = mapOf( "closedGroupPublicKey" to closedGroupPublicKey, "pubKey" to publicKey )
|
||||||
val url = "$server/${operation.rawValue}"
|
val url = "$server/${operation.rawValue}"
|
||||||
val body = RequestBody.create(MediaType.get("application/json"), JsonUtil.toJson(parameters))
|
val body = RequestBody.create("application/json".toMediaType(), JsonUtil.toJson(parameters))
|
||||||
val request = Request.Builder().url(url).post(body)
|
val request = Request.Builder().url(url).post(body)
|
||||||
retryIfNeeded(maxRetryCount) {
|
retryIfNeeded(maxRetryCount) {
|
||||||
OnionRequestAPI.sendOnionRequest(request.build(), server, serverPublicKey, Version.V2).map { response ->
|
OnionRequestAPI.sendOnionRequest(request.build(), server, serverPublicKey, Version.V2).map { response ->
|
||||||
|
|
|
@ -466,9 +466,11 @@ object OnionRequestAPI {
|
||||||
x25519PublicKey: String,
|
x25519PublicKey: String,
|
||||||
version: Version = Version.V4
|
version: Version = Version.V4
|
||||||
): Promise<OnionResponse, Exception> {
|
): Promise<OnionResponse, Exception> {
|
||||||
val url = request.url()
|
val url = request.url
|
||||||
val payload = generatePayload(request, server, version)
|
val payload = generatePayload(request, server, version)
|
||||||
val destination = Destination.Server(url.host(), version.value, x25519PublicKey, url.scheme(), url.port())
|
val destination = Destination.Server(url.host, version.value, x25519PublicKey,
|
||||||
|
url.scheme, url.port
|
||||||
|
)
|
||||||
return sendOnionRequest(destination, payload, version).recover { exception ->
|
return sendOnionRequest(destination, payload, version).recover { exception ->
|
||||||
Log.d("Loki", "Couldn't reach server: $url due to error: $exception.")
|
Log.d("Loki", "Couldn't reach server: $url due to error: $exception.")
|
||||||
throw exception
|
throw exception
|
||||||
|
@ -477,7 +479,7 @@ object OnionRequestAPI {
|
||||||
|
|
||||||
private fun generatePayload(request: Request, server: String, version: Version): ByteArray {
|
private fun generatePayload(request: Request, server: String, version: Version): ByteArray {
|
||||||
val headers = request.getHeadersForOnionRequest().toMutableMap()
|
val headers = request.getHeadersForOnionRequest().toMutableMap()
|
||||||
val url = request.url()
|
val url = request.url
|
||||||
val urlAsString = url.toString()
|
val urlAsString = url.toString()
|
||||||
val body = request.getBodyForOnionRequest() ?: "null"
|
val body = request.getBodyForOnionRequest() ?: "null"
|
||||||
val endpoint = when {
|
val endpoint = when {
|
||||||
|
@ -485,19 +487,19 @@ object OnionRequestAPI {
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
return if (version == Version.V4) {
|
return if (version == Version.V4) {
|
||||||
if (request.body() != null &&
|
if (request.body != null &&
|
||||||
headers.keys.find { it.equals("Content-Type", true) } == null) {
|
headers.keys.find { it.equals("Content-Type", true) } == null) {
|
||||||
headers["Content-Type"] = "application/json"
|
headers["Content-Type"] = "application/json"
|
||||||
}
|
}
|
||||||
val requestPayload = mapOf(
|
val requestPayload = mapOf(
|
||||||
"endpoint" to endpoint,
|
"endpoint" to endpoint,
|
||||||
"method" to request.method(),
|
"method" to request.method,
|
||||||
"headers" to headers
|
"headers" to headers
|
||||||
)
|
)
|
||||||
val requestData = JsonUtil.toJson(requestPayload).toByteArray()
|
val requestData = JsonUtil.toJson(requestPayload).toByteArray()
|
||||||
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 = if (body is ByteArray) body else 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
|
||||||
|
@ -508,7 +510,7 @@ object OnionRequestAPI {
|
||||||
val payload = mapOf(
|
val payload = mapOf(
|
||||||
"body" to body,
|
"body" to body,
|
||||||
"endpoint" to endpoint.removePrefix("/"),
|
"endpoint" to endpoint.removePrefix("/"),
|
||||||
"method" to request.method(),
|
"method" to request.method,
|
||||||
"headers" to headers
|
"headers" to headers
|
||||||
)
|
)
|
||||||
JsonUtil.toJson(payload).toByteArray()
|
JsonUtil.toJson(payload).toByteArray()
|
||||||
|
|
|
@ -9,11 +9,11 @@ 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>()
|
||||||
val contentType = body()?.contentType()
|
val contentType = body?.contentType()
|
||||||
if (contentType != null) {
|
if (contentType != null) {
|
||||||
result["content-type"] = contentType.toString()
|
result["content-type"] = contentType.toString()
|
||||||
}
|
}
|
||||||
val headers = headers()
|
val headers = headers
|
||||||
for (name in headers.names()) {
|
for (name in headers.names()) {
|
||||||
val value = headers.get(name)
|
val value = headers.get(name)
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
@ -33,7 +33,7 @@ internal fun Request.getBodyForOnionRequest(): Any? {
|
||||||
try {
|
try {
|
||||||
val copyOfThis = newBuilder().build()
|
val copyOfThis = newBuilder().build()
|
||||||
val buffer = Buffer()
|
val buffer = Buffer()
|
||||||
val body = copyOfThis.body() ?: return null
|
val body = copyOfThis.body ?: return null
|
||||||
body.writeTo(buffer)
|
body.writeTo(buffer)
|
||||||
val bodyAsData = buffer.readByteArray()
|
val bodyAsData = buffer.readByteArray()
|
||||||
if (body is MultipartBody) {
|
if (body is MultipartBody) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.session.libsession.utilities
|
package org.session.libsession.utilities
|
||||||
|
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.session.libsession.messaging.file_server.FileServerApi
|
import org.session.libsession.messaging.file_server.FileServerApi
|
||||||
import org.session.libsignal.utilities.HTTP
|
import org.session.libsignal.utilities.HTTP
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
@ -34,8 +35,8 @@ object DownloadUtilities {
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun downloadFile(outputStream: OutputStream, urlAsString: String) {
|
fun downloadFile(outputStream: OutputStream, urlAsString: String) {
|
||||||
val url = HttpUrl.parse(urlAsString)!!
|
val url = urlAsString.toHttpUrlOrNull()!!
|
||||||
val fileID = url.pathSegments().last()
|
val fileID = url.pathSegments.last()
|
||||||
try {
|
try {
|
||||||
FileServerApi.download(fileID).get().let {
|
FileServerApi.download(fileID).get().let {
|
||||||
outputStream.write(it)
|
outputStream.write(it)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.session.libsession.utilities
|
package org.session.libsession.utilities
|
||||||
|
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import org.session.libsession.messaging.open_groups.migrateLegacyServerUrl
|
import org.session.libsession.messaging.open_groups.migrateLegacyServerUrl
|
||||||
|
|
||||||
object OpenGroupUrlParser {
|
object OpenGroupUrlParser {
|
||||||
|
@ -19,10 +20,10 @@ object OpenGroupUrlParser {
|
||||||
// URL has to start with 'http://'
|
// URL has to start with 'http://'
|
||||||
val urlWithPrefix = if (!string.startsWith("http")) "http://$string" else string
|
val urlWithPrefix = if (!string.startsWith("http")) "http://$string" else string
|
||||||
// If the URL is malformed, throw an exception
|
// If the URL is malformed, throw an exception
|
||||||
val url = HttpUrl.parse(urlWithPrefix) ?: throw Error.MalformedURL
|
val url = urlWithPrefix.toHttpUrlOrNull() ?: throw Error.MalformedURL
|
||||||
// Parse components
|
// Parse components
|
||||||
val server = HttpUrl.Builder().scheme(url.scheme()).host(url.host()).port(url.port()).build().toString().removeSuffix(suffix).migrateLegacyServerUrl()
|
val server = HttpUrl.Builder().scheme(url.scheme).host(url.host).port(url.port).build().toString().removeSuffix(suffix).migrateLegacyServerUrl()
|
||||||
val room = url.pathSegments().firstOrNull { !it.isNullOrEmpty() } ?: throw Error.NoRoom
|
val room = url.pathSegments.firstOrNull { !it.isNullOrEmpty() } ?: throw Error.NoRoom
|
||||||
val publicKey = url.queryParameter(queryPrefix) ?: throw Error.NoPublicKey
|
val publicKey = url.queryParameter(queryPrefix) ?: throw Error.NoPublicKey
|
||||||
if (publicKey.length != 64) throw Error.InvalidPublicKey
|
if (publicKey.length != 64) throw Error.InvalidPublicKey
|
||||||
// Return
|
// Return
|
||||||
|
|
|
@ -20,6 +20,7 @@ dependencies {
|
||||||
implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
|
implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
|
||||||
implementation "com.github.oxen-io.session-android-curve-25519:curve25519-java:$curve25519Version"
|
implementation "com.github.oxen-io.session-android-curve-25519:curve25519-java:$curve25519Version"
|
||||||
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
||||||
|
implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:$okhttpVersion"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package org.session.libsignal.utilities
|
package org.session.libsignal.utilities
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
import okhttp3.dnsoverhttps.DnsOverHttps
|
||||||
|
import java.net.InetAddress
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -15,7 +19,13 @@ object HTTP {
|
||||||
var isConnectedToNetwork: (() -> Boolean) = { false }
|
var isConnectedToNetwork: (() -> Boolean) = { false }
|
||||||
|
|
||||||
private val seedNodeConnection by lazy {
|
private val seedNodeConnection by lazy {
|
||||||
OkHttpClient().newBuilder()
|
val bootstrapClient = OkHttpClient.Builder().build()
|
||||||
|
val dns =DnsOverHttps.Builder().client(bootstrapClient)
|
||||||
|
.url("https://dns.quad9.net/dns-query".toHttpUrl())
|
||||||
|
.bootstrapDnsHosts(InetAddress.getByName("8.8.4.4"), InetAddress.getByName("8.8.8.8"))
|
||||||
|
.build()
|
||||||
|
bootstrapClient.newBuilder()
|
||||||
|
.dns(dns)
|
||||||
.callTimeout(timeout, TimeUnit.SECONDS)
|
.callTimeout(timeout, TimeUnit.SECONDS)
|
||||||
.connectTimeout(timeout, TimeUnit.SECONDS)
|
.connectTimeout(timeout, TimeUnit.SECONDS)
|
||||||
.readTimeout(timeout, TimeUnit.SECONDS)
|
.readTimeout(timeout, TimeUnit.SECONDS)
|
||||||
|
@ -33,7 +43,13 @@ object HTTP {
|
||||||
}
|
}
|
||||||
val sslContext = SSLContext.getInstance("SSL")
|
val sslContext = SSLContext.getInstance("SSL")
|
||||||
sslContext.init(null, arrayOf( trustManager ), SecureRandom())
|
sslContext.init(null, arrayOf( trustManager ), SecureRandom())
|
||||||
OkHttpClient().newBuilder()
|
val bootstrapClient = OkHttpClient.Builder().build()
|
||||||
|
val dns = DnsOverHttps.Builder().client(bootstrapClient)
|
||||||
|
.url("https://dns.quad9.net/dns-query".toHttpUrl())
|
||||||
|
.bootstrapDnsHosts(InetAddress.getByName("8.8.4.4"), InetAddress.getByName("8.8.8.8"))
|
||||||
|
.build()
|
||||||
|
bootstrapClient.newBuilder()
|
||||||
|
.dns(dns)
|
||||||
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
||||||
.hostnameVerifier { _, _ -> true }
|
.hostnameVerifier { _, _ -> true }
|
||||||
.callTimeout(timeout, TimeUnit.SECONDS)
|
.callTimeout(timeout, TimeUnit.SECONDS)
|
||||||
|
@ -53,7 +69,13 @@ object HTTP {
|
||||||
}
|
}
|
||||||
val sslContext = SSLContext.getInstance("SSL")
|
val sslContext = SSLContext.getInstance("SSL")
|
||||||
sslContext.init(null, arrayOf( trustManager ), SecureRandom())
|
sslContext.init(null, arrayOf( trustManager ), SecureRandom())
|
||||||
return OkHttpClient().newBuilder()
|
val bootstrapClient = OkHttpClient.Builder().build()
|
||||||
|
val dns =DnsOverHttps.Builder().client(bootstrapClient)
|
||||||
|
.url("https://dns.quad9.net/dns-query".toHttpUrl())
|
||||||
|
.bootstrapDnsHosts(InetAddress.getByName("8.8.4.4"), InetAddress.getByName("8.8.8.8"))
|
||||||
|
.build()
|
||||||
|
return bootstrapClient.newBuilder()
|
||||||
|
.dns(dns)
|
||||||
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
||||||
.hostnameVerifier { _, _ -> true }
|
.hostnameVerifier { _, _ -> true }
|
||||||
.callTimeout(timeout, TimeUnit.SECONDS)
|
.callTimeout(timeout, TimeUnit.SECONDS)
|
||||||
|
@ -106,7 +128,7 @@ object HTTP {
|
||||||
Verb.GET -> request.get()
|
Verb.GET -> request.get()
|
||||||
Verb.PUT, Verb.POST -> {
|
Verb.PUT, Verb.POST -> {
|
||||||
if (body == null) { throw Exception("Invalid request body.") }
|
if (body == null) { throw Exception("Invalid request body.") }
|
||||||
val contentType = MediaType.get("application/json; charset=utf-8")
|
val contentType = "application/json; charset=utf-8".toMediaType()
|
||||||
@Suppress("NAME_SHADOWING") val body = RequestBody.create(contentType, body)
|
@Suppress("NAME_SHADOWING") val body = RequestBody.create(contentType, body)
|
||||||
if (verb == Verb.PUT) request.put(body) else request.post(body)
|
if (verb == Verb.PUT) request.put(body) else request.post(body)
|
||||||
}
|
}
|
||||||
|
@ -131,9 +153,9 @@ object HTTP {
|
||||||
// Override the actual error so that we can correctly catch failed requests in OnionRequestAPI
|
// Override the actual error so that we can correctly catch failed requests in OnionRequestAPI
|
||||||
throw HTTPRequestFailedException(0, null, "HTTP request failed due to: ${exception.message}")
|
throw HTTPRequestFailedException(0, null, "HTTP request failed due to: ${exception.message}")
|
||||||
}
|
}
|
||||||
return when (val statusCode = response.code()) {
|
return when (val statusCode = response.code) {
|
||||||
200 -> {
|
200 -> {
|
||||||
response.body()?.bytes() ?: throw Exception("An error occurred.")
|
response.body?.bytes() ?: throw Exception("An error occurred.")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Log.d("Loki", "${verb.rawValue} request to $url failed with status code: $statusCode.")
|
Log.d("Loki", "${verb.rawValue} request to $url failed with status code: $statusCode.")
|
||||||
|
|
Loading…
Reference in a new issue