mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix search
This commit is contained in:
@@ -37,6 +37,7 @@ import com.kunzisoft.keepass.database.save.PwDbV3Output
|
||||
import com.kunzisoft.keepass.database.save.PwDbV4Output
|
||||
import com.kunzisoft.keepass.database.search.SearchDbHelper
|
||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.stream.LEDataInputStream
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.EmptyUtils
|
||||
@@ -297,7 +298,7 @@ class Database {
|
||||
|
||||
try {
|
||||
isPasswordEncodingError = !(pwDatabaseV3?.validatePasswordEncoding(password) ?: pwDatabaseV4?.validatePasswordEncoding(password) ?: true)
|
||||
searchHelper = SearchDbHelper(ctx)
|
||||
searchHelper = SearchDbHelper(PreferencesUtil.omitBackup(ctx))
|
||||
loaded = true
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Load can't be performed with this Database version", e)
|
||||
@@ -313,40 +314,30 @@ class Database {
|
||||
|
||||
@JvmOverloads
|
||||
fun search(str: String, max: Int = Integer.MAX_VALUE): GroupVersioned? {
|
||||
return if (searchHelper == null) null else searchHelper?.search(this, str, max)
|
||||
return searchHelper?.search(this, str, max)
|
||||
}
|
||||
|
||||
fun searchEntry(query: String): Cursor? {
|
||||
if (pwDatabaseV3 != null) {
|
||||
val cursorV3 = EntryCursorV3()
|
||||
if (query.isNotEmpty()) {
|
||||
val searchResult = search(query, 6)
|
||||
if (searchResult != null) {
|
||||
for (entry in searchResult.getChildEntries()) {
|
||||
if (!entry.isMetaStream) { // TODO metastream
|
||||
cursorV3.addEntry(entry.pwEntryV3)
|
||||
}
|
||||
}
|
||||
|
||||
var cursorV3: EntryCursorV3? = null
|
||||
var cursorV4: EntryCursorV4? = null
|
||||
|
||||
if (pwDatabaseV3 != null)
|
||||
cursorV3 = EntryCursorV3()
|
||||
if (pwDatabaseV4 != null)
|
||||
cursorV4 = EntryCursorV4()
|
||||
|
||||
val searchResult = search(query, SearchDbHelper.MAX_SEARCH_ENTRY)
|
||||
if (searchResult != null) {
|
||||
for (entry in searchResult.getChildEntries()) {
|
||||
if (!entry.isMetaStream) { // TODO metastream
|
||||
cursorV3?.addEntry(entry.pwEntryV3)
|
||||
cursorV4?.addEntry(entry.pwEntryV4)
|
||||
}
|
||||
}
|
||||
return cursorV3
|
||||
}
|
||||
|
||||
if (pwDatabaseV4 != null) {
|
||||
val cursorV4 = EntryCursorV4()
|
||||
if (query.isNotEmpty()) {
|
||||
val searchResult = search(query, 6)
|
||||
if (searchResult != null) {
|
||||
for (entry in searchResult.getChildEntries()) {
|
||||
if (!entry.isMetaStream) { // TODO metastream
|
||||
cursorV4.addEntry(entry.pwEntryV4)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cursorV4
|
||||
}
|
||||
return null
|
||||
return cursorV3 ?: cursorV4
|
||||
}
|
||||
|
||||
fun getEntryFrom(cursor: Cursor): EntryVersioned? {
|
||||
|
||||
@@ -114,7 +114,7 @@ class GroupVersioned : NodeVersioned, PwGroupInterface<GroupVersioned, EntryVers
|
||||
return pwGroupV3?.isContainedIn(container.pwGroupV3) ?: pwGroupV4?.isContainedIn(container.pwGroupV4) ?: false
|
||||
}
|
||||
|
||||
override val isSearchingEnabled: Boolean?
|
||||
override val isSearchingEnabled: Boolean
|
||||
get() = pwGroupV3?.isSearchingEnabled ?: pwGroupV4?.isSearchingEnabled ?: false
|
||||
|
||||
override fun getLastModificationTime(): PwDate? {
|
||||
|
||||
@@ -311,7 +311,7 @@ public class PwEntryV3 extends PwEntry<PwGroupV3, PwEntryV3> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isSearchingEnabled() {
|
||||
public boolean isSearchingEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ public class PwEntryV4 extends PwEntry<PwGroupV4, PwEntryV4> implements ITimeLog
|
||||
parentGroupLastMod = parcel.readParcelable(PwDate.class.getClassLoader());
|
||||
customData = MemUtil.readStringParcelableMap(parcel);
|
||||
fields = parcel.readParcelable(ExtraFields.class.getClassLoader());
|
||||
binaries = MemUtil.readStringParcelableMap(parcel, ProtectedBinary.class);
|
||||
// TODO binaries = MemUtil.readStringParcelableMap(parcel, ProtectedBinary.class);
|
||||
foregroundColor = parcel.readString();
|
||||
backgroupColor = parcel.readString();
|
||||
overrideURL = parcel.readString();
|
||||
@@ -313,7 +313,7 @@ public class PwEntryV4 extends PwEntry<PwGroupV4, PwEntryV4> implements ITimeLog
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIcon(PwIcon icon) {
|
||||
public void setIcon(@NonNull PwIcon icon) {
|
||||
if (icon instanceof PwIconStandard)
|
||||
setIconStandard((PwIconStandard) icon);
|
||||
if (icon instanceof PwIconCustom)
|
||||
@@ -508,12 +508,13 @@ public class PwEntryV4 extends PwEntry<PwGroupV4, PwEntryV4> implements ITimeLog
|
||||
public void touchLocation() {
|
||||
parentGroupLastMod = new PwDate();
|
||||
}
|
||||
|
||||
public Boolean isSearchingEnabled() {
|
||||
|
||||
@Override
|
||||
public boolean isSearchingEnabled() {
|
||||
if (getParent() != null) {
|
||||
return getParent().isSearchingEnabled();
|
||||
}
|
||||
return PwGroupV4.DEFAULT_SEARCHING_ENABLED;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,10 +27,12 @@ interface PwGroupInterface<Group: PwGroupInterface<Group, Entry>, Entry> : PwNod
|
||||
fun doForEachChild(entryHandler: NodeHandler<Entry>,
|
||||
groupHandler: NodeHandler<Group>?): Boolean {
|
||||
for (entry in this.getChildEntries()) {
|
||||
if (!entryHandler.operate(entry)) return false
|
||||
if (!entryHandler.operate(entry))
|
||||
return false
|
||||
}
|
||||
for (group in this.getChildGroups()) {
|
||||
if (groupHandler != null && !groupHandler.operate(group)) return false
|
||||
if (groupHandler != null && !groupHandler.operate(group))
|
||||
return false
|
||||
group.doForEachChild(entryHandler, groupHandler)
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -101,7 +101,7 @@ public class PwGroupV3 extends PwGroup<Integer, PwGroupV3, PwEntryV3> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isSearchingEnabled() {
|
||||
public boolean isSearchingEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ import java.util.UUID;
|
||||
|
||||
public class PwGroupV4 extends PwGroup<UUID, PwGroupV4, PwEntryV4> implements ITimeLogger {
|
||||
|
||||
public static final boolean DEFAULT_SEARCHING_ENABLED = true;
|
||||
|
||||
private PwIconCustom customIcon = PwIconCustom.ZERO;
|
||||
private long usageCount = 0;
|
||||
private PwDate locationChangeDate = new PwDate();
|
||||
@@ -277,20 +275,13 @@ public class PwGroupV4 extends PwGroup<UUID, PwGroupV4, PwEntryV4> implements IT
|
||||
this.lastTopVisibleEntry = lastTopVisibleEntry;
|
||||
}
|
||||
|
||||
public Boolean isSearchingEnabled() {
|
||||
|
||||
GroupVersioned group = new GroupVersioned(this);
|
||||
while (group != null) {
|
||||
Boolean search = group.isSearchingEnabled();
|
||||
if (search != null) {
|
||||
return search;
|
||||
}
|
||||
group = group.getParent();
|
||||
}
|
||||
|
||||
// If we get to the root tree and its null, default to true
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isSearchingEnabled() {
|
||||
if (getParent() != null) {
|
||||
return getParent().isSearchingEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowAddEntryIfIsRoot() {
|
||||
|
||||
@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.database.element;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
/**
|
||||
@@ -119,12 +120,13 @@ public abstract class PwNode
|
||||
/**
|
||||
* @return Visual icon
|
||||
*/
|
||||
@NonNull
|
||||
public PwIcon getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIcon(PwIcon icon) {
|
||||
public void setIcon(@NonNull PwIcon icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ interface PwNodeInterface<ParentGroup> : SmallTimeInterface, Parcelable {
|
||||
*/
|
||||
var parent: ParentGroup?
|
||||
|
||||
val isSearchingEnabled: Boolean?
|
||||
val isSearchingEnabled: Boolean
|
||||
|
||||
fun containsParent(): Boolean
|
||||
|
||||
|
||||
@@ -67,15 +67,13 @@ public class EntrySearchHandlerV4 extends NodeHandler<PwEntryV4> {
|
||||
PwGroupV4 parent = entry.getParent();
|
||||
if (parent != null) {
|
||||
String groupName = parent.getTitle();
|
||||
if (groupName != null) {
|
||||
if (sp.ignoreCase) {
|
||||
groupName = groupName.toLowerCase();
|
||||
}
|
||||
if (sp.ignoreCase) {
|
||||
groupName = groupName.toLowerCase();
|
||||
}
|
||||
|
||||
if (groupName.contains(term)) {
|
||||
listStorage.add(entry);
|
||||
return true;
|
||||
}
|
||||
if (groupName.contains(term)) {
|
||||
listStorage.add(entry);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,7 +99,7 @@ public class EntrySearchHandlerV4 extends NodeHandler<PwEntryV4> {
|
||||
EntrySearchStringIterator iter = new EntrySearchStringIteratorV4(entry, sp);
|
||||
while (iter.hasNext()) {
|
||||
String str = iter.next();
|
||||
if (str != null && str.length() > 0) {
|
||||
if (str.length() > 0) {
|
||||
if (sp.ignoreCase) {
|
||||
str = str.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft.
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
@@ -19,9 +19,6 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.search
|
||||
|
||||
import android.content.Context
|
||||
import android.preference.PreferenceManager
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.NodeHandler
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.EntryVersioned
|
||||
@@ -29,42 +26,44 @@ import com.kunzisoft.keepass.database.element.GroupVersioned
|
||||
import com.kunzisoft.keepass.database.iterator.EntrySearchStringIterator
|
||||
import java.util.*
|
||||
|
||||
class SearchDbHelper(private val mContext: Context) {
|
||||
private var incrementEntry = 0
|
||||
class SearchDbHelper(private val isOmitBackup: Boolean) {
|
||||
|
||||
private fun omitBackup(): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(mContext)
|
||||
return prefs.getBoolean(mContext.getString(R.string.omitbackup_key), mContext.resources.getBoolean(R.bool.omitbackup_default))
|
||||
companion object {
|
||||
const val MAX_SEARCH_ENTRY = 6
|
||||
}
|
||||
|
||||
fun search(pm: Database, qStr: String, max: Int): GroupVersioned {
|
||||
private var incrementEntry = 0
|
||||
|
||||
val searchGroup = pm.createGroup()
|
||||
searchGroup!!.title = "\"" + qStr + "\""
|
||||
fun search(database: Database, qStr: String, max: Int): GroupVersioned? {
|
||||
|
||||
val searchGroup = database.createGroup()
|
||||
searchGroup?.title = "\"" + qStr + "\""
|
||||
|
||||
// Search all entries
|
||||
val loc = Locale.getDefault()
|
||||
val finalQStr = qStr.toLowerCase(loc)
|
||||
val isOmitBackup = omitBackup()
|
||||
|
||||
|
||||
incrementEntry = 0
|
||||
pm.rootGroup?.doForEachChild(
|
||||
database.rootGroup?.doForEachChild(
|
||||
object : NodeHandler<EntryVersioned>() {
|
||||
override fun operate(entry: EntryVersioned): Boolean {
|
||||
if (incrementEntry >= max)
|
||||
return false
|
||||
if (entryContainsString(entry, finalQStr, loc)) {
|
||||
searchGroup.addChildEntry(entry)
|
||||
searchGroup?.addChildEntry(entry)
|
||||
incrementEntry++
|
||||
}
|
||||
// Stop searching when we have max entries
|
||||
return incrementEntry <= max
|
||||
return incrementEntry < max
|
||||
}
|
||||
},
|
||||
object : NodeHandler<GroupVersioned>() {
|
||||
override fun operate(group: GroupVersioned): Boolean {
|
||||
return if (pm.isGroupSearchable(group, isOmitBackup)!!) {
|
||||
true
|
||||
} else incrementEntry <= max
|
||||
return when {
|
||||
incrementEntry >= max -> false
|
||||
database.isGroupSearchable(group, isOmitBackup) -> true
|
||||
else -> incrementEntry < max
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -54,6 +54,12 @@ public class PreferencesUtil {
|
||||
sharedPreferencesEditor.apply();
|
||||
}
|
||||
|
||||
public static boolean omitBackup(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
return prefs.getBoolean(context.getString(R.string.omitbackup_key),
|
||||
context.getResources().getBoolean(R.bool.omitbackup_default));
|
||||
}
|
||||
|
||||
public static boolean showUsernamesListEntries(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
return prefs.getBoolean(context.getString(R.string.list_entries_show_username_key),
|
||||
|
||||
Reference in New Issue
Block a user