mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-26 15:18:19 +08:00
WIP integration with old SDK (not working)
This commit is contained in:
parent
3215fa47d5
commit
108fae2f28
Binary file not shown.
@ -5,9 +5,9 @@ import android.view.View
|
||||
import android.widget.Toast
|
||||
import im.vector.matrix.android.api.Matrix
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.platform.RiotActivity
|
||||
import im.vector.riotredesign.features.home.HomeActivity
|
||||
@ -17,7 +17,6 @@ import org.koin.android.ext.android.inject
|
||||
class LoginActivity : RiotActivity() {
|
||||
|
||||
private val matrix by inject<Matrix>()
|
||||
private val homeServerConnectionConfig = HomeServerConnectionConfig("https://matrix.org/")
|
||||
private val authenticator = matrix.authenticator()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@ -30,6 +29,11 @@ class LoginActivity : RiotActivity() {
|
||||
val login = loginField.text.trim().toString()
|
||||
val password = passwordField.text.trim().toString()
|
||||
progressBar.visibility = View.VISIBLE
|
||||
val homeServerConnectionConfig = HomeServerConnectionConfig.Builder()
|
||||
.withHomeServerUri("https://matrix.org/")
|
||||
.withIdentityServerUri("https://vector.im")
|
||||
.build()
|
||||
|
||||
authenticator.authenticate(homeServerConnectionConfig, login, password, object : MatrixCallback<Session> {
|
||||
override fun onSuccess(data: Session?) {
|
||||
matrix.currentSession = data
|
||||
|
@ -3,9 +3,6 @@ apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'io.objectbox'
|
||||
|
||||
ext.support_version = '28.0.0'
|
||||
ext.moshi_version = '1.7.0'
|
||||
|
||||
buildscript {
|
||||
|
||||
repositories {
|
||||
@ -43,6 +40,11 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
def arrow_version = "0.7.3"
|
||||
def support_version = '28.0.0'
|
||||
def moshi_version = '1.7.0'
|
||||
|
||||
implementation fileTree(dir: 'libs', include: ['*.aar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
@ -65,6 +67,8 @@ dependencies {
|
||||
// Paging
|
||||
implementation "android.arch.paging:runtime:1.0.1"
|
||||
|
||||
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
||||
|
||||
// DI
|
||||
implementation "org.koin:koin-core:$koin_version"
|
||||
implementation "org.koin:koin-core-ext:$koin_version"
|
||||
|
@ -4,50 +4,77 @@
|
||||
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
|
||||
"entities": [
|
||||
{
|
||||
"id": "3:213989653016909134",
|
||||
"lastPropertyId": "6:8192129106205548340",
|
||||
"id": "6:5991986256653472999",
|
||||
"lastPropertyId": "6:5675340775405504775",
|
||||
"name": "Credentials",
|
||||
"properties": [
|
||||
{
|
||||
"id": "1:3516672544602138732",
|
||||
"id": "1:904844404428661340",
|
||||
"name": "id"
|
||||
},
|
||||
{
|
||||
"id": "2:8457998089049891725",
|
||||
"indexId": "1:7573100044105293219",
|
||||
"id": "2:4962733318674873893",
|
||||
"name": "userId"
|
||||
},
|
||||
{
|
||||
"id": "3:878535388660167894",
|
||||
"id": "3:6496111157191804406",
|
||||
"name": "homeServer"
|
||||
},
|
||||
{
|
||||
"id": "4:7030303501035684102",
|
||||
"id": "4:6583709765305423919",
|
||||
"name": "accessToken"
|
||||
},
|
||||
{
|
||||
"id": "5:7193051897929077560",
|
||||
"id": "5:865976960498370870",
|
||||
"name": "refreshToken"
|
||||
},
|
||||
{
|
||||
"id": "6:8192129106205548340",
|
||||
"id": "6:5675340775405504775",
|
||||
"name": "deviceId"
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
},
|
||||
{
|
||||
"id": "7:6920598293865885979",
|
||||
"lastPropertyId": "3:5795529890406591571",
|
||||
"name": "ObjectBoxSessionParams",
|
||||
"properties": [
|
||||
{
|
||||
"id": "1:7073183456619398402",
|
||||
"name": "credentialsJson"
|
||||
},
|
||||
{
|
||||
"id": "2:8905537494398356078",
|
||||
"name": "homeServerConnectionConfigJson"
|
||||
},
|
||||
{
|
||||
"id": "3:5795529890406591571",
|
||||
"name": "id"
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
}
|
||||
],
|
||||
"lastEntityId": "3:213989653016909134",
|
||||
"lastIndexId": "1:7573100044105293219",
|
||||
"lastEntityId": "7:6920598293865885979",
|
||||
"lastIndexId": "4:1616715309690181473",
|
||||
"lastRelationId": "0:0",
|
||||
"lastSequenceId": "0:0",
|
||||
"modelVersion": 4,
|
||||
"modelVersionParserMinimum": 4,
|
||||
"retiredEntityUids": [
|
||||
637433444018824383,
|
||||
5577202525246066978
|
||||
5577202525246066978,
|
||||
213989653016909134,
|
||||
826321009570992494,
|
||||
1775102368193732759
|
||||
],
|
||||
"retiredIndexUids": [
|
||||
7573100044105293219,
|
||||
7664899561635023422,
|
||||
762622607983996029,
|
||||
1616715309690181473
|
||||
],
|
||||
"retiredIndexUids": [],
|
||||
"retiredPropertyUids": [
|
||||
6211403495341530846,
|
||||
1774175862476960436,
|
||||
@ -60,7 +87,25 @@
|
||||
8258973118557394726,
|
||||
4167129800901721265,
|
||||
4654729568692986907,
|
||||
958528673818813300
|
||||
958528673818813300,
|
||||
3516672544602138732,
|
||||
8457998089049891725,
|
||||
878535388660167894,
|
||||
7030303501035684102,
|
||||
7193051897929077560,
|
||||
8192129106205548340,
|
||||
7632656533038841948,
|
||||
1390065349267803135,
|
||||
6024884732066241356,
|
||||
3502558420506448922,
|
||||
3999645739247298623,
|
||||
8488502568193639300,
|
||||
594512591943458255,
|
||||
5113574037182501000,
|
||||
4929796643260285955,
|
||||
5690571528511905880,
|
||||
1811444397594387116,
|
||||
8817556524159529201
|
||||
],
|
||||
"retiredRelationUids": [],
|
||||
"version": 1
|
||||
|
@ -4,49 +4,76 @@
|
||||
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
|
||||
"entities": [
|
||||
{
|
||||
"id": "3:213989653016909134",
|
||||
"lastPropertyId": "6:8192129106205548340",
|
||||
"name": "Credentials",
|
||||
"id": "4:1775102368193732759",
|
||||
"lastPropertyId": "6:8817556524159529201",
|
||||
"name": "SessionParams",
|
||||
"properties": [
|
||||
{
|
||||
"id": "1:3516672544602138732",
|
||||
"id": "2:5690571528511905880",
|
||||
"name": "homeServerConnectionConfig"
|
||||
},
|
||||
{
|
||||
"id": "3:1811444397594387116",
|
||||
"name": "id"
|
||||
},
|
||||
{
|
||||
"id": "2:8457998089049891725",
|
||||
"id": "6:8817556524159529201",
|
||||
"indexId": "4:1616715309690181473",
|
||||
"name": "credentialsRelationId"
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
},
|
||||
{
|
||||
"id": "6:5991986256653472999",
|
||||
"lastPropertyId": "6:5675340775405504775",
|
||||
"name": "Credentials",
|
||||
"properties": [
|
||||
{
|
||||
"id": "1:904844404428661340",
|
||||
"name": "id"
|
||||
},
|
||||
{
|
||||
"id": "2:4962733318674873893",
|
||||
"name": "userId"
|
||||
},
|
||||
{
|
||||
"id": "3:878535388660167894",
|
||||
"id": "3:6496111157191804406",
|
||||
"name": "homeServer"
|
||||
},
|
||||
{
|
||||
"id": "4:7030303501035684102",
|
||||
"id": "4:6583709765305423919",
|
||||
"name": "accessToken"
|
||||
},
|
||||
{
|
||||
"id": "5:7193051897929077560",
|
||||
"id": "5:865976960498370870",
|
||||
"name": "refreshToken"
|
||||
},
|
||||
{
|
||||
"id": "6:8192129106205548340",
|
||||
"id": "6:5675340775405504775",
|
||||
"name": "deviceId"
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
}
|
||||
],
|
||||
"lastEntityId": "3:213989653016909134",
|
||||
"lastIndexId": "0:0",
|
||||
"lastEntityId": "6:5991986256653472999",
|
||||
"lastIndexId": "4:1616715309690181473",
|
||||
"lastRelationId": "0:0",
|
||||
"lastSequenceId": "0:0",
|
||||
"modelVersion": 4,
|
||||
"modelVersionParserMinimum": 4,
|
||||
"retiredEntityUids": [
|
||||
637433444018824383,
|
||||
5577202525246066978
|
||||
5577202525246066978,
|
||||
213989653016909134,
|
||||
826321009570992494
|
||||
],
|
||||
"retiredIndexUids": [
|
||||
7573100044105293219,
|
||||
7664899561635023422,
|
||||
762622607983996029
|
||||
],
|
||||
"retiredIndexUids": [],
|
||||
"retiredPropertyUids": [
|
||||
6211403495341530846,
|
||||
1774175862476960436,
|
||||
@ -59,7 +86,22 @@
|
||||
8258973118557394726,
|
||||
4167129800901721265,
|
||||
4654729568692986907,
|
||||
958528673818813300
|
||||
958528673818813300,
|
||||
3516672544602138732,
|
||||
8457998089049891725,
|
||||
878535388660167894,
|
||||
7030303501035684102,
|
||||
7193051897929077560,
|
||||
8192129106205548340,
|
||||
7632656533038841948,
|
||||
1390065349267803135,
|
||||
6024884732066241356,
|
||||
3502558420506448922,
|
||||
3999645739247298623,
|
||||
8488502568193639300,
|
||||
594512591943458255,
|
||||
5113574037182501000,
|
||||
4929796643260285955
|
||||
],
|
||||
"retiredRelationUids": [],
|
||||
"version": 1
|
||||
|
@ -1,11 +0,0 @@
|
||||
package im.vector.matrix.android.api.auth
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials
|
||||
|
||||
interface CredentialsStore {
|
||||
|
||||
fun get(): Credentials?
|
||||
|
||||
fun save(credentials: Credentials)
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package im.vector.matrix.android.api.auth
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||
|
||||
interface SessionParamsStore {
|
||||
|
||||
fun get(): SessionParams?
|
||||
|
||||
fun save(sessionParams: SessionParams)
|
||||
|
||||
}
|
@ -1,9 +1,225 @@
|
||||
package im.vector.matrix.android.api.auth.data
|
||||
|
||||
import android.net.Uri
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.internal.network.ssl.Fingerprint
|
||||
import okhttp3.CipherSuite
|
||||
import okhttp3.TlsVersion
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class HomeServerConnectionConfig(
|
||||
// the home server URI
|
||||
val hsUri: String
|
||||
)
|
||||
val homeServerUri: Uri,
|
||||
val identityServerUri: Uri,
|
||||
val antiVirusServerUri: Uri? = null,
|
||||
val allowedFingerprints: MutableList<Fingerprint> = ArrayList(),
|
||||
val shouldPin: Boolean = false,
|
||||
val tlsVersions: MutableList<TlsVersion>? = null,
|
||||
val tlsCipherSuites: MutableList<CipherSuite>? = null,
|
||||
val shouldAcceptTlsExtensions: Boolean = true,
|
||||
val allowHttpExtension: Boolean = false,
|
||||
val forceUsageTlsVersions: Boolean = false
|
||||
) {
|
||||
|
||||
class Builder {
|
||||
|
||||
private lateinit var homeServerUri: Uri
|
||||
private lateinit var identityServerUri: Uri
|
||||
private var antiVirusServerUri: Uri? = null
|
||||
private val allowedFingerprints: MutableList<Fingerprint> = ArrayList()
|
||||
private var shouldPin: Boolean = false
|
||||
private val tlsVersions: MutableList<TlsVersion> = ArrayList()
|
||||
private val tlsCipherSuites: MutableList<CipherSuite> = ArrayList()
|
||||
private var shouldAcceptTlsExtensions: Boolean = true
|
||||
private var allowHttpExtension: Boolean = false
|
||||
private var forceUsageTlsVersions: Boolean = false
|
||||
|
||||
fun withHomeServerUri(hsUriString: String): Builder {
|
||||
return withHomeServerUri(Uri.parse(hsUriString))
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hsUri The URI to use to connect to the homeserver.
|
||||
* @return this builder
|
||||
*/
|
||||
fun withHomeServerUri(hsUri: Uri): Builder {
|
||||
if (hsUri.scheme != "http" && hsUri.scheme != "https") {
|
||||
throw RuntimeException("Invalid home server URI: " + hsUri!!)
|
||||
}
|
||||
// remove trailing /
|
||||
homeServerUri = if (hsUri.toString().endsWith("/")) {
|
||||
try {
|
||||
val url = hsUri.toString()
|
||||
Uri.parse(url.substring(0, url.length - 1))
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException("Invalid home server URI: $hsUri")
|
||||
}
|
||||
} else {
|
||||
hsUri
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun withIdentityServerUri(identityServerUriString: String): Builder {
|
||||
return withIdentityServerUri(Uri.parse(identityServerUriString))
|
||||
}
|
||||
|
||||
/**
|
||||
* @param identityServerUri The URI to use to manage identity.
|
||||
* @return this builder
|
||||
*/
|
||||
fun withIdentityServerUri(identityServerUri: Uri): Builder {
|
||||
if (identityServerUri.scheme != "http" && identityServerUri.scheme != "https") {
|
||||
throw RuntimeException("Invalid identity server URI: $identityServerUri")
|
||||
}
|
||||
// remove trailing /
|
||||
if (identityServerUri.toString().endsWith("/")) {
|
||||
try {
|
||||
val url = identityServerUri.toString()
|
||||
this.identityServerUri = Uri.parse(url.substring(0, url.length - 1))
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException("Invalid identity server URI: $identityServerUri")
|
||||
}
|
||||
} else {
|
||||
this.identityServerUri = identityServerUri
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* @param allowedFingerprints If using SSL, allow server certs that match these fingerprints.
|
||||
* @return this builder
|
||||
*/
|
||||
fun withAllowedFingerPrints(allowedFingerprints: List<Fingerprint>?): Builder {
|
||||
if (allowedFingerprints != null) {
|
||||
this.allowedFingerprints.addAll(allowedFingerprints)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pin If true only allow certs matching given fingerprints, otherwise fallback to
|
||||
* standard X509 checks.
|
||||
* @return this builder
|
||||
*/
|
||||
fun withPin(pin: Boolean): Builder {
|
||||
this.shouldPin = pin
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shouldAcceptTlsExtension
|
||||
* @return this builder
|
||||
*/
|
||||
fun withShouldAcceptTlsExtensions(shouldAcceptTlsExtension: Boolean): Builder {
|
||||
this.shouldAcceptTlsExtensions = shouldAcceptTlsExtension
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an accepted TLS version for TLS connections with the home server.
|
||||
*
|
||||
* @param tlsVersion the tls version to add to the set of TLS versions accepted.
|
||||
* @return this builder
|
||||
*/
|
||||
fun addAcceptedTlsVersion(tlsVersion: TlsVersion): Builder {
|
||||
this.tlsVersions.add(tlsVersion)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the usage of TlsVersion. This can be usefull for device on Android version < 20
|
||||
*
|
||||
* @param forceUsageOfTlsVersions set to true to force the usage of specified TlsVersions (with [.addAcceptedTlsVersion]
|
||||
* @return this builder
|
||||
*/
|
||||
fun forceUsageOfTlsVersions(forceUsageOfTlsVersions: Boolean): Builder {
|
||||
this.forceUsageTlsVersions = forceUsageOfTlsVersions
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a TLS cipher suite to the list of accepted TLS connections with the home server.
|
||||
*
|
||||
* @param tlsCipherSuite the tls cipher suite to add.
|
||||
* @return this builder
|
||||
*/
|
||||
fun addAcceptedTlsCipherSuite(tlsCipherSuite: CipherSuite): Builder {
|
||||
this.tlsCipherSuites.add(tlsCipherSuite)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the anti-virus server URI.
|
||||
*
|
||||
* @param antivirusServerUri the new anti-virus uri. Can be null
|
||||
* @return this builder
|
||||
*/
|
||||
fun withAntiVirusServerUri(antivirusServerUri: Uri?): Builder {
|
||||
if (null != antivirusServerUri && "http" != antivirusServerUri.scheme && "https" != antivirusServerUri.scheme) {
|
||||
throw RuntimeException("Invalid antivirus server URI: $antivirusServerUri")
|
||||
}
|
||||
this.antiVirusServerUri = antivirusServerUri
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method to limit the TLS versions and cipher suites for this Builder
|
||||
* Ref:
|
||||
* - https://www.ssi.gouv.fr/uploads/2017/02/security-recommendations-for-tls_v1.1.pdf
|
||||
* - https://developer.android.com/reference/javax/net/ssl/SSLEngine
|
||||
*
|
||||
* @param tlsLimitations true to use Tls limitations
|
||||
* @param enableCompatibilityMode set to true for Android < 20
|
||||
* @return this builder
|
||||
*/
|
||||
fun withTlsLimitations(tlsLimitations: Boolean, enableCompatibilityMode: Boolean): Builder {
|
||||
if (tlsLimitations) {
|
||||
withShouldAcceptTlsExtensions(false)
|
||||
|
||||
// Tls versions
|
||||
addAcceptedTlsVersion(TlsVersion.TLS_1_2)
|
||||
addAcceptedTlsVersion(TlsVersion.TLS_1_3)
|
||||
|
||||
forceUsageOfTlsVersions(enableCompatibilityMode)
|
||||
|
||||
// Cipher suites
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256)
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||
|
||||
if (enableCompatibilityMode) {
|
||||
// Adopt some preceding cipher suites for Android < 20 to be able to negotiate
|
||||
// a TLS session.
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun withAllowHttpConnection(allowHttpExtension: Boolean): Builder {
|
||||
this.allowHttpExtension = allowHttpExtension
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the [HomeServerConnectionConfig]
|
||||
*/
|
||||
fun build(): HomeServerConnectionConfig {
|
||||
return HomeServerConnectionConfig(homeServerUri, identityServerUri, antiVirusServerUri, allowedFingerprints, shouldPin, tlsVersions, tlsCipherSuites, shouldAcceptTlsExtensions, allowHttpExtension, forceUsageTlsVersions)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
package im.vector.matrix.android.api.events
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Event(
|
||||
@ -14,4 +16,14 @@ data class Event(
|
||||
@Json(name = "state_key") val stateKey: String? = null,
|
||||
@Json(name = "room_id") val roomId: String? = null,
|
||||
@Json(name = "unsigned_data") val unsignedData: UnsignedData? = null
|
||||
)
|
||||
){
|
||||
|
||||
fun contentAsJsonObject(): JsonObject? {
|
||||
return JsonUtils.toJson(content)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,43 +1,42 @@
|
||||
package im.vector.matrix.android.api.events
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
|
||||
object EventType {
|
||||
|
||||
enum class EventType {
|
||||
|
||||
@Json(name ="m.presence") PRESENCE,
|
||||
@Json(name ="m.room.message") MESSAGE,
|
||||
@Json(name ="m.sticker") STICKER,
|
||||
@Json(name ="m.room.encrypted") ENCRYPTED,
|
||||
@Json(name ="m.room.encryption") ENCRYPTION,
|
||||
@Json(name ="m.room.message.feedback") FEEDBACK,
|
||||
@Json(name ="m.typing") TYPING,
|
||||
@Json(name ="m.room.redaction") REDACTION,
|
||||
@Json(name ="m.receipt") RECEIPT,
|
||||
@Json(name ="m.tag") TAG,
|
||||
@Json(name ="m.room_key") ROOM_KEY,
|
||||
@Json(name ="m.fully_read") FULLY_READ,
|
||||
@Json(name ="m.room.plumbing") PLUMBING,
|
||||
@Json(name ="m.room.bot.options") BOT_OPTIONS,
|
||||
@Json(name ="m.room_key_request") KEY_REQUEST,
|
||||
@Json(name ="m.forwarded_room_key") FORWARDED_ROOM_KEY,
|
||||
@Json(name ="org.matrix.room.preview_urls") PREVIEW_URLS,
|
||||
const val PRESENCE = "m.presence"
|
||||
const val MESSAGE = "m.room.message"
|
||||
const val STICKER = "m.sticker"
|
||||
const val ENCRYPTED = "m.room.encrypted"
|
||||
const val ENCRYPTION = "m.room.encryption"
|
||||
const val FEEDBACK = "m.room.message.feedback"
|
||||
const val TYPING = "m.typing"
|
||||
const val REDACTION = "m.room.redaction"
|
||||
const val RECEIPT = "m.receipt"
|
||||
const val TAG = "m.tag"
|
||||
const val ROOM_KEY = "m.room_key"
|
||||
const val FULLY_READ = "m.fully_read"
|
||||
const val PLUMBING = "m.room.plumbing"
|
||||
const val BOT_OPTIONS = "m.room.bot.options"
|
||||
const val KEY_REQUEST = "m.room_key_request"
|
||||
const val FORWARDED_ROOM_KEY = "m.forwarded_room_key"
|
||||
const val PREVIEW_URLS = "org.matrix.room.preview_urls"
|
||||
|
||||
// State Events
|
||||
@Json(name ="m.room.name") STATE_ROOM_NAME,
|
||||
@Json(name ="m.room.topic") STATE_ROOM_TOPIC,
|
||||
@Json(name ="m.room.avatar") STATE_ROOM_AVATAR,
|
||||
@Json(name ="m.room.member") STATE_ROOM_MEMBER,
|
||||
@Json(name ="m.room.third_party_invite") STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
@Json(name ="m.room.create") STATE_ROOM_CREATE,
|
||||
@Json(name ="m.room.join_rules") STATE_ROOM_JOIN_RULES,
|
||||
@Json(name ="m.room.guest_access") STATE_ROOM_GUEST_ACCESS,
|
||||
@Json(name ="m.room.power_levels") STATE_ROOM_POWER_LEVELS,
|
||||
@Json(name ="m.room.aliases") STATE_ROOM_ALIASES,
|
||||
@Json(name ="m.room.tombstone") STATE_ROOM_TOMBSTONE,
|
||||
@Json(name ="m.room.canonical_alias") STATE_CANONICAL_ALIAS,
|
||||
@Json(name ="m.room.history_visibility") STATE_HISTORY_VISIBILITY,
|
||||
@Json(name ="m.room.related_groups") STATE_RELATED_GROUPS,
|
||||
@Json(name ="m.room.pinned_events") STATE_PINNED_EVENT
|
||||
|
||||
const val STATE_ROOM_NAME = "m.room.name"
|
||||
const val STATE_ROOM_TOPIC = "m.room.topic"
|
||||
const val STATE_ROOM_AVATAR = "m.room.avatar"
|
||||
const val STATE_ROOM_MEMBER = "m.room.member"
|
||||
const val STATE_ROOM_THIRD_PARTY_INVITE = "m.room.third_party_invite"
|
||||
const val STATE_ROOM_CREATE = "m.room.create"
|
||||
const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
|
||||
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
||||
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
||||
const val STATE_ROOM_ALIASES = "m.room.aliases"
|
||||
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
||||
const val STATE_CANONICAL_ALIAS = "m.room.canonical_alias"
|
||||
const val STATE_HISTORY_VISIBILITY = "m.room.history_visibility"
|
||||
const val STATE_RELATED_GROUPS = "m.room.related_groups"
|
||||
const val STATE_PINNED_EVENT = "m.room.pinned_events"
|
||||
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
package im.vector.matrix.android.api.rooms
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Invite(
|
||||
@Json(name = "display_name") val displayName: String,
|
||||
@Json(name = "signed") val signed: Signed
|
||||
|
@ -1,12 +1,15 @@
|
||||
package im.vector.matrix.android.api.rooms
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.events.UnsignedData
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RoomMember(
|
||||
val membership: Membership,
|
||||
val displayDame: String? = null,
|
||||
val avatarUrl: String? = null,
|
||||
val isDirect: Boolean = false,
|
||||
val thirdPartyInvite: Invite? = null,
|
||||
val unsignedData: UnsignedData? = null
|
||||
@Json(name = "membership") val membership: Membership,
|
||||
@Json(name = "display_name") val displayDame: String? = null,
|
||||
@Json(name = "avatar_url") val avatarUrl: String? = null,
|
||||
@Json(name = "is_direct") val isDirect: Boolean = false,
|
||||
@Json(name = "third_party_invite") val thirdPartyInvite: Invite? = null,
|
||||
@Json(name = "unsigned_data") val unsignedData: UnsignedData? = null
|
||||
)
|
||||
|
@ -2,10 +2,10 @@ package im.vector.matrix.android.internal.auth
|
||||
|
||||
import android.content.Context
|
||||
import im.vector.matrix.android.api.auth.Authenticator
|
||||
import im.vector.matrix.android.api.auth.CredentialsStore
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials
|
||||
import im.vector.matrix.android.internal.auth.data.MyObjectBox
|
||||
import im.vector.matrix.android.internal.auth.db.ObjectBoxCredentialsStore
|
||||
import im.vector.matrix.android.api.auth.SessionParamsStore
|
||||
import im.vector.matrix.android.internal.auth.db.ObjectBoxSessionParams
|
||||
import im.vector.matrix.android.internal.auth.db.ObjectBoxSessionParamsMapper
|
||||
import im.vector.matrix.android.internal.auth.db.ObjectBoxSessionParamsStore
|
||||
import io.objectbox.Box
|
||||
import io.objectbox.BoxStore
|
||||
import org.koin.dsl.context.ModuleDefinition
|
||||
@ -26,13 +26,14 @@ class AuthModule(private val context: Context) : Module {
|
||||
MyObjectBox.builder().androidContext(context).build()
|
||||
}
|
||||
|
||||
|
||||
single {
|
||||
val boxStore = get(name = AUTH_BOX_STORE) as BoxStore
|
||||
boxStore.boxFor(Credentials::class.java) as Box<Credentials>
|
||||
boxStore.boxFor(ObjectBoxSessionParams::class.java) as Box<ObjectBoxSessionParams>
|
||||
}
|
||||
|
||||
single {
|
||||
ObjectBoxCredentialsStore(get()) as CredentialsStore
|
||||
ObjectBoxSessionParamsStore(ObjectBoxSessionParamsMapper((get())), get()) as SessionParamsStore
|
||||
}
|
||||
|
||||
}.invoke()
|
||||
|
@ -1,19 +1,21 @@
|
||||
package im.vector.matrix.android.internal.auth
|
||||
|
||||
import arrow.core.leftIfNull
|
||||
import com.squareup.moshi.Moshi
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.auth.Authenticator
|
||||
import im.vector.matrix.android.api.auth.CredentialsStore
|
||||
import im.vector.matrix.android.api.auth.SessionParamsStore
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.internal.session.DefaultSession
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials
|
||||
import im.vector.matrix.android.internal.auth.data.PasswordLoginParams
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.session.DefaultSession
|
||||
import im.vector.matrix.android.internal.util.CancelableCoroutine
|
||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||
import im.vector.matrix.android.internal.util.map
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import retrofit2.Retrofit
|
||||
@ -21,28 +23,34 @@ import retrofit2.Retrofit
|
||||
class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder,
|
||||
private val jsonMapper: Moshi,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val credentialsStore: CredentialsStore) : Authenticator {
|
||||
private val sessionParamsStore: SessionParamsStore) : Authenticator {
|
||||
|
||||
override fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig, login: String, password: String, callback: MatrixCallback<Session>): Cancelable {
|
||||
val authAPI = buildAuthAPI(homeServerConnectionConfig)
|
||||
|
||||
val job = GlobalScope.launch(coroutineDispatchers.main) {
|
||||
val loginParams = PasswordLoginParams.userIdentifier(login, password, "Mobile")
|
||||
val loginResult = executeRequest<Credentials> {
|
||||
executeRequest<Credentials> {
|
||||
apiCall = authAPI.login(loginParams)
|
||||
moshi = jsonMapper
|
||||
dispatcher = coroutineDispatchers.io
|
||||
}.leftIfNull {
|
||||
Failure.Unknown(IllegalArgumentException("Credentials shouldn't not be null"))
|
||||
}.map {
|
||||
it?.apply { credentialsStore.save(it) }
|
||||
val sessionParams = SessionParams(it, homeServerConnectionConfig)
|
||||
sessionParamsStore.save(sessionParams)
|
||||
sessionParams
|
||||
}.map {
|
||||
DefaultSession(homeServerConnectionConfig)
|
||||
}
|
||||
loginResult.either({ callback.onFailure(it) }, { callback.onSuccess(it) })
|
||||
DefaultSession(it)
|
||||
}.bimap(
|
||||
{ callback.onFailure(it) }, { callback.onSuccess(it) }
|
||||
)
|
||||
}
|
||||
return CancelableCoroutine(job)
|
||||
}
|
||||
|
||||
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {
|
||||
val retrofit = retrofitBuilder.baseUrl(homeServerConnectionConfig.hsUri).build()
|
||||
val retrofit = retrofitBuilder.baseUrl(homeServerConnectionConfig.homeServerUri.toString()).build()
|
||||
return retrofit.create(AuthAPI::class.java)
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,12 @@ import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import io.objectbox.annotation.Index
|
||||
|
||||
@Entity
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Entity
|
||||
data class Credentials(
|
||||
@Id var id: Long = 0,
|
||||
@Index @Json(name = "user_id") val userId: String,
|
||||
@Json(name = "user_id") val userId: String,
|
||||
@Json(name = "home_server") val homeServer: String,
|
||||
@Json(name = "access_token") val accessToken: String,
|
||||
@Json(name = "refresh_token") val refreshToken: String?,
|
||||
|
@ -0,0 +1,8 @@
|
||||
package im.vector.matrix.android.internal.auth.data
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
|
||||
data class SessionParams(
|
||||
val credentials: Credentials,
|
||||
val homeServerConnectionConfig: HomeServerConnectionConfig
|
||||
)
|
@ -1,17 +0,0 @@
|
||||
package im.vector.matrix.android.internal.auth.db
|
||||
|
||||
import im.vector.matrix.android.api.auth.CredentialsStore
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials
|
||||
import io.objectbox.Box
|
||||
|
||||
class ObjectBoxCredentialsStore(private val box: Box<Credentials>) : CredentialsStore {
|
||||
|
||||
override fun save(credentials: Credentials) {
|
||||
box.put(credentials)
|
||||
}
|
||||
|
||||
override fun get(): Credentials? {
|
||||
return box.all.lastOrNull()
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package im.vector.matrix.android.internal.auth.db
|
||||
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
@Entity
|
||||
data class ObjectBoxSessionParams(
|
||||
val credentialsJson: String,
|
||||
val homeServerConnectionConfigJson: String,
|
||||
@Id var id: Long = 0
|
||||
)
|
@ -0,0 +1,38 @@
|
||||
package im.vector.matrix.android.internal.auth.db
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||
|
||||
class ObjectBoxSessionParamsMapper(moshi: Moshi) {
|
||||
|
||||
private val credentialsAdapter = moshi.adapter(Credentials::class.java)
|
||||
private val homeServerConnectionConfigAdapter = moshi.adapter(HomeServerConnectionConfig::class.java)
|
||||
|
||||
fun map(objectBoxSessionParams: ObjectBoxSessionParams?): SessionParams? {
|
||||
if (objectBoxSessionParams == null) {
|
||||
return null
|
||||
}
|
||||
val credentials = credentialsAdapter.fromJson(objectBoxSessionParams.credentialsJson)
|
||||
val homeServerConnectionConfig = homeServerConnectionConfigAdapter.fromJson(objectBoxSessionParams.homeServerConnectionConfigJson)
|
||||
if (credentials == null || homeServerConnectionConfig == null) {
|
||||
return null
|
||||
}
|
||||
return SessionParams(credentials, homeServerConnectionConfig)
|
||||
}
|
||||
|
||||
fun map(sessionParams: SessionParams?): ObjectBoxSessionParams? {
|
||||
if (sessionParams == null) {
|
||||
return null
|
||||
}
|
||||
val credentialsJson = credentialsAdapter.toJson(sessionParams.credentials)
|
||||
val homeServerConnectionConfigJson = homeServerConnectionConfigAdapter.toJson(sessionParams.homeServerConnectionConfig)
|
||||
if (credentialsJson == null || homeServerConnectionConfigJson == null) {
|
||||
return null
|
||||
}
|
||||
return ObjectBoxSessionParams(credentialsJson, homeServerConnectionConfigJson)
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package im.vector.matrix.android.internal.auth.db
|
||||
|
||||
import im.vector.matrix.android.api.auth.SessionParamsStore
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||
import io.objectbox.Box
|
||||
|
||||
class ObjectBoxSessionParamsStore(private val mapper: ObjectBoxSessionParamsMapper,
|
||||
private val box: Box<ObjectBoxSessionParams>) : SessionParamsStore {
|
||||
|
||||
override fun save(sessionParams: SessionParams) {
|
||||
val objectBoxSessionParams = mapper.map(sessionParams)
|
||||
objectBoxSessionParams?.let {
|
||||
box.put(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun get(): SessionParams? {
|
||||
return box.all.map { mapper.map(it) }.lastOrNull()
|
||||
}
|
||||
|
||||
}
|
@ -14,6 +14,10 @@ class MatrixModule(private val options: MatrixOptions) : Module {
|
||||
|
||||
override fun invoke(): ModuleDefinition = module {
|
||||
|
||||
single {
|
||||
options.context
|
||||
}
|
||||
|
||||
single {
|
||||
MatrixCoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.IO, main = options.mainExecutor.asCoroutineDispatcher())
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package im.vector.matrix.android.internal.di
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
|
||||
object MoshiProvider {
|
||||
|
||||
private val moshi: Moshi = Moshi.Builder().build()
|
||||
|
||||
fun providesMoshi(): Moshi {
|
||||
return moshi
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package im.vector.matrix.android.internal.di
|
||||
|
||||
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
|
||||
import com.squareup.moshi.Moshi
|
||||
import im.vector.matrix.android.internal.network.AccessTokenInterceptor
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
@ -25,7 +24,7 @@ class NetworkModule : Module {
|
||||
|
||||
single {
|
||||
val logger = HttpLoggingInterceptor.Logger { message -> Timber.v(message) }
|
||||
HttpLoggingInterceptor(logger).apply { level = HttpLoggingInterceptor.Level.BODY }
|
||||
HttpLoggingInterceptor(logger).apply { level = HttpLoggingInterceptor.Level.BASIC }
|
||||
}
|
||||
|
||||
single {
|
||||
@ -39,7 +38,7 @@ class NetworkModule : Module {
|
||||
}
|
||||
|
||||
single {
|
||||
Moshi.Builder().build()
|
||||
MoshiProvider.providesMoshi()
|
||||
}
|
||||
|
||||
single {
|
||||
|
@ -1,20 +1,32 @@
|
||||
package im.vector.matrix.android.internal.di
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||
import im.vector.matrix.android.internal.legacy.MXDataHandler
|
||||
import im.vector.matrix.android.internal.legacy.MXSession
|
||||
import im.vector.matrix.android.internal.legacy.data.store.MXFileStore
|
||||
import im.vector.matrix.android.internal.session.DefaultSession
|
||||
import org.koin.dsl.context.ModuleDefinition
|
||||
import org.koin.dsl.module.Module
|
||||
import org.koin.dsl.module.module
|
||||
import retrofit2.Retrofit
|
||||
|
||||
class SessionModule(private val connectionConfig: HomeServerConnectionConfig) : Module {
|
||||
class SessionModule(private val sessionParams: SessionParams) : Module {
|
||||
|
||||
override fun invoke(): ModuleDefinition = module(override = true) {
|
||||
scope(DefaultSession.SCOPE) {
|
||||
val retrofitBuilder = get() as Retrofit.Builder
|
||||
retrofitBuilder
|
||||
.baseUrl(connectionConfig.hsUri)
|
||||
.baseUrl(sessionParams.homeServerConnectionConfig?.homeServerUri.toString())
|
||||
.build()
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
val store = MXFileStore(sessionParams.credentials, false, get())
|
||||
val dataHandler = MXDataHandler(store, sessionParams.credentials)
|
||||
MXSession.Builder(sessionParams, dataHandler, get()).build()
|
||||
}
|
||||
|
||||
}.invoke()
|
||||
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,11 @@ class SyncModule : Module {
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
Synchronizer(get(), get(), get())
|
||||
SyncResponseHandler(get(), get())
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
Synchronizer(get(), get(), get(), get())
|
||||
}
|
||||
|
||||
}.invoke()
|
||||
|
@ -0,0 +1,523 @@
|
||||
package im.vector.matrix.android.internal.events.sync
|
||||
|
||||
import android.text.TextUtils
|
||||
import im.vector.matrix.android.api.events.Event
|
||||
import im.vector.matrix.android.internal.events.sync.data.SyncResponse
|
||||
import im.vector.matrix.android.internal.legacy.MXDataHandler
|
||||
import im.vector.matrix.android.internal.legacy.data.Room
|
||||
import im.vector.matrix.android.internal.legacy.data.store.IMXStore
|
||||
import im.vector.matrix.android.internal.legacy.data.store.MXMemoryStore
|
||||
import im.vector.matrix.android.internal.legacy.rest.client.AccountDataRestClient
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.RoomMember
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.bingrules.PushRulesResponse
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils
|
||||
import timber.log.Timber
|
||||
import java.util.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.List
|
||||
import kotlin.collections.Map
|
||||
import kotlin.collections.MutableList
|
||||
import kotlin.collections.MutableMap
|
||||
import kotlin.collections.emptyList
|
||||
import kotlin.collections.isNotEmpty
|
||||
import kotlin.collections.set
|
||||
|
||||
class SyncResponseHandler(private val dataHandler: MXDataHandler,
|
||||
private val store: IMXStore) {
|
||||
|
||||
private val leftRoomsStore = MXMemoryStore()
|
||||
private var isStartingCryptoWithInitialSync = false
|
||||
private var areLeftRoomsSynced = false
|
||||
|
||||
fun handleResponse(syncResponse: SyncResponse?, fromToken: String?, isCatchingUp: Boolean) {
|
||||
if (syncResponse == null) {
|
||||
return
|
||||
}
|
||||
Timber.v("Handle sync response")
|
||||
val isInitialSync = null == fromToken
|
||||
var isEmptyResponse = true
|
||||
|
||||
// Handle the to device events before the room ones
|
||||
// to ensure to decrypt them properly
|
||||
if (syncResponse.toDevice?.events != null) {
|
||||
for (toDeviceEvent in syncResponse.toDevice.events) {
|
||||
handleToDeviceEvent(toDeviceEvent)
|
||||
}
|
||||
}
|
||||
// Handle account data before the room events
|
||||
// to be able to update direct chats dictionary during invites handling.
|
||||
if (syncResponse.accountData != null) {
|
||||
manageAccountData(syncResponse.accountData, isInitialSync)
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (syncResponse.rooms != null) {
|
||||
// joined rooms events
|
||||
if (syncResponse.rooms.join.isNotEmpty()) {
|
||||
val roomIds = syncResponse.rooms.join.keys
|
||||
// Handle first joined rooms
|
||||
for (roomId in roomIds) {
|
||||
if (null != leftRoomsStore.getRoom(roomId)) {
|
||||
leftRoomsStore.deleteRoom(roomId)
|
||||
}
|
||||
// TODO handle joined room
|
||||
//getRoom(roomId).handleJoinedRoomSync(syncResponse.rooms.join[roomId], isInitialSync)
|
||||
}
|
||||
isEmptyResponse = false
|
||||
}
|
||||
|
||||
// invited room management
|
||||
if (syncResponse.rooms.invite.isNotEmpty()) {
|
||||
val roomIds = syncResponse.rooms.invite.keys
|
||||
|
||||
var updatedDirectChatRoomsDict: MutableMap<String, List<String>>? = null
|
||||
var hasChanged = false
|
||||
|
||||
for (roomId in roomIds) {
|
||||
if (null != leftRoomsStore.getRoom(roomId)) {
|
||||
leftRoomsStore.deleteRoom(roomId)
|
||||
}
|
||||
val room = getRoom(roomId)
|
||||
val invitedRoomSync = syncResponse.rooms.invite[roomId]
|
||||
// TODO handle invited room
|
||||
//room.handleInvitedRoomSync(invitedRoomSync)
|
||||
|
||||
// Handle here the invites to a direct chat.
|
||||
if (room.isDirectChatInvitation) {
|
||||
// Retrieve the inviter user id.
|
||||
var participantUserId: String? = null
|
||||
for (event in invitedRoomSync?.inviteState?.events ?: emptyList()) {
|
||||
if (event.sender != null) {
|
||||
participantUserId = event.sender
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (participantUserId != null) {
|
||||
// Prepare the updated dictionary.
|
||||
if (updatedDirectChatRoomsDict == null) updatedDirectChatRoomsDict = if (null != store.directChatRoomsDict) {
|
||||
// Consider the current dictionary.
|
||||
HashMap(store.directChatRoomsDict)
|
||||
} else {
|
||||
java.util.HashMap()
|
||||
}
|
||||
|
||||
val roomIdsList: MutableList<String> = if (updatedDirectChatRoomsDict.containsKey(participantUserId)) {
|
||||
ArrayList(updatedDirectChatRoomsDict[participantUserId])
|
||||
} else {
|
||||
ArrayList()
|
||||
}
|
||||
|
||||
// Check whether the room was not yet seen as direct chat
|
||||
if (roomIdsList.indexOf(roomId) < 0) {
|
||||
|
||||
roomIdsList.add(roomId) // update room list with the new room
|
||||
updatedDirectChatRoomsDict[participantUserId] = roomIdsList
|
||||
hasChanged = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
isEmptyResponse = false
|
||||
|
||||
if (hasChanged) {
|
||||
// Update account data to add new direct chat room(s)
|
||||
/* mAccountDataRestClient.setAccountData(mCredentials.userId, AccountDataRestClient.ACCOUNT_DATA_TYPE_DIRECT_MESSAGES,
|
||||
updatedDirectChatRoomsDict, object : ApiCallback<Void> {
|
||||
override fun onSuccess(info: Void) {
|
||||
}
|
||||
|
||||
override fun onNetworkError(e: Exception) {
|
||||
// TODO: we should try again.
|
||||
}
|
||||
|
||||
override fun onMatrixError(e: MatrixError) {
|
||||
}
|
||||
|
||||
override fun onUnexpectedError(e: Exception) {
|
||||
}
|
||||
})*/
|
||||
}
|
||||
}
|
||||
|
||||
// left room management
|
||||
// it should be done at the end but it seems there is a server issue
|
||||
// when inviting after leaving a room, the room is defined in the both leave & invite rooms list.
|
||||
if (syncResponse.rooms.leave.isNotEmpty()) {
|
||||
val roomIds = syncResponse.rooms.leave.keys
|
||||
for (roomId in roomIds) {
|
||||
// RoomSync leftRoomSync = syncResponse.rooms.leave.get(roomId);
|
||||
|
||||
// Presently we remove the existing room from the rooms list.
|
||||
// FIXME SYNC V2 Archive/Display the left rooms!
|
||||
// For that create 'handleArchivedRoomSync' method
|
||||
|
||||
var membership = RoomMember.MEMBERSHIP_LEAVE
|
||||
val room = getRoom(roomId)
|
||||
|
||||
// Retrieve existing room
|
||||
// The room will then be able to notify its listeners.
|
||||
// TODO handle
|
||||
// room.handleJoinedRoomSync(syncResponse.rooms.leave[roomId], isInitialSync)
|
||||
|
||||
val member = room.getMember(dataHandler.userId)
|
||||
if (null != member) {
|
||||
membership = member.membership
|
||||
}
|
||||
if (!TextUtils.equals(membership, RoomMember.MEMBERSHIP_KICK) && !TextUtils.equals(membership, RoomMember.MEMBERSHIP_BAN)) {
|
||||
// ensure that the room data are properly deleted
|
||||
store.deleteRoom(roomId)
|
||||
dataHandler.onLeaveRoom(roomId)
|
||||
} else {
|
||||
dataHandler.onRoomKick(roomId)
|
||||
}
|
||||
// don't add to the left rooms if the user has been kicked / banned
|
||||
if (areLeftRoomsSynced && TextUtils.equals(membership, RoomMember.MEMBERSHIP_LEAVE)) {
|
||||
val leftRoom = getRoom(leftRoomsStore, roomId, true)
|
||||
//Todo handle
|
||||
//leftRoom.handleJoinedRoomSync(syncResponse.rooms.leave[roomId], isInitialSync)
|
||||
}
|
||||
}
|
||||
isEmptyResponse = false
|
||||
}
|
||||
}
|
||||
|
||||
// groups
|
||||
if (null != syncResponse.groups) {
|
||||
// Handle invited groups
|
||||
if (null != syncResponse.groups.invite && !syncResponse.groups.invite.isEmpty()) {
|
||||
// Handle invited groups
|
||||
for (groupId in syncResponse.groups.invite.keys) {
|
||||
val invitedGroupSync = syncResponse.groups.invite[groupId]
|
||||
dataHandler.groupsManager.onNewGroupInvitation(groupId, invitedGroupSync?.profile, invitedGroupSync?.inviter, !isInitialSync)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle joined groups
|
||||
if (null != syncResponse.groups.join && !syncResponse.groups.join.isEmpty()) {
|
||||
for (groupId in syncResponse.groups.join.keys) {
|
||||
dataHandler.groupsManager.onJoinGroup(groupId, !isInitialSync)
|
||||
}
|
||||
}
|
||||
// Handle left groups
|
||||
if (null != syncResponse.groups.leave && !syncResponse.groups.leave.isEmpty()) {
|
||||
// Handle joined groups
|
||||
for (groupId in syncResponse.groups.leave.keys) {
|
||||
dataHandler.groupsManager.onLeaveGroup(groupId, !isInitialSync)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle presence of other users
|
||||
if (syncResponse.presence?.events != null) {
|
||||
for (presenceEvent in syncResponse.presence.events) {
|
||||
handlePresenceEvent(presenceEvent)
|
||||
}
|
||||
}
|
||||
dataHandler.crypto?.onSyncCompleted(syncResponse, fromToken, isCatchingUp)
|
||||
if (!isEmptyResponse) {
|
||||
store.eventStreamToken = syncResponse.nextBatch
|
||||
store.commit()
|
||||
}
|
||||
|
||||
if (isInitialSync) {
|
||||
if (!isCatchingUp) {
|
||||
dataHandler.startCrypto(true)
|
||||
} else {
|
||||
// the events thread sends a dummy initial sync event
|
||||
// when the application is restarted.
|
||||
isStartingCryptoWithInitialSync = !isEmptyResponse
|
||||
}
|
||||
|
||||
dataHandler.onInitialSyncComplete(syncResponse?.nextBatch)
|
||||
} else {
|
||||
|
||||
if (!isCatchingUp) {
|
||||
dataHandler.startCrypto(isStartingCryptoWithInitialSync)
|
||||
}
|
||||
|
||||
dataHandler.onLiveEventsChunkProcessed(fromToken, syncResponse.nextBatch)
|
||||
dataHandler.callsManager?.checkPendingIncomingCalls()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun manageAccountData(accountData: Map<String, Any>, isInitialSync: Boolean) {
|
||||
if (accountData.containsKey("events")) {
|
||||
val events = accountData["events"] as List<Map<String, Any>>
|
||||
if (!events.isEmpty()) {
|
||||
// ignored users list
|
||||
manageIgnoredUsers(events, isInitialSync)
|
||||
// push rules
|
||||
managePushRulesUpdate(events)
|
||||
// direct messages rooms
|
||||
manageDirectChatRooms(events, isInitialSync)
|
||||
// URL preview
|
||||
manageUrlPreview(events)
|
||||
// User widgets
|
||||
manageUserWidgets(events)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the push rules from the account data events list
|
||||
*
|
||||
* @param events the account data events.
|
||||
*/
|
||||
private fun managePushRulesUpdate(events: List<Map<String, Any>>) {
|
||||
for (event in events) {
|
||||
val type = event["type"] as String
|
||||
|
||||
if (TextUtils.equals(type, "m.push_rules")) {
|
||||
if (event.containsKey("content")) {
|
||||
val gson = JsonUtils.getGson(false)
|
||||
|
||||
// convert the data to PushRulesResponse
|
||||
// because BingRulesManager supports only PushRulesResponse
|
||||
val element = gson.toJsonTree(event["content"])
|
||||
dataHandler.bingRulesManager?.buildRules(gson.fromJson(element, PushRulesResponse::class.java))
|
||||
|
||||
// warn the client that the push rules have been updated
|
||||
dataHandler.onBingRulesUpdate()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the ignored users list is updated
|
||||
*
|
||||
* @param events the account data events list
|
||||
*/
|
||||
private fun manageIgnoredUsers(events: List<Map<String, Any>>, isInitialSync: Boolean) {
|
||||
val newIgnoredUsers = dataHandler.ignoredUsers(events)
|
||||
|
||||
if (null != newIgnoredUsers) {
|
||||
val curIgnoredUsers = dataHandler.ignoredUserIds
|
||||
// the both lists are not empty
|
||||
if (0 != newIgnoredUsers.size || 0 != curIgnoredUsers.size) {
|
||||
// check if the ignored users list has been updated
|
||||
if (newIgnoredUsers.size != curIgnoredUsers.size || !newIgnoredUsers.containsAll(curIgnoredUsers)) {
|
||||
// update the store
|
||||
store.setIgnoredUserIdsList(newIgnoredUsers)
|
||||
if (!isInitialSync) {
|
||||
// warn there is an update
|
||||
dataHandler.onIgnoredUsersListUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the direct chat rooms list from the dedicated events.
|
||||
*
|
||||
* @param events the account data events list.
|
||||
*/
|
||||
private fun manageDirectChatRooms(events: List<Map<String, Any>>, isInitialSync: Boolean) {
|
||||
if (events.isNotEmpty()) {
|
||||
for (event in events) {
|
||||
val type = event["type"] as String
|
||||
|
||||
if (TextUtils.equals(type, AccountDataRestClient.ACCOUNT_DATA_TYPE_DIRECT_MESSAGES)) {
|
||||
if (event.containsKey("content")) {
|
||||
val contentDict = event["content"] as Map<String, List<String>>
|
||||
store.directChatRoomsDict = contentDict
|
||||
// reset the current list of the direct chat roomIDs
|
||||
// to update it
|
||||
if (!isInitialSync) {
|
||||
// warn there is an update
|
||||
dataHandler.onDirectMessageChatRoomsListUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the URL preview flag
|
||||
*
|
||||
* @param events the events list
|
||||
*/
|
||||
private fun manageUrlPreview(events: List<Map<String, Any>>) {
|
||||
if (0 != events.size) {
|
||||
for (event in events) {
|
||||
val type = event["type"] as String
|
||||
|
||||
if (TextUtils.equals(type, AccountDataRestClient.ACCOUNT_DATA_TYPE_PREVIEW_URLS)) {
|
||||
if (event.containsKey("content")) {
|
||||
val contentDict = event["content"] as Map<String, Any>
|
||||
var enable = true
|
||||
if (contentDict.containsKey(AccountDataRestClient.ACCOUNT_DATA_KEY_URL_PREVIEW_DISABLE)) {
|
||||
enable = !(contentDict[AccountDataRestClient.ACCOUNT_DATA_KEY_URL_PREVIEW_DISABLE] as Boolean)
|
||||
}
|
||||
|
||||
store.setURLPreviewEnabled(enable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the user widgets
|
||||
*
|
||||
* @param events the events list
|
||||
*/
|
||||
private fun manageUserWidgets(events: List<Map<String, Any>>) {
|
||||
if (0 != events.size) {
|
||||
for (event in events) {
|
||||
val type = event["type"] as String
|
||||
|
||||
if (TextUtils.equals(type, AccountDataRestClient.ACCOUNT_DATA_TYPE_WIDGETS)) {
|
||||
if (event.containsKey("content")) {
|
||||
val contentDict = event["content"] as Map<String, Any>
|
||||
store.setUserWidgets(contentDict)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a presence event.
|
||||
*
|
||||
* @param presenceEvent the presence event.
|
||||
*/
|
||||
private fun handlePresenceEvent(presenceEvent: Event) {
|
||||
/* // Presence event
|
||||
if (EventType.PRESENCE == presenceEvent.type) {
|
||||
val userPresence = JsonUtils.toUser(presenceEvent.getContent())
|
||||
|
||||
// use the sender by default
|
||||
if (!TextUtils.isEmpty(presenceEvent.getSender())) {
|
||||
userPresence.user_id = presenceEvent.getSender()
|
||||
}
|
||||
var user: User? = store.getUser(userPresence.user_id)
|
||||
|
||||
if (user == null) {
|
||||
user = userPresence
|
||||
user!!.setDataHandler(dataHandler)
|
||||
} else {
|
||||
user.currently_active = userPresence.currently_active
|
||||
user.presence = userPresence.presence
|
||||
user.lastActiveAgo = userPresence.lastActiveAgo
|
||||
}
|
||||
user.latestPresenceTs = System.currentTimeMillis()
|
||||
// check if the current user has been updated
|
||||
if (mCredentials.userId == user.user_id) {
|
||||
// always use the up-to-date information
|
||||
getMyUser().displayname = user.displayname
|
||||
getMyUser().avatar_url = user.avatarUrl
|
||||
|
||||
store.setAvatarURL(user.avatarUrl, presenceEvent.getOriginServerTs())
|
||||
store.setDisplayName(user.displayname, presenceEvent.getOriginServerTs())
|
||||
}
|
||||
store.storeUser(user)
|
||||
onPresenceUpdate(presenceEvent, user)
|
||||
}*/
|
||||
}
|
||||
|
||||
private fun handleToDeviceEvent(event: Event) {
|
||||
// Decrypt event if necessary
|
||||
/*
|
||||
decryptEvent(event, null)
|
||||
if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE)
|
||||
&& null != event.getContent()
|
||||
&& TextUtils.equals(JsonUtils.getMessageMsgType(event.getContent()), "m.bad.encrypted")) {
|
||||
Timber.e("## handleToDeviceEvent() : Warning: Unable to decrypt to-device event : %s", event.getContent())
|
||||
} else {
|
||||
//onToDeviceEvent(event)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt an encrypted event
|
||||
*
|
||||
* @param event the event to decrypt
|
||||
* @param timelineId the timeline identifier
|
||||
* @return true if the event has been decrypted
|
||||
*/
|
||||
fun decryptEvent(event: Event?, timelineId: String?): Boolean {
|
||||
/*
|
||||
if (null != event && TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE_ENCRYPTED)) {
|
||||
if (null != getCrypto()) {
|
||||
var result: MXEventDecryptionResult? = null
|
||||
try {
|
||||
result = getCrypto().decryptEvent(event, timelineId)
|
||||
} catch (exception: MXDecryptionException) {
|
||||
event.cryptoError = exception.cryptoError
|
||||
}
|
||||
if (null != result) {
|
||||
event.setClearData(result)
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
event.cryptoError = MXCryptoError(MXCryptoError.ENCRYPTING_NOT_ENABLED_ERROR_CODE, MXCryptoError.ENCRYPTING_NOT_ENABLED_REASON, null)
|
||||
}
|
||||
}
|
||||
*/
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the room object for the corresponding room id. Creates and initializes the object if there is none.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @return the corresponding room
|
||||
*/
|
||||
fun getRoom(roomId: String): Room {
|
||||
return getRoom(roomId, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the room object for the corresponding room id.
|
||||
* The left rooms are not included.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param create create the room it does not exist.
|
||||
* @return the corresponding room
|
||||
*/
|
||||
fun getRoom(roomId: String, create: Boolean): Room {
|
||||
return getRoom(store, roomId, create)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the room object for the corresponding room id.
|
||||
* By default, the left rooms are not included.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param testLeftRooms true to test if the room is a left room
|
||||
* @param create create the room it does not exist.
|
||||
* @return the corresponding room
|
||||
*/
|
||||
fun getRoom(roomId: String, testLeftRooms: Boolean, create: Boolean): Room {
|
||||
var room = store.getRoom(roomId)
|
||||
if (room == null && testLeftRooms) {
|
||||
room = leftRoomsStore.getRoom(roomId)
|
||||
}
|
||||
if (room == null && create) {
|
||||
room = getRoom(store, roomId, create)
|
||||
}
|
||||
return room
|
||||
}
|
||||
|
||||
fun getRoom(store: IMXStore, roomId: String, create: Boolean): Room {
|
||||
var room = store.getRoom(roomId)
|
||||
if (room == null && create) {
|
||||
room = Room(dataHandler, store, roomId)
|
||||
store.storeRoom(room)
|
||||
}
|
||||
return room
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -14,7 +14,8 @@ import kotlinx.coroutines.launch
|
||||
|
||||
class Synchronizer(private val syncAPI: SyncAPI,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val jsonMapper: Moshi) {
|
||||
private val jsonMapper: Moshi,
|
||||
private val syncResponseHandler: SyncResponseHandler) {
|
||||
|
||||
fun synchronize(callback: MatrixCallback<SyncResponse>): Cancelable {
|
||||
val job = GlobalScope.launch(coroutineDispatchers.main) {
|
||||
@ -27,8 +28,11 @@ class Synchronizer(private val syncAPI: SyncAPI,
|
||||
apiCall = syncAPI.sync(params)
|
||||
moshi = jsonMapper
|
||||
dispatcher = coroutineDispatchers.io
|
||||
}.map {
|
||||
syncResponseHandler.handleResponse(it, null, false)
|
||||
it
|
||||
}
|
||||
syncResponse.either({ callback.onFailure(it) }, { callback.onSuccess(it) })
|
||||
syncResponse.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) })
|
||||
}
|
||||
return CancelableCoroutine(job)
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package im.vector.matrix.android.internal.events.sync.data
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DeviceOneTimeKeysCountSyncResponse(
|
||||
val signed_curve25519: Int? = null
|
||||
@Json(name = "signed_curve25519") val signedCurve25519: Int? = null
|
||||
|
||||
)
|
@ -0,0 +1,17 @@
|
||||
package im.vector.matrix.android.internal.events.sync.data
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class GroupSyncProfile(
|
||||
/**
|
||||
* The name of the group, if any. May be nil.
|
||||
*/
|
||||
@Json(name = "name") var name: String? = null,
|
||||
|
||||
/**
|
||||
* The URL for the group's avatar. May be nil.
|
||||
*/
|
||||
@Json(name = "avatar_url") var avatarUrl: String? = null
|
||||
)
|
@ -0,0 +1,22 @@
|
||||
package im.vector.matrix.android.internal.events.sync.data
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class GroupsSyncResponse(
|
||||
/**
|
||||
* Joined groups: An array of groups ids.
|
||||
*/
|
||||
@Json(name = "join") val join: Map<String, Any> = emptyMap(),
|
||||
|
||||
/**
|
||||
* Invitations. The groups that the user has been invited to: keys are groups ids.
|
||||
*/
|
||||
@Json(name = "invite") val invite: Map<String, InvitedGroupSync> = emptyMap(),
|
||||
|
||||
/**
|
||||
* Left groups. An array of groups ids: the groups that the user has left or been banned from.
|
||||
*/
|
||||
@Json(name = "leave") val leave: Map<String, Any> = emptyMap()
|
||||
)
|
@ -0,0 +1,17 @@
|
||||
package im.vector.matrix.android.internal.events.sync.data
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class InvitedGroupSync(
|
||||
/**
|
||||
* The identifier of the inviter.
|
||||
*/
|
||||
@Json(name = "inviter") val inviter: String? = null,
|
||||
|
||||
/**
|
||||
* The group profile.
|
||||
*/
|
||||
@Json(name = "profile") val profile: GroupSyncProfile? = null
|
||||
)
|
@ -2,11 +2,11 @@ package im.vector.matrix.android.internal.events.sync.data
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.GroupsSyncResponse
|
||||
|
||||
// SyncResponse represents the request response for server sync v2.
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class SyncResponse(
|
||||
|
||||
/**
|
||||
* The user private data.
|
||||
*/
|
||||
@ -40,6 +40,13 @@ data class SyncResponse(
|
||||
/**
|
||||
* One time keys management
|
||||
*/
|
||||
@Json(name = "device_one_time_keys_count") val deviceOneTimeKeysCount: DeviceOneTimeKeysCountSyncResponse? = null
|
||||
@Json(name = "device_one_time_keys_count") val deviceOneTimeKeysCount: DeviceOneTimeKeysCountSyncResponse? = null,
|
||||
|
||||
|
||||
/**
|
||||
* List of groups.
|
||||
*/
|
||||
@Json(name = "groups") val groups: GroupsSyncResponse? = null
|
||||
|
||||
|
||||
)
|
@ -1,532 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
* Copyright 2018 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.legacy;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.ssl.Fingerprint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.CipherSuite;
|
||||
import okhttp3.TlsVersion;
|
||||
|
||||
/**
|
||||
* Represents how to connect to a specific Homeserver, may include credentials to use.
|
||||
*/
|
||||
public class HomeServerConnectionConfig {
|
||||
|
||||
// the home server URI
|
||||
private Uri mHsUri;
|
||||
// the identity server URI
|
||||
private Uri mIdentityServerUri;
|
||||
// the anti-virus server URI
|
||||
private Uri mAntiVirusServerUri;
|
||||
// allowed fingerprints
|
||||
private List<Fingerprint> mAllowedFingerprints = new ArrayList<>();
|
||||
// the credentials
|
||||
private Credentials mCredentials;
|
||||
// tell whether we should reject X509 certs that were issued by trusts CAs and only trustcerts with matching fingerprints.
|
||||
private boolean mPin;
|
||||
// the accepted TLS versions
|
||||
private List<TlsVersion> mTlsVersions;
|
||||
// the accepted TLS cipher suites
|
||||
private List<CipherSuite> mTlsCipherSuites;
|
||||
// should accept TLS extensions
|
||||
private boolean mShouldAcceptTlsExtensions = true;
|
||||
// allow Http connection
|
||||
private boolean mAllowHttpExtension;
|
||||
// Force usage of TLS versions
|
||||
private boolean mForceUsageTlsVersions;
|
||||
|
||||
/**
|
||||
* Private constructor. Please use the Builder
|
||||
*/
|
||||
private HomeServerConnectionConfig() {
|
||||
// Private constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the home server URI.
|
||||
*
|
||||
* @param uri the new HS uri
|
||||
*/
|
||||
public void setHomeserverUri(Uri uri) {
|
||||
mHsUri = uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the home server uri
|
||||
*/
|
||||
public Uri getHomeserverUri() {
|
||||
return mHsUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the identity server uri
|
||||
*/
|
||||
public Uri getIdentityServerUri() {
|
||||
if (null != mIdentityServerUri) {
|
||||
return mIdentityServerUri;
|
||||
}
|
||||
// Else consider the HS uri by default.
|
||||
return mHsUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the anti-virus server uri
|
||||
*/
|
||||
public Uri getAntiVirusServerUri() {
|
||||
if (null != mAntiVirusServerUri) {
|
||||
return mAntiVirusServerUri;
|
||||
}
|
||||
// Else consider the HS uri by default.
|
||||
return mHsUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the allowed fingerprints.
|
||||
*/
|
||||
public List<Fingerprint> getAllowedFingerprints() {
|
||||
return mAllowedFingerprints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the credentials
|
||||
*/
|
||||
public Credentials getCredentials() {
|
||||
return mCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the credentials.
|
||||
*
|
||||
* @param credentials the new credentials
|
||||
*/
|
||||
public void setCredentials(Credentials credentials) {
|
||||
mCredentials = credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether we should reject X509 certs that were issued by trusts CAs and only trust
|
||||
* certs with matching fingerprints.
|
||||
*/
|
||||
public boolean shouldPin() {
|
||||
return mPin;
|
||||
}
|
||||
|
||||
/**
|
||||
* TLS versions accepted for TLS connections with the home server.
|
||||
*/
|
||||
@Nullable
|
||||
public List<TlsVersion> getAcceptedTlsVersions() {
|
||||
return mTlsVersions;
|
||||
}
|
||||
|
||||
/**
|
||||
* TLS cipher suites accepted for TLS connections with the home server.
|
||||
*/
|
||||
@Nullable
|
||||
public List<CipherSuite> getAcceptedTlsCipherSuites() {
|
||||
return mTlsCipherSuites;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether we should accept TLS extensions.
|
||||
*/
|
||||
public boolean shouldAcceptTlsExtensions() {
|
||||
return mShouldAcceptTlsExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if Http connection is allowed (false by default).
|
||||
*/
|
||||
public boolean isHttpConnectionAllowed() {
|
||||
return mAllowHttpExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the usage of TlsVersions has to be forced
|
||||
*/
|
||||
public boolean forceUsageOfTlsVersions() {
|
||||
return mForceUsageTlsVersions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HomeserverConnectionConfig{" +
|
||||
"mHsUri=" + mHsUri +
|
||||
", mIdentityServerUri=" + mIdentityServerUri +
|
||||
", mAntiVirusServerUri=" + mAntiVirusServerUri +
|
||||
", mAllowedFingerprints size=" + mAllowedFingerprints.size() +
|
||||
", mCredentials=" + mCredentials +
|
||||
", mPin=" + mPin +
|
||||
", mShouldAcceptTlsExtensions=" + mShouldAcceptTlsExtensions +
|
||||
", mTlsVersions=" + (null == mTlsVersions ? "" : mTlsVersions.size()) +
|
||||
", mTlsCipherSuites=" + (null == mTlsCipherSuites ? "" : mTlsCipherSuites.size()) +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object instance into a JSon object
|
||||
*
|
||||
* @return the JSon representation
|
||||
* @throws JSONException the JSON conversion failure reason
|
||||
*/
|
||||
public JSONObject toJson() throws JSONException {
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
json.put("home_server_url", mHsUri.toString());
|
||||
json.put("identity_server_url", getIdentityServerUri().toString());
|
||||
if (mAntiVirusServerUri != null) {
|
||||
json.put("antivirus_server_url", mAntiVirusServerUri.toString());
|
||||
}
|
||||
|
||||
json.put("pin", mPin);
|
||||
|
||||
if (mCredentials != null) json.put("credentials", mCredentials.toJson());
|
||||
if (mAllowedFingerprints != null) {
|
||||
List<JSONObject> fingerprints = new ArrayList<>(mAllowedFingerprints.size());
|
||||
|
||||
for (Fingerprint fingerprint : mAllowedFingerprints) {
|
||||
fingerprints.add(fingerprint.toJson());
|
||||
}
|
||||
|
||||
json.put("fingerprints", new JSONArray(fingerprints));
|
||||
}
|
||||
|
||||
json.put("tls_extensions", mShouldAcceptTlsExtensions);
|
||||
|
||||
if (mTlsVersions != null) {
|
||||
List<String> tlsVersions = new ArrayList<>(mTlsVersions.size());
|
||||
|
||||
for (TlsVersion tlsVersion : mTlsVersions) {
|
||||
tlsVersions.add(tlsVersion.javaName());
|
||||
}
|
||||
|
||||
json.put("tls_versions", new JSONArray(tlsVersions));
|
||||
}
|
||||
|
||||
json.put("force_usage_of_tls_versions", mForceUsageTlsVersions);
|
||||
|
||||
if (mTlsCipherSuites != null) {
|
||||
List<String> tlsCipherSuites = new ArrayList<>(mTlsCipherSuites.size());
|
||||
|
||||
for (CipherSuite tlsCipherSuite : mTlsCipherSuites) {
|
||||
tlsCipherSuites.add(tlsCipherSuite.javaName());
|
||||
}
|
||||
|
||||
json.put("tls_cipher_suites", new JSONArray(tlsCipherSuites));
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an object instance from the json object.
|
||||
*
|
||||
* @param jsonObject the json object
|
||||
* @return a HomeServerConnectionConfig instance
|
||||
* @throws JSONException the conversion failure reason
|
||||
*/
|
||||
public static HomeServerConnectionConfig fromJson(JSONObject jsonObject) throws JSONException {
|
||||
JSONArray fingerprintArray = jsonObject.optJSONArray("fingerprints");
|
||||
List<Fingerprint> fingerprints = new ArrayList<>();
|
||||
if (fingerprintArray != null) {
|
||||
for (int i = 0; i < fingerprintArray.length(); i++) {
|
||||
fingerprints.add(Fingerprint.fromJson(fingerprintArray.getJSONObject(i)));
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject credentialsObj = jsonObject.optJSONObject("credentials");
|
||||
Credentials creds = credentialsObj != null ? Credentials.fromJson(credentialsObj) : null;
|
||||
|
||||
Builder builder = new Builder()
|
||||
.withHomeServerUri(Uri.parse(jsonObject.getString("home_server_url")))
|
||||
.withIdentityServerUri(jsonObject.has("identity_server_url") ? Uri.parse(jsonObject.getString("identity_server_url")) : null)
|
||||
.withCredentials(creds)
|
||||
.withAllowedFingerPrints(fingerprints)
|
||||
.withPin(jsonObject.optBoolean("pin", false));
|
||||
|
||||
// Set the anti-virus server uri if any
|
||||
if (jsonObject.has("antivirus_server_url")) {
|
||||
builder.withAntiVirusServerUri(Uri.parse(jsonObject.getString("antivirus_server_url")));
|
||||
}
|
||||
|
||||
builder.withShouldAcceptTlsExtensions(jsonObject.optBoolean("tls_extensions", true));
|
||||
|
||||
// Set the TLS versions if any
|
||||
if (jsonObject.has("tls_versions")) {
|
||||
JSONArray tlsVersionsArray = jsonObject.optJSONArray("tls_versions");
|
||||
if (tlsVersionsArray != null) {
|
||||
for (int i = 0; i < tlsVersionsArray.length(); i++) {
|
||||
builder.addAcceptedTlsVersion(TlsVersion.forJavaName(tlsVersionsArray.getString(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.forceUsageOfTlsVersions(jsonObject.optBoolean("force_usage_of_tls_versions", false));
|
||||
|
||||
// Set the TLS cipher suites if any
|
||||
if (jsonObject.has("tls_cipher_suites")) {
|
||||
JSONArray tlsCipherSuitesArray = jsonObject.optJSONArray("tls_cipher_suites");
|
||||
if (tlsCipherSuitesArray != null) {
|
||||
for (int i = 0; i < tlsCipherSuitesArray.length(); i++) {
|
||||
builder.addAcceptedTlsCipherSuite(CipherSuite.forJavaName(tlsCipherSuitesArray.getString(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder
|
||||
*/
|
||||
public static class Builder {
|
||||
private HomeServerConnectionConfig mHomeServerConnectionConfig;
|
||||
|
||||
/**
|
||||
* Builder constructor
|
||||
*/
|
||||
public Builder() {
|
||||
mHomeServerConnectionConfig = new HomeServerConnectionConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hsUri The URI to use to connect to the homeserver. Cannot be null
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withHomeServerUri(final Uri hsUri) {
|
||||
if (hsUri == null || (!"http".equals(hsUri.getScheme()) && !"https".equals(hsUri.getScheme()))) {
|
||||
throw new RuntimeException("Invalid home server URI: " + hsUri);
|
||||
}
|
||||
|
||||
// remove trailing /
|
||||
if (hsUri.toString().endsWith("/")) {
|
||||
try {
|
||||
String url = hsUri.toString();
|
||||
mHomeServerConnectionConfig.mHsUri = Uri.parse(url.substring(0, url.length() - 1));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Invalid home server URI: " + hsUri);
|
||||
}
|
||||
} else {
|
||||
mHomeServerConnectionConfig.mHsUri = hsUri;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param identityServerUri The URI to use to manage identity. Can be null
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withIdentityServerUri(@Nullable final Uri identityServerUri) {
|
||||
if ((null != identityServerUri) && (!"http".equals(identityServerUri.getScheme()) && !"https".equals(identityServerUri.getScheme()))) {
|
||||
throw new RuntimeException("Invalid identity server URI: " + identityServerUri);
|
||||
}
|
||||
|
||||
// remove trailing /
|
||||
if ((null != identityServerUri) && identityServerUri.toString().endsWith("/")) {
|
||||
try {
|
||||
String url = identityServerUri.toString();
|
||||
mHomeServerConnectionConfig.mIdentityServerUri = Uri.parse(url.substring(0, url.length() - 1));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Invalid identity server URI: " + identityServerUri);
|
||||
}
|
||||
} else {
|
||||
mHomeServerConnectionConfig.mIdentityServerUri = identityServerUri;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param credentials The credentials to use, if needed. Can be null.
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withCredentials(@Nullable Credentials credentials) {
|
||||
mHomeServerConnectionConfig.mCredentials = credentials;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param allowedFingerprints If using SSL, allow server certs that match these fingerprints.
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withAllowedFingerPrints(@Nullable List<Fingerprint> allowedFingerprints) {
|
||||
if (allowedFingerprints != null) {
|
||||
mHomeServerConnectionConfig.mAllowedFingerprints.addAll(allowedFingerprints);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pin If true only allow certs matching given fingerprints, otherwise fallback to
|
||||
* standard X509 checks.
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withPin(boolean pin) {
|
||||
mHomeServerConnectionConfig.mPin = pin;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shouldAcceptTlsExtension
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withShouldAcceptTlsExtensions(boolean shouldAcceptTlsExtension) {
|
||||
mHomeServerConnectionConfig.mShouldAcceptTlsExtensions = shouldAcceptTlsExtension;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an accepted TLS version for TLS connections with the home server.
|
||||
*
|
||||
* @param tlsVersion the tls version to add to the set of TLS versions accepted.
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder addAcceptedTlsVersion(@NonNull TlsVersion tlsVersion) {
|
||||
if (mHomeServerConnectionConfig.mTlsVersions == null) {
|
||||
mHomeServerConnectionConfig.mTlsVersions = new ArrayList<>();
|
||||
}
|
||||
|
||||
mHomeServerConnectionConfig.mTlsVersions.add(tlsVersion);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the usage of TlsVersion. This can be usefull for device on Android version < 20
|
||||
*
|
||||
* @param forceUsageOfTlsVersions set to true to force the usage of specified TlsVersions (with {@link #addAcceptedTlsVersion(TlsVersion)}
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder forceUsageOfTlsVersions(boolean forceUsageOfTlsVersions) {
|
||||
mHomeServerConnectionConfig.mForceUsageTlsVersions = forceUsageOfTlsVersions;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a TLS cipher suite to the list of accepted TLS connections with the home server.
|
||||
*
|
||||
* @param tlsCipherSuite the tls cipher suite to add.
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder addAcceptedTlsCipherSuite(@NonNull CipherSuite tlsCipherSuite) {
|
||||
if (mHomeServerConnectionConfig.mTlsCipherSuites == null) {
|
||||
mHomeServerConnectionConfig.mTlsCipherSuites = new ArrayList<>();
|
||||
}
|
||||
|
||||
mHomeServerConnectionConfig.mTlsCipherSuites.add(tlsCipherSuite);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the anti-virus server URI.
|
||||
*
|
||||
* @param antivirusServerUri the new anti-virus uri. Can be null
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withAntiVirusServerUri(@Nullable Uri antivirusServerUri) {
|
||||
if ((null != antivirusServerUri) && (!"http".equals(antivirusServerUri.getScheme()) && !"https".equals(antivirusServerUri.getScheme()))) {
|
||||
throw new RuntimeException("Invalid antivirus server URI: " + antivirusServerUri);
|
||||
}
|
||||
|
||||
mHomeServerConnectionConfig.mAntiVirusServerUri = antivirusServerUri;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* For test only: allow Http connection
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public Builder withAllowHttpConnection() {
|
||||
mHomeServerConnectionConfig.mAllowHttpExtension = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method to limit the TLS versions and cipher suites for this Builder
|
||||
* Ref:
|
||||
* - https://www.ssi.gouv.fr/uploads/2017/02/security-recommendations-for-tls_v1.1.pdf
|
||||
* - https://developer.android.com/reference/javax/net/ssl/SSLEngine
|
||||
*
|
||||
* @param tlsLimitations true to use Tls limitations
|
||||
* @param enableCompatibilityMode set to true for Android < 20
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withTlsLimitations(boolean tlsLimitations, boolean enableCompatibilityMode) {
|
||||
if (tlsLimitations) {
|
||||
withShouldAcceptTlsExtensions(false);
|
||||
|
||||
// Tls versions
|
||||
addAcceptedTlsVersion(TlsVersion.TLS_1_2);
|
||||
addAcceptedTlsVersion(TlsVersion.TLS_1_3);
|
||||
|
||||
forceUsageOfTlsVersions(enableCompatibilityMode);
|
||||
|
||||
// Cipher suites
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256);
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384);
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
|
||||
|
||||
if (enableCompatibilityMode) {
|
||||
// Adopt some preceding cipher suites for Android < 20 to be able to negotiate
|
||||
// a TLS session.
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
|
||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link HomeServerConnectionConfig}
|
||||
*/
|
||||
public HomeServerConnectionConfig build() {
|
||||
// Check mandatory parameters
|
||||
if (mHomeServerConnectionConfig.mHsUri == null) {
|
||||
throw new RuntimeException("Home server URI not set");
|
||||
}
|
||||
|
||||
return mHomeServerConnectionConfig;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ import android.text.TextUtils;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.call.MXCallsManager;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXCrypto;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXCryptoError;
|
||||
@ -62,13 +63,12 @@ import im.vector.matrix.android.internal.legacy.rest.model.bingrules.BingRule;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.bingrules.PushRuleSet;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.bingrules.PushRulesResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.InvitedGroupSync;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.sync.InvitedRoomSync;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.sync.SyncResponse;
|
||||
import im.vector.matrix.android.internal.legacy.ssl.UnrecognizedCertificateException;
|
||||
import im.vector.matrix.android.internal.legacy.util.BingRulesManager;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import im.vector.matrix.android.internal.network.ssl.UnrecognizedCertificateException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -173,7 +173,7 @@ public class MXDataHandler {
|
||||
* Default constructor.
|
||||
*
|
||||
* @param store the data storage implementation.
|
||||
* @param credentials the credentials
|
||||
* @param credentials the getCredentials
|
||||
*/
|
||||
public MXDataHandler(IMXStore store, Credentials credentials) {
|
||||
mStore = store;
|
||||
@ -208,8 +208,12 @@ public class MXDataHandler {
|
||||
mMetricsListener = metricsListener;
|
||||
}
|
||||
|
||||
public GroupsManager getGroupsManager() {
|
||||
return mGroupsManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the credentials
|
||||
* @return the getCredentials
|
||||
*/
|
||||
public Credentials getCredentials() {
|
||||
return mCredentials;
|
||||
@ -426,7 +430,7 @@ public class MXDataHandler {
|
||||
// MyUser is initialized as late as possible to have a better chance at having the info in storage,
|
||||
// which should be the case if this is called after the initial sync
|
||||
if (mMyUser == null) {
|
||||
mMyUser = new MyUser(store.getUser(mCredentials.userId));
|
||||
mMyUser = new MyUser(store.getUser(mCredentials.getUserId()));
|
||||
mMyUser.setDataHandler(this);
|
||||
|
||||
// assume the profile is not yet initialized
|
||||
@ -441,7 +445,7 @@ public class MXDataHandler {
|
||||
}
|
||||
|
||||
// Handle the case where the user is null by loading the user information from the server
|
||||
mMyUser.user_id = mCredentials.userId;
|
||||
mMyUser.user_id = mCredentials.getUserId();
|
||||
} else if (null != store) {
|
||||
// assume the profile is not yet initialized
|
||||
if ((null == store.displayName()) && (null != mMyUser.displayname)) {
|
||||
@ -634,7 +638,7 @@ public class MXDataHandler {
|
||||
*/
|
||||
public String getUserId() {
|
||||
if (isAlive()) {
|
||||
return mCredentials.userId;
|
||||
return mCredentials.getUserId();
|
||||
} else {
|
||||
return "dummy";
|
||||
}
|
||||
@ -934,7 +938,7 @@ public class MXDataHandler {
|
||||
|
||||
RoomSummary summary = mStore.getSummary(event.roomId);
|
||||
if (null == summary) {
|
||||
summary = new RoomSummary(null, lastEvent, beforeLiveRoomState, mCredentials.userId);
|
||||
summary = new RoomSummary(null, lastEvent, beforeLiveRoomState, mCredentials.getUserId());
|
||||
} else {
|
||||
summary.setLatestReceivedEvent(lastEvent, beforeLiveRoomState);
|
||||
}
|
||||
@ -1069,7 +1073,7 @@ public class MXDataHandler {
|
||||
* @param events the account data events list.
|
||||
* @return the ignored users list. null means that there is no defined user ids list.
|
||||
*/
|
||||
private List<String> ignoredUsers(List<Map<String, Object>> events) {
|
||||
public List<String> ignoredUsers(List<Map<String, Object>> events) {
|
||||
List<String> ignoredUsers = null;
|
||||
|
||||
if (0 != events.size()) {
|
||||
@ -1212,7 +1216,7 @@ public class MXDataHandler {
|
||||
user.setLatestPresenceTs(System.currentTimeMillis());
|
||||
|
||||
// check if the current user has been updated
|
||||
if (mCredentials.userId.equals(user.user_id)) {
|
||||
if (mCredentials.getUserId().equals(user.user_id)) {
|
||||
// always use the up-to-date information
|
||||
getMyUser().displayname = user.displayname;
|
||||
getMyUser().avatar_url = user.getAvatarUrl();
|
||||
@ -1420,7 +1424,7 @@ public class MXDataHandler {
|
||||
|
||||
if (hasChanged) {
|
||||
// Update account data to add new direct chat room(s)
|
||||
mAccountDataRestClient.setAccountData(mCredentials.userId, AccountDataRestClient.ACCOUNT_DATA_TYPE_DIRECT_MESSAGES,
|
||||
mAccountDataRestClient.setAccountData(mCredentials.getUserId(), AccountDataRestClient.ACCOUNT_DATA_TYPE_DIRECT_MESSAGES,
|
||||
updatedDirectChatRoomsDict, new ApiCallback<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void info) {
|
||||
@ -1532,10 +1536,6 @@ public class MXDataHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (null != mCrypto) {
|
||||
mCrypto.onSyncCompleted(syncResponse, fromToken, isCatchingUp);
|
||||
}
|
||||
|
||||
IMXStore store = getStore();
|
||||
|
||||
if (!isEmptyResponse && (null != store)) {
|
||||
@ -1890,7 +1890,7 @@ public class MXDataHandler {
|
||||
/**
|
||||
* Start the crypto
|
||||
*/
|
||||
private void startCrypto(final boolean isInitialSync) {
|
||||
public void startCrypto(final boolean isInitialSync) {
|
||||
if ((null != getCrypto()) && !getCrypto().isStarted() && !getCrypto().isStarting()) {
|
||||
getCrypto().setNetworkConnectivityReceiver(mNetworkConnectivityReceiver);
|
||||
getCrypto().start(isInitialSync, new ApiCallback<Void>() {
|
||||
|
@ -30,8 +30,24 @@ import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import im.vector.matrix.android.BuildConfig;
|
||||
import im.vector.matrix.android.R;
|
||||
import org.matrix.olm.OlmManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.call.MXCallsManager;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXCrypto;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXCryptoConfig;
|
||||
@ -79,7 +95,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.Versions;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.bingrules.BingRule;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterBody;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.LoginFlow;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.RegistrationFlowResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.message.MediaMessage;
|
||||
@ -101,21 +116,6 @@ import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import im.vector.matrix.android.internal.legacy.util.UnsentEventsManager;
|
||||
import im.vector.matrix.android.internal.legacy.util.VersionsUtil;
|
||||
import org.matrix.olm.OlmManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Class that represents one user's session with a particular home server.
|
||||
@ -192,38 +192,38 @@ public class MXSession {
|
||||
/**
|
||||
* Create a basic session for direct API calls.
|
||||
*
|
||||
* @param hsConfig the home server connection config
|
||||
* @param sessionParams the session connection data
|
||||
*/
|
||||
private MXSession(HomeServerConnectionConfig hsConfig) {
|
||||
mCredentials = hsConfig.getCredentials();
|
||||
mHsConfig = hsConfig;
|
||||
private MXSession(final SessionParams sessionParams) {
|
||||
mCredentials = sessionParams.getCredentials();
|
||||
mHsConfig = sessionParams.getHomeServerConnectionConfig();
|
||||
|
||||
mEventsRestClient = new EventsRestClient(hsConfig);
|
||||
mProfileRestClient = new ProfileRestClient(hsConfig);
|
||||
mPresenceRestClient = new PresenceRestClient(hsConfig);
|
||||
mRoomsRestClient = new RoomsRestClient(hsConfig);
|
||||
mPushRulesRestClient = new PushRulesRestClient(hsConfig);
|
||||
mPushersRestClient = new PushersRestClient(hsConfig);
|
||||
mThirdPidRestClient = new ThirdPidRestClient(hsConfig);
|
||||
mCallRestClient = new CallRestClient(hsConfig);
|
||||
mAccountDataRestClient = new AccountDataRestClient(hsConfig);
|
||||
mCryptoRestClient = new CryptoRestClient(hsConfig);
|
||||
mLoginRestClient = new LoginRestClient(hsConfig);
|
||||
mGroupsRestClient = new GroupsRestClient(hsConfig);
|
||||
mMediaScanRestClient = new MediaScanRestClient(hsConfig);
|
||||
mFilterRestClient = new FilterRestClient(hsConfig);
|
||||
mEventsRestClient = new EventsRestClient(sessionParams);
|
||||
mProfileRestClient = new ProfileRestClient(sessionParams);
|
||||
mPresenceRestClient = new PresenceRestClient(sessionParams);
|
||||
mRoomsRestClient = new RoomsRestClient(sessionParams);
|
||||
mPushRulesRestClient = new PushRulesRestClient(sessionParams);
|
||||
mPushersRestClient = new PushersRestClient(sessionParams);
|
||||
mThirdPidRestClient = new ThirdPidRestClient(sessionParams);
|
||||
mCallRestClient = new CallRestClient(sessionParams);
|
||||
mAccountDataRestClient = new AccountDataRestClient(sessionParams);
|
||||
mCryptoRestClient = new CryptoRestClient(sessionParams);
|
||||
mLoginRestClient = new LoginRestClient(sessionParams);
|
||||
mGroupsRestClient = new GroupsRestClient(sessionParams);
|
||||
mMediaScanRestClient = new MediaScanRestClient(sessionParams);
|
||||
mFilterRestClient = new FilterRestClient(sessionParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a user session with a data handler.
|
||||
* Private, please use the MxSession.Builder now
|
||||
*
|
||||
* @param hsConfig the home server connection config
|
||||
* @param dataHandler the data handler
|
||||
* @param appContext the application context
|
||||
* @param sessionParams the session connection data
|
||||
* @param dataHandler the data handler
|
||||
* @param appContext the application context
|
||||
*/
|
||||
private MXSession(HomeServerConnectionConfig hsConfig, MXDataHandler dataHandler, Context appContext) {
|
||||
this(hsConfig);
|
||||
private MXSession(final SessionParams sessionParams, MXDataHandler dataHandler, Context appContext) {
|
||||
this(sessionParams);
|
||||
mDataHandler = dataHandler;
|
||||
|
||||
mDataHandler.getStore().addMXStoreListener(new MXStoreListener() {
|
||||
@ -300,7 +300,7 @@ public class MXSession {
|
||||
|
||||
mUnsentEventsManager = new UnsentEventsManager(mNetworkConnectivityReceiver, mDataHandler);
|
||||
|
||||
mContentManager = new ContentManager(hsConfig, mUnsentEventsManager);
|
||||
mContentManager = new ContentManager(mHsConfig, mCredentials, mUnsentEventsManager);
|
||||
|
||||
//
|
||||
mCallsManager = new MXCallsManager(this, mAppContent);
|
||||
@ -321,8 +321,8 @@ public class MXSession {
|
||||
mGroupsRestClient.setUnsentEventsManager(mUnsentEventsManager);
|
||||
|
||||
// return the default cache manager
|
||||
mLatestChatMessageCache = new MXLatestChatMessageCache(mCredentials.userId);
|
||||
mMediasCache = new MXMediasCache(mContentManager, mNetworkConnectivityReceiver, mCredentials.userId, appContext);
|
||||
mLatestChatMessageCache = new MXLatestChatMessageCache(mCredentials.getUserId());
|
||||
mMediasCache = new MXMediasCache(mContentManager, mNetworkConnectivityReceiver, mCredentials.getUserId(), appContext);
|
||||
mDataHandler.setMediasCache(mMediasCache);
|
||||
|
||||
mMediaScanRestClient.setMxStore(mDataHandler.getStore());
|
||||
@ -380,9 +380,9 @@ public class MXSession {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user credentials.
|
||||
* Get the user getCredentials.
|
||||
*
|
||||
* @return the credentials
|
||||
* @return the getCredentials
|
||||
*/
|
||||
public Credentials getCredentials() {
|
||||
checkIfAlive();
|
||||
@ -842,7 +842,7 @@ public class MXSession {
|
||||
mEventsThread.setFailureCallback(mFailureCallback);
|
||||
}
|
||||
|
||||
if (mCredentials.accessToken != null && !mEventsThread.isAlive()) {
|
||||
if (mCredentials.getAccessToken() != null && !mEventsThread.isAlive()) {
|
||||
// GA issue
|
||||
try {
|
||||
mEventsThread.start();
|
||||
@ -860,35 +860,6 @@ public class MXSession {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the access token
|
||||
*/
|
||||
public void refreshToken() {
|
||||
checkIfAlive();
|
||||
|
||||
mProfileRestClient.refreshTokens(new ApiCallback<Credentials>() {
|
||||
@Override
|
||||
public void onSuccess(Credentials info) {
|
||||
Log.d(LOG_TAG, "refreshToken : succeeds.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkError(Exception e) {
|
||||
Log.e(LOG_TAG, "refreshToken : onNetworkError " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMatrixError(MatrixError e) {
|
||||
Log.e(LOG_TAG, "refreshToken : onMatrixError " + e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnexpectedError(Exception e) {
|
||||
Log.e(LOG_TAG, "refreshToken : onMatrixError " + e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the online status
|
||||
*
|
||||
@ -1246,7 +1217,7 @@ public class MXSession {
|
||||
|
||||
params.addCryptoAlgorithm(algorithm);
|
||||
params.setDirectMessage();
|
||||
params.addParticipantIds(mHsConfig, Arrays.asList(aParticipantUserId));
|
||||
params.addParticipantIds(mHsConfig, mCredentials, Arrays.asList(aParticipantUserId));
|
||||
|
||||
createRoom(params, aCreateRoomCallBack);
|
||||
}
|
||||
@ -2436,7 +2407,7 @@ public class MXSession {
|
||||
DeleteDeviceParams params = new DeleteDeviceParams();
|
||||
params.auth = new DeleteDeviceAuth();
|
||||
params.auth.session = registrationFlowResponse.session;
|
||||
params.auth.user = mCredentials.userId;
|
||||
params.auth.user = mCredentials.getUserId();
|
||||
params.auth.password = password;
|
||||
|
||||
Log.d(LOG_TAG, "## deleteDevice() : supported stages " + stages);
|
||||
@ -2512,10 +2483,12 @@ public class MXSession {
|
||||
* ========================================================================================== */
|
||||
|
||||
public static class Builder {
|
||||
private MXSession mxSession;
|
||||
|
||||
public Builder(HomeServerConnectionConfig hsConfig, MXDataHandler dataHandler, Context context) {
|
||||
mxSession = new MXSession(hsConfig, dataHandler, context);
|
||||
private MXSession mxSession;
|
||||
private SessionParams sessionParams;
|
||||
|
||||
public Builder(SessionParams sessionParams, MXDataHandler dataHandler, Context context) {
|
||||
mxSession = new MXSession(sessionParams, dataHandler, context);
|
||||
}
|
||||
|
||||
public Builder withFileEncryption(boolean enableFileEncryption) {
|
||||
@ -2538,9 +2511,8 @@ public class MXSession {
|
||||
try {
|
||||
HomeServerConnectionConfig alteredHsConfig = new HomeServerConnectionConfig.Builder()
|
||||
.withHomeServerUri(Uri.parse(pushServerUrl))
|
||||
.withCredentials(mxSession.mHsConfig.getCredentials())
|
||||
.build();
|
||||
pushersRestClient = new PushersRestClient(alteredHsConfig);
|
||||
pushersRestClient = new PushersRestClient(new SessionParams(sessionParams.getCredentials(), alteredHsConfig));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## withPushServerUrl() failed " + e.getMessage(), e);
|
||||
}
|
||||
@ -2562,7 +2534,6 @@ public class MXSession {
|
||||
*/
|
||||
public Builder withMetricsListener(@Nullable MetricsListener metricsListener) {
|
||||
mxSession.mMetricsListener = metricsListener;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -36,15 +36,16 @@ import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import im.vector.matrix.android.BuildConfig;
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXNetworkEventListener;
|
||||
import im.vector.matrix.android.internal.legacy.network.NetworkConnectivityReceiver;
|
||||
import im.vector.matrix.android.internal.legacy.rest.client.MXRestExecutorService;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.ssl.CertUtil;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import im.vector.matrix.android.internal.legacy.util.PolymorphicRequestBodyConverter;
|
||||
import im.vector.matrix.android.internal.legacy.util.UnsentEventsManager;
|
||||
import im.vector.matrix.android.internal.network.ssl.CertUtil;
|
||||
import okhttp3.Dispatcher;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
@ -53,12 +54,12 @@ import okhttp3.Response;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Class for making Matrix API calls.
|
||||
*/
|
||||
public class RestClient<T> {
|
||||
private static final String LOG_TAG = RestClient.class.getSimpleName();
|
||||
|
||||
public static final String URI_API_PREFIX_PATH_MEDIA_R0 = "_matrix/media/r0/";
|
||||
public static final String URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE = "_matrix/media_proxy/unstable/";
|
||||
@ -103,38 +104,37 @@ public class RestClient<T> {
|
||||
// http client
|
||||
private OkHttpClient mOkHttpClient = new OkHttpClient();
|
||||
|
||||
public RestClient(HomeServerConnectionConfig hsConfig, Class<T> type, String uriPrefix, boolean withNullSerialization) {
|
||||
this(hsConfig, type, uriPrefix, withNullSerialization, EndPointServer.HOME_SERVER);
|
||||
public RestClient(SessionParams sessionParams, Class<T> type, String uriPrefix, boolean withNullSerialization) {
|
||||
this(sessionParams, type, uriPrefix, withNullSerialization, EndPointServer.HOME_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor.
|
||||
*
|
||||
* @param hsConfig the home server configuration.
|
||||
* @param sessionParams the session data
|
||||
* @param type the REST type
|
||||
* @param uriPrefix the URL request prefix
|
||||
* @param withNullSerialization true to serialise class member with null value
|
||||
* @param useIdentityServer true to use the identity server URL as base request
|
||||
*/
|
||||
public RestClient(HomeServerConnectionConfig hsConfig, Class<T> type, String uriPrefix, boolean withNullSerialization, boolean useIdentityServer) {
|
||||
this(hsConfig, type, uriPrefix, withNullSerialization, useIdentityServer ? EndPointServer.IDENTITY_SERVER : EndPointServer.HOME_SERVER);
|
||||
public RestClient(SessionParams sessionParams, Class<T> type, String uriPrefix, boolean withNullSerialization, boolean useIdentityServer) {
|
||||
this(sessionParams, type, uriPrefix, withNullSerialization, useIdentityServer ? EndPointServer.IDENTITY_SERVER : EndPointServer.HOME_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor.
|
||||
*
|
||||
* @param hsConfig the home server configuration.
|
||||
* @param sessionParams the session data
|
||||
* @param type the REST type
|
||||
* @param uriPrefix the URL request prefix
|
||||
* @param withNullSerialization true to serialise class member with null value
|
||||
* @param endPointServer tell which server is used to define the base url
|
||||
*/
|
||||
public RestClient(HomeServerConnectionConfig hsConfig, Class<T> type, String uriPrefix, boolean withNullSerialization, EndPointServer endPointServer) {
|
||||
public RestClient(SessionParams sessionParams, Class<T> type, String uriPrefix, boolean withNullSerialization, EndPointServer endPointServer) {
|
||||
// The JSON -> object mapper
|
||||
gson = JsonUtils.getGson(withNullSerialization);
|
||||
|
||||
mHsConfig = hsConfig;
|
||||
mCredentials = hsConfig.getCredentials();
|
||||
mHsConfig = sessionParams.getHomeServerConnectionConfig();
|
||||
mCredentials = sessionParams.getCredentials();
|
||||
|
||||
Interceptor authentInterceptor = new Interceptor() {
|
||||
|
||||
@ -146,12 +146,10 @@ public class RestClient<T> {
|
||||
// set a custom user agent
|
||||
newRequestBuilder.addHeader("User-Agent", sUserAgent);
|
||||
}
|
||||
|
||||
// Add the access token to all requests if it is set
|
||||
if ((mCredentials != null) && (mCredentials.accessToken != null)) {
|
||||
newRequestBuilder.addHeader("Authorization", "Bearer " + mCredentials.accessToken);
|
||||
if (mCredentials != null) {
|
||||
newRequestBuilder.addHeader("Authorization", "Bearer " + mCredentials.getAccessToken());
|
||||
}
|
||||
|
||||
request = newRequestBuilder.build();
|
||||
|
||||
return chain.proceed(request);
|
||||
@ -191,17 +189,15 @@ public class RestClient<T> {
|
||||
}
|
||||
|
||||
try {
|
||||
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.newPinnedSSLSocketFactory(hsConfig);
|
||||
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.INSTANCE.newPinnedSSLSocketFactory(mHsConfig);
|
||||
okHttpClientBuilder.sslSocketFactory(pair.first, pair.second);
|
||||
okHttpClientBuilder.hostnameVerifier(CertUtil.newHostnameVerifier(hsConfig));
|
||||
okHttpClientBuilder.connectionSpecs(CertUtil.newConnectionSpecs(hsConfig));
|
||||
okHttpClientBuilder.hostnameVerifier(CertUtil.INSTANCE.newHostnameVerifier(mHsConfig));
|
||||
okHttpClientBuilder.connectionSpecs(CertUtil.INSTANCE.newConnectionSpecs(mHsConfig));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## RestClient() setSslSocketFactory failed" + e.getMessage(), e);
|
||||
Timber.e("## RestClient() setSslSocketFactory failed" + e.getMessage(), e);
|
||||
}
|
||||
|
||||
mOkHttpClient = okHttpClientBuilder.build();
|
||||
final String endPoint = makeEndpoint(hsConfig, uriPrefix, endPointServer);
|
||||
|
||||
final String endPoint = makeEndpoint(mHsConfig, uriPrefix, endPointServer);
|
||||
// Rest adapter for turning API interfaces into actual REST-calling objects
|
||||
Retrofit.Builder builder = new Retrofit.Builder()
|
||||
.baseUrl(endPoint)
|
||||
@ -226,9 +222,12 @@ public class RestClient<T> {
|
||||
break;
|
||||
case HOME_SERVER:
|
||||
default:
|
||||
baseUrl = hsConfig.getHomeserverUri().toString();
|
||||
baseUrl = hsConfig.getHomeServerUri().toString();
|
||||
|
||||
}
|
||||
if (baseUrl == null) {
|
||||
throw new IllegalArgumentException("Base url shouldn't be null");
|
||||
}
|
||||
baseUrl = sanitizeBaseUrl(baseUrl);
|
||||
String dynamicPath = sanitizeDynamicPath(uriPrefix);
|
||||
return baseUrl + dynamicPath;
|
||||
@ -270,7 +269,7 @@ public class RestClient<T> {
|
||||
PackageInfo pkgInfo = pm.getPackageInfo(appContext.getApplicationContext().getPackageName(), 0);
|
||||
appVersion = pkgInfo.versionName;
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## initUserAgent() : failed " + e.getMessage(), e);
|
||||
Timber.e("## initUserAgent() : failed " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,12 +320,12 @@ public class RestClient<T> {
|
||||
.readTimeout((int) (READ_TIMEOUT_MS * factor), TimeUnit.MILLISECONDS)
|
||||
.writeTimeout((int) (WRITE_TIMEOUT_MS * factor), TimeUnit.MILLISECONDS);
|
||||
|
||||
Log.d(LOG_TAG, "## refreshConnectionTimeout() : update setConnectTimeout to " + (CONNECTION_TIMEOUT_MS * factor) + " ms");
|
||||
Log.d(LOG_TAG, "## refreshConnectionTimeout() : update setReadTimeout to " + (READ_TIMEOUT_MS * factor) + " ms");
|
||||
Log.d(LOG_TAG, "## refreshConnectionTimeout() : update setWriteTimeout to " + (WRITE_TIMEOUT_MS * factor) + " ms");
|
||||
Timber.d("## refreshConnectionTimeout() : update setConnectTimeout to " + (CONNECTION_TIMEOUT_MS * factor) + " ms");
|
||||
Timber.d("## refreshConnectionTimeout() : update setReadTimeout to " + (READ_TIMEOUT_MS * factor) + " ms");
|
||||
Timber.d("## refreshConnectionTimeout() : update setWriteTimeout to " + (WRITE_TIMEOUT_MS * factor) + " ms");
|
||||
} else {
|
||||
builder.connectTimeout(1, TimeUnit.MILLISECONDS);
|
||||
Log.d(LOG_TAG, "## refreshConnectionTimeout() : update the requests timeout to 1 ms");
|
||||
Timber.d("## refreshConnectionTimeout() : update the requests timeout to 1 ms");
|
||||
}
|
||||
|
||||
// FIXME It has no effect to the rest client
|
||||
@ -373,25 +372,25 @@ public class RestClient<T> {
|
||||
networkConnectivityReceiver.addEventListener(new IMXNetworkEventListener() {
|
||||
@Override
|
||||
public void onNetworkConnectionUpdate(boolean isConnected) {
|
||||
Log.d(LOG_TAG, "## setUnsentEventsManager() : update the requests timeout to " + (isConnected ? CONNECTION_TIMEOUT_MS : 1) + " ms");
|
||||
Timber.d("## setUnsentEventsManager() : update the requests timeout to " + (isConnected ? CONNECTION_TIMEOUT_MS : 1) + " ms");
|
||||
refreshConnectionTimeout(networkConnectivityReceiver);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's credentials. Typically for saving them somewhere persistent.
|
||||
* Get the user's getCredentials. Typically for saving them somewhere persistent.
|
||||
*
|
||||
* @return the user credentials
|
||||
* @return the user getCredentials
|
||||
*/
|
||||
public Credentials getCredentials() {
|
||||
return mCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the user's credentials. To be called after login or registration.
|
||||
* Provide the user's getCredentials. To be called after login or registration.
|
||||
*
|
||||
* @param credentials the user credentials
|
||||
* @param credentials the user getCredentials
|
||||
*/
|
||||
public void setCredentials(Credentials credentials) {
|
||||
mCredentials = credentials;
|
||||
|
@ -26,13 +26,6 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.MXSession;
|
||||
import im.vector.matrix.android.internal.legacy.data.Room;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.Event;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@ -40,6 +33,13 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.MXSession;
|
||||
import im.vector.matrix.android.internal.legacy.data.Room;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.Event;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
/**
|
||||
* This class is the default implementation
|
||||
*/
|
||||
@ -657,7 +657,7 @@ public class MXCall implements IMXCall {
|
||||
hangupContent.add("reason", new JsonPrimitive(reason));
|
||||
}
|
||||
|
||||
Event event = new Event(Event.EVENT_TYPE_CALL_HANGUP, hangupContent, mSession.getCredentials().userId, mCallSignalingRoom.getRoomId());
|
||||
Event event = new Event(Event.EVENT_TYPE_CALL_HANGUP, hangupContent, mSession.getCredentials().getUserId(), mCallSignalingRoom.getRoomId());
|
||||
|
||||
// local notification to indicate the end of call
|
||||
mUIThreadHandler.post(new Runnable() {
|
||||
|
@ -631,7 +631,7 @@ public class MXChromeCall extends MXCall {
|
||||
}
|
||||
|
||||
if (addIt) {
|
||||
Event event = new Event(eventType, content, mSession.getCredentials().userId, mCallSignalingRoom.getRoomId());
|
||||
Event event = new Event(eventType, content, mSession.getCredentials().getUserId(), mCallSignalingRoom.getRoomId());
|
||||
|
||||
if (null != event) {
|
||||
// receive an hangup -> close the window asap
|
||||
|
@ -374,7 +374,7 @@ public class MXWebRtcCall extends MXCall {
|
||||
offerContent.addProperty("type", sessionDescription.type.canonicalForm());
|
||||
inviteContent.add("offer", offerContent);
|
||||
|
||||
Event event = new Event(Event.EVENT_TYPE_CALL_INVITE, inviteContent, mSession.getCredentials().userId, mCallSignalingRoom.getRoomId());
|
||||
Event event = new Event(Event.EVENT_TYPE_CALL_INVITE, inviteContent, mSession.getCredentials().getUserId(), mCallSignalingRoom.getRoomId());
|
||||
|
||||
mPendingEvents.add(event);
|
||||
|
||||
@ -434,7 +434,7 @@ public class MXWebRtcCall extends MXCall {
|
||||
offerContent.addProperty("type", sessionDescription.type.canonicalForm());
|
||||
answerContent.add("answer", offerContent);
|
||||
|
||||
Event event = new Event(Event.EVENT_TYPE_CALL_ANSWER, answerContent, mSession.getCredentials().userId, mCallSignalingRoom.getRoomId());
|
||||
Event event = new Event(Event.EVENT_TYPE_CALL_ANSWER, answerContent, mSession.getCredentials().getUserId(), mCallSignalingRoom.getRoomId());
|
||||
mPendingEvents.add(event);
|
||||
sendNextEvent();
|
||||
|
||||
@ -737,7 +737,7 @@ public class MXWebRtcCall extends MXCall {
|
||||
}
|
||||
|
||||
if (addIt) {
|
||||
Event event = new Event(Event.EVENT_TYPE_CALL_CANDIDATES, content, mSession.getCredentials().userId,
|
||||
Event event = new Event(Event.EVENT_TYPE_CALL_CANDIDATES, content, mSession.getCredentials().getUserId(),
|
||||
mCallSignalingRoom.getRoomId());
|
||||
|
||||
mPendingEvents.add(event);
|
||||
|
@ -207,17 +207,17 @@ public class MXCrypto {
|
||||
mRoomEncryptors = new HashMap<>();
|
||||
mRoomDecryptors = new HashMap<>();
|
||||
|
||||
String deviceId = mSession.getCredentials().deviceId;
|
||||
String deviceId = mSession.getCredentials().getDeviceId();
|
||||
// deviceId should always be defined
|
||||
boolean refreshDevicesList = !TextUtils.isEmpty(deviceId);
|
||||
|
||||
if (TextUtils.isEmpty(deviceId)) {
|
||||
// use the stored one
|
||||
mSession.getCredentials().deviceId = deviceId = mCryptoStore.getDeviceId();
|
||||
deviceId = mCryptoStore.getDeviceId();
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(deviceId)) {
|
||||
mSession.getCredentials().deviceId = deviceId = UUID.randomUUID().toString();
|
||||
deviceId = UUID.randomUUID().toString();
|
||||
Log.d(LOG_TAG, "Warning: No device id in MXCredentials. An id was created. Think of storing it");
|
||||
mCryptoStore.storeDeviceId(deviceId);
|
||||
}
|
||||
@ -230,11 +230,11 @@ public class MXCrypto {
|
||||
Map<String, String> keys = new HashMap<>();
|
||||
|
||||
if (!TextUtils.isEmpty(mOlmDevice.getDeviceEd25519Key())) {
|
||||
keys.put("ed25519:" + mSession.getCredentials().deviceId, mOlmDevice.getDeviceEd25519Key());
|
||||
keys.put("ed25519:" + mSession.getCredentials().getDeviceId(), mOlmDevice.getDeviceEd25519Key());
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(mOlmDevice.getDeviceCurve25519Key())) {
|
||||
keys.put("curve25519:" + mSession.getCredentials().deviceId, mOlmDevice.getDeviceCurve25519Key());
|
||||
keys.put("curve25519:" + mSession.getCredentials().getDeviceId(), mOlmDevice.getDeviceCurve25519Key());
|
||||
}
|
||||
|
||||
mMyDevice.keys = keys;
|
||||
@ -441,7 +441,7 @@ public class MXCrypto {
|
||||
if (!hasBeenReleased()) {
|
||||
Log.d(LOG_TAG, "###########################################################");
|
||||
Log.d(LOG_TAG, "uploadDeviceKeys done for " + mSession.getMyUserId());
|
||||
Log.d(LOG_TAG, " - device id : " + mSession.getCredentials().deviceId);
|
||||
Log.d(LOG_TAG, " - device id : " + mSession.getCredentials().getDeviceId());
|
||||
Log.d(LOG_TAG, " - ed25519 : " + mOlmDevice.getDeviceEd25519Key());
|
||||
Log.d(LOG_TAG, " - curve25519 : " + mOlmDevice.getDeviceCurve25519Key());
|
||||
Log.d(LOG_TAG, " - oneTimeKeys: " + mLastPublishedOneTimeKeys); // They are
|
||||
@ -600,17 +600,17 @@ public class MXCrypto {
|
||||
* @param fromToken the start sync token
|
||||
* @param isCatchingUp true if there is a catch-up in progress.
|
||||
*/
|
||||
public void onSyncCompleted(final SyncResponse syncResponse, final String fromToken, final boolean isCatchingUp) {
|
||||
public void onSyncCompleted(final im.vector.matrix.android.internal.events.sync.data.SyncResponse syncResponse, final String fromToken, final boolean isCatchingUp) {
|
||||
getEncryptingThreadHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (null != syncResponse.deviceLists) {
|
||||
getDeviceList().handleDeviceListsChanges(syncResponse.deviceLists.changed, syncResponse.deviceLists.left);
|
||||
if (null != syncResponse.getDeviceLists()) {
|
||||
getDeviceList().handleDeviceListsChanges(syncResponse.getDeviceLists().getChanged(), syncResponse.getDeviceLists().getLeft());
|
||||
}
|
||||
|
||||
if (null != syncResponse.deviceOneTimeKeysCount) {
|
||||
int currentCount = (null != syncResponse.deviceOneTimeKeysCount.signed_curve25519) ?
|
||||
syncResponse.deviceOneTimeKeysCount.signed_curve25519 : 0;
|
||||
if (null != syncResponse.getDeviceOneTimeKeysCount()) {
|
||||
int currentCount = (null != syncResponse.getDeviceOneTimeKeysCount().getSignedCurve25519()) ?
|
||||
syncResponse.getDeviceOneTimeKeysCount().getSignedCurve25519() : 0;
|
||||
updateOneTimeKeyCount(currentCount);
|
||||
}
|
||||
|
||||
@ -1470,7 +1470,7 @@ public class MXCrypto {
|
||||
Map<String, Object> payloadJson = new HashMap<>(payloadFields);
|
||||
|
||||
payloadJson.put("sender", mSession.getMyUserId());
|
||||
payloadJson.put("sender_device", mSession.getCredentials().deviceId);
|
||||
payloadJson.put("sender_device", mSession.getCredentials().getDeviceId());
|
||||
|
||||
// Include the Ed25519 key so that the recipient knows what
|
||||
// device this message came from.
|
||||
|
@ -22,6 +22,12 @@ import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.MXSession;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXCrypto;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXCryptoAlgorithms;
|
||||
@ -39,12 +45,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MXMegolmEncryption implements IMXEncrypting {
|
||||
private static final String LOG_TAG = MXMegolmEncryption.class.getSimpleName();
|
||||
|
||||
@ -76,7 +76,7 @@ public class MXMegolmEncryption implements IMXEncrypting {
|
||||
mCrypto = matrixSession.getCrypto();
|
||||
|
||||
mRoomId = roomId;
|
||||
mDeviceId = matrixSession.getCredentials().deviceId;
|
||||
mDeviceId = matrixSession.getCredentials().getDeviceId();
|
||||
|
||||
// Default rotation periods
|
||||
// TODO: Make it configurable via parameters
|
||||
|
@ -18,11 +18,11 @@ package im.vector.matrix.android.internal.legacy.data.cryptostore;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.IncomingRoomKeyRequest;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.OutgoingRoomKeyRequest;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXDeviceInfo;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXOlmInboundGroupSession2;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import org.matrix.olm.OlmAccount;
|
||||
import org.matrix.olm.OlmSession;
|
||||
|
||||
@ -35,10 +35,10 @@ import java.util.Set;
|
||||
*/
|
||||
public interface IMXCryptoStore {
|
||||
/**
|
||||
* Init a crypto store for the passed credentials.
|
||||
* Init a crypto store for the passed getCredentials.
|
||||
*
|
||||
* @param context the application context
|
||||
* @param credentials the credentials of the account.
|
||||
* @param credentials the getCredentials of the account.
|
||||
*/
|
||||
void initWithCredentials(Context context, Credentials credentials);
|
||||
|
||||
@ -55,7 +55,7 @@ public interface IMXCryptoStore {
|
||||
boolean hasData();
|
||||
|
||||
/**
|
||||
* Delete the crypto store for the passed credentials.
|
||||
* Delete the crypto store for the passed getCredentials.
|
||||
*/
|
||||
void deleteStore();
|
||||
|
||||
|
@ -22,16 +22,6 @@ import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.crypto.IncomingRoomKeyRequest;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.OutgoingRoomKeyRequest;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXDeviceInfo;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXOlmInboundGroupSession;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXOlmInboundGroupSession2;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXUsersDevicesMap;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.util.CompatUtil;
|
||||
import im.vector.matrix.android.internal.legacy.util.ContentUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import org.matrix.olm.OlmAccount;
|
||||
import org.matrix.olm.OlmSession;
|
||||
|
||||
@ -51,6 +41,17 @@ import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.IncomingRoomKeyRequest;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.OutgoingRoomKeyRequest;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXDeviceInfo;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXOlmInboundGroupSession;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXOlmInboundGroupSession2;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXUsersDevicesMap;
|
||||
import im.vector.matrix.android.internal.legacy.util.CompatUtil;
|
||||
import im.vector.matrix.android.internal.legacy.util.ContentUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
/**
|
||||
* the crypto data store
|
||||
*/
|
||||
@ -91,7 +92,7 @@ public class MXFileCryptoStore implements IMXCryptoStore {
|
||||
private static final String MXFILE_CRYPTO_STORE_INCOMING_ROOM_KEY_REQUESTS_FILE = "incomingRoomKeyRequests";
|
||||
private static final String MXFILE_CRYPTO_STORE_INCOMING_ROOM_KEY_REQUESTS_FILE_TMP = "incomingRoomKeyRequests.tmp";
|
||||
|
||||
// The credentials used for this store
|
||||
// The getCredentials used for this store
|
||||
private Credentials mCredentials;
|
||||
|
||||
// Meta data about the store
|
||||
@ -182,7 +183,7 @@ public class MXFileCryptoStore implements IMXCryptoStore {
|
||||
public void initWithCredentials(Context context, Credentials credentials) {
|
||||
mCredentials = credentials;
|
||||
|
||||
mStoreFile = new File(new File(context.getApplicationContext().getFilesDir(), MXFILE_CRYPTO_STORE_FOLDER), mCredentials.userId);
|
||||
mStoreFile = new File(new File(context.getApplicationContext().getFilesDir(), MXFILE_CRYPTO_STORE_FOLDER), mCredentials.getUserId());
|
||||
|
||||
mMetaDataFile = new File(mStoreFile, MXFILE_CRYPTO_STORE_METADATA_FILE);
|
||||
mMetaDataFileTmp = new File(mStoreFile, MXFILE_CRYPTO_STORE_METADATA_FILE_TMP);
|
||||
@ -217,11 +218,8 @@ public class MXFileCryptoStore implements IMXCryptoStore {
|
||||
mIncomingRoomKeyRequestsFileTmp = new File(mStoreFile, MXFILE_CRYPTO_STORE_INCOMING_ROOM_KEY_REQUESTS_FILE_TMP);
|
||||
|
||||
// Build default metadata
|
||||
if ((null == mMetaData)
|
||||
&& (null != credentials.homeServer)
|
||||
&& (null != credentials.userId)
|
||||
&& (null != credentials.accessToken)) {
|
||||
mMetaData = new MXFileCryptoStoreMetaData2(mCredentials.userId, mCredentials.deviceId, MXFILE_CRYPTO_VERSION);
|
||||
if (mMetaData == null) {
|
||||
mMetaData = new MXFileCryptoStoreMetaData2(mCredentials.getUserId(), mCredentials.getDeviceId(), MXFILE_CRYPTO_VERSION);
|
||||
}
|
||||
|
||||
mUsersDevicesInfoMap = new MXUsersDevicesMap<>();
|
||||
@ -243,7 +241,7 @@ public class MXFileCryptoStore implements IMXCryptoStore {
|
||||
|
||||
if (null != mMetaData) {
|
||||
result = TextUtils.isEmpty(mMetaData.mDeviceId)
|
||||
|| TextUtils.equals(mCredentials.deviceId, mMetaData.mDeviceId);
|
||||
|| TextUtils.equals(mCredentials.getDeviceId(), mMetaData.mDeviceId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,11 +282,11 @@ public class MXFileCryptoStore implements IMXCryptoStore {
|
||||
Log.e(LOG_TAG, "## open() : New MXFileCryptoStore version detected");
|
||||
resetData();
|
||||
}
|
||||
// Check credentials
|
||||
// The device id may not have been provided in credentials.
|
||||
// Check getCredentials
|
||||
// The device id may not have been provided in getCredentials.
|
||||
// Check it only if provided, else trust the stored one.
|
||||
else if (!TextUtils.equals(mMetaData.mUserId, mCredentials.userId)
|
||||
|| ((null != mCredentials.deviceId) && !TextUtils.equals(mCredentials.deviceId, mMetaData.mDeviceId))) {
|
||||
else if (!TextUtils.equals(mMetaData.mUserId, mCredentials.getUserId())
|
||||
|| ((null != mCredentials.getDeviceId()) && !TextUtils.equals(mCredentials.getDeviceId(), mMetaData.mDeviceId))) {
|
||||
Log.e(LOG_TAG, "## open() : Credentials do not match");
|
||||
resetData();
|
||||
}
|
||||
@ -298,12 +296,9 @@ public class MXFileCryptoStore implements IMXCryptoStore {
|
||||
preloadCryptoData();
|
||||
}
|
||||
|
||||
// Else, if credentials is valid, create and store it
|
||||
if ((null == mMetaData)
|
||||
&& (null != mCredentials.homeServer)
|
||||
&& (null != mCredentials.userId)
|
||||
&& (null != mCredentials.accessToken)) {
|
||||
mMetaData = new MXFileCryptoStoreMetaData2(mCredentials.userId, mCredentials.deviceId, MXFILE_CRYPTO_VERSION);
|
||||
// Else, if getCredentials is valid, create and store it
|
||||
if (mMetaData == null){
|
||||
mMetaData = new MXFileCryptoStoreMetaData2(mCredentials.getUserId(), mCredentials.getDeviceId(), MXFILE_CRYPTO_VERSION);
|
||||
mIsReady = true;
|
||||
// flush the metadata
|
||||
saveMetaData();
|
||||
|
@ -23,25 +23,6 @@ import android.os.HandlerThread;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.legacy.data.Room;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomAccountData;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomState;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomSummary;
|
||||
import im.vector.matrix.android.internal.legacy.data.timeline.EventTimeline;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.Event;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.ReceiptData;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.RoomMember;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.TokensChunkEvents;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.User;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.Group;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThirdPartyIdentifier;
|
||||
import im.vector.matrix.android.internal.legacy.util.CompatUtil;
|
||||
import im.vector.matrix.android.internal.legacy.util.ContentUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import im.vector.matrix.android.internal.legacy.util.MXOsHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@ -60,6 +41,25 @@ import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.data.Room;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomAccountData;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomState;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomSummary;
|
||||
import im.vector.matrix.android.internal.legacy.data.timeline.EventTimeline;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.Event;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.ReceiptData;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.RoomMember;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.TokensChunkEvents;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.User;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.Group;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThirdPartyIdentifier;
|
||||
import im.vector.matrix.android.internal.legacy.util.CompatUtil;
|
||||
import im.vector.matrix.android.internal.legacy.util.ContentUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import im.vector.matrix.android.internal.legacy.util.MXOsHandler;
|
||||
|
||||
/**
|
||||
* An in-file IMXStore.
|
||||
*/
|
||||
@ -217,21 +217,21 @@ public class MXFileStore extends MXMemoryStore {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param hsConfig the expected credentials
|
||||
* @param credentials the expected getCredentials
|
||||
* @param enableFileEncryption set to true to enable file encryption.
|
||||
* @param context the context.
|
||||
*/
|
||||
public MXFileStore(HomeServerConnectionConfig hsConfig, boolean enableFileEncryption, Context context) {
|
||||
public MXFileStore(Credentials credentials, boolean enableFileEncryption, Context context) {
|
||||
setContext(context);
|
||||
|
||||
mEnableFileEncryption = enableFileEncryption;
|
||||
|
||||
mIsReady = false;
|
||||
mCredentials = hsConfig.getCredentials();
|
||||
mCredentials = credentials;
|
||||
|
||||
mHandlerThread = new HandlerThread("MXFileStoreBackgroundThread_" + mCredentials.userId, Thread.MIN_PRIORITY);
|
||||
mHandlerThread = new HandlerThread("MXFileStoreBackgroundThread_" + mCredentials.getUserId(), Thread.MIN_PRIORITY);
|
||||
|
||||
createDirTree(mCredentials.userId);
|
||||
createDirTree(mCredentials.getUserId());
|
||||
|
||||
// updated data
|
||||
mRoomsToCommitForMessages = new HashSet<>();
|
||||
@ -260,8 +260,8 @@ public class MXFileStore extends MXMemoryStore {
|
||||
mFileStoreHandler = new MXOsHandler(mHandlerThread.getLooper());
|
||||
|
||||
mMetadata = new MXFileStoreMetaData();
|
||||
mMetadata.mUserId = mCredentials.userId;
|
||||
mMetadata.mAccessToken = mCredentials.accessToken;
|
||||
mMetadata.mUserId = mCredentials.getUserId();
|
||||
mMetadata.mAccessToken = mCredentials.getAccessToken();
|
||||
mMetadata.mVersion = MXFILE_VERSION;
|
||||
mMetaDataHasChanged = true;
|
||||
saveMetaData();
|
||||
@ -360,8 +360,8 @@ public class MXFileStore extends MXMemoryStore {
|
||||
|
||||
String errorDescription = null;
|
||||
boolean succeed = (mMetadata.mVersion == MXFILE_VERSION)
|
||||
&& TextUtils.equals(mMetadata.mUserId, mCredentials.userId)
|
||||
&& TextUtils.equals(mMetadata.mAccessToken, mCredentials.accessToken);
|
||||
&& TextUtils.equals(mMetadata.mUserId, mCredentials.getUserId())
|
||||
&& TextUtils.equals(mMetadata.mAccessToken, mCredentials.getAccessToken());
|
||||
|
||||
if (!succeed) {
|
||||
errorDescription = "Invalid store content";
|
||||
@ -437,7 +437,7 @@ public class MXFileStore extends MXMemoryStore {
|
||||
if (null == room) {
|
||||
succeed = false;
|
||||
Log.e(LOG_TAG, "loadSummaries : the room " + roomId + " does not exist");
|
||||
} else if (null == room.getMember(mCredentials.userId)) {
|
||||
} else if (null == room.getMember(mCredentials.getUserId())) {
|
||||
//succeed = false;
|
||||
Log.e(LOG_TAG, "loadSummaries) : a summary exists for the roomId "
|
||||
+ roomId + " but the user is not anymore a member");
|
||||
@ -482,8 +482,8 @@ public class MXFileStore extends MXMemoryStore {
|
||||
// mMetadata should only be null at file store loading
|
||||
if (null == mMetadata) {
|
||||
mMetadata = new MXFileStoreMetaData();
|
||||
mMetadata.mUserId = mCredentials.userId;
|
||||
mMetadata.mAccessToken = mCredentials.accessToken;
|
||||
mMetadata.mUserId = mCredentials.getUserId();
|
||||
mMetadata.mAccessToken = mCredentials.getAccessToken();
|
||||
mMetaDataHasChanged = true;
|
||||
} else {
|
||||
mMetadata.mEventStreamToken = null;
|
||||
@ -515,7 +515,7 @@ public class MXFileStore extends MXMemoryStore {
|
||||
|
||||
// post processing
|
||||
Log.d(LOG_TAG, "## open() : post processing.");
|
||||
dispatchPostProcess(mCredentials.userId);
|
||||
dispatchPostProcess(mCredentials.getUserId());
|
||||
mIsPostProcessingDone = true;
|
||||
|
||||
synchronized (this) {
|
||||
@ -525,7 +525,7 @@ public class MXFileStore extends MXMemoryStore {
|
||||
|
||||
if (!succeed && !mIsNewStorage) {
|
||||
Log.e(LOG_TAG, "The store is corrupted.");
|
||||
dispatchOnStoreCorrupted(mCredentials.userId, errorDescription);
|
||||
dispatchOnStoreCorrupted(mCredentials.getUserId(), errorDescription);
|
||||
} else {
|
||||
// extract the room states
|
||||
mRoomReceiptsToLoad.addAll(listFiles(mStoreRoomsMessagesReceiptsFolderFile.list()));
|
||||
@ -535,7 +535,7 @@ public class MXFileStore extends MXMemoryStore {
|
||||
}
|
||||
|
||||
Log.d(LOG_TAG, "The store is opened.");
|
||||
dispatchOnStoreReady(mCredentials.userId);
|
||||
dispatchOnStoreReady(mCredentials.getUserId());
|
||||
|
||||
// load the following items with delay
|
||||
// theses items are not required to be ready
|
||||
@ -567,12 +567,12 @@ public class MXFileStore extends MXMemoryStore {
|
||||
} else {
|
||||
if (!mIsPostProcessingDone) {
|
||||
Log.e(LOG_TAG, "## open() : is ready but the post processing was not yet done.");
|
||||
dispatchPostProcess(mCredentials.userId);
|
||||
dispatchPostProcess(mCredentials.getUserId());
|
||||
mIsPostProcessingDone = true;
|
||||
} else {
|
||||
Log.e(LOG_TAG, "## open() when ready : the post processing is already done.");
|
||||
}
|
||||
dispatchOnStoreReady(mCredentials.userId);
|
||||
dispatchOnStoreReady(mCredentials.getUserId());
|
||||
mPreloadTime = System.currentTimeMillis() - fLoadTimeT0;
|
||||
if (mMetricsListener != null) {
|
||||
mMetricsListener.onStorePreloaded(mPreloadTime);
|
||||
@ -662,7 +662,7 @@ public class MXFileStore extends MXMemoryStore {
|
||||
try {
|
||||
ContentUtils.deleteDirectory(mStoreFolderFile);
|
||||
if (init) {
|
||||
createDirTree(mCredentials.userId);
|
||||
createDirTree(mCredentials.getUserId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "deleteAllData failed " + e.getMessage(), e);
|
||||
@ -790,7 +790,7 @@ public class MXFileStore extends MXMemoryStore {
|
||||
|
||||
@Override
|
||||
public void storeUser(User user) {
|
||||
if (!TextUtils.equals(mCredentials.userId, user.user_id)) {
|
||||
if (!TextUtils.equals(mCredentials.getUserId(), user.user_id)) {
|
||||
mUserIdsToCommit.add(user.user_id);
|
||||
}
|
||||
super.storeUser(user);
|
||||
|
@ -24,6 +24,7 @@ import android.os.Looper;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.MXDataHandler;
|
||||
import im.vector.matrix.android.internal.legacy.data.Room;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomAccountData;
|
||||
@ -38,7 +39,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.RoomMember;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.TokensChunkEvents;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.User;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.Group;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThirdPartyIdentifier;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
@ -149,7 +149,7 @@ public class MXMemoryStore implements IMXStore {
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param credentials the expected credentials
|
||||
* @param credentials the expected getCredentials
|
||||
* @param context the context
|
||||
*/
|
||||
public MXMemoryStore(Credentials credentials, Context context) {
|
||||
@ -245,7 +245,7 @@ public class MXMemoryStore implements IMXStore {
|
||||
*/
|
||||
@Override
|
||||
public void setCorrupted(String reason) {
|
||||
dispatchOnStoreCorrupted(mCredentials.userId, reason);
|
||||
dispatchOnStoreCorrupted(mCredentials.getUserId(), reason);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -607,7 +607,7 @@ public class MXMemoryStore implements IMXStore {
|
||||
*/
|
||||
@Override
|
||||
public int eventsCountAfter(String roomId, String eventId) {
|
||||
return eventsAfter(roomId, eventId, mCredentials.userId, null).size();
|
||||
return eventsAfter(roomId, eventId, mCredentials.getUserId(), null).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1155,7 +1155,7 @@ public class MXMemoryStore implements IMXStore {
|
||||
|
||||
synchronized (mReceiptsByRoomIdLock) {
|
||||
if (mReceiptsByRoomId.containsKey(roomId)) {
|
||||
String myUserID = mCredentials.userId;
|
||||
String myUserID = mCredentials.getUserId();
|
||||
|
||||
Map<String, ReceiptData> receiptsByUserId = mReceiptsByRoomId.get(roomId);
|
||||
// copy the user id list to avoid having update while looping
|
||||
@ -1237,7 +1237,7 @@ public class MXMemoryStore implements IMXStore {
|
||||
}
|
||||
|
||||
// check if the read receipt is not for an already read message
|
||||
if (TextUtils.equals(receipt.userId, mCredentials.userId)) {
|
||||
if (TextUtils.equals(receipt.userId, mCredentials.getUserId())) {
|
||||
synchronized (mReceiptsByRoomIdLock) {
|
||||
LinkedHashMap<String, Event> eventsMap = mRoomEvents.get(roomId);
|
||||
|
||||
@ -1334,7 +1334,7 @@ public class MXMemoryStore implements IMXStore {
|
||||
for (int index = 0; index < events.size(); index++) {
|
||||
Event event = events.get(index);
|
||||
|
||||
if (TextUtils.equals(event.getSender(), mCredentials.userId) || TextUtils.equals(event.getType(), Event.EVENT_TYPE_STATE_ROOM_MEMBER)) {
|
||||
if (TextUtils.equals(event.getSender(), mCredentials.getUserId()) || TextUtils.equals(event.getType(), Event.EVENT_TYPE_STATE_ROOM_MEMBER)) {
|
||||
events.remove(index);
|
||||
index--;
|
||||
}
|
||||
@ -1402,10 +1402,10 @@ public class MXMemoryStore implements IMXStore {
|
||||
if (mReceiptsByRoomId.containsKey(roomId)) {
|
||||
Map<String, ReceiptData> receiptsByUserId = mReceiptsByRoomId.get(roomId);
|
||||
|
||||
if (receiptsByUserId.containsKey(mCredentials.userId)) {
|
||||
ReceiptData data = receiptsByUserId.get(mCredentials.userId);
|
||||
if (receiptsByUserId.containsKey(mCredentials.getUserId())) {
|
||||
ReceiptData data = receiptsByUserId.get(mCredentials.getUserId());
|
||||
|
||||
res = eventsAfter(roomId, data.eventId, mCredentials.userId, types);
|
||||
res = eventsAfter(roomId, data.eventId, mCredentials.getUserId(), types);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1479,7 +1479,7 @@ public class MXMemoryStore implements IMXStore {
|
||||
List<IMXStoreListener> listeners = getListeners();
|
||||
|
||||
for (IMXStoreListener listener : listeners) {
|
||||
listener.onStoreOOM(mCredentials.userId, e.getMessage());
|
||||
listener.onStoreOOM(mCredentials.getUserId(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ class TimelineEventSaver {
|
||||
|
||||
public void storeEvent(@NonNull final Event event) {
|
||||
final MXDataHandler dataHandler = mRoom.getDataHandler();
|
||||
final String myUserId = dataHandler.getCredentials().userId;
|
||||
final String myUserId = dataHandler.getCredentials().getUserId();
|
||||
|
||||
// create dummy read receipt for any incoming event
|
||||
// to avoid not synchronized read receipt and event
|
||||
|
@ -19,6 +19,11 @@ package im.vector.matrix.android.internal.legacy.data.timeline;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.MXDataHandler;
|
||||
import im.vector.matrix.android.internal.legacy.data.MyUser;
|
||||
import im.vector.matrix.android.internal.legacy.data.Room;
|
||||
@ -32,11 +37,6 @@ import im.vector.matrix.android.internal.legacy.util.EventDisplay;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* This class is responsible for handling live event
|
||||
*/
|
||||
@ -203,7 +203,7 @@ class TimelineLiveEventHandler {
|
||||
@NonNull Event event,
|
||||
final boolean checkRedactedStateEvent) {
|
||||
boolean shouldBeSaved = false;
|
||||
String myUserId = dataHandler.getCredentials().userId;
|
||||
String myUserId = dataHandler.getCredentials().getUserId();
|
||||
|
||||
if (Event.EVENT_TYPE_REDACTION.equals(event.getType())) {
|
||||
if (event.getRedactedEventId() != null) {
|
||||
|
@ -32,23 +32,6 @@ import android.widget.ImageView;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXEncryptedAttachments;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXMediaDownloadListener;
|
||||
import im.vector.matrix.android.internal.legacy.network.NetworkConnectivityReceiver;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.SimpleApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.client.MediaScanRestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.EncryptedMediaScanBody;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.EncryptedMediaScanEncryptedBody;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.crypto.EncryptedBodyFileInfo;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.crypto.EncryptedFileInfo;
|
||||
import im.vector.matrix.android.internal.legacy.ssl.CertUtil;
|
||||
import im.vector.matrix.android.internal.legacy.util.ImageUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import org.matrix.olm.OlmPkEncryption;
|
||||
import org.matrix.olm.OlmPkMessage;
|
||||
|
||||
@ -78,6 +61,24 @@ import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXEncryptedAttachments;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXMediaDownloadListener;
|
||||
import im.vector.matrix.android.internal.legacy.network.NetworkConnectivityReceiver;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.SimpleApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.client.MediaScanRestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.EncryptedMediaScanBody;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.EncryptedMediaScanEncryptedBody;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.crypto.EncryptedBodyFileInfo;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.crypto.EncryptedFileInfo;
|
||||
import im.vector.matrix.android.internal.legacy.util.ImageUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import im.vector.matrix.android.internal.network.ssl.CertUtil;
|
||||
|
||||
/**
|
||||
* This class manages the media downloading in background.
|
||||
* <p>
|
||||
@ -746,9 +747,9 @@ class MXMediaDownloadWorkerTask extends AsyncTask<Void, Void, JsonElement> {
|
||||
// Add SSL Socket factory.
|
||||
HttpsURLConnection sslConn = (HttpsURLConnection) connection;
|
||||
try {
|
||||
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.newPinnedSSLSocketFactory(mHsConfig);
|
||||
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.INSTANCE.newPinnedSSLSocketFactory(mHsConfig);
|
||||
sslConn.setSSLSocketFactory(pair.first);
|
||||
sslConn.setHostnameVerifier(CertUtil.newHostnameVerifier(mHsConfig));
|
||||
sslConn.setHostnameVerifier(CertUtil.INSTANCE.newHostnameVerifier(mHsConfig));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "doInBackground SSL exception " + e.getMessage(), e);
|
||||
}
|
||||
|
@ -22,15 +22,6 @@ import android.util.Pair;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXMediaUploadListener;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.ContentResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.ssl.CertUtil;
|
||||
import im.vector.matrix.android.internal.legacy.util.ContentManager;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
@ -51,6 +42,16 @@ import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXMediaUploadListener;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.ContentResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.util.ContentManager;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import im.vector.matrix.android.internal.network.ssl.CertUtil;
|
||||
|
||||
/**
|
||||
* Private AsyncTask used to upload files.
|
||||
*/
|
||||
@ -282,7 +283,7 @@ public class MXMediaUploadWorkerTask extends AsyncTask<Void, Void, String> {
|
||||
|
||||
String serverResponse = null;
|
||||
|
||||
String urlString = mContentManager.getHsConfig().getHomeserverUri().toString() + ContentManager.URI_PREFIX_CONTENT_API + "upload";
|
||||
String urlString = mContentManager.getHsConfig().getHomeServerUri().toString() + ContentManager.URI_PREFIX_CONTENT_API + "upload";
|
||||
|
||||
if (null != mFilename) {
|
||||
try {
|
||||
@ -300,7 +301,7 @@ public class MXMediaUploadWorkerTask extends AsyncTask<Void, Void, String> {
|
||||
if (RestClient.getUserAgent() != null) {
|
||||
conn.setRequestProperty("User-Agent", RestClient.getUserAgent());
|
||||
}
|
||||
conn.setRequestProperty("Authorization", "Bearer " + mContentManager.getHsConfig().getCredentials().accessToken);
|
||||
conn.setRequestProperty("Authorization", "Bearer " + mContentManager.getCredentials().getAccessToken());
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
conn.setUseCaches(false);
|
||||
@ -310,9 +311,9 @@ public class MXMediaUploadWorkerTask extends AsyncTask<Void, Void, String> {
|
||||
// Add SSL Socket factory.
|
||||
HttpsURLConnection sslConn = (HttpsURLConnection) conn;
|
||||
try {
|
||||
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.newPinnedSSLSocketFactory(mContentManager.getHsConfig());
|
||||
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.INSTANCE.newPinnedSSLSocketFactory(mContentManager.getHsConfig());
|
||||
sslConn.setSSLSocketFactory(pair.first);
|
||||
sslConn.setHostnameVerifier(CertUtil.newHostnameVerifier(mContentManager.getHsConfig()));
|
||||
sslConn.setHostnameVerifier(CertUtil.INSTANCE.newHostnameVerifier(mContentManager.getHsConfig()));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "sslConn " + e.getMessage(), e);
|
||||
}
|
||||
|
@ -31,7 +31,18 @@ import android.text.TextUtils;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.MXEncryptedAttachments;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXMediaDownloadListener;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXMediaUploadListener;
|
||||
@ -46,17 +57,6 @@ import im.vector.matrix.android.internal.legacy.util.ContentUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
import im.vector.matrix.android.internal.legacy.util.MXOsHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
public class MXMediasCache {
|
||||
|
||||
private static final String LOG_TAG = MXMediasCache.class.getSimpleName();
|
||||
|
@ -16,15 +16,15 @@
|
||||
*/
|
||||
package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.AccountDataApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AccountDataRestClient extends RestClient<AccountDataApi> {
|
||||
/**
|
||||
* Account data types
|
||||
@ -43,8 +43,8 @@ public class AccountDataRestClient extends RestClient<AccountDataApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public AccountDataRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, AccountDataApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
public AccountDataRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, AccountDataApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,11 +62,11 @@ public class AccountDataRestClient extends RestClient<AccountDataApi> {
|
||||
|
||||
mApi.setAccountData(userId, type, params)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
setAccountData(userId, type, params, callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
setAccountData(userId, type, params, callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,11 +82,11 @@ public class AccountDataRestClient extends RestClient<AccountDataApi> {
|
||||
|
||||
mApi.openIdToken(userId, new HashMap<>())
|
||||
.enqueue(new RestAdapterCallback<Map<Object, Object>>(description, mUnsentEventsManager, callback,
|
||||
new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
openIdToken(userId, callback);
|
||||
}
|
||||
}));
|
||||
new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
openIdToken(userId, callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.CallRulesApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
@ -28,8 +28,8 @@ public class CallRestClient extends RestClient<CallRulesApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CallRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, CallRulesApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
public CallRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, CallRulesApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
}
|
||||
|
||||
public void getTurnServer(final ApiCallback<JsonObject> callback) {
|
||||
|
@ -19,7 +19,12 @@ package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXKey;
|
||||
import im.vector.matrix.android.internal.legacy.crypto.data.MXUsersDevicesMap;
|
||||
@ -34,12 +39,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.pid.DeleteDeviceParam
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.sync.DevicesListResponse;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import retrofit2.Response;
|
||||
|
||||
public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
@ -49,8 +48,8 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CryptoRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, CryptoApi.class, URI_API_PREFIX_PATH_UNSTABLE, false, false);
|
||||
public CryptoRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, CryptoApi.class, URI_API_PREFIX_PATH_UNSTABLE, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,20 +81,20 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
mApi.uploadKeys(encodedDeviceId, params)
|
||||
.enqueue(new RestAdapterCallback<KeysUploadResponse>(description, null, callback,
|
||||
new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
uploadKeys(deviceKeys, oneTimeKeys, deviceId, callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
uploadKeys(deviceKeys, oneTimeKeys, deviceId, callback);
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
mApi.uploadKeys(params)
|
||||
.enqueue(new RestAdapterCallback<KeysUploadResponse>(description, null, callback,
|
||||
new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
uploadKeys(deviceKeys, oneTimeKeys, deviceId, callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
uploadKeys(deviceKeys, oneTimeKeys, deviceId, callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,11 +126,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
mApi.downloadKeysForUsers(parameters)
|
||||
.enqueue(new RestAdapterCallback<KeysQueryResponse>(description, mUnsentEventsManager, callback,
|
||||
new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
downloadKeysForUsers(userIds, token, callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
downloadKeysForUsers(userIds, token, callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,40 +150,40 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
mApi.claimOneTimeKeysForUsersDevices(params)
|
||||
.enqueue(new RestAdapterCallback<KeysClaimResponse>(description, mUnsentEventsManager, callback,
|
||||
new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
claimOneTimeKeysForUsersDevices(usersDevicesKeyTypesMap, callback);
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public void success(KeysClaimResponse keysClaimResponse, Response response) {
|
||||
onEventSent();
|
||||
@Override
|
||||
public void onRetry() {
|
||||
claimOneTimeKeysForUsersDevices(usersDevicesKeyTypesMap, callback);
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public void success(KeysClaimResponse keysClaimResponse, Response response) {
|
||||
onEventSent();
|
||||
|
||||
Map<String, Map<String, MXKey>> map = new HashMap<>();
|
||||
Map<String, Map<String, MXKey>> map = new HashMap<>();
|
||||
|
||||
if (null != keysClaimResponse.oneTimeKeys) {
|
||||
for (String userId : keysClaimResponse.oneTimeKeys.keySet()) {
|
||||
Map<String, Map<String, Map<String, Object>>> mapByUserId = keysClaimResponse.oneTimeKeys.get(userId);
|
||||
if (null != keysClaimResponse.oneTimeKeys) {
|
||||
for (String userId : keysClaimResponse.oneTimeKeys.keySet()) {
|
||||
Map<String, Map<String, Map<String, Object>>> mapByUserId = keysClaimResponse.oneTimeKeys.get(userId);
|
||||
|
||||
Map<String, MXKey> keysMap = new HashMap<>();
|
||||
Map<String, MXKey> keysMap = new HashMap<>();
|
||||
|
||||
for (String deviceId : mapByUserId.keySet()) {
|
||||
try {
|
||||
keysMap.put(deviceId, new MXKey(mapByUserId.get(deviceId)));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## claimOneTimeKeysForUsersDevices : fail to create a MXKey " + e.getMessage(), e);
|
||||
for (String deviceId : mapByUserId.keySet()) {
|
||||
try {
|
||||
keysMap.put(deviceId, new MXKey(mapByUserId.get(deviceId)));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## claimOneTimeKeysForUsersDevices : fail to create a MXKey " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (keysMap.size() != 0) {
|
||||
map.put(userId, keysMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keysMap.size() != 0) {
|
||||
map.put(userId, keysMap);
|
||||
}
|
||||
callback.onSuccess(new MXUsersDevicesMap<>(map));
|
||||
}
|
||||
}
|
||||
|
||||
callback.onSuccess(new MXUsersDevicesMap<>(map));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,11 +216,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
|
||||
mApi.sendToDevice(eventType, transactionId, content)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, null, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
sendToDevice(eventType, contentMap, callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
sendToDevice(eventType, contentMap, callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,11 +234,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
mApi.getDevices()
|
||||
.enqueue(new RestAdapterCallback<DevicesListResponse>(description, mUnsentEventsManager, callback,
|
||||
new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
getDevices(callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
getDevices(callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -255,11 +254,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
|
||||
mApi.deleteDevice(deviceId, params)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
deleteDevice(deviceId, params, callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
deleteDevice(deviceId, params, callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -278,11 +277,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
|
||||
mApi.updateDeviceInfo(deviceId, params)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
setDeviceName(deviceId, deviceName, callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
setDeviceName(deviceId, deviceName, callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -299,10 +298,10 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
|
||||
mApi.getKeyChanges(from, to)
|
||||
.enqueue(new RestAdapterCallback<KeyChangesResponse>(description, mUnsentEventsManager, callback,
|
||||
new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
getKeyChanges(from, to, callback);
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onRetry() {
|
||||
getKeyChanges(from, to, callback);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.EventsApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
@ -62,8 +62,8 @@ public class EventsRestClient extends RestClient<EventsApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EventsRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, EventsApi.class, "", false);
|
||||
public EventsRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, EventsApi.class, "", false);
|
||||
}
|
||||
|
||||
protected EventsRestClient(EventsApi api) {
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.FilterApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
@ -24,21 +24,21 @@ import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallbac
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterBody;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterResponse;
|
||||
|
||||
public class FilterRestClient extends RestClient<FilterApi>{
|
||||
public class FilterRestClient extends RestClient<FilterApi> {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public FilterRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, FilterApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
public FilterRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, FilterApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads a FilterBody to homeserver
|
||||
*
|
||||
* @param userId the user id
|
||||
* @param userId the user id
|
||||
* @param filterBody FilterBody which should be send to server
|
||||
* @param callback on success callback containing a String with populated filterId
|
||||
* @param callback on success callback containing a String with populated filterId
|
||||
*/
|
||||
public void uploadFilter(final String userId, final FilterBody filterBody, final ApiCallback<FilterResponse> callback) {
|
||||
final String description = "uploadFilter userId : " + userId + " filter : " + filterBody;
|
||||
|
@ -17,13 +17,18 @@
|
||||
*/
|
||||
package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.GroupsApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.SimpleApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.AcceptGroupInvitationParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.AddGroupParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.CreateGroupParams;
|
||||
@ -39,13 +44,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.group.GroupSummary;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.GroupUsers;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.LeaveGroupParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.group.UpdatePubliciseParams;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
@ -56,8 +54,8 @@ public class GroupsRestClient extends RestClient<GroupsApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public GroupsRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, GroupsApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
public GroupsRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, GroupsApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
}
|
||||
|
||||
protected GroupsRestClient(GroupsApi api) {
|
||||
|
@ -23,23 +23,22 @@ import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.LoginApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.Versions;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.LoginFlow;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.LoginFlowResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.LoginParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.PasswordLoginParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.RegistrationParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.TokenLoginParams;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
@ -59,10 +58,10 @@ public class LoginRestClient extends RestClient<LoginApi> {
|
||||
/**
|
||||
* Public constructor.
|
||||
*
|
||||
* @param hsConfig the home server connection config
|
||||
* @param sessionParams the session connection data
|
||||
*/
|
||||
public LoginRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, LoginApi.class, "", false);
|
||||
public LoginRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, LoginApi.class, "", false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,7 +18,11 @@ package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import org.matrix.olm.OlmException;
|
||||
import org.matrix.olm.OlmPkEncryption;
|
||||
import org.matrix.olm.OlmPkMessage;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.data.store.IMXStore;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.MediaScanApi;
|
||||
@ -32,10 +36,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.MediaScanPublicKeyRes
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MediaScanResult;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.crypto.EncryptedBodyFileInfo;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
import org.matrix.olm.OlmException;
|
||||
import org.matrix.olm.OlmPkEncryption;
|
||||
import org.matrix.olm.OlmPkMessage;
|
||||
|
||||
import retrofit2.Call;
|
||||
|
||||
/**
|
||||
@ -49,8 +49,8 @@ public class MediaScanRestClient extends RestClient<MediaScanApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public MediaScanRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, MediaScanApi.class, RestClient.URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE, false, EndPointServer.ANTIVIRUS_SERVER);
|
||||
public MediaScanRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, MediaScanApi.class, RestClient.URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE, false, EndPointServer.ANTIVIRUS_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.PresenceApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
@ -31,8 +31,8 @@ public class PresenceRestClient extends RestClient<PresenceApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public PresenceRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, PresenceApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
public PresenceRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, PresenceApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,7 +18,10 @@ package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.ProfileApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
@ -34,18 +37,11 @@ import im.vector.matrix.android.internal.legacy.rest.model.RequestPhoneNumberVal
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.RequestPhoneNumberValidationResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.ThreePidCreds;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.User;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.TokenRefreshParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.login.TokenRefreshResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.AccountThreePidsResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.AddThreePidsParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.DeleteThreePidParams;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThirdPartyIdentifier;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThreePid;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
@ -57,8 +53,8 @@ public class ProfileRestClient extends RestClient<ProfileApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ProfileRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, ProfileApi.class, "", false);
|
||||
public ProfileRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, ProfileApi.class, "", false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +98,7 @@ public class ProfileRestClient extends RestClient<ProfileApi> {
|
||||
|
||||
// don't retry if the network comes back
|
||||
// let the user chooses what he want to do
|
||||
mApi.displayname(mCredentials.userId, user)
|
||||
mApi.displayname(mCredentials.getUserId(), user)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
@ -150,7 +146,7 @@ public class ProfileRestClient extends RestClient<ProfileApi> {
|
||||
User user = new User();
|
||||
user.setAvatarUrl(newUrl);
|
||||
|
||||
mApi.avatarUrl(mCredentials.userId, user)
|
||||
mApi.avatarUrl(mCredentials.getUserId(), user)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
@ -288,31 +284,6 @@ public class ProfileRestClient extends RestClient<ProfileApi> {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh access/refresh tokens, using the current refresh token.
|
||||
*
|
||||
* @param callback the callback success and failure callback
|
||||
*/
|
||||
public void refreshTokens(final ApiCallback<Credentials> callback) {
|
||||
final String description = "refreshTokens";
|
||||
|
||||
TokenRefreshParams params = new TokenRefreshParams();
|
||||
params.refresh_token = mCredentials.refreshToken;
|
||||
|
||||
mApi.tokenrefresh(params)
|
||||
.enqueue(new RestAdapterCallback<TokenRefreshResponse>(description, mUnsentEventsManager, callback, null) {
|
||||
@Override
|
||||
public void success(TokenRefreshResponse tokenreponse, Response response) {
|
||||
onEventSent();
|
||||
mCredentials.refreshToken = tokenreponse.refresh_token;
|
||||
mCredentials.accessToken = tokenreponse.access_token;
|
||||
if (null != callback) {
|
||||
callback.onSuccess(mCredentials);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* List all 3PIDs linked to the Matrix user account.
|
||||
*
|
||||
@ -447,14 +418,14 @@ public class ProfileRestClient extends RestClient<ProfileApi> {
|
||||
|
||||
AddThreePidsParams params = new AddThreePidsParams();
|
||||
params.three_pid_creds = new ThreePidCreds();
|
||||
|
||||
String identityServerHost = mHsConfig.getIdentityServerUri().toString();
|
||||
if (identityServerHost.startsWith("http://")) {
|
||||
identityServerHost = identityServerHost.substring("http://".length());
|
||||
} else if (identityServerHost.startsWith("https://")) {
|
||||
identityServerHost = identityServerHost.substring("https://".length());
|
||||
if (identityServerHost != null) {
|
||||
if (identityServerHost.startsWith("http://")) {
|
||||
identityServerHost = identityServerHost.substring("http://".length());
|
||||
} else if (identityServerHost.startsWith("https://")) {
|
||||
identityServerHost = identityServerHost.substring("https://".length());
|
||||
}
|
||||
}
|
||||
|
||||
params.three_pid_creds.id_server = identityServerHost;
|
||||
params.three_pid_creds.sid = pid.sid;
|
||||
params.three_pid_creds.client_secret = pid.clientSecret;
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.PushRulesApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
@ -29,8 +29,8 @@ public class PushRulesRestClient extends RestClient<PushRulesApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public PushRulesRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, PushRulesApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
public PushRulesRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, PushRulesApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,9 @@
|
||||
|
||||
package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.util.HashMap;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.data.Pusher;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.PushersApi;
|
||||
@ -25,8 +27,6 @@ import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.PushersResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* REST client for the Pushers API.
|
||||
*/
|
||||
@ -36,8 +36,8 @@ public class PushersRestClient extends RestClient<PushersApi> {
|
||||
private static final String PUSHER_KIND_HTTP = "http";
|
||||
private static final String DATA_KEY_HTTP_URL = "url";
|
||||
|
||||
public PushersRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, PushersApi.class, RestClient.URI_API_PREFIX_PATH_R0, true);
|
||||
public PushersRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, PushersApi.class, RestClient.URI_API_PREFIX_PATH_R0, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,10 @@ import android.text.TextUtils;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomState;
|
||||
import im.vector.matrix.android.internal.legacy.data.timeline.EventTimeline;
|
||||
@ -52,14 +55,10 @@ import im.vector.matrix.android.internal.legacy.rest.model.filter.RoomEventFilte
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.message.Message;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.sync.RoomResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class used to make requests to the rooms API.
|
||||
*/
|
||||
public class RoomsRestClient extends RestClient<RoomsApi> {
|
||||
private static final String LOG_TAG = RoomsRestClient.class.getSimpleName();
|
||||
|
||||
public static final int DEFAULT_MESSAGES_PAGINATION_LIMIT = 30;
|
||||
|
||||
@ -70,8 +69,8 @@ public class RoomsRestClient extends RestClient<RoomsApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public RoomsRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, RoomsApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
public RoomsRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, RoomsApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -857,7 +856,7 @@ public class RoomsRestClient extends RestClient<RoomsApi> {
|
||||
Map<String, Object> hashMap = new HashMap<>();
|
||||
hashMap.put("order", order);
|
||||
|
||||
mApi.addTag(mCredentials.userId, roomId, tag, hashMap)
|
||||
mApi.addTag(mCredentials.getUserId(), roomId, tag, hashMap)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
@ -876,7 +875,7 @@ public class RoomsRestClient extends RestClient<RoomsApi> {
|
||||
public void removeTag(final String roomId, final String tag, final ApiCallback<Void> callback) {
|
||||
final String description = "removeTag : roomId " + roomId + " - tag " + tag;
|
||||
|
||||
mApi.removeTag(mCredentials.userId, roomId, tag)
|
||||
mApi.removeTag(mCredentials.getUserId(), roomId, tag)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
@ -898,7 +897,7 @@ public class RoomsRestClient extends RestClient<RoomsApi> {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(AccountDataRestClient.ACCOUNT_DATA_KEY_URL_PREVIEW_DISABLE, !status);
|
||||
|
||||
mApi.updateAccountData(mCredentials.userId, roomId, Event.EVENT_TYPE_URL_PREVIEW, params)
|
||||
mApi.updateAccountData(mCredentials.getUserId(), roomId, Event.EVENT_TYPE_URL_PREVIEW, params)
|
||||
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
|
||||
@Override
|
||||
public void onRetry() {
|
||||
|
@ -17,7 +17,14 @@
|
||||
*/
|
||||
package im.vector.matrix.android.internal.legacy.rest.client;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
import im.vector.matrix.android.internal.legacy.rest.api.ThirdPidApi;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
@ -27,14 +34,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.BulkLookupResponse;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.HttpError;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.HttpException;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.PidResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
@ -46,8 +45,8 @@ public class ThirdPidRestClient extends RestClient<ThirdPidApi> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ThirdPidRestClient(HomeServerConnectionConfig hsConfig) {
|
||||
super(hsConfig, ThirdPidApi.class, URI_API_PREFIX_IDENTITY, false, true);
|
||||
public ThirdPidRestClient(SessionParams sessionParams) {
|
||||
super(sessionParams, ThirdPidApi.class, URI_API_PREFIX_IDENTITY, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,19 +22,20 @@ import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.legacy.MXPatterns;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomState;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.Invite3Pid;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThreePid;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.MXPatterns;
|
||||
import im.vector.matrix.android.internal.legacy.data.RoomState;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.Invite3Pid;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThreePid;
|
||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||
|
||||
public class CreateRoomParams {
|
||||
|
||||
public static final String PRESET_PRIVATE_CHAT = "private_chat";
|
||||
@ -225,7 +226,7 @@ public class CreateRoomParams {
|
||||
*
|
||||
* @param ids the participant ids to add.
|
||||
*/
|
||||
public void addParticipantIds(HomeServerConnectionConfig hsConfig, List<String> ids) {
|
||||
public void addParticipantIds(HomeServerConnectionConfig homeServerConnectionConfig, Credentials credentials, List<String> ids) {
|
||||
for (String id : ids) {
|
||||
if (android.util.Patterns.EMAIL_ADDRESS.matcher(id).matches()) {
|
||||
if (null == invite3pids) {
|
||||
@ -233,14 +234,14 @@ public class CreateRoomParams {
|
||||
}
|
||||
|
||||
Invite3Pid pid = new Invite3Pid();
|
||||
pid.id_server = hsConfig.getIdentityServerUri().getHost();
|
||||
pid.id_server = homeServerConnectionConfig.getIdentityServerUri().getHost();
|
||||
pid.medium = ThreePid.MEDIUM_EMAIL;
|
||||
pid.address = id;
|
||||
|
||||
invite3pids.add(pid);
|
||||
} else if (MXPatterns.isUserId(id)) {
|
||||
// do not invite oneself
|
||||
if (!TextUtils.equals(hsConfig.getCredentials().userId, id)) {
|
||||
if (!TextUtils.equals(credentials.getUserId(), id)) {
|
||||
if (null == invitedUserIds) {
|
||||
invitedUserIds = new ArrayList<>();
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package im.vector.matrix.android.internal.legacy.rest.model;
|
||||
|
||||
/**
|
||||
* 3 pid credentials
|
||||
* 3 pid getCredentials
|
||||
*/
|
||||
public class ThreePidCreds {
|
||||
|
||||
|
@ -21,7 +21,7 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* The user's credentials.
|
||||
* The user's getCredentials.
|
||||
*/
|
||||
public class Credentials {
|
||||
public String userId;
|
||||
|
@ -23,7 +23,7 @@ import im.vector.matrix.android.internal.legacy.rest.model.ThreePidCreds;
|
||||
*/
|
||||
public class AddThreePidsParams {
|
||||
|
||||
// the 3rd party id credentials
|
||||
// the 3rd party id getCredentials
|
||||
public ThreePidCreds three_pid_creds;
|
||||
|
||||
// true when the email has been binded.
|
||||
|
@ -1,270 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.legacy.ssl;
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.CipherSuite;
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.TlsVersion;
|
||||
|
||||
/**
|
||||
* Various utility classes for dealing with X509Certificates
|
||||
*/
|
||||
public class CertUtil {
|
||||
private static final String LOG_TAG = CertUtil.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Generates the SHA-256 fingerprint of the given certificate
|
||||
*
|
||||
* @param cert the certificate.
|
||||
* @return the finger print
|
||||
* @throws CertificateException the certificate exception
|
||||
*/
|
||||
public static byte[] generateSha256Fingerprint(X509Certificate cert) throws CertificateException {
|
||||
return generateFingerprint(cert, "SHA-256");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the SHA-1 fingerprint of the given certificate
|
||||
*
|
||||
* @param cert the certificated
|
||||
* @return the SHA1 fingerprint
|
||||
* @throws CertificateException the certificate exception
|
||||
*/
|
||||
public static byte[] generateSha1Fingerprint(X509Certificate cert) throws CertificateException {
|
||||
return generateFingerprint(cert, "SHA-1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the fingerprint for a dedicated type.
|
||||
*
|
||||
* @param cert the certificate
|
||||
* @param type the type
|
||||
* @return the fingerprint
|
||||
* @throws CertificateException certificate exception
|
||||
*/
|
||||
private static byte[] generateFingerprint(X509Certificate cert, String type) throws CertificateException {
|
||||
final byte[] fingerprint;
|
||||
final MessageDigest md;
|
||||
try {
|
||||
md = MessageDigest.getInstance(type);
|
||||
} catch (Exception e) {
|
||||
// This really *really* shouldn't throw, as java should always have a SHA-256 and SHA-1 impl.
|
||||
throw new CertificateException(e);
|
||||
}
|
||||
|
||||
fingerprint = md.digest(cert.getEncoded());
|
||||
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
final private static char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||
|
||||
/**
|
||||
* Convert the fingerprint to an hexa string.
|
||||
*
|
||||
* @param fingerprint the fingerprint
|
||||
* @return the hexa string.
|
||||
*/
|
||||
public static String fingerprintToHexString(byte[] fingerprint) {
|
||||
return fingerprintToHexString(fingerprint, ' ');
|
||||
}
|
||||
|
||||
public static String fingerprintToHexString(byte[] fingerprint, char sep) {
|
||||
char[] hexChars = new char[fingerprint.length * 3];
|
||||
for (int j = 0; j < fingerprint.length; j++) {
|
||||
int v = fingerprint[j] & 0xFF;
|
||||
hexChars[j * 3] = hexArray[v >>> 4];
|
||||
hexChars[j * 3 + 1] = hexArray[v & 0x0F];
|
||||
hexChars[j * 3 + 2] = sep;
|
||||
}
|
||||
return new String(hexChars, 0, hexChars.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively checks the exception to see if it was caused by an
|
||||
* UnrecognizedCertificateException
|
||||
*
|
||||
* @param e the throwable.
|
||||
* @return The UnrecognizedCertificateException if exists, else null.
|
||||
*/
|
||||
public static UnrecognizedCertificateException getCertificateException(Throwable e) {
|
||||
int i = 0; // Just in case there is a getCause loop
|
||||
while (e != null && i < 10) {
|
||||
if (e instanceof UnrecognizedCertificateException) {
|
||||
return (UnrecognizedCertificateException) e;
|
||||
}
|
||||
e = e.getCause();
|
||||
i++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SSLSocket factory for a HS config.
|
||||
*
|
||||
* @param hsConfig the HS config.
|
||||
* @return SSLSocket factory
|
||||
*/
|
||||
public static Pair<SSLSocketFactory, X509TrustManager> newPinnedSSLSocketFactory(HomeServerConnectionConfig hsConfig) {
|
||||
try {
|
||||
X509TrustManager defaultTrustManager = null;
|
||||
|
||||
// If we haven't specified that we wanted to pin the certs, fallback to standard
|
||||
// X509 checks if fingerprints don't match.
|
||||
if (!hsConfig.shouldPin()) {
|
||||
TrustManagerFactory tf = null;
|
||||
|
||||
// get the PKIX instance
|
||||
try {
|
||||
tf = TrustManagerFactory.getInstance("PKIX");
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## newPinnedSSLSocketFactory() : TrustManagerFactory.getInstance failed " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
// it doesn't exist, use the default one.
|
||||
if (null == tf) {
|
||||
try {
|
||||
tf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## addRule : onBingRuleUpdateFailure failed " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
tf.init((KeyStore) null);
|
||||
TrustManager[] trustManagers = tf.getTrustManagers();
|
||||
|
||||
for (int i = 0; i < trustManagers.length; i++) {
|
||||
if (trustManagers[i] instanceof X509TrustManager) {
|
||||
defaultTrustManager = (X509TrustManager) trustManagers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TrustManager[] trustPinned = new TrustManager[]{
|
||||
new PinnedTrustManager(hsConfig.getAllowedFingerprints(), defaultTrustManager)
|
||||
};
|
||||
|
||||
SSLSocketFactory sslSocketFactory;
|
||||
|
||||
if (hsConfig.forceUsageOfTlsVersions() && hsConfig.getAcceptedTlsVersions() != null) {
|
||||
// Force usage of accepted Tls Versions for Android < 20
|
||||
sslSocketFactory = new TLSSocketFactory(trustPinned, hsConfig.getAcceptedTlsVersions());
|
||||
} else {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, trustPinned, new java.security.SecureRandom());
|
||||
sslSocketFactory = sslContext.getSocketFactory();
|
||||
}
|
||||
|
||||
return new Pair<>(sslSocketFactory, defaultTrustManager);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Host name verifier for a hs config.
|
||||
*
|
||||
* @param hsConfig the hs config.
|
||||
* @return a new HostnameVerifier.
|
||||
*/
|
||||
public static HostnameVerifier newHostnameVerifier(HomeServerConnectionConfig hsConfig) {
|
||||
final HostnameVerifier defaultVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
|
||||
final List<Fingerprint> trusted_fingerprints = hsConfig.getAllowedFingerprints();
|
||||
|
||||
return new HostnameVerifier() {
|
||||
@Override
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
if (defaultVerifier.verify(hostname, session)) return true;
|
||||
if (trusted_fingerprints == null || trusted_fingerprints.size() == 0) return false;
|
||||
|
||||
// If remote cert matches an allowed fingerprint, just accept it.
|
||||
try {
|
||||
for (Certificate cert : session.getPeerCertificates()) {
|
||||
for (Fingerprint allowedFingerprint : trusted_fingerprints) {
|
||||
if (allowedFingerprint != null && cert instanceof X509Certificate && allowedFingerprint.matchesCert((X509Certificate) cert)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SSLPeerUnverifiedException e) {
|
||||
return false;
|
||||
} catch (CertificateException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list of accepted TLS specifications for a hs config.
|
||||
*
|
||||
* @param hsConfig the hs config.
|
||||
* @return a list of accepted TLS specifications.
|
||||
*/
|
||||
public static List<ConnectionSpec> newConnectionSpecs(HomeServerConnectionConfig hsConfig) {
|
||||
final ConnectionSpec.Builder builder = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS);
|
||||
|
||||
final List<TlsVersion> tlsVersions = hsConfig.getAcceptedTlsVersions();
|
||||
if (null != tlsVersions) {
|
||||
builder.tlsVersions(tlsVersions.toArray(new TlsVersion[0]));
|
||||
}
|
||||
|
||||
final List<CipherSuite> tlsCipherSuites = hsConfig.getAcceptedTlsCipherSuites();
|
||||
if (null != tlsCipherSuites) {
|
||||
builder.cipherSuites(tlsCipherSuites.toArray(new CipherSuite[0]));
|
||||
}
|
||||
|
||||
builder.supportsTlsExtensions(hsConfig.shouldAcceptTlsExtensions());
|
||||
|
||||
List<ConnectionSpec> list = new ArrayList<>();
|
||||
|
||||
list.add(builder.build());
|
||||
|
||||
if (hsConfig.isHttpConnectionAllowed()) {
|
||||
list.add(ConnectionSpec.CLEARTEXT);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.legacy.ssl;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Represents a X509 Certificate fingerprint.
|
||||
*/
|
||||
public class Fingerprint {
|
||||
public enum HashType {SHA1, SHA256}
|
||||
|
||||
private final byte[] mBytes;
|
||||
private final HashType mHashType;
|
||||
private String mDisplayableHexRepr;
|
||||
|
||||
public Fingerprint(byte[] bytes, HashType hashType) {
|
||||
mBytes = bytes;
|
||||
mHashType = hashType;
|
||||
mDisplayableHexRepr = null;
|
||||
}
|
||||
|
||||
public static Fingerprint newSha256Fingerprint(X509Certificate cert) throws CertificateException {
|
||||
return new Fingerprint(
|
||||
CertUtil.generateSha256Fingerprint(cert),
|
||||
HashType.SHA256
|
||||
);
|
||||
}
|
||||
|
||||
public static Fingerprint newSha1Fingerprint(X509Certificate cert) throws CertificateException {
|
||||
return new Fingerprint(
|
||||
CertUtil.generateSha1Fingerprint(cert),
|
||||
HashType.SHA1
|
||||
);
|
||||
}
|
||||
|
||||
public HashType getType() {
|
||||
return mHashType;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return mBytes;
|
||||
}
|
||||
|
||||
public String getBytesAsHexString() {
|
||||
if (mDisplayableHexRepr == null) {
|
||||
mDisplayableHexRepr = CertUtil.fingerprintToHexString(mBytes);
|
||||
}
|
||||
|
||||
return mDisplayableHexRepr;
|
||||
}
|
||||
|
||||
public JSONObject toJson() throws JSONException {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("bytes", Base64.encodeToString(getBytes(), Base64.DEFAULT));
|
||||
obj.put("hash_type", mHashType.toString());
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static Fingerprint fromJson(JSONObject obj) throws JSONException {
|
||||
String hashTypeStr = obj.getString("hash_type");
|
||||
byte[] fingerprintBytes = Base64.decode(obj.getString("bytes"), Base64.DEFAULT);
|
||||
|
||||
final HashType hashType;
|
||||
if ("SHA256".equalsIgnoreCase(hashTypeStr)) {
|
||||
hashType = HashType.SHA256;
|
||||
} else if ("SHA1".equalsIgnoreCase(hashTypeStr)) {
|
||||
hashType = HashType.SHA1;
|
||||
} else {
|
||||
throw new JSONException("Unrecognized hash type: " + hashTypeStr);
|
||||
}
|
||||
|
||||
return new Fingerprint(fingerprintBytes, hashType);
|
||||
}
|
||||
|
||||
public boolean matchesCert(X509Certificate cert) throws CertificateException {
|
||||
Fingerprint o = null;
|
||||
switch (mHashType) {
|
||||
case SHA256:
|
||||
o = Fingerprint.newSha256Fingerprint(cert);
|
||||
break;
|
||||
case SHA1:
|
||||
o = Fingerprint.newSha1Fingerprint(cert);
|
||||
break;
|
||||
}
|
||||
|
||||
return equals(o);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("Fingerprint{type: '%s', fingeprint: '%s'}", mHashType.toString(), getBytesAsHexString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Fingerprint that = (Fingerprint) o;
|
||||
|
||||
if (!Arrays.equals(mBytes, that.mBytes)) return false;
|
||||
return mHashType == that.mHashType;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = mBytes != null ? Arrays.hashCode(mBytes) : 0;
|
||||
result = 31 * result + (mHashType != null ? mHashType.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.legacy.ssl;
|
||||
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
* Implements a TrustManager that checks Certificates against an explicit list of known
|
||||
* fingerprints.
|
||||
*/
|
||||
public class PinnedTrustManager implements X509TrustManager {
|
||||
private final List<Fingerprint> mFingerprints;
|
||||
private final X509TrustManager mDefaultTrustManager;
|
||||
|
||||
/**
|
||||
* @param fingerprints An array of SHA256 cert fingerprints
|
||||
* @param defaultTrustManager Optional trust manager to fall back on if cert does not match
|
||||
* any of the fingerprints. Can be null.
|
||||
*/
|
||||
public PinnedTrustManager(List<Fingerprint> fingerprints, X509TrustManager defaultTrustManager) {
|
||||
mFingerprints = fingerprints;
|
||||
mDefaultTrustManager = defaultTrustManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String s) throws CertificateException {
|
||||
try {
|
||||
if (mDefaultTrustManager != null) {
|
||||
mDefaultTrustManager.checkClientTrusted(
|
||||
chain, s
|
||||
);
|
||||
return;
|
||||
}
|
||||
} catch (CertificateException e) {
|
||||
// If there is an exception we fall back to checking fingerprints
|
||||
if (mFingerprints == null || mFingerprints.size() == 0) {
|
||||
throw new UnrecognizedCertificateException(chain[0], Fingerprint.newSha256Fingerprint(chain[0]), e.getCause());
|
||||
}
|
||||
}
|
||||
checkTrusted("client", chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String s) throws CertificateException {
|
||||
try {
|
||||
if (mDefaultTrustManager != null) {
|
||||
mDefaultTrustManager.checkServerTrusted(
|
||||
chain, s
|
||||
);
|
||||
return;
|
||||
}
|
||||
} catch (CertificateException e) {
|
||||
// If there is an exception we fall back to checking fingerprints
|
||||
if (mFingerprints == null || mFingerprints.size() == 0) {
|
||||
throw new UnrecognizedCertificateException(chain[0], Fingerprint.newSha256Fingerprint(chain[0]), e.getCause());
|
||||
}
|
||||
}
|
||||
checkTrusted("server", chain);
|
||||
}
|
||||
|
||||
private void checkTrusted(String type, X509Certificate[] chain) throws CertificateException {
|
||||
X509Certificate cert = chain[0];
|
||||
|
||||
boolean found = false;
|
||||
if (mFingerprints != null) {
|
||||
for (Fingerprint allowedFingerprint : mFingerprints) {
|
||||
if (allowedFingerprint != null && allowedFingerprint.matchesCert(cert)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new UnrecognizedCertificateException(cert, Fingerprint.newSha256Fingerprint(cert), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.legacy.ssl;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
import okhttp3.TlsVersion;
|
||||
|
||||
/**
|
||||
* Force the usage of Tls versions on every created socket
|
||||
* Inspired from https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/
|
||||
*/
|
||||
/*package*/ class TLSSocketFactory extends SSLSocketFactory {
|
||||
private static final String LOG_TAG = TLSSocketFactory.class.getSimpleName();
|
||||
|
||||
private SSLSocketFactory internalSSLSocketFactory;
|
||||
|
||||
private String[] enabledProtocols;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param trustPinned
|
||||
* @param acceptedTlsVersions
|
||||
* @throws KeyManagementException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
/*package*/ TLSSocketFactory(TrustManager[] trustPinned, List<TlsVersion> acceptedTlsVersions) throws KeyManagementException, NoSuchAlgorithmException {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, trustPinned, new SecureRandom());
|
||||
internalSSLSocketFactory = context.getSocketFactory();
|
||||
|
||||
enabledProtocols = new String[acceptedTlsVersions.size()];
|
||||
int i = 0;
|
||||
for (TlsVersion tlsVersion : acceptedTlsVersions) {
|
||||
enabledProtocols[i] = tlsVersion.javaName();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return internalSSLSocketFactory.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return internalSSLSocketFactory.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
|
||||
}
|
||||
|
||||
private Socket enableTLSOnSocket(Socket socket) {
|
||||
if (socket != null && (socket instanceof SSLSocket)) {
|
||||
SSLSocket sslSocket = (SSLSocket) socket;
|
||||
|
||||
List<String> supportedProtocols = Arrays.asList(sslSocket.getSupportedProtocols());
|
||||
List<String> filteredEnabledProtocols = new ArrayList<>();
|
||||
|
||||
for (String protocol : enabledProtocols) {
|
||||
if (supportedProtocols.contains(protocol)) {
|
||||
filteredEnabledProtocols.add(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
if (!filteredEnabledProtocols.isEmpty()) {
|
||||
try {
|
||||
sslSocket.setEnabledProtocols(filteredEnabledProtocols.toArray(new String[filteredEnabledProtocols.size()]));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Exception: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.legacy.ssl;
|
||||
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* Thrown when we are given a certificate that does match the certificate we were told to
|
||||
* expect.
|
||||
*/
|
||||
public class UnrecognizedCertificateException extends CertificateException {
|
||||
private final X509Certificate mCert;
|
||||
private final Fingerprint mFingerprint;
|
||||
|
||||
public UnrecognizedCertificateException(X509Certificate cert, Fingerprint fingerprint, Throwable cause) {
|
||||
super("Unrecognized certificate with unknown fingerprint: " + cert.getSubjectDN(), cause);
|
||||
mCert = cert;
|
||||
mFingerprint = fingerprint;
|
||||
}
|
||||
|
||||
public X509Certificate getCertificate() {
|
||||
return mCert;
|
||||
}
|
||||
|
||||
public Fingerprint getFingerprint() {
|
||||
return mFingerprint;
|
||||
}
|
||||
}
|
@ -146,7 +146,7 @@ public class BingRulesManager {
|
||||
public BingRulesManager(MXSession session, NetworkConnectivityReceiver networkConnectivityReceiver) {
|
||||
mSession = session;
|
||||
mApiClient = session.getBingRulesApiClient();
|
||||
mMyUserId = session.getCredentials().userId;
|
||||
mMyUserId = session.getCredentials().getUserId();
|
||||
mDataHandler = session.getDataHandler();
|
||||
|
||||
mNetworkListener = new IMXNetworkEventListener() {
|
||||
|
@ -19,7 +19,8 @@ package im.vector.matrix.android.internal.legacy.util;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig;
|
||||
import im.vector.matrix.android.internal.auth.data.Credentials;
|
||||
import im.vector.matrix.android.internal.legacy.RestClient;
|
||||
|
||||
/**
|
||||
@ -39,6 +40,7 @@ public class ContentManager {
|
||||
|
||||
// HS config
|
||||
private final HomeServerConnectionConfig mHsConfig;
|
||||
private final Credentials mCredentials;
|
||||
|
||||
// the unsent events Manager
|
||||
private final UnsentEventsManager mUnsentEventsManager;
|
||||
@ -53,8 +55,9 @@ public class ContentManager {
|
||||
* @param hsConfig the HomeserverConnectionConfig to use
|
||||
* @param unsentEventsManager the unsent events manager
|
||||
*/
|
||||
public ContentManager(HomeServerConnectionConfig hsConfig, UnsentEventsManager unsentEventsManager) {
|
||||
public ContentManager(HomeServerConnectionConfig hsConfig, Credentials credentials, UnsentEventsManager unsentEventsManager) {
|
||||
mHsConfig = hsConfig;
|
||||
mCredentials = credentials;
|
||||
mUnsentEventsManager = unsentEventsManager;
|
||||
// The AV scanner is disabled by default
|
||||
configureAntiVirusScanner(false);
|
||||
@ -73,7 +76,7 @@ public class ContentManager {
|
||||
if (isEnabled) {
|
||||
mDownloadUrlPrefix = mHsConfig.getAntiVirusServerUri().toString() + "/" + RestClient.URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE;
|
||||
} else {
|
||||
mDownloadUrlPrefix = mHsConfig.getHomeserverUri().toString() + URI_PREFIX_CONTENT_API;
|
||||
mDownloadUrlPrefix = mHsConfig.getHomeServerUri().toString() + URI_PREFIX_CONTENT_API;
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,6 +91,13 @@ public class ContentManager {
|
||||
return mHsConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the getCredentials.
|
||||
*/
|
||||
public Credentials getCredentials() {
|
||||
return mCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the unsent events manager
|
||||
*/
|
||||
@ -210,7 +220,7 @@ public class ContentManager {
|
||||
// Caution: identicon has no thumbnail path.
|
||||
if (mediaServerAndId.startsWith(MATRIX_CONTENT_IDENTICON_PREFIX)) {
|
||||
// identicon url still go to the media repo since they don’t need virus scanning
|
||||
url = mHsConfig.getHomeserverUri().toString() + URI_PREFIX_CONTENT_API;
|
||||
url = mHsConfig.getHomeServerUri().toString() + URI_PREFIX_CONTENT_API;
|
||||
} else {
|
||||
// Use the current download url prefix to take into account a potential antivirus scanner
|
||||
url = mDownloadUrlPrefix + "thumbnail/";
|
||||
|
@ -97,7 +97,7 @@ public class EventUtils {
|
||||
|
||||
Room room = session.getDataHandler().getRoom(event.roomId);
|
||||
return RoomDirectoryVisibility.DIRECTORY_VISIBILITY_PRIVATE.equals(room.getVisibility())
|
||||
&& !TextUtils.equals(event.getSender(), session.getCredentials().userId);
|
||||
&& !TextUtils.equals(event.getSender(), session.getCredentials().getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,6 +26,12 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.rest.json.BooleanDeserializer;
|
||||
import im.vector.matrix.android.internal.legacy.rest.json.ConditionDeserializer;
|
||||
import im.vector.matrix.android.internal.legacy.rest.json.MatrixFieldNamingStrategy;
|
||||
@ -59,11 +65,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.message.StickerMessag
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.message.VideoMessage;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.RoomThirdPartyInvite;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Static methods for converting json into objects.
|
||||
*/
|
||||
@ -527,6 +528,16 @@ public class JsonUtils {
|
||||
return new JsonObject();
|
||||
}
|
||||
|
||||
public static JsonObject toJson(Map<String, Object> data) {
|
||||
try {
|
||||
return (JsonObject) gson.toJsonTree(data);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## toJson failed " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return new JsonObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an Message instance into a Json object.
|
||||
*
|
||||
|
@ -20,15 +20,6 @@ package im.vector.matrix.android.internal.legacy.util;
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.MXDataHandler;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXNetworkEventListener;
|
||||
import im.vector.matrix.android.internal.legacy.network.NetworkConnectivityReceiver;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.legacy.ssl.CertUtil;
|
||||
import im.vector.matrix.android.internal.legacy.ssl.UnrecognizedCertificateException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -38,6 +29,14 @@ import java.util.Random;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.MXDataHandler;
|
||||
import im.vector.matrix.android.internal.legacy.listeners.IMXNetworkEventListener;
|
||||
import im.vector.matrix.android.internal.legacy.network.NetworkConnectivityReceiver;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback;
|
||||
import im.vector.matrix.android.internal.legacy.rest.model.MatrixError;
|
||||
import im.vector.matrix.android.internal.network.ssl.CertUtil;
|
||||
import im.vector.matrix.android.internal.network.ssl.UnrecognizedCertificateException;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
@ -405,8 +404,7 @@ public class UnsentEventsManager {
|
||||
}
|
||||
|
||||
if (null != exception) {
|
||||
UnrecognizedCertificateException unrecCertEx = CertUtil.getCertificateException(exception);
|
||||
|
||||
UnrecognizedCertificateException unrecCertEx = CertUtil.INSTANCE.getCertificateException(exception);
|
||||
if (null != unrecCertEx) {
|
||||
Log.e(LOG_TAG, "## onEventSendingFailed() : SSL issue detected");
|
||||
mDataHandler.onSSLCertificateError(unrecCertEx);
|
||||
|
@ -1,18 +1,18 @@
|
||||
package im.vector.matrix.android.internal.network
|
||||
|
||||
import im.vector.matrix.android.api.auth.CredentialsStore
|
||||
import im.vector.matrix.android.api.auth.SessionParamsStore
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
class AccessTokenInterceptor(private val credentialsStore: CredentialsStore) : Interceptor {
|
||||
class AccessTokenInterceptor(private val sessionParamsStore: SessionParamsStore) : Interceptor {
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
var request = chain.request()
|
||||
val newRequestBuilder = request.newBuilder()
|
||||
// Add the access token to all requests if it is set
|
||||
val credentials = credentialsStore.get()
|
||||
credentials?.let {
|
||||
newRequestBuilder.addHeader("Authorization", "Bearer " + it.accessToken)
|
||||
val sessionParams = sessionParamsStore.get()
|
||||
sessionParams?.let {
|
||||
newRequestBuilder.addHeader("Authorization", "Bearer " + it.credentials.accessToken)
|
||||
}
|
||||
request = newRequestBuilder.build()
|
||||
return chain.proceed(request)
|
||||
|
@ -1,9 +1,9 @@
|
||||
package im.vector.matrix.android.internal.network
|
||||
|
||||
import arrow.core.Either
|
||||
import com.squareup.moshi.Moshi
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.failure.MatrixError
|
||||
import im.vector.matrix.android.internal.util.Either
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.network.ssl
|
||||
|
||||
import android.util.Pair
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import okhttp3.ConnectionSpec
|
||||
import timber.log.Timber
|
||||
import java.security.KeyStore
|
||||
import java.security.MessageDigest
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.*
|
||||
import javax.net.ssl.*
|
||||
import kotlin.experimental.and
|
||||
|
||||
/**
|
||||
* Various utility classes for dealing with X509Certificates
|
||||
*/
|
||||
object CertUtil {
|
||||
|
||||
private val hexArray = "0123456789ABCDEF".toCharArray()
|
||||
|
||||
/**
|
||||
* Generates the SHA-256 fingerprint of the given certificate
|
||||
*
|
||||
* @param cert the certificate.
|
||||
* @return the finger print
|
||||
* @throws CertificateException the certificate exception
|
||||
*/
|
||||
@Throws(CertificateException::class)
|
||||
fun generateSha256Fingerprint(cert: X509Certificate): ByteArray {
|
||||
return generateFingerprint(cert, "SHA-256")
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the SHA-1 fingerprint of the given certificate
|
||||
*
|
||||
* @param cert the certificated
|
||||
* @return the SHA1 fingerprint
|
||||
* @throws CertificateException the certificate exception
|
||||
*/
|
||||
@Throws(CertificateException::class)
|
||||
fun generateSha1Fingerprint(cert: X509Certificate): ByteArray {
|
||||
return generateFingerprint(cert, "SHA-1")
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the fingerprint for a dedicated type.
|
||||
*
|
||||
* @param cert the certificate
|
||||
* @param type the type
|
||||
* @return the fingerprint
|
||||
* @throws CertificateException certificate exception
|
||||
*/
|
||||
@Throws(CertificateException::class)
|
||||
private fun generateFingerprint(cert: X509Certificate, type: String): ByteArray {
|
||||
val fingerprint: ByteArray
|
||||
val md: MessageDigest
|
||||
try {
|
||||
md = MessageDigest.getInstance(type)
|
||||
} catch (e: Exception) {
|
||||
// This really *really* shouldn't throw, as java should always have a SHA-256 and SHA-1 impl.
|
||||
throw CertificateException(e)
|
||||
}
|
||||
|
||||
fingerprint = md.digest(cert.encoded)
|
||||
|
||||
return fingerprint
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the fingerprint to an hexa string.
|
||||
*
|
||||
* @param fingerprint the fingerprint
|
||||
* @return the hexa string.
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun fingerprintToHexString(fingerprint: ByteArray, sep: Char = ' '): String {
|
||||
val hexChars = CharArray(fingerprint.size * 3)
|
||||
for (j in fingerprint.indices) {
|
||||
val v = (fingerprint[j] and 0xFF.toByte()).toInt()
|
||||
hexChars[j * 3] = hexArray[v.ushr(4)]
|
||||
hexChars[j * 3 + 1] = hexArray[v and 0x0F]
|
||||
hexChars[j * 3 + 2] = sep
|
||||
}
|
||||
return String(hexChars, 0, hexChars.size - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively checks the exception to see if it was caused by an
|
||||
* UnrecognizedCertificateException
|
||||
*
|
||||
* @param e the throwable.
|
||||
* @return The UnrecognizedCertificateException if exists, else null.
|
||||
*/
|
||||
fun getCertificateException(e: Throwable?): UnrecognizedCertificateException? {
|
||||
var e = e
|
||||
var i = 0 // Just in case there is a getCause loop
|
||||
while (e != null && i < 10) {
|
||||
if (e is UnrecognizedCertificateException) {
|
||||
return e
|
||||
}
|
||||
e = e.cause
|
||||
i++
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SSLSocket factory for a HS config.
|
||||
*
|
||||
* @param hsConfig the HS config.
|
||||
* @return SSLSocket factory
|
||||
*/
|
||||
fun newPinnedSSLSocketFactory(hsConfig: HomeServerConnectionConfig): Pair<SSLSocketFactory, X509TrustManager> {
|
||||
try {
|
||||
var defaultTrustManager: X509TrustManager? = null
|
||||
|
||||
// If we haven't specified that we wanted to shouldPin the certs, fallback to standard
|
||||
// X509 checks if fingerprints don't match.
|
||||
if (!hsConfig.shouldPin) {
|
||||
var tf: TrustManagerFactory? = null
|
||||
|
||||
// get the PKIX instance
|
||||
try {
|
||||
tf = TrustManagerFactory.getInstance("PKIX")
|
||||
} catch (e: Exception) {
|
||||
Timber.e("## newPinnedSSLSocketFactory() : TrustManagerFactory.getInstance failed " + e.message, e)
|
||||
}
|
||||
|
||||
// it doesn't exist, use the default one.
|
||||
if (null == tf) {
|
||||
try {
|
||||
tf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
|
||||
} catch (e: Exception) {
|
||||
Timber.e("## addRule : onBingRuleUpdateFailure failed " + e.message, e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tf!!.init(null as KeyStore?)
|
||||
val trustManagers = tf.trustManagers
|
||||
|
||||
for (i in trustManagers.indices) {
|
||||
if (trustManagers[i] is X509TrustManager) {
|
||||
defaultTrustManager = trustManagers[i] as X509TrustManager
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val trustPinned = arrayOf<TrustManager>(PinnedTrustManager(hsConfig.allowedFingerprints, defaultTrustManager))
|
||||
|
||||
val sslSocketFactory: SSLSocketFactory
|
||||
|
||||
if (hsConfig.forceUsageTlsVersions && hsConfig.tlsVersions != null) {
|
||||
// Force usage of accepted Tls Versions for Android < 20
|
||||
sslSocketFactory = TLSSocketFactory(trustPinned, hsConfig.tlsVersions)
|
||||
} else {
|
||||
val sslContext = SSLContext.getInstance("TLS")
|
||||
sslContext.init(null, trustPinned, java.security.SecureRandom())
|
||||
sslSocketFactory = sslContext.socketFactory
|
||||
}
|
||||
|
||||
return Pair<SSLSocketFactory, X509TrustManager>(sslSocketFactory, defaultTrustManager)
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Host name verifier for a hs config.
|
||||
*
|
||||
* @param hsConfig the hs config.
|
||||
* @return a new HostnameVerifier.
|
||||
*/
|
||||
fun newHostnameVerifier(hsConfig: HomeServerConnectionConfig): HostnameVerifier {
|
||||
val defaultVerifier = HttpsURLConnection.getDefaultHostnameVerifier()
|
||||
val trustedFingerprints = hsConfig.allowedFingerprints
|
||||
|
||||
return HostnameVerifier { hostname, session ->
|
||||
if (defaultVerifier.verify(hostname, session)) return@HostnameVerifier true
|
||||
if (trustedFingerprints == null || trustedFingerprints.size == 0) return@HostnameVerifier false
|
||||
|
||||
// If remote cert matches an allowed fingerprint, just accept it.
|
||||
try {
|
||||
for (cert in session.peerCertificates) {
|
||||
for (allowedFingerprint in trustedFingerprints) {
|
||||
if (allowedFingerprint != null && cert is X509Certificate && allowedFingerprint.matchesCert(cert)) {
|
||||
return@HostnameVerifier true
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: SSLPeerUnverifiedException) {
|
||||
return@HostnameVerifier false
|
||||
} catch (e: CertificateException) {
|
||||
return@HostnameVerifier false
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list of accepted TLS specifications for a hs config.
|
||||
*
|
||||
* @param hsConfig the hs config.
|
||||
* @return a list of accepted TLS specifications.
|
||||
*/
|
||||
fun newConnectionSpecs(hsConfig: HomeServerConnectionConfig): List<ConnectionSpec> {
|
||||
val builder = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||
val tlsVersions = hsConfig.tlsVersions
|
||||
if (null != tlsVersions) {
|
||||
builder.tlsVersions(*tlsVersions.toTypedArray())
|
||||
}
|
||||
|
||||
val tlsCipherSuites = hsConfig.tlsCipherSuites
|
||||
if (null != tlsCipherSuites) {
|
||||
builder.cipherSuites(*tlsCipherSuites.toTypedArray())
|
||||
}
|
||||
|
||||
builder.supportsTlsExtensions(hsConfig.shouldAcceptTlsExtensions)
|
||||
val list = ArrayList<ConnectionSpec>()
|
||||
list.add(builder.build())
|
||||
if (hsConfig.allowHttpExtension) {
|
||||
list.add(ConnectionSpec.CLEARTEXT)
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package im.vector.matrix.android.internal.network.ssl
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Fingerprint(
|
||||
val mBytes: ByteArray,
|
||||
val mHashType: HashType
|
||||
) {
|
||||
|
||||
val displayableHexRepr: String by lazy {
|
||||
CertUtil.fingerprintToHexString(mBytes)
|
||||
}
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
fun matchesCert(cert: X509Certificate): Boolean {
|
||||
var o: Fingerprint? = when (mHashType) {
|
||||
Fingerprint.HashType.SHA256 -> Fingerprint.newSha256Fingerprint(cert)
|
||||
Fingerprint.HashType.SHA1 -> Fingerprint.newSha1Fingerprint(cert)
|
||||
}
|
||||
return equals(o)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as Fingerprint
|
||||
if (!mBytes.contentEquals(other.mBytes)) return false
|
||||
if (mHashType != other.mHashType) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = mBytes.contentHashCode()
|
||||
result = 31 * result + mHashType.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
fun newSha256Fingerprint(cert: X509Certificate): Fingerprint {
|
||||
return Fingerprint(
|
||||
CertUtil.generateSha256Fingerprint(cert),
|
||||
HashType.SHA256
|
||||
)
|
||||
}
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
fun newSha1Fingerprint(cert: X509Certificate): Fingerprint {
|
||||
return Fingerprint(
|
||||
CertUtil.generateSha1Fingerprint(cert),
|
||||
HashType.SHA1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class HashType {
|
||||
@Json(name = "sha-1") SHA1,
|
||||
@Json(name = "sha-256")SHA256
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.network.ssl
|
||||
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
/**
|
||||
* Implements a TrustManager that checks Certificates against an explicit list of known
|
||||
* fingerprints.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param fingerprints An array of SHA256 cert fingerprints
|
||||
* @param defaultTrustManager Optional trust manager to fall back on if cert does not match
|
||||
* any of the fingerprints. Can be null.
|
||||
*/
|
||||
class PinnedTrustManager(private val mFingerprints: List<Fingerprint>?,
|
||||
private val mDefaultTrustManager: X509TrustManager?) : X509TrustManager {
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkClientTrusted(chain: Array<X509Certificate>, s: String) {
|
||||
try {
|
||||
if (mDefaultTrustManager != null) {
|
||||
mDefaultTrustManager.checkClientTrusted(
|
||||
chain, s
|
||||
)
|
||||
return
|
||||
}
|
||||
} catch (e: CertificateException) {
|
||||
// If there is an exception we fall back to checking fingerprints
|
||||
if (mFingerprints == null || mFingerprints.isEmpty()) {
|
||||
throw UnrecognizedCertificateException(chain[0], Fingerprint.newSha256Fingerprint(chain[0]), e.cause)
|
||||
}
|
||||
}
|
||||
|
||||
checkTrusted("client", chain)
|
||||
}
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkServerTrusted(chain: Array<X509Certificate>, s: String) {
|
||||
try {
|
||||
if (mDefaultTrustManager != null) {
|
||||
mDefaultTrustManager.checkServerTrusted(
|
||||
chain, s
|
||||
)
|
||||
return
|
||||
}
|
||||
} catch (e: CertificateException) {
|
||||
// If there is an exception we fall back to checking fingerprints
|
||||
if (mFingerprints == null || mFingerprints.isEmpty()) {
|
||||
throw UnrecognizedCertificateException(chain[0], Fingerprint.newSha256Fingerprint(chain[0]), e.cause)
|
||||
}
|
||||
}
|
||||
|
||||
checkTrusted("server", chain)
|
||||
}
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
private fun checkTrusted(type: String, chain: Array<X509Certificate>) {
|
||||
val cert = chain[0]
|
||||
|
||||
var found = false
|
||||
if (mFingerprints != null) {
|
||||
for (allowedFingerprint in mFingerprints) {
|
||||
if (allowedFingerprint.matchesCert(cert)) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw UnrecognizedCertificateException(cert, Fingerprint.newSha256Fingerprint(cert), null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate> {
|
||||
return emptyArray()
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2018 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.network.ssl
|
||||
|
||||
import im.vector.matrix.android.internal.legacy.util.Log
|
||||
import okhttp3.TlsVersion
|
||||
import java.io.IOException
|
||||
import java.net.InetAddress
|
||||
import java.net.Socket
|
||||
import java.net.UnknownHostException
|
||||
import java.security.KeyManagementException
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.SSLSocket
|
||||
import javax.net.ssl.SSLSocketFactory
|
||||
import javax.net.ssl.TrustManager
|
||||
|
||||
/**
|
||||
* Force the usage of Tls versions on every created socket
|
||||
* Inspired from https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/
|
||||
*/
|
||||
|
||||
internal class TLSSocketFactory
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param trustPinned
|
||||
* @param acceptedTlsVersions
|
||||
* @throws KeyManagementException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
@Throws(KeyManagementException::class, NoSuchAlgorithmException::class)
|
||||
constructor(trustPinned: Array<TrustManager>, acceptedTlsVersions: List<TlsVersion>) : SSLSocketFactory() {
|
||||
|
||||
private val internalSSLSocketFactory: SSLSocketFactory
|
||||
private val enabledProtocols: Array<String>
|
||||
|
||||
init {
|
||||
val context = SSLContext.getInstance("TLS")
|
||||
context.init(null, trustPinned, SecureRandom())
|
||||
internalSSLSocketFactory = context.socketFactory
|
||||
enabledProtocols = Array(acceptedTlsVersions.size) {
|
||||
acceptedTlsVersions[it].javaName()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDefaultCipherSuites(): Array<String> {
|
||||
return internalSSLSocketFactory.defaultCipherSuites
|
||||
}
|
||||
|
||||
override fun getSupportedCipherSuites(): Array<String> {
|
||||
return internalSSLSocketFactory.supportedCipherSuites
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun createSocket(): Socket? {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket())
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket? {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose))
|
||||
}
|
||||
|
||||
@Throws(IOException::class, UnknownHostException::class)
|
||||
override fun createSocket(host: String, port: Int): Socket? {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port))
|
||||
}
|
||||
|
||||
@Throws(IOException::class, UnknownHostException::class)
|
||||
override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket? {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort))
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun createSocket(host: InetAddress, port: Int): Socket? {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port))
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket? {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort))
|
||||
}
|
||||
|
||||
private fun enableTLSOnSocket(socket: Socket?): Socket? {
|
||||
if (socket != null && socket is SSLSocket) {
|
||||
val sslSocket = socket as SSLSocket?
|
||||
|
||||
val supportedProtocols = Arrays.asList(*sslSocket!!.supportedProtocols)
|
||||
val filteredEnabledProtocols = ArrayList<String>()
|
||||
|
||||
for (protocol in enabledProtocols) {
|
||||
if (supportedProtocols.contains(protocol)) {
|
||||
filteredEnabledProtocols.add(protocol)
|
||||
}
|
||||
}
|
||||
|
||||
if (!filteredEnabledProtocols.isEmpty()) {
|
||||
try {
|
||||
sslSocket.enabledProtocols = filteredEnabledProtocols.toTypedArray()
|
||||
} catch (e: Exception) {
|
||||
Log.e(LOG_TAG, "Exception: ", e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return socket
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG_TAG = TLSSocketFactory::class.java.simpleName
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.network.ssl
|
||||
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
/**
|
||||
* Thrown when we are given a certificate that does match the certificate we were told to
|
||||
* expect.
|
||||
*/
|
||||
data class UnrecognizedCertificateException(
|
||||
val certificate: X509Certificate,
|
||||
val fingerprint: Fingerprint,
|
||||
override val cause: Throwable?
|
||||
) : CertificateException("Unrecognized certificate with unknown fingerprint: " + certificate.subjectDN, cause)
|
@ -1,7 +1,7 @@
|
||||
package im.vector.matrix.android.internal.session
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||
import im.vector.matrix.android.internal.di.SessionModule
|
||||
import im.vector.matrix.android.internal.events.sync.SyncModule
|
||||
import im.vector.matrix.android.internal.events.sync.Synchronizer
|
||||
@ -11,13 +11,13 @@ import org.koin.standalone.StandAloneContext
|
||||
import org.koin.standalone.getKoin
|
||||
import org.koin.standalone.inject
|
||||
|
||||
class DefaultSession(homeServerConnectionConfig: HomeServerConnectionConfig) : Session, KoinComponent {
|
||||
class DefaultSession(sessionParams: SessionParams) : Session, KoinComponent {
|
||||
|
||||
private val synchronizer by inject<Synchronizer>()
|
||||
private val scope: Scope
|
||||
|
||||
init {
|
||||
val sessionModule = SessionModule(homeServerConnectionConfig)
|
||||
val sessionModule = SessionModule(sessionParams)
|
||||
val syncModule = SyncModule()
|
||||
StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule))
|
||||
scope = getKoin().createScope(SCOPE)
|
||||
|
@ -1,35 +0,0 @@
|
||||
package im.vector.matrix.android.internal.util
|
||||
|
||||
sealed class Either<out L, out R> {
|
||||
/** * Represents the left side of [Either] class which by convention is a "Failure". */
|
||||
data class Left<out L>(val a: L) : Either<L, Nothing>()
|
||||
|
||||
/** * Represents the right side of [Either] class which by convention is a "Success". */
|
||||
data class Right<out R>(val b: R) : Either<Nothing, R>()
|
||||
|
||||
val isRight get() = this is Right<R>
|
||||
val isLeft get() = this is Left<L>
|
||||
|
||||
fun <L> left(a: L) = Left(a)
|
||||
fun <R> right(b: R) = Right(b)
|
||||
|
||||
fun either(fnL: (L) -> Any, fnR: (R) -> Any): Any =
|
||||
when (this) {
|
||||
is Left -> fnL(a)
|
||||
is Right -> fnR(b)
|
||||
}
|
||||
}
|
||||
|
||||
// Credits to Alex Hart -> https://proandroiddev.com/kotlins-nothing-type-946de7d464fb
|
||||
// Composes 2 functions
|
||||
fun <A, B, C> ((A) -> B).c(f: (B) -> C): (A) -> C = {
|
||||
f(this(it))
|
||||
}
|
||||
|
||||
fun <T, L, R> Either<L, R>.flatMap(fn: (R) -> Either<L, T>): Either<L, T> =
|
||||
when (this) {
|
||||
is Either.Left -> Either.Left(a)
|
||||
is Either.Right -> fn(b)
|
||||
}
|
||||
|
||||
fun <T, L, R> Either<L, R>.map(fn: (R) -> (T)): Either<L, T> = this.flatMap(fn.c(::right))
|
Loading…
Reference in New Issue
Block a user