mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Distinct block lists for AppId and WebDomain
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user