2525package com.phpbg.easysync.dav
2626
2727import android.util.Log
28+ import com.burgstaller.okhttp.AuthenticationCacheInterceptor
29+ import com.burgstaller.okhttp.CachingAuthenticatorDecorator
30+ import com.burgstaller.okhttp.DefaultRequestCacheKeyProvider
31+ import com.burgstaller.okhttp.DispatchingAuthenticator
32+ import com.burgstaller.okhttp.basic.BasicAuthenticator
33+ import com.burgstaller.okhttp.digest.CachingAuthenticator
34+ import com.burgstaller.okhttp.digest.Credentials
35+ import com.burgstaller.okhttp.digest.DigestAuthenticator
36+ import com.google.common.cache.Cache
37+ import com.google.common.cache.CacheBuilder
38+ import com.google.common.net.UrlEscapers
2839import com.phpbg.easysync.BuildConfig
2940import com.phpbg.easysync.settings.Settings
3041import com.phpbg.easysync.util.ParametrizedMutex
3142import com.phpbg.easysync.util.TTLHashSet
32- import com.google.common.cache.Cache
33- import com.google.common.cache.CacheBuilder
34- import com.google.common.net.UrlEscapers
43+ import kotlinx.coroutines.CoroutineScope
3544import kotlinx.coroutines.Dispatchers
36- import kotlinx.coroutines.coroutineScope
3745import kotlinx.coroutines.flow.Flow
3846import kotlinx.coroutines.flow.first
47+ import kotlinx.coroutines.flow.launchIn
3948import kotlinx.coroutines.flow.onEach
40- import kotlinx.coroutines.launch
4149import kotlinx.coroutines.sync.Mutex
4250import kotlinx.coroutines.sync.withLock
4351import kotlinx.coroutines.withContext
@@ -60,14 +68,15 @@ import java.nio.file.attribute.FileTime
6068import java.time.ZonedDateTime
6169import java.time.format.DateTimeFormatter.ISO_DATE_TIME
6270import java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
71+ import java.util.concurrent.ConcurrentHashMap
6372import java.util.concurrent.TimeUnit
6473
74+
6575private const val TAG = " WebDavService"
6676
6777class WebDavService (
6878 private var rootUrl : RootPath ,
69- private val httpClient : OkHttpClient ,
70- private val optionalBasicAuthInterceptor : OptionalBasicAuthInterceptor
79+ private var httpClient : OkHttpClient ,
7180) {
7281 // Mutex to avoid concurrent creation of same directories
7382 private val mkcolPMutex = ParametrizedMutex <String >()
@@ -83,7 +92,7 @@ class WebDavService(
8392
8493 fun updateFromSettings (settings : Settings ) {
8594 rootUrl = RootPath (settings.url).concat(CollectionPath (settings.davPath))
86- optionalBasicAuthInterceptor.updateCredentials (settings.username, settings.password )
95+ httpClient = createHttpClient (settings)
8796 }
8897
8998 // https://learn.microsoft.com/en-us/previous-versions/office/developer/exchange-server-2003/aa142923(v=exchg.65)
@@ -367,39 +376,38 @@ class WebDavService(
367376 mutex.withLock {
368377 if (instance == null ) {
369378 instance = create(settings)
370- coroutineScope {
371- launch {
372- settingsFlow.onEach { newSettings ->
373- instance!! .updateFromSettings(newSettings)
374- }
375- }
376- }
379+ settingsFlow
380+ .onEach { instance!! .updateFromSettings(it) }
381+ .launchIn(CoroutineScope (Dispatchers .Default ))
377382 }
378383 }
379384 }
380385 return instance!!
381386 }
382387
383- fun create (settings : Settings ): WebDavService {
384- Log .d(TAG , " Creating DAVService with URL: " + settings.url)
385- if (settings.url.isEmpty()) {
386- throw MisconfigurationException ()
387- }
388- val basicAuthInterceptor = OptionalBasicAuthInterceptor (
389- settings.username,
390- settings.password
391- )
388+ private fun createHttpClient (settings : Settings ): OkHttpClient {
389+ val authCache: Map <String , CachingAuthenticator > = ConcurrentHashMap ()
390+ val credentials = Credentials (settings.username, settings.password)
391+ val basicAuthenticator = BasicAuthenticator (credentials)
392+ val digestAuthenticator = DigestAuthenticator (credentials)
393+
394+ // note that all auth schemes should be registered as lowercase!
395+ val authenticator = DispatchingAuthenticator .Builder ()
396+ .with (" digest" , digestAuthenticator)
397+ .with (" basic" , basicAuthenticator)
398+ .build()
392399
393400 val dispatcher = Dispatcher ()
394401 dispatcher.maxRequestsPerHost = 6
395402 val okHttpClientBuilder = OkHttpClient .Builder ()
403+ .authenticator(CachingAuthenticatorDecorator (authenticator, authCache))
404+ .addInterceptor(AuthenticationCacheInterceptor (authCache, DefaultRequestCacheKeyProvider ()))
396405 .connectTimeout(10 , TimeUnit .SECONDS )
397406 .readTimeout(60 , TimeUnit .SECONDS )
398407 .writeTimeout(60 , TimeUnit .SECONDS )
399408 .callTimeout(3600 , TimeUnit .SECONDS )
400409 .dispatcher(dispatcher)
401410 .addInterceptor(TrafficStatsInterceptor ())
402- .addInterceptor(basicAuthInterceptor)
403411 .retryOnConnectionFailure(false )
404412
405413 if (BuildConfig .DEBUG ) {
@@ -409,12 +417,20 @@ class WebDavService(
409417 okHttpClientBuilder.addInterceptor(loggingInterceptor)
410418 }
411419
412- val okHttpClient = okHttpClientBuilder.build()
420+ return okHttpClientBuilder.build()
421+ }
422+
423+ fun create (settings : Settings ): WebDavService {
424+ Log .d(TAG , " Creating DAVService with URL: " + settings.url)
425+ if (settings.url.isEmpty()) {
426+ throw MisconfigurationException ()
427+ }
428+
429+ val okHttpClient = createHttpClient(settings)
413430
414431 return WebDavService (
415432 RootPath (settings.url).concat(CollectionPath (settings.davPath)),
416- okHttpClient,
417- basicAuthInterceptor
433+ okHttpClient
418434 )
419435 }
420436 }
0 commit comments