From 15d7a073f9b697e9f596876aa027cb9dfaa7ef52 Mon Sep 17 00:00:00 2001
From: nielsandriesse <andriesseniels@gmail.com>
Date: Wed, 19 Aug 2020 11:29:52 +1000
Subject: [PATCH] Hopefully fix file loading crash

---
 .../ApplicationPreferencesActivity.java       | 17 +++++-----
 .../securesms/DeviceListFragment.java         | 17 +++++-----
 .../database/loaders/DeviceListLoader.java    | 10 ++----
 .../loki/activities/LinkedDevicesLoader.kt    |  6 ++--
 .../loki/activities/RegisterActivity.kt       | 23 --------------
 .../loki/activities/RestoreActivity.kt        | 31 +++----------------
 .../securesms/loki/activities/SeedActivity.kt |  8 +++--
 .../dialogs/LinkDeviceMasterModeDialog.kt     | 20 ++++++------
 .../loki/dialogs/LinkDeviceSlaveModeDialog.kt | 12 ++++---
 .../securesms/loki/dialogs/SeedDialog.kt      | 19 +++++++-----
 .../loki/utilities/MnemonicUtilities.kt       | 27 +++++-----------
 .../widgets/ProfilePreference.java            | 12 +++----
 12 files changed, 73 insertions(+), 129 deletions(-)

diff --git a/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java b/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java
index 4400f061a8..7f75443aed 100644
--- a/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java
+++ b/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java
@@ -29,16 +29,17 @@ import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Build.VERSION;
 import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+
 import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.core.content.ContextCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
-import androidx.core.content.ContextCompat;
-import androidx.core.graphics.drawable.DrawableCompat;
-import androidx.appcompat.app.AlertDialog;
 import androidx.preference.Preference;
-import android.util.Log;
-import android.widget.Toast;
 
 import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
 import org.thoughtcrime.securesms.loki.activities.HomeActivity;
@@ -51,11 +52,8 @@ import org.thoughtcrime.securesms.service.KeyCachingService;
 import org.thoughtcrime.securesms.util.DynamicLanguage;
 import org.thoughtcrime.securesms.util.DynamicTheme;
 import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.whispersystems.signalservice.loki.crypto.MnemonicCodec;
 import org.whispersystems.signalservice.loki.utilities.HexEncodingKt;
 
-import java.io.File;
-
 import network.loki.messenger.R;
 
 /**
@@ -337,13 +335,12 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
         case PREFERENCE_CATEGORY_QR_CODE: break;
         case PREFERENCE_CATEGORY_LINKED_DEVICES: break;
         case PREFERENCE_CATEGORY_SEED:
-          File languageFileDirectory = new File(getContext().getApplicationInfo().dataDir);
           try {
             String hexEncodedSeed = IdentityKeyUtil.retrieve(getContext(), IdentityKeyUtil.lokiSeedKey);
             if (hexEncodedSeed == null) {
               hexEncodedSeed = HexEncodingKt.getHexEncodedPrivateKey(IdentityKeyUtil.getIdentityKeyPair(getContext())); // Legacy account
             }
-            String seed = new MnemonicCodec(languageFileDirectory).encode(hexEncodedSeed, MnemonicCodec.Language.Configuration.Companion.getEnglish());
+            String seed = "";
             new AlertDialog.Builder(getContext())
                            .setTitle(R.string.activity_settings_seed_dialog_title)
                            .setMessage(seed)
diff --git a/src/org/thoughtcrime/securesms/DeviceListFragment.java b/src/org/thoughtcrime/securesms/DeviceListFragment.java
index ea400e0481..54b17038f6 100644
--- a/src/org/thoughtcrime/securesms/DeviceListFragment.java
+++ b/src/org/thoughtcrime/securesms/DeviceListFragment.java
@@ -4,11 +4,6 @@ import android.app.Activity;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.ListFragment;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.Loader;
-import androidx.appcompat.app.AlertDialog;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -19,6 +14,12 @@ import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.ListFragment;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
+
 import com.melnykov.fab.FloatingActionButton;
 
 import org.thoughtcrime.securesms.database.DatabaseFactory;
@@ -26,12 +27,10 @@ import org.thoughtcrime.securesms.database.loaders.DeviceListLoader;
 import org.thoughtcrime.securesms.dependencies.InjectableType;
 import org.thoughtcrime.securesms.devicelist.Device;
 import org.thoughtcrime.securesms.loki.dialogs.DeviceEditingOptionsBottomSheet;
-import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities;
 import org.thoughtcrime.securesms.util.TextSecurePreferences;
 import org.thoughtcrime.securesms.util.ViewUtil;
 import org.whispersystems.libsignal.util.guava.Function;
 
-import java.io.File;
 import java.util.List;
 import java.util.Locale;
 
@@ -48,7 +47,6 @@ public class DeviceListFragment extends ListFragment
 
   private static final String TAG = DeviceListFragment.class.getSimpleName();
 
-  private File                   languageFileDirectory;
   private Locale                 locale;
   private View                   empty;
   private View                   progressContainer;
@@ -85,7 +83,6 @@ public class DeviceListFragment extends ListFragment
   @Override
   public void onActivityCreated(Bundle bundle) {
     super.onActivityCreated(bundle);
-    this.languageFileDirectory = MnemonicUtilities.getLanguageFileDirectory(getContext());
     getLoaderManager().initLoader(0, null, this);
     getListView().setOnItemClickListener(this);
   }
@@ -107,7 +104,7 @@ public class DeviceListFragment extends ListFragment
     empty.setVisibility(View.GONE);
     progressContainer.setVisibility(View.VISIBLE);
 
-    return new DeviceListLoader(getActivity(), languageFileDirectory);
+    return new DeviceListLoader(getActivity());
   }
 
   @Override
diff --git a/src/org/thoughtcrime/securesms/database/loaders/DeviceListLoader.java b/src/org/thoughtcrime/securesms/database/loaders/DeviceListLoader.java
index 711d557ce9..1f868d28ca 100644
--- a/src/org/thoughtcrime/securesms/database/loaders/DeviceListLoader.java
+++ b/src/org/thoughtcrime/securesms/database/loaders/DeviceListLoader.java
@@ -1,6 +1,7 @@
 package org.thoughtcrime.securesms.database.loaders;
 
 import android.content.Context;
+
 import androidx.annotation.NonNull;
 
 import com.annimon.stream.Stream;
@@ -8,13 +9,10 @@ import com.annimon.stream.Stream;
 import org.thoughtcrime.securesms.database.DatabaseFactory;
 import org.thoughtcrime.securesms.devicelist.Device;
 import org.thoughtcrime.securesms.logging.Log;
-import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities;
 import org.thoughtcrime.securesms.util.AsyncLoader;
 import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.whispersystems.signalservice.loki.crypto.MnemonicCodec;
 import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol;
 
-import java.io.File;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
@@ -23,11 +21,9 @@ import java.util.Set;
 public class DeviceListLoader extends AsyncLoader<List<Device>> {
 
   private static final String TAG = DeviceListLoader.class.getSimpleName();
-  private MnemonicCodec mnemonicCodec;
 
-  public DeviceListLoader(Context context, File languageFileDirectory) {
+  public DeviceListLoader(Context context) {
     super(context);
-    this.mnemonicCodec = new MnemonicCodec(languageFileDirectory);
   }
 
   @Override
@@ -45,7 +41,7 @@ public class DeviceListLoader extends AsyncLoader<List<Device>> {
   }
 
   private Device mapToDevice(@NonNull String hexEncodedPublicKey) {
-    String shortId = MnemonicUtilities.getFirst3Words(mnemonicCodec, hexEncodedPublicKey);
+    String shortId = "";
     String name = DatabaseFactory.getLokiUserDatabase(getContext()).getDisplayName(hexEncodedPublicKey);
     return new Device(hexEncodedPublicKey, shortId, name);
   }
diff --git a/src/org/thoughtcrime/securesms/loki/activities/LinkedDevicesLoader.kt b/src/org/thoughtcrime/securesms/loki/activities/LinkedDevicesLoader.kt
index 785566b2d7..663f83dc84 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/LinkedDevicesLoader.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/LinkedDevicesLoader.kt
@@ -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>? {
diff --git a/src/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt
index 9d5a71c85b..1ebf1ca1fd 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt
@@ -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)
diff --git a/src/org/thoughtcrime/securesms/loki/activities/RestoreActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/RestoreActivity.kt
index 195801191c..5c4ffa7863 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/RestoreActivity.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/RestoreActivity.kt
@@ -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 }
diff --git a/src/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt
index d0995ee019..c91113aa98 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt
@@ -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
diff --git a/src/org/thoughtcrime/securesms/loki/dialogs/LinkDeviceMasterModeDialog.kt b/src/org/thoughtcrime/securesms/loki/dialogs/LinkDeviceMasterModeDialog.kt
index ed55eca238..91edb872c2 100644
--- a/src/org/thoughtcrime/securesms/loki/dialogs/LinkDeviceMasterModeDialog.kt
+++ b/src/org/thoughtcrime/securesms/loki/dialogs/LinkDeviceMasterModeDialog.kt
@@ -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()
diff --git a/src/org/thoughtcrime/securesms/loki/dialogs/LinkDeviceSlaveModeDialog.kt b/src/org/thoughtcrime/securesms/loki/dialogs/LinkDeviceSlaveModeDialog.kt
index d795e3148f..54f5d3d48b 100644
--- a/src/org/thoughtcrime/securesms/loki/dialogs/LinkDeviceSlaveModeDialog.kt
+++ b/src/org/thoughtcrime/securesms/loki/dialogs/LinkDeviceSlaveModeDialog.kt
@@ -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()
diff --git a/src/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt b/src/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt
index 59f96ae433..a52e08f606 100644
--- a/src/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt
+++ b/src/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt
@@ -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()
     }
 }
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/loki/utilities/MnemonicUtilities.kt b/src/org/thoughtcrime/securesms/loki/utilities/MnemonicUtilities.kt
index c1e10551c2..040419a1df 100644
--- a/src/org/thoughtcrime/securesms/loki/utilities/MnemonicUtilities.kt
+++ b/src/org/thoughtcrime/securesms/loki/utilities/MnemonicUtilities.kt
@@ -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(" ")
   }
 }
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/preferences/widgets/ProfilePreference.java b/src/org/thoughtcrime/securesms/preferences/widgets/ProfilePreference.java
index 21ad43fdd4..f6c15d2ac5 100644
--- a/src/org/thoughtcrime/securesms/preferences/widgets/ProfilePreference.java
+++ b/src/org/thoughtcrime/securesms/preferences/widgets/ProfilePreference.java
@@ -7,9 +7,6 @@ import android.content.Context;
 import android.graphics.Outline;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
-import androidx.annotation.RequiresApi;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
@@ -18,14 +15,16 @@ import android.widget.ImageView;
 import android.widget.TextView;
 import android.widget.Toast;
 
+import androidx.annotation.RequiresApi;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
 import com.bumptech.glide.load.engine.DiskCacheStrategy;
 
 import org.thoughtcrime.securesms.database.Address;
-import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities;
 import org.thoughtcrime.securesms.mms.GlideApp;
 import org.thoughtcrime.securesms.recipients.Recipient;
 import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.whispersystems.signalservice.loki.crypto.MnemonicCodec;
 
 import network.loki.messenger.R;
 
@@ -124,8 +123,7 @@ public class ProfilePreference extends Preference {
     profileTagView.setVisibility(userMasterPublicKey == null ? View.GONE : View.VISIBLE);
 
     if (userMasterPublicKey != null && shortDeviceMnemonic == null) {
-      MnemonicCodec codec = new MnemonicCodec(MnemonicUtilities.getLanguageFileDirectory(context));
-      shortDeviceMnemonic = MnemonicUtilities.getFirst3Words(codec, userPublicKey);
+      shortDeviceMnemonic = "";
     }
 
     String tag = context.getResources().getString(R.string.activity_settings_linked_device_tag);