mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Add temp advanced service to store encrypted elements
This commit is contained in:
@@ -174,13 +174,17 @@
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".notifications.AttachmentFileNotificationService"
|
||||
android:name="com.kunzisoft.keepass.notifications.AttachmentFileNotificationService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name="com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name="com.kunzisoft.keepass.notifications.AdvancedUnlockNotificationService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<!-- Receiver for Autofill -->
|
||||
<service
|
||||
android:name="com.kunzisoft.keepass.autofill.KeeAutofillService"
|
||||
|
||||
@@ -19,19 +19,69 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.app.database
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.IBinder
|
||||
import com.kunzisoft.keepass.notifications.AdvancedUnlockNotificationService
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
||||
|
||||
class CipherDatabaseAction(applicationContext: Context) {
|
||||
class CipherDatabaseAction(context: Context) {
|
||||
|
||||
private val applicationContext = context.applicationContext
|
||||
private val cipherDatabaseDao =
|
||||
AppDatabase
|
||||
.getDatabase(applicationContext)
|
||||
.cipherDatabaseDao()
|
||||
|
||||
// Temp DAO to easily remove content if object no longer in memory
|
||||
private val useTempDao = PreferencesUtil.isTempAdvancedUnlockEnable(applicationContext)
|
||||
|
||||
private val mIntentAdvancedUnlockService = Intent(applicationContext,
|
||||
AdvancedUnlockNotificationService::class.java)
|
||||
private var mBinder: AdvancedUnlockNotificationService.AdvancedUnlockBinder? = null
|
||||
private var mServiceConnection: ServiceConnection? = null
|
||||
|
||||
fun initialize() {
|
||||
applicationContext.startService(mIntentAdvancedUnlockService)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun getTempCipherDao(tempCipherDaoRetrieved: (MutableList<CipherDatabaseEntity>?) -> Unit) {
|
||||
// Check if a service is currently running else do nothing
|
||||
if (mBinder != null) {
|
||||
tempCipherDaoRetrieved.invoke(mBinder?.getTempCipherDao())
|
||||
} else if (mServiceConnection == null) {
|
||||
mServiceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
|
||||
mBinder = (serviceBinder as AdvancedUnlockNotificationService.AdvancedUnlockBinder)
|
||||
tempCipherDaoRetrieved.invoke(mBinder?.getTempCipherDao())
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
mBinder = null
|
||||
mServiceConnection = null
|
||||
}
|
||||
}
|
||||
// bind Service
|
||||
mServiceConnection?.let {
|
||||
applicationContext.bindService(mIntentAdvancedUnlockService,
|
||||
it,
|
||||
Context.BIND_ABOVE_CLIENT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getCipherDatabase(databaseUri: Uri,
|
||||
cipherDatabaseResultListener: (CipherDatabaseEntity?) -> Unit) {
|
||||
if (useTempDao) {
|
||||
getTempCipherDao { tempCipherDao ->
|
||||
cipherDatabaseResultListener.invoke(tempCipherDao?.firstOrNull { it.databaseUri == databaseUri.toString()})
|
||||
}
|
||||
} else {
|
||||
IOActionTask(
|
||||
{
|
||||
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())
|
||||
@@ -41,6 +91,7 @@ class CipherDatabaseAction(applicationContext: Context) {
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
}
|
||||
|
||||
fun containsCipherDatabase(databaseUri: Uri,
|
||||
contains: (Boolean) -> Unit) {
|
||||
@@ -51,10 +102,17 @@ class CipherDatabaseAction(applicationContext: Context) {
|
||||
|
||||
fun addOrUpdateCipherDatabase(cipherDatabaseEntity: CipherDatabaseEntity,
|
||||
cipherDatabaseResultListener: (() -> Unit)? = null) {
|
||||
if (useTempDao) {
|
||||
getTempCipherDao { tempCipherDao ->
|
||||
val cipherDatabaseRetrieve = tempCipherDao?.firstOrNull { it.databaseUri == cipherDatabaseEntity.databaseUri }
|
||||
cipherDatabaseRetrieve?.replaceContent(cipherDatabaseEntity)
|
||||
?: tempCipherDao?.add(cipherDatabaseEntity)
|
||||
cipherDatabaseResultListener?.invoke()
|
||||
}
|
||||
} else {
|
||||
IOActionTask(
|
||||
{
|
||||
val cipherDatabaseRetrieve = cipherDatabaseDao.getByDatabaseUri(cipherDatabaseEntity.databaseUri)
|
||||
|
||||
// Update values if element not yet in the database
|
||||
if (cipherDatabaseRetrieve == null) {
|
||||
cipherDatabaseDao.add(cipherDatabaseEntity)
|
||||
@@ -67,9 +125,15 @@ class CipherDatabaseAction(applicationContext: Context) {
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteByDatabaseUri(databaseUri: Uri,
|
||||
cipherDatabaseResultListener: (() -> Unit)? = null) {
|
||||
getTempCipherDao { tempCipherDao ->
|
||||
tempCipherDao?.firstOrNull { it.databaseUri == databaseUri.toString() }?.let {
|
||||
tempCipherDao.remove(it)
|
||||
}
|
||||
}
|
||||
IOActionTask(
|
||||
{
|
||||
cipherDatabaseDao.deleteByDatabaseUri(databaseUri.toString())
|
||||
@@ -81,6 +145,9 @@ class CipherDatabaseAction(applicationContext: Context) {
|
||||
}
|
||||
|
||||
fun deleteAll() {
|
||||
getTempCipherDao { tempCipherDao ->
|
||||
tempCipherDao?.clear()
|
||||
}
|
||||
IOActionTask(
|
||||
{
|
||||
cipherDatabaseDao.deleteAll()
|
||||
|
||||
@@ -43,6 +43,11 @@ data class CipherDatabaseEntity(
|
||||
parcel.readString()!!,
|
||||
parcel.readString()!!)
|
||||
|
||||
fun replaceContent(copy: CipherDatabaseEntity) {
|
||||
this.encryptedValue = copy.encryptedValue
|
||||
this.specParameters = copy.specParameters
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(databaseUri)
|
||||
parcel.writeString(encryptedValue)
|
||||
|
||||
@@ -78,6 +78,7 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
|
||||
// Add old listener to enable the button, only be call here because of onCheckedChange bug
|
||||
onCheckedPasswordChangeListener?.onCheckedChanged(compoundButton, checked)
|
||||
}
|
||||
cipherDatabaseAction.initialize()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.kunzisoft.keepass.notifications
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
||||
|
||||
class AdvancedUnlockNotificationService : NotificationService() {
|
||||
|
||||
private lateinit var mTempCipherDao: ArrayList<CipherDatabaseEntity>
|
||||
|
||||
private var mActionTaskBinder = AdvancedUnlockBinder()
|
||||
|
||||
inner class AdvancedUnlockBinder: Binder() {
|
||||
fun getTempCipherDao(): MutableList<CipherDatabaseEntity> {
|
||||
return mTempCipherDao
|
||||
}
|
||||
}
|
||||
|
||||
override val notificationId: Int = 593
|
||||
|
||||
override fun retrieveChannelId(): String {
|
||||
return CHANNEL_ADVANCED_UNLOCK_ID
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
super.onBind(intent)
|
||||
return mActionTaskBinder
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
|
||||
val deleteIntent = Intent(this, AdvancedUnlockNotificationService::class.java).apply {
|
||||
action = ACTION_REMOVE_KEYS
|
||||
}
|
||||
val pendingDeleteIntent = PendingIntent.getService(this, 0, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val notificationBuilder = buildNewNotification().apply {
|
||||
setSmallIcon(R.drawable.bolt)
|
||||
intent?.let {
|
||||
setContentTitle(getString(R.string.advanced_unlock))
|
||||
}
|
||||
setContentText(getString(R.string.advanced_unlock_tap_delete))
|
||||
setContentIntent(pendingDeleteIntent)
|
||||
// Unfortunately swipe is disabled in lollipop+
|
||||
setDeleteIntent(pendingDeleteIntent)
|
||||
}
|
||||
startForeground(notificationId, notificationBuilder.build())
|
||||
|
||||
if (intent?.action == ACTION_REMOVE_KEYS) {
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
mTempCipherDao = ArrayList()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
mTempCipherDao.clear()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CHANNEL_ADVANCED_UNLOCK_ID = "com.kunzisoft.keepass.notification.channel.unlock"
|
||||
|
||||
const val ACTION_REMOVE_KEYS = "ACTION_REMOVE_KEYS"
|
||||
}
|
||||
}
|
||||
@@ -319,6 +319,7 @@
|
||||
<string name="lock_database_show_button_summary">Displays the lock button in the user interface</string>
|
||||
<string name="content">Content</string>
|
||||
<string name="advanced_unlock">Advanced unlock</string>
|
||||
<string name="advanced_unlock_tap_delete">Tap to delete advanced unlocking keys</string>
|
||||
<string name="advanced_unlock_explanation_summary">Use advanced unlocking to open a database more easily</string>
|
||||
<string name="biometric_unlock_enable_title">Biometric unlocking</string>
|
||||
<string name="biometric_unlock_enable_summary">Lets you scan your biometric to open the database</string>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
android:dependency="@string/temp_advanced_unlock_enable_key"
|
||||
android:entries="@array/timeout_options"
|
||||
android:entryValues="@array/timeout_values"
|
||||
android:dialogTitle="@string/clipboard_timeout"
|
||||
android:dialogTitle="@string/advanced_unlock_timeout"
|
||||
android:defaultValue="@string/temp_advanced_unlock_timeout_default"/>
|
||||
<Preference
|
||||
android:key="@string/biometric_delete_all_key_key"
|
||||
|
||||
Reference in New Issue
Block a user