forked from hardcoresushi/DroidFS
Explorer loading dialogs & Logo fix
This commit is contained in:
parent
2571849bc3
commit
34d7f19927
@ -15,7 +15,7 @@ android {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.1.0"
|
||||
versionName "1.1.1"
|
||||
|
||||
ndk {
|
||||
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
|
@ -3,7 +3,6 @@ package sushi.hardcore.droidfs
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.jaredrummler.cyanea.app.CyaneaAppCompatActivity
|
||||
@ -30,8 +29,4 @@ open class BaseActivity: CyaneaAppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun toastFromThread(stringId: Int){
|
||||
runOnUiThread { Toast.makeText(this, stringId, Toast.LENGTH_SHORT).show() }
|
||||
}
|
||||
}
|
@ -8,8 +8,8 @@ import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.View
|
||||
import android.widget.AdapterView.OnItemClickListener
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import kotlinx.android.synthetic.main.activity_change_password.*
|
||||
import kotlinx.android.synthetic.main.activity_change_password.checkbox_remember_path
|
||||
import kotlinx.android.synthetic.main.activity_change_password.checkbox_save_password
|
||||
@ -18,10 +18,7 @@ import kotlinx.android.synthetic.main.activity_change_password.saved_path_listvi
|
||||
import kotlinx.android.synthetic.main.toolbar.*
|
||||
import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter
|
||||
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
||||
import sushi.hardcore.droidfs.util.Wiper
|
||||
import sushi.hardcore.droidfs.util.*
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.util.*
|
||||
|
||||
@ -59,8 +56,11 @@ class ChangePasswordActivity : BaseActivity() {
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
if (sharedPrefs.getString(s.toString(), null) == null) {
|
||||
edit_old_password.hint = null
|
||||
edit_old_password.isEnabled = true
|
||||
} else {
|
||||
edit_old_password.text = null
|
||||
edit_old_password.hint = getString(R.string.hash_saved_hint)
|
||||
edit_old_password.isEnabled = false
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -97,80 +97,70 @@ class ChangePasswordActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun changePassword(givenHash: ByteArray?){
|
||||
val dialogLoadingView = layoutInflater.inflate(R.layout.dialog_loading, null)
|
||||
val dialogTextMessage = dialogLoadingView.findViewById<TextView>(R.id.text_message)
|
||||
dialogTextMessage.text = getString(R.string.loading_msg_change_password)
|
||||
val dialogLoading = ColoredAlertDialogBuilder(this)
|
||||
.setView(dialogLoadingView)
|
||||
.setTitle(R.string.loading)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
dialogLoading.show()
|
||||
Thread {
|
||||
val newPassword = edit_new_password.text.toString().toCharArray()
|
||||
val newPasswordConfirm = edit_new_password_confirm.text.toString().toCharArray()
|
||||
if (!newPassword.contentEquals(newPasswordConfirm)) {
|
||||
dialogLoading.dismiss()
|
||||
toastFromThread(R.string.passwords_mismatch)
|
||||
} else {
|
||||
val oldPassword = edit_old_password.text.toString().toCharArray()
|
||||
var returnedHash: ByteArray? = null
|
||||
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||
}
|
||||
var changePasswordImmediately = true
|
||||
if (givenHash == null){
|
||||
val cipherText = sharedPrefs.getString(rootCipherDir, null)
|
||||
if (cipherText != null){ //password hash saved
|
||||
dialogLoading.dismiss()
|
||||
fingerprintPasswordHashSaver.decrypt(cipherText, rootCipherDir, ::changePassword)
|
||||
changePasswordImmediately = false
|
||||
object : LoadingTask(this, R.string.loading_msg_change_password){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
val newPassword = edit_new_password.text.toString().toCharArray()
|
||||
val newPasswordConfirm = edit_new_password_confirm.text.toString().toCharArray()
|
||||
if (!newPassword.contentEquals(newPasswordConfirm)) {
|
||||
stopTaskWithToast(R.string.passwords_mismatch)
|
||||
} else {
|
||||
val oldPassword = edit_old_password.text.toString().toCharArray()
|
||||
var returnedHash: ByteArray? = null
|
||||
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||
}
|
||||
}
|
||||
if (changePasswordImmediately){
|
||||
if (GocryptfsVolume.change_password(rootCipherDir, oldPassword, givenHash, newPassword, returnedHash)) {
|
||||
val editor = sharedPrefs.edit()
|
||||
if (sharedPrefs.getString(rootCipherDir, null) != null){
|
||||
editor.remove(rootCipherDir)
|
||||
editor.apply()
|
||||
var changePasswordImmediately = true
|
||||
if (givenHash == null){
|
||||
val cipherText = sharedPrefs.getString(rootCipherDir, null)
|
||||
if (cipherText != null){ //password hash saved
|
||||
stopTask {
|
||||
fingerprintPasswordHashSaver.decrypt(cipherText, rootCipherDir, ::changePassword)
|
||||
}
|
||||
changePasswordImmediately = false
|
||||
}
|
||||
var continueImmediately = true
|
||||
if (checkbox_remember_path.isChecked) {
|
||||
val oldSavedVolumesPaths = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set<String>
|
||||
val newSavedVolumesPaths = oldSavedVolumesPaths.toMutableList()
|
||||
if (!oldSavedVolumesPaths.contains(rootCipherDir)) {
|
||||
newSavedVolumesPaths.add(rootCipherDir)
|
||||
editor.putStringSet(ConstValues.saved_volumes_key, newSavedVolumesPaths.toSet())
|
||||
}
|
||||
if (changePasswordImmediately){
|
||||
if (GocryptfsVolume.change_password(rootCipherDir, oldPassword, givenHash, newPassword, returnedHash)) {
|
||||
val editor = sharedPrefs.edit()
|
||||
if (sharedPrefs.getString(rootCipherDir, null) != null){
|
||||
editor.remove(rootCipherDir)
|
||||
editor.apply()
|
||||
}
|
||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||
dialogLoading.dismiss()
|
||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
||||
onPasswordChanged()
|
||||
var continueImmediately = true
|
||||
if (checkbox_remember_path.isChecked) {
|
||||
val oldSavedVolumesPaths = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set<String>
|
||||
val newSavedVolumesPaths = oldSavedVolumesPaths.toMutableList()
|
||||
if (!oldSavedVolumesPaths.contains(rootCipherDir)) {
|
||||
newSavedVolumesPaths.add(rootCipherDir)
|
||||
editor.putStringSet(ConstValues.saved_volumes_key, newSavedVolumesPaths.toSet())
|
||||
editor.apply()
|
||||
}
|
||||
continueImmediately = false
|
||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
||||
stopTask { onPasswordChanged() }
|
||||
}
|
||||
continueImmediately = false
|
||||
}
|
||||
}
|
||||
if (continueImmediately){
|
||||
stopTask { onPasswordChanged() }
|
||||
}
|
||||
} else {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.change_password_failed)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
if (continueImmediately){
|
||||
dialogLoading.dismiss()
|
||||
runOnUiThread { onPasswordChanged() }
|
||||
}
|
||||
} else {
|
||||
dialogLoading.dismiss()
|
||||
runOnUiThread {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.change_password_failed)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
Arrays.fill(oldPassword, 0.toChar())
|
||||
}
|
||||
Arrays.fill(oldPassword, 0.toChar())
|
||||
Arrays.fill(newPassword, 0.toChar())
|
||||
Arrays.fill(newPasswordConfirm, 0.toChar())
|
||||
}
|
||||
Arrays.fill(newPassword, 0.toChar())
|
||||
Arrays.fill(newPasswordConfirm, 0.toChar())
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onPasswordChanged(){
|
||||
|
@ -5,7 +5,7 @@ import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import kotlinx.android.synthetic.main.activity_create.*
|
||||
import kotlinx.android.synthetic.main.activity_create.checkbox_remember_path
|
||||
import kotlinx.android.synthetic.main.activity_create.checkbox_save_password
|
||||
@ -14,10 +14,7 @@ import kotlinx.android.synthetic.main.activity_create.edit_volume_path
|
||||
import kotlinx.android.synthetic.main.toolbar.*
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerActivity
|
||||
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
||||
import sushi.hardcore.droidfs.util.Wiper
|
||||
import sushi.hardcore.droidfs.util.*
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
@ -64,99 +61,84 @@ class CreateActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
fun onClickCreate(view: View?) {
|
||||
val dialogLoadingView = layoutInflater.inflate(R.layout.dialog_loading, null)
|
||||
val dialogTextMessage = dialogLoadingView.findViewById<TextView>(R.id.text_message)
|
||||
dialogTextMessage.text = getString(R.string.loading_msg_create)
|
||||
val dialogLoading = ColoredAlertDialogBuilder(this)
|
||||
.setView(dialogLoadingView)
|
||||
.setTitle(R.string.loading)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
dialogLoading.show()
|
||||
Thread {
|
||||
val password = edit_password.text.toString().toCharArray()
|
||||
val passwordConfirm = edit_password_confirm.text.toString().toCharArray()
|
||||
if (!password.contentEquals(passwordConfirm)) {
|
||||
dialogLoading.dismiss()
|
||||
toastFromThread(R.string.passwords_mismatch)
|
||||
} else {
|
||||
rootCipherDir = edit_volume_path.text.toString()
|
||||
val volumePathFile = File(rootCipherDir)
|
||||
var goodDirectory = false
|
||||
if (!volumePathFile.isDirectory) {
|
||||
if (volumePathFile.mkdirs()) {
|
||||
goodDirectory = true
|
||||
} else {
|
||||
dialogLoading.dismiss()
|
||||
toastFromThread(R.string.error_mkdir)
|
||||
}
|
||||
object: LoadingTask(this, R.string.loading_msg_create){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
val password = edit_password.text.toString().toCharArray()
|
||||
val passwordConfirm = edit_password_confirm.text.toString().toCharArray()
|
||||
if (!password.contentEquals(passwordConfirm)) {
|
||||
stopTaskWithToast(R.string.passwords_mismatch)
|
||||
} else {
|
||||
val dirContent = volumePathFile.list()
|
||||
if (dirContent != null){
|
||||
if (dirContent.isEmpty()) {
|
||||
rootCipherDir = edit_volume_path.text.toString()
|
||||
val volumePathFile = File(rootCipherDir)
|
||||
var goodDirectory = false
|
||||
if (!volumePathFile.isDirectory) {
|
||||
if (volumePathFile.mkdirs()) {
|
||||
goodDirectory = true
|
||||
} else {
|
||||
dialogLoading.dismiss()
|
||||
toastFromThread(R.string.dir_not_empty)
|
||||
stopTaskWithToast(R.string.error_mkdir)
|
||||
}
|
||||
} else {
|
||||
dialogLoading.dismiss()
|
||||
toastFromThread(R.string.listdir_null_error_msg)
|
||||
}
|
||||
}
|
||||
if (goodDirectory) {
|
||||
if (GocryptfsVolume.create_volume(rootCipherDir, password, GocryptfsVolume.ScryptDefaultLogN, ConstValues.creator)) {
|
||||
var returnedHash: ByteArray? = null
|
||||
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||
}
|
||||
sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash)
|
||||
if (sessionID != -1) {
|
||||
var startExplorerImmediately = true
|
||||
if (checkbox_remember_path.isChecked) {
|
||||
val oldSavedVolumesPaths = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set<String>
|
||||
val editor = sharedPrefs.edit()
|
||||
val newSavedVolumesPaths = oldSavedVolumesPaths.toMutableList()
|
||||
if (oldSavedVolumesPaths.contains(rootCipherDir)) {
|
||||
if (sharedPrefs.getString(rootCipherDir, null) != null){
|
||||
editor.remove(rootCipherDir)
|
||||
}
|
||||
} else {
|
||||
newSavedVolumesPaths.add(rootCipherDir)
|
||||
editor.putStringSet(ConstValues.saved_volumes_key, newSavedVolumesPaths.toSet())
|
||||
}
|
||||
editor.apply()
|
||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||
dialogLoading.dismiss()
|
||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
||||
runOnUiThread { startExplorer() }
|
||||
}
|
||||
startExplorerImmediately = false
|
||||
}
|
||||
}
|
||||
if (startExplorerImmediately){
|
||||
dialogLoading.dismiss()
|
||||
runOnUiThread { startExplorer() }
|
||||
val dirContent = volumePathFile.list()
|
||||
if (dirContent != null){
|
||||
if (dirContent.isEmpty()) {
|
||||
goodDirectory = true
|
||||
} else {
|
||||
stopTaskWithToast(R.string.dir_not_empty)
|
||||
}
|
||||
} else {
|
||||
dialogLoading.dismiss()
|
||||
toastFromThread(R.string.open_volume_failed)
|
||||
stopTaskWithToast(R.string.listdir_null_error_msg)
|
||||
}
|
||||
} else {
|
||||
dialogLoading.dismiss()
|
||||
runOnUiThread {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.create_volume_failed)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
if (goodDirectory) {
|
||||
if (GocryptfsVolume.create_volume(rootCipherDir, password, GocryptfsVolume.ScryptDefaultLogN, ConstValues.creator)) {
|
||||
var returnedHash: ByteArray? = null
|
||||
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||
}
|
||||
sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash)
|
||||
if (sessionID != -1) {
|
||||
var startExplorerImmediately = true
|
||||
if (checkbox_remember_path.isChecked) {
|
||||
val oldSavedVolumesPaths = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set<String>
|
||||
val editor = sharedPrefs.edit()
|
||||
val newSavedVolumesPaths = oldSavedVolumesPaths.toMutableList()
|
||||
if (oldSavedVolumesPaths.contains(rootCipherDir)) {
|
||||
if (sharedPrefs.getString(rootCipherDir, null) != null){
|
||||
editor.remove(rootCipherDir)
|
||||
}
|
||||
} else {
|
||||
newSavedVolumesPaths.add(rootCipherDir)
|
||||
editor.putStringSet(ConstValues.saved_volumes_key, newSavedVolumesPaths.toSet())
|
||||
}
|
||||
editor.apply()
|
||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
||||
stopTask { startExplorer() }
|
||||
}
|
||||
startExplorerImmediately = false
|
||||
}
|
||||
}
|
||||
if (startExplorerImmediately){
|
||||
stopTask { startExplorer() }
|
||||
}
|
||||
} else {
|
||||
stopTaskWithToast(R.string.open_volume_failed)
|
||||
}
|
||||
} else {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.create_volume_failed)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Arrays.fill(password, 0.toChar())
|
||||
Arrays.fill(passwordConfirm, 0.toChar())
|
||||
}
|
||||
Arrays.fill(password, 0.toChar())
|
||||
Arrays.fill(passwordConfirm, 0.toChar())
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startExplorer(){
|
||||
|
@ -7,6 +7,8 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.AdapterView.OnItemClickListener
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import kotlinx.android.synthetic.main.activity_open.checkbox_remember_path
|
||||
import kotlinx.android.synthetic.main.activity_open.checkbox_save_password
|
||||
import kotlinx.android.synthetic.main.activity_open.edit_password
|
||||
@ -18,10 +20,7 @@ import sushi.hardcore.droidfs.explorers.ExplorerActivity
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerActivityDrop
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerActivityPick
|
||||
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
||||
import sushi.hardcore.droidfs.util.Wiper
|
||||
import sushi.hardcore.droidfs.util.*
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
@ -83,72 +82,65 @@ class OpenActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
fun onClickOpen(view: View?) {
|
||||
val dialogLoadingView = layoutInflater.inflate(R.layout.dialog_loading, null)
|
||||
val dialogTextMessage = dialogLoadingView.findViewById<TextView>(R.id.text_message)
|
||||
dialogTextMessage.text = getString(R.string.loading_msg_open)
|
||||
val dialogLoading = ColoredAlertDialogBuilder(this)
|
||||
.setView(dialogLoadingView)
|
||||
.setTitle(R.string.loading)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
dialogLoading.show()
|
||||
Thread {
|
||||
rootCipherDir = edit_volume_path.text.toString() //fresh get in case of manual rewrite
|
||||
if (rootCipherDir.isEmpty()) {
|
||||
dialogLoading.dismiss()
|
||||
toastFromThread(R.string.enter_volume_path)
|
||||
} else {
|
||||
val password = edit_password.text.toString().toCharArray()
|
||||
var returnedHash: ByteArray? = null
|
||||
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||
}
|
||||
sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash)
|
||||
if (sessionID != -1) {
|
||||
var startExplorerImmediately = true
|
||||
if (checkbox_remember_path.isChecked) {
|
||||
savedVolumesAdapter.addVolumePath(rootCipherDir)
|
||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { success ->
|
||||
dialogLoading.dismiss()
|
||||
if (success){
|
||||
startExplorer()
|
||||
object : LoadingTask(this, R.string.loading_msg_open){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
rootCipherDir = edit_volume_path.text.toString() //fresh get in case of manual rewrite
|
||||
if (rootCipherDir.isEmpty()) {
|
||||
stopTaskWithToast(R.string.enter_volume_path)
|
||||
} else {
|
||||
val password = edit_password.text.toString().toCharArray()
|
||||
var returnedHash: ByteArray? = null
|
||||
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||
}
|
||||
sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash)
|
||||
if (sessionID != -1) {
|
||||
var startExplorerImmediately = true
|
||||
if (checkbox_remember_path.isChecked) {
|
||||
savedVolumesAdapter.addVolumePath(rootCipherDir)
|
||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { _ ->
|
||||
stopTask { startExplorer() }
|
||||
}
|
||||
startExplorerImmediately = false
|
||||
}
|
||||
startExplorerImmediately = false
|
||||
}
|
||||
if (startExplorerImmediately){
|
||||
stopTask { startExplorer() }
|
||||
}
|
||||
} else {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.open_volume_failed)
|
||||
.setMessage(R.string.open_volume_failed_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
if (startExplorerImmediately){
|
||||
dialogLoading.dismiss()
|
||||
startExplorer()
|
||||
}
|
||||
Arrays.fill(password, 0.toChar())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openUsingPasswordHash(passwordHash: ByteArray){
|
||||
object : LoadingTask(this, R.string.loading_msg_open){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
sessionID = GocryptfsVolume.init(rootCipherDir, null, passwordHash, null)
|
||||
if (sessionID != -1){
|
||||
stopTask { startExplorer() }
|
||||
} else {
|
||||
dialogLoading.dismiss()
|
||||
runOnUiThread {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.open_volume_failed)
|
||||
.setMessage(R.string.open_volume_failed_msg)
|
||||
.setMessage(R.string.open_failed_hash_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
Arrays.fill(password, 0.toChar())
|
||||
Arrays.fill(passwordHash, 0)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun openUsingPasswordHash(passwordHash: ByteArray){
|
||||
sessionID = GocryptfsVolume.init(rootCipherDir, null, passwordHash, null)
|
||||
if (sessionID != -1){
|
||||
startExplorer()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.open_volume_failed)
|
||||
.setMessage(R.string.open_failed_hash_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
Arrays.fill(passwordHash, 0)
|
||||
}
|
||||
|
||||
private fun startExplorer() {
|
||||
|
@ -133,6 +133,11 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
protected fun unselectAll(){
|
||||
explorerAdapter.unSelectAll()
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private fun sortExplorerElements() {
|
||||
when (sortModesValues[currentSortModeIndex]) {
|
||||
"name" -> {
|
||||
@ -199,8 +204,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath))
|
||||
}
|
||||
} else {
|
||||
explorerAdapter.unSelectAll()
|
||||
invalidateOptionsMenu()
|
||||
unselectAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,8 +291,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
explorerAdapter.unSelectAll()
|
||||
invalidateOptionsMenu()
|
||||
unselectAll()
|
||||
true
|
||||
}
|
||||
R.id.explorer_menu_sort -> {
|
||||
@ -331,8 +334,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
R.id.explorer_menu_external_open -> {
|
||||
if (usf_open){
|
||||
ExternalProvider.open(this, gocryptfsVolume, PathUtils.path_join(currentDirectoryPath, explorerElements[explorerAdapter.selectedItems[0]].name))
|
||||
explorerAdapter.unSelectAll()
|
||||
invalidateOptionsMenu()
|
||||
unselectAll()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -8,15 +8,14 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.github.clans.fab.FloatingActionMenu
|
||||
import kotlinx.android.synthetic.main.activity_explorer.*
|
||||
import sushi.hardcore.droidfs.OpenActivity
|
||||
import sushi.hardcore.droidfs.R
|
||||
import sushi.hardcore.droidfs.util.ExternalProvider
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.util.Wiper
|
||||
import sushi.hardcore.droidfs.util.*
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
@ -77,7 +76,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
||||
|
||||
fun onClickAddFile(view: View?) {
|
||||
fam_explorer.close(true)
|
||||
val i = Intent(Intent.ACTION_GET_CONTENT)
|
||||
val i = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||
i.type = "*/*"
|
||||
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
|
||||
i.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
@ -95,139 +94,175 @@ class ExplorerActivity : BaseExplorerActivity() {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == PICK_FILES_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val uris: MutableList<Uri> = ArrayList()
|
||||
val singleUri = data.data
|
||||
if (singleUri == null) { //multiples choices
|
||||
val clipData = data.clipData
|
||||
if (clipData != null){
|
||||
for (i in 0 until clipData.itemCount) {
|
||||
uris.add(clipData.getItemAt(i).uri)
|
||||
object : LoadingTask(this, R.string.loading_msg_import){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
val uris: MutableList<Uri> = ArrayList()
|
||||
val singleUri = data.data
|
||||
if (singleUri == null) { //multiples choices
|
||||
val clipData = data.clipData
|
||||
if (clipData != null){
|
||||
for (i in 0 until clipData.itemCount) {
|
||||
uris.add(clipData.getItemAt(i).uri)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uris.add(singleUri)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uris.add(singleUri)
|
||||
}
|
||||
if (uris.isNotEmpty()){
|
||||
var success = true
|
||||
for (uri in uris) {
|
||||
val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri))
|
||||
contentResolver.openInputStream(uri)?.let {
|
||||
success = gocryptfsVolume.import_file(it, dstPath)
|
||||
var success = true
|
||||
for (uri in uris) {
|
||||
val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(activity, uri))
|
||||
contentResolver.openInputStream(uri)?.let {
|
||||
success = gocryptfsVolume.import_file(it, dstPath)
|
||||
}
|
||||
if (!success) {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.import_failed, uri))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.import_failed, uri))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.success_import)
|
||||
.setMessage("""
|
||||
${getString(R.string.success_import_msg)}
|
||||
${getString(R.string.ask_for_wipe)}
|
||||
""".trimIndent())
|
||||
.setPositiveButton(R.string.yes) { _, _ ->
|
||||
success = true
|
||||
for (uri in uris) {
|
||||
if (!Wiper.wipe(this, uri)) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.wipe_failed, uri))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
success = false
|
||||
break
|
||||
if (success) {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.success_import)
|
||||
.setMessage("""
|
||||
${getString(R.string.success_import_msg)}
|
||||
${getString(R.string.ask_for_wipe)}
|
||||
""".trimIndent())
|
||||
.setPositiveButton(R.string.yes) { _, _ ->
|
||||
object : LoadingTask(activity, R.string.loading_msg_wipe){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
success = true
|
||||
for (uri in uris) {
|
||||
val errorMsg = Wiper.wipe(activity, uri)
|
||||
if (errorMsg != null) {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.wipe_failed, errorMsg))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
success = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.wipe_successful)
|
||||
.setMessage(R.string.wipe_success_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.wipe_successful)
|
||||
.setMessage(R.string.wipe_success_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
.setNegativeButton(getString(R.string.no), null)
|
||||
.show()
|
||||
.setNegativeButton(getString(R.string.no), null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun doFinally(activity: AppCompatActivity){
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
}
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
}
|
||||
}
|
||||
} else if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val uri = data.data
|
||||
val outputDir = PathUtils.getFullPathFromTreeUri(uri, this)
|
||||
var failedItem: String? = null
|
||||
for (i in explorerAdapter.selectedItems) {
|
||||
val element = explorerAdapter.getItem(i)
|
||||
val fullPath = PathUtils.path_join(currentDirectoryPath, element.name)
|
||||
failedItem = if (element.isDirectory) {
|
||||
recursiveExportDirectory(fullPath, outputDir)
|
||||
} else {
|
||||
if (gocryptfsVolume.export_file(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath
|
||||
}
|
||||
if (failedItem != null) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.export_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (failedItem == null) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.success_export)
|
||||
.setMessage(R.string.success_export_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
explorerAdapter.unSelectAll()
|
||||
invalidateOptionsMenu()
|
||||
} else if (requestCode == PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val remoteSessionID = data.getIntExtra("sessionID", -1)
|
||||
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
||||
val path = data.getStringExtra("path")
|
||||
var failedItem: String? = null
|
||||
if (path == null) {
|
||||
val paths = data.getStringArrayListExtra("paths")
|
||||
val types = data.getIntegerArrayListExtra("types")
|
||||
if (types != null && paths != null){
|
||||
for (i in paths.indices) {
|
||||
failedItem = if (types[i] == 0) { //directory
|
||||
recursiveImportDirectoryFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath)
|
||||
object : LoadingTask(this, R.string.loading_msg_export){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
val uri = data.data
|
||||
val outputDir = PathUtils.getFullPathFromTreeUri(uri, activity)
|
||||
var failedItem: String? = null
|
||||
for (i in explorerAdapter.selectedItems) {
|
||||
val element = explorerAdapter.getItem(i)
|
||||
val fullPath = PathUtils.path_join(currentDirectoryPath, element.name)
|
||||
failedItem = if (element.isDirectory) {
|
||||
recursiveExportDirectory(fullPath, outputDir)
|
||||
} else {
|
||||
if (importFileFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath)) null else paths[i]
|
||||
if (gocryptfsVolume.export_file(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath
|
||||
}
|
||||
if (failedItem != null) {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.export_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if (failedItem == null) {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.success_export)
|
||||
.setMessage(R.string.success_export_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun doFinally(activity: AppCompatActivity) {
|
||||
unselectAll()
|
||||
}
|
||||
} else {
|
||||
failedItem = if (importFileFromOtherVolume(remoteGocryptfsVolume, path, currentDirectoryPath)) null else path
|
||||
}
|
||||
if (failedItem == null) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.success_import)
|
||||
.setMessage(R.string.success_import_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.import_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
} else if (requestCode == PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
object : LoadingTask(this, R.string.loading_msg_import){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
val remoteSessionID = data.getIntExtra("sessionID", -1)
|
||||
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
||||
val path = data.getStringExtra("path")
|
||||
var failedItem: String? = null
|
||||
if (path == null) {
|
||||
val paths = data.getStringArrayListExtra("paths")
|
||||
val types = data.getIntegerArrayListExtra("types")
|
||||
if (types != null && paths != null){
|
||||
for (i in paths.indices) {
|
||||
failedItem = if (types[i] == 0) { //directory
|
||||
recursiveImportDirectoryFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath)
|
||||
} else {
|
||||
if (importFileFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath)) null else paths[i]
|
||||
}
|
||||
if (failedItem != null) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
failedItem = if (importFileFromOtherVolume(remoteGocryptfsVolume, path, currentDirectoryPath)) null else path
|
||||
}
|
||||
if (failedItem == null) {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.success_import)
|
||||
.setMessage(R.string.success_import_msg)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.import_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
remoteGocryptfsVolume.close()
|
||||
}
|
||||
override fun doFinally(activity: AppCompatActivity) {
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
}
|
||||
}
|
||||
remoteGocryptfsVolume.close()
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -285,8 +320,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
||||
paths.add(PathUtils.path_join(currentDirectoryPath, e.name))
|
||||
}
|
||||
ExternalProvider.share(this, gocryptfsVolume, paths)
|
||||
explorerAdapter.unSelectAll()
|
||||
invalidateOptionsMenu()
|
||||
unselectAll()
|
||||
true
|
||||
}
|
||||
R.id.explorer_menu_decrypt -> {
|
||||
@ -407,8 +441,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
||||
break
|
||||
}
|
||||
}
|
||||
explorerAdapter.unSelectAll()
|
||||
invalidateOptionsMenu()
|
||||
unselectAll()
|
||||
setCurrentPath(currentDirectoryPath) //refresh
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package sushi.hardcore.droidfs.fingerprint_stuff
|
||||
|
||||
import android.content.Context
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.os.Build
|
||||
import android.os.CancellationSignal
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
class FingerprintHandler(private val context: Context) : FingerprintManager.AuthenticationCallback(){
|
||||
private lateinit var cancellationSignal: CancellationSignal
|
||||
private lateinit var onTouched: (resultCode: onTouchedResultCodes) -> Unit
|
||||
|
||||
fun startAuth(fingerprintManager: FingerprintManager, cryptoObject: FingerprintManager.CryptoObject, onTouched: (resultCode: onTouchedResultCodes) -> Unit){
|
||||
cancellationSignal = CancellationSignal()
|
||||
this.onTouched = onTouched
|
||||
fingerprintManager.authenticate(cryptoObject, cancellationSignal, 0, this, null)
|
||||
}
|
||||
|
||||
override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult?) {
|
||||
onTouched(onTouchedResultCodes.SUCCEED)
|
||||
}
|
||||
|
||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
|
||||
onTouched(onTouchedResultCodes.ERROR)
|
||||
}
|
||||
|
||||
override fun onAuthenticationFailed() {
|
||||
onTouched(onTouchedResultCodes.FAILED)
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package sushi.hardcore.droidfs.fingerprint_stuff
|
||||
|
||||
enum class onTouchedResultCodes {
|
||||
SUCCEED,
|
||||
FAILED,
|
||||
ERROR
|
||||
}
|
@ -3,12 +3,14 @@ package sushi.hardcore.droidfs.util
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import sushi.hardcore.droidfs.R
|
||||
import sushi.hardcore.droidfs.provider.RestrictedFileProvider
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.io.File
|
||||
import java.net.URLConnection
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
object ExternalProvider {
|
||||
private const val content_type_all = "*/*"
|
||||
@ -37,55 +39,78 @@ object ExternalProvider {
|
||||
return Pair(tmpFileUri, getContentType(fileName, previous_content_type))
|
||||
}
|
||||
}
|
||||
ColoredAlertDialogBuilder(context)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(context.getString(R.string.export_failed, file_path))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
return Pair(null, null)
|
||||
}
|
||||
|
||||
fun share(context: Context, gocryptfsVolume: GocryptfsVolume, file_paths: List<String>) {
|
||||
var contentType: String? = null
|
||||
val uris = ArrayList<Uri>()
|
||||
for (path in file_paths) {
|
||||
val result = exportFile(context, gocryptfsVolume, path, contentType)
|
||||
contentType = if (result.first != null) {
|
||||
uris.add(result.first!!)
|
||||
result.second
|
||||
} else {
|
||||
return
|
||||
fun share(activity: AppCompatActivity, gocryptfsVolume: GocryptfsVolume, file_paths: List<String>) {
|
||||
object : LoadingTask(activity, R.string.loading_msg_export){
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
var contentType: String? = null
|
||||
val uris = ArrayList<Uri>()
|
||||
for (path in file_paths) {
|
||||
val result = exportFile(activity, gocryptfsVolume, path, contentType)
|
||||
contentType = if (result.first != null) {
|
||||
uris.add(result.first!!)
|
||||
result.second
|
||||
} else {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(activity.getString(R.string.export_failed, path))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
val shareIntent = Intent()
|
||||
shareIntent.type = contentType
|
||||
if (uris.size == 1) {
|
||||
shareIntent.action = Intent.ACTION_SEND
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, uris[0])
|
||||
} else {
|
||||
shareIntent.action = Intent.ACTION_SEND_MULTIPLE
|
||||
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
|
||||
}
|
||||
stopTask {
|
||||
activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_chooser)))
|
||||
}
|
||||
}
|
||||
}
|
||||
val shareIntent = Intent()
|
||||
shareIntent.type = contentType
|
||||
if (uris.size == 1) {
|
||||
shareIntent.action = Intent.ACTION_SEND
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, uris[0])
|
||||
} else {
|
||||
shareIntent.action = Intent.ACTION_SEND_MULTIPLE
|
||||
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
|
||||
}
|
||||
context.startActivity(Intent.createChooser(shareIntent, context.getString(R.string.share_chooser)))
|
||||
}
|
||||
|
||||
fun open(context: Context, gocryptfsVolume: GocryptfsVolume, file_path: String) {
|
||||
val result = exportFile(context, gocryptfsVolume, file_path, null)
|
||||
result.first?.let {
|
||||
val openIntent = Intent()
|
||||
openIntent.action = Intent.ACTION_VIEW
|
||||
openIntent.setDataAndType(result.first, result.second)
|
||||
context.startActivity(openIntent)
|
||||
fun open(activity: AppCompatActivity, gocryptfsVolume: GocryptfsVolume, file_path: String) {
|
||||
object : LoadingTask(activity, R.string.loading_msg_export) {
|
||||
override fun doTask(activity: AppCompatActivity) {
|
||||
val result = exportFile(activity, gocryptfsVolume, file_path, null)
|
||||
if (result.first != null) {
|
||||
val openIntent = Intent(Intent.ACTION_VIEW)
|
||||
openIntent.setDataAndType(result.first, result.second)
|
||||
stopTask { activity.startActivity(openIntent) }
|
||||
} else {
|
||||
stopTask {
|
||||
ColoredAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(activity.getString(R.string.export_failed, file_path))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeFiles(context: Context) {
|
||||
Thread{
|
||||
val wiped = ArrayList<Uri>()
|
||||
for (uri in storedFiles) {
|
||||
if (Wiper.wipe(context, uri)){
|
||||
storedFiles.remove(uri)
|
||||
if (Wiper.wipe(context, uri) == null){
|
||||
wiped.add(uri)
|
||||
}
|
||||
}
|
||||
for (uri in wiped){
|
||||
storedFiles.remove(uri)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
39
app/src/main/java/sushi/hardcore/droidfs/util/LoadingTask.kt
Normal file
39
app/src/main/java/sushi/hardcore/droidfs/util/LoadingTask.kt
Normal file
@ -0,0 +1,39 @@
|
||||
package sushi.hardcore.droidfs.util
|
||||
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import sushi.hardcore.droidfs.R
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
|
||||
abstract class LoadingTask(private val activity: AppCompatActivity, private val loadingMessageResId: Int) {
|
||||
private val dialogLoadingView = activity.layoutInflater.inflate(R.layout.dialog_loading, null)
|
||||
private val dialogLoading: AlertDialog = ColoredAlertDialogBuilder(activity)
|
||||
.setView(dialogLoadingView)
|
||||
.setTitle(R.string.loading)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
init {
|
||||
dialogLoadingView.findViewById<TextView>(R.id.text_message).text = activity.getString(loadingMessageResId)
|
||||
startTask()
|
||||
}
|
||||
abstract fun doTask(activity: AppCompatActivity)
|
||||
open fun doFinally(activity: AppCompatActivity){}
|
||||
private fun startTask() {
|
||||
dialogLoading.show()
|
||||
Thread {
|
||||
doTask(activity)
|
||||
activity.runOnUiThread { doFinally(activity) }
|
||||
}.start()
|
||||
}
|
||||
protected fun stopTask(onUiThread: () -> Unit){
|
||||
dialogLoading.dismiss()
|
||||
activity.runOnUiThread {
|
||||
onUiThread()
|
||||
}
|
||||
}
|
||||
protected fun stopTaskWithToast(stringId: Int){
|
||||
stopTask { Toast.makeText(activity, stringId, Toast.LENGTH_SHORT).show() }
|
||||
}
|
||||
}
|
@ -4,7 +4,8 @@ import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.OpenableColumns
|
||||
import android.widget.EditText
|
||||
import sushi.hardcore.droidfs.ConstValues.Companion.wipe_passes
|
||||
import sushi.hardcore.droidfs.ConstValues
|
||||
import sushi.hardcore.droidfs.R
|
||||
import java.io.*
|
||||
import java.lang.Exception
|
||||
import java.lang.StringBuilder
|
||||
@ -14,7 +15,7 @@ import kotlin.math.ceil
|
||||
|
||||
object Wiper {
|
||||
private const val buff_size = 4096
|
||||
fun wipe(context: Context, uri: Uri): Boolean {
|
||||
fun wipe(context: Context, uri: Uri): String? {
|
||||
val cursor = context.contentResolver.query(uri, null, null, null, null)
|
||||
cursor?.let {
|
||||
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
|
||||
@ -26,11 +27,11 @@ object Wiper {
|
||||
val buff = ByteArray(buff_size)
|
||||
Arrays.fill(buff, 0.toByte())
|
||||
val writes = ceil(size.toDouble() / buff_size).toInt()
|
||||
for (i in 0 until wipe_passes) {
|
||||
for (i in 0 until ConstValues.wipe_passes) {
|
||||
for (j in 0 until writes) {
|
||||
os!!.write(buff)
|
||||
}
|
||||
if (i < wipe_passes - 1) {
|
||||
if (i < ConstValues.wipe_passes - 1) {
|
||||
//reopening to flush and seek
|
||||
os!!.close()
|
||||
os = context.contentResolver.openOutputStream(uri)
|
||||
@ -42,26 +43,25 @@ object Wiper {
|
||||
(os as FileOutputStream).channel.truncate(0) //truncate to 0 if cannot delete
|
||||
}
|
||||
os!!.close()
|
||||
return true
|
||||
return null
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return e.message
|
||||
}
|
||||
}
|
||||
return false
|
||||
return context.getString(R.string.query_cursor_null_error_msg)
|
||||
}
|
||||
@JvmStatic
|
||||
fun wipe(file: File): Boolean{
|
||||
fun wipe(file: File): String? {
|
||||
val size = file.length()
|
||||
try {
|
||||
var os = FileOutputStream(file)
|
||||
val buff = ByteArray(buff_size)
|
||||
Arrays.fill(buff, 0.toByte())
|
||||
val writes = ceil(size.toDouble() / buff_size).toInt()
|
||||
for (i in 0 until wipe_passes) {
|
||||
for (i in 0 until ConstValues.wipe_passes) {
|
||||
for (j in 0 until writes) {
|
||||
os.write(buff)
|
||||
}
|
||||
if (i < wipe_passes - 1) {
|
||||
if (i < ConstValues.wipe_passes - 1) {
|
||||
//reopening to flush and seek
|
||||
os.close()
|
||||
os = FileOutputStream(file)
|
||||
@ -73,10 +73,9 @@ object Wiper {
|
||||
os.channel.truncate(0) //truncate to 0 if cannot delete
|
||||
}
|
||||
os.close()
|
||||
return true
|
||||
return null
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return false
|
||||
return e.message
|
||||
}
|
||||
}
|
||||
private fun randomString(minSize: Int, maxSize: Int): String {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 42 KiB |
@ -126,21 +126,22 @@
|
||||
android:id="@+id/saved_path_listview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="50dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginHorizontal="@dimen/action_activity_listview_margin_horizontal"
|
||||
android:layout_marginTop="@dimen/action_activity_listview_margin_top"
|
||||
android:background="@drawable/listview_border"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="20dp"
|
||||
android:padding="@dimen/warning_msg_padding"
|
||||
android:gravity="center"
|
||||
android:text="@string/create_password_warning"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_activity_button_height"
|
||||
android:layout_marginHorizontal="@dimen/action_activity_button_hor_margin"
|
||||
android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/action_activity_button_margin_bottom"
|
||||
android:onClick="onClickChangePassword"
|
||||
android:text="@string/change_volume_password"
|
||||
style="@style/button"/>
|
||||
|
@ -105,14 +105,14 @@
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="20dp"
|
||||
android:padding="@dimen/warning_msg_padding"
|
||||
android:gravity="center"
|
||||
android:text="@string/create_password_warning"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_activity_button_height"
|
||||
android:layout_marginHorizontal="@dimen/action_activity_button_hor_margin"
|
||||
android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin"
|
||||
android:onClick="onClickCreate"
|
||||
android:text="@string/create_volume"
|
||||
style="@style/button"/>
|
||||
|
@ -86,20 +86,21 @@
|
||||
android:id="@+id/saved_path_listview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="50dp"
|
||||
android:layout_marginTop="20dp"/>
|
||||
android:layout_marginHorizontal="@dimen/action_activity_listview_margin_horizontal"
|
||||
android:layout_marginTop="@dimen/action_activity_listview_margin_top"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="20dp"
|
||||
android:padding="@dimen/warning_msg_padding"
|
||||
android:gravity="center"
|
||||
android:text="@string/open_activity_warning"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_activity_button_height"
|
||||
android:layout_marginHorizontal="@dimen/action_activity_button_hor_margin"
|
||||
android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/action_activity_button_margin_bottom"
|
||||
android:onClick="onClickOpen"
|
||||
android:text="@string/open_volume"
|
||||
style="@style/button"/>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.5 KiB |
@ -7,7 +7,11 @@
|
||||
<dimen name="edit_text_label_size">15sp</dimen>
|
||||
<dimen name="open_activity_label_width">90dp</dimen>
|
||||
<dimen name="change_password_activity_label_width">100dp</dimen>
|
||||
<dimen name="action_activity_button_hor_margin">60dp</dimen>
|
||||
<dimen name="action_activity_button_horizontal_margin">60dp</dimen>
|
||||
<dimen name="action_activity_button_height">60dp</dimen>
|
||||
<dimen name="action_activity_listview_margin_horizontal">50dp</dimen>
|
||||
<dimen name="action_activity_listview_margin_top">20dp</dimen>
|
||||
<dimen name="warning_msg_padding">20dp</dimen>
|
||||
<dimen name="action_activity_button_margin_bottom">20dp</dimen>
|
||||
<dimen name="adapter_text_size">18sp</dimen>
|
||||
</resources>
|
@ -50,7 +50,7 @@
|
||||
<string name="yes">YES</string>
|
||||
<string name="no">NO</string>
|
||||
<string name="ask_for_wipe">Do you want to wipe the original files ?</string>
|
||||
<string name="wipe_failed">Wiping of %1$s failed</string>
|
||||
<string name="wipe_failed">Wiping failed: %1$s</string>
|
||||
<string name="wipe_successful">Files successfully wiped !</string>
|
||||
<string name="wipe_success_msg">The imported files have been successfully wiped from their original locations.</string>
|
||||
<string name="create_password_warning">Warning !\nThis password will be the only way to decrypt the volume and access the files inside.\nChoose a very strong password (not \"123456\" or \"password\"), do not lose it and keep it secure (preferably only in your mind).\n\nDroidFS cannot protect you from screen recording apps, keyloggers, apk backdooring, compromised root accesses, memory dumps etc.\nDo not type passwords in insecure environments.</string>
|
||||
@ -62,6 +62,7 @@
|
||||
<string name="sort_order">Sort order:</string>
|
||||
<string name="old_password">Old password:</string>
|
||||
<string name="new_password">New password:</string>
|
||||
<string name="new_password_confirmation">New Password (confirmation):</string>
|
||||
<string name="success_change_password">Password successfully changed !</string>
|
||||
<string name="success_change_password_msg">The volume\'s password has been successfully changed.</string>
|
||||
<string name="change_password_failed">Failed to change the volume\'s password. Check the selected volume path and the entered old password.</string>
|
||||
@ -118,12 +119,15 @@
|
||||
<string name="discard">Discard</string>
|
||||
<string name="word_wrap">Word Wrap</string>
|
||||
<string name="outofmemoryerror_msg">OutOfMemoryError: This file is too large to be loaded in memory.</string>
|
||||
<string name="new_file">New File</string>
|
||||
<string name="new_file">Create New File</string>
|
||||
<string name="enter_file_name">File name:</string>
|
||||
<string name="file_creation_failed">Failed to create the file.</string>
|
||||
<string name="loading">Loading...</string>
|
||||
<string name="loading_msg_create">Creating volume...</string>
|
||||
<string name="loading_msg_change_password">Changing password...</string>
|
||||
<string name="new_password_confirmation">New Password (confirmation):</string>
|
||||
<string name="loading_msg_open">Opening volume...</string>
|
||||
<string name="loading">Loading…</string>
|
||||
<string name="loading_msg_create">Creating volume…</string>
|
||||
<string name="loading_msg_change_password">Changing password…</string>
|
||||
<string name="loading_msg_open">Opening volume…</string>
|
||||
<string name="loading_msg_import">Importing selected files…</string>
|
||||
<string name="loading_msg_wipe">Wiping original files…</string>
|
||||
<string name="loading_msg_export">Exporting files…</string>
|
||||
<string name="query_cursor_null_error_msg">Unable to access this file</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user