Hopefully fix file loading crash

This commit is contained in:
nielsandriesse
2020-08-19 11:29:52 +10:00
parent 3a1a99b183
commit 15d7a073f9
12 changed files with 73 additions and 129 deletions

View File

@@ -13,8 +13,10 @@ import java.io.File
class LinkedDevicesLoader(context: Context) : AsyncLoader<List<Device>>(context) {
private val mnemonicCodec by lazy {
val languageFileDirectory = File(context.applicationInfo.dataDir)
MnemonicCodec(languageFileDirectory)
val loadFileContents: (String) -> String = { fileName ->
MnemonicUtilities.loadFileContents(context, fileName)
}
MnemonicCodec(loadFileContents)
}
override fun loadInBackground(): List<Device>? {

View File

@@ -44,7 +44,6 @@ class RegisterActivity : BaseActionBarActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_register)
setUpLanguageFileDirectory()
setUpActionBarSessionLogo()
registerButton.setOnClickListener { register() }
copyButton.setOnClickListener { copyPublicKey() }
@@ -69,28 +68,6 @@ class RegisterActivity : BaseActionBarActivity() {
}
// endregion
// region General
private fun setUpLanguageFileDirectory() {
val languages = listOf( "english", "japanese", "portuguese", "spanish" )
val directory = File(applicationInfo.dataDir)
for (language in languages) {
val fileName = "$language.txt"
if (directory.list().contains(fileName)) { continue }
val inputStream = assets.open("mnemonic/$fileName")
val file = File(directory, fileName)
val outputStream = FileOutputStream(file)
val buffer = ByteArray(1024)
while (true) {
val count = inputStream.read(buffer)
if (count < 0) { break }
outputStream.write(buffer, 0, count)
}
inputStream.close()
outputStream.close()
}
}
// endregion
// region Updating
private fun updateKeyPair() {
val seedCandidate = Curve25519.getInstance(Curve25519.BEST).generateSeed(16)

View File

@@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.IdentityDatabase
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
import org.thoughtcrime.securesms.loki.utilities.push
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.util.Base64
@@ -31,12 +32,10 @@ import java.io.File
import java.io.FileOutputStream
class RestoreActivity : BaseActionBarActivity() {
private lateinit var languageFileDirectory: File
// region Lifecycle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setUpLanguageFileDirectory()
setUpActionBarSessionLogo()
setContentView(R.layout.activity_restore)
mnemonicEditText.imeOptions = mnemonicEditText.imeOptions or 16777216 // Always use incognito keyboard
@@ -61,34 +60,14 @@ class RestoreActivity : BaseActionBarActivity() {
}
// endregion
// region General
private fun setUpLanguageFileDirectory() {
val languages = listOf( "english", "japanese", "portuguese", "spanish" )
val directory = File(applicationInfo.dataDir)
for (language in languages) {
val fileName = "$language.txt"
if (directory.list().contains(fileName)) { continue }
val inputStream = assets.open("mnemonic/$fileName")
val file = File(directory, fileName)
val outputStream = FileOutputStream(file)
val buffer = ByteArray(1024)
while (true) {
val count = inputStream.read(buffer)
if (count < 0) { break }
outputStream.write(buffer, 0, count)
}
inputStream.close()
outputStream.close()
}
languageFileDirectory = directory
}
// endregion
// region Interaction
private fun restore() {
val mnemonic = mnemonicEditText.text.toString()
try {
val hexEncodedSeed = MnemonicCodec(languageFileDirectory).decode(mnemonic)
val loadFileContents: (String) -> String = { fileName ->
MnemonicUtilities.loadFileContents(this, fileName)
}
val hexEncodedSeed = MnemonicCodec(loadFileContents).decode(mnemonic)
var seed = Hex.fromStringCondensed(hexEncodedSeed)
IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, Hex.toStringCondensed(seed))
if (seed.size == 16) { seed = seed + seed }

View File

@@ -7,12 +7,14 @@ import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.util.Log
import android.widget.LinearLayout
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_seed.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
@@ -22,12 +24,14 @@ import java.io.File
class SeedActivity : BaseActionBarActivity() {
private val seed by lazy {
val languageFileDirectory = File(applicationInfo.dataDir)
var hexEncodedSeed = IdentityKeyUtil.retrieve(this, IdentityKeyUtil.lokiSeedKey)
if (hexEncodedSeed == null) {
hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(this).hexEncodedPrivateKey // Legacy account
}
MnemonicCodec(languageFileDirectory).encode(hexEncodedSeed!!, MnemonicCodec.Language.Configuration.english)
val loadFileContents: (String) -> String = { fileName ->
MnemonicUtilities.loadFileContents(this, fileName)
}
MnemonicCodec(loadFileContents).encode(hexEncodedSeed!!, MnemonicCodec.Language.Configuration.english)
}
// region Lifecycle

View File

@@ -29,16 +29,15 @@ import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.Device
import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.DeviceLinkingSessionListener
class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListener {
private val languageFileDirectory by lazy { MnemonicUtilities.getLanguageFileDirectory(context!!) }
private lateinit var contentView: View
private var deviceLink: DeviceLink? = null
var delegate: LinkDeviceMasterModeDialogDelegate? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(context!!)
contentView = LayoutInflater.from(context!!).inflate(R.layout.dialog_link_device_master_mode, null)
val builder = AlertDialog.Builder(requireContext())
contentView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_link_device_master_mode, null)
val size = toPx(128, resources)
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context!!)
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(requireContext())
val qrCode = QRCodeUtilities.encode(hexEncodedPublicKey, size, false, false)
contentView.qrCodeImageView.setImageBitmap(qrCode)
contentView.cancelButton.setOnClickListener { onDeviceLinkCanceled() }
@@ -52,7 +51,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
}
override fun requestUserAuthorization(deviceLink: DeviceLink) {
if (deviceLink.type != DeviceLink.Type.REQUEST || deviceLink.masterPublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.deviceLink != null) { return }
if (deviceLink.type != DeviceLink.Type.REQUEST || deviceLink.masterPublicKey != TextSecurePreferences.getLocalNumber(requireContext()) || this.deviceLink != null) { return }
Util.runOnMain {
this.deviceLink = deviceLink
contentView.qrCodeImageView.visibility = View.GONE
@@ -62,7 +61,10 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
contentView.titleTextView.text = resources.getString(R.string.dialog_link_device_master_mode_title_2)
contentView.explanationTextView.text = resources.getString(R.string.dialog_link_device_master_mode_explanation_2)
contentView.mnemonicTextView.visibility = View.VISIBLE
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), deviceLink.slavePublicKey)
val loadFileContents: (String) -> String = { fileName ->
MnemonicUtilities.loadFileContents(requireContext(), fileName)
}
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(loadFileContents), deviceLink.slavePublicKey)
contentView.authorizeButton.visibility = View.VISIBLE
}
}
@@ -85,15 +87,15 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
contentView.authorizeButton.visibility = View.GONE
}
FileServerAPI.shared.addDeviceLink(deviceLink).bind(SnodeAPI.sharedContext) {
MultiDeviceProtocol.signAndSendDeviceLinkMessage(context!!, deviceLink)
MultiDeviceProtocol.signAndSendDeviceLinkMessage(requireContext(), deviceLink)
}.success {
TextSecurePreferences.setMultiDevice(context!!, true)
TextSecurePreferences.setMultiDevice(requireContext(), true)
}.successUi {
delegate?.onDeviceLinkRequestAuthorized()
dismiss()
}.fail {
FileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
DatabaseFactory.getLokiPreKeyBundleDatabase(context!!).removePreKeyBundle(deviceLink.slavePublicKey)
DatabaseFactory.getLokiPreKeyBundleDatabase(requireContext()).removePreKeyBundle(deviceLink.slavePublicKey)
}.failUi {
delegate?.onDeviceLinkAuthorizationFailed()
dismiss()

View File

@@ -21,16 +21,18 @@ import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.Device
import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.DeviceLinkingSessionListener
class LinkDeviceSlaveModeDialog : DialogFragment(), DeviceLinkingSessionListener {
private val languageFileDirectory by lazy { MnemonicUtilities.getLanguageFileDirectory(context!!) }
private lateinit var contentView: View
private var deviceLink: DeviceLink? = null
var delegate: LinkDeviceSlaveModeDialogDelegate? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(context!!)
contentView = LayoutInflater.from(context!!).inflate(R.layout.dialog_link_device_slave_mode, null)
val builder = AlertDialog.Builder(requireContext())
contentView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_link_device_slave_mode, null)
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), hexEncodedPublicKey)
val loadFileContents: (String) -> String = { fileName ->
MnemonicUtilities.loadFileContents(requireContext(), fileName)
}
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(loadFileContents), hexEncodedPublicKey)
contentView.cancelButton.setOnClickListener { onDeviceLinkCanceled() }
builder.setView(contentView)
DeviceLinkingSession.shared.startListeningForLinkingRequests()
@@ -41,7 +43,7 @@ class LinkDeviceSlaveModeDialog : DialogFragment(), DeviceLinkingSessionListener
}
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
if (deviceLink.type != DeviceLink.Type.AUTHORIZATION || deviceLink.slavePublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.deviceLink != null) { return }
if (deviceLink.type != DeviceLink.Type.AUTHORIZATION || deviceLink.slavePublicKey != TextSecurePreferences.getLocalNumber(requireContext()) || this.deviceLink != null) { return }
Util.runOnMain {
this.deviceLink = deviceLink
DeviceLinkingSession.shared.stopListeningForLinkingRequests()

View File

@@ -14,6 +14,7 @@ import android.widget.Toast
import kotlinx.android.synthetic.main.dialog_seed.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
import org.whispersystems.signalservice.loki.utilities.hexEncodedPrivateKey
import java.io.File
@@ -21,17 +22,19 @@ import java.io.File
class SeedDialog : DialogFragment() {
private val seed by lazy {
val languageFileDirectory = File(context!!.applicationInfo.dataDir)
var hexEncodedSeed = IdentityKeyUtil.retrieve(context!!, IdentityKeyUtil.lokiSeedKey)
var hexEncodedSeed = IdentityKeyUtil.retrieve(requireContext(), IdentityKeyUtil.lokiSeedKey)
if (hexEncodedSeed == null) {
hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(context!!).hexEncodedPrivateKey // Legacy account
hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(requireContext()).hexEncodedPrivateKey // Legacy account
}
MnemonicCodec(languageFileDirectory).encode(hexEncodedSeed!!, MnemonicCodec.Language.Configuration.english)
val loadFileContents: (String) -> String = { fileName ->
MnemonicUtilities.loadFileContents(requireContext(), fileName)
}
MnemonicCodec(loadFileContents).encode(hexEncodedSeed!!, MnemonicCodec.Language.Configuration.english)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(context!!)
val contentView = LayoutInflater.from(context!!).inflate(R.layout.dialog_seed, null)
val builder = AlertDialog.Builder(requireContext())
val contentView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_seed, null)
contentView.seedTextView.text = seed
contentView.cancelButton.setOnClickListener { dismiss() }
contentView.copyButton.setOnClickListener { copySeed() }
@@ -42,10 +45,10 @@ class SeedDialog : DialogFragment() {
}
private fun copySeed() {
val clipboard = activity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipboard = requireActivity().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("Seed", seed)
clipboard.setPrimaryClip(clip)
Toast.makeText(context!!, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
dismiss()
}
}

View File

@@ -8,30 +8,17 @@ import java.io.FileOutputStream
object MnemonicUtilities {
@JvmStatic
public fun getLanguageFileDirectory(context: Context): File {
val languages = listOf( "english", "japanese", "portuguese", "spanish" )
val directory = File(context.applicationInfo.dataDir)
for (language in languages) {
val fileName = "$language.txt"
if (directory.list().contains(fileName)) { continue }
val inputStream = context.assets.open("mnemonic/$fileName")
val file = File(directory, fileName)
val outputStream = FileOutputStream(file)
val buffer = ByteArray(1024)
while (true) {
val count = inputStream.read(buffer)
if (count < 0) { break }
outputStream.write(buffer, 0, count)
}
public fun loadFileContents(context: Context, fileName: String): String {
val inputStream = context.assets.open("mnemonic/$fileName.txt")
val size = inputStream.available()
val buffer = ByteArray(size)
inputStream.read(buffer)
inputStream.close()
outputStream.close()
}
return directory
return String(buffer)
}
@JvmStatic
public fun getFirst3Words(codec: MnemonicCodec, hexEncodedPublicKey: String): String {
return codec.encode(hexEncodedPublicKey.removing05PrefixIfNeeded()).split(" ").slice(0 until 3).joinToString(" ")
return codec.encode(hexEncodedPublicKey.removing05PrefixIfNeeded()).split(" ").slice(0 until 3).joinToString(" ")
}
}