mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-27 03:27:51 +02:00
103 lines
4.0 KiB
Kotlin
Executable File
103 lines
4.0 KiB
Kotlin
Executable File
package exh.ui.lock
|
|
|
|
import android.annotation.TargetApi
|
|
import android.app.AppOpsManager
|
|
import android.content.ActivityNotFoundException
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.pm.PackageManager
|
|
import android.os.Build
|
|
import android.provider.Settings
|
|
import com.afollestad.materialdialogs.MaterialDialog
|
|
import com.elvishew.xlog.XLog
|
|
import eu.kanade.tachiyomi.R
|
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
|
import uy.kohesive.injekt.Injekt
|
|
import uy.kohesive.injekt.api.get
|
|
import java.security.MessageDigest
|
|
import kotlin.experimental.and
|
|
|
|
|
|
/**
|
|
* Password hashing utils
|
|
*/
|
|
|
|
/**
|
|
* Yes, I know SHA512 is fast, but bcrypt on mobile devices is too slow apparently
|
|
*/
|
|
fun sha512(passwordToHash: String, salt: String): String {
|
|
val md = MessageDigest.getInstance("SHA-512")
|
|
md.update(salt.toByteArray(charset("UTF-8")))
|
|
val bytes = md.digest(passwordToHash.toByteArray(charset("UTF-8")))
|
|
val sb = StringBuilder()
|
|
for (i in bytes.indices) {
|
|
sb.append(Integer.toString((bytes[i] and 0xff.toByte()) + 0x100, 16).substring(1))
|
|
}
|
|
return sb.toString()
|
|
}
|
|
|
|
/**
|
|
* Check if lock is enabled
|
|
*/
|
|
fun lockEnabled(prefs: PreferencesHelper = Injekt.get())
|
|
= prefs.eh_lockHash().get() != null
|
|
&& prefs.eh_lockSalt().get() != null
|
|
&& prefs.eh_lockLength().getOrDefault() != -1
|
|
|
|
/**
|
|
* Check if the lock will function properly
|
|
*
|
|
* @return true if action is required, false if lock is working properly
|
|
*/
|
|
fun notifyLockSecurity(context: Context,
|
|
prefs: PreferencesHelper = Injekt.get()): Boolean {
|
|
return false
|
|
if (!prefs.eh_lockManually().getOrDefault()
|
|
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
|
&& !hasAccessToUsageStats(context)) {
|
|
MaterialDialog.Builder(context)
|
|
.title("Permission required")
|
|
.content("${context.getString(R.string.app_name)} requires the usage stats permission to detect when you leave the app. " +
|
|
"This is required for the application lock to function properly. " +
|
|
"Press OK to grant this permission now.")
|
|
.negativeText("Cancel")
|
|
.positiveText("Ok")
|
|
.onPositive { _, _ ->
|
|
try {
|
|
context.startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
|
|
} catch(e: ActivityNotFoundException) {
|
|
XLog.e("Device does not support USAGE_ACCESS_SETTINGS shortcut!")
|
|
MaterialDialog.Builder(context)
|
|
.title("Grant permission manually")
|
|
.content("Failed to launch the window used to grant the usage stats permission. " +
|
|
"You can still grant this permission manually: go to your phone's settings and search for 'usage access'.")
|
|
.positiveText("Ok")
|
|
.onPositive { dialog, _ -> dialog.dismiss() }
|
|
.cancelable(true)
|
|
.canceledOnTouchOutside(false)
|
|
.show()
|
|
}
|
|
}
|
|
.autoDismiss(true)
|
|
.cancelable(false)
|
|
.show()
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
fun hasAccessToUsageStats(context: Context): Boolean {
|
|
return try {
|
|
val packageManager = context.packageManager
|
|
val applicationInfo = packageManager.getApplicationInfo(context.packageName, 0)
|
|
val appOpsManager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
|
|
val mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName)
|
|
(mode == AppOpsManager.MODE_ALLOWED)
|
|
} catch (e: PackageManager.NameNotFoundException) {
|
|
false
|
|
}
|
|
}
|