mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-04-20 23:07:26 -04:00
[index] Add proper test data and clean up some things for tests
This commit is contained in:
@@ -11,7 +11,6 @@ import kotlinx.serialization.json.JsonDecoder
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import org.fdroid.index.DEFAULT_LOCALE
|
||||
import org.fdroid.index.IndexParser
|
||||
import org.fdroid.index.DEFAULT_LOCALE
|
||||
import org.fdroid.index.RELEASE_CHANNEL_BETA
|
||||
import org.fdroid.index.getV1ReleaseChannels
|
||||
import org.fdroid.index.mapInto
|
||||
@@ -22,6 +21,18 @@ import org.fdroid.index.v2.LocalizedTextV2
|
||||
import org.fdroid.index.v2.PackageVersionV2
|
||||
import java.io.InputStream
|
||||
|
||||
/**
|
||||
* Processes a indexV1 stream and calls the given [indexStreamReceiver] while parsing it.
|
||||
* Attention: This requires the following canonical top-level order in the JSON
|
||||
* as produced by `fdroidserver`.
|
||||
* * repo
|
||||
* * requests
|
||||
* * apps
|
||||
* * packages
|
||||
*
|
||||
* Any other order of those elements will produce unexpected results
|
||||
* or throw [IllegalArgumentException].
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
public class IndexV1StreamProcessor(
|
||||
@@ -29,37 +40,49 @@ public class IndexV1StreamProcessor(
|
||||
private val certificate: String?,
|
||||
private val locale: String = DEFAULT_LOCALE,
|
||||
private val json: Json = IndexParser.json,
|
||||
private val getAndLogReadBytes: () -> Long? = { null },
|
||||
) {
|
||||
|
||||
public fun process(repoId: Long, inputStream: InputStream) {
|
||||
json.decodeFromStream(IndexStreamSerializer(repoId), inputStream)
|
||||
getAndLogReadBytes()
|
||||
public fun process(inputStream: InputStream) {
|
||||
json.decodeFromStream(IndexStreamSerializer(), inputStream)
|
||||
}
|
||||
|
||||
private inner class IndexStreamSerializer(val repoId: Long) : KSerializer<IndexV1?> {
|
||||
private inner class IndexStreamSerializer : KSerializer<IndexV1?> {
|
||||
override val descriptor = IndexV1.serializer().descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): IndexV1? {
|
||||
getAndLogReadBytes()
|
||||
decoder as? JsonDecoder ?: error("Can be deserialized only by JSON")
|
||||
|
||||
decoder.beginStructure(descriptor)
|
||||
var index = decoder.decodeElementIndex(descriptor)
|
||||
deserializeRepo(decoder, index, repoId)
|
||||
index = decoder.decodeElementIndex(descriptor)
|
||||
deserializeRequests(decoder, index, repoId)
|
||||
index = decoder.decodeElementIndex(descriptor)
|
||||
val appDataMap = deserializeApps(decoder, index, repoId)
|
||||
index = decoder.decodeElementIndex(descriptor)
|
||||
deserializePackages(decoder, index, repoId, appDataMap)
|
||||
val index0 = decoder.decodeElementIndex(descriptor)
|
||||
deserializeRepo(decoder, index0)
|
||||
val index1 = decoder.decodeElementIndex(descriptor)
|
||||
if (index1 == DECODE_DONE) {
|
||||
updateRepoData(emptyMap())
|
||||
decoder.endStructure(descriptor)
|
||||
return null
|
||||
}
|
||||
deserializeRequests(decoder, index1)
|
||||
val index2 = decoder.decodeElementIndex(descriptor)
|
||||
if (index2 == DECODE_DONE) {
|
||||
updateRepoData(emptyMap())
|
||||
decoder.endStructure(descriptor)
|
||||
return null
|
||||
}
|
||||
val appDataMap = deserializeApps(decoder, index2)
|
||||
val index3 = decoder.decodeElementIndex(descriptor)
|
||||
if (index3 == DECODE_DONE) {
|
||||
updateRepoData(appDataMap)
|
||||
decoder.endStructure(descriptor)
|
||||
return null
|
||||
}
|
||||
deserializePackages(decoder, index3, appDataMap)
|
||||
decoder.endStructure(descriptor)
|
||||
|
||||
updateRepoData(appDataMap)
|
||||
return null
|
||||
}
|
||||
|
||||
private fun deserializeRepo(decoder: JsonDecoder, index: Int, repoId: Long) {
|
||||
private fun deserializeRepo(decoder: JsonDecoder, index: Int) {
|
||||
require(index == descriptor.getElementIndex("repo"))
|
||||
val repo = decoder.decodeSerializableValue(RepoV1.serializer())
|
||||
val repoV2 = repo.toRepoV2(
|
||||
@@ -68,32 +91,27 @@ public class IndexV1StreamProcessor(
|
||||
categories = emptyMap(),
|
||||
releaseChannels = emptyMap()
|
||||
)
|
||||
indexStreamReceiver.receive(repoId, repoV2, repo.version, certificate)
|
||||
indexStreamReceiver.receive(repoV2, repo.version, certificate)
|
||||
}
|
||||
|
||||
private fun deserializeRequests(decoder: JsonDecoder, index: Int, repoId: Long) {
|
||||
private fun deserializeRequests(decoder: JsonDecoder, index: Int) {
|
||||
require(index == descriptor.getElementIndex("requests"))
|
||||
decoder.decodeSerializableValue(Requests.serializer())
|
||||
// we ignore the requests here, don't act on them
|
||||
}
|
||||
|
||||
private fun deserializeApps(
|
||||
decoder: JsonDecoder,
|
||||
index: Int,
|
||||
repoId: Long,
|
||||
): Map<String, AppData> {
|
||||
private fun deserializeApps(decoder: JsonDecoder, index: Int): Map<String, AppData> {
|
||||
require(index == descriptor.getElementIndex("apps"))
|
||||
val appDataMap = HashMap<String, AppData>()
|
||||
val mapDescriptor = descriptor.getElementDescriptor(index)
|
||||
val compositeDecoder = decoder.beginStructure(mapDescriptor)
|
||||
while (true) {
|
||||
getAndLogReadBytes()
|
||||
val packageIndex = compositeDecoder.decodeElementIndex(descriptor)
|
||||
if (packageIndex == DECODE_DONE) break
|
||||
val appV1 =
|
||||
decoder.decodeSerializableElement(descriptor, packageIndex, AppV1.serializer())
|
||||
val appV2 = appV1.toMetadataV2(null, locale)
|
||||
indexStreamReceiver.receive(repoId, appV1.packageName, appV2)
|
||||
indexStreamReceiver.receive(appV1.packageName, appV2)
|
||||
appDataMap[appV1.packageName] = AppData(
|
||||
antiFeatures = appV1.antiFeatures.associateWith { emptyMap() },
|
||||
whatsNew = appV1.localized?.mapValuesNotNull { it.value.whatsNew },
|
||||
@@ -108,20 +126,17 @@ public class IndexV1StreamProcessor(
|
||||
private fun deserializePackages(
|
||||
decoder: JsonDecoder,
|
||||
index: Int,
|
||||
repoId: Long,
|
||||
appDataMap: Map<String, AppData>,
|
||||
) {
|
||||
require(index == descriptor.getElementIndex("packages"))
|
||||
val mapDescriptor = descriptor.getElementDescriptor(index)
|
||||
val compositeDecoder = decoder.beginStructure(mapDescriptor)
|
||||
while (true) {
|
||||
getAndLogReadBytes()
|
||||
val packageIndex = compositeDecoder.decodeElementIndex(descriptor)
|
||||
if (packageIndex == DECODE_DONE) break
|
||||
readPackageMapEntry(
|
||||
decoder = compositeDecoder as JsonDecoder,
|
||||
index = packageIndex,
|
||||
repoId = repoId,
|
||||
appDataMap = appDataMap,
|
||||
)
|
||||
}
|
||||
@@ -131,7 +146,6 @@ public class IndexV1StreamProcessor(
|
||||
private fun readPackageMapEntry(
|
||||
decoder: JsonDecoder,
|
||||
index: Int,
|
||||
repoId: Long,
|
||||
appDataMap: Map<String, AppData>,
|
||||
) {
|
||||
val packageName = decoder.decodeStringElement(descriptor, index)
|
||||
@@ -142,7 +156,6 @@ public class IndexV1StreamProcessor(
|
||||
val compositeDecoder = decoder.beginStructure(listDescriptor)
|
||||
var isFirstVersion = true
|
||||
while (true) {
|
||||
getAndLogReadBytes()
|
||||
val packageIndex = compositeDecoder.decodeElementIndex(descriptor)
|
||||
if (packageIndex == DECODE_DONE) break
|
||||
val packageVersionV1 = decoder.decodeSerializableElement(
|
||||
@@ -159,17 +172,13 @@ public class IndexV1StreamProcessor(
|
||||
whatsNew = if (isFirstVersion) appDataMap[packageName]?.whatsNew else null
|
||||
)
|
||||
if (isFirstVersion) {
|
||||
indexStreamReceiver.updateAppMetadata(
|
||||
repoId,
|
||||
packageName,
|
||||
packageVersionV1.signer
|
||||
)
|
||||
indexStreamReceiver.updateAppMetadata(packageName, packageVersionV1.signer)
|
||||
}
|
||||
isFirstVersion = false
|
||||
val versionId = packageVersionV2.file.sha256
|
||||
versions[versionId] = packageVersionV2
|
||||
}
|
||||
indexStreamReceiver.receive(repoId, packageName, versions)
|
||||
indexStreamReceiver.receive(packageName, versions)
|
||||
compositeDecoder.endStructure(listDescriptor)
|
||||
}
|
||||
|
||||
@@ -177,17 +186,11 @@ public class IndexV1StreamProcessor(
|
||||
val antiFeatures = HashMap<String, AntiFeatureV2>()
|
||||
val categories = HashMap<String, CategoryV2>()
|
||||
appDataMap.values.forEach { appData ->
|
||||
appData.antiFeatures.keys.mapInto(
|
||||
antiFeatures,
|
||||
AntiFeatureV2(name = emptyMap(), description = emptyMap())
|
||||
)
|
||||
appData.categories.mapInto(
|
||||
categories,
|
||||
CategoryV2(name = emptyMap(), description = emptyMap())
|
||||
)
|
||||
appData.antiFeatures.mapInto(antiFeatures)
|
||||
appData.categories.mapInto(categories)
|
||||
}
|
||||
val releaseChannels = getV1ReleaseChannels()
|
||||
indexStreamReceiver.updateRepo(repoId, antiFeatures, categories, releaseChannels)
|
||||
indexStreamReceiver.updateRepo(antiFeatures, categories, releaseChannels)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: IndexV1?) {
|
||||
|
||||
@@ -12,26 +12,20 @@ import org.fdroid.index.IndexParser
|
||||
import java.io.InputStream
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
public class IndexStreamProcessor(
|
||||
private val indexStreamReceiver: IndexStreamReceiver,
|
||||
public class IndexV2StreamProcessor(
|
||||
private val indexStreamReceiver: IndexV2StreamReceiver,
|
||||
private val certificate: String?,
|
||||
private val json: Json = IndexParser.json,
|
||||
private val getAndLogReadBytes: () -> Long? = { null },
|
||||
) {
|
||||
|
||||
public fun process(repoId: Long, version: Int, inputStream: InputStream) {
|
||||
json.decodeFromStream(IndexStreamSerializer(repoId, version), inputStream)
|
||||
getAndLogReadBytes()
|
||||
public fun process(version: Int, inputStream: InputStream) {
|
||||
json.decodeFromStream(IndexStreamSerializer(version), inputStream)
|
||||
}
|
||||
|
||||
private inner class IndexStreamSerializer(
|
||||
val repoId: Long,
|
||||
val version: Int,
|
||||
) : KSerializer<IndexV2?> {
|
||||
private inner class IndexStreamSerializer(val version: Int) : KSerializer<IndexV2?> {
|
||||
override val descriptor = IndexV2.serializer().descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): IndexV2? {
|
||||
getAndLogReadBytes()
|
||||
decoder as? JsonDecoder ?: error("Can be deserialized only by JSON")
|
||||
|
||||
decoder.beginStructure(descriptor)
|
||||
@@ -40,49 +34,47 @@ public class IndexStreamProcessor(
|
||||
|
||||
when (val startIndex = decoder.decodeElementIndex(descriptor)) {
|
||||
repoIndex -> {
|
||||
deserializeRepo(decoder, startIndex, repoId)
|
||||
deserializeRepo(decoder, startIndex)
|
||||
val index = decoder.decodeElementIndex(descriptor)
|
||||
deserializePackages(decoder, index, repoId)
|
||||
if (index == packagesIndex) deserializePackages(decoder, index)
|
||||
}
|
||||
packagesIndex -> {
|
||||
deserializePackages(decoder, startIndex, repoId)
|
||||
deserializePackages(decoder, startIndex)
|
||||
val index = decoder.decodeElementIndex(descriptor)
|
||||
deserializeRepo(decoder, index, repoId)
|
||||
if (index == repoIndex) deserializeRepo(decoder, index)
|
||||
}
|
||||
else -> error("Unexpected startIndex: $startIndex")
|
||||
}
|
||||
decoder.endStructure(descriptor)
|
||||
indexStreamReceiver.onStreamEnded(repoId)
|
||||
indexStreamReceiver.onStreamEnded()
|
||||
return null
|
||||
}
|
||||
|
||||
private fun deserializeRepo(decoder: JsonDecoder, index: Int, repoId: Long) {
|
||||
private fun deserializeRepo(decoder: JsonDecoder, index: Int) {
|
||||
require(index == descriptor.getElementIndex("repo"))
|
||||
val repo = decoder.decodeSerializableValue(RepoV2.serializer())
|
||||
// TODO this replaces the index and thus removes all data, not good when repo is second
|
||||
indexStreamReceiver.receive(repoId, repo, version, certificate)
|
||||
indexStreamReceiver.receive(repo, version, certificate)
|
||||
}
|
||||
|
||||
private fun deserializePackages(decoder: JsonDecoder, index: Int, repoId: Long) {
|
||||
private fun deserializePackages(decoder: JsonDecoder, index: Int) {
|
||||
require(index == descriptor.getElementIndex("packages"))
|
||||
val mapDescriptor = descriptor.getElementDescriptor(index)
|
||||
val compositeDecoder = decoder.beginStructure(mapDescriptor)
|
||||
while (true) {
|
||||
getAndLogReadBytes()
|
||||
val packageIndex = compositeDecoder.decodeElementIndex(descriptor)
|
||||
if (packageIndex == CompositeDecoder.DECODE_DONE) break
|
||||
readMapEntry(compositeDecoder, packageIndex, repoId)
|
||||
readMapEntry(compositeDecoder, packageIndex)
|
||||
}
|
||||
compositeDecoder.endStructure(mapDescriptor)
|
||||
}
|
||||
|
||||
private fun readMapEntry(decoder: CompositeDecoder, index: Int, repoId: Long) {
|
||||
private fun readMapEntry(decoder: CompositeDecoder, index: Int) {
|
||||
val packageName = decoder.decodeStringElement(descriptor, index)
|
||||
decoder.decodeElementIndex(descriptor)
|
||||
val packageV2 = decoder.decodeSerializableElement(
|
||||
descriptor, index + 1, PackageV2.serializer()
|
||||
)
|
||||
indexStreamReceiver.receive(repoId, packageName, packageV2)
|
||||
indexStreamReceiver.receive(packageName, packageV2)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: IndexV2?) {
|
||||
@@ -1,8 +1,5 @@
|
||||
package org.fdroid.index.v1
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import org.fdroid.index.v2.AntiFeatureV2
|
||||
import org.fdroid.index.v2.CategoryV2
|
||||
import org.fdroid.index.v2.IndexV2
|
||||
@@ -11,101 +8,85 @@ import org.fdroid.index.v2.PackageV2
|
||||
import org.fdroid.index.v2.PackageVersionV2
|
||||
import org.fdroid.index.v2.ReleaseChannelV2
|
||||
import org.fdroid.index.v2.RepoV2
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.fdroid.test.TestDataEmptyV2
|
||||
import org.fdroid.test.TestDataMaxV2
|
||||
import org.fdroid.test.TestDataMidV2
|
||||
import org.fdroid.test.TestDataMinV2
|
||||
import org.fdroid.test.v1compat
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.fail
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
internal class IndexV1StreamProcessorTest {
|
||||
|
||||
private val json = Json
|
||||
|
||||
/**
|
||||
* Tests that indexV1 parsed with a stream receiver matches the indexV2 parsed normally.
|
||||
*/
|
||||
@Test
|
||||
fun testFDroidStreamProcessing() {
|
||||
val file1 = File("src/commonTest/resources/index-v1.json")
|
||||
val file2 = File("src/commonTest/resources/index-v2.json")
|
||||
assumeTrue(file1.isFile)
|
||||
assumeTrue(file2.isFile)
|
||||
val indexParsed: IndexV2 = FileInputStream(file2).use { json.decodeFromStream(it) }
|
||||
fun testEmpty() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-empty-v1.json",
|
||||
TestDataEmptyV2.index.v1compat())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMin() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-min-v1.json",
|
||||
TestDataMinV2.index.v1compat())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMid() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-mid-v1.json",
|
||||
TestDataMidV2.indexCompat)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMax() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-max-v1.json",
|
||||
TestDataMaxV2.indexCompat)
|
||||
}
|
||||
|
||||
private fun testStreamProcessing(filePath: String, indexV2: IndexV2) {
|
||||
val file = File(filePath)
|
||||
val testStreamReceiver = TestStreamReceiver()
|
||||
val streamProcessor = IndexV1StreamProcessor(testStreamReceiver, null, json = json)
|
||||
FileInputStream(file1).use { streamProcessor.process(1, it) }
|
||||
|
||||
assertEquals(indexParsed.repo, testStreamReceiver.repo)
|
||||
assertEquals(indexParsed.packages.size, testStreamReceiver.packages.size)
|
||||
indexParsed.packages.entries.forEach { (packageName, packageV2) ->
|
||||
assertEquals(packageV2, testStreamReceiver.packages[packageName])
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFDroidArchiveStreamProcessing() {
|
||||
testStreamProcessing("src/commonTest/resources/fdroid-archive/index-v1.json")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGuardianStreamProcessing() {
|
||||
testStreamProcessing("src/commonTest/resources/guardian/index-v1.json")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIzzyStreamProcessing() {
|
||||
testStreamProcessing("src/commonTest/resources/izzy/index-v1.json")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWindStreamProcessing() {
|
||||
testStreamProcessing("src/commonTest/resources/wind/index-v1.json")
|
||||
}
|
||||
|
||||
private fun testStreamProcessing(filePath1: String) {
|
||||
val file1 = File(filePath1)
|
||||
assumeTrue(file1.isFile)
|
||||
val testStreamReceiver = TestStreamReceiver()
|
||||
val streamProcessor = IndexV1StreamProcessor(testStreamReceiver, null, json = json)
|
||||
FileInputStream(file1).use { streamProcessor.process(1, it) }
|
||||
val streamProcessor = IndexV1StreamProcessor(testStreamReceiver, null)
|
||||
FileInputStream(file).use { streamProcessor.process(it) }
|
||||
assertEquals(indexV2.repo, testStreamReceiver.repo)
|
||||
assertEquals(indexV2.packages, testStreamReceiver.packages)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private class TestStreamReceiver : IndexV1StreamReceiver {
|
||||
var repo: RepoV2? = null
|
||||
val packages = HashMap<String, PackageV2>()
|
||||
|
||||
override fun receive(repoId: Long, repo: RepoV2, version: Int, certificate: String?) {
|
||||
override fun receive(repo: RepoV2, version: Int, certificate: String?) {
|
||||
this.repo = repo
|
||||
}
|
||||
|
||||
override fun receive(repoId: Long, packageId: String, m: MetadataV2) {
|
||||
override fun receive(packageId: String, m: MetadataV2) {
|
||||
packages[packageId] = PackageV2(
|
||||
metadata = m,
|
||||
versions = emptyMap(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun receive(repoId: Long, packageId: String, v: Map<String, PackageVersionV2>) {
|
||||
override fun receive(packageId: String, v: Map<String, PackageVersionV2>) {
|
||||
packages[packageId] = packages[packageId]!!.copy(versions = v)
|
||||
}
|
||||
|
||||
override fun updateRepo(
|
||||
repoId: Long,
|
||||
antiFeatures: Map<String, AntiFeatureV2>,
|
||||
categories: Map<String, CategoryV2>,
|
||||
releaseChannels: Map<String, ReleaseChannelV2>,
|
||||
) {
|
||||
repo = repo!!.copy(
|
||||
repo = repo?.copy(
|
||||
antiFeatures = antiFeatures,
|
||||
categories = categories,
|
||||
releaseChannels = releaseChannels,
|
||||
)
|
||||
) ?: fail()
|
||||
}
|
||||
|
||||
override fun updateAppMetadata(repoId: Long, packageId: String, preferredSigner: String?) {
|
||||
override fun updateAppMetadata(packageId: String, preferredSigner: String?) {
|
||||
val currentPackage = packages[packageId] ?: fail()
|
||||
packages[packageId] = currentPackage.copy(
|
||||
metadata = currentPackage.metadata.copy(preferredSigner = preferredSigner),
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package org.fdroid.index.v1
|
||||
|
||||
import io.ktor.utils.io.jvm.javaio.toByteReadChannel
|
||||
import io.ktor.utils.io.jvm.javaio.toInputStream
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import org.junit.Assume.assumeTrue
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import kotlin.test.Test
|
||||
|
||||
internal class StreamTest {
|
||||
|
||||
@Test
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
fun test() = runBlocking {
|
||||
val file = File("src/commonTest/resources/index-v1.json")
|
||||
assumeTrue(file.isFile)
|
||||
val byteChannel = FileInputStream(file).toByteReadChannel()
|
||||
val index = Json.decodeFromStream<IndexV1>(byteChannel.toInputStream())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package org.fdroid.index.v2
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import kotlinx.serialization.json.encodeToStream
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
private const val INDEX_V2 = "src/commonTest/resources/index-v2.json"
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
internal class IndexStreamProcessorTest {
|
||||
|
||||
@get:Rule
|
||||
var folder: TemporaryFolder = TemporaryFolder()
|
||||
|
||||
private val json = Json
|
||||
|
||||
/**
|
||||
* Tests that index parsed with a stream receiver matches the index parsed normally.
|
||||
*/
|
||||
@Test
|
||||
fun testStreamProcessing() {
|
||||
val file = File(INDEX_V2)
|
||||
assumeTrue(file.isFile)
|
||||
val indexParsed: IndexV2 = FileInputStream(file).use { json.decodeFromStream(it) }
|
||||
|
||||
val testStreamReceiver = TestStreamReceiver()
|
||||
val certificate = "foo bar"
|
||||
val streamProcessor = IndexStreamProcessor(testStreamReceiver, certificate, json)
|
||||
FileInputStream(file).use { streamProcessor.process(1, 42, it) }
|
||||
|
||||
assertEquals(indexParsed.repo, testStreamReceiver.repo)
|
||||
assertTrue(testStreamReceiver.calledOnStreamEnded)
|
||||
assertEquals(certificate, testStreamReceiver.certificate)
|
||||
assertEquals(indexParsed.packages.size, testStreamReceiver.packages.size)
|
||||
indexParsed.packages.entries.forEach { (packageName, packageV2) ->
|
||||
assertEquals(packageV2, testStreamReceiver.packages[packageName])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that that [IndexStreamProcessor] can handle a re-ordered index,
|
||||
* i.e. repo only after packages.
|
||||
*/
|
||||
@Test
|
||||
fun testReorderedStreamProcessing() {
|
||||
val file = File(INDEX_V2)
|
||||
assumeTrue(file.isFile)
|
||||
val indexParsed: IndexV2 = FileInputStream(file).use { json.decodeFromStream(it) }
|
||||
val newFile = folder.newFile()
|
||||
// write out parsed index in reverse order (repo after packages)
|
||||
FileOutputStream(newFile).use { outputStream ->
|
||||
outputStream.write("{ \"packages\": ".encodeToByteArray())
|
||||
json.encodeToStream(indexParsed.packages, outputStream)
|
||||
outputStream.write(", \"repo\": ".encodeToByteArray())
|
||||
json.encodeToStream(indexParsed.repo, outputStream)
|
||||
outputStream.write("}".encodeToByteArray())
|
||||
}
|
||||
val testStreamReceiver = ReorderedTestStreamReceiver()
|
||||
val certificate = "foo bar"
|
||||
val streamProcessor = IndexStreamProcessor(testStreamReceiver, certificate, json)
|
||||
FileInputStream(newFile).use { streamProcessor.process(1, 42, it) }
|
||||
|
||||
assertTrue(testStreamReceiver.repoReceived)
|
||||
assertTrue(testStreamReceiver.calledOnStreamEnded)
|
||||
assertEquals(indexParsed.repo, testStreamReceiver.repo)
|
||||
assertEquals(certificate, testStreamReceiver.certificate)
|
||||
assertEquals(indexParsed.packages.size, testStreamReceiver.packages.size)
|
||||
indexParsed.packages.entries.forEach { (packageName, packageV2) ->
|
||||
assertEquals(packageV2, testStreamReceiver.packages[packageName])
|
||||
}
|
||||
}
|
||||
|
||||
private open class TestStreamReceiver : IndexStreamReceiver {
|
||||
var repo: RepoV2? = null
|
||||
var certificate: String? = null
|
||||
val packages = HashMap<String, PackageV2>()
|
||||
var calledOnStreamEnded: Boolean = false
|
||||
|
||||
override fun receive(repoId: Long, repo: RepoV2, version: Int, certificate: String?) {
|
||||
this.repo = repo
|
||||
this.certificate = certificate
|
||||
}
|
||||
|
||||
override fun receive(repoId: Long, packageId: String, p: PackageV2) {
|
||||
packages[packageId] = p
|
||||
}
|
||||
|
||||
override fun onStreamEnded(repoId: Long) {
|
||||
if (calledOnStreamEnded) fail()
|
||||
calledOnStreamEnded = true
|
||||
}
|
||||
}
|
||||
|
||||
private class ReorderedTestStreamReceiver : TestStreamReceiver() {
|
||||
var repoReceived: Boolean = false
|
||||
|
||||
override fun receive(repoId: Long, repo: RepoV2, version: Int, certificate: String?) {
|
||||
super.receive(repoId, repo, version, certificate)
|
||||
assertFalse(repoReceived)
|
||||
repoReceived = true
|
||||
}
|
||||
|
||||
override fun receive(repoId: Long, packageId: String, p: PackageV2) {
|
||||
super.receive(repoId, packageId, p)
|
||||
assertFalse(repoReceived)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.fdroid.index.v2
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import org.fdroid.test.TestDataEmptyV2
|
||||
import org.fdroid.test.TestDataMaxV2
|
||||
import org.fdroid.test.TestDataMidV2
|
||||
import org.fdroid.test.TestDataMinV2
|
||||
import org.fdroid.test.TestUtils.getRandomString
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
internal class IndexV2StreamProcessorTest {
|
||||
|
||||
@get:Rule
|
||||
var folder: TemporaryFolder = TemporaryFolder()
|
||||
|
||||
@Test
|
||||
fun testEmpty() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-empty-v2.json", TestDataEmptyV2.index)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMin() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-min-v2.json", TestDataMinV2.index)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinReordered() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-min-reordered-v2.json",
|
||||
TestDataMinV2.index)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMid() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-mid-v2.json", TestDataMidV2.index)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMax() {
|
||||
testStreamProcessing("src/sharedTest/resources/index-max-v2.json", TestDataMaxV2.index)
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that index parsed with a stream receiver is equal to the expected test data.
|
||||
*/
|
||||
fun testStreamProcessing(filePath: String, index: IndexV2) {
|
||||
val file = File(filePath)
|
||||
val testStreamReceiver = TestStreamReceiver()
|
||||
val certificate = getRandomString()
|
||||
val streamProcessor = IndexV2StreamProcessor(testStreamReceiver, certificate)
|
||||
FileInputStream(file).use { streamProcessor.process(42, it) }
|
||||
|
||||
assertTrue(testStreamReceiver.calledOnStreamEnded)
|
||||
assertEquals(index.repo, testStreamReceiver.repo)
|
||||
assertEquals(certificate, testStreamReceiver.certificate)
|
||||
assertEquals(index.packages, testStreamReceiver.packages)
|
||||
}
|
||||
|
||||
private open class TestStreamReceiver : IndexV2StreamReceiver {
|
||||
var repo: RepoV2? = null
|
||||
var certificate: String? = null
|
||||
val packages = HashMap<String, PackageV2>()
|
||||
var calledOnStreamEnded: Boolean = false
|
||||
|
||||
override fun receive(repo: RepoV2, version: Int, certificate: String?) {
|
||||
this.repo = repo
|
||||
this.certificate = certificate
|
||||
}
|
||||
|
||||
override fun receive(packageId: String, p: PackageV2) {
|
||||
packages[packageId] = p
|
||||
}
|
||||
|
||||
override fun onStreamEnded() {
|
||||
if (calledOnStreamEnded) fail()
|
||||
calledOnStreamEnded = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.fdroid.index.v2
|
||||
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import org.fdroid.index.IndexParser.json
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@@ -15,14 +15,14 @@ internal class ReflectionDifferTest {
|
||||
put("en", "bar")
|
||||
put("de-DE", "foo bar")
|
||||
}
|
||||
val json = """
|
||||
val jsonInput = """
|
||||
{
|
||||
"de": "foo",
|
||||
"en": null,
|
||||
"en-US": "bar"
|
||||
}
|
||||
""".trimIndent()
|
||||
val diff = Json.parseToJsonElement(json).jsonObject
|
||||
val diff = json.parseToJsonElement(jsonInput).jsonObject
|
||||
val result = ReflectionDiffer.applyDiff(old, diff)
|
||||
|
||||
assertEquals(3, result.size)
|
||||
@@ -38,13 +38,13 @@ internal class ReflectionDifferTest {
|
||||
sha256 = "bar",
|
||||
size = Random.nextLong()
|
||||
)
|
||||
val json = """
|
||||
val jsonInput = """
|
||||
{
|
||||
"name": "foo bar",
|
||||
"size": null
|
||||
}
|
||||
""".trimIndent()
|
||||
val diff = Json.parseToJsonElement(json).jsonObject
|
||||
val diff = json.parseToJsonElement(jsonInput).jsonObject
|
||||
val result = ReflectionDiffer.applyDiff(old, diff)
|
||||
|
||||
assertEquals("foo bar", result.name)
|
||||
|
||||
@@ -39,14 +39,8 @@ public class IndexConverter(
|
||||
it.hash to it.toPackageVersionV2(versionReleaseChannels, appAntiFeatures, wn)
|
||||
} ?: emptyMap(),
|
||||
)
|
||||
appAntiFeatures.keys.mapInto(
|
||||
antiFeatures,
|
||||
AntiFeatureV2(name = emptyMap(), description = emptyMap())
|
||||
)
|
||||
app.categories.mapInto(
|
||||
categories,
|
||||
CategoryV2(name = emptyMap(), description = emptyMap())
|
||||
)
|
||||
appAntiFeatures.mapInto(antiFeatures)
|
||||
app.categories.mapInto(categories)
|
||||
packagesV2[app.packageName] = packageV2
|
||||
}
|
||||
return IndexV2(
|
||||
@@ -62,14 +56,29 @@ public class IndexConverter(
|
||||
|
||||
}
|
||||
|
||||
internal fun <T> Collection<String>.mapInto(map: HashMap<String, T>, value: T) {
|
||||
internal fun <T> Collection<String>.mapInto(map: HashMap<String, T>, valueGetter: (String) -> T) {
|
||||
forEach { key ->
|
||||
if (!map.containsKey(key)) map[key] = value
|
||||
if (!map.containsKey(key)) map[key] = valueGetter(key)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getV1ReleaseChannels() = mapOf(
|
||||
RELEASE_CHANNEL_BETA to ReleaseChannelV2(emptyMap(), emptyMap())
|
||||
internal fun List<String>.mapInto(map: HashMap<String, CategoryV2>) {
|
||||
mapInto(map) { key ->
|
||||
CategoryV2(name = mapOf(DEFAULT_LOCALE to key))
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Map<String, LocalizedTextV2>.mapInto(map: HashMap<String, AntiFeatureV2>) {
|
||||
keys.mapInto(map) { key ->
|
||||
AntiFeatureV2(name = mapOf(DEFAULT_LOCALE to key))
|
||||
}
|
||||
}
|
||||
|
||||
public fun getV1ReleaseChannels(): Map<String, ReleaseChannelV2> = mapOf(
|
||||
RELEASE_CHANNEL_BETA to ReleaseChannelV2(
|
||||
name = mapOf(DEFAULT_LOCALE to RELEASE_CHANNEL_BETA),
|
||||
description = emptyMap(),
|
||||
)
|
||||
)
|
||||
|
||||
internal fun <T> Map<String, Localized>.mapValuesNotNull(
|
||||
|
||||
@@ -78,8 +78,8 @@ public data class AppV1(
|
||||
litecoin = litecoin,
|
||||
flattrID = flattrID,
|
||||
).takeIf { !it.isNull },
|
||||
icon = icon?.let { mapOf(locale to FileV2("/icons/$it")) }
|
||||
?: localized.toLocalizedFileV2 { it.icon },
|
||||
icon = localized.toLocalizedFileV2 { it.icon }
|
||||
?: icon?.let { mapOf(locale to FileV2("/icons/$it")) },
|
||||
featureGraphic = localized.toLocalizedFileV2 { it.featureGraphic },
|
||||
promoGraphic = localized.toLocalizedFileV2 { it.promoGraphic },
|
||||
tvBanner = localized.toLocalizedFileV2 { it.tvBanner },
|
||||
|
||||
@@ -13,9 +13,9 @@ import org.fdroid.index.v2.RepoV2
|
||||
@Serializable
|
||||
public data class IndexV1(
|
||||
val repo: RepoV1,
|
||||
val requests: Requests,
|
||||
val apps: List<AppV1>,
|
||||
val packages: Map<String, List<PackageV1>>,
|
||||
val requests: Requests = Requests(emptyList(), emptyList()),
|
||||
val apps: List<AppV1> = emptyList(),
|
||||
val packages: Map<String, List<PackageV1>> = emptyMap(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
||||
@@ -10,12 +10,11 @@ import org.fdroid.index.v2.RepoV2
|
||||
@Deprecated("Use IndexV2 instead")
|
||||
public interface IndexV1StreamReceiver {
|
||||
|
||||
public fun receive(repoId: Long, repo: RepoV2, version: Int, certificate: String?)
|
||||
public fun receive(repoId: Long, packageId: String, m: MetadataV2)
|
||||
public fun receive(repoId: Long, packageId: String, v: Map<String, PackageVersionV2>)
|
||||
public fun receive(repo: RepoV2, version: Int, certificate: String?)
|
||||
public fun receive(packageId: String, m: MetadataV2)
|
||||
public fun receive(packageId: String, v: Map<String, PackageVersionV2>)
|
||||
|
||||
public fun updateRepo(
|
||||
repoId: Long,
|
||||
antiFeatures: Map<String, AntiFeatureV2>,
|
||||
categories: Map<String, CategoryV2>,
|
||||
releaseChannels: Map<String, ReleaseChannelV2>,
|
||||
@@ -25,6 +24,6 @@ public interface IndexV1StreamReceiver {
|
||||
* Updates [MetadataV2.preferredSigner] with the given [preferredSigner]
|
||||
* for the given [packageId].
|
||||
*/
|
||||
public fun updateAppMetadata(repoId: Long, packageId: String, preferredSigner: String?)
|
||||
public fun updateAppMetadata(packageId: String, preferredSigner: String?)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package org.fdroid.index.v1
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||
import kotlinx.serialization.descriptors.element
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.encoding.encodeCollection
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonDecoder
|
||||
import kotlinx.serialization.json.intOrNull
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
@@ -84,7 +88,7 @@ public data class PackageV1(
|
||||
@Serializable(with = PermissionV1Serializer::class)
|
||||
public data class PermissionV1(
|
||||
val name: String,
|
||||
val maxSdk: Int?,
|
||||
val maxSdk: Int? = null,
|
||||
)
|
||||
|
||||
internal class PermissionV1Serializer : KSerializer<PermissionV1> {
|
||||
@@ -102,8 +106,12 @@ internal class PermissionV1Serializer : KSerializer<PermissionV1> {
|
||||
return PermissionV1(name, maxSdk)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
override fun serialize(encoder: Encoder, value: PermissionV1) {
|
||||
TODO("Not yet implemented")
|
||||
encoder.encodeCollection(JsonArray.serializer().descriptor, 2) {
|
||||
encodeStringElement(descriptor, 0, value.name)
|
||||
encodeNullableSerializableElement(descriptor, 1, Int.serializer(), value.maxSdk)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package org.fdroid.index.v2
|
||||
|
||||
public interface IndexStreamReceiver {
|
||||
|
||||
public fun receive(repoId: Long, repo: RepoV2, version: Int, certificate: String?)
|
||||
public fun receive(repoId: Long, packageId: String, p: PackageV2)
|
||||
public fun onStreamEnded(repoId: Long)
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public data class FileV2(
|
||||
@Serializable
|
||||
public data class IndexV2(
|
||||
val repo: RepoV2,
|
||||
val packages: Map<String, PackageV2>,
|
||||
val packages: Map<String, PackageV2> = emptyMap(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.fdroid.index.v2
|
||||
|
||||
public interface IndexV2StreamReceiver {
|
||||
|
||||
/**
|
||||
* Receives the [RepoV2] from the index stream.
|
||||
* Attention: This might get called after receiving packages.
|
||||
*/
|
||||
public fun receive(repo: RepoV2, version: Int, certificate: String?)
|
||||
|
||||
/**
|
||||
* Receives one [PackageV2] from the index stream.
|
||||
* This is called once for each package in the index.
|
||||
*/
|
||||
public fun receive(packageId: String, p: PackageV2)
|
||||
|
||||
/**
|
||||
* Called when the stream has been processed to its end.
|
||||
*/
|
||||
public fun onStreamEnded()
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
public data class PackageV2(
|
||||
val metadata: MetadataV2,
|
||||
val versions: Map<String, PackageVersionV2>,
|
||||
val versions: Map<String, PackageVersionV2> = emptyMap(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
||||
@@ -1,40 +1,51 @@
|
||||
package org.fdroid.index
|
||||
|
||||
import com.goncalossilva.resources.Resource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.fdroid.index.v1.IndexV1
|
||||
import org.fdroid.index.IndexParser.parseV1
|
||||
import org.fdroid.index.v2.IndexV2
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.fdroid.test.TestDataEmptyV2
|
||||
import org.fdroid.test.TestDataMaxV2
|
||||
import org.fdroid.test.TestDataMidV2
|
||||
import org.fdroid.test.TestDataMinV2
|
||||
import org.fdroid.test.TestUtils.sorted
|
||||
import org.fdroid.test.v1compat
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class IndexConverterTest {
|
||||
|
||||
@Test
|
||||
fun testToIndexV2() {
|
||||
val res1 = Resource("src/commonTest/resources/index-v1.json")
|
||||
assumeTrue(res1.exists())
|
||||
val indexV1Str = res1.readText()
|
||||
val indexV1 = Json.decodeFromString<IndexV1>(indexV1Str)
|
||||
fun testEmpty() {
|
||||
testConversation("src/sharedTest/resources/index-empty-v1.json",
|
||||
TestDataEmptyV2.index.v1compat())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMin() {
|
||||
testConversation("src/sharedTest/resources/index-min-v1.json",
|
||||
TestDataMinV2.index.v1compat())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMid() {
|
||||
testConversation("src/sharedTest/resources/index-mid-v1.json",
|
||||
TestDataMidV2.indexCompat)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMax() {
|
||||
testConversation("src/sharedTest/resources/index-max-v1.json",
|
||||
TestDataMaxV2.indexCompat)
|
||||
}
|
||||
|
||||
private fun testConversation(file: String, expectedIndex: IndexV2) {
|
||||
val indexV1Res = Resource(file)
|
||||
val indexV1Str = indexV1Res.readText()
|
||||
val indexV1 = parseV1(indexV1Str)
|
||||
|
||||
val v2 = IndexConverter().toIndexV2(indexV1)
|
||||
|
||||
val res2 = Resource("src/commonTest/resources/index-v2.json")
|
||||
assumeTrue(res2.exists())
|
||||
val indexV2Str = res2.readText()
|
||||
val indexV2 = Json.decodeFromString<IndexV2>(indexV2Str)
|
||||
|
||||
assertEquals(
|
||||
indexV2.repo,
|
||||
v2.repo.copy(
|
||||
antiFeatures = emptyMap(), categories = emptyMap(), releaseChannels = emptyMap()
|
||||
)
|
||||
) // TODO remove copies when test data is fixed
|
||||
assertEquals(indexV2.packages.size, v2.packages.size)
|
||||
indexV2.packages.keys.forEach { packageName ->
|
||||
assertEquals(indexV2.packages[packageName], v2.packages[packageName])
|
||||
}
|
||||
assertEquals(expectedIndex.sorted(), v2.sorted())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,40 +1,46 @@
|
||||
package org.fdroid.index.v1
|
||||
|
||||
import com.goncalossilva.resources.Resource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.fdroid.index.IndexParser.parseV1
|
||||
import org.fdroid.test.TestDataEmptyV1
|
||||
import org.fdroid.test.TestDataMaxV1
|
||||
import org.fdroid.test.TestDataMidV1
|
||||
import org.fdroid.test.TestDataMinV1
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class IndexV1Test {
|
||||
|
||||
@Test
|
||||
fun testIndexV1() {
|
||||
val indexRes = Resource("src/commonTest/resources/index-v1.json")
|
||||
assumeTrue(indexRes.exists())
|
||||
fun testIndexEmptyV1() {
|
||||
val indexRes = Resource("src/sharedTest/resources/index-empty-v1.json")
|
||||
val indexStr = indexRes.readText()
|
||||
val index = Json.decodeFromString<IndexV1>(indexStr)
|
||||
val index = parseV1(indexStr)
|
||||
assertEquals(TestDataEmptyV1.index, index)
|
||||
}
|
||||
|
||||
val indexArchiveRes = Resource("src/commonTest/resources/fdroid-archive/index-v1.json")
|
||||
assumeTrue(indexArchiveRes.exists())
|
||||
val indexArchiveStr = indexArchiveRes.readText()
|
||||
assumeTrue(indexRes.exists())
|
||||
Json.decodeFromString<IndexV1>(indexArchiveStr)
|
||||
@Test
|
||||
fun testIndexMinV1() {
|
||||
val indexRes = Resource("src/sharedTest/resources/index-min-v1.json")
|
||||
val indexStr = indexRes.readText()
|
||||
val index = parseV1(indexStr)
|
||||
assertEquals(TestDataMinV1.index, index)
|
||||
}
|
||||
|
||||
val indexGuardianRes = Resource("src/commonTest/resources/guardian/index-v1.json")
|
||||
assumeTrue(indexGuardianRes.exists())
|
||||
val indexGuardianStr = indexGuardianRes.readText()
|
||||
Json.decodeFromString<IndexV1>(indexGuardianStr)
|
||||
@Test
|
||||
fun testIndexMidV1() {
|
||||
val indexRes = Resource("src/sharedTest/resources/index-mid-v1.json")
|
||||
val indexStr = indexRes.readText()
|
||||
val index = parseV1(indexStr)
|
||||
assertEquals(TestDataMidV1.index, index)
|
||||
}
|
||||
|
||||
val indexIzzyRes = Resource("src/commonTest/resources/izzy/index-v1.json")
|
||||
assumeTrue(indexIzzyRes.exists())
|
||||
val indexIzzyStr = indexIzzyRes.readText()
|
||||
Json.decodeFromString<IndexV1>(indexIzzyStr)
|
||||
|
||||
val indexWindRes = Resource("src/commonTest/resources/wind/index-v1.json")
|
||||
assumeTrue(indexWindRes.exists())
|
||||
val indexWindStr = indexWindRes.readText()
|
||||
Json.decodeFromString<IndexV1>(indexWindStr)
|
||||
@Test
|
||||
fun testIndexMaxV1() {
|
||||
val indexRes = Resource("src/sharedTest/resources/index-max-v1.json")
|
||||
val indexStr = indexRes.readText()
|
||||
val index = parseV1(indexStr)
|
||||
assertEquals(TestDataMaxV1.index, index)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,33 +1,48 @@
|
||||
package org.fdroid.index.v2
|
||||
|
||||
import com.goncalossilva.resources.Resource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.fdroid.index.IndexParser.parseV2
|
||||
import org.fdroid.test.TestDataEmptyV2
|
||||
import org.fdroid.test.TestDataMaxV2
|
||||
import org.fdroid.test.TestDataMidV2
|
||||
import org.fdroid.test.TestDataMinV2
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class IndexV2Test {
|
||||
|
||||
@Test
|
||||
fun testIndexV2() {
|
||||
val entryRes = Resource("src/commonTest/resources/entry.json")
|
||||
assumeTrue(entryRes.exists())
|
||||
val entryStr = entryRes.readText()
|
||||
val entry = Json.decodeFromString<EntryV2>(entryStr)
|
||||
|
||||
val indexRes = Resource("src/commonTest/resources/index-v2.json")
|
||||
assumeTrue(indexRes.exists())
|
||||
val indexStr = indexRes.readText()
|
||||
val index = Json.decodeFromString<IndexV2>(indexStr)
|
||||
fun testEmpty() {
|
||||
testIndexEquality("src/sharedTest/resources/index-empty-v2.json", TestDataEmptyV2.index)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDiffV2() {
|
||||
// val diff1Res = Resource("src/commonTest/resources/tmp.json")
|
||||
// assumeTrue(diff1Res.exists())
|
||||
// val diff1Str = diff1Res.readText()
|
||||
// val diff1 = Json.decodeFromString<DiffV2>(diff1Str)
|
||||
// println(diff1)
|
||||
fun testMin() {
|
||||
testIndexEquality("src/sharedTest/resources/index-min-v2.json", TestDataMinV2.index)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinReordered() {
|
||||
testIndexEquality("src/sharedTest/resources/index-min-reordered-v2.json",
|
||||
TestDataMinV2.index)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMid() {
|
||||
testIndexEquality("src/sharedTest/resources/index-mid-v2.json", TestDataMidV2.index)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMax() {
|
||||
testIndexEquality("src/sharedTest/resources/index-max-v2.json", TestDataMaxV2.index)
|
||||
}
|
||||
|
||||
private fun testIndexEquality(file: String, expectedIndex: IndexV2) {
|
||||
val indexV2Res = Resource(file)
|
||||
val indexV2Str = indexV2Res.readText()
|
||||
val indexV2 = parseV2(indexV2Str)
|
||||
|
||||
assertEquals(expectedIndex, indexV2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
615
index/src/sharedTest/kotlin/org/fdroid/test/TestDataV1.kt
Normal file
615
index/src/sharedTest/kotlin/org/fdroid/test/TestDataV1.kt
Normal file
@@ -0,0 +1,615 @@
|
||||
package org.fdroid.test
|
||||
|
||||
import org.fdroid.index.v1.AppV1
|
||||
import org.fdroid.index.v1.IndexV1
|
||||
import org.fdroid.index.v1.Localized
|
||||
import org.fdroid.index.v1.PackageV1
|
||||
import org.fdroid.index.v1.PermissionV1
|
||||
import org.fdroid.index.v1.RepoV1
|
||||
import org.fdroid.index.v1.Requests
|
||||
|
||||
internal object TestDataEmptyV1 {
|
||||
val repo = RepoV1(
|
||||
timestamp = 23,
|
||||
version = 23,
|
||||
name = "EmptyV1",
|
||||
icon = "empty-v1.png",
|
||||
address = "https://empty-v1.org",
|
||||
description = "This is a repo with empty data.",
|
||||
)
|
||||
val index = IndexV1(
|
||||
repo = repo,
|
||||
)
|
||||
}
|
||||
|
||||
internal object TestDataMinV1 {
|
||||
|
||||
val repo = RepoV1(
|
||||
timestamp = 42,
|
||||
version = 1,
|
||||
name = "MinV1",
|
||||
icon = "min-v1.png",
|
||||
address = "https://min-v1.org",
|
||||
description = "This is a repo with minimal data.",
|
||||
)
|
||||
|
||||
const val packageName = "org.fdroid.min1"
|
||||
val app = AppV1(
|
||||
packageName = packageName,
|
||||
categories = emptyList(),
|
||||
antiFeatures = emptyList(),
|
||||
license = "",
|
||||
)
|
||||
val apps = listOf(app)
|
||||
|
||||
val version = PackageV1(
|
||||
packageName = packageName,
|
||||
apkName = "${packageName}_23.apk",
|
||||
hash = "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
hashType = "sha256",
|
||||
size = 1337,
|
||||
versionName = "0",
|
||||
)
|
||||
val versions = listOf(version)
|
||||
val packages = mapOf(packageName to versions)
|
||||
|
||||
val index = IndexV1(
|
||||
repo = repo,
|
||||
requests = Requests(emptyList(), emptyList()),
|
||||
apps = apps,
|
||||
packages = packages,
|
||||
)
|
||||
}
|
||||
|
||||
internal object TestDataMidV1 {
|
||||
|
||||
val repo = RepoV1(
|
||||
timestamp = 1337,
|
||||
version = 1,
|
||||
maxAge = 23,
|
||||
name = "MidV1",
|
||||
icon = "mid-v1.png",
|
||||
address = "https://mid-v1.org",
|
||||
description = "This is a repo with medium data.",
|
||||
mirrors = listOf("https://mid-v1.com"),
|
||||
)
|
||||
|
||||
const val packageName1 = TestDataMinV1.packageName
|
||||
const val packageName2 = "org.fdroid.fdroid"
|
||||
val categories = listOf("Cat1", "Cat2", "Cat3")
|
||||
val app1 = TestDataMinV1.app.copy(
|
||||
packageName = packageName1,
|
||||
categories = listOf(categories[0]),
|
||||
antiFeatures = listOf("AntiFeature"),
|
||||
summary = "App1 summary",
|
||||
description = "App1 description",
|
||||
name = "App1",
|
||||
authorName = "App1 author",
|
||||
license = "GPLv3",
|
||||
webSite = "http://min1.test.org",
|
||||
added = 1234567890,
|
||||
icon = "icon-min1.png",
|
||||
lastUpdated = 1234567891,
|
||||
localized = mapOf(
|
||||
"de" to Localized(
|
||||
description = "App1 beschreibung",
|
||||
name = "app 1 name",
|
||||
summary = "App1 Zusammenfassung",
|
||||
),
|
||||
),
|
||||
)
|
||||
val app2 = AppV1(
|
||||
categories = listOf("System"),
|
||||
antiFeatures = emptyList(),
|
||||
changelog = "https://gitlab.com/fdroid/fdroidclient/raw/HEAD/CHANGELOG.md",
|
||||
translation = "https://hosted.weblate.org/projects/f-droid/f-droid",
|
||||
issueTracker = "https://gitlab.com/fdroid/fdroidclient/issues",
|
||||
sourceCode = "https://gitlab.com/fdroid/fdroidclient",
|
||||
donate = "https://f-droid.org/donate",
|
||||
liberapayID = "27859",
|
||||
openCollective = "F-Droid-Euro",
|
||||
flattrID = "343053",
|
||||
suggestedVersionName = "1.14",
|
||||
suggestedVersionCode = "1014050",
|
||||
license = "GPL-3.0-or-later",
|
||||
webSite = "https://f-droid.org",
|
||||
added = 1295222400000,
|
||||
icon = "org.fdroid.fdroid.1014050.png",
|
||||
packageName = "org.fdroid.fdroid",
|
||||
lastUpdated = 1643250075000,
|
||||
localized = mapOf(
|
||||
"af" to Localized(
|
||||
description = "F-Droid is 'n installeerbare katalogus van gratis sagteware",
|
||||
name = "-درويد",
|
||||
summary = "متجر التطبيقات الذي يحترم الحرية والخصوصية)",
|
||||
),
|
||||
"be" to Localized(
|
||||
name = "F-Droid",
|
||||
summary = "Крама праграм, якая паважае свабоду і прыватнасць",
|
||||
),
|
||||
"bg" to Localized(
|
||||
summary = "Магазинът за приложения, който уважава независимостта и поверителността",
|
||||
),
|
||||
"bn" to Localized(
|
||||
name = "এফ-ড্রয়েড",
|
||||
summary = "যে অ্যাপ স্টোর স্বাধীনতা ও গোপনীয়তা সম্মান করে"
|
||||
),
|
||||
"bo" to Localized(
|
||||
description = "ཨེཕ་རོཌ་ནི་ཨེན་ཀྲོཌ་བབ་སྟེགས་ཀྱི་ཆེད་དུ་FOSS",
|
||||
summary = "རང་དབང་དང་གསང་དོན་ལ་གུས་བརྩི་ཞུས་མཁན་གྱི་མཉེན་ཆས་ཉར་ཚགས་ཁང་།",
|
||||
),
|
||||
"ca" to Localized(
|
||||
description = "F-Droid és un catàleg instal·lable d'aplicacions de software lliure",
|
||||
name = "F-Droid",
|
||||
summary = "La botiga d'aplicacions que respecta la llibertat i la privacitat",
|
||||
),
|
||||
"cs" to Localized(
|
||||
description = "F-Droid je instalovatelný katalog softwarových libre",
|
||||
name = "F-Droid",
|
||||
summary = "Zdroj aplikací který respektuje vaši svobodu a soukromí",
|
||||
),
|
||||
"cy" to Localized(
|
||||
description = "Mae F-Droid yn gatalog y gellir ei osod o apiau meddalwedd rhydd" +
|
||||
"ar gyfer Android.",
|
||||
name = "F-Droid",
|
||||
summary = "Yr ystorfa apiau sy'n parchu rhyddid a phreifatrwydd",
|
||||
),
|
||||
"de" to Localized(
|
||||
description = "F-Droid ist ein installierbarer Katalog mit Libre Software" +
|
||||
"Android-Apps.",
|
||||
summary = "Der App-Store, der Freiheit und Privatsphäre respektiert",
|
||||
),
|
||||
"el" to Localized(
|
||||
description = "Το F-Droid είναι ένας κατάλογος εφαρμογών ελεύθερου λογισμικού",
|
||||
name = "F-Droid",
|
||||
summary = "Το κατάστημα εφαρμογών που σέβεται την ελευθερία και την ιδιωτικότητα",
|
||||
),
|
||||
"en-US" to Localized(
|
||||
description = "F-Droid is an installable catalogue of libre software",
|
||||
name = "F-Droid",
|
||||
whatsNew = "* Overhaul Share menu to use built-in options like Nearby",
|
||||
phoneScreenshots = listOf(
|
||||
"screenshot-app-details.png",
|
||||
"screenshot-dark-details.png",
|
||||
"screenshot-dark-home.png",
|
||||
"screenshot-dark-knownvuln.png",
|
||||
"screenshot-knownvuln.png",
|
||||
"screenshot-search.png",
|
||||
"screenshot-updates.png",
|
||||
),
|
||||
featureGraphic = "featureGraphic_PTun9TO4cMFOeiqbvQSrkdcxNUcOFQCymMIaj9UJOAY=.jpg",
|
||||
summary = "The app store that respects freedom and privacy",
|
||||
),
|
||||
"eo" to Localized(
|
||||
description = "F-Droid estas instalebla katalogo de liberaj aplikaĵoj por Android.",
|
||||
name = "F-Droid",
|
||||
whatsNew = "• rekonstruita menuo “Kunhavigi” por uzi enkonstruitajn eblojn, ekz.",
|
||||
summary = "Aplikaĵa vendejo respektanta liberecon kaj privatecon",
|
||||
),
|
||||
),
|
||||
)
|
||||
val apps = listOf(app1, app2)
|
||||
|
||||
val version1_1 = TestDataMinV1.version.copy(
|
||||
added = 2342,
|
||||
apkName = "${packageName1}_23_2.apk",
|
||||
size = 1338,
|
||||
srcName = "${packageName1}_23_2.zip",
|
||||
usesPermission = listOf(PermissionV1("perm")),
|
||||
usesPermission23 = emptyList(),
|
||||
versionCode = 1,
|
||||
versionName = "1",
|
||||
nativeCode = listOf("x86"),
|
||||
features = listOf("feature"),
|
||||
antiFeatures = listOf("anti-feature"),
|
||||
)
|
||||
val version1_2 = PackageV1(
|
||||
packageName = packageName1,
|
||||
apkName = "${packageName1}_42.apk",
|
||||
hash = "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
hashType = "sha256",
|
||||
minSdkVersion = 21,
|
||||
maxSdkVersion = 4568,
|
||||
targetSdkVersion = 32,
|
||||
sig = "old",
|
||||
signer = "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
size = 1337,
|
||||
srcName = "${packageName1}_42.zip",
|
||||
versionCode = 24,
|
||||
versionName = "24",
|
||||
)
|
||||
|
||||
val version2_1 = PackageV1(
|
||||
added = 1643250075000,
|
||||
apkName = "org.fdroid.fdroid_1014050.apk",
|
||||
hash = "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06",
|
||||
hashType = "sha256",
|
||||
minSdkVersion = 22,
|
||||
targetSdkVersion = 25,
|
||||
packageName = "org.fdroid.fdroid",
|
||||
sig = "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
signer = "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
size = 8165518,
|
||||
srcName = "org.fdroid.fdroid_1014050_src.tar.gz",
|
||||
usesPermission = listOf(
|
||||
PermissionV1(name = "android.permission.INTERNET"),
|
||||
PermissionV1(name = "android.permission.ACCESS_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.ACCESS_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_MULTICAST_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH_ADMIN"),
|
||||
PermissionV1(name = "android.permission.RECEIVE_BOOT_COMPLETED"),
|
||||
PermissionV1(name = "android.permission.READ_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_SETTINGS"),
|
||||
PermissionV1(name = "android.permission.NFC"),
|
||||
PermissionV1(name = "android.permission.USB_PERMISSION", maxSdk = 22),
|
||||
PermissionV1(name = "android.permission.WAKE_LOCK"),
|
||||
PermissionV1(name = "android.permission.FOREGROUND_SERVICE")
|
||||
),
|
||||
usesPermission23 = listOf(PermissionV1(name = "android.permission.ACCESS_COARSE_LOCATION")),
|
||||
versionCode = 1014050,
|
||||
versionName = "1.14",
|
||||
)
|
||||
val version2_2 = PackageV1(
|
||||
added = 1642785071000,
|
||||
apkName = "org.fdroid.fdroid_1014005.apk",
|
||||
hash = "b4282febf5558d43c7c51a00478961f6df1b6d59e0a6674974cdacb792683e5d",
|
||||
hashType = "sha256",
|
||||
minSdkVersion = 22,
|
||||
targetSdkVersion = 25,
|
||||
packageName = "org.fdroid.fdroid",
|
||||
sig = "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
signer = "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
size = 8382606,
|
||||
srcName = "org.fdroid.fdroid_1014005_src.tar.gz",
|
||||
usesPermission = listOf(
|
||||
PermissionV1(name = "android.permission.INTERNET"),
|
||||
PermissionV1(name = "android.permission.ACCESS_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.ACCESS_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_MULTICAST_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH_ADMIN"),
|
||||
PermissionV1(name = "android.permission.RECEIVE_BOOT_COMPLETED"),
|
||||
PermissionV1(name = "android.permission.READ_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_SETTINGS"),
|
||||
PermissionV1(name = "android.permission.NFC"),
|
||||
PermissionV1(name = "android.permission.USB_PERMISSION", maxSdk = 22),
|
||||
PermissionV1(name = "android.permission.WAKE_LOCK"),
|
||||
PermissionV1(name = "android.permission.FOREGROUND_SERVICE")
|
||||
),
|
||||
usesPermission23 = listOf(PermissionV1(name = "android.permission.ACCESS_COARSE_LOCATION")),
|
||||
versionCode = 1014005,
|
||||
versionName = "1.14-alpha5",
|
||||
nativeCode = listOf("fakeNativeCode"),
|
||||
features = listOf("fake feature"),
|
||||
antiFeatures = listOf("FakeAntiFeature")
|
||||
)
|
||||
val version2_3 = PackageV1(
|
||||
added = 1635169849000,
|
||||
apkName = "org.fdroid.fdroid_1014003.apk",
|
||||
hash = "c062a9642fde08aacabbfa4cab1ab5773c83f4e6b81551ffd92027d2b20f37d3",
|
||||
hashType = "sha256",
|
||||
minSdkVersion = 22,
|
||||
targetSdkVersion = 25,
|
||||
packageName = "org.fdroid.fdroid",
|
||||
sig = "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
signer = "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
size = 8276110,
|
||||
srcName = "org.fdroid.fdroid_1014003_src.tar.gz",
|
||||
usesPermission = listOf(
|
||||
PermissionV1(name = "android.permission.INTERNET"),
|
||||
PermissionV1(name = "android.permission.ACCESS_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.ACCESS_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_MULTICAST_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH_ADMIN"),
|
||||
PermissionV1(name = "android.permission.RECEIVE_BOOT_COMPLETED"),
|
||||
PermissionV1(name = "android.permission.READ_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_SETTINGS"),
|
||||
PermissionV1(name = "android.permission.NFC"),
|
||||
PermissionV1(name = "android.permission.USB_PERMISSION", maxSdk = 22),
|
||||
PermissionV1(name = "android.permission.WAKE_LOCK"),
|
||||
PermissionV1(name = "android.permission.FOREGROUND_SERVICE"),
|
||||
),
|
||||
usesPermission23 = listOf(PermissionV1(name = "android.permission.ACCESS_COARSE_LOCATION")),
|
||||
versionCode = 1014003,
|
||||
versionName = "1.14-alpha3",
|
||||
)
|
||||
val version2_4 = PackageV1(
|
||||
added = 1632281731000,
|
||||
apkName = "org.fdroid.fdroid_1014002.apk",
|
||||
hash = "3243c24ee95be0fce0830d72e7d2605e3e24f6ccf4ee72a7c8e720fccd7621a1",
|
||||
hashType = "sha256",
|
||||
minSdkVersion = 22,
|
||||
targetSdkVersion = 25,
|
||||
packageName = "org.fdroid.fdroid",
|
||||
sig = "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
signer = "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
size = 8284386,
|
||||
srcName = "org.fdroid.fdroid_1014002_src.tar.gz",
|
||||
usesPermission = listOf(
|
||||
PermissionV1(name = "android.permission.INTERNET"),
|
||||
PermissionV1(name = "android.permission.ACCESS_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.ACCESS_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_MULTICAST_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH_ADMIN"),
|
||||
PermissionV1(name = "android.permission.RECEIVE_BOOT_COMPLETED"),
|
||||
PermissionV1(name = "android.permission.READ_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_SETTINGS"),
|
||||
PermissionV1(name = "android.permission.NFC"),
|
||||
PermissionV1(name = "android.permission.USB_PERMISSION", maxSdk = 22),
|
||||
PermissionV1(name = "android.permission.WAKE_LOCK"),
|
||||
PermissionV1(name = "android.permission.FOREGROUND_SERVICE"),
|
||||
),
|
||||
usesPermission23 = listOf(PermissionV1(name = "android.permission.ACCESS_COARSE_LOCATION")),
|
||||
versionCode = 1014002,
|
||||
versionName = "1.14-alpha2",
|
||||
)
|
||||
val version2_5 = PackageV1(
|
||||
added = 1632281729000,
|
||||
apkName = "org.fdroid.fdroid_1014001.apk",
|
||||
hash = "7ebfd5eb76f9ec95ba955e549260fe930dc38fb99ed3532f92c93b879aca5610",
|
||||
hashType = "sha256",
|
||||
minSdkVersion = 22,
|
||||
targetSdkVersion = 25,
|
||||
packageName = "org.fdroid.fdroid",
|
||||
sig = "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
signer = "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
size = 8272166,
|
||||
srcName = "org.fdroid.fdroid_1014001_src.tar.gz",
|
||||
usesPermission = listOf(
|
||||
PermissionV1(name = "android.permission.INTERNET"),
|
||||
PermissionV1(name = "android.permission.ACCESS_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.ACCESS_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_MULTICAST_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH_ADMIN"),
|
||||
PermissionV1(name = "android.permission.RECEIVE_BOOT_COMPLETED"),
|
||||
PermissionV1(name = "android.permission.READ_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_SETTINGS"),
|
||||
PermissionV1(name = "android.permission.NFC"),
|
||||
PermissionV1(name = "android.permission.USB_PERMISSION", maxSdk = 22),
|
||||
PermissionV1(name = "android.permission.WAKE_LOCK"),
|
||||
PermissionV1(name = "android.permission.FOREGROUND_SERVICE"),
|
||||
),
|
||||
usesPermission23 = listOf(PermissionV1(name = "android.permission.ACCESS_COARSE_LOCATION")),
|
||||
versionCode = 1014001,
|
||||
versionName = "1.14-alpha1",
|
||||
)
|
||||
val versions1 = listOf(version1_1, version1_2)
|
||||
val versions2 = listOf(version2_1, version2_2, version2_3, version2_4, version2_5)
|
||||
val packages = mapOf(
|
||||
packageName1 to versions1,
|
||||
packageName2 to versions2,
|
||||
)
|
||||
|
||||
val index = IndexV1(
|
||||
repo = repo,
|
||||
requests = Requests(listOf("installThis"), listOf("uninstallThis")),
|
||||
apps = apps,
|
||||
packages = packages,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
internal object TestDataMaxV1 {
|
||||
|
||||
val repo = RepoV1(
|
||||
timestamp = Long.MAX_VALUE,
|
||||
version = Int.MAX_VALUE,
|
||||
maxAge = Int.MAX_VALUE,
|
||||
name = "MaxV1",
|
||||
icon = "max-v1.png",
|
||||
address = "https://max-v1.org",
|
||||
description = "This is a repo with maximum data.",
|
||||
mirrors = listOf("https://max-v1.com", "https://max-v1.org"),
|
||||
)
|
||||
|
||||
const val packageName1 = TestDataMidV1.packageName1
|
||||
const val packageName2 = TestDataMidV1.packageName2
|
||||
const val packageName3 = "Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moo" +
|
||||
"dahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5Ung" +
|
||||
"ohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raeph" +
|
||||
"oowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y"
|
||||
val categories = listOf("Cat1", "Cat2", "Cat3")
|
||||
|
||||
val app2 = TestDataMidV1.app2.copy(
|
||||
categories = listOf("NoMoreSystem", "OneMore"),
|
||||
antiFeatures = listOf("AddOne"),
|
||||
summary = "new summary",
|
||||
description = "new description",
|
||||
webSite = "https://fdroid.org",
|
||||
binaries = "https://fdroid.org/binaries",
|
||||
name = "F-DroidX",
|
||||
localized = mapOf(
|
||||
"ch" to Localized(
|
||||
description = "new desc",
|
||||
name = "new name",
|
||||
summary = "new summary",
|
||||
tenInchScreenshots = listOf("new screenshots"),
|
||||
whatsNew = "This is new!"
|
||||
),
|
||||
"de" to Localized(
|
||||
summary = "Der App-Store, der Freiheit und Privatsphäre respektiert",
|
||||
),
|
||||
"en-US" to Localized(
|
||||
description = "F-Droid is an installable catalogue of libre software",
|
||||
summary = "new summary in en-US",
|
||||
phoneScreenshots = listOf(
|
||||
"screenshot-app-details.png",
|
||||
"screenshot-dark-details.png",
|
||||
"screenshot-dark-home.png",
|
||||
"screenshot-search.png",
|
||||
"screenshot-updates.png",
|
||||
),
|
||||
featureGraphic = "featureGraphic_PTun9TO4cMFOeiqbvQSrkdcxNUcOFQCymMIaj9UJOAY=.jpg",
|
||||
icon = "new icon",
|
||||
),
|
||||
),
|
||||
)
|
||||
val app3 = AppV1(
|
||||
packageName = packageName3,
|
||||
categories = categories,
|
||||
antiFeatures = listOf("AntiFeature", "NonFreeNet", "NotNice", "VeryBad", "Dont,Show,This"),
|
||||
summary = "App3 summary",
|
||||
description = "App3 description",
|
||||
changelog = "changeLog3",
|
||||
translation = "translation3",
|
||||
issueTracker = "tracker3",
|
||||
sourceCode = "source code3",
|
||||
binaries = "binaries3",
|
||||
name = "App3",
|
||||
authorName = "App3 author",
|
||||
authorEmail = "email",
|
||||
authorWebSite = "website",
|
||||
authorPhone = "phone",
|
||||
donate = "donate",
|
||||
liberapayID = "liberapayID",
|
||||
liberapay = "liberapay",
|
||||
openCollective = "openCollective",
|
||||
bitcoin = "bitcoin",
|
||||
litecoin = "litecoin",
|
||||
flattrID = "flattrID",
|
||||
suggestedVersionName = "1.0",
|
||||
suggestedVersionCode = Long.MIN_VALUE.toString(),
|
||||
license = "GPLv3",
|
||||
webSite = "http://min1.test.org",
|
||||
added = 1234567890,
|
||||
icon = "icon-max1.png",
|
||||
lastUpdated = Long.MAX_VALUE,
|
||||
localized = mapOf(
|
||||
LOCALE to Localized(
|
||||
whatsNew = "this is new",
|
||||
),
|
||||
"de" to Localized(
|
||||
whatsNew = "das ist neu",
|
||||
),
|
||||
"en" to Localized(
|
||||
description = "en ",
|
||||
name = "en ",
|
||||
icon = "en ",
|
||||
video = "en ",
|
||||
phoneScreenshots = listOf("en phoneScreenshots", "en phoneScreenshots2"),
|
||||
sevenInchScreenshots = listOf("en sevenInchScreenshots",
|
||||
"en sevenInchScreenshots2"),
|
||||
tenInchScreenshots = listOf("en tenInchScreenshots", "en tenInchScreenshots2"),
|
||||
wearScreenshots = listOf("en wearScreenshots", "en wearScreenshots2"),
|
||||
tvScreenshots = listOf("en tvScreenshots", "en tvScreenshots2"),
|
||||
featureGraphic = "en ",
|
||||
promoGraphic = "en ",
|
||||
tvBanner = "en ",
|
||||
summary = "en ",
|
||||
)
|
||||
),
|
||||
allowedAPKSigningKeys = listOf("key1, key2"),
|
||||
)
|
||||
val apps = listOf(TestDataMidV1.app1, app2, app3)
|
||||
|
||||
val version2_2 = TestDataMidV1.version2_2.copy(
|
||||
usesPermission = emptyList(),
|
||||
usesPermission23 = emptyList(),
|
||||
nativeCode = emptyList(),
|
||||
features = emptyList(),
|
||||
antiFeatures = emptyList(),
|
||||
)
|
||||
val version2_3 = TestDataMidV1.version2_3.copy(
|
||||
minSdkVersion = 22,
|
||||
targetSdkVersion = 25,
|
||||
packageName = "org.fdroid.fdroid",
|
||||
sig = "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
signer = "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
size = 8276110,
|
||||
srcName = "org.fdroid.fdroid_1014003_src.tar.gz",
|
||||
usesPermission = listOf(
|
||||
PermissionV1(name = "android.permission.ACCESS_MEDIA"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_STATE", maxSdk = 32),
|
||||
PermissionV1(name = "android.permission.READ_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.NFC"),
|
||||
PermissionV1(name = "android.permission.USB_PERMISSION", maxSdk = 22),
|
||||
PermissionV1(name = "android.permission.WAKE_LOCK"),
|
||||
PermissionV1(name = "android.permission.READ_MY_ASS"),
|
||||
PermissionV1(name = "android.permission.FOREGROUND_SERVICE"),
|
||||
),
|
||||
usesPermission23 = listOf(
|
||||
PermissionV1(name = "android.permission.ACCESS_FINE_LOCATION"),
|
||||
PermissionV1(name = "android.permission.ACCESS_COARSE_LOCATION", maxSdk = 3),
|
||||
),
|
||||
versionCode = 1014003,
|
||||
versionName = "1.14-alpha3",
|
||||
)
|
||||
val version3_1 = PackageV1(
|
||||
added = 1643250075000,
|
||||
apkName = "org.fdroid.fdroid_1014050.apk",
|
||||
hash = "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06",
|
||||
hashType = "sha256",
|
||||
minSdkVersion = 22,
|
||||
maxSdkVersion = Int.MAX_VALUE,
|
||||
targetSdkVersion = 25,
|
||||
packageName = "org.fdroid.fdroid",
|
||||
sig = "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
signer = "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
size = 8165518,
|
||||
srcName = "org.fdroid.fdroid_1014050_src.tar.gz",
|
||||
usesPermission = listOf(
|
||||
PermissionV1(name = "android.permission.INTERNET"),
|
||||
PermissionV1(name = "android.permission.ACCESS_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.ACCESS_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_MULTICAST_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_NETWORK_STATE"),
|
||||
PermissionV1(name = "android.permission.CHANGE_WIFI_STATE"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH"),
|
||||
PermissionV1(name = "android.permission.BLUETOOTH_ADMIN"),
|
||||
PermissionV1(name = "android.permission.RECEIVE_BOOT_COMPLETED"),
|
||||
PermissionV1(name = "android.permission.READ_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_EXTERNAL_STORAGE"),
|
||||
PermissionV1(name = "android.permission.WRITE_SETTINGS"),
|
||||
PermissionV1(name = "android.permission.NFC"),
|
||||
PermissionV1(name = "android.permission.USB_PERMISSION", maxSdk = 22),
|
||||
PermissionV1(name = "android.permission.WAKE_LOCK"),
|
||||
PermissionV1(name = "android.permission.FOREGROUND_SERVICE")
|
||||
),
|
||||
usesPermission23 = listOf(
|
||||
PermissionV1(name = "android.permission.ACCESS_COARSE_LOCATION"),
|
||||
PermissionV1(name = "android.permission.USB_PERMISSION", maxSdk = Int.MAX_VALUE),
|
||||
),
|
||||
versionCode = 1014050,
|
||||
versionName = "1.14",
|
||||
nativeCode = listOf("x86", "x86_64"),
|
||||
features = listOf("feature", "feature2"),
|
||||
antiFeatures = listOf("anti-feature", "anti-feature2"),
|
||||
)
|
||||
val versions1 = TestDataMidV1.versions1
|
||||
val versions2 = listOf(
|
||||
version2_2, version2_3, TestDataMidV1.version2_4, TestDataMidV1.version2_5
|
||||
)
|
||||
val versions3 = listOf(version3_1)
|
||||
val packages = mapOf(
|
||||
packageName1 to versions1,
|
||||
packageName2 to versions2,
|
||||
packageName3 to versions3,
|
||||
)
|
||||
|
||||
val index = IndexV1(
|
||||
repo = repo,
|
||||
requests = Requests(listOf("installThis", "installThat"), listOf("uninstallThis")),
|
||||
apps = apps,
|
||||
packages = packages,
|
||||
)
|
||||
}
|
||||
1260
index/src/sharedTest/kotlin/org/fdroid/test/TestDataV2.kt
Normal file
1260
index/src/sharedTest/kotlin/org/fdroid/test/TestDataV2.kt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
package org.fdroid.test
|
||||
|
||||
import org.fdroid.index.v2.IndexV2
|
||||
import kotlin.random.Random
|
||||
|
||||
public object TestUtils {
|
||||
@@ -34,4 +35,26 @@ public object TestUtils {
|
||||
return if (Random.nextBoolean()) null else this
|
||||
}
|
||||
|
||||
public fun IndexV2.sorted(): IndexV2 = copy(
|
||||
packages = packages.toSortedMap().mapValues { entry ->
|
||||
entry.value.copy(
|
||||
metadata = entry.value.metadata.copy(
|
||||
name = entry.value.metadata.name?.toSortedMap(),
|
||||
summary = entry.value.metadata.summary?.toSortedMap(),
|
||||
description = entry.value.metadata.description?.toSortedMap(),
|
||||
icon = entry.value.metadata.icon?.toSortedMap(),
|
||||
),
|
||||
versions = entry.value.versions.mapValues {
|
||||
val pv = it.value
|
||||
pv.copy(
|
||||
manifest = pv.manifest.copy(
|
||||
usesPermission = pv.manifest.usesPermission.sortedBy { p -> p.name },
|
||||
usesPermissionSdk23 = pv.manifest.usesPermissionSdk23.sortedBy { p -> p.name }
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
10
index/src/sharedTest/resources/index-empty-v1.json
Normal file
10
index/src/sharedTest/resources/index-empty-v1.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"repo": {
|
||||
"timestamp": 23,
|
||||
"version": 23,
|
||||
"name": "EmptyV1",
|
||||
"icon": "empty-v1.png",
|
||||
"address": "https://empty-v1.org",
|
||||
"description": "This is a repo with empty data."
|
||||
}
|
||||
}
|
||||
15
index/src/sharedTest/resources/index-empty-v2.json
Normal file
15
index/src/sharedTest/resources/index-empty-v2.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"repo": {
|
||||
"name": "EmptyV1",
|
||||
"icon": {
|
||||
"name": "/icons/empty-v1.png",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 32492
|
||||
},
|
||||
"address": "https://empty-v1.org",
|
||||
"description": {
|
||||
"en-US": "This is a repo with empty data."
|
||||
},
|
||||
"timestamp": 23
|
||||
}
|
||||
}
|
||||
600
index/src/sharedTest/resources/index-max-v1.json
Normal file
600
index/src/sharedTest/resources/index-max-v1.json
Normal file
@@ -0,0 +1,600 @@
|
||||
{
|
||||
"repo": {
|
||||
"timestamp": 9223372036854775807,
|
||||
"version": 2147483647,
|
||||
"maxage": 2147483647,
|
||||
"name": "MaxV1",
|
||||
"icon": "max-v1.png",
|
||||
"address": "https://max-v1.org",
|
||||
"description": "This is a repo with maximum data.",
|
||||
"mirrors": [
|
||||
"https://max-v1.com",
|
||||
"https://max-v1.org"
|
||||
]
|
||||
},
|
||||
"requests": {
|
||||
"install": [
|
||||
"installThis",
|
||||
"installThat"
|
||||
],
|
||||
"uninstall": [
|
||||
"uninstallThis"
|
||||
]
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"categories": [
|
||||
"Cat1"
|
||||
],
|
||||
"antiFeatures": [
|
||||
"AntiFeature"
|
||||
],
|
||||
"summary": "App1 summary",
|
||||
"description": "App1 description",
|
||||
"name": "App1",
|
||||
"authorName": "App1 author",
|
||||
"license": "GPLv3",
|
||||
"webSite": "http://min1.test.org",
|
||||
"added": 1234567890,
|
||||
"icon": "icon-min1.png",
|
||||
"packageName": "org.fdroid.min1",
|
||||
"lastUpdated": 1234567891,
|
||||
"localized": {
|
||||
"de": {
|
||||
"description": "App1 beschreibung",
|
||||
"name": "app 1 name",
|
||||
"summary": "App1 Zusammenfassung"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"categories": [
|
||||
"NoMoreSystem",
|
||||
"OneMore"
|
||||
],
|
||||
"antiFeatures": [
|
||||
"AddOne"
|
||||
],
|
||||
"summary": "new summary",
|
||||
"description": "new description",
|
||||
"changelog": "https://gitlab.com/fdroid/fdroidclient/raw/HEAD/CHANGELOG.md",
|
||||
"translation": "https://hosted.weblate.org/projects/f-droid/f-droid",
|
||||
"issueTracker": "https://gitlab.com/fdroid/fdroidclient/issues",
|
||||
"sourceCode": "https://gitlab.com/fdroid/fdroidclient",
|
||||
"binaries": "https://fdroid.org/binaries",
|
||||
"name": "F-DroidX",
|
||||
"donate": "https://f-droid.org/donate",
|
||||
"liberapayID": "27859",
|
||||
"openCollective": "F-Droid-Euro",
|
||||
"flattrID": "343053",
|
||||
"suggestedVersionName": "1.14",
|
||||
"suggestedVersionCode": "1014050",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"webSite": "https://fdroid.org",
|
||||
"added": 1295222400000,
|
||||
"icon": "org.fdroid.fdroid.1014050.png",
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"lastUpdated": 1643250075000,
|
||||
"localized": {
|
||||
"ch": {
|
||||
"description": "new desc",
|
||||
"name": "new name",
|
||||
"whatsNew": "This is new!",
|
||||
"tenInchScreenshots": [
|
||||
"new screenshots"
|
||||
],
|
||||
"summary": "new summary"
|
||||
},
|
||||
"de": {
|
||||
"summary": "Der App-Store, der Freiheit und Privatsphäre respektiert"
|
||||
},
|
||||
"en-US": {
|
||||
"description": "F-Droid is an installable catalogue of libre software",
|
||||
"icon": "new icon",
|
||||
"phoneScreenshots": [
|
||||
"screenshot-app-details.png",
|
||||
"screenshot-dark-details.png",
|
||||
"screenshot-dark-home.png",
|
||||
"screenshot-search.png",
|
||||
"screenshot-updates.png"
|
||||
],
|
||||
"featureGraphic": "featureGraphic_PTun9TO4cMFOeiqbvQSrkdcxNUcOFQCymMIaj9UJOAY=.jpg",
|
||||
"summary": "new summary in en-US"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"categories": [
|
||||
"Cat1",
|
||||
"Cat2",
|
||||
"Cat3"
|
||||
],
|
||||
"antiFeatures": [
|
||||
"AntiFeature",
|
||||
"NonFreeNet",
|
||||
"NotNice",
|
||||
"VeryBad",
|
||||
"Dont,Show,This"
|
||||
],
|
||||
"summary": "App3 summary",
|
||||
"description": "App3 description",
|
||||
"changelog": "changeLog3",
|
||||
"translation": "translation3",
|
||||
"issueTracker": "tracker3",
|
||||
"sourceCode": "source code3",
|
||||
"binaries": "binaries3",
|
||||
"name": "App3",
|
||||
"authorName": "App3 author",
|
||||
"authorEmail": "email",
|
||||
"authorWebSite": "website",
|
||||
"authorPhone": "phone",
|
||||
"donate": "donate",
|
||||
"liberapayID": "liberapayID",
|
||||
"liberapay": "liberapay",
|
||||
"openCollective": "openCollective",
|
||||
"bitcoin": "bitcoin",
|
||||
"litecoin": "litecoin",
|
||||
"flattrID": "flattrID",
|
||||
"suggestedVersionName": "1.0",
|
||||
"suggestedVersionCode": "-9223372036854775808",
|
||||
"license": "GPLv3",
|
||||
"webSite": "http://min1.test.org",
|
||||
"added": 1234567890,
|
||||
"icon": "icon-max1.png",
|
||||
"packageName": "Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y",
|
||||
"lastUpdated": 9223372036854775807,
|
||||
"localized": {
|
||||
"en-US": {
|
||||
"whatsNew": "this is new"
|
||||
},
|
||||
"de": {
|
||||
"whatsNew": "das ist neu"
|
||||
},
|
||||
"en": {
|
||||
"description": "en ",
|
||||
"name": "en ",
|
||||
"icon": "en ",
|
||||
"video": "en ",
|
||||
"phoneScreenshots": [
|
||||
"en phoneScreenshots",
|
||||
"en phoneScreenshots2"
|
||||
],
|
||||
"sevenInchScreenshots": [
|
||||
"en sevenInchScreenshots",
|
||||
"en sevenInchScreenshots2"
|
||||
],
|
||||
"tenInchScreenshots": [
|
||||
"en tenInchScreenshots",
|
||||
"en tenInchScreenshots2"
|
||||
],
|
||||
"wearScreenshots": [
|
||||
"en wearScreenshots",
|
||||
"en wearScreenshots2"
|
||||
],
|
||||
"tvScreenshots": [
|
||||
"en tvScreenshots",
|
||||
"en tvScreenshots2"
|
||||
],
|
||||
"featureGraphic": "en ",
|
||||
"promoGraphic": "en ",
|
||||
"tvBanner": "en ",
|
||||
"summary": "en "
|
||||
}
|
||||
},
|
||||
"allowedAPKSigningKeys": [
|
||||
"key1, key2"
|
||||
]
|
||||
}
|
||||
],
|
||||
"packages": {
|
||||
"org.fdroid.min1": [
|
||||
{
|
||||
"added": 2342,
|
||||
"apkName": "org.fdroid.min1_23_2.apk",
|
||||
"hash": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"hashType": "sha256",
|
||||
"packageName": "org.fdroid.min1",
|
||||
"size": 1338,
|
||||
"srcname": "org.fdroid.min1_23_2.zip",
|
||||
"uses-permission": [
|
||||
[
|
||||
"perm",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1,
|
||||
"versionName": "1",
|
||||
"nativecode": [
|
||||
"x86"
|
||||
],
|
||||
"features": [
|
||||
"feature"
|
||||
],
|
||||
"antiFeatures": [
|
||||
"anti-feature"
|
||||
]
|
||||
},
|
||||
{
|
||||
"apkName": "org.fdroid.min1_42.apk",
|
||||
"hash": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 21,
|
||||
"maxSdkVersion": 4568,
|
||||
"targetSdkVersion": 32,
|
||||
"packageName": "org.fdroid.min1",
|
||||
"sig": "old",
|
||||
"signer": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1337,
|
||||
"srcname": "org.fdroid.min1_42.zip",
|
||||
"versionCode": 24,
|
||||
"versionName": "24"
|
||||
}
|
||||
],
|
||||
"org.fdroid.fdroid": [
|
||||
{
|
||||
"added": 1642785071000,
|
||||
"apkName": "org.fdroid.fdroid_1014005.apk",
|
||||
"hash": "b4282febf5558d43c7c51a00478961f6df1b6d59e0a6674974cdacb792683e5d",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8382606,
|
||||
"srcname": "org.fdroid.fdroid_1014005_src.tar.gz",
|
||||
"versionCode": 1014005,
|
||||
"versionName": "1.14-alpha5",
|
||||
"nativecode": [
|
||||
],
|
||||
"features": [
|
||||
],
|
||||
"antiFeatures": [
|
||||
]
|
||||
},
|
||||
{
|
||||
"added": 1635169849000,
|
||||
"apkName": "org.fdroid.fdroid_1014003.apk",
|
||||
"hash": "c062a9642fde08aacabbfa4cab1ab5773c83f4e6b81551ffd92027d2b20f37d3",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8276110,
|
||||
"srcname": "org.fdroid.fdroid_1014003_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.ACCESS_MEDIA",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
32
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_MY_ASS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
3
|
||||
]
|
||||
],
|
||||
"versionCode": 1014003,
|
||||
"versionName": "1.14-alpha3"
|
||||
},
|
||||
{
|
||||
"added": 1632281731000,
|
||||
"apkName": "org.fdroid.fdroid_1014002.apk",
|
||||
"hash": "3243c24ee95be0fce0830d72e7d2605e3e24f6ccf4ee72a7c8e720fccd7621a1",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8284386,
|
||||
"srcname": "org.fdroid.fdroid_1014002_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.INTERNET",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH_ADMIN",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.RECEIVE_BOOT_COMPLETED",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_SETTINGS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1014002,
|
||||
"versionName": "1.14-alpha2"
|
||||
},
|
||||
{
|
||||
"added": 1632281729000,
|
||||
"apkName": "org.fdroid.fdroid_1014001.apk",
|
||||
"hash": "7ebfd5eb76f9ec95ba955e549260fe930dc38fb99ed3532f92c93b879aca5610",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8272166,
|
||||
"srcname": "org.fdroid.fdroid_1014001_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.INTERNET",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH_ADMIN",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.RECEIVE_BOOT_COMPLETED",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_SETTINGS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1014001,
|
||||
"versionName": "1.14-alpha1"
|
||||
}
|
||||
],
|
||||
"Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y": [
|
||||
{
|
||||
"added": 1643250075000,
|
||||
"apkName": "org.fdroid.fdroid_1014050.apk",
|
||||
"hash": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"maxSdkVersion": 2147483647,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8165518,
|
||||
"srcname": "org.fdroid.fdroid_1014050_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.INTERNET",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH_ADMIN",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.RECEIVE_BOOT_COMPLETED",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_SETTINGS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
2147483647
|
||||
]
|
||||
],
|
||||
"versionCode": 1014050,
|
||||
"versionName": "1.14",
|
||||
"nativecode": [
|
||||
"x86",
|
||||
"x86_64"
|
||||
],
|
||||
"features": [
|
||||
"feature",
|
||||
"feature2"
|
||||
],
|
||||
"antiFeatures": [
|
||||
"anti-feature",
|
||||
"anti-feature2"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
853
index/src/sharedTest/resources/index-max-v2.json
Normal file
853
index/src/sharedTest/resources/index-max-v2.json
Normal file
@@ -0,0 +1,853 @@
|
||||
{
|
||||
"repo": {
|
||||
"name": "MaxV1",
|
||||
"icon": {
|
||||
"name": "/icons/max-v1.png",
|
||||
"sha256": "14758e480ae76297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 9223372036854775807
|
||||
},
|
||||
"address": "https://max-v1.org",
|
||||
"webBaseUrl": "https://www.max-v1.org",
|
||||
"description": {
|
||||
"en-US": "This is a repo with maximum data.",
|
||||
"de": "Dies ist ein Repo mit maximaler Datendichte."
|
||||
},
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://max-v1.com",
|
||||
"location": "us"
|
||||
},
|
||||
{
|
||||
"url": "https://max-v1.org",
|
||||
"location": "nl"
|
||||
}
|
||||
],
|
||||
"timestamp": 9223372036854775807,
|
||||
"antiFeatures": {
|
||||
"VeryBad": {
|
||||
"name": {
|
||||
}
|
||||
},
|
||||
"Dont,Show,This": {
|
||||
"name": {
|
||||
}
|
||||
},
|
||||
"NotNice": {
|
||||
"name": {
|
||||
}
|
||||
},
|
||||
"AntiFeature": {
|
||||
"icon": {
|
||||
"name": "/icons/antifeature.png",
|
||||
"sha256": "24758e480ae66297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 254916
|
||||
},
|
||||
"name": {
|
||||
"en-US": "AntiFeature"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "A bad anti-feature, we can't show to users."
|
||||
}
|
||||
},
|
||||
"NonFreeNet": {
|
||||
"name": {
|
||||
"en-US": "NonFreeNet"
|
||||
}
|
||||
},
|
||||
"AddOne": {
|
||||
"name": {
|
||||
"en-US": "AddOne anti feature"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "A bad anti-feature, that was added in an update."
|
||||
}
|
||||
}
|
||||
},
|
||||
"categories": {
|
||||
"Cat3": {
|
||||
"icon": {
|
||||
"name": "/icons/cat3.png",
|
||||
"sha256": "54758e480ae76297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 9223372036854775807
|
||||
},
|
||||
"name": {
|
||||
"en-US": "Cat3"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "Cat3"
|
||||
}
|
||||
},
|
||||
"Cat2": {
|
||||
"icon": {
|
||||
"name": "/icons/cat2.png",
|
||||
"sha256": "54758e480ae76297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 9223372036854775807
|
||||
},
|
||||
"name": {
|
||||
"en-US": "Cat3"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "Cat3"
|
||||
}
|
||||
},
|
||||
"Cat1": {
|
||||
"icon": {
|
||||
"name": "/icons/cat1.png",
|
||||
"sha256": "54758e480ae76297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 9223372036854775807
|
||||
},
|
||||
"name": {
|
||||
"en-US": "Cat1"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "Cat1"
|
||||
}
|
||||
},
|
||||
"NoMoreSystem": {
|
||||
"name": {
|
||||
}
|
||||
},
|
||||
"OneMore": {
|
||||
"name": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"releaseChannels": {
|
||||
"Alpha": {
|
||||
"name": {
|
||||
"de": "channel name alpha"
|
||||
},
|
||||
"description": {
|
||||
"de-DE": "channel desc alpha"
|
||||
}
|
||||
},
|
||||
"Beta": {
|
||||
"name": {
|
||||
"en-US": "channel name"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "channel desc"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages": {
|
||||
"org.fdroid.min1": {
|
||||
"metadata": {
|
||||
"name": {
|
||||
"en-US": "App1",
|
||||
"de": "app 1 name"
|
||||
},
|
||||
"summary": {
|
||||
"en-US": "App1 summary",
|
||||
"de": "App1 Zusammenfassung"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "App1 description",
|
||||
"de": "App1 beschreibung"
|
||||
},
|
||||
"added": 1234567890,
|
||||
"lastUpdated": 1234567891,
|
||||
"webSite": "http://min1.test.org",
|
||||
"license": "GPLv3",
|
||||
"categories": [
|
||||
"Cat1"
|
||||
],
|
||||
"author": {
|
||||
"name": "App1 author"
|
||||
},
|
||||
"icon": {
|
||||
"en-US": {
|
||||
"name": "/icons/icon-min1.png",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1337
|
||||
}
|
||||
}
|
||||
},
|
||||
"versions": {
|
||||
"824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf": {
|
||||
"added": 0,
|
||||
"file": {
|
||||
"name": "/org.fdroid.min1_42.apk",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1337
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.min1_42.zip",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1338
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "24",
|
||||
"versionCode": 24,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 21,
|
||||
"targetSdkVersion": 32
|
||||
},
|
||||
"maxSdkVersion": 4568,
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf"
|
||||
]
|
||||
}
|
||||
},
|
||||
"releaseChannels": [
|
||||
"Beta"
|
||||
],
|
||||
"antiFeatures": {
|
||||
"AntiFeature": {
|
||||
"en-US": "reason"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"org.fdroid.fdroid": {
|
||||
"metadata": {
|
||||
"name": {
|
||||
"en-US": "F-DroidX",
|
||||
"ch": "new name"
|
||||
},
|
||||
"summary": {
|
||||
"en-US": "new summary in en-US",
|
||||
"ch": "new summary",
|
||||
"de": "Der App-Store, der Freiheit und Privatsphäre respektiert"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "F-Droid is an installable catalogue of libre software",
|
||||
"ch": "new desc"
|
||||
},
|
||||
"added": 1295222400000,
|
||||
"lastUpdated": 1643250075000,
|
||||
"webSite": "https://fdroid.org",
|
||||
"changelog": "https://gitlab.com/fdroid/fdroidclient/raw/HEAD/CHANGELOG.md",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"sourceCode": "https://gitlab.com/fdroid/fdroidclient",
|
||||
"issueTracker": "https://gitlab.com/fdroid/fdroidclient/issues",
|
||||
"translation": "https://hosted.weblate.org/projects/f-droid/f-droid",
|
||||
"preferredSigner": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"categories": [
|
||||
"NoMoreSystem",
|
||||
"OneMore"
|
||||
],
|
||||
"donation": {
|
||||
"url": "https://f-droid.org/donate",
|
||||
"liberapayID": "27859",
|
||||
"openCollective": "F-Droid-Euro",
|
||||
"flattrID": "343053"
|
||||
},
|
||||
"icon": {
|
||||
"en-US": {
|
||||
"name": "/org.fdroid.fdroid/en-US/new icon",
|
||||
"sha256": "324a109b2352138c3699760e1683385d1ed50ce526fc7982f8d65757743374ba",
|
||||
"size": 2233
|
||||
}
|
||||
},
|
||||
"featureGraphic": {
|
||||
"en-US": {
|
||||
"name": "/org.fdroid.fdroid/en-US/featureGraphic_PTun9TO4cMFOeiqbvQSrkdcxNUcOFQCymMIaj9UJOAY=.jpg",
|
||||
"sha256": "424a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 4237
|
||||
}
|
||||
},
|
||||
"screenshots": {
|
||||
"phone": {
|
||||
"en-US": [
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-app-details.png",
|
||||
"sha256": "424a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 4237
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-dark-details.png",
|
||||
"sha256": "424a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 44287
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-dark-home.png",
|
||||
"sha256": "424a109b2352138c3699760e1673385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 4587
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-search.png",
|
||||
"sha256": "424a109b2352138c3694760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 2857
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-updates.png",
|
||||
"sha256": "424a109b2352138c3699750e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 485286
|
||||
}
|
||||
]
|
||||
},
|
||||
"tenInch": {
|
||||
"ch": [
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/ch/tenInchScreenshots/new screenshots",
|
||||
"sha256": "54758e380ae76297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": -9223372036854775808
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"versions": {
|
||||
"b4282febf5558d43c7c51a00478961f6df1b6d59e0a6674974cdacb792683e5d": {
|
||||
"added": 1642785071000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014005.apk",
|
||||
"sha256": "b4282febf5558d43c7c51a00478961f6df1b6d59e0a6674974cdacb792683e5d",
|
||||
"size": 8382606
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014005_src.tar.gz",
|
||||
"sha256": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d07",
|
||||
"size": 8165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14-alpha5",
|
||||
"versionCode": 1014005,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
}
|
||||
},
|
||||
"antiFeatures": {
|
||||
"AddOne": {
|
||||
"en-US": "was added this update"
|
||||
}
|
||||
},
|
||||
"whatsNew": {
|
||||
"ch": "This is new!"
|
||||
}
|
||||
},
|
||||
"c062a9642fde08aacabbfa4cab1ab5773c83f4e6b81551ffd92027d2b20f37d3": {
|
||||
"added": 1635169849000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014003.apk",
|
||||
"sha256": "c062a9642fde08aacabbfa4cab1ab5773c83f4e6b81551ffd92027d2b20f37d3",
|
||||
"size": 8276110
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014003_src.tar.gz",
|
||||
"sha256": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cb067d510ac6f3e0d07",
|
||||
"size": 8165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14-alpha3",
|
||||
"versionCode": 1014003,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_MEDIA"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE",
|
||||
"maxSdkVersion": 32
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_MY_ASS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_FINE_LOCATION"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION",
|
||||
"maxSdkVersion": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
"antiFeatures": {
|
||||
"AddOne": {
|
||||
"en-US": "was added this update"
|
||||
}
|
||||
}
|
||||
},
|
||||
"3243c24ee95be0fce0830d72e7d2605e3e24f6ccf4ee72a7c8e720fccd7621a1": {
|
||||
"added": 1632281731000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014002.apk",
|
||||
"sha256": "3243c24ee95be0fce0830d72e7d2605e3e24f6ccf4ee72a7c8e720fccd7621a1",
|
||||
"size": 8284386
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014002_src.tar.gz",
|
||||
"sha256": "7c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cb067d510ac6f3e0d07",
|
||||
"size": 7165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14-alpha2",
|
||||
"versionCode": 1014002,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH_ADMIN"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_SETTINGS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION"
|
||||
}
|
||||
]
|
||||
},
|
||||
"antiFeatures": {
|
||||
"AddOne": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"7ebfd5eb76f9ec95ba955e549260fe930dc38fb99ed3532f92c93b879aca5610": {
|
||||
"added": 1632281729000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014001.apk",
|
||||
"sha256": "7ebfd5eb76f9ec95ba955e549260fe930dc38fb99ed3532f92c93b879aca5610",
|
||||
"size": 8272166
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014001_src.tar.gz",
|
||||
"sha256": "6c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cb067d510ac6f3e0d07",
|
||||
"size": 6165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14-alpha1",
|
||||
"versionCode": 1014001,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH_ADMIN"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_SETTINGS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION"
|
||||
}
|
||||
]
|
||||
},
|
||||
"antiFeatures": {
|
||||
"AddOne": {
|
||||
"en-US": "was added this update"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y": {
|
||||
"metadata": {
|
||||
"name": {
|
||||
"en-US": "App3",
|
||||
"en": "en "
|
||||
},
|
||||
"summary": {
|
||||
"en-US": "App3 summary",
|
||||
"en": "en "
|
||||
},
|
||||
"description": {
|
||||
"en-US": "App3 description",
|
||||
"en": "en "
|
||||
},
|
||||
"added": 1234567890,
|
||||
"lastUpdated": 9223372036854775807,
|
||||
"webSite": "http://min1.test.org",
|
||||
"changelog": "changeLog3",
|
||||
"license": "GPLv3",
|
||||
"sourceCode": "source code3",
|
||||
"issueTracker": "tracker3",
|
||||
"translation": "translation3",
|
||||
"preferredSigner": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"categories": [
|
||||
"Cat1",
|
||||
"Cat2",
|
||||
"Cat3"
|
||||
],
|
||||
"author": {
|
||||
"name": "App3 author",
|
||||
"email": "email",
|
||||
"website": "website",
|
||||
"phone": "phone"
|
||||
},
|
||||
"donation": {
|
||||
"url": "donate",
|
||||
"liberapayID": "liberapayID",
|
||||
"liberapay": "liberapay",
|
||||
"openCollective": "openCollective",
|
||||
"bitcoin": "bitcoin",
|
||||
"litecoin": "litecoin",
|
||||
"flattrID": "flattrID"
|
||||
},
|
||||
"icon": {
|
||||
"en": {
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/en ",
|
||||
"sha256": "32758e380aeg6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 2253245
|
||||
}
|
||||
},
|
||||
"featureGraphic": {
|
||||
"en": {
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/en ",
|
||||
"sha256": "54758e380ae762f7c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 32453245
|
||||
}
|
||||
},
|
||||
"promoGraphic": {
|
||||
"en": {
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/en ",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 4523325
|
||||
}
|
||||
},
|
||||
"tvBanner": {
|
||||
"en": {
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/en ",
|
||||
"sha256": "54758e380aeh6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 32453245
|
||||
}
|
||||
},
|
||||
"video": {
|
||||
"en": "en "
|
||||
},
|
||||
"screenshots": {
|
||||
"phone": {
|
||||
"en": [
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/phoneScreenshots/en phoneScreenshots",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
},
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/phoneScreenshots/en phoneScreenshots2",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"sevenInch": {
|
||||
"en": [
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/sevenInchScreenshots/en sevenInchScreenshots",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
},
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/sevenInchScreenshots/en sevenInchScreenshots2",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"tenInch": {
|
||||
"en": [
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/tenInchScreenshots/en tenInchScreenshots",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
},
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/tenInchScreenshots/en tenInchScreenshots2",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"wear": {
|
||||
"en": [
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/wearScreenshots/en wearScreenshots",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
},
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/wearScreenshots/en wearScreenshots2",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"tv": {
|
||||
"en": [
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/tvScreenshots/en tvScreenshots",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
},
|
||||
{
|
||||
"name": "/Haoheiseeshai2que2Che0ooSa6aikeemoo2ap9Aequoh4ju5chooYuPhiev8moodahlonu2oht5Eikahvushapeum5aefo6xig4aghahyaaNuezoo4eexee1Goo5UngohGha6quaeghe8uCh9iex9Oowa9aiyohzoo2ij5miifiegaeth8nie9jae6raephoowishoor1Ien5vahGhahm7eidaiy2AeCaej9iexahyooshu2ic9tea1ool8tu4Y/en/tvScreenshots/en tvScreenshots2",
|
||||
"sha256": "54758e380aee6297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"versions": {
|
||||
"8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06": {
|
||||
"added": 1643250075000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014050.apk",
|
||||
"sha256": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06",
|
||||
"size": 8165518
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014050_src.tar.gz",
|
||||
"sha256": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06",
|
||||
"size": 8165518
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14",
|
||||
"versionCode": 1014050,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"maxSdkVersion": 2147483647,
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"33238d512c1e3eb2d6569f4a3bfbf5523418b22e0a3ed1552770abb9a9c9ccvb"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH_ADMIN"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_SETTINGS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 2147483647
|
||||
}
|
||||
],
|
||||
"nativecode": [
|
||||
"x86",
|
||||
"x86_64"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "feature"
|
||||
},
|
||||
{
|
||||
"name": "feature2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"releaseChannels": [
|
||||
"Beta",
|
||||
"Alpha"
|
||||
],
|
||||
"antiFeatures": {
|
||||
"AntiFeature": {
|
||||
},
|
||||
"NonFreeNet": {
|
||||
},
|
||||
"NotNice": {
|
||||
},
|
||||
"VeryBad": {
|
||||
},
|
||||
"Dont,Show,This": {
|
||||
},
|
||||
"anti-feature": {
|
||||
"en-US": "bla",
|
||||
"de": "blubb"
|
||||
},
|
||||
"anti-feature2": {
|
||||
"de": "blabla"
|
||||
}
|
||||
},
|
||||
"whatsNew": {
|
||||
"en-US": "this is new",
|
||||
"de": "das ist neu"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
629
index/src/sharedTest/resources/index-mid-v1.json
Normal file
629
index/src/sharedTest/resources/index-mid-v1.json
Normal file
@@ -0,0 +1,629 @@
|
||||
{
|
||||
"repo": {
|
||||
"timestamp": 1337,
|
||||
"version": 1,
|
||||
"maxage": 23,
|
||||
"name": "MidV1",
|
||||
"icon": "mid-v1.png",
|
||||
"address": "https://mid-v1.org",
|
||||
"description": "This is a repo with medium data.",
|
||||
"mirrors": [
|
||||
"https://mid-v1.com"
|
||||
]
|
||||
},
|
||||
"requests": {
|
||||
"install": [
|
||||
"installThis"
|
||||
],
|
||||
"uninstall": [
|
||||
"uninstallThis"
|
||||
]
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"categories": [
|
||||
"Cat1"
|
||||
],
|
||||
"antiFeatures": [
|
||||
"AntiFeature"
|
||||
],
|
||||
"summary": "App1 summary",
|
||||
"description": "App1 description",
|
||||
"name": "App1",
|
||||
"authorName": "App1 author",
|
||||
"license": "GPLv3",
|
||||
"webSite": "http://min1.test.org",
|
||||
"added": 1234567890,
|
||||
"icon": "icon-min1.png",
|
||||
"packageName": "org.fdroid.min1",
|
||||
"lastUpdated": 1234567891,
|
||||
"localized": {
|
||||
"de": {
|
||||
"description": "App1 beschreibung",
|
||||
"name": "app 1 name",
|
||||
"summary": "App1 Zusammenfassung"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"categories": [
|
||||
"System"
|
||||
],
|
||||
"changelog": "https://gitlab.com/fdroid/fdroidclient/raw/HEAD/CHANGELOG.md",
|
||||
"translation": "https://hosted.weblate.org/projects/f-droid/f-droid",
|
||||
"issueTracker": "https://gitlab.com/fdroid/fdroidclient/issues",
|
||||
"sourceCode": "https://gitlab.com/fdroid/fdroidclient",
|
||||
"donate": "https://f-droid.org/donate",
|
||||
"liberapayID": "27859",
|
||||
"openCollective": "F-Droid-Euro",
|
||||
"flattrID": "343053",
|
||||
"suggestedVersionName": "1.14",
|
||||
"suggestedVersionCode": "1014050",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"webSite": "https://f-droid.org",
|
||||
"added": 1295222400000,
|
||||
"icon": "org.fdroid.fdroid.1014050.png",
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"lastUpdated": 1643250075000,
|
||||
"localized": {
|
||||
"af": {
|
||||
"description": "F-Droid is 'n installeerbare katalogus van gratis sagteware",
|
||||
"name": "-درويد",
|
||||
"summary": "متجر التطبيقات الذي يحترم الحرية والخصوصية)"
|
||||
},
|
||||
"be": {
|
||||
"name": "F-Droid",
|
||||
"summary": "Крама праграм, якая паважае свабоду і прыватнасць"
|
||||
},
|
||||
"bg": {
|
||||
"summary": "Магазинът за приложения, който уважава независимостта и поверителността"
|
||||
},
|
||||
"bn": {
|
||||
"name": "এফ-ড্রয়েড",
|
||||
"summary": "যে অ্যাপ স্টোর স্বাধীনতা ও গোপনীয়তা সম্মান করে"
|
||||
},
|
||||
"bo": {
|
||||
"description": "ཨེཕ་རོཌ་ནི་ཨེན་ཀྲོཌ་བབ་སྟེགས་ཀྱི་ཆེད་དུ་FOSS",
|
||||
"summary": "རང་དབང་དང་གསང་དོན་ལ་གུས་བརྩི་ཞུས་མཁན་གྱི་མཉེན་ཆས་ཉར་ཚགས་ཁང་།"
|
||||
},
|
||||
"ca": {
|
||||
"description": "F-Droid és un catàleg instal·lable d'aplicacions de software lliure",
|
||||
"name": "F-Droid",
|
||||
"summary": "La botiga d'aplicacions que respecta la llibertat i la privacitat"
|
||||
},
|
||||
"cs": {
|
||||
"description": "F-Droid je instalovatelný katalog softwarových libre",
|
||||
"name": "F-Droid",
|
||||
"summary": "Zdroj aplikací který respektuje vaši svobodu a soukromí"
|
||||
},
|
||||
"cy": {
|
||||
"description": "Mae F-Droid yn gatalog y gellir ei osod o apiau meddalwedd rhyddar gyfer Android.",
|
||||
"name": "F-Droid",
|
||||
"summary": "Yr ystorfa apiau sy'n parchu rhyddid a phreifatrwydd"
|
||||
},
|
||||
"de": {
|
||||
"description": "F-Droid ist ein installierbarer Katalog mit Libre SoftwareAndroid-Apps.",
|
||||
"summary": "Der App-Store, der Freiheit und Privatsphäre respektiert"
|
||||
},
|
||||
"el": {
|
||||
"description": "Το F-Droid είναι ένας κατάλογος εφαρμογών ελεύθερου λογισμικού",
|
||||
"name": "F-Droid",
|
||||
"summary": "Το κατάστημα εφαρμογών που σέβεται την ελευθερία και την ιδιωτικότητα"
|
||||
},
|
||||
"en-US": {
|
||||
"description": "F-Droid is an installable catalogue of libre software",
|
||||
"name": "F-Droid",
|
||||
"whatsNew": "* Overhaul Share menu to use built-in options like Nearby",
|
||||
"phoneScreenshots": [
|
||||
"screenshot-app-details.png",
|
||||
"screenshot-dark-details.png",
|
||||
"screenshot-dark-home.png",
|
||||
"screenshot-dark-knownvuln.png",
|
||||
"screenshot-knownvuln.png",
|
||||
"screenshot-search.png",
|
||||
"screenshot-updates.png"
|
||||
],
|
||||
"featureGraphic": "featureGraphic_PTun9TO4cMFOeiqbvQSrkdcxNUcOFQCymMIaj9UJOAY=.jpg",
|
||||
"summary": "The app store that respects freedom and privacy"
|
||||
},
|
||||
"eo": {
|
||||
"description": "F-Droid estas instalebla katalogo de liberaj aplikaĵoj por Android.",
|
||||
"name": "F-Droid",
|
||||
"whatsNew": "• rekonstruita menuo “Kunhavigi” por uzi enkonstruitajn eblojn, ekz.",
|
||||
"summary": "Aplikaĵa vendejo respektanta liberecon kaj privatecon"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"packages": {
|
||||
"org.fdroid.min1": [
|
||||
{
|
||||
"added": 2342,
|
||||
"apkName": "org.fdroid.min1_23_2.apk",
|
||||
"hash": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"hashType": "sha256",
|
||||
"packageName": "org.fdroid.min1",
|
||||
"size": 1338,
|
||||
"srcname": "org.fdroid.min1_23_2.zip",
|
||||
"uses-permission": [
|
||||
[
|
||||
"perm",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1,
|
||||
"versionName": "1",
|
||||
"nativecode": [
|
||||
"x86"
|
||||
],
|
||||
"features": [
|
||||
"feature"
|
||||
],
|
||||
"antiFeatures": [
|
||||
"anti-feature"
|
||||
]
|
||||
},
|
||||
{
|
||||
"apkName": "org.fdroid.min1_42.apk",
|
||||
"hash": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 21,
|
||||
"maxSdkVersion": 4568,
|
||||
"targetSdkVersion": 32,
|
||||
"packageName": "org.fdroid.min1",
|
||||
"sig": "old",
|
||||
"signer": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1337,
|
||||
"srcname": "org.fdroid.min1_42.zip",
|
||||
"versionCode": 24,
|
||||
"versionName": "24"
|
||||
}
|
||||
],
|
||||
"org.fdroid.fdroid": [
|
||||
{
|
||||
"added": 1643250075000,
|
||||
"apkName": "org.fdroid.fdroid_1014050.apk",
|
||||
"hash": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8165518,
|
||||
"srcname": "org.fdroid.fdroid_1014050_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.INTERNET",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH_ADMIN",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.RECEIVE_BOOT_COMPLETED",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_SETTINGS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1014050,
|
||||
"versionName": "1.14"
|
||||
},
|
||||
{
|
||||
"added": 1642785071000,
|
||||
"apkName": "org.fdroid.fdroid_1014005.apk",
|
||||
"hash": "b4282febf5558d43c7c51a00478961f6df1b6d59e0a6674974cdacb792683e5d",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8382606,
|
||||
"srcname": "org.fdroid.fdroid_1014005_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.INTERNET",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH_ADMIN",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.RECEIVE_BOOT_COMPLETED",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_SETTINGS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1014005,
|
||||
"versionName": "1.14-alpha5",
|
||||
"nativecode": [
|
||||
"fakeNativeCode"
|
||||
],
|
||||
"features": [
|
||||
"fake feature"
|
||||
],
|
||||
"antiFeatures": [
|
||||
"FakeAntiFeature"
|
||||
]
|
||||
},
|
||||
{
|
||||
"added": 1635169849000,
|
||||
"apkName": "org.fdroid.fdroid_1014003.apk",
|
||||
"hash": "c062a9642fde08aacabbfa4cab1ab5773c83f4e6b81551ffd92027d2b20f37d3",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8276110,
|
||||
"srcname": "org.fdroid.fdroid_1014003_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.INTERNET",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH_ADMIN",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.RECEIVE_BOOT_COMPLETED",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_SETTINGS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1014003,
|
||||
"versionName": "1.14-alpha3"
|
||||
},
|
||||
{
|
||||
"added": 1632281731000,
|
||||
"apkName": "org.fdroid.fdroid_1014002.apk",
|
||||
"hash": "3243c24ee95be0fce0830d72e7d2605e3e24f6ccf4ee72a7c8e720fccd7621a1",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8284386,
|
||||
"srcname": "org.fdroid.fdroid_1014002_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.INTERNET",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH_ADMIN",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.RECEIVE_BOOT_COMPLETED",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_SETTINGS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1014002,
|
||||
"versionName": "1.14-alpha2"
|
||||
},
|
||||
{
|
||||
"added": 1632281729000,
|
||||
"apkName": "org.fdroid.fdroid_1014001.apk",
|
||||
"hash": "7ebfd5eb76f9ec95ba955e549260fe930dc38fb99ed3532f92c93b879aca5610",
|
||||
"hashType": "sha256",
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25,
|
||||
"packageName": "org.fdroid.fdroid",
|
||||
"sig": "9063aaadfff9cfd811a9c72fb5012f28",
|
||||
"signer": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"size": 8272166,
|
||||
"srcname": "org.fdroid.fdroid_1014001_src.tar.gz",
|
||||
"uses-permission": [
|
||||
[
|
||||
"android.permission.INTERNET",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.ACCESS_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_NETWORK_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.CHANGE_WIFI_STATE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.BLUETOOTH_ADMIN",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.RECEIVE_BOOT_COMPLETED",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.WRITE_SETTINGS",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.NFC",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.USB_PERMISSION",
|
||||
22
|
||||
],
|
||||
[
|
||||
"android.permission.WAKE_LOCK",
|
||||
null
|
||||
],
|
||||
[
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
null
|
||||
]
|
||||
],
|
||||
"uses-permission-sdk-23": [
|
||||
[
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
null
|
||||
]
|
||||
],
|
||||
"versionCode": 1014001,
|
||||
"versionName": "1.14-alpha1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
660
index/src/sharedTest/resources/index-mid-v2.json
Normal file
660
index/src/sharedTest/resources/index-mid-v2.json
Normal file
@@ -0,0 +1,660 @@
|
||||
{
|
||||
"repo": {
|
||||
"name": "MidV1",
|
||||
"icon": {
|
||||
"name": "/icons/mid-v1.png",
|
||||
"sha256": "74758e480ae76297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 234232352235
|
||||
},
|
||||
"address": "https://mid-v1.org",
|
||||
"description": {
|
||||
"en-US": "This is a repo with medium data.",
|
||||
"de": "Dies ist ein Repo mit mittlerer Datendichte."
|
||||
},
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mid-v1.com"
|
||||
}
|
||||
],
|
||||
"timestamp": 1337,
|
||||
"antiFeatures": {
|
||||
"AntiFeature": {
|
||||
"name": {
|
||||
"en-US": "AntiFeature"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "A bad anti-feature, we can't show to users."
|
||||
}
|
||||
}
|
||||
},
|
||||
"categories": {
|
||||
"Cat1": {
|
||||
"icon": {
|
||||
"name": "/icons/cat2.png",
|
||||
"sha256": "54758e480ae76297c7947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 9223372036854775807
|
||||
},
|
||||
"name": {
|
||||
"en-US": "Cat1"
|
||||
}
|
||||
},
|
||||
"System": {
|
||||
"name": {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages": {
|
||||
"org.fdroid.min1": {
|
||||
"metadata": {
|
||||
"name": {
|
||||
"en-US": "App1",
|
||||
"de" : "app 1 name"
|
||||
},
|
||||
"summary": {
|
||||
"en-US": "App1 summary",
|
||||
"de": "App1 Zusammenfassung"
|
||||
},
|
||||
"description": {
|
||||
"en-US": "App1 description",
|
||||
"de": "App1 beschreibung"
|
||||
},
|
||||
"added": 1234567890,
|
||||
"lastUpdated": 1234567891,
|
||||
"webSite": "http://min1.test.org",
|
||||
"license": "GPLv3",
|
||||
"categories": [
|
||||
"Cat1"
|
||||
],
|
||||
"author": {
|
||||
"name": "App1 author"
|
||||
},
|
||||
"icon": {
|
||||
"en-US": {
|
||||
"name": "/icons/icon-min1.png",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1337
|
||||
}
|
||||
}
|
||||
},
|
||||
"versions": {
|
||||
"824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf": {
|
||||
"added": 0,
|
||||
"file": {
|
||||
"name": "/org.fdroid.min1_42.apk",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1337
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.min1_42.zip",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1338
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "24",
|
||||
"versionCode": 24,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 21,
|
||||
"targetSdkVersion": 32
|
||||
},
|
||||
"maxSdkVersion": 4568,
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf"
|
||||
]
|
||||
}
|
||||
},
|
||||
"releaseChannels": [
|
||||
"Beta"
|
||||
],
|
||||
"antiFeatures": {
|
||||
"AntiFeature": {
|
||||
"en-US": "reason"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"org.fdroid.fdroid": {
|
||||
"metadata": {
|
||||
"name": {
|
||||
"af": "-درويد",
|
||||
"be": "F-Droid",
|
||||
"bn": "এফ-ড্রয়েড",
|
||||
"ca": "F-Droid",
|
||||
"cs": "F-Droid",
|
||||
"cy": "F-Droid",
|
||||
"el": "F-Droid",
|
||||
"en-US": "F-Droid",
|
||||
"eo": "F-Droid"
|
||||
},
|
||||
"summary": {
|
||||
"af": "متجر التطبيقات الذي يحترم الحرية والخصوصية)",
|
||||
"be": "Крама праграм, якая паважае свабоду і прыватнасць",
|
||||
"bg": "Магазинът за приложения, който уважава независимостта и поверителността",
|
||||
"bn": "যে অ্যাপ স্টোর স্বাধীনতা ও গোপনীয়তা সম্মান করে",
|
||||
"bo": "རང་དབང་དང་གསང་དོན་ལ་གུས་བརྩི་ཞུས་མཁན་གྱི་མཉེན་ཆས་ཉར་ཚགས་ཁང་།",
|
||||
"ca": "La botiga d'aplicacions que respecta la llibertat i la privacitat",
|
||||
"cs": "Zdroj aplikací který respektuje vaši svobodu a soukromí",
|
||||
"cy": "Yr ystorfa apiau sy'n parchu rhyddid a phreifatrwydd",
|
||||
"de": "Der App-Store, der Freiheit und Privatsphäre respektiert",
|
||||
"el": "Το κατάστημα εφαρμογών που σέβεται την ελευθερία και την ιδιωτικότητα",
|
||||
"en-US": "The app store that respects freedom and privacy",
|
||||
"eo": "Aplikaĵa vendejo respektanta liberecon kaj privatecon"
|
||||
},
|
||||
"description": {
|
||||
"af": "F-Droid is 'n installeerbare katalogus van gratis sagteware",
|
||||
"bo": "ཨེཕ་རོཌ་ནི་ཨེན་ཀྲོཌ་བབ་སྟེགས་ཀྱི་ཆེད་དུ་FOSS",
|
||||
"ca": "F-Droid és un catàleg instal·lable d'aplicacions de software lliure",
|
||||
"cs": "F-Droid je instalovatelný katalog softwarových libre",
|
||||
"cy": "Mae F-Droid yn gatalog y gellir ei osod o apiau meddalwedd rhyddar gyfer Android.",
|
||||
"de": "F-Droid ist ein installierbarer Katalog mit Libre SoftwareAndroid-Apps.",
|
||||
"el": "Το F-Droid είναι ένας κατάλογος εφαρμογών ελεύθερου λογισμικού",
|
||||
"en-US": "F-Droid is an installable catalogue of libre software",
|
||||
"eo": "F-Droid estas instalebla katalogo de liberaj aplikaĵoj por Android."
|
||||
},
|
||||
"added": 1295222400000,
|
||||
"lastUpdated": 1643250075000,
|
||||
"webSite": "https://f-droid.org",
|
||||
"changelog": "https://gitlab.com/fdroid/fdroidclient/raw/HEAD/CHANGELOG.md",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"sourceCode": "https://gitlab.com/fdroid/fdroidclient",
|
||||
"issueTracker": "https://gitlab.com/fdroid/fdroidclient/issues",
|
||||
"translation": "https://hosted.weblate.org/projects/f-droid/f-droid",
|
||||
"preferredSigner": "43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab",
|
||||
"categories": [
|
||||
"System"
|
||||
],
|
||||
"donation": {
|
||||
"url": "https://f-droid.org/donate",
|
||||
"liberapayID": "27859",
|
||||
"openCollective": "F-Droid-Euro",
|
||||
"flattrID": "343053"
|
||||
},
|
||||
"icon": {
|
||||
"en-US": {
|
||||
"name": "/icons/org.fdroid.fdroid.1014050.png",
|
||||
"sha256": "224a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1237
|
||||
}
|
||||
},
|
||||
"featureGraphic": {
|
||||
"en-US": {
|
||||
"name": "/org.fdroid.fdroid/en-US/featureGraphic_PTun9TO4cMFOeiqbvQSrkdcxNUcOFQCymMIaj9UJOAY=.jpg",
|
||||
"sha256": "424a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 4237
|
||||
}
|
||||
},
|
||||
"screenshots": {
|
||||
"phone": {
|
||||
"en-US": [
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-app-details.png",
|
||||
"sha256": "424a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 4237
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-dark-details.png",
|
||||
"sha256": "424a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 44287
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-dark-home.png",
|
||||
"sha256": "424a109b2352138c3699760e1673385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 4587
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-dark-knownvuln.png",
|
||||
"sha256": "424a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 445837
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-knownvuln.png",
|
||||
"sha256": "424a109b2352138c4599760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 4287
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-search.png",
|
||||
"sha256": "424a109b2352138c3694760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 2857
|
||||
},
|
||||
{
|
||||
"name": "/org.fdroid.fdroid/en-US/phoneScreenshots/screenshot-updates.png",
|
||||
"sha256": "424a109b2352138c3699750e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 485287
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"versions": {
|
||||
"8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06": {
|
||||
"added": 1643250075000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014050.apk",
|
||||
"sha256": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d06",
|
||||
"size": 8165518
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014050_src.tar.gz",
|
||||
"sha256": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d07",
|
||||
"size": 8165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14",
|
||||
"versionCode": 1014050,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH_ADMIN"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_SETTINGS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION"
|
||||
}
|
||||
]
|
||||
},
|
||||
"whatsNew": {
|
||||
"en-US": "* Overhaul Share menu to use built-in options like Nearby",
|
||||
"eo": "• rekonstruita menuo “Kunhavigi” por uzi enkonstruitajn eblojn, ekz."
|
||||
}
|
||||
},
|
||||
"b4282febf5558d43c7c51a00478961f6df1b6d59e0a6674974cdacb792683e5d": {
|
||||
"added": 1642785071000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014005.apk",
|
||||
"sha256": "b4282febf5558d43c7c51a00478961f6df1b6d59e0a6674974cdacb792683e5d",
|
||||
"size": 8382606
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014005_src.tar.gz",
|
||||
"sha256": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cc067d510ac6f3e0d07",
|
||||
"size": 8165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14-alpha5",
|
||||
"versionCode": 1014005,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH_ADMIN"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_SETTINGS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION"
|
||||
}
|
||||
],
|
||||
"nativecode": [
|
||||
"fakeNativeCode"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "fake feature"
|
||||
}
|
||||
]
|
||||
},
|
||||
"antiFeatures": {
|
||||
"FakeAntiFeature": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"c062a9642fde08aacabbfa4cab1ab5773c83f4e6b81551ffd92027d2b20f37d3": {
|
||||
"added": 1635169849000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014003.apk",
|
||||
"sha256": "c062a9642fde08aacabbfa4cab1ab5773c83f4e6b81551ffd92027d2b20f37d3",
|
||||
"size": 8276110
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014003_src.tar.gz",
|
||||
"sha256": "8c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cb067d510ac6f3e0d07",
|
||||
"size": 8165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14-alpha3",
|
||||
"versionCode": 1014003,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH_ADMIN"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_SETTINGS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"3243c24ee95be0fce0830d72e7d2605e3e24f6ccf4ee72a7c8e720fccd7621a1": {
|
||||
"added": 1632281731000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014002.apk",
|
||||
"sha256": "3243c24ee95be0fce0830d72e7d2605e3e24f6ccf4ee72a7c8e720fccd7621a1",
|
||||
"size": 8284386
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014002_src.tar.gz",
|
||||
"sha256": "7c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cb067d510ac6f3e0d07",
|
||||
"size": 7165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14-alpha2",
|
||||
"versionCode": 1014002,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH_ADMIN"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_SETTINGS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"7ebfd5eb76f9ec95ba955e549260fe930dc38fb99ed3532f92c93b879aca5610": {
|
||||
"added": 1632281729000,
|
||||
"file": {
|
||||
"name": "/org.fdroid.fdroid_1014001.apk",
|
||||
"sha256": "7ebfd5eb76f9ec95ba955e549260fe930dc38fb99ed3532f92c93b879aca5610",
|
||||
"size": 8272166
|
||||
},
|
||||
"src": {
|
||||
"name": "/org.fdroid.fdroid_1014001_src.tar.gz",
|
||||
"sha256": "6c89ce2f42f4a89af8ca6e1ea220f9dfdee220724d8a9cb067d510ac6f3e0d07",
|
||||
"size": 6165519
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "1.14-alpha1",
|
||||
"versionCode": 1014001,
|
||||
"usesSdk": {
|
||||
"minSdkVersion": 22,
|
||||
"targetSdkVersion": 25
|
||||
},
|
||||
"signer": {
|
||||
"sha256": [
|
||||
"43238d512c1e5eb2d6569f4a3afbf5523418b82e0a3ed1552770abb9a9c9ccab"
|
||||
]
|
||||
},
|
||||
"usesPermission": [
|
||||
{
|
||||
"name": "android.permission.INTERNET"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.ACCESS_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_NETWORK_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.CHANGE_WIFI_STATE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.BLUETOOTH_ADMIN"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.READ_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WRITE_SETTINGS"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.NFC"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.USB_PERMISSION",
|
||||
"maxSdkVersion": 22
|
||||
},
|
||||
{
|
||||
"name": "android.permission.WAKE_LOCK"
|
||||
},
|
||||
{
|
||||
"name": "android.permission.FOREGROUND_SERVICE"
|
||||
}
|
||||
],
|
||||
"usesPermissionSdk23": [
|
||||
{
|
||||
"name": "android.permission.ACCESS_COARSE_LOCATION"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
index/src/sharedTest/resources/index-min-reordered-v2.json
Normal file
38
index/src/sharedTest/resources/index-min-reordered-v2.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"packages": {
|
||||
"org.fdroid.min1": {
|
||||
"versions": {
|
||||
"824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf": {
|
||||
"added": 0,
|
||||
"manifest": {
|
||||
"versionName": "0",
|
||||
"versionCode": 1
|
||||
},
|
||||
"file": {
|
||||
"name": "/org.fdroid.min1_23.apk",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1337
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"added": 0,
|
||||
"lastUpdated": 0,
|
||||
"license": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"repo": {
|
||||
"name": "MinV1",
|
||||
"icon": {
|
||||
"name": "/icons/min-v1.png",
|
||||
"sha256": "74758e480ae76297c8947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
},
|
||||
"address": "https://min-v1.org",
|
||||
"description": {
|
||||
"en-US": "This is a repo with minimal data."
|
||||
},
|
||||
"timestamp": 42
|
||||
}
|
||||
}
|
||||
34
index/src/sharedTest/resources/index-min-v1.json
Normal file
34
index/src/sharedTest/resources/index-min-v1.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"repo": {
|
||||
"timestamp": 42,
|
||||
"version": 1,
|
||||
"name": "MinV1",
|
||||
"icon": "min-v1.png",
|
||||
"address": "https://min-v1.org",
|
||||
"description": "This is a repo with minimal data."
|
||||
},
|
||||
"requests": {
|
||||
"install": [
|
||||
],
|
||||
"uninstall": [
|
||||
]
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"license": "",
|
||||
"packageName": "org.fdroid.min1"
|
||||
}
|
||||
],
|
||||
"packages": {
|
||||
"org.fdroid.min1": [
|
||||
{
|
||||
"apkName": "org.fdroid.min1_23.apk",
|
||||
"hash": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"hashType": "sha256",
|
||||
"packageName": "org.fdroid.min1",
|
||||
"size": 1337,
|
||||
"versionName": "0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
38
index/src/sharedTest/resources/index-min-v2.json
Normal file
38
index/src/sharedTest/resources/index-min-v2.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"repo": {
|
||||
"name": "MinV1",
|
||||
"icon": {
|
||||
"name": "/icons/min-v1.png",
|
||||
"sha256": "74758e480ae76297c8947f107db9ea03d2933c9d5c110d02046977cf78d43def",
|
||||
"size": 0
|
||||
},
|
||||
"address": "https://min-v1.org",
|
||||
"description": {
|
||||
"en-US": "This is a repo with minimal data."
|
||||
},
|
||||
"timestamp": 42
|
||||
},
|
||||
"packages": {
|
||||
"org.fdroid.min1": {
|
||||
"metadata": {
|
||||
"added": 0,
|
||||
"lastUpdated": 0,
|
||||
"license": ""
|
||||
},
|
||||
"versions": {
|
||||
"824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf": {
|
||||
"added": 0,
|
||||
"file": {
|
||||
"name": "/org.fdroid.min1_23.apk",
|
||||
"sha256": "824a109b2352138c3699760e1683385d0ed50ce526fc7982f8d65757743374bf",
|
||||
"size": 1337
|
||||
},
|
||||
"manifest": {
|
||||
"versionName": "0",
|
||||
"versionCode": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user