DroidFS/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt

290 lines
12 KiB
Kotlin
Raw Normal View History

2020-07-17 16:35:39 +02:00
package sushi.hardcore.droidfs
import android.app.Activity
import android.content.Intent
import android.os.Build
import android.os.Bundle
2020-10-15 17:43:13 +02:00
import android.text.Editable
import android.text.TextWatcher
import android.view.MenuItem
2020-07-17 16:35:39 +02:00
import android.view.View
import android.widget.AdapterView.OnItemClickListener
2020-08-25 14:10:46 +02:00
import android.widget.Toast
2020-07-28 22:25:10 +02:00
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_open.*
2020-10-15 17:43:13 +02:00
import kotlinx.android.synthetic.main.activity_open.saved_path_listview
import kotlinx.android.synthetic.main.checkboxes_section.*
2020-07-17 16:35:39 +02:00
import kotlinx.android.synthetic.main.toolbar.*
import kotlinx.android.synthetic.main.volume_path_section.*
2020-07-17 16:35:39 +02:00
import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter
import sushi.hardcore.droidfs.explorers.ExplorerActivity
import sushi.hardcore.droidfs.explorers.ExplorerActivityDrop
import sushi.hardcore.droidfs.explorers.ExplorerActivityPick
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
import sushi.hardcore.droidfs.provider.RestrictedFileProvider
2020-07-28 22:25:10 +02:00
import sushi.hardcore.droidfs.util.*
2020-07-27 16:20:52 +02:00
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
2020-07-17 16:35:39 +02:00
import java.io.File
import java.util.*
2020-07-21 15:05:05 +02:00
class OpenActivity : BaseActivity() {
2020-07-17 16:35:39 +02:00
companion object {
private const val PICK_DIRECTORY_REQUEST_CODE = 1
}
private lateinit var savedVolumesAdapter: SavedVolumesAdapter
private lateinit var fingerprintPasswordHashSaver: FingerprintPasswordHashSaver
2020-07-27 16:20:52 +02:00
private lateinit var rootCipherDir: String
2020-07-17 16:35:39 +02:00
private var sessionID = -1
2020-08-29 20:48:12 +02:00
private var isStartingActivity = false
private var isFinishingIntentionally = false
2020-07-17 16:35:39 +02:00
private var usf_fingerprint = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_open)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
2020-07-17 16:35:39 +02:00
usf_fingerprint = sharedPrefs.getBoolean("usf_fingerprint", false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && usf_fingerprint) {
fingerprintPasswordHashSaver = FingerprintPasswordHashSaver(this, sharedPrefs)
} else {
WidgetUtil.hide(checkbox_save_password)
}
savedVolumesAdapter = SavedVolumesAdapter(this, sharedPrefs)
if (savedVolumesAdapter.count > 0){
saved_path_listview.adapter = savedVolumesAdapter
saved_path_listview.onItemClickListener = OnItemClickListener { _, _, position, _ ->
2020-07-27 16:20:52 +02:00
rootCipherDir = savedVolumesAdapter.getItem(position)
edit_volume_path.setText(rootCipherDir)
val cipherText = sharedPrefs.getString(rootCipherDir, null)
2020-07-17 16:35:39 +02:00
if (cipherText != null){ //password hash saved
2020-07-27 16:20:52 +02:00
fingerprintPasswordHashSaver.decrypt(cipherText, rootCipherDir, ::openUsingPasswordHash)
2020-07-17 16:35:39 +02:00
}
}
} else {
WidgetUtil.hide(saved_path_listview)
}
2020-10-15 17:43:13 +02:00
edit_volume_path.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (savedVolumesAdapter.isPathSaved(s.toString())){
checkbox_remember_path.isEnabled = false
checkbox_remember_path.isChecked = false
if (sharedPrefs.getString(s.toString(), null) != null){
checkbox_save_password.isEnabled = false
checkbox_save_password.isChecked = false
} else {
checkbox_save_password.isEnabled = true
}
} else {
checkbox_remember_path.isEnabled = true
checkbox_save_password.isEnabled = true
}
}
})
2020-07-17 16:35:39 +02:00
edit_password.setOnEditorActionListener { v, _, _ ->
onClickOpen(v)
true
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when(item.itemId){
android.R.id.home -> {
isFinishingIntentionally = true
finish()
true
}
else -> super.onOptionsItemSelected(item)
}
}
2020-07-21 15:05:05 +02:00
fun pickDirectory(view: View?) {
2020-07-17 16:35:39 +02:00
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
2020-08-29 20:48:12 +02:00
isStartingActivity = true
2020-07-17 16:35:39 +02:00
startActivityForResult(i, PICK_DIRECTORY_REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
2020-08-25 14:10:46 +02:00
if (data?.data != null) {
if (PathUtils.isTreeUriOnPrimaryStorage(data.data)){
val path = PathUtils.getFullPathFromTreeUri(data.data, this)
if (path != null){
edit_volume_path.setText(path)
} else {
ColoredAlertDialogBuilder(this)
.setTitle(R.string.error)
.setMessage(R.string.path_from_uri_null_error_msg)
.setPositiveButton(R.string.ok, null)
.show()
}
} else {
ColoredAlertDialogBuilder(this)
.setTitle(R.string.warning)
.setMessage(R.string.open_on_sdcard_warning)
.setPositiveButton(R.string.ok, null)
.show()
}
2020-07-17 16:35:39 +02:00
}
}
}
}
fun onClickOpen(view: View?) {
2020-08-25 14:10:46 +02:00
rootCipherDir = edit_volume_path.text.toString()
if (rootCipherDir.isEmpty()) {
Toast.makeText(this, R.string.enter_volume_path, Toast.LENGTH_SHORT).show()
} else {
2020-10-14 19:04:19 +02:00
val rootCipherDirFile = File(rootCipherDir)
if (!GocryptfsVolume.isGocryptfsVolume(rootCipherDirFile)){
ColoredAlertDialogBuilder(this)
.setTitle(R.string.error)
.setMessage(R.string.error_not_a_volume)
.setPositiveButton(R.string.ok, null)
.show()
} else if (!rootCipherDirFile.canWrite()) {
2020-08-25 14:10:46 +02:00
ColoredAlertDialogBuilder(this)
.setTitle(R.string.warning)
.setMessage(R.string.open_cant_write_warning)
.setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> openVolume() }
.show()
} else {
openVolume()
}
}
}
private fun openVolume(){
2020-07-28 22:25:10 +02:00
object : LoadingTask(this, R.string.loading_msg_open){
override fun doTask(activity: AppCompatActivity) {
2020-08-25 14:10:46 +02:00
val password = edit_password.text.toString().toCharArray()
var returnedHash: ByteArray? = null
if (usf_fingerprint && checkbox_save_password.isChecked){
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
}
sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash)
if (sessionID != -1) {
if (checkbox_remember_path.isChecked) {
savedVolumesAdapter.addVolumePath(rootCipherDir)
2020-07-27 16:20:52 +02:00
}
2020-10-15 17:43:13 +02:00
if (checkbox_save_password.isChecked && returnedHash != null){
fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { _ ->
stopTask { startExplorer() }
}
} else {
2020-08-25 14:10:46 +02:00
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()
}
2020-07-28 22:25:10 +02:00
}
2020-08-25 14:10:46 +02:00
Arrays.fill(password, 0.toChar())
2020-07-28 22:25:10 +02:00
}
}
}
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() }
2020-07-27 16:20:52 +02:00
} else {
2020-07-28 22:25:10 +02:00
stopTask {
ColoredAlertDialogBuilder(activity)
2020-07-27 16:20:52 +02:00
.setTitle(R.string.open_volume_failed)
2020-07-28 22:25:10 +02:00
.setMessage(R.string.open_failed_hash_msg)
2020-07-27 16:20:52 +02:00
.setPositiveButton(R.string.ok, null)
.show()
2020-07-17 16:35:39 +02:00
}
}
2020-07-28 22:25:10 +02:00
Arrays.fill(passwordHash, 0)
2020-07-17 16:35:39 +02:00
}
}
}
private fun startExplorer() {
2020-07-27 16:20:52 +02:00
var explorerIntent: Intent? = null
val currentIntentAction = intent.action
if (currentIntentAction != null) {
if ((currentIntentAction == Intent.ACTION_SEND || currentIntentAction == Intent.ACTION_SEND_MULTIPLE) && intent.extras != null) { //import via android share menu
explorerIntent = Intent(this, ExplorerActivityDrop::class.java)
explorerIntent.action = currentIntentAction //forward action
explorerIntent.putExtras(intent.extras!!) //forward extras
} else if (currentIntentAction == "pick") { //pick items to import
explorerIntent = Intent(this, ExplorerActivityPick::class.java)
explorerIntent.putExtra("originalSessionID", intent.getIntExtra("sessionID", -1))
2020-07-27 16:20:52 +02:00
explorerIntent.flags = Intent.FLAG_ACTIVITY_FORWARD_RESULT
2020-07-17 16:35:39 +02:00
}
}
2020-07-27 16:20:52 +02:00
if (explorerIntent == null) {
explorerIntent = Intent(this, ExplorerActivity::class.java) //default opening
2020-07-17 16:35:39 +02:00
}
2020-07-27 16:20:52 +02:00
explorerIntent.putExtra("sessionID", sessionID)
explorerIntent.putExtra("volume_name", File(rootCipherDir).name)
startActivity(explorerIntent)
isFinishingIntentionally = true
2020-07-17 16:35:39 +02:00
finish()
}
fun onClickSavePasswordHash(view: View) {
if (checkbox_save_password.isChecked){
if (!fingerprintPasswordHashSaver.canAuthenticate()){
checkbox_save_password.isChecked = false
} else {
2020-10-15 17:43:13 +02:00
checkbox_remember_path.isChecked = checkbox_remember_path.isEnabled
2020-07-17 16:35:39 +02:00
}
}
}
fun onClickRememberPath(view: View) {
if (!checkbox_remember_path.isChecked){
checkbox_save_password.isChecked = false
}
}
override fun onBackPressed() {
super.onBackPressed()
isFinishingIntentionally = true
}
2020-07-17 16:35:39 +02:00
override fun onPause() {
super.onPause()
if (intent.action == "pick"){
2020-08-29 20:48:12 +02:00
if (isStartingActivity){
isStartingActivity = false
} else {
finish()
}
}
2020-07-17 16:35:39 +02:00
if (::fingerprintPasswordHashSaver.isInitialized && fingerprintPasswordHashSaver.isListening){
fingerprintPasswordHashSaver.stopListening()
if (fingerprintPasswordHashSaver.fingerprintFragment.isAdded){
fingerprintPasswordHashSaver.fingerprintFragment.dismiss()
}
}
}
override fun onDestroy() {
super.onDestroy()
Wiper.wipeEditText(edit_password)
if (intent.action == "pick" && !isFinishingIntentionally){
val sessionID = intent.getIntExtra("sessionID", -1)
if (sessionID != -1){
GocryptfsVolume(sessionID).close()
RestrictedFileProvider.wipeAll(this)
}
}
2020-07-17 16:35:39 +02:00
}
}