Improved backup/restore w/o Crypto class
This commit is contained in:
@@ -35,12 +35,11 @@ import com.google.android.material.snackbar.Snackbar
|
|||||||
import com.tutpro.baresip.Utils.showSnackBar
|
import com.tutpro.baresip.Utils.showSnackBar
|
||||||
import com.tutpro.baresip.databinding.ActivityMainBinding
|
import com.tutpro.baresip.databinding.ActivityMainBinding
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@@ -88,10 +87,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
private lateinit var contactsRequest: ActivityResultLauncher<Intent>
|
private lateinit var contactsRequest: ActivityResultLauncher<Intent>
|
||||||
private lateinit var callsRequest: ActivityResultLauncher<Intent>
|
private lateinit var callsRequest: ActivityResultLauncher<Intent>
|
||||||
|
|
||||||
private var downloadsInputStream: FileInputStream? = null
|
private var downloadsInputUri: Uri? = null
|
||||||
private var downloadsOutputStream: FileOutputStream? = null
|
private var downloadsOutputUri: Uri? = null
|
||||||
private var downloadsInputFile = "baresip.bs"
|
|
||||||
private var downloadsOutputFile = "baresip.bs"
|
|
||||||
|
|
||||||
private lateinit var baresipService: Intent
|
private lateinit var baresipService: Intent
|
||||||
|
|
||||||
@@ -543,26 +540,20 @@ class MainActivity : AppCompatActivity() {
|
|||||||
backupRequest = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
backupRequest = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
if (it.resultCode == Activity.RESULT_OK)
|
if (it.resultCode == Activity.RESULT_OK)
|
||||||
it.data?.data?.also { uri ->
|
it.data?.data?.also { uri ->
|
||||||
downloadsOutputStream = applicationContext.contentResolver.openOutputStream(uri)
|
downloadsOutputUri = uri
|
||||||
as FileOutputStream
|
if (downloadsOutputUri != null)
|
||||||
if (downloadsOutputStream != null) {
|
|
||||||
downloadsOutputFile = Utils.fileNameOfUri(applicationContext, uri)
|
|
||||||
askPassword(getString(R.string.encrypt_password))
|
askPassword(getString(R.string.encrypt_password))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
restoreRequest = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
restoreRequest = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
if (it.resultCode == Activity.RESULT_OK)
|
if (it.resultCode == Activity.RESULT_OK)
|
||||||
it.data?.data?.also { uri ->
|
it.data?.data?.also { uri ->
|
||||||
downloadsInputStream = applicationContext.contentResolver.openInputStream(uri)
|
downloadsInputUri = uri
|
||||||
as FileInputStream
|
if (downloadsInputUri != null)
|
||||||
if (downloadsInputStream != null) {
|
|
||||||
downloadsInputFile = Utils.fileNameOfUri(applicationContext, uri)
|
|
||||||
askPassword(getString(R.string.decrypt_password))
|
askPassword(getString(R.string.decrypt_password))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
swipeRefresh.setOnTouchListener(object : OnSwipeTouchListener(this@MainActivity) {
|
swipeRefresh.setOnTouchListener(object : OnSwipeTouchListener(this@MainActivity) {
|
||||||
|
|
||||||
@@ -1266,7 +1257,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
) == PackageManager.PERMISSION_GRANTED -> {
|
) == PackageManager.PERMISSION_GRANTED -> {
|
||||||
Log.d(TAG, "Write External Storage permission granted")
|
Log.d(TAG, "Write External Storage permission granted")
|
||||||
val path = Utils.downloadsPath("baresip.bs")
|
val path = Utils.downloadsPath("baresip.bs")
|
||||||
downloadsOutputStream = FileOutputStream(File(path))
|
downloadsOutputUri = File(path).toUri()
|
||||||
askPassword(getString(R.string.encrypt_password))
|
askPassword(getString(R.string.encrypt_password))
|
||||||
}
|
}
|
||||||
ActivityCompat.shouldShowRequestPermissionRationale(
|
ActivityCompat.shouldShowRequestPermissionRationale(
|
||||||
@@ -1289,14 +1280,15 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
R.id.restore -> {
|
R.id.restore -> {
|
||||||
when {
|
when {
|
||||||
Build.VERSION.SDK_INT >= 29 -> pickupFileFromDownloads("restore")
|
Build.VERSION.SDK_INT >= 29 ->
|
||||||
|
pickupFileFromDownloads("restore")
|
||||||
ContextCompat.checkSelfPermission(
|
ContextCompat.checkSelfPermission(
|
||||||
this,
|
this,
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
) == PackageManager.PERMISSION_GRANTED -> {
|
) == PackageManager.PERMISSION_GRANTED -> {
|
||||||
Log.d(TAG, "Read External Storage permission granted")
|
Log.d(TAG, "Read External Storage permission granted")
|
||||||
val path = Utils.downloadsPath("baresip.bs")
|
val path = Utils.downloadsPath("baresip.bs")
|
||||||
downloadsInputStream = FileInputStream(File(path))
|
downloadsInputUri = File(path).toUri()
|
||||||
askPassword(getString(R.string.decrypt_password))
|
askPassword(getString(R.string.decrypt_password))
|
||||||
}
|
}
|
||||||
ActivityCompat.shouldShowRequestPermissionRationale(
|
ActivityCompat.shouldShowRequestPermissionRationale(
|
||||||
@@ -1552,7 +1544,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
Log.w(TAG, "Failed to write zip file '$zipFile'")
|
Log.w(TAG, "Failed to write zip file '$zipFile'")
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.backup_failed),
|
String.format(getString(R.string.backup_failed),
|
||||||
downloadsOutputFile))
|
Utils.fileNameOfUri(applicationContext, downloadsOutputUri!!)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val content = Utils.getFileContents(zipFilePath)
|
val content = Utils.getFileContents(zipFilePath)
|
||||||
@@ -1560,43 +1552,43 @@ class MainActivity : AppCompatActivity() {
|
|||||||
Log.w(TAG, "Failed to read zip file '$zipFile'")
|
Log.w(TAG, "Failed to read zip file '$zipFile'")
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.backup_failed),
|
String.format(getString(R.string.backup_failed),
|
||||||
downloadsOutputFile))
|
Utils.fileNameOfUri(applicationContext, downloadsOutputUri!!)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!Utils.encryptToStream(downloadsOutputStream, content, password)) {
|
if (!Utils.encryptToUri(applicationContext, downloadsOutputUri!!, content, password)) {
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.backup_failed),
|
String.format(getString(R.string.backup_failed),
|
||||||
downloadsOutputFile))
|
Utils.fileNameOfUri(applicationContext, downloadsOutputUri!!)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Utils.alertView(this, getString(R.string.info),
|
Utils.alertView(this, getString(R.string.info),
|
||||||
String.format(getString(R.string.backed_up),
|
String.format(getString(R.string.backed_up),
|
||||||
downloadsOutputFile))
|
Utils.fileNameOfUri(applicationContext, downloadsOutputUri!!)))
|
||||||
Utils.deleteFile(File(zipFilePath))
|
Utils.deleteFile(File(zipFilePath))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restore(password: String) {
|
private fun restore(password: String) {
|
||||||
val zipFile = getString(R.string.app_name) + ".zip"
|
val zipFile = getString(R.string.app_name) + ".zip"
|
||||||
val zipFilePath = BaresipService.filesPath + "/$zipFile"
|
val zipFilePath = BaresipService.filesPath + "/$zipFile"
|
||||||
val zipData = Utils.decryptFromStream(downloadsInputStream, password)
|
val zipData = Utils.decryptFromUri(applicationContext, downloadsInputUri!!, password)
|
||||||
if (zipData == null) {
|
if (zipData == null) {
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.restore_failed),
|
String.format(getString(R.string.restore_failed),
|
||||||
downloadsInputFile))
|
Utils.fileNameOfUri(applicationContext, downloadsInputUri!!)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!Utils.putFileContents(zipFilePath, zipData)) {
|
if (!Utils.putFileContents(zipFilePath, zipData)) {
|
||||||
Log.w(TAG, "Failed to write zip file '$zipFile'")
|
Log.w(TAG, "Failed to write zip file '$zipFile'")
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.restore_failed),
|
String.format(getString(R.string.restore_failed),
|
||||||
downloadsInputFile))
|
Utils.fileNameOfUri(applicationContext, downloadsInputUri!!)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!Utils.unZip(zipFilePath)) {
|
if (!Utils.unZip(zipFilePath)) {
|
||||||
Log.w(TAG, "Failed to unzip file '$zipFile'")
|
Log.w(TAG, "Failed to unzip file '$zipFile'")
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.restore_failed),
|
String.format(getString(R.string.restore_failed),
|
||||||
downloadsInputFile))
|
Utils.fileNameOfUri(applicationContext, downloadsInputUri!!)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Utils.deleteFile(File(zipFilePath))
|
Utils.deleteFile(File(zipFilePath))
|
||||||
|
|||||||
@@ -629,38 +629,41 @@ object Utils {
|
|||||||
return plainData
|
return plainData
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encryptToStream(stream: FileOutputStream?, content: ByteArray, password: String): Boolean {
|
fun encryptToUri(ctx: Context, uri: Uri, content: ByteArray, password: String): Boolean {
|
||||||
val obj = encrypt(content, password.toCharArray())
|
val obj = encrypt(content, password.toCharArray())
|
||||||
|
val stream = ctx.contentResolver.openOutputStream(uri) as FileOutputStream
|
||||||
try {
|
try {
|
||||||
ObjectOutputStream(stream).use {
|
ObjectOutputStream(stream).use {
|
||||||
it.writeObject(obj)
|
it.writeObject(obj)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.w(TAG, "encryptToStream failed: $e")
|
Log.w(TAG, "encryptToUri failed: $e")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun decryptFromStream(stream: FileInputStream?, password: String): ByteArray? {
|
fun decryptFromUri(ctx: Context, uri: Uri, password: String): ByteArray? {
|
||||||
var plainData: ByteArray? = null
|
var plainData: ByteArray? = null
|
||||||
if (stream == null)
|
var stream = ctx.contentResolver.openInputStream(uri) as FileInputStream
|
||||||
return null
|
|
||||||
try {
|
try {
|
||||||
ObjectInputStream(stream).use {
|
ObjectInputStream(stream).use {
|
||||||
val content = it.readObject() as ByteArray
|
val content = it.readObject() as ByteArray
|
||||||
plainData = decrypt(content, password.toCharArray())
|
plainData = decrypt(content, password.toCharArray())
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.w(TAG, "decryptFromStream as ByteArray failed: $e")
|
|
||||||
try {
|
|
||||||
stream.close()
|
stream.close()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "decryptFromUri as ByteArray failed: $e")
|
||||||
|
stream.close()
|
||||||
|
try {
|
||||||
|
stream = ctx.contentResolver.openInputStream(uri) as FileInputStream
|
||||||
ObjectInputStream(stream).use {
|
ObjectInputStream(stream).use {
|
||||||
val obj = it.readObject() as Crypto
|
val obj = it.readObject() as Crypto
|
||||||
plainData = decryptOld(obj, password.toCharArray())
|
plainData = decryptOld(obj, password.toCharArray())
|
||||||
}
|
}
|
||||||
|
stream.close()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.w(TAG, "decryptFromStream as Crypto failed: $e")
|
Log.w(TAG, "decryptFromUri as Crypto failed: $e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return plainData
|
return plainData
|
||||||
|
|||||||
Reference in New Issue
Block a user