Skip to content

Commit a90ecc5

Browse files
committed
Merge branch 'develop' into codokie-rtl
2 parents 47896fc + 2faa0ac commit a90ecc5

File tree

180 files changed

+3281
-1036
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

180 files changed

+3281
-1036
lines changed

CHANGELOG

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
KeePassDX(4.1.2)
2+
* Fix URL search #1940 #1946 #2003 #2044
3+
* Fix Autofill popup #2054
4+
* Fix Dialog background #2005 #2004 (Thx @codokie)
5+
* Fix OTP code alignment in the main screen #2007 (Thx @ymcx)
6+
* App Metadata to translation #1823
7+
18
KeePassDX(4.1.1)
29
* Fix date parser #1933
310
* Fix domain search #1820 #1936

app/build.gradle

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ android {
1111
applicationId "com.kunzisoft.keepass"
1212
minSdkVersion 15
1313
targetSdkVersion 34
14-
versionCode = 133
15-
versionName = "4.1.1"
14+
versionCode = 134
15+
versionName = "4.1.2"
1616
multiDexEnabled true
1717

1818
testApplicationId = "com.kunzisoft.keepass.tests"
@@ -91,12 +91,15 @@ android {
9191
}
9292

9393
compileOptions {
94-
targetCompatibility JavaVersion.VERSION_1_8
95-
sourceCompatibility JavaVersion.VERSION_1_8
94+
targetCompatibility JavaVersion.VERSION_17
95+
sourceCompatibility JavaVersion.VERSION_17
9696
}
9797

9898
kotlinOptions {
99-
jvmTarget = "1.8"
99+
jvmTarget = "17"
100+
}
101+
buildFeatures {
102+
buildConfig true
100103
}
101104
}
102105

@@ -143,5 +146,4 @@ dependencies {
143146

144147
// Tests
145148
androidTestImplementation "androidx.test:runner:$android_test_version"
146-
androidTestImplementation "androidx.test:rules:$android_test_version"
147149
}

app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,9 @@ import com.kunzisoft.keepass.database.ContextualDatabase
4141
import com.kunzisoft.keepass.database.helper.SearchHelper
4242
import com.kunzisoft.keepass.model.RegisterInfo
4343
import com.kunzisoft.keepass.model.SearchInfo
44-
import com.kunzisoft.keepass.settings.PreferencesUtil
44+
import com.kunzisoft.keepass.utils.WebDomain
4545
import com.kunzisoft.keepass.utils.getParcelableCompat
4646
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
47-
import com.kunzisoft.keepass.utils.WebDomain
48-
import java.lang.RuntimeException
4947

5048
@RequiresApi(api = Build.VERSION_CODES.O)
5149
class AutofillLauncherActivity : DatabaseModeActivity() {
@@ -126,10 +124,11 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
126124
if (autofillComponent == null) {
127125
setResult(Activity.RESULT_CANCELED)
128126
finish()
129-
} else if (!KeeAutofillService.autofillAllowedFor(searchInfo.applicationId,
130-
PreferencesUtil.applicationIdBlocklist(this))
131-
|| !KeeAutofillService.autofillAllowedFor(searchInfo.webDomain,
132-
PreferencesUtil.webDomainBlocklist(this))) {
127+
} else if (!KeeAutofillService.autofillAllowedFor(
128+
applicationId = searchInfo.applicationId,
129+
webDomain = searchInfo.webDomain,
130+
context = this
131+
)) {
133132
showBlockRestartMessage()
134133
setResult(Activity.RESULT_CANCELED)
135134
finish()
@@ -166,10 +165,11 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
166165
private fun launchRegistration(database: ContextualDatabase?,
167166
searchInfo: SearchInfo,
168167
registerInfo: RegisterInfo?) {
169-
if (!KeeAutofillService.autofillAllowedFor(searchInfo.applicationId,
170-
PreferencesUtil.applicationIdBlocklist(this))
171-
|| !KeeAutofillService.autofillAllowedFor(searchInfo.webDomain,
172-
PreferencesUtil.webDomainBlocklist(this))) {
168+
if (KeeAutofillService.autofillAllowedFor(
169+
applicationId = searchInfo.applicationId,
170+
webDomain = searchInfo.webDomain,
171+
context = this
172+
)) {
173173
showBlockRestartMessage()
174174
setResult(Activity.RESULT_CANCELED)
175175
} else {

app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,7 @@ class GroupEditDialogFragment : DatabaseDialogFragment() {
248248

249249
private fun retrieveGroupInfoFromViews() {
250250
mGroupInfo.title = nameTextView.text.toString()
251-
// Only if there
252-
val newNotes = notesTextView.text.toString()
253-
if (newNotes.isNotEmpty()) {
254-
mGroupInfo.notes = newNotes
255-
}
251+
mGroupInfo.notes = notesTextView.text?.toString()
256252
mGroupInfo.expires = expirationView.activation
257253
mGroupInfo.expiryTime = expirationView.dateTime
258254
mGroupInfo.searchable = searchableView.getValue()

app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,21 @@ package com.kunzisoft.keepass.autofill
2121

2222
import android.annotation.SuppressLint
2323
import android.app.PendingIntent
24+
import android.content.Context
2425
import android.content.Intent
2526
import android.graphics.BlendMode
2627
import android.graphics.drawable.Icon
2728
import android.os.Build
2829
import android.os.CancellationSignal
29-
import android.service.autofill.*
30+
import android.service.autofill.AutofillService
31+
import android.service.autofill.FillCallback
32+
import android.service.autofill.FillRequest
33+
import android.service.autofill.FillResponse
34+
import android.service.autofill.InlinePresentation
35+
import android.service.autofill.Presentations
36+
import android.service.autofill.SaveCallback
37+
import android.service.autofill.SaveInfo
38+
import android.service.autofill.SaveRequest
3039
import android.util.Log
3140
import android.view.autofill.AutofillId
3241
import android.widget.RemoteViews
@@ -35,6 +44,7 @@ import androidx.autofill.inline.UiVersions
3544
import androidx.autofill.inline.v1.InlineSuggestionUi
3645
import com.kunzisoft.keepass.R
3746
import com.kunzisoft.keepass.activities.AutofillLauncherActivity
47+
import com.kunzisoft.keepass.autofill.StructureParser.Companion.APPLICATION_ID_POPUP_WINDOW
3848
import com.kunzisoft.keepass.database.ContextualDatabase
3949
import com.kunzisoft.keepass.database.DatabaseTaskProvider
4050
import com.kunzisoft.keepass.database.helper.SearchHelper
@@ -99,8 +109,12 @@ class KeeAutofillService : AutofillService() {
99109
StructureParser(latestStructure).parse()?.let { parseResult ->
100110

101111
// Build search info only if applicationId or webDomain are not blocked
102-
if (autofillAllowedFor(parseResult.applicationId, applicationIdBlocklist)
103-
&& autofillAllowedFor(parseResult.webDomain, webDomainBlocklist)) {
112+
if (autofillAllowedFor(
113+
applicationId = parseResult.applicationId,
114+
applicationIdBlocklist = applicationIdBlocklist,
115+
webDomain = parseResult.webDomain,
116+
webDomainBlocklist = webDomainBlocklist)
117+
) {
104118
val searchInfo = SearchInfo().apply {
105119
applicationId = parseResult.applicationId
106120
webDomain = parseResult.webDomain
@@ -258,7 +272,7 @@ class KeeAutofillService : AutofillService() {
258272
val inlinePresentationSpecs =
259273
inlineSuggestionsRequest.inlinePresentationSpecs
260274
if (inlineSuggestionsRequest.maxSuggestionCount > 0
261-
&& inlinePresentationSpecs.size > 0
275+
&& inlinePresentationSpecs.isNotEmpty()
262276
) {
263277
val inlinePresentationSpec = inlinePresentationSpecs[0]
264278

@@ -274,11 +288,7 @@ class KeeAutofillService : AutofillService() {
274288
this,
275289
0,
276290
Intent(this, AutofillSettingsActivity::class.java),
277-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
278-
PendingIntent.FLAG_IMMUTABLE
279-
} else {
280-
0
281-
}
291+
PendingIntent.FLAG_IMMUTABLE
282292
)
283293
).apply {
284294
setContentDescription(getString(R.string.autofill_sign_in_prompt))
@@ -352,8 +362,12 @@ class KeeAutofillService : AutofillService() {
352362
val latestStructure = request.fillContexts.last().structure
353363
StructureParser(latestStructure).parse(true)?.let { parseResult ->
354364

355-
if (autofillAllowedFor(parseResult.applicationId, applicationIdBlocklist)
356-
&& autofillAllowedFor(parseResult.webDomain, webDomainBlocklist)) {
365+
if (autofillAllowedFor(
366+
applicationId = parseResult.applicationId,
367+
applicationIdBlocklist = applicationIdBlocklist,
368+
webDomain = parseResult.webDomain,
369+
webDomainBlocklist = webDomainBlocklist)
370+
) {
357371
Log.d(TAG, "autofill onSaveRequest password")
358372

359373
// Build expiration from date or from year and month
@@ -414,6 +428,28 @@ class KeeAutofillService : AutofillService() {
414428
companion object {
415429
private val TAG = KeeAutofillService::class.java.name
416430

431+
fun autofillAllowedFor(applicationId: String?,
432+
webDomain: String?,
433+
context: Context
434+
): Boolean {
435+
return autofillAllowedFor(
436+
applicationId = applicationId,
437+
applicationIdBlocklist = PreferencesUtil.applicationIdBlocklist(context),
438+
webDomain = webDomain,
439+
webDomainBlocklist = PreferencesUtil.webDomainBlocklist(context))
440+
}
441+
442+
fun autofillAllowedFor(applicationId: String?,
443+
applicationIdBlocklist: Set<String>?,
444+
webDomain: String?,
445+
webDomainBlocklist: Set<String>?
446+
): Boolean {
447+
return autofillAllowedFor(applicationId, applicationIdBlocklist)
448+
// To prevent unrecognized autofill popup id
449+
&& applicationId?.contains(APPLICATION_ID_POPUP_WINDOW) != true
450+
&& autofillAllowedFor(webDomain, webDomainBlocklist)
451+
}
452+
417453
fun autofillAllowedFor(element: String?, blockList: Set<String>?): Boolean {
418454
element?.let { elementNotNull ->
419455
if (blockList?.any { appIdBlocked ->

app/src/main/java/com/kunzisoft/keepass/autofill/StructureParser.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ import android.view.autofill.AutofillId
2727
import android.view.autofill.AutofillValue
2828
import androidx.annotation.RequiresApi
2929
import org.joda.time.DateTime
30-
import java.util.*
31-
import kotlin.collections.ArrayList
30+
import java.util.Locale
3231

3332

3433
/**
@@ -52,7 +51,7 @@ class StructureParser(private val structure: AssistStructure) {
5251
applicationId = windowNode.title.toString().split("/")[0]
5352
Log.d(TAG, "Autofill applicationId: $applicationId")
5453

55-
if (applicationId?.contains("PopupWindow:") == false) {
54+
if (applicationId?.contains(APPLICATION_ID_POPUP_WINDOW) == false) {
5655
if (parseViewNode(windowNode.rootViewNode))
5756
break@mainLoop
5857
}
@@ -583,5 +582,7 @@ class StructureParser(private val structure: AssistStructure) {
583582

584583
companion object {
585584
private val TAG = StructureParser::class.java.name
585+
586+
const val APPLICATION_ID_POPUP_WINDOW = "PopupWindow:"
586587
}
587588
}

app/src/main/java/com/kunzisoft/keepass/database/helper/SearchHelper.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ object SearchHelper {
6060
// If search provide results
6161
database.createVirtualGroupFromSearchInfo(
6262
searchInfo.toString(),
63+
searchInfo.isASearchByDomain(),
6364
MAX_SEARCH_ENTRY
6465
)?.let { searchGroup ->
6566
if (searchGroup.numberOfChildEntries > 0) {

app/src/main/java/com/kunzisoft/keepass/view/SearchFiltersView.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class SearchFiltersView @JvmOverloads constructor(context: Context,
3131
private var searchUsername: CompoundButton
3232
private var searchPassword: CompoundButton
3333
private var searchURL: CompoundButton
34+
private var searchByURLDomain: Boolean = false
3435
private var searchExpired: CompoundButton
3536
private var searchNotes: CompoundButton
3637
private var searchOther: CompoundButton
@@ -50,6 +51,7 @@ class SearchFiltersView @JvmOverloads constructor(context: Context,
5051
this.searchInUsernames = searchUsername.isChecked
5152
this.searchInPasswords = searchPassword.isChecked
5253
this.searchInUrls = searchURL.isChecked
54+
this.searchByDomain = searchByURLDomain
5355
this.searchInExpired = searchExpired.isChecked
5456
this.searchInNotes = searchNotes.isChecked
5557
this.searchInOther = searchOther.isChecked
@@ -70,6 +72,7 @@ class SearchFiltersView @JvmOverloads constructor(context: Context,
7072
searchUsername.isChecked = value.searchInUsernames
7173
searchPassword.isChecked = value.searchInPasswords
7274
searchURL.isChecked = value.searchInUrls
75+
searchByURLDomain = value.searchByDomain
7376
searchExpired.isChecked = value.searchInExpired
7477
searchNotes.isChecked = value.searchInNotes
7578
searchOther.isChecked = value.searchInOther

app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@ import com.kunzisoft.keepass.database.element.DateInstant
1818
import com.kunzisoft.keepass.database.element.Field
1919
import com.kunzisoft.keepass.database.element.icon.IconImage
2020
import com.kunzisoft.keepass.database.element.security.ProtectedString
21-
import com.kunzisoft.keepass.database.element.template.*
21+
import com.kunzisoft.keepass.database.element.template.Template
22+
import com.kunzisoft.keepass.database.element.template.TemplateAttribute
23+
import com.kunzisoft.keepass.database.element.template.TemplateAttributeAction
24+
import com.kunzisoft.keepass.database.element.template.TemplateAttributeOption
25+
import com.kunzisoft.keepass.database.element.template.TemplateAttributeType
26+
import com.kunzisoft.keepass.database.element.template.TemplateEngine
2227
import com.kunzisoft.keepass.database.element.template.TemplateEngine.Companion.addTemplateDecorator
28+
import com.kunzisoft.keepass.database.element.template.TemplateField
2329
import com.kunzisoft.keepass.model.EntryInfo
2430
import com.kunzisoft.keepass.otp.OtpElement
2531
import com.kunzisoft.keepass.otp.OtpEntryFields
@@ -608,9 +614,8 @@ abstract class TemplateAbstractView<
608614
getViewFieldByName(oldField.name)?.view?.let { viewToReplace ->
609615
val oldValue = getCustomField(oldField.name).protectedValue.toString()
610616

611-
val parentGroup = viewToReplace.parent as ViewGroup
612-
val indexInParent = parentGroup.indexOfChild(viewToReplace)
613-
parentGroup.removeView(viewToReplace)
617+
val parentGroup = viewToReplace.parent as? ViewGroup?
618+
parentGroup?.removeView(viewToReplace)
614619

615620
val newCustomFieldWithValue = if (keepOldValue)
616621
Field(newField.name,
@@ -624,7 +629,9 @@ abstract class TemplateAbstractView<
624629

625630
val newCustomView = buildViewForCustomField(newCustomFieldWithValue)
626631
newCustomView?.let {
627-
parentGroup.addView(newCustomView, indexInParent)
632+
parentGroup?.indexOfChild(viewToReplace)?.let { indexInParent ->
633+
parentGroup.addView(newCustomView, indexInParent)
634+
}
628635
mViewFields.add(
629636
oldPosition,
630637
ViewField(

app/src/main/res/layout/item_list_nodes_entry.xml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@
125125
android:paddingStart="8dp"
126126
android:paddingLeft="8dp"
127127
android:paddingEnd="4dp"
128-
android:paddingRight="4dp"
129-
android:paddingVertical="4dp">
128+
android:paddingRight="4dp">
130129

131130
<TextView
132131
android:id="@+id/node_otp_token"
@@ -179,4 +178,4 @@
179178
tools:text="Database / Group A / Group B" />
180179

181180
</androidx.constraintlayout.widget.ConstraintLayout>
182-
</androidx.constraintlayout.widget.ConstraintLayout>
181+
</androidx.constraintlayout.widget.ConstraintLayout>

0 commit comments

Comments
 (0)