Distinct block lists for AppId and WebDomain

This commit is contained in:
J-Jamet
2020-06-10 15:40:04 +02:00
parent 2655b1b3d1
commit 59f11a1b26
10 changed files with 151 additions and 50 deletions

View File

@@ -406,7 +406,7 @@ class Database {
fun createVirtualGroupFromSearch(searchInfo: SearchInfo,
max: Int = Integer.MAX_VALUE): Group? {
if (searchInfo.isNull())
if (searchInfo.containsOnlyNullValues())
return null
return mSearchHelper?.createVirtualGroupWithSearchResult(this, searchInfo.toString(), SearchParameters().apply {
searchInTitles = false

View File

@@ -10,8 +10,6 @@ class SearchInfo : ObjectNameResource, Parcelable {
var applicationId: String? = null
var webDomain: String? = null
var genericInfo: String? = null
constructor()
private constructor(parcel: Parcel) {
@@ -19,8 +17,6 @@ class SearchInfo : ObjectNameResource, Parcelable {
applicationId = if (readAppId.isNullOrEmpty()) null else readAppId
val readDomain = parcel.readString()
webDomain = if (readDomain.isNullOrEmpty()) null else readDomain
val readGeneric = parcel.readString()
genericInfo = if (readGeneric.isNullOrEmpty()) null else readGeneric
}
override fun describeContents(): Int {
@@ -30,15 +26,14 @@ class SearchInfo : ObjectNameResource, Parcelable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(applicationId ?: "")
parcel.writeString(webDomain ?: "")
parcel.writeString(genericInfo ?: "")
}
override fun getName(resources: Resources): String {
return applicationId ?: webDomain ?: genericInfo ?: ""
return applicationId ?: webDomain ?: ""
}
fun isNull(): Boolean {
return applicationId == null && webDomain == null && genericInfo == null
fun containsOnlyNullValues(): Boolean {
return applicationId == null && webDomain == null
}
override fun equals(other: Any?): Boolean {
@@ -49,7 +44,6 @@ class SearchInfo : ObjectNameResource, Parcelable {
if (applicationId != other.applicationId) return false
if (webDomain != other.webDomain) return false
if (genericInfo != other.genericInfo) return false
return true
}
@@ -57,12 +51,11 @@ class SearchInfo : ObjectNameResource, Parcelable {
override fun hashCode(): Int {
var result = applicationId?.hashCode() ?: 0
result = 31 * result + (webDomain?.hashCode() ?: 0)
result = 31 * result + (genericInfo?.hashCode() ?: 0)
return result
}
override fun toString(): String {
return applicationId ?: webDomain ?: genericInfo ?: ""
return applicationId ?: webDomain ?: ""
}
companion object {

View File

@@ -24,7 +24,8 @@ import androidx.fragment.app.DialogFragment
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.settings.preferencedialogfragment.AutofillBlocklistPreferenceDialogFragmentCompat
import com.kunzisoft.keepass.settings.preferencedialogfragment.AutofillBlocklistAppIdPreferenceDialogFragmentCompat
import com.kunzisoft.keepass.settings.preferencedialogfragment.AutofillBlocklistWebDomainPreferenceDialogFragmentCompat
class AutofillSettingsFragment : PreferenceFragmentCompat() {
@@ -39,8 +40,11 @@ class AutofillSettingsFragment : PreferenceFragmentCompat() {
var dialogFragment: DialogFragment? = null
when (preference?.key) {
getString(R.string.autofill_blocklist_key) -> {
dialogFragment = AutofillBlocklistPreferenceDialogFragmentCompat.newInstance(preference.key)
getString(R.string.autofill_application_id_blocklist_key) -> {
dialogFragment = AutofillBlocklistAppIdPreferenceDialogFragmentCompat.newInstance(preference.key)
}
getString(R.string.autofill_web_domain_blocklist_key) -> {
dialogFragment = AutofillBlocklistWebDomainPreferenceDialogFragmentCompat.newInstance(preference.key)
}
else -> otherDialogFragment = true
}

View File

@@ -0,0 +1,49 @@
/*
* 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.settings.preferencedialogfragment
import android.os.Bundle
import com.kunzisoft.keepass.model.SearchInfo
class AutofillBlocklistAppIdPreferenceDialogFragmentCompat
: AutofillBlocklistPreferenceDialogFragmentCompat() {
override fun buildSearchInfoFromString(searchInfoString: String): SearchInfo? {
return if (Regex(APPLICATION_ID_REGEX).matches(searchInfoString)) {
SearchInfo().apply { this.applicationId = searchInfoString }
} else {
null
}
}
companion object {
// https://gist.github.com/rishabhmhjn/8663966
private const val APPLICATION_ID_REGEX = "^(?:[a-zA-Z]+(?:\\d*[a-zA-Z_]*)*)(?:\\.[a-zA-Z]+(?:\\d*[a-zA-Z_]*)*)+\$"
fun newInstance(key: String): AutofillBlocklistAppIdPreferenceDialogFragmentCompat {
val fragment = AutofillBlocklistAppIdPreferenceDialogFragmentCompat()
val bundle = Bundle(1)
bundle.putString(ARG_KEY, key)
fragment.arguments = bundle
return fragment
}
}
}

View File

@@ -19,34 +19,37 @@
*/
package com.kunzisoft.keepass.settings.preferencedialogfragment
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.AutofillBlocklistAdapter
import java.util.*
import kotlin.Comparator
import kotlin.collections.HashSet
class AutofillBlocklistPreferenceDialogFragmentCompat
abstract class AutofillBlocklistPreferenceDialogFragmentCompat
: InputPreferenceDialogFragmentCompat(),
AutofillBlocklistAdapter.ItemDeletedCallback<SearchInfo> {
private var persistedItems = HashSet<SearchInfo>()
private var persistedItems = TreeSet<SearchInfo>(
Comparator { o1, o2 -> o1.toString().compareTo(o2.toString()) })
private var filterAdapter: AutofillBlocklistAdapter<SearchInfo>? = null
abstract fun buildSearchInfoFromString(searchInfoString: String): SearchInfo?
override fun onBindDialogView(view: View) {
super.onBindDialogView(view)
preference.getPersistedStringSet(emptySet()).forEach { searchInfoString ->
persistedItems.add(SearchInfo().apply { genericInfo = searchInfoString })
addSearchInfo(searchInfoString)
}
val addItemButton = view.findViewById<View>(R.id.add_item_button)
addItemButton?.setOnClickListener {
persistedItems.add(SearchInfo().apply {
genericInfo = inputText
})
addSearchInfo(inputText)
filterAdapter?.replaceItems(persistedItems.toList())
}
@@ -61,6 +64,12 @@ class AutofillBlocklistPreferenceDialogFragmentCompat
}
}
private fun addSearchInfo(searchInfoString: String) {
val itemToAdd = buildSearchInfoFromString(searchInfoString)
if (itemToAdd != null && !itemToAdd.containsOnlyNullValues())
persistedItems.add(itemToAdd)
}
override fun onItemDeleted(item: SearchInfo) {
persistedItems.remove(item)
filterAdapter?.replaceItems(persistedItems.toList())
@@ -81,16 +90,4 @@ class AutofillBlocklistPreferenceDialogFragmentCompat
preference.persistStringSet(getStringItems())
}
}
companion object {
fun newInstance(key: String): AutofillBlocklistPreferenceDialogFragmentCompat {
val fragment = AutofillBlocklistPreferenceDialogFragmentCompat()
val bundle = Bundle(1)
bundle.putString(ARG_KEY, key)
fragment.arguments = bundle
return fragment
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* 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.settings.preferencedialogfragment
import android.os.Bundle
import com.kunzisoft.keepass.model.SearchInfo
import java.net.URI
class AutofillBlocklistWebDomainPreferenceDialogFragmentCompat
: AutofillBlocklistPreferenceDialogFragmentCompat() {
override fun buildSearchInfoFromString(searchInfoString: String): SearchInfo? {
// remove prefix https://
val newSearchInfo = searchInfoString.replace(Regex("^.*?://"), "")
return if (Regex(WEB_DOMAIN_REGEX).matches(newSearchInfo)) {
SearchInfo().apply { webDomain = newSearchInfo }
} else {
null
}
}
companion object {
private const val WEB_DOMAIN_REGEX = "^(?!://)([a-zA-Z0-9-_]+\\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+\\.[a-zA-Z]{2,11}?\$"
fun newInstance(key: String): AutofillBlocklistWebDomainPreferenceDialogFragmentCompat {
val fragment = AutofillBlocklistWebDomainPreferenceDialogFragmentCompat()
val bundle = Bundle(1)
bundle.putString(ARG_KEY, key)
fragment.arguments = bundle
return fragment
}
}
}

View File

@@ -42,7 +42,7 @@
android:id="@+id/switch_element"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:layout_margin="24dp"
android:text="@string/enable"
android:background="@drawable/background_button_small"
android:textColor="?attr/textColorInverse"
@@ -55,18 +55,16 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="@dimen/default_margin"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginEnd="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
app:layout_constraintTop_toBottomOf="@id/switch_element"
android:orientation="horizontal">
<EditText
android:id="@+id/input_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/add_item_button"
app:layout_constraintBottom_toBottomOf="@id/add_item_button"
@@ -88,10 +86,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/default_margin"
android:paddingStart="@dimen/default_margin"
android:paddingLeft="@dimen/default_margin"
android:paddingEnd="@dimen/default_margin"
android:paddingRight="@dimen/default_margin"
android:paddingStart="24dp"
android:paddingLeft="24dp"
android:paddingEnd="24dp"
android:paddingRight="24dp"
app:layout_constraintTop_toBottomOf="@id/add_item_container"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

View File

@@ -132,7 +132,8 @@
<bool name="keyboard_key_sound_default" translatable="false">false</bool>
<string name="autofill_auto_search_key" translatable="false">autofill_auto_search_key</string>
<bool name="autofill_auto_search_default" translatable="false">true</bool>
<string name="autofill_blocklist_key" translatable="false">autofill_blocklist_key</string>
<string name="autofill_application_id_blocklist_key" translatable="false">autofill_application_id_blocklist_key</string>
<string name="autofill_web_domain_blocklist_key" translatable="false">autofill_web_domain_blocklist_key</string>
<!-- Advanced Unlock Settings -->
<string name="settings_advanced_unlock_key" translatable="false">settings_advanced_unlock_key</string>

View File

@@ -380,8 +380,11 @@
<string name="keyboard_key_vibrate_title">Vibratory keypresses</string>
<string name="keyboard_key_sound_title">Audible keypresses</string>
<string name="autofill_auto_search_title">Auto search</string>
<string name="autofill_auto_search_summary">Automatically suggest search results from the web domain or application Id</string>
<string name="autofill_blocklist_title">Blocklist</string>
<string name="autofill_auto_search_summary">Automatically suggest search results from the web domain or application ID</string>
<string name="autofill_application_id_blocklist_title">Application block list</string>
<string name="autofill_application_id_blocklist_summary">Block list that prevents auto filling of apps</string>
<string name="autofill_web_domain_blocklist_title">Web domain block list</string>
<string name="autofill_web_domain_blocklist_summary">Block list that prevents auto filling of web domains</string>
<string name="allow_no_password_title">Allow no master key</string>
<string name="allow_no_password_summary">Enable the \"Open\" button if no credentials are selected</string>
<string name="delete_entered_password_title">Delete password</string>

View File

@@ -29,7 +29,12 @@
<PreferenceCategory
android:title="@string/filter">
<com.kunzisoft.keepass.settings.preference.InputListPreference
android:key="@string/autofill_blocklist_key"
android:title="@string/autofill_blocklist_title"/>
android:key="@string/autofill_application_id_blocklist_key"
android:title="@string/autofill_application_id_blocklist_title"
android:summary="@string/autofill_application_id_blocklist_summary"/>
<com.kunzisoft.keepass.settings.preference.InputListPreference
android:key="@string/autofill_web_domain_blocklist_key"
android:title="@string/autofill_web_domain_blocklist_title"
android:summary="@string/autofill_web_domain_blocklist_summary"/>
</PreferenceCategory>
</PreferenceScreen>