diff --git a/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java b/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java index f4d9bb832..152ddb012 100644 --- a/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java +++ b/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java @@ -1,10 +1,6 @@ package org.fdroid.fdroid.net; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - import android.os.Build; import android.util.Log; @@ -29,6 +25,10 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + public class HttpDownloaderTest { private static final String TAG = "HttpDownloaderTest"; diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/SwapWorkflowActivity.java b/app/src/full/java/org/fdroid/fdroid/nearby/SwapWorkflowActivity.java index 4d2b59c8a..34fc24359 100644 --- a/app/src/full/java/org/fdroid/fdroid/nearby/SwapWorkflowActivity.java +++ b/app/src/full/java/org/fdroid/fdroid/nearby/SwapWorkflowActivity.java @@ -41,7 +41,6 @@ import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; import org.fdroid.download.Downloader; -import org.fdroid.download.HttpDownloader; import org.fdroid.fdroid.BuildConfig; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.NfcHelper; @@ -466,7 +465,7 @@ public class SwapWorkflowActivity extends AppCompatActivity { return; } Uri uri = intent.getData(); - if (uri != null && !HttpDownloader.isSwapUrl(uri) && !BluetoothDownloader.isBluetoothUri(uri)) { + if (uri != null && !isSwapUrl(uri) && !BluetoothDownloader.isBluetoothUri(uri)) { String msg = getString(R.string.swap_toast_invalid_url, uri); Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); return; @@ -474,6 +473,16 @@ public class SwapWorkflowActivity extends AppCompatActivity { confirmSwapConfig = new NewRepoConfig(this, intent); } + private static boolean isSwapUrl(Uri uri) { + return isSwapUrl(uri.getHost(), uri.getPort()); + } + + private static boolean isSwapUrl(String host, int port) { + return port > 1023 // only root can use <= 1023, so never a swap repo + && host.matches("[0-9.]+") // host must be an IP address + && FDroidApp.subnetInfo.isInRange(host); // on the same subnet as we are + } + public void promptToSelectWifiNetwork() { new AlertDialog.Builder(this) .setTitle(R.string.swap_join_same_wifi) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2910c7238..f1ba9a3d1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -46,7 +46,6 @@ android:name="android.hardware.touchscreen" android:required="false" /> - diff --git a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java index cdc4573f7..e055f12e8 100644 --- a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java +++ b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java @@ -50,7 +50,6 @@ import org.acra.ReportField; import org.acra.ReportingInteractionMode; import org.acra.annotation.ReportsCrashes; import org.apache.commons.net.util.SubnetUtils; -import org.fdroid.download.Downloader; import org.fdroid.fdroid.Preferences.ChangeListener; import org.fdroid.fdroid.Preferences.Theme; import org.fdroid.fdroid.compat.PRNGFixes; @@ -127,8 +126,6 @@ public class FDroidApp extends Application implements androidx.work.Configuratio @Nullable public static volatile String queryString; - private static volatile int timeout = Downloader.DEFAULT_TIMEOUT; - // Leaving the fully qualified class name here to help clarify the difference between spongy/bouncy castle. private static final org.bouncycastle.jce.provider.BouncyCastleProvider BOUNCYCASTLE_PROVIDER; @@ -246,10 +243,6 @@ public class FDroidApp extends Application implements androidx.work.Configuratio repo = new Repo(); } - public static int getTimeout() { - return timeout; - } - @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); diff --git a/app/src/main/java/org/fdroid/fdroid/IndexUpdater.java b/app/src/main/java/org/fdroid/fdroid/IndexUpdater.java index 492237246..85ce21782 100644 --- a/app/src/main/java/org/fdroid/fdroid/IndexUpdater.java +++ b/app/src/main/java/org/fdroid/fdroid/IndexUpdater.java @@ -33,8 +33,6 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; -import androidx.annotation.NonNull; - import org.fdroid.download.Downloader; import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.ApkProvider; @@ -70,6 +68,8 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import androidx.annotation.NonNull; + // TODO move to org.fdroid.fdroid.updater // TODO reduce visibility of methods once in .updater package (.e.g tests need it public now) diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java index c8a510a15..56bb569af 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -300,6 +300,8 @@ public class InstallManagerService extends Service { } } else if (Downloader.ACTION_INTERRUPTED.equals(action)) { localBroadcastManager.unregisterReceiver(this); + } else if (Downloader.ACTION_CONNECTION_FAILED.equals(action)) { + localBroadcastManager.unregisterReceiver(this); } else { throw new RuntimeException("intent action not handled!"); } diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index 2ddf3d1f8..345011d77 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -33,8 +33,6 @@ import android.text.TextUtils; import android.util.Log; import android.util.LogPrinter; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; - import org.fdroid.download.Downloader; import org.fdroid.fdroid.BuildConfig; import org.fdroid.fdroid.ProgressListener; @@ -58,6 +56,8 @@ import javax.net.ssl.SSLKeyException; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLProtocolException; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + /** * DownloaderService is a service that handles asynchronous download requests * (expressed as {@link Intent}s) on demand. Clients send download requests diff --git a/app/src/main/java/org/fdroid/fdroid/net/FDroidGlideModule.java b/app/src/main/java/org/fdroid/fdroid/net/FDroidGlideModule.java index fbf6cc35a..5a80857f2 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/FDroidGlideModule.java +++ b/app/src/main/java/org/fdroid/fdroid/net/FDroidGlideModule.java @@ -18,7 +18,6 @@ import com.bumptech.glide.request.RequestOptions; import org.fdroid.download.DownloadRequest; import org.fdroid.download.glide.DownloadRequestLoader; import org.fdroid.download.glide.HttpGlideUrlLoader; -import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.Preferences; import androidx.annotation.NonNull; @@ -39,8 +38,7 @@ public class FDroidGlideModule extends AppGlideModule { BitmapTransitionOptions.withCrossFade()) .setDefaultRequestOptions(new RequestOptions() .format(DecodeFormat.PREFER_RGB_565) - .onlyRetrieveFromCache(!Preferences.get().isBackgroundDownloadAllowed()) - .timeout(FDroidApp.getTimeout())); + .onlyRetrieveFromCache(!Preferences.get().isBackgroundDownloadAllowed())); } @Override diff --git a/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java b/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java index 0b656eb96..30f17f6c7 100644 --- a/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/privileged/views/InstallConfirmActivity.java @@ -37,8 +37,6 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import androidx.viewpager.widget.ViewPager; -import com.bumptech.glide.Glide; - import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.R; import org.fdroid.fdroid.Utils; diff --git a/download/build.gradle b/download/build.gradle index a5dfc5ba5..76340f562 100644 --- a/download/build.gradle +++ b/download/build.gradle @@ -28,6 +28,8 @@ kotlin { all { languageSettings { optIn('kotlin.RequiresOptIn') + explicitApi() + explicitApi = 'strict' } } commonMain { diff --git a/download/src/androidMain/AndroidManifest.xml b/download/src/androidMain/AndroidManifest.xml index 5cedd19b9..377a09c5b 100644 --- a/download/src/androidMain/AndroidManifest.xml +++ b/download/src/androidMain/AndroidManifest.xml @@ -1,2 +1,6 @@ - \ No newline at end of file + + + + diff --git a/download/src/androidMain/kotlin/org/fdroid/download/Downloader.kt b/download/src/androidMain/kotlin/org/fdroid/download/Downloader.kt index 9336eb779..67ddb24c7 100644 --- a/download/src/androidMain/kotlin/org/fdroid/download/Downloader.kt +++ b/download/src/androidMain/kotlin/org/fdroid/download/Downloader.kt @@ -8,25 +8,26 @@ import java.io.IOException import java.io.InputStream import java.io.OutputStream -abstract class Downloader constructor( +public abstract class Downloader constructor( @JvmField protected val outputFile: File, ) { - companion object { - val log = KotlinLogging.logger {} + public companion object { + private val log = KotlinLogging.logger {} - const val ACTION_STARTED = "org.fdroid.fdroid.net.Downloader.action.STARTED" - const val ACTION_PROGRESS = "org.fdroid.fdroid.net.Downloader.action.PROGRESS" - const val ACTION_INTERRUPTED = "org.fdroid.fdroid.net.Downloader.action.INTERRUPTED" - const val ACTION_CONNECTION_FAILED = "org.fdroid.fdroid.net.Downloader.action.CONNECTION_FAILED" - const val ACTION_COMPLETE = "org.fdroid.fdroid.net.Downloader.action.COMPLETE" - const val EXTRA_DOWNLOAD_PATH = "org.fdroid.fdroid.net.Downloader.extra.DOWNLOAD_PATH" - const val EXTRA_BYTES_READ = "org.fdroid.fdroid.net.Downloader.extra.BYTES_READ" - const val EXTRA_TOTAL_BYTES = "org.fdroid.fdroid.net.Downloader.extra.TOTAL_BYTES" - const val EXTRA_ERROR_MESSAGE = "org.fdroid.fdroid.net.Downloader.extra.ERROR_MESSAGE" - const val EXTRA_REPO_ID = "org.fdroid.fdroid.net.Downloader.extra.REPO_ID" - const val EXTRA_MIRROR_URL = "org.fdroid.fdroid.net.Downloader.extra.MIRROR_URL" + public const val ACTION_STARTED: String = "org.fdroid.fdroid.net.Downloader.action.STARTED" + public const val ACTION_PROGRESS: String = "org.fdroid.fdroid.net.Downloader.action.PROGRESS" + public const val ACTION_INTERRUPTED: String = "org.fdroid.fdroid.net.Downloader.action.INTERRUPTED" + public const val ACTION_CONNECTION_FAILED: String = + "org.fdroid.fdroid.net.Downloader.action.CONNECTION_FAILED" + public const val ACTION_COMPLETE: String = "org.fdroid.fdroid.net.Downloader.action.COMPLETE" + public const val EXTRA_DOWNLOAD_PATH: String = "org.fdroid.fdroid.net.Downloader.extra.DOWNLOAD_PATH" + public const val EXTRA_BYTES_READ: String = "org.fdroid.fdroid.net.Downloader.extra.BYTES_READ" + public const val EXTRA_TOTAL_BYTES: String = "org.fdroid.fdroid.net.Downloader.extra.TOTAL_BYTES" + public const val EXTRA_ERROR_MESSAGE: String = "org.fdroid.fdroid.net.Downloader.extra.ERROR_MESSAGE" + public const val EXTRA_REPO_ID: String = "org.fdroid.fdroid.net.Downloader.extra.REPO_ID" + public const val EXTRA_MIRROR_URL: String = "org.fdroid.fdroid.net.Downloader.extra.MIRROR_URL" /** * Unique ID used to represent this specific package's install process, @@ -36,10 +37,7 @@ abstract class Downloader constructor( * * @see android.content.Intent.EXTRA_ORIGINATING_URI */ - const val EXTRA_CANONICAL_URL = "org.fdroid.fdroid.net.Downloader.extra.CANONICAL_URL" - - const val DEFAULT_TIMEOUT = 10000 - const val LONGEST_TIMEOUT = 600000 // 10 minutes + public const val EXTRA_CANONICAL_URL: String = "org.fdroid.fdroid.net.Downloader.extra.CANONICAL_URL" } /** @@ -50,7 +48,7 @@ abstract class Downloader constructor( * If this cacheTag matches that returned by the server, then no download will * take place, and a status code of 304 will be returned by download(). */ - var cacheTag: String? = null + public var cacheTag: String? = null @Volatile private var cancelled = false @@ -63,7 +61,7 @@ abstract class Downloader constructor( * Never call this more than once. Create a new [Downloader], if you need to download again! */ @Throws(IOException::class, InterruptedException::class) - abstract fun download() + public abstract fun download() @Throws(IOException::class) protected abstract fun getInputStream(resumable: Boolean): InputStream @@ -82,10 +80,10 @@ abstract class Downloader constructor( * After calling [download], this returns true if a new file was downloaded and * false if the file on the server has not changed and thus was not downloaded. */ - abstract fun hasChanged(): Boolean - abstract fun close() + public abstract fun hasChanged(): Boolean + public abstract fun close() - fun setListener(listener: ProgressListener) { + public fun setListener(listener: ProgressListener) { progressListener = listener } @@ -179,7 +177,7 @@ abstract class Downloader constructor( /** * Cancel a running download, triggering an [InterruptedException] */ - fun cancelDownload() { + public fun cancelDownload() { cancelled = true } diff --git a/download/src/androidMain/kotlin/org/fdroid/download/HttpDownloader.kt b/download/src/androidMain/kotlin/org/fdroid/download/HttpDownloader.kt index 6b398884f..03891edb8 100644 --- a/download/src/androidMain/kotlin/org/fdroid/download/HttpDownloader.kt +++ b/download/src/androidMain/kotlin/org/fdroid/download/HttpDownloader.kt @@ -22,7 +22,6 @@ package org.fdroid.download import android.annotation.TargetApi -import android.net.Uri import android.os.Build.VERSION.SDK_INT import io.ktor.client.features.ResponseException import kotlinx.coroutines.DelicateCoroutinesApi @@ -36,26 +35,14 @@ import java.util.Date /** * Download files over HTTP, with support for proxies, `.onion` addresses, HTTP Basic Auth, etc. */ -class HttpDownloader constructor( +public class HttpDownloader constructor( private val httpManager: HttpManager, private val request: DownloadRequest, destFile: File, ) : Downloader(destFile) { - companion object { + private companion object { val log = KotlinLogging.logger {} - - @JvmStatic - fun isSwapUrl(uri: Uri): Boolean { - return isSwapUrl(uri.host, uri.port) - } - - fun isSwapUrl(host: String?, port: Int): Boolean { - return (port > 1023 // only root can use <= 1023, so never a swap repo - && host!!.matches(Regex("[0-9.]+")) // host must be an IP address - ) - // TODO check if is local - } } private var hasChanged = false diff --git a/download/src/androidMain/kotlin/org/fdroid/download/HttpManager.kt b/download/src/androidMain/kotlin/org/fdroid/download/HttpManager.kt index 250a27f26..c238b5597 100644 --- a/download/src/androidMain/kotlin/org/fdroid/download/HttpManager.kt +++ b/download/src/androidMain/kotlin/org/fdroid/download/HttpManager.kt @@ -7,7 +7,7 @@ import io.ktor.client.engine.okhttp.OkHttpConfig import okhttp3.Dns import java.net.InetAddress -actual fun getHttpClientEngineFactory(): HttpClientEngineFactory<*> { +internal actual fun getHttpClientEngineFactory(): HttpClientEngineFactory<*> { return object : HttpClientEngineFactory { override fun create(block: OkHttpConfig.() -> Unit): HttpClientEngine = OkHttp.create { block() diff --git a/download/src/androidMain/kotlin/org/fdroid/download/HttpPoster.kt b/download/src/androidMain/kotlin/org/fdroid/download/HttpPoster.kt index db676b313..49f3c3aeb 100644 --- a/download/src/androidMain/kotlin/org/fdroid/download/HttpPoster.kt +++ b/download/src/androidMain/kotlin/org/fdroid/download/HttpPoster.kt @@ -7,13 +7,13 @@ import java.io.IOException /** * HTTP POST a JSON string to the URL configured in the constructor. */ -class HttpPoster( +public class HttpPoster( private val httpManager: HttpManager, private val url: String, ) { @Throws(IOException::class) - fun post(json: String) { + public fun post(json: String) { runBlocking { try { httpManager.post(url, json) diff --git a/download/src/androidMain/kotlin/org/fdroid/download/glide/DownloadRequestLoader.kt b/download/src/androidMain/kotlin/org/fdroid/download/glide/DownloadRequestLoader.kt index bc9c82689..fc8e3b06f 100644 --- a/download/src/androidMain/kotlin/org/fdroid/download/glide/DownloadRequestLoader.kt +++ b/download/src/androidMain/kotlin/org/fdroid/download/glide/DownloadRequestLoader.kt @@ -10,7 +10,7 @@ import org.fdroid.download.DownloadRequest import org.fdroid.download.HttpManager import java.io.InputStream -class DownloadRequestLoader( +public class DownloadRequestLoader( private val httpManager: HttpManager, ) : ModelLoader { @@ -27,7 +27,7 @@ class DownloadRequestLoader( return LoadData(downloadRequest.getKey(), HttpFetcher(httpManager, downloadRequest)) } - class Factory( + public class Factory( private val httpManager: HttpManager, ) : ModelLoaderFactory { override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader { @@ -39,7 +39,7 @@ class DownloadRequestLoader( } -fun DownloadRequest.getKey(): ObjectKey { +internal fun DownloadRequest.getKey(): ObjectKey { // TODO should we choose a unique key or is it ok for this to work cross-repo based on file path only? return ObjectKey(path) } diff --git a/download/src/androidMain/kotlin/org/fdroid/download/glide/HttpFetcher.kt b/download/src/androidMain/kotlin/org/fdroid/download/glide/HttpFetcher.kt index 22f74c43a..cb1c3f9a6 100644 --- a/download/src/androidMain/kotlin/org/fdroid/download/glide/HttpFetcher.kt +++ b/download/src/androidMain/kotlin/org/fdroid/download/glide/HttpFetcher.kt @@ -17,7 +17,7 @@ import org.fdroid.download.HttpManager import org.fdroid.download.Mirror import java.io.InputStream -class HttpFetcher( +internal class HttpFetcher( private val httpManager: HttpManager, private val downloadRequest: DownloadRequest, ) : DataFetcher { diff --git a/download/src/androidMain/kotlin/org/fdroid/download/glide/HttpGlideUrlLoader.kt b/download/src/androidMain/kotlin/org/fdroid/download/glide/HttpGlideUrlLoader.kt index 64e03541d..ff456e0db 100644 --- a/download/src/androidMain/kotlin/org/fdroid/download/glide/HttpGlideUrlLoader.kt +++ b/download/src/androidMain/kotlin/org/fdroid/download/glide/HttpGlideUrlLoader.kt @@ -12,12 +12,12 @@ import org.fdroid.download.HttpManager import java.io.InputStream @Deprecated("Use DownloadRequestLoader instead") -class HttpGlideUrlLoader( +public class HttpGlideUrlLoader( private val httpManager: HttpManager, private val proxyGetter: () -> ProxyConfig?, ) : ModelLoader { - companion object { + private companion object { private val log = KotlinLogging.logger { } } @@ -30,7 +30,7 @@ class HttpGlideUrlLoader( return LoadData(glideUrl, HttpFetcher(httpManager, glideUrl, proxyGetter())) } - class Factory( + public class Factory( private val httpManager: HttpManager, private val proxyGetter: () -> ProxyConfig?, ) : ModelLoaderFactory { diff --git a/download/src/commonMain/kotlin/org/fdroid/download/DownloadRequest.kt b/download/src/commonMain/kotlin/org/fdroid/download/DownloadRequest.kt index 8fdf5fb7b..457beb336 100644 --- a/download/src/commonMain/kotlin/org/fdroid/download/DownloadRequest.kt +++ b/download/src/commonMain/kotlin/org/fdroid/download/DownloadRequest.kt @@ -3,7 +3,7 @@ package org.fdroid.download import io.ktor.client.engine.ProxyConfig import kotlin.jvm.JvmOverloads -data class DownloadRequest @JvmOverloads constructor( +public data class DownloadRequest @JvmOverloads constructor( val path: String, val mirrors: List, val proxy: ProxyConfig? = null, diff --git a/download/src/commonMain/kotlin/org/fdroid/download/HeadInfo.kt b/download/src/commonMain/kotlin/org/fdroid/download/HeadInfo.kt index 4052d1088..fa8dd9a16 100644 --- a/download/src/commonMain/kotlin/org/fdroid/download/HeadInfo.kt +++ b/download/src/commonMain/kotlin/org/fdroid/download/HeadInfo.kt @@ -1,6 +1,6 @@ package org.fdroid.download -data class HeadInfo( +public data class HeadInfo( val eTagChanged: Boolean, val eTag: String?, val contentLength: Long?, diff --git a/download/src/commonMain/kotlin/org/fdroid/download/HttpManager.kt b/download/src/commonMain/kotlin/org/fdroid/download/HttpManager.kt index b3c3e9fa8..e0a9de068 100644 --- a/download/src/commonMain/kotlin/org/fdroid/download/HttpManager.kt +++ b/download/src/commonMain/kotlin/org/fdroid/download/HttpManager.kt @@ -49,7 +49,7 @@ public open class HttpManager @JvmOverloads constructor( private val httpClientEngineFactory: HttpClientEngineFactory<*> = getHttpClientEngineFactory(), ) { - companion object { + private companion object { val log = KotlinLogging.logger {} } @@ -187,7 +187,7 @@ public open class HttpManager @JvmOverloads constructor( return channel.toByteArray() } - suspend fun post(url: String, json: String, proxy: ProxyConfig? = null) { + public suspend fun post(url: String, json: String, proxy: ProxyConfig? = null) { resetProxyIfNeeded(proxy) httpClient.post(url) { header(ContentType, "application/json; utf-8") @@ -217,3 +217,5 @@ public open class HttpManager @JvmOverloads constructor( } } + +public class NoResumeException : Exception() diff --git a/download/src/commonMain/kotlin/org/fdroid/download/Mirror.kt b/download/src/commonMain/kotlin/org/fdroid/download/Mirror.kt index 8d9a882a1..7ee34d047 100644 --- a/download/src/commonMain/kotlin/org/fdroid/download/Mirror.kt +++ b/download/src/commonMain/kotlin/org/fdroid/download/Mirror.kt @@ -8,11 +8,11 @@ import mu.KotlinLogging import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmStatic -data class Mirror @JvmOverloads constructor( +public data class Mirror @JvmOverloads constructor( private val baseUrl: String, val location: String? = null, ) { - val url by lazy { + public val url: Url by lazy { try { URLBuilder(baseUrl).build() // we fall back to a non-existent URL if someone tries to sneak in an invalid mirror URL to crash us @@ -28,17 +28,17 @@ data class Mirror @JvmOverloads constructor( } } - fun getUrl(path: String): Url { + public fun getUrl(path: String): Url { return URLBuilder(url).pathComponents(path).build() } - fun isOnion(): Boolean = url.isOnion() + public fun isOnion(): Boolean = url.isOnion() - fun isLocal(): Boolean = url.isLocal() + public fun isLocal(): Boolean = url.isLocal() - companion object { + public companion object { @JvmStatic - fun fromStrings(list: List): List = list.map { Mirror(it) } + public fun fromStrings(list: List): List = list.map { Mirror(it) } } } diff --git a/download/src/commonMain/kotlin/org/fdroid/download/MirrorChooser.kt b/download/src/commonMain/kotlin/org/fdroid/download/MirrorChooser.kt index ca3658a34..bea654056 100644 --- a/download/src/commonMain/kotlin/org/fdroid/download/MirrorChooser.kt +++ b/download/src/commonMain/kotlin/org/fdroid/download/MirrorChooser.kt @@ -4,9 +4,9 @@ import io.ktor.client.features.ResponseException import io.ktor.http.Url import mu.KotlinLogging -interface MirrorChooser { - fun orderMirrors(downloadRequest: DownloadRequest): List - suspend fun mirrorRequest( +public interface MirrorChooser { + public fun orderMirrors(downloadRequest: DownloadRequest): List + public suspend fun mirrorRequest( downloadRequest: DownloadRequest, request: suspend (mirror: Mirror, url: Url) -> T, ): T @@ -25,7 +25,15 @@ internal abstract class MirrorChooserImpl : MirrorChooser { downloadRequest: DownloadRequest, request: suspend (mirror: Mirror, url: Url) -> T, ): T { - orderMirrors(downloadRequest).forEachIndexed { index, mirror -> + val mirrors = if (downloadRequest.proxy == null) { + // if we don't use a proxy, filter out onion mirrors (won't work without Orbot) + val orderedMirrors = orderMirrors(downloadRequest).filter { mirror -> !mirror.isOnion() } + // if we only have onion mirrors, take what we have and expect errors + if (orderedMirrors.isEmpty()) downloadRequest.mirrors else orderedMirrors + } else { + orderMirrors(downloadRequest) + } + mirrors.forEachIndexed { index, mirror -> val url = mirror.getUrl(downloadRequest.path) try { return request(mirror, url) @@ -45,13 +53,8 @@ internal class MirrorChooserRandom : MirrorChooserImpl() { * Returns a list of mirrors with the best mirrors first. */ override fun orderMirrors(downloadRequest: DownloadRequest): List { - val mirrors = if (downloadRequest.proxy == null) { - downloadRequest.mirrors.filter { mirror -> !mirror.isOnion() }.toMutableList() - } else { - downloadRequest.mirrors.toMutableList() - } // simple random selection for now - return mirrors.apply { shuffle() } + return downloadRequest.mirrors.toMutableList().apply { shuffle() } } } diff --git a/download/src/commonMain/kotlin/org/fdroid/download/NoResumeException.kt b/download/src/commonMain/kotlin/org/fdroid/download/NoResumeException.kt deleted file mode 100644 index ce0d5c0d6..000000000 --- a/download/src/commonMain/kotlin/org/fdroid/download/NoResumeException.kt +++ /dev/null @@ -1,3 +0,0 @@ -package org.fdroid.download - -public class NoResumeException : Exception() diff --git a/download/src/commonMain/kotlin/org/fdroid/fdroid/ProgressListener.kt b/download/src/commonMain/kotlin/org/fdroid/fdroid/ProgressListener.kt index 9147ecdf1..8d988c6c3 100644 --- a/download/src/commonMain/kotlin/org/fdroid/fdroid/ProgressListener.kt +++ b/download/src/commonMain/kotlin/org/fdroid/fdroid/ProgressListener.kt @@ -16,6 +16,6 @@ package org.fdroid.fdroid * * `int`s, i.e. [String.hashCode] * */ -interface ProgressListener { - fun onProgress(bytesRead: Long, totalBytes: Long) +public interface ProgressListener { + public fun onProgress(bytesRead: Long, totalBytes: Long) } diff --git a/download/src/jvmMain/kotlin/org/fdroid/download/HttpManager.kt b/download/src/jvmMain/kotlin/org/fdroid/download/HttpManager.kt index 9a5cdfad8..7049c7ea6 100644 --- a/download/src/jvmMain/kotlin/org/fdroid/download/HttpManager.kt +++ b/download/src/jvmMain/kotlin/org/fdroid/download/HttpManager.kt @@ -3,6 +3,6 @@ package org.fdroid.download import io.ktor.client.engine.HttpClientEngineFactory import io.ktor.client.engine.cio.CIO -actual fun getHttpClientEngineFactory(): HttpClientEngineFactory<*> { +internal actual fun getHttpClientEngineFactory(): HttpClientEngineFactory<*> { return CIO } diff --git a/download/src/nativeMain/kotlin/org/fdroid/download/HttpManager.kt b/download/src/nativeMain/kotlin/org/fdroid/download/HttpManager.kt index db1ed0993..a7289d4ff 100644 --- a/download/src/nativeMain/kotlin/org/fdroid/download/HttpManager.kt +++ b/download/src/nativeMain/kotlin/org/fdroid/download/HttpManager.kt @@ -3,6 +3,6 @@ package org.fdroid.download import io.ktor.client.engine.HttpClientEngineFactory import io.ktor.client.engine.curl.Curl -actual fun getHttpClientEngineFactory(): HttpClientEngineFactory<*> { +internal actual fun getHttpClientEngineFactory(): HttpClientEngineFactory<*> { return Curl }