diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java b/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java
deleted file mode 100644
index 6da4de8c3..000000000
--- a/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.nextcloud.talk.dagger.modules;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.github.aurae.retrofit2.LoganSquareConverterFactory;
-import com.nextcloud.talk.BuildConfig;
-import com.nextcloud.talk.R;
-import com.nextcloud.talk.api.NcApi;
-import com.nextcloud.talk.application.NextcloudTalkApplication;
-import com.nextcloud.talk.users.UserManager;
-import com.nextcloud.talk.utils.ApiUtils;
-import com.nextcloud.talk.utils.LoggingUtils;
-import com.nextcloud.talk.utils.preferences.AppPreferences;
-import com.nextcloud.talk.utils.ssl.KeyManager;
-import com.nextcloud.talk.utils.ssl.SSLSocketFactoryCompat;
-import com.nextcloud.talk.utils.ssl.TrustManager;
-
-import java.io.IOException;
-import java.net.CookieManager;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.nio.charset.StandardCharsets;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.util.concurrent.TimeUnit;
-
-import javax.inject.Singleton;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.X509KeyManager;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import dagger.Module;
-import dagger.Provides;
-import io.reactivex.schedulers.Schedulers;
-import okhttp3.Authenticator;
-import okhttp3.Cache;
-import okhttp3.Credentials;
-import okhttp3.Dispatcher;
-import okhttp3.Interceptor;
-import okhttp3.JavaNetCookieJar;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-import okhttp3.Route;
-import okhttp3.internal.tls.OkHostnameVerifier;
-import okhttp3.logging.HttpLoggingInterceptor;
-import retrofit2.Retrofit;
-import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
-
-@Module(includes = DatabaseModule.class)
-public class RestModule {
-
- private static final String TAG = "RestModule";
- private final Context context;
-
- public RestModule(Context context) {
- this.context = context;
- }
-
- @Singleton
- @Provides
- NcApi provideNcApi(Retrofit retrofit) {
- return retrofit.create(NcApi.class);
- }
-
- @Singleton
- @Provides
- Proxy provideProxy(AppPreferences appPreferences) {
- if (!TextUtils.isEmpty(appPreferences.getProxyType()) && !"No proxy".equals(appPreferences.getProxyType())
- && !TextUtils.isEmpty(appPreferences.getProxyHost())) {
- GetProxyRunnable getProxyRunnable = new GetProxyRunnable(appPreferences);
- Thread getProxyThread = new Thread(getProxyRunnable);
- getProxyThread.start();
- try {
- getProxyThread.join();
- return getProxyRunnable.getProxyValue();
- } catch (InterruptedException e) {
- Log.e(TAG, "Failed to join the thread while getting proxy: " + e.getLocalizedMessage());
- return Proxy.NO_PROXY;
- }
- } else {
- return Proxy.NO_PROXY;
- }
- }
-
- @Singleton
- @Provides
- Retrofit provideRetrofit(OkHttpClient httpClient) {
- Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
- .client(httpClient)
- .baseUrl("https://nextcloud.com")
- .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
- .addConverterFactory(LoganSquareConverterFactory.create());
-
- return retrofitBuilder.build();
- }
-
- @Singleton
- @Provides
- TrustManager provideTrustManager() {
- return new TrustManager();
- }
-
- @Singleton
- @Provides
- KeyManager provideKeyManager(AppPreferences appPreferences, UserManager userManager) {
- KeyStore keyStore = null;
- try {
- keyStore = KeyStore.getInstance("AndroidKeyStore");
- keyStore.load(null);
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- kmf.init(keyStore, null);
- X509KeyManager origKm = (X509KeyManager) kmf.getKeyManagers()[0];
- return new KeyManager(origKm, userManager, appPreferences);
- } catch (KeyStoreException e) {
- Log.e(TAG, "KeyStoreException " + e.getLocalizedMessage());
- } catch (CertificateException e) {
- Log.e(TAG, "CertificateException " + e.getLocalizedMessage());
- } catch (NoSuchAlgorithmException e) {
- Log.e(TAG, "NoSuchAlgorithmException " + e.getLocalizedMessage());
- } catch (IOException e) {
- Log.e(TAG, "IOException " + e.getLocalizedMessage());
- } catch (UnrecoverableKeyException e) {
- Log.e(TAG, "UnrecoverableKeyException " + e.getLocalizedMessage());
- }
-
- return null;
- }
-
- @Singleton
- @Provides
- SSLSocketFactoryCompat provideSslSocketFactoryCompat(KeyManager keyManager, TrustManager
- trustManager) {
- return new SSLSocketFactoryCompat(keyManager, trustManager);
- }
-
- @Singleton
- @Provides
- CookieManager provideCookieManager() {
- return new CookieManager();
- }
-
- @Singleton
- @Provides
- Cache provideCache() {
- int cacheSize = 128 * 1024 * 1024; // 128 MB
-
- return new Cache(NextcloudTalkApplication.Companion.getSharedApplication().getCacheDir(), cacheSize);
- }
-
- @Singleton
- @Provides
- Dispatcher provideDispatcher() {
- Dispatcher dispatcher = new Dispatcher();
- dispatcher.setMaxRequestsPerHost(100);
- dispatcher.setMaxRequests(100);
- return dispatcher;
- }
-
- @Singleton
- @Provides
- OkHttpClient provideHttpClient(Proxy proxy, AppPreferences appPreferences,
- TrustManager trustManager,
- SSLSocketFactoryCompat sslSocketFactoryCompat, Cache cache,
- CookieManager cookieManager, Dispatcher dispatcher) {
- OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
-
- httpClient.retryOnConnectionFailure(true);
- httpClient.connectTimeout(45, TimeUnit.SECONDS);
- httpClient.readTimeout(45, TimeUnit.SECONDS);
- httpClient.writeTimeout(45, TimeUnit.SECONDS);
-
- httpClient.cookieJar(new JavaNetCookieJar(cookieManager));
- httpClient.cache(cache);
-
- // Trust own CA and all self-signed certs
- httpClient.sslSocketFactory(sslSocketFactoryCompat, trustManager);
- httpClient.retryOnConnectionFailure(true);
- httpClient.hostnameVerifier(trustManager.getHostnameVerifier(OkHostnameVerifier.INSTANCE));
-
- httpClient.dispatcher(dispatcher);
- if (!Proxy.NO_PROXY.equals(proxy)) {
- httpClient.proxy(proxy);
-
- if (appPreferences.getProxyCredentials() &&
- !TextUtils.isEmpty(appPreferences.getProxyUsername()) &&
- !TextUtils.isEmpty(appPreferences.getProxyPassword())) {
- httpClient.proxyAuthenticator(new HttpAuthenticator(
- Credentials.basic(
- appPreferences.getProxyUsername(),
- appPreferences.getProxyPassword(),
- StandardCharsets.UTF_8),
- "Proxy-Authorization"));
- }
- }
-
- httpClient.addInterceptor(new HeadersInterceptor());
-
- if (BuildConfig.DEBUG && !context.getResources().getBoolean(R.bool.nc_is_debug)) {
- HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
- loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
- loggingInterceptor.redactHeader("Authorization");
- loggingInterceptor.redactHeader("Proxy-Authorization");
- httpClient.addInterceptor(loggingInterceptor);
- } else if (context.getResources().getBoolean(R.bool.nc_is_debug)) {
- HttpLoggingInterceptor.Logger fileLogger =
- s -> LoggingUtils.INSTANCE.writeLogEntryToFile(context, s);
- HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(fileLogger);
- loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
- loggingInterceptor.redactHeader("Authorization");
- loggingInterceptor.redactHeader("Proxy-Authorization");
- httpClient.addInterceptor(loggingInterceptor);
- }
-
- return httpClient.build();
- }
-
- public static class HeadersInterceptor implements Interceptor {
-
- @NonNull
- @Override
- public Response intercept(@NonNull Chain chain) throws IOException {
- Request original = chain.request();
- Request request = original.newBuilder()
- .header("User-Agent", ApiUtils.getUserAgent())
- .header("Accept", "application/json")
- .header("OCS-APIRequest", "true")
- .header("ngrok-skip-browser-warning", "true")
- .method(original.method(), original.body())
- .build();
-
- return chain.proceed(request);
- }
- }
-
- public static class HttpAuthenticator implements Authenticator {
-
- private String credentials;
- private String authenticatorType;
-
- public HttpAuthenticator(@NonNull String credentials, @NonNull String authenticatorType) {
- this.credentials = credentials;
- this.authenticatorType = authenticatorType;
- }
-
- @Nullable
- @Override
- public Request authenticate(@Nullable Route route, @NonNull Response response) {
- if (response.request().header(authenticatorType) != null) {
- return null;
- }
-
- Response countedResponse = response;
-
- int attemptsCount = 0;
-
- while ((countedResponse = countedResponse.priorResponse()) != null) {
- attemptsCount++;
- if (attemptsCount == 3) {
- return null;
- }
- }
-
- return response.request().newBuilder()
- .header(authenticatorType, credentials)
- .build();
- }
- }
-
- private class GetProxyRunnable implements Runnable {
- private volatile Proxy proxy;
- private AppPreferences appPreferences;
-
- GetProxyRunnable(AppPreferences appPreferences) {
- this.appPreferences = appPreferences;
- }
-
- @Override
- public void run() {
- if (Proxy.Type.valueOf(appPreferences.getProxyType()) == Proxy.Type.SOCKS) {
- proxy = new Proxy(Proxy.Type.valueOf(appPreferences.getProxyType()),
- InetSocketAddress.createUnresolved(appPreferences.getProxyHost(), Integer.parseInt(
- appPreferences.getProxyPort())));
- } else {
- proxy = new Proxy(Proxy.Type.valueOf(appPreferences.getProxyType()),
- new InetSocketAddress(appPreferences.getProxyHost(),
- Integer.parseInt(appPreferences.getProxyPort())));
- }
- }
-
- Proxy getProxyValue() {
- return proxy;
- }
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.kt
new file mode 100644
index 000000000..cb1760bc2
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.kt
@@ -0,0 +1,290 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.nextcloud.talk.dagger.modules
+
+import android.content.Context
+import android.text.TextUtils
+import android.util.Log
+import com.github.aurae.retrofit2.LoganSquareConverterFactory
+import com.nextcloud.talk.BuildConfig
+import com.nextcloud.talk.R
+import com.nextcloud.talk.api.NcApi
+import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
+import com.nextcloud.talk.users.UserManager
+import com.nextcloud.talk.utils.ApiUtils.userAgent
+import com.nextcloud.talk.utils.LoggingUtils.writeLogEntryToFile
+import com.nextcloud.talk.utils.preferences.AppPreferences
+import com.nextcloud.talk.utils.ssl.KeyManager
+import com.nextcloud.talk.utils.ssl.SSLSocketFactoryCompat
+import com.nextcloud.talk.utils.ssl.TrustManager
+import dagger.Module
+import dagger.Provides
+import io.reactivex.schedulers.Schedulers
+import okhttp3.Authenticator
+import okhttp3.Cache
+import okhttp3.Credentials.basic
+import okhttp3.Dispatcher
+import okhttp3.Interceptor
+import okhttp3.Interceptor.Chain
+import okhttp3.JavaNetCookieJar
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.Response
+import okhttp3.Route
+import okhttp3.internal.tls.OkHostnameVerifier
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
+import java.io.IOException
+import java.net.CookieManager
+import java.net.InetSocketAddress
+import java.net.Proxy
+import java.nio.charset.StandardCharsets
+import java.security.KeyStore
+import java.security.KeyStoreException
+import java.security.NoSuchAlgorithmException
+import java.security.UnrecoverableKeyException
+import java.security.cert.CertificateException
+import java.util.concurrent.TimeUnit
+import javax.inject.Singleton
+import javax.net.ssl.KeyManagerFactory
+import javax.net.ssl.X509KeyManager
+import kotlin.concurrent.Volatile
+
+@Module(includes = [DatabaseModule::class])
+class RestModule(private val context: Context) {
+ @Singleton
+ @Provides
+ fun provideNcApi(retrofit: Retrofit): NcApi {
+ return retrofit.create(NcApi::class.java)
+ }
+
+ @Singleton
+ @Provides
+ fun provideProxy(appPreferences: AppPreferences): Proxy? {
+ return if (!TextUtils.isEmpty(appPreferences.getProxyType()) && "No proxy" != appPreferences.getProxyType() &&
+ !TextUtils.isEmpty(appPreferences.getProxyHost())
+ ) {
+ val getProxyRunnable = GetProxyRunnable(appPreferences)
+ val getProxyThread = Thread(getProxyRunnable)
+ getProxyThread.start()
+ try {
+ getProxyThread.join()
+ getProxyRunnable.proxyValue
+ } catch (e: InterruptedException) {
+ Log.e(TAG, "Failed to join the thread while getting proxy: " + e.localizedMessage)
+ Proxy.NO_PROXY
+ }
+ } else {
+ Proxy.NO_PROXY
+ }
+ }
+
+ @Singleton
+ @Provides
+ fun provideRetrofit(httpClient: OkHttpClient?): Retrofit {
+ val retrofitBuilder = Retrofit.Builder()
+ .client(httpClient!!)
+ .baseUrl("https://nextcloud.com")
+ .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
+ .addConverterFactory(LoganSquareConverterFactory.create())
+ return retrofitBuilder.build()
+ }
+
+ @Singleton
+ @Provides
+ fun provideTrustManager(): TrustManager {
+ return TrustManager()
+ }
+
+ @Singleton
+ @Provides
+ fun provideKeyManager(appPreferences: AppPreferences?, userManager: UserManager?): KeyManager? {
+ val keyStore: KeyStore?
+ try {
+ keyStore = KeyStore.getInstance("AndroidKeyStore")
+ keyStore.load(null)
+ val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
+ kmf.init(keyStore, null)
+ val origKm = kmf.keyManagers[0] as X509KeyManager
+ return KeyManager(origKm, userManager, appPreferences)
+ } catch (e: KeyStoreException) {
+ Log.e(TAG, "KeyStoreException " + e.localizedMessage)
+ } catch (e: CertificateException) {
+ Log.e(TAG, "CertificateException " + e.localizedMessage)
+ } catch (e: NoSuchAlgorithmException) {
+ Log.e(TAG, "NoSuchAlgorithmException " + e.localizedMessage)
+ } catch (e: IOException) {
+ Log.e(TAG, "IOException " + e.localizedMessage)
+ } catch (e: UnrecoverableKeyException) {
+ Log.e(TAG, "UnrecoverableKeyException " + e.localizedMessage)
+ }
+ return null
+ }
+
+ @Singleton
+ @Provides
+ fun provideSslSocketFactoryCompat(keyManager: KeyManager?, trustManager: TrustManager?): SSLSocketFactoryCompat {
+ return SSLSocketFactoryCompat(keyManager, trustManager!!)
+ }
+
+ @Singleton
+ @Provides
+ fun provideCookieManager(): CookieManager {
+ return CookieManager()
+ }
+
+ @Singleton
+ @Provides
+ fun provideCache(): Cache {
+ val cacheSize = 128 * 1024 * 1024 // 128 MB
+ return Cache(sharedApplication!!.cacheDir, cacheSize.toLong())
+ }
+
+ @Singleton
+ @Provides
+ fun provideDispatcher(): Dispatcher {
+ val dispatcher = Dispatcher()
+ dispatcher.maxRequestsPerHost = 100
+ dispatcher.maxRequests = 100
+ return dispatcher
+ }
+
+ @Singleton
+ @Provides
+ fun provideHttpClient(
+ proxy: Proxy?,
+ appPreferences: AppPreferences,
+ trustManager: TrustManager,
+ sslSocketFactoryCompat: SSLSocketFactoryCompat?,
+ cache: Cache?,
+ cookieManager: CookieManager?,
+ dispatcher: Dispatcher?
+ ): OkHttpClient {
+ val httpClient = OkHttpClient.Builder()
+ httpClient.retryOnConnectionFailure(true)
+ httpClient.connectTimeout(45, TimeUnit.SECONDS)
+ httpClient.readTimeout(45, TimeUnit.SECONDS)
+ httpClient.writeTimeout(45, TimeUnit.SECONDS)
+ httpClient.cookieJar(JavaNetCookieJar(cookieManager!!))
+ httpClient.cache(cache)
+
+ // Trust own CA and all self-signed certs
+ httpClient.sslSocketFactory(sslSocketFactoryCompat!!, trustManager)
+ httpClient.retryOnConnectionFailure(true)
+ httpClient.hostnameVerifier(trustManager.getHostnameVerifier(OkHostnameVerifier))
+ httpClient.dispatcher(dispatcher!!)
+ if (Proxy.NO_PROXY != proxy) {
+ httpClient.proxy(proxy)
+ if (appPreferences.getProxyCredentials() &&
+ !TextUtils.isEmpty(appPreferences.getProxyUsername()) &&
+ !TextUtils.isEmpty(appPreferences.getProxyPassword())
+ ) {
+ httpClient.proxyAuthenticator(
+ HttpAuthenticator(
+ basic(
+ appPreferences.getProxyUsername(),
+ appPreferences.getProxyPassword(),
+ StandardCharsets.UTF_8
+ ),
+ "Proxy-Authorization"
+ )
+ )
+ }
+ }
+ httpClient.addInterceptor(HeadersInterceptor())
+ if (BuildConfig.DEBUG && !context.resources.getBoolean(R.bool.nc_is_debug)) {
+ val loggingInterceptor = HttpLoggingInterceptor()
+ loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
+ loggingInterceptor.redactHeader("Authorization")
+ loggingInterceptor.redactHeader("Proxy-Authorization")
+ httpClient.addInterceptor(loggingInterceptor)
+ } else if (context.resources.getBoolean(R.bool.nc_is_debug)) {
+ val fileLogger = HttpLoggingInterceptor.Logger { s: String? -> writeLogEntryToFile(context, s!!) }
+ val loggingInterceptor = HttpLoggingInterceptor(fileLogger)
+ loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
+ loggingInterceptor.redactHeader("Authorization")
+ loggingInterceptor.redactHeader("Proxy-Authorization")
+ httpClient.addInterceptor(loggingInterceptor)
+ }
+ return httpClient.build()
+ }
+
+ class HeadersInterceptor : Interceptor {
+ @Throws(IOException::class)
+ override fun intercept(chain: Chain): Response {
+ val original: Request = chain.request()
+ val request = original.newBuilder()
+ .header("User-Agent", userAgent)
+ .header("Accept", "application/json")
+ .header("OCS-APIRequest", "true")
+ .header("ngrok-skip-browser-warning", "true")
+ .method(original.method, original.body)
+ .build()
+ return chain.proceed(request)
+ }
+ }
+
+ class HttpAuthenticator(private val credentials: String, private val authenticatorType: String) : Authenticator {
+ override fun authenticate(route: Route?, response: Response): Request? {
+ if (response.request.header(authenticatorType) != null) {
+ return null
+ }
+ var countedResponse = response
+ var attemptsCount = 0
+ while (countedResponse.priorResponse.also { countedResponse = it!! } != null) {
+ attemptsCount++
+ if (attemptsCount == 3) {
+ return null
+ }
+ }
+ return response.request.newBuilder()
+ .header(authenticatorType, credentials)
+ .build()
+ }
+ }
+
+ private inner class GetProxyRunnable(private val appPreferences: AppPreferences) : Runnable {
+ @Volatile
+ var proxyValue: Proxy? = null
+ private set
+
+ override fun run() {
+ proxyValue = if (Proxy.Type.valueOf(appPreferences.getProxyType()) == Proxy.Type.SOCKS) {
+ Proxy(
+ Proxy.Type.valueOf(appPreferences.getProxyType()),
+ InetSocketAddress.createUnresolved(
+ appPreferences.getProxyHost(),
+ appPreferences.getProxyPort().toInt()
+ )
+ )
+ } else {
+ Proxy(
+ Proxy.Type.valueOf(appPreferences.getProxyType()),
+ InetSocketAddress(appPreferences.getProxyHost(), appPreferences.getProxyPort().toInt())
+ )
+ }
+ }
+ }
+
+ companion object {
+ private const val TAG = "RestModule"
+ }
+}