diff --git a/CHANGELOG b/CHANGELOG index 7618fce57..0e13b6b87 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,9 @@ KeepassDX (2.5.0.0beta19) * Add lock button always visible * Refactor connection workflow * Better Magikeyboard connection + * Kotlinized code + * Fix Recycle Bin + * Fix small bugs KeepassDX (2.5.0.0beta18) * New recent databases views diff --git a/ReadMe.md b/ReadMe.md index 15f6a2417..13f53c6e4 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -63,7 +63,7 @@ Other questions? You can read the [F.A.Q.](https://www.keepassdx.com/FAQ) ## License - Copyright (c) 2017 Jeremy Jamet / [Kunzisoft](https://www.kunzisoft.com). + Copyright (c) 2019 Jeremy Jamet / [Kunzisoft](https://www.kunzisoft.com). This file is part of KeePass DX. diff --git a/app/src/androidTest/java/com/kunzisoft/keepass/tests/PwDateTest.kt b/app/src/androidTest/java/com/kunzisoft/keepass/tests/PwDateTest.kt index 05a2993c7..7cb932d86 100644 --- a/app/src/androidTest/java/com/kunzisoft/keepass/tests/PwDateTest.kt +++ b/app/src/androidTest/java/com/kunzisoft/keepass/tests/PwDateTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft. + * Copyright 2019 Jeremy Jamet / Kunzisoft. * * This file is part of KeePass DX. * diff --git a/app/src/androidTest/java/com/kunzisoft/keepass/tests/TestUtil.java b/app/src/androidTest/java/com/kunzisoft/keepass/tests/TestUtil.java index 1a4ae6e1a..542f69e4b 100644 --- a/app/src/androidTest/java/com/kunzisoft/keepass/tests/TestUtil.java +++ b/app/src/androidTest/java/com/kunzisoft/keepass/tests/TestUtil.java @@ -19,18 +19,13 @@ */ package com.kunzisoft.keepass.tests; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.InputStream; - import android.content.Context; import android.content.res.AssetManager; -import android.net.Uri; import android.os.Environment; -import com.kunzisoft.keepass.utils.EmptyUtils; -import com.kunzisoft.keepass.utils.UriUtil; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; public class TestUtil { private static final File sdcard = Environment.getExternalStorageDirectory(); diff --git a/app/src/androidTest/java/com/kunzisoft/keepass/tests/crypto/AESTest.java b/app/src/androidTest/java/com/kunzisoft/keepass/tests/crypto/AESTest.java index ab91076bc..b439b28a4 100644 --- a/app/src/androidTest/java/com/kunzisoft/keepass/tests/crypto/AESTest.java +++ b/app/src/androidTest/java/com/kunzisoft/keepass/tests/crypto/AESTest.java @@ -68,11 +68,11 @@ public class AESTest extends TestCase { mRand.nextBytes(ivArray); IvParameterSpec iv = new IvParameterSpec(ivArray); - Cipher android = CipherFactory.getInstance("AES/CBC/PKCS5Padding", true); + Cipher android = CipherFactory.INSTANCE.getInstance("AES/CBC/PKCS5Padding", true); android.init(Cipher.ENCRYPT_MODE, key, iv); byte[] outAndroid = android.doFinal(input, 0, dataSize); - Cipher nat = CipherFactory.getInstance("AES/CBC/PKCS5Padding"); + Cipher nat = CipherFactory.INSTANCE.getInstance("AES/CBC/PKCS5Padding"); nat.init(Cipher.ENCRYPT_MODE, key, iv); byte[] outNative = nat.doFinal(input, 0, dataSize); diff --git a/app/src/androidTest/java/com/kunzisoft/keepass/tests/crypto/CipherTest.java b/app/src/androidTest/java/com/kunzisoft/keepass/tests/crypto/CipherTest.java index 2dd634a11..ce2906456 100644 --- a/app/src/androidTest/java/com/kunzisoft/keepass/tests/crypto/CipherTest.java +++ b/app/src/androidTest/java/com/kunzisoft/keepass/tests/crypto/CipherTest.java @@ -56,7 +56,7 @@ public class CipherTest extends TestCase { rand.nextBytes(iv); rand.nextBytes(plaintext); - CipherEngine aes = CipherFactory.getInstance(AesEngine.CIPHER_UUID); + CipherEngine aes = CipherFactory.INSTANCE.getInstance(AesEngine.CIPHER_UUID); Cipher encrypt = aes.getCipher(Cipher.ENCRYPT_MODE, key, iv); Cipher decrypt = aes.getCipher(Cipher.DECRYPT_MODE, key, iv); @@ -78,7 +78,7 @@ public class CipherTest extends TestCase { rand.nextBytes(iv); rand.nextBytes(plaintext); - CipherEngine aes = CipherFactory.getInstance(AesEngine.CIPHER_UUID); + CipherEngine aes = CipherFactory.INSTANCE.getInstance(AesEngine.CIPHER_UUID); Cipher encrypt = aes.getCipher(Cipher.ENCRYPT_MODE, key, iv); Cipher decrypt = aes.getCipher(Cipher.DECRYPT_MODE, key, iv); diff --git a/app/src/androidTest/java/com/kunzisoft/keepass/tests/database/SprEngineTest.java b/app/src/androidTest/java/com/kunzisoft/keepass/tests/database/SprEngineTest.java index 8cf081d38..bfa06f696 100644 --- a/app/src/androidTest/java/com/kunzisoft/keepass/tests/database/SprEngineTest.java +++ b/app/src/androidTest/java/com/kunzisoft/keepass/tests/database/SprEngineTest.java @@ -23,16 +23,10 @@ import android.content.Context; import android.content.res.AssetManager; import android.test.AndroidTestCase; -import com.kunzisoft.keepass.database.element.PwDatabase; import com.kunzisoft.keepass.database.element.PwDatabaseV4; -import com.kunzisoft.keepass.database.element.PwEntryV4; -import com.kunzisoft.keepass.utils.SprEngineV4; -import com.kunzisoft.keepass.utils.Types; +import com.kunzisoft.keepass.database.element.SprEngineV4; import java.io.InputStream; -import java.util.UUID; - -import biz.source_code.base64Coder.Base64Coder; public class SprEngineTest extends AndroidTestCase { private PwDatabaseV4 db; @@ -73,14 +67,4 @@ public class SprEngineTest extends AndroidTestCase { */ } - - private UUID decodeUUID(String encoded) { - if (encoded == null || encoded.length() == 0 ) { - return PwDatabase.UUID_ZERO; - } - - byte[] buf = Base64Coder.decode(encoded); - return Types.bytestoUUID(buf); - } - } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3789cf299..d34879ec2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -142,6 +142,10 @@ + (R.id.toolbar) toolbar.title = getString(R.string.menu_about) setSupportActionBar(toolbar) - assert(supportActionBar != null) - supportActionBar!!.setDisplayHomeAsUpEnabled(true) - supportActionBar!!.setDisplayShowHomeEnabled(true) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setDisplayShowHomeEnabled(true) var version: String var build: String diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt index 786f5c4a5..38177a673 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt @@ -42,6 +42,7 @@ import com.kunzisoft.keepass.view.EntryContentsView import com.kunzisoft.keepass.app.App import com.kunzisoft.keepass.database.element.EntryVersioned import com.kunzisoft.keepass.database.element.PwNodeId +import com.kunzisoft.keepass.icons.assignDatabaseIcon import com.kunzisoft.keepass.notifications.NotificationEntryCopyManager import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.settings.PreferencesUtil.isFirstTimeAskAllowCopyPasswordAndProtectedFields @@ -140,7 +141,7 @@ class EntryActivity : LockingHideActivity() { val database = App.currentDatabase database.startManageEntry(entry) // Assign title icon - database.drawFactory.assignDatabaseIconTo(this, titleIconView, entry.icon, iconColor) + titleIconView?.assignDatabaseIcon(database.drawFactory, entry.icon, iconColor) // Assign title text titleView?.text = entry.getVisualTitle() diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index 0ac2aeaf3..00ddeab4c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -35,7 +35,6 @@ import com.kunzisoft.keepass.activities.dialogs.GeneratePasswordDialogFragment import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment.Companion.KEY_ICON_STANDARD import com.kunzisoft.keepass.activities.lock.LockingHideActivity -import com.kunzisoft.keepass.view.EntryEditCustomField import com.kunzisoft.keepass.app.App import com.kunzisoft.keepass.database.action.ProgressDialogSaveDatabaseThread import com.kunzisoft.keepass.database.action.node.ActionNodeValues @@ -45,11 +44,15 @@ import com.kunzisoft.keepass.database.action.node.UpdateEntryRunnable import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.database.element.security.ProtectedString import com.kunzisoft.keepass.education.EntryEditActivityEducation +import com.kunzisoft.keepass.icons.assignDatabaseIcon +import com.kunzisoft.keepass.icons.assignDefaultDatabaseIcon import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.MenuUtil import com.kunzisoft.keepass.utils.Util +import com.kunzisoft.keepass.utils.applyFontVisibility +import com.kunzisoft.keepass.view.EntryEditCustomField class EntryEditActivity : LockingHideActivity(), IconPickerDialogFragment.IconPickerListener, GeneratePasswordDialogFragment.GeneratePasswordListener { @@ -140,7 +143,9 @@ class EntryEditActivity : LockingHideActivity(), IconPickerDialogFragment.IconPi mEntry = mDatabase?.createEntry() mParent = mDatabase?.getGroupById(it) // Add the default icon - mDatabase?.drawFactory?.assignDefaultDatabaseIconTo(this, entryIconView, iconColor) + mDatabase?.drawFactory?.let { iconFactory -> + entryIconView?.assignDefaultDatabaseIcon(iconFactory, iconColor) + } } // Close the activity if entry or parent can't be retrieve @@ -252,7 +257,7 @@ class EntryEditActivity : LockingHideActivity(), IconPickerDialogFragment.IconPi var actionRunnable: ActionRunnable? = null val afterActionNodeFinishRunnable = object : AfterActionNodeFinishRunnable() { override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) { - if (actionNodeValues.success) + if (actionNodeValues.result.isSuccess) finish() } } @@ -306,7 +311,7 @@ class EntryEditActivity : LockingHideActivity(), IconPickerDialogFragment.IconPi for (i in 0 until it.childCount) { val entryEditCustomField = it.getChildAt(i) as EntryEditCustomField val key = entryEditCustomField.label - if (key == null || key.isEmpty()) { + if (key.isEmpty()) { validationErrorMessageId = R.string.error_string_key return false } @@ -392,12 +397,8 @@ class EntryEditActivity : LockingHideActivity(), IconPickerDialogFragment.IconPi } private fun assignIconView() { - mEntry?.icon?.let { - mDatabase?.drawFactory?.assignDatabaseIconTo( - this, - entryIconView, - it, - iconColor) + if (mDatabase?.drawFactory != null && mEntry?.icon != null) { + entryIconView?.assignDatabaseIcon(mDatabase?.drawFactory!!, mEntry?.icon!!, iconColor) } } @@ -418,10 +419,10 @@ class EntryEditActivity : LockingHideActivity(), IconPickerDialogFragment.IconPi val visibilityFontActivated = PreferencesUtil.fieldFontIsInVisibility(this) if (visibilityFontActivated) { - Util.applyFontVisibilityTo(this, entryUserNameView) - Util.applyFontVisibilityTo(this, entryPasswordView) - Util.applyFontVisibilityTo(this, entryConfirmationPasswordView) - Util.applyFontVisibilityTo(this, entryCommentView) + entryUserNameView?.applyFontVisibility() + entryPasswordView?.applyFontVisibility() + entryConfirmationPasswordView?.applyFontVisibility() + entryCommentView?.applyFontVisibility() } if (entry.allowExtraFields()) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt index 1f7842538..86b0438d0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt @@ -49,6 +49,7 @@ import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper import com.kunzisoft.keepass.activities.helpers.KeyFileHelper import com.kunzisoft.keepass.activities.stylish.StylishActivity import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter +import com.kunzisoft.keepass.app.App import com.kunzisoft.keepass.autofill.AutofillHelper import com.kunzisoft.keepass.database.action.* import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation @@ -59,7 +60,6 @@ import com.kunzisoft.keepass.fileselect.database.FileDatabaseHistory import com.kunzisoft.keepass.magikeyboard.KeyboardHelper import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.ActionRunnable -import com.kunzisoft.keepass.utils.EmptyUtils import com.kunzisoft.keepass.utils.MenuUtil import com.kunzisoft.keepass.utils.UriUtil import net.cachapa.expandablelayout.ExpandableLayout @@ -170,13 +170,13 @@ class FileDatabaseSelectActivity : StylishActivity(), val prefs = PreferenceManager.getDefaultSharedPreferences(this) val fileName = prefs.getString(PasswordActivity.KEY_DEFAULT_FILENAME, "") - if (fileName!!.isNotEmpty()) { - val dbUri = UriUtil.parseDefaultFile(fileName) + if (fileName != null && fileName.isNotEmpty()) { + val dbUri = UriUtil.parseUriFile(fileName) var scheme: String? = null if (dbUri != null) scheme = dbUri.scheme - if (!EmptyUtils.isNullOrEmpty(scheme) && scheme!!.equals("file", ignoreCase = true)) { + if (scheme != null && scheme.isNotEmpty() && scheme.equals("file", ignoreCase = true)) { val path = dbUri!!.path val db = File(path!!) @@ -404,23 +404,21 @@ class FileDatabaseSelectActivity : StylishActivity(), keyFileChecked: Boolean, keyFile: Uri?) { try { - mDatabaseFileUri?.path?.let { databaseFilename -> - // Create the new database and start prof + UriUtil.parseUriFile(mDatabaseFileUri)?.let { databaseUri -> + + // Create the new database ProgressDialogThread(this@FileDatabaseSelectActivity, { - CreateDatabaseRunnable(databaseFilename) { database -> - // TODO store database created - AssignPasswordInDatabaseRunnable( - this@FileDatabaseSelectActivity, - database, + CreateDatabaseRunnable(this@FileDatabaseSelectActivity, + databaseUri, + App.currentDatabase, masterPasswordChecked, masterPassword, keyFileChecked, keyFile, true, // TODO get readonly - LaunchGroupActivityFinish(UriUtil.parseDefaultFile(databaseFilename)) + LaunchGroupActivityFinish(databaseUri) ) - } }, R.string.progress_create) .start() @@ -432,7 +430,6 @@ class FileDatabaseSelectActivity : StylishActivity(), // TODO remove e.printStackTrace() } - } private inner class LaunchGroupActivityFinish internal constructor(private val fileURI: Uri) : ActionRunnable() { @@ -441,9 +438,9 @@ class FileDatabaseSelectActivity : StylishActivity(), finishRun(true, null) } - override fun onFinishRun(isSuccess: Boolean, message: String?) { + override fun onFinishRun(result: Result) { runOnUiThread { - if (isSuccess) { + if (result.isSuccess) { // Add database to recent files mFileDatabaseHistory?.addDatabaseUri(fileURI) mAdapterDatabaseHistory?.notifyDataSetChanged() diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index a97ca3067..25aa50951 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -55,10 +55,10 @@ import com.kunzisoft.keepass.autofill.AutofillHelper import com.kunzisoft.keepass.database.SortNodeEnum import com.kunzisoft.keepass.database.action.AssignPasswordInDatabaseRunnable import com.kunzisoft.keepass.database.action.ProgressDialogSaveDatabaseThread -import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.action.node.* import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.education.GroupActivityEducation +import com.kunzisoft.keepass.icons.assignDatabaseIcon import com.kunzisoft.keepass.magikeyboard.KeyboardEntryNotificationService import com.kunzisoft.keepass.magikeyboard.KeyboardHelper import com.kunzisoft.keepass.magikeyboard.MagikIME @@ -193,16 +193,16 @@ class GroupActivity : LockingActivity(), .commit() // Add listeners to the add buttons - addNodeButtonView?.setAddGroupClickListener { + addNodeButtonView?.setAddGroupClickListener(View.OnClickListener { GroupEditDialogFragment.build() .show(supportFragmentManager, GroupEditDialogFragment.TAG_CREATE_GROUP) - } - addNodeButtonView?.setAddEntryClickListener { + }) + addNodeButtonView?.setAddEntryClickListener(View.OnClickListener { mCurrentGroup?.let { currentGroup -> EntryEditActivity.launch(this@GroupActivity, currentGroup) } - } + }) // Search suggestion mDatabase?.let { database -> @@ -348,7 +348,8 @@ class GroupActivity : LockingActivity(), // Assign the group icon depending of IconPack or custom icon iconView?.visibility = View.VISIBLE mCurrentGroup?.let { - mDatabase?.drawFactory?.assignDatabaseIconTo(this, iconView, it.icon, mIconColor) + if (mDatabase?.drawFactory != null) + iconView?.assignDatabaseIcon(mDatabase?.drawFactory!!, it.icon, mIconColor) if (toolbar != null) { if (mCurrentGroup?.containsParent() == true) @@ -408,7 +409,7 @@ class GroupActivity : LockingActivity(), EntryActivity.launch(this@GroupActivity, entry, readOnly) }, { - MagikIME.setEntryKey(getEntry(entry)) + MagikIME.entryKey = getEntry(entry) // Show the notification if allowed in Preferences if (PreferencesUtil.enableKeyboardNotificationEntry(this@GroupActivity)) { startService(Intent( @@ -442,7 +443,7 @@ class GroupActivity : LockingActivity(), if (entry.containsCustomFields()) { entry.fields .doActionToAllCustomProtectedField { key, value -> - entryModel.addCustomField( + entryModel.customFields.add( Field(key, value.toString())) } } @@ -603,12 +604,6 @@ class GroupActivity : LockingActivity(), mSearchSuggestionAdapter?.reInit(this) } - override fun onStop() { - super.onStop() - // Hide button - addNodeButtonView?.hideButton() - } - override fun onCreateOptionsMenu(menu: Menu): Boolean { val inflater = menuInflater @@ -661,10 +656,10 @@ class GroupActivity : LockingActivity(), // If no node, show education to add new one if (mListNodesFragment != null && mListNodesFragment!!.isEmpty - && addNodeButtonView != null + && addNodeButtonView?.addButtonView != null && addNodeButtonView!!.isEnable && groupActivityEducation.checkAndPerformedAddNodeButtonEducation( - addNodeButtonView!!, + addNodeButtonView?.addButtonView!!, { addNodeButtonView?.openButtonIfClose() }, @@ -829,7 +824,7 @@ class GroupActivity : LockingActivity(), internal inner class AfterAddNodeRunnable : AfterActionNodeFinishRunnable() { override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) { runOnUiThread { - if (actionNodeValues.success) { + if (actionNodeValues.result.isSuccess) { if (actionNodeValues.newNode != null) mListNodesFragment?.addNode(actionNodeValues.newNode) } @@ -840,7 +835,7 @@ class GroupActivity : LockingActivity(), internal inner class AfterUpdateNodeRunnable : AfterActionNodeFinishRunnable() { override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) { runOnUiThread { - if (actionNodeValues.success) { + if (actionNodeValues.result.isSuccess) { if (actionNodeValues.oldNode!= null && actionNodeValues.newNode != null) mListNodesFragment?.updateNode(actionNodeValues.oldNode, actionNodeValues.newNode) } @@ -851,22 +846,20 @@ class GroupActivity : LockingActivity(), internal inner class AfterDeleteNodeRunnable : AfterActionNodeFinishRunnable() { override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) { runOnUiThread { - if (actionNodeValues.success) { - if (actionNodeValues.oldNode != null) - mListNodesFragment?.removeNode(actionNodeValues.oldNode) - + if (actionNodeValues.result.isSuccess) { actionNodeValues.oldNode?.let { oldNode -> - oldNode.parent?.let { parent -> - val database = App.currentDatabase - if (database.isRecycleBinAvailable && database.isRecycleBinEnabled) { - val recycleBin = database.recycleBin - // Add trash if it doesn't exists - if (parent == recycleBin - && mCurrentGroup != null - && mCurrentGroup!!.parent == null - && mCurrentGroup != recycleBin) { - mListNodesFragment?.addNode(parent) - } + + mListNodesFragment?.removeNode(oldNode) + + // TODO Move trash view + // Add trash in views list if it doesn't exists + val database = App.currentDatabase + if (database.isRecycleBinEnabled) { + val recycleBin = database.recycleBin + if (mCurrentGroup != null && recycleBin != null + && mCurrentGroup!!.parent == null + && mCurrentGroup != recycleBin) { + mListNodesFragment?.addNode(recycleBin) } } } @@ -877,7 +870,7 @@ class GroupActivity : LockingActivity(), override fun cancelEditGroup(action: GroupEditDialogFragment.EditGroupDialogAction?, name: String?, - iconId: PwIcon?) { + icon: PwIcon?) { // Do nothing here } @@ -913,11 +906,15 @@ class GroupActivity : LockingActivity(), true) } // Show the progress dialog now or after dialog confirmation - if (database.validatePasswordEncoding(masterPassword!!)) { + if (database.validatePasswordEncoding(masterPassword)) { progressDialogThread.start() } else { - PasswordEncodingDialogHelper() - .show(this, DialogInterface.OnClickListener{ _, _ -> progressDialogThread.start() }) + PasswordEncodingDialogFragment().apply { + positiveButtonClickListener = DialogInterface.OnClickListener { _, _ -> + progressDialogThread.start() + } + show(supportFragmentManager, "passwordEncodingTag") + } } } } @@ -940,7 +937,7 @@ class GroupActivity : LockingActivity(), } // Not directly get the entry from intent data but from database - // Is refresh from onResume() + mListNodesFragment?.rebuildList() } @SuppressLint("RestrictedApi") @@ -976,7 +973,7 @@ class GroupActivity : LockingActivity(), // Else lock if needed else { if (PreferencesUtil.isLockDatabaseWhenBackButtonOnRootClicked(this)) { - App.currentDatabase.closeAndClear(applicationContext) + App.currentDatabase.closeAndClear(applicationContext.filesDir) super.onBackPressed() } else { moveTaskToBack(true) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/ListNodesFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/ListNodesFragment.kt index f1b3ce630..6c9ef2b04 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/ListNodesFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/ListNodesFragment.kt @@ -94,7 +94,7 @@ class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionLis } } - mAdapter = NodeAdapter(getContextThemed(), currentActivity.menuInflater) + mAdapter = NodeAdapter(contextThemed, currentActivity.menuInflater) mAdapter?.apply { setReadOnly(readOnly) setIsASearchResult(isASearchResult) @@ -115,7 +115,7 @@ class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionLis super.onCreateView(inflater, container, savedInstanceState) // To apply theme - val rootView = inflater.cloneInContext(getContextThemed()) + val rootView = inflater.cloneInContext(contextThemed) .inflate(R.layout.list_nodes_fragment, container, false) listView = rootView.findViewById(R.id.nodes_list) notFoundView = rootView.findViewById(R.id.not_found_container) @@ -129,14 +129,14 @@ class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionLis }) } + rebuildList() + return rootView } override fun onResume() { super.onResume() - rebuildList() - if (isASearchResult && mAdapter!= null && mAdapter!!.isEmpty) { // To show the " no search entry found " listView?.visibility = View.GONE @@ -186,26 +186,28 @@ class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionLis when (item?.itemId) { R.id.menu_sort -> { - val sortDialogFragment: SortDialogFragment + context?.let { context -> + val sortDialogFragment: SortDialogFragment - /* - // TODO Recycle bin bottom - if (database.isRecycleBinAvailable() && database.isRecycleBinEnabled()) { - sortDialogFragment = - SortDialogFragment.getInstance( - PrefsUtil.getListSort(this), - PrefsUtil.getAscendingSort(this), - PrefsUtil.getGroupsBeforeSort(this), - PrefsUtil.getRecycleBinBottomSort(this)); - } else { - */ - sortDialogFragment = SortDialogFragment.getInstance( - PreferencesUtil.getListSort(context), - PreferencesUtil.getAscendingSort(context), - PreferencesUtil.getGroupsBeforeSort(context)) - //} + /* + // TODO Recycle bin bottom + if (database.isRecycleBinAvailable() && database.isRecycleBinEnabled()) { + sortDialogFragment = + SortDialogFragment.getInstance( + PrefsUtil.getListSort(this), + PrefsUtil.getAscendingSort(this), + PrefsUtil.getGroupsBeforeSort(this), + PrefsUtil.getRecycleBinBottomSort(this)); + } else { + */ + sortDialogFragment = SortDialogFragment.getInstance( + PreferencesUtil.getListSort(context), + PreferencesUtil.getAscendingSort(context), + PreferencesUtil.getGroupsBeforeSort(context)) + //} - sortDialogFragment.show(childFragmentManager, "sortDialog") + sortDialogFragment.show(childFragmentManager, "sortDialog") + } return true } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index 66175c0f1..c4c959da0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -43,7 +43,7 @@ import android.view.MenuItem import android.view.View import android.widget.* import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogHelper +import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogFragment import com.kunzisoft.keepass.activities.helpers.* import com.kunzisoft.keepass.activities.lock.LockingActivity import com.kunzisoft.keepass.activities.stylish.StylishActivity @@ -59,7 +59,6 @@ import com.kunzisoft.keepass.fingerprint.FingerPrintHelper import com.kunzisoft.keepass.magikeyboard.KeyboardHelper import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.ActionRunnable -import com.kunzisoft.keepass.utils.EmptyUtils import com.kunzisoft.keepass.utils.MenuUtil import com.kunzisoft.keepass.utils.UriUtil import permissions.dispatcher.* @@ -265,8 +264,8 @@ class PasswordActivity : StylishActivity(), // Retrieve settings for default database val defaultFilename = prefs?.getString(KEY_DEFAULT_FILENAME, "") if (mDatabaseFileUri != null - && !EmptyUtils.isNullOrEmpty(mDatabaseFileUri!!.path) - && UriUtil.equalsDefaultfile(mDatabaseFileUri, defaultFilename)) { + && mDatabaseFileUri!!.path != null && mDatabaseFileUri!!.path!!.isNotEmpty() + && mDatabaseFileUri == UriUtil.parseUriFile(defaultFilename)) { checkboxDefaultDatabaseView?.isChecked = true } @@ -526,9 +525,9 @@ class PasswordActivity : StylishActivity(), setFingerPrintView(R.string.encrypted_value_stored) } - override fun handleDecryptedResult(passwordValue: String) { + override fun handleDecryptedResult(value: String) { // Load database directly - verifyKeyFileViewsAndLoadDatabase(passwordValue) + verifyKeyFileViewsAndLoadDatabase(value) } @RequiresApi(api = Build.VERSION_CODES.M) @@ -563,8 +562,8 @@ class PasswordActivity : StylishActivity(), private fun verifyAllViewsAndLoadDatabase() { verifyCheckboxesAndLoadDatabase( - passwordView?.text.toString(), - UriUtil.parseDefaultFile(keyFileView?.text.toString())) + passwordView?.text?.toString(), + UriUtil.parseUriFile(keyFileView?.text?.toString())) } private fun verifyCheckboxesAndLoadDatabase(password: String?, keyFile: Uri?) { @@ -580,8 +579,8 @@ class PasswordActivity : StylishActivity(), } private fun verifyKeyFileViewsAndLoadDatabase(password: String) { - val key = keyFileView?.text.toString() - var keyUri = UriUtil.parseDefaultFile(key) + val key = keyFileView?.text?.toString() + var keyUri = UriUtil.parseUriFile(key) if (checkboxKeyFileView?.isChecked != true) { keyUri = null } @@ -591,20 +590,20 @@ class PasswordActivity : StylishActivity(), private fun loadDatabase(password: String?, keyFile: Uri?) { // Clear before we load val database = App.currentDatabase - database.closeAndClear(applicationContext) + database.closeAndClear(applicationContext.filesDir) mDatabaseFileUri?.let { databaseUri -> // Show the progress dialog and load the database ProgressDialogThread(this, { progressTaskUpdater -> LoadDatabaseRunnable( - WeakReference(this@PasswordActivity.applicationContext), + WeakReference(this@PasswordActivity), database, databaseUri, password, keyFile, progressTaskUpdater, - AfterLoadingDatabase(database)) + AfterLoadingDatabase(database, password)) }, R.string.loading_database).start() } @@ -613,9 +612,11 @@ class PasswordActivity : StylishActivity(), /** * Called after verify and try to opening the database */ - private inner class AfterLoadingDatabase internal constructor(var database: Database) : ActionRunnable() { + private inner class AfterLoadingDatabase internal constructor(var database: Database, + val password: String?) + : ActionRunnable() { - override fun onFinishRun(isSuccess: Boolean, message: String?) { + override fun onFinishRun(result: Result) { runOnUiThread { // Recheck fingerprint if error if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -623,15 +624,20 @@ class PasswordActivity : StylishActivity(), reInitWithFingerprintMode() } - if (database.isPasswordEncodingError) { - val dialog = PasswordEncodingDialogHelper() - dialog.show(this@PasswordActivity, - DialogInterface.OnClickListener { _, _ -> launchGroupActivity() }) - } else if (isSuccess) { - launchGroupActivity() + if (result.isSuccess) { + if (database.validatePasswordEncoding(password)) { + launchGroupActivity() + } else { + PasswordEncodingDialogFragment().apply { + positiveButtonClickListener = DialogInterface.OnClickListener { _, _ -> + launchGroupActivity() + } + show(supportFragmentManager, "passwordEncodingTag") + } + } } else { - if (message != null && message.isNotEmpty()) { - Toast.makeText(this@PasswordActivity, message, Toast.LENGTH_LONG).show() + if (result.message != null && result.message!!.isNotEmpty()) { + Toast.makeText(this@PasswordActivity, result.message, Toast.LENGTH_LONG).show() } } } @@ -762,7 +768,7 @@ class PasswordActivity : StylishActivity(), when (resultCode) { LockingActivity.RESULT_EXIT_LOCK, Activity.RESULT_CANCELED -> { setEmptyViews() - App.currentDatabase.closeAndClear(applicationContext) + App.currentDatabase.closeAndClear(applicationContext.filesDir) } } } @@ -814,14 +820,13 @@ class PasswordActivity : StylishActivity(), @Throws(FileNotFoundException::class) private fun verifyFileNameUriFromLaunch(fileName: String) { - if (EmptyUtils.isNullOrEmpty(fileName)) { + if (fileName.isEmpty()) { throw FileNotFoundException() } - val uri = UriUtil.parseDefaultFile(fileName) - val scheme = uri.scheme - - if (!EmptyUtils.isNullOrEmpty(scheme) && scheme.equals("file", ignoreCase = true)) { + val uri = UriUtil.parseUriFile(fileName) + val scheme = uri?.scheme + if (scheme != null && scheme.isNotEmpty() && scheme.equals("file", ignoreCase = true)) { val dbFile = File(uri.path!!) if (!dbFile.exists()) { throw FileNotFoundException() diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/AssignMasterKeyDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/AssignMasterKeyDialogFragment.kt index 0edf563f9..47f5df68d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/AssignMasterKeyDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/AssignMasterKeyDialogFragment.kt @@ -35,7 +35,6 @@ import android.widget.TextView import android.widget.Toast import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.helpers.KeyFileHelper -import com.kunzisoft.keepass.utils.EmptyUtils import com.kunzisoft.keepass.utils.UriUtil class AssignMasterKeyDialogFragment : DialogFragment() { @@ -178,13 +177,12 @@ class AssignMasterKeyDialogFragment : DialogFragment() { private fun verifyFile(): Boolean { var error = false if (keyFileCheckBox != null - && keyFileCheckBox!!.isChecked - && keyFileView != null) { - val keyFile = UriUtil.parseDefaultFile(keyFileView!!.text.toString()) + && keyFileCheckBox!!.isChecked) { + val keyFile = UriUtil.parseUriFile(keyFileView?.text?.toString()) mKeyFile = keyFile // Verify that a keyfile is set - if (EmptyUtils.isNullOrEmpty(keyFile)) { + if (keyFile == null || keyFile.toString().isEmpty()) { error = true Toast.makeText(context, R.string.error_nokeyfile, Toast.LENGTH_LONG).show() } @@ -229,11 +227,10 @@ class AssignMasterKeyDialogFragment : DialogFragment() { mKeyFileHelper?.onActivityResultCallback(requestCode, resultCode, data ) { uri -> - uri?.let { currentUri -> - UriUtil.parseDefaultFile(currentUri.toString())?.let { pathString -> - keyFileCheckBox?.isChecked = true - keyFileView?.text = pathString.toString() - } + UriUtil.parseUriFile(uri)?.let { pathUri -> + keyFileCheckBox?.isChecked = true + keyFileView?.text = pathUri.toString() + } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/BrowserDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/BrowserDialogFragment.kt index 9441f6dff..00a403e80 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/BrowserDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/BrowserDialogFragment.kt @@ -39,13 +39,13 @@ class BrowserDialogFragment : DialogFragment() { val market = root.findViewById