mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix incomplete attachment deletion #684
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
KeePassDX(2.9)
|
||||
*
|
||||
KeePassDX(2.8.4)
|
||||
* Fix incomplete attachment deletion #684
|
||||
|
||||
KeePassDX(2.8.3)
|
||||
* Upload attachments
|
||||
|
||||
@@ -45,7 +45,6 @@ import com.kunzisoft.keepass.database.element.*
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
import com.kunzisoft.keepass.education.EntryEditActivityEducation
|
||||
import com.kunzisoft.keepass.model.*
|
||||
import com.kunzisoft.keepass.notifications.AttachmentFileNotificationService
|
||||
@@ -65,6 +64,7 @@ import com.kunzisoft.keepass.view.showActionError
|
||||
import com.kunzisoft.keepass.view.updateLockPaddingLeft
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class EntryEditActivity : LockingActivity(),
|
||||
IconPickerDialogFragment.IconPickerListener,
|
||||
@@ -99,6 +99,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
private var mSelectFileHelper: SelectFileHelper? = null
|
||||
private var mAttachmentFileBinderManager: AttachmentFileBinderManager? = null
|
||||
private var mAllowMultipleAttachments: Boolean = false
|
||||
private var mTempAttachments = ArrayList<Attachment>()
|
||||
|
||||
// Education
|
||||
private var entryEditActivityEducation: EntryEditActivityEducation? = null
|
||||
@@ -206,6 +207,10 @@ class EntryEditActivity : LockingActivity(),
|
||||
mFocusedEditExtraField = savedInstanceState.getParcelable(EXTRA_FIELD_FOCUSED_ENTRY)
|
||||
}
|
||||
|
||||
if (savedInstanceState?.containsKey(TEMP_ATTACHMENTS) == true) {
|
||||
mTempAttachments = savedInstanceState.getParcelableArrayList(TEMP_ATTACHMENTS) ?: mTempAttachments
|
||||
}
|
||||
|
||||
// Close the activity if entry or parent can't be retrieve
|
||||
if (mNewEntry == null || mParent == null) {
|
||||
finish()
|
||||
@@ -317,6 +322,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
scrollView?.smoothScrollTo(0, it.toInt())
|
||||
}
|
||||
}
|
||||
mTempAttachments.add(entryAttachmentState.attachment)
|
||||
}
|
||||
AttachmentState.IN_PROGRESS -> {
|
||||
entryEditContentsView?.putAttachment(entryAttachmentState)
|
||||
@@ -536,6 +542,15 @@ class EntryEditActivity : LockingActivity(),
|
||||
|
||||
populateEntryWithViews(newEntry)
|
||||
|
||||
// Delete temp attachment if not used
|
||||
mTempAttachments.forEach {
|
||||
mDatabase?.binaryPool?.let { binaryPool ->
|
||||
if (!newEntry.getAttachments(binaryPool).contains(it)) {
|
||||
mDatabase?.removeAttachmentIfNotUsed(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Open a progress dialog and save entry
|
||||
if (mIsNew) {
|
||||
mParent?.let { parent ->
|
||||
@@ -705,6 +720,8 @@ class EntryEditActivity : LockingActivity(),
|
||||
outState.putParcelable(EXTRA_FIELD_FOCUSED_ENTRY, it)
|
||||
}
|
||||
|
||||
outState.putParcelableArrayList(TEMP_ATTACHMENTS, mTempAttachments)
|
||||
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
@@ -763,6 +780,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
// SaveInstanceState
|
||||
const val KEY_NEW_ENTRY = "new_entry"
|
||||
const val EXTRA_FIELD_FOCUSED_ENTRY = "EXTRA_FIELD_FOCUSED_ENTRY"
|
||||
const val TEMP_ATTACHMENTS = "TEMP_ATTACHMENTS"
|
||||
|
||||
// Keys for callback
|
||||
const val ADD_ENTRY_RESULT_CODE = 31
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2020 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.activities.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.kunzisoft.keepass.R
|
||||
|
||||
/**
|
||||
* Custom Dialog to confirm big file to upload
|
||||
*/
|
||||
class RemoveUnlinkedAttachmentsDialogFragment : DialogFragment() {
|
||||
|
||||
private var mActionChooseListener: ActionChooseListener? = null
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
// Verify that the host activity implements the callback interface
|
||||
try {
|
||||
mActionChooseListener = context as ActionChooseListener
|
||||
} catch (e: ClassCastException) {
|
||||
throw ClassCastException(context.toString()
|
||||
+ " must implement " + ActionChooseListener::class.java.name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
activity?.let { activity ->
|
||||
// Use the Builder class for convenient dialog construction
|
||||
val builder = AlertDialog.Builder(activity)
|
||||
builder.setMessage(SpannableStringBuilder().apply {
|
||||
append(getString(R.string.warning_remove_unlinked_attachment))
|
||||
append("\n\n")
|
||||
append(getString(R.string.warning_sure_remove_data))
|
||||
})
|
||||
builder.setPositiveButton(android.R.string.yes) { _, _ ->
|
||||
mActionChooseListener?.onValidateRemoveUnlinkedAttachments()
|
||||
}
|
||||
builder.setNegativeButton(android.R.string.no) { _, _ ->
|
||||
dismiss()
|
||||
}
|
||||
// Create the AlertDialog object and return it
|
||||
return builder.create()
|
||||
}
|
||||
return super.onCreateDialog(savedInstanceState)
|
||||
}
|
||||
|
||||
interface ActionChooseListener {
|
||||
fun onValidateRemoveUnlinkedAttachments()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun build(): RemoveUnlinkedAttachmentsDialogFragment {
|
||||
val fragment = RemoveUnlinkedAttachmentsDialogFragment()
|
||||
fragment.arguments = Bundle().apply {}
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -598,6 +598,8 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
binariesToRemove.forEach {
|
||||
try {
|
||||
binaryPool.remove(it)
|
||||
// bug with big attachment, not needed to be delete here
|
||||
// it.clear()
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Unable to clean binaries", e)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import androidx.preference.SwitchPreference
|
||||
import com.kunzisoft.androidclearchroma.ChromaUtil
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.RemoveUnlinkedAttachmentsDialogFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
@@ -135,7 +136,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
|
||||
findPreference<Preference>(getString(R.string.database_version_key))
|
||||
?.summary = mDatabase.version
|
||||
|
||||
val dbCompressionPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_compression_key))
|
||||
val dbCompressionPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_data_key))
|
||||
|
||||
// Database compression
|
||||
dbDataCompressionPref = findPreference(getString(R.string.database_data_compression_key))
|
||||
@@ -149,6 +150,12 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
|
||||
val dbRecycleBinPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_recycle_bin_key))
|
||||
recycleBinGroupPref = findPreference(getString(R.string.recycle_bin_group_key))
|
||||
|
||||
val removeUnlinkedAttachments: Preference? = findPreference(getString(R.string.database_data_remove_unlinked_attachments_key))
|
||||
removeUnlinkedAttachments?.setOnPreferenceClickListener {
|
||||
RemoveUnlinkedAttachmentsDialogFragment.build().show(parentFragmentManager, "remove_unlinked_dialog")
|
||||
true
|
||||
}
|
||||
|
||||
// Recycle bin
|
||||
if (mDatabase.allowConfigurableRecycleBin) {
|
||||
val recycleBinEnablePref: SwitchPreference? = findPreference(getString(R.string.recycle_bin_enable_key))
|
||||
|
||||
@@ -33,6 +33,7 @@ import androidx.fragment.app.Fragment
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogFragment
|
||||
import com.kunzisoft.keepass.activities.dialogs.RemoveUnlinkedAttachmentsDialogFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
import com.kunzisoft.keepass.activities.lock.LockingActivity
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
@@ -42,7 +43,8 @@ import com.kunzisoft.keepass.view.showActionError
|
||||
open class SettingsActivity
|
||||
: LockingActivity(),
|
||||
MainPreferenceFragment.Callback,
|
||||
AssignMasterKeyDialogFragment.AssignPasswordDialogListener {
|
||||
AssignMasterKeyDialogFragment.AssignPasswordDialogListener,
|
||||
RemoveUnlinkedAttachmentsDialogFragment.ActionChooseListener {
|
||||
|
||||
private var backupManager: BackupManager? = null
|
||||
|
||||
@@ -164,7 +166,10 @@ open class SettingsActivity
|
||||
override fun onAssignKeyDialogNegativeClick(masterPasswordChecked: Boolean,
|
||||
masterPassword: String?,
|
||||
keyFileChecked: Boolean,
|
||||
keyFile: Uri?) {
|
||||
keyFile: Uri?) {}
|
||||
|
||||
override fun onValidateRemoveUnlinkedAttachments() {
|
||||
Database.getInstance().removeUnlinkedAttachments()
|
||||
}
|
||||
|
||||
private fun hideOrShowLockButton(key: NestedSettingsFragment.Screen) {
|
||||
|
||||
@@ -178,8 +178,9 @@
|
||||
<string name="database_custom_color_key" translatable="false">database_custom_color_key</string>
|
||||
<string name="database_version_key" translatable="false">database_version_key</string>
|
||||
|
||||
<string name="database_category_compression_key" translatable="false">database_category_compression_key</string>
|
||||
<string name="database_category_data_key" translatable="false">database_category_data_key</string>
|
||||
<string name="database_data_compression_key" translatable="false">database_data_compression_key</string>
|
||||
<string name="database_data_remove_unlinked_attachments_key" translatable="false">database_data_remove_unlinked_attachments_key</string>
|
||||
|
||||
<string name="database_category_recycle_bin_key" translatable="false">database_category_recycle_bin_key</string>
|
||||
<string name="recycle_bin_enable_key" translatable="false">recycle_bin_enable_key</string>
|
||||
|
||||
@@ -260,6 +260,8 @@
|
||||
<string name="warning_file_too_big">A KeePass database is supposed to contain only small utility files (such as PGP key files).\n\nYour database may get very large and reduce performance with this upload.</string>
|
||||
<string name="warning_replace_file">Uploading this file will replace the existing one.</string>
|
||||
<string name="warning_sure_add_file">Add the file anyway?</string>
|
||||
<string name="warning_remove_unlinked_attachment">Removing unlinked data may decrease the size of your database but may also delete data used for KeePass plugins.</string>
|
||||
<string name="warning_sure_remove_data">Remove this data anyway?</string>
|
||||
<string name="version_label">Version %1$s</string>
|
||||
<string name="build_label">Build %1$s</string>
|
||||
<string name="configure_biometric">Biometric prompt is supported, but not set up.</string>
|
||||
@@ -318,8 +320,11 @@
|
||||
<string name="file_name">Filename</string>
|
||||
<string name="path">Path</string>
|
||||
<string name="assign_master_key">Assign a master key</string>
|
||||
<string name="data">Data</string>
|
||||
<string name="database_data_compression_title">Data compression</string>
|
||||
<string name="database_data_compression_summary">Data compression reduces the size of the database.</string>
|
||||
<string name="database_data_compression_summary">Data compression reduces the size of the database</string>
|
||||
<string name="database_data_remove_unlinked_attachments_title">Remove unlinked attachments</string>
|
||||
<string name="database_data_remove_unlinked_attachments_summary">Removes attachments contained in the database but not linked to an entry</string>
|
||||
<string name="recycle_bin_title">Recycle bin usage</string>
|
||||
<string name="recycle_bin_summary">Moves groups and entries to \"Recycle bin\" group before deleting</string>
|
||||
<string name="recycle_bin_group_title">Recycle bin group</string>
|
||||
|
||||
@@ -59,14 +59,19 @@
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/database_category_compression_key"
|
||||
android:title="@string/compression">
|
||||
android:key="@string/database_category_data_key"
|
||||
android:title="@string/data">
|
||||
|
||||
<com.kunzisoft.keepass.settings.preference.DialogListExplanationPreference
|
||||
android:key="@string/database_data_compression_key"
|
||||
android:persistent="false"
|
||||
android:title="@string/database_data_compression_title"/>
|
||||
|
||||
<Preference
|
||||
android:key="@string/database_data_remove_unlinked_attachments_key"
|
||||
android:persistent="false"
|
||||
android:title="@string/database_data_remove_unlinked_attachments_title"
|
||||
android:summary="@string/database_data_remove_unlinked_attachments_summary"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
||||
@@ -1 +1 @@
|
||||
*
|
||||
* Fix incomplete attachment deletion #684
|
||||
|
||||
@@ -1 +1 @@
|
||||
*
|
||||
* Correction de la suppression incomplète des fichiers joints #684
|
||||
|
||||
Reference in New Issue
Block a user