mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Refactorize uri util
This commit is contained in:
@@ -169,8 +169,8 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val fileName = prefs.getString(PasswordActivity.KEY_DEFAULT_FILENAME, "")
|
||||
|
||||
if (fileName!!.isNotEmpty()) {
|
||||
val dbUri = UriUtil.parseDefaultFile(fileName)
|
||||
if (fileName != null && fileName.isNotEmpty()) {
|
||||
val dbUri = UriUtil.parseUriFile(fileName)
|
||||
var scheme: String? = null
|
||||
if (dbUri != null)
|
||||
scheme = dbUri.scheme
|
||||
@@ -408,17 +408,20 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
||||
ProgressDialogThread(this@FileDatabaseSelectActivity,
|
||||
{
|
||||
CreateDatabaseRunnable(databaseFilename) { database ->
|
||||
// TODO store database created
|
||||
AssignPasswordInDatabaseRunnable(
|
||||
this@FileDatabaseSelectActivity,
|
||||
database,
|
||||
masterPasswordChecked,
|
||||
masterPassword,
|
||||
keyFileChecked,
|
||||
keyFile,
|
||||
true, // TODO get readonly
|
||||
LaunchGroupActivityFinish(UriUtil.parseDefaultFile(databaseFilename))
|
||||
)
|
||||
|
||||
UriUtil.parseUriFile(databaseFilename)?.let { databaseUri ->
|
||||
// TODO store database created
|
||||
AssignPasswordInDatabaseRunnable(
|
||||
this@FileDatabaseSelectActivity,
|
||||
database,
|
||||
masterPasswordChecked,
|
||||
masterPassword,
|
||||
keyFileChecked,
|
||||
keyFile,
|
||||
true, // TODO get readonly
|
||||
LaunchGroupActivityFinish(databaseUri)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
R.string.progress_create)
|
||||
|
||||
@@ -265,7 +265,7 @@ class PasswordActivity : StylishActivity(),
|
||||
val defaultFilename = prefs?.getString(KEY_DEFAULT_FILENAME, "")
|
||||
if (mDatabaseFileUri != null
|
||||
&& mDatabaseFileUri!!.path != null && mDatabaseFileUri!!.path!!.isNotEmpty()
|
||||
&& UriUtil.equalsDefaultfile(mDatabaseFileUri, defaultFilename)) {
|
||||
&& mDatabaseFileUri == UriUtil.parseUriFile(defaultFilename)) {
|
||||
checkboxDefaultDatabaseView?.isChecked = true
|
||||
}
|
||||
|
||||
@@ -562,8 +562,8 @@ class PasswordActivity : StylishActivity(),
|
||||
|
||||
private fun verifyAllViewsAndLoadDatabase() {
|
||||
verifyCheckboxesAndLoadDatabase(
|
||||
passwordView?.text.toString(),
|
||||
UriUtil.parseDefaultFile(keyFileView?.text.toString()))
|
||||
passwordView?.text?.toString(),
|
||||
UriUtil.parseUriFile(keyFileView?.text?.toString()))
|
||||
}
|
||||
|
||||
private fun verifyCheckboxesAndLoadDatabase(password: String?, keyFile: Uri?) {
|
||||
@@ -579,8 +579,8 @@ class PasswordActivity : StylishActivity(),
|
||||
}
|
||||
|
||||
private fun verifyKeyFileViewsAndLoadDatabase(password: String) {
|
||||
val key = keyFileView?.text.toString()
|
||||
var keyUri = UriUtil.parseDefaultFile(key)
|
||||
val key = keyFileView?.text?.toString()
|
||||
var keyUri = UriUtil.parseUriFile(key)
|
||||
if (checkboxKeyFileView?.isChecked != true) {
|
||||
keyUri = null
|
||||
}
|
||||
@@ -817,9 +817,8 @@ class PasswordActivity : StylishActivity(),
|
||||
throw FileNotFoundException()
|
||||
}
|
||||
|
||||
val uri = UriUtil.parseDefaultFile(fileName)
|
||||
val scheme = uri.scheme
|
||||
|
||||
val uri = UriUtil.parseUriFile(fileName)
|
||||
val scheme = uri?.scheme
|
||||
if (scheme != null && scheme.isNotEmpty() && scheme.equals("file", ignoreCase = true)) {
|
||||
val dbFile = File(uri.path!!)
|
||||
if (!dbFile.exists()) {
|
||||
|
||||
@@ -177,9 +177,8 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
|
||||
private fun verifyFile(): Boolean {
|
||||
var error = false
|
||||
if (keyFileCheckBox != null
|
||||
&& keyFileCheckBox!!.isChecked
|
||||
&& keyFileView != null) {
|
||||
val keyFile = UriUtil.parseDefaultFile(keyFileView!!.text.toString())
|
||||
&& keyFileCheckBox!!.isChecked) {
|
||||
val keyFile = UriUtil.parseUriFile(keyFileView?.text?.toString())
|
||||
mKeyFile = keyFile
|
||||
|
||||
// Verify that a keyfile is set
|
||||
@@ -228,11 +227,10 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
|
||||
|
||||
mKeyFileHelper?.onActivityResultCallback(requestCode, resultCode, data
|
||||
) { uri ->
|
||||
uri?.let { currentUri ->
|
||||
UriUtil.parseDefaultFile(currentUri.toString())?.let { pathString ->
|
||||
keyFileCheckBox?.isChecked = true
|
||||
keyFileView?.text = pathString.toString()
|
||||
}
|
||||
UriUtil.parseUriFile(uri)?.let { pathUri ->
|
||||
keyFileCheckBox?.isChecked = true
|
||||
keyFileView?.text = pathUri.toString()
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ class CreateFileDialogFragment : DialogFragment(), AdapterView.OnItemSelectedLis
|
||||
|
||||
// Spinner Drop down elements
|
||||
val fileTypes = resources.getStringArray(R.array.file_types)
|
||||
val dataAdapter = ArrayAdapter(activity!!, android.R.layout.simple_spinner_item, fileTypes)
|
||||
val dataAdapter = ArrayAdapter(activity, android.R.layout.simple_spinner_item, fileTypes)
|
||||
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spinner.adapter = dataAdapter
|
||||
// Or text if only one item https://github.com/Kunzisoft/KeePassDX/issues/105
|
||||
@@ -158,7 +158,7 @@ class CreateFileDialogFragment : DialogFragment(), AdapterView.OnItemSelectedLis
|
||||
|
||||
val dialog = builder.create()
|
||||
|
||||
dialog.setOnShowListener { dialog1 ->
|
||||
dialog.setOnShowListener { _ ->
|
||||
positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE)
|
||||
negativeButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE)
|
||||
positiveButton?.setOnClickListener { _ ->
|
||||
@@ -181,11 +181,13 @@ class CreateFileDialogFragment : DialogFragment(), AdapterView.OnItemSelectedLis
|
||||
}
|
||||
|
||||
private fun buildPath(): Uri? {
|
||||
if (folderPathView != null && mDatabaseFileExtension != null) {
|
||||
if (folderPathView != null && fileNameView != null && mDatabaseFileExtension != null) {
|
||||
var path = Uri.Builder().path(folderPathView!!.text.toString())
|
||||
.appendPath(fileNameView!!.text.toString() + mDatabaseFileExtension!!)
|
||||
.build()
|
||||
path = UriUtil.translate(context, path)
|
||||
context?.let { context ->
|
||||
path = UriUtil.translateUri(context, path)
|
||||
}
|
||||
return path
|
||||
}
|
||||
return null
|
||||
|
||||
@@ -68,7 +68,6 @@ class KeyFileHelper {
|
||||
if (lookForOpenIntentsFilePicker(dataUri?.invoke()))
|
||||
showBrowserDialog()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +182,7 @@ class KeyFileHelper {
|
||||
val filename = data?.dataString
|
||||
var keyUri: Uri? = null
|
||||
if (filename != null) {
|
||||
keyUri = UriUtil.parseDefaultFile(filename)
|
||||
keyUri = UriUtil.parseUriFile(filename)
|
||||
}
|
||||
keyFileCallback?.invoke(keyUri)
|
||||
}
|
||||
@@ -194,7 +193,7 @@ class KeyFileHelper {
|
||||
if (data != null) {
|
||||
var uri = data.data
|
||||
if (uri != null) {
|
||||
if (activity != null && StorageAF.useStorageFramework(activity!!)) {
|
||||
if (StorageAF.useStorageFramework(activity!!)) {
|
||||
try {
|
||||
// try to persist read and write permissions
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
@@ -208,7 +207,7 @@ class KeyFileHelper {
|
||||
}
|
||||
}
|
||||
if (requestCode == GET_CONTENT) {
|
||||
uri = UriUtil.translate(activity, uri)
|
||||
uri = UriUtil.translateUri(activity!!, uri)
|
||||
}
|
||||
keyFileCallback?.invoke(uri)
|
||||
}
|
||||
|
||||
@@ -58,8 +58,8 @@ class UriIntentInitTask(private val weakContext: WeakReference<Context>,
|
||||
}
|
||||
|
||||
} else {
|
||||
databaseUri = UriUtil.parseDefaultFile(intent.getStringExtra(KEY_FILENAME))
|
||||
keyFileUri = UriUtil.parseDefaultFile(intent.getStringExtra(KEY_KEYFILE))
|
||||
databaseUri = UriUtil.parseUriFile(intent.getStringExtra(KEY_FILENAME))
|
||||
keyFileUri = UriUtil.parseUriFile(intent.getStringExtra(KEY_KEYFILE))
|
||||
|
||||
if (keyFileUri == null || keyFileUri!!.toString().isEmpty()) {
|
||||
keyFileUri = getKeyFileUri(databaseUri)
|
||||
|
||||
@@ -24,7 +24,7 @@ import android.net.Uri
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.exception.InvalidKeyFileException
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.utils.getUriInputStream
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import java.io.IOException
|
||||
|
||||
class AssignPasswordInDatabaseRunnable @JvmOverloads constructor(
|
||||
@@ -57,7 +57,7 @@ class AssignPasswordInDatabaseRunnable @JvmOverloads constructor(
|
||||
mBackupKey = ByteArray(database.masterKey.size)
|
||||
System.arraycopy(database.masterKey, 0, mBackupKey!!, 0, mBackupKey!!.size)
|
||||
|
||||
val uriInputStream = getUriInputStream(context.contentResolver, mKeyFile)
|
||||
val uriInputStream = UriUtil.getUriInputStream(context.contentResolver, mKeyFile)
|
||||
database.retrieveMasterKey(mMasterPassword, uriInputStream)
|
||||
|
||||
// To save the database
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
|
||||
class CreateDatabaseRunnable(private val mFilename: String,
|
||||
val onDatabaseCreate: (database: Database) -> ActionRunnable)
|
||||
val onDatabaseCreate: (database: Database) -> ActionRunnable?)
|
||||
: ActionRunnable() {
|
||||
|
||||
override fun run() {
|
||||
@@ -35,7 +35,7 @@ class CreateDatabaseRunnable(private val mFilename: String,
|
||||
// Set Database state
|
||||
loaded = true
|
||||
// Commit changes
|
||||
onDatabaseCreate(this).run()
|
||||
onDatabaseCreate(this)?.run()
|
||||
}
|
||||
|
||||
finishRun(true)
|
||||
|
||||
@@ -44,7 +44,6 @@ import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.stream.LEDataInputStream
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.utils.getUriInputStream
|
||||
import org.apache.commons.io.FileUtils
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
@@ -196,7 +195,9 @@ class Database {
|
||||
setDatabaseV4(databaseV4)
|
||||
}
|
||||
|
||||
setUri(UriUtil.parseDefaultFile(databasePath))
|
||||
UriUtil.parseUriFile(databasePath)?.let { uri ->
|
||||
setUri(uri)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setDatabaseV3(pwDatabaseV3: PwDatabaseV3) {
|
||||
@@ -245,7 +246,7 @@ class Database {
|
||||
// Pass Uris as InputStreams
|
||||
val inputStream: InputStream?
|
||||
try {
|
||||
inputStream = getUriInputStream(ctx.contentResolver, uri)
|
||||
inputStream = UriUtil.getUriInputStream(ctx.contentResolver, uri)
|
||||
} catch (e: Exception) {
|
||||
Log.e("KPD", "Database::loadData", e)
|
||||
throw ContentFileNotFoundException.getInstance(uri)
|
||||
@@ -255,7 +256,7 @@ class Database {
|
||||
var keyFileInputStream: InputStream? = null
|
||||
keyfile?.let {
|
||||
try {
|
||||
keyFileInputStream = getUriInputStream(ctx.contentResolver, keyfile)
|
||||
keyFileInputStream = UriUtil.getUriInputStream(ctx.contentResolver, keyfile)
|
||||
} catch (e: Exception) {
|
||||
Log.e("KPD", "Database::loadData", e)
|
||||
throw ContentFileNotFoundException.getInstance(keyfile)
|
||||
|
||||
@@ -209,18 +209,16 @@ class FileDatabaseHistory private constructor(private val context: WeakReference
|
||||
}
|
||||
}
|
||||
|
||||
fun getKeyFileUriByDatabaseUri(database: Uri): Uri? {
|
||||
if (!isEnabled) return null
|
||||
|
||||
fun getKeyFileUriByDatabaseUri(uri: Uri): Uri? {
|
||||
if (!isEnabled)
|
||||
return null
|
||||
init()
|
||||
|
||||
val size = mDatabasesUriList.size
|
||||
for (i in 0 until size) {
|
||||
if (UriUtil.equalsDefaultfile(database, mDatabasesUriList[i])) {
|
||||
return UriUtil.parseDefaultFile(mKeyFilesUriList[i])
|
||||
if (uri == UriUtil.parseUriFile(mDatabasesUriList[i])) {
|
||||
return UriUtil.parseUriFile(mKeyFilesUriList[i])
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePass DX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.kunzisoft.keepass.fileselect.StorageAF;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Created by bpellin on 3/5/16.
|
||||
*/
|
||||
public class UriUtil {
|
||||
public static Uri parseDefaultFile(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Uri uri = Uri.parse(text);
|
||||
if (uri.getScheme() == null || uri.getScheme().isEmpty()) {
|
||||
uri = uri.buildUpon().scheme("file").authority("").build();
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
public static Uri parseDefaultFile(Uri uri) {
|
||||
if (uri.getScheme() == null || uri.getScheme().isEmpty()) {
|
||||
uri = uri.buildUpon().scheme("file").authority("").build();
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
public static boolean equalsDefaultfile(Uri left, String right) {
|
||||
left = parseDefaultFile(left);
|
||||
Uri uriRight = parseDefaultFile(right);
|
||||
|
||||
return left.equals(uriRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public static Uri translate(Context ctx, Uri uri) {
|
||||
// StorageAF provides nice URIs
|
||||
if (StorageAF.INSTANCE.useStorageFramework(ctx) || hasWritableContentUri(uri)) { return uri; }
|
||||
|
||||
String scheme = uri.getScheme();
|
||||
if (scheme == null || scheme.isEmpty()) { return uri; }
|
||||
|
||||
String filepath = null;
|
||||
|
||||
try {
|
||||
// Use content resolver to try and find the file
|
||||
if (scheme.equalsIgnoreCase("content")) {
|
||||
Cursor cursor = ctx.getContentResolver().query(uri, new String[]{android.provider.MediaStore.Images.ImageColumns.DATA}, null, null, null);
|
||||
cursor.moveToFirst();
|
||||
|
||||
if (cursor != null) {
|
||||
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 = uri.getEncodedPath();
|
||||
if (!isValidFilePath(filepath)) {
|
||||
filepath = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fall back to URI if this fails.
|
||||
catch (Exception e) {
|
||||
filepath = null;
|
||||
}
|
||||
|
||||
// Update the file to a file URI
|
||||
if (filepath != null && !filepath.isEmpty()) {
|
||||
Uri.Builder b = new Uri.Builder();
|
||||
uri = b.scheme("file").authority("").path(filepath).build();
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
private static boolean isValidFilePath(String filepath) {
|
||||
if (filepath == null || filepath.isEmpty()) { return false; }
|
||||
|
||||
File file = new File(filepath);
|
||||
return file.exists() && file.canRead();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whitelist for known content providers that support writing
|
||||
* @param uri
|
||||
* @return
|
||||
*/
|
||||
private static boolean hasWritableContentUri(Uri uri) {
|
||||
String scheme = uri.getScheme();
|
||||
|
||||
if (scheme == null || scheme.isEmpty()) { return false; }
|
||||
|
||||
if (!scheme.equalsIgnoreCase("content")) { return false; }
|
||||
|
||||
switch (uri.getAuthority()) {
|
||||
case "com.google.android.apps.docs.storage":
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
149
app/src/main/java/com/kunzisoft/keepass/utils/UriUtil.kt
Normal file
149
app/src/main/java/com/kunzisoft/keepass/utils/UriUtil.kt
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePass DX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.utils
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.fileselect.StorageAF
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.InputStream
|
||||
|
||||
|
||||
object UriUtil {
|
||||
|
||||
fun parseUriFile(text: String?): Uri? {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
return parseUriFile(Uri.parse(text))
|
||||
}
|
||||
|
||||
fun parseUriFile(uri: Uri?): Uri? {
|
||||
if (uri == null) {
|
||||
return null
|
||||
}
|
||||
var currentUri = uri
|
||||
if (currentUri.scheme == null || currentUri.scheme!!.isEmpty()) {
|
||||
currentUri = currentUri.buildUpon().scheme("file").authority("").build()
|
||||
}
|
||||
return currentUri
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (StorageAF.useStorageFramework(ctx) || 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)
|
||||
fun getUriInputStream(contentResolver: ContentResolver, uri: Uri?): InputStream? {
|
||||
if (uri == null)
|
||||
return null
|
||||
val scheme = uri.scheme
|
||||
return if (scheme == null || scheme.isEmpty() || scheme == "file") {
|
||||
FileInputStream(uri.path!!)
|
||||
} else if (scheme == "content") {
|
||||
contentResolver.openInputStream(uri)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.kunzisoft.keepass.utils
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.InputStream
|
||||
|
||||
@Throws(FileNotFoundException::class)
|
||||
fun getUriInputStream(contentResolver: ContentResolver, uri: Uri?): InputStream? {
|
||||
if (uri == null) return null
|
||||
|
||||
val scheme = uri.scheme
|
||||
return if (scheme == null || scheme.isEmpty() || scheme == "file") {
|
||||
FileInputStream(uri.path!!)
|
||||
} else if (scheme == "content") {
|
||||
contentResolver.openInputStream(uri)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user