mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'feature/OPEN_DOCUMENT' into develop
This commit is contained in:
@@ -193,17 +193,10 @@ class PasswordActivity : StylishActivity() {
|
|||||||
|
|
||||||
// If is a view intent
|
// If is a view intent
|
||||||
val action = intent.action
|
val action = intent.action
|
||||||
if (action != null && action == VIEW_INTENT) {
|
if (action != null
|
||||||
|
&& action == VIEW_INTENT) {
|
||||||
val databaseUriRetrieve = intent.data
|
databaseUri = intent.data
|
||||||
// Stop activity here if we can't verify database URI
|
|
||||||
if (!UriUtil.verifyFileUri(databaseUriRetrieve)) {
|
|
||||||
Log.e(TAG, "File URI not validate")
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
databaseUri = databaseUriRetrieve
|
|
||||||
keyFileUri = UriUtil.getUriFromIntent(intent, KEY_KEYFILE)
|
keyFileUri = UriUtil.getUriFromIntent(intent, KEY_KEYFILE)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
databaseUri = intent.getParcelableExtra(KEY_FILENAME)
|
databaseUri = intent.getParcelableExtra(KEY_FILENAME)
|
||||||
keyFileUri = intent.getParcelableExtra(KEY_KEYFILE)
|
keyFileUri = intent.getParcelableExtra(KEY_KEYFILE)
|
||||||
|
|||||||
@@ -177,22 +177,19 @@ class OpenFileHelper {
|
|||||||
GET_CONTENT, OPEN_DOC -> {
|
GET_CONTENT, OPEN_DOC -> {
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
var uri = data.data
|
val uri = data.data
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
try {
|
try {
|
||||||
// try to persist read and write permissions
|
// try to persist read and write permissions
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
activity?.contentResolver?.apply {
|
activity?.contentResolver?.apply {
|
||||||
takePersistableUriPermission(uri!!, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
takePersistableUriPermission(uri!!, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// nop
|
// nop
|
||||||
}
|
}
|
||||||
if (requestCode == GET_CONTENT) {
|
|
||||||
uri = UriUtil.translateUri(activity!!, uri)
|
|
||||||
}
|
|
||||||
keyFileCallback?.invoke(uri)
|
keyFileCallback?.invoke(uri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.utils
|
package com.kunzisoft.keepass.utils
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -27,7 +26,6 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
@@ -35,89 +33,6 @@ import java.io.InputStream
|
|||||||
|
|
||||||
object UriUtil {
|
object UriUtil {
|
||||||
|
|
||||||
/**
|
|
||||||
* Many android apps respond with non-writeable content URIs that correspond to files.
|
|
||||||
* This will attempt to translate the content URIs to file URIs when possible/appropriate
|
|
||||||
* @param uri
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
fun translateUri(ctx: Context, uri: Uri): Uri {
|
|
||||||
var currentUri = uri
|
|
||||||
// StorageAF provides nice URIs
|
|
||||||
if (hasWritableContentUri(currentUri)) {
|
|
||||||
return currentUri
|
|
||||||
}
|
|
||||||
|
|
||||||
val scheme = currentUri.scheme
|
|
||||||
if (scheme == null || scheme.isEmpty()) {
|
|
||||||
return currentUri
|
|
||||||
}
|
|
||||||
|
|
||||||
var filepath: String? = null
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Use content resolver to try and find the file
|
|
||||||
if (scheme.equals("content", ignoreCase = true)) {
|
|
||||||
val cursor = ctx.contentResolver.query(currentUri, arrayOf(android.provider.MediaStore.Images.ImageColumns.DATA), null, null, null)
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.moveToFirst()
|
|
||||||
filepath = cursor.getString(0)
|
|
||||||
cursor.close()
|
|
||||||
if (!isValidFilePath(filepath)) {
|
|
||||||
filepath = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try using the URI path as a straight file
|
|
||||||
if (filepath == null || filepath.isEmpty()) {
|
|
||||||
filepath = currentUri.encodedPath
|
|
||||||
if (!isValidFilePath(filepath)) {
|
|
||||||
filepath = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
filepath = null
|
|
||||||
}
|
|
||||||
// Fall back to URI if this fails.
|
|
||||||
|
|
||||||
// Update the file to a file URI
|
|
||||||
if (filepath != null && filepath.isNotEmpty()) {
|
|
||||||
val b = Uri.Builder()
|
|
||||||
currentUri = b.scheme("file").authority("").path(filepath).build()
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentUri
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isValidFilePath(filepath: String?): Boolean {
|
|
||||||
if (filepath == null || filepath.isEmpty()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
val file = File(filepath)
|
|
||||||
return file.exists() && file.canRead()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whitelist for known content providers that support writing
|
|
||||||
* @param uri
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private fun hasWritableContentUri(uri: Uri): Boolean {
|
|
||||||
val scheme = uri.scheme
|
|
||||||
if (scheme == null || scheme.isEmpty()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!scheme.equals("content", ignoreCase = true)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
when (uri.authority) {
|
|
||||||
"com.google.android.apps.docs.storage" -> return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(FileNotFoundException::class)
|
@Throws(FileNotFoundException::class)
|
||||||
fun getUriInputStream(contentResolver: ContentResolver, uri: Uri?): InputStream? {
|
fun getUriInputStream(contentResolver: ContentResolver, uri: Uri?): InputStream? {
|
||||||
if (uri == null)
|
if (uri == null)
|
||||||
@@ -132,38 +47,9 @@ object UriUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun verifyFileUri(fileUri: Uri?): Boolean {
|
|
||||||
|
|
||||||
if (fileUri == null || fileUri == Uri.EMPTY)
|
|
||||||
return false
|
|
||||||
|
|
||||||
val scheme = fileUri.scheme
|
|
||||||
return when {
|
|
||||||
scheme == null || scheme.isEmpty() -> {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
scheme.equals("file", ignoreCase = true) -> {
|
|
||||||
val filePath = fileUri.path
|
|
||||||
if (filePath == null || filePath.isEmpty())
|
|
||||||
false
|
|
||||||
else {
|
|
||||||
File(filePath).exists()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scheme.equals("content", ignoreCase = true) -> {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parse(stringUri: String?): Uri? {
|
fun parse(stringUri: String?): Uri? {
|
||||||
return if (stringUri?.isNotEmpty() == true) {
|
return if (stringUri?.isNotEmpty() == true) {
|
||||||
val uriParsed = Uri.parse(stringUri)
|
Uri.parse(stringUri)
|
||||||
if (verifyFileUri(uriParsed))
|
|
||||||
uriParsed
|
|
||||||
else
|
|
||||||
null
|
|
||||||
} else
|
} else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -193,18 +79,16 @@ object UriUtil {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(ActivityNotFoundException::class)
|
|
||||||
fun gotoUrl(context: Context, url: String?) {
|
fun gotoUrl(context: Context, url: String?) {
|
||||||
try {
|
try {
|
||||||
if (url != null && url.isNotEmpty()) {
|
if (url != null && url.isNotEmpty()) {
|
||||||
context.startActivity(Intent(Intent.ACTION_VIEW, parse(url)))
|
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||||
}
|
}
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: Exception) {
|
||||||
Toast.makeText(context, R.string.no_url_handler, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, R.string.no_url_handler, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(ActivityNotFoundException::class)
|
|
||||||
fun gotoUrl(context: Context, resId: Int) {
|
fun gotoUrl(context: Context, resId: Int) {
|
||||||
gotoUrl(context, context.getString(resId))
|
gotoUrl(context, context.getString(resId))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user