WIP integration with old SDK (not working)

This commit is contained in:
ganfra 2018-10-10 19:46:43 +02:00
parent 3215fa47d5
commit 108fae2f28
87 changed files with 2233 additions and 1937 deletions

View File

@ -5,9 +5,9 @@ import android.view.View
import android.widget.Toast import android.widget.Toast
import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.Matrix
import im.vector.matrix.android.api.MatrixCallback 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.auth.data.HomeServerConnectionConfig
import im.vector.matrix.android.api.failure.Failure 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.R
import im.vector.riotredesign.core.platform.RiotActivity import im.vector.riotredesign.core.platform.RiotActivity
import im.vector.riotredesign.features.home.HomeActivity import im.vector.riotredesign.features.home.HomeActivity
@ -17,7 +17,6 @@ import org.koin.android.ext.android.inject
class LoginActivity : RiotActivity() { class LoginActivity : RiotActivity() {


private val matrix by inject<Matrix>() private val matrix by inject<Matrix>()
private val homeServerConnectionConfig = HomeServerConnectionConfig("https://matrix.org/")
private val authenticator = matrix.authenticator() private val authenticator = matrix.authenticator()


override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -30,6 +29,11 @@ class LoginActivity : RiotActivity() {
val login = loginField.text.trim().toString() val login = loginField.text.trim().toString()
val password = passwordField.text.trim().toString() val password = passwordField.text.trim().toString()
progressBar.visibility = View.VISIBLE 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> { authenticator.authenticate(homeServerConnectionConfig, login, password, object : MatrixCallback<Session> {
override fun onSuccess(data: Session?) { override fun onSuccess(data: Session?) {
matrix.currentSession = data matrix.currentSession = data

View File

@ -3,9 +3,6 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'io.objectbox' apply plugin: 'io.objectbox'


ext.support_version = '28.0.0'
ext.moshi_version = '1.7.0'

buildscript { buildscript {


repositories { repositories {
@ -43,6 +40,11 @@ android {
} }


dependencies { 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 fileTree(dir: 'libs', include: ['*.aar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"


@ -65,6 +67,8 @@ dependencies {
// Paging // Paging
implementation "android.arch.paging:runtime:1.0.1" implementation "android.arch.paging:runtime:1.0.1"


implementation "io.arrow-kt:arrow-core:$arrow_version"

// DI // DI
implementation "org.koin:koin-core:$koin_version" implementation "org.koin:koin-core:$koin_version"
implementation "org.koin:koin-core-ext:$koin_version" implementation "org.koin:koin-core-ext:$koin_version"

View File

@ -4,50 +4,77 @@
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
"entities": [ "entities": [
{ {
"id": "3:213989653016909134", "id": "6:5991986256653472999",
"lastPropertyId": "6:8192129106205548340", "lastPropertyId": "6:5675340775405504775",
"name": "Credentials", "name": "Credentials",
"properties": [ "properties": [
{ {
"id": "1:3516672544602138732", "id": "1:904844404428661340",
"name": "id" "name": "id"
}, },
{ {
"id": "2:8457998089049891725", "id": "2:4962733318674873893",
"indexId": "1:7573100044105293219",
"name": "userId" "name": "userId"
}, },
{ {
"id": "3:878535388660167894", "id": "3:6496111157191804406",
"name": "homeServer" "name": "homeServer"
}, },
{ {
"id": "4:7030303501035684102", "id": "4:6583709765305423919",
"name": "accessToken" "name": "accessToken"
}, },
{ {
"id": "5:7193051897929077560", "id": "5:865976960498370870",
"name": "refreshToken" "name": "refreshToken"
}, },
{ {
"id": "6:8192129106205548340", "id": "6:5675340775405504775",
"name": "deviceId" "name": "deviceId"
} }
], ],
"relations": [] "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", "lastEntityId": "7:6920598293865885979",
"lastIndexId": "1:7573100044105293219", "lastIndexId": "4:1616715309690181473",
"lastRelationId": "0:0", "lastRelationId": "0:0",
"lastSequenceId": "0:0", "lastSequenceId": "0:0",
"modelVersion": 4, "modelVersion": 4,
"modelVersionParserMinimum": 4, "modelVersionParserMinimum": 4,
"retiredEntityUids": [ "retiredEntityUids": [
637433444018824383, 637433444018824383,
5577202525246066978 5577202525246066978,
213989653016909134,
826321009570992494,
1775102368193732759
],
"retiredIndexUids": [
7573100044105293219,
7664899561635023422,
762622607983996029,
1616715309690181473
], ],
"retiredIndexUids": [],
"retiredPropertyUids": [ "retiredPropertyUids": [
6211403495341530846, 6211403495341530846,
1774175862476960436, 1774175862476960436,
@ -60,7 +87,25 @@
8258973118557394726, 8258973118557394726,
4167129800901721265, 4167129800901721265,
4654729568692986907, 4654729568692986907,
958528673818813300 958528673818813300,
3516672544602138732,
8457998089049891725,
878535388660167894,
7030303501035684102,
7193051897929077560,
8192129106205548340,
7632656533038841948,
1390065349267803135,
6024884732066241356,
3502558420506448922,
3999645739247298623,
8488502568193639300,
594512591943458255,
5113574037182501000,
4929796643260285955,
5690571528511905880,
1811444397594387116,
8817556524159529201
], ],
"retiredRelationUids": [], "retiredRelationUids": [],
"version": 1 "version": 1

View File

@ -4,49 +4,76 @@
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
"entities": [ "entities": [
{ {
"id": "3:213989653016909134", "id": "4:1775102368193732759",
"lastPropertyId": "6:8192129106205548340", "lastPropertyId": "6:8817556524159529201",
"name": "Credentials", "name": "SessionParams",
"properties": [ "properties": [
{ {
"id": "1:3516672544602138732", "id": "2:5690571528511905880",
"name": "homeServerConnectionConfig"
},
{
"id": "3:1811444397594387116",
"name": "id" "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" "name": "userId"
}, },
{ {
"id": "3:878535388660167894", "id": "3:6496111157191804406",
"name": "homeServer" "name": "homeServer"
}, },
{ {
"id": "4:7030303501035684102", "id": "4:6583709765305423919",
"name": "accessToken" "name": "accessToken"
}, },
{ {
"id": "5:7193051897929077560", "id": "5:865976960498370870",
"name": "refreshToken" "name": "refreshToken"
}, },
{ {
"id": "6:8192129106205548340", "id": "6:5675340775405504775",
"name": "deviceId" "name": "deviceId"
} }
], ],
"relations": [] "relations": []
} }
], ],
"lastEntityId": "3:213989653016909134", "lastEntityId": "6:5991986256653472999",
"lastIndexId": "0:0", "lastIndexId": "4:1616715309690181473",
"lastRelationId": "0:0", "lastRelationId": "0:0",
"lastSequenceId": "0:0", "lastSequenceId": "0:0",
"modelVersion": 4, "modelVersion": 4,
"modelVersionParserMinimum": 4, "modelVersionParserMinimum": 4,
"retiredEntityUids": [ "retiredEntityUids": [
637433444018824383, 637433444018824383,
5577202525246066978 5577202525246066978,
213989653016909134,
826321009570992494
],
"retiredIndexUids": [
7573100044105293219,
7664899561635023422,
762622607983996029
], ],
"retiredIndexUids": [],
"retiredPropertyUids": [ "retiredPropertyUids": [
6211403495341530846, 6211403495341530846,
1774175862476960436, 1774175862476960436,
@ -59,7 +86,22 @@
8258973118557394726, 8258973118557394726,
4167129800901721265, 4167129800901721265,
4654729568692986907, 4654729568692986907,
958528673818813300 958528673818813300,
3516672544602138732,
8457998089049891725,
878535388660167894,
7030303501035684102,
7193051897929077560,
8192129106205548340,
7632656533038841948,
1390065349267803135,
6024884732066241356,
3502558420506448922,
3999645739247298623,
8488502568193639300,
594512591943458255,
5113574037182501000,
4929796643260285955
], ],
"retiredRelationUids": [], "retiredRelationUids": [],
"version": 1 "version": 1

View File

@ -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)

}

View File

@ -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)

}

View File

@ -1,9 +1,225 @@
package im.vector.matrix.android.api.auth.data package im.vector.matrix.android.api.auth.data


import android.net.Uri
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import im.vector.matrix.android.internal.network.ssl.Fingerprint
import okhttp3.CipherSuite
import okhttp3.TlsVersion


@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class HomeServerConnectionConfig( data class HomeServerConnectionConfig(
// the home server URI val homeServerUri: Uri,
val hsUri: String 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)
}

}


}






View File

@ -1,7 +1,9 @@
package im.vector.matrix.android.api.events package im.vector.matrix.android.api.events


import com.google.gson.JsonObject
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import im.vector.matrix.android.internal.legacy.util.JsonUtils


@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class Event( data class Event(
@ -14,4 +16,14 @@ data class Event(
@Json(name = "state_key") val stateKey: String? = null, @Json(name = "state_key") val stateKey: String? = null,
@Json(name = "room_id") val roomId: String? = null, @Json(name = "room_id") val roomId: String? = null,
@Json(name = "unsigned_data") val unsignedData: UnsignedData? = null @Json(name = "unsigned_data") val unsignedData: UnsignedData? = null
) ){

fun contentAsJsonObject(): JsonObject? {
return JsonUtils.toJson(content)
}



}



View File

@ -1,43 +1,42 @@
package im.vector.matrix.android.api.events package im.vector.matrix.android.api.events


import com.squareup.moshi.Json


object EventType {


enum class EventType { const val PRESENCE = "m.presence"

const val MESSAGE = "m.room.message"
@Json(name ="m.presence") PRESENCE, const val STICKER = "m.sticker"
@Json(name ="m.room.message") MESSAGE, const val ENCRYPTED = "m.room.encrypted"
@Json(name ="m.sticker") STICKER, const val ENCRYPTION = "m.room.encryption"
@Json(name ="m.room.encrypted") ENCRYPTED, const val FEEDBACK = "m.room.message.feedback"
@Json(name ="m.room.encryption") ENCRYPTION, const val TYPING = "m.typing"
@Json(name ="m.room.message.feedback") FEEDBACK, const val REDACTION = "m.room.redaction"
@Json(name ="m.typing") TYPING, const val RECEIPT = "m.receipt"
@Json(name ="m.room.redaction") REDACTION, const val TAG = "m.tag"
@Json(name ="m.receipt") RECEIPT, const val ROOM_KEY = "m.room_key"
@Json(name ="m.tag") TAG, const val FULLY_READ = "m.fully_read"
@Json(name ="m.room_key") ROOM_KEY, const val PLUMBING = "m.room.plumbing"
@Json(name ="m.fully_read") FULLY_READ, const val BOT_OPTIONS = "m.room.bot.options"
@Json(name ="m.room.plumbing") PLUMBING, const val KEY_REQUEST = "m.room_key_request"
@Json(name ="m.room.bot.options") BOT_OPTIONS, const val FORWARDED_ROOM_KEY = "m.forwarded_room_key"
@Json(name ="m.room_key_request") KEY_REQUEST, const val PREVIEW_URLS = "org.matrix.room.preview_urls"
@Json(name ="m.forwarded_room_key") FORWARDED_ROOM_KEY,
@Json(name ="org.matrix.room.preview_urls") PREVIEW_URLS,


// State Events // State Events
@Json(name ="m.room.name") STATE_ROOM_NAME,
@Json(name ="m.room.topic") STATE_ROOM_TOPIC, const val STATE_ROOM_NAME = "m.room.name"
@Json(name ="m.room.avatar") STATE_ROOM_AVATAR, const val STATE_ROOM_TOPIC = "m.room.topic"
@Json(name ="m.room.member") STATE_ROOM_MEMBER, const val STATE_ROOM_AVATAR = "m.room.avatar"
@Json(name ="m.room.third_party_invite") STATE_ROOM_THIRD_PARTY_INVITE, const val STATE_ROOM_MEMBER = "m.room.member"
@Json(name ="m.room.create") STATE_ROOM_CREATE, const val STATE_ROOM_THIRD_PARTY_INVITE = "m.room.third_party_invite"
@Json(name ="m.room.join_rules") STATE_ROOM_JOIN_RULES, const val STATE_ROOM_CREATE = "m.room.create"
@Json(name ="m.room.guest_access") STATE_ROOM_GUEST_ACCESS, const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
@Json(name ="m.room.power_levels") STATE_ROOM_POWER_LEVELS, const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
@Json(name ="m.room.aliases") STATE_ROOM_ALIASES, const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
@Json(name ="m.room.tombstone") STATE_ROOM_TOMBSTONE, const val STATE_ROOM_ALIASES = "m.room.aliases"
@Json(name ="m.room.canonical_alias") STATE_CANONICAL_ALIAS, const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
@Json(name ="m.room.history_visibility") STATE_HISTORY_VISIBILITY, const val STATE_CANONICAL_ALIAS = "m.room.canonical_alias"
@Json(name ="m.room.related_groups") STATE_RELATED_GROUPS, const val STATE_HISTORY_VISIBILITY = "m.room.history_visibility"
@Json(name ="m.room.pinned_events") STATE_PINNED_EVENT const val STATE_RELATED_GROUPS = "m.room.related_groups"
const val STATE_PINNED_EVENT = "m.room.pinned_events"


} }

View File

@ -1,7 +1,9 @@
package im.vector.matrix.android.api.rooms package im.vector.matrix.android.api.rooms


import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass


@JsonClass(generateAdapter = true)
data class Invite( data class Invite(
@Json(name = "display_name") val displayName: String, @Json(name = "display_name") val displayName: String,
@Json(name = "signed") val signed: Signed @Json(name = "signed") val signed: Signed

View File

@ -1,12 +1,15 @@
package im.vector.matrix.android.api.rooms 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 import im.vector.matrix.android.api.events.UnsignedData


@JsonClass(generateAdapter = true)
data class RoomMember( data class RoomMember(
val membership: Membership, @Json(name = "membership") val membership: Membership,
val displayDame: String? = null, @Json(name = "display_name") val displayDame: String? = null,
val avatarUrl: String? = null, @Json(name = "avatar_url") val avatarUrl: String? = null,
val isDirect: Boolean = false, @Json(name = "is_direct") val isDirect: Boolean = false,
val thirdPartyInvite: Invite? = null, @Json(name = "third_party_invite") val thirdPartyInvite: Invite? = null,
val unsignedData: UnsignedData? = null @Json(name = "unsigned_data") val unsignedData: UnsignedData? = null
) )

View File

@ -2,10 +2,10 @@ package im.vector.matrix.android.internal.auth


import android.content.Context import android.content.Context
import im.vector.matrix.android.api.auth.Authenticator 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.internal.auth.data.Credentials import im.vector.matrix.android.internal.auth.db.ObjectBoxSessionParams
import im.vector.matrix.android.internal.auth.data.MyObjectBox import im.vector.matrix.android.internal.auth.db.ObjectBoxSessionParamsMapper
import im.vector.matrix.android.internal.auth.db.ObjectBoxCredentialsStore import im.vector.matrix.android.internal.auth.db.ObjectBoxSessionParamsStore
import io.objectbox.Box import io.objectbox.Box
import io.objectbox.BoxStore import io.objectbox.BoxStore
import org.koin.dsl.context.ModuleDefinition import org.koin.dsl.context.ModuleDefinition
@ -26,13 +26,14 @@ class AuthModule(private val context: Context) : Module {
MyObjectBox.builder().androidContext(context).build() MyObjectBox.builder().androidContext(context).build()
} }



single { single {
val boxStore = get(name = AUTH_BOX_STORE) as BoxStore 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 { single {
ObjectBoxCredentialsStore(get()) as CredentialsStore ObjectBoxSessionParamsStore(ObjectBoxSessionParamsMapper((get())), get()) as SessionParamsStore
} }


}.invoke() }.invoke()

View File

@ -1,19 +1,21 @@
package im.vector.matrix.android.internal.auth package im.vector.matrix.android.internal.auth


import arrow.core.leftIfNull
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import im.vector.matrix.android.api.MatrixCallback 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.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.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.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.Credentials
import im.vector.matrix.android.internal.auth.data.PasswordLoginParams 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.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.CancelableCoroutine
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import im.vector.matrix.android.internal.util.map
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.Retrofit import retrofit2.Retrofit
@ -21,28 +23,34 @@ import retrofit2.Retrofit
class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder, class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder,
private val jsonMapper: Moshi, private val jsonMapper: Moshi,
private val coroutineDispatchers: MatrixCoroutineDispatchers, 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 { override fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig, login: String, password: String, callback: MatrixCallback<Session>): Cancelable {
val authAPI = buildAuthAPI(homeServerConnectionConfig) val authAPI = buildAuthAPI(homeServerConnectionConfig)

val job = GlobalScope.launch(coroutineDispatchers.main) { val job = GlobalScope.launch(coroutineDispatchers.main) {
val loginParams = PasswordLoginParams.userIdentifier(login, password, "Mobile") val loginParams = PasswordLoginParams.userIdentifier(login, password, "Mobile")
val loginResult = executeRequest<Credentials> { executeRequest<Credentials> {
apiCall = authAPI.login(loginParams) apiCall = authAPI.login(loginParams)
moshi = jsonMapper moshi = jsonMapper
dispatcher = coroutineDispatchers.io dispatcher = coroutineDispatchers.io
}.leftIfNull {
Failure.Unknown(IllegalArgumentException("Credentials shouldn't not be null"))
}.map { }.map {
it?.apply { credentialsStore.save(it) } val sessionParams = SessionParams(it, homeServerConnectionConfig)
sessionParamsStore.save(sessionParams)
sessionParams
}.map { }.map {
DefaultSession(homeServerConnectionConfig) DefaultSession(it)
} }.bimap(
loginResult.either({ callback.onFailure(it) }, { callback.onSuccess(it) }) { callback.onFailure(it) }, { callback.onSuccess(it) }
)
} }
return CancelableCoroutine(job) return CancelableCoroutine(job)
} }


private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI { 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) return retrofit.create(AuthAPI::class.java)
} }



View File

@ -4,13 +4,12 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import io.objectbox.annotation.Entity import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id import io.objectbox.annotation.Id
import io.objectbox.annotation.Index


@Entity
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
@Entity
data class Credentials( data class Credentials(
@Id var id: Long = 0, @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 = "home_server") val homeServer: String,
@Json(name = "access_token") val accessToken: String, @Json(name = "access_token") val accessToken: String,
@Json(name = "refresh_token") val refreshToken: String?, @Json(name = "refresh_token") val refreshToken: String?,

View File

@ -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
)

View File

@ -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()
}

}

View File

@ -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
)

View File

@ -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)
}


}

View File

@ -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()
}

}

View File

@ -14,6 +14,10 @@ class MatrixModule(private val options: MatrixOptions) : Module {


override fun invoke(): ModuleDefinition = module { override fun invoke(): ModuleDefinition = module {


single {
options.context
}

single { single {
MatrixCoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.IO, main = options.mainExecutor.asCoroutineDispatcher()) MatrixCoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.IO, main = options.mainExecutor.asCoroutineDispatcher())
} }

View File

@ -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
}

}

View File

@ -1,7 +1,6 @@
package im.vector.matrix.android.internal.di package im.vector.matrix.android.internal.di


import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
import com.squareup.moshi.Moshi
import im.vector.matrix.android.internal.network.AccessTokenInterceptor import im.vector.matrix.android.internal.network.AccessTokenInterceptor
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
@ -25,7 +24,7 @@ class NetworkModule : Module {


single { single {
val logger = HttpLoggingInterceptor.Logger { message -> Timber.v(message) } val logger = HttpLoggingInterceptor.Logger { message -> Timber.v(message) }
HttpLoggingInterceptor(logger).apply { level = HttpLoggingInterceptor.Level.BODY } HttpLoggingInterceptor(logger).apply { level = HttpLoggingInterceptor.Level.BASIC }
} }


single { single {
@ -39,7 +38,7 @@ class NetworkModule : Module {
} }


single { single {
Moshi.Builder().build() MoshiProvider.providesMoshi()
} }


single { single {

View File

@ -1,20 +1,32 @@
package im.vector.matrix.android.internal.di 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 im.vector.matrix.android.internal.session.DefaultSession
import org.koin.dsl.context.ModuleDefinition import org.koin.dsl.context.ModuleDefinition
import org.koin.dsl.module.Module import org.koin.dsl.module.Module
import org.koin.dsl.module.module import org.koin.dsl.module.module
import retrofit2.Retrofit import retrofit2.Retrofit


class SessionModule(private val connectionConfig: HomeServerConnectionConfig) : Module { class SessionModule(private val sessionParams: SessionParams) : Module {


override fun invoke(): ModuleDefinition = module(override = true) { override fun invoke(): ModuleDefinition = module(override = true) {
scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
val retrofitBuilder = get() as Retrofit.Builder val retrofitBuilder = get() as Retrofit.Builder
retrofitBuilder retrofitBuilder
.baseUrl(connectionConfig.hsUri) .baseUrl(sessionParams.homeServerConnectionConfig?.homeServerUri.toString())
.build() .build()
} }

scope(DefaultSession.SCOPE) {
val store = MXFileStore(sessionParams.credentials, false, get())
val dataHandler = MXDataHandler(store, sessionParams.credentials)
MXSession.Builder(sessionParams, dataHandler, get()).build()
}

}.invoke() }.invoke()


} }

View File

@ -16,7 +16,11 @@ class SyncModule : Module {
} }


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
Synchronizer(get(), get(), get()) SyncResponseHandler(get(), get())
}

scope(DefaultSession.SCOPE) {
Synchronizer(get(), get(), get(), get())
} }


}.invoke() }.invoke()

View File

@ -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
}


}

View File

@ -14,7 +14,8 @@ import kotlinx.coroutines.launch


class Synchronizer(private val syncAPI: SyncAPI, class Synchronizer(private val syncAPI: SyncAPI,
private val coroutineDispatchers: MatrixCoroutineDispatchers, private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val jsonMapper: Moshi) { private val jsonMapper: Moshi,
private val syncResponseHandler: SyncResponseHandler) {


fun synchronize(callback: MatrixCallback<SyncResponse>): Cancelable { fun synchronize(callback: MatrixCallback<SyncResponse>): Cancelable {
val job = GlobalScope.launch(coroutineDispatchers.main) { val job = GlobalScope.launch(coroutineDispatchers.main) {
@ -27,8 +28,11 @@ class Synchronizer(private val syncAPI: SyncAPI,
apiCall = syncAPI.sync(params) apiCall = syncAPI.sync(params)
moshi = jsonMapper moshi = jsonMapper
dispatcher = coroutineDispatchers.io 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) return CancelableCoroutine(job)
} }

View File

@ -1,9 +1,10 @@
package im.vector.matrix.android.internal.events.sync.data package im.vector.matrix.android.internal.events.sync.data


import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass


@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class DeviceOneTimeKeysCountSyncResponse( data class DeviceOneTimeKeysCountSyncResponse(
val signed_curve25519: Int? = null @Json(name = "signed_curve25519") val signedCurve25519: Int? = null


) )

View File

@ -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
)

View File

@ -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()
)

View File

@ -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
)

View File

@ -2,11 +2,11 @@ package im.vector.matrix.android.internal.events.sync.data


import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass 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. // SyncResponse represents the request response for server sync v2.
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class SyncResponse( data class SyncResponse(

/** /**
* The user private data. * The user private data.
*/ */
@ -40,6 +40,13 @@ data class SyncResponse(
/** /**
* One time keys management * 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



) )

View File

@ -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;
}

}
}

View File

@ -25,6 +25,7 @@ import android.text.TextUtils;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonElement; 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.call.MXCallsManager;
import im.vector.matrix.android.internal.legacy.crypto.MXCrypto; import im.vector.matrix.android.internal.legacy.crypto.MXCrypto;
import im.vector.matrix.android.internal.legacy.crypto.MXCryptoError; 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.PushRuleSet;
import im.vector.matrix.android.internal.legacy.rest.model.bingrules.PushRulesResponse; 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.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.InvitedRoomSync;
import im.vector.matrix.android.internal.legacy.rest.model.sync.SyncResponse; 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.BingRulesManager;
import im.vector.matrix.android.internal.legacy.util.JsonUtils; 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.Log;
import im.vector.matrix.android.internal.network.ssl.UnrecognizedCertificateException;


import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -173,7 +173,7 @@ public class MXDataHandler {
* Default constructor. * Default constructor.
* *
* @param store the data storage implementation. * @param store the data storage implementation.
* @param credentials the credentials * @param credentials the getCredentials
*/ */
public MXDataHandler(IMXStore store, Credentials credentials) { public MXDataHandler(IMXStore store, Credentials credentials) {
mStore = store; mStore = store;
@ -208,8 +208,12 @@ public class MXDataHandler {
mMetricsListener = metricsListener; mMetricsListener = metricsListener;
} }


public GroupsManager getGroupsManager() {
return mGroupsManager;
}

/** /**
* @return the credentials * @return the getCredentials
*/ */
public Credentials getCredentials() { public Credentials getCredentials() {
return mCredentials; 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, // 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 // which should be the case if this is called after the initial sync
if (mMyUser == null) { if (mMyUser == null) {
mMyUser = new MyUser(store.getUser(mCredentials.userId)); mMyUser = new MyUser(store.getUser(mCredentials.getUserId()));
mMyUser.setDataHandler(this); mMyUser.setDataHandler(this);


// assume the profile is not yet initialized // 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 // 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) { } else if (null != store) {
// assume the profile is not yet initialized // assume the profile is not yet initialized
if ((null == store.displayName()) && (null != mMyUser.displayname)) { if ((null == store.displayName()) && (null != mMyUser.displayname)) {
@ -634,7 +638,7 @@ public class MXDataHandler {
*/ */
public String getUserId() { public String getUserId() {
if (isAlive()) { if (isAlive()) {
return mCredentials.userId; return mCredentials.getUserId();
} else { } else {
return "dummy"; return "dummy";
} }
@ -934,7 +938,7 @@ public class MXDataHandler {


RoomSummary summary = mStore.getSummary(event.roomId); RoomSummary summary = mStore.getSummary(event.roomId);
if (null == summary) { if (null == summary) {
summary = new RoomSummary(null, lastEvent, beforeLiveRoomState, mCredentials.userId); summary = new RoomSummary(null, lastEvent, beforeLiveRoomState, mCredentials.getUserId());
} else { } else {
summary.setLatestReceivedEvent(lastEvent, beforeLiveRoomState); summary.setLatestReceivedEvent(lastEvent, beforeLiveRoomState);
} }
@ -1069,7 +1073,7 @@ public class MXDataHandler {
* @param events the account data events list. * @param events the account data events list.
* @return the ignored users list. null means that there is no defined user ids 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; List<String> ignoredUsers = null;


if (0 != events.size()) { if (0 != events.size()) {
@ -1212,7 +1216,7 @@ public class MXDataHandler {
user.setLatestPresenceTs(System.currentTimeMillis()); user.setLatestPresenceTs(System.currentTimeMillis());


// check if the current user has been updated // 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 // always use the up-to-date information
getMyUser().displayname = user.displayname; getMyUser().displayname = user.displayname;
getMyUser().avatar_url = user.getAvatarUrl(); getMyUser().avatar_url = user.getAvatarUrl();
@ -1420,7 +1424,7 @@ public class MXDataHandler {


if (hasChanged) { if (hasChanged) {
// Update account data to add new direct chat room(s) // 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>() { updatedDirectChatRoomsDict, new ApiCallback<Void>() {
@Override @Override
public void onSuccess(Void info) { public void onSuccess(Void info) {
@ -1532,10 +1536,6 @@ public class MXDataHandler {
} }
} }


if (null != mCrypto) {
mCrypto.onSyncCompleted(syncResponse, fromToken, isCatchingUp);
}

IMXStore store = getStore(); IMXStore store = getStore();


if (!isEmptyResponse && (null != store)) { if (!isEmptyResponse && (null != store)) {
@ -1890,7 +1890,7 @@ public class MXDataHandler {
/** /**
* Start the crypto * Start the crypto
*/ */
private void startCrypto(final boolean isInitialSync) { public void startCrypto(final boolean isInitialSync) {
if ((null != getCrypto()) && !getCrypto().isStarted() && !getCrypto().isStarting()) { if ((null != getCrypto()) && !getCrypto().isStarted() && !getCrypto().isStarting()) {
getCrypto().setNetworkConnectivityReceiver(mNetworkConnectivityReceiver); getCrypto().setNetworkConnectivityReceiver(mNetworkConnectivityReceiver);
getCrypto().start(isInitialSync, new ApiCallback<Void>() { getCrypto().start(isInitialSync, new ApiCallback<Void>() {

View File

@ -30,8 +30,24 @@ import android.text.TextUtils;


import com.google.gson.JsonObject; import com.google.gson.JsonObject;


import im.vector.matrix.android.BuildConfig; import org.matrix.olm.OlmManager;
import im.vector.matrix.android.R;
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.call.MXCallsManager;
import im.vector.matrix.android.internal.legacy.crypto.MXCrypto; import im.vector.matrix.android.internal.legacy.crypto.MXCrypto;
import im.vector.matrix.android.internal.legacy.crypto.MXCryptoConfig; 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.bingrules.BingRule;
import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterBody; 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.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.LoginFlow;
import im.vector.matrix.android.internal.legacy.rest.model.login.RegistrationFlowResponse; import im.vector.matrix.android.internal.legacy.rest.model.login.RegistrationFlowResponse;
import im.vector.matrix.android.internal.legacy.rest.model.message.MediaMessage; 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.Log;
import im.vector.matrix.android.internal.legacy.util.UnsentEventsManager; import im.vector.matrix.android.internal.legacy.util.UnsentEventsManager;
import im.vector.matrix.android.internal.legacy.util.VersionsUtil; 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. * 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. * 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) { private MXSession(final SessionParams sessionParams) {
mCredentials = hsConfig.getCredentials(); mCredentials = sessionParams.getCredentials();
mHsConfig = hsConfig; mHsConfig = sessionParams.getHomeServerConnectionConfig();


mEventsRestClient = new EventsRestClient(hsConfig); mEventsRestClient = new EventsRestClient(sessionParams);
mProfileRestClient = new ProfileRestClient(hsConfig); mProfileRestClient = new ProfileRestClient(sessionParams);
mPresenceRestClient = new PresenceRestClient(hsConfig); mPresenceRestClient = new PresenceRestClient(sessionParams);
mRoomsRestClient = new RoomsRestClient(hsConfig); mRoomsRestClient = new RoomsRestClient(sessionParams);
mPushRulesRestClient = new PushRulesRestClient(hsConfig); mPushRulesRestClient = new PushRulesRestClient(sessionParams);
mPushersRestClient = new PushersRestClient(hsConfig); mPushersRestClient = new PushersRestClient(sessionParams);
mThirdPidRestClient = new ThirdPidRestClient(hsConfig); mThirdPidRestClient = new ThirdPidRestClient(sessionParams);
mCallRestClient = new CallRestClient(hsConfig); mCallRestClient = new CallRestClient(sessionParams);
mAccountDataRestClient = new AccountDataRestClient(hsConfig); mAccountDataRestClient = new AccountDataRestClient(sessionParams);
mCryptoRestClient = new CryptoRestClient(hsConfig); mCryptoRestClient = new CryptoRestClient(sessionParams);
mLoginRestClient = new LoginRestClient(hsConfig); mLoginRestClient = new LoginRestClient(sessionParams);
mGroupsRestClient = new GroupsRestClient(hsConfig); mGroupsRestClient = new GroupsRestClient(sessionParams);
mMediaScanRestClient = new MediaScanRestClient(hsConfig); mMediaScanRestClient = new MediaScanRestClient(sessionParams);
mFilterRestClient = new FilterRestClient(hsConfig); mFilterRestClient = new FilterRestClient(sessionParams);
} }


/** /**
* Create a user session with a data handler. * Create a user session with a data handler.
* Private, please use the MxSession.Builder now * Private, please use the MxSession.Builder now
* *
* @param hsConfig the home server connection config * @param sessionParams the session connection data
* @param dataHandler the data handler * @param dataHandler the data handler
* @param appContext the application context * @param appContext the application context
*/ */
private MXSession(HomeServerConnectionConfig hsConfig, MXDataHandler dataHandler, Context appContext) { private MXSession(final SessionParams sessionParams, MXDataHandler dataHandler, Context appContext) {
this(hsConfig); this(sessionParams);
mDataHandler = dataHandler; mDataHandler = dataHandler;


mDataHandler.getStore().addMXStoreListener(new MXStoreListener() { mDataHandler.getStore().addMXStoreListener(new MXStoreListener() {
@ -300,7 +300,7 @@ public class MXSession {


mUnsentEventsManager = new UnsentEventsManager(mNetworkConnectivityReceiver, mDataHandler); mUnsentEventsManager = new UnsentEventsManager(mNetworkConnectivityReceiver, mDataHandler);


mContentManager = new ContentManager(hsConfig, mUnsentEventsManager); mContentManager = new ContentManager(mHsConfig, mCredentials, mUnsentEventsManager);


// //
mCallsManager = new MXCallsManager(this, mAppContent); mCallsManager = new MXCallsManager(this, mAppContent);
@ -321,8 +321,8 @@ public class MXSession {
mGroupsRestClient.setUnsentEventsManager(mUnsentEventsManager); mGroupsRestClient.setUnsentEventsManager(mUnsentEventsManager);


// return the default cache manager // return the default cache manager
mLatestChatMessageCache = new MXLatestChatMessageCache(mCredentials.userId); mLatestChatMessageCache = new MXLatestChatMessageCache(mCredentials.getUserId());
mMediasCache = new MXMediasCache(mContentManager, mNetworkConnectivityReceiver, mCredentials.userId, appContext); mMediasCache = new MXMediasCache(mContentManager, mNetworkConnectivityReceiver, mCredentials.getUserId(), appContext);
mDataHandler.setMediasCache(mMediasCache); mDataHandler.setMediasCache(mMediasCache);


mMediaScanRestClient.setMxStore(mDataHandler.getStore()); 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() { public Credentials getCredentials() {
checkIfAlive(); checkIfAlive();
@ -842,7 +842,7 @@ public class MXSession {
mEventsThread.setFailureCallback(mFailureCallback); mEventsThread.setFailureCallback(mFailureCallback);
} }


if (mCredentials.accessToken != null && !mEventsThread.isAlive()) { if (mCredentials.getAccessToken() != null && !mEventsThread.isAlive()) {
// GA issue // GA issue
try { try {
mEventsThread.start(); 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 * Update the online status
* *
@ -1246,7 +1217,7 @@ public class MXSession {


params.addCryptoAlgorithm(algorithm); params.addCryptoAlgorithm(algorithm);
params.setDirectMessage(); params.setDirectMessage();
params.addParticipantIds(mHsConfig, Arrays.asList(aParticipantUserId)); params.addParticipantIds(mHsConfig, mCredentials, Arrays.asList(aParticipantUserId));


createRoom(params, aCreateRoomCallBack); createRoom(params, aCreateRoomCallBack);
} }
@ -2436,7 +2407,7 @@ public class MXSession {
DeleteDeviceParams params = new DeleteDeviceParams(); DeleteDeviceParams params = new DeleteDeviceParams();
params.auth = new DeleteDeviceAuth(); params.auth = new DeleteDeviceAuth();
params.auth.session = registrationFlowResponse.session; params.auth.session = registrationFlowResponse.session;
params.auth.user = mCredentials.userId; params.auth.user = mCredentials.getUserId();
params.auth.password = password; params.auth.password = password;


Log.d(LOG_TAG, "## deleteDevice() : supported stages " + stages); Log.d(LOG_TAG, "## deleteDevice() : supported stages " + stages);
@ -2512,10 +2483,12 @@ public class MXSession {
* ========================================================================================== */ * ========================================================================================== */


public static class Builder { public static class Builder {
private MXSession mxSession;


public Builder(HomeServerConnectionConfig hsConfig, MXDataHandler dataHandler, Context context) { private MXSession mxSession;
mxSession = new MXSession(hsConfig, dataHandler, context); private SessionParams sessionParams;

public Builder(SessionParams sessionParams, MXDataHandler dataHandler, Context context) {
mxSession = new MXSession(sessionParams, dataHandler, context);
} }


public Builder withFileEncryption(boolean enableFileEncryption) { public Builder withFileEncryption(boolean enableFileEncryption) {
@ -2538,9 +2511,8 @@ public class MXSession {
try { try {
HomeServerConnectionConfig alteredHsConfig = new HomeServerConnectionConfig.Builder() HomeServerConnectionConfig alteredHsConfig = new HomeServerConnectionConfig.Builder()
.withHomeServerUri(Uri.parse(pushServerUrl)) .withHomeServerUri(Uri.parse(pushServerUrl))
.withCredentials(mxSession.mHsConfig.getCredentials())
.build(); .build();
pushersRestClient = new PushersRestClient(alteredHsConfig); pushersRestClient = new PushersRestClient(new SessionParams(sessionParams.getCredentials(), alteredHsConfig));
} catch (Exception e) { } catch (Exception e) {
Log.e(LOG_TAG, "## withPushServerUrl() failed " + e.getMessage(), e); Log.e(LOG_TAG, "## withPushServerUrl() failed " + e.getMessage(), e);
} }
@ -2562,7 +2534,6 @@ public class MXSession {
*/ */
public Builder withMetricsListener(@Nullable MetricsListener metricsListener) { public Builder withMetricsListener(@Nullable MetricsListener metricsListener) {
mxSession.mMetricsListener = metricsListener; mxSession.mMetricsListener = metricsListener;

return this; return this;
} }



View File

@ -36,15 +36,16 @@ import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;


import im.vector.matrix.android.BuildConfig; 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.listeners.IMXNetworkEventListener;
import im.vector.matrix.android.internal.legacy.network.NetworkConnectivityReceiver; 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.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.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.PolymorphicRequestBodyConverter;
import im.vector.matrix.android.internal.legacy.util.UnsentEventsManager; import im.vector.matrix.android.internal.legacy.util.UnsentEventsManager;
import im.vector.matrix.android.internal.network.ssl.CertUtil;
import okhttp3.Dispatcher; import okhttp3.Dispatcher;
import okhttp3.Interceptor; import okhttp3.Interceptor;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
@ -53,12 +54,12 @@ import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.gson.GsonConverterFactory;
import timber.log.Timber;


/** /**
* Class for making Matrix API calls. * Class for making Matrix API calls.
*/ */
public class RestClient<T> { 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_R0 = "_matrix/media/r0/";
public static final String URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE = "_matrix/media_proxy/unstable/"; 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 // http client
private OkHttpClient mOkHttpClient = new OkHttpClient(); private OkHttpClient mOkHttpClient = new OkHttpClient();


public RestClient(HomeServerConnectionConfig hsConfig, Class<T> type, String uriPrefix, boolean withNullSerialization) { public RestClient(SessionParams sessionParams, Class<T> type, String uriPrefix, boolean withNullSerialization) {
this(hsConfig, type, uriPrefix, withNullSerialization, EndPointServer.HOME_SERVER); this(sessionParams, type, uriPrefix, withNullSerialization, EndPointServer.HOME_SERVER);
} }


/** /**
* Public constructor. * Public constructor.
* *
* @param hsConfig the home server configuration. * @param sessionParams the session data
* @param type the REST type * @param type the REST type
* @param uriPrefix the URL request prefix * @param uriPrefix the URL request prefix
* @param withNullSerialization true to serialise class member with null value * @param withNullSerialization true to serialise class member with null value
* @param useIdentityServer true to use the identity server URL as base request * @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) { public RestClient(SessionParams sessionParams, Class<T> type, String uriPrefix, boolean withNullSerialization, boolean useIdentityServer) {
this(hsConfig, type, uriPrefix, withNullSerialization, useIdentityServer ? EndPointServer.IDENTITY_SERVER : EndPointServer.HOME_SERVER); this(sessionParams, type, uriPrefix, withNullSerialization, useIdentityServer ? EndPointServer.IDENTITY_SERVER : EndPointServer.HOME_SERVER);
} }


/** /**
* Public constructor. * Public constructor.
* *
* @param hsConfig the home server configuration. * @param sessionParams the session data
* @param type the REST type * @param type the REST type
* @param uriPrefix the URL request prefix * @param uriPrefix the URL request prefix
* @param withNullSerialization true to serialise class member with null value * @param withNullSerialization true to serialise class member with null value
* @param endPointServer tell which server is used to define the base url * @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 // The JSON -> object mapper
gson = JsonUtils.getGson(withNullSerialization); gson = JsonUtils.getGson(withNullSerialization);

mHsConfig = sessionParams.getHomeServerConnectionConfig();
mHsConfig = hsConfig; mCredentials = sessionParams.getCredentials();
mCredentials = hsConfig.getCredentials();


Interceptor authentInterceptor = new Interceptor() { Interceptor authentInterceptor = new Interceptor() {


@ -146,12 +146,10 @@ public class RestClient<T> {
// set a custom user agent // set a custom user agent
newRequestBuilder.addHeader("User-Agent", sUserAgent); newRequestBuilder.addHeader("User-Agent", sUserAgent);
} }

// Add the access token to all requests if it is set // Add the access token to all requests if it is set
if ((mCredentials != null) && (mCredentials.accessToken != null)) { if (mCredentials != null) {
newRequestBuilder.addHeader("Authorization", "Bearer " + mCredentials.accessToken); newRequestBuilder.addHeader("Authorization", "Bearer " + mCredentials.getAccessToken());
} }

request = newRequestBuilder.build(); request = newRequestBuilder.build();


return chain.proceed(request); return chain.proceed(request);
@ -191,17 +189,15 @@ public class RestClient<T> {
} }


try { try {
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.newPinnedSSLSocketFactory(hsConfig); Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.INSTANCE.newPinnedSSLSocketFactory(mHsConfig);
okHttpClientBuilder.sslSocketFactory(pair.first, pair.second); okHttpClientBuilder.sslSocketFactory(pair.first, pair.second);
okHttpClientBuilder.hostnameVerifier(CertUtil.newHostnameVerifier(hsConfig)); okHttpClientBuilder.hostnameVerifier(CertUtil.INSTANCE.newHostnameVerifier(mHsConfig));
okHttpClientBuilder.connectionSpecs(CertUtil.newConnectionSpecs(hsConfig)); okHttpClientBuilder.connectionSpecs(CertUtil.INSTANCE.newConnectionSpecs(mHsConfig));
} catch (Exception e) { } catch (Exception e) {
Log.e(LOG_TAG, "## RestClient() setSslSocketFactory failed" + e.getMessage(), e); Timber.e("## RestClient() setSslSocketFactory failed" + e.getMessage(), e);
} }

mOkHttpClient = okHttpClientBuilder.build(); 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 // Rest adapter for turning API interfaces into actual REST-calling objects
Retrofit.Builder builder = new Retrofit.Builder() Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(endPoint) .baseUrl(endPoint)
@ -226,9 +222,12 @@ public class RestClient<T> {
break; break;
case HOME_SERVER: case HOME_SERVER:
default: default:
baseUrl = hsConfig.getHomeserverUri().toString(); baseUrl = hsConfig.getHomeServerUri().toString();


} }
if (baseUrl == null) {
throw new IllegalArgumentException("Base url shouldn't be null");
}
baseUrl = sanitizeBaseUrl(baseUrl); baseUrl = sanitizeBaseUrl(baseUrl);
String dynamicPath = sanitizeDynamicPath(uriPrefix); String dynamicPath = sanitizeDynamicPath(uriPrefix);
return baseUrl + dynamicPath; return baseUrl + dynamicPath;
@ -270,7 +269,7 @@ public class RestClient<T> {
PackageInfo pkgInfo = pm.getPackageInfo(appContext.getApplicationContext().getPackageName(), 0); PackageInfo pkgInfo = pm.getPackageInfo(appContext.getApplicationContext().getPackageName(), 0);
appVersion = pkgInfo.versionName; appVersion = pkgInfo.versionName;
} catch (Exception e) { } 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) .readTimeout((int) (READ_TIMEOUT_MS * factor), TimeUnit.MILLISECONDS)
.writeTimeout((int) (WRITE_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"); Timber.d("## refreshConnectionTimeout() : update setConnectTimeout to " + (CONNECTION_TIMEOUT_MS * factor) + " ms");
Log.d(LOG_TAG, "## refreshConnectionTimeout() : update setReadTimeout to " + (READ_TIMEOUT_MS * factor) + " ms"); Timber.d("## 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 setWriteTimeout to " + (WRITE_TIMEOUT_MS * factor) + " ms");
} else { } else {
builder.connectTimeout(1, TimeUnit.MILLISECONDS); 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 // FIXME It has no effect to the rest client
@ -373,25 +372,25 @@ public class RestClient<T> {
networkConnectivityReceiver.addEventListener(new IMXNetworkEventListener() { networkConnectivityReceiver.addEventListener(new IMXNetworkEventListener() {
@Override @Override
public void onNetworkConnectionUpdate(boolean isConnected) { 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); 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() { public Credentials getCredentials() {
return mCredentials; 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) { public void setCredentials(Credentials credentials) {
mCredentials = credentials; mCredentials = credentials;

View File

@ -26,13 +26,6 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive; 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.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@ -40,6 +33,13 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.Timer; 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 * This class is the default implementation
*/ */
@ -657,7 +657,7 @@ public class MXCall implements IMXCall {
hangupContent.add("reason", new JsonPrimitive(reason)); 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 // local notification to indicate the end of call
mUIThreadHandler.post(new Runnable() { mUIThreadHandler.post(new Runnable() {

View File

@ -631,7 +631,7 @@ public class MXChromeCall extends MXCall {
} }


if (addIt) { 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) { if (null != event) {
// receive an hangup -> close the window asap // receive an hangup -> close the window asap

View File

@ -374,7 +374,7 @@ public class MXWebRtcCall extends MXCall {
offerContent.addProperty("type", sessionDescription.type.canonicalForm()); offerContent.addProperty("type", sessionDescription.type.canonicalForm());
inviteContent.add("offer", offerContent); 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); mPendingEvents.add(event);


@ -434,7 +434,7 @@ public class MXWebRtcCall extends MXCall {
offerContent.addProperty("type", sessionDescription.type.canonicalForm()); offerContent.addProperty("type", sessionDescription.type.canonicalForm());
answerContent.add("answer", offerContent); 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); mPendingEvents.add(event);
sendNextEvent(); sendNextEvent();


@ -737,7 +737,7 @@ public class MXWebRtcCall extends MXCall {
} }


if (addIt) { 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()); mCallSignalingRoom.getRoomId());


mPendingEvents.add(event); mPendingEvents.add(event);

View File

@ -207,17 +207,17 @@ public class MXCrypto {
mRoomEncryptors = new HashMap<>(); mRoomEncryptors = new HashMap<>();
mRoomDecryptors = new HashMap<>(); mRoomDecryptors = new HashMap<>();


String deviceId = mSession.getCredentials().deviceId; String deviceId = mSession.getCredentials().getDeviceId();
// deviceId should always be defined // deviceId should always be defined
boolean refreshDevicesList = !TextUtils.isEmpty(deviceId); boolean refreshDevicesList = !TextUtils.isEmpty(deviceId);


if (TextUtils.isEmpty(deviceId)) { if (TextUtils.isEmpty(deviceId)) {
// use the stored one // use the stored one
mSession.getCredentials().deviceId = deviceId = mCryptoStore.getDeviceId(); deviceId = mCryptoStore.getDeviceId();
} }


if (TextUtils.isEmpty(deviceId)) { 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"); Log.d(LOG_TAG, "Warning: No device id in MXCredentials. An id was created. Think of storing it");
mCryptoStore.storeDeviceId(deviceId); mCryptoStore.storeDeviceId(deviceId);
} }
@ -230,11 +230,11 @@ public class MXCrypto {
Map<String, String> keys = new HashMap<>(); Map<String, String> keys = new HashMap<>();


if (!TextUtils.isEmpty(mOlmDevice.getDeviceEd25519Key())) { 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())) { if (!TextUtils.isEmpty(mOlmDevice.getDeviceCurve25519Key())) {
keys.put("curve25519:" + mSession.getCredentials().deviceId, mOlmDevice.getDeviceCurve25519Key()); keys.put("curve25519:" + mSession.getCredentials().getDeviceId(), mOlmDevice.getDeviceCurve25519Key());
} }


mMyDevice.keys = keys; mMyDevice.keys = keys;
@ -441,7 +441,7 @@ public class MXCrypto {
if (!hasBeenReleased()) { if (!hasBeenReleased()) {
Log.d(LOG_TAG, "###########################################################"); Log.d(LOG_TAG, "###########################################################");
Log.d(LOG_TAG, "uploadDeviceKeys done for " + mSession.getMyUserId()); 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, " - ed25519 : " + mOlmDevice.getDeviceEd25519Key());
Log.d(LOG_TAG, " - curve25519 : " + mOlmDevice.getDeviceCurve25519Key()); Log.d(LOG_TAG, " - curve25519 : " + mOlmDevice.getDeviceCurve25519Key());
Log.d(LOG_TAG, " - oneTimeKeys: " + mLastPublishedOneTimeKeys); // They are Log.d(LOG_TAG, " - oneTimeKeys: " + mLastPublishedOneTimeKeys); // They are
@ -600,17 +600,17 @@ public class MXCrypto {
* @param fromToken the start sync token * @param fromToken the start sync token
* @param isCatchingUp true if there is a catch-up in progress. * @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() { getEncryptingThreadHandler().post(new Runnable() {
@Override @Override
public void run() { public void run() {
if (null != syncResponse.deviceLists) { if (null != syncResponse.getDeviceLists()) {
getDeviceList().handleDeviceListsChanges(syncResponse.deviceLists.changed, syncResponse.deviceLists.left); getDeviceList().handleDeviceListsChanges(syncResponse.getDeviceLists().getChanged(), syncResponse.getDeviceLists().getLeft());
} }


if (null != syncResponse.deviceOneTimeKeysCount) { if (null != syncResponse.getDeviceOneTimeKeysCount()) {
int currentCount = (null != syncResponse.deviceOneTimeKeysCount.signed_curve25519) ? int currentCount = (null != syncResponse.getDeviceOneTimeKeysCount().getSignedCurve25519()) ?
syncResponse.deviceOneTimeKeysCount.signed_curve25519 : 0; syncResponse.getDeviceOneTimeKeysCount().getSignedCurve25519() : 0;
updateOneTimeKeyCount(currentCount); updateOneTimeKeyCount(currentCount);
} }


@ -1470,7 +1470,7 @@ public class MXCrypto {
Map<String, Object> payloadJson = new HashMap<>(payloadFields); Map<String, Object> payloadJson = new HashMap<>(payloadFields);


payloadJson.put("sender", mSession.getMyUserId()); 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 // Include the Ed25519 key so that the recipient knows what
// device this message came from. // device this message came from.

View File

@ -22,6 +22,12 @@ import android.text.TextUtils;


import com.google.gson.JsonElement; 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.MXSession;
import im.vector.matrix.android.internal.legacy.crypto.MXCrypto; import im.vector.matrix.android.internal.legacy.crypto.MXCrypto;
import im.vector.matrix.android.internal.legacy.crypto.MXCryptoAlgorithms; 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.JsonUtils;
import im.vector.matrix.android.internal.legacy.util.Log; 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 { public class MXMegolmEncryption implements IMXEncrypting {
private static final String LOG_TAG = MXMegolmEncryption.class.getSimpleName(); private static final String LOG_TAG = MXMegolmEncryption.class.getSimpleName();


@ -76,7 +76,7 @@ public class MXMegolmEncryption implements IMXEncrypting {
mCrypto = matrixSession.getCrypto(); mCrypto = matrixSession.getCrypto();


mRoomId = roomId; mRoomId = roomId;
mDeviceId = matrixSession.getCredentials().deviceId; mDeviceId = matrixSession.getCredentials().getDeviceId();


// Default rotation periods // Default rotation periods
// TODO: Make it configurable via parameters // TODO: Make it configurable via parameters

View File

@ -18,11 +18,11 @@ package im.vector.matrix.android.internal.legacy.data.cryptostore;


import android.content.Context; 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.IncomingRoomKeyRequest;
import im.vector.matrix.android.internal.legacy.crypto.OutgoingRoomKeyRequest; 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.MXDeviceInfo;
import im.vector.matrix.android.internal.legacy.crypto.data.MXOlmInboundGroupSession2; 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.OlmAccount;
import org.matrix.olm.OlmSession; import org.matrix.olm.OlmSession;


@ -35,10 +35,10 @@ import java.util.Set;
*/ */
public interface IMXCryptoStore { 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 context the application context
* @param credentials the credentials of the account. * @param credentials the getCredentials of the account.
*/ */
void initWithCredentials(Context context, Credentials credentials); void initWithCredentials(Context context, Credentials credentials);


@ -55,7 +55,7 @@ public interface IMXCryptoStore {
boolean hasData(); boolean hasData();


/** /**
* Delete the crypto store for the passed credentials. * Delete the crypto store for the passed getCredentials.
*/ */
void deleteStore(); void deleteStore();



View File

@ -22,16 +22,6 @@ import android.content.Context;
import android.os.Looper; import android.os.Looper;
import android.text.TextUtils; 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.OlmAccount;
import org.matrix.olm.OlmSession; import org.matrix.olm.OlmSession;


@ -51,6 +41,17 @@ import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; 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 * 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 = "incomingRoomKeyRequests";
private static final String MXFILE_CRYPTO_STORE_INCOMING_ROOM_KEY_REQUESTS_FILE_TMP = "incomingRoomKeyRequests.tmp"; 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; private Credentials mCredentials;


// Meta data about the store // Meta data about the store
@ -182,7 +183,7 @@ public class MXFileCryptoStore implements IMXCryptoStore {
public void initWithCredentials(Context context, Credentials credentials) { public void initWithCredentials(Context context, Credentials credentials) {
mCredentials = 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); mMetaDataFile = new File(mStoreFile, MXFILE_CRYPTO_STORE_METADATA_FILE);
mMetaDataFileTmp = new File(mStoreFile, MXFILE_CRYPTO_STORE_METADATA_FILE_TMP); 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); mIncomingRoomKeyRequestsFileTmp = new File(mStoreFile, MXFILE_CRYPTO_STORE_INCOMING_ROOM_KEY_REQUESTS_FILE_TMP);


// Build default metadata // Build default metadata
if ((null == mMetaData) if (mMetaData == null) {
&& (null != credentials.homeServer) mMetaData = new MXFileCryptoStoreMetaData2(mCredentials.getUserId(), mCredentials.getDeviceId(), MXFILE_CRYPTO_VERSION);
&& (null != credentials.userId)
&& (null != credentials.accessToken)) {
mMetaData = new MXFileCryptoStoreMetaData2(mCredentials.userId, mCredentials.deviceId, MXFILE_CRYPTO_VERSION);
} }


mUsersDevicesInfoMap = new MXUsersDevicesMap<>(); mUsersDevicesInfoMap = new MXUsersDevicesMap<>();
@ -243,7 +241,7 @@ public class MXFileCryptoStore implements IMXCryptoStore {


if (null != mMetaData) { if (null != mMetaData) {
result = TextUtils.isEmpty(mMetaData.mDeviceId) 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"); Log.e(LOG_TAG, "## open() : New MXFileCryptoStore version detected");
resetData(); resetData();
} }
// Check credentials // Check getCredentials
// The device id may not have been provided in credentials. // The device id may not have been provided in getCredentials.
// Check it only if provided, else trust the stored one. // Check it only if provided, else trust the stored one.
else if (!TextUtils.equals(mMetaData.mUserId, mCredentials.userId) else if (!TextUtils.equals(mMetaData.mUserId, mCredentials.getUserId())
|| ((null != mCredentials.deviceId) && !TextUtils.equals(mCredentials.deviceId, mMetaData.mDeviceId))) { || ((null != mCredentials.getDeviceId()) && !TextUtils.equals(mCredentials.getDeviceId(), mMetaData.mDeviceId))) {
Log.e(LOG_TAG, "## open() : Credentials do not match"); Log.e(LOG_TAG, "## open() : Credentials do not match");
resetData(); resetData();
} }
@ -298,12 +296,9 @@ public class MXFileCryptoStore implements IMXCryptoStore {
preloadCryptoData(); preloadCryptoData();
} }


// Else, if credentials is valid, create and store it // Else, if getCredentials is valid, create and store it
if ((null == mMetaData) if (mMetaData == null){
&& (null != mCredentials.homeServer) mMetaData = new MXFileCryptoStoreMetaData2(mCredentials.getUserId(), mCredentials.getDeviceId(), MXFILE_CRYPTO_VERSION);
&& (null != mCredentials.userId)
&& (null != mCredentials.accessToken)) {
mMetaData = new MXFileCryptoStoreMetaData2(mCredentials.userId, mCredentials.deviceId, MXFILE_CRYPTO_VERSION);
mIsReady = true; mIsReady = true;
// flush the metadata // flush the metadata
saveMetaData(); saveMetaData();

View File

@ -23,25 +23,6 @@ import android.os.HandlerThread;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.TextUtils; 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.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -60,6 +41,25 @@ import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; 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. * An in-file IMXStore.
*/ */
@ -217,21 +217,21 @@ public class MXFileStore extends MXMemoryStore {
/** /**
* Constructor * Constructor
* *
* @param hsConfig the expected credentials * @param credentials the expected getCredentials
* @param enableFileEncryption set to true to enable file encryption. * @param enableFileEncryption set to true to enable file encryption.
* @param context the context. * @param context the context.
*/ */
public MXFileStore(HomeServerConnectionConfig hsConfig, boolean enableFileEncryption, Context context) { public MXFileStore(Credentials credentials, boolean enableFileEncryption, Context context) {
setContext(context); setContext(context);


mEnableFileEncryption = enableFileEncryption; mEnableFileEncryption = enableFileEncryption;


mIsReady = false; 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 // updated data
mRoomsToCommitForMessages = new HashSet<>(); mRoomsToCommitForMessages = new HashSet<>();
@ -260,8 +260,8 @@ public class MXFileStore extends MXMemoryStore {
mFileStoreHandler = new MXOsHandler(mHandlerThread.getLooper()); mFileStoreHandler = new MXOsHandler(mHandlerThread.getLooper());


mMetadata = new MXFileStoreMetaData(); mMetadata = new MXFileStoreMetaData();
mMetadata.mUserId = mCredentials.userId; mMetadata.mUserId = mCredentials.getUserId();
mMetadata.mAccessToken = mCredentials.accessToken; mMetadata.mAccessToken = mCredentials.getAccessToken();
mMetadata.mVersion = MXFILE_VERSION; mMetadata.mVersion = MXFILE_VERSION;
mMetaDataHasChanged = true; mMetaDataHasChanged = true;
saveMetaData(); saveMetaData();
@ -360,8 +360,8 @@ public class MXFileStore extends MXMemoryStore {


String errorDescription = null; String errorDescription = null;
boolean succeed = (mMetadata.mVersion == MXFILE_VERSION) boolean succeed = (mMetadata.mVersion == MXFILE_VERSION)
&& TextUtils.equals(mMetadata.mUserId, mCredentials.userId) && TextUtils.equals(mMetadata.mUserId, mCredentials.getUserId())
&& TextUtils.equals(mMetadata.mAccessToken, mCredentials.accessToken); && TextUtils.equals(mMetadata.mAccessToken, mCredentials.getAccessToken());


if (!succeed) { if (!succeed) {
errorDescription = "Invalid store content"; errorDescription = "Invalid store content";
@ -437,7 +437,7 @@ public class MXFileStore extends MXMemoryStore {
if (null == room) { if (null == room) {
succeed = false; succeed = false;
Log.e(LOG_TAG, "loadSummaries : the room " + roomId + " does not exist"); 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; //succeed = false;
Log.e(LOG_TAG, "loadSummaries) : a summary exists for the roomId " Log.e(LOG_TAG, "loadSummaries) : a summary exists for the roomId "
+ roomId + " but the user is not anymore a member"); + 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 // mMetadata should only be null at file store loading
if (null == mMetadata) { if (null == mMetadata) {
mMetadata = new MXFileStoreMetaData(); mMetadata = new MXFileStoreMetaData();
mMetadata.mUserId = mCredentials.userId; mMetadata.mUserId = mCredentials.getUserId();
mMetadata.mAccessToken = mCredentials.accessToken; mMetadata.mAccessToken = mCredentials.getAccessToken();
mMetaDataHasChanged = true; mMetaDataHasChanged = true;
} else { } else {
mMetadata.mEventStreamToken = null; mMetadata.mEventStreamToken = null;
@ -515,7 +515,7 @@ public class MXFileStore extends MXMemoryStore {


// post processing // post processing
Log.d(LOG_TAG, "## open() : post processing."); Log.d(LOG_TAG, "## open() : post processing.");
dispatchPostProcess(mCredentials.userId); dispatchPostProcess(mCredentials.getUserId());
mIsPostProcessingDone = true; mIsPostProcessingDone = true;


synchronized (this) { synchronized (this) {
@ -525,7 +525,7 @@ public class MXFileStore extends MXMemoryStore {


if (!succeed && !mIsNewStorage) { if (!succeed && !mIsNewStorage) {
Log.e(LOG_TAG, "The store is corrupted."); Log.e(LOG_TAG, "The store is corrupted.");
dispatchOnStoreCorrupted(mCredentials.userId, errorDescription); dispatchOnStoreCorrupted(mCredentials.getUserId(), errorDescription);
} else { } else {
// extract the room states // extract the room states
mRoomReceiptsToLoad.addAll(listFiles(mStoreRoomsMessagesReceiptsFolderFile.list())); mRoomReceiptsToLoad.addAll(listFiles(mStoreRoomsMessagesReceiptsFolderFile.list()));
@ -535,7 +535,7 @@ public class MXFileStore extends MXMemoryStore {
} }


Log.d(LOG_TAG, "The store is opened."); Log.d(LOG_TAG, "The store is opened.");
dispatchOnStoreReady(mCredentials.userId); dispatchOnStoreReady(mCredentials.getUserId());


// load the following items with delay // load the following items with delay
// theses items are not required to be ready // theses items are not required to be ready
@ -567,12 +567,12 @@ public class MXFileStore extends MXMemoryStore {
} else { } else {
if (!mIsPostProcessingDone) { if (!mIsPostProcessingDone) {
Log.e(LOG_TAG, "## open() : is ready but the post processing was not yet done."); Log.e(LOG_TAG, "## open() : is ready but the post processing was not yet done.");
dispatchPostProcess(mCredentials.userId); dispatchPostProcess(mCredentials.getUserId());
mIsPostProcessingDone = true; mIsPostProcessingDone = true;
} else { } else {
Log.e(LOG_TAG, "## open() when ready : the post processing is already done."); Log.e(LOG_TAG, "## open() when ready : the post processing is already done.");
} }
dispatchOnStoreReady(mCredentials.userId); dispatchOnStoreReady(mCredentials.getUserId());
mPreloadTime = System.currentTimeMillis() - fLoadTimeT0; mPreloadTime = System.currentTimeMillis() - fLoadTimeT0;
if (mMetricsListener != null) { if (mMetricsListener != null) {
mMetricsListener.onStorePreloaded(mPreloadTime); mMetricsListener.onStorePreloaded(mPreloadTime);
@ -662,7 +662,7 @@ public class MXFileStore extends MXMemoryStore {
try { try {
ContentUtils.deleteDirectory(mStoreFolderFile); ContentUtils.deleteDirectory(mStoreFolderFile);
if (init) { if (init) {
createDirTree(mCredentials.userId); createDirTree(mCredentials.getUserId());
} }
} catch (Exception e) { } catch (Exception e) {
Log.e(LOG_TAG, "deleteAllData failed " + e.getMessage(), e); Log.e(LOG_TAG, "deleteAllData failed " + e.getMessage(), e);
@ -790,7 +790,7 @@ public class MXFileStore extends MXMemoryStore {


@Override @Override
public void storeUser(User user) { 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); mUserIdsToCommit.add(user.user_id);
} }
super.storeUser(user); super.storeUser(user);

View File

@ -24,6 +24,7 @@ import android.os.Looper;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.TextUtils; 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.MXDataHandler;
import im.vector.matrix.android.internal.legacy.data.Room; 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.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.TokensChunkEvents;
import im.vector.matrix.android.internal.legacy.rest.model.User; 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.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.rest.model.pid.ThirdPartyIdentifier;
import im.vector.matrix.android.internal.legacy.util.Log; import im.vector.matrix.android.internal.legacy.util.Log;


@ -149,7 +149,7 @@ public class MXMemoryStore implements IMXStore {
/** /**
* Default constructor * Default constructor
* *
* @param credentials the expected credentials * @param credentials the expected getCredentials
* @param context the context * @param context the context
*/ */
public MXMemoryStore(Credentials credentials, Context context) { public MXMemoryStore(Credentials credentials, Context context) {
@ -245,7 +245,7 @@ public class MXMemoryStore implements IMXStore {
*/ */
@Override @Override
public void setCorrupted(String reason) { public void setCorrupted(String reason) {
dispatchOnStoreCorrupted(mCredentials.userId, reason); dispatchOnStoreCorrupted(mCredentials.getUserId(), reason);
} }


/** /**
@ -607,7 +607,7 @@ public class MXMemoryStore implements IMXStore {
*/ */
@Override @Override
public int eventsCountAfter(String roomId, String eventId) { public int eventsCountAfter(String roomId, String eventId) {
return eventsAfter(roomId, eventId, mCredentials.userId, null).size(); return eventsAfter(roomId, eventId, mCredentials.getUserId(), null).size();
} }


@Override @Override
@ -1155,7 +1155,7 @@ public class MXMemoryStore implements IMXStore {


synchronized (mReceiptsByRoomIdLock) { synchronized (mReceiptsByRoomIdLock) {
if (mReceiptsByRoomId.containsKey(roomId)) { if (mReceiptsByRoomId.containsKey(roomId)) {
String myUserID = mCredentials.userId; String myUserID = mCredentials.getUserId();


Map<String, ReceiptData> receiptsByUserId = mReceiptsByRoomId.get(roomId); Map<String, ReceiptData> receiptsByUserId = mReceiptsByRoomId.get(roomId);
// copy the user id list to avoid having update while looping // 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 // 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) { synchronized (mReceiptsByRoomIdLock) {
LinkedHashMap<String, Event> eventsMap = mRoomEvents.get(roomId); LinkedHashMap<String, Event> eventsMap = mRoomEvents.get(roomId);


@ -1334,7 +1334,7 @@ public class MXMemoryStore implements IMXStore {
for (int index = 0; index < events.size(); index++) { for (int index = 0; index < events.size(); index++) {
Event event = events.get(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); events.remove(index);
index--; index--;
} }
@ -1402,10 +1402,10 @@ public class MXMemoryStore implements IMXStore {
if (mReceiptsByRoomId.containsKey(roomId)) { if (mReceiptsByRoomId.containsKey(roomId)) {
Map<String, ReceiptData> receiptsByUserId = mReceiptsByRoomId.get(roomId); Map<String, ReceiptData> receiptsByUserId = mReceiptsByRoomId.get(roomId);


if (receiptsByUserId.containsKey(mCredentials.userId)) { if (receiptsByUserId.containsKey(mCredentials.getUserId())) {
ReceiptData data = receiptsByUserId.get(mCredentials.userId); 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(); List<IMXStoreListener> listeners = getListeners();


for (IMXStoreListener listener : listeners) { for (IMXStoreListener listener : listeners) {
listener.onStoreOOM(mCredentials.userId, e.getMessage()); listener.onStoreOOM(mCredentials.getUserId(), e.getMessage());
} }
} }



View File

@ -51,7 +51,7 @@ class TimelineEventSaver {


public void storeEvent(@NonNull final Event event) { public void storeEvent(@NonNull final Event event) {
final MXDataHandler dataHandler = mRoom.getDataHandler(); 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 // create dummy read receipt for any incoming event
// to avoid not synchronized read receipt and event // to avoid not synchronized read receipt and event

View File

@ -19,6 +19,11 @@ package im.vector.matrix.android.internal.legacy.data.timeline;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; 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.MXDataHandler;
import im.vector.matrix.android.internal.legacy.data.MyUser; import im.vector.matrix.android.internal.legacy.data.MyUser;
import im.vector.matrix.android.internal.legacy.data.Room; 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.JsonUtils;
import im.vector.matrix.android.internal.legacy.util.Log; 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 * This class is responsible for handling live event
*/ */
@ -203,7 +203,7 @@ class TimelineLiveEventHandler {
@NonNull Event event, @NonNull Event event,
final boolean checkRedactedStateEvent) { final boolean checkRedactedStateEvent) {
boolean shouldBeSaved = false; boolean shouldBeSaved = false;
String myUserId = dataHandler.getCredentials().userId; String myUserId = dataHandler.getCredentials().getUserId();


if (Event.EVENT_TYPE_REDACTION.equals(event.getType())) { if (Event.EVENT_TYPE_REDACTION.equals(event.getType())) {
if (event.getRedactedEventId() != null) { if (event.getRedactedEventId() != null) {

View File

@ -32,23 +32,6 @@ import android.widget.ImageView;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonParser; 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.OlmPkEncryption;
import org.matrix.olm.OlmPkMessage; import org.matrix.olm.OlmPkMessage;


@ -78,6 +61,24 @@ import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager; 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. * This class manages the media downloading in background.
* <p> * <p>
@ -746,9 +747,9 @@ class MXMediaDownloadWorkerTask extends AsyncTask<Void, Void, JsonElement> {
// Add SSL Socket factory. // Add SSL Socket factory.
HttpsURLConnection sslConn = (HttpsURLConnection) connection; HttpsURLConnection sslConn = (HttpsURLConnection) connection;
try { try {
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.newPinnedSSLSocketFactory(mHsConfig); Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.INSTANCE.newPinnedSSLSocketFactory(mHsConfig);
sslConn.setSSLSocketFactory(pair.first); sslConn.setSSLSocketFactory(pair.first);
sslConn.setHostnameVerifier(CertUtil.newHostnameVerifier(mHsConfig)); sslConn.setHostnameVerifier(CertUtil.INSTANCE.newHostnameVerifier(mHsConfig));
} catch (Exception e) { } catch (Exception e) {
Log.e(LOG_TAG, "doInBackground SSL exception " + e.getMessage(), e); Log.e(LOG_TAG, "doInBackground SSL exception " + e.getMessage(), e);
} }

View File

@ -22,15 +22,6 @@ import android.util.Pair;


import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; 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.DataOutputStream;
import java.io.EOFException; import java.io.EOFException;
@ -51,6 +42,16 @@ import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager; 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. * Private AsyncTask used to upload files.
*/ */
@ -282,7 +283,7 @@ public class MXMediaUploadWorkerTask extends AsyncTask<Void, Void, String> {


String serverResponse = null; 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) { if (null != mFilename) {
try { try {
@ -300,7 +301,7 @@ public class MXMediaUploadWorkerTask extends AsyncTask<Void, Void, String> {
if (RestClient.getUserAgent() != null) { if (RestClient.getUserAgent() != null) {
conn.setRequestProperty("User-Agent", RestClient.getUserAgent()); 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.setDoInput(true);
conn.setDoOutput(true); conn.setDoOutput(true);
conn.setUseCaches(false); conn.setUseCaches(false);
@ -310,9 +311,9 @@ public class MXMediaUploadWorkerTask extends AsyncTask<Void, Void, String> {
// Add SSL Socket factory. // Add SSL Socket factory.
HttpsURLConnection sslConn = (HttpsURLConnection) conn; HttpsURLConnection sslConn = (HttpsURLConnection) conn;
try { try {
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.newPinnedSSLSocketFactory(mContentManager.getHsConfig()); Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.INSTANCE.newPinnedSSLSocketFactory(mContentManager.getHsConfig());
sslConn.setSSLSocketFactory(pair.first); sslConn.setSSLSocketFactory(pair.first);
sslConn.setHostnameVerifier(CertUtil.newHostnameVerifier(mContentManager.getHsConfig())); sslConn.setHostnameVerifier(CertUtil.INSTANCE.newHostnameVerifier(mContentManager.getHsConfig()));
} catch (Exception e) { } catch (Exception e) {
Log.e(LOG_TAG, "sslConn " + e.getMessage(), e); Log.e(LOG_TAG, "sslConn " + e.getMessage(), e);
} }

View File

@ -31,7 +31,18 @@ import android.text.TextUtils;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.widget.ImageView; 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.crypto.MXEncryptedAttachments;
import im.vector.matrix.android.internal.legacy.listeners.IMXMediaDownloadListener; import im.vector.matrix.android.internal.legacy.listeners.IMXMediaDownloadListener;
import im.vector.matrix.android.internal.legacy.listeners.IMXMediaUploadListener; 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.Log;
import im.vector.matrix.android.internal.legacy.util.MXOsHandler; 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 { public class MXMediasCache {


private static final String LOG_TAG = MXMediasCache.class.getSimpleName(); private static final String LOG_TAG = MXMediasCache.class.getSimpleName();

View File

@ -16,15 +16,15 @@
*/ */
package im.vector.matrix.android.internal.legacy.rest.client; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.AccountDataApi; 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.ApiCallback;
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback; import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback;


import java.util.HashMap;
import java.util.Map;

public class AccountDataRestClient extends RestClient<AccountDataApi> { public class AccountDataRestClient extends RestClient<AccountDataApi> {
/** /**
* Account data types * Account data types
@ -43,8 +43,8 @@ public class AccountDataRestClient extends RestClient<AccountDataApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public AccountDataRestClient(HomeServerConnectionConfig hsConfig) { public AccountDataRestClient(SessionParams sessionParams) {
super(hsConfig, AccountDataApi.class, RestClient.URI_API_PREFIX_PATH_R0, false); 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) mApi.setAccountData(userId, type, params)
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() { .enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
setAccountData(userId, type, params, callback); setAccountData(userId, type, params, callback);
} }
})); }));
} }


/** /**
@ -82,11 +82,11 @@ public class AccountDataRestClient extends RestClient<AccountDataApi> {


mApi.openIdToken(userId, new HashMap<>()) mApi.openIdToken(userId, new HashMap<>())
.enqueue(new RestAdapterCallback<Map<Object, Object>>(description, mUnsentEventsManager, callback, .enqueue(new RestAdapterCallback<Map<Object, Object>>(description, mUnsentEventsManager, callback,
new RestAdapterCallback.RequestRetryCallBack() { new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
openIdToken(userId, callback); openIdToken(userId, callback);
} }
})); }));
} }
} }

View File

@ -17,7 +17,7 @@ package im.vector.matrix.android.internal.legacy.rest.client;


import com.google.gson.JsonObject; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.CallRulesApi; import im.vector.matrix.android.internal.legacy.rest.api.CallRulesApi;
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback; import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
@ -28,8 +28,8 @@ public class CallRestClient extends RestClient<CallRulesApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public CallRestClient(HomeServerConnectionConfig hsConfig) { public CallRestClient(SessionParams sessionParams) {
super(hsConfig, CallRulesApi.class, RestClient.URI_API_PREFIX_PATH_R0, false); super(sessionParams, CallRulesApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
} }


public void getTurnServer(final ApiCallback<JsonObject> callback) { public void getTurnServer(final ApiCallback<JsonObject> callback) {

View File

@ -19,7 +19,12 @@ package im.vector.matrix.android.internal.legacy.rest.client;


import android.text.TextUtils; 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.RestClient;
import im.vector.matrix.android.internal.legacy.crypto.data.MXKey; import im.vector.matrix.android.internal.legacy.crypto.data.MXKey;
import im.vector.matrix.android.internal.legacy.crypto.data.MXUsersDevicesMap; 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.rest.model.sync.DevicesListResponse;
import im.vector.matrix.android.internal.legacy.util.JsonUtils; 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.Log;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import retrofit2.Response; import retrofit2.Response;


public class CryptoRestClient extends RestClient<CryptoApi> { public class CryptoRestClient extends RestClient<CryptoApi> {
@ -49,8 +48,8 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public CryptoRestClient(HomeServerConnectionConfig hsConfig) { public CryptoRestClient(SessionParams sessionParams) {
super(hsConfig, CryptoApi.class, URI_API_PREFIX_PATH_UNSTABLE, false, false); 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) mApi.uploadKeys(encodedDeviceId, params)
.enqueue(new RestAdapterCallback<KeysUploadResponse>(description, null, callback, .enqueue(new RestAdapterCallback<KeysUploadResponse>(description, null, callback,
new RestAdapterCallback.RequestRetryCallBack() { new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
uploadKeys(deviceKeys, oneTimeKeys, deviceId, callback); uploadKeys(deviceKeys, oneTimeKeys, deviceId, callback);
} }
})); }));
} else { } else {
mApi.uploadKeys(params) mApi.uploadKeys(params)
.enqueue(new RestAdapterCallback<KeysUploadResponse>(description, null, callback, .enqueue(new RestAdapterCallback<KeysUploadResponse>(description, null, callback,
new RestAdapterCallback.RequestRetryCallBack() { new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
uploadKeys(deviceKeys, oneTimeKeys, deviceId, callback); uploadKeys(deviceKeys, oneTimeKeys, deviceId, callback);
} }
})); }));
} }
} }


@ -127,11 +126,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
mApi.downloadKeysForUsers(parameters) mApi.downloadKeysForUsers(parameters)
.enqueue(new RestAdapterCallback<KeysQueryResponse>(description, mUnsentEventsManager, callback, .enqueue(new RestAdapterCallback<KeysQueryResponse>(description, mUnsentEventsManager, callback,
new RestAdapterCallback.RequestRetryCallBack() { new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
downloadKeysForUsers(userIds, token, callback); downloadKeysForUsers(userIds, token, callback);
} }
})); }));
} }


/** /**
@ -151,40 +150,40 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
mApi.claimOneTimeKeysForUsersDevices(params) mApi.claimOneTimeKeysForUsersDevices(params)
.enqueue(new RestAdapterCallback<KeysClaimResponse>(description, mUnsentEventsManager, callback, .enqueue(new RestAdapterCallback<KeysClaimResponse>(description, mUnsentEventsManager, callback,
new RestAdapterCallback.RequestRetryCallBack() { new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
claimOneTimeKeysForUsersDevices(usersDevicesKeyTypesMap, callback); claimOneTimeKeysForUsersDevices(usersDevicesKeyTypesMap, callback);
} }
}) { }) {
@Override @Override
public void success(KeysClaimResponse keysClaimResponse, Response response) { public void success(KeysClaimResponse keysClaimResponse, Response response) {
onEventSent(); onEventSent();


Map<String, Map<String, MXKey>> map = new HashMap<>(); Map<String, Map<String, MXKey>> map = new HashMap<>();


if (null != keysClaimResponse.oneTimeKeys) { if (null != keysClaimResponse.oneTimeKeys) {
for (String userId : keysClaimResponse.oneTimeKeys.keySet()) { for (String userId : keysClaimResponse.oneTimeKeys.keySet()) {
Map<String, Map<String, Map<String, Object>>> mapByUserId = keysClaimResponse.oneTimeKeys.get(userId); 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()) { for (String deviceId : mapByUserId.keySet()) {
try { try {
keysMap.put(deviceId, new MXKey(mapByUserId.get(deviceId))); keysMap.put(deviceId, new MXKey(mapByUserId.get(deviceId)));
} catch (Exception e) { } catch (Exception e) {
Log.e(LOG_TAG, "## claimOneTimeKeysForUsersDevices : fail to create a MXKey " + e.getMessage(), 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) { callback.onSuccess(new MXUsersDevicesMap<>(map));
map.put(userId, keysMap);
}
} }
} });

callback.onSuccess(new MXUsersDevicesMap<>(map));
}
});
} }


/** /**
@ -217,11 +216,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {


mApi.sendToDevice(eventType, transactionId, content) mApi.sendToDevice(eventType, transactionId, content)
.enqueue(new RestAdapterCallback<Void>(description, null, callback, new RestAdapterCallback.RequestRetryCallBack() { .enqueue(new RestAdapterCallback<Void>(description, null, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
sendToDevice(eventType, contentMap, callback); sendToDevice(eventType, contentMap, callback);
} }
})); }));
} }


/** /**
@ -235,11 +234,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
mApi.getDevices() mApi.getDevices()
.enqueue(new RestAdapterCallback<DevicesListResponse>(description, mUnsentEventsManager, callback, .enqueue(new RestAdapterCallback<DevicesListResponse>(description, mUnsentEventsManager, callback,
new RestAdapterCallback.RequestRetryCallBack() { new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
getDevices(callback); getDevices(callback);
} }
})); }));
} }


/** /**
@ -255,11 +254,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {


mApi.deleteDevice(deviceId, params) mApi.deleteDevice(deviceId, params)
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() { .enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
deleteDevice(deviceId, params, callback); deleteDevice(deviceId, params, callback);
} }
})); }));
} }


/** /**
@ -278,11 +277,11 @@ public class CryptoRestClient extends RestClient<CryptoApi> {


mApi.updateDeviceInfo(deviceId, params) mApi.updateDeviceInfo(deviceId, params)
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() { .enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
setDeviceName(deviceId, deviceName, callback); setDeviceName(deviceId, deviceName, callback);
} }
})); }));
} }


/** /**
@ -299,10 +298,10 @@ public class CryptoRestClient extends RestClient<CryptoApi> {
mApi.getKeyChanges(from, to) mApi.getKeyChanges(from, to)
.enqueue(new RestAdapterCallback<KeyChangesResponse>(description, mUnsentEventsManager, callback, .enqueue(new RestAdapterCallback<KeyChangesResponse>(description, mUnsentEventsManager, callback,
new RestAdapterCallback.RequestRetryCallBack() { new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
getKeyChanges(from, to, callback); getKeyChanges(from, to, callback);
} }
})); }));
} }
} }

View File

@ -19,7 +19,7 @@ package im.vector.matrix.android.internal.legacy.rest.client;


import android.text.TextUtils; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.EventsApi; import im.vector.matrix.android.internal.legacy.rest.api.EventsApi;
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback; import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
@ -62,8 +62,8 @@ public class EventsRestClient extends RestClient<EventsApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public EventsRestClient(HomeServerConnectionConfig hsConfig) { public EventsRestClient(SessionParams sessionParams) {
super(hsConfig, EventsApi.class, "", false); super(sessionParams, EventsApi.class, "", false);
} }


protected EventsRestClient(EventsApi api) { protected EventsRestClient(EventsApi api) {

View File

@ -16,7 +16,7 @@
*/ */
package im.vector.matrix.android.internal.legacy.rest.client; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.FilterApi; import im.vector.matrix.android.internal.legacy.rest.api.FilterApi;
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback; 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.FilterBody;
import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterResponse; import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterResponse;


public class FilterRestClient extends RestClient<FilterApi>{ public class FilterRestClient extends RestClient<FilterApi> {


/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public FilterRestClient(HomeServerConnectionConfig hsConfig) { public FilterRestClient(SessionParams sessionParams) {
super(hsConfig, FilterApi.class, RestClient.URI_API_PREFIX_PATH_R0, false); super(sessionParams, FilterApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
} }


/** /**
* Uploads a FilterBody to homeserver * 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 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) { public void uploadFilter(final String userId, final FilterBody filterBody, final ApiCallback<FilterResponse> callback) {
final String description = "uploadFilter userId : " + userId + " filter : " + filterBody; final String description = "uploadFilter userId : " + userId + " filter : " + filterBody;

View File

@ -17,13 +17,18 @@
*/ */
package im.vector.matrix.android.internal.legacy.rest.client; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.GroupsApi; 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.ApiCallback;
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback; 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.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.AcceptGroupInvitationParams;
import im.vector.matrix.android.internal.legacy.rest.model.group.AddGroupParams; import im.vector.matrix.android.internal.legacy.rest.model.group.AddGroupParams;
import im.vector.matrix.android.internal.legacy.rest.model.group.CreateGroupParams; 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.GroupUsers;
import im.vector.matrix.android.internal.legacy.rest.model.group.LeaveGroupParams; import im.vector.matrix.android.internal.legacy.rest.model.group.LeaveGroupParams;
import im.vector.matrix.android.internal.legacy.rest.model.group.UpdatePubliciseParams; 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; import retrofit2.Response;


/** /**
@ -56,8 +54,8 @@ public class GroupsRestClient extends RestClient<GroupsApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public GroupsRestClient(HomeServerConnectionConfig hsConfig) { public GroupsRestClient(SessionParams sessionParams) {
super(hsConfig, GroupsApi.class, RestClient.URI_API_PREFIX_PATH_R0, false); super(sessionParams, GroupsApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
} }


protected GroupsRestClient(GroupsApi api) { protected GroupsRestClient(GroupsApi api) {

View File

@ -23,23 +23,22 @@ import android.text.TextUtils;


import com.google.gson.JsonObject; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.LoginApi; 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.ApiCallback;
import im.vector.matrix.android.internal.legacy.rest.callback.RestAdapterCallback; 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.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.LoginFlow;
import im.vector.matrix.android.internal.legacy.rest.model.login.LoginFlowResponse; 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.LoginParams;
import im.vector.matrix.android.internal.legacy.rest.model.login.PasswordLoginParams; 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.RegistrationParams;
import im.vector.matrix.android.internal.legacy.rest.model.login.TokenLoginParams; import im.vector.matrix.android.internal.legacy.rest.model.login.TokenLoginParams;

import java.util.List;
import java.util.UUID;

import retrofit2.Response; import retrofit2.Response;


/** /**
@ -59,10 +58,10 @@ public class LoginRestClient extends RestClient<LoginApi> {
/** /**
* Public constructor. * Public constructor.
* *
* @param hsConfig the home server connection config * @param sessionParams the session connection data
*/ */
public LoginRestClient(HomeServerConnectionConfig hsConfig) { public LoginRestClient(SessionParams sessionParams) {
super(hsConfig, LoginApi.class, "", false); super(sessionParams, LoginApi.class, "", false);
} }


/** /**

View File

@ -18,7 +18,11 @@ package im.vector.matrix.android.internal.legacy.rest.client;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.TextUtils; 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.RestClient;
import im.vector.matrix.android.internal.legacy.data.store.IMXStore; import im.vector.matrix.android.internal.legacy.data.store.IMXStore;
import im.vector.matrix.android.internal.legacy.rest.api.MediaScanApi; 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.MediaScanResult;
import im.vector.matrix.android.internal.legacy.rest.model.crypto.EncryptedBodyFileInfo; import im.vector.matrix.android.internal.legacy.rest.model.crypto.EncryptedBodyFileInfo;
import im.vector.matrix.android.internal.legacy.util.JsonUtils; 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; import retrofit2.Call;


/** /**
@ -49,8 +49,8 @@ public class MediaScanRestClient extends RestClient<MediaScanApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public MediaScanRestClient(HomeServerConnectionConfig hsConfig) { public MediaScanRestClient(SessionParams sessionParams) {
super(hsConfig, MediaScanApi.class, RestClient.URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE, false, EndPointServer.ANTIVIRUS_SERVER); super(sessionParams, MediaScanApi.class, RestClient.URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE, false, EndPointServer.ANTIVIRUS_SERVER);
} }


/** /**

View File

@ -16,7 +16,7 @@
*/ */
package im.vector.matrix.android.internal.legacy.rest.client; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.PresenceApi; import im.vector.matrix.android.internal.legacy.rest.api.PresenceApi;
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback; import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
@ -31,8 +31,8 @@ public class PresenceRestClient extends RestClient<PresenceApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public PresenceRestClient(HomeServerConnectionConfig hsConfig) { public PresenceRestClient(SessionParams sessionParams) {
super(hsConfig, PresenceApi.class, RestClient.URI_API_PREFIX_PATH_R0, false); super(sessionParams, PresenceApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
} }


/** /**

View File

@ -18,7 +18,10 @@ package im.vector.matrix.android.internal.legacy.rest.client;


import android.text.TextUtils; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.ProfileApi; import im.vector.matrix.android.internal.legacy.rest.api.ProfileApi;
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback; 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.RequestPhoneNumberValidationResponse;
import im.vector.matrix.android.internal.legacy.rest.model.ThreePidCreds; 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.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.AccountThreePidsResponse;
import im.vector.matrix.android.internal.legacy.rest.model.pid.AddThreePidsParams; 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.DeleteThreePidParams;
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThirdPartyIdentifier; import im.vector.matrix.android.internal.legacy.rest.model.pid.ThirdPartyIdentifier;
import im.vector.matrix.android.internal.legacy.rest.model.pid.ThreePid; import im.vector.matrix.android.internal.legacy.rest.model.pid.ThreePid;

import java.util.List;
import java.util.Map;

import retrofit2.Response; import retrofit2.Response;


/** /**
@ -57,8 +53,8 @@ public class ProfileRestClient extends RestClient<ProfileApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public ProfileRestClient(HomeServerConnectionConfig hsConfig) { public ProfileRestClient(SessionParams sessionParams) {
super(hsConfig, ProfileApi.class, "", false); super(sessionParams, ProfileApi.class, "", false);
} }


/** /**
@ -102,7 +98,7 @@ public class ProfileRestClient extends RestClient<ProfileApi> {


// don't retry if the network comes back // don't retry if the network comes back
// let the user chooses what he want to do // 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() { .enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
@ -150,7 +146,7 @@ public class ProfileRestClient extends RestClient<ProfileApi> {
User user = new User(); User user = new User();
user.setAvatarUrl(newUrl); user.setAvatarUrl(newUrl);


mApi.avatarUrl(mCredentials.userId, user) mApi.avatarUrl(mCredentials.getUserId(), user)
.enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() { .enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { 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. * List all 3PIDs linked to the Matrix user account.
* *
@ -447,14 +418,14 @@ public class ProfileRestClient extends RestClient<ProfileApi> {


AddThreePidsParams params = new AddThreePidsParams(); AddThreePidsParams params = new AddThreePidsParams();
params.three_pid_creds = new ThreePidCreds(); params.three_pid_creds = new ThreePidCreds();

String identityServerHost = mHsConfig.getIdentityServerUri().toString(); String identityServerHost = mHsConfig.getIdentityServerUri().toString();
if (identityServerHost.startsWith("http://")) { if (identityServerHost != null) {
identityServerHost = identityServerHost.substring("http://".length()); if (identityServerHost.startsWith("http://")) {
} else if (identityServerHost.startsWith("https://")) { identityServerHost = identityServerHost.substring("http://".length());
identityServerHost = identityServerHost.substring("https://".length()); } else if (identityServerHost.startsWith("https://")) {
identityServerHost = identityServerHost.substring("https://".length());
}
} }

params.three_pid_creds.id_server = identityServerHost; params.three_pid_creds.id_server = identityServerHost;
params.three_pid_creds.sid = pid.sid; params.three_pid_creds.sid = pid.sid;
params.three_pid_creds.client_secret = pid.clientSecret; params.three_pid_creds.client_secret = pid.clientSecret;

View File

@ -16,7 +16,7 @@
*/ */
package im.vector.matrix.android.internal.legacy.rest.client; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.PushRulesApi; import im.vector.matrix.android.internal.legacy.rest.api.PushRulesApi;
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback; import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback;
@ -29,8 +29,8 @@ public class PushRulesRestClient extends RestClient<PushRulesApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public PushRulesRestClient(HomeServerConnectionConfig hsConfig) { public PushRulesRestClient(SessionParams sessionParams) {
super(hsConfig, PushRulesApi.class, RestClient.URI_API_PREFIX_PATH_R0, false); super(sessionParams, PushRulesApi.class, RestClient.URI_API_PREFIX_PATH_R0, false);
} }


/** /**

View File

@ -17,7 +17,9 @@


package im.vector.matrix.android.internal.legacy.rest.client; 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.RestClient;
import im.vector.matrix.android.internal.legacy.data.Pusher; import im.vector.matrix.android.internal.legacy.data.Pusher;
import im.vector.matrix.android.internal.legacy.rest.api.PushersApi; 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.callback.RestAdapterCallback;
import im.vector.matrix.android.internal.legacy.rest.model.PushersResponse; import im.vector.matrix.android.internal.legacy.rest.model.PushersResponse;


import java.util.HashMap;

/** /**
* REST client for the Pushers API. * 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 PUSHER_KIND_HTTP = "http";
private static final String DATA_KEY_HTTP_URL = "url"; private static final String DATA_KEY_HTTP_URL = "url";


public PushersRestClient(HomeServerConnectionConfig hsConfig) { public PushersRestClient(SessionParams sessionParams) {
super(hsConfig, PushersApi.class, RestClient.URI_API_PREFIX_PATH_R0, true); super(sessionParams, PushersApi.class, RestClient.URI_API_PREFIX_PATH_R0, true);
} }


/** /**

View File

@ -24,7 +24,10 @@ import android.text.TextUtils;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; 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.RestClient;
import im.vector.matrix.android.internal.legacy.data.RoomState; import im.vector.matrix.android.internal.legacy.data.RoomState;
import im.vector.matrix.android.internal.legacy.data.timeline.EventTimeline; 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.message.Message;
import im.vector.matrix.android.internal.legacy.rest.model.sync.RoomResponse; 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. * Class used to make requests to the rooms API.
*/ */
public class RoomsRestClient extends RestClient<RoomsApi> { public class RoomsRestClient extends RestClient<RoomsApi> {
private static final String LOG_TAG = RoomsRestClient.class.getSimpleName();


public static final int DEFAULT_MESSAGES_PAGINATION_LIMIT = 30; public static final int DEFAULT_MESSAGES_PAGINATION_LIMIT = 30;


@ -70,8 +69,8 @@ public class RoomsRestClient extends RestClient<RoomsApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public RoomsRestClient(HomeServerConnectionConfig hsConfig) { public RoomsRestClient(SessionParams sessionParams) {
super(hsConfig, RoomsApi.class, RestClient.URI_API_PREFIX_PATH_R0, false); 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<>(); Map<String, Object> hashMap = new HashMap<>();
hashMap.put("order", order); 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() { .enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { 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) { public void removeTag(final String roomId, final String tag, final ApiCallback<Void> callback) {
final String description = "removeTag : roomId " + roomId + " - tag " + tag; 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() { .enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {
@ -898,7 +897,7 @@ public class RoomsRestClient extends RestClient<RoomsApi> {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.put(AccountDataRestClient.ACCOUNT_DATA_KEY_URL_PREVIEW_DISABLE, !status); 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() { .enqueue(new RestAdapterCallback<Void>(description, mUnsentEventsManager, callback, new RestAdapterCallback.RequestRetryCallBack() {
@Override @Override
public void onRetry() { public void onRetry() {

View File

@ -17,7 +17,14 @@
*/ */
package im.vector.matrix.android.internal.legacy.rest.client; 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.RestClient;
import im.vector.matrix.android.internal.legacy.rest.api.ThirdPidApi; import im.vector.matrix.android.internal.legacy.rest.api.ThirdPidApi;
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback; 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.HttpError;
import im.vector.matrix.android.internal.legacy.rest.model.HttpException; import im.vector.matrix.android.internal.legacy.rest.model.HttpException;
import im.vector.matrix.android.internal.legacy.rest.model.pid.PidResponse; 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.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@ -46,8 +45,8 @@ public class ThirdPidRestClient extends RestClient<ThirdPidApi> {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public ThirdPidRestClient(HomeServerConnectionConfig hsConfig) { public ThirdPidRestClient(SessionParams sessionParams) {
super(hsConfig, ThirdPidApi.class, URI_API_PREFIX_IDENTITY, false, true); super(sessionParams, ThirdPidApi.class, URI_API_PREFIX_IDENTITY, false, true);
} }


/** /**

View File

@ -22,19 +22,20 @@ import android.text.TextUtils;


import com.google.gson.annotations.SerializedName; 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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 class CreateRoomParams {


public static final String PRESET_PRIVATE_CHAT = "private_chat"; public static final String PRESET_PRIVATE_CHAT = "private_chat";
@ -225,7 +226,7 @@ public class CreateRoomParams {
* *
* @param ids the participant ids to add. * @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) { for (String id : ids) {
if (android.util.Patterns.EMAIL_ADDRESS.matcher(id).matches()) { if (android.util.Patterns.EMAIL_ADDRESS.matcher(id).matches()) {
if (null == invite3pids) { if (null == invite3pids) {
@ -233,14 +234,14 @@ public class CreateRoomParams {
} }


Invite3Pid pid = new Invite3Pid(); Invite3Pid pid = new Invite3Pid();
pid.id_server = hsConfig.getIdentityServerUri().getHost(); pid.id_server = homeServerConnectionConfig.getIdentityServerUri().getHost();
pid.medium = ThreePid.MEDIUM_EMAIL; pid.medium = ThreePid.MEDIUM_EMAIL;
pid.address = id; pid.address = id;


invite3pids.add(pid); invite3pids.add(pid);
} else if (MXPatterns.isUserId(id)) { } else if (MXPatterns.isUserId(id)) {
// do not invite oneself // do not invite oneself
if (!TextUtils.equals(hsConfig.getCredentials().userId, id)) { if (!TextUtils.equals(credentials.getUserId(), id)) {
if (null == invitedUserIds) { if (null == invitedUserIds) {
invitedUserIds = new ArrayList<>(); invitedUserIds = new ArrayList<>();
} }

View File

@ -16,7 +16,7 @@
package im.vector.matrix.android.internal.legacy.rest.model; package im.vector.matrix.android.internal.legacy.rest.model;


/** /**
* 3 pid credentials * 3 pid getCredentials
*/ */
public class ThreePidCreds { public class ThreePidCreds {



View File

@ -21,7 +21,7 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;


/** /**
* The user's credentials. * The user's getCredentials.
*/ */
public class Credentials { public class Credentials {
public String userId; public String userId;

View File

@ -23,7 +23,7 @@ import im.vector.matrix.android.internal.legacy.rest.model.ThreePidCreds;
*/ */
public class AddThreePidsParams { public class AddThreePidsParams {


// the 3rd party id credentials // the 3rd party id getCredentials
public ThreePidCreds three_pid_creds; public ThreePidCreds three_pid_creds;


// true when the email has been binded. // true when the email has been binded.

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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];
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -146,7 +146,7 @@ public class BingRulesManager {
public BingRulesManager(MXSession session, NetworkConnectivityReceiver networkConnectivityReceiver) { public BingRulesManager(MXSession session, NetworkConnectivityReceiver networkConnectivityReceiver) {
mSession = session; mSession = session;
mApiClient = session.getBingRulesApiClient(); mApiClient = session.getBingRulesApiClient();
mMyUserId = session.getCredentials().userId; mMyUserId = session.getCredentials().getUserId();
mDataHandler = session.getDataHandler(); mDataHandler = session.getDataHandler();


mNetworkListener = new IMXNetworkEventListener() { mNetworkListener = new IMXNetworkEventListener() {

View File

@ -19,7 +19,8 @@ package im.vector.matrix.android.internal.legacy.util;


import android.support.annotation.Nullable; 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; import im.vector.matrix.android.internal.legacy.RestClient;


/** /**
@ -39,6 +40,7 @@ public class ContentManager {


// HS config // HS config
private final HomeServerConnectionConfig mHsConfig; private final HomeServerConnectionConfig mHsConfig;
private final Credentials mCredentials;


// the unsent events Manager // the unsent events Manager
private final UnsentEventsManager mUnsentEventsManager; private final UnsentEventsManager mUnsentEventsManager;
@ -53,8 +55,9 @@ public class ContentManager {
* @param hsConfig the HomeserverConnectionConfig to use * @param hsConfig the HomeserverConnectionConfig to use
* @param unsentEventsManager the unsent events manager * @param unsentEventsManager the unsent events manager
*/ */
public ContentManager(HomeServerConnectionConfig hsConfig, UnsentEventsManager unsentEventsManager) { public ContentManager(HomeServerConnectionConfig hsConfig, Credentials credentials, UnsentEventsManager unsentEventsManager) {
mHsConfig = hsConfig; mHsConfig = hsConfig;
mCredentials = credentials;
mUnsentEventsManager = unsentEventsManager; mUnsentEventsManager = unsentEventsManager;
// The AV scanner is disabled by default // The AV scanner is disabled by default
configureAntiVirusScanner(false); configureAntiVirusScanner(false);
@ -73,7 +76,7 @@ public class ContentManager {
if (isEnabled) { if (isEnabled) {
mDownloadUrlPrefix = mHsConfig.getAntiVirusServerUri().toString() + "/" + RestClient.URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE; mDownloadUrlPrefix = mHsConfig.getAntiVirusServerUri().toString() + "/" + RestClient.URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE;
} else { } 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 mHsConfig;
} }


/**
* @return the getCredentials.
*/
public Credentials getCredentials() {
return mCredentials;
}

/** /**
* @return the unsent events manager * @return the unsent events manager
*/ */
@ -210,7 +220,7 @@ public class ContentManager {
// Caution: identicon has no thumbnail path. // Caution: identicon has no thumbnail path.
if (mediaServerAndId.startsWith(MATRIX_CONTENT_IDENTICON_PREFIX)) { if (mediaServerAndId.startsWith(MATRIX_CONTENT_IDENTICON_PREFIX)) {
// identicon url still go to the media repo since they dont need virus scanning // identicon url still go to the media repo since they dont need virus scanning
url = mHsConfig.getHomeserverUri().toString() + URI_PREFIX_CONTENT_API; url = mHsConfig.getHomeServerUri().toString() + URI_PREFIX_CONTENT_API;
} else { } else {
// Use the current download url prefix to take into account a potential antivirus scanner // Use the current download url prefix to take into account a potential antivirus scanner
url = mDownloadUrlPrefix + "thumbnail/"; url = mDownloadUrlPrefix + "thumbnail/";

View File

@ -97,7 +97,7 @@ public class EventUtils {


Room room = session.getDataHandler().getRoom(event.roomId); Room room = session.getDataHandler().getRoom(event.roomId);
return RoomDirectoryVisibility.DIRECTORY_VISIBILITY_PRIVATE.equals(room.getVisibility()) return RoomDirectoryVisibility.DIRECTORY_VISIBILITY_PRIVATE.equals(room.getVisibility())
&& !TextUtils.equals(event.getSender(), session.getCredentials().userId); && !TextUtils.equals(event.getSender(), session.getCredentials().getUserId());
} }


/** /**

View File

@ -26,6 +26,12 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; 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.BooleanDeserializer;
import im.vector.matrix.android.internal.legacy.rest.json.ConditionDeserializer; import im.vector.matrix.android.internal.legacy.rest.json.ConditionDeserializer;
import im.vector.matrix.android.internal.legacy.rest.json.MatrixFieldNamingStrategy; 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.message.VideoMessage;
import im.vector.matrix.android.internal.legacy.rest.model.pid.RoomThirdPartyInvite; 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. * Static methods for converting json into objects.
*/ */
@ -527,6 +528,16 @@ public class JsonUtils {
return new JsonObject(); 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. * Convert an Message instance into a Json object.
* *

View File

@ -20,15 +20,6 @@ package im.vector.matrix.android.internal.legacy.util;
import android.content.Context; import android.content.Context;
import android.text.TextUtils; 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.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -38,6 +29,14 @@ import java.util.Random;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; 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; import retrofit2.Response;


/** /**
@ -405,8 +404,7 @@ public class UnsentEventsManager {
} }


if (null != exception) { if (null != exception) {
UnrecognizedCertificateException unrecCertEx = CertUtil.getCertificateException(exception); UnrecognizedCertificateException unrecCertEx = CertUtil.INSTANCE.getCertificateException(exception);

if (null != unrecCertEx) { if (null != unrecCertEx) {
Log.e(LOG_TAG, "## onEventSendingFailed() : SSL issue detected"); Log.e(LOG_TAG, "## onEventSendingFailed() : SSL issue detected");
mDataHandler.onSSLCertificateError(unrecCertEx); mDataHandler.onSSLCertificateError(unrecCertEx);

View File

@ -1,18 +1,18 @@
package im.vector.matrix.android.internal.network 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.Interceptor
import okhttp3.Response import okhttp3.Response


class AccessTokenInterceptor(private val credentialsStore: CredentialsStore) : Interceptor { class AccessTokenInterceptor(private val sessionParamsStore: SessionParamsStore) : Interceptor {


override fun intercept(chain: Interceptor.Chain): Response { override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request() var request = chain.request()
val newRequestBuilder = request.newBuilder() val newRequestBuilder = request.newBuilder()
// Add the access token to all requests if it is set // Add the access token to all requests if it is set
val credentials = credentialsStore.get() val sessionParams = sessionParamsStore.get()
credentials?.let { sessionParams?.let {
newRequestBuilder.addHeader("Authorization", "Bearer " + it.accessToken) newRequestBuilder.addHeader("Authorization", "Bearer " + it.credentials.accessToken)
} }
request = newRequestBuilder.build() request = newRequestBuilder.build()
return chain.proceed(request) return chain.proceed(request)

View File

@ -1,9 +1,9 @@
package im.vector.matrix.android.internal.network package im.vector.matrix.android.internal.network


import arrow.core.Either
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.failure.MatrixError import im.vector.matrix.android.api.failure.MatrixError
import im.vector.matrix.android.internal.util.Either
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Deferred import kotlinx.coroutines.Deferred
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext

View File

@ -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
}
}

View File

@ -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
}

}

View File

@ -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()
}
}

View File

@ -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
}
}

View File

@ -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)

View File

@ -1,7 +1,7 @@
package im.vector.matrix.android.internal.session 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.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.di.SessionModule
import im.vector.matrix.android.internal.events.sync.SyncModule import im.vector.matrix.android.internal.events.sync.SyncModule
import im.vector.matrix.android.internal.events.sync.Synchronizer 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.getKoin
import org.koin.standalone.inject 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 synchronizer by inject<Synchronizer>()
private val scope: Scope private val scope: Scope


init { init {
val sessionModule = SessionModule(homeServerConnectionConfig) val sessionModule = SessionModule(sessionParams)
val syncModule = SyncModule() val syncModule = SyncModule()
StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule)) StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule))
scope = getKoin().createScope(SCOPE) scope = getKoin().createScope(SCOPE)

View File

@ -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))