Skip to content

Commit

Permalink
minor fixes, update deps
Browse files Browse the repository at this point in the history
  • Loading branch information
kawaiiDango committed Aug 17, 2024
1 parent 9a6e002 commit eea1f2d
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 36 deletions.
6 changes: 3 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -375,20 +375,20 @@ fun fetchCrowdinLanguages(projectId: String, token: String, minProgress: Int) {
).sorted()

// write to locale_config.xml
val localesConfigText = """
<?xml version='1.0' encoding='UTF-8'?>
val localesConfigText =
"""<?xml version='1.0' encoding='UTF-8'?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
${languagesFiltered.joinToString("\n") { " <locale android:name=\"$it\" />" }}
</locale-config>
"""
file("src/main/res/xml/locales_config.xml").writeText(localesConfigText)

// write to LocaleUtils.kt
val localeUtilsPartialText = """
val localesSet = arrayOf(
${languagesFiltered.joinToString("\n") { " \"$it\"," }}
)
"""
// write to LocaleUtils.kt
val localeUtilsFile = file("src/main/java/com/arn/scrobble/utils/LocaleUtils.kt")

val localeUtilsText = localeUtilsFile.readText()
Expand Down
32 changes: 21 additions & 11 deletions app/src/main/java/com/arn/scrobble/NLService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -106,21 +106,26 @@ class NLService : NotificationListenerService() {
// onCreate seems to get called only once in those cases.
// also unreliable on lp and mm
// just gate them with an inited flag
if (BuildConfig.DEBUG)
toast(R.string.scrobbler_on)

if (!inited)
init()

if (!inited) {
job = SupervisorJob()
coroutineScope = CoroutineScope(Dispatchers.Main + job!!)

// API 23 bug, force run them on Main thread
coroutineScope.launch {
if (BuildConfig.DEBUG)
toast(R.string.scrobbler_on)
init()
}
}
}


private fun init() {
// set it to true right away in case onListenerConnected gets called again before init has finished
inited = true

job = SupervisorJob()
coroutineScope = CoroutineScope(Dispatchers.Main + job!!)

val filter = IntentFilter().apply {
addAction(iCANCEL)
addAction(iLOVE)
Expand Down Expand Up @@ -240,22 +245,27 @@ class NLService : NotificationListenerService() {
sessListener = null
scrobbleQueue.shutdown()
}
job?.cancel()
PanoDb.destroyInstance()
job?.cancel()
}

override fun onListenerDisconnected() { //api 24+ only
if (BuildConfig.DEBUG)
toast(R.string.scrobbler_off)

if (inited && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
if (inited && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
destroy()
}
}


override fun onDestroy() {
if (inited && Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
destroy()
if (inited && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
// API 23 bug, force run them on Main thread
coroutineScope.launch {
destroy()
}
}
super.onDestroy()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ class FileScrobblable(userAccount: UserAccountSerializable) : Scrobblable(userAc
track = row[3],
album = row[4],
albumArtist = row[5],
durationMs = row[6].toLong(),
durationMs = row[6].toLongOrNull(),
mediaPlayerPackage = row[7],
mediaPlayerName = row.getOrNull(8),
mediaPlayerVersion = row.getOrNull(9),
Expand Down
70 changes: 63 additions & 7 deletions app/src/main/java/com/arn/scrobble/billing/Security.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ package com.arn.scrobble.billing
* frauds.
*/
import android.content.pm.PackageManager
import android.util.Base64
import com.android.billingclient.api.Purchase
import com.arn.scrobble.Tokens
import com.arn.scrobble.main.App
import com.arn.scrobble.utils.Stuff
import io.ktor.util.decodeBase64Bytes
import io.ktor.util.decodeBase64String
import kotlinx.serialization.Serializable
import java.io.IOException
import java.security.*
import java.security.spec.InvalidKeySpecException
Expand All @@ -35,7 +38,8 @@ import java.security.spec.X509EncodedKeySpec
*/
object Security {
private const val KEY_FACTORY_ALGORITHM = "RSA"
private const val SIGNATURE_ALGORITHM = "SHA1withRSA"
private const val PLAY_SIGNATURE_ALGORITHM = "SHA1withRSA"
private const val JWT_SIGNATURE_ALGORITHM = "SHA256withRSA"

/**
* Verifies that the data was signed with the given signature
Expand All @@ -53,7 +57,7 @@ object Security {
) {
return false
}
val key = generatePublicKey(Tokens.BASE_64_ENCODED_PUBLIC_KEY)
val key = loadPublicKey(Tokens.BASE_64_ENCODED_PUBLIC_KEY)
return verify(key, purchase.originalJson, purchase.signature)
}

Expand All @@ -65,9 +69,9 @@ object Security {
* is invalid
*/
@Throws(IOException::class)
private fun generatePublicKey(encodedPublicKey: String): PublicKey {
private fun loadPublicKey(encodedPublicKey: String): PublicKey {
try {
val decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT)
val decodedKey = encodedPublicKey.decodeBase64Bytes()
val keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM)
return keyFactory.generatePublic(X509EncodedKeySpec(decodedKey))
} catch (e: NoSuchAlgorithmException) {
Expand All @@ -90,12 +94,12 @@ object Security {
private fun verify(publicKey: PublicKey, signedData: String, signature: String): Boolean {
val signatureBytes: ByteArray
try {
signatureBytes = Base64.decode(signature, Base64.DEFAULT)
signatureBytes = signature.decodeBase64Bytes()
} catch (e: IllegalArgumentException) {
return false
}
try {
val signatureAlgorithm = Signature.getInstance(SIGNATURE_ALGORITHM)
val signatureAlgorithm = Signature.getInstance(PLAY_SIGNATURE_ALGORITHM)
signatureAlgorithm.initVerify(publicKey)
signatureAlgorithm.update(signedData.toByteArray())
return signatureAlgorithm.verify(signatureBytes)
Expand All @@ -122,4 +126,56 @@ object Security {
android.os.Process.killProcess(android.os.Process.myPid())
return null
}

@OptIn(ExperimentalStdlibApi::class)
fun sha256(s: String) =
MessageDigest.getInstance("SHA-256")
.digest(s.toByteArray())
.toHexString()

fun validateJwt(token: String, base64PublicKey: String): Boolean {
@Serializable
data class JwtHeader(val alg: String, val typ: String)

try {
val parts = token.split(".")
if (parts.size != 3) return false

val header = parts[0].decodeBase64String().let {
Stuff.myJson.decodeFromString<JwtHeader>(it)
}

if (header.alg != "RS256") return false
// val payload = String(Base64.decode(parts[1], Base64.DEFAULT))
val signature = parts[2].decodeBase64Bytes()

val data = "${parts[0]}.${parts[1]}".toByteArray()

val trimmedKey = base64PublicKey.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replace("\\s".toRegex(), "")

val publicKey = loadPublicKey(trimmedKey)
verifySignature(data, signature, publicKey)
} catch (e: Exception) {
return false
}
return true
}

private fun verifySignature(
data: ByteArray,
signature: ByteArray,
publicKey: PublicKey
): Boolean {
return try {
val sig = Signature.getInstance("SHA256withRSA")
sig.initVerify(publicKey)
sig.update(data)
sig.verify(signature)
} catch (e: Exception) {
false
}
}

}
2 changes: 0 additions & 2 deletions app/src/main/java/com/arn/scrobble/main/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import androidx.work.Configuration
import coil3.ImageLoader
import coil3.PlatformContext
import coil3.SingletonImageLoader
import coil3.networkObserverEnabled
import coil3.request.allowHardware
import coil3.request.crossfade
import coil3.size.Precision
Expand Down Expand Up @@ -158,7 +157,6 @@ class App : Application(), SingletonImageLoader.Factory, Configuration.Provider
.crossfade(true)
.precision(Precision.INEXACT)
.allowHardware(false)
.networkObserverEnabled(true)
.build()

fun clearMusicEntryImageCache(entry: MusicEntry) {
Expand Down
10 changes: 6 additions & 4 deletions app/src/main/java/com/arn/scrobble/pref/PrefFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class PrefFragment : PreferenceFragmentCompat() {
val changeLocalePref = findPreference<Preference>(MainPrefs.PREF_LOCALE)!!

var prevLang = ""
val localeEntryValues = arrayOf("auto") + LocaleUtils.localesSet.toTypedArray()
val localeEntryValues = arrayOf("auto") + LocaleUtils.localesSet
val localeEntries = localeEntryValues.map {
if (it == "auto")
return@map getString(R.string.auto)
Expand Down Expand Up @@ -300,8 +300,8 @@ class PrefFragment : PreferenceFragmentCompat() {
.title = getString(R.string.s_top_scrobbles, getString(R.string.monthly))

val chartsWidget = findPreference<Preference>("charts_widget")!!
chartsWidget.setOnPreferenceClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
chartsWidget.setOnPreferenceClickListener {
val appWidgetManager = AppWidgetManager.getInstance(requireContext())
if (appWidgetManager.isRequestPinAppWidgetSupported) {
val pi = PendingIntent.getActivity(
Expand All @@ -316,8 +316,10 @@ class PrefFragment : PreferenceFragmentCompat() {
ComponentName(requireContext(), ChartsWidgetProvider::class.java)
appWidgetManager.requestPinAppWidget(myProvider, null, pi)
}
true
}
true
} else {
chartsWidget.isVisible = false
}

hideOnTV += chartsWidget
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/xml/locales_config.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

<?xml version='1.0' encoding='UTF-8'?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<locale android:name="ar" />
Expand Down
10 changes: 5 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
targetSdk = "35"
minSdk = "23"
minSdkBaselineProfile = "28"
android-application = "8.7.0-alpha05"
android-application = "8.7.0-alpha07"
aboutlibraries = "11.2.2"
activity = "1.9.1"
androidSnowfall = "1.2.1"
coil = "3.0.0-alpha09"
coil = "3.0.0-alpha10"
constraintlayout = "2.2.0-alpha14"
billing = "7.0.0"
core = "1.15.0-alpha01"
Expand All @@ -20,7 +20,7 @@ fragment = "1.8.2"
harmony = "1.2.6"
junit = "4.13.2"
kotlin = "2.0.10"
kotlinCsvJvm = "1.9.3"
kotlinCsvJvm = "1.10.0"
kotlinx-serialization-json = "1.7.1"
ktorBom = "3.0.0-beta-2"
kumo-core = "1.28.1"
Expand All @@ -37,7 +37,7 @@ play-publisher = "3.10.1"
preference-ktx = "1.2.1"
profileinstaller = "1.4.0-alpha02"
recyclerview = "1.4.0-alpha02"
runner = "1.6.1"
runner = "1.6.2"
skeletonlayout = "5.0.0"
timber = "5.0.1"
swiperefreshlayout = "1.2.0-alpha01"
Expand All @@ -60,7 +60,7 @@ android-snowfall = { module = "com.github.jetradarmobile:android-snowfall", vers
androidx-activity = { module = "androidx.activity:activity", version.ref = "activity" }
androidx-viewpager = { module = "androidx.viewpager:viewpager", version.ref = "viewpager" }
desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" }
kotlin-csv-jvm = { module = "com.github.doyaaaaaken:kotlin-csv-jvm", version.ref = "kotlinCsvJvm" }
kotlin-csv-jvm = { module = "com.jsoizo:kotlin-csv-jvm", version.ref = "kotlinCsvJvm" }
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
ktor-bom = { module = "io.ktor:ktor-bom", version.ref = "ktorBom" }
ktor-client-core = { module = "io.ktor:ktor-client-core" }
Expand Down
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Sun Jul 14 06:10:57 IST 2024
#Thu Aug 15 09:00:19 IST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

0 comments on commit eea1f2d

Please sign in to comment.