Skip to content

Commit

Permalink
Merge branch 'verification-database'
Browse files Browse the repository at this point in the history
# Conflicts:
#	app/src/main/kotlin/dev/soupslurpr/appverifier/AppVerifier.kt
#	app/src/main/kotlin/dev/soupslurpr/appverifier/ui/VerifyAppScreen.kt
  • Loading branch information
soupslurpr committed Jan 2, 2024
2 parents d9c9787 + 5945156 commit 69869e0
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 18 deletions.
3 changes: 2 additions & 1 deletion LICENSE.material-symbols.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
A copy of the license for the verified material symbol used in the app icon is provided below.
A copy of the license for the verified material symbol used in the app icon
and material symbols used in the app is provided below.

Apache License
Version 2.0, January 2004
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.activity:activity-compose:1.8.2")
implementation("androidx.navigation:navigation-compose:2.7.6")
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("androidx.compose.material:material-icons-extended")
implementation("com.google.android.material:material:1.11.0")
implementation("com.google.accompanist:accompanist-drawablepainter:0.33.2-alpha")

implementation(platform("androidx.compose:compose-bom:2023.10.01"))
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")

implementation("androidx.datastore:datastore-preferences:1.0.0")
}
9 changes: 6 additions & 3 deletions app/src/main/kotlin/dev/soupslurpr/appverifier/AppVerifier.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import dev.soupslurpr.appverifier.data.InternalDatabaseStatus
import dev.soupslurpr.appverifier.preferences.PreferencesViewModel
import dev.soupslurpr.appverifier.ui.AppListScreen
import dev.soupslurpr.appverifier.ui.CreditsScreen
Expand Down Expand Up @@ -99,13 +100,14 @@ fun AppVerifierApp(
}
composable(route = AppVerifierScreens.AppList.name) {
AppListScreen(
{ name: String, packageName: String, hash: String, icon: Drawable ->
verifyAppViewModel.setAppVerificationInfo(name, packageName, hash)
{ name: String, packageName: String, hash: String, icon: Drawable, internalDatabaseStatus: InternalDatabaseStatus ->
verifyAppViewModel.setAppVerificationInfo(name, packageName, hash, internalDatabaseStatus)
verifyAppViewModel.setAppIcon(icon)
navController.navigate(AppVerifierScreens.VerifyApp.name)
},
{ verifyAppViewModel.clearUiState() },
{ verifyAppViewModel.getHashHexFromPackageInfo(it) }
{ verifyAppViewModel.getHashHexFromPackageInfo(it) },
{ verifyAppViewModel.getInternalDatabaseStatusFromVerificationInfo(it) }
)
}
composable(route = AppVerifierScreens.VerifyApp.name) {
Expand All @@ -118,6 +120,7 @@ fun AppVerifierApp(
verifyAppUiState.value.appNotFound.value,
{ verifyAppViewModel.verifyFromText(it) },
verifyAppUiState.value.invalidFormat.value,
verifyAppUiState.value.internalDatabaseStatus.value,
{ navController.navigateUp() }
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package dev.soupslurpr.appverifier

import dev.soupslurpr.appverifier.data.VerificationInfo

val internalVerificationInfoDatabase = setOf(
VerificationInfo(
"dev.soupslurpr.beautyxt",
setOf(
"00:03:01:CC:29:1B:B9:9B:5E:BC:13:BE:89:F0:8C:46:03:80:71:27:B5:5E:21:AA:1E:69:8B:1D:E6:B8:43:46"
)
),
VerificationInfo(
"org.thoughtcrime.securesms",
setOf(
"29:F3:4E:5F:27:F2:11:B4:24:BC:5B:F9:D6:71:62:C0:EA:FB:A2:DA:35:AF:35:C1:64:16:FC:44:62:76:BA:26"
)
),
VerificationInfo(
"app.accrescent.client",
setOf(
"06:7A:40:C4:19:3A:AD:51:AC:87:F9:DD:FD:EB:B1:5E:24:A1:85:0B:AB:FA:48:21:C2:8C:5C:25:C3:FD:C0:71"
)
),
VerificationInfo(
"net.mullvad.mullvadvpn",
setOf(
// Official
"7B:E2:19:30:C3:B4:D7:39:06:B0:89:30:45:0A:1D:3A:FB:D2:2C:98:D9:D8:E9:87:DF:8C:1F:BC:2D:0C:90:BB",
// Google Play Store
"D7:4C:E0:E0:B2:9F:4D:1D:57:AB:F5:EF:7F:9A:37:57:E7:87:CC:A7:A6:25:9B:9C:32:BB:5B:B1:8E:34:63:BD",
// F-Droid
"E1:B6:6A:F1:AC:48:69:A3:3B:09:1F:81:DC:BD:57:7B:F8:DC:FE:91:25:DD:DE:33:81:BF:FF:91:81:33:31:EC",
)
),
VerificationInfo(
"com.dominospizza",
setOf(
"97:59:E1:5B:C7:AD:25:FB:A0:5D:43:36:16:E5:1C:E5:04:09:2E:F0:4F:63:C3:61:36:5C:FD:FE:DA:DD:3B:FC"
)
),
VerificationInfo(
"com.google.android.GoogleCamera",
setOf(
"F0:FD:6C:5B:41:0F:25:CB:25:C3:B5:33:46:C8:97:2F:AE:30:F8:EE:74:11:DF:91:04:80:AD:6B:2D:60:DB:83"
)
),
VerificationInfo(
"com.google.android.inputmethod.latin",
setOf(
"F0:FD:6C:5B:41:0F:25:CB:25:C3:B5:33:46:C8:97:2F:AE:30:F8:EE:74:11:DF:91:04:80:AD:6B:2D:60:DB:83"
)
),
VerificationInfo(
"com.einnovation.temu",
setOf(
"8A:DE:FE:CE:37:49:DC:F2:3C:3C:EB:3A:8B:BB:C9:A1:D8:80:91:B6:76:30:05:88:91:1B:B5:8B:85:97:0B:AF"
)
),
VerificationInfo(
"com.zhiliaoapp.musically",
setOf(
"90:41:80:3E:91:BC:B8:14:B4:B4:39:9F:B5:C8:5A:91:64:0B:75:5E:5E:8B:A7:68:13:81:4B:F4:CF:2A:B5:BA"
)
),
VerificationInfo(
"com.whatsapp",
setOf(
"39:87:D0:43:D1:0A:EF:AF:5A:87:10:B3:67:14:18:FE:57:E0:E1:9B:65:3C:9D:F8:25:58:FE:B5:FF:CE:5D:44"
)
),
VerificationInfo(
"com.squareup.cash",
setOf(
"21:A7:46:75:96:C1:68:65:0F:D7:B6:31:B6:54:22:EB:56:3E:1D:21:AF:F2:2D:DE:73:89:BA:0D:5D:73:87:48"
)
),
VerificationInfo(
"im.molly.app",
setOf(
"6A:A8:0F:DF:4A:8C:C1:37:37:CF:B4:34:FC:0C:DE:48:6F:09:CF:8F:CD:A2:1A:67:BE:A5:EE:1C:A2:70:08:86"
)
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,34 @@ data class VerifyAppUiState(
val verificationStatus: MutableState<VerificationStatus> = mutableStateOf(VerificationStatus.UNKNOWN),
val appNotFound: MutableState<Boolean> = mutableStateOf(false),
val invalidFormat: MutableState<Boolean> = mutableStateOf(false),
val internalDatabaseStatus: MutableState<InternalDatabaseStatus> = mutableStateOf(InternalDatabaseStatus.NOT_FOUND)
)

enum class InternalDatabaseStatus(val info: String, val simpleInternalDatabaseStatus: SimpleInternalDatabaseStatus) {
NOT_FOUND(
"This app was not found in the internal database. This isn't anything to worry about, but please verify the " +
"app normally.",
SimpleInternalDatabaseStatus.NOT_FOUND,
),
MATCH(
"This app's verification info matches an entry in the internal database. You don't need to verify normally.",
SimpleInternalDatabaseStatus.SUCCESS,
),
NOMATCH(
"This app was found in the internal database, but its hash did NOT match. This app may be " +
"non-genuine.",
SimpleInternalDatabaseStatus.FAILURE,
),
}

enum class SimpleInternalDatabaseStatus(val color: Color) {
NOT_FOUND(Color.Gray),
SUCCESS(Color.Green),
FAILURE(Color.Red)
}

data class VerificationInfo(val packageName: String, val hashes: Set<String>)

enum class SimpleVerificationStatus(val color: Color) {
UNKNOWN(Color.Gray),
SUCCESS(Color.Green),
Expand All @@ -24,7 +50,7 @@ enum class SimpleVerificationStatus(val color: Color) {

enum class VerificationStatus(val info: String, val simpleVerificationStatus: SimpleVerificationStatus) {
UNKNOWN(
"Since you haven't provided any verification information, I'm unable to determine your verification status",
"Since you haven't provided any verification information, I'm unable to determine the verification status",
SimpleVerificationStatus.UNKNOWN,
),
MATCH(
Expand Down
43 changes: 40 additions & 3 deletions app/src/main/kotlin/dev/soupslurpr/appverifier/ui/AppListScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Error
import androidx.compose.material.icons.filled.Verified
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand All @@ -16,17 +20,22 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import dev.soupslurpr.appverifier.data.InternalDatabaseStatus
import dev.soupslurpr.appverifier.data.SimpleVerificationStatus
import dev.soupslurpr.appverifier.data.VerificationInfo

@Composable
fun AppListScreen(
onClickAppItem: (
name: String,
packageName: String,
hash: String,
icon: Drawable
icon: Drawable,
internalDatabusStatus: InternalDatabaseStatus,
) -> Unit,
onLaunchedEffect: () -> Unit,
getHashHexFromPackageInfo: (packageInfo: PackageInfo) -> String,
getInternalDatabaseStatusFromVerificationInfo: (verification: VerificationInfo) -> InternalDatabaseStatus,
) {
val context = LocalContext.current

Expand Down Expand Up @@ -54,12 +63,15 @@ fun AppListScreen(

val hashHex = getHashHexFromPackageInfo(packageInfo)

val verificationInfo = VerificationInfo(packageInfo.packageName, setOf(hashHex))

AppItem(
name = packageManager.getApplicationLabel(packageInfo.applicationInfo).toString(),
packageName = packageInfo.packageName,
hash = hashHex,
icon = packageManager.getApplicationIcon(packageInfo.applicationInfo),
onClickAppItem = onClickAppItem,
internalDatabaseStatus = getInternalDatabaseStatusFromVerificationInfo(verificationInfo),
)
}
}
Expand All @@ -72,11 +84,18 @@ fun AppItem(
packageName: String,
hash: String,
icon: Drawable,
onClickAppItem: (name: String, packageName: String, hash: String, icon: Drawable) -> Unit,
onClickAppItem: (
name: String,
packageName: String,
hash: String,
icon: Drawable,
internalDatabaseStatus: InternalDatabaseStatus
) -> Unit,
internalDatabaseStatus: InternalDatabaseStatus,
) {
ListItem(
modifier = Modifier.clickable {
onClickAppItem(name, packageName, hash, icon)
onClickAppItem(name, packageName, hash, icon, internalDatabaseStatus)
},
headlineContent = {
Text(name)
Expand All @@ -90,6 +109,24 @@ fun AppItem(
null,
Modifier.size(50.dp),
)
},
trailingContent = {
when (internalDatabaseStatus) {
InternalDatabaseStatus.NOT_FOUND -> null
InternalDatabaseStatus.MATCH -> Icon(
Icons.Filled.Verified,
"Verified successfully with internal database",
Modifier,
SimpleVerificationStatus.SUCCESS.color,
)

InternalDatabaseStatus.NOMATCH -> Icon(
Icons.Filled.Error,
"Verification with internal database NOT successful!",
Modifier,
SimpleVerificationStatus.FAILURE.color,
)
}
}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ fun CreditsScreen() {
item {
CreditsItem(
dependencyName = "Material Symbols",
dependencyPackageName = "",
dependencyPackageName = "androidx.compose.material:material-icons-extended",
dependencyLicense = APACHE2LICENSE,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
Expand Down Expand Up @@ -39,6 +40,7 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import dev.soupslurpr.appverifier.data.InternalDatabaseStatus
import dev.soupslurpr.appverifier.data.VerificationStatus

@Composable
Expand All @@ -52,6 +54,7 @@ fun VerifyAppScreen(
onVerifyFromClipboard: (String) -> Unit,
invalidFormat: Boolean,
onLaunchedEffectHashEmpty: () -> Unit,
internalDatabaseStatus: InternalDatabaseStatus,
) {
val context = LocalContext.current

Expand All @@ -61,6 +64,8 @@ fun VerifyAppScreen(

var showMoreInfoAboutVerificationStatusDialog by rememberSaveable { mutableStateOf(false) }

var showMoreInfoAboutInternalDatabaseStatusDialog by rememberSaveable { mutableStateOf(false) }

LaunchedEffect(hash) {
if (hash.isEmpty()) {
onLaunchedEffectHashEmpty()
Expand Down Expand Up @@ -88,6 +93,26 @@ fun VerifyAppScreen(
"following:\n\ncom.example.app\n96:C0:2C:55:75:5C:17:1C:68:13:70:29:3B:37:11:2B:4A:5D:F7:B9:82:C2:C5:58:05:4C:45:51:AD:F5:50:DC"
)
} else {
Text(
"Internal Database Status:"
)
Row {
FilledTonalButton(
onClick = { showMoreInfoAboutInternalDatabaseStatusDialog = true },
) {
Text(
internalDatabaseStatus.simpleInternalDatabaseStatus.name.replace('_', ' '),
style = typography.headlineLarge
)
Spacer(Modifier.width(8.dp))
Icon(
Icons.Default.Info,
"More info about internal database status",
tint = internalDatabaseStatus.simpleInternalDatabaseStatus.color,
)
}
}
Spacer(Modifier.height(8.dp))
if (icon != null) {
Image(
rememberDrawablePainter(drawable = icon),
Expand Down Expand Up @@ -151,6 +176,34 @@ fun VerifyAppScreen(
}
}

if (showMoreInfoAboutInternalDatabaseStatusDialog) {
AlertDialog(
onDismissRequest = { showMoreInfoAboutInternalDatabaseStatusDialog = false },
confirmButton = {
TextButton(
{ showMoreInfoAboutInternalDatabaseStatusDialog = false }
) {
Text(stringResource(id = android.R.string.ok))
}
},
title = {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
internalDatabaseStatus.name,
style = typography.headlineSmall,
color = internalDatabaseStatus.simpleInternalDatabaseStatus.color,
)
}
},
text = {
Text(internalDatabaseStatus.info)
}
)
}

if (showMoreInfoAboutVerificationStatusDialog) {
AlertDialog(
onDismissRequest = { showMoreInfoAboutVerificationStatusDialog = false },
Expand Down
Loading

0 comments on commit 69869e0

Please sign in to comment.