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,7 +37,8 @@ import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import java.util.*
|
||||
|
||||
class SearchEntryCursorAdapter(context: Context, private val database: Database) : CursorAdapter(context, null, FLAG_REGISTER_CONTENT_OBSERVER) {
|
||||
class SearchEntryCursorAdapter(context: Context, private val database: Database)
|
||||
: CursorAdapter(context, null, FLAG_REGISTER_CONTENT_OBSERVER) {
|
||||
|
||||
private val cursorInflater: LayoutInflater = context.getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
@@ -109,7 +110,7 @@ class SearchEntryCursorAdapter(context: Context, private val database: Database)
|
||||
}
|
||||
|
||||
override fun runQueryOnBackgroundThread(constraint: CharSequence): Cursor? {
|
||||
return database.searchEntry(constraint.toString())
|
||||
return database.searchEntries(constraint.toString())
|
||||
}
|
||||
|
||||
fun getEntryFromPosition(position: Int): EntryVersioned? {
|
||||
|
||||
@@ -321,7 +321,7 @@ class Database {
|
||||
return searchHelper?.search(this, str, max)
|
||||
}
|
||||
|
||||
fun searchEntry(query: String): Cursor? {
|
||||
fun searchEntries(query: String): Cursor? {
|
||||
|
||||
var cursorV3: EntryCursorV3? = null
|
||||
var cursorV4: EntryCursorV4? = null
|
||||
|
||||
@@ -166,7 +166,7 @@ class PwEntryV4 : PwEntry<PwGroupV4, PwEntryV4>, NodeV4Interface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a reference key woth the SprEngineV4
|
||||
* Decode a reference key with the SprEngineV4
|
||||
* @param decodeRef
|
||||
* @param key
|
||||
* @return
|
||||
@@ -174,7 +174,7 @@ class PwEntryV4 : PwEntry<PwGroupV4, PwEntryV4>, NodeV4Interface {
|
||||
private fun decodeRefKey(decodeRef: Boolean, key: String): String {
|
||||
val text = fields.getProtectedStringValue(key)
|
||||
return if (decodeRef) {
|
||||
if (mDatabase == null) text else SprEngineV4().compile(text, this, mDatabase)
|
||||
if (mDatabase == null) text else SprEngineV4().compile(text, this, mDatabase!!)
|
||||
} else text
|
||||
}
|
||||
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX 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.
|
||||
*
|
||||
* KeePass DX 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 KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.element;
|
||||
|
||||
import com.kunzisoft.keepass.database.search.EntrySearchHandlerV4;
|
||||
import com.kunzisoft.keepass.database.search.SearchParametersV4;
|
||||
import com.kunzisoft.keepass.utils.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class SprEngineV4 {
|
||||
private static final int MAX_RECURSION_DEPTH = 12;
|
||||
private static final String STR_REF_START = "{REF:";
|
||||
private static final String STR_REF_END = "}";
|
||||
|
||||
public class TargetResult {
|
||||
public PwEntryV4 entry;
|
||||
public char wanted;
|
||||
|
||||
public TargetResult(PwEntryV4 entry, char wanted) {
|
||||
this.entry = entry;
|
||||
this.wanted = wanted;
|
||||
}
|
||||
}
|
||||
|
||||
private class SprContextV4 {
|
||||
|
||||
public PwDatabaseV4 db;
|
||||
public PwEntryV4 entry;
|
||||
public Map<String, String> refsCache = new HashMap<>();
|
||||
|
||||
SprContextV4(PwDatabaseV4 db, PwEntryV4 entry) {
|
||||
this.db = db;
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
SprContextV4(SprContextV4 source) {
|
||||
this.db = source.db;
|
||||
this.entry = source.entry;
|
||||
this.refsCache = source.refsCache;
|
||||
}
|
||||
}
|
||||
|
||||
public String compile(String text, PwEntryV4 entry, PwDatabase database) {
|
||||
SprContextV4 ctx = new SprContextV4((PwDatabaseV4)database, entry);
|
||||
|
||||
return compileInternal(text, ctx, 0);
|
||||
}
|
||||
|
||||
private String compileInternal(String text, SprContextV4 sprContextV4, int recursionLevel) {
|
||||
if (text == null) { return ""; }
|
||||
if (sprContextV4 == null) { return ""; }
|
||||
if (recursionLevel >= MAX_RECURSION_DEPTH) { return ""; }
|
||||
|
||||
return fillRefPlaceholders(text, sprContextV4, recursionLevel);
|
||||
}
|
||||
|
||||
private String fillRefPlaceholders(String text, SprContextV4 contextV4, int recursionLevel) {
|
||||
|
||||
if (contextV4.db == null) { return text; }
|
||||
|
||||
int offset = 0;
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
text = fillRefsUsingCache(text, contextV4);
|
||||
|
||||
int start = StringUtil.INSTANCE.indexOfIgnoreCase(text, STR_REF_START, offset, Locale.ENGLISH);
|
||||
if (start < 0) { break; }
|
||||
int end = StringUtil.INSTANCE.indexOfIgnoreCase(text, STR_REF_END, start + 1, Locale.ENGLISH);
|
||||
if (end <= start) { break; }
|
||||
|
||||
String fullRef = text.substring(start, end - start + 1);
|
||||
TargetResult result = findRefTarget(fullRef, contextV4);
|
||||
|
||||
if (result != null) {
|
||||
PwEntryV4 found = result.entry;
|
||||
char wanted = result.wanted;
|
||||
|
||||
if (found != null) {
|
||||
String data;
|
||||
switch (wanted) {
|
||||
case 'T':
|
||||
data = found.getTitle();
|
||||
break;
|
||||
case 'U':
|
||||
data = found.getUsername();
|
||||
break;
|
||||
case 'A':
|
||||
data = found.getUrl();
|
||||
break;
|
||||
case 'P':
|
||||
data = found.getPassword();
|
||||
break;
|
||||
case 'N':
|
||||
data = found.getNotes();
|
||||
break;
|
||||
case 'I':
|
||||
data = found.getNodeId().toString();
|
||||
break;
|
||||
default:
|
||||
offset = start + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
SprContextV4 subCtx = new SprContextV4(contextV4);
|
||||
subCtx.entry = found;
|
||||
|
||||
String innerContent = compileInternal(data, subCtx, recursionLevel + 1);
|
||||
addRefsToCache(fullRef, innerContent, contextV4);
|
||||
text = fillRefsUsingCache(text, contextV4);
|
||||
} else {
|
||||
offset = start + 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private TargetResult findRefTarget(String fullRef, SprContextV4 contextV4) {
|
||||
if (fullRef == null) { return null; }
|
||||
|
||||
fullRef = fullRef.toUpperCase(Locale.ENGLISH);
|
||||
if (!fullRef.startsWith(STR_REF_START) || !fullRef.endsWith(STR_REF_END)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String ref = fullRef.substring(STR_REF_START.length(), fullRef.length() - STR_REF_START.length() - STR_REF_END.length());
|
||||
if (ref.length() <= 4) { return null; }
|
||||
if (ref.charAt(1) != '@') { return null; }
|
||||
if (ref.charAt(3) != ':') { return null; }
|
||||
|
||||
char scan = Character.toUpperCase(ref.charAt(2));
|
||||
char wanted = Character.toUpperCase(ref.charAt(0));
|
||||
|
||||
SearchParametersV4 searchParametersV4 = new SearchParametersV4();
|
||||
searchParametersV4.setupNone();
|
||||
|
||||
searchParametersV4.setSearchString(ref.substring(4));
|
||||
if (scan == 'T') { searchParametersV4.setSearchInTitles(true); }
|
||||
else if (scan == 'U') { searchParametersV4.setSearchInUserNames(true); }
|
||||
else if (scan == 'A') { searchParametersV4.setSearchInUrls(true); }
|
||||
else if (scan == 'P') { searchParametersV4.setSearchInPasswords(true); }
|
||||
else if (scan == 'N') { searchParametersV4.setSearchInNotes(true); }
|
||||
else if (scan == 'I') { searchParametersV4.setSearchInUUIDs(true); }
|
||||
else if (scan == 'O') { searchParametersV4.setSearchInOther(true); }
|
||||
else { return null; }
|
||||
|
||||
List<PwEntryV4> list = new ArrayList<>();
|
||||
// TODO type parameter
|
||||
searchEntries(contextV4.db.getRootGroup(), searchParametersV4, list);
|
||||
|
||||
if (list.size() > 0) {
|
||||
return new TargetResult(list.get(0), wanted);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addRefsToCache(String ref, String value, SprContextV4 ctx) {
|
||||
if (ref == null) { return; }
|
||||
if (value == null) { return; }
|
||||
if (ctx == null) { return; }
|
||||
|
||||
if (!ctx.refsCache.containsKey(ref)) {
|
||||
ctx.refsCache.put(ref, value);
|
||||
}
|
||||
}
|
||||
|
||||
private String fillRefsUsingCache(String text, SprContextV4 sprContextV4) {
|
||||
for (Entry<String, String> entry : sprContextV4.refsCache.entrySet()) {
|
||||
text = StringUtil.INSTANCE.replaceAllIgnoresCase(text, entry.getKey(), entry.getValue(), Locale.ENGLISH);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private void searchEntries(PwGroupV4 root, SearchParametersV4 searchParametersV4, List<PwEntryV4> listStorage) {
|
||||
if (searchParametersV4 == null) { return; }
|
||||
if (listStorage == null) { return; }
|
||||
|
||||
List<String> terms = StringUtil.INSTANCE.splitStringTerms(searchParametersV4.getSearchString());
|
||||
if (terms.size() <= 1 || searchParametersV4.getRegularExpression()) {
|
||||
root.doForEachChild(new EntrySearchHandlerV4(searchParametersV4, listStorage), null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Search longest term first
|
||||
Comparator<String> stringLengthComparator = (lhs, rhs) -> lhs.length() - rhs.length();
|
||||
Collections.sort(terms, stringLengthComparator);
|
||||
|
||||
String fullSearch = searchParametersV4.getSearchString();
|
||||
List<PwEntryV4> childEntries = root.getChildEntries();
|
||||
for (int i = 0; i < terms.size(); i ++) {
|
||||
List<PwEntryV4> pgNew = new ArrayList<>();
|
||||
|
||||
searchParametersV4.setSearchString(terms.get(i));
|
||||
|
||||
boolean negate = false;
|
||||
if (searchParametersV4.getSearchString().startsWith("-")) {
|
||||
searchParametersV4.setSearchString(searchParametersV4.getSearchString().substring(1));
|
||||
negate = searchParametersV4.getSearchString().length() > 0;
|
||||
}
|
||||
|
||||
if (!root.doForEachChild(new EntrySearchHandlerV4(searchParametersV4, pgNew), null)) {
|
||||
childEntries = null;
|
||||
break;
|
||||
}
|
||||
|
||||
List<PwEntryV4> complement = new ArrayList<>();
|
||||
if (negate) {
|
||||
for (PwEntryV4 entry: childEntries) {
|
||||
if (!pgNew.contains(entry)) {
|
||||
complement.add(entry);
|
||||
}
|
||||
}
|
||||
childEntries = complement;
|
||||
}
|
||||
else {
|
||||
childEntries = pgNew;
|
||||
}
|
||||
}
|
||||
|
||||
if (childEntries != null) {
|
||||
listStorage.addAll(childEntries);
|
||||
}
|
||||
searchParametersV4.setSearchString(fullSearch);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX 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.
|
||||
*
|
||||
* KeePass DX 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 KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.element
|
||||
|
||||
import com.kunzisoft.keepass.database.search.EntrySearchHandlerV4
|
||||
import com.kunzisoft.keepass.database.search.SearchParametersV4
|
||||
import com.kunzisoft.keepass.utils.StringUtil
|
||||
import java.util.*
|
||||
|
||||
class SprEngineV4 {
|
||||
|
||||
inner class TargetResult(var entry: PwEntryV4?, var wanted: Char)
|
||||
|
||||
private inner class SprContextV4 {
|
||||
|
||||
var databaseV4: PwDatabaseV4? = null
|
||||
var entry: PwEntryV4
|
||||
var refsCache: MutableMap<String, String> = HashMap()
|
||||
|
||||
internal constructor(db: PwDatabaseV4, entry: PwEntryV4) {
|
||||
this.databaseV4 = db
|
||||
this.entry = entry
|
||||
}
|
||||
|
||||
internal constructor(source: SprContextV4) {
|
||||
this.databaseV4 = source.databaseV4
|
||||
this.entry = source.entry
|
||||
this.refsCache = source.refsCache
|
||||
}
|
||||
}
|
||||
|
||||
fun compile(text: String, entry: PwEntryV4, database: PwDatabaseV4): String {
|
||||
return compileInternal(text, SprContextV4(database, entry), 0)
|
||||
}
|
||||
|
||||
private fun compileInternal(text: String?, sprContextV4: SprContextV4?, recursionLevel: Int): String {
|
||||
if (text == null) {
|
||||
return ""
|
||||
}
|
||||
if (sprContextV4 == null) {
|
||||
return ""
|
||||
}
|
||||
return if (recursionLevel >= MAX_RECURSION_DEPTH) {
|
||||
""
|
||||
} else fillRefPlaceholders(text, sprContextV4, recursionLevel)
|
||||
|
||||
}
|
||||
|
||||
private fun fillRefPlaceholders(text: String, contextV4: SprContextV4, recursionLevel: Int): String {
|
||||
var text = text
|
||||
|
||||
if (contextV4.databaseV4 == null) {
|
||||
return text
|
||||
}
|
||||
|
||||
var offset = 0
|
||||
for (i in 0..19) {
|
||||
text = fillRefsUsingCache(text, contextV4)
|
||||
|
||||
val start = StringUtil.indexOfIgnoreCase(text!!, STR_REF_START, offset, Locale.ENGLISH)
|
||||
if (start < 0) {
|
||||
break
|
||||
}
|
||||
val end = StringUtil.indexOfIgnoreCase(text, STR_REF_END, start + 1, Locale.ENGLISH)
|
||||
if (end <= start) {
|
||||
break
|
||||
}
|
||||
|
||||
val fullRef = text.substring(start, end - start + 1)
|
||||
val result = findRefTarget(fullRef, contextV4)
|
||||
|
||||
if (result != null) {
|
||||
val found = result.entry
|
||||
val wanted = result.wanted
|
||||
|
||||
var data: String? = null
|
||||
when (wanted) {
|
||||
'T' -> data = found?.title
|
||||
'U' -> data = found?.username
|
||||
'A' -> data = found?.url
|
||||
'P' -> data = found?.password
|
||||
'N' -> data = found?.notes
|
||||
'I' -> data = found?.nodeId.toString()
|
||||
}
|
||||
|
||||
if (data != null && found != null) {
|
||||
val subCtx = SprContextV4(contextV4)
|
||||
subCtx.entry = found
|
||||
|
||||
val innerContent = compileInternal(data, subCtx, recursionLevel + 1)
|
||||
addRefsToCache(fullRef, innerContent, contextV4)
|
||||
text = fillRefsUsingCache(text, contextV4)
|
||||
} else {
|
||||
offset = start + 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
private fun findRefTarget(fullRef: String?, contextV4: SprContextV4): TargetResult? {
|
||||
var fullRef: String? = fullRef ?: return null
|
||||
|
||||
fullRef = fullRef!!.toUpperCase(Locale.ENGLISH)
|
||||
if (!fullRef.startsWith(STR_REF_START) || !fullRef.endsWith(STR_REF_END)) {
|
||||
return null
|
||||
}
|
||||
|
||||
val ref = fullRef.substring(STR_REF_START.length, fullRef.length - STR_REF_START.length - STR_REF_END.length)
|
||||
if (ref.length <= 4) {
|
||||
return null
|
||||
}
|
||||
if (ref[1] != '@') {
|
||||
return null
|
||||
}
|
||||
if (ref[3] != ':') {
|
||||
return null
|
||||
}
|
||||
|
||||
val scan = Character.toUpperCase(ref[2])
|
||||
val wanted = Character.toUpperCase(ref[0])
|
||||
|
||||
val searchParametersV4 = SearchParametersV4()
|
||||
searchParametersV4.setupNone()
|
||||
|
||||
searchParametersV4.searchString = ref.substring(4)
|
||||
if (scan == 'T') {
|
||||
searchParametersV4.searchInTitles = true
|
||||
} else if (scan == 'U') {
|
||||
searchParametersV4.searchInUserNames = true
|
||||
} else if (scan == 'A') {
|
||||
searchParametersV4.searchInUrls = true
|
||||
} else if (scan == 'P') {
|
||||
searchParametersV4.searchInPasswords = true
|
||||
} else if (scan == 'N') {
|
||||
searchParametersV4.searchInNotes = true
|
||||
} else if (scan == 'I') {
|
||||
searchParametersV4.searchInUUIDs = true
|
||||
} else if (scan == 'O') {
|
||||
searchParametersV4.searchInOther = true
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
|
||||
val list = ArrayList<PwEntryV4>()
|
||||
// TODO type parameter
|
||||
searchEntries(contextV4.databaseV4!!.rootGroup, searchParametersV4, list)
|
||||
|
||||
return if (list.size > 0) {
|
||||
TargetResult(list[0], wanted)
|
||||
} else null
|
||||
|
||||
}
|
||||
|
||||
private fun addRefsToCache(ref: String?, value: String?, ctx: SprContextV4?) {
|
||||
if (ref == null) {
|
||||
return
|
||||
}
|
||||
if (value == null) {
|
||||
return
|
||||
}
|
||||
if (ctx == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!ctx.refsCache.containsKey(ref)) {
|
||||
ctx.refsCache[ref] = value
|
||||
}
|
||||
}
|
||||
|
||||
private fun fillRefsUsingCache(text: String, sprContextV4: SprContextV4): String {
|
||||
var newText = text
|
||||
for ((key, value) in sprContextV4.refsCache) {
|
||||
newText = StringUtil.replaceAllIgnoresCase(text, key, value, Locale.ENGLISH)
|
||||
}
|
||||
return newText
|
||||
}
|
||||
|
||||
private fun searchEntries(root: PwGroupV4?, searchParametersV4: SearchParametersV4?, listStorage: MutableList<PwEntryV4>?) {
|
||||
if (searchParametersV4 == null) {
|
||||
return
|
||||
}
|
||||
if (listStorage == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val terms = StringUtil.splitStringTerms(searchParametersV4.searchString)
|
||||
if (terms.size <= 1 || searchParametersV4.regularExpression) {
|
||||
root!!.doForEachChild(EntrySearchHandlerV4(searchParametersV4, listStorage), null)
|
||||
return
|
||||
}
|
||||
|
||||
// Search longest term first
|
||||
val stringLengthComparator = Comparator<String> { lhs, rhs -> lhs.length - rhs.length }
|
||||
Collections.sort(terms, stringLengthComparator)
|
||||
|
||||
val fullSearch = searchParametersV4.searchString
|
||||
var childEntries: List<PwEntryV4>? = root!!.getChildEntries()
|
||||
for (i in terms.indices) {
|
||||
val pgNew = ArrayList<PwEntryV4>()
|
||||
|
||||
searchParametersV4.searchString = terms[i]
|
||||
|
||||
var negate = false
|
||||
if (searchParametersV4.searchString.startsWith("-")) {
|
||||
searchParametersV4.searchString = searchParametersV4.searchString.substring(1)
|
||||
negate = searchParametersV4.searchString.length > 0
|
||||
}
|
||||
|
||||
if (!root.doForEachChild(EntrySearchHandlerV4(searchParametersV4, pgNew), null)) {
|
||||
childEntries = null
|
||||
break
|
||||
}
|
||||
|
||||
val complement = ArrayList<PwEntryV4>()
|
||||
if (negate) {
|
||||
for (entry in childEntries!!) {
|
||||
if (!pgNew.contains(entry)) {
|
||||
complement.add(entry)
|
||||
}
|
||||
}
|
||||
childEntries = complement
|
||||
} else {
|
||||
childEntries = pgNew
|
||||
}
|
||||
}
|
||||
|
||||
if (childEntries != null) {
|
||||
listStorage.addAll(childEntries)
|
||||
}
|
||||
searchParametersV4.searchString = fullSearch
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MAX_RECURSION_DEPTH = 12
|
||||
private const val STR_REF_START = "{REF:"
|
||||
private const val STR_REF_END = "}"
|
||||
}
|
||||
}
|
||||
@@ -72,9 +72,13 @@ class SearchDbHelper(private val isOmitBackup: Boolean) {
|
||||
return searchGroup
|
||||
}
|
||||
|
||||
private fun entryContainsString(entry: EntryVersioned, qStr: String, loc: Locale): Boolean {
|
||||
// Search all strings in the entry
|
||||
private fun entryContainsString(entry: EntryVersioned, searchString: String, locale: Locale): Boolean {
|
||||
|
||||
// Entry don't contains string if the search string is empty
|
||||
if (searchString.isEmpty())
|
||||
return false
|
||||
|
||||
// Search all strings in the entry
|
||||
var iterator: EntrySearchStringIterator? = null
|
||||
entry.pwEntryV3?.let {
|
||||
iterator = EntrySearchStringIteratorV3(it)
|
||||
@@ -87,8 +91,7 @@ class SearchDbHelper(private val isOmitBackup: Boolean) {
|
||||
while (it.hasNext()) {
|
||||
val str = it.next()
|
||||
if (str.isNotEmpty()) {
|
||||
val lower = str.toLowerCase(loc)
|
||||
if (lower.contains(qStr)) {
|
||||
if (str.toLowerCase(locale).contains(searchString)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class EntrySearchStringIteratorV4 : EntrySearchStringIterator {
|
||||
|
||||
private var mCurrent: String? = null
|
||||
private var mSetIterator: Iterator<Entry<String, ProtectedString>>? = null
|
||||
private var mSearchParametersV4: SearchParametersV4? = null
|
||||
private var mSearchParametersV4: SearchParametersV4
|
||||
|
||||
constructor(entry: PwEntryV4) {
|
||||
this.mSearchParametersV4 = SearchParametersV4()
|
||||
@@ -52,9 +52,9 @@ class EntrySearchStringIteratorV4 : EntrySearchStringIterator {
|
||||
throw NoSuchElementException("Past the end of the list.")
|
||||
}
|
||||
|
||||
val next = mCurrent
|
||||
val next:String = mCurrent!!
|
||||
advance()
|
||||
return next!!
|
||||
return next
|
||||
}
|
||||
|
||||
private fun advance() {
|
||||
@@ -75,12 +75,12 @@ class EntrySearchStringIteratorV4 : EntrySearchStringIterator {
|
||||
|
||||
private fun searchInField(key: String): Boolean {
|
||||
return when (key) {
|
||||
PwEntryV4.STR_TITLE -> mSearchParametersV4!!.searchInTitles
|
||||
PwEntryV4.STR_USERNAME -> mSearchParametersV4!!.searchInUserNames
|
||||
PwEntryV4.STR_PASSWORD -> mSearchParametersV4!!.searchInPasswords
|
||||
PwEntryV4.STR_URL -> mSearchParametersV4!!.searchInUrls
|
||||
PwEntryV4.STR_NOTES -> mSearchParametersV4!!.searchInNotes
|
||||
else -> mSearchParametersV4!!.searchInOther
|
||||
PwEntryV4.STR_TITLE -> mSearchParametersV4.searchInTitles
|
||||
PwEntryV4.STR_USERNAME -> mSearchParametersV4.searchInUserNames
|
||||
PwEntryV4.STR_PASSWORD -> mSearchParametersV4.searchInPasswords
|
||||
PwEntryV4.STR_URL -> mSearchParametersV4.searchInUrls
|
||||
PwEntryV4.STR_NOTES -> mSearchParametersV4.searchInNotes
|
||||
else -> mSearchParametersV4.searchInOther
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,14 +69,10 @@ object StringUtil {
|
||||
return indexOfIgnoreCase(text, search, 0, locale)
|
||||
}
|
||||
|
||||
fun replaceAllIgnoresCase(text: String?, find: String?, newText: String?, locale: Locale): String? {
|
||||
fun replaceAllIgnoresCase(text: String, find: String, newText: String, locale: Locale): String {
|
||||
var currentText = text
|
||||
if (currentText == null || find == null || newText == null) {
|
||||
return currentText
|
||||
}
|
||||
|
||||
var pos = 0
|
||||
while (pos < currentText!!.length) {
|
||||
while (pos < currentText.length) {
|
||||
pos = indexOfIgnoreCase(currentText, find, pos, locale)
|
||||
if (pos < 0) {
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user