package community.yuvomi.mobile import android.content.ContentResolver import android.net.Uri import java.net.URI import javax.net.ssl.HttpsURLConnection object FileTransfer { /** Never forwards session cookies across a redirect, even to another HTTPS origin. */ fun save(server: ServerAddress, url: String, cookie: String?, resolver: ContentResolver, destination: Uri) { require(server.owns(url)) val connection = URI(url).toURL().openConnection() as HttpsURLConnection try { connection.instanceFollowRedirects = false connection.connectTimeout = 15_000 connection.readTimeout = 20_000 cookie?.let { connection.setRequestProperty("Cookie", it) } require(connection.responseCode == 200) { "Download refused" } require(connection.contentLengthLong <= 100L * 1024 * 1024) { "Download too large" } connection.inputStream.use { input -> requireNotNull(resolver.openOutputStream(destination, "w")).use { output -> val buffer = ByteArray(8192) var total = 0L val deadline = System.nanoTime() + 120_000_000_000L while (true) { check(!Thread.currentThread().isInterrupted && System.nanoTime() < deadline) val count = input.read(buffer) if (count < 0) break total += count require(total <= 100L * 1024 * 1024) output.write(buffer, 0, count) } } } } finally { connection.disconnect() } } }