mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-28 09:38:14 +03:00
convert RestModule to kt
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
954648459e
commit
a576e5f41c
2 changed files with 290 additions and 320 deletions
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue