Skip to content

Commit

Permalink
I am not explaining this commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Iamlooker committed Aug 9, 2023
1 parent 40c1915 commit 2c0eabd
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ object RepositoryUpdater {
}
}
val fingerprintFromJar = certificateFromJar.fingerprint()
fingerprintFromJar
fingerprintFromJar.uppercase()
}

val commitRepository = if (workRepository.fingerprint != fingerprint) {
Expand Down
28 changes: 9 additions & 19 deletions app/src/main/kotlin/com/looker/droidify/service/DownloadService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import com.looker.core.common.*
import com.looker.core.common.cache.Cache
import com.looker.core.common.extension.*
import com.looker.core.common.result.Result.*
import com.looker.core.common.signature.SHA256
import com.looker.core.common.signature.verifyHash
import com.looker.core.datastore.UserPreferencesRepository
import com.looker.core.datastore.model.InstallerType
import com.looker.core.model.Release
Expand Down Expand Up @@ -316,33 +318,21 @@ class DownloadService : ConnectionService<DownloadService.Binder>() {
task: Task,
file: File
): ValidationError? = withContext(Dispatchers.IO) {
val hash = try {
val hashType = task.release.hashType.ifEmpty { "SHA256" }
val digest = MessageDigest.getInstance(hashType)
file.inputStream().use {
val bytes = ByteArray(8 * 1024)
generateSequence { it.read(bytes) }.takeWhile { it >= 0 }
.forEach { digest.update(bytes, 0, it) }
digest.digest().hex()
}
} catch (e: Exception) {
""
}
var validationError: ValidationError? = null
if (hash.isEmpty() || hash != task.release.hash) validationError = ValidationError.INTEGRITY
if (!file.verifyHash(SHA256(task.release.hash))) validationError = ValidationError.INTEGRITY
yield()
val packageInfo = packageManager.getPackageArchiveInfoCompat(file.path)
?: return@withContext ValidationError.FORMAT
if (packageInfo.packageName != task.packageName || packageInfo.versionCodeCompat != task.release.versionCode) validationError =
ValidationError.METADATA
if (packageInfo.packageName != task.packageName || packageInfo.versionCodeCompat != task.release.versionCode)
validationError = ValidationError.METADATA
yield()
val signature = packageInfo.singleSignature?.calculateHash().orEmpty()
if (signature.isEmpty() || signature != task.release.signature) validationError =
ValidationError.SIGNATURE
if (signature.isEmpty() || signature != task.release.signature)
validationError = ValidationError.SIGNATURE
yield()
val permissions = packageInfo.permissions?.asSequence().orEmpty().map { it.name }.toSet()
if (!task.release.permissions.containsAll(permissions)) validationError =
ValidationError.PERMISSIONS
if (!task.release.permissions.containsAll(permissions))
validationError = ValidationError.PERMISSIONS
yield()
validationError
}
Expand Down
6 changes: 2 additions & 4 deletions core/common/src/main/java/com/looker/core/common/Text.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ fun Long.formatSize(): String {
return sizeFormats[index].format(Locale.US, size)
}

fun ByteArray.hex(): String = buildString {
this@hex.forEach { byte ->
append("%02x".format(Locale.US, byte.toInt() and 0xff))
}
fun ByteArray.hex(): String = joinToString(separator = "") { byte ->
"%02x".format(Locale.US, byte.toInt() and 0xff)
}

fun Any.log(message: Any) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ package com.looker.core.common.extension

fun <T> Set<T>.updateAsMutable(block: MutableSet<T>.() -> Unit): Set<T> {
return toMutableSet().apply(block)
}
}

fun <T> Collection<T>.firstIfOnly(
block: () -> Exception = { NoSuchElementException("Collection is empty.") }
): T = firstOrNull() ?: throw block()
25 changes: 10 additions & 15 deletions core/common/src/main/java/com/looker/core/common/extension/File.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
package com.looker.core.common.extension

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import kotlinx.coroutines.*
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream

val File.size: Long?
get() = if (exists()) length().takeIf { it > 0L } else null

suspend fun File.readFrom(input: InputStream) = withContext(Dispatchers.IO) {
suspend infix fun InputStream.writeTo(file: File) = withContext(Dispatchers.IO) {
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
var bytesRead = input.read(buffer)
val output = FileOutputStream(this@readFrom)
while (bytesRead != -1) {
ensureActive()
output.write(buffer, 0, bytesRead)
yield()
bytesRead = input.read(buffer)
var bytesRead = read(buffer)
file.outputStream().use { output ->
while (bytesRead != -1) {
ensureActive()
output.write(buffer, 0, bytesRead)
bytesRead = read(buffer)
}
output.flush()
}
output.flush()
output.close()
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.looker.core.common.extension

import com.looker.core.common.hex
import java.security.MessageDigest
import java.security.cert.Certificate
import java.security.cert.CertificateEncodingException
import java.util.Locale

fun Certificate.fingerprint(): String {
val encoded = try {
Expand All @@ -17,11 +17,7 @@ fun Certificate.fingerprint(): String {
fun ByteArray.fingerprint(): String = if (size >= 256) {
try {
val fingerprint = MessageDigest.getInstance("SHA-256").digest(this)
val builder = StringBuilder()
for (byte in fingerprint) {
builder.append("%02X".format(Locale.US, byte.toInt() and 0xff))
}
builder.toString()
fingerprint.hex()
} catch (e: Exception) {
e.printStackTrace()
""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.looker.core.common.signature

import com.looker.core.common.extension.exceptCancellation
import com.looker.core.common.hex
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.withContext
import java.io.File
import java.security.MessageDigest

suspend fun File.verifyHash(hash: Hash): Boolean = withContext(Dispatchers.IO) {
try {
val digest = MessageDigest
.getInstance(hash.name)
if (length() < Int.MAX_VALUE) {
return@withContext digest
.digest(readBytes())
.hex()
.equals(hash.hash, ignoreCase = true)
}
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
inputStream().use { input ->
var bytesRead = input.read(buffer)
while (bytesRead >= 0) {
ensureActive()
digest.update(buffer, 0, bytesRead)
bytesRead = input.read(buffer)
}
digest
.digest()
.hex()
.equals(hash.hash, ignoreCase = true)
}
} catch (e: Exception) {
e.exceptCancellation()
false
}
}

sealed class Hash(val name: String, val hash: String)

data class SHA256(val value: String) : Hash(name = "sha256", hash = value) {
init {
require(value.length == 64)
}
}

data class MD5(val value: String) : Hash(name = "md5", hash = value) {
init {
require(value.length == 32)
}
}
33 changes: 17 additions & 16 deletions core/network/src/main/java/com/looker/network/KtorDownloader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ class KtorDownloader @Inject constructor(private val client: HttpClient) : Downl
url: String,
headers: HeadersBuilder.() -> Unit
): NetworkResponse {
val headRequest = request {
url(url)
headers {
KtorHeadersBuilder(this).headers()
}
}
val headRequest = createRequest(
url = url,
headers = headers,
block = null
)
val status = client.head(headRequest).status
return status.toNetworkResponse()
}
Expand All @@ -41,10 +40,16 @@ class KtorDownloader @Inject constructor(private val client: HttpClient) : Downl
block: ProgressListener?
): NetworkResponse {
return try {
val request = createRequest(url, target.size, headers, block)
val request = createRequest(
url = url,
headers = {
target.size?.let { inRange(it) }
headers()
},
block = block
)
client.prepareGet(request).execute { response ->
val channel = response.bodyAsChannel()
channel.saveToFile(target)
response.bodyAsChannel() saveTo target
response.status.toNetworkResponse()
}
} catch (e: Exception) {
Expand All @@ -55,23 +60,19 @@ class KtorDownloader @Inject constructor(private val client: HttpClient) : Downl

private fun createRequest(
url: String,
fileLength: Long?,
headers: HeadersBuilder.() -> Unit,
block: ProgressListener?
) = request {
url(url)
headers {
val headerBuilder = KtorHeadersBuilder(this)
with(headerBuilder) {
if (fileLength != null) inRange(fileLength)
headers()
}
KtorHeadersBuilder(this).headers()
}
onDownload(block)
}

private suspend fun ByteReadChannel.saveToFile(target: File) {
private suspend infix fun ByteReadChannel.saveTo(target: File) {
while (!isClosedForRead) {
yield()
val packet = readRemaining(DEFAULT_BUFFER_SIZE.toLong())
packet.appendTo(target)
}
Expand Down

0 comments on commit 2c0eabd

Please sign in to comment.