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
|
minSdkVersion 21
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.1.0"
|
versionName "1.1.1"
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||||
|
@ -3,7 +3,6 @@ package sushi.hardcore.droidfs
|
|||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.jaredrummler.cyanea.app.CyaneaAppCompatActivity
|
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.text.TextWatcher
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.AdapterView.OnItemClickListener
|
import android.widget.AdapterView.OnItemClickListener
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
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.*
|
||||||
import kotlinx.android.synthetic.main.activity_change_password.checkbox_remember_path
|
import kotlinx.android.synthetic.main.activity_change_password.checkbox_remember_path
|
||||||
import kotlinx.android.synthetic.main.activity_change_password.checkbox_save_password
|
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 kotlinx.android.synthetic.main.toolbar.*
|
||||||
import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter
|
import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter
|
||||||
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
||||||
import sushi.hardcore.droidfs.util.PathUtils
|
import sushi.hardcore.droidfs.util.*
|
||||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
|
||||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
|
||||||
import sushi.hardcore.droidfs.util.Wiper
|
|
||||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -59,8 +56,11 @@ class ChangePasswordActivity : BaseActivity() {
|
|||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
if (sharedPrefs.getString(s.toString(), null) == null) {
|
if (sharedPrefs.getString(s.toString(), null) == null) {
|
||||||
edit_old_password.hint = null
|
edit_old_password.hint = null
|
||||||
|
edit_old_password.isEnabled = true
|
||||||
} else {
|
} else {
|
||||||
|
edit_old_password.text = null
|
||||||
edit_old_password.hint = getString(R.string.hash_saved_hint)
|
edit_old_password.hint = getString(R.string.hash_saved_hint)
|
||||||
|
edit_old_password.isEnabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -97,21 +97,12 @@ class ChangePasswordActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun changePassword(givenHash: ByteArray?){
|
private fun changePassword(givenHash: ByteArray?){
|
||||||
val dialogLoadingView = layoutInflater.inflate(R.layout.dialog_loading, null)
|
object : LoadingTask(this, R.string.loading_msg_change_password){
|
||||||
val dialogTextMessage = dialogLoadingView.findViewById<TextView>(R.id.text_message)
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
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 newPassword = edit_new_password.text.toString().toCharArray()
|
||||||
val newPasswordConfirm = edit_new_password_confirm.text.toString().toCharArray()
|
val newPasswordConfirm = edit_new_password_confirm.text.toString().toCharArray()
|
||||||
if (!newPassword.contentEquals(newPasswordConfirm)) {
|
if (!newPassword.contentEquals(newPasswordConfirm)) {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.passwords_mismatch)
|
||||||
toastFromThread(R.string.passwords_mismatch)
|
|
||||||
} else {
|
} else {
|
||||||
val oldPassword = edit_old_password.text.toString().toCharArray()
|
val oldPassword = edit_old_password.text.toString().toCharArray()
|
||||||
var returnedHash: ByteArray? = null
|
var returnedHash: ByteArray? = null
|
||||||
@ -122,8 +113,9 @@ class ChangePasswordActivity : BaseActivity() {
|
|||||||
if (givenHash == null){
|
if (givenHash == null){
|
||||||
val cipherText = sharedPrefs.getString(rootCipherDir, null)
|
val cipherText = sharedPrefs.getString(rootCipherDir, null)
|
||||||
if (cipherText != null){ //password hash saved
|
if (cipherText != null){ //password hash saved
|
||||||
dialogLoading.dismiss()
|
stopTask {
|
||||||
fingerprintPasswordHashSaver.decrypt(cipherText, rootCipherDir, ::changePassword)
|
fingerprintPasswordHashSaver.decrypt(cipherText, rootCipherDir, ::changePassword)
|
||||||
|
}
|
||||||
changePasswordImmediately = false
|
changePasswordImmediately = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,21 +136,18 @@ class ChangePasswordActivity : BaseActivity() {
|
|||||||
editor.apply()
|
editor.apply()
|
||||||
}
|
}
|
||||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||||
dialogLoading.dismiss()
|
|
||||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
||||||
onPasswordChanged()
|
stopTask { onPasswordChanged() }
|
||||||
}
|
}
|
||||||
continueImmediately = false
|
continueImmediately = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (continueImmediately){
|
if (continueImmediately){
|
||||||
dialogLoading.dismiss()
|
stopTask { onPasswordChanged() }
|
||||||
runOnUiThread { onPasswordChanged() }
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTask {
|
||||||
runOnUiThread {
|
ColoredAlertDialogBuilder(activity)
|
||||||
ColoredAlertDialogBuilder(this)
|
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(R.string.change_password_failed)
|
.setMessage(R.string.change_password_failed)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
@ -170,7 +159,8 @@ class ChangePasswordActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
Arrays.fill(newPassword, 0.toChar())
|
Arrays.fill(newPassword, 0.toChar())
|
||||||
Arrays.fill(newPasswordConfirm, 0.toChar())
|
Arrays.fill(newPasswordConfirm, 0.toChar())
|
||||||
}.start()
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onPasswordChanged(){
|
private fun onPasswordChanged(){
|
||||||
|
@ -5,7 +5,7 @@ import android.content.Intent
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
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.*
|
||||||
import kotlinx.android.synthetic.main.activity_create.checkbox_remember_path
|
import kotlinx.android.synthetic.main.activity_create.checkbox_remember_path
|
||||||
import kotlinx.android.synthetic.main.activity_create.checkbox_save_password
|
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 kotlinx.android.synthetic.main.toolbar.*
|
||||||
import sushi.hardcore.droidfs.explorers.ExplorerActivity
|
import sushi.hardcore.droidfs.explorers.ExplorerActivity
|
||||||
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
||||||
import sushi.hardcore.droidfs.util.PathUtils
|
import sushi.hardcore.droidfs.util.*
|
||||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
|
||||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
|
||||||
import sushi.hardcore.droidfs.util.Wiper
|
|
||||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -64,21 +61,12 @@ class CreateActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onClickCreate(view: View?) {
|
fun onClickCreate(view: View?) {
|
||||||
val dialogLoadingView = layoutInflater.inflate(R.layout.dialog_loading, null)
|
object: LoadingTask(this, R.string.loading_msg_create){
|
||||||
val dialogTextMessage = dialogLoadingView.findViewById<TextView>(R.id.text_message)
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
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 password = edit_password.text.toString().toCharArray()
|
||||||
val passwordConfirm = edit_password_confirm.text.toString().toCharArray()
|
val passwordConfirm = edit_password_confirm.text.toString().toCharArray()
|
||||||
if (!password.contentEquals(passwordConfirm)) {
|
if (!password.contentEquals(passwordConfirm)) {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.passwords_mismatch)
|
||||||
toastFromThread(R.string.passwords_mismatch)
|
|
||||||
} else {
|
} else {
|
||||||
rootCipherDir = edit_volume_path.text.toString()
|
rootCipherDir = edit_volume_path.text.toString()
|
||||||
val volumePathFile = File(rootCipherDir)
|
val volumePathFile = File(rootCipherDir)
|
||||||
@ -87,8 +75,7 @@ class CreateActivity : BaseActivity() {
|
|||||||
if (volumePathFile.mkdirs()) {
|
if (volumePathFile.mkdirs()) {
|
||||||
goodDirectory = true
|
goodDirectory = true
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.error_mkdir)
|
||||||
toastFromThread(R.string.error_mkdir)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val dirContent = volumePathFile.list()
|
val dirContent = volumePathFile.list()
|
||||||
@ -96,12 +83,10 @@ class CreateActivity : BaseActivity() {
|
|||||||
if (dirContent.isEmpty()) {
|
if (dirContent.isEmpty()) {
|
||||||
goodDirectory = true
|
goodDirectory = true
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.dir_not_empty)
|
||||||
toastFromThread(R.string.dir_not_empty)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.listdir_null_error_msg)
|
||||||
toastFromThread(R.string.listdir_null_error_msg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (goodDirectory) {
|
if (goodDirectory) {
|
||||||
@ -127,25 +112,21 @@ class CreateActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
editor.apply()
|
editor.apply()
|
||||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||||
dialogLoading.dismiss()
|
|
||||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
||||||
runOnUiThread { startExplorer() }
|
stopTask { startExplorer() }
|
||||||
}
|
}
|
||||||
startExplorerImmediately = false
|
startExplorerImmediately = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (startExplorerImmediately){
|
if (startExplorerImmediately){
|
||||||
dialogLoading.dismiss()
|
stopTask { startExplorer() }
|
||||||
runOnUiThread { startExplorer() }
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.open_volume_failed)
|
||||||
toastFromThread(R.string.open_volume_failed)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTask {
|
||||||
runOnUiThread {
|
ColoredAlertDialogBuilder(activity)
|
||||||
ColoredAlertDialogBuilder(this)
|
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(R.string.create_volume_failed)
|
.setMessage(R.string.create_volume_failed)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
@ -156,7 +137,8 @@ class CreateActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
Arrays.fill(password, 0.toChar())
|
Arrays.fill(password, 0.toChar())
|
||||||
Arrays.fill(passwordConfirm, 0.toChar())
|
Arrays.fill(passwordConfirm, 0.toChar())
|
||||||
}.start()
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startExplorer(){
|
private fun startExplorer(){
|
||||||
|
@ -7,6 +7,8 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.AdapterView.OnItemClickListener
|
import android.widget.AdapterView.OnItemClickListener
|
||||||
import android.widget.TextView
|
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_remember_path
|
||||||
import kotlinx.android.synthetic.main.activity_open.checkbox_save_password
|
import kotlinx.android.synthetic.main.activity_open.checkbox_save_password
|
||||||
import kotlinx.android.synthetic.main.activity_open.edit_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.ExplorerActivityDrop
|
||||||
import sushi.hardcore.droidfs.explorers.ExplorerActivityPick
|
import sushi.hardcore.droidfs.explorers.ExplorerActivityPick
|
||||||
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
|
||||||
import sushi.hardcore.droidfs.util.PathUtils
|
import sushi.hardcore.droidfs.util.*
|
||||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
|
||||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
|
||||||
import sushi.hardcore.droidfs.util.Wiper
|
|
||||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -83,20 +82,11 @@ class OpenActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onClickOpen(view: View?) {
|
fun onClickOpen(view: View?) {
|
||||||
val dialogLoadingView = layoutInflater.inflate(R.layout.dialog_loading, null)
|
object : LoadingTask(this, R.string.loading_msg_open){
|
||||||
val dialogTextMessage = dialogLoadingView.findViewById<TextView>(R.id.text_message)
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
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
|
rootCipherDir = edit_volume_path.text.toString() //fresh get in case of manual rewrite
|
||||||
if (rootCipherDir.isEmpty()) {
|
if (rootCipherDir.isEmpty()) {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.enter_volume_path)
|
||||||
toastFromThread(R.string.enter_volume_path)
|
|
||||||
} else {
|
} else {
|
||||||
val password = edit_password.text.toString().toCharArray()
|
val password = edit_password.text.toString().toCharArray()
|
||||||
var returnedHash: ByteArray? = null
|
var returnedHash: ByteArray? = null
|
||||||
@ -109,23 +99,18 @@ class OpenActivity : BaseActivity() {
|
|||||||
if (checkbox_remember_path.isChecked) {
|
if (checkbox_remember_path.isChecked) {
|
||||||
savedVolumesAdapter.addVolumePath(rootCipherDir)
|
savedVolumesAdapter.addVolumePath(rootCipherDir)
|
||||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { success ->
|
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { _ ->
|
||||||
dialogLoading.dismiss()
|
stopTask { startExplorer() }
|
||||||
if (success){
|
|
||||||
startExplorer()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
startExplorerImmediately = false
|
startExplorerImmediately = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (startExplorerImmediately){
|
if (startExplorerImmediately){
|
||||||
dialogLoading.dismiss()
|
stopTask { startExplorer() }
|
||||||
startExplorer()
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTask {
|
||||||
runOnUiThread {
|
ColoredAlertDialogBuilder(activity)
|
||||||
ColoredAlertDialogBuilder(this)
|
|
||||||
.setTitle(R.string.open_volume_failed)
|
.setTitle(R.string.open_volume_failed)
|
||||||
.setMessage(R.string.open_volume_failed_msg)
|
.setMessage(R.string.open_volume_failed_msg)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
@ -134,22 +119,29 @@ class OpenActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
Arrays.fill(password, 0.toChar())
|
Arrays.fill(password, 0.toChar())
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openUsingPasswordHash(passwordHash: ByteArray){
|
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)
|
sessionID = GocryptfsVolume.init(rootCipherDir, null, passwordHash, null)
|
||||||
if (sessionID != -1){
|
if (sessionID != -1){
|
||||||
startExplorer()
|
stopTask { startExplorer() }
|
||||||
} else {
|
} else {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.open_volume_failed)
|
.setTitle(R.string.open_volume_failed)
|
||||||
.setMessage(R.string.open_failed_hash_msg)
|
.setMessage(R.string.open_failed_hash_msg)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Arrays.fill(passwordHash, 0)
|
Arrays.fill(passwordHash, 0)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun startExplorer() {
|
private fun startExplorer() {
|
||||||
var explorerIntent: Intent? = null
|
var explorerIntent: Intent? = null
|
||||||
|
@ -133,6 +133,11 @@ open class BaseExplorerActivity : BaseActivity() {
|
|||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun unselectAll(){
|
||||||
|
explorerAdapter.unSelectAll()
|
||||||
|
invalidateOptionsMenu()
|
||||||
|
}
|
||||||
|
|
||||||
private fun sortExplorerElements() {
|
private fun sortExplorerElements() {
|
||||||
when (sortModesValues[currentSortModeIndex]) {
|
when (sortModesValues[currentSortModeIndex]) {
|
||||||
"name" -> {
|
"name" -> {
|
||||||
@ -199,8 +204,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
|||||||
setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath))
|
setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
explorerAdapter.unSelectAll()
|
unselectAll()
|
||||||
invalidateOptionsMenu()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,8 +291,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
|||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
explorerAdapter.unSelectAll()
|
unselectAll()
|
||||||
invalidateOptionsMenu()
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.explorer_menu_sort -> {
|
R.id.explorer_menu_sort -> {
|
||||||
@ -331,8 +334,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
|||||||
R.id.explorer_menu_external_open -> {
|
R.id.explorer_menu_external_open -> {
|
||||||
if (usf_open){
|
if (usf_open){
|
||||||
ExternalProvider.open(this, gocryptfsVolume, PathUtils.path_join(currentDirectoryPath, explorerElements[explorerAdapter.selectedItems[0]].name))
|
ExternalProvider.open(this, gocryptfsVolume, PathUtils.path_join(currentDirectoryPath, explorerElements[explorerAdapter.selectedItems[0]].name))
|
||||||
explorerAdapter.unSelectAll()
|
unselectAll()
|
||||||
invalidateOptionsMenu()
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,14 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.github.clans.fab.FloatingActionMenu
|
import com.github.clans.fab.FloatingActionMenu
|
||||||
import kotlinx.android.synthetic.main.activity_explorer.*
|
import kotlinx.android.synthetic.main.activity_explorer.*
|
||||||
import sushi.hardcore.droidfs.OpenActivity
|
import sushi.hardcore.droidfs.OpenActivity
|
||||||
import sushi.hardcore.droidfs.R
|
import sushi.hardcore.droidfs.R
|
||||||
import sushi.hardcore.droidfs.util.ExternalProvider
|
import sushi.hardcore.droidfs.util.*
|
||||||
import sushi.hardcore.droidfs.util.PathUtils
|
|
||||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
|
||||||
import sushi.hardcore.droidfs.util.Wiper
|
|
||||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -77,7 +76,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
|
|
||||||
fun onClickAddFile(view: View?) {
|
fun onClickAddFile(view: View?) {
|
||||||
fam_explorer.close(true)
|
fam_explorer.close(true)
|
||||||
val i = Intent(Intent.ACTION_GET_CONTENT)
|
val i = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||||
i.type = "*/*"
|
i.type = "*/*"
|
||||||
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
|
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
|
||||||
i.addCategory(Intent.CATEGORY_OPENABLE)
|
i.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
@ -95,6 +94,8 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
if (requestCode == PICK_FILES_REQUEST_CODE) {
|
if (requestCode == PICK_FILES_REQUEST_CODE) {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
|
object : LoadingTask(this, R.string.loading_msg_import){
|
||||||
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
val uris: MutableList<Uri> = ArrayList()
|
val uris: MutableList<Uri> = ArrayList()
|
||||||
val singleUri = data.data
|
val singleUri = data.data
|
||||||
if (singleUri == null) { //multiples choices
|
if (singleUri == null) { //multiples choices
|
||||||
@ -107,60 +108,77 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
} else {
|
} else {
|
||||||
uris.add(singleUri)
|
uris.add(singleUri)
|
||||||
}
|
}
|
||||||
if (uris.isNotEmpty()){
|
|
||||||
var success = true
|
var success = true
|
||||||
for (uri in uris) {
|
for (uri in uris) {
|
||||||
val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri))
|
val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(activity, uri))
|
||||||
contentResolver.openInputStream(uri)?.let {
|
contentResolver.openInputStream(uri)?.let {
|
||||||
success = gocryptfsVolume.import_file(it, dstPath)
|
success = gocryptfsVolume.import_file(it, dstPath)
|
||||||
}
|
}
|
||||||
if (!success) {
|
if (!success) {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(getString(R.string.import_failed, uri))
|
.setMessage(getString(R.string.import_failed, uri))
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.success_import)
|
.setTitle(R.string.success_import)
|
||||||
.setMessage("""
|
.setMessage("""
|
||||||
${getString(R.string.success_import_msg)}
|
${getString(R.string.success_import_msg)}
|
||||||
${getString(R.string.ask_for_wipe)}
|
${getString(R.string.ask_for_wipe)}
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
.setPositiveButton(R.string.yes) { _, _ ->
|
.setPositiveButton(R.string.yes) { _, _ ->
|
||||||
|
object : LoadingTask(activity, R.string.loading_msg_wipe){
|
||||||
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
success = true
|
success = true
|
||||||
for (uri in uris) {
|
for (uri in uris) {
|
||||||
if (!Wiper.wipe(this, uri)) {
|
val errorMsg = Wiper.wipe(activity, uri)
|
||||||
ColoredAlertDialogBuilder(this)
|
if (errorMsg != null) {
|
||||||
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(getString(R.string.wipe_failed, uri))
|
.setMessage(getString(R.string.wipe_failed, errorMsg))
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
|
}
|
||||||
success = false
|
success = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.wipe_successful)
|
.setTitle(R.string.wipe_successful)
|
||||||
.setMessage(R.string.wipe_success_msg)
|
.setMessage(R.string.wipe_success_msg)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.setNegativeButton(getString(R.string.no), null)
|
.setNegativeButton(getString(R.string.no), null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun doFinally(activity: AppCompatActivity){
|
||||||
setCurrentPath(currentDirectoryPath)
|
setCurrentPath(currentDirectoryPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
|
} else if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
|
object : LoadingTask(this, R.string.loading_msg_export){
|
||||||
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
val uri = data.data
|
val uri = data.data
|
||||||
val outputDir = PathUtils.getFullPathFromTreeUri(uri, this)
|
val outputDir = PathUtils.getFullPathFromTreeUri(uri, activity)
|
||||||
var failedItem: String? = null
|
var failedItem: String? = null
|
||||||
for (i in explorerAdapter.selectedItems) {
|
for (i in explorerAdapter.selectedItems) {
|
||||||
val element = explorerAdapter.getItem(i)
|
val element = explorerAdapter.getItem(i)
|
||||||
@ -171,26 +189,35 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
if (gocryptfsVolume.export_file(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath
|
if (gocryptfsVolume.export_file(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath
|
||||||
}
|
}
|
||||||
if (failedItem != null) {
|
if (failedItem != null) {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(getString(R.string.export_failed, failedItem))
|
.setMessage(getString(R.string.export_failed, failedItem))
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (failedItem == null) {
|
if (failedItem == null) {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.success_export)
|
.setTitle(R.string.success_export)
|
||||||
.setMessage(R.string.success_export_msg)
|
.setMessage(R.string.success_export_msg)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
explorerAdapter.unSelectAll()
|
}
|
||||||
invalidateOptionsMenu()
|
override fun doFinally(activity: AppCompatActivity) {
|
||||||
|
unselectAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (requestCode == PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE) {
|
} else if (requestCode == PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE) {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
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 remoteSessionID = data.getIntExtra("sessionID", -1)
|
||||||
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
||||||
val path = data.getStringExtra("path")
|
val path = data.getStringExtra("path")
|
||||||
@ -214,23 +241,31 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
failedItem = if (importFileFromOtherVolume(remoteGocryptfsVolume, path, currentDirectoryPath)) null else path
|
failedItem = if (importFileFromOtherVolume(remoteGocryptfsVolume, path, currentDirectoryPath)) null else path
|
||||||
}
|
}
|
||||||
if (failedItem == null) {
|
if (failedItem == null) {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.success_import)
|
.setTitle(R.string.success_import)
|
||||||
.setMessage(R.string.success_import_msg)
|
.setMessage(R.string.success_import_msg)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(getString(R.string.import_failed, failedItem))
|
.setMessage(getString(R.string.import_failed, failedItem))
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
remoteGocryptfsVolume.close()
|
remoteGocryptfsVolume.close()
|
||||||
|
}
|
||||||
|
override fun doFinally(activity: AppCompatActivity) {
|
||||||
setCurrentPath(currentDirectoryPath)
|
setCurrentPath(currentDirectoryPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.explorer, menu)
|
menuInflater.inflate(R.menu.explorer, menu)
|
||||||
@ -285,8 +320,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
paths.add(PathUtils.path_join(currentDirectoryPath, e.name))
|
paths.add(PathUtils.path_join(currentDirectoryPath, e.name))
|
||||||
}
|
}
|
||||||
ExternalProvider.share(this, gocryptfsVolume, paths)
|
ExternalProvider.share(this, gocryptfsVolume, paths)
|
||||||
explorerAdapter.unSelectAll()
|
unselectAll()
|
||||||
invalidateOptionsMenu()
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.explorer_menu_decrypt -> {
|
R.id.explorer_menu_decrypt -> {
|
||||||
@ -407,8 +441,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
explorerAdapter.unSelectAll()
|
unselectAll()
|
||||||
invalidateOptionsMenu()
|
|
||||||
setCurrentPath(currentDirectoryPath) //refresh
|
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.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import sushi.hardcore.droidfs.R
|
import sushi.hardcore.droidfs.R
|
||||||
import sushi.hardcore.droidfs.provider.RestrictedFileProvider
|
import sushi.hardcore.droidfs.provider.RestrictedFileProvider
|
||||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLConnection
|
import java.net.URLConnection
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
object ExternalProvider {
|
object ExternalProvider {
|
||||||
private const val content_type_all = "*/*"
|
private const val content_type_all = "*/*"
|
||||||
@ -37,23 +39,27 @@ object ExternalProvider {
|
|||||||
return Pair(tmpFileUri, getContentType(fileName, previous_content_type))
|
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)
|
return Pair(null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun share(context: Context, gocryptfsVolume: GocryptfsVolume, file_paths: List<String>) {
|
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
|
var contentType: String? = null
|
||||||
val uris = ArrayList<Uri>()
|
val uris = ArrayList<Uri>()
|
||||||
for (path in file_paths) {
|
for (path in file_paths) {
|
||||||
val result = exportFile(context, gocryptfsVolume, path, contentType)
|
val result = exportFile(activity, gocryptfsVolume, path, contentType)
|
||||||
contentType = if (result.first != null) {
|
contentType = if (result.first != null) {
|
||||||
uris.add(result.first!!)
|
uris.add(result.first!!)
|
||||||
result.second
|
result.second
|
||||||
} else {
|
} else {
|
||||||
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.error)
|
||||||
|
.setMessage(activity.getString(R.string.export_failed, path))
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,26 +72,45 @@ object ExternalProvider {
|
|||||||
shareIntent.action = Intent.ACTION_SEND_MULTIPLE
|
shareIntent.action = Intent.ACTION_SEND_MULTIPLE
|
||||||
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
|
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
|
||||||
}
|
}
|
||||||
context.startActivity(Intent.createChooser(shareIntent, context.getString(R.string.share_chooser)))
|
stopTask {
|
||||||
|
activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_chooser)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun open(context: Context, gocryptfsVolume: GocryptfsVolume, file_path: String) {
|
fun open(activity: AppCompatActivity, gocryptfsVolume: GocryptfsVolume, file_path: String) {
|
||||||
val result = exportFile(context, gocryptfsVolume, file_path, null)
|
object : LoadingTask(activity, R.string.loading_msg_export) {
|
||||||
result.first?.let {
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
val openIntent = Intent()
|
val result = exportFile(activity, gocryptfsVolume, file_path, null)
|
||||||
openIntent.action = Intent.ACTION_VIEW
|
if (result.first != null) {
|
||||||
|
val openIntent = Intent(Intent.ACTION_VIEW)
|
||||||
openIntent.setDataAndType(result.first, result.second)
|
openIntent.setDataAndType(result.first, result.second)
|
||||||
context.startActivity(openIntent)
|
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) {
|
fun removeFiles(context: Context) {
|
||||||
Thread{
|
Thread{
|
||||||
|
val wiped = ArrayList<Uri>()
|
||||||
for (uri in storedFiles) {
|
for (uri in storedFiles) {
|
||||||
if (Wiper.wipe(context, uri)){
|
if (Wiper.wipe(context, uri) == null){
|
||||||
storedFiles.remove(uri)
|
wiped.add(uri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (uri in wiped){
|
||||||
|
storedFiles.remove(uri)
|
||||||
|
}
|
||||||
}.start()
|
}.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.net.Uri
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
import android.widget.EditText
|
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.io.*
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
import java.lang.StringBuilder
|
import java.lang.StringBuilder
|
||||||
@ -14,7 +15,7 @@ import kotlin.math.ceil
|
|||||||
|
|
||||||
object Wiper {
|
object Wiper {
|
||||||
private const val buff_size = 4096
|
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)
|
val cursor = context.contentResolver.query(uri, null, null, null, null)
|
||||||
cursor?.let {
|
cursor?.let {
|
||||||
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
|
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
|
||||||
@ -26,11 +27,11 @@ object Wiper {
|
|||||||
val buff = ByteArray(buff_size)
|
val buff = ByteArray(buff_size)
|
||||||
Arrays.fill(buff, 0.toByte())
|
Arrays.fill(buff, 0.toByte())
|
||||||
val writes = ceil(size.toDouble() / buff_size).toInt()
|
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) {
|
for (j in 0 until writes) {
|
||||||
os!!.write(buff)
|
os!!.write(buff)
|
||||||
}
|
}
|
||||||
if (i < wipe_passes - 1) {
|
if (i < ConstValues.wipe_passes - 1) {
|
||||||
//reopening to flush and seek
|
//reopening to flush and seek
|
||||||
os!!.close()
|
os!!.close()
|
||||||
os = context.contentResolver.openOutputStream(uri)
|
os = context.contentResolver.openOutputStream(uri)
|
||||||
@ -42,26 +43,25 @@ object Wiper {
|
|||||||
(os as FileOutputStream).channel.truncate(0) //truncate to 0 if cannot delete
|
(os as FileOutputStream).channel.truncate(0) //truncate to 0 if cannot delete
|
||||||
}
|
}
|
||||||
os!!.close()
|
os!!.close()
|
||||||
return true
|
return null
|
||||||
} catch (e: Exception) {
|
} 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): String? {
|
||||||
fun wipe(file: File): Boolean{
|
|
||||||
val size = file.length()
|
val size = file.length()
|
||||||
try {
|
try {
|
||||||
var os = FileOutputStream(file)
|
var os = FileOutputStream(file)
|
||||||
val buff = ByteArray(buff_size)
|
val buff = ByteArray(buff_size)
|
||||||
Arrays.fill(buff, 0.toByte())
|
Arrays.fill(buff, 0.toByte())
|
||||||
val writes = ceil(size.toDouble() / buff_size).toInt()
|
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) {
|
for (j in 0 until writes) {
|
||||||
os.write(buff)
|
os.write(buff)
|
||||||
}
|
}
|
||||||
if (i < wipe_passes - 1) {
|
if (i < ConstValues.wipe_passes - 1) {
|
||||||
//reopening to flush and seek
|
//reopening to flush and seek
|
||||||
os.close()
|
os.close()
|
||||||
os = FileOutputStream(file)
|
os = FileOutputStream(file)
|
||||||
@ -73,10 +73,9 @@ object Wiper {
|
|||||||
os.channel.truncate(0) //truncate to 0 if cannot delete
|
os.channel.truncate(0) //truncate to 0 if cannot delete
|
||||||
}
|
}
|
||||||
os.close()
|
os.close()
|
||||||
return true
|
return null
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
return e.message
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private fun randomString(minSize: Int, maxSize: Int): String {
|
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:id="@+id/saved_path_listview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="50dp"
|
android:layout_marginHorizontal="@dimen/action_activity_listview_margin_horizontal"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="@dimen/action_activity_listview_margin_top"
|
||||||
android:background="@drawable/listview_border"/>
|
android:background="@drawable/listview_border"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="20dp"
|
android:padding="@dimen/warning_msg_padding"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/create_password_warning"/>
|
android:text="@string/create_password_warning"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/action_activity_button_height"
|
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:onClick="onClickChangePassword"
|
||||||
android:text="@string/change_volume_password"
|
android:text="@string/change_volume_password"
|
||||||
style="@style/button"/>
|
style="@style/button"/>
|
||||||
|
@ -105,14 +105,14 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="20dp"
|
android:padding="@dimen/warning_msg_padding"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/create_password_warning"/>
|
android:text="@string/create_password_warning"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/action_activity_button_height"
|
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:onClick="onClickCreate"
|
||||||
android:text="@string/create_volume"
|
android:text="@string/create_volume"
|
||||||
style="@style/button"/>
|
style="@style/button"/>
|
||||||
|
@ -86,20 +86,21 @@
|
|||||||
android:id="@+id/saved_path_listview"
|
android:id="@+id/saved_path_listview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="50dp"
|
android:layout_marginHorizontal="@dimen/action_activity_listview_margin_horizontal"
|
||||||
android:layout_marginTop="20dp"/>
|
android:layout_marginTop="@dimen/action_activity_listview_margin_top"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="20dp"
|
android:padding="@dimen/warning_msg_padding"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/open_activity_warning"/>
|
android:text="@string/open_activity_warning"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/action_activity_button_height"
|
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:onClick="onClickOpen"
|
||||||
android:text="@string/open_volume"
|
android:text="@string/open_volume"
|
||||||
style="@style/button"/>
|
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="edit_text_label_size">15sp</dimen>
|
||||||
<dimen name="open_activity_label_width">90dp</dimen>
|
<dimen name="open_activity_label_width">90dp</dimen>
|
||||||
<dimen name="change_password_activity_label_width">100dp</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_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>
|
<dimen name="adapter_text_size">18sp</dimen>
|
||||||
</resources>
|
</resources>
|
@ -50,7 +50,7 @@
|
|||||||
<string name="yes">YES</string>
|
<string name="yes">YES</string>
|
||||||
<string name="no">NO</string>
|
<string name="no">NO</string>
|
||||||
<string name="ask_for_wipe">Do you want to wipe the original files ?</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_successful">Files successfully wiped !</string>
|
||||||
<string name="wipe_success_msg">The imported files have been successfully wiped from their original locations.</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>
|
<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="sort_order">Sort order:</string>
|
||||||
<string name="old_password">Old password:</string>
|
<string name="old_password">Old password:</string>
|
||||||
<string name="new_password">New 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">Password successfully changed !</string>
|
||||||
<string name="success_change_password_msg">The volume\'s password has been 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>
|
<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="discard">Discard</string>
|
||||||
<string name="word_wrap">Word Wrap</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="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="enter_file_name">File name:</string>
|
||||||
<string name="file_creation_failed">Failed to create the file.</string>
|
<string name="file_creation_failed">Failed to create the file.</string>
|
||||||
<string name="loading">Loading...</string>
|
<string name="loading">Loading…</string>
|
||||||
<string name="loading_msg_create">Creating volume...</string>
|
<string name="loading_msg_create">Creating volume…</string>
|
||||||
<string name="loading_msg_change_password">Changing password...</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_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>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user