mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Check URI permissions #626
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
KeePassDX(3.0.0)
|
||||
* Add / Manage dynamic templates #191
|
||||
* Manually select RecycleBin group and Templates group #191
|
||||
* Small changes #1035
|
||||
* Fix timeout in dialogs #716
|
||||
* Check URI permissions #626
|
||||
* Small changes #1035
|
||||
|
||||
KeePassDX(2.10.5)
|
||||
* Increase the saving speed of database #1028
|
||||
|
||||
@@ -126,6 +126,12 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
||||
}
|
||||
mAdapterDatabaseHistory?.setOnFileDatabaseHistoryDeleteListener { fileDatabaseHistoryToDelete ->
|
||||
// Remove from app database
|
||||
fileDatabaseHistoryToDelete.databaseUri?.let { databaseUri ->
|
||||
UriUtil.releaseUriPermission(
|
||||
contentResolver,
|
||||
databaseUri
|
||||
)
|
||||
}
|
||||
databaseFilesViewModel.deleteDatabaseFile(fileDatabaseHistoryToDelete)
|
||||
true
|
||||
}
|
||||
|
||||
@@ -127,17 +127,7 @@ class ExternalFileHelper {
|
||||
if (data != null) {
|
||||
val uri = data.data
|
||||
if (uri != null) {
|
||||
try {
|
||||
// try to persist read and write permissions
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
activity?.contentResolver?.apply {
|
||||
takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// nop
|
||||
}
|
||||
UriUtil.takeUriPermission(activity?.contentResolver, uri)
|
||||
onFileSelected?.invoke(uri)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@ import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.database.action.node.NodeHandler
|
||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
|
||||
import com.kunzisoft.keepass.services.ClipboardEntryNotificationService
|
||||
@@ -139,4 +140,21 @@ fun Context.closeDatabase(database: Database?) {
|
||||
}
|
||||
// Clear data
|
||||
database?.clearAndClose(this)
|
||||
|
||||
// Release not useful URI permission
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
applicationContext?.let { appContext ->
|
||||
val fileDatabaseHistoryAction = FileDatabaseHistoryAction.getInstance(appContext)
|
||||
fileDatabaseHistoryAction.getDatabaseFileList { databaseFileList ->
|
||||
val listToNotRemove = databaseFileList.map { it.databaseUri }
|
||||
// Remove URI permission for not database files
|
||||
val resolver = appContext.contentResolver
|
||||
resolver.persistedUriPermissions.forEach { uriPermission ->
|
||||
val uri = uriPermission.uri
|
||||
if (!listToNotRemove.contains(uri))
|
||||
UriUtil.releaseUriPermission(resolver, uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ object UriUtil {
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("FileData", "Unable to get document file", e)
|
||||
Log.e(TAG, "Unable to get document file", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -110,6 +110,83 @@ object UriUtil {
|
||||
return Uri.decode(uri) ?: ""
|
||||
}
|
||||
|
||||
private fun persistUriPermission(contentResolver: ContentResolver?,
|
||||
uri: Uri,
|
||||
release: Boolean,
|
||||
readOnly: Boolean) {
|
||||
try {
|
||||
// try to persist read and write permissions
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
contentResolver?.apply {
|
||||
var readPermissionAllowed = false
|
||||
var writePermissionAllowed = false
|
||||
// Check current permissions allowed
|
||||
persistedUriPermissions.find { uriPermission ->
|
||||
uriPermission.uri == uri
|
||||
}?.let { uriPermission ->
|
||||
Log.d(TAG, "Check URI permission : $uriPermission")
|
||||
if (uriPermission.isReadPermission) {
|
||||
readPermissionAllowed = true
|
||||
}
|
||||
if (uriPermission.isWritePermission) {
|
||||
writePermissionAllowed = true
|
||||
}
|
||||
}
|
||||
|
||||
// Release permission
|
||||
if (release) {
|
||||
if (writePermissionAllowed) {
|
||||
Log.d(TAG, "Release write permission : $uri")
|
||||
val removeFlags: Int = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
releasePersistableUriPermission(uri, removeFlags)
|
||||
}
|
||||
if (readPermissionAllowed) {
|
||||
Log.d(TAG, "Release read permission $uri")
|
||||
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
releasePersistableUriPermission(uri, takeFlags)
|
||||
}
|
||||
}
|
||||
|
||||
// Take missing permission
|
||||
if (!readPermissionAllowed) {
|
||||
Log.d(TAG, "Take read permission $uri")
|
||||
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
takePersistableUriPermission(uri, takeFlags)
|
||||
}
|
||||
if (readOnly) {
|
||||
if (writePermissionAllowed) {
|
||||
Log.d(TAG, "Release write permission $uri")
|
||||
val removeFlags: Int = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
releasePersistableUriPermission(uri, removeFlags)
|
||||
}
|
||||
} else {
|
||||
if (!writePermissionAllowed) {
|
||||
Log.d(TAG, "Take write permission $uri")
|
||||
val takeFlags: Int = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
takePersistableUriPermission(uri, takeFlags)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (release)
|
||||
Log.e(TAG, "Unable to release persistable URI permission", e)
|
||||
else
|
||||
Log.e(TAG, "Unable to take persistable URI permission", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun takeUriPermission(contentResolver: ContentResolver?,
|
||||
uri: Uri,
|
||||
readOnly: Boolean = false) {
|
||||
persistUriPermission(contentResolver, uri, false, readOnly)
|
||||
}
|
||||
|
||||
fun releaseUriPermission(contentResolver: ContentResolver?,
|
||||
uri: Uri) {
|
||||
persistUriPermission(contentResolver, uri, release = true, readOnly = false)
|
||||
}
|
||||
|
||||
fun getUriFromIntent(intent: Intent, key: String): Uri? {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
@@ -156,7 +233,7 @@ object UriUtil {
|
||||
context.applicationContext.packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.e(javaClass.simpleName, "App not accessible", e)
|
||||
Log.e(TAG, "App not accessible", e)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -165,7 +242,7 @@ object UriUtil {
|
||||
try {
|
||||
context.startActivity(context.applicationContext.packageManager.getLaunchIntentForPackage(packageName))
|
||||
} catch (e: Exception) {
|
||||
Log.e(javaClass.simpleName, "App cannot be open", e)
|
||||
Log.e(TAG, "App cannot be open", e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,4 +254,5 @@ object UriUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private const val TAG = "UriUtil"
|
||||
}
|
||||
|
||||
@@ -48,6 +48,10 @@ class FileDatabaseInfo : Serializable {
|
||||
}
|
||||
|
||||
fun init() {
|
||||
// Check permission
|
||||
fileUri?.let { uri ->
|
||||
UriUtil.takeUriPermission(context.contentResolver, uri)
|
||||
}
|
||||
documentFile = UriUtil.getFileData(context, fileUri)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
* Add / Manage dynamic templates #191
|
||||
* Allow to manually select RecycleBin group and Templates group #191
|
||||
* Small changes #1035
|
||||
* Fix timeout in dialogs #716
|
||||
* Fix timeout in dialogs #716
|
||||
* Check URI permissions #626
|
||||
* Small changes #1035
|
||||
@@ -1,4 +1,5 @@
|
||||
* Ajout / Gestion dynamique des templates #191
|
||||
* Sélection manuelle des groupes de la corbeille et des templates #191
|
||||
* Petits changements #1035
|
||||
* Correction du délai d'expiration dans les dialogues #716
|
||||
* Correction du délai d'expiration dans les dialogues #716
|
||||
* Vérification des permissions URI #626
|
||||
* Petits changements #1035
|
||||
Reference in New Issue
Block a user