mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'feature/Module_Refactoring' into develop
This commit is contained in:
@@ -6,7 +6,6 @@ apply plugin: 'kotlin-kapt'
|
||||
android {
|
||||
compileSdkVersion 32
|
||||
buildToolsVersion "32.0.0"
|
||||
ndkVersion "21.4.7075529"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.kunzisoft.keepass"
|
||||
@@ -129,11 +128,10 @@ dependencies {
|
||||
implementation 'commons-codec:commons-codec:1.15'
|
||||
// Password generator
|
||||
implementation 'me.gosimple:nbvcxz:1.5.0'
|
||||
// Encrypt lib
|
||||
implementation project(path: ':crypto')
|
||||
// Icon pack
|
||||
implementation project(path: ':icon-pack-classic')
|
||||
implementation project(path: ':icon-pack-material')
|
||||
|
||||
// Modules import
|
||||
implementation project(path: ':database')
|
||||
implementation project(path: ':icon-pack')
|
||||
|
||||
// Tests
|
||||
androidTestImplementation "androidx.test:runner:$android_test_version"
|
||||
|
||||
@@ -30,7 +30,7 @@ import androidx.core.text.HtmlCompat
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.isContributingUser
|
||||
import org.joda.time.DateTime
|
||||
|
||||
class AboutActivity : StylishActivity() {
|
||||
@@ -46,7 +46,7 @@ class AboutActivity : StylishActivity() {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
|
||||
val appName = if (UriUtil.contributingUser(this))
|
||||
val appName = if (this.isContributingUser())
|
||||
getString(R.string.app_name) + " " + getString(R.string.app_name_part3)
|
||||
else
|
||||
getString(R.string.app_name)
|
||||
|
||||
@@ -36,11 +36,12 @@ import com.kunzisoft.keepass.autofill.AutofillComponent
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.autofill.CompatInlineSuggestionsRequest
|
||||
import com.kunzisoft.keepass.autofill.KeeAutofillService
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.helper.SearchHelper
|
||||
import com.kunzisoft.keepass.model.RegisterInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.WebDomain
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
class AutofillLauncherActivity : DatabaseModeActivity() {
|
||||
@@ -58,7 +59,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
// Retrieve selection mode
|
||||
@@ -73,7 +74,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
|
||||
}
|
||||
// Build search param
|
||||
bundle.getParcelable<SearchInfo>(KEY_SEARCH_INFO)?.let { searchInfo ->
|
||||
SearchInfo.getConcreteWebDomain(
|
||||
WebDomain.getConcreteWebDomain(
|
||||
this,
|
||||
searchInfo.webDomain
|
||||
) { concreteWebDomain ->
|
||||
@@ -101,7 +102,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
|
||||
// To register info
|
||||
val registerInfo = intent.getParcelableExtra<RegisterInfo>(KEY_REGISTER_INFO)
|
||||
val searchInfo = SearchInfo(registerInfo?.searchInfo)
|
||||
SearchInfo.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain ->
|
||||
WebDomain.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain ->
|
||||
searchInfo.webDomain = concreteWebDomain
|
||||
launchRegistration(database, searchInfo, registerInfo)
|
||||
}
|
||||
@@ -115,7 +116,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchSelection(database: Database?,
|
||||
private fun launchSelection(database: ContextualDatabase?,
|
||||
autofillComponent: AutofillComponent?,
|
||||
searchInfo: SearchInfo) {
|
||||
if (autofillComponent == null) {
|
||||
@@ -158,7 +159,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchRegistration(database: Database?,
|
||||
private fun launchRegistration(database: ContextualDatabase?,
|
||||
searchInfo: SearchInfo,
|
||||
registerInfo: RegisterInfo?) {
|
||||
if (!KeeAutofillService.autofillAllowedFor(searchInfo.applicationId,
|
||||
|
||||
@@ -36,11 +36,11 @@ import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.core.graphics.BlendModeColorFilterCompat
|
||||
import androidx.core.graphics.BlendModeCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
@@ -51,8 +51,8 @@ import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.SpecialMode
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
|
||||
import com.kunzisoft.keepass.adapters.TagsAdapter
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Attachment
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.education.EntryActivityEducation
|
||||
@@ -67,14 +67,14 @@ import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.AttachmentFileBinderManager
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
import com.kunzisoft.keepass.utils.UuidUtil
|
||||
import com.kunzisoft.keepass.view.changeControlColor
|
||||
import com.kunzisoft.keepass.view.changeTitleColor
|
||||
import com.kunzisoft.keepass.view.hideByFading
|
||||
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
|
||||
import com.kunzisoft.keepass.viewmodels.EntryViewModel
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
|
||||
class EntryActivity : DatabaseLockActivity() {
|
||||
|
||||
@@ -310,14 +310,14 @@ class EntryActivity : DatabaseLockActivity() {
|
||||
return coordinatorLayout
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
mEntryViewModel.loadDatabase(database)
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
@@ -376,7 +376,7 @@ class EntryActivity : DatabaseLockActivity() {
|
||||
.createBlendModeColorFilterCompat(backgroundDarker, BlendModeCompat.SRC_IN)
|
||||
mIcon?.let { icon ->
|
||||
titleIconView?.let { iconView ->
|
||||
mIconDrawableFactory?.assignDatabaseIcon(
|
||||
mDatabase?.iconDrawableFactory?.assignDatabaseIcon(
|
||||
iconView,
|
||||
icon,
|
||||
mForegroundColor ?: mColorAccent
|
||||
@@ -473,7 +473,7 @@ class EntryActivity : DatabaseLockActivity() {
|
||||
}
|
||||
R.id.menu_goto_url -> {
|
||||
mUrl?.let { url ->
|
||||
UriUtil.gotoUrl(this, url)
|
||||
this.openUrl(url)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -526,7 +526,7 @@ class EntryActivity : DatabaseLockActivity() {
|
||||
* Open standard Entry activity
|
||||
*/
|
||||
fun launch(activity: Activity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entryId: NodeId<UUID>,
|
||||
activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||
if (database.loaded) {
|
||||
@@ -542,7 +542,7 @@ class EntryActivity : DatabaseLockActivity() {
|
||||
* Open history Entry activity
|
||||
*/
|
||||
fun launch(activity: Activity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entryId: NodeId<UUID>,
|
||||
historyPosition: Int,
|
||||
activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||
|
||||
@@ -32,7 +32,11 @@ import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import android.widget.AdapterView
|
||||
import android.widget.DatePicker
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Spinner
|
||||
import android.widget.TimePicker
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
@@ -46,8 +50,14 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.*
|
||||
import com.kunzisoft.keepass.activities.dialogs.ColorPickerDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.DatePickerFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.EntryCustomFieldDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.FileTooBigDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.FileTooBigDialogFragment.Companion.MAX_WARNING_BINARY_FILE
|
||||
import com.kunzisoft.keepass.activities.dialogs.ReplaceFileDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.SetOTPDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.TimePickerFragment
|
||||
import com.kunzisoft.keepass.activities.fragments.EntryEditFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
|
||||
@@ -55,7 +65,11 @@ import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
|
||||
import com.kunzisoft.keepass.adapters.TemplatesSelectorAdapter
|
||||
import com.kunzisoft.keepass.autofill.AutofillComponent
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.database.element.*
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Attachment
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Field
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.template.Template
|
||||
@@ -76,12 +90,16 @@ import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.AttachmentFileBinderManager
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.view.*
|
||||
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
|
||||
import com.kunzisoft.keepass.view.ToolbarAction
|
||||
import com.kunzisoft.keepass.view.asError
|
||||
import com.kunzisoft.keepass.view.hideByFading
|
||||
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
|
||||
import com.kunzisoft.keepass.view.updateLockPaddingLeft
|
||||
import com.kunzisoft.keepass.viewmodels.ColorPickerViewModel
|
||||
import com.kunzisoft.keepass.viewmodels.EntryEditViewModel
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
|
||||
class EntryEditActivity : DatabaseLockActivity(),
|
||||
EntryCustomFieldDialogFragment.EntryCustomFieldListener,
|
||||
@@ -185,7 +203,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
mExternalFileHelper = ExternalFileHelper(this)
|
||||
mExternalFileHelper?.buildOpenDocument { uri ->
|
||||
uri?.let { attachmentToUploadUri ->
|
||||
UriUtil.getFileData(this, attachmentToUploadUri)?.also { documentFile ->
|
||||
attachmentToUploadUri.getDocumentFile(this)?.also { documentFile ->
|
||||
documentFile.name?.let { fileName ->
|
||||
if (documentFile.length() > MAX_WARNING_BINARY_FILE) {
|
||||
FileTooBigDialogFragment.build(attachmentToUploadUri, fileName)
|
||||
@@ -221,7 +239,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
this@EntryEditActivity,
|
||||
templates
|
||||
).apply {
|
||||
iconDrawableFactory = mIconDrawableFactory
|
||||
iconDrawableFactory = mDatabase?.iconDrawableFactory
|
||||
}
|
||||
adapter = mTemplatesSelectorAdapter
|
||||
val selectedTemplate = if (mTemplate != null)
|
||||
@@ -368,19 +386,19 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
mAllowCustomFields = database?.allowEntryCustomFields() == true
|
||||
mAllowOTP = database?.allowOTP == true
|
||||
mEntryEditViewModel.loadDatabase(database)
|
||||
mTemplatesSelectorAdapter?.apply {
|
||||
iconDrawableFactory = mIconDrawableFactory
|
||||
iconDrawableFactory = mDatabase?.iconDrawableFactory
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
@@ -433,7 +451,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
finishForEntryResult(entry)
|
||||
}
|
||||
|
||||
private fun entryValidatedForKeyboardSelection(database: Database, entry: Entry) {
|
||||
private fun entryValidatedForKeyboardSelection(database: ContextualDatabase, entry: Entry) {
|
||||
// Populate Magikeyboard with entry
|
||||
MagikeyboardService.populateKeyboardAndMoveAppToBackground(
|
||||
this,
|
||||
@@ -444,7 +462,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
finishForEntryResult(entry)
|
||||
}
|
||||
|
||||
private fun entryValidatedForAutofillSelection(database: Database, entry: Entry) {
|
||||
private fun entryValidatedForAutofillSelection(database: ContextualDatabase, entry: Entry) {
|
||||
// Build Autofill response with the entry selected
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
AutofillHelper.buildResponseAndSetResult(this@EntryEditActivity,
|
||||
@@ -759,7 +777,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
* Launch EntryEditActivity to update an existing entry by his [entryId]
|
||||
*/
|
||||
fun launchToUpdate(activity: Activity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entryId: NodeId<UUID>,
|
||||
activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
@@ -775,7 +793,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
* Launch EntryEditActivity to add a new entry in an existent group
|
||||
*/
|
||||
fun launchToCreate(activity: Activity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
groupId: NodeId<*>,
|
||||
activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
@@ -788,7 +806,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
fun launchToUpdateForSave(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entryId: NodeId<UUID>,
|
||||
searchInfo: SearchInfo) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
@@ -805,7 +823,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
fun launchToCreateForSave(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
groupId: NodeId<*>,
|
||||
searchInfo: SearchInfo) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
@@ -825,7 +843,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
* Launch EntryEditActivity to add a new entry in keyboard selection
|
||||
*/
|
||||
fun launchForKeyboardSelectionResult(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
groupId: NodeId<*>,
|
||||
searchInfo: SearchInfo? = null) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
@@ -846,7 +864,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
fun launchForAutofillResult(activity: AppCompatActivity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
activityResultLauncher: ActivityResultLauncher<Intent>?,
|
||||
autofillComponent: AutofillComponent,
|
||||
groupId: NodeId<*>,
|
||||
@@ -870,7 +888,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
* Launch EntryEditActivity to register an updated entry (from autofill)
|
||||
*/
|
||||
fun launchToUpdateForRegistration(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entryId: NodeId<UUID>,
|
||||
registerInfo: RegisterInfo? = null) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
@@ -890,7 +908,7 @@ class EntryEditActivity : DatabaseLockActivity(),
|
||||
* Launch EntryEditActivity to register a new entry (from autofill)
|
||||
*/
|
||||
fun launchToCreateForRegistration(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
groupId: NodeId<*>,
|
||||
registerInfo: RegisterInfo? = null) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
|
||||
@@ -26,11 +26,12 @@ import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseModeActivity
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.helper.SearchHelper
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.otp.OtpEntryFields
|
||||
import com.kunzisoft.keepass.utils.WebDomain
|
||||
|
||||
/**
|
||||
* Activity to search or select entry in database,
|
||||
@@ -46,7 +47,7 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
val keySelectionBundle = intent.getBundleExtra(KEY_SELECTION_BUNDLE)
|
||||
@@ -95,7 +96,7 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun launchSelection(database: Database?,
|
||||
private fun launchSelection(database: ContextualDatabase?,
|
||||
sharedWebDomain: String?,
|
||||
otpString: String?) {
|
||||
// Build domain search param
|
||||
@@ -104,13 +105,13 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
|
||||
this.otpString = otpString
|
||||
}
|
||||
|
||||
SearchInfo.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain ->
|
||||
WebDomain.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain ->
|
||||
searchInfo.webDomain = concreteWebDomain
|
||||
launch(database, searchInfo)
|
||||
}
|
||||
}
|
||||
|
||||
private fun launch(database: Database?,
|
||||
private fun launch(database: ContextualDatabase?,
|
||||
searchInfo: SearchInfo) {
|
||||
|
||||
// Setting to integrate Magikeyboard
|
||||
|
||||
@@ -53,9 +53,9 @@ import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.autofill.AutofillComponent
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.model.RegisterInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
@@ -65,7 +65,12 @@ import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.utils.*
|
||||
import com.kunzisoft.keepass.utils.DexUtil
|
||||
import com.kunzisoft.keepass.utils.MagikeyboardUtil
|
||||
import com.kunzisoft.keepass.utils.MenuUtil
|
||||
import com.kunzisoft.keepass.utils.UriHelper.parseUri
|
||||
import com.kunzisoft.keepass.utils.UriUtil.isContributingUser
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
import com.kunzisoft.keepass.view.asError
|
||||
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
|
||||
import com.kunzisoft.keepass.viewmodels.DatabaseFilesViewModel
|
||||
@@ -179,7 +184,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
||||
&& savedInstanceState.getBoolean(EXTRA_STAY, false))) {
|
||||
val databasePath = PreferencesUtil.getDefaultDatabasePath(this)
|
||||
|
||||
UriUtil.parse(databasePath)?.let { databaseFileUri ->
|
||||
databasePath?.parseUri()?.let { databaseFileUri ->
|
||||
launchPasswordActivityWithPath(databaseFileUri)
|
||||
} ?: run {
|
||||
Log.i(TAG, "No default database to prepare")
|
||||
@@ -228,7 +233,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
if (database != null) {
|
||||
launchGroupActivityIfLoaded(database)
|
||||
@@ -236,7 +241,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
@@ -304,7 +309,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
||||
mAutofillActivityResultLauncher)
|
||||
}
|
||||
|
||||
private fun launchGroupActivityIfLoaded(database: Database) {
|
||||
private fun launchGroupActivityIfLoaded(database: ContextualDatabase) {
|
||||
if (database.loaded) {
|
||||
GroupActivity.launch(this,
|
||||
database,
|
||||
@@ -326,7 +331,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
||||
super.onResume()
|
||||
|
||||
// Define special title
|
||||
specialTitle?.isVisible = UriUtil.contributingUser(this)
|
||||
specialTitle?.isVisible = this.isContributingUser()
|
||||
|
||||
// Show open and create button or special mode
|
||||
when (mSpecialMode) {
|
||||
@@ -426,7 +431,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> UriUtil.gotoUrl(this, R.string.file_manager_explanation_url)
|
||||
android.R.id.home -> this.openUrl(R.string.file_manager_explanation_url)
|
||||
}
|
||||
MenuUtil.onDefaultMenuOptionsItemSelected(this, item)
|
||||
return super.onOptionsItemSelected(item)
|
||||
|
||||
@@ -27,13 +27,23 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.PorterDuff
|
||||
import android.net.Uri
|
||||
import android.os.*
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import android.widget.DatePicker
|
||||
import android.widget.ImageView
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import android.widget.TimePicker
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.RequiresApi
|
||||
@@ -50,7 +60,12 @@ import androidx.core.view.isVisible
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.*
|
||||
import com.kunzisoft.keepass.activities.dialogs.DatePickerFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.GroupDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.MainCredentialDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.SortDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.TimePickerFragment
|
||||
import com.kunzisoft.keepass.activities.fragments.GroupFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
|
||||
@@ -59,17 +74,21 @@ import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
|
||||
import com.kunzisoft.keepass.adapters.BreadcrumbAdapter
|
||||
import com.kunzisoft.keepass.autofill.AutofillComponent
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.database.element.*
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.SortNodeEnum
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.database.helper.SearchHelper
|
||||
import com.kunzisoft.keepass.database.search.SearchParameters
|
||||
import com.kunzisoft.keepass.education.GroupActivityEducation
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
|
||||
import com.kunzisoft.keepass.model.GroupInfo
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.model.RegisterInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK
|
||||
@@ -81,8 +100,14 @@ import com.kunzisoft.keepass.settings.SettingsActivity
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.view.*
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
import com.kunzisoft.keepass.view.AddNodeButtonView
|
||||
import com.kunzisoft.keepass.view.NavigationDatabaseView
|
||||
import com.kunzisoft.keepass.view.SearchFiltersView
|
||||
import com.kunzisoft.keepass.view.ToolbarAction
|
||||
import com.kunzisoft.keepass.view.hideByFading
|
||||
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
|
||||
import com.kunzisoft.keepass.view.updateLockPaddingLeft
|
||||
import com.kunzisoft.keepass.viewmodels.GroupEditViewModel
|
||||
import com.kunzisoft.keepass.viewmodels.GroupViewModel
|
||||
import org.joda.time.DateTime
|
||||
@@ -302,7 +327,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
lockAndExit()
|
||||
}
|
||||
R.id.menu_contribute -> {
|
||||
UriUtil.gotoUrl(this@GroupActivity, R.string.contribution_url)
|
||||
this@GroupActivity.openUrl(R.string.contribution_url)
|
||||
}
|
||||
R.id.menu_about -> {
|
||||
startActivity(Intent(this@GroupActivity, AboutActivity::class.java))
|
||||
@@ -570,7 +595,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
mGroupEditViewModel.setGroupNamesNotAllowed(database?.groupNamesNotAllowed)
|
||||
@@ -614,7 +639,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
@@ -800,7 +825,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onNodeClick(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
node: Node
|
||||
) {
|
||||
when (node.type) {
|
||||
@@ -873,7 +898,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
reloadGroupIfSearch()
|
||||
}
|
||||
|
||||
private fun entrySelectedForSave(database: Database, entry: Entry, searchInfo: SearchInfo) {
|
||||
private fun entrySelectedForSave(database: ContextualDatabase, entry: Entry, searchInfo: SearchInfo) {
|
||||
reloadCurrentGroup()
|
||||
// Save to update the entry
|
||||
EntryEditActivity.launchToUpdateForSave(
|
||||
@@ -885,7 +910,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
onLaunchActivitySpecialMode()
|
||||
}
|
||||
|
||||
private fun entrySelectedForKeyboardSelection(database: Database, entry: Entry) {
|
||||
private fun entrySelectedForKeyboardSelection(database: ContextualDatabase, entry: Entry) {
|
||||
reloadCurrentGroup()
|
||||
// Populate Magikeyboard with entry
|
||||
MagikeyboardService.populateKeyboardAndMoveAppToBackground(
|
||||
@@ -895,7 +920,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
onValidateSpecialMode()
|
||||
}
|
||||
|
||||
private fun entrySelectedForAutofillSelection(database: Database, entry: Entry) {
|
||||
private fun entrySelectedForAutofillSelection(database: ContextualDatabase, entry: Entry) {
|
||||
// Build response with the entry selected
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
AutofillHelper.buildResponseAndSetResult(
|
||||
@@ -908,7 +933,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
private fun entrySelectedForRegistration(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entry: Entry,
|
||||
registerInfo: RegisterInfo?
|
||||
) {
|
||||
@@ -924,7 +949,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
private fun updateEntryWithSearchInfo(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entry: Entry,
|
||||
searchInfo: SearchInfo
|
||||
) {
|
||||
@@ -964,7 +989,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onNodeSelected(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
nodes: List<Node>
|
||||
): Boolean {
|
||||
if (nodes.isNotEmpty()) {
|
||||
@@ -990,7 +1015,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onOpenMenuClick(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
node: Node
|
||||
): Boolean {
|
||||
finishNodeAction()
|
||||
@@ -999,7 +1024,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onEditMenuClick(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
node: Node
|
||||
): Boolean {
|
||||
finishNodeAction()
|
||||
@@ -1047,7 +1072,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onCopyMenuClick(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
nodes: List<Node>
|
||||
): Boolean {
|
||||
actionNodeMode?.invalidate()
|
||||
@@ -1057,7 +1082,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onMoveMenuClick(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
nodes: List<Node>
|
||||
): Boolean {
|
||||
actionNodeMode?.invalidate()
|
||||
@@ -1067,7 +1092,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onPasteMenuClick(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
pasteMode: GroupFragment.PasteMode?,
|
||||
nodes: List<Node>
|
||||
): Boolean {
|
||||
@@ -1092,7 +1117,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
}
|
||||
|
||||
override fun onDeleteMenuClick(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
nodes: List<Node>
|
||||
): Boolean {
|
||||
deleteNodes(nodes)
|
||||
@@ -1101,15 +1126,19 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onAskMainCredentialDialogPositiveClick(databaseUri: Uri?,
|
||||
mainCredential: MainCredential) {
|
||||
override fun onAskMainCredentialDialogPositiveClick(
|
||||
databaseUri: Uri?,
|
||||
mainCredential: MainCredential
|
||||
) {
|
||||
databaseUri?.let {
|
||||
mergeDatabaseFrom(it, mainCredential)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAskMainCredentialDialogNegativeClick(databaseUri: Uri?,
|
||||
mainCredential: MainCredential) { }
|
||||
override fun onAskMainCredentialDialogNegativeClick(
|
||||
databaseUri: Uri?,
|
||||
mainCredential: MainCredential
|
||||
) { }
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
@@ -1475,7 +1504,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launch(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
autoSearch: Boolean = false) {
|
||||
if (database.loaded) {
|
||||
checkTimeAndBuildIntent(context, null) { intent ->
|
||||
@@ -1491,7 +1520,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launchForSearchResult(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
searchInfo: SearchInfo,
|
||||
autoSearch: Boolean = false) {
|
||||
if (database.loaded) {
|
||||
@@ -1512,7 +1541,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launchForSaveResult(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
searchInfo: SearchInfo,
|
||||
autoSearch: Boolean = false) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
@@ -1533,7 +1562,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launchForKeyboardSelectionResult(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
searchInfo: SearchInfo? = null,
|
||||
autoSearch: Boolean = false) {
|
||||
if (database.loaded) {
|
||||
@@ -1555,7 +1584,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
fun launchForAutofillResult(activity: AppCompatActivity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
activityResultLaunch: ActivityResultLauncher<Intent>?,
|
||||
autofillComponent: AutofillComponent,
|
||||
searchInfo: SearchInfo? = null,
|
||||
@@ -1580,7 +1609,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launchForRegistration(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
registerInfo: RegisterInfo? = null) {
|
||||
if (database.loaded && !database.isReadOnly) {
|
||||
checkTimeAndBuildIntent(context, null) { intent ->
|
||||
@@ -1600,7 +1629,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
* -------------------------
|
||||
*/
|
||||
fun launch(activity: AppCompatActivity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
onValidateSpecialMode: () -> Unit,
|
||||
onCancelSpecialMode: () -> Unit,
|
||||
onLaunchActivitySpecialMode: () -> Unit,
|
||||
|
||||
@@ -41,16 +41,22 @@ import com.kunzisoft.keepass.activities.fragments.IconPickerFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.BinaryDatabaseManager
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
import com.kunzisoft.keepass.view.asError
|
||||
import com.kunzisoft.keepass.view.updateLockPaddingLeft
|
||||
import com.kunzisoft.keepass.viewmodels.IconPickerViewModel
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
||||
class IconPickerActivity : DatabaseLockActivity() {
|
||||
@@ -166,7 +172,7 @@ class IconPickerActivity : DatabaseLockActivity() {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
if (database?.allowCustomIcons == true) {
|
||||
@@ -243,7 +249,7 @@ class IconPickerActivity : DatabaseLockActivity() {
|
||||
}
|
||||
}
|
||||
R.id.menu_external_icon -> {
|
||||
UriUtil.gotoUrl(this, R.string.external_icon_url)
|
||||
this.openUrl(R.string.external_icon_url)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +263,7 @@ class IconPickerActivity : DatabaseLockActivity() {
|
||||
// on Progress with thread
|
||||
val asyncResult: Deferred<IconPickerViewModel.IconCustomState?> = async {
|
||||
val iconCustomState = IconPickerViewModel.IconCustomState(null, true, R.string.error_upload_file)
|
||||
UriUtil.getFileData(this@IconPickerActivity, iconToUploadUri)?.also { documentFile ->
|
||||
iconToUploadUri?.getDocumentFile(this@IconPickerActivity)?.also { documentFile ->
|
||||
if (documentFile.length() > MAX_ICON_SIZE) {
|
||||
iconCustomState.errorStringId = R.string.error_file_to_big
|
||||
} else {
|
||||
|
||||
@@ -33,8 +33,8 @@ import androidx.appcompat.widget.Toolbar
|
||||
import com.igreenwood.loupe.Loupe
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Attachment
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.tasks.BinaryDatabaseManager
|
||||
import kotlin.math.max
|
||||
|
||||
@@ -100,7 +100,7 @@ class ImageViewerActivity : DatabaseLockActivity() {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
try {
|
||||
|
||||
@@ -55,8 +55,8 @@ import com.kunzisoft.keepass.autofill.AutofillComponent
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.biometric.AdvancedUnlockFragment
|
||||
import com.kunzisoft.keepass.biometric.AdvancedUnlockManager
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
||||
import com.kunzisoft.keepass.database.exception.FileNotFoundDatabaseException
|
||||
import com.kunzisoft.keepass.education.PasswordActivityEducation
|
||||
@@ -72,7 +72,7 @@ import com.kunzisoft.keepass.settings.SettingsAdvancedUnlockActivity
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION
|
||||
import com.kunzisoft.keepass.utils.MenuUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.getUri
|
||||
import com.kunzisoft.keepass.view.MainCredentialView
|
||||
import com.kunzisoft.keepass.view.asError
|
||||
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
|
||||
@@ -262,7 +262,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
if (database != null) {
|
||||
// Trying to load another database
|
||||
@@ -279,7 +279,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
@@ -344,7 +344,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
||||
if (action == VIEW_INTENT) {
|
||||
fillCredentials(
|
||||
intent.data,
|
||||
UriUtil.getUriFromIntent(intent, KEY_KEYFILE),
|
||||
intent.getUri(KEY_KEYFILE),
|
||||
HardwareKey.getHardwareKeyFromString(intent.getStringExtra(KEY_HARDWARE_KEY))
|
||||
)
|
||||
} else {
|
||||
@@ -357,7 +357,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
||||
try {
|
||||
intent?.removeExtra(KEY_KEYFILE)
|
||||
intent?.removeExtra(KEY_HARDWARE_KEY)
|
||||
} catch (e: Exception) {}
|
||||
} catch (_: Exception) {}
|
||||
mDatabaseFileUri?.let {
|
||||
mDatabaseFileViewModel.checkIfIsDefaultDatabase(it)
|
||||
}
|
||||
@@ -376,7 +376,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
|
||||
getUriFromIntent(intent)
|
||||
}
|
||||
|
||||
private fun launchGroupActivityIfLoaded(database: Database) {
|
||||
private fun launchGroupActivityIfLoaded(database: ContextualDatabase) {
|
||||
// Check if database really loaded
|
||||
if (database.loaded) {
|
||||
clearCredentialsViews(clearKeyFile = true, clearHardwareKey = true)
|
||||
|
||||
@@ -78,7 +78,8 @@ class DatabaseChangedDialogFragment : DatabaseDialogFragment() {
|
||||
private const val NEW_FILE_DATABASE_INFO = "NEW_FILE_DATABASE_INFO"
|
||||
|
||||
fun getInstance(oldSnapFileDatabaseInfo: SnapFileDatabaseInfo,
|
||||
newSnapFileDatabaseInfo: SnapFileDatabaseInfo)
|
||||
newSnapFileDatabaseInfo: SnapFileDatabaseInfo
|
||||
)
|
||||
: DatabaseChangedDialogFragment {
|
||||
val fragment = DatabaseChangedDialogFragment()
|
||||
fragment.arguments = Bundle().apply {
|
||||
|
||||
@@ -5,7 +5,8 @@ import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
|
||||
import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||
@@ -13,7 +14,9 @@ import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||
abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
|
||||
|
||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
||||
private var mDatabase: Database? = null
|
||||
private var mDatabase: ContextualDatabase? = null
|
||||
|
||||
protected var mIconDrawableFactory: IconDrawableFactory? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -36,12 +39,12 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
|
||||
resetAppTimeoutOnTouchOrFocus()
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
// Can be overridden by a subclass
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
|
||||
@@ -21,12 +21,12 @@ package com.kunzisoft.keepass.activities.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
|
||||
class FileManagerDialogFragment : DialogFragment() {
|
||||
|
||||
@@ -42,7 +42,7 @@ class FileManagerDialogFragment : DialogFragment() {
|
||||
textDescription.text = getString(R.string.file_manager_install_description)
|
||||
|
||||
root.findViewById<Button>(R.id.file_manager_button).setOnClickListener {
|
||||
UriUtil.gotoUrl(requireContext(), R.string.file_manager_explanation_url)
|
||||
context?.openUrl(R.string.file_manager_explanation_url)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.adapters.TagsAdapter
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.model.GroupInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.TimeUtil.getDateTimeString
|
||||
import com.kunzisoft.keepass.utils.UuidUtil
|
||||
import com.kunzisoft.keepass.view.DateTimeFieldView
|
||||
|
||||
@@ -60,10 +61,10 @@ class GroupDialogFragment : DatabaseDialogFragment() {
|
||||
private lateinit var uuidContainerView: ViewGroup
|
||||
private lateinit var uuidReferenceView: TextView
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
mPopulateIconMethod = { imageView, icon ->
|
||||
database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor)
|
||||
mIconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor)
|
||||
}
|
||||
mPopulateIconMethod?.invoke(iconView, mGroupInfo.icon)
|
||||
|
||||
|
||||
@@ -24,14 +24,18 @@ import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment.EditGroupDialogAction.*
|
||||
import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment.EditGroupDialogAction.CREATION
|
||||
import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment.EditGroupDialogAction.NONE
|
||||
import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment.EditGroupDialogAction.UPDATE
|
||||
import com.kunzisoft.keepass.adapters.TagsProposalAdapter
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.model.GroupInfo
|
||||
@@ -116,7 +120,7 @@ class GroupEditDialogFragment : DatabaseDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
mPopulateIconMethod = { imageView, icon ->
|
||||
|
||||
@@ -27,7 +27,7 @@ import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
|
||||
@@ -44,7 +44,7 @@ class IconEditDialogFragment : DatabaseDialogFragment() {
|
||||
|
||||
private var mCustomIcon: IconImageCustom? = null
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
mPopulateIconMethod = { imageView, icon ->
|
||||
database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon)
|
||||
|
||||
@@ -27,8 +27,8 @@ import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
|
||||
import com.kunzisoft.keepass.view.MainCredentialView
|
||||
|
||||
class MainCredentialDialogFragment : DatabaseDialogFragment() {
|
||||
@@ -74,7 +74,7 @@ class MainCredentialDialogFragment : DatabaseDialogFragment() {
|
||||
mainCredentialView = root.findViewById(R.id.main_credential_view)
|
||||
databaseUri?.let {
|
||||
root.findViewById<TextView>(R.id.title_database)?.text =
|
||||
UriUtil.getFileData(requireContext(), it)?.name
|
||||
it.getDocumentFile(requireContext())?.name
|
||||
}
|
||||
builder.setView(root)
|
||||
// Add action buttons
|
||||
|
||||
@@ -26,7 +26,7 @@ import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
|
||||
class PasswordEncodingDialogFragment : DialogFragment() {
|
||||
|
||||
@@ -78,8 +78,10 @@ class PasswordEncodingDialogFragment : DialogFragment() {
|
||||
private const val DATABASE_URI_KEY = "DATABASE_URI_KEY"
|
||||
private const val MAIN_CREDENTIAL = "MAIN_CREDENTIAL"
|
||||
|
||||
fun getInstance(databaseUri: Uri,
|
||||
mainCredential: MainCredential): SortDialogFragment {
|
||||
fun getInstance(
|
||||
databaseUri: Uri,
|
||||
mainCredential: MainCredential
|
||||
): SortDialogFragment {
|
||||
val fragment = SortDialogFragment()
|
||||
fragment.arguments = Bundle().apply {
|
||||
putParcelable(DATABASE_URI_KEY, databaseUri)
|
||||
|
||||
@@ -28,7 +28,7 @@ import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
|
||||
/**
|
||||
* Custom Dialog that asks the user to download the pro version or make a donation.
|
||||
@@ -45,7 +45,7 @@ class ProFeatureDialogFragment : DialogFragment() {
|
||||
stringBuilder.append(HtmlCompat.fromHtml(getString(R.string.html_text_ad_free), FROM_HTML_MODE_LEGACY)).append("\n\n")
|
||||
stringBuilder.append(HtmlCompat.fromHtml(getString(R.string.html_text_buy_pro), FROM_HTML_MODE_LEGACY))
|
||||
builder.setPositiveButton(R.string.download) { _, _ ->
|
||||
UriUtil.gotoUrl(activity,
|
||||
activity.openUrl(
|
||||
activity.getString(R.string.play_store_url,
|
||||
activity.getString(R.string.keepro_app_id))
|
||||
)
|
||||
@@ -54,7 +54,7 @@ class ProFeatureDialogFragment : DialogFragment() {
|
||||
stringBuilder.append(HtmlCompat.fromHtml(getString(R.string.html_text_feature_generosity), FROM_HTML_MODE_LEGACY)).append("\n\n")
|
||||
stringBuilder.append(HtmlCompat.fromHtml(getString(R.string.html_text_donation), FROM_HTML_MODE_LEGACY))
|
||||
builder.setPositiveButton(R.string.contribute) { _, _ ->
|
||||
UriUtil.gotoUrl(activity, R.string.contribution_url)
|
||||
activity.openUrl(R.string.contribution_url)
|
||||
}
|
||||
}
|
||||
builder.setMessage(stringBuilder)
|
||||
|
||||
@@ -35,11 +35,12 @@ import com.google.android.material.textfield.TextInputLayout
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.hardware.HardwareKeyActivity
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.password.PasswordEntropy
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
import com.kunzisoft.keepass.view.HardwareKeySelectionView
|
||||
import com.kunzisoft.keepass.view.KeyFileSelectionView
|
||||
import com.kunzisoft.keepass.view.PassKeyView
|
||||
@@ -136,7 +137,7 @@ class SetMainCredentialDialogFragment : DatabaseDialogFragment() {
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
|
||||
rootView.findViewById<View>(R.id.credentials_information)?.setOnClickListener {
|
||||
UriUtil.gotoUrl(activity, R.string.credentials_explanation_url)
|
||||
activity.openUrl(R.string.credentials_explanation_url)
|
||||
}
|
||||
|
||||
passwordCheckBox = rootView.findViewById(R.id.password_checkbox)
|
||||
@@ -154,7 +155,7 @@ class SetMainCredentialDialogFragment : DatabaseDialogFragment() {
|
||||
mExternalFileHelper = ExternalFileHelper(this)
|
||||
mExternalFileHelper?.buildOpenDocument { uri ->
|
||||
uri?.let { pathUri ->
|
||||
UriUtil.getFileData(requireContext(), uri)?.length()?.let { lengthFile ->
|
||||
pathUri.getDocumentFile(requireContext())?.length()?.let { lengthFile ->
|
||||
keyFileSelectionView.error = null
|
||||
keyFileCheckBox.isChecked = true
|
||||
keyFileSelectionView.uri = pathUri
|
||||
|
||||
@@ -32,7 +32,6 @@ import android.view.inputmethod.EditorInfo
|
||||
import android.widget.*
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.model.OtpModel
|
||||
import com.kunzisoft.keepass.otp.OtpElement
|
||||
@@ -45,7 +44,8 @@ import com.kunzisoft.keepass.otp.OtpElement.Companion.MIN_TOTP_PERIOD
|
||||
import com.kunzisoft.keepass.otp.OtpTokenType
|
||||
import com.kunzisoft.keepass.otp.OtpType
|
||||
import com.kunzisoft.keepass.otp.TokenCalculator
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.isContributingUser
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
import java.util.*
|
||||
|
||||
class SetOTPDialogFragment : DatabaseDialogFragment() {
|
||||
@@ -206,7 +206,7 @@ class SetOTPDialogFragment : DatabaseDialogFragment() {
|
||||
}
|
||||
// Proprietary only on full version
|
||||
mTotpTokenTypeArray = OtpTokenType.getTotpTokenTypeValues(
|
||||
UriUtil.contributingUser(activity)
|
||||
activity.isContributingUser()
|
||||
)
|
||||
totpTokenTypeAdapter = ArrayAdapter(activity,
|
||||
android.R.layout.simple_spinner_item, mTotpTokenTypeArray!!).apply {
|
||||
@@ -242,7 +242,7 @@ class SetOTPDialogFragment : DatabaseDialogFragment() {
|
||||
}
|
||||
|
||||
root?.findViewById<View>(R.id.otp_information)?.setOnClickListener {
|
||||
UriUtil.gotoUrl(activity, R.string.otp_explanation_url)
|
||||
activity.openUrl(R.string.otp_explanation_url)
|
||||
}
|
||||
|
||||
return builder.create()
|
||||
|
||||
@@ -26,7 +26,7 @@ import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
|
||||
/**
|
||||
* Custom Dialog that asks the user to download the pro version or make a donation.
|
||||
@@ -40,7 +40,7 @@ class UnderDevelopmentFeatureDialogFragment : DialogFragment() {
|
||||
|
||||
val stringBuilder = SpannableStringBuilder()
|
||||
/*
|
||||
if (UriUtil.contributingUser(activity)) {
|
||||
if (activity.isContributingUser()) {
|
||||
stringBuilder.append(HtmlCompat.fromHtml(getString(R.string.html_text_dev_feature_thanks), HtmlCompat.FROM_HTML_MODE_LEGACY)).append("\n\n")
|
||||
.append(HtmlCompat.fromHtml(getString(R.string.html_rose), HtmlCompat.FROM_HTML_MODE_LEGACY)).append("\n\n")
|
||||
.append(HtmlCompat.fromHtml(getString(R.string.html_text_dev_feature_work_hard), HtmlCompat.FROM_HTML_MODE_LEGACY)).append("\n")
|
||||
@@ -52,7 +52,7 @@ class UnderDevelopmentFeatureDialogFragment : DialogFragment() {
|
||||
.append(HtmlCompat.fromHtml(getString(R.string.html_text_dev_feature_contibute), HtmlCompat.FROM_HTML_MODE_LEGACY)).append(" ")
|
||||
.append(HtmlCompat.fromHtml(getString(R.string.html_text_dev_feature_encourage), HtmlCompat.FROM_HTML_MODE_LEGACY))
|
||||
builder.setPositiveButton(R.string.contribute) { _, _ ->
|
||||
UriUtil.gotoUrl(requireContext(), R.string.contribution_url)
|
||||
context?.openUrl(R.string.contribution_url)
|
||||
}
|
||||
//}
|
||||
builder.setMessage(stringBuilder)
|
||||
|
||||
@@ -6,7 +6,7 @@ import androidx.fragment.app.activityViewModels
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
|
||||
import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishFragment
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||
@@ -14,7 +14,7 @@ import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||
abstract class DatabaseFragment : StylishFragment(), DatabaseRetrieval {
|
||||
|
||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
||||
protected var mDatabase: Database? = null
|
||||
protected var mDatabase: ContextualDatabase? = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
@@ -38,7 +38,7 @@ abstract class DatabaseFragment : StylishFragment(), DatabaseRetrieval {
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
|
||||
@@ -35,14 +35,18 @@ import com.kunzisoft.keepass.activities.dialogs.ReplaceFileDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.SetOTPDialogFragment
|
||||
import com.kunzisoft.keepass.adapters.EntryAttachmentsItemsAdapter
|
||||
import com.kunzisoft.keepass.adapters.TagsProposalAdapter
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Attachment
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.template.Template
|
||||
import com.kunzisoft.keepass.model.AttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.StreamDirection
|
||||
import com.kunzisoft.keepass.view.*
|
||||
import com.kunzisoft.keepass.view.TagsCompletionView
|
||||
import com.kunzisoft.keepass.view.TemplateEditView
|
||||
import com.kunzisoft.keepass.view.collapse
|
||||
import com.kunzisoft.keepass.view.expand
|
||||
import com.kunzisoft.keepass.view.showByFading
|
||||
import com.kunzisoft.keepass.viewmodels.EntryEditViewModel
|
||||
import com.tokenautocomplete.FilteredArrayAdapter
|
||||
|
||||
@@ -268,7 +272,7 @@ class EntryEditFragment: DatabaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
|
||||
templateView.populateIconMethod = { imageView, icon ->
|
||||
database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor)
|
||||
|
||||
@@ -14,14 +14,16 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.adapters.EntryAttachmentsItemsAdapter
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Attachment
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.template.TemplateField
|
||||
import com.kunzisoft.keepass.database.helper.getLocalizedName
|
||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.StreamDirection
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.ClipboardHelper
|
||||
import com.kunzisoft.keepass.utils.TimeUtil.getDateTimeString
|
||||
import com.kunzisoft.keepass.utils.UuidUtil
|
||||
import com.kunzisoft.keepass.view.TemplateView
|
||||
import com.kunzisoft.keepass.view.hideByFading
|
||||
@@ -132,7 +134,7 @@ class EntryFragment: DatabaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
context?.let { context ->
|
||||
attachmentsAdapter = EntryAttachmentsItemsAdapter(context)
|
||||
attachmentsAdapter?.database = database
|
||||
|
||||
@@ -22,7 +22,12 @@ package com.kunzisoft.keepass.activities.fragments
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@@ -34,7 +39,7 @@ import com.kunzisoft.keepass.activities.dialogs.SortDialogFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.SpecialMode
|
||||
import com.kunzisoft.keepass.adapters.NodesAdapter
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.SortNodeEnum
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
@@ -42,7 +47,7 @@ import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.viewmodels.GroupViewModel
|
||||
import java.util.*
|
||||
import java.util.LinkedList
|
||||
|
||||
class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListener {
|
||||
|
||||
@@ -143,7 +148,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
mRecycleBinEnable = database?.isRecycleBinEnabled == true
|
||||
mRecycleBin = database?.recycleBin
|
||||
|
||||
@@ -151,7 +156,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
||||
database?.let { database ->
|
||||
mAdapter = NodesAdapter(context, database).apply {
|
||||
setOnNodeClickListener(object : NodesAdapter.NodeClickCallback {
|
||||
override fun onNodeClick(database: Database, node: Node) {
|
||||
override fun onNodeClick(database: ContextualDatabase, node: Node) {
|
||||
if (mCurrentGroup?.isVirtual == false
|
||||
&& nodeActionSelectionMode) {
|
||||
if (listActionNodes.contains(node)) {
|
||||
@@ -169,7 +174,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNodeLongClick(database: Database, node: Node): Boolean {
|
||||
override fun onNodeLongClick(database: ContextualDatabase, node: Node): Boolean {
|
||||
if (mCurrentGroup?.isVirtual == false
|
||||
&& nodeActionPasteMode == PasteMode.UNDEFINED) {
|
||||
// Select the first item after a long click
|
||||
@@ -191,7 +196,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
@@ -329,7 +334,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
||||
}
|
||||
}
|
||||
|
||||
fun actionNodesCallback(database: Database,
|
||||
fun actionNodesCallback(database: ContextualDatabase,
|
||||
nodes: List<Node>,
|
||||
menuListener: NodesActionMenuListener?,
|
||||
onDestroyActionMode: (mode: ActionMode?) -> Unit) : ActionMode.Callback {
|
||||
@@ -433,20 +438,20 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
||||
* Callback listener to redefine to do an action when a node is click
|
||||
*/
|
||||
interface NodeClickListener {
|
||||
fun onNodeClick(database: Database, node: Node)
|
||||
fun onNodeSelected(database: Database, nodes: List<Node>): Boolean
|
||||
fun onNodeClick(database: ContextualDatabase, node: Node)
|
||||
fun onNodeSelected(database: ContextualDatabase, nodes: List<Node>): Boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu listener to redefine to do an action in menu
|
||||
*/
|
||||
interface NodesActionMenuListener {
|
||||
fun onOpenMenuClick(database: Database, node: Node): Boolean
|
||||
fun onEditMenuClick(database: Database, node: Node): Boolean
|
||||
fun onCopyMenuClick(database: Database, nodes: List<Node>): Boolean
|
||||
fun onMoveMenuClick(database: Database, nodes: List<Node>): Boolean
|
||||
fun onDeleteMenuClick(database: Database, nodes: List<Node>): Boolean
|
||||
fun onPasteMenuClick(database: Database, pasteMode: PasteMode?, nodes: List<Node>): Boolean
|
||||
fun onOpenMenuClick(database: ContextualDatabase, node: Node): Boolean
|
||||
fun onEditMenuClick(database: ContextualDatabase, node: Node): Boolean
|
||||
fun onCopyMenuClick(database: ContextualDatabase, nodes: List<Node>): Boolean
|
||||
fun onMoveMenuClick(database: ContextualDatabase, nodes: List<Node>): Boolean
|
||||
fun onDeleteMenuClick(database: ContextualDatabase, nodes: List<Node>): Boolean
|
||||
fun onPasteMenuClick(database: ContextualDatabase, pasteMode: PasteMode?, nodes: List<Node>): Boolean
|
||||
}
|
||||
|
||||
enum class PasteMode {
|
||||
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.activities.fragments
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class IconCustomFragment : IconFragment<IconImageCustom>() {
|
||||
return R.layout.fragment_icon_grid
|
||||
}
|
||||
|
||||
override fun defineIconList(database: Database?) {
|
||||
override fun defineIconList(database: ContextualDatabase?) {
|
||||
database?.doForEachCustomIcons { customIcon, _ ->
|
||||
iconPickerAdapter.addIcon(customIcon, false)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.adapters.IconPickerAdapter
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageDraw
|
||||
import com.kunzisoft.keepass.viewmodels.IconPickerViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -47,7 +47,7 @@ abstract class IconFragment<T: IconImageDraw> : DatabaseFragment(),
|
||||
|
||||
abstract fun retrieveMainLayoutId(): Int
|
||||
|
||||
abstract fun defineIconList(database: Database?)
|
||||
abstract fun defineIconList(database: ContextualDatabase?)
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -71,7 +71,7 @@ abstract class IconFragment<T: IconImageDraw> : DatabaseFragment(),
|
||||
resetAppTimeoutWhenViewFocusedOrChanged(view)
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
iconPickerAdapter.iconDrawableFactory = database?.iconDrawableFactory
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.adapters.IconPickerPagerAdapter
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.viewmodels.IconPickerViewModel
|
||||
|
||||
class IconPickerFragment : DatabaseFragment() {
|
||||
@@ -48,7 +48,7 @@ class IconPickerFragment : DatabaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
iconPickerPagerAdapter = IconPickerPagerAdapter(this,
|
||||
if (database?.allowCustomIcons == true) 2 else 1)
|
||||
viewPager.adapter = iconPickerPagerAdapter
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
package com.kunzisoft.keepass.activities.fragments
|
||||
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class IconStandardFragment : IconFragment<IconImageStandard>() {
|
||||
return R.layout.fragment_icon_grid
|
||||
}
|
||||
|
||||
override fun defineIconList(database: Database?) {
|
||||
override fun defineIconList(database: ContextualDatabase?) {
|
||||
database?.doForEachStandardIcons { standardIcon ->
|
||||
iconPickerAdapter.addIcon(standardIcon, false)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.adapters.KeyGeneratorPagerAdapter
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.viewmodels.KeyGeneratorViewModel
|
||||
|
||||
class KeyGeneratorFragment : DatabaseFragment() {
|
||||
@@ -107,7 +107,7 @@ class KeyGeneratorFragment : DatabaseFragment() {
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
// Nothing here
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import com.google.android.material.slider.Slider
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.password.PassphraseGenerator
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.ClipboardHelper
|
||||
@@ -244,7 +244,7 @@ class PassphraseGeneratorFragment : DatabaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
// Nothing here
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import com.google.android.material.slider.Slider
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.password.PasswordGenerator
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.ClipboardHelper
|
||||
@@ -318,7 +318,7 @@ class PasswordGeneratorFragment : DatabaseFragment() {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
// Nothing here
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.kunzisoft.keepass.activities.dialogs.FileManagerDialogFragment
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.takeUriPermission
|
||||
|
||||
class ExternalFileHelper {
|
||||
|
||||
@@ -57,10 +57,8 @@ class ExternalFileHelper {
|
||||
fun buildOpenDocument(onFileSelected: ((uri: Uri?) -> Unit)?) {
|
||||
|
||||
val resultCallback = ActivityResultCallback<Uri?> { result ->
|
||||
result?.let { uri ->
|
||||
UriUtil.takeUriPermission(activity?.contentResolver, uri)
|
||||
onFileSelected?.invoke(uri)
|
||||
}
|
||||
activity?.contentResolver?.takeUriPermission(result)
|
||||
onFileSelected?.invoke(result)
|
||||
}
|
||||
|
||||
getContentResultLauncher = if (fragment != null) {
|
||||
|
||||
@@ -4,18 +4,19 @@ import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.activity.viewModels
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.database.DatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
|
||||
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||
|
||||
abstract class DatabaseActivity: StylishActivity(), DatabaseRetrieval {
|
||||
|
||||
protected val mDatabaseViewModel: DatabaseViewModel by viewModels()
|
||||
protected var mDatabaseTaskProvider: DatabaseTaskProvider? = null
|
||||
protected var mDatabase: Database? = null
|
||||
protected var mDatabase: ContextualDatabase? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -47,14 +48,14 @@ abstract class DatabaseActivity: StylishActivity(), DatabaseRetrieval {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
mDatabase = database
|
||||
mDatabaseViewModel.defineDatabase(database)
|
||||
// optional method implementation
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
@@ -62,21 +63,25 @@ abstract class DatabaseActivity: StylishActivity(), DatabaseRetrieval {
|
||||
// optional method implementation
|
||||
}
|
||||
|
||||
fun createDatabase(databaseUri: Uri,
|
||||
mainCredential: MainCredential) {
|
||||
fun createDatabase(
|
||||
databaseUri: Uri,
|
||||
mainCredential: MainCredential
|
||||
) {
|
||||
mDatabaseTaskProvider?.startDatabaseCreate(databaseUri, mainCredential)
|
||||
}
|
||||
|
||||
fun loadDatabase(databaseUri: Uri,
|
||||
mainCredential: MainCredential,
|
||||
readOnly: Boolean,
|
||||
cipherEncryptDatabase: CipherEncryptDatabase?,
|
||||
fixDuplicateUuid: Boolean) {
|
||||
fun loadDatabase(
|
||||
databaseUri: Uri,
|
||||
mainCredential: MainCredential,
|
||||
readOnly: Boolean,
|
||||
cipherEncryptDatabase: CipherEncryptDatabase?,
|
||||
fixDuplicateUuid: Boolean
|
||||
) {
|
||||
mDatabaseTaskProvider?.startDatabaseLoad(databaseUri, mainCredential, readOnly, cipherEncryptDatabase, fixDuplicateUuid)
|
||||
}
|
||||
|
||||
protected fun closeDatabase() {
|
||||
mDatabase?.clearAndClose(this)
|
||||
mDatabase?.clearAndClose(this.getBinaryDir())
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
||||
@@ -36,14 +36,13 @@ import com.kunzisoft.keepass.activities.dialogs.DeleteNodesDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.SpecialMode
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||
import com.kunzisoft.keepass.model.GroupInfo
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
@@ -67,8 +66,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
||||
protected var mMergeDataAllowed: Boolean = false
|
||||
private var mAutoSaveEnable: Boolean = true
|
||||
|
||||
protected var mIconDrawableFactory: IconDrawableFactory? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -167,7 +164,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
// End activity if database not loaded
|
||||
@@ -207,7 +204,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
||||
|
||||
mDatabaseReadOnly = database.isReadOnly
|
||||
mMergeDataAllowed = database.isMergeDataAllowed()
|
||||
mIconDrawableFactory = database.iconDrawableFactory
|
||||
|
||||
checkRegister()
|
||||
}
|
||||
@@ -216,7 +212,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
||||
abstract fun viewToInvalidateTimeout(): View?
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
@@ -238,15 +234,19 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPasswordEncodingValidateListener(databaseUri: Uri?,
|
||||
mainCredential: MainCredential) {
|
||||
override fun onPasswordEncodingValidateListener(
|
||||
databaseUri: Uri?,
|
||||
mainCredential: MainCredential
|
||||
) {
|
||||
assignDatabasePassword(databaseUri, mainCredential)
|
||||
}
|
||||
|
||||
private fun assignDatabasePassword(databaseUri: Uri?,
|
||||
mainCredential: MainCredential) {
|
||||
private fun assignDatabasePassword(
|
||||
databaseUri: Uri?,
|
||||
mainCredential: MainCredential
|
||||
) {
|
||||
if (databaseUri != null) {
|
||||
mDatabaseTaskProvider?.startDatabaseAssignPassword(databaseUri, mainCredential)
|
||||
mDatabaseTaskProvider?.startDatabaseAssignCredential(databaseUri, mainCredential)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
||||
mDatabase?.let { database ->
|
||||
database.fileUri?.let { databaseUri ->
|
||||
// Show the progress dialog now or after dialog confirmation
|
||||
if (database.validatePasswordEncoding(mainCredential)) {
|
||||
if (database.isValidCredential(mainCredential.toMasterCredential(contentResolver))) {
|
||||
assignDatabasePassword(databaseUri, mainCredential)
|
||||
} else {
|
||||
PasswordEncodingDialogFragment.getInstance(databaseUri, mainCredential)
|
||||
@@ -306,7 +306,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
||||
mDatabaseTaskProvider?.startDatabaseMoveNodes(nodesToMove, newParent, mAutoSaveEnable)
|
||||
}
|
||||
|
||||
private fun eachNodeRecyclable(database: Database, nodes: List<Node>): Boolean {
|
||||
private fun eachNodeRecyclable(database: ContextualDatabase, nodes: List<Node>): Boolean {
|
||||
return nodes.find { node ->
|
||||
var cannotRecycle = true
|
||||
if (node is Entry) {
|
||||
@@ -322,7 +322,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
||||
mDatabase?.let { database ->
|
||||
// If recycle bin enabled, ensure it exists
|
||||
if (database.isRecycleBinEnabled) {
|
||||
database.ensureRecycleBinExists(resources)
|
||||
database.ensureRecycleBinExists(resources.getString(R.string.recycle_bin))
|
||||
}
|
||||
|
||||
// If recycle bin enabled and not in recycle bin, move in recycle bin
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.kunzisoft.keepass.activities.legacy
|
||||
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
|
||||
interface DatabaseRetrieval {
|
||||
fun onDatabaseRetrieved(database: Database?)
|
||||
fun onDatabaseActionFinished(database: Database,
|
||||
fun onDatabaseRetrieved(database: ContextualDatabase?)
|
||||
fun onDatabaseActionFinished(database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result)
|
||||
}
|
||||
@@ -112,7 +112,11 @@ class BreadcrumbAdapter(val context: Context)
|
||||
|
||||
holder.groupNumbersView?.apply {
|
||||
if (mShowNumberEntries) {
|
||||
group.refreshNumberOfChildEntries(Group.ChildFilter.getDefaults(context))
|
||||
group.refreshNumberOfChildEntries(
|
||||
Group.ChildFilter.getDefaults(
|
||||
PreferencesUtil.showExpiredEntries(context)
|
||||
)
|
||||
)
|
||||
text = group.numberOfChildEntries.toString()
|
||||
visibility = View.VISIBLE
|
||||
} else {
|
||||
|
||||
@@ -32,8 +32,9 @@ import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.ImageViewerActivity
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
||||
import com.kunzisoft.keepass.database.helper.getLocalizedName
|
||||
import com.kunzisoft.keepass.model.AttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||
import com.kunzisoft.keepass.model.StreamDirection
|
||||
@@ -45,7 +46,7 @@ import kotlin.math.max
|
||||
class EntryAttachmentsItemsAdapter(context: Context)
|
||||
: AnimatedItemsAdapter<EntryAttachmentState, EntryAttachmentsItemsAdapter.EntryBinariesViewHolder>(context) {
|
||||
|
||||
var database: Database? = null
|
||||
var database: ContextualDatabase? = null
|
||||
var onItemClickListener: ((item: EntryAttachmentState)->Unit)? = null
|
||||
var onBinaryPreviewLoaded: ((item: EntryAttachmentState) -> Unit)? = null
|
||||
|
||||
@@ -130,7 +131,7 @@ class EntryAttachmentsItemsAdapter(context: Context)
|
||||
holder.binaryFileSize.text = Formatter.formatFileSize(context, size)
|
||||
holder.binaryFileCompression.apply {
|
||||
if (entryAttachmentState.attachment.binaryData.isCompressed) {
|
||||
text = CompressionAlgorithm.GZip.getName(context.resources)
|
||||
text = CompressionAlgorithm.GZIP.getLocalizedName(context.resources)
|
||||
visibility = View.VISIBLE
|
||||
} else {
|
||||
text = ""
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.utils.TimeUtil.getDateTimeString
|
||||
|
||||
class EntryHistoryAdapter(val context: Context) : RecyclerView.Adapter<EntryHistoryAdapter.EntryHistoryViewHolder>() {
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import androidx.recyclerview.widget.SortedList
|
||||
import androidx.recyclerview.widget.SortedListAdapterCallback
|
||||
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.SortNodeEnum
|
||||
@@ -42,21 +42,23 @@ import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.NodeVersionedInterface
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.database.element.template.TemplateField
|
||||
import com.kunzisoft.keepass.database.helper.getLocalizedName
|
||||
import com.kunzisoft.keepass.otp.OtpElement
|
||||
import com.kunzisoft.keepass.otp.OtpType
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.ClipboardHelper
|
||||
import com.kunzisoft.keepass.view.setTextSize
|
||||
import com.kunzisoft.keepass.view.strikeOut
|
||||
import java.util.*
|
||||
import java.util.LinkedList
|
||||
|
||||
/**
|
||||
* Create node list adapter with contextMenu or not
|
||||
* @param context Context to use
|
||||
*/
|
||||
class NodesAdapter (private val context: Context,
|
||||
private val database: Database)
|
||||
: RecyclerView.Adapter<NodesAdapter.NodeViewHolder>() {
|
||||
class NodesAdapter (
|
||||
private val context: Context,
|
||||
private val database: ContextualDatabase
|
||||
) : RecyclerView.Adapter<NodesAdapter.NodeViewHolder>() {
|
||||
|
||||
private var mNodeComparator: Comparator<NodeVersionedInterface<Group>>? = null
|
||||
private val mNodeSortedListCallback: NodeSortedListCallback
|
||||
@@ -152,7 +154,9 @@ class NodesAdapter (private val context: Context,
|
||||
this.mShowOTP = PreferencesUtil.showOTPToken(context)
|
||||
this.mShowUUID = PreferencesUtil.showUUID(context)
|
||||
|
||||
this.mEntryFilters = Group.ChildFilter.getDefaults(context)
|
||||
this.mEntryFilters = Group.ChildFilter.getDefaults(
|
||||
PreferencesUtil.showExpiredEntries(context)
|
||||
)
|
||||
|
||||
// Reinit textSize for all view type
|
||||
mCalculateViewTypeTextSize.forEachIndexed { index, _ -> mCalculateViewTypeTextSize[index] = true }
|
||||
@@ -562,8 +566,8 @@ class NodesAdapter (private val context: Context,
|
||||
* Callback listener to redefine to do an action when a node is click
|
||||
*/
|
||||
interface NodeClickCallback {
|
||||
fun onNodeClick(database: Database, node: Node)
|
||||
fun onNodeLongClick(database: Database, node: Node): Boolean
|
||||
fun onNodeClick(database: ContextualDatabase, node: Node)
|
||||
fun onNodeLongClick(database: ContextualDatabase, node: Node): Boolean
|
||||
}
|
||||
|
||||
class NodeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import android.widget.TextView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.template.Template
|
||||
import com.kunzisoft.keepass.database.element.template.TemplateField
|
||||
import com.kunzisoft.keepass.database.helper.getLocalizedName
|
||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||
|
||||
|
||||
|
||||
@@ -19,24 +19,27 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.app.database
|
||||
|
||||
import android.content.*
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.IntentFilter
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.IBinder
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData.Companion.BASE64_FLAG
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.services.AdvancedUnlockNotificationService
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.IOActionTask
|
||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
||||
import java.util.*
|
||||
import java.util.LinkedList
|
||||
|
||||
class CipherDatabaseAction(context: Context) {
|
||||
|
||||
private val applicationContext = context.applicationContext
|
||||
private val cipherDatabaseDao =
|
||||
AppDatabase
|
||||
.getDatabase(applicationContext)
|
||||
.cipherDatabaseDao()
|
||||
AppDatabase.getDatabase(applicationContext).cipherDatabaseDao()
|
||||
|
||||
// Temp DAO to easily remove content if object no longer in memory
|
||||
private var useTempDao = PreferencesUtil.isTempAdvancedUnlockEnable(applicationContext)
|
||||
@@ -83,7 +86,7 @@ class CipherDatabaseAction(context: Context) {
|
||||
try {
|
||||
AdvancedUnlockNotificationService.bindService(applicationContext,
|
||||
mServiceConnection!!,
|
||||
Context.BIND_AUTO_CREATE)
|
||||
Context.BIND_AUTO_CREATE)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to start cipher action", e)
|
||||
performedAction.invoke()
|
||||
@@ -136,11 +139,11 @@ class CipherDatabaseAction(context: Context) {
|
||||
this.databaseUri = Uri.parse(cipherDatabaseEntity.databaseUri)
|
||||
this.encryptedValue = Base64.decode(
|
||||
cipherDatabaseEntity.encryptedValue,
|
||||
Base64.NO_WRAP
|
||||
BASE64_FLAG
|
||||
)
|
||||
this.specParameters = Base64.decode(
|
||||
cipherDatabaseEntity.specParameters,
|
||||
Base64.NO_WRAP
|
||||
BASE64_FLAG
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -148,8 +151,9 @@ class CipherDatabaseAction(context: Context) {
|
||||
}
|
||||
} else {
|
||||
IOActionTask(
|
||||
{
|
||||
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())?.let { cipherDatabaseEntity ->
|
||||
{
|
||||
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())
|
||||
?.let { cipherDatabaseEntity ->
|
||||
CipherEncryptDatabase().apply {
|
||||
this.databaseUri = Uri.parse(cipherDatabaseEntity.databaseUri)
|
||||
this.encryptedValue = Base64.decode(
|
||||
@@ -162,10 +166,10 @@ class CipherDatabaseAction(context: Context) {
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
cipherDatabaseResultListener.invoke(it)
|
||||
}
|
||||
},
|
||||
{
|
||||
cipherDatabaseResultListener.invoke(it)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
}
|
||||
@@ -183,8 +187,8 @@ class CipherDatabaseAction(context: Context) {
|
||||
|
||||
val cipherDatabaseEntity = CipherDatabaseEntity(
|
||||
databaseUri.toString(),
|
||||
Base64.encodeToString(cipherEncryptDatabase.encryptedValue, Base64.NO_WRAP),
|
||||
Base64.encodeToString(cipherEncryptDatabase.specParameters, Base64.NO_WRAP),
|
||||
Base64.encodeToString(cipherEncryptDatabase.encryptedValue, BASE64_FLAG),
|
||||
Base64.encodeToString(cipherEncryptDatabase.specParameters, BASE64_FLAG),
|
||||
)
|
||||
|
||||
if (useTempDao) {
|
||||
@@ -222,12 +226,12 @@ class CipherDatabaseAction(context: Context) {
|
||||
}
|
||||
} else {
|
||||
IOActionTask(
|
||||
{
|
||||
cipherDatabaseDao.deleteByDatabaseUri(databaseUri.toString())
|
||||
},
|
||||
{
|
||||
cipherDatabaseResultListener?.invoke()
|
||||
}
|
||||
{
|
||||
cipherDatabaseDao.deleteByDatabaseUri(databaseUri.toString())
|
||||
},
|
||||
{
|
||||
cipherDatabaseResultListener?.invoke()
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
}
|
||||
@@ -240,9 +244,9 @@ class CipherDatabaseAction(context: Context) {
|
||||
}
|
||||
// To erase the residues
|
||||
IOActionTask(
|
||||
{
|
||||
cipherDatabaseDao.deleteAll()
|
||||
}
|
||||
{
|
||||
cipherDatabaseDao.deleteAll()
|
||||
}
|
||||
).execute()
|
||||
// Unbind
|
||||
removeAllDataAndDetach()
|
||||
|
||||
@@ -25,88 +25,96 @@ import android.util.Log
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.model.DatabaseFile
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.IOActionTask
|
||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriHelper.decodeUri
|
||||
import com.kunzisoft.keepass.utils.UriHelper.parseUri
|
||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
||||
|
||||
class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
|
||||
private val databaseFileHistoryDao =
|
||||
AppDatabase
|
||||
.getDatabase(applicationContext)
|
||||
.fileDatabaseHistoryDao()
|
||||
AppDatabase.getDatabase(applicationContext).fileDatabaseHistoryDao()
|
||||
|
||||
fun getDatabaseFile(databaseUri: Uri,
|
||||
databaseFileResult: (DatabaseFile?) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
val fileDatabaseHistoryEntity = databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext, databaseUri)
|
||||
DatabaseFile(
|
||||
databaseUri,
|
||||
UriUtil.parse(fileDatabaseHistoryEntity?.keyFileUri),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity?.hardwareKey),
|
||||
UriUtil.decode(fileDatabaseHistoryEntity?.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias ?: ""),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
},
|
||||
{
|
||||
databaseFileResult.invoke(it)
|
||||
}
|
||||
{
|
||||
val fileDatabaseHistoryEntity =
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
val fileDatabaseInfo = FileDatabaseInfo(
|
||||
applicationContext,
|
||||
databaseUri)
|
||||
DatabaseFile(
|
||||
databaseUri,
|
||||
fileDatabaseHistoryEntity?.keyFileUri?.parseUri(),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity?.hardwareKey),
|
||||
fileDatabaseHistoryEntity?.databaseUri?.decodeUri(),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias
|
||||
?: ""),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
},
|
||||
{
|
||||
databaseFileResult.invoke(it)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun getKeyFileUriByDatabaseUri(databaseUri: Uri,
|
||||
keyFileUriResultListener: (Uri?) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
},
|
||||
{
|
||||
it?.let { fileHistoryEntity ->
|
||||
fileHistoryEntity.keyFileUri?.let { keyFileUri ->
|
||||
keyFileUriResultListener.invoke(UriUtil.parse(keyFileUri))
|
||||
}
|
||||
} ?: keyFileUriResultListener.invoke(null)
|
||||
}
|
||||
{
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
},
|
||||
{
|
||||
it?.let { fileHistoryEntity ->
|
||||
fileHistoryEntity.keyFileUri?.let { keyFileUri ->
|
||||
keyFileUriResultListener.invoke(keyFileUri.parseUri())
|
||||
}
|
||||
} ?: keyFileUriResultListener.invoke(null)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun getDatabaseFileList(databaseFileListResult: (List<DatabaseFile>) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
val hideBrokenLocations = PreferencesUtil.hideBrokenLocations(applicationContext)
|
||||
// Show only uri accessible
|
||||
val databaseFileListLoaded = ArrayList<DatabaseFile>()
|
||||
databaseFileHistoryDao.getAll().forEach { fileDatabaseHistoryEntity ->
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext, fileDatabaseHistoryEntity.databaseUri)
|
||||
if (hideBrokenLocations && fileDatabaseInfo.exists
|
||||
|| !hideBrokenLocations) {
|
||||
databaseFileListLoaded.add(
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistoryEntity.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistoryEntity.keyFileUri),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity.hardwareKey),
|
||||
UriUtil.decode(fileDatabaseHistoryEntity.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
{
|
||||
val hideBrokenLocations =
|
||||
PreferencesUtil.hideBrokenLocations(
|
||||
applicationContext)
|
||||
// Show only uri accessible
|
||||
val databaseFileListLoaded = ArrayList<DatabaseFile>()
|
||||
databaseFileHistoryDao.getAll().forEach { fileDatabaseHistoryEntity ->
|
||||
val fileDatabaseInfo = FileDatabaseInfo(
|
||||
applicationContext,
|
||||
fileDatabaseHistoryEntity.databaseUri)
|
||||
if (hideBrokenLocations && fileDatabaseInfo.exists
|
||||
|| !hideBrokenLocations
|
||||
) {
|
||||
databaseFileListLoaded.add(
|
||||
DatabaseFile(
|
||||
fileDatabaseHistoryEntity.databaseUri.parseUri(),
|
||||
fileDatabaseHistoryEntity.keyFileUri?.parseUri(),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity.hardwareKey),
|
||||
fileDatabaseHistoryEntity.databaseUri.decodeUri(),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
}
|
||||
}
|
||||
databaseFileListLoaded
|
||||
},
|
||||
{
|
||||
databaseFileList ->
|
||||
databaseFileList?.let {
|
||||
databaseFileListResult.invoke(it)
|
||||
)
|
||||
}
|
||||
}
|
||||
databaseFileListLoaded
|
||||
},
|
||||
{ databaseFileList ->
|
||||
databaseFileList?.let {
|
||||
databaseFileListResult.invoke(it)
|
||||
}
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
@@ -124,111 +132,115 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
fun addOrUpdateDatabaseFile(databaseFileToAddOrUpdate: DatabaseFile,
|
||||
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileToAddOrUpdate.databaseUri?.let { databaseUri ->
|
||||
// Try to get info in database first
|
||||
val fileDatabaseHistoryRetrieve = databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
{
|
||||
databaseFileToAddOrUpdate.databaseUri?.let { databaseUri ->
|
||||
// Try to get info in database first
|
||||
val fileDatabaseHistoryRetrieve =
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
|
||||
// Complete alias if not exists
|
||||
val fileDatabaseHistory = FileDatabaseHistoryEntity(
|
||||
databaseUri.toString(),
|
||||
databaseFileToAddOrUpdate.databaseAlias
|
||||
?: fileDatabaseHistoryRetrieve?.databaseAlias
|
||||
?: "",
|
||||
databaseFileToAddOrUpdate.keyFileUri?.toString(),
|
||||
databaseFileToAddOrUpdate.hardwareKey?.value,
|
||||
System.currentTimeMillis()
|
||||
// Complete alias if not exists
|
||||
val fileDatabaseHistory =
|
||||
FileDatabaseHistoryEntity(
|
||||
databaseUri.toString(),
|
||||
databaseFileToAddOrUpdate.databaseAlias
|
||||
?: fileDatabaseHistoryRetrieve?.databaseAlias
|
||||
?: "",
|
||||
databaseFileToAddOrUpdate.keyFileUri?.toString(),
|
||||
databaseFileToAddOrUpdate.hardwareKey?.value,
|
||||
System.currentTimeMillis()
|
||||
)
|
||||
|
||||
// Update values if history element not yet in the database
|
||||
try {
|
||||
if (fileDatabaseHistoryRetrieve == null) {
|
||||
databaseFileHistoryDao.add(fileDatabaseHistory)
|
||||
} else {
|
||||
databaseFileHistoryDao.update(fileDatabaseHistory)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to add or update database history", e)
|
||||
// Update values if history element not yet in the database
|
||||
try {
|
||||
if (fileDatabaseHistoryRetrieve == null) {
|
||||
databaseFileHistoryDao.add(fileDatabaseHistory)
|
||||
} else {
|
||||
databaseFileHistoryDao.update(fileDatabaseHistory)
|
||||
}
|
||||
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext,
|
||||
fileDatabaseHistory.databaseUri)
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to add or update database history", e)
|
||||
}
|
||||
},
|
||||
{
|
||||
databaseFileAddedOrUpdatedResult?.invoke(it)
|
||||
|
||||
val fileDatabaseInfo =
|
||||
FileDatabaseInfo(applicationContext,
|
||||
fileDatabaseHistory.databaseUri)
|
||||
DatabaseFile(
|
||||
fileDatabaseHistory.databaseUri.parseUri(),
|
||||
fileDatabaseHistory.keyFileUri?.parseUri(),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||
fileDatabaseHistory.databaseUri.decodeUri(),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
databaseFileAddedOrUpdatedResult?.invoke(it)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun deleteDatabaseFile(databaseFileToDelete: DatabaseFile,
|
||||
databaseFileDeletedResult: (DatabaseFile?) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileToDelete.databaseUri?.let { databaseUri ->
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())?.let { fileDatabaseHistory ->
|
||||
{
|
||||
databaseFileToDelete.databaseUri?.let { databaseUri ->
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
?.let { fileDatabaseHistory ->
|
||||
val returnValue = databaseFileHistoryDao.delete(fileDatabaseHistory)
|
||||
if (returnValue > 0) {
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
||||
fileDatabaseHistory.databaseUri.parseUri(),
|
||||
fileDatabaseHistory.keyFileUri?.parseUri(),
|
||||
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
|
||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
||||
fileDatabaseHistory.databaseUri.decodeUri(),
|
||||
databaseFileToDelete.databaseAlias
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
databaseFileDeletedResult.invoke(it)
|
||||
}
|
||||
},
|
||||
{
|
||||
databaseFileDeletedResult.invoke(it)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun deleteKeyFileByDatabaseUri(databaseUri: Uri,
|
||||
result: (() ->Unit)? = null) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileHistoryDao.deleteKeyFileByDatabaseUri(databaseUri.toString())
|
||||
},
|
||||
{
|
||||
result?.invoke()
|
||||
}
|
||||
{
|
||||
databaseFileHistoryDao.deleteKeyFileByDatabaseUri(databaseUri.toString())
|
||||
},
|
||||
{
|
||||
result?.invoke()
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun deleteAllKeyFiles(result: (() ->Unit)? = null) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileHistoryDao.deleteAllKeyFiles()
|
||||
},
|
||||
{
|
||||
result?.invoke()
|
||||
}
|
||||
{
|
||||
databaseFileHistoryDao.deleteAllKeyFiles()
|
||||
},
|
||||
{
|
||||
result?.invoke()
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun deleteAll(result: (() ->Unit)? = null) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileHistoryDao.deleteAll()
|
||||
},
|
||||
{
|
||||
result?.invoke()
|
||||
}
|
||||
{
|
||||
databaseFileHistoryDao.deleteAll()
|
||||
},
|
||||
{
|
||||
result?.invoke()
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.AutofillLauncherActivity
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.activities.helpers.SpecialMode
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.element.template.TemplateField
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
@@ -89,7 +89,7 @@ object AutofillHelper {
|
||||
}
|
||||
|
||||
private fun newRemoteViews(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
remoteViewsText: String,
|
||||
remoteViewsIcon: IconImage? = null): RemoteViews {
|
||||
val presentation = RemoteViews(context.packageName, R.layout.item_autofill_entry)
|
||||
@@ -108,7 +108,7 @@ object AutofillHelper {
|
||||
}
|
||||
|
||||
private fun buildDataset(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entryInfo: EntryInfo,
|
||||
struct: StructureParser.Result,
|
||||
additionalBuild: ((build: Dataset.Builder) -> Unit)? = null): Dataset? {
|
||||
@@ -214,7 +214,7 @@ object AutofillHelper {
|
||||
* Method to assign a drawable to a new icon from a database icon
|
||||
*/
|
||||
private fun buildIconFromEntry(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entryInfo: EntryInfo): Icon? {
|
||||
try {
|
||||
database.iconDrawableFactory.getBitmapFromIcon(context,
|
||||
@@ -230,7 +230,7 @@ object AutofillHelper {
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
@SuppressLint("RestrictedApi")
|
||||
private fun buildInlinePresentationForEntry(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
compatInlineSuggestionsRequest: CompatInlineSuggestionsRequest,
|
||||
positionItem: Int,
|
||||
entryInfo: EntryInfo): InlinePresentation? {
|
||||
@@ -302,7 +302,7 @@ object AutofillHelper {
|
||||
}
|
||||
|
||||
fun buildResponse(context: Context,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entriesInfo: List<EntryInfo>,
|
||||
parseResult: StructureParser.Result,
|
||||
compatInlineSuggestionsRequest: CompatInlineSuggestionsRequest?): FillResponse? {
|
||||
@@ -395,7 +395,7 @@ object AutofillHelper {
|
||||
* Build the Autofill response for one entry
|
||||
*/
|
||||
fun buildResponseAndSetResult(activity: Activity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entryInfo: EntryInfo) {
|
||||
buildResponseAndSetResult(activity, database, ArrayList<EntryInfo>().apply { add(entryInfo) })
|
||||
}
|
||||
@@ -404,7 +404,7 @@ object AutofillHelper {
|
||||
* Build the Autofill response for many entry
|
||||
*/
|
||||
fun buildResponseAndSetResult(activity: Activity,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
entriesInfo: List<EntryInfo>) {
|
||||
if (entriesInfo.isEmpty()) {
|
||||
activity.setResult(Activity.RESULT_CANCELED)
|
||||
|
||||
@@ -29,21 +29,21 @@ import android.os.CancellationSignal
|
||||
import android.service.autofill.*
|
||||
import android.util.Log
|
||||
import android.view.autofill.AutofillId
|
||||
import android.view.inputmethod.InlineSuggestionsRequest
|
||||
import android.widget.RemoteViews
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.autofill.inline.UiVersions
|
||||
import androidx.autofill.inline.v1.InlineSuggestionUi
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.AutofillLauncherActivity
|
||||
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.DatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.helper.SearchHelper
|
||||
import com.kunzisoft.keepass.model.CreditCard
|
||||
import com.kunzisoft.keepass.model.RegisterInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.settings.AutofillSettingsActivity
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.WebDomain
|
||||
import org.joda.time.DateTime
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
@@ -52,7 +52,7 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
class KeeAutofillService : AutofillService() {
|
||||
|
||||
private var mDatabaseTaskProvider: DatabaseTaskProvider? = null
|
||||
private var mDatabase: Database? = null
|
||||
private var mDatabase: ContextualDatabase? = null
|
||||
private var applicationIdBlocklist: Set<String>? = null
|
||||
private var webDomainBlocklist: Set<String>? = null
|
||||
private var askToSaveData: Boolean = false
|
||||
@@ -105,7 +105,7 @@ class KeeAutofillService : AutofillService() {
|
||||
webDomain = parseResult.webDomain
|
||||
webScheme = parseResult.webScheme
|
||||
}
|
||||
SearchInfo.getConcreteWebDomain(this, searchInfo.webDomain) { webDomainWithoutSubDomain ->
|
||||
WebDomain.getConcreteWebDomain(this, searchInfo.webDomain) { webDomainWithoutSubDomain ->
|
||||
searchInfo.webDomain = webDomainWithoutSubDomain
|
||||
val inlineSuggestionsRequest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
||||
&& autofillInlineSuggestionsEnabled) {
|
||||
@@ -124,7 +124,7 @@ class KeeAutofillService : AutofillService() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchSelection(database: Database?,
|
||||
private fun launchSelection(database: ContextualDatabase?,
|
||||
searchInfo: SearchInfo,
|
||||
parseResult: StructureParser.Result,
|
||||
inlineSuggestionsRequest: CompatInlineSuggestionsRequest?,
|
||||
@@ -153,7 +153,7 @@ class KeeAutofillService : AutofillService() {
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
private fun showUIForEntrySelection(parseResult: StructureParser.Result,
|
||||
database: Database?,
|
||||
database: ContextualDatabase?,
|
||||
searchInfo: SearchInfo,
|
||||
inlineSuggestionsRequest: CompatInlineSuggestionsRequest?,
|
||||
callback: FillCallback) {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.kunzisoft.keepass.database
|
||||
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
|
||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||
import com.kunzisoft.keepass.utils.SingletonHolder
|
||||
import java.io.File
|
||||
|
||||
class ContextualDatabase: Database() {
|
||||
|
||||
var fileUri: Uri? = null
|
||||
|
||||
val iconDrawableFactory = IconDrawableFactory(
|
||||
retrieveBinaryCache = { binaryCache },
|
||||
retrieveCustomIconBinary = { iconId -> getBinaryForCustomIcon(iconId) }
|
||||
)
|
||||
|
||||
override fun removeCustomIcon(customIcon: IconImageCustom) {
|
||||
iconDrawableFactory.clearFromCache(customIcon)
|
||||
super.removeCustomIcon(customIcon)
|
||||
}
|
||||
|
||||
override fun clearIndexesAndBinaries(filesDirectory: File?) {
|
||||
iconDrawableFactory.clearCache()
|
||||
super.clearIndexesAndBinaries(filesDirectory)
|
||||
}
|
||||
|
||||
override fun clearAndClose(filesDirectory: File?) {
|
||||
super.clearAndClose(filesDirectory)
|
||||
this.fileUri = null
|
||||
}
|
||||
|
||||
companion object : SingletonHolder<ContextualDatabase>(::ContextualDatabase) {
|
||||
private val TAG = ContextualDatabase::class.java.name
|
||||
}
|
||||
}
|
||||
@@ -17,16 +17,23 @@
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.action
|
||||
package com.kunzisoft.keepass.database
|
||||
|
||||
import android.content.*
|
||||
import android.content.Context.*
|
||||
import android.app.AlertDialog
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Context.BIND_ABOVE_CLIENT
|
||||
import android.content.Context.BIND_AUTO_CREATE
|
||||
import android.content.Context.BIND_IMPORTANT
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.kunzisoft.keepass.R
|
||||
@@ -34,20 +41,17 @@ import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment.Companion.DATABASE_CHANGED_DIALOG_TAG
|
||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.model.ProgressMessage
|
||||
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_CHALLENGE_RESPONDED
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_CREDENTIAL_TASK
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_ENTRY_TASK
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_GROUP_TASK
|
||||
@@ -84,22 +88,24 @@ import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.PROGRESS
|
||||
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
|
||||
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Utility class to connect an activity or a service to the DatabaseTaskNotificationService,
|
||||
* Useful to retrieve a database instance and sending tasks commands
|
||||
*/
|
||||
class DatabaseTaskProvider(private var context: Context,
|
||||
private var showDialog: Boolean = true) {
|
||||
class DatabaseTaskProvider(
|
||||
private var context: Context,
|
||||
private var showDialog: Boolean = true
|
||||
) {
|
||||
|
||||
// To show dialog only if context is an activity
|
||||
private var activity: FragmentActivity? = try { context as? FragmentActivity? }
|
||||
catch (_: Exception) { null }
|
||||
|
||||
var onDatabaseRetrieved: ((database: Database?) -> Unit)? = null
|
||||
var onDatabaseRetrieved: ((database: ContextualDatabase?) -> Unit)? = null
|
||||
|
||||
var onActionFinish: ((database: Database,
|
||||
var onActionFinish: ((database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result) -> Unit)? = null
|
||||
|
||||
@@ -128,26 +134,34 @@ class DatabaseTaskProvider(private var context: Context,
|
||||
}
|
||||
|
||||
private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener {
|
||||
override fun onActionStarted(database: Database,
|
||||
progressMessage: ProgressMessage) {
|
||||
override fun onActionStarted(
|
||||
database: ContextualDatabase,
|
||||
progressMessage: ProgressMessage
|
||||
) {
|
||||
if (showDialog)
|
||||
startDialog(progressMessage)
|
||||
}
|
||||
|
||||
override fun onActionUpdated(database: Database,
|
||||
progressMessage: ProgressMessage) {
|
||||
override fun onActionUpdated(
|
||||
database: ContextualDatabase,
|
||||
progressMessage: ProgressMessage
|
||||
) {
|
||||
if (showDialog)
|
||||
updateDialog(progressMessage)
|
||||
}
|
||||
|
||||
override fun onActionStopped(database: Database) {
|
||||
override fun onActionStopped(
|
||||
database: ContextualDatabase
|
||||
) {
|
||||
// Remove the progress task
|
||||
stopDialog()
|
||||
}
|
||||
|
||||
override fun onActionFinished(database: Database,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result) {
|
||||
override fun onActionFinished(
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
onActionFinish?.invoke(database, actionTask, result)
|
||||
onActionStopped(database)
|
||||
}
|
||||
@@ -159,7 +173,8 @@ class DatabaseTaskProvider(private var context: Context,
|
||||
}
|
||||
}
|
||||
|
||||
private var databaseInfoListener = object: DatabaseTaskNotificationService.DatabaseInfoListener {
|
||||
private var databaseInfoListener = object:
|
||||
DatabaseTaskNotificationService.DatabaseInfoListener {
|
||||
override fun onDatabaseInfoChanged(previousDatabaseInfo: SnapFileDatabaseInfo,
|
||||
newDatabaseInfo: SnapFileDatabaseInfo) {
|
||||
activity?.let { activity ->
|
||||
@@ -188,7 +203,7 @@ class DatabaseTaskProvider(private var context: Context,
|
||||
}
|
||||
|
||||
private var databaseListener = object: DatabaseTaskNotificationService.DatabaseListener {
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
onDatabaseRetrieved?.invoke(database)
|
||||
}
|
||||
}
|
||||
@@ -399,15 +414,15 @@ class DatabaseTaskProvider(private var context: Context,
|
||||
}
|
||||
}
|
||||
|
||||
fun startDatabaseAssignPassword(databaseUri: Uri,
|
||||
mainCredential: MainCredential
|
||||
fun startDatabaseAssignCredential(databaseUri: Uri,
|
||||
mainCredential: MainCredential
|
||||
) {
|
||||
|
||||
start(Bundle().apply {
|
||||
putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, databaseUri)
|
||||
putParcelable(DatabaseTaskNotificationService.MAIN_CREDENTIAL_KEY, mainCredential)
|
||||
}
|
||||
, ACTION_DATABASE_ASSIGN_PASSWORD_TASK)
|
||||
, ACTION_DATABASE_ASSIGN_CREDENTIAL_TASK)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2022 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.kunzisoft.keepass.database
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.kunzisoft.keepass.database.element.MasterCredential
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream
|
||||
import com.kunzisoft.keepass.utils.readEnum
|
||||
import com.kunzisoft.keepass.utils.writeEnum
|
||||
|
||||
data class MainCredential(var password: String? = null,
|
||||
var keyFileUri: Uri? = null,
|
||||
var hardwareKey: HardwareKey? = null): Parcelable {
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
password = parcel.readString()
|
||||
keyFileUri = parcel.readParcelable(Uri::class.java.classLoader)
|
||||
hardwareKey = parcel.readEnum<HardwareKey>()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(password)
|
||||
parcel.writeParcelable(keyFileUri, flags)
|
||||
parcel.writeEnum(hardwareKey)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as MainCredential
|
||||
|
||||
if (password != other.password) return false
|
||||
if (keyFileUri != other.keyFileUri) return false
|
||||
if (hardwareKey != other.hardwareKey) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = password?.hashCode() ?: 0
|
||||
result = 31 * result + (keyFileUri?.hashCode() ?: 0)
|
||||
result = 31 * result + (hardwareKey?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
fun toMasterCredential(contentResolver: ContentResolver): MasterCredential {
|
||||
return MasterCredential(
|
||||
this.password,
|
||||
this.keyFileUri?.let {
|
||||
getKeyFileData(contentResolver, it)
|
||||
},
|
||||
this.hardwareKey
|
||||
)
|
||||
}
|
||||
|
||||
private fun getKeyFileData(contentResolver: ContentResolver,
|
||||
keyFileUri: Uri): ByteArray? {
|
||||
contentResolver.getUriInputStream(keyFileUri)?.use { keyFileInputStream ->
|
||||
return keyFileInputStream.readBytes()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MainCredential> {
|
||||
override fun createFromParcel(parcel: Parcel): MainCredential {
|
||||
return MainCredential(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MainCredential?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
|
||||
private val TAG = MainCredential::class.java.simpleName
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.kunzisoft.keepass.model
|
||||
package com.kunzisoft.keepass.database
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
|
||||
open class AssignMainCredentialInDatabaseRunnable (
|
||||
context: Context,
|
||||
database: Database,
|
||||
protected val mDatabaseUri: Uri,
|
||||
mainCredential: MainCredential,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: SaveDatabaseRunnable(context, database, true, mainCredential, challengeResponseRetriever) {
|
||||
|
||||
private var mBackupKey: ByteArray? = null
|
||||
|
||||
override fun onStartRun() {
|
||||
// Set key
|
||||
try {
|
||||
mBackupKey = ByteArray(database.masterKey.size)
|
||||
database.masterKey.copyInto(mBackupKey!!)
|
||||
} catch (e: Exception) {
|
||||
erase(mBackupKey)
|
||||
setError(e)
|
||||
}
|
||||
|
||||
super.onStartRun()
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
super.onFinishRun()
|
||||
|
||||
// Erase the biometric
|
||||
CipherDatabaseAction.getInstance(context)
|
||||
.deleteByDatabaseUri(mDatabaseUri)
|
||||
// Erase the register keyfile
|
||||
FileDatabaseHistoryAction.getInstance(context)
|
||||
.deleteKeyFileByDatabaseUri(mDatabaseUri)
|
||||
|
||||
if (!result.isSuccess) {
|
||||
// Erase the current master key
|
||||
erase(database.masterKey)
|
||||
mBackupKey?.let {
|
||||
database.masterKey = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite the array as soon as we don't need it to avoid keeping the extra data in memory
|
||||
*/
|
||||
private fun erase(array: ByteArray?) {
|
||||
if (array == null) return
|
||||
for (i in array.indices) {
|
||||
array[i] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,65 +21,46 @@ package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
|
||||
class CreateDatabaseRunnable(context: Context,
|
||||
private val mDatabase: Database,
|
||||
databaseUri: Uri,
|
||||
private val databaseName: String,
|
||||
private val rootName: String,
|
||||
private val templateGroupName: String?,
|
||||
val mainCredential: MainCredential,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||
private val createDatabaseResult: ((Result) -> Unit)?)
|
||||
: AssignMainCredentialInDatabaseRunnable(context, mDatabase, databaseUri, mainCredential, challengeResponseRetriever) {
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
|
||||
|
||||
class CreateDatabaseRunnable(
|
||||
context: Context,
|
||||
private val mDatabase: ContextualDatabase,
|
||||
private val databaseUri: Uri,
|
||||
private val databaseName: String,
|
||||
private val rootName: String,
|
||||
private val templateGroupName: String?,
|
||||
val mainCredential: MainCredential,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : SaveDatabaseRunnable(
|
||||
context,
|
||||
mDatabase,
|
||||
true,
|
||||
mainCredential,
|
||||
challengeResponseRetriever
|
||||
) {
|
||||
override fun onStartRun() {
|
||||
try {
|
||||
// Create new database record
|
||||
mDatabase.apply {
|
||||
createData(mDatabaseUri, databaseName, rootName, templateGroupName)
|
||||
this.fileUri = databaseUri
|
||||
createData(databaseName, rootName, templateGroupName)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
mDatabase.clearAndClose(context)
|
||||
mDatabase.clearAndClose(context.getBinaryDir())
|
||||
setError(e)
|
||||
}
|
||||
|
||||
super.onStartRun()
|
||||
}
|
||||
|
||||
override fun onActionRun() {
|
||||
super.onActionRun()
|
||||
|
||||
if (result.isSuccess) {
|
||||
// Add database to recent files
|
||||
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
||||
FileDatabaseHistoryAction.getInstance(context.applicationContext)
|
||||
.addOrUpdateDatabaseUri(
|
||||
mDatabaseUri,
|
||||
if (PreferencesUtil.rememberKeyFileLocations(context)) mainCredential.keyFileUri else null,
|
||||
if (PreferencesUtil.rememberHardwareKey(context)) mainCredential.hardwareKey else null,
|
||||
)
|
||||
}
|
||||
|
||||
// Register the current time to init the lock timer
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
} else {
|
||||
Log.e("CreateDatabaseRunnable", "Unable to create the database")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
super.onFinishRun()
|
||||
|
||||
if (result.isSuccess) {
|
||||
mDatabase.loaded = true
|
||||
}
|
||||
createDatabaseResult?.invoke(result)
|
||||
super.onFinishRun()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,81 +21,65 @@ package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.database.exception.DatabaseInputException
|
||||
import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream
|
||||
|
||||
class LoadDatabaseRunnable(private val context: Context,
|
||||
private val mDatabase: Database,
|
||||
private val mDatabaseUri: Uri,
|
||||
private val mMainCredential: MainCredential,
|
||||
private val mChallengeResponseRetriever: (hardwareKey: HardwareKey, seed: ByteArray?) -> ByteArray,
|
||||
private val mReadonly: Boolean,
|
||||
private val mCipherEncryptDatabase: CipherEncryptDatabase?,
|
||||
private val mFixDuplicateUUID: Boolean,
|
||||
private val progressTaskUpdater: ProgressTaskUpdater?,
|
||||
private val mLoadDatabaseResult: ((Result) -> Unit)?)
|
||||
: ActionRunnable() {
|
||||
class LoadDatabaseRunnable(
|
||||
private val context: Context,
|
||||
private val mDatabase: ContextualDatabase,
|
||||
private val mDatabaseUri: Uri,
|
||||
private val mMainCredential: MainCredential,
|
||||
private val mChallengeResponseRetriever: (hardwareKey: HardwareKey, seed: ByteArray?) -> ByteArray,
|
||||
private val mReadonly: Boolean,
|
||||
private val mFixDuplicateUUID: Boolean,
|
||||
private val progressTaskUpdater: ProgressTaskUpdater?
|
||||
) : ActionRunnable() {
|
||||
|
||||
var afterLoadDatabase : ((Result) -> Unit)? = null
|
||||
|
||||
private val binaryDir = context.getBinaryDir()
|
||||
|
||||
override fun onStartRun() {
|
||||
// Clear before we load
|
||||
mDatabase.clearAndClose(context)
|
||||
mDatabase.clearAndClose(binaryDir)
|
||||
}
|
||||
|
||||
override fun onActionRun() {
|
||||
try {
|
||||
val contentResolver = context.contentResolver
|
||||
// Save database URI
|
||||
mDatabase.fileUri = mDatabaseUri
|
||||
mDatabase.loadData(
|
||||
context.contentResolver,
|
||||
mDatabaseUri,
|
||||
mMainCredential,
|
||||
contentResolver.getUriInputStream(mDatabaseUri)
|
||||
?: throw UnknownDatabaseLocationException(),
|
||||
mMainCredential.toMasterCredential(contentResolver),
|
||||
mChallengeResponseRetriever,
|
||||
mReadonly,
|
||||
UriUtil.getBinaryDir(context),
|
||||
binaryDir,
|
||||
{ memoryWanted ->
|
||||
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
||||
},
|
||||
mFixDuplicateUUID,
|
||||
progressTaskUpdater
|
||||
)
|
||||
}
|
||||
catch (e: DatabaseInputException) {
|
||||
} catch (e: DatabaseInputException) {
|
||||
setError(e)
|
||||
}
|
||||
|
||||
if (result.isSuccess) {
|
||||
// Save keyFile in app database
|
||||
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
||||
FileDatabaseHistoryAction.getInstance(context)
|
||||
.addOrUpdateDatabaseUri(
|
||||
mDatabaseUri,
|
||||
if (PreferencesUtil.rememberKeyFileLocations(context)) mMainCredential.keyFileUri else null,
|
||||
if (PreferencesUtil.rememberHardwareKey(context)) mMainCredential.hardwareKey else null,
|
||||
)
|
||||
}
|
||||
|
||||
// Register the biometric
|
||||
mCipherEncryptDatabase?.let { cipherDatabase ->
|
||||
CipherDatabaseAction.getInstance(context)
|
||||
.addOrUpdateCipherDatabase(cipherDatabase) // return value not called
|
||||
}
|
||||
|
||||
// Register the current time to init the lock timer
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
} else {
|
||||
mDatabase.clearAndClose(context)
|
||||
if (!result.isSuccess) {
|
||||
mDatabase.clearAndClose(binaryDir)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
mLoadDatabaseResult?.invoke(result)
|
||||
afterLoadDatabase?.invoke(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,31 @@ package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.database.exception.DatabaseException
|
||||
import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream
|
||||
|
||||
class MergeDatabaseRunnable(
|
||||
context: Context,
|
||||
private val mDatabaseToMergeUri: Uri?,
|
||||
private val mDatabaseToMergeMainCredential: MainCredential?,
|
||||
private val mDatabaseToMergeChallengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
saveDatabase: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||
private val progressTaskUpdater: ProgressTaskUpdater?,
|
||||
private val mLoadDatabaseResult: ((Result) -> Unit)?)
|
||||
: SaveDatabaseRunnable(context, database, saveDatabase, null, challengeResponseRetriever) {
|
||||
|
||||
) : SaveDatabaseRunnable(
|
||||
context,
|
||||
database,
|
||||
saveDatabase,
|
||||
null,
|
||||
challengeResponseRetriever
|
||||
) {
|
||||
override fun onStartRun() {
|
||||
database.wasReloaded = true
|
||||
super.onStartRun()
|
||||
@@ -48,10 +53,12 @@ class MergeDatabaseRunnable(
|
||||
|
||||
override fun onActionRun() {
|
||||
try {
|
||||
val contentResolver = context.contentResolver
|
||||
database.mergeData(
|
||||
context.contentResolver,
|
||||
mDatabaseToMergeUri,
|
||||
mDatabaseToMergeMainCredential,
|
||||
context.contentResolver.getUriInputStream(
|
||||
mDatabaseToMergeUri ?: database.fileUri
|
||||
) ?: throw UnknownDatabaseLocationException(),
|
||||
mDatabaseToMergeMainCredential?.toMasterCredential(contentResolver),
|
||||
mDatabaseToMergeChallengeResponseRetriever,
|
||||
{ memoryWanted ->
|
||||
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
||||
@@ -62,15 +69,6 @@ class MergeDatabaseRunnable(
|
||||
setError(e)
|
||||
}
|
||||
|
||||
if (result.isSuccess) {
|
||||
// Register the current time to init the lock timer
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
}
|
||||
super.onActionRun()
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
super.onFinishRun()
|
||||
mLoadDatabaseResult?.invoke(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,46 +20,50 @@
|
||||
package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.database.exception.DatabaseException
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getBinaryDir
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getUriInputStream
|
||||
|
||||
class ReloadDatabaseRunnable(private val context: Context,
|
||||
private val mDatabase: Database,
|
||||
private val progressTaskUpdater: ProgressTaskUpdater?,
|
||||
private val mLoadDatabaseResult: ((Result) -> Unit)?)
|
||||
: ActionRunnable() {
|
||||
class ReloadDatabaseRunnable(
|
||||
private val context: Context,
|
||||
private val mDatabase: ContextualDatabase,
|
||||
private val progressTaskUpdater: ProgressTaskUpdater?
|
||||
) : ActionRunnable() {
|
||||
|
||||
var afterReloadDatabase : ((Result) -> Unit)? = null
|
||||
|
||||
private val binaryDir = context.getBinaryDir()
|
||||
|
||||
override fun onStartRun() {
|
||||
// Clear before we load
|
||||
mDatabase.clearIndexesAndBinaries(UriUtil.getBinaryDir(context))
|
||||
mDatabase.clearIndexesAndBinaries(binaryDir)
|
||||
mDatabase.wasReloaded = true
|
||||
}
|
||||
|
||||
override fun onActionRun() {
|
||||
try {
|
||||
mDatabase.reloadData(context.contentResolver,
|
||||
{ memoryWanted ->
|
||||
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
||||
},
|
||||
progressTaskUpdater)
|
||||
mDatabase.reloadData(
|
||||
context.contentResolver.getUriInputStream(mDatabase.fileUri)
|
||||
?: throw UnknownDatabaseLocationException(),
|
||||
{ memoryWanted ->
|
||||
BinaryData.canMemoryBeAllocatedInRAM(context, memoryWanted)
|
||||
},
|
||||
progressTaskUpdater)
|
||||
} catch (e: DatabaseException) {
|
||||
setError(e)
|
||||
}
|
||||
|
||||
if (result.isSuccess) {
|
||||
// Register the current time to init the lock timer
|
||||
PreferencesUtil.saveCurrentTime(context)
|
||||
} else {
|
||||
mDatabase.clearAndClose(context)
|
||||
if (!result.isSuccess) {
|
||||
mDatabase.clearAndClose(binaryDir)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
mLoadDatabaseResult?.invoke(result)
|
||||
afterReloadDatabase?.invoke(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,21 @@
|
||||
package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class RemoveUnlinkedDataDatabaseRunnable (
|
||||
context: Context,
|
||||
database: Database,
|
||||
saveDatabase: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: SaveDatabaseRunnable(context, database, saveDatabase, null, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
saveDatabase: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : SaveDatabaseRunnable(
|
||||
context,
|
||||
database,
|
||||
saveDatabase,
|
||||
null,
|
||||
challengeResponseRetriever
|
||||
) {
|
||||
|
||||
override fun onActionRun() {
|
||||
try {
|
||||
|
||||
@@ -21,21 +21,24 @@ package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.database.exception.DatabaseException
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.utils.UriHelper.getUriOutputStream
|
||||
import java.io.File
|
||||
|
||||
open class SaveDatabaseRunnable(protected var context: Context,
|
||||
protected var database: Database,
|
||||
private var saveDatabase: Boolean,
|
||||
private var mainCredential: MainCredential?, // If null, uses composite Key
|
||||
private var challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||
private var databaseCopyUri: Uri? = null)
|
||||
: ActionRunnable() {
|
||||
open class SaveDatabaseRunnable(
|
||||
protected var context: Context,
|
||||
protected var database: ContextualDatabase,
|
||||
private var saveDatabase: Boolean,
|
||||
private var mainCredential: MainCredential?, // If null, uses composite Key
|
||||
private var challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray,
|
||||
private var databaseCopyUri: Uri? = null
|
||||
) : ActionRunnable() {
|
||||
|
||||
var mAfterSaveDatabase: ((Result) -> Unit)? = null
|
||||
var afterSaveDatabase: ((Result) -> Unit)? = null
|
||||
|
||||
override fun onStartRun() {}
|
||||
|
||||
@@ -43,11 +46,14 @@ open class SaveDatabaseRunnable(protected var context: Context,
|
||||
database.checkVersion()
|
||||
if (saveDatabase && result.isSuccess) {
|
||||
try {
|
||||
val contentResolver = context.contentResolver
|
||||
// Build temp database file to avoid file corruption if error
|
||||
database.saveData(
|
||||
context.contentResolver,
|
||||
context.cacheDir,
|
||||
databaseCopyUri,
|
||||
mainCredential,
|
||||
cacheFile = File(context.cacheDir, databaseCopyUri.hashCode().toString()),
|
||||
databaseOutputStream = contentResolver
|
||||
.getUriOutputStream(databaseCopyUri ?: database.fileUri),
|
||||
isNewLocation = databaseCopyUri == null,
|
||||
mainCredential?.toMasterCredential(contentResolver),
|
||||
challengeResponseRetriever)
|
||||
} catch (e: DatabaseException) {
|
||||
setError(e)
|
||||
@@ -57,6 +63,6 @@ open class SaveDatabaseRunnable(protected var context: Context,
|
||||
|
||||
override fun onFinishRun() {
|
||||
// Need to call super.onFinishRun() in child class
|
||||
mAfterSaveDatabase?.invoke(result)
|
||||
afterSaveDatabase?.invoke(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,18 +20,24 @@
|
||||
package com.kunzisoft.keepass.database.action
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class UpdateCompressionBinariesDatabaseRunnable (
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val oldCompressionAlgorithm: CompressionAlgorithm,
|
||||
private val newCompressionAlgorithm: CompressionAlgorithm,
|
||||
saveDatabase: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: SaveDatabaseRunnable(context, database, saveDatabase, null, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val oldCompressionAlgorithm: CompressionAlgorithm,
|
||||
private val newCompressionAlgorithm: CompressionAlgorithm,
|
||||
saveDatabase: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : SaveDatabaseRunnable(
|
||||
context,
|
||||
database,
|
||||
saveDatabase,
|
||||
null,
|
||||
challengeResponseRetriever
|
||||
) {
|
||||
|
||||
override fun onStartRun() {
|
||||
// Set new compression
|
||||
|
||||
@@ -20,19 +20,19 @@
|
||||
package com.kunzisoft.keepass.database.action.history
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.action.SaveDatabaseRunnable
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class DeleteEntryHistoryDatabaseRunnable (
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val mainEntry: Entry,
|
||||
private val entryHistoryPosition: Int,
|
||||
saveDatabase: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: SaveDatabaseRunnable(context, database, saveDatabase, null, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val mainEntry: Entry,
|
||||
private val entryHistoryPosition: Int,
|
||||
saveDatabase: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : SaveDatabaseRunnable(context, database, saveDatabase, null, challengeResponseRetriever) {
|
||||
|
||||
override fun onStartRun() {
|
||||
try {
|
||||
|
||||
@@ -20,20 +20,20 @@
|
||||
package com.kunzisoft.keepass.database.action.history
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.action.node.UpdateEntryRunnable
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
|
||||
class RestoreEntryHistoryDatabaseRunnable (
|
||||
private val context: Context,
|
||||
private val database: Database,
|
||||
private val mainEntry: Entry,
|
||||
private val entryHistoryPosition: Int,
|
||||
private val saveDatabase: Boolean,
|
||||
private val challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: ActionRunnable() {
|
||||
private val context: Context,
|
||||
private val database: ContextualDatabase,
|
||||
private val mainEntry: Entry,
|
||||
private val entryHistoryPosition: Int,
|
||||
private val saveDatabase: Boolean,
|
||||
private val challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : ActionRunnable() {
|
||||
|
||||
private var updateEntryRunnable: UpdateEntryRunnable? = null
|
||||
|
||||
|
||||
@@ -20,17 +20,17 @@
|
||||
package com.kunzisoft.keepass.database.action.node
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.action.SaveDatabaseRunnable
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
abstract class ActionNodeDatabaseRunnable(
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
save: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: SaveDatabaseRunnable(context, database, save, null, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
save: Boolean,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : SaveDatabaseRunnable(context, database, save, null, challengeResponseRetriever) {
|
||||
|
||||
/**
|
||||
* Function do to a node action
|
||||
|
||||
@@ -20,21 +20,21 @@
|
||||
package com.kunzisoft.keepass.database.action.node
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class AddEntryRunnable constructor(
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val mNewEntry: Entry,
|
||||
private val mParent: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val mNewEntry: Entry,
|
||||
private val mParent: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
|
||||
override fun nodeAction() {
|
||||
mNewEntry.touch(modified = true, touchParents = true)
|
||||
|
||||
@@ -20,20 +20,20 @@
|
||||
package com.kunzisoft.keepass.database.action.node
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class AddGroupRunnable constructor(
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val mNewGroup: Group,
|
||||
private val mParent: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val mNewGroup: Group,
|
||||
private val mParent: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
|
||||
override fun nodeAction() {
|
||||
mNewGroup.touch(modified = true, touchParents = true)
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.database.action.node
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
@@ -31,14 +31,14 @@ import com.kunzisoft.keepass.database.exception.CopyGroupDatabaseException
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class CopyNodesRunnable constructor(
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val mNodesToCopy: List<Node>,
|
||||
private val mNewParent: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val mNodesToCopy: List<Node>,
|
||||
private val mNewParent: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
|
||||
private var mEntriesCopied = ArrayList<Entry>()
|
||||
|
||||
|
||||
@@ -20,20 +20,22 @@
|
||||
package com.kunzisoft.keepass.database.action.node
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class DeleteNodesRunnable(context: Context,
|
||||
database: Database,
|
||||
private val mNodesToDelete: List<Node>,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
class DeleteNodesRunnable(
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val mNodesToDelete: List<Node>,
|
||||
private val recyclerBinTitle: String,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
|
||||
private var mOldParent: Group? = null
|
||||
private var mCanRecycle: Boolean = false
|
||||
@@ -54,7 +56,7 @@ class DeleteNodesRunnable(context: Context,
|
||||
// Remove Node from parent
|
||||
mCanRecycle = database.canRecycle(groupToDelete)
|
||||
if (mCanRecycle) {
|
||||
database.recycle(groupToDelete, context.resources)
|
||||
database.recycle(groupToDelete, recyclerBinTitle)
|
||||
groupToDelete.setPreviousParentGroup(mOldParent)
|
||||
groupToDelete.touch(modified = true, touchParents = true)
|
||||
} else {
|
||||
@@ -68,7 +70,7 @@ class DeleteNodesRunnable(context: Context,
|
||||
// Remove Node from parent
|
||||
mCanRecycle = database.canRecycle(entryToDelete)
|
||||
if (mCanRecycle) {
|
||||
database.recycle(entryToDelete, context.resources)
|
||||
database.recycle(entryToDelete, recyclerBinTitle)
|
||||
entryToDelete.setPreviousParentGroup(mOldParent)
|
||||
entryToDelete.touch(modified = true, touchParents = true)
|
||||
} else {
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.database.action.node
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
@@ -31,14 +31,14 @@ import com.kunzisoft.keepass.database.exception.MoveGroupDatabaseException
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class MoveNodesRunnable constructor(
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val mNodesToMove: List<Node>,
|
||||
private val mNewParent: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val mNodesToMove: List<Node>,
|
||||
private val mNewParent: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
|
||||
private var mOldParent: Group? = null
|
||||
|
||||
|
||||
@@ -20,21 +20,21 @@
|
||||
package com.kunzisoft.keepass.database.action.node
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Attachment
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.Entry
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class UpdateEntryRunnable constructor(
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val mOldEntry: Entry,
|
||||
private val mNewEntry: Entry,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val mOldEntry: Entry,
|
||||
private val mNewEntry: Entry,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
|
||||
override fun nodeAction() {
|
||||
if (mOldEntry.nodeId == mNewEntry.nodeId) {
|
||||
|
||||
@@ -20,20 +20,20 @@
|
||||
package com.kunzisoft.keepass.database.action.node
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
|
||||
class UpdateGroupRunnable constructor(
|
||||
context: Context,
|
||||
database: Database,
|
||||
private val mOldGroup: Group,
|
||||
private val mNewGroup: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray)
|
||||
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
context: Context,
|
||||
database: ContextualDatabase,
|
||||
private val mOldGroup: Group,
|
||||
private val mNewGroup: Group,
|
||||
save: Boolean,
|
||||
afterActionNodesFinish: AfterActionNodesFinish?,
|
||||
challengeResponseRetriever: (HardwareKey, ByteArray?) -> ByteArray
|
||||
) : ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save, challengeResponseRetriever) {
|
||||
|
||||
override fun nodeAction() {
|
||||
if (mOldGroup.nodeId == mNewGroup.nodeId) {
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.element.template
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.R
|
||||
|
||||
object TemplateField {
|
||||
|
||||
const val LABEL_STANDARD = "Standard"
|
||||
const val LABEL_TEMPLATE = "Template"
|
||||
const val LABEL_VERSION = "Version"
|
||||
|
||||
const val LABEL_TITLE = "Title"
|
||||
const val LABEL_USERNAME = "Username"
|
||||
const val LABEL_PASSWORD = "Password"
|
||||
const val LABEL_URL = "URL"
|
||||
const val LABEL_EXPIRATION = "Expires"
|
||||
const val LABEL_NOTES = "Notes"
|
||||
|
||||
const val LABEL_DEBIT_CREDIT_CARD = "Debit / Credit Card"
|
||||
const val LABEL_HOLDER = "Holder"
|
||||
const val LABEL_NUMBER = "Number"
|
||||
const val LABEL_CVV = "CVV"
|
||||
const val LABEL_PIN = "PIN"
|
||||
const val LABEL_ID_CARD = "ID Card"
|
||||
const val LABEL_NAME = "Name"
|
||||
const val LABEL_PLACE_OF_ISSUE = "Place of issue"
|
||||
const val LABEL_DATE_OF_ISSUE = "Date of issue"
|
||||
const val LABEL_EMAIL = "Email"
|
||||
const val LABEL_EMAIL_ADDRESS = "Email address"
|
||||
const val LABEL_WIRELESS = "Wi-Fi"
|
||||
const val LABEL_SSID = "SSID"
|
||||
const val LABEL_TYPE = "Type"
|
||||
const val LABEL_CRYPTOCURRENCY = "Cryptocurrency wallet"
|
||||
const val LABEL_TOKEN = "Token"
|
||||
const val LABEL_PUBLIC_KEY = "Public key"
|
||||
const val LABEL_PRIVATE_KEY = "Private key"
|
||||
const val LABEL_SEED = "Seed"
|
||||
const val LABEL_ACCOUNT = "Account"
|
||||
const val LABEL_BANK = "Bank"
|
||||
const val LABEL_BIC = "BIC"
|
||||
const val LABEL_IBAN = "IBAN"
|
||||
const val LABEL_SECURE_NOTE = "Secure Note"
|
||||
const val LABEL_MEMBERSHIP = "Membership"
|
||||
|
||||
fun isStandardPasswordName(context: Context, name: String): Boolean {
|
||||
return name.equals(LABEL_PASSWORD, true)
|
||||
|| name == getLocalizedName(context, LABEL_PASSWORD)
|
||||
}
|
||||
|
||||
fun isStandardFieldName(name: String): Boolean {
|
||||
return arrayOf(
|
||||
LABEL_TITLE,
|
||||
LABEL_USERNAME,
|
||||
LABEL_PASSWORD,
|
||||
LABEL_URL,
|
||||
LABEL_EXPIRATION,
|
||||
LABEL_NOTES
|
||||
).firstOrNull { it.equals(name, true) } != null
|
||||
}
|
||||
|
||||
fun getLocalizedName(context: Context?, name: String): String {
|
||||
if (context == null
|
||||
|| TemplateEngine.containsTemplateDecorator(name))
|
||||
return name
|
||||
|
||||
return when {
|
||||
LABEL_STANDARD.equals(name, true) -> context.getString(R.string.standard)
|
||||
LABEL_TEMPLATE.equals(name, true) -> context.getString(R.string.template)
|
||||
LABEL_VERSION.equals(name, true) -> context.getString(R.string.version)
|
||||
|
||||
LABEL_TITLE.equals(name, true) -> context.getString(R.string.entry_title)
|
||||
LABEL_USERNAME.equals(name, true) -> context.getString(R.string.entry_user_name)
|
||||
LABEL_PASSWORD.equals(name, true) -> context.getString(R.string.entry_password)
|
||||
LABEL_URL.equals(name, true) -> context.getString(R.string.entry_url)
|
||||
LABEL_EXPIRATION.equals(name, true) -> context.getString(R.string.entry_expires)
|
||||
LABEL_NOTES.equals(name, true) -> context.getString(R.string.entry_notes)
|
||||
|
||||
LABEL_DEBIT_CREDIT_CARD.equals(name, true) -> context.getString(R.string.debit_credit_card)
|
||||
LABEL_HOLDER.equals(name, true) -> context.getString(R.string.holder)
|
||||
LABEL_NUMBER.equals(name, true) -> context.getString(R.string.number)
|
||||
LABEL_CVV.equals(name, true) -> context.getString(R.string.card_verification_value)
|
||||
LABEL_PIN.equals(name, true) -> context.getString(R.string.personal_identification_number)
|
||||
LABEL_ID_CARD.equals(name, true) -> context.getString(R.string.id_card)
|
||||
LABEL_NAME.equals(name, true) -> context.getString(R.string.name)
|
||||
LABEL_PLACE_OF_ISSUE.equals(name, true) -> context.getString(R.string.place_of_issue)
|
||||
LABEL_DATE_OF_ISSUE.equals(name, true) -> context.getString(R.string.date_of_issue)
|
||||
LABEL_EMAIL.equals(name, true) -> context.getString(R.string.email)
|
||||
LABEL_EMAIL_ADDRESS.equals(name, true) -> context.getString(R.string.email_address)
|
||||
LABEL_WIRELESS.equals(name, true) -> context.getString(R.string.wireless)
|
||||
LABEL_SSID.equals(name, true) -> context.getString(R.string.ssid)
|
||||
LABEL_TYPE.equals(name, true) -> context.getString(R.string.type)
|
||||
LABEL_CRYPTOCURRENCY.equals(name, true) -> context.getString(R.string.cryptocurrency)
|
||||
LABEL_TOKEN.equals(name, false) -> context.getString(R.string.token)
|
||||
LABEL_PUBLIC_KEY.equals(name, true) -> context.getString(R.string.public_key)
|
||||
LABEL_PRIVATE_KEY.equals(name, true) -> context.getString(R.string.private_key)
|
||||
LABEL_SEED.equals(name, true) -> context.getString(R.string.seed)
|
||||
LABEL_ACCOUNT.equals(name, true) -> context.getString(R.string.account)
|
||||
LABEL_BANK.equals(name, true) -> context.getString(R.string.bank)
|
||||
LABEL_BIC.equals(name, true) -> context.getString(R.string.bank_identifier_code)
|
||||
LABEL_IBAN.equals(name, true) -> context.getString(R.string.international_bank_account_number)
|
||||
LABEL_SECURE_NOTE.equals(name, true) -> context.getString(R.string.secure_note)
|
||||
LABEL_MEMBERSHIP.equals(name, true) -> context.getString(R.string.membership)
|
||||
|
||||
else -> name
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2021 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.helper
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
||||
import com.kunzisoft.keepass.database.element.template.TemplateEngine
|
||||
import com.kunzisoft.keepass.database.element.template.TemplateField
|
||||
import com.kunzisoft.keepass.database.exception.*
|
||||
|
||||
fun DatabaseException.getLocalizedMessage(resources: Resources): String = parameters?.let {
|
||||
when (this) {
|
||||
is FileNotFoundDatabaseException -> resources.getString(R.string.file_not_found_content)
|
||||
is CorruptedDatabaseException -> resources.getString(R.string.corrupted_file)
|
||||
is InvalidAlgorithmDatabaseException -> resources.getString(R.string.invalid_algorithm)
|
||||
is UnknownDatabaseLocationException -> resources.getString(R.string.error_location_unknown)
|
||||
is HardwareKeyDatabaseException -> resources.getString(R.string.error_hardware_key_unsupported)
|
||||
is EmptyKeyDatabaseException -> resources.getString(R.string.error_empty_key)
|
||||
is SignatureDatabaseException -> resources.getString(R.string.invalid_db_sig)
|
||||
is VersionDatabaseException -> resources.getString(R.string.unsupported_db_version)
|
||||
is InvalidCredentialsDatabaseException -> resources.getString(R.string.invalid_credentials)
|
||||
is KDFMemoryDatabaseException -> resources.getString(R.string.error_load_database_KDF_memory)
|
||||
is NoMemoryDatabaseException -> resources.getString(R.string.error_out_of_memory)
|
||||
is DuplicateUuidDatabaseException -> resources.getString(R.string.invalid_db_same_uuid)
|
||||
is XMLMalformedDatabaseException -> resources.getString(R.string.error_XML_malformed)
|
||||
is MergeDatabaseKDBException -> resources.getString(R.string.error_unable_merge_database_kdb)
|
||||
is MoveEntryDatabaseException -> resources.getString(R.string.error_move_entry_here)
|
||||
is MoveGroupDatabaseException -> resources.getString(R.string.error_move_group_here)
|
||||
is CopyEntryDatabaseException -> resources.getString(R.string.error_copy_entry_here)
|
||||
is CopyGroupDatabaseException -> resources.getString(R.string.error_copy_group_here)
|
||||
is DatabaseInputException -> resources.getString(R.string.error_load_database)
|
||||
is DatabaseOutputException -> resources.getString(R.string.error_save_database)
|
||||
else -> (mThrowable as? DatabaseException)?.getLocalizedMessage(resources)
|
||||
}
|
||||
} ?: resources.getString(R.string.error_load_database)
|
||||
|
||||
fun CompressionAlgorithm.getLocalizedName(resources: Resources): String {
|
||||
return when (this) {
|
||||
CompressionAlgorithm.NONE -> resources.getString(R.string.compression_none)
|
||||
CompressionAlgorithm.GZIP -> resources.getString(R.string.compression_gzip)
|
||||
}
|
||||
}
|
||||
|
||||
fun TemplateField.isStandardPasswordName(context: Context, name: String): Boolean {
|
||||
return name.equals(LABEL_PASSWORD, true)
|
||||
|| name == getLocalizedName(context, LABEL_PASSWORD)
|
||||
}
|
||||
|
||||
fun TemplateField.getLocalizedName(context: Context?, name: String): String {
|
||||
if (context == null
|
||||
|| TemplateEngine.containsTemplateDecorator(name)
|
||||
)
|
||||
return name
|
||||
|
||||
return when {
|
||||
LABEL_STANDARD.equals(name, true) -> context.getString(R.string.standard)
|
||||
LABEL_TEMPLATE.equals(name, true) -> context.getString(R.string.template)
|
||||
LABEL_VERSION.equals(name, true) -> context.getString(R.string.version)
|
||||
|
||||
LABEL_TITLE.equals(name, true) -> context.getString(R.string.entry_title)
|
||||
LABEL_USERNAME.equals(name, true) -> context.getString(R.string.entry_user_name)
|
||||
LABEL_PASSWORD.equals(name, true) -> context.getString(R.string.entry_password)
|
||||
LABEL_URL.equals(name, true) -> context.getString(R.string.entry_url)
|
||||
LABEL_EXPIRATION.equals(name, true) -> context.getString(R.string.entry_expires)
|
||||
LABEL_NOTES.equals(name, true) -> context.getString(R.string.entry_notes)
|
||||
|
||||
LABEL_DEBIT_CREDIT_CARD.equals(name, true) -> context.getString(R.string.debit_credit_card)
|
||||
LABEL_HOLDER.equals(name, true) -> context.getString(R.string.holder)
|
||||
LABEL_NUMBER.equals(name, true) -> context.getString(R.string.number)
|
||||
LABEL_CVV.equals(name, true) -> context.getString(R.string.card_verification_value)
|
||||
LABEL_PIN.equals(name, true) -> context.getString(R.string.personal_identification_number)
|
||||
LABEL_ID_CARD.equals(name, true) -> context.getString(R.string.id_card)
|
||||
LABEL_NAME.equals(name, true) -> context.getString(R.string.name)
|
||||
LABEL_PLACE_OF_ISSUE.equals(name, true) -> context.getString(R.string.place_of_issue)
|
||||
LABEL_DATE_OF_ISSUE.equals(name, true) -> context.getString(R.string.date_of_issue)
|
||||
LABEL_EMAIL.equals(name, true) -> context.getString(R.string.email)
|
||||
LABEL_EMAIL_ADDRESS.equals(name, true) -> context.getString(R.string.email_address)
|
||||
LABEL_WIRELESS.equals(name, true) -> context.getString(R.string.wireless)
|
||||
LABEL_SSID.equals(name, true) -> context.getString(R.string.ssid)
|
||||
LABEL_TYPE.equals(name, true) -> context.getString(R.string.type)
|
||||
LABEL_CRYPTOCURRENCY.equals(name, true) -> context.getString(R.string.cryptocurrency)
|
||||
LABEL_TOKEN.equals(name, false) -> context.getString(R.string.token)
|
||||
LABEL_PUBLIC_KEY.equals(name, true) -> context.getString(R.string.public_key)
|
||||
LABEL_PRIVATE_KEY.equals(name, true) -> context.getString(R.string.private_key)
|
||||
LABEL_SEED.equals(name, true) -> context.getString(R.string.seed)
|
||||
LABEL_ACCOUNT.equals(name, true) -> context.getString(R.string.account)
|
||||
LABEL_BANK.equals(name, true) -> context.getString(R.string.bank)
|
||||
LABEL_BIC.equals(name, true) -> context.getString(R.string.bank_identifier_code)
|
||||
LABEL_IBAN.equals(name, true) -> context.getString(R.string.international_bank_account_number)
|
||||
LABEL_SECURE_NOTE.equals(name, true) -> context.getString(R.string.secure_note)
|
||||
LABEL_MEMBERSHIP.equals(name, true) -> context.getString(R.string.membership)
|
||||
|
||||
else -> name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.helper
|
||||
|
||||
import android.content.Context
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
|
||||
object SearchHelper {
|
||||
|
||||
const val MAX_SEARCH_ENTRY = 1000
|
||||
|
||||
/**
|
||||
* Method to show the number of search results with max results
|
||||
*/
|
||||
fun showNumberOfSearchResults(number: Int): String {
|
||||
return if (number >= MAX_SEARCH_ENTRY) {
|
||||
(MAX_SEARCH_ENTRY -1).toString() + "+"
|
||||
} else {
|
||||
number.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to perform actions if item is found or not after an auto search in [database]
|
||||
*/
|
||||
fun checkAutoSearchInfo(context: Context,
|
||||
database: ContextualDatabase?,
|
||||
searchInfo: SearchInfo?,
|
||||
onItemsFound: (openedDatabase: ContextualDatabase,
|
||||
items: List<EntryInfo>) -> Unit,
|
||||
onItemNotFound: (openedDatabase: ContextualDatabase) -> Unit,
|
||||
onDatabaseClosed: () -> Unit) {
|
||||
if (database == null || !database.loaded) {
|
||||
onDatabaseClosed.invoke()
|
||||
} else if (TimeoutHelper.checkTime(context)) {
|
||||
var searchWithoutUI = false
|
||||
if (searchInfo != null
|
||||
&& !searchInfo.manualSelection
|
||||
&& !searchInfo.containsOnlyNullValues()) {
|
||||
// If search provide results
|
||||
database.createVirtualGroupFromSearchInfo(
|
||||
searchInfo.toString(),
|
||||
MAX_SEARCH_ENTRY
|
||||
)?.let { searchGroup ->
|
||||
if (searchGroup.numberOfChildEntries > 0) {
|
||||
searchWithoutUI = true
|
||||
onItemsFound.invoke(database,
|
||||
searchGroup.getChildEntriesInfo(database))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!searchWithoutUI) {
|
||||
onItemNotFound.invoke(database)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,10 @@ import androidx.activity.result.ActivityResultCallback
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseModeActivity
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openExternalApp
|
||||
|
||||
/**
|
||||
* Special activity to deal with hardware key drivers,
|
||||
@@ -49,7 +48,7 @@ class HardwareKeyActivity: DatabaseModeActivity(){
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
val hardwareKey = HardwareKey.getHardwareKeyFromString(
|
||||
@@ -158,8 +157,7 @@ class HardwareKeyActivity: DatabaseModeActivity(){
|
||||
context.getString(R.string.error_driver_required, hardwareKey.toString())
|
||||
)
|
||||
.setPositiveButton(R.string.download) { _, _ ->
|
||||
UriUtil.openExternalApp(
|
||||
context,
|
||||
context.openExternalApp(
|
||||
context.getString(R.string.key_driver_app_id),
|
||||
context.getString(R.string.key_driver_url)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.kunzisoft.keepass.hardware
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.ActivityResultCallback
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openExternalApp
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class HardwareKeyResponseHelper {
|
||||
|
||||
private var activity: FragmentActivity? = null
|
||||
private var fragment: Fragment? = null
|
||||
|
||||
private var getChallengeResponseResultLauncher: ActivityResultLauncher<Intent>? = null
|
||||
|
||||
constructor(context: FragmentActivity) {
|
||||
this.activity = context
|
||||
this.fragment = null
|
||||
}
|
||||
|
||||
constructor(context: Fragment) {
|
||||
this.activity = context.activity
|
||||
this.fragment = context
|
||||
}
|
||||
|
||||
fun buildHardwareKeyResponse(onChallengeResponded: (challengeResponse: ByteArray?,
|
||||
extra: Bundle?) -> Unit) {
|
||||
val resultCallback = ActivityResultCallback<ActivityResult> { result ->
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
val challengeResponse: ByteArray? = result.data?.getByteArrayExtra(HARDWARE_KEY_RESPONSE_KEY)
|
||||
Log.d(TAG, "Response form challenge")
|
||||
onChallengeResponded.invoke(challengeResponse,
|
||||
result.data?.getBundleExtra(EXTRA_BUNDLE_KEY))
|
||||
} else {
|
||||
Log.e(TAG, "Response from challenge error")
|
||||
onChallengeResponded.invoke(null,
|
||||
result.data?.getBundleExtra(EXTRA_BUNDLE_KEY))
|
||||
}
|
||||
}
|
||||
|
||||
getChallengeResponseResultLauncher = if (fragment != null) {
|
||||
fragment?.registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult(),
|
||||
resultCallback
|
||||
)
|
||||
} else {
|
||||
activity?.registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult(),
|
||||
resultCallback
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun launchChallengeForResponse(hardwareKey: HardwareKey, seed: ByteArray?) {
|
||||
when (hardwareKey) {
|
||||
/*
|
||||
HardwareKey.FIDO2_SECRET -> {
|
||||
// TODO FIDO2 under development
|
||||
throw Exception("FIDO2 not implemented")
|
||||
}
|
||||
*/
|
||||
HardwareKey.CHALLENGE_RESPONSE_YUBIKEY -> {
|
||||
// Transform the seed before sending
|
||||
var challenge: ByteArray? = null
|
||||
if (seed != null) {
|
||||
challenge = ByteArray(64)
|
||||
seed.copyInto(challenge, 0, 0, 32)
|
||||
challenge.fill(32, 32, 64)
|
||||
}
|
||||
// Send to the driver
|
||||
getChallengeResponseResultLauncher!!.launch(
|
||||
Intent(YUBIKEY_CHALLENGE_RESPONSE_INTENT).apply {
|
||||
putExtra(HARDWARE_KEY_CHALLENGE_KEY, challenge)
|
||||
}
|
||||
)
|
||||
Log.d(TAG, "Challenge sent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = HardwareKeyResponseHelper::class.java.simpleName
|
||||
|
||||
private const val YUBIKEY_CHALLENGE_RESPONSE_INTENT = "android.yubikey.intent.action.CHALLENGE_RESPONSE"
|
||||
private const val HARDWARE_KEY_CHALLENGE_KEY = "challenge"
|
||||
private const val HARDWARE_KEY_RESPONSE_KEY = "response"
|
||||
private const val EXTRA_BUNDLE_KEY = "EXTRA_BUNDLE_KEY"
|
||||
|
||||
fun isHardwareKeyAvailable(
|
||||
activity: FragmentActivity,
|
||||
hardwareKey: HardwareKey,
|
||||
showDialog: Boolean = true
|
||||
): Boolean {
|
||||
return when (hardwareKey) {
|
||||
/*
|
||||
HardwareKey.FIDO2_SECRET -> {
|
||||
// TODO FIDO2 under development
|
||||
if (showDialog)
|
||||
UnderDevelopmentFeatureDialogFragment()
|
||||
.show(activity.supportFragmentManager, "underDevFeatureDialog")
|
||||
false
|
||||
}
|
||||
*/
|
||||
HardwareKey.CHALLENGE_RESPONSE_YUBIKEY -> {
|
||||
// Check available intent
|
||||
val yubikeyDriverAvailable =
|
||||
Intent(YUBIKEY_CHALLENGE_RESPONSE_INTENT)
|
||||
.resolveActivity(activity.packageManager) != null
|
||||
if (showDialog && !yubikeyDriverAvailable)
|
||||
showHardwareKeyDriverNeeded(activity, hardwareKey)
|
||||
yubikeyDriverAvailable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showHardwareKeyDriverNeeded(
|
||||
activity: FragmentActivity,
|
||||
hardwareKey: HardwareKey
|
||||
) {
|
||||
activity.lifecycleScope.launch {
|
||||
val builder = AlertDialog.Builder(activity)
|
||||
builder
|
||||
.setMessage(
|
||||
activity.getString(R.string.error_driver_required, hardwareKey.toString())
|
||||
)
|
||||
.setPositiveButton(R.string.download) { _, _ ->
|
||||
activity.openExternalApp(activity.getString(R.string.key_driver_app_id))
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
builder.create().show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,25 +32,25 @@ import android.widget.RemoteViews
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.core.widget.ImageViewCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryCache
|
||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageDraw
|
||||
import com.kunzisoft.keepass.icon.IconPack
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
/**
|
||||
* Factory class who build database icons dynamically, can assign an icon of IconPack, or a custom icon to an ImageView with a tint
|
||||
*/
|
||||
class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
private val retrieveCustomIconBinary : (iconId: UUID) -> BinaryData?) {
|
||||
class IconDrawableFactory(
|
||||
private val retrieveBinaryCache: () -> BinaryCache?,
|
||||
private val retrieveCustomIconBinary: (iconId: UUID) -> BinaryData?,
|
||||
) {
|
||||
|
||||
/** customIconMap
|
||||
* Cache for icon drawable.
|
||||
@@ -72,10 +72,12 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
/**
|
||||
* Get the [SuperDrawable] [iconDraw] (from cache, or build it and add it to the cache if not exists yet), then tint it with [tintColor] if needed
|
||||
*/
|
||||
private fun getIconSuperDrawable(context: Context,
|
||||
iconDraw: IconImageDraw,
|
||||
width: Int,
|
||||
tintColor: Int = Color.WHITE): SuperDrawable {
|
||||
private fun getIconSuperDrawable(
|
||||
context: Context,
|
||||
iconDraw: IconImageDraw,
|
||||
width: Int,
|
||||
tintColor: Int = Color.WHITE,
|
||||
): SuperDrawable {
|
||||
val icon = iconDraw.getIconImageToDraw()
|
||||
val customIconBinary = retrieveCustomIconBinary(icon.custom.uuid)
|
||||
val binaryCache = retrieveBinaryCache()
|
||||
@@ -90,24 +92,29 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
this.clearCache()
|
||||
}
|
||||
iconPack?.iconToResId(icon.standard.id)?.let { iconId ->
|
||||
return SuperDrawable(getIconDrawable(context.resources, iconId, width, tintColor), iconPack.tintable())
|
||||
return SuperDrawable(getIconDrawable(context.resources, iconId, width, tintColor),
|
||||
iconPack.tintable())
|
||||
} ?: run {
|
||||
return SuperDrawable(PatternIcon(context.resources).blankDrawable)
|
||||
return SuperDrawable(PatternIcon(IconPackChooser.defaultIconSize).blankDrawable)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a custom [Drawable] from custom [icon]
|
||||
*/
|
||||
private fun getIconDrawable(resources: Resources, icon: IconImageCustom, iconCustomBinary: BinaryData?): Drawable? {
|
||||
val patternIcon = PatternIcon(resources)
|
||||
val binaryManager = retrieveBinaryCache()
|
||||
if (binaryManager != null) {
|
||||
private fun getIconDrawable(
|
||||
resources: Resources,
|
||||
icon: IconImageCustom,
|
||||
iconCustomBinary: BinaryData?,
|
||||
): Drawable? {
|
||||
val patternIcon = PatternIcon(IconPackChooser.defaultIconSize)
|
||||
retrieveBinaryCache()?.let { binaryCache ->
|
||||
val draw: Drawable? = customIconMap[icon.uuid]?.get()
|
||||
if (draw == null) {
|
||||
iconCustomBinary?.let { binaryFile ->
|
||||
try {
|
||||
var bitmap: Bitmap? = BitmapFactory.decodeStream(binaryFile.getInputDataStream(binaryManager))
|
||||
var bitmap: Bitmap? =
|
||||
BitmapFactory.decodeStream(binaryFile.getInputDataStream(binaryCache))
|
||||
bitmap?.let { bitmapIcon ->
|
||||
bitmap = resize(bitmapIcon, patternIcon)
|
||||
val createdDraw = BitmapDrawable(resources, bitmap)
|
||||
@@ -130,7 +137,12 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
* Get the standard [Drawable] icon from [iconId] (cache or build it and add it to the cache if not exists yet)
|
||||
* , then tint it with [tintColor] if needed
|
||||
*/
|
||||
private fun getIconDrawable(resources: Resources, iconId: Int, width: Int, tintColor: Int): Drawable {
|
||||
private fun getIconDrawable(
|
||||
resources: Resources,
|
||||
iconId: Int,
|
||||
width: Int,
|
||||
tintColor: Int,
|
||||
): Drawable {
|
||||
val newCacheKey = CacheKey(iconId, width, true, tintColor)
|
||||
|
||||
var draw: Drawable? = standardIconMap[newCacheKey]?.get()
|
||||
@@ -147,7 +159,7 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
}
|
||||
|
||||
if (draw == null) {
|
||||
draw = PatternIcon(resources).blankDrawable
|
||||
draw = PatternIcon(IconPackChooser.defaultIconSize).blankDrawable
|
||||
}
|
||||
draw.isFilterBitmap = false
|
||||
|
||||
@@ -166,28 +178,34 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
|
||||
return if (width == dimensionPattern.width && height == dimensionPattern.height) {
|
||||
bitmap
|
||||
} else Bitmap.createScaledBitmap(bitmap, dimensionPattern.width, dimensionPattern.height, true)
|
||||
} else Bitmap.createScaledBitmap(bitmap,
|
||||
dimensionPattern.width,
|
||||
dimensionPattern.height,
|
||||
true)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a database [icon] to an ImageView and tint it with [tintColor] if needed
|
||||
*/
|
||||
fun assignDatabaseIcon(imageView: ImageView,
|
||||
icon: IconImageDraw,
|
||||
tintColor: Int = Color.WHITE) {
|
||||
fun assignDatabaseIcon(
|
||||
imageView: ImageView,
|
||||
icon: IconImageDraw,
|
||||
tintColor: Int = Color.WHITE,
|
||||
) {
|
||||
try {
|
||||
val context = imageView.context
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
addToCustomCache(context.resources, icon)
|
||||
withContext(Dispatchers.Main) {
|
||||
val superDrawable = getIconSuperDrawable(context,
|
||||
icon,
|
||||
imageView.width,
|
||||
tintColor)
|
||||
icon,
|
||||
imageView.width,
|
||||
tintColor)
|
||||
imageView.setImageDrawable(superDrawable.drawable)
|
||||
if (superDrawable.tintable) {
|
||||
ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(tintColor))
|
||||
ImageViewCompat.setImageTintList(imageView,
|
||||
ColorStateList.valueOf(tintColor))
|
||||
} else {
|
||||
ImageViewCompat.setImageTintList(imageView, null)
|
||||
}
|
||||
@@ -201,14 +219,16 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
/**
|
||||
* Build a bitmap from a database [icon]
|
||||
*/
|
||||
fun getBitmapFromIcon(context: Context,
|
||||
icon: IconImageDraw,
|
||||
tintColor: Int = Color.BLACK): Bitmap? {
|
||||
fun getBitmapFromIcon(
|
||||
context: Context,
|
||||
icon: IconImageDraw,
|
||||
tintColor: Int = Color.BLACK,
|
||||
): Bitmap? {
|
||||
try {
|
||||
val superDrawable = getIconSuperDrawable(context,
|
||||
icon,
|
||||
24,
|
||||
tintColor)
|
||||
icon,
|
||||
24,
|
||||
tintColor)
|
||||
val bitmap = superDrawable.drawable.toBitmap()
|
||||
// Tint bitmap if it's not a custom icon
|
||||
if (superDrawable.tintable && bitmap.isMutable) {
|
||||
@@ -230,8 +250,9 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
val icon = iconDraw.getIconImageToDraw()
|
||||
val customIconBinary = retrieveCustomIconBinary(icon.custom.uuid)
|
||||
if (customIconBinary != null
|
||||
&& customIconBinary.dataExists()
|
||||
&& !customIconMap.containsKey(icon.custom.uuid))
|
||||
&& customIconBinary.dataExists()
|
||||
&& !customIconMap.containsKey(icon.custom.uuid)
|
||||
)
|
||||
getIconDrawable(resources, icon.custom, customIconBinary)
|
||||
}
|
||||
|
||||
@@ -254,15 +275,15 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
* Build a blankDrawable drawable
|
||||
* @param res Resource to build the drawable
|
||||
*/
|
||||
private class PatternIcon(res: Resources) {
|
||||
private class PatternIcon(defaultIconSize : Int) {
|
||||
|
||||
var blankDrawable: Drawable = ColorDrawable(Color.TRANSPARENT)
|
||||
var width = -1
|
||||
var height = -1
|
||||
|
||||
init {
|
||||
width = res.getDimension(R.dimen.icon_size).toInt()
|
||||
height = res.getDimension(R.dimen.icon_size).toInt()
|
||||
width = defaultIconSize
|
||||
height = defaultIconSize
|
||||
blankDrawable.setBounds(0, 0, width, height)
|
||||
}
|
||||
}
|
||||
@@ -275,7 +296,12 @@ class IconDrawableFactory(private val retrieveBinaryCache : () -> BinaryCache?,
|
||||
/**
|
||||
* Key class to retrieve a Drawable in the cache if it's tinted or not
|
||||
*/
|
||||
private inner class CacheKey(var resId: Int, var density: Int, var isTint: Boolean, var color: Int) {
|
||||
private inner class CacheKey(
|
||||
var resId: Int,
|
||||
var density: Int,
|
||||
var isTint: Boolean,
|
||||
var color: Int,
|
||||
) {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
@@ -22,8 +22,8 @@ package com.kunzisoft.keepass.icons
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.BuildConfig
|
||||
import com.kunzisoft.keepass.icon.IconPack
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Utility class to built and select an IconPack dynamically by libraries importation
|
||||
@@ -36,9 +36,11 @@ object IconPackChooser {
|
||||
|
||||
private val iconPackList = ArrayList<IconPack>()
|
||||
private var iconPackSelected: IconPack? = null
|
||||
var defaultIconSize: Int = 0
|
||||
|
||||
private var isIconPackChooserBuilt: Boolean = false
|
||||
|
||||
|
||||
/**
|
||||
* Built the icon pack chooser based on imports made in *build.gradle*
|
||||
*
|
||||
@@ -50,7 +52,7 @@ object IconPackChooser {
|
||||
* @param context Context to construct each pack with the resources
|
||||
* @return An unique instance of [IconPackChooser], recall [.build] provide the same instance
|
||||
*/
|
||||
fun build(context: Context) {
|
||||
private fun build(context: Context) {
|
||||
synchronized(IconPackChooser::class.java) {
|
||||
if (!isIconPackChooserBuilt) {
|
||||
isIconPackChooserBuilt = true
|
||||
@@ -62,6 +64,9 @@ object IconPackChooser {
|
||||
Log.e(TAG, "Icon packs can't be load, retry with one by default")
|
||||
addDefaultIconPack(context)
|
||||
}
|
||||
if(defaultIconSize == 0) {
|
||||
defaultIconSize = IconPack.defaultIconSize(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,10 +84,14 @@ object IconPackChooser {
|
||||
*/
|
||||
private fun addOrCatchNewIconPack(context: Context, iconPackString: String) {
|
||||
try {
|
||||
iconPackList.add(IconPack(context.packageName, context.resources, context.resources.getIdentifier(
|
||||
iconPackList.add(
|
||||
IconPack(context.packageName,
|
||||
context.resources,
|
||||
context.resources.getIdentifier(
|
||||
iconPackString + "_resource_id",
|
||||
"string",
|
||||
context.packageName)))
|
||||
context.packageName))
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Icon pack $iconPackString can't be load")
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@ import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.EntrySelectionLauncherActivity
|
||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.adapters.FieldsAdapter
|
||||
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.DatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Field
|
||||
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.database.helper.SearchHelper
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
|
||||
@@ -59,7 +59,7 @@ import java.util.*
|
||||
class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionListener {
|
||||
|
||||
private var mDatabaseTaskProvider: DatabaseTaskProvider? = null
|
||||
private var mDatabase: Database? = null
|
||||
private var mDatabase: ContextualDatabase? = null
|
||||
|
||||
private var keyboardView: KeyboardView? = null
|
||||
private var entryContainer: View? = null
|
||||
|
||||
@@ -26,7 +26,7 @@ import android.os.Parcelable
|
||||
import android.text.format.Formatter
|
||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* Utility data class to get FileDatabaseInfo at a `t` time
|
||||
@@ -92,10 +92,10 @@ data class SnapFileDatabaseInfo(var fileUri: Uri?,
|
||||
|
||||
fun fromFileDatabaseInfo(fileDatabaseInfo: FileDatabaseInfo): SnapFileDatabaseInfo {
|
||||
return SnapFileDatabaseInfo(
|
||||
fileDatabaseInfo.fileUri,
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModification(),
|
||||
fileDatabaseInfo.getSize())
|
||||
fileDatabaseInfo.fileUri,
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getLastModification(),
|
||||
fileDatabaseInfo.getSize())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.password
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.app.database.IOActionTask
|
||||
import com.kunzisoft.keepass.utils.IOActionTask
|
||||
import kotlinx.coroutines.*
|
||||
import me.gosimple.nbvcxz.Nbvcxz
|
||||
import me.gosimple.nbvcxz.resources.Configuration
|
||||
|
||||
@@ -2,7 +2,10 @@ package com.kunzisoft.keepass.services
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.content.*
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.Binder
|
||||
import android.os.Build
|
||||
@@ -122,7 +125,7 @@ class AdvancedUnlockNotificationService : NotificationService() {
|
||||
// Only one service connection
|
||||
fun bindService(context: Context, serviceConnection: ServiceConnection, flags: Int) {
|
||||
context.bindService(Intent(context,
|
||||
AdvancedUnlockNotificationService::class.java),
|
||||
AdvancedUnlockNotificationService::class.java),
|
||||
serviceConnection,
|
||||
flags)
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.core.app.ServiceCompat
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.action.DatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.DatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Attachment
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.model.AttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||
import com.kunzisoft.keepass.model.StreamDirection
|
||||
import com.kunzisoft.keepass.tasks.BinaryDatabaseManager
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -48,7 +48,7 @@ import java.util.concurrent.CopyOnWriteArrayList
|
||||
class AttachmentFileNotificationService: LockNotificationService() {
|
||||
|
||||
private var mDatabaseTaskProvider: DatabaseTaskProvider? = null
|
||||
private var mDatabase: Database? = null
|
||||
private var mDatabase: ContextualDatabase? = null
|
||||
private val mPendingCommands: MutableList<Intent?> = mutableListOf()
|
||||
|
||||
override val notificationId: Int = 10000
|
||||
@@ -218,7 +218,7 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
}
|
||||
)
|
||||
|
||||
val fileName = UriUtil.getFileData(this, attachmentNotification.uri)?.name
|
||||
val fileName = attachmentNotification.uri.getDocumentFile(this)?.name
|
||||
?: attachmentNotification.uri.path
|
||||
|
||||
val builder = buildNewNotification().apply {
|
||||
@@ -365,9 +365,9 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
}
|
||||
|
||||
private class AttachmentFileAction(
|
||||
private val attachmentNotification: AttachmentNotification,
|
||||
private val database: Database,
|
||||
private val contentResolver: ContentResolver) {
|
||||
private val attachmentNotification: AttachmentNotification,
|
||||
private val database: ContextualDatabase,
|
||||
private val contentResolver: ContentResolver) {
|
||||
|
||||
private val updateMinFrequency = 1000
|
||||
private var previousSaveTime = System.currentTimeMillis()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,7 +47,9 @@ import com.kunzisoft.keepass.icons.IconPackChooser
|
||||
import com.kunzisoft.keepass.services.ClipboardEntryNotificationService
|
||||
import com.kunzisoft.keepass.settings.preference.IconPackListPreference
|
||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.DurationDialogFragmentCompat
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.isContributingUser
|
||||
import com.kunzisoft.keepass.utils.UriUtil.openUrl
|
||||
import com.kunzisoft.keepass.utils.UriUtil.releaseAllUnnecessaryPermissionUris
|
||||
|
||||
|
||||
class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
@@ -81,7 +83,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
findPreference<Preference>(getString(R.string.remember_database_locations_key))?.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (!(newValue as Boolean)) {
|
||||
FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAll {
|
||||
UriUtil.releaseAllUnnecessaryPermissionUris(activity.applicationContext)
|
||||
activity.releaseAllUnnecessaryPermissionUris()
|
||||
}
|
||||
}
|
||||
true
|
||||
@@ -90,7 +92,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
findPreference<Preference>(getString(R.string.remember_keyfile_locations_key))?.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (!(newValue as Boolean)) {
|
||||
FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAllKeyFiles {
|
||||
UriUtil.releaseAllUnnecessaryPermissionUris(activity.applicationContext)
|
||||
activity.releaseAllUnnecessaryPermissionUris()
|
||||
}
|
||||
}
|
||||
true
|
||||
@@ -168,7 +170,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
}
|
||||
|
||||
findPreference<Preference>(getString(R.string.magic_keyboard_explanation_key))?.setOnPreferenceClickListener {
|
||||
UriUtil.gotoUrl(requireContext(), R.string.magic_keyboard_explanation_url)
|
||||
context?.openUrl(R.string.magic_keyboard_explanation_url)
|
||||
false
|
||||
}
|
||||
|
||||
@@ -185,7 +187,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
}
|
||||
|
||||
findPreference<Preference>(getString(R.string.autofill_explanation_key))?.setOnPreferenceClickListener {
|
||||
UriUtil.gotoUrl(requireContext(), R.string.autofill_explanation_url)
|
||||
context?.openUrl(R.string.autofill_explanation_url)
|
||||
false
|
||||
}
|
||||
|
||||
@@ -202,7 +204,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
}
|
||||
|
||||
findPreference<Preference>(getString(R.string.clipboard_explanation_key))?.setOnPreferenceClickListener {
|
||||
UriUtil.gotoUrl(requireContext(), R.string.clipboard_explanation_url)
|
||||
context?.openUrl(R.string.clipboard_explanation_url)
|
||||
false
|
||||
}
|
||||
|
||||
@@ -360,7 +362,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
}
|
||||
|
||||
findPreference<Preference>(getString(R.string.advanced_unlock_explanation_key))?.setOnPreferenceClickListener {
|
||||
UriUtil.gotoUrl(requireContext(), R.string.advanced_unlock_explanation_url)
|
||||
context?.openUrl(R.string.advanced_unlock_explanation_url)
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -404,7 +406,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
findPreference<ListPreference>(getString(R.string.setting_style_key))?.setOnPreferenceChangeListener { _, newValue ->
|
||||
var styleEnabled = true
|
||||
val styleIdString = newValue as String
|
||||
if (!UriUtil.contributingUser(activity)) {
|
||||
if (!activity.isContributingUser()) {
|
||||
for (themeIdDisabled in BuildConfig.STYLES_DISABLED) {
|
||||
if (themeIdDisabled == styleIdString) {
|
||||
styleEnabled = false
|
||||
@@ -435,7 +437,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
findPreference<IconPackListPreference>(getString(R.string.setting_icon_pack_choose_key))?.setOnPreferenceChangeListener { _, newValue ->
|
||||
var iconPackEnabled = true
|
||||
val iconPackId = newValue as String
|
||||
if (!UriUtil.contributingUser(activity)) {
|
||||
if (!activity.isContributingUser()) {
|
||||
for (iconPackIdDisabled in BuildConfig.ICON_PACKS_DISABLED) {
|
||||
if (iconPackIdDisabled == iconPackId) {
|
||||
iconPackEnabled = false
|
||||
|
||||
@@ -33,12 +33,12 @@ import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.SetMainCredentialDialogFragment
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
|
||||
import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
||||
import com.kunzisoft.keepass.database.element.template.TemplateEngine
|
||||
import com.kunzisoft.keepass.database.helper.*
|
||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
||||
import com.kunzisoft.keepass.settings.preference.*
|
||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.*
|
||||
@@ -48,7 +48,7 @@ import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||
class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetrieval {
|
||||
|
||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
||||
private var mDatabase: Database? = null
|
||||
private var mDatabase: ContextualDatabase? = null
|
||||
private var mDatabaseReadOnly: Boolean = false
|
||||
private var mMergeDataAllowed: Boolean = false
|
||||
private var mDatabaseAutoSaveEnabled: Boolean = true
|
||||
@@ -123,7 +123,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
mDatabaseViewModel.reloadDatabase(false)
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
mDatabase = database
|
||||
mDatabaseReadOnly = database?.isReadOnly == true
|
||||
mMergeDataAllowed = database?.isMergeDataAllowed() == true
|
||||
@@ -149,7 +149,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCreateDatabasePreference(database: Database) {
|
||||
private fun onCreateDatabasePreference(database: ContextualDatabase) {
|
||||
val dbGeneralPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_general_key))
|
||||
|
||||
// Database name
|
||||
@@ -199,7 +199,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
dbDataCompressionPref = findPreference(getString(R.string.database_data_compression_key))
|
||||
if (database.allowDataCompression) {
|
||||
dbDataCompressionPref?.summary = (database.compressionAlgorithm
|
||||
?: CompressionAlgorithm.None).getName(resources)
|
||||
?: CompressionAlgorithm.NONE).getLocalizedName(resources)
|
||||
} else {
|
||||
dbCompressionPrefCategory?.isVisible = false
|
||||
}
|
||||
@@ -215,7 +215,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
isEnabled = if (!mDatabaseReadOnly) {
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val recycleBinEnabled = newValue as Boolean
|
||||
database.enableRecycleBin(recycleBinEnabled, resources)
|
||||
database.enableRecycleBin(recycleBinEnabled, resources.getString(R.string.recycle_bin))
|
||||
refreshRecycleBinGroup(database)
|
||||
// Save the database if not in readonly mode
|
||||
saveDatabase(mDatabaseAutoSaveEnabled)
|
||||
@@ -249,7 +249,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val templatesEnabled = newValue as Boolean
|
||||
database.enableTemplates(templatesEnabled,
|
||||
TemplateEngine.getDefaultTemplateGroupName(resources)
|
||||
resources.getString(R.string.templates)
|
||||
)
|
||||
refreshTemplatesGroup(database)
|
||||
// Save the database if not in readonly mode
|
||||
@@ -282,7 +282,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshRecycleBinGroup(database: Database?) {
|
||||
private fun refreshRecycleBinGroup(database: ContextualDatabase?) {
|
||||
recycleBinGroupPref?.apply {
|
||||
if (database?.isRecycleBinEnabled == true) {
|
||||
summary = database.recycleBin?.toString()
|
||||
@@ -294,7 +294,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshTemplatesGroup(database: Database?) {
|
||||
private fun refreshTemplatesGroup(database: ContextualDatabase?) {
|
||||
templatesGroupPref?.apply {
|
||||
if (database?.isTemplatesEnabled == true) {
|
||||
summary = database.templatesGroup?.toString()
|
||||
@@ -306,7 +306,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCreateDatabaseSecurityPreference(database: Database) {
|
||||
private fun onCreateDatabaseSecurityPreference(database: ContextualDatabase) {
|
||||
// Encryption Algorithm
|
||||
mEncryptionAlgorithmPref = findPreference<DialogListExplanationPreference>(getString(R.string.encryption_algorithm_key))?.apply {
|
||||
summary = database.getEncryptionAlgorithmName()
|
||||
@@ -333,7 +333,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCreateDatabaseMasterKeyPreference(database: Database) {
|
||||
private fun onCreateDatabaseMasterKeyPreference(database: ContextualDatabase) {
|
||||
findPreference<Preference>(getString(R.string.settings_database_change_credentials_key))?.apply {
|
||||
isEnabled = if (!mDatabaseReadOnly) {
|
||||
onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
@@ -371,7 +371,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
}
|
||||
|
||||
// TODO check error
|
||||
override fun onDatabaseActionFinished(database: Database,
|
||||
override fun onDatabaseActionFinished(database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result) {
|
||||
result.data?.let { data ->
|
||||
@@ -442,7 +442,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
||||
mDatabase?.compressionAlgorithm = oldCompression
|
||||
oldCompression
|
||||
}
|
||||
dbDataCompressionPref?.summary = algorithmToShow.getName(resources)
|
||||
dbDataCompressionPref?.summary = algorithmToShow.getLocalizedName(resources)
|
||||
}
|
||||
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK -> {
|
||||
val oldRecycleBin = data.getParcelable<Group?>(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||
|
||||
@@ -36,7 +36,7 @@ import com.kunzisoft.keepass.education.Education
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
|
||||
import com.kunzisoft.keepass.password.PassphraseGenerator
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil.isContributingUser
|
||||
import java.util.*
|
||||
|
||||
object PreferencesUtil {
|
||||
@@ -75,25 +75,25 @@ object PreferencesUtil {
|
||||
fun rememberDatabaseLocations(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.remember_database_locations_key),
|
||||
context.resources.getBoolean(R.bool.remember_database_locations_default))
|
||||
context.resources.getBoolean(R.bool.remember_database_locations_default))
|
||||
}
|
||||
|
||||
fun showRecentFiles(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.show_recent_files_key),
|
||||
context.resources.getBoolean(R.bool.show_recent_files_default))
|
||||
context.resources.getBoolean(R.bool.show_recent_files_default))
|
||||
}
|
||||
|
||||
fun hideBrokenLocations(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.hide_broken_locations_key),
|
||||
context.resources.getBoolean(R.bool.hide_broken_locations_default))
|
||||
context.resources.getBoolean(R.bool.hide_broken_locations_default))
|
||||
}
|
||||
|
||||
fun rememberKeyFileLocations(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.remember_keyfile_locations_key),
|
||||
context.resources.getBoolean(R.bool.remember_keyfile_locations_default))
|
||||
context.resources.getBoolean(R.bool.remember_keyfile_locations_default))
|
||||
}
|
||||
|
||||
fun rememberHardwareKey(context: Context): Boolean {
|
||||
@@ -105,13 +105,13 @@ object PreferencesUtil {
|
||||
fun automaticallyFocusSearch(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.auto_focus_search_key),
|
||||
context.resources.getBoolean(R.bool.auto_focus_search_default))
|
||||
context.resources.getBoolean(R.bool.auto_focus_search_default))
|
||||
}
|
||||
|
||||
fun searchSubdomains(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.subdomain_search_key),
|
||||
context.resources.getBoolean(R.bool.subdomain_search_default))
|
||||
context.resources.getBoolean(R.bool.subdomain_search_default))
|
||||
}
|
||||
|
||||
fun showEntryColors(context: Context): Boolean {
|
||||
@@ -135,13 +135,13 @@ object PreferencesUtil {
|
||||
fun showUsernamesListEntries(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.list_entries_show_username_key),
|
||||
context.resources.getBoolean(R.bool.list_entries_show_username_default))
|
||||
context.resources.getBoolean(R.bool.list_entries_show_username_default))
|
||||
}
|
||||
|
||||
fun showNumberEntries(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.list_groups_show_number_entries_key),
|
||||
context.resources.getBoolean(R.bool.list_groups_show_number_entries_default))
|
||||
context.resources.getBoolean(R.bool.list_groups_show_number_entries_default))
|
||||
}
|
||||
|
||||
fun showOTPToken(context: Context): Boolean {
|
||||
@@ -159,21 +159,21 @@ object PreferencesUtil {
|
||||
fun showExpiredEntries(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return ! prefs.getBoolean(context.getString(R.string.hide_expired_entries_key),
|
||||
context.resources.getBoolean(R.bool.hide_expired_entries_default))
|
||||
context.resources.getBoolean(R.bool.hide_expired_entries_default))
|
||||
}
|
||||
|
||||
fun getStyle(context: Context): String {
|
||||
val defaultStyleString = Stylish.defaultStyle(context)
|
||||
val styleString = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(context.getString(R.string.setting_style_key), defaultStyleString)
|
||||
?: defaultStyleString
|
||||
.getString(context.getString(R.string.setting_style_key), defaultStyleString)
|
||||
?: defaultStyleString
|
||||
// Return the system style
|
||||
return Stylish.retrieveEquivalentSystemStyle(context, styleString)
|
||||
}
|
||||
|
||||
fun setStyle(context: Context, styleString: String) {
|
||||
var tempThemeString = styleString
|
||||
if (!UriUtil.contributingUser(context)) {
|
||||
if (!context.isContributingUser()) {
|
||||
if (tempThemeString in BuildConfig.STYLES_DISABLED) {
|
||||
tempThemeString = Stylish.defaultStyle(context)
|
||||
}
|
||||
@@ -181,16 +181,16 @@ object PreferencesUtil {
|
||||
// Store light style to show selection in array list
|
||||
tempThemeString = Stylish.retrieveEquivalentLightStyle(context, tempThemeString)
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.edit()
|
||||
.putString(context.getString(R.string.setting_style_key), tempThemeString)
|
||||
.apply()
|
||||
.edit()
|
||||
.putString(context.getString(R.string.setting_style_key), tempThemeString)
|
||||
.apply()
|
||||
Stylish.load(context)
|
||||
}
|
||||
|
||||
fun getStyleBrightness(context: Context): String? {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getString(context.getString(R.string.setting_style_brightness_key),
|
||||
context.getString(R.string.list_style_brightness_follow_system))
|
||||
context.getString(R.string.list_style_brightness_follow_system))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,7 +200,7 @@ object PreferencesUtil {
|
||||
val index = try {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val listSizeString = prefs.getString(context.getString(R.string.list_size_key),
|
||||
context.getString(R.string.list_size_string_medium))
|
||||
context.getString(R.string.list_size_string_medium))
|
||||
context.resources.getStringArray(R.array.list_size_string_values).indexOf(listSizeString)
|
||||
} catch (e: Exception) {
|
||||
1
|
||||
@@ -214,7 +214,7 @@ object PreferencesUtil {
|
||||
fun getDefaultPasswordLength(context: Context): Int {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getInt(context.getString(R.string.password_generator_length_key),
|
||||
context.resources.getInteger(R.integer.password_generator_length_default))
|
||||
context.resources.getInteger(R.integer.password_generator_length_default))
|
||||
}
|
||||
|
||||
fun setDefaultPasswordLength(context: Context, passwordLength: Int) {
|
||||
@@ -406,7 +406,7 @@ object PreferencesUtil {
|
||||
fun isClipboardNotificationsEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.clipboard_notifications_key),
|
||||
context.resources.getBoolean(R.bool.clipboard_notifications_default))
|
||||
context.resources.getBoolean(R.bool.clipboard_notifications_default))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -425,7 +425,7 @@ object PreferencesUtil {
|
||||
fun getTimeSaved(context: Context): Long {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getLong(context.getString(R.string.timeout_backup_key),
|
||||
TimeoutHelper.NEVER)
|
||||
TimeoutHelper.NEVER)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,7 +435,7 @@ object PreferencesUtil {
|
||||
return try {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
(prefs.getString(context.getString(R.string.app_timeout_key),
|
||||
context.getString(R.string.timeout_default)) ?: "300000").toLong()
|
||||
context.getString(R.string.timeout_default)) ?: "300000").toLong()
|
||||
} catch (e: NumberFormatException) {
|
||||
TimeoutHelper.DEFAULT_TIMEOUT
|
||||
}
|
||||
@@ -444,39 +444,39 @@ object PreferencesUtil {
|
||||
fun getClipboardTimeout(context: Context): Long {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getString(context.getString(R.string.clipboard_timeout_key),
|
||||
context.getString(R.string.clipboard_timeout_default))?.toLong()
|
||||
?: TimeoutHelper.DEFAULT_TIMEOUT
|
||||
context.getString(R.string.clipboard_timeout_default))?.toLong()
|
||||
?: TimeoutHelper.DEFAULT_TIMEOUT
|
||||
}
|
||||
|
||||
fun getAdvancedUnlockTimeout(context: Context): Long {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getString(context.getString(R.string.temp_advanced_unlock_timeout_key),
|
||||
context.getString(R.string.temp_advanced_unlock_timeout_default))?.toLong()
|
||||
?: TimeoutHelper.DEFAULT_TIMEOUT
|
||||
context.getString(R.string.temp_advanced_unlock_timeout_default))?.toLong()
|
||||
?: TimeoutHelper.DEFAULT_TIMEOUT
|
||||
}
|
||||
|
||||
fun isLockDatabaseWhenScreenShutOffEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.lock_database_screen_off_key),
|
||||
context.resources.getBoolean(R.bool.lock_database_screen_off_default))
|
||||
context.resources.getBoolean(R.bool.lock_database_screen_off_default))
|
||||
}
|
||||
|
||||
fun isLockDatabaseWhenBackButtonOnRootClicked(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.lock_database_back_root_key),
|
||||
context.resources.getBoolean(R.bool.lock_database_back_root_default))
|
||||
context.resources.getBoolean(R.bool.lock_database_back_root_default))
|
||||
}
|
||||
|
||||
fun showLockDatabaseButton(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.lock_database_show_button_key),
|
||||
context.resources.getBoolean(R.bool.lock_database_show_button_default))
|
||||
context.resources.getBoolean(R.bool.lock_database_show_button_default))
|
||||
}
|
||||
|
||||
fun isAutoSaveDatabaseEnabled(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.enable_auto_save_database_key),
|
||||
context.resources.getBoolean(R.bool.enable_auto_save_database_default))
|
||||
context.resources.getBoolean(R.bool.enable_auto_save_database_default))
|
||||
}
|
||||
|
||||
fun isKeepScreenOnEnabled(context: Context): Boolean {
|
||||
@@ -498,39 +498,39 @@ object PreferencesUtil {
|
||||
fun isBiometricUnlockEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.biometric_unlock_enable_key),
|
||||
context.resources.getBoolean(R.bool.biometric_unlock_enable_default))
|
||||
context.resources.getBoolean(R.bool.biometric_unlock_enable_default))
|
||||
&& (if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
AdvancedUnlockManager.biometricUnlockSupported(context)
|
||||
} else {
|
||||
false
|
||||
})
|
||||
AdvancedUnlockManager.biometricUnlockSupported(context)
|
||||
} else {
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
fun isDeviceCredentialUnlockEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
// Priority to biometric unlock
|
||||
return prefs.getBoolean(context.getString(R.string.device_credential_unlock_enable_key),
|
||||
context.resources.getBoolean(R.bool.device_credential_unlock_enable_default))
|
||||
context.resources.getBoolean(R.bool.device_credential_unlock_enable_default))
|
||||
&& !isBiometricUnlockEnable(context)
|
||||
}
|
||||
|
||||
fun isTempAdvancedUnlockEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.temp_advanced_unlock_enable_key),
|
||||
context.resources.getBoolean(R.bool.temp_advanced_unlock_enable_default))
|
||||
context.resources.getBoolean(R.bool.temp_advanced_unlock_enable_default))
|
||||
}
|
||||
|
||||
fun isAdvancedUnlockPromptAutoOpenEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.biometric_auto_open_prompt_key),
|
||||
context.resources.getBoolean(R.bool.biometric_auto_open_prompt_default))
|
||||
context.resources.getBoolean(R.bool.biometric_auto_open_prompt_default))
|
||||
}
|
||||
|
||||
fun getListSort(context: Context): SortNodeEnum {
|
||||
try {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
prefs.getString(context.getString(R.string.sort_node_key),
|
||||
SortNodeEnum.DB.name)?.let {
|
||||
SortNodeEnum.DB.name)?.let {
|
||||
return SortNodeEnum.valueOf(it)
|
||||
}
|
||||
} catch (e: Exception) {}
|
||||
@@ -540,94 +540,94 @@ object PreferencesUtil {
|
||||
fun getGroupsBeforeSort(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.sort_group_before_key),
|
||||
context.resources.getBoolean(R.bool.sort_group_before_default))
|
||||
context.resources.getBoolean(R.bool.sort_group_before_default))
|
||||
}
|
||||
|
||||
fun getAscendingSort(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.sort_ascending_key),
|
||||
context.resources.getBoolean(R.bool.sort_ascending_default))
|
||||
context.resources.getBoolean(R.bool.sort_ascending_default))
|
||||
}
|
||||
|
||||
fun getRecycleBinBottomSort(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.sort_recycle_bin_bottom_key),
|
||||
context.resources.getBoolean(R.bool.sort_recycle_bin_bottom_default))
|
||||
context.resources.getBoolean(R.bool.sort_recycle_bin_bottom_default))
|
||||
}
|
||||
|
||||
fun fieldFontIsInVisibility(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.monospace_font_fields_enable_key),
|
||||
context.resources.getBoolean(R.bool.monospace_font_fields_enable_default))
|
||||
context.resources.getBoolean(R.bool.monospace_font_fields_enable_default))
|
||||
}
|
||||
|
||||
fun isFirstTimeAskAllowCopyProtectedFields(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.allow_copy_password_first_time_key),
|
||||
context.resources.getBoolean(R.bool.allow_copy_password_first_time_default))
|
||||
context.resources.getBoolean(R.bool.allow_copy_password_first_time_default))
|
||||
}
|
||||
|
||||
fun allowCopyProtectedFields(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.allow_copy_password_key),
|
||||
context.resources.getBoolean(R.bool.allow_copy_password_default))
|
||||
context.resources.getBoolean(R.bool.allow_copy_password_default))
|
||||
}
|
||||
|
||||
fun isClearClipboardNotificationEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.clear_clipboard_notification_key),
|
||||
context.resources.getBoolean(R.bool.clear_clipboard_notification_default))
|
||||
context.resources.getBoolean(R.bool.clear_clipboard_notification_default))
|
||||
}
|
||||
|
||||
fun isClearKeyboardNotificationEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_notification_entry_clear_close_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_notification_entry_clear_close_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_notification_entry_clear_close_default))
|
||||
}
|
||||
|
||||
fun setAllowCopyPasswordAndProtectedFields(context: Context, allowCopy: Boolean) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
prefs.edit()
|
||||
.putBoolean(context.getString(R.string.allow_copy_password_first_time_key), false)
|
||||
.putBoolean(context.getString(R.string.allow_copy_password_key), allowCopy)
|
||||
.apply()
|
||||
.putBoolean(context.getString(R.string.allow_copy_password_first_time_key), false)
|
||||
.putBoolean(context.getString(R.string.allow_copy_password_key), allowCopy)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun getIconPackSelectedId(context: Context): String? {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getString(
|
||||
context.getString(R.string.setting_icon_pack_choose_key),
|
||||
context.getString(R.string.setting_icon_pack_choose_default))
|
||||
context.getString(R.string.setting_icon_pack_choose_key),
|
||||
context.getString(R.string.setting_icon_pack_choose_default))
|
||||
}
|
||||
|
||||
fun emptyPasswordAllowed(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.allow_no_password_key),
|
||||
context.resources.getBoolean(R.bool.allow_no_password_default))
|
||||
context.resources.getBoolean(R.bool.allow_no_password_default))
|
||||
}
|
||||
|
||||
fun enableReadOnlyDatabase(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.enable_read_only_key),
|
||||
context.resources.getBoolean(R.bool.enable_read_only_default))
|
||||
context.resources.getBoolean(R.bool.enable_read_only_default))
|
||||
}
|
||||
|
||||
fun deletePasswordAfterConnexionAttempt(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.delete_entered_password_key),
|
||||
context.resources.getBoolean(R.bool.delete_entered_password_default))
|
||||
context.resources.getBoolean(R.bool.delete_entered_password_default))
|
||||
}
|
||||
|
||||
fun isKeyboardNotificationEntryEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_notification_entry_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_notification_entry_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_notification_entry_default))
|
||||
}
|
||||
|
||||
fun isKeyboardEntrySelectionEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_selection_entry_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_selection_entry_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_selection_entry_default))
|
||||
}
|
||||
|
||||
fun isKeyboardSaveSearchInfoEnable(context: Context): Boolean {
|
||||
@@ -635,79 +635,79 @@ object PreferencesUtil {
|
||||
return false
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_save_search_info_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_save_search_info_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_save_search_info_default))
|
||||
}
|
||||
|
||||
fun isAutoGoActionEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_auto_go_action_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_auto_go_action_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_auto_go_action_default))
|
||||
}
|
||||
|
||||
fun isKeyboardVibrationEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_key_vibrate_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_key_vibrate_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_key_vibrate_default))
|
||||
}
|
||||
|
||||
fun isKeyboardSoundEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_key_sound_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_key_sound_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_key_sound_default))
|
||||
}
|
||||
|
||||
fun isKeyboardPreviousDatabaseCredentialsEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_previous_database_credentials_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_database_credentials_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_database_credentials_default))
|
||||
}
|
||||
|
||||
fun isKeyboardPreviousSearchEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_previous_search_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_search_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_search_default))
|
||||
}
|
||||
|
||||
fun isKeyboardPreviousFillInEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_previous_fill_in_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_fill_in_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_fill_in_default))
|
||||
}
|
||||
|
||||
fun isKeyboardPreviousLockEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.keyboard_previous_lock_key),
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_lock_default))
|
||||
context.resources.getBoolean(R.bool.keyboard_previous_lock_default))
|
||||
}
|
||||
|
||||
fun isAutofillCloseDatabaseEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.autofill_close_database_key),
|
||||
context.resources.getBoolean(R.bool.autofill_close_database_default))
|
||||
context.resources.getBoolean(R.bool.autofill_close_database_default))
|
||||
}
|
||||
|
||||
fun isAutofillInlineSuggestionsEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.autofill_inline_suggestions_key),
|
||||
context.resources.getBoolean(R.bool.autofill_inline_suggestions_default))
|
||||
context.resources.getBoolean(R.bool.autofill_inline_suggestions_default))
|
||||
}
|
||||
|
||||
fun isAutofillManualSelectionEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.autofill_manual_selection_key),
|
||||
context.resources.getBoolean(R.bool.autofill_manual_selection_default))
|
||||
context.resources.getBoolean(R.bool.autofill_manual_selection_default))
|
||||
}
|
||||
|
||||
fun isAutofillSaveSearchInfoEnable(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.autofill_save_search_info_key),
|
||||
context.resources.getBoolean(R.bool.autofill_save_search_info_default))
|
||||
context.resources.getBoolean(R.bool.autofill_save_search_info_default))
|
||||
}
|
||||
|
||||
fun askToSaveAutofillData(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.autofill_ask_to_save_data_key),
|
||||
context.resources.getBoolean(R.bool.autofill_ask_to_save_data_default))
|
||||
context.resources.getBoolean(R.bool.autofill_ask_to_save_data_default))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -715,23 +715,23 @@ object PreferencesUtil {
|
||||
*/
|
||||
fun getDefaultApplicationIdBlocklist(resources: Resources?): Set<String> {
|
||||
return resources?.getStringArray(R.array.autofill_application_id_blocklist_default)
|
||||
?.toMutableSet()?.apply {
|
||||
add(BuildConfig.APPLICATION_ID)
|
||||
} ?: emptySet()
|
||||
?.toMutableSet()?.apply {
|
||||
add(BuildConfig.APPLICATION_ID)
|
||||
} ?: emptySet()
|
||||
}
|
||||
|
||||
fun applicationIdBlocklist(context: Context): Set<String> {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getStringSet(context.getString(R.string.autofill_application_id_blocklist_key),
|
||||
getDefaultApplicationIdBlocklist(context.resources))
|
||||
?: emptySet()
|
||||
getDefaultApplicationIdBlocklist(context.resources))
|
||||
?: emptySet()
|
||||
}
|
||||
|
||||
fun webDomainBlocklist(context: Context): Set<String> {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getStringSet(context.getString(R.string.autofill_web_domain_blocklist_key),
|
||||
context.resources.getStringArray(R.array.autofill_web_domain_blocklist_default).toMutableSet())
|
||||
?: emptySet()
|
||||
context.resources.getStringArray(R.array.autofill_web_domain_blocklist_default).toMutableSet())
|
||||
?: emptySet()
|
||||
}
|
||||
|
||||
fun addApplicationIdToBlocklist(context: Context, applicationId: String) {
|
||||
@@ -739,8 +739,8 @@ object PreferencesUtil {
|
||||
val setItems: MutableSet<String> = applicationIdBlocklist(context).toMutableSet()
|
||||
setItems.add(applicationId)
|
||||
prefs.edit()
|
||||
.putStringSet(context.getString(R.string.autofill_application_id_blocklist_key), setItems)
|
||||
.apply()
|
||||
.putStringSet(context.getString(R.string.autofill_application_id_blocklist_key), setItems)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun addWebDomainToBlocklist(context: Context, webDomain: String) {
|
||||
@@ -748,8 +748,8 @@ object PreferencesUtil {
|
||||
val setItems: MutableSet<String> = webDomainBlocklist(context).toMutableSet()
|
||||
setItems.add(webDomain)
|
||||
prefs.edit()
|
||||
.putStringSet(context.getString(R.string.autofill_web_domain_blocklist_key), setItems)
|
||||
.apply()
|
||||
.putStringSet(context.getString(R.string.autofill_web_domain_blocklist_key), setItems)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun getAppProperties(context: Context): Properties {
|
||||
@@ -765,9 +765,9 @@ object PreferencesUtil {
|
||||
|
||||
private fun getStringSetFromProperties(value: String): Set<String> {
|
||||
return value.removePrefix("[")
|
||||
.removeSuffix("]")
|
||||
.split(", ")
|
||||
.toSet()
|
||||
.removeSuffix("]")
|
||||
.split(", ")
|
||||
.toSet()
|
||||
}
|
||||
|
||||
private fun putPropertiesInPreferences(properties: Properties,
|
||||
@@ -788,7 +788,7 @@ object PreferencesUtil {
|
||||
|
||||
fun setAppProperties(context: Context, properties: Properties) {
|
||||
putPropertiesInPreferences(properties,
|
||||
PreferenceManager.getDefaultSharedPreferences(context)) { editor, name, value ->
|
||||
PreferenceManager.getDefaultSharedPreferences(context)) { editor, name, value ->
|
||||
when (name) {
|
||||
context.getString(R.string.allow_no_password_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
context.getString(R.string.delete_entered_password_key) -> editor.putBoolean(name, value.toBoolean())
|
||||
@@ -869,7 +869,7 @@ object PreferencesUtil {
|
||||
}
|
||||
|
||||
putPropertiesInPreferences(properties,
|
||||
Education.getEducationSharedPreferences(context)) { editor, name, value ->
|
||||
Education.getEducationSharedPreferences(context)) { editor, name, value ->
|
||||
Education.putPropertiesInEducationPreferences(context, editor, name, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,13 +35,13 @@ import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.SetMainCredentialDialogFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
|
||||
import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.MainCredential
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
import java.util.Properties
|
||||
|
||||
open class SettingsActivity
|
||||
: DatabaseLockActivity(),
|
||||
@@ -150,7 +150,7 @@ open class SettingsActivity
|
||||
}
|
||||
|
||||
override fun onDatabaseActionFinished(
|
||||
database: Database,
|
||||
database: ContextualDatabase,
|
||||
actionTask: String,
|
||||
result: ActionRunnable.Result
|
||||
) {
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.content.Context
|
||||
import androidx.preference.ListPreference
|
||||
import android.util.AttributeSet
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.icons.IconPackChooser
|
||||
import java.util.*
|
||||
|
||||
@@ -37,9 +36,9 @@ class IconPackListPreference @JvmOverloads constructor(context: Context,
|
||||
val entries = ArrayList<String>()
|
||||
val values = ArrayList<String>()
|
||||
for (iconPack in IconPackChooser.getIconPackList(context)) {
|
||||
if (iconPack.id != null) {
|
||||
iconPack.id?.let { iconPackId ->
|
||||
entries.add(iconPack.name)
|
||||
values.add(iconPack.id!!)
|
||||
values.add(iconPackId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
import android.app.Dialog
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -30,14 +29,9 @@ import android.view.Window
|
||||
import android.widget.CompoundButton
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.kunzisoft.androidclearchroma.IndicatorMode
|
||||
import com.kunzisoft.androidclearchroma.colormode.ColorMode
|
||||
import com.kunzisoft.androidclearchroma.fragment.ChromaColorFragment
|
||||
import com.kunzisoft.androidclearchroma.fragment.ChromaColorFragment.*
|
||||
import com.kunzisoft.androidclearchroma.view.ChromaColorView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.ColorPickerDialogFragment
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
|
||||
class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
|
||||
@@ -101,7 +95,7 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog
|
||||
return dialog
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
|
||||
database?.let {
|
||||
@@ -117,7 +111,7 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
if (positiveResult) {
|
||||
val newColor: Int? = if (enableSwitchView.isChecked)
|
||||
|
||||
@@ -24,7 +24,7 @@ import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter
|
||||
|
||||
@@ -50,7 +50,7 @@ class DatabaseDataCompressionPreferenceDialogFragmentCompat
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
setExplanationText(R.string.database_data_compression_summary)
|
||||
|
||||
@@ -62,7 +62,7 @@ class DatabaseDataCompressionPreferenceDialogFragmentCompat
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
|
||||
@@ -20,16 +20,16 @@
|
||||
package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
|
||||
class DatabaseDefaultUsernamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
inputText = database?.defaultUsername?: ""
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
database?.let {
|
||||
if (positiveResult) {
|
||||
|
||||
@@ -20,16 +20,16 @@
|
||||
package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
|
||||
class DatabaseDescriptionPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
inputText = database?.description ?: ""
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
database?.let {
|
||||
if (positiveResult) {
|
||||
|
||||
@@ -24,8 +24,8 @@ import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter
|
||||
|
||||
class DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat
|
||||
@@ -51,7 +51,7 @@ class DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
database?.let {
|
||||
algorithmSelected = database.encryptionAlgorithm
|
||||
@@ -59,7 +59,7 @@ class DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
|
||||
@@ -25,8 +25,8 @@ import androidx.preference.Preference
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter
|
||||
|
||||
class DatabaseKeyDerivationPreferenceDialogFragmentCompat
|
||||
@@ -54,7 +54,7 @@ class DatabaseKeyDerivationPreferenceDialogFragmentCompat
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
database?.let {
|
||||
kdfEngineSelected = database.kdfEngine
|
||||
@@ -62,7 +62,7 @@ class DatabaseKeyDerivationPreferenceDialogFragmentCompat
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
|
||||
class DatabaseMaxHistoryItemsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
|
||||
@@ -31,7 +31,7 @@ class DatabaseMaxHistoryItemsPreferenceDialogFragmentCompat : DatabaseSavePrefer
|
||||
setExplanationText(R.string.max_history_items_summary)
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
database?.historyMaxItems?.let { maxItemsDatabase ->
|
||||
inputText = maxItemsDatabase.toString()
|
||||
@@ -46,7 +46,7 @@ class DatabaseMaxHistoryItemsPreferenceDialogFragmentCompat : DatabaseSavePrefer
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.utils.DataByte
|
||||
|
||||
class DatabaseMaxHistorySizePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
@@ -34,7 +34,7 @@ class DatabaseMaxHistorySizePreferenceDialogFragmentCompat : DatabaseSavePrefere
|
||||
setExplanationText(R.string.max_history_size_summary)
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
database?.historyMaxSize?.let { maxItemsDatabase ->
|
||||
dataByte = DataByte(maxItemsDatabase, DataByte.ByteFormat.BYTE)
|
||||
@@ -61,7 +61,7 @@ class DatabaseMaxHistorySizePreferenceDialogFragmentCompat : DatabaseSavePrefere
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.utils.DataByte
|
||||
|
||||
class DatabaseMemoryUsagePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
@@ -34,7 +34,7 @@ class DatabaseMemoryUsagePreferenceDialogFragmentCompat : DatabaseSavePreference
|
||||
setExplanationText(R.string.memory_usage_explanation)
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
database?.let {
|
||||
val memoryBytes = database.memoryUsage
|
||||
@@ -45,7 +45,7 @@ class DatabaseMemoryUsagePreferenceDialogFragmentCompat : DatabaseSavePreference
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
var newMemoryUsage: Long = try {
|
||||
|
||||
@@ -20,16 +20,16 @@
|
||||
package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
|
||||
class DatabaseNamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
inputText = database?.name ?: ""
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
|
||||
class DatabaseParallelismPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
|
||||
@@ -31,12 +31,12 @@ class DatabaseParallelismPreferenceDialogFragmentCompat : DatabaseSavePreference
|
||||
setExplanationText(R.string.parallelism_explanation)
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
inputText = database?.parallelism?.toString() ?: MIN_PARALLELISM.toString()
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
val parallelism: Long = try {
|
||||
|
||||
@@ -24,7 +24,7 @@ import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.element.Group
|
||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter
|
||||
|
||||
@@ -48,7 +48,7 @@ class DatabaseRecycleBinGroupPreferenceDialogFragmentCompat
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDatabaseRetrieved(database: Database?) {
|
||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||
super.onDatabaseRetrieved(database)
|
||||
database?.let {
|
||||
mGroupRecycleBin = database.recycleBin
|
||||
@@ -60,7 +60,7 @@ class DatabaseRecycleBinGroupPreferenceDialogFragmentCompat
|
||||
mGroupRecycleBin = item
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
if (positiveResult) {
|
||||
database?.let {
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.view.View
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
|
||||
class DatabaseRemoveUnlinkedDataPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
|
||||
|
||||
@@ -37,7 +37,7 @@ class DatabaseRemoveUnlinkedDataPreferenceDialogFragmentCompat : DatabaseSavePre
|
||||
}.toString()
|
||||
}
|
||||
|
||||
override fun onDialogClosed(database: Database?, positiveResult: Boolean) {
|
||||
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||
super.onDialogClosed(database, positiveResult)
|
||||
database?.let {
|
||||
if (positiveResult) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user