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,80 +97,70 @@ 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 newPassword = edit_new_password.text.toString().toCharArray()
|
||||||
val dialogLoading = ColoredAlertDialogBuilder(this)
|
val newPasswordConfirm = edit_new_password_confirm.text.toString().toCharArray()
|
||||||
.setView(dialogLoadingView)
|
if (!newPassword.contentEquals(newPasswordConfirm)) {
|
||||||
.setTitle(R.string.loading)
|
stopTaskWithToast(R.string.passwords_mismatch)
|
||||||
.setCancelable(false)
|
} else {
|
||||||
.create()
|
val oldPassword = edit_old_password.text.toString().toCharArray()
|
||||||
dialogLoading.show()
|
var returnedHash: ByteArray? = null
|
||||||
Thread {
|
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||||
val newPassword = edit_new_password.text.toString().toCharArray()
|
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
var changePasswordImmediately = true
|
||||||
if (changePasswordImmediately){
|
if (givenHash == null){
|
||||||
if (GocryptfsVolume.change_password(rootCipherDir, oldPassword, givenHash, newPassword, returnedHash)) {
|
val cipherText = sharedPrefs.getString(rootCipherDir, null)
|
||||||
val editor = sharedPrefs.edit()
|
if (cipherText != null){ //password hash saved
|
||||||
if (sharedPrefs.getString(rootCipherDir, null) != null){
|
stopTask {
|
||||||
editor.remove(rootCipherDir)
|
fingerprintPasswordHashSaver.decrypt(cipherText, rootCipherDir, ::changePassword)
|
||||||
editor.apply()
|
}
|
||||||
|
changePasswordImmediately = false
|
||||||
}
|
}
|
||||||
var continueImmediately = true
|
}
|
||||||
if (checkbox_remember_path.isChecked) {
|
if (changePasswordImmediately){
|
||||||
val oldSavedVolumesPaths = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set<String>
|
if (GocryptfsVolume.change_password(rootCipherDir, oldPassword, givenHash, newPassword, returnedHash)) {
|
||||||
val newSavedVolumesPaths = oldSavedVolumesPaths.toMutableList()
|
val editor = sharedPrefs.edit()
|
||||||
if (!oldSavedVolumesPaths.contains(rootCipherDir)) {
|
if (sharedPrefs.getString(rootCipherDir, null) != null){
|
||||||
newSavedVolumesPaths.add(rootCipherDir)
|
editor.remove(rootCipherDir)
|
||||||
editor.putStringSet(ConstValues.saved_volumes_key, newSavedVolumesPaths.toSet())
|
|
||||||
editor.apply()
|
editor.apply()
|
||||||
}
|
}
|
||||||
if (checkbox_save_password.isChecked && returnedHash != null){
|
var continueImmediately = true
|
||||||
dialogLoading.dismiss()
|
if (checkbox_remember_path.isChecked) {
|
||||||
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ ->
|
val oldSavedVolumesPaths = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set<String>
|
||||||
onPasswordChanged()
|
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(){
|
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,99 +61,84 @@ 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 password = edit_password.text.toString().toCharArray()
|
||||||
val dialogLoading = ColoredAlertDialogBuilder(this)
|
val passwordConfirm = edit_password_confirm.text.toString().toCharArray()
|
||||||
.setView(dialogLoadingView)
|
if (!password.contentEquals(passwordConfirm)) {
|
||||||
.setTitle(R.string.loading)
|
stopTaskWithToast(R.string.passwords_mismatch)
|
||||||
.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)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
val dirContent = volumePathFile.list()
|
rootCipherDir = edit_volume_path.text.toString()
|
||||||
if (dirContent != null){
|
val volumePathFile = File(rootCipherDir)
|
||||||
if (dirContent.isEmpty()) {
|
var goodDirectory = false
|
||||||
|
if (!volumePathFile.isDirectory) {
|
||||||
|
if (volumePathFile.mkdirs()) {
|
||||||
goodDirectory = true
|
goodDirectory = true
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.error_mkdir)
|
||||||
toastFromThread(R.string.dir_not_empty)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
val dirContent = volumePathFile.list()
|
||||||
toastFromThread(R.string.listdir_null_error_msg)
|
if (dirContent != null){
|
||||||
}
|
if (dirContent.isEmpty()) {
|
||||||
}
|
goodDirectory = true
|
||||||
if (goodDirectory) {
|
} else {
|
||||||
if (GocryptfsVolume.create_volume(rootCipherDir, password, GocryptfsVolume.ScryptDefaultLogN, ConstValues.creator)) {
|
stopTaskWithToast(R.string.dir_not_empty)
|
||||||
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() }
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dialogLoading.dismiss()
|
stopTaskWithToast(R.string.listdir_null_error_msg)
|
||||||
toastFromThread(R.string.open_volume_failed)
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
dialogLoading.dismiss()
|
if (goodDirectory) {
|
||||||
runOnUiThread {
|
if (GocryptfsVolume.create_volume(rootCipherDir, password, GocryptfsVolume.ScryptDefaultLogN, ConstValues.creator)) {
|
||||||
ColoredAlertDialogBuilder(this)
|
var returnedHash: ByteArray? = null
|
||||||
.setTitle(R.string.error)
|
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||||
.setMessage(R.string.create_volume_failed)
|
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||||
.setPositiveButton(R.string.ok, null)
|
}
|
||||||
.show()
|
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(){
|
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,72 +82,65 @@ 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)
|
rootCipherDir = edit_volume_path.text.toString() //fresh get in case of manual rewrite
|
||||||
val dialogLoading = ColoredAlertDialogBuilder(this)
|
if (rootCipherDir.isEmpty()) {
|
||||||
.setView(dialogLoadingView)
|
stopTaskWithToast(R.string.enter_volume_path)
|
||||||
.setTitle(R.string.loading)
|
} else {
|
||||||
.setCancelable(false)
|
val password = edit_password.text.toString().toCharArray()
|
||||||
.create()
|
var returnedHash: ByteArray? = null
|
||||||
dialogLoading.show()
|
if (usf_fingerprint && checkbox_save_password.isChecked){
|
||||||
Thread {
|
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||||
rootCipherDir = edit_volume_path.text.toString() //fresh get in case of manual rewrite
|
}
|
||||||
if (rootCipherDir.isEmpty()) {
|
sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash)
|
||||||
dialogLoading.dismiss()
|
if (sessionID != -1) {
|
||||||
toastFromThread(R.string.enter_volume_path)
|
var startExplorerImmediately = true
|
||||||
} else {
|
if (checkbox_remember_path.isChecked) {
|
||||||
val password = edit_password.text.toString().toCharArray()
|
savedVolumesAdapter.addVolumePath(rootCipherDir)
|
||||||
var returnedHash: ByteArray? = null
|
if (checkbox_save_password.isChecked && returnedHash != null){
|
||||||
if (usf_fingerprint && checkbox_save_password.isChecked){
|
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { _ ->
|
||||||
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
stopTask { startExplorer() }
|
||||||
}
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
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){
|
Arrays.fill(password, 0.toChar())
|
||||||
dialogLoading.dismiss()
|
}
|
||||||
startExplorer()
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
} 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_failed_hash_msg)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.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() {
|
private fun startExplorer() {
|
||||||
|
@ -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,139 +94,175 @@ 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) {
|
||||||
val uris: MutableList<Uri> = ArrayList()
|
object : LoadingTask(this, R.string.loading_msg_import){
|
||||||
val singleUri = data.data
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
if (singleUri == null) { //multiples choices
|
val uris: MutableList<Uri> = ArrayList()
|
||||||
val clipData = data.clipData
|
val singleUri = data.data
|
||||||
if (clipData != null){
|
if (singleUri == null) { //multiples choices
|
||||||
for (i in 0 until clipData.itemCount) {
|
val clipData = data.clipData
|
||||||
uris.add(clipData.getItemAt(i).uri)
|
if (clipData != null){
|
||||||
|
for (i in 0 until clipData.itemCount) {
|
||||||
|
uris.add(clipData.getItemAt(i).uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uris.add(singleUri)
|
||||||
}
|
}
|
||||||
}
|
var success = true
|
||||||
} else {
|
for (uri in uris) {
|
||||||
uris.add(singleUri)
|
val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(activity, uri))
|
||||||
}
|
contentResolver.openInputStream(uri)?.let {
|
||||||
if (uris.isNotEmpty()){
|
success = gocryptfsVolume.import_file(it, dstPath)
|
||||||
var success = true
|
}
|
||||||
for (uri in uris) {
|
if (!success) {
|
||||||
val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri))
|
stopTask {
|
||||||
contentResolver.openInputStream(uri)?.let {
|
ColoredAlertDialogBuilder(activity)
|
||||||
success = gocryptfsVolume.import_file(it, dstPath)
|
.setTitle(R.string.error)
|
||||||
|
.setMessage(getString(R.string.import_failed, uri))
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!success) {
|
if (success) {
|
||||||
ColoredAlertDialogBuilder(this)
|
stopTask {
|
||||||
.setTitle(R.string.error)
|
ColoredAlertDialogBuilder(activity)
|
||||||
.setMessage(getString(R.string.import_failed, uri))
|
.setTitle(R.string.success_import)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setMessage("""
|
||||||
.show()
|
${getString(R.string.success_import_msg)}
|
||||||
break
|
${getString(R.string.ask_for_wipe)}
|
||||||
}
|
""".trimIndent())
|
||||||
}
|
.setPositiveButton(R.string.yes) { _, _ ->
|
||||||
if (success) {
|
object : LoadingTask(activity, R.string.loading_msg_wipe){
|
||||||
ColoredAlertDialogBuilder(this)
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
.setTitle(R.string.success_import)
|
success = true
|
||||||
.setMessage("""
|
for (uri in uris) {
|
||||||
${getString(R.string.success_import_msg)}
|
val errorMsg = Wiper.wipe(activity, uri)
|
||||||
${getString(R.string.ask_for_wipe)}
|
if (errorMsg != null) {
|
||||||
""".trimIndent())
|
stopTask {
|
||||||
.setPositiveButton(R.string.yes) { _, _ ->
|
ColoredAlertDialogBuilder(activity)
|
||||||
success = true
|
.setTitle(R.string.error)
|
||||||
for (uri in uris) {
|
.setMessage(getString(R.string.wipe_failed, errorMsg))
|
||||||
if (!Wiper.wipe(this, uri)) {
|
.setPositiveButton(R.string.ok, null)
|
||||||
ColoredAlertDialogBuilder(this)
|
.show()
|
||||||
.setTitle(R.string.error)
|
}
|
||||||
.setMessage(getString(R.string.wipe_failed, uri))
|
success = false
|
||||||
.setPositiveButton(R.string.ok, null)
|
break
|
||||||
.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) {
|
.setNegativeButton(getString(R.string.no), null)
|
||||||
ColoredAlertDialogBuilder(this)
|
.show()
|
||||||
.setTitle(R.string.wipe_successful)
|
}
|
||||||
.setMessage(R.string.wipe_success_msg)
|
}
|
||||||
.setPositiveButton(R.string.ok, null)
|
}
|
||||||
.show()
|
override fun doFinally(activity: AppCompatActivity){
|
||||||
}
|
setCurrentPath(currentDirectoryPath)
|
||||||
}
|
|
||||||
.setNegativeButton(getString(R.string.no), null)
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
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) {
|
||||||
val uri = data.data
|
object : LoadingTask(this, R.string.loading_msg_export){
|
||||||
val outputDir = PathUtils.getFullPathFromTreeUri(uri, this)
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
var failedItem: String? = null
|
val uri = data.data
|
||||||
for (i in explorerAdapter.selectedItems) {
|
val outputDir = PathUtils.getFullPathFromTreeUri(uri, activity)
|
||||||
val element = explorerAdapter.getItem(i)
|
var failedItem: String? = null
|
||||||
val fullPath = PathUtils.path_join(currentDirectoryPath, element.name)
|
for (i in explorerAdapter.selectedItems) {
|
||||||
failedItem = if (element.isDirectory) {
|
val element = explorerAdapter.getItem(i)
|
||||||
recursiveExportDirectory(fullPath, outputDir)
|
val fullPath = PathUtils.path_join(currentDirectoryPath, element.name)
|
||||||
} else {
|
failedItem = if (element.isDirectory) {
|
||||||
if (gocryptfsVolume.export_file(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath
|
recursiveExportDirectory(fullPath, outputDir)
|
||||||
}
|
|
||||||
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)
|
|
||||||
} else {
|
} 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) {
|
if (failedItem != null) {
|
||||||
|
stopTask {
|
||||||
|
ColoredAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.error)
|
||||||
|
.setMessage(getString(R.string.export_failed, failedItem))
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
break
|
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)
|
} else if (requestCode == PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE) {
|
||||||
.setTitle(R.string.success_import)
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
.setMessage(R.string.success_import_msg)
|
object : LoadingTask(this, R.string.loading_msg_import){
|
||||||
.setPositiveButton(R.string.ok, null)
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
.show()
|
val remoteSessionID = data.getIntExtra("sessionID", -1)
|
||||||
} else {
|
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
||||||
ColoredAlertDialogBuilder(this)
|
val path = data.getStringExtra("path")
|
||||||
.setTitle(R.string.error)
|
var failedItem: String? = null
|
||||||
.setMessage(getString(R.string.import_failed, failedItem))
|
if (path == null) {
|
||||||
.setPositiveButton(R.string.ok, null)
|
val paths = data.getStringArrayListExtra("paths")
|
||||||
.show()
|
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))
|
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,55 +39,78 @@ 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>) {
|
||||||
var contentType: String? = null
|
object : LoadingTask(activity, R.string.loading_msg_export){
|
||||||
val uris = ArrayList<Uri>()
|
override fun doTask(activity: AppCompatActivity) {
|
||||||
for (path in file_paths) {
|
var contentType: String? = null
|
||||||
val result = exportFile(context, gocryptfsVolume, path, contentType)
|
val uris = ArrayList<Uri>()
|
||||||
contentType = if (result.first != null) {
|
for (path in file_paths) {
|
||||||
uris.add(result.first!!)
|
val result = exportFile(activity, gocryptfsVolume, path, contentType)
|
||||||
result.second
|
contentType = if (result.first != null) {
|
||||||
} else {
|
uris.add(result.first!!)
|
||||||
return
|
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) {
|
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) {
|
||||||
openIntent.setDataAndType(result.first, result.second)
|
val openIntent = Intent(Intent.ACTION_VIEW)
|
||||||
context.startActivity(openIntent)
|
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) {
|
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