Compare commits

..

39 Commits

Author SHA1 Message Date
J-Jamet
a846ec29ca Merge branch 'release/2.5beta28' 2020-03-10 18:59:59 +01:00
J-Jamet
4533e96bff Upgrade CHANGELOG 2020-03-10 18:48:57 +01:00
J-Jamet
0a401c3ac9 Fix strings 2020-03-10 18:41:35 +01:00
J-Jamet
468abaf077 Fix strings 2020-03-10 18:29:19 +01:00
J-Jamet
4ccf2f641c Merge branch 'master' of https://hosted.weblate.org/projects/keepass-dx/strings into develop 2020-03-10 18:14:14 +01:00
Dominik Baláž
34eb2785cf Translated using Weblate (Slovak)
Currently translated at 21.5% (92 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/sk/
2020-03-10 17:21:26 +01:00
anonymous
09dbfe323e Translated using Weblate (Slovak)
Currently translated at 21.5% (92 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/sk/
2020-03-10 17:21:26 +01:00
Destiny Li
1f06c5b425 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (426 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2020-03-10 11:33:21 +01:00
Destiny Li
b98e089f7a Translated using Weblate (Chinese (Traditional))
Currently translated at 48.3% (206 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hant/
2020-03-10 11:33:20 +01:00
Aurel F
a0ad06ed0a Translated using Weblate (Romanian)
Currently translated at 40.8% (174 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ro/
2020-03-10 11:33:18 +01:00
solokot
ec63365429 Translated using Weblate (Russian)
Currently translated at 100.0% (426 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2020-03-10 11:33:10 +01:00
J-Jamet
2cb85e4346 Update items after appearance change #452 2020-03-10 08:58:22 +01:00
J-Jamet
0d7c479c51 Merge branch 'feature/Migration_SDK_29' into develop 2020-03-10 08:40:53 +01:00
J-Jamet
5a6c21e662 Try to fix read only bug #480 2020-03-10 08:38:49 +01:00
J-Jamet
d6cadac98f Fix small warning 2020-03-08 13:22:11 +01:00
J-Jamet
dac2fc2c37 Use PreferenceManager from AndroidX 2020-03-08 13:10:16 +01:00
J-Jamet
0fb45cef0d Encapsulate preferences 2020-03-08 13:04:25 +01:00
anonymous
5ebdbd4003 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (426 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2020-03-08 12:08:21 +01:00
Destiny Li
b30f1023cb Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (426 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2020-03-08 12:08:21 +01:00
J-Jamet
e5f65a4d1e Fix % issue in string 2020-03-08 11:48:47 +01:00
J-Jamet
ab42a65aa4 Fix null issues 2020-03-08 11:41:13 +01:00
J-Jamet
e351456bfe First pass migration SDK 29 2020-03-08 11:03:21 +01:00
J-Jamet
452e68b08f Fix C cast warning 2020-03-08 10:52:29 +01:00
J-Jamet
d65beed7a1 Fix small warnings 2020-03-08 10:49:06 +01:00
J-Jamet
f5a5a0e8cb Add generated JSON for database 2020-03-08 10:41:52 +01:00
solokot
98380a0906 Translated using Weblate (Russian)
Currently translated at 100.0% (426 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2020-03-08 10:20:37 +01:00
J-Jamet
22fe7508f3 Fix doForEachChild warning 2020-03-08 10:16:31 +01:00
J-Jamet
c8e241fc76 Fix Room incremental warning 2020-03-08 09:50:32 +01:00
J-Jamet
2c943e00d0 Fix writeEnum warning 2020-03-08 09:50:07 +01:00
J-Jamet
7ddb83b72d Fix DateFormatter warning 2020-03-08 09:36:45 +01:00
Kunzisoft
50bac01699 Translated using Weblate (French)
Currently translated at 99.7% (425 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/
2020-03-08 09:33:23 +01:00
Aurel F
e0a92dfadd Translated using Weblate (Romanian)
Currently translated at 12.2% (52 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ro/
2020-03-08 09:33:22 +01:00
solokot
b50c951091 Translated using Weblate (Russian)
Currently translated at 100.0% (426 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2020-03-08 09:33:17 +01:00
Kunzisoft
2f589a95a9 Translated using Weblate (English)
Currently translated at 100.0% (426 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/en/
2020-03-08 09:33:15 +01:00
J-Jamet
53eac86a95 Update AndroidX dependencies and fix small warning 2020-03-08 09:17:18 +01:00
J-Jamet
9412f8955e Update kotlin to 1.3.61 2020-03-08 09:07:14 +01:00
J-Jamet
71c98d82b1 Update gradle to 5.6.4 2020-03-08 09:00:56 +01:00
J-Jamet
42c1a925b4 Upgrade app to 2.54beta28 2020-03-08 08:59:41 +01:00
J-Jamet
1e84534ffd Merge tag '2.5beta27' into develop
2.5beta27
2020-03-07 14:41:37 +01:00
55 changed files with 689 additions and 267 deletions

View File

@@ -1,4 +1,8 @@
KeepassDX (2.5beta27) KeePassDX(2.5beta28)
* Fix read only database
* Upgrade to Android SDK 29
KeePassDX (2.5beta27)
* New setting to hide broken links * New setting to hide broken links
* Show URL when title is empty * Show URL when title is empty
* Setting to open search field at database opening * Setting to open search field at database opening
@@ -7,7 +11,7 @@ KeepassDX (2.5beta27)
* Fix appearance refresh settings * Fix appearance refresh settings
* Sort optimization * Sort optimization
KeepassDX (2.5.0.0beta26) KeePassDX (2.5.0.0beta26)
* Download attachments * Download attachments
* Change file size string format * Change file size string format
* Prevent screenshot for all screen * Prevent screenshot for all screen
@@ -20,7 +24,7 @@ KeepassDX (2.5.0.0beta26)
* Fix dates * Fix dates
* Fix UUID message for Database v1 * Fix UUID message for Database v1
KeepassDX (2.5.0.0beta25) KeePassDX (2.5.0.0beta25)
* Setting for Recycle Bin * Setting for Recycle Bin
* Fix Recycle bin issues * Fix Recycle bin issues
* Fix TOTP * Fix TOTP
@@ -28,7 +32,7 @@ KeepassDX (2.5.0.0beta25)
* Fix update group * Fix update group
* Fix OOM * Fix OOM
KeepassDX (2.5.0.0beta24) KeePassDX (2.5.0.0beta24)
* Add OTP (HOTP / TOTP) * Add OTP (HOTP / TOTP)
* Add settings (Color, Security, Master Key) * Add settings (Color, Security, Master Key)
* Show history of each entry * Show history of each entry
@@ -38,7 +42,7 @@ KeepassDX (2.5.0.0beta24)
* Open/Save database as service / Add persistent notification * Open/Save database as service / Add persistent notification
* Fix settings / edit group / small bugs * Fix settings / edit group / small bugs
KeepassDX (2.5.0.0beta23) KeePassDX (2.5.0.0beta23)
* New, more secure database creation workflow * New, more secure database creation workflow
* Recognize more database files * Recognize more database files
* Add alias for history files (WARNING: history is erased) * Add alias for history files (WARNING: history is erased)
@@ -47,14 +51,14 @@ KeepassDX (2.5.0.0beta23)
* Fix OOM with KeyFile * Fix OOM with KeyFile
* Fix small issues * Fix small issues
KeepassDX (2.5.0.0beta22) KeePassDX (2.5.0.0beta22)
* Rebuild code for actions * Rebuild code for actions
* Add UUID as entry view * Add UUID as entry view
* Fix bug with natural order * Fix bug with natural order
* Fix number of entries in databaseV1 * Fix number of entries in databaseV1
* New entry views * New entry views
KeepassDX (2.5.0.0beta21) KeePassDX (2.5.0.0beta21)
* Fix nested groups no longer visible in V1 databases * Fix nested groups no longer visible in V1 databases
* Improved data import algorithm for V1 databases * Improved data import algorithm for V1 databases
* Add natural database sort * Add natural database sort
@@ -62,10 +66,10 @@ KeepassDX (2.5.0.0beta21)
* Fix button disabled with only KeyFile * Fix button disabled with only KeyFile
* Show the number of entries in a group * Show the number of entries in a group
KeepassDX (2.5.0.0beta20) KeePassDX (2.5.0.0beta20)
* Fix a major bug that displays an entry history * Fix a major bug that displays an entry history
KeepassDX (2.5.0.0beta19) KeePassDX (2.5.0.0beta19)
* Add lock button always visible * Add lock button always visible
* New connection workflow * New connection workflow
* Code refactored in Kotlin * Code refactored in Kotlin
@@ -76,7 +80,7 @@ KeepassDX (2.5.0.0beta19)
* Fix memory when load database * Fix memory when load database
* Fix small bugs * Fix small bugs
KeepassDX (2.5.0.0beta18) KeePassDX (2.5.0.0beta18)
* New recent databases views * New recent databases views
* New information dialog * New information dialog
* Custom fields for the Magikeyboard * Custom fields for the Magikeyboard
@@ -85,10 +89,10 @@ KeepassDX (2.5.0.0beta18)
* Fix memory when opening the database * Fix memory when opening the database
* Memory management for attachments * Memory management for attachments
KeepassDX (2.5.0.0beta17) KeePassDX (2.5.0.0beta17)
* Fix font and search * Fix font and search
KeepassDX (2.5.0.0beta16) KeePassDX (2.5.0.0beta16)
* New search in a single fragment * New search in a single fragment
* Search suggestions * Search suggestions
* Added the display of usernames * Added the display of usernames
@@ -96,20 +100,20 @@ KeepassDX (2.5.0.0beta16)
* Fix read-only mode * Fix read-only mode
* Fix parcelable / toolbar / back * Fix parcelable / toolbar / back
KeepassDX (2.5.0.0beta15) KeePassDX (2.5.0.0beta15)
* Read only mode * Read only mode
* Best group recovery for the navigation fragment * Best group recovery for the navigation fragment
* Fix copies in notifications * Fix copies in notifications
* Fix orientation * Fix orientation
* Added translations * Added translations
KeepassDX (2.5.0.0beta14) KeePassDX (2.5.0.0beta14)
* Optimize all the memory with parcelables / fix search * Optimize all the memory with parcelables / fix search
KeepassDX (2.5.0.0beta13) KeePassDX (2.5.0.0beta13)
* Fix memory issue with parcelable (crash in beta12 version) * Fix memory issue with parcelable (crash in beta12 version)
KeepassDX (2.5.0.0beta12) KeePassDX (2.5.0.0beta12)
* Added the Magikeyboard to fill the forms (settings still in development) * Added the Magikeyboard to fill the forms (settings still in development)
* Added move and copy for groups and entries * Added move and copy for groups and entries
* New navigation in a single screen / new animations between activities * New navigation in a single screen / new animations between activities
@@ -122,10 +126,10 @@ KeepassDX (2.5.0.0beta12)
* Fix the fingerprint recognition (WARNING : The keystore is reinit, you must delete the old keys) * Fix the fingerprint recognition (WARNING : The keystore is reinit, you must delete the old keys)
* Fix small bugs * Fix small bugs
KeepassDX (2.5.0.0beta11) KeePassDX (2.5.0.0beta11)
* Fix crash in beta10 version * Fix crash in beta10 version
KeepassDX (2.5.0.0beta10) KeePassDX (2.5.0.0beta10)
* Dynamically change Algorithm and Key Derivation Function in settings * Dynamically change Algorithm and Key Derivation Function in settings
* Upgrade translations * Upgrade translations
* New red volcano theme, fix classic dark theme * New red volcano theme, fix classic dark theme
@@ -133,7 +137,7 @@ KeepassDX (2.5.0.0beta10)
* Update fingerprint state with checkbox * Update fingerprint state with checkbox
* Fix bugs * Fix bugs
KeepassDX (2.5.0.0beta9) KeePassDX (2.5.0.0beta9)
* Education Screens to learn how to use the app * Education Screens to learn how to use the app
* New designs * New designs
* New custom font for character visibility * New custom font for character visibility
@@ -142,9 +146,9 @@ KeepassDX (2.5.0.0beta9)
* Change setting organisation * Change setting organisation
* Pro version * Pro version
KeepassDX (2.5.0.0beta8) KeePassDX (2.5.0.0beta8)
* Hide custom entries protected * Hide custom entries protected
* Best management of field references (https://keepass.info/help/base/fieldrefs.html) * Best management of field references (https://KeePass.info/help/base/fieldrefs.html)
* Change database / default settings * Change database / default settings
* Add Autofill for search * Add Autofill for search
* Add sorting by last access and by creation time * Add sorting by last access and by creation time
@@ -152,7 +156,7 @@ KeepassDX (2.5.0.0beta8)
* Refactor old code * Refactor old code
* Fix bugs * Fix bugs
KeepassDX (2.5.0.0beta7) KeePassDX (2.5.0.0beta7)
* Rebuild Notifications * Rebuild Notifications
* Change links to https * Change links to https
* Add extended Ascii (ñæËÌÂÝÜ...) * Add extended Ascii (ñæËÌÂÝÜ...)
@@ -161,10 +165,10 @@ KeepassDX (2.5.0.0beta7)
* Add setting to prevent the password copy * Add setting to prevent the password copy
* Fix bugs * Fix bugs
KeepassDX (2.5.0.0beta6) KeePassDX (2.5.0.0beta6)
* Fix crash * Fix crash
KeepassDX (2.5.0.0beta5) KeePassDX (2.5.0.0beta5)
* Autofill (Android O) * Autofill (Android O)
* Deletion for group * Deletion for group
* New sorts with (Asc/Dsc, Groups before or after) * New sorts with (Asc/Dsc, Groups before or after)
@@ -185,7 +189,7 @@ KeepassDX (2.5.0.0beta5)
* Fix many small bugs * Fix many small bugs
* Add recycle bin setting (not yet accessible) * Add recycle bin setting (not yet accessible)
KeepassDX (2.5.0.0beta4) KeePassDX (2.5.0.0beta4)
* Show only file name * Show only file name
* Setting for full path * Setting for full path
* Add information for each database file * Add information for each database file
@@ -194,7 +198,7 @@ KeepassDX (2.5.0.0beta4)
* Delete view assignment for fingerprint opening * Delete view assignment for fingerprint opening
* Merge KeePassDroid 2.2.1 * Merge KeePassDroid 2.2.1
KeepassDX (2.5.0.0beta3) KeePassDX (2.5.0.0beta3)
* New database workflow with new screens and folder selection * New database workflow with new screens and folder selection
* Settings for default password generation * Settings for default password generation
* Fingerprint dialog for explanations * Fingerprint dialog for explanations
@@ -205,17 +209,17 @@ KeepassDX (2.5.0.0beta3)
* Merge KeePassDroid 2.2.0.9 * Merge KeePassDroid 2.2.0.9
* Add corruption fix mode * Add corruption fix mode
KeepassDX (2.5.0.0beta2) KeePassDX (2.5.0.0beta2)
* Remove libs for F-Droid * Remove libs for F-Droid
KeepassDX (2.5.0.0beta1) KeePassDX (2.5.0.0beta1)
* Fork KeepassDroid * Fork KeePassDroid
* Add Material Design * Add Material Design
* Add Light and Night theme * Add Light and Night theme
* Min API is 14 * Min API is 14
* Solve bug for fingerprint * Solve bug for fingerprint
* Update French translation * Update French translation
* Change donation (see KeepassDroid to contribute on both projects) * Change donation (see KeePassDroid to contribute on both projects)
KeePassDroid (2.2.1) KeePassDroid (2.2.1)
* Fix kdbx4 date corruption * Fix kdbx4 date corruption
@@ -476,7 +480,7 @@ KeePassDroid (1.9.10)
KeePassDroid (1.9.9) KeePassDroid (1.9.9)
* Go back to explicitly storing blank fields in the database * Go back to explicitly storing blank fields in the database
(works around bug in keepassx) (works around bug in KeePassx)
* Add support for native code on MIPS architectures * Add support for native code on MIPS architectures
* Adding Vibrate permission. On some devices notifications fail * Adding Vibrate permission. On some devices notifications fail
without the vibrate permission. without the vibrate permission.

View File

@@ -4,21 +4,28 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
android { android {
compileSdkVersion 28 compileSdkVersion 29
buildToolsVersion '28.0.3' buildToolsVersion '29.0.3'
defaultConfig { defaultConfig {
applicationId "com.kunzisoft.keepass" applicationId "com.kunzisoft.keepass"
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 28 targetSdkVersion 29
versionCode = 27 versionCode = 28
versionName = "2.5beta27" versionName = "2.5beta28"
multiDexEnabled true multiDexEnabled true
testApplicationId = "com.kunzisoft.keepass.tests" testApplicationId = "com.kunzisoft.keepass.tests"
testInstrumentationRunner = "android.test.InstrumentationTestRunner" testInstrumentationRunner = "android.test.InstrumentationTestRunner"
buildConfigField "String[]", "ICON_PACKS", "{\"classic\",\"material\"}" buildConfigField "String[]", "ICON_PACKS", "{\"classic\",\"material\"}"
kapt {
arguments {
arg("room.incremental", "true")
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
} }
externalNativeBuild { externalNativeBuild {
@@ -79,7 +86,7 @@ android {
} }
def spongycastleVersion = "1.58.0.0" def spongycastleVersion = "1.58.0.0"
def room_version = "2.2.1" def room_version = "2.2.4"
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
@@ -88,7 +95,9 @@ dependencies {
implementation 'androidx.legacy:legacy-preference-v14:1.0.0' implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.biometric:biometric:1.0.0' implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.biometric:biometric:1.0.1'
// To upgrade with style
implementation 'com.google.android.material:material:1.0.0' implementation 'com.google.android.material:material:1.0.0'
implementation "androidx.room:room-runtime:$room_version" implementation "androidx.room:room-runtime:$room_version"

View File

@@ -0,0 +1,84 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "56438e5f7372ef3e36e33b782aed245d",
"entities": [
{
"tableName": "file_database_history",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`database_uri` TEXT NOT NULL, `database_alias` TEXT NOT NULL, `keyfile_uri` TEXT, `updated` INTEGER NOT NULL, PRIMARY KEY(`database_uri`))",
"fields": [
{
"fieldPath": "databaseUri",
"columnName": "database_uri",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "databaseAlias",
"columnName": "database_alias",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyFileUri",
"columnName": "keyfile_uri",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "updated",
"columnName": "updated",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"database_uri"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "cipher_database",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`database_uri` TEXT NOT NULL, `encrypted_value` TEXT NOT NULL, `specs_parameters` TEXT NOT NULL, PRIMARY KEY(`database_uri`))",
"fields": [
{
"fieldPath": "databaseUri",
"columnName": "database_uri",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "encryptedValue",
"columnName": "encrypted_value",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "specParameters",
"columnName": "specs_parameters",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"database_uri"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '56438e5f7372ef3e36e33b782aed245d')"
]
}
}

View File

@@ -150,9 +150,11 @@ class EntryActivity : LockingActivity() {
// Get Entry from UUID // Get Entry from UUID
try { try {
val keyEntry: NodeId<UUID> = intent.getParcelableExtra(KEY_ENTRY) val keyEntry: NodeId<UUID>? = intent.getParcelableExtra(KEY_ENTRY)
mEntry = mDatabase?.getEntryById(keyEntry) if (keyEntry != null) {
mEntryLastVersion = mEntry mEntry = mDatabase?.getEntryById(keyEntry)
mEntryLastVersion = mEntry
}
} catch (e: ClassCastException) { } catch (e: ClassCastException) {
Log.e(TAG, "Unable to retrieve the entry key") Log.e(TAG, "Unable to retrieve the entry key")
} }

View File

@@ -28,7 +28,6 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.os.Handler import android.os.Handler
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
@@ -142,8 +141,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
if (!(savedInstanceState != null if (!(savedInstanceState != null
&& savedInstanceState.containsKey(EXTRA_STAY) && savedInstanceState.containsKey(EXTRA_STAY)
&& savedInstanceState.getBoolean(EXTRA_STAY, false))) { && savedInstanceState.getBoolean(EXTRA_STAY, false))) {
val prefs = PreferenceManager.getDefaultSharedPreferences(this) val databasePath = PreferencesUtil.getDefaultDatabasePath(this)
val databasePath = prefs.getString(PasswordActivity.KEY_DEFAULT_DATABASE_PATH, "")
UriUtil.parse(databasePath)?.let { databaseFileUri -> UriUtil.parse(databasePath)?.let { databaseFileUri ->
launchPasswordActivityWithPath(databaseFileUri) launchPasswordActivityWithPath(databaseFileUri)

View File

@@ -346,7 +346,8 @@ class GroupActivity : LockingActivity(),
// If it's a search // If it's a search
if (Intent.ACTION_SEARCH == intent.action) { if (Intent.ACTION_SEARCH == intent.action) {
return mDatabase?.search(intent.getStringExtra(SearchManager.QUERY).trim { it <= ' ' }) val searchString = intent.getStringExtra(SearchManager.QUERY)?.trim { it <= ' ' } ?: ""
return mDatabase?.search(searchString)
} }
// else a real group // else a real group
else { else {
@@ -859,8 +860,8 @@ class GroupActivity : LockingActivity(),
.iconPicked(bundle) .iconPicked(bundle)
} }
override fun onSortSelected(sortNodeEnum: SortNodeEnum, ascending: Boolean, groupsBefore: Boolean, recycleBinBottom: Boolean) { override fun onSortSelected(sortNodeEnum: SortNodeEnum, sortNodeParameters: SortNodeEnum.SortNodeParameters) {
mListNodesFragment?.onSortSelected(sortNodeEnum, ascending, groupsBefore, recycleBinBottom) mListNodesFragment?.onSortSelected(sortNodeEnum, sortNodeParameters)
} }
override fun startActivity(intent: Intent) { override fun startActivity(intent: Intent) {

View File

@@ -21,9 +21,7 @@ package com.kunzisoft.keepass.activities
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.util.Log import android.util.Log
@@ -69,8 +67,6 @@ class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionLis
private var notFoundView: View? = null private var notFoundView: View? = null
private var isASearchResult: Boolean = false private var isASearchResult: Boolean = false
// Preferences for sorting
private var prefs: SharedPreferences? = null
private var readOnly: Boolean = false private var readOnly: Boolean = false
get() { get() {
@@ -155,7 +151,6 @@ class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionLis
}) })
} }
} }
prefs = PreferenceManager.getDefaultSharedPreferences(context)
} }
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
@@ -213,26 +208,26 @@ class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionLis
fun rebuildList() { fun rebuildList() {
// Add elements to the list // Add elements to the list
mainGroup?.let { mainGroup -> mainGroup?.let { mainGroup ->
mAdapter?.rebuildList(mainGroup) mAdapter?.apply {
rebuildList(mainGroup)
// To visually change the elements
if (PreferencesUtil.APPEARANCE_CHANGED) {
notifyDataSetChanged()
PreferencesUtil.APPEARANCE_CHANGED = false
}
}
} }
} }
override fun onSortSelected(sortNodeEnum: SortNodeEnum, override fun onSortSelected(sortNodeEnum: SortNodeEnum,
ascending: Boolean, sortNodeParameters: SortNodeEnum.SortNodeParameters) {
groupsBefore: Boolean, // Save setting
recycleBinBottom: Boolean) { context?.let {
// Toggle setting PreferencesUtil.saveNodeSort(it, sortNodeEnum, sortNodeParameters)
prefs?.edit()?.apply {
putString(getString(R.string.sort_node_key), sortNodeEnum.name)
putBoolean(getString(R.string.sort_ascending_key), ascending)
putBoolean(getString(R.string.sort_group_before_key), groupsBefore)
putBoolean(getString(R.string.sort_recycle_bin_bottom_key), recycleBinBottom)
apply()
} }
// Tell the adapter to refresh it's list // Tell the adapter to refresh it's list
mAdapter?.notifyChangeSort(sortNodeEnum, mAdapter?.notifyChangeSort(sortNodeEnum, sortNodeParameters)
SortNodeEnum.SortNodeParameters(ascending, groupsBefore, recycleBinBottom))
rebuildList() rebuildList()
} }

View File

@@ -23,12 +23,10 @@ import android.app.Activity
import android.app.assist.AssistStructure import android.app.assist.AssistStructure
import android.app.backup.BackupManager import android.app.backup.BackupManager
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.preference.PreferenceManager
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.util.Log import android.util.Log
@@ -91,8 +89,6 @@ open class PasswordActivity : StylishActivity() {
private var mDatabaseFileUri: Uri? = null private var mDatabaseFileUri: Uri? = null
private var mDatabaseKeyFileUri: Uri? = null private var mDatabaseKeyFileUri: Uri? = null
private var mSharedPreferences: SharedPreferences? = null
private var mRememberKeyFile: Boolean = false private var mRememberKeyFile: Boolean = false
private var mOpenFileHelper: OpenFileHelper? = null private var mOpenFileHelper: OpenFileHelper? = null
@@ -115,8 +111,6 @@ open class PasswordActivity : StylishActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this) mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
setContentView(R.layout.activity_password) setContentView(R.layout.activity_password)
@@ -309,7 +303,7 @@ open class PasswordActivity : StylishActivity() {
keyFileUri = intent.getParcelableExtra(KEY_KEYFILE) keyFileUri = intent.getParcelableExtra(KEY_KEYFILE)
} }
mForceReadOnly = UriUtil.isUriNotWritable(contentResolver, databaseUri) mForceReadOnly = !UriUtil.isUriWritable(contentResolver, databaseUri)
// Post init uri with KeyFile if needed // Post init uri with KeyFile if needed
if (mRememberKeyFile && (keyFileUri == null || keyFileUri.toString().isEmpty())) { if (mRememberKeyFile && (keyFileUri == null || keyFileUri.toString().isEmpty())) {
@@ -344,19 +338,12 @@ open class PasswordActivity : StylishActivity() {
// Define listeners for default database checkbox and validate button // Define listeners for default database checkbox and validate button
checkboxDefaultDatabaseView?.setOnCheckedChangeListener { _, isChecked -> checkboxDefaultDatabaseView?.setOnCheckedChangeListener { _, isChecked ->
var newDefaultFileName: Uri? = null var newDefaultFileUri: Uri? = null
if (isChecked) { if (isChecked) {
newDefaultFileName = databaseFileUri ?: newDefaultFileName newDefaultFileUri = databaseFileUri ?: newDefaultFileUri
} }
mSharedPreferences?.edit()?.apply { PreferencesUtil.saveDefaultDatabasePath(this, newDefaultFileUri)
newDefaultFileName?.let {
putString(KEY_DEFAULT_DATABASE_PATH, newDefaultFileName.toString())
} ?: kotlin.run {
remove(KEY_DEFAULT_DATABASE_PATH)
}
apply()
}
val backupManager = BackupManager(this@PasswordActivity) val backupManager = BackupManager(this@PasswordActivity)
backupManager.dataChanged() backupManager.dataChanged()
@@ -364,7 +351,7 @@ open class PasswordActivity : StylishActivity() {
confirmButtonView?.setOnClickListener { verifyCheckboxesAndLoadDatabase() } confirmButtonView?.setOnClickListener { verifyCheckboxesAndLoadDatabase() }
// Retrieve settings for default database // Retrieve settings for default database
val defaultFilename = mSharedPreferences?.getString(KEY_DEFAULT_DATABASE_PATH, "") val defaultFilename = PreferencesUtil.getDefaultDatabasePath(this)
if (databaseFileUri != null if (databaseFileUri != null
&& databaseFileUri.path != null && databaseFileUri.path!!.isNotEmpty() && databaseFileUri.path != null && databaseFileUri.path!!.isNotEmpty()
&& databaseFileUri == UriUtil.parse(defaultFilename)) { && databaseFileUri == UriUtil.parse(defaultFilename)) {
@@ -703,8 +690,6 @@ open class PasswordActivity : StylishActivity() {
private val TAG = PasswordActivity::class.java.name private val TAG = PasswordActivity::class.java.name
const val KEY_DEFAULT_DATABASE_PATH = "KEY_DEFAULT_DATABASE_PATH"
private const val KEY_FILENAME = "fileName" private const val KEY_FILENAME = "fileName"
private const val KEY_KEYFILE = "keyFile" private const val KEY_KEYFILE = "keyFile"
private const val VIEW_INTENT = "android.intent.action.VIEW" private const val VIEW_INTENT = "android.intent.action.VIEW"

View File

@@ -112,7 +112,7 @@ class IconPickerDialogFragment : DialogFragment() {
// Retrieve the textColor to tint the icon // Retrieve the textColor to tint the icon
val ta = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColor)) val ta = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColor))
ImageViewCompat.setImageTintList(iconImageView, ColorStateList.valueOf(ta.getColor(0, Color.BLACK))) ImageViewCompat.setImageTintList(iconImageView, ColorStateList.valueOf(ta.getColor(0, Color.BLACK)))
ta?.recycle() ta.recycle()
} }
} }

View File

@@ -82,7 +82,9 @@ class SortDialogFragment : DialogFragment() {
builder.setView(rootView) builder.setView(rootView)
// Add action buttons // Add action buttons
.setPositiveButton(android.R.string.ok .setPositiveButton(android.R.string.ok
) { _, _ -> mListener?.onSortSelected(mSortNodeEnum, mAscending, mGroupsBefore, mRecycleBinBottom) } ) { _, _ -> mListener?.onSortSelected(mSortNodeEnum,
SortNodeEnum.SortNodeParameters(mAscending, mGroupsBefore, mRecycleBinBottom))
}
.setNegativeButton(android.R.string.cancel) { _, _ -> } .setNegativeButton(android.R.string.cancel) { _, _ -> }
val ascendingView = rootView.findViewById<CompoundButton>(R.id.sort_selection_ascending) val ascendingView = rootView.findViewById<CompoundButton>(R.id.sort_selection_ascending)
@@ -150,10 +152,7 @@ class SortDialogFragment : DialogFragment() {
} }
interface SortSelectionListener { interface SortSelectionListener {
fun onSortSelected(sortNodeEnum: SortNodeEnum, fun onSortSelected(sortNodeEnum: SortNodeEnum, sortNodeParameters: SortNodeEnum.SortNodeParameters)
ascending: Boolean,
groupsBefore: Boolean,
recycleBinBottom: Boolean)
} }
companion object { companion object {

View File

@@ -313,8 +313,9 @@ class AdvancedUnlockedManager(var context: FragmentActivity,
} }
override fun onBiometricException(e: Exception) { override fun onBiometricException(e: Exception) {
if (e.localizedMessage != null) e.localizedMessage?.let {
setAdvancedUnlockedMessageView(e.localizedMessage) setAdvancedUnlockedMessageView(it)
}
} }
private fun showFingerPrintViews(show: Boolean) { private fun showFingerPrintViews(show: Boolean) {

View File

@@ -493,10 +493,11 @@ class Database {
var outputStream: OutputStream? = null var outputStream: OutputStream? = null
try { try {
outputStream = contentResolver.openOutputStream(uri) outputStream = contentResolver.openOutputStream(uri)
val pmo = outputStream?.let { definedOutputStream ->
mDatabaseKDB?.let { DatabaseOutputKDB(it, outputStream) } val databaseOutput = mDatabaseKDB?.let { DatabaseOutputKDB(it, definedOutputStream) }
?: mDatabaseKDBX?.let { DatabaseOutputKDBX(it, outputStream) } ?: mDatabaseKDBX?.let { DatabaseOutputKDBX(it, definedOutputStream) }
pmo?.output() databaseOutput?.output()
}
} catch (e: Exception) { } catch (e: Exception) {
throw IOException(e) throw IOException(e)
} finally { } finally {
@@ -723,7 +724,7 @@ class Database {
fun canRecycle(entry: Entry): Boolean { fun canRecycle(entry: Entry): Boolean {
var canRecycle: Boolean? = null var canRecycle: Boolean? = null
entry.entryKDB?.let { entry.entryKDB?.let {
canRecycle = mDatabaseKDB?.canRecycle(it) canRecycle = mDatabaseKDB?.canRecycle()
} }
entry.entryKDBX?.let { entry.entryKDBX?.let {
canRecycle = mDatabaseKDBX?.canRecycle(it) canRecycle = mDatabaseKDBX?.canRecycle(it)
@@ -734,7 +735,7 @@ class Database {
fun canRecycle(group: Group): Boolean { fun canRecycle(group: Group): Boolean {
var canRecycle: Boolean? = null var canRecycle: Boolean? = null
group.groupKDB?.let { group.groupKDB?.let {
canRecycle = mDatabaseKDB?.canRecycle(it) canRecycle = mDatabaseKDB?.canRecycle()
} }
group.groupKDBX?.let { group.groupKDBX?.let {
canRecycle = mDatabaseKDBX?.canRecycle(it) canRecycle = mDatabaseKDBX?.canRecycle(it)

View File

@@ -46,7 +46,7 @@ class DateInstant : Parcelable {
} }
constructor(string: String) { constructor(string: String) {
jDate = dateFormat.parse(string) jDate = dateFormat.parse(string) ?: jDate
} }
constructor() { constructor() {
@@ -121,7 +121,7 @@ class DateInstant : Parcelable {
} }
} }
private fun isSameDate(d1: Date?, d2: Date?): Boolean { private fun isSameDate(d1: Date, d2: Date): Boolean {
val cal1 = Calendar.getInstance() val cal1 = Calendar.getInstance()
cal1.time = d1 cal1.time = d1
cal1.set(Calendar.MILLISECOND, 0) cal1.set(Calendar.MILLISECOND, 0)

View File

@@ -26,17 +26,25 @@ import java.util.UUID
class DeletedObject { class DeletedObject {
var uuid: UUID = DatabaseVersioned.UUID_ZERO var uuid: UUID = DatabaseVersioned.UUID_ZERO
var deletionTime: Date? = null private var mDeletionTime: Date? = null
get() = if (field == null) {
Date(System.currentTimeMillis()) fun getDeletionTime(): Date {
} else field if (mDeletionTime == null) {
mDeletionTime = Date(System.currentTimeMillis())
}
return mDeletionTime!!
}
fun setDeletionTime(deletionTime: Date) {
this.mDeletionTime = deletionTime
}
constructor() constructor()
@JvmOverloads @JvmOverloads
constructor(uuid: UUID, deletionTime: Date = Date()) { constructor(uuid: UUID, deletionTime: Date = Date()) {
this.uuid = uuid this.uuid = uuid
this.deletionTime = deletionTime this.mDeletionTime = deletionTime
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

View File

@@ -231,8 +231,9 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
* @param node Node to remove * @param node Node to remove
* @return true if node can be recycle, false elsewhere * @return true if node can be recycle, false elsewhere
*/ */
fun canRecycle(node: NodeVersioned<*, GroupKDB, EntryKDB>): Boolean { // TODO #394 Backup KDB
// TODO #394 Backup pw3 // fun canRecycle(node: NodeVersioned<*, GroupKDB, EntryKDB>): Boolean {
fun canRecycle(): Boolean {
return true return true
} }

View File

@@ -40,6 +40,7 @@ interface GroupVersionedInterface<Group: GroupVersionedInterface<Group, Entry>,
fun allowAddEntryIfIsRoot(): Boolean fun allowAddEntryIfIsRoot(): Boolean
@Suppress("UNCHECKED_CAST")
fun doForEachChildAndForIt(entryHandler: NodeHandler<Entry>, fun doForEachChildAndForIt(entryHandler: NodeHandler<Entry>,
groupHandler: NodeHandler<Group>) { groupHandler: NodeHandler<Group>) {
doForEachChild(entryHandler, groupHandler) doForEachChild(entryHandler, groupHandler)

View File

@@ -61,7 +61,9 @@ class BinaryAttachment : Parcelable {
val compressedByte = parcel.readByte().toInt() val compressedByte = parcel.readByte().toInt()
isCompressed = if (compressedByte == 2) null else compressedByte != 0 isCompressed = if (compressedByte == 2) null else compressedByte != 0
isProtected = parcel.readByte().toInt() != 0 isProtected = parcel.readByte().toInt() != 0
dataFile = File(parcel.readString()) parcel.readString()?.let {
dataFile = File(it)
}
} }
@Throws(IOException::class) @Throws(IOException::class)
@@ -74,10 +76,10 @@ class BinaryAttachment : Parcelable {
@Throws(IOException::class) @Throws(IOException::class)
fun compress(bufferSize: Int = DEFAULT_BUFFER_SIZE) { fun compress(bufferSize: Int = DEFAULT_BUFFER_SIZE) {
if (dataFile != null) { dataFile?.let { concreteDataFile ->
// To compress, create a new binary with file // To compress, create a new binary with file
if (isCompressed != true) { if (isCompressed != true) {
val fileBinaryCompress = File(dataFile!!.parent, dataFile!!.name + "_temp") val fileBinaryCompress = File(concreteDataFile.parent, concreteDataFile.name + "_temp")
var outputStream: GZIPOutputStream? = null var outputStream: GZIPOutputStream? = null
var inputStream: InputStream? = null var inputStream: InputStream? = null
try { try {
@@ -91,8 +93,8 @@ class BinaryAttachment : Parcelable {
outputStream?.close() outputStream?.close()
// Remove unGzip file // Remove unGzip file
if (dataFile!!.delete()) { if (concreteDataFile.delete()) {
if (fileBinaryCompress.renameTo(dataFile)) { if (fileBinaryCompress.renameTo(concreteDataFile)) {
// Harmonize with database compression // Harmonize with database compression
isCompressed = true isCompressed = true
} }
@@ -104,9 +106,9 @@ class BinaryAttachment : Parcelable {
@Throws(IOException::class) @Throws(IOException::class)
fun decompress(bufferSize: Int = DEFAULT_BUFFER_SIZE) { fun decompress(bufferSize: Int = DEFAULT_BUFFER_SIZE) {
if (dataFile != null) { dataFile?.let { concreteDataFile ->
if (isCompressed != false) { if (isCompressed != false) {
val fileBinaryDecompress = File(dataFile!!.parent, dataFile!!.name + "_temp") val fileBinaryDecompress = File(concreteDataFile.parent, concreteDataFile.name + "_temp")
var outputStream: FileOutputStream? = null var outputStream: FileOutputStream? = null
var inputStream: GZIPInputStream? = null var inputStream: GZIPInputStream? = null
try { try {
@@ -120,8 +122,8 @@ class BinaryAttachment : Parcelable {
outputStream?.close() outputStream?.close()
// Remove gzip file // Remove gzip file
if (dataFile!!.delete()) { if (concreteDataFile.delete()) {
if (fileBinaryDecompress.renameTo(dataFile)) { if (fileBinaryDecompress.renameTo(concreteDataFile)) {
// Harmonize with database compression // Harmonize with database compression
isCompressed = false isCompressed = false
} }

View File

@@ -127,11 +127,7 @@ object DatabaseKDBXXML {
const val ElemCustomData = "CustomData" const val ElemCustomData = "CustomData"
const val ElemStringDictExItem = "Item" const val ElemStringDictExItem = "Item"
val dateFormatter: ThreadLocal<SimpleDateFormat> = object : ThreadLocal<SimpleDateFormat>() { val DateFormatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT).apply {
override fun initialValue(): SimpleDateFormat { timeZone = TimeZone.getTimeZone("UTC")
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
dateFormat.timeZone = TimeZone.getTimeZone("UTC")
return dateFormat
}
} }
} }

View File

@@ -660,7 +660,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
KdbContext.DeletedObject -> if (name.equals(DatabaseKDBXXML.ElemUuid, ignoreCase = true)) { KdbContext.DeletedObject -> if (name.equals(DatabaseKDBXXML.ElemUuid, ignoreCase = true)) {
ctxDeletedObject?.uuid = readUuid(xpp) ctxDeletedObject?.uuid = readUuid(xpp)
} else if (name.equals(DatabaseKDBXXML.ElemDeletionTime, ignoreCase = true)) { } else if (name.equals(DatabaseKDBXXML.ElemDeletionTime, ignoreCase = true)) {
ctxDeletedObject?.deletionTime = readTime(xpp) ctxDeletedObject?.setDeletionTime(readTime(xpp))
} else { } else {
readUnknown(xpp) readUnknown(xpp)
} }
@@ -829,7 +829,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
} else { } else {
try { try {
utcDate = DatabaseKDBXXML.dateFormatter.get()?.parse(sDate) utcDate = DatabaseKDBXXML.DateFormatter.parse(sDate)
} catch (e: ParseException) { } catch (e: ParseException) {
// Catch with null test below // Catch with null test below
} }

View File

@@ -384,9 +384,9 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
} }
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class) @Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
private fun writeObject(name: String, value: Date?) { private fun writeObject(name: String, value: Date) {
if (header!!.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) { if (header!!.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
writeObject(name, DatabaseKDBXXML.dateFormatter.get().format(value)) writeObject(name, DatabaseKDBXXML.DateFormatter.format(value))
} else { } else {
val dt = DateTime(value) val dt = DateTime(value)
val seconds = DateKDBXUtil.convertDateToKDBX4Time(dt) val seconds = DateKDBXUtil.convertDateToKDBX4Time(dt)
@@ -553,7 +553,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
xml.startTag(null, DatabaseKDBXXML.ElemDeletedObject) xml.startTag(null, DatabaseKDBXXML.ElemDeletedObject)
writeUuid(DatabaseKDBXXML.ElemUuid, value.uuid) writeUuid(DatabaseKDBXXML.ElemUuid, value.uuid)
writeObject(DatabaseKDBXXML.ElemDeletionTime, value.deletionTime) writeObject(DatabaseKDBXXML.ElemDeletionTime, value.getDeletionTime())
xml.endTag(null, DatabaseKDBXXML.ElemDeletedObject) xml.endTag(null, DatabaseKDBXXML.ElemDeletedObject)
} }

View File

@@ -22,8 +22,8 @@ package com.kunzisoft.keepass.education
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import androidx.preference.PreferenceManager
import com.getkeepsafe.taptargetview.TapTarget import com.getkeepsafe.taptargetview.TapTarget
import com.getkeepsafe.taptargetview.TapTargetView import com.getkeepsafe.taptargetview.TapTargetView
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R

View File

@@ -45,7 +45,7 @@ class EntryInfo : Parcelable {
password = parcel.readString() ?: password password = parcel.readString() ?: password
url = parcel.readString() ?: url url = parcel.readString() ?: url
notes = parcel.readString() ?: notes notes = parcel.readString() ?: notes
parcel.readList(customFields, Field::class.java.classLoader) parcel.readList(customFields as List<Field>, Field::class.java.classLoader)
otpModel = parcel.readParcelable(OtpModel::class.java.classLoader) ?: otpModel otpModel = parcel.readParcelable(OtpModel::class.java.classLoader) ?: otpModel
} }

View File

@@ -94,20 +94,21 @@ class AttachmentFileNotificationService: LockNotificationService() {
val nextNotificationId = (downloadFileUris.values.maxBy { it.notificationId } val nextNotificationId = (downloadFileUris.values.maxBy { it.notificationId }
?.notificationId ?: notificationId) + 1 ?.notificationId ?: notificationId) + 1
val entryAttachment: EntryAttachment = intent.getParcelableExtra(ATTACHMENT_KEY)
val attachmentNotification = AttachmentNotification(nextNotificationId, entryAttachment)
downloadFileUris[downloadFileUri] = attachmentNotification
try { try {
AttachmentFileAsyncTask(downloadFileUri, intent.getParcelableExtra<EntryAttachment>(ATTACHMENT_KEY)?.let { entryAttachment ->
attachmentNotification, val attachmentNotification = AttachmentNotification(nextNotificationId, entryAttachment)
contentResolver).apply { downloadFileUris[downloadFileUri] = attachmentNotification
onUpdate = { uri, attachment, notificationIdAttach -> AttachmentFileAsyncTask(downloadFileUri,
newNotification(uri, attachment, notificationIdAttach) attachmentNotification,
mActionTaskListeners.forEach { actionListener -> contentResolver).apply {
actionListener.onAttachmentProgress(downloadFileUri, attachment) onUpdate = { uri, attachment, notificationIdAttach ->
newNotification(uri, attachment, notificationIdAttach)
mActionTaskListeners.forEach { actionListener ->
actionListener.onAttachmentProgress(downloadFileUri, attachment)
}
} }
} }.execute()
}.execute() }
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Unable to download $downloadFileUri", e) Log.e(TAG, "Unable to download $downloadFileUri", e)
} }

View File

@@ -22,14 +22,11 @@ package com.kunzisoft.keepass.notifications
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.exception.ClipboardException
import com.kunzisoft.keepass.model.EntryInfo import com.kunzisoft.keepass.model.EntryInfo
import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.timeout.ClipboardHelper import com.kunzisoft.keepass.timeout.ClipboardHelper
import com.kunzisoft.keepass.timeout.TimeoutHelper
import com.kunzisoft.keepass.timeout.TimeoutHelper.NEVER import com.kunzisoft.keepass.timeout.TimeoutHelper.NEVER
import com.kunzisoft.keepass.utils.LOCK_ACTION import com.kunzisoft.keepass.utils.LOCK_ACTION
import java.util.* import java.util.*
@@ -62,9 +59,7 @@ class ClipboardEntryNotificationService : LockNotificationService() {
mEntryInfo = intent?.getParcelableExtra(EXTRA_ENTRY_INFO) mEntryInfo = intent?.getParcelableExtra(EXTRA_ENTRY_INFO)
//Get settings //Get settings
notificationTimeoutMilliSecs = PreferenceManager.getDefaultSharedPreferences(this) notificationTimeoutMilliSecs = PreferencesUtil.getClipboardTimeout(this)
.getString(getString(R.string.clipboard_timeout_key),
getString(R.string.clipboard_timeout_default))?.toLong() ?: TimeoutHelper.DEFAULT_TIMEOUT
when { when {
intent == null -> Log.w(TAG, "null intent") intent == null -> Log.w(TAG, "null intent")
@@ -78,12 +73,14 @@ class ClipboardEntryNotificationService : LockNotificationService() {
} }
else -> for (actionKey in ClipboardEntryNotificationField.allActionKeys) { else -> for (actionKey in ClipboardEntryNotificationField.allActionKeys) {
if (actionKey == intent.action) { if (actionKey == intent.action) {
val fieldToCopy = intent.getParcelableExtra<ClipboardEntryNotificationField>( intent.getParcelableExtra<ClipboardEntryNotificationField>(
ClipboardEntryNotificationField.getExtraKeyLinkToActionKey(actionKey)) ClipboardEntryNotificationField.getExtraKeyLinkToActionKey(actionKey))?.let {
val nextFields = constructListOfField(intent) fieldToCopy ->
// Remove the current field from the next fields val nextFields = constructListOfField(intent)
nextFields.remove(fieldToCopy) // Remove the current field from the next fields
copyField(fieldToCopy, nextFields) nextFields.remove(fieldToCopy)
copyField(fieldToCopy, nextFields)
}
} }
} }
} }
@@ -91,10 +88,12 @@ class ClipboardEntryNotificationService : LockNotificationService() {
} }
private fun constructListOfField(intent: Intent?): ArrayList<ClipboardEntryNotificationField> { private fun constructListOfField(intent: Intent?): ArrayList<ClipboardEntryNotificationField> {
var fieldList = ArrayList<ClipboardEntryNotificationField>() val fieldList = ArrayList<ClipboardEntryNotificationField>()
if (intent != null && intent.extras != null) { if (intent?.extras?.containsKey(EXTRA_CLIPBOARD_FIELDS) == true) {
if (intent.extras!!.containsKey(EXTRA_CLIPBOARD_FIELDS)) intent.getParcelableArrayListExtra<ClipboardEntryNotificationField>(EXTRA_CLIPBOARD_FIELDS)?.let { retrieveFields ->
fieldList = intent.getParcelableArrayListExtra(EXTRA_CLIPBOARD_FIELDS) fieldList.clear()
fieldList.addAll(retrieveFields)
}
} }
return fieldList return fieldList
} }

View File

@@ -32,6 +32,7 @@ import com.kunzisoft.keepass.database.action.history.DeleteEntryHistoryDatabaseR
import com.kunzisoft.keepass.database.action.history.RestoreEntryHistoryDatabaseRunnable import com.kunzisoft.keepass.database.action.history.RestoreEntryHistoryDatabaseRunnable
import com.kunzisoft.keepass.database.action.node.* import com.kunzisoft.keepass.database.action.node.*
import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.database.element.*
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
import com.kunzisoft.keepass.database.element.node.Node import com.kunzisoft.keepass.database.element.node.Node
import com.kunzisoft.keepass.database.element.node.NodeId import com.kunzisoft.keepass.database.element.node.NodeId
import com.kunzisoft.keepass.database.element.node.Type import com.kunzisoft.keepass.database.element.node.Type
@@ -209,8 +210,12 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(KEY_FILE_CHECKED_KEY) && intent.hasExtra(KEY_FILE_CHECKED_KEY)
&& intent.hasExtra(KEY_FILE_KEY) && intent.hasExtra(KEY_FILE_KEY)
) { ) {
val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY) val databaseUri: Uri? = intent.getParcelableExtra(DATABASE_URI_KEY)
val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY) val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY)
if (databaseUri == null)
return null
return CreateDatabaseRunnable(this, return CreateDatabaseRunnable(this,
Database.getInstance(), Database.getInstance(),
databaseUri, databaseUri,
@@ -236,12 +241,15 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(FIX_DUPLICATE_UUID_KEY) && intent.hasExtra(FIX_DUPLICATE_UUID_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY) val databaseUri: Uri? = intent.getParcelableExtra(DATABASE_URI_KEY)
val masterPassword: String? = intent.getStringExtra(MASTER_PASSWORD_KEY) val masterPassword: String? = intent.getStringExtra(MASTER_PASSWORD_KEY)
val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY) val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY)
val readOnly: Boolean = intent.getBooleanExtra(READ_ONLY_KEY, true) val readOnly: Boolean = intent.getBooleanExtra(READ_ONLY_KEY, true)
val cipherEntity: CipherDatabaseEntity? = intent.getParcelableExtra(CIPHER_ENTITY_KEY) val cipherEntity: CipherDatabaseEntity? = intent.getParcelableExtra(CIPHER_ENTITY_KEY)
if (databaseUri == null)
return null
return LoadDatabaseRunnable( return LoadDatabaseRunnable(
this, this,
database, database,
@@ -275,9 +283,10 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(KEY_FILE_CHECKED_KEY) && intent.hasExtra(KEY_FILE_CHECKED_KEY)
&& intent.hasExtra(KEY_FILE_KEY) && intent.hasExtra(KEY_FILE_KEY)
) { ) {
val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY) ?: return null
AssignPasswordInDatabaseRunnable(this, AssignPasswordInDatabaseRunnable(this,
Database.getInstance(), Database.getInstance(),
intent.getParcelableExtra(DATABASE_URI_KEY), databaseUri,
intent.getBooleanExtra(MASTER_PASSWORD_CHECKED_KEY, false), intent.getBooleanExtra(MASTER_PASSWORD_CHECKED_KEY, false),
intent.getStringExtra(MASTER_PASSWORD_KEY), intent.getStringExtra(MASTER_PASSWORD_KEY),
intent.getBooleanExtra(KEY_FILE_CHECKED_KEY, false), intent.getBooleanExtra(KEY_FILE_CHECKED_KEY, false),
@@ -304,10 +313,17 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(SAVE_DATABASE_KEY) && intent.hasExtra(SAVE_DATABASE_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
database.getGroupById(intent.getParcelableExtra(PARENT_ID_KEY))?.let { parent -> val parentId: NodeId<*>? = intent.getParcelableExtra(PARENT_ID_KEY)
val newGroup: Group? = intent.getParcelableExtra(GROUP_KEY)
if (parentId == null
|| newGroup == null)
return null
database.getGroupById(parentId)?.let { parent ->
AddGroupRunnable(this, AddGroupRunnable(this,
database, database,
intent.getParcelableExtra(GROUP_KEY), newGroup,
parent, parent,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false), intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodesRunnable()) AfterActionNodesRunnable())
@@ -323,8 +339,14 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(SAVE_DATABASE_KEY) && intent.hasExtra(SAVE_DATABASE_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
database.getGroupById(intent.getParcelableExtra(GROUP_ID_KEY))?.let { oldGroup -> val groupId: NodeId<*>? = intent.getParcelableExtra(GROUP_ID_KEY)
val newGroup: Group = intent.getParcelableExtra(GROUP_KEY) val newGroup: Group? = intent.getParcelableExtra(GROUP_KEY)
if (groupId == null
|| newGroup == null)
return null
database.getGroupById(groupId)?.let { oldGroup ->
UpdateGroupRunnable(this, UpdateGroupRunnable(this,
database, database,
oldGroup, oldGroup,
@@ -343,10 +365,17 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(SAVE_DATABASE_KEY) && intent.hasExtra(SAVE_DATABASE_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
database.getGroupById(intent.getParcelableExtra(PARENT_ID_KEY))?.let { parent -> val parentId: NodeId<*>? = intent.getParcelableExtra(PARENT_ID_KEY)
val newEntry: Entry? = intent.getParcelableExtra(ENTRY_KEY)
if (parentId == null
|| newEntry == null)
return null
database.getGroupById(parentId)?.let { parent ->
AddEntryRunnable(this, AddEntryRunnable(this,
database, database,
intent.getParcelableExtra(ENTRY_KEY), newEntry,
parent, parent,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false), intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodesRunnable()) AfterActionNodesRunnable())
@@ -362,8 +391,14 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(SAVE_DATABASE_KEY) && intent.hasExtra(SAVE_DATABASE_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
database.getEntryById(intent.getParcelableExtra(ENTRY_ID_KEY))?.let { oldEntry -> val entryId: NodeId<UUID>? = intent.getParcelableExtra(ENTRY_ID_KEY)
val newEntry: Entry = intent.getParcelableExtra(ENTRY_KEY) val newEntry: Entry? = intent.getParcelableExtra(ENTRY_KEY)
if (entryId == null
|| newEntry == null)
return null
database.getEntryById(entryId)?.let { oldEntry ->
UpdateEntryRunnable(this, UpdateEntryRunnable(this,
database, database,
oldEntry, oldEntry,
@@ -383,7 +418,9 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(SAVE_DATABASE_KEY) && intent.hasExtra(SAVE_DATABASE_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
database.getGroupById(intent.getParcelableExtra(PARENT_ID_KEY))?.let { newParent -> val parentId: NodeId<*> = intent.getParcelableExtra(PARENT_ID_KEY) ?: return null
database.getGroupById(parentId)?.let { newParent ->
CopyNodesRunnable(this, CopyNodesRunnable(this,
database, database,
getListNodesFromBundle(database, intent.extras!!), getListNodesFromBundle(database, intent.extras!!),
@@ -403,7 +440,9 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(SAVE_DATABASE_KEY) && intent.hasExtra(SAVE_DATABASE_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
database.getGroupById(intent.getParcelableExtra(PARENT_ID_KEY))?.let { newParent -> val parentId: NodeId<*> = intent.getParcelableExtra(PARENT_ID_KEY) ?: return null
database.getGroupById(parentId)?.let { newParent ->
MoveNodesRunnable(this, MoveNodesRunnable(this,
database, database,
getListNodesFromBundle(database, intent.extras!!), getListNodesFromBundle(database, intent.extras!!),
@@ -438,7 +477,9 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(SAVE_DATABASE_KEY) && intent.hasExtra(SAVE_DATABASE_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
database.getEntryById(intent.getParcelableExtra(ENTRY_ID_KEY))?.let { mainEntry -> val entryId: NodeId<UUID> = intent.getParcelableExtra(ENTRY_ID_KEY) ?: return null
database.getEntryById(entryId)?.let { mainEntry ->
RestoreEntryHistoryDatabaseRunnable(this, RestoreEntryHistoryDatabaseRunnable(this,
database, database,
mainEntry, mainEntry,
@@ -456,7 +497,9 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(SAVE_DATABASE_KEY) && intent.hasExtra(SAVE_DATABASE_KEY)
) { ) {
val database = Database.getInstance() val database = Database.getInstance()
database.getEntryById(intent.getParcelableExtra(ENTRY_ID_KEY))?.let { mainEntry -> val entryId: NodeId<UUID> = intent.getParcelableExtra(ENTRY_ID_KEY) ?: return null
database.getEntryById(entryId)?.let { mainEntry ->
DeleteEntryHistoryDatabaseRunnable(this, DeleteEntryHistoryDatabaseRunnable(this,
database, database,
mainEntry, mainEntry,
@@ -472,10 +515,18 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
return if (intent.hasExtra(OLD_ELEMENT_KEY) return if (intent.hasExtra(OLD_ELEMENT_KEY)
&& intent.hasExtra(NEW_ELEMENT_KEY) && intent.hasExtra(NEW_ELEMENT_KEY)
&& intent.hasExtra(SAVE_DATABASE_KEY)) { && intent.hasExtra(SAVE_DATABASE_KEY)) {
val oldElement: CompressionAlgorithm? = intent.getParcelableExtra(OLD_ELEMENT_KEY)
val newElement: CompressionAlgorithm? = intent.getParcelableExtra(NEW_ELEMENT_KEY)
if (oldElement == null
|| newElement == null)
return null
return UpdateCompressionBinariesDatabaseRunnable(this, return UpdateCompressionBinariesDatabaseRunnable(this,
Database.getInstance(), Database.getInstance(),
intent.getParcelableExtra(OLD_ELEMENT_KEY), oldElement,
intent.getParcelableExtra(NEW_ELEMENT_KEY), newElement,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false) intent.getBooleanExtra(SAVE_DATABASE_KEY, false)
).apply { ).apply {
mAfterSaveDatabase = { result -> mAfterSaveDatabase = { result ->

View File

@@ -62,7 +62,9 @@ class KeyboardEntryNotificationService : LockNotificationService() {
else -> { else -> {
notificationManager?.cancel(notificationId) notificationManager?.cancel(notificationId)
if (intent.hasExtra(ENTRY_INFO_KEY)) { if (intent.hasExtra(ENTRY_INFO_KEY)) {
newNotification(intent.getParcelableExtra(ENTRY_INFO_KEY)) intent.getParcelableExtra<EntryInfo>(ENTRY_INFO_KEY)?.let {
newNotification(it)
}
} }
} }
} }

View File

@@ -281,8 +281,10 @@ object OtpEntryFields {
// malformed // malformed
return false return false
} }
otpElement.period = matcher.group(1).toIntOrNull() ?: TOTP_DEFAULT_PERIOD otpElement.period = matcher.group(1)?.toIntOrNull() ?: TOTP_DEFAULT_PERIOD
otpElement.tokenType = OtpTokenType.getFromString(matcher.group(2)) otpElement.tokenType = matcher.group(2)?.let {
OtpTokenType.getFromString(it)
} ?: OtpTokenType.RFC6238
} }
} catch (exception: Exception) { } catch (exception: Exception) {
return false return false

View File

@@ -276,6 +276,9 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
private fun onCreateAppearancePreferences(rootKey: String?) { private fun onCreateAppearancePreferences(rootKey: String?) {
setPreferencesFromResource(R.xml.preferences_appearance, rootKey) setPreferencesFromResource(R.xml.preferences_appearance, rootKey)
// To change list items appearance
PreferencesUtil.APPEARANCE_CHANGED = true
activity?.let { activity -> activity?.let { activity ->
findPreference<ListPreference>(getString(R.string.setting_style_key))?.setOnPreferenceChangeListener { _, newValue -> findPreference<ListPreference>(getString(R.string.setting_style_key))?.setOnPreferenceChangeListener { _, newValue ->
var styleEnabled = true var styleEnabled = true

View File

@@ -20,7 +20,8 @@
package com.kunzisoft.keepass.settings package com.kunzisoft.keepass.settings
import android.content.Context import android.content.Context
import android.preference.PreferenceManager import android.net.Uri
import androidx.preference.PreferenceManager
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.SortNodeEnum import com.kunzisoft.keepass.database.element.SortNodeEnum
import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.timeout.TimeoutHelper
@@ -28,6 +29,40 @@ import java.util.*
object PreferencesUtil { object PreferencesUtil {
var APPEARANCE_CHANGED = false
private const val KEY_DEFAULT_DATABASE_PATH = "KEY_DEFAULT_DATABASE_PATH"
fun saveDefaultDatabasePath(context: Context, defaultDatabaseUri: Uri?) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs?.edit()?.apply {
defaultDatabaseUri?.let {
putString(KEY_DEFAULT_DATABASE_PATH, it.toString())
} ?: kotlin.run {
remove(KEY_DEFAULT_DATABASE_PATH)
}
apply()
}
}
fun getDefaultDatabasePath(context: Context): String? {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getString(KEY_DEFAULT_DATABASE_PATH, "")
}
fun saveNodeSort(context: Context,
sortNodeEnum: SortNodeEnum,
sortNodeParameters: SortNodeEnum.SortNodeParameters) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs?.edit()?.apply {
putString(context.getString(R.string.sort_node_key), sortNodeEnum.name)
putBoolean(context.getString(R.string.sort_ascending_key), sortNodeParameters.ascending)
putBoolean(context.getString(R.string.sort_group_before_key), sortNodeParameters.groupsBefore)
putBoolean(context.getString(R.string.sort_recycle_bin_bottom_key), sortNodeParameters.recycleBinBottom)
apply()
}
}
fun rememberDatabaseLocations(context: Context): Boolean { fun rememberDatabaseLocations(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.remember_database_locations_key), return prefs.getBoolean(context.getString(R.string.remember_database_locations_key),
@@ -147,6 +182,13 @@ object PreferencesUtil {
} }
} }
fun getClipboardTimeout(context: Context): Long {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getString(context.getString(R.string.clipboard_timeout_key),
context.getString(R.string.clipboard_timeout_default))?.toLong()
?: TimeoutHelper.DEFAULT_TIMEOUT
}
fun isLockDatabaseWhenScreenShutOffEnable(context: Context): Boolean { fun isLockDatabaseWhenScreenShutOffEnable(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.lock_database_screen_off_key), return prefs.getBoolean(context.getString(R.string.lock_database_screen_off_key),

View File

@@ -120,7 +120,7 @@ class HashedBlockInputStream(inputStream: InputStream) : InputStream() {
} }
val computedHash = messageDigest.digest(buffer) val computedHash = messageDigest.digest(buffer)
if (computedHash == null || computedHash.size != HASH_SIZE) { if (computedHash.size != HASH_SIZE) {
throw IOException("Hash wrong size") throw IOException("Hash wrong size")
} }

View File

@@ -23,6 +23,7 @@ import java.io.IOException
import java.io.OutputStream import java.io.OutputStream
import java.security.MessageDigest import java.security.MessageDigest
import java.security.NoSuchAlgorithmException import java.security.NoSuchAlgorithmException
import kotlin.math.min
class HashedBlockOutputStream : OutputStream { class HashedBlockOutputStream : OutputStream {
@@ -61,11 +62,11 @@ class HashedBlockOutputStream : OutputStream {
override fun close() { override fun close() {
if (bufferPos != 0) { if (bufferPos != 0) {
// Write remaining buffered amount // Write remaining buffered amount
WriteHashedBlock() writeHashedBlock()
} }
// Write terminating block // Write terminating block
WriteHashedBlock() writeHashedBlock()
flush() flush()
baseStream!!.close() baseStream!!.close()
@@ -82,12 +83,12 @@ class HashedBlockOutputStream : OutputStream {
var counter = count var counter = count
while (counter > 0) { while (counter > 0) {
if (bufferPos == buffer!!.size) { if (bufferPos == buffer!!.size) {
WriteHashedBlock() writeHashedBlock()
} }
val copyLen = Math.min(buffer!!.size - bufferPos, counter) val copyLen = min(buffer!!.size - bufferPos, counter)
System.arraycopy(b, currentOffset, buffer, bufferPos, copyLen) System.arraycopy(b, currentOffset, buffer!!, bufferPos, copyLen)
currentOffset += copyLen currentOffset += copyLen
bufferPos += copyLen bufferPos += copyLen
@@ -97,21 +98,21 @@ class HashedBlockOutputStream : OutputStream {
} }
@Throws(IOException::class) @Throws(IOException::class)
private fun WriteHashedBlock() { private fun writeHashedBlock() {
baseStream!!.writeUInt(bufferIndex) baseStream!!.writeUInt(bufferIndex)
bufferIndex++ bufferIndex++
if (bufferPos > 0) { if (bufferPos > 0) {
var md: MessageDigest? = null val messageDigest: MessageDigest
try { try {
md = MessageDigest.getInstance("SHA-256") messageDigest = MessageDigest.getInstance("SHA-256")
} catch (e: NoSuchAlgorithmException) { } catch (e: NoSuchAlgorithmException) {
throw IOException("SHA-256 not implemented here.") throw IOException("SHA-256 not implemented here.")
} }
val hash: ByteArray val hash: ByteArray
md!!.update(buffer, 0, bufferPos) messageDigest.update(buffer!!, 0, bufferPos)
hash = md.digest() hash = messageDigest.digest()
/* /*
if ( bufferPos == buffer.length) { if ( bufferPos == buffer.length) {
hash = md.digest(buffer); hash = md.digest(buffer);

View File

@@ -25,7 +25,6 @@ import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import android.preference.PreferenceManager
import android.text.SpannableString import android.text.SpannableString
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.text.util.Linkify import android.text.util.Linkify
@@ -33,6 +32,7 @@ import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import com.kunzisoft.keepass.R import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.exception.ClipboardException import com.kunzisoft.keepass.database.exception.ClipboardException
import com.kunzisoft.keepass.settings.PreferencesUtil
import java.util.* import java.util.*
class ClipboardHelper(private val context: Context) { class ClipboardHelper(private val context: Context) {
@@ -58,13 +58,9 @@ class ClipboardHelper(private val context: Context) {
return return
} }
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val clipboardTimeout = PreferencesUtil.getClipboardTimeout(context)
val sClipClear = prefs.getString(context.getString(R.string.clipboard_timeout_key), if (clipboardTimeout > 0) {
context.getString(R.string.clipboard_timeout_default)) mTimer.schedule(ClearClipboardTask(context, text), clipboardTimeout)
val clipClearTime = (sClipClear ?: "300000").toLong()
if (clipClearTime > 0) {
mTimer.schedule(ClearClipboardTask(context, text), clipClearTime)
} }
} }
@@ -89,7 +85,7 @@ class ClipboardHelper(private val context: Context) {
@Throws(ClipboardException::class) @Throws(ClipboardException::class)
fun copyToClipboard(label: String, value: String) { fun copyToClipboard(label: String, value: String) {
try { try {
getClipboardManager()?.primaryClip = ClipData.newPlainText(label, value) getClipboardManager()?.setPrimaryClip(ClipData.newPlainText(label, value))
} catch (e: Exception) { } catch (e: Exception) {
throw ClipboardException(e) throw ClipboardException(e)
} }

View File

@@ -100,5 +100,5 @@ object ParcelableUtil {
inline fun <reified T : Enum<T>> Parcel.readEnum() = inline fun <reified T : Enum<T>> Parcel.readEnum() =
readString()?.let { enumValueOf<T>(it) } readString()?.let { enumValueOf<T>(it) }
inline fun <T : Enum<T>> Parcel.writeEnum(value: T?) = fun <T : Enum<T>> Parcel.writeEnum(value: T?) =
writeString(value?.name) writeString(value?.name)

View File

@@ -42,7 +42,7 @@ object UriUtil {
return false return false
return try { return try {
//https://developer.android.com/reference/android/content/res/AssetFileDescriptor //https://developer.android.com/reference/android/content/res/AssetFileDescriptor
contentResolver.openAssetFileDescriptor(fileUri, "r")?.close() contentResolver.openInputStream(fileUri)?.close()
true true
} catch (e: Exception) { } catch (e: Exception) {
Log.e(UriUtil.javaClass.name, "Unable to access uri $fileUri : ${e.message}") Log.e(UriUtil.javaClass.name, "Unable to access uri $fileUri : ${e.message}")
@@ -50,16 +50,11 @@ object UriUtil {
} }
} }
fun isUriNotWritable(contentResolver: ContentResolver, fileUri: Uri?): Boolean { fun isUriWritable(contentResolver: ContentResolver, fileUri: Uri?): Boolean {
if (fileUri == null) if (fileUri == null)
return true return false
return try { // TODO Uri writeable detection
contentResolver.openAssetFileDescriptor(fileUri, "wa")?.close() return true
false
} catch (e: Exception) {
Log.e(UriUtil.javaClass.name, "Unable to access uri $fileUri : ${e.message}")
true
}
} }
fun getFileData(context: Context, fileUri: Uri?): DocumentFile? { fun getFileData(context: Context, fileUri: Uri?): DocumentFile? {

View File

@@ -103,7 +103,7 @@ class EntryEditCustomField @JvmOverloads constructor(context: Context,
parent.removeView(this) parent.removeView(this)
parent.invalidate() parent.invalidate()
} catch (e: ClassCastException) { } catch (e: ClassCastException) {
Log.e(javaClass.name, e.message) Log.e(javaClass.name, "Unable to delete view", e)
} }
} }
} }

View File

@@ -384,7 +384,7 @@ typedef struct _master_key {
} master_key; } master_key;
void *generate_key_material(void *arg) { uint32_t generate_key_material(void *arg) {
#if defined(KPD_PROFILE) #if defined(KPD_PROFILE)
struct timespec start, end; struct timespec start, end;
#endif #endif
@@ -435,7 +435,7 @@ void *generate_key_material(void *arg) {
pthread_mutex_unlock(&mk->lock2); pthread_mutex_unlock(&mk->lock2);
} }
return (void *)flip; return flip;
} }
JNIEXPORT jbyteArray JNICALL Java_com_kunzisoft_keepass_crypto_finalkey_NativeFinalKey_nTransformMasterKey(JNIEnv *env, jobject this, jbyteArray seed, jbyteArray key, jlong rounds) { JNIEXPORT jbyteArray JNICALL Java_com_kunzisoft_keepass_crypto_finalkey_NativeFinalKey_nTransformMasterKey(JNIEnv *env, jobject this, jbyteArray seed, jbyteArray key, jlong rounds) {
@@ -474,12 +474,12 @@ JNIEXPORT jbyteArray JNICALL Java_com_kunzisoft_keepass_crypto_finalkey_NativeFi
(*env)->GetByteArrayRegion(env, key, 0, MASTER_KEY_SIZE, (jbyte *)mk.key1); (*env)->GetByteArrayRegion(env, key, 0, MASTER_KEY_SIZE, (jbyte *)mk.key1);
// step 2: encrypt the hash "rounds" (default: 6000) times // step 2: encrypt the hash "rounds" (default: 6000) times
iret = pthread_create( &t1, NULL, generate_key_material, (void*)&mk ); iret = pthread_create( &t1, NULL, (void*)generate_key_material, (void*)&mk );
if( iret != 0 ) { if( iret != 0 ) {
(*env)->ThrowNew(env, bad_arg, "TransformMasterKey: failed to launch thread 1"); // FIXME: get a better exception class for this... (*env)->ThrowNew(env, bad_arg, "TransformMasterKey: failed to launch thread 1"); // FIXME: get a better exception class for this...
return NULL; return NULL;
} }
iret = pthread_create( &t2, NULL, generate_key_material, (void*)&mk ); iret = pthread_create( &t2, NULL, (void*)generate_key_material, (void*)&mk );
if( iret != 0 ) { if( iret != 0 ) {
(*env)->ThrowNew(env, bad_arg, "TransformMasterKey: failed to launch thread 2"); // FIXME: get a better exception class for this... (*env)->ThrowNew(env, bad_arg, "TransformMasterKey: failed to launch thread 2"); // FIXME: get a better exception class for this...
return NULL; return NULL;

View File

@@ -450,7 +450,7 @@
<string name="keyboard_auto_go_action_summary">Automatická akce klíče Jít po stisknutí klíče Pole</string> <string name="keyboard_auto_go_action_summary">Automatická akce klíče Jít po stisknutí klíče Pole</string>
<string name="download_attachment">Stáhnout %1$s</string> <string name="download_attachment">Stáhnout %1$s</string>
<string name="download_initialization">Zahajuji…</string> <string name="download_initialization">Zahajuji…</string>
<string name="download_progression">Probíhá: %1$d%</string> <string name="download_progression">Probíhá: %1$d&#37;</string>
<string name="download_finalization">Dokončuji…</string> <string name="download_finalization">Dokončuji…</string>
<string name="download_complete">Ukončeno! Klepnout pro otevření souboru.</string> <string name="download_complete">Ukončeno! Klepnout pro otevření souboru.</string>
<string name="hide_expired_entries_title">Skrýt propadlé záznamy</string> <string name="hide_expired_entries_title">Skrýt propadlé záznamy</string>

View File

@@ -449,7 +449,7 @@
<string name="keyboard_auto_go_action_summary">Handling af Gå-tasten udføres automatisk, efter der er trykket på en Felt nøgle</string> <string name="keyboard_auto_go_action_summary">Handling af Gå-tasten udføres automatisk, efter der er trykket på en Felt nøgle</string>
<string name="download_attachment">Hent %1$s</string> <string name="download_attachment">Hent %1$s</string>
<string name="download_initialization">Initialiserer…</string> <string name="download_initialization">Initialiserer…</string>
<string name="download_progression">I gang: %1$d%</string> <string name="download_progression">I gang: %1$d&#37;</string>
<string name="download_finalization">Færdiggørelse…</string> <string name="download_finalization">Færdiggørelse…</string>
<string name="download_complete">Komplet! Tryk for at åbne filen.</string> <string name="download_complete">Komplet! Tryk for at åbne filen.</string>
<string name="hide_expired_entries_title">Skjul udløbne poster</string> <string name="hide_expired_entries_title">Skjul udløbne poster</string>

View File

@@ -453,7 +453,7 @@
<string name="keyboard_auto_go_action_summary">Aktion der Go-Taste, die automatisch nach dem Drücken einer Feldtaste ausgeführt wird</string> <string name="keyboard_auto_go_action_summary">Aktion der Go-Taste, die automatisch nach dem Drücken einer Feldtaste ausgeführt wird</string>
<string name="download_attachment">%1$s herunterladen</string> <string name="download_attachment">%1$s herunterladen</string>
<string name="download_initialization">Initialisieren…</string> <string name="download_initialization">Initialisieren…</string>
<string name="download_progression">Fortschritt: %1$d%</string> <string name="download_progression">Fortschritt: %1$d&#37;</string>
<string name="download_finalization">Fertigstellung…</string> <string name="download_finalization">Fertigstellung…</string>
<string name="download_complete">Vollständig! Tippen Sie, um die Datei zu öffnen.</string> <string name="download_complete">Vollständig! Tippen Sie, um die Datei zu öffnen.</string>
<string name="hide_expired_entries_title">Abgelaufene Einträge ausblenden</string> <string name="hide_expired_entries_title">Abgelaufene Einträge ausblenden</string>

View File

@@ -449,7 +449,7 @@
<string name="keyboard_auto_go_action_summary">Η ενέργεια του πλήκτρου Go γίνεται αυτόματα αφού πατήσετε ένα πλήκτρο πεδίου</string> <string name="keyboard_auto_go_action_summary">Η ενέργεια του πλήκτρου Go γίνεται αυτόματα αφού πατήσετε ένα πλήκτρο πεδίου</string>
<string name="download_attachment">Λήψη %1$s</string> <string name="download_attachment">Λήψη %1$s</string>
<string name="download_initialization">Αρχικοποίηση…</string> <string name="download_initialization">Αρχικοποίηση…</string>
<string name="download_progression">Σε εξέλιξη: %1$d%</string> <string name="download_progression">Σε εξέλιξη: %1$d&#37;</string>
<string name="download_finalization">Ολοκλήρωση…</string> <string name="download_finalization">Ολοκλήρωση…</string>
<string name="download_complete">Ολοκληρώθηκε! Πατήστε για να ανοίξετε το αρχείο.</string> <string name="download_complete">Ολοκληρώθηκε! Πατήστε για να ανοίξετε το αρχείο.</string>
<string name="hide_expired_entries_title">Απόκρυψη καταχωρίσεων που έχουν λήξει</string> <string name="hide_expired_entries_title">Απόκρυψη καταχωρίσεων που έχουν λήξει</string>

View File

@@ -460,9 +460,23 @@
<string name="keyboard_auto_go_action_summary">Action de la touche Go effectuée automatiquement après avoir appuyé sur une touche de champ</string> <string name="keyboard_auto_go_action_summary">Action de la touche Go effectuée automatiquement après avoir appuyé sur une touche de champ</string>
<string name="download_attachment">Téléchargement %1$s</string> <string name="download_attachment">Téléchargement %1$s</string>
<string name="download_initialization">Initialisation…</string> <string name="download_initialization">Initialisation…</string>
<string name="download_progression">En cours : %1$d%</string> <string name="download_progression">En cours : %1$d&#37;</string>
<string name="download_finalization">Finalisation…</string> <string name="download_finalization">Finalisation…</string>
<string name="download_complete">Terminé ! Appuyer pour ouvrir le fichier.</string> <string name="download_complete">Terminé ! Appuyer pour ouvrir le fichier.</string>
<string name="hide_expired_entries_title">Masquer les entrées expirées</string> <string name="hide_expired_entries_title">Masquer les entrées expirées</string>
<string name="hide_expired_entries_summary">Les entrées expirées seront masquées</string> <string name="hide_expired_entries_summary">Les entrées expirées seront masquées</string>
<string name="contact">Contact</string>
<string name="contribution">Contribution</string>
<string name="html_about_contribution">Afin de &lt;strong&gt;garder notre liberté&lt;/strong&gt;, &lt;strong&gt;corriger les bugs&lt;/strong&gt;, &lt;strong&gt;ajouter des fonctionnalités&lt;/strong&gt; et &lt;strong&gt;être toujours actif&lt;/strong&gt;, nous comptons sur votre &lt;strong&gt;contribution&lt;/strong&gt;.</string>
<string name="auto_focus_search_title">Recherche rapide</string>
<string name="auto_focus_search_summary">Demander une recherche lors de l\'ouverture d\'une base de données</string>
<string name="remember_database_locations_title">Enregistrer l\'emplacement des bases de données</string>
<string name="remember_database_locations_summary">Se souvenir de l\'emplacement des bases de données</string>
<string name="remember_keyfile_locations_title">Enregistrer l\'emplacement des fichiers clés</string>
<string name="remember_keyfile_locations_summary">Se souvenir de l\'emplacement des fichiers de clés des bases de données</string>
<string name="show_recent_files_title">Afficher les fichiers récents</string>
<string name="show_recent_files_summary">Afficher les emplacements des bases de données récentes</string>
<string name="hide_broken_locations_title">Masquer les liens rompus de base de données</string>
<string name="hide_broken_locations_summary">Masquer les liens rompus dans la liste des bases de données récentes</string>
<string name="warning_database_read_only">Accorder un accès en écriture au fichier pour enregistrer les modifications de la base de données</string>
</resources> </resources>

View File

@@ -408,7 +408,7 @@
<string name="menu_restore_entry_history">Gjenopprett historikk</string> <string name="menu_restore_entry_history">Gjenopprett historikk</string>
<string name="menu_delete_entry_history">Slett historikk</string> <string name="menu_delete_entry_history">Slett historikk</string>
<string name="download_attachment">Last ned %1$s</string> <string name="download_attachment">Last ned %1$s</string>
<string name="download_progression">Underveis: %1$d%</string> <string name="download_progression">Underveis: %1$d&#37;</string>
<string name="download_finalization">Fullfører…</string> <string name="download_finalization">Fullfører…</string>
<string name="download_complete">Fullført. Trykk for å åpne filen.</string> <string name="download_complete">Fullført. Trykk for å åpne filen.</string>
<string name="hide_expired_entries_title">Skjul utløpte oppføringer</string> <string name="hide_expired_entries_title">Skjul utløpte oppføringer</string>

View File

@@ -449,7 +449,7 @@
<string name="keyboard_auto_go_action_summary">Działanie klawisza Go wykonywane jest automatycznie po naciśnięciu klawisza Field</string> <string name="keyboard_auto_go_action_summary">Działanie klawisza Go wykonywane jest automatycznie po naciśnięciu klawisza Field</string>
<string name="download_attachment">Pobierz %1$s</string> <string name="download_attachment">Pobierz %1$s</string>
<string name="download_initialization">Inicjowanie…</string> <string name="download_initialization">Inicjowanie…</string>
<string name="download_progression">W trakcie realizacji: %1$d%</string> <string name="download_progression">W trakcie realizacji: %1$d&#37;</string>
<string name="download_finalization">Kończę…</string> <string name="download_finalization">Kończę…</string>
<string name="download_complete">Kompletny! Stuknij, aby otworzyć plik.</string> <string name="download_complete">Kompletny! Stuknij, aby otworzyć plik.</string>
<string name="hide_expired_entries_title">Ukryj wygasłe wpisy</string> <string name="hide_expired_entries_title">Ukryj wygasłe wpisy</string>

View File

@@ -1,2 +1,178 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="about_description">Implementarea Android a managerului de parole KeePass</string>
<string name="accept">Accept</string>
<string name="add_entry">Introduce intrarea</string>
<string name="edit_entry">Editeaza intrarea</string>
<string name="add_group">Aduce grup</string>
<string name="master_key">Cheia generala</string>
<string name="security">Securitate</string>
<string name="encryption">Criptare</string>
<string name="encryption_algorithm">Algoritm de criptare</string>
<string name="key_derivation_function">Functie derivata a cheii</string>
<string name="app_timeout">Timpul aplicatiei a expirat</string>
<string name="app_timeout_summary">Timpul de asteptare inaintea blocarii bancii de date</string>
<string name="application">Aplicatie</string>
<string name="beta_dontask">Nu mai arata inca odata</string>
<string name="brackets">Paranteze patrate</string>
<string name="extended_ASCII">ASCII extins</string>
<string name="file_manager_install_description">Un manager de fișiere care acceptă acțiunea de creeare ACTION_CREATE_DOCUMENT si ACTION_OPEN_DOCUMENT este necesara sa creeze ,deschida si salveze fisierele din banca de date</string>
<string name="allow">Permite</string>
<string name="clipboard_cleared">Carnetelul din memorie curatat</string>
<string name="clipboard_error_title">Eroare de citire copiere memorie</string>
<string name="clipboard_error">Unele dispozitive nu permit aplicatiei sa foloseasca memoria de citire din carnetel.</string>
<string name="clipboard_error_clear">Nu s-a putut curata memoria carnetelului</string>
<string name="clipboard_timeout">Timp expirat de citire a carnetelului</string>
<string name="clipboard_timeout_summary">Durata de memorare din carnetel</string>
<string name="clipboard_swipe_clean">Schimba ca sa cureti carnetelul acum</string>
<string name="content_description_background">In spate</string>
<string name="content_description_open_file">Deschide fisier</string>
<string name="content_description_node_children">Copil nod</string>
<string name="content_description_add_node">Introduce nod</string>
<string name="content_description_add_entry">Introduce o intrare</string>
<string name="content_description_add_group">Aduce un grup</string>
<string name="content_description_file_information">Informatia fisierului</string>
<string name="content_description_password_checkbox">Verifica parola</string>
<string name="content_description_keyfile_checkbox">Verifica fisierul cheie</string>
<string name="content_description_repeat_toggle_password_visibility">Repetați pentru a comuta vizibilitatea parolei</string>
<string name="content_description_entry_icon">Pictograma de intrare</string>
<string name="content_description_entry_save">Salvați intrarea</string>
<string name="content_description_password_generator">Generator de parole</string>
<string name="content_description_password_length">Lungimea parolei</string>
<string name="content_description_add_field">Adăugați câmp</string>
<string name="content_description_remove_field">Elimina câmp</string>
<string name="content_description_update_from_list">Actualizați</string>
<string name="content_description_remove_from_list">Elimina</string>
<string name="content_description_keyboard_close_fields">Câmpuri închise</string>
<string name="select_to_copy">%1$s is either \\\"Nume\\\" si \\\"Parola\\\".</string>
<string name="retrieving_db_key">Obtinerea cheii bazei de date…</string>
<string name="database">Baza de date</string>
<string name="decrypting_db">Decriptarea continutului bazei de date.…</string>
<string name="contact">Contact</string>
<string name="contribution">Contributie</string>
<string name="feedback">Opinii</string>
<string name="homepage">Pagina acasa</string>
<string name="default_checkbox">Folosiți ca bază de date implicită</string>
<string name="digits">Digits</string>
<string name="entry_accessed">Accesat</string>
<string name="entry_cancel">Anuleaza</string>
<string name="entry_notes">Note</string>
<string name="entry_confpassword">Confirma parola</string>
<string name="entry_created">Creeat</string>
<string name="entry_expires">Expira</string>
<string name="entry_UUID">UUID</string>
<string name="entry_history">Istoric</string>
<string name="entry_attachments">Atasamente</string>
<string name="entry_keyfile">Fisiercheie</string>
<string name="entry_modified">Modificat</string>
<string name="entry_not_found">Nu s-au putut găsi date de intrare.</string>
<string name="entry_password">Parola</string>
<string name="entry_save">Salveaza</string>
<string name="entry_title">Titlu</string>
<string name="entry_setup_otp">Setați o singură parolă</string>
<string name="otp_type">Tipul OTP</string>
<string name="otp_secret">Secret</string>
<string name="otp_period">Perioada(secunde)</string>
<string name="otp_counter">Numaratoare</string>
<string name="otp_digits">Digiti</string>
<string name="otp_algorithm">Algoritm</string>
<string name="entry_otp">OTP</string>
<string name="entry_url">URL</string>
<string name="entry_user_name">Nume utilizator</string>
<string name="error_arc4">Cifrarea fluxului Arcfour nu este acceptată.</string>
<string name="error_can_not_handle_uri">Nu s-a putut gestiona acest URI în KeePassDX.</string>
<string name="error_file_not_create">Nu s-a putut creea fisierul:</string>
<string name="error_invalid_db">Nu s-a putut citi baza de date.</string>
<string name="error_invalid_path">Asigurați-vă că calea este corectă.</string>
<string name="error_invalid_OTP">Secret OTP nevalid.</string>
<string name="error_no_name">Introduce un nume.</string>
<string name="error_nokeyfile">Alege un fisier cheie.</string>
<string name="error_out_of_memory">Nicio memorie pentru a încărca întreaga dvs. bază de date.</string>
<string name="error_load_database">Nu s-a putut încărca baza de date.</string>
<string name="error_load_database_KDF_memory">Nu s-a putut încărca cheia. Încercați să reduceți KDF „Utilizarea memoriei”.</string>
<string name="error_pass_gen_type">Trebuie selectat cel puțin un tip de generare a parolei.</string>
<string name="error_disallow_no_credentials">Trebuie să fie stabilit cel puțin o acreditare.</string>
<string name="error_pass_match">Parolele nu se potrivesc.</string>
<string name="error_rounds_too_large">\"Transformările rotunde\" prea sus. Setarea la 2147483648.</string>
<string name="error_string_key">Fiecare șir trebuie să aibă un nume de câmp.</string>
<string name="error_title_required">Adăugați un titlu.</string>
<string name="error_wrong_length">Introduceți un număr întreg pozitiv în câmpul \"Lungime\".</string>
<string name="error_autofill_enable_service">Nu s-a putut activa serviciul de completare automată.</string>
<string name="error_move_folder_in_itself">Nu puteți muta un grup în sine.</string>
<string name="error_move_entry_here">Nu puteți muta o intrare aici.</string>
<string name="error_copy_entry_here">Nu puteți copia o intrare aici.</string>
<string name="error_copy_group_here">Nu puteți copia un grup aici.</string>
<string name="error_create_database_file">Nu se poate crea baza de date cu această parolă și cu fișierul cheie.</string>
<string name="error_save_database">Nu s-a putut salva baza de date.</string>
<string name="error_otp_secret_key">Cheia secretă trebuie să fie în format Base32.</string>
<string name="error_otp_counter">Contorul trebuie să fie între %1$d and %2$d.</string>
<string name="error_otp_period">Perioada trebuie să fie cuprinsă între%1$d and %2$d seconds.</string>
<string name="error_otp_digits">Tokenul trebuie să conțină cifre de la %1$d to %2$d digits.</string>
<string name="field_name">Numele domeniului</string>
<string name="field_value">Valoarea câmpului</string>
<string name="file_not_found_content">Nu s-a putut găsi fișierul. Încercați să-l redeschideți din browserul de fișiere.</string>
<string name="file_browser">Browser de fișiere</string>
<string name="generate_password">Generați parola</string>
<string name="hint_conf_pass">Confirmă parola</string>
<string name="hint_generated_password">Parola generata</string>
<string name="hint_group_name">Numele Grupului</string>
<string name="hint_keyfile">Fisier cheie</string>
<string name="hint_length">Lungime</string>
<string name="hint_pass">Parola</string>
<string name="password">Parola</string>
<string name="install_from_f_droid">Instalați din F-Droid</string>
<string name="install_from_play_store">Instalați din Play Store</string>
<string name="invalid_credentials">Nu s-a putut citi datele de acreditare. Dacă reîncepe, baza de date a dumneavoastra poate fi coruptă.</string>
<string name="invalid_algorithm">Algoritm greșit.</string>
<string name="invalid_db_same_uuid">%1$s cu același UUID %2$s există deja.</string>
<string name="invalid_db_sig">Nu s-a putut recunoaște formatul bazei de date.</string>
<string name="keyfile_is_empty">Fișierul cheie este gol.</string>
<string name="length">Lungime</string>
<string name="list_entries_show_username_title">Afișați numele de utilizator</string>
<string name="list_entries_show_username_summary">Afișați numele de utilizator în listele de intrare</string>
<string name="list_groups_show_number_entries_title">Afișează numărul de intrări</string>
<string name="list_groups_show_number_entries_summary">Afișează numărul de intrări dintr-un grup</string>
<string name="list_size_title">Mărimea articolelor din listă</string>
<string name="list_size_summary">Dimensiunea textului în lista de elemente</string>
<string name="creating_database">Crearea bazei de date …</string>
<string name="loading_database">Se încarcă baza de date …</string>
<string name="lowercase">Caz jos</string>
<string name="menu_change_key_settings">Schimbă cheia principală</string>
<string name="copy_field">Copie din %1$s</string>
<string name="settings">Setări</string>
<string name="menu_app_settings">Setările aplicației</string>
<string name="menu_form_filling_settings">Completarea formularului</string>
<string name="menu_advanced_unlock_settings">Deblocare avansată</string>
<string name="menu_database_settings">Setările bazei de date</string>
<string name="menu_security_settings">Setări de securitate</string>
<string name="menu_master_key_settings">Setări cheie master</string>
<string name="menu_donate">Donează</string>
<string name="menu_edit">Editați</string>
<string name="menu_copy">Copie</string>
<string name="menu_move">Muta</string>
<string name="menu_paste">Lipeste</string>
<string name="menu_delete">Șterge</string>
<string name="menu_cancel">Anulare</string>
<string name="menu_hide_password">Ascunde parola</string>
<string name="menu_lock">Blocați baza de date</string>
<string name="menu_save_database">Salvați baza de date</string>
<string name="menu_open">Deschide</string>
<string name="menu_search">Căutare</string>
<string name="menu_showpass">Arata parola</string>
<string name="menu_biometric_remove_key">Ștergeți cheia biometrică salvată</string>
<string name="menu_url">Accesați adresa URL</string>
<string name="menu_file_selection_read_only">Protejat la scriere</string>
<string name="menu_open_file_read_and_write">Modificabil</string>
<string name="menu_empty_recycle_bin">Golește coșul de gunoi</string>
<string name="menu_restore_entry_history">Restaurați istoria</string>
<string name="menu_delete_entry_history">Ștergeți istoricul</string>
<string name="minus">Minus</string>
<string name="never">Niciodata</string>
<string name="no_results">Nu există Rezultate</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft is &lt;strong&gt;sursa deschisa&lt;strong&gt; and &lt;strong&gt;fara publicitate&lt;strong&gt;.
\nEste prevăzut așa cum este, sub &lt;strong&gt;GPLv3&lt;strong&gt; licenta,fara nici un fel de garantie.</string>
<string name="html_about_contribution">In oridine sa &lt;strong&gt;pastram libertatea noastra &lt;strong&gt;, &lt;strong&gt;fix bugs&lt;strong&gt;, &lt;strong&gt;adăugați funcții&lt;strong&gt; si&lt;strong&gt;sa fie intotdeauna activ&lt;strong&gt;", ne bazam pe "&lt;strong&gt;contributie.&lt;strong&gt;</string>
<string name="hide_password_title">Ascundeți parolele</string>
<string name="hide_password_summary">Mascați parolele (***) în mod implicit</string>
<string name="about">Despre</string>
</resources>

View File

@@ -38,12 +38,13 @@
<string name="clipboard_timeout">Задержка очистки буфера обмена</string> <string name="clipboard_timeout">Задержка очистки буфера обмена</string>
<string name="clipboard_timeout_summary">Продолжительность хранения в буфере обмена</string> <string name="clipboard_timeout_summary">Продолжительность хранения в буфере обмена</string>
<string name="select_to_copy">Выберите %1$s для копирования в буфер обмена</string> <string name="select_to_copy">Выберите %1$s для копирования в буфер обмена</string>
<string name="retrieving_db_key">Создание ключа базы…</string> <string name="retrieving_db_key">Получение ключа базы…</string>
<string name="database">База</string> <string name="database">База</string>
<string name="decrypting_db">Расшифровка базы…</string> <string name="decrypting_db">Расшифровка базы…</string>
<string name="default_checkbox">База по умолчанию</string> <string name="default_checkbox">База по умолчанию</string>
<string name="digits">Цифры</string> <string name="digits">Цифры</string>
<string name="html_about_licence">Приложение KeePassDX © %1$d Kunzisoft предоставляется без каких-либо гарантий. Распространяется свободно по лицензии GPL v3 или новее.</string> <string name="html_about_licence">KeePassDX © %1$d Kunzisoft с &lt;strong&gt;открытым исходным кодом&lt;strong&gt; и &lt;strong&gt;без рекламы&lt;strong&gt;.
\nРаспространяется под лицензией &lt;strong&gt;GPLv3&lt;strong&gt; без каких-либо гарантий.</string>
<string name="select_database_file">Открыть существующую базу</string> <string name="select_database_file">Открыть существующую базу</string>
<string name="entry_accessed">Доступ</string> <string name="entry_accessed">Доступ</string>
<string name="entry_cancel">Отмена</string> <string name="entry_cancel">Отмена</string>
@@ -115,7 +116,7 @@
<string name="never">Никогда</string> <string name="never">Никогда</string>
<string name="no_results">Совпадения не найдены</string> <string name="no_results">Совпадения не найдены</string>
<string name="no_url_handler">Установите браузер, чтобы открыть этот URL.</string> <string name="no_url_handler">Установите браузер, чтобы открыть этот URL.</string>
<string name="open_recent">Недавно открытые</string> <string name="open_recent">Недавно открытые базы</string>
<string name="omit_backup_search_title">Не искать в резервных копиях</string> <string name="omit_backup_search_title">Не искать в резервных копиях</string>
<string name="omit_backup_search_summary">Не искать в группах \"Резервирование\" и \"Корзина\"</string> <string name="omit_backup_search_summary">Не искать в группах \"Резервирование\" и \"Корзина\"</string>
<string name="progress_create">Создание новой базы…</string> <string name="progress_create">Создание новой базы…</string>
@@ -284,7 +285,7 @@
<string name="education_generate_password_title">Создайте надёжный пароль для записи.</string> <string name="education_generate_password_title">Создайте надёжный пароль для записи.</string>
<string name="education_generate_password_summary">Создайте надёжный пароль, связанный с записью, легко настраиваемый под критерии формы. И не забудьте главный пароль от базы.</string> <string name="education_generate_password_summary">Создайте надёжный пароль, связанный с записью, легко настраиваемый под критерии формы. И не забудьте главный пароль от базы.</string>
<string name="education_entry_new_field_title">Добавляйте настраиваемые поля</string> <string name="education_entry_new_field_title">Добавляйте настраиваемые поля</string>
<string name="education_entry_new_field_summary">Зарегистрируйте дополнительное поле, просто заполнив его, добавьте значение и при необходимости защитите.</string> <string name="education_entry_new_field_summary">Зарегистрируйте дополнительное поле, добавьте значение и при необходимости защитите его.</string>
<string name="education_unlock_title">Разблокируйте базу</string> <string name="education_unlock_title">Разблокируйте базу</string>
<string name="education_read_only_title">База только для чтения</string> <string name="education_read_only_title">База только для чтения</string>
<string name="education_read_only_summary">Изменяйте режим открытия в сессии. <string name="education_read_only_summary">Изменяйте режим открытия в сессии.
@@ -301,7 +302,7 @@
<string name="education_sort_summary">Выберите критерий сортировки записей и групп.</string> <string name="education_sort_summary">Выберите критерий сортировки записей и групп.</string>
<string name="education_donation_title">Участвуйте</string> <string name="education_donation_title">Участвуйте</string>
<string name="education_donation_summary">Примите участие в проекте для повышения стабильности, безопасности и добавления новых возможностей.</string> <string name="education_donation_summary">Примите участие в проекте для повышения стабильности, безопасности и добавления новых возможностей.</string>
<string name="html_text_ad_free">В отличие от многих приложений управления паролями, это &lt;strong&gt;без рекламы&lt;/strong&gt;, &lt;strong&gt;с открытым исходным кодом&lt;/strong&gt; и &lt;strong&gt;свободно от лицензирования&lt;/strong&gt;. Оно &lt;strong&gt;не хранит ваши личные данные&lt;/strong&gt; на своих серверах независимо от того, какую версию (бесплатную или профессиональную) вы используете.</string> <string name="html_text_ad_free">В отличие от многих приложений управления паролями, это &lt;strong&gt;без рекламы&lt;strong&gt; и &lt;strong&gt;свободно от лицензирования&lt;strong&gt;. Оно не собирает ваши личные данные на своих серверах независимо от того, какую версию вы используете.</string>
<string name="html_text_buy_pro">При покупке Pro-версии вы будете иметь доступ к этим &lt;strong&gt;визуальным стилям&lt;/strong&gt; и особенно поможете &lt;strong&gt;реализации общественных проектов&lt;/strong&gt;.</string> <string name="html_text_buy_pro">При покупке Pro-версии вы будете иметь доступ к этим &lt;strong&gt;визуальным стилям&lt;/strong&gt; и особенно поможете &lt;strong&gt;реализации общественных проектов&lt;/strong&gt;.</string>
<string name="html_text_feature_generosity">Эти &lt;strong&gt;визуальные стили&lt;/strong&gt; доступны благодаря вашей щедрости.</string> <string name="html_text_feature_generosity">Эти &lt;strong&gt;визуальные стили&lt;/strong&gt; доступны благодаря вашей щедрости.</string>
<string name="html_text_donation">Для того, чтобы сохранить нашу независимость и быть всегда активными, мы рассчитываем на ваш &lt;strong&gt;вклад&lt;/strong&gt;.</string> <string name="html_text_donation">Для того, чтобы сохранить нашу независимость и быть всегда активными, мы рассчитываем на ваш &lt;strong&gt;вклад&lt;/strong&gt;.</string>
@@ -449,9 +450,23 @@
<string name="keyboard_auto_go_action_summary">Выполнять команду \"Ввод\" автоматически после нажатия кнопки заполнения поля</string> <string name="keyboard_auto_go_action_summary">Выполнять команду \"Ввод\" автоматически после нажатия кнопки заполнения поля</string>
<string name="download_attachment">Скачать %1$s</string> <string name="download_attachment">Скачать %1$s</string>
<string name="download_initialization">Инициализация…</string> <string name="download_initialization">Инициализация…</string>
<string name="download_progression">Выполнение: %1$d%</string> <string name="download_progression">Выполнение: %1$d&#37;</string>
<string name="download_finalization">Завершение…</string> <string name="download_finalization">Завершение…</string>
<string name="download_complete">Готово! Нажмите, чтобы открыть файл.</string> <string name="download_complete">Готово! Нажмите, чтобы открыть файл.</string>
<string name="hide_expired_entries_title">Скрывать устаревшие записи</string> <string name="hide_expired_entries_title">Скрывать устаревшие записи</string>
<string name="hide_expired_entries_summary">Записи с истёкшим сроком окончания будут скрыты</string> <string name="hide_expired_entries_summary">Записи с истёкшим сроком окончания будут скрыты</string>
<string name="contact">Контактная информация</string>
<string name="contribution">Вклад</string>
<string name="html_about_contribution">Для &lt;strong&gt;сохранения нашей независимости&lt;strong&gt;, &lt;strong&gt;исправления ошибок&lt;strong&gt;, &lt;strong&gt;добавления новых функций&lt;strong&gt; и &lt;strong&gt;поддержания разработки в активном состоянии&lt;strong&gt;, мы рассчитываем на ваш &lt;strong&gt;вклад&lt;strong&gt;.</string>
<string name="auto_focus_search_title">Быстрый поиск</string>
<string name="auto_focus_search_summary">Открывать поисковый запрос при открытии базы</string>
<string name="remember_database_locations_title">Хранить расположение баз</string>
<string name="remember_database_locations_summary">Запоминать расположение баз</string>
<string name="remember_keyfile_locations_title">Хранить расположение файлов ключей</string>
<string name="remember_keyfile_locations_summary">Запоминать расположение файлов ключей баз</string>
<string name="show_recent_files_title">Показывать последние базы</string>
<string name="show_recent_files_summary">Показывать расположение последних открытых баз</string>
<string name="hide_broken_locations_title">Скрывать отсутствующие</string>
<string name="hide_broken_locations_summary">Не показывать неработающие ссылки в списке последних открытых баз</string>
<string name="warning_database_read_only">Необходимо разрешение на запись в файл для сохранения изменений базы</string>
</resources> </resources>

View File

@@ -150,8 +150,17 @@
<string name="extended_ASCII">Rozšírené ASCII</string> <string name="extended_ASCII">Rozšírené ASCII</string>
<string name="allow">Povoliť</string> <string name="allow">Povoliť</string>
<string name="clipboard_error_title">Chyba schránky</string> <string name="clipboard_error_title">Chyba schránky</string>
<string name="clipboard_error">Niektoré Samsungy nedovolia aplikáciám používať schránku.</string> <string name="clipboard_error">Niektoré zariadenia nedovolia aplikáciám používať schránku.</string>
<string name="clipboard_error_clear">Nepodarilo sa vymazať schránku</string> <string name="clipboard_error_clear">Nepodarilo sa vymazať schránku</string>
<string name="clipboard_swipe_clean">Schránku vymažete potiahnutím prsta cez políčko</string> <string name="clipboard_swipe_clean">Schránku vymažete potiahnutím prsta cez políčko</string>
<string name="entry_not_found">Nenašli sa údaje záznamu</string> <string name="entry_not_found">Nenašli sa údaje záznamu</string>
<string name="contact">Kontakt</string>
<string name="content_description_open_file">Otvoriť súbor</string>
<string name="content_description_file_information">Informácie o súbore</string>
<string name="content_description_entry_save">Uložiť záznam</string>
<string name="content_description_password_generator">Generátor hesla</string>
<string name="content_description_password_length">Dĺžka hesla</string>
<string name="content_description_background">Pozadie</string>
<string name="security">Bezpečnosť</string>
<string name="contribution">Príspevok</string>
</resources> </resources>

View File

@@ -433,7 +433,7 @@
<string name="keyboard_auto_go_action_summary">Alan tuşuna bastıktan sonra otomatik olarak gerçekleştirilen Git tuşunun eylemi</string> <string name="keyboard_auto_go_action_summary">Alan tuşuna bastıktan sonra otomatik olarak gerçekleştirilen Git tuşunun eylemi</string>
<string name="download_attachment">İndir %1$s</string> <string name="download_attachment">İndir %1$s</string>
<string name="download_initialization">Başlatılıyor…</string> <string name="download_initialization">Başlatılıyor…</string>
<string name="download_progression">Devam ediyor: %1$d%</string> <string name="download_progression">Devam ediyor: %1$d&#37;</string>
<string name="download_finalization">Sonlandırılıyor…</string> <string name="download_finalization">Sonlandırılıyor…</string>
<string name="download_complete">Tamamlandı! Dosyayı açmak için dokunun.</string> <string name="download_complete">Tamamlandı! Dosyayı açmak için dokunun.</string>
<string name="hide_expired_entries_title">Süresi dolmuş girdileri gizle</string> <string name="hide_expired_entries_title">Süresi dolmuş girdileri gizle</string>

View File

@@ -39,7 +39,8 @@
<string name="decrypting_db">正在解密数据库内容…</string> <string name="decrypting_db">正在解密数据库内容…</string>
<string name="default_checkbox">设为默认数据库</string> <string name="default_checkbox">设为默认数据库</string>
<string name="digits">数字</string> <string name="digits">数字</string>
<string name="html_about_licence">磐密码©%1$dKunzisoft程序绝对不带有担保。本程序是自由程序可在遵循GPLv3或者此开源协议的更高版本的情况下重新发布。</string> <string name="html_about_licence">KeePassDX © %1$dKunzisoft的一个&lt;strong&gt;开源&lt;strong&gt;&lt;strong&gt;无广告&lt;strong&gt;软件。
\n它是根据&lt;strong&gt;GPLv3 &lt;strong&gt;许可证分发的您可在遵循GPL 3或者更高版本的协议下重新发布。对软件的质量和性能等问题不提供任何形式的担保。</string>
<string name="select_database_file">打开已有数据库</string> <string name="select_database_file">打开已有数据库</string>
<string name="entry_accessed">访问时间</string> <string name="entry_accessed">访问时间</string>
<string name="entry_cancel">取消</string> <string name="entry_cancel">取消</string>
@@ -55,7 +56,7 @@
<string name="entry_url">链接</string> <string name="entry_url">链接</string>
<string name="entry_user_name">用户名</string> <string name="entry_user_name">用户名</string>
<string name="error_arc4">不支持Arcfour流式加密。</string> <string name="error_arc4">不支持Arcfour流式加密。</string>
<string name="error_can_not_handle_uri">无法在磐密码中处理此URI。</string> <string name="error_can_not_handle_uri">无法在KeePassDX中处理此URI。</string>
<string name="error_file_not_create">无法新建文件:</string> <string name="error_file_not_create">无法新建文件:</string>
<string name="error_invalid_db">无法读取数据库。</string> <string name="error_invalid_db">无法读取数据库。</string>
<string name="error_invalid_path">请确保路径正确。</string> <string name="error_invalid_path">请确保路径正确。</string>
@@ -78,7 +79,7 @@
<string name="hint_pass">密码</string> <string name="hint_pass">密码</string>
<string name="install_from_play_store">从Play商店安装</string> <string name="install_from_play_store">从Play商店安装</string>
<string name="install_from_f_droid">从F-Droid安装</string> <string name="install_from_f_droid">从F-Droid安装</string>
<string name="invalid_credentials">无法读取凭据。如果再次发生,则数据库文件可能已损坏。</string> <string name="invalid_credentials">无法读取您的密码或密钥文件。如果重试后仍然如此,你的数据库可能已损坏。</string>
<string name="invalid_db_sig">无法识别数据库格式。</string> <string name="invalid_db_sig">无法识别数据库格式。</string>
<string name="length">长度</string> <string name="length">长度</string>
<string name="list_size_title">列表项目尺寸</string> <string name="list_size_title">列表项目尺寸</string>
@@ -109,8 +110,8 @@
<string name="content_description_remove_from_list">移除</string> <string name="content_description_remove_from_list">移除</string>
<string name="encryption_rijndael">Rijndael(AES)</string> <string name="encryption_rijndael">Rijndael(AES)</string>
<string name="root">Root</string> <string name="root">Root</string>
<string name="rounds">转换次数</string> <string name="rounds">迭代次数</string>
<string name="rounds_explanation">更多的转换次数能更好地抵抗暴力破解攻击,但也的确会增加读取和保存的时间。</string> <string name="rounds_explanation">更多的迭代次数能更好地抵抗暴力破解攻击,但也会增加读取和保存的时间。</string>
<string name="saving_database">正在保存数据库…</string> <string name="saving_database">正在保存数据库…</string>
<string name="space">空格</string> <string name="space">空格</string>
<string name="search_label">搜索</string> <string name="search_label">搜索</string>
@@ -146,7 +147,7 @@
<string name="extended_ASCII">ASCII拓展区字符</string> <string name="extended_ASCII">ASCII拓展区字符</string>
<string name="allow">允许</string> <string name="allow">允许</string>
<string name="clipboard_error_title">剪切板错误</string> <string name="clipboard_error_title">剪切板错误</string>
<string name="clipboard_error">一些设备不程序使用剪切板。</string> <string name="clipboard_error">一些设备不允许程序使用剪切板。</string>
<string name="clipboard_error_clear">无法清空剪切板</string> <string name="clipboard_error_clear">无法清空剪切板</string>
<string name="clipboard_swipe_clean">滑动以清空剪切板</string> <string name="clipboard_swipe_clean">滑动以清空剪切板</string>
<string name="encryption_chacha20">ChaCha20</string> <string name="encryption_chacha20">ChaCha20</string>
@@ -180,11 +181,11 @@
<string name="omit_backup_search_summary">搜索时忽略“备份”与“回收站”群组</string> <string name="omit_backup_search_summary">搜索时忽略“备份”与“回收站”群组</string>
<string name="protection">保护</string> <string name="protection">保护</string>
<string name="read_only">只读</string> <string name="read_only">只读</string>
<string name="read_only_warning">磐密码需要写入权限以修改数据库。</string> <string name="read_only_warning">KeePassDX需要写入权限以修改数据库。</string>
<string name="show_recent_files_title">最近文件历史</string> <string name="show_recent_files_title">最近文件历史</string>
<string name="show_recent_files_summary">记住最近使用的文件名</string> <string name="show_recent_files_summary">记住最近使用的文件名</string>
<string name="encryption_explanation">加密所有数据时采用的算法。</string> <string name="encryption_explanation">加密所有数据时采用的算法。</string>
<string name="kdf_explanation">转换主密钥以生成加密数据库所需的密钥,转换方式为随机加盐算法。</string> <string name="kdf_explanation">迭代主密钥以生成加密数据库所需的密钥,转换方式为随机加盐算法。</string>
<string name="memory_usage">内存使用量</string> <string name="memory_usage">内存使用量</string>
<string name="memory_usage_explanation">密钥推导算法使用的内存(以二进制字节计)。</string> <string name="memory_usage_explanation">密钥推导算法使用的内存(以二进制字节计)。</string>
<string name="parallelism">并行</string> <string name="parallelism">并行</string>
@@ -203,8 +204,8 @@
<string name="menu_appearance_settings">外观</string> <string name="menu_appearance_settings">外观</string>
<string name="general">常规</string> <string name="general">常规</string>
<string name="autofill">自动填充</string> <string name="autofill">自动填充</string>
<string name="autofill_service_name">磐密码自动填充</string> <string name="autofill_service_name">使用KeePassDX自动填充</string>
<string name="autofill_sign_in_prompt">使用密码登录</string> <string name="autofill_sign_in_prompt">使用KeePassDX密码登录</string>
<string name="clipboard">剪贴板</string> <string name="clipboard">剪贴板</string>
<string name="clipboard_notifications_title">剪贴板通知</string> <string name="clipboard_notifications_title">剪贴板通知</string>
<string name="lock">锁定</string> <string name="lock">锁定</string>
@@ -221,7 +222,7 @@
<string name="application_appearance">程序</string> <string name="application_appearance">程序</string>
<string name="other">其他</string> <string name="other">其他</string>
<string name="keyboard">键盘</string> <string name="keyboard">键盘</string>
<string name="magic_keyboard_title">磐密码键盘</string> <string name="magic_keyboard_title">魔法键盘</string>
<string name="enable_read_only_title">写保护(只读模式)</string> <string name="enable_read_only_title">写保护(只读模式)</string>
<string name="enable_read_only_summary">默认以只读方式打开数据库</string> <string name="enable_read_only_summary">默认以只读方式打开数据库</string>
<string name="download">下载</string> <string name="download">下载</string>
@@ -238,14 +239,14 @@
<string name="warning_empty_password">确定不用密码解锁?</string> <string name="warning_empty_password">确定不用密码解锁?</string>
<string name="warning_no_encryption_key">确认使用空密钥吗?</string> <string name="warning_no_encryption_key">确认使用空密钥吗?</string>
<string name="build_label">版本%1$s</string> <string name="build_label">版本%1$s</string>
<string name="configure_biometric">支持但未配置生物识别。</string> <string name="configure_biometric">支持生物识别设置,但并未启用生物识别。</string>
<string name="open_biometric_prompt_unlock_database">打开生物识别对话框以解锁数据库</string> <string name="open_biometric_prompt_unlock_database">打开生物识别对话框以解锁数据库</string>
<string name="encrypted_value_stored">加密密码已保存</string> <string name="encrypted_value_stored">加密密码已保存</string>
<string name="biometric_invalid_key">不能读取生物识别密钥。请将其删除后重新设置</string> <string name="biometric_invalid_key">不能读取生物识别密钥,请删除所有生物密钥,并重新录入</string>
<string name="biometric_not_recognized">无法识别生物识别信息</string> <string name="biometric_not_recognized">无法识别生物识别信息</string>
<string name="biometric_scanning_error">生物识别错误:%1$s</string> <string name="biometric_scanning_error">生物识别错误:%1$s</string>
<string name="no_credentials_stored">当前数据库无密码。</string> <string name="no_credentials_stored">当前数据库无密码。</string>
<string name="set_autofill_service_title">设为默认填充服务</string> <string name="set_autofill_service_title">设为默认填充服务</string>
<string name="autofill_explanation_summary">启用自动填充功能,以便捷地在其他程序中填写信息</string> <string name="autofill_explanation_summary">启用自动填充功能,以便捷地在其他程序中填写信息</string>
<string name="password_size_title">密码生成长度</string> <string name="password_size_title">密码生成长度</string>
<string name="password_size_summary">设置生成密码的默认长度</string> <string name="password_size_summary">设置生成密码的默认长度</string>
@@ -268,20 +269,20 @@
<string name="recycle_bin_summary">删除群组和条目前先移至回收站</string> <string name="recycle_bin_summary">删除群组和条目前先移至回收站</string>
<string name="monospace_font_fields_enable_title">字段字体</string> <string name="monospace_font_fields_enable_title">字段字体</string>
<string name="monospace_font_fields_enable_summary">更改字段字体,可以使字符更清楚</string> <string name="monospace_font_fields_enable_summary">更改字段字体,可以使字符更清楚</string>
<string name="allow_copy_password_summary">让剪切板保存条目密码及保密字段</string> <string name="allow_copy_password_summary">允许复制整段密码和受保护的字段至剪切板</string>
<string name="allow_copy_password_warning">警告:复制密码时密码在剪贴板中,而所有程序都可访问剪切板。因此复制密码时,设备上的其他程序也能看到密码。</string> <string name="allow_copy_password_warning">警告:复制密码时密码在剪贴板中,而所有程序都可访问剪切板。因此复制密码时,设备上的其他程序也能看到密码。</string>
<string name="magic_keyboard_explanation_summary">激活自定义键盘以填写密码和所有身份字段</string> <string name="magic_keyboard_explanation_summary">激活自定义键盘以填写密码和所有身份字段</string>
<string name="allow_copy_password_title">信任剪贴板</string> <string name="allow_copy_password_title">信任剪贴板</string>
<string name="keyboard_name">磐密码键盘</string> <string name="keyboard_name">魔法键盘</string>
<string name="keyboard_label">磐密码键盘</string> <string name="keyboard_label">魔法键盘KeePassDX</string>
<string name="keyboard_setting_label">磐密码键盘设置</string> <string name="keyboard_setting_label">魔法键盘设置</string>
<string name="keyboard_entry_category">条目</string> <string name="keyboard_entry_category">条目</string>
<string name="keyboard_entry_timeout_title">超时</string> <string name="keyboard_entry_timeout_title">超时</string>
<string name="keyboard_entry_timeout_summary">设置多久后清空键盘记录</string> <string name="keyboard_entry_timeout_summary">设置多久后清空键盘记录</string>
<string name="keyboard_notification_entry_title">通知信息</string> <string name="keyboard_notification_entry_title">通知信息</string>
<string name="keyboard_notification_entry_summary">在条目可用时显示通知</string> <string name="keyboard_notification_entry_summary">在条目可用时显示通知</string>
<string name="keyboard_notification_entry_content_title_text">条目</string> <string name="keyboard_notification_entry_content_title_text">条目</string>
<string name="keyboard_notification_entry_content_title">%1$s在磐密码键盘中可用</string> <string name="keyboard_notification_entry_content_title">%1$s 在魔法键盘中可用</string>
<string name="keyboard_notification_entry_content_text">%1$s</string> <string name="keyboard_notification_entry_content_text">%1$s</string>
<string name="keyboard_notification_entry_clear_close_title">关闭时清空</string> <string name="keyboard_notification_entry_clear_close_title">关闭时清空</string>
<string name="keyboard_notification_entry_clear_close_summary">在关闭通知时锁定数据库</string> <string name="keyboard_notification_entry_clear_close_summary">在关闭通知时锁定数据库</string>
@@ -314,7 +315,7 @@
<string name="education_generate_password_title">为记录新建强密码。</string> <string name="education_generate_password_title">为记录新建强密码。</string>
<string name="education_generate_password_summary">依据表格中的标准生成新密码,并将密码与条目关联起来,永不忘记。</string> <string name="education_generate_password_summary">依据表格中的标准生成新密码,并将密码与条目关联起来,永不忘记。</string>
<string name="education_entry_new_field_title">添加自定义字段</string> <string name="education_entry_new_field_title">添加自定义字段</string>
<string name="education_entry_new_field_summary">可能有的字段程序没有提供。这时可以新建可以被保护字段。</string> <string name="education_entry_new_field_summary">添加一个新的字段并添加为其添加一个值,此时可以选择是否保护字段及其值</string>
<string name="education_unlock_title">解锁数据库</string> <string name="education_unlock_title">解锁数据库</string>
<string name="education_read_only_title">为数据库开启写保护(只读)</string> <string name="education_read_only_title">为数据库开启写保护(只读)</string>
<string name="education_read_only_summary">在会话中改变打开模式。 <string name="education_read_only_summary">在会话中改变打开模式。
@@ -331,7 +332,7 @@
<string name="education_sort_summary">选择条目和群组的排序方式。</string> <string name="education_sort_summary">选择条目和群组的排序方式。</string>
<string name="education_donation_title">参与开发</string> <string name="education_donation_title">参与开发</string>
<string name="education_donation_summary">帮助增加稳定性,安全性并添加更多的功能。</string> <string name="education_donation_summary">帮助增加稳定性,安全性并添加更多的功能。</string>
<string name="html_text_ad_free">不同于大多数的密码管理程序,不论使用免费还是付费版本的磐密码,都没有&lt;strong&gt;广告&lt;/strong&gt;并且&lt;strong&gt;开源&lt;/strong&gt;,使用&lt;strong&gt;自由程序协议&lt;/strong&gt;&lt;strong&gt;不收集&lt;/strong&gt;任何用户的个人信息。</string> <string name="html_text_ad_free">不同于大多数的密码管理程序,无论您是使用免费版本还是付费版本的KeePassDX这都是一款&lt;strong&gt;没有广告&lt;strong&gt;&lt;strong&gt;基于copylefted版权协议的免费软件&lt;strong&gt;,同样的本软件的任何版本也不会收集您的个人信息。</string>
<string name="html_text_buy_pro">通过购买高级版本,您将解锁全部&lt;strong&gt;主题样式&lt;/strong&gt;,重要的是,您会为&lt;strong&gt;社区项目的进行&lt;/strong&gt;提供的帮助</string> <string name="html_text_buy_pro">通过购买高级版本,您将解锁全部&lt;strong&gt;主题样式&lt;/strong&gt;,重要的是,您会为&lt;strong&gt;社区项目的进行&lt;/strong&gt;提供的帮助</string>
<string name="html_text_feature_generosity">&lt;strong&gt;主题样式&lt;/strong&gt;现在已经可用,感谢慷慨相助。</string> <string name="html_text_feature_generosity">&lt;strong&gt;主题样式&lt;/strong&gt;现在已经可用,感谢慷慨相助。</string>
<string name="html_text_donation">为继续建设此自由项目,我们需要&lt;strong&gt;捐助。&lt;/strong&gt;</string> <string name="html_text_donation">为继续建设此自由项目,我们需要&lt;strong&gt;捐助。&lt;/strong&gt;</string>
@@ -347,12 +348,12 @@
<string name="lock_database_back_root_title">按返回键以锁定</string> <string name="lock_database_back_root_title">按返回键以锁定</string>
<string name="lock_database_back_root_summary">在点按根屏幕上的后退按钮时锁定数据库</string> <string name="lock_database_back_root_summary">在点按根屏幕上的后退按钮时锁定数据库</string>
<string name="clear_clipboard_notification_title">关闭程序时清空剪贴板</string> <string name="clear_clipboard_notification_title">关闭程序时清空剪贴板</string>
<string name="clear_clipboard_notification_summary">关闭通知时关闭数据库</string> <string name="clear_clipboard_notification_summary">清除通知时锁定数据库</string>
<string name="recycle_bin">回收站</string> <string name="recycle_bin">回收站</string>
<string name="keyboard_selection_entry_title">条目选择</string> <string name="keyboard_selection_entry_title">条目选择</string>
<string name="keyboard_selection_entry_summary">在查看条目时,在专用键盘中显示输入字段</string> <string name="keyboard_selection_entry_summary">在查看条目时,在专用键盘中显示输入字段</string>
<string name="delete_entered_password_title">删除密码</string> <string name="delete_entered_password_title">删除密码</string>
<string name="delete_entered_password_summary">删除尝试连接后输入的密码</string> <string name="delete_entered_password_summary">密码错误后删除已输入的密码</string>
<string name="content_description_open_file">打开文件</string> <string name="content_description_open_file">打开文件</string>
<string name="content_description_node_children">子节点</string> <string name="content_description_node_children">子节点</string>
<string name="content_description_add_node">增加节点</string> <string name="content_description_add_node">增加节点</string>
@@ -379,7 +380,7 @@
<string name="error_create_database_file">无法使用此密码和密钥文件新建数据库。</string> <string name="error_create_database_file">无法使用此密码和密钥文件新建数据库。</string>
<string name="menu_advanced_unlock_settings">高级解锁</string> <string name="menu_advanced_unlock_settings">高级解锁</string>
<string name="biometric_prompt_store_credential_title">保存生物识别信息</string> <string name="biometric_prompt_store_credential_title">保存生物识别信息</string>
<string name="biometric_prompt_store_credential_message">警告:即使用生物识别数据存储了凭据,你仍需牢记主密码。</string> <string name="biometric_prompt_store_credential_message">警告:即使您已经使用生物识别数据存储了凭据,你仍需牢记主密码。</string>
<string name="biometric_prompt_extract_credential_title">使用生物识别功能打开数据库</string> <string name="biometric_prompt_extract_credential_title">使用生物识别功能打开数据库</string>
<string name="biometric_prompt_extract_credential_message">使用生物识别数据提取数据库凭据</string> <string name="biometric_prompt_extract_credential_message">使用生物识别数据提取数据库凭据</string>
<string name="biometric">生物识别</string> <string name="biometric">生物识别</string>
@@ -410,7 +411,7 @@
<string name="menu_security_settings">安全设置</string> <string name="menu_security_settings">安全设置</string>
<string name="menu_master_key_settings">主密钥设置</string> <string name="menu_master_key_settings">主密钥设置</string>
<string name="contains_duplicate_uuid">数据库包含重复UUID。</string> <string name="contains_duplicate_uuid">数据库包含重复UUID。</string>
<string name="contains_duplicate_uuid_procedure">通过验证此对话框,磐密码将解决这个问题通过给重复项生成新的UUID并继续。</string> <string name="contains_duplicate_uuid_procedure">通过验证此对话框,KeePassDX将解决这个问题通过给重复项生成新的UUID并继续。</string>
<string name="database_opened">数据库开启</string> <string name="database_opened">数据库开启</string>
<string name="clipboard_explanation_summary">使用设备的剪贴板来复制输入字段</string> <string name="clipboard_explanation_summary">使用设备的剪贴板来复制输入字段</string>
<string name="persistent_notification_title">持久通知</string> <string name="persistent_notification_title">持久通知</string>
@@ -443,17 +444,29 @@
<string name="recycle_bin_group_title">回收站(组)</string> <string name="recycle_bin_group_title">回收站(组)</string>
<string name="enable_auto_save_database_title">自动保存数据库</string> <string name="enable_auto_save_database_title">自动保存数据库</string>
<string name="enable_auto_save_database_summary">在进行重要操作后自动保存数据库(仅在编辑模式下有效)</string> <string name="enable_auto_save_database_summary">在进行重要操作后自动保存数据库(仅在编辑模式下有效)</string>
<string name="keystore_not_accessible">密钥库未正确初始化。</string> <string name="keystore_not_accessible">密钥库未正确初始化。</string>
<string name="entry_attachments">附件</string> <string name="entry_attachments">附件</string>
<string name="menu_restore_entry_history">恢复历史记录</string> <string name="menu_restore_entry_history">恢复历史记录</string>
<string name="menu_delete_entry_history">删除历史记录</string> <string name="menu_delete_entry_history">删除历史记录</string>
<string name="keyboard_auto_go_action_title">自动键操作</string> <string name="keyboard_auto_go_action_title">自动键操作</string>
<string name="keyboard_auto_go_action_summary">按下Field键后自动执行Go键的动作</string> <string name="keyboard_auto_go_action_summary">填入用户名或密码后直接登录</string>
<string name="download_attachment">下载%1$s</string> <string name="download_attachment">下载%1$s</string>
<string name="download_initialization">正在初始化…</string> <string name="download_initialization">正在初始化…</string>
<string name="download_progression">进行中:%1$d%</string> <string name="download_progression">进行中:%1$d&#37;</string>
<string name="download_finalization">正在完成…</string> <string name="download_finalization">正在完成…</string>
<string name="download_complete">完成!点击打开文件。</string> <string name="download_complete">完成!点击打开文件。</string>
<string name="hide_expired_entries_title">隐藏过期条目</string> <string name="hide_expired_entries_title">隐藏过期条目</string>
<string name="hide_expired_entries_summary">过期条目将被隐藏</string> <string name="hide_expired_entries_summary">过期条目将被隐藏</string>
<string name="contact">联系我们</string>
<string name="contribution">贡献</string>
<string name="html_about_contribution">为了&lt;strong&gt;保持我们的自由&lt;strong&gt;&lt;strong&gt;修复错误&lt;strong&gt;&lt;strong&gt;添加功能&lt;strong&gt;&lt;strong&gt;始终保持活跃&lt;strong&gt;,我们期待您的 &lt;strong&gt;贡献。&lt;strong&gt;</string>
<string name="auto_focus_search_title">快速搜索</string>
<string name="auto_focus_search_summary">打开数据库时询问是否进行搜索</string>
<string name="remember_database_locations_title">数据库保存的路径</string>
<string name="remember_database_locations_summary">记住数据库的路径</string>
<string name="remember_keyfile_locations_title">密钥文件保存的路径</string>
<string name="remember_keyfile_locations_summary">记住密钥文件的路径</string>
<string name="hide_broken_locations_title">隐藏已损坏的数据库路径</string>
<string name="hide_broken_locations_summary">在最近的数据库列表中隐藏已损坏的数据库的链接</string>
<string name="warning_database_read_only">授予软件文件读写访问权限以保存数据库更改</string>
</resources> </resources>

View File

@@ -143,7 +143,7 @@
<string name="extended_ASCII">增強的ASCII</string> <string name="extended_ASCII">增強的ASCII</string>
<string name="allow">允許</string> <string name="allow">允許</string>
<string name="clipboard_error_title">剪貼簿錯誤</string> <string name="clipboard_error_title">剪貼簿錯誤</string>
<string name="clipboard_error">部份 Samsung 手機不容許其他程式使用剪貼簿。</string> <string name="clipboard_error">部份設備不容許其他程式使用剪貼簿。</string>
<string name="clipboard_error_clear">無法清除剪貼簿</string> <string name="clipboard_error_clear">無法清除剪貼簿</string>
<string name="clipboard_swipe_clean">滑动即可清除剪贴板</string> <string name="clipboard_swipe_clean">滑动即可清除剪贴板</string>
<string name="error_autofill_enable_service">無法啟用自動填入服務。</string> <string name="error_autofill_enable_service">無法啟用自動填入服務。</string>
@@ -251,4 +251,15 @@
<string name="menu_security_settings">安全設定</string> <string name="menu_security_settings">安全設定</string>
<string name="contains_duplicate_uuid">資料庫包含重複的 UUID。</string> <string name="contains_duplicate_uuid">資料庫包含重複的 UUID。</string>
<string name="contains_duplicate_uuid_procedure">通過驗證此對話方塊KeePassDX 將修復問題(通過為重複項生成新的 UUID並繼續。</string> <string name="contains_duplicate_uuid_procedure">通過驗證此對話方塊KeePassDX 將修復問題(通過為重複項生成新的 UUID並繼續。</string>
<string name="set_autofill_service_title">設置為默認的填充服務</string>
<string name="password_size_title">生成密碼的長度</string>
<string name="password_size_summary">設置生成密碼的默認長度</string>
<string name="list_password_generator_options_title">密碼字符集</string>
<string name="list_password_generator_options_summary">設置密碼生成時所需要的字符集</string>
<string name="clipboard">剪貼板</string>
<string name="autofill_explanation_summary">啟用自動填充功能以快速填寫其他應用程序中的用戶名和密碼</string>
<string name="database_opened">數據庫已打開</string>
<string name="clipboard_explanation_summary">使用設備的剪貼板複製輸入密碼</string>
<string name="contact">聯繫方式</string>
<string name="contribution">貢獻</string>
</resources> </resources>

View File

@@ -73,7 +73,7 @@
<string name="default_checkbox">Use as default database</string> <string name="default_checkbox">Use as default database</string>
<string name="digits">Digits</string> <string name="digits">Digits</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft is &lt;strong&gt;open source&lt;/strong&gt; and &lt;strong&gt;without advertising&lt;/strong&gt;. \nIt is provided as is, under &lt;strong&gt;GPLv3&lt;/strong&gt; license, without any warranty.</string> <string name="html_about_licence">KeePassDX © %1$d Kunzisoft is &lt;strong&gt;open source&lt;/strong&gt; and &lt;strong&gt;without advertising&lt;/strong&gt;. \nIt is provided as is, under &lt;strong&gt;GPLv3&lt;/strong&gt; license, without any warranty.</string>
<string name="html_about_contribution">In order to &lt;strong&gt;keep our freedom&lt;/strong&gt;, &lt;strong&gt;fix bugs&lt;/strong&gt;, &lt;strong&gt;add features&lt;/strong&gt; and &lt;strong&gt;to be always active&lt;/strong&gt;, we count on your &lt;strong&gt;contribution.&lt;/strong&gt;</string> <string name="html_about_contribution">In order to &lt;strong&gt;keep our freedom&lt;/strong&gt;, &lt;strong&gt;fix bugs&lt;/strong&gt;, &lt;strong&gt;add features&lt;/strong&gt; and &lt;strong&gt;to be always active&lt;/strong&gt;, we count on your &lt;strong&gt;contribution&lt;/strong&gt;.</string>
<string name="entry_accessed">Accessed</string> <string name="entry_accessed">Accessed</string>
<string name="entry_cancel">Cancel</string> <string name="entry_cancel">Cancel</string>
<string name="entry_notes">Notes</string> <string name="entry_notes">Notes</string>
@@ -405,7 +405,7 @@
<string name="education_generate_password_title">Create a strong password for your entry.</string> <string name="education_generate_password_title">Create a strong password for your entry.</string>
<string name="education_generate_password_summary">Generate a strong password to associate with your entry, easily define it according to the criteria of the form and don\'t forget secure password.</string> <string name="education_generate_password_summary">Generate a strong password to associate with your entry, easily define it according to the criteria of the form and don\'t forget secure password.</string>
<string name="education_entry_new_field_title">Add custom fields</string> <string name="education_entry_new_field_title">Add custom fields</string>
<string name="education_entry_new_field_summary">Register a basic non-supplied field by filling in a new one that you can also protect.</string> <string name="education_entry_new_field_summary">Register an additional field, add a value and optionally protect it.</string>
<string name="education_unlock_title">Unlock your database</string> <string name="education_unlock_title">Unlock your database</string>
<string name="education_unlock_summary">Enter the password and/or keyfile to unlock your database.\n\nBackup your database file in a safe place after each change.</string> <string name="education_unlock_summary">Enter the password and/or keyfile to unlock your database.\n\nBackup your database file in a safe place after each change.</string>
<string name="education_read_only_title">Write protect your database</string> <string name="education_read_only_title">Write protect your database</string>
@@ -433,7 +433,7 @@
<string name="contribute">Contribute</string> <string name="contribute">Contribute</string>
<string name="download_attachment">Download %1$s</string> <string name="download_attachment">Download %1$s</string>
<string name="download_initialization">Initializing…</string> <string name="download_initialization">Initializing…</string>
<string name="download_progression">In progress: %1$d\%%</string> <string name="download_progression">In progress: %1$d&#37;</string>
<string name="download_finalization">Finalizing…</string> <string name="download_finalization">Finalizing…</string>
<string name="download_complete">Complete! Tap to open the file.</string> <string name="download_complete">Complete! Tap to open the file.</string>
<!-- Encryption Algorithms --> <!-- Encryption Algorithms -->

View File

@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.3.41' ext.kotlin_version = '1.3.61'
repositories { repositories {
jcenter() jcenter()
maven { maven {
@@ -10,7 +10,7 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.2' classpath 'com.android.tools.build:gradle:3.6.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }

View File

@@ -0,0 +1,2 @@
* Fix read only database
* Upgrade to Android SDK 29

View File

@@ -0,0 +1,2 @@
* Correction base de données en lecture seule
* Mise à jour vers Android SDK 29

View File

@@ -1,3 +1,4 @@
android.enableJetifier=true android.enableJetifier=true
android.useAndroidX=true android.useAndroidX=true
kapt.incremental.apt=true
org.gradle.jvmargs=-Xmx2048M org.gradle.jvmargs=-Xmx2048M

View File

@@ -1,6 +1,6 @@
#Thu Aug 29 16:23:48 CEST 2019 #Sun Mar 08 08:59:59 CET 2020
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip