Files
Yuvomi-App/legacy/android/FileTransfer.kt
T
Yuvomi Mobile Contributors 8c480ddca3 feat(android): replace WebView with tested native Compose API slice
Add real native onboarding/auth/dashboard/tasks/notes/shopping, origin-bound HTTPS and encrypted AndroidKeyStore session persistence. Archive the superseded browser renderer and tests. Verify 10 JVM tests, 6 native API-35 emulator tests, lintDebug/lintRelease and debug/unsigned release APK/AAB builds; the real upstream suite passes 7 tests and exports a nonblank native fixture screenshot. Tink host-tool update removes the old generated-protobuf warning. Full module/visual parity remains explicitly incomplete.
2026-10-21 09:12:47 +02:00

40 lines
1.7 KiB
Kotlin

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()
}
}
}